Compare commits

...

178 Commits

Author SHA1 Message Date
snipe
fe5e813970 Updated translations 2016-10-04 12:23:02 -07:00
snipe
d6f7e03431 Bumped version for pre-release 2016-10-04 11:58:19 -07:00
snipe
87f50dfd10 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-09-29 22:37:59 -07:00
snipe
85ddb9cfff Bumped version 2016-09-29 22:37:54 -07:00
Michael T
c6338d6a8b Apologies. Still learning Git, and CentOS isn't a big strength for me. (#2701)
This should properly include #2674
Cleaned up the script itself, added progress bars so end users don't think the script is stuck
2016-09-29 22:37:05 -07:00
Daniel Meltzer
b92d26f3c4 When checking out a consumable, don't say asset (#2718) 2016-09-29 22:20:58 -07:00
Daniel Meltzer
2a95a95e00 Company to logs (#2717)
* Fix the actionlog/companyables problem by adding a company_id to all actionlogs and scoping directly on that.  Works around bugs in laravel where trying to hunt down the polymorphic relationship would lead to an infinite loop

* Scope companyables in getactivityreport.  Also eager load.

* Improve reportscontroller, work on seeder to test this.

* Only show company users in checkout dialogs

* If no admin associated with log, it might be a request.  Leave blank instead of saying deleted admin

* When injecting company_id, use target instead of user if user is a superadmin

* Build up the seeder to generate users, companies, and logs.

* Eager load the log, don't scope the users log because the log should already include things only related to the user.
2016-09-29 22:20:49 -07:00
Brady Wetherington
7ca7877740 Fix mismerged code. (#2705) 2016-09-28 22:57:19 -07:00
snipe
1394424760 Merge branch 'hotfixes/customfields_in_asset_report' into develop
# Conflicts:
#	resources/views/models/custom_fields_form.blade.php
2016-09-28 19:28:55 -07:00
snipe
fc07753a5c Use $customfields in closure 2016-09-28 19:18:01 -07:00
snipe
7bbe85801e Fixed typo :( 2016-09-28 15:45:05 -07:00
snipe
8774927b91 PHPStorm lag = fail 2016-09-28 15:40:51 -07:00
snipe
8cb4954f8a Apply encrypted fields patch from develop 2016-09-28 14:58:01 -07:00
snipe
48b52a0ccc Merge branch 'hotfixes/p-typo' into develop 2016-09-28 08:59:07 -07:00
snipe
9ecb0e6ca1 Fixed errant typo 2016-09-28 08:58:16 -07:00
snipe
9091385182 Merge branch 'hotfixes/purchase_cost' into develop
# Conflicts:
#	app/Http/Controllers/ReportsController.php
#	config/version.php
2016-09-27 19:13:21 -07:00
snipe
b90c0de822 Fix companyable reult in maintenances 2016-09-27 19:07:45 -07:00
snipe
ee2522571c Fixes #2673 2016-09-27 19:07:30 -07:00
snipe
d3a13bcd45 Functional config for laravel 5 2016-09-27 18:47:00 -07:00
snipe
67f199b09d Added customfields to asset CSV export 2016-09-27 15:09:47 -07:00
snipe
f1c458185d Client-side pagination on asset report for faster loading 2016-09-27 14:56:05 -07:00
snipe
ed22ec4b36 Bumped hash 2016-09-27 08:42:55 -07:00
snipe
fa72e64b98 Add checkout date to asset report 2016-09-27 08:42:48 -07:00
snipe
2a8ab06ca3 Remove escaping for CSV to prevent weird encoding 2016-09-27 07:25:28 -07:00
snipe
61d07bdc7c Sigh. 2016-09-27 07:24:26 -07:00
snipe
3061ce2983 Missed delimiter for CSV 2016-09-27 07:23:30 -07:00
snipe
e9f3d622f5 Add company name to custom asset report 2016-09-27 07:19:52 -07:00
snipe
1e3244b2b3 Merge branch 'hotfixes/eol' into develop
# Conflicts:
#	app/Http/Controllers/AssetModelsController.php
2016-09-27 07:04:45 -07:00
snipe
a92bfe8ade Default EOL to null, not 0, if no value entered 2016-09-27 06:53:59 -07:00
snipe
c42dfadd17 Merge branch 'hotfixes/purchase_order' into develop
# Conflicts:
#	app/Http/Controllers/LicensesController.php
2016-09-27 01:31:02 -07:00
snipe
0a391de09f Fixes #2682 - search on purchase_order 2016-09-27 01:29:31 -07:00
snipe
b6cc7e7c14 Fixes bug where 12-hour fprmat for hours was used 2016-09-26 22:35:51 -07:00
snipe
819ca2921b Fixes bug where 12-hour format was used for hours 2016-09-26 22:34:09 -07:00
Joris van Eijden
7d272e3c96 Fix pre-flight port number check. (#2681) 2016-09-26 18:23:56 -07:00
Andrés Núñez
40f00665b3 Translate emails (#2652)
* commit temporal

* final translation commit -- added email translations

* final translation commit -- removed file for spanish translations

* final translation commit -- removed file for spanish translations

* added missing translations

* method overrided and config files back to default

* config files back to default

* config files back to default
2016-09-26 14:13:07 -07:00
tiagom62
03ee6b8f91 SELinux and iptables update for installer (#2674)
* detect SELinux

detect SELinux is enforcing and set required security policies for
CentOS 7

* Centos 6 iptables

allow http/https if iptables is running
2016-09-26 14:11:43 -07:00
snipe
937192f7ce Ugh… git… why? 2016-09-23 14:13:41 -07:00
snipe
ce1f62b9be Merge branch 'hotfixes/2672' into develop
# Conflicts:
#	app/Http/Controllers/ReportsController.php
2016-09-23 14:12:52 -07:00
snipe
3208522dd1 Fixes #2672 - model_no field updated to be string 2016-09-23 14:10:08 -07:00
snipe
c3cd329604 Merge branch 'develop' of github.com:snipe/snipe-it into develop 2016-09-23 13:14:18 -07:00
snipe
2ba4986396 Updated history importer message 2016-09-23 13:14:11 -07:00
snipe
8ba19632cf Removed new badge 2016-09-23 13:13:42 -07:00
Michael T
caf6a10227 grr.. Fixed git commit message stuck in file. (#2659) 2016-09-21 15:27:09 -07:00
Eammon Hanlon
580091269d mkdir not recursive (#2460)
* Fix path to snipeit-ssl.crt (#2428)

* Modified 'recursive' part of the tuple to true
2016-09-21 12:05:06 -07:00
Michael T
bcc6ca5180 Deb/Ubu pro bar & Ubu 16 php-xml pkg (#2644) 2016-09-20 13:26:53 -07:00
snipe
7fdd4fbe98 Updates to the history importer to make it a little less brittle and provide better feedback 2016-09-20 09:22:49 -07:00
snipe
aecef2618f Add reply-to for mail 2016-09-20 07:20:40 -07:00
snipe
bd5e6d8551 Add reply-to config setting 2016-09-20 07:20:10 -07:00
snipe
1e4e9dd3d7 Updated language files 2016-09-20 05:08:04 -07:00
snipe
2ab91fed01 Fixes #2607 - non-encrypted now visible to non-admins with asset access 2016-09-20 03:48:38 -07:00
snipe
5b0220ac1e Fixed typo 2016-09-20 03:01:04 -07:00
snipe
aa92b93bd1 Fixes #2622 - add depreciation to license report 2016-09-20 02:58:08 -07:00
snipe
998624ad68 Bumped version for v3.5-beta 2016-09-20 00:50:35 -07:00
snipe
d3d36315d3 Hotfixes adding company name to custom report 2016-09-20 00:49:08 -07:00
snipe
6dc143d95d Use Ajax activity report for dashboard to prevent data duplication 2016-09-20 00:46:46 -07:00
snipe
d8753a7d86 Use Ajax for activity report 2016-09-20 00:46:24 -07:00
snipe
90af734f6b Fix migration from integer to string to handle polymorphic migration 2016-09-20 00:46:14 -07:00
snipe
3aa7c60765 Costometic cleanup 2016-09-20 00:45:25 -07:00
snipe
0962d770cf Ajax activity report 2016-09-20 00:45:16 -07:00
snipe
5d8c06bc30 Eager loading for custom report 2016-09-19 23:52:20 -07:00
snipe
2597a7b896 Added Ajax reporting view 2016-09-19 23:52:01 -07:00
snipe
3741a93884 Added docblocks and cleaned up spacing 2016-09-19 23:51:45 -07:00
snipe
71be73781b Add company name option to reports 2016-09-19 22:27:34 -07:00
Daniel Meltzer
7aea9341f8 Have the installer install php-xml in ubuntu 16.04, it's where the utf8_decode function is located (#2638) 2016-09-19 17:28:07 -07:00
tiagom62
e5098c3ba1 missing semicolon (#2629)
Rookie mistake. Fixes missing semicolon in previous pr #2624.
2016-09-17 11:39:24 -07:00
tiagom62
46507c929a Sort backups newest to oldest (#2624)
Viewing the backup list produces a seemingly random list.

This PR sorts the files newest to oldest.
2016-09-17 00:00:39 -07:00
tiagom62
8233d520c6 Missing file formats (#2621)
Missing allowed file formats zip and rar.

Added rtf format pending PR 2614.
2016-09-16 16:18:33 -07:00
tiagom62
06f174adf9 Allow uploading rtf files (#2620)
Microsoft Open License Order Confirmation's are sent in RTF format. 

This change allows us to upload the RTF files under View License -> File Uploads.
2016-09-16 16:18:24 -07:00
tiagom62
08f320b76a DB_DUMP_PATH not set when using install.sh (#2623)
Backup errors out when DB_DUMP_PATH is not set. According to https://snipe-it.readme.io/docs/configuration#required-database-settings this is usually '/usr/bin'
2016-09-16 16:17:04 -07:00
snipe
04898c49b2 Fixed wrong translation from PR 2016-09-15 20:03:47 -07:00
Karol
eeff305b02 Update dashboard.blade.php (#2593) 2016-09-15 19:59:01 -07:00
Daniel Meltzer
2d8269ddcd Checkout Improvements, and initial support for requesting an asset model (#2573)
* Create a new action_log table to replace asset_log.  Use Polymorphism to generalize class and targets.  Port everything I can find to use it.  Add a migration to port the asset_logs table to action_logs.

* Initial work on requestable asset models

* Backend work for polymorphic requests table to store checkout requests.

* Add missing files

* Add a record to the db when requesting items.  Build up a testing route for interfacing with this.

* Users can now toggle requests of items on the request page.  Reformat page to use the same tab layout we use elsewhere

* Polymorphic request function.  Implement requesting of asset models.  Need to port mail/slack to notifications still.

* Implement requesting of asset models.  Build up emails and notifications to support it.  Allow specifying a quantity of model to request.

* Add view to show currently requested assets.  Needs some work and cleanup, but it isn't accessible from anywhere yet.
2016-09-15 19:58:27 -07:00
snipe
b0a8a0427d Merge branch 'hotfix/license-clone' into develop
# Conflicts:
#	app/Http/Controllers/ReportsController.php
2016-09-14 19:08:06 -07:00
snipe
f384593e19 Fix license cloning 2016-09-14 19:04:52 -07:00
snipe
5846f23d8b Fix stupid migration? Maybe? Might be more trouble later 2016-09-14 18:59:14 -07:00
snipe
91a035ec5b Text BOM text BOM, you’re my Text BOM…. 2016-09-14 18:58:52 -07:00
snipe
d357326dc1 Use PHP streaming to generate asset report to prevent timeouts 2016-09-12 14:10:04 -07:00
snipe
5e2dbaffc4 Use streaming to handle large exports 2016-09-12 14:06:55 -07:00
snipe
391c9a77ef Misc debug template for use with debugging CSV exports, etc 2016-09-12 14:05:31 -07:00
snipe
7bde0f4f92 Fixes #2586 2016-09-08 20:01:46 -07:00
snipe
aa0ccf11fa Only load the remote gravatar image if the server can talk to the outside world 2016-09-07 01:41:23 -07:00
snipe
a8f79369ee Added components checkout gate 2016-09-07 01:15:14 -07:00
snipe
0a506120b7 Hotfix for dumb enum issue 2016-09-06 20:01:10 -07:00
snipe
0e28f36678 Fixes for weird stupid enum issue 2016-09-06 20:00:37 -07:00
Daniel Meltzer
e86adccf19 Actionlog Class: Improvements and polymorphism (#2561)
* Save progress

* Create a new action_log table to replace asset_log.  Use Polymorphism to generalize class and targets.  Port everything I can find to use it.  Add a migration to port the asset_logs table to action_logs.

* Allow accepted_id to be nullable.

* Comment out the thread_id migration, because it b0rks on a new database with the move.  I'm unsure if the thread_id does anything...It doesn't seem to be used

* Clean up all old methods from Actionlog model.  Port everything to use new cleaner interface.

* Port the actionlog factory to fix travis.

* Adjust code to work on php5.  Also fix lurking adminlog call.

* Remove weird code

* Port the pave command.  Also fix dangling adminlog
2016-09-06 19:39:42 -07:00
snipe
e7fba08f92 Merge remote-tracking branch 'origin/develop' 2016-09-06 10:38:31 -07:00
snipe
35f3f1432f Bumped version 2016-09-06 10:38:07 -07:00
snipe
934b39268d Merge remote-tracking branch 'origin/develop' 2016-09-06 10:35:33 -07:00
snipe
67315d81d6 Fixes #2134 - hide archived assets from list all 2016-09-01 13:28:15 -07:00
snipe
eee64d5509 Set the public path for users who can’t use public as a directory (shared hosting) 2016-09-01 12:53:38 -07:00
snipe
b450ef3534 Cast group permissions as array for older, wonky installs 2016-08-30 13:25:14 -07:00
snipe
d4dc1830ec Fixes #2527 - honor the setting for whether Snpie-IT can access the outside world 2016-08-30 12:58:08 -07:00
snipe
04e9ca0942 Fixes #2399 2016-08-30 12:34:23 -07:00
snipe
06021d79c1 Fixed typo 2016-08-30 12:25:46 -07:00
snipe
7ecb8d7bc1 Patches PR#2526 to develop 2016-08-30 12:13:29 -07:00
Ryan Stafford
efe95d9ad0 Syntax error on VOLUME instruction (#2526)
Added quotes to volume path.
2016-08-30 12:11:42 -07:00
snipe
6f89699f1a Make purchase cost default to null
I don’t know why I need to do this?
2016-08-30 08:52:33 -07:00
snipe
2c18bc24a7 Check if username is userprincipalname
If it is, skip building the UPN for AD
2016-08-30 08:34:17 -07:00
snipe
f81b21208b Bumped version for v3.4.0-beta 2016-08-30 07:39:55 -07:00
snipe
ba70e5b053 A little demo-proofing of the maintenances page 2016-08-30 07:34:33 -07:00
snipe
5090468357 Fixes #2510 and #2488 - CSS class added to images in views 2016-08-30 07:20:07 -07:00
snipe
213cda8cf4 Fixes #2525 2016-08-30 07:03:22 -07:00
snipe
421cbf11fc Patches PR#2500 for dev because @dmeltzer forgot that we commit to the develop branch :P 2016-08-30 06:54:04 -07:00
snipe
8816c481af Added HTML for generating passwords in asset user creation modal 2016-08-30 06:48:23 -07:00
snipe
3ed0cf2be8 Moved import errors up higher on the screen, fixed some weird formatting bugaboos 2016-08-30 06:48:00 -07:00
snipe
cd28b012b3 Remove last name requirement in save user request 2016-08-30 06:47:38 -07:00
snipe
25902db659 Generate password from modal 2016-08-30 06:47:18 -07:00
snipe
35a67ab18a Fixes #2516 - listbox error on new asset 2016-08-29 23:49:23 -07:00
snipe
2cfb015b1a Removed extra debugging info 2016-08-29 23:13:30 -07:00
snipe
e4dcd47d6c Fix UTF-8 issues in imports 2016-08-29 22:57:48 -07:00
snipe
64cd4fb1c9 Allow X-Frame-Options to be disabled via env if necessary 2016-08-29 22:57:29 -07:00
Daniel Meltzer
276e0a7114 Importer: Implement item update and interface improvments (#2507)
* Add support for updating assets to the importer.

If an asset with a matching asset tag is found, and the --update flag is
passed to the importer, we edit the matching asset with any
asset-specific values, and persist to the database.  Any missing/blank
values are skipped.

TODO: Add to web interface, add support in consumables/accessories

* Allow deleting of files on the import page.

* Extend web interface to allow updating of imported items.

This adds a modal dialog to the import process.  Currently the dialog
allows the choice of update vs ignore, and choosing the item type to
import (Accessory, Asset, Consumable).

Also use Helper::ParseFloat() for purchase_cost processing.  It exists,
and fixes issues on my end at least.

* Implement editing of consumables and accessories.

* Rename getProcessImportFile to postProcessImportFile to reflect how it's now used

* Fix copy-pasta error.
2016-08-29 15:49:32 -07:00
Daniel Meltzer
9bf3403f31 Fix #2499 (#2500)
Missed this instance when renaming the method. Sorry!
2016-08-26 06:01:58 -07:00
snipe
0d088f3031 Fixes #2491 - show asset tag on dashboard 2016-08-25 21:28:46 -07:00
snipe
a92ed97b4e Definitely not beta ;) 2016-08-25 21:06:43 -07:00
snipe
fcdea4825e Bumped version 2016-08-25 21:04:43 -07:00
snipe
35439f9976 Additional strings 2016-08-25 21:04:36 -07:00
snipe
d473432436 Show encryption in fieldset list 2016-08-25 21:04:25 -07:00
snipe
4dff58ec26 Fix array generation for select 2016-08-25 21:04:10 -07:00
snipe
537ad28a67 Don’t make required encrypted custom fields required if user is not an admin 2016-08-25 21:03:52 -07:00
snipe
96eb832fd3 Only decrypt if the user is an admin 2016-08-25 21:03:24 -07:00
snipe
130c798c90 Only accept a new value for encrypted fields if the user is an admin 2016-08-25 20:59:54 -07:00
snipe
e1229bfb0f Graceful decryption method 2016-08-25 20:58:56 -07:00
snipe
f185c2e0de Hide radio and checkboxes for now 2016-08-25 19:48:11 -07:00
snipe
122f0b9cba Custom fields form in asset edit view 2016-08-25 18:35:28 -07:00
snipe
c49f10c9bb Removed line break 2016-08-25 18:35:16 -07:00
snipe
97a938f119 Method helper to translate piped field_values into a useable array 2016-08-25 18:35:01 -07:00
snipe
308fcf96de Updated language strings 2016-08-25 17:43:07 -07:00
snipe
f1fab8b164 Added Indonesian to dropdown locale list 2016-08-25 17:22:08 -07:00
snipe
0e8502a323 Removed newline 2016-08-25 17:12:50 -07:00
snipe
3171d9230b Better language 2016-08-25 17:12:34 -07:00
snipe
11b9df4b48 Use updated L5 request method 2016-08-25 17:11:52 -07:00
snipe
0c2524954f Removed unusued status_id variable 2016-08-25 17:10:09 -07:00
snipe
b76ad5ea88 Reverted name of form field 2016-08-25 17:08:39 -07:00
snipe
43fbd54a12 Store new fields in the database 2016-08-25 17:08:08 -07:00
snipe
406d270c01 Use L5 Request method for input 2016-08-25 17:07:58 -07:00
snipe
98eb26a2bd Merge branch 'features/cusom_field_types' into develop 2016-08-25 16:36:21 -07:00
snipe
61aa9beddb Added new fields to custom fields views 2016-08-25 16:36:00 -07:00
snipe
e89fd9b3a2 Additional strings 2016-08-25 16:35:45 -07:00
snipe
d72443c335 Use trans() for custom format text 2016-08-25 16:35:31 -07:00
snipe
f38593b530 Merge remote-tracking branch 'origin/develop' 2016-08-23 19:01:53 -07:00
snipe
4cf2d16c7a Temp fix for number import on cost 2016-08-23 19:01:40 -07:00
snipe
f38912a5cf Custom fields additions 2016-08-23 18:52:54 -07:00
snipe
ad22293f4b Added show in nav for status label views and controller 2016-08-23 18:52:42 -07:00
snipe
fb402e138d Smaller dashboard number 2016-08-23 18:52:12 -07:00
snipe
90d2d0c7e1 Fixes #2469 - corrected config app.url 2016-08-23 16:04:22 -07:00
snipe
9d730af50f Added single quotes to env for mail sender 2016-08-23 16:03:57 -07:00
snipe
9407b4e28c Removed console warning 2016-08-23 15:53:18 -07:00
snipe
ec19924bea Custom field types 2016-08-23 15:52:34 -07:00
snipe
7b8403cdb9 Pass status ID to ajax 2016-08-23 15:52:10 -07:00
snipe
85f3e7e3d4 Added filter by status type 2016-08-23 15:51:59 -07:00
snipe
11dc20de61 Show in nav language option 2016-08-23 15:51:45 -07:00
snipe
14fa7ed965 Fixed indenting 2016-08-23 15:51:14 -07:00
snipe
5cf1c8dfa3 Added DB DUMP PATH to docker.env 2016-08-23 15:51:05 -07:00
snipe
f04cfb3e7f Allow admins to show status labels in nav 2016-08-23 15:50:52 -07:00
snipe
d970daa666 Add new fields to custom fields table 2016-08-23 15:50:43 -07:00
snipe
0b0c81a110 Merge remote-tracking branch 'origin/develop' 2016-08-23 11:38:03 -07:00
snipe
b1324c2e64 Removed beta from version 2016-08-23 11:37:49 -07:00
snipe
3c28be33c5 Bumped version 2016-08-23 11:37:00 -07:00
snipe
e52a0f65bb Update asset report to show deployed if asset is checked out 2016-08-23 11:36:34 -07:00
snipe
b726d131a4 More helpful message for LDAP TLS issue 2016-08-23 11:32:11 -07:00
snipe
014167699d Fixes #2441 - use showAssetName to avoid blank entries in link name which makes Slack do weird things 2016-08-18 13:10:31 -07:00
snipe
d9f2e7bf58 If custom field is type URL, display it as a link 2016-08-18 12:44:55 -07:00
snipe
4c8c58d453 Clean up divs for gates in list view 2016-08-18 12:31:45 -07:00
snipe
923352537c Moved column for in/out 2016-08-18 07:06:55 -07:00
snipe
be8049b41a Include asset maintenances in purge 2016-08-18 07:06:15 -07:00
snipe
4419dc7434 Merge branch 'fix-double-format' of https://github.com/dmeltzer/snipe-it into dmeltzer-fix-double-format
# Conflicts:
#	app/Http/Controllers/ConsumablesController.php
#	app/Http/Controllers/LicensesController.php
#	resources/views/hardware/view.blade.php
2016-08-16 18:53:45 -07:00
Daniel Meltzer
ac63642224 Add manufacturer to licenses (#2436)
* Add manufacturer to licenses.  Shows in table and edit.  Need to improve manufacturer view to show lists beyond assets still.

* Remove extra closing tags, formatting

* Work on making the manufacturer view show more options. Need to figure out how to change the table dynamically.

* Cleanup formatting and fix a few weirdities in hardware/view.blade.php

* Standardize on two-space tabs in this file, as it seems the most
* common.

* Fix a few places where we call number_format without guaranteeing the
* item is a number and not a string.

* Show a "No Results" message on components page if there are no
* components.

* Show table of licenses on manufacturer view page.

This reworks the ManufacturersController::getDataView method to delegate
the view to a sub method (currently assets or licenses, but plan to
extend to consumables/accessories/components as well).  We then put tabs
at the top of the view to show multiple tables.  This just duplicates
the table layout from licenses/index.blade, but I wonder if theres a way
to centralize that code, maybe through partials, over time..

The only known missing part of manufacturers for licenses would be adding it
to the importer, but the license importer should probably migrate to
object importer before doing too much more...

* Add manufacturer to accessory.

* Add consumables to the manufacturer view page.
2016-08-16 18:49:54 -07:00
Daniel Meltzer
5959f83de3 Rename parseCurrencyString to formatCurrencyOutput to clarify what it does better. 2016-08-16 20:47:53 -05:00
Daniel Meltzer
0c912bcf49 Fix more number_format madness.
This does two main things:
1) The importer now imports as numbers, not parsed strings.  This allows
is to format values on output instead of input, which is what was
happening in most places.

2) Add a Helper::parseCurrencyString method and port everything to use
this.  This checks to see if the value is numeric or empty, and returns
the appropriate value in all cases.  Should fix all known occurances of
number_format expections.
2016-08-16 20:41:28 -05:00
snipe
16014945b6 Merge remote-tracking branch 'origin/develop' 2016-08-16 18:23:36 -07:00
snipe
44821b9667 Fixes #2404 Only update name of asset if it isn't null. 2016-08-16 18:23:20 -07:00
snipe
c5d7a1fdd6 Merge remote-tracking branch 'origin/develop' 2016-08-16 18:21:05 -07:00
snipe
29c4189419 Bumped version 2016-08-16 18:20:42 -07:00
Daniel Meltzer
7ef4f23d0f Validate that purchase_cost is a numeric value. (#2452) 2016-08-16 18:18:50 -07:00
timwsuqld
8232cefbba Fix path to snipeit-ssl.crt (#2428) 2016-08-16 13:03:55 -07:00
Daniel Meltzer
a852c624d3 Fix 2347 (#2394)
* Prevent multiple checkouts of the same asset.

This adds a new method to the Asset model, availableForCheckout.
Port getDataTable to use availableForCheckout instead of doing the
check manually.

Fixes Issue #2347

* Use availableForCheckout in categories controller.  Also gate the checkin/checkout actions here.

* Use gate and availableForCheckout in manufactuers as well.
2016-08-16 13:02:42 -07:00
snipe
7edf1db101 Small tweaks to history 2016-08-12 19:03:32 -07:00
654 changed files with 10073 additions and 4640 deletions

View File

@@ -30,7 +30,9 @@ MAIL_USERNAME=YOURUSERNAME
MAIL_PASSWORD=YOURPASSWORD
MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
# --------------------------------------------
@@ -74,4 +76,5 @@ AWS_BUCKET=null
APP_LOG=single
APP_LOCKED=false
FILESYSTEM_DISK=local
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false

View File

@@ -80,7 +80,7 @@ RUN cd /var/www/html;composer install
############### DATA VOLUME #################
VOLUME [/var/lib/snipeit]
VOLUME ["/var/lib/snipeit"]
##### START SERVER

View File

@@ -1,25 +1,27 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use League\Csv\Reader;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\CustomField;
use App\Models\Location;
use App\Models\Manufacturer;
use App\Models\Setting;
use App\Models\Statuslabel;
use App\Models\Supplier;
use App\Models\User;
use App\Models\CustomField;
use DB;
use App\Models\Setting;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Model;
use League\Csv\Reader;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use ForceUTF8\Encoding;
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
ini_set('memory_limit', '500M');
@@ -102,9 +104,17 @@ class ObjectImportCommand extends Command
$this->companies = Company::All(['name', 'id']);
$this->status_labels = Statuslabel::All(['name', 'id']);
$this->suppliers = Supplier::All(['name', 'id']);
$this->assets = Asset::all(['asset_tag']);
$this->accessories = Accessory::All(['name']);
$this->consumables = Consumable::All(['name']);
switch (strtolower($this->option('item-type'))) {
case "asset":
$this->assets = Asset::all();
break;
case "accessory":
$this->accessories = Accessory::All();
break;
case "consumable":
$this->consumables = Consumable::All();
break;
}
$this->customfields = CustomField::All(['name']);
$bar = null;
@@ -275,7 +285,7 @@ class ObjectImportCommand extends Command
*/
public function array_smart_fetch(array $array, $key, $default = '')
{
return array_key_exists($key, $array) ? e(trim($array[ $key ])) : $default;
return array_key_exists(trim($key), $array) ? e(Encoding::fixUTF8(trim($array[ $key ]))) : $default;
}
@@ -313,7 +323,7 @@ class ObjectImportCommand extends Command
$asset_model_name = $this->array_smart_fetch($row, "model name");
$asset_modelno = $this->array_smart_fetch($row, "model number");
if (empty($asset_model_name)) {
$asset_model_name='Unknown';
$asset_model_name ='Unknown';
}
if (empty($asset_modelno)) {
$asset_modelno='';
@@ -346,6 +356,7 @@ class ObjectImportCommand extends Command
return $asset_model;
} else {
$this->jsonError('Asset Model "' . $asset_model_name . '"', $asset_model->getErrors());
$this->log('Asset Model "' . $asset_model_name . '"', $asset_model->getErrors());
return $asset_model;
}
} else {
@@ -732,6 +743,24 @@ class ObjectImportCommand extends Command
*/
public function createAssetIfNotExists(array $row, array $item)
{
$asset = null;
$editingAsset = false;
foreach ($this->assets as $tempasset) {
if (strcasecmp($tempasset->asset_tag, $item['asset_tag']) == 0) {
$this->log('A matching Asset ' . $item['asset_tag'] . ' already exists');
if (!$this->option('update')) {
$this->log("Skipping item.");
return;
}
$this->log('Updating matching asset with new values');
$editingAsset = true;
$asset = $tempasset;
}
}
if (is_null($asset)) {
$this->log("No Matching Asset, Creating a new one");
$asset = new Asset;
}
$asset_serial = $this->array_smart_fetch($row, "serial number");
$asset_image = $this->array_smart_fetch($row, "image");
$asset_warranty_months = intval($this->array_smart_fetch($row, "warranty months"));
@@ -747,12 +776,7 @@ class ObjectImportCommand extends Command
$this->log('Notes: '.$item["notes"]);
$this->log('Warranty Months: ' . $asset_warranty_months);
foreach ($this->assets as $tempasset) {
if (strcasecmp($tempasset->asset_tag, $item['asset_tag']) == 0) {
$this->log('A matching Asset ' . $item['asset_tag'] . ' already exists');
return;
}
}
if ($item["status_label"]) {
$status_id = $item["status_label"]->id;
@@ -763,12 +787,14 @@ class ObjectImportCommand extends Command
$status_id = 1;
}
$asset = new Asset();
$asset->name = $item["item_name"];
if ($item["purchase_date"] != '') {
if (!$editingAsset) {
$asset->asset_tag = $item['asset_tag']; // This doesn't need to be guarded for empty because it's the key we use to identify the asset.
}
if (!empty($item['item_name'])) {
$asset->name = $item["item_name"];
}
if (!empty($item["purchase_date"])) {
$asset->purchase_date = $item["purchase_date"];
} else {
$asset->purchase_date = null;
}
if (array_key_exists('custom_fields', $item)) {
@@ -780,37 +806,53 @@ class ObjectImportCommand extends Command
if (!empty($item["purchase_cost"])) {
//TODO How to generalize this for not USD?
$purchase_cost = substr($item["purchase_cost"], 0, 1) === '$' ? substr($item["purchase_cost"], 1) : $item["purchase_cost"];
$asset->purchase_cost = number_format($purchase_cost, 2);
// $asset->purchase_cost = number_format($purchase_cost, 2, '.', '');
$asset->purchase_cost = Helper::ParseFloat($purchase_cost);
$this->log("Asset cost parsed: " . $asset->purchase_cost);
} else {
$asset->purchase_cost = 0.00;
}
$asset->serial = $asset_serial;
$asset->asset_tag = $item['asset_tag'];
$asset->warranty_months = $asset_warranty_months;
if (!empty($asset_serial)) {
$asset->serial = $asset_serial;
}
if (!empty($asset_warranty_months)) {
$asset->warranty_months = $asset_warranty_months;
}
if ($asset_model) {
$asset->model_id = $asset_model->id;
}
if ($item["user"]) {
$asset->assigned_to = $item["user"]->id;
}
if ($item["location"]) {
$asset->rtd_location_id = $item["location"]->id;
}
$asset->user_id = $this->option('user_id');
$this->log("status_id: " . $status_id);
$asset->status_id = $status_id;
if (!empty($status_id)) {
$asset->status_id = $status_id;
}
if ($item["company"]) {
$asset->company_id = $item["company"]->id;
}
$asset->order_number = $item["order_number"];
if ($item["order_number"]) {
$asset->order_number = $item["order_number"];
}
if ($supplier) {
$asset->supplier_id = $supplier->id;
}
$asset->notes = $item["notes"];
$asset->image = $asset_image;
$this->assets->add($asset);
if ($item["notes"]) {
$asset->notes = $item["notes"];
}
if (!empty($asset_image)) {
$asset->image = $asset_image;
}
if (!$editingAsset) {
$this->assets->add($asset);
}
if (!$this->option('testrun')) {
if ($asset->save()) {
@@ -835,17 +877,29 @@ class ObjectImportCommand extends Command
*/
public function createAccessoryIfNotExists(array $item)
{
$accessory = null;
$editingAccessory = false;
$this->log("Creating Accessory");
foreach ($this->accessories as $tempaccessory) {
if (strcasecmp($tempaccessory->name, $item["item_name"]) == 0) {
$this->log('A matching Accessory ' . $item["item_name"] . ' already exists. ');
// FUTURE: Adjust quantity on import maybe?
return;
if (!$this->option('update')) {
$this->log("Skipping accessory.");
return;
}
$this->log('Updating matching accessory with new values');
$editingAccessory = true;
$accessory = $tempaccessory;
}
}
if (is_null($accessory)) {
$this->log("No Matching Accessory, Creating a new one");
$accessory = new Accessory();
}
$accessory = new Accessory();
$accessory->name = $item["item_name"];
if (!$editingAccessory) {
$accessory->name = $item["item_name"];
}
if (!empty($item["purchase_date"])) {
$accessory->purchase_date = $item["purchase_date"];
@@ -853,10 +907,9 @@ class ObjectImportCommand extends Command
$accessory->purchase_date = null;
}
if (!empty($item["purchase_cost"])) {
$accessory->purchase_cost = number_format(e($item["purchase_cost"]), 2);
} else {
$accessory->purchase_cost = 0.00;
$accessory->purchase_cost = Helper::ParseFloat($item["purchase_cost"]);
}
if ($item["location"]) {
$accessory->location_id = $item["location"]->id;
}
@@ -864,20 +917,26 @@ class ObjectImportCommand extends Command
if ($item["company"]) {
$accessory->company_id = $item["company"]->id;
}
$accessory->order_number = $item["order_number"];
if (!empty($item["order_number"])) {
$accessory->order_number = $item["order_number"];
}
if ($item["category"]) {
$accessory->category_id = $item["category"]->id;
}
//TODO: Implement
// $accessory->notes = e($item_notes);
$accessory->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
if (!empty($item["requestable"])) {
$accessory->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
}
//Must have at least zero of the item if we import it.
if ($item["quantity"] > -1) {
$accessory->qty = $item["quantity"];
} else {
$accessory->qty = 1;
if (!empty($item["quantity"])) {
if ($item["quantity"] > -1) {
$accessory->qty = $item["quantity"];
} else {
$accessory->qty = 1;
}
}
if (!$this->option('testrun')) {
@@ -904,18 +963,29 @@ class ObjectImportCommand extends Command
*/
public function createConsumableIfNotExists(array $item)
{
$consumable = null;
$editingConsumable = false;
$this->log("Creating Consumable");
foreach ($this->consumables as $tempconsumable) {
if (strcasecmp($tempconsumable->name, $item["item_name"]) == 0) {
$this->log("A matching consumable " . $item["item_name"] . " already exists");
//TODO: Adjust quantity if different maybe?
return;
if (!$this->option('update')) {
$this->log("Skipping consumable.");
return;
}
$this->log('Updating matching consumable with new values');
$editingConsumable = true;
$consumable = $tempconsumable;
}
}
$consumable = new Consumable();
$consumable->name = $item["item_name"];
if (is_null($consumable)) {
$this->log("No matching consumable, creating one");
$consumable = new Consumable();
}
if (!$editingConsumable) {
$consumable->name = $item["item_name"];
}
if (!empty($item["purchase_date"])) {
$consumable->purchase_date = $item["purchase_date"];
} else {
@@ -923,26 +993,37 @@ class ObjectImportCommand extends Command
}
if (!empty($item["purchase_cost"])) {
$consumable->purchase_cost = number_format(e($item["purchase_cost"]), 2);
} else {
$consumable->purchase_cost = 0.00;
$consumable->purchase_cost = Helper::ParseFloat($item["purchase_cost"]);
}
if ($item["location"]) {
$consumable->location_id = $item["location"]->id;
}
$consumable->location_id = $item["location"]->id;
$consumable->user_id = $this->option('user_id');
$consumable->company_id = $item["company"]->id;
$consumable->order_number = $item["order_number"];
$consumable->category_id = $item["category"]->id;
if ($item["company"]) {
$consumable->company_id = $item["company"]->id;
}
if (!empty($item["order_number"])) {
$consumable->order_number = $item["order_number"];
}
if ($item["category"]) {
$consumable->category_id = $item["category"]->id;
}
// TODO:Implement
//$consumable->notes= e($item_notes);
$consumable->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
if (!empty($item["requestable"])) {
$consumable->requestable = filter_var($item["requestable"], FILTER_VALIDATE_BOOLEAN);
}
if ($item["quantity"] > -1) {
$consumable->qty = $item["quantity"];
} else {
$consumable->qty = 1;
if (!empty($item["quantity"])) {
if ($item["quantity"] > -1) {
$consumable->qty = $item["quantity"];
} else {
$consumable->qty = 1;
}
}
if (!$this->option("testrun")) {
// dd($consumable);
if ($consumable->save()) {
$this->log("Consumable " . $item["item_name"] . ' was created');
// $this->comment("Consumable " . $item["item_name"] . ' was created');
@@ -985,8 +1066,9 @@ class ObjectImportCommand extends Command
array('testrun', null, InputOption::VALUE_NONE, 'If set, will parse and output data without adding to database', null),
array('logfile', null, InputOption::VALUE_REQUIRED, 'The path to log output to. storage/logs/importer.log by default', storage_path('logs/importer.log') ),
array('item-type', null, InputOption::VALUE_REQUIRED, 'Item Type To import. Valid Options are Asset, Consumable, Or Accessory', 'Asset'),
array('web-importer', null, InputOption::VALUE_NONE, 'Internal: packages output for use with the web importer'),
array('user_id', null, InputOption::VALUE_REQUIRED, 'ID of user creating items', 1)
array('web-importer', null, InputOption::VALUE_NONE, 'Internal: packages output for use with the web importer'),
array('user_id', null, InputOption::VALUE_REQUIRED, 'ID of user creating items', 1),
array('update', null, InputOption::VALUE_NONE, 'If a matching item is found, update item information'),
);
}

View File

@@ -77,6 +77,8 @@ class PaveIt extends Command
DB::statement('delete from asset_logs');
DB::statement('delete from asset_maintenances');
DB::statement('delete from asset_uploads');
DB::statement('delete from action_logs');
DB::statement('delete from checkout_requests');
DB::statement('delete from consumables_users');
DB::statement('delete from custom_field_custom_fieldset');
DB::statement('delete from custom_fields');
@@ -92,10 +94,12 @@ class PaveIt extends Command
\DB::statement('drop table IF EXISTS accessories_users');
\DB::statement('drop table IF EXISTS accessories');
\DB::statement('drop table IF EXISTS asset_logs');
\DB::statement('drop table IF EXISTS action_logs');
\DB::statement('drop table IF EXISTS asset_maintenances');
\DB::statement('drop table IF EXISTS asset_uploads');
\DB::statement('drop table IF EXISTS assets');
\DB::statement('drop table IF EXISTS categories');
\DB::statement('drop table IF EXISTS checkout_requests');
\DB::statement('drop table IF EXISTS companies');
\DB::statement('drop table IF EXISTS consumables_users');
\DB::statement('drop table IF EXISTS consumables');

View File

@@ -62,15 +62,19 @@ class Purge extends Command
$assetcount = $assets->count();
$this->info($assets->count().' assets purged.');
$asset_assoc = 0;
$asset_maintenances = 0;
foreach ($assets as $asset) {
$this->info('- Asset "'.$asset->showAssetName().'" deleted.');
$asset_assoc += $asset->assetlog()->count();
$asset->assetlog()->forceDelete();
$asset_maintenances += $asset->assetmaintenances()->count();
$asset->assetmaintenances()->forceDelete();
$asset->forceDelete();
}
$this->info($asset_assoc.' corresponding log records purged.');
$this->info($asset_maintenances.' corresponding maintenance records purged.');
$locations = Location::whereNotNull('deleted_at')->withTrashed()->get();
$this->info($locations->count().' locations purged.');

View File

@@ -66,7 +66,7 @@ class SendExpirationAlerts extends Command
$asset_data['email_content'] .= '<td><a href="'.config('app.url').'/hardware/'.e($asset->id).'/view">';
$asset_data['email_content'] .= $asset->showAssetName().'</a></td><td>'.e($asset->asset_tag).'</td>';
$asset_data['email_content'] .= '<td>'.e($asset->warrantee_expires()).'</td>';
$asset_data['email_content'] .= '<td>'.$difference.' days</td>';
$asset_data['email_content'] .= '<td>'.$difference.' '.trans('mail.days').'</td>';
$asset_data['email_content'] .= '<td>'.($asset->supplier ? e($asset->supplier->name) : '').'</td>';
$asset_data['email_content'] .= '<td>'.($asset->assigneduser ? e($asset->assigneduser->fullName()) : '').'</td>';
$asset_data['email_content'] .= '</tr>';
@@ -100,17 +100,21 @@ class SendExpirationAlerts extends Command
if (count($expiring_assets) > 0) {
$this->info('Report sent to '.Setting::getSettings()->alert_email);
\Mail::send('emails.expiring-assets-report', $asset_data, function ($m) {
$m->to(explode(',', Setting::getSettings()->alert_email), Setting::getSettings()->site_name);
$m->subject('Expiring Assets Report');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Expiring_Assets_Report'));
});
}
if (count($expiring_licenses) > 0) {
$this->info('Report sent to '.Setting::getSettings()->alert_email);
\Mail::send('emails.expiring-licenses-report', $license_data, function ($m) {
$m->to(explode(',', Setting::getSettings()->alert_email), Setting::getSettings()->site_name);
$m->subject('Expiring Licenses Report');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Expiring_Licenses_Report'));
});
}

View File

@@ -50,7 +50,8 @@ class SendInventoryAlerts extends Command
if (count($data['data']) > 0) {
\Mail::send('emails.low-inventory', $data, function ($m) {
$m->to(explode(',', Setting::getSettings()->alert_email), Setting::getSettings()->site_name);
$m->subject('Low Inventory Report');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Low_Inventory_Report'));
});
}

View File

@@ -17,6 +17,8 @@ use App\Models\Component;
use App\Models\Accessory;
use App\Models\Consumable;
use App\Models\Asset;
use Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
/*
* To change this license header, choose License Headers in Project Properties.
@@ -43,6 +45,17 @@ class Helper
return array_walk($emails_array, 'trim_value');
}
public static function formatCurrencyOutput($cost)
{
// The importer has formatted number strings since v3, so the value might be a string, or an integer.
// If it's a number, format it as a string
if (is_numeric($cost)) {
return number_format($cost, 2, '.', '');
}
// It's already been parsed.
return $cost;
}
// This doesn't do anything yet
public static function trim_value(&$value)
{
@@ -191,7 +204,7 @@ class Helper
public static function usersList()
{
$users_list = array( '' => trans('general.select_user')) +
User::where('deleted_at', '=', null)
Company::scopeCompanyables(User::where('deleted_at', '=', null))
->where('show_in_list','=',1)
->orderBy('last_name', 'asc')
->orderBy('first_name', 'asc')->get()
@@ -226,7 +239,7 @@ class Helper
{
$keys=array_keys(CustomField::$PredefinedFormats);
$stuff=array_combine($keys, $keys);
return $stuff+["" => "Custom Format..."];
return $stuff+["" => trans('admin/custom_fields/general.custom_format')];
}
public static function barcodeDimensions($barcode_type = 'QRCODE')
@@ -465,6 +478,33 @@ class Helper
}
public static function gracefulDecrypt(CustomField $field, $string) {
if ($field->isFieldDecryptable($string)) {
try {
Crypt::decrypt($string);
return Crypt::decrypt($string);
} catch (DecryptException $e) {
return 'Error Decrypting: '.$e->getMessage();
}
}
return $string;
}
public static function stripTagsFromJSON(Array $array) {
foreach ($array as $key => $value) {
$clean_value = strip_tags($value);
$clean_array[$key] = $clean_value;
}
return $clean_array;
}
}

View File

@@ -53,14 +53,12 @@ class AccessoriesController extends Controller
public function getCreate(Request $request)
{
// Show the page
$category_list = Helper::categoryList('accessory');
$company_list = Helper::companyList();
$location_list = Helper::locationsList();
return View::make('accessories/edit')
->with('accessory', new Accessory)
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list);
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -77,12 +75,13 @@ class AccessoriesController extends Controller
$accessory = new Accessory();
// Update the accessory data
$accessory->name = e(Input::get('name'));
$accessory->category_id = e(Input::get('category_id'));
$accessory->location_id = e(Input::get('location_id'));
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->name = e(Input::get('name'));
$accessory->category_id = e(Input::get('category_id'));
$accessory->location_id = e(Input::get('location_id'));
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$accessory->order_number = e(Input::get('order_number'));
$accessory->manufacturer_id = e(Input::get('manufacturer_id'));
if (e(Input::get('purchase_date')) == '') {
$accessory->purchase_date = null;
@@ -93,11 +92,11 @@ class AccessoriesController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$accessory->purchase_cost = null;
} else {
$accessory->purchase_cost = e(Input::get('purchase_cost'));
$accessory->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$accessory->qty = e(Input::get('qty'));
$accessory->user_id = Auth::user()->id;
$accessory->qty = e(Input::get('qty'));
$accessory->user_id = Auth::user()->id;
// Was the accessory created?
if ($accessory->save()) {
@@ -126,14 +125,11 @@ class AccessoriesController extends Controller
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
}
$category_list = Helper::categoryList('accessory');
$company_list = Helper::companyList();
$location_list = Helper::locationsList();
return View::make('accessories/edit', compact('accessory'))
->with('category_list', $category_list)
->with('company_list', $company_list)
->with('location_list', $location_list);
->with('category_list', Helper::categoryList('accessory'))
->with('company_list', Helper::companyList())
->with('location_list', Helper::locationsList())
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -146,9 +142,9 @@ class AccessoriesController extends Controller
*/
public function postEdit(Request $request, $accessoryId = null)
{
// Check if the blog post exists
// Check if the accessory exists
if (is_null($accessory = Accessory::find($accessoryId))) {
// Redirect to the blogs management page
// Redirect to the accessory index page
return redirect()->to('admin/accessories')->with('error', trans('admin/accessories/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($accessory)) {
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
@@ -160,11 +156,12 @@ class AccessoriesController extends Controller
if (e(Input::get('location_id')) == '') {
$accessory->location_id = null;
} else {
$accessory->location_id = e(Input::get('location_id'));
$accessory->location_id = e(Input::get('location_id'));
}
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->min_amt = e(Input::get('min_amt'));
$accessory->category_id = e(Input::get('category_id'));
$accessory->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
$accessory->manufacturer_id = e(Input::get('manufacturer_id'));
$accessory->order_number = e(Input::get('order_number'));
if (e(Input::get('purchase_date')) == '') {
@@ -181,9 +178,9 @@ class AccessoriesController extends Controller
$accessory->qty = e(Input::get('qty'));
// Was the accessory created?
// Was the accessory updated?
if ($accessory->save()) {
// Redirect to the new accessory page
// Redirect to the updated accessory page
return redirect()->to("admin/accessories")->with('success', trans('admin/accessories/message.update.success'));
}
@@ -312,14 +309,7 @@ class AccessoriesController extends Controller
'user_id' => Auth::user()->id,
'assigned_to' => e(Input::get('assigned_to'))));
$logaction = new Actionlog();
$logaction->accessory_id = $accessory->id;
$logaction->asset_id = 0;
$logaction->checkedout_to = $accessory->assigned_to;
$logaction->asset_type = 'accessory';
$logaction->location_id = $user->location_id;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction = $accessory->logCheckout(e(Input::get('note')));
@@ -343,11 +333,11 @@ class AccessoriesController extends Controller
'fields' => [
[
'title' => 'Checked Out:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/accessories/'.$accessory->id.'/view'.'|'.$accessory->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
'value' => 'Accessory <'.config('app.url').'/admin/accessories/'.$accessory->id.'/view'.'|'.$accessory->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
],
[
'title' => 'Note:',
'value' => e($logaction->note)
'value' => e(Input::get('note'))
],
]
])->send('Accessory Checked Out');
@@ -358,9 +348,6 @@ class AccessoriesController extends Controller
}
$log = $logaction->logaction('checkout');
$accessory_user = DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
$data['log_id'] = $logaction->id;
@@ -378,7 +365,8 @@ class AccessoriesController extends Controller
Mail::send('emails.accept-accessory', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm accessory delivery');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_accessory_delivery'));
});
}
@@ -438,8 +426,7 @@ class AccessoriesController extends Controller
return redirect()->to('admin/accessories')->with('error', trans('general.insufficient_permissions'));
}
$logaction = new Actionlog();
$logaction->checkedout_to = e($accessory_user->assigned_to);
$logaction = $accessory->logCheckin(e(Input::get('note')));
$return_to = e($accessory_user->assigned_to);
$admin_user = Auth::user();
@@ -447,12 +434,6 @@ class AccessoriesController extends Controller
// Was the accessory updated?
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
$logaction->accessory_id = e($accessory->id);
$logaction->location_id = null;
$logaction->asset_type = 'accessory';
$logaction->user_id = e($admin_user->id);
$logaction->note = e(Input::get('note'));
$settings = Setting::getSettings();
if ($settings->slack_endpoint) {
@@ -472,7 +453,7 @@ class AccessoriesController extends Controller
'fields' => [
[
'title' => 'Checked In:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/accessories/'.e($accessory->id).'/view'.'|'.e($accessory->name).'> checked in by <'.config('app.url').'/admin/users/'.e($admin_user->id).'/view'.'|'.e($admin_user->fullName()).'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' <'.config('app.url').'/admin/accessories/'.e($accessory->id).'/view'.'|'.e($accessory->name).'> checked in by <'.config('app.url').'/admin/users/'.e($admin_user->id).'/view'.'|'.e($admin_user->fullName()).'>.'
],
[
'title' => 'Note:',
@@ -488,9 +469,6 @@ class AccessoriesController extends Controller
}
$log = $logaction->logaction('checkin from');
if (!is_null($accessory_user->assigned_to)) {
$user = User::find($accessory_user->assigned_to);
}
@@ -506,7 +484,8 @@ class AccessoriesController extends Controller
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm Accessory Checkin');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_Accessory_Checkin'));
});
}
@@ -617,10 +596,12 @@ class AccessoriesController extends Controller
'min_amt' => e($accessory->min_amt),
'location' => ($accessory->location) ? e($accessory->location->name): '',
'purchase_date' => e($accessory->purchase_date),
'purchase_cost' => number_format($accessory->purchase_cost, 2),
'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost),
'numRemaining' => $accessory->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name)
'companyName' => is_null($company) ? '' : e($company->name),
'manufacturer' => $accessory->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$accessory->manufacturer_id.'/view', $accessory->manufacturer->name) : ''
);
}

View File

@@ -122,20 +122,18 @@ class AssetMaintenancesController extends Controller
$actions = '<nobr><a href="'.route('update/asset_maintenance', $maintenance->id).'" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a><a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'.route('delete/asset_maintenance', $maintenance->id).'" data-content="'.trans('admin/asset_maintenances/message.delete.confirm').'" data-title="'.trans('general.delete').' '.htmlspecialchars($maintenance->title).'?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></nobr>';
if (($maintenance->cost) && ($maintenance->asset->assetloc) && ($maintenance->asset->assetloc->currency!='')) {
if (($maintenance->cost) && (isset($maintenance->asset)) && ($maintenance->asset->assetloc) && ($maintenance->asset->assetloc->currency!='')) {
$maintenance_cost = $maintenance->asset->assetloc->currency.$maintenance->cost;
} else {
$maintenance_cost = $settings->default_currency.$maintenance->cost;
}
$company = $maintenance->asset->company;
$rows[] = array(
'id' => $maintenance->id,
'asset_name' => (string)link_to('/hardware/'.$maintenance->asset->id.'/view', $maintenance->asset->showAssetName()) ,
'asset_name' => ($maintenance->asset) ? (string)link_to('/hardware/'.$maintenance->asset->id.'/view', $maintenance->asset->showAssetName()) : 'Deleted Asset' ,
'title' => $maintenance->title,
'notes' => $maintenance->notes,
'supplier' => $maintenance->supplier->name,
'supplier' => ($maintenance->supplier) ? (string)link_to('/admin/settings/suppliers/'.$maintenance->supplier->id.'/view', $maintenance->supplier->name) : 'Deleted Supplier',
'cost' => $maintenance_cost,
'asset_maintenance_type' => e($maintenance->asset_maintenance_type),
'start_date' => $maintenance->start_date,
@@ -143,7 +141,7 @@ class AssetMaintenancesController extends Controller
'completion_date' => $maintenance->completion_date,
'user_id' => ($maintenance->admin) ? (string)link_to('/admin/users/'.$maintenance->admin->id.'/view', $maintenance->admin->fullName()) : '',
'actions' => $actions,
'companyName' => is_null($company) ? '' : $company->name
'companyName' => ($maintenance->asset->company) ? $maintenance->asset->company->name : ''
);
}
@@ -217,7 +215,7 @@ class AssetMaintenancesController extends Controller
if (e(Input::get('cost')) == '') {
$assetMaintenance->cost = '';
} else {
$assetMaintenance->cost = e(Input::get('cost'));
$assetMaintenance->cost = Helper::ParseFloat(e(Input::get('cost')));
}
if (e(Input::get('notes')) == '') {
@@ -365,7 +363,7 @@ class AssetMaintenancesController extends Controller
if (e(Input::get('cost')) == '') {
$assetMaintenance->cost = '';
} else {
$assetMaintenance->cost = e(Input::get('cost'));
$assetMaintenance->cost = Helper::ParseFloat(e(Input::get('cost')));
}
if (e(Input::get('notes')) == '') {

View File

@@ -92,19 +92,19 @@ class AssetModelsController extends Controller
$model->eol = e(Input::get('eol'));
}
// Save the model data
$model->name = e(Input::get('name'));
$model->modelno = e(Input::get('modelno'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->note = e(Input::get('note'));
$model->user_id = Auth::user()->id;
// Save the model data
$model->name = e(Input::get('name'));
$model->modelno = e(Input::get('modelno'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->note = e(Input::get('note'));
$model->user_id = Auth::user()->id;
$model->requestable = Input::has('requestable');
if (Input::get('custom_fieldset')!='') {
$model->fieldset_id = e(Input::get('custom_fieldset'));
}
//$model->show_mac_address = e(Input::get('show_mac_address', '0'));
if (Input::file('image')) {
$image = Input::file('image');
@@ -141,7 +141,7 @@ class AssetModelsController extends Controller
$model = new AssetModel;
$settings=Input::all();
$settings['eol']=0;
$settings['eol']= null;
$model->name=e(Input::get('name'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
@@ -149,7 +149,7 @@ class AssetModelsController extends Controller
$model->modelno = e(Input::get('modelno'));
$model->user_id = Auth::user()->id;
$model->note = e(Input::get('note'));
$model->eol=0;
$model->eol= null;
if (Input::get('fieldset_id')=='') {
$model->fieldset_id = null;
@@ -217,7 +217,7 @@ class AssetModelsController extends Controller
}
if (e(Input::get('eol')) == '') {
$model->eol = 0;
$model->eol = null;
} else {
$model->eol = e(Input::get('eol'));
}
@@ -227,7 +227,10 @@ class AssetModelsController extends Controller
$model->modelno = e(Input::get('modelno'));
$model->manufacturer_id = e(Input::get('manufacturer_id'));
$model->category_id = e(Input::get('category_id'));
$model->note = e(Input::get('note'));
$model->note = e(Input::get('note'));
$model->requestable = Input::has('requestable');
if (Input::get('custom_fieldset')=='') {
$model->fieldset_id = null;
} else {

View File

@@ -178,7 +178,7 @@ class AssetsController extends Controller
if (e(Input::get('purchase_cost')) == '') {
$asset->purchase_cost = null;
} else {
$asset->purchase_cost = (e(Input::get('purchase_cost')));
$asset->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (e(Input::get('purchase_date')) == '') {
@@ -231,7 +231,7 @@ class AssetsController extends Controller
$directory= public_path('uploads/assets/');
// Check if the uploads directory exists. If not, try to create it.
if (!file_exists($directory)) {
mkdir($directory, 0755);
mkdir($directory, 0755, true);
}
$path = public_path('uploads/assets/'.$file_name);
try {
@@ -267,7 +267,7 @@ class AssetsController extends Controller
if (Input::get('assigned_to')!='') {
$user = User::find(e(Input::get('assigned_to')));
$asset->checkOutToUser($user, Auth::user(), date('Y-m-d h:i:s'), '', 'Checked out on asset creation', e(Input::get('name')));
$asset->checkOutToUser($user, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e(Input::get('name')));
}
// Redirect to the asset listing page
\Session::flash('success', trans('admin/hardware/message.create.success'));
@@ -288,7 +288,7 @@ class AssetsController extends Controller
*/
public function getEdit($assetId = null)
{
// Check if the asset exists
if (!$asset = Asset::find($assetId)) {
// Redirect to the asset management page
@@ -354,7 +354,7 @@ class AssetsController extends Controller
}
if ($request->has('purchase_cost')) {
$asset->purchase_cost = e(number_format($request->input('purchase_cost'), 2, '.', ''));
$asset->purchase_cost = Helper::ParseFloat(e($request->input('purchase_cost')));
} else {
$asset->purchase_cost = null;
}
@@ -407,7 +407,7 @@ class AssetsController extends Controller
$directory= public_path('uploads/assets/');
// Check if the uploads directory exists. If not, try to create it.
if (!file_exists($directory)) {
mkdir($directory, 0755);
mkdir($directory, 0755, true);
}
$file_name = str_random(25).".".$extension;
@@ -436,14 +436,22 @@ class AssetsController extends Controller
$model = AssetModel::find($request->get('model_id'));
if ($model->fieldset) {
foreach ($model->fieldset->fields as $field) {
$asset->{\App\Models\CustomField::name_to_db_name($field->name)} = e($request->input(\App\Models\CustomField::name_to_db_name($field->name)));
// LOG::debug($field->name);
// LOG::debug(\App\Models\CustomField::name_to_db_name($field->name));
// LOG::debug($field->db_column_name());
if ($field->field_encrypted=='1') {
if (Gate::allows('admin')) {
$asset->{\App\Models\CustomField::name_to_db_name($field->name)} = \Crypt::encrypt(e($request->input(\App\Models\CustomField::name_to_db_name($field->name))));
}
} else {
$asset->{\App\Models\CustomField::name_to_db_name($field->name)} = e($request->input(\App\Models\CustomField::name_to_db_name($field->name)));
}
}
}
if ($asset->save()) {
// Redirect to the new asset page
\Session::flash('success', trans('admin/hardware/message.update.success'));
@@ -530,6 +538,8 @@ class AssetsController extends Controller
return redirect()->to('hardware')->with('error', trans('admin/hardware/message.does_not_exist'));
} elseif (!Company::isCurrentUserHasAccess($asset)) {
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
} elseif (!$asset->availableForCheckout()) {
return redirect()->to('hardware')->with('error', trans('admin/hardware/message.checkout.not_available'));
}
$user = User::find(e(Input::get('assigned_to')));
@@ -649,7 +659,7 @@ class AssetsController extends Controller
'fields' => [
[
'title' => 'Checked In:',
'value' => strtoupper($logaction->asset_type).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.e($asset->showAssetName()).'> checked in by <'.config('app.url').'/admin/users/'.Auth::user()->id.'/view'.'|'.e(Auth::user()->fullName()).'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.e($asset->showAssetName()).'> checked in by <'.config('app.url').'/admin/users/'.Auth::user()->id.'/view'.'|'.e(Auth::user()->fullName()).'>.'
],
[
'title' => 'Note:',
@@ -676,7 +686,8 @@ class AssetsController extends Controller
if ((($asset->checkin_email()=='1')) && ($user) && (!config('app.lock_passwords'))) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm Asset Checkin');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_Asset_Checkin'));
});
}
@@ -829,7 +840,7 @@ class AssetsController extends Controller
// Check if the uploads directory exists. If not, try to create it.
if (!file_exists($path)) {
mkdir($path, 0755);
mkdir($path, 0755, true);
}
if ($handle = opendir($path)) {
@@ -917,6 +928,18 @@ class AssetsController extends Controller
}
public function getDeleteImportFile($filename)
{
if (!Company::isCurrentUserAuthorized()) {
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
}
if (unlink(config('app.private_uploads').'/imports/assets/'.$filename)) {
return redirect()->back()->with('success', trans('admin/hardware/message.import.file_delete_success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.import.file_delete_error'));
}
/**
* Process the uploaded file
@@ -926,28 +949,47 @@ class AssetsController extends Controller
* @since [v2.0]
* @return Redirect
*/
public function getProcessImportFile($filename)
public function postProcessImportFile()
{
// php artisan asset-import:csv path/to/your/file.csv --domain=yourdomain.com --email_format=firstname.lastname
$filename = Input::get('filename');
$itemType = Input::get('import-type');
$updateItems = Input::get('import-update');
if (!Company::isCurrentUserAuthorized()) {
return redirect()->to('hardware')->with('error', trans('general.insufficient_permissions'));
}
$return = Artisan::call(
'snipeit:import',
['filename'=> config('app.private_uploads').'/imports/assets/'.$filename,
$importOptions = ['filename'=> config('app.private_uploads').'/imports/assets/'.$filename,
'--email_format'=>'firstname.lastname',
'--username_format'=>'firstname.lastname',
'--web-importer' => true,
'--user_id' => Auth::user()->id
]
);
'--user_id' => Auth::user()->id,
'--item-type' => $itemType,
];
if ($updateItems) {
$importOptions['--update'] = true;
}
$return = Artisan::call('snipeit:import', $importOptions);
$display_output = Artisan::output();
$file = config('app.private_uploads').'/imports/assets/'.str_replace('.csv', '', $filename).'-output-'.date("Y-m-d-his").'.txt';
file_put_contents($file, $display_output);
// We use hardware instead of asset in the url
$redirectTo = "hardware";
switch($itemType) {
case "asset":
$redirectTo = "hardware";
break;
case "accessory":
$redirectTo = "accessories";
break;
case "consumable":
$redirectTo = "consumables";
break;
}
if ($return === 0) { //Success
return redirect()->to('hardware')->with('success', trans('admin/hardware/message.import.success'));
return redirect()->to(route($redirectTo))->with('success', trans('admin/hardware/message.import.success'));
} elseif ($return === 1) { // Failure
return redirect()->back()->with('import_errors', json_decode($display_output))->with('error', trans('admin/hardware/message.import.error'));
}
@@ -1044,7 +1086,9 @@ class AssetsController extends Controller
$results = $csv->fetchAssoc();
$item = array();
$errors = array();
$status = array();
$status['error'] = array();
$status['success'] = array();
foreach($results as $row) {
@@ -1058,114 +1102,119 @@ class AssetsController extends Controller
}
$batch_counter = count($item[$asset_tag]);
$item[$asset_tag][$batch_counter]['date'] = date('Y-m-d H:i:s', strtotime(Helper::array_smart_fetch($row, "date")));
$item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "date"))->format('Y-m-d H:i:s');
$item[$asset_tag][$batch_counter]['asset_tag'] = Helper::array_smart_fetch($row, "asset tag");
$item[$asset_tag][$batch_counter]['name'] = Helper::array_smart_fetch($row, "name");
$item[$asset_tag][$batch_counter]['email'] = Helper::array_smart_fetch($row, "email");
$asset = Asset::where('asset_tag','=',$asset_tag)->first();
$item[$asset_tag][$batch_counter]['asset_id'] = $asset->id;
if ($asset = Asset::where('asset_tag','=',$asset_tag)->first()) {
$base_username = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format,$item[$asset_tag][$batch_counter]['name']);
$user = User::where('username','=',$base_username['username']);
$user_query = ' on username '.$base_username['username'];
$item[$asset_tag][$batch_counter]['asset_id'] = $asset->id;
if ($request->input('match_firstnamelastname')=='1') {
$firstnamedotlastname = User::generateFormattedNameFromFullName('firstname.lastname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $firstnamedotlastname['username'];
$user->orWhere('username','=',$firstnamedotlastname['username']);
$user_query .= ', or on username '.$firstnamedotlastname['username'];
}
$base_username = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format,$item[$asset_tag][$batch_counter]['name']);
$user = User::where('username','=',$base_username['username']);
$user_query = ' on username '.$base_username['username'];
if ($request->input('match_flastname')=='1') {
$flastname = User::generateFormattedNameFromFullName('filastname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $flastname['username'];
$user->orWhere('username','=',$flastname['username']);
$user_query .= ', or on username '.$flastname['username'];
}
if ($request->input('match_firstname')=='1') {
$firstname = User::generateFormattedNameFromFullName('firstname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $firstname['username'];
$user->orWhere('username','=',$firstname['username']);
$user_query .= ', or on username '.$firstname['username'];
}
if ($request->input('match_email')=='1') {
if ($item[$asset_tag][$batch_counter]['email']=='') {
$item[$asset_tag][$batch_counter]['username'][] = $user_email = User::generateEmailFromFullName($item[$asset_tag][$batch_counter]['name']);
$user->orWhere('username','=',$user_email);
$user_query .= ', or on username '.$user_email;
if ($request->input('match_firstnamelastname')=='1') {
$firstnamedotlastname = User::generateFormattedNameFromFullName('firstname.lastname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $firstnamedotlastname['username'];
$user->orWhere('username','=',$firstnamedotlastname['username']);
$user_query .= ', or on username '.$firstnamedotlastname['username'];
}
}
// A matching user was found
if ($user = $user->first()) {
$item[$asset_tag][$batch_counter]['checkedout_to'] = $user->id;
$status['success'][] = 'Found user '.Helper::array_smart_fetch($row, "name").$user_query;
if ($asset) {
if ($request->input('match_flastname')=='1') {
$flastname = User::generateFormattedNameFromFullName('filastname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $flastname['username'];
$user->orWhere('username','=',$flastname['username']);
$user_query .= ', or on username '.$flastname['username'];
}
if ($request->input('match_firstname')=='1') {
$firstname = User::generateFormattedNameFromFullName('firstname',$item[$asset_tag][$batch_counter]['name']);
$item[$asset_tag][$batch_counter]['username'][] = $firstname['username'];
$user->orWhere('username','=',$firstname['username']);
$user_query .= ', or on username '.$firstname['username'];
}
if ($request->input('match_email')=='1') {
if ($item[$asset_tag][$batch_counter]['email']=='') {
$item[$asset_tag][$batch_counter]['username'][] = $user_email = User::generateEmailFromFullName($item[$asset_tag][$batch_counter]['name']);
$user->orWhere('username','=',$user_email);
$user_query .= ', or on username '.$user_email;
}
}
// A matching user was found
if ($user = $user->first()) {
$item[$asset_tag][$batch_counter]['checkedout_to'] = $user->id;
$item[$asset_tag][$batch_counter]['user_id'] = $user->id;
Actionlog::firstOrCreate(array(
'asset_id' => $asset->id,
'asset_type' => 'hardware',
'user_id' => Auth::user()->id,
'note' => 'Checkout imported by '.Auth::user()->fullName().' from history importer',
'checkedout_to' => $item[$asset_tag][$batch_counter]['user_id'],
'created_at' => $item[$asset_tag][$batch_counter]['date'],
'action_type' => 'checkout'
'item_id' => $asset->id,
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkout imported by '.Auth::user()->fullName().' from history importer',
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
'target_type' => User::class,
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
'action_type' => 'checkout',
)
);
$asset->assigned_to = $user->id;
$asset->save();
if ($asset->save()) {
$status['success'][]['asset'][$asset_tag]['msg'] = 'Asset successfully matched for '.Helper::array_smart_fetch($row, "name").$user_query.' on '.$item[$asset_tag][$batch_counter]['checkout_date'];
} else {
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset and user was matched but could not be saved.';
}
} else {
$status['error'][] = 'Asset does not exist so no checkin log was created.';
$item[$asset_tag][$batch_counter]['checkedout_to'] = null;
$status['error'][]['user'][Helper::array_smart_fetch($row, "name")]['msg'] = 'User does not exist so no checkin log was created.';
}
} else {
$item[$asset_tag][$batch_counter]['checkedout_to'] = null;
$status['error'][] = 'No matching user for '.Helper::array_smart_fetch($row, "name");
$item[$asset_tag][$batch_counter]['asset_id'] = null;
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset does not exist so no match was attempted.';
}
}
}
// Loop through and backfill the checkins
foreach ($item as $key => $asset_batch) {
$batch_counter = 0;
for($x = 0; $x < count($asset_batch); $x++) {
$total_in_batch = count($asset_batch);
for($x = 0; $x < $total_in_batch; $x++) {
$next = $x + 1;
// Only do this if a matching user was found
if ($asset_batch[$x]['checkedout_to']!='') {
$batch_counter++;
if ((array_key_exists('checkedout_to',$asset_batch[$x])) && ($asset_batch[$x]['checkedout_to']!='')) {
if (($total_in_batch > 1) && ($x < $total_in_batch) && (array_key_exists($next,$asset_batch))) {
$checkin_date = Carbon::parse($asset_batch[$next]['checkout_date'])->subDay(1)->format('Y-m-d H:i:s');
$asset_batch[$x]['real_checkin'] = $checkin_date;
if ((count($asset_batch) != 1) && ($batch_counter < count($asset_batch))) {
$checkin_date = date('Y-m-d H:i:s',(strtotime($asset_batch[$x]['date']) + 10));
Actionlog::firstOrCreate(array(
'asset_id' => $asset_batch[$x]['asset_id'],
'asset_type' => 'hardware',
'user_id' => Auth::user()->id,
'note' => 'Checkin imported by '.Auth::user()->fullName().' from history importer',
'checkedout_to' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin'
'item_id' => $asset_batch[$x]['asset_id'],
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkin imported by ' . Auth::user()->fullName() . ' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin'
)
);
}
}
}
}
return View::make('hardware/history')->with('status',$status);
}
@@ -1231,15 +1280,8 @@ class AssetsController extends Controller
$upload_success = $file->move($destinationPath, $filename);
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->asset_type = 'hardware';
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('notes'));
$logaction->checkedout_to = null;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->filename = $filename;
$log = $logaction->logaction('uploaded');
$asset->logUpload($filename, e(Input::get('notes')));
}
} else {
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
@@ -1382,7 +1424,7 @@ class AssetsController extends Controller
return View::make('hardware/labels')->with('assets', $assets)->with('settings', $settings)->with('count', $count)->with('settings', $settings);
} elseif (Input::get('bulk_actions')=='delete') {
@@ -1450,7 +1492,7 @@ class AssetsController extends Controller
}
if (Input::has('purchase_cost')) {
$update_array['purchase_cost'] = e(Input::get('purchase_cost'));
$update_array['purchase_cost'] = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (Input::has('supplier_id')) {
@@ -1496,8 +1538,8 @@ class AssetsController extends Controller
->update($update_array)) {
$logaction = new Actionlog();
$logaction->asset_id = $key;
$logaction->asset_type = 'hardware';
$logaction->item_type = Asset::class;
$logaction->item_id = $key;
$logaction->created_at = date("Y-m-d H:i:s");
if (Input::has('rtd_location_id')) {
@@ -1546,7 +1588,7 @@ class AssetsController extends Controller
foreach ($assets as $asset) {
//echo '<li>'.$asset;
$update_array['deleted_at'] = date('Y-m-d h:i:s');
$update_array['deleted_at'] = date('Y-m-d H:i:s');
$update_array['assigned_to'] = null;
if (DB::table('assets')
@@ -1554,8 +1596,8 @@ class AssetsController extends Controller
->update($update_array)) {
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->asset_type = 'hardware';
$logaction->item_type = Asset::class;
$logaction->item_id = $asset->id;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->user_id = Auth::user()->id;
$log = $logaction->logaction('deleted');
@@ -1586,31 +1628,31 @@ class AssetsController extends Controller
* @since [v2.0]
* @return String JSON
*/
public function getDatatable($status = null)
public function getDatatable(Request $request, $status = null)
{
$assets = Company::scopeCompanyables(Asset::select('assets.*'))->with('model', 'assigneduser', 'assigneduser.userloc', 'assetstatus', 'defaultLoc', 'assetlog', 'model', 'model.category', 'model.manufacturer', 'model.fieldset', 'assetstatus', 'assetloc', 'company')
->Hardware();
if (Input::has('search')) {
$assets = $assets->TextSearch(e(Input::get('search')));
if ($request->has('search')) {
$assets = $assets->TextSearch(e($request->get('search')));
}
if (Input::has('offset')) {
$offset = e(Input::get('offset'));
if ($request->has('offset')) {
$offset = e($request->get('offset'));
} else {
$offset = 0;
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
if ($request->has('limit')) {
$limit = e($request->get('limit'));
} else {
$limit = 50;
}
if (Input::has('order_number')) {
$assets->where('order_number', '=', e(Input::get('order_number')));
if ($request->has('order_number')) {
$assets->where('order_number', '=', e($request->get('order_number')));
}
switch ($status) {
@@ -1635,9 +1677,14 @@ class AssetsController extends Controller
case 'Deployed':
$assets->Deployed();
break;
}
if ($request->has('status_id')) {
$assets->where('status_id','=', e($request->get('status_id')));
}
$allowed_columns = [
'id',
'name',
@@ -1667,8 +1714,8 @@ class AssetsController extends Controller
$allowed_columns[]=$field->db_column_name();
}
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? Input::get('sort') : 'asset_tag';
$order = $request->get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'asset_tag';
switch ($sort) {
case 'model':
@@ -1707,45 +1754,41 @@ class AssetsController extends Controller
$rows = array();
foreach ($assets as $asset) {
$inout = '';
$actions = '';
$actions = '<div style="white-space: nowrap;">';
if ($asset->deleted_at=='') {
if (Gate::allows('assets.create')) {
$actions = '<div style=" white-space: nowrap;"><a href="' . route('clone/hardware',
$asset->id) . '" class="btn btn-info btn-sm" title="Clone asset" data-toggle="tooltip"><i class="fa fa-clone"></i>';
$actions .= '<a href="' . route('clone/hardware',
$asset->id) . '" class="btn btn-info btn-sm" title="Clone asset" data-toggle="tooltip"><i class="fa fa-clone"></i></a> ';
}
if (Gate::allows('assets.edit')) {
$actions .= '</a> <a href="' . route('update/hardware',
$actions .= '<a href="' . route('update/hardware',
$asset->id) . '" class="btn btn-warning btn-sm" title="Edit asset" data-toggle="tooltip"><i class="fa fa-pencil icon-white"></i></a> ';
}
if (Gate::allows('assets.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/hardware',
$asset->id) . '" data-content="' . trans('admin/hardware/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($asset->asset_tag) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a></div>';
$asset->id) . '" data-content="' . trans('admin/hardware/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($asset->asset_tag) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
} elseif ($asset->model->deleted_at=='') {
$actions = '<a href="'.route('restore/hardware', $asset->id).'" title="Restore asset" data-toggle="tooltip" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
$actions .= '<a href="'.route('restore/hardware', $asset->id).'" title="Restore asset" data-toggle="tooltip" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
}
if ($asset->assetstatus) {
if (($asset->assetstatus->deployable != 0) && ($asset->deleted_at=='')) {
if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) {
if (Gate::allows('assets.checkin')) {
$inout = '<a href="' . route('checkin/hardware',
$asset->id) . '" class="btn btn-primary btn-sm" title="Checkin this asset" data-toggle="tooltip">' . trans('general.checkin') . '</a>';
}
} else {
if (Gate::allows('assets.checkout')) {
$inout = '<a href="' . route('checkout/hardware',
$asset->id) . '" class="btn btn-info btn-sm" title="Checkout this asset to a user" data-toggle="tooltip">' . trans('general.checkout') . '</a>';
}
}
$actions .= '</div>';
if (($asset->availableForCheckout()))
{
if (Gate::allows('assets.checkout')) {
$inout = '<a href="' . route('checkout/hardware',
$asset->id) . '" class="btn btn-info btn-sm" title="Checkout this asset to a user" data-toggle="tooltip">' . trans('general.checkout') . '</a>';
}
} else {
if (Gate::allows('assets.checkin')) {
$inout = '<a href="' . route('checkin/hardware',
$asset->id) . '" class="btn btn-primary btn-sm" title="Checkin this asset" data-toggle="tooltip">' . trans('general.checkin') . '</a>';
}
}
// Lots going on here. Importer has parsed numbers before importing, so we need to check and see if it's a number before trying to parse.
$purchase_cost = $asset->purchase_cost ?: '';
if (is_numeric($purchase_cost)) {
$purchase_cost = number_format($purchase_cost, 2);
}
$purchase_cost = Helper::formatCurrencyOutput($asset->purchase_cost);
$row = array(
'checkbox' =>'<div class="text-center"><input type="checkbox" name="edit_asset['.$asset->id.']" class="one_required"></div>',
@@ -1758,7 +1801,7 @@ class AssetsController extends Controller
'model_number' => ($asset->model && $asset->model->modelno) ? (string)$asset->model->modelno : '',
'status_label' => ($asset->assigneduser) ? 'Deployed' : ((e($asset->assetstatus)) ? e($asset->assetstatus->name) : ''),
'assigned_to' => ($asset->assigneduser) ? (string)link_to(config('app.url').'/admin/users/'.$asset->assigned_to.'/view', e($asset->assigneduser->fullName())) : '',
'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? (string)link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/view', e($asset->assigneduser->userloc->name)) : (($asset->defaultLoc!='') ? (string)link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/edit', e($asset->defaultLoc->name)) : ''),
'location' => (($asset->assigneduser) && ($asset->assigneduser->userloc!='')) ? (string)link_to('admin/settings/locations/'.$asset->assigneduser->userloc->id.'/view', e($asset->assigneduser->userloc->name)) : (($asset->defaultLoc!='') ? (string)link_to('admin/settings/locations/'.$asset->defaultLoc->id.'/view', e($asset->defaultLoc->name)) : ''),
'category' => (($asset->model) && ($asset->model->category)) ?(string)link_to('/admin/settings/categories/'.$asset->model->category->id.'/view', e($asset->model->category->name)) : '',
'manufacturer' => (($asset->model) && ($asset->model->manufacturer)) ? (string)link_to('/admin/settings/manufacturers/'.$asset->model->manufacturer->id.'/view', e($asset->model->manufacturer->name)) : '',
'eol' => ($asset->eol_date()) ? $asset->eol_date() : '',
@@ -1774,9 +1817,36 @@ class AssetsController extends Controller
'companyName' => is_null($asset->company) ? '' : e($asset->company->name)
);
foreach ($all_custom_fields as $field) {
$row[$field->db_column_name()]=$asset->{$field->db_column_name()};
$column_name = $field->db_column_name();
if ($field->isFieldDecryptable($asset->{$column_name})) {
if (Gate::allows('admin')) {
if (($field->format=='URL') && ($asset->{$column_name}!='')) {
$row[$column_name] = '<a href="'.Helper::gracefulDecrypt($field, $asset->{$column_name}).'" target="_blank">'.Helper::gracefulDecrypt($field, $asset->{$column_name}).'</a>';
} else {
$row[$column_name] = Helper::gracefulDecrypt($field, $asset->{$column_name});
}
} else {
$row[$field->db_column_name()] = strtoupper(trans('admin/custom_fields/general.encrypted'));
}
} else {
if (($field->format=='URL') && ($asset->{$field->db_column_name()}!='')) {
$row[$field->db_column_name()] = '<a href="'.$asset->{$field->db_column_name()}.'" target="_blank">'.$asset->{$field->db_column_name()}.'</a>';
} else {
$row[$field->db_column_name()] = e($asset->{$field->db_column_name()});
}
}
}
$rows[]=$row;
if (($request->has('report')) && ($request->get('report')=='true')) {
$rows[]= Helper::stripTagsFromJSON($row);
} else {
$rows[]= $row;
}
}
$data = array('total'=>$assetCount, 'rows'=>$rows);
@@ -1790,12 +1860,12 @@ class AssetsController extends Controller
$users_list = Helper::usersList();
// Filter out assets that are not deployable.
$assets = Asset::RTD()->get();
$assets_list = Company::scopeCompanyables($assets, 'assets.company_id')->lists('detailed_name', 'id')->toArray();
return View::make('hardware/bulk-checkout')->with('users_list', $users_list)->with('assets_list', $assets_list);
}
public function postBulkCheckout(Request $request)
{
@@ -1805,31 +1875,31 @@ class AssetsController extends Controller
$user = User::find(e(Input::get('assigned_to')));
$admin = Auth::user();
$asset_ids = array_filter(Input::get('selected_assets'));
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
$checkout_at = e(Input::get('checkout_at'));
} else {
$checkout_at = date("Y-m-d H:i:s");
}
if (Input::has('expected_checkin')) {
$expected_checkin = e(Input::get('expected_checkin'));
} else {
$expected_checkin = '';
}
$has_errors = false;
$errors = [];
DB::transaction(function() use ($user, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids)
{
{
foreach($asset_ids as $asset_id)
{
$asset = Asset::find($asset_id);
$error = $asset->checkOutToUser($user, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), null);
if($error)
{
$has_errors = true;
@@ -1837,12 +1907,12 @@ class AssetsController extends Controller
}
}
});
if (!$errors) {
// Redirect to the new asset page
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.checkout.success'));
}
// Redirect to the asset management page with error
return redirect()->to("hardware/bulk-checkout")->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
}

View File

@@ -37,4 +37,13 @@ class PasswordController extends Controller
{
$this->middleware('guest');
}
/**
* Get the e-mail subject line to be used for the reset link email.
* Overriding method "getEmailSubject()" from trait "use ResetsPasswords"
* @return string
*/
public function getEmailSubject(){
return property_exists($this, 'subject') ? $this->subject : \Lang::get('mail.reset_link');
}
}

View File

@@ -1,13 +1,14 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Helpers\Helper;
use App\Models\Category as Category;
use App\Models\Company;
use App\Models\Setting;
use Auth;
use DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Input;
use Lang;
use Redirect;
@@ -344,13 +345,13 @@ class CategoriesController extends Controller
$actions = '<a href="'.route('restore/hardware', $asset->id).'" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
}
if ($asset->assetstatus) {
if ($asset->assetstatus->deployable != 0) {
if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
} else {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
if ($asset->availableForCheckout()) {
if (Gate::allows('assets.checkout')) {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
} else {
if (Gate::allows('assets.checkin')) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
}
}

View File

@@ -99,7 +99,7 @@ class ComponentsController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$component->purchase_cost = null;
} else {
$component->purchase_cost = e(Input::get('purchase_cost'));
$component->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$component->total_qty = e(Input::get('total_qty'));
@@ -183,7 +183,7 @@ class ComponentsController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$component->purchase_cost = null;
} else {
$component->purchase_cost = e(Input::get('purchase_cost'));
$component->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$component->total_qty = e(Input::get('total_qty'));
@@ -345,17 +345,11 @@ class ComponentsController extends Controller
$component->assets()->attach($component->id, array(
'component_id' => $component->id,
'user_id' => $admin_user->id,
'created_at' => date('Y-m-d h:i:s'),
'created_at' => date('Y-m-d H:i:s'),
'assigned_qty' => e(Input::get('assigned_qty')),
'asset_id' => $asset_id));
$logaction = new Actionlog();
$logaction->component_id = $component->id;
$logaction->asset_id = $asset_id;
$logaction->asset_type = 'component';
$logaction->location_id = $asset->location_id;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction = $component->logCheckout(e(Input::get('note')), $asset_id);
$settings = Setting::getSettings();
@@ -375,7 +369,7 @@ class ComponentsController extends Controller
'fields' => [
[
'title' => 'Checked Out:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/components/'.$component->id.'/view'.'|'.$component->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->name.'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' <'.config('app.url').'/admin/components/'.$component->id.'/view'.'|'.$component->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->showAssetName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
],
[
'title' => 'Note:',
@@ -389,9 +383,6 @@ class ComponentsController extends Controller
}
}
$log = $logaction->logaction('checkout');
// Redirect to the new component page
return redirect()->to("admin/components")->with('success', trans('admin/components/message.checkout.success'));
@@ -484,7 +475,7 @@ class ComponentsController extends Controller
'category' => ($component->category) ? e($component->category->name) : 'Missing category',
'order_number' => e($component->order_number),
'purchase_date' => e($component->purchase_date),
'purchase_cost' => ($component->purchase_cost!='') ? number_format($component->purchase_cost, 2): '' ,
'purchase_cost' => Helper::formatCurrencyOutput($component->purchase_cost),
'numRemaining' => $component->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),

View File

@@ -97,7 +97,7 @@ class ConsumablesController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$consumable->purchase_cost = null;
} else {
$consumable->purchase_cost = e(Input::get('purchase_cost'));
$consumable->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$consumable->qty = e(Input::get('qty'));
@@ -182,10 +182,10 @@ class ConsumablesController extends Controller
if (e(Input::get('purchase_cost')) == '0.00') {
$consumable->purchase_cost = null;
} else {
$consumable->purchase_cost = e(Input::get('purchase_cost'));
$consumable->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
$consumable->qty = e(Input::get('qty'));
$consumable->qty = Helper::ParseFloat(e(Input::get('qty')));
if ($consumable->save()) {
return redirect()->to("admin/consumables")->with('success', trans('admin/consumables/message.update.success'));
@@ -316,14 +316,7 @@ class ConsumablesController extends Controller
'user_id' => $admin_user->id,
'assigned_to' => e(Input::get('assigned_to'))));
$logaction = new Actionlog();
$logaction->consumable_id = $consumable->id;
$logaction->checkedout_to = $consumable->assigned_to;
$logaction->asset_type = 'consumable';
$logaction->asset_id = 0;
$logaction->location_id = $user->location_id;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction = $consumable->logCheckout(e(Input::get('note')));
$settings = Setting::getSettings();
@@ -343,7 +336,7 @@ class ConsumablesController extends Controller
'fields' => [
[
'title' => 'Checked Out:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/consumables/'.$consumable->id.'/view'.'|'.$consumable->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
'value' => 'Consumable <'.config('app.url').'/admin/consumables/'.$consumable->id.'/view'.'|'.$consumable->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$user->fullName().'> by <'.config('app.url').'/admin/users/'.$admin_user->id.'/view'.'|'.$admin_user->fullName().'>.'
],
[
'title' => 'Note:',
@@ -357,9 +350,6 @@ class ConsumablesController extends Controller
}
}
$log = $logaction->logaction('checkout');
$consumable_user = DB::table('consumables_users')->where('assigned_to', '=', $consumable->assigned_to)->where('consumable_id', '=', $consumable->id)->first();
$data['log_id'] = $logaction->id;
@@ -375,7 +365,8 @@ class ConsumablesController extends Controller
Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm consumable delivery');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_consumable_delivery'));
});
}
@@ -470,13 +461,13 @@ class ConsumablesController extends Controller
'location' => ($consumable->location) ? e($consumable->location->name) : '',
'min_amt' => e($consumable->min_amt),
'qty' => e($consumable->qty),
'manufacturer' => ($consumable->manufacturer) ? e($consumable->manufacturer->name) : '',
'model_no' => e($consumable->model_no),
'item_no' => e($consumable->item_no),
'category' => ($consumable->category) ? e($consumable->category->name) : 'Missing category',
'manufacturer' => ($consumable->manufacturer) ? (string) link_to('/admin/settings/manufacturers/'.$consumable->manufacturer_id.'/view', $consumable->manufacturer->name): '',
'model_no' => e($consumable->model_no),
'item_no' => e($consumable->item_no),
'category' => ($consumable->category) ? (string) link_to('/admin/settings/categories/'.$consumable->category_id.'/view', $consumable->category->name) : 'Missing category',
'order_number' => e($consumable->order_number),
'purchase_date' => e($consumable->purchase_date),
'purchase_cost' => ($consumable->purchase_cost!='') ? number_format($consumable->purchase_cost, 2): '' ,
'purchase_cost' => Helper::formatCurrencyOutput($consumable->purchase_cost),
'numRemaining' => $consumable->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),

View File

@@ -10,6 +10,7 @@ use Redirect;
use App\Models\AssetModel;
use Lang;
use Auth;
use Illuminate\Http\Request;
/**
* This controller handles all actions related to Custom Asset Fields for
@@ -63,10 +64,15 @@ class CustomFieldsController extends Controller
* @since [v1.8]
* @return Redirect
*/
public function store()
public function store(Request $request)
{
//
$cfset=new CustomFieldset(["name" => Input::get("name"),"user_id" => Auth::user()->id]);
$cfset = new CustomFieldset(
[
"name" => e($request->get("name")),
"user_id" => Auth::user()->id]
);
$validator=Validator::make(Input::all(), $cfset->rules);
if ($validator->passes()) {
$cfset->save();
@@ -122,24 +128,33 @@ class CustomFieldsController extends Controller
* @since [v1.8]
* @return Redirect
*/
public function storeField()
public function storeField(Request $request)
{
$field=new CustomField(["name" => Input::get("name"),"element" => Input::get("element"),"user_id" => Auth::user()->id]);
$field = new CustomField([
"name" => e($request->get("name")),
"element" => e($request->get("element")),
"field_values" => e($request->get("field_values")),
"field_encrypted" => e($request->get("field_encrypted", 0)),
"user_id" => Auth::user()->id
]);
if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) {
$field->format=Input::get("custom_format");
$field->format = e($request->get("custom_format"));
} else {
$field->format=Input::get('format');
$field->format = e($request->get("format"));
}
$validator=Validator::make(Input::all(), $field->rules);
if ($validator->passes()) {
$results=$field->save();
//return "postCreateField: $results";
$results = $field->save();
if ($results) {
return redirect()->route("admin.custom_fields.index")->with("success", trans('admin/custom_fields/message.field.create.success'));
} else {
dd($field);
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error'));
}
} else {
@@ -175,9 +190,7 @@ class CustomFieldsController extends Controller
*/
public function deleteField($field_id)
{
$field=CustomField::find($field_id);
$field = CustomField::find($field_id);
if ($field->fieldset->count()>0) {
return redirect()->back()->withErrors(['message' => "Field is in-use"]);

View File

@@ -30,12 +30,6 @@ class DashboardController extends Controller
// Show the page
if (Auth::user()->hasAccess('admin')) {
$recent_activity = Actionlog::orderBy('created_at', 'DESC')
->with('accessorylog', 'consumablelog', 'licenselog', 'assetlog', 'adminlog', 'userlog', 'componentlog')
->take(30)
->get();
$asset_stats['total'] = Asset::Hardware()->count();
$asset_stats['rtd']['total'] = Asset::Hardware()->RTD()->count();
@@ -82,7 +76,7 @@ class DashboardController extends Controller
}
return View::make('dashboard')->with('asset_stats', $asset_stats)->with('recent_activity', $recent_activity);
return View::make('dashboard')->with('asset_stats', $asset_stats);
} else {
// Redirect to the profile page
return redirect()->route('view-assets');

View File

@@ -61,18 +61,17 @@ class LicensesController extends Controller
public function getCreate()
{
$depreciation_list = Helper::depreciationList();
$supplier_list = Helper::suppliersList();
$maintained_list = array('' => 'Maintained', '1' => 'Yes', '0' => 'No');
$company_list = Helper::companyList();
return View::make('licenses/edit')
//->with('license_options',$license_options)
->with('depreciation_list', $depreciation_list)
->with('supplier_list', $supplier_list)
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('maintained_list', $maintained_list)
->with('company_list', $company_list)
->with('company_list', Helper::companyList())
->with('manufacturer_list', Helper::manufacturerList())
->with('license', new License);
}
@@ -88,17 +87,13 @@ class LicensesController extends Controller
public function postCreate()
{
// get the POST data
$new = Input::all();
// create a new model instance
$license = new License();
if (e(Input::get('purchase_cost')) == '') {
$license->purchase_cost = null;
} else {
$license->purchase_cost = e(Input::get('purchase_cost'));
$license->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (e(Input::get('supplier_id')) == '') {
@@ -125,6 +120,12 @@ class LicensesController extends Controller
$license->purchase_order = e(Input::get('purchase_order'));
}
if (empty(e(Input::get('manufacturer_id')))) {
$license->manufacturer_id = null;
} else {
$license->manufacturer_id = e(Input::get('manufacturer_id'));
}
// Save the license data
$license->name = e(Input::get('name'));
$license->serial = e(Input::get('serial'));
@@ -206,17 +207,15 @@ class LicensesController extends Controller
// Show the page
$license_options = array('' => 'Top Level') + DB::table('assets')->where('id', '!=', $licenseId)->pluck('name', 'id');
$depreciation_list = array('0' => trans('admin/licenses/form.no_depreciation')) + Depreciation::pluck('name', 'id')->toArray();
$supplier_list = array('' => 'Select Supplier') + Supplier::orderBy('name', 'asc')->pluck('name', 'id')->toArray();
$maintained_list = array('' => 'Maintained', '1' => 'Yes', '0' => 'No');
$company_list = Helper::companyList();
return View::make('licenses/edit', compact('license'))
->with('license_options', $license_options)
->with('depreciation_list', $depreciation_list)
->with('supplier_list', $supplier_list)
->with('company_list', $company_list)
->with('maintained_list', $maintained_list);
->with('depreciation_list', Helper::depreciationList())
->with('supplier_list', Helper::suppliersList())
->with('company_list', Helper::companyList())
->with('maintained_list', $maintained_list)
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -253,6 +252,13 @@ class LicensesController extends Controller
$license->maintained = e(Input::get('maintained'));
$license->reassignable = e(Input::get('reassignable'));
if (empty(e(Input::get('manufacturer_id')))) {
$license->manufacturer_id = null;
} else {
$license->manufacturer_id = e(Input::get('manufacturer_id'));
}
if (e(Input::get('supplier_id')) == '') {
$license->supplier_id = null;
} else {
@@ -279,10 +285,9 @@ class LicensesController extends Controller
}
if (e(Input::get('purchase_cost')) == '') {
$license->purchase_cost = null;
$license->purchase_cost = null;
} else {
$license->purchase_cost = e(Input::get('purchase_cost'));
//$license->purchase_cost = e(Input::get('purchase_cost'));
$license->purchase_cost = Helper::ParseFloat(e(Input::get('purchase_cost')));
}
if (e(Input::get('maintained')) == '') {
@@ -324,11 +329,11 @@ class LicensesController extends Controller
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->asset_type = 'software';
$logaction->item_type = License::class;
$logaction->item_id = $license->id;
$logaction->user_id = Auth::user()->id;
$logaction->note = abs($difference)." seats";
$logaction->checkedout_to = null;
$logaction->note = '-'.abs($difference)." seats";
$logaction->target_id = null;
$log = $logaction->logaction('delete seats');
} else {
@@ -349,10 +354,11 @@ class LicensesController extends Controller
//Log the addition of license to the log.
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->asset_type = 'software';
$logaction->item_type = License::class;
$logaction->item_id = $license->id;
$logaction->user_id = Auth::user()->id;
$logaction->note = abs($difference)." seats";
$logaction->note = '+'.abs($difference)." seats";
$logaction->target_id = null;
$log = $logaction->logaction('add seats');
}
$license->seats = e(Input::get('seats'));
@@ -502,7 +508,7 @@ class LicensesController extends Controller
}
if (($asset->assigned_to!='') && (($asset->assigned_to!=$assigned_to)) && ($assigned_to!='') ) {
if (($asset->assigned_to!='') && (($asset->assigned_to!=$assigned_to)) && ($assigned_to!='')) {
return redirect()->to('admin/licenses')->with('error', trans('admin/licenses/message.owner_doesnt_match_asset'));
}
@@ -533,14 +539,10 @@ class LicensesController extends Controller
// Was the asset updated?
if ($licenseseat->save()) {
$logaction = new Actionlog();
//$logaction->location_id = $assigned_to->location_id;
$logaction->asset_type = 'software';
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('note'));
$logaction->asset_id = $licenseseat->license_id;
$licenseseat->logCheckout(e(Input::get('note')));
$data['license_id'] =$licenseseat->license_id;
$data['note'] = e(Input::get('note'));
$license = License::find($licenseseat->license_id);
$settings = Setting::getSettings();
@@ -548,11 +550,9 @@ class LicensesController extends Controller
// Update the asset data
if (e(Input::get('assigned_to')) == '') {
$logaction->checkedout_to = null;
$slack_msg = strtoupper($logaction->asset_type).' license <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->showAssetName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
$slack_msg = 'License <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/hardware/'.$asset->id.'/view|'.$asset->showAssetName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
} else {
$logaction->checkedout_to = e(Input::get('assigned_to'));
$slack_msg = strtoupper($logaction->asset_type).' license <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$is_assigned_to->fullName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
$slack_msg = 'License <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked out to <'.config('app.url').'/admin/users/'.$user->id.'/view|'.$is_assigned_to->fullName().'> by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.';
}
@@ -578,7 +578,7 @@ class LicensesController extends Controller
],
[
'title' => 'Note:',
'value' => e($logaction->note)
'value' => e(Input::get('note'))
],
@@ -592,9 +592,6 @@ class LicensesController extends Controller
}
$log = $logaction->logaction('checkout');
// Redirect to the new asset page
return redirect()->to("admin/licenses")->with('success', trans('admin/licenses/message.checkout.success'));
}
@@ -673,8 +670,6 @@ class LicensesController extends Controller
return redirect()->back()->withInput()->withErrors($validator);
}
$return_to = $licenseseat->assigned_to;
$logaction = new Actionlog();
$logaction->checkedout_to = $licenseseat->assigned_to;
// Update the asset data
$licenseseat->assigned_to = null;
@@ -684,11 +679,7 @@ class LicensesController extends Controller
// Was the asset updated?
if ($licenseseat->save()) {
$logaction->asset_id = $licenseseat->license_id;
$logaction->location_id = null;
$logaction->asset_type = 'software';
$logaction->note = e(Input::get('note'));
$logaction->user_id = $user->id;
$licenseseat->logCheckin(e(Input::get('note')));
$settings = Setting::getSettings();
@@ -709,11 +700,11 @@ class LicensesController extends Controller
'fields' => [
[
'title' => 'Checked In:',
'value' => strtoupper($logaction->asset_type).' <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked in by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.'
'value' => 'License: <'.config('app.url').'/admin/licenses/'.$license->id.'/view'.'|'.$license->name.'> checked in by <'.config('app.url').'/admin/users/'.$user->id.'/view'.'|'.$user->fullName().'>.'
],
[
'title' => 'Note:',
'value' => e($logaction->note)
'value' => e(Input::get('note'))
],
]
@@ -726,9 +717,6 @@ class LicensesController extends Controller
}
$log = $logaction->logaction('checkin from');
if ($backto=='user') {
return redirect()->to("admin/users/".$return_to.'/view')->with('success', trans('admin/licenses/message.checkin.success'));
@@ -799,7 +787,8 @@ class LicensesController extends Controller
->with('supplier_list', $supplier_list)
->with('license', $license)
->with('maintained_list', $maintained_list)
->with('company_list', $company_list);
->with('company_list', $company_list)
->with('manufacturer_list', Helper::manufacturerList());
}
@@ -832,7 +821,7 @@ class LicensesController extends Controller
foreach (Input::file('licensefile') as $file) {
$rules = array(
'licensefile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar|max:2000'
'licensefile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar,rtf|max:2000'
);
$validator = Validator::make(array('licensefile'=> $file), $rules);
@@ -843,16 +832,8 @@ class LicensesController extends Controller
$filename .= '-'.str_slug($file->getClientOriginalName()).'.'.$extension;
$upload_success = $file->move($destinationPath, $filename);
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->asset_type = 'software';
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('notes'));
$logaction->checkedout_to = null;
$logaction->created_at = date("Y-m-d h:i:s");
$logaction->filename = $filename;
$log = $logaction->logaction('uploaded');
//Log the upload to the log
$license->logUpload($filename, e(Input::get('notes')));
} else {
return redirect()->back()->with('error', trans('admin/licenses/message.upload.invalidfiles'));
}
@@ -987,21 +968,22 @@ class LicensesController extends Controller
$actions = '<span style="white-space: nowrap;">';
if (Gate::allows('licenses.checkout')) {
$actions .= '<a href="' . route('freecheckout/license',
$license->id) . '" class="btn btn-primary btn-sm' . (($license->remaincount() > 0) ? '' : ' disabled') . '" style="margin-right:5px;">' . trans('general.checkout') . '</a> ';
$actions .= '<a href="' . route('freecheckout/license', $license->id)
. '" class="btn btn-primary btn-sm' . (($license->remaincount() > 0) ? '' : ' disabled') . '" style="margin-right:5px;">' . trans('general.checkout') . '</a> ';
}
if (Gate::allows('licenses.create')) {
$actions .= '<a href="' . route('clone/license',
$license->id) . '" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone asset"><i class="fa fa-files-o"></i></a>';
$actions .= '<a href="' . route('clone/license', $license->id)
. '" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone license"><i class="fa fa-files-o"></i></a>';
}
if (Gate::allows('licenses.edit')) {
$actions .= '<a href="' . route('update/license',
$license->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
$actions .= '<a href="' . route('update/license', $license->id)
. '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('licenses.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/license',
$license->id) . '" data-content="' . trans('admin/licenses/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($license->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'
. route('delete/license', $license->id)
. '" data-content="' . trans('admin/licenses/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($license->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</span>';
@@ -1012,15 +994,16 @@ class LicensesController extends Controller
'totalSeats' => $license->totalSeatsByLicenseID(),
'remaining' => $license->remaincount(),
'license_name' => e($license->license_name),
'license_email' => e($license->license_email),
'license_email' => e($license->license_email),
'purchase_date' => ($license->purchase_date) ? $license->purchase_date : '',
'expiration_date' => ($license->expiration_date) ? $license->expiration_date : '',
'purchase_cost' => ($license->purchase_cost) ? number_format($license->purchase_cost, 2) : '',
'purchase_cost' => Helper::formatCurrencyOutput($license->purchase_cost),
'purchase_order' => ($license->purchase_order) ? e($license->purchase_order) : '',
'order_number' => ($license->order_number) ? e($license->order_number) : '',
'notes' => ($license->notes) ? e($license->notes) : '',
'actions' => $actions,
'companyName' => is_null($license->company) ? '' : e($license->company->name)
'companyName' => is_null($license->company) ? '' : e($license->company->name),
'manufacturer' => $license->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$license->manufacturer_id.'/view', $license->manufacturer->name) : ''
);
}

View File

@@ -2,14 +2,15 @@
namespace App\Http\Controllers;
use App\Models\Company;
use App\Models\Manufacturer;
use App\Models\Setting;
use Auth;
use Gate;
use Input;
use Lang;
use App\Models\Manufacturer;
use Redirect;
use App\Models\Setting;
use Str;
use View;
use Auth;
/**
* This controller handles all actions related to Manufacturers for
@@ -254,10 +255,27 @@ class ManufacturersController extends Controller
* @since [v1.0]
* @return String JSON
*/
public function getDataView($manufacturerId)
public function getDataView($manufacturerId, $itemtype = null)
{
$manufacturer = Manufacturer::with('assets.company')->find($manufacturerId);
switch ($itemtype) {
case "assets":
return $this->getDataAssetsView($manufacturer);
case "licenses":
return $this->getDataLicensesView($manufacturer);
case "accessories":
return $this->getDataAccessoriesView($manufacturer);
case "consumables":
return $this->getDataConsumablesView($manufacturer);
}
throw new Exception("We shouldn't be here");
}
protected function getDataAssetsView(Manufacturer $manufacturer)
{
$manufacturer_assets = $manufacturer->assets;
if (Input::has('search')) {
@@ -293,35 +311,213 @@ class ManufacturersController extends Controller
$actions = '<a href="'.route('restore/hardware', $asset->id).'" class="btn btn-warning btn-sm"><i class="fa fa-recycle icon-white"></i></a>';
}
if ($asset->assetstatus) {
if ($asset->assetstatus->deployable != 0) {
if (($asset->assigned_to !='') && ($asset->assigned_to > 0)) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
} else {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
if ($asset->availableForCheckout()) {
if (Gate::allows('assets.checkout')) {
$inout = '<a href="'.route('checkout/hardware', $asset->id).'" class="btn btn-info btn-sm">'.trans('general.checkout').'</a>';
}
} else {
if (Gate::allows('assets.checkin')) {
$inout = '<a href="'.route('checkin/hardware', $asset->id).'" class="btn btn-primary btn-sm">'.trans('general.checkin').'</a>';
}
}
$row = array(
'id' => $asset->id,
'name' => (string)link_to('/hardware/'.$asset->id.'/view', e($asset->showAssetName())),
'model' => e($asset->model->name),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
'assigned_to' => ($asset->assigneduser) ? (string)link_to('/admin/users/'.$asset->assigneduser->id.'/view', e($asset->assigneduser->fullName())): '',
'actions' => $actions,
'companyName' => e(Company::getName($asset)),
);
$rows[] = array(
'id' => $asset->id,
'name' => (string)link_to('/hardware/'.$asset->id.'/view', e($asset->showAssetName())),
'model' => e($asset->model->name),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
'assigned_to' => ($asset->assigneduser) ? (string)link_to('/admin/users/'.$asset->assigneduser->id.'/view', e($asset->assigneduser->fullName())): '',
'actions' => $actions,
'companyName' => e(Company::getName($asset)),
);
if (isset($inout)) {
$row['change'] = $inout;
if (isset($inout)) {
$row['change'] = $inout;
}
}
$rows[] = $row;
}
$data = array('total' => $count, 'rows' => $rows);
return $data;
}
protected function getDataLicensesView(Manufacturer $manufacturer)
{
$licenses = $manufacturer->licenses;
if (Input::has('search')) {
$licenses = $licenses->TextSearch(Input::get('search'));
}
$licenseCount = $licenses->count();
$rows = array();
foreach ($licenses as $license) {
$actions = '<span style="white-space: nowrap;">';
if (Gate::allows('licenses.checkout')) {
$actions .= '<a href="' . route('freecheckout/license', $license->id)
. '" class="btn btn-primary btn-sm' . (($license->remaincount() > 0) ? '' : ' disabled') . '" style="margin-right:5px;">' . trans('general.checkout') . '</a> ';
}
if (Gate::allows('licenses.create')) {
$actions .= '<a href="' . route('clone/license', $license->id)
. '" class="btn btn-info btn-sm" style="margin-right:5px;" title="Clone asset"><i class="fa fa-files-o"></i></a>';
}
if (Gate::allows('licenses.edit')) {
$actions .= '<a href="' . route('update/license', $license->id)
. '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('licenses.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="'
. route('delete/license', $license->id)
. '" data-content="' . trans('admin/licenses/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($license->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</span>';
$rows[] = array(
'id' => $license->id,
'name' => (string) link_to('/admin/licenses/'.$license->id.'/view', $license->name),
'serial' => (string) link_to('/admin/licenses/'.$license->id.'/view', mb_strimwidth($license->serial, 0, 50, "...")),
'totalSeats' => $license->totalSeatsByLicenseID(),
'remaining' => $license->remaincount(),
'license_name' => e($license->license_name),
'license_email' => e($license->license_email),
'purchase_date' => ($license->purchase_date) ? $license->purchase_date : '',
'expiration_date' => ($license->expiration_date) ? $license->expiration_date : '',
'purchase_cost' => ($license->purchase_cost) ? number_format($license->purchase_cost, 2) : '',
'purchase_order' => ($license->purchase_order) ? e($license->purchase_order) : '',
'order_number' => ($license->order_number) ? e($license->order_number) : '',
'notes' => ($license->notes) ? e($license->notes) : '',
'actions' => $actions,
'companyName' => is_null($license->company) ? '' : e($license->company->name),
'manufacturer' => $license->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$license->manufacturer_id.'/view', $license->manufacturer->name) : ''
);
}
$data = array('total' => $licenseCount, 'rows' => $rows);
return $data;
}
public function getDataAccessoriesView(Manufacturer $manufacturer)
{
$accessories = $manufacturer->accessories;
if (Input::has('search')) {
$accessories = $accessories->TextSearch(e(Input::get('search')));
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
} else {
$limit = 50;
}
$accessCount = $accessories->count();
$rows = array();
foreach ($accessories as $accessory) {
$actions = '<nobr>';
if (Gate::allows('accessories.checkout')) {
$actions .= '<a href="' . route('checkout/accessory',
$accessory->id) . '" style="margin-right:5px;" class="btn btn-info btn-sm" ' . (($accessory->numRemaining() > 0) ? '' : ' disabled') . '>' . trans('general.checkout') . '</a>';
}
if (Gate::allows('accessories.edit')) {
$actions .= '<a href="' . route('update/accessory',
$accessory->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('accessories.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/accessory',
$accessory->id) . '" data-content="' . trans('admin/accessories/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($accessory->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .= '</nobr>';
$company = $accessory->company;
$rows[] = array(
'name' => '<a href="'.url('admin/accessories/'.$accessory->id).'/view">'. $accessory->name.'</a>',
'category' => ($accessory->category) ? (string)link_to('admin/settings/categories/'.$accessory->category->id.'/view', $accessory->category->name) : '',
'qty' => e($accessory->qty),
'order_number' => e($accessory->order_number),
'min_amt' => e($accessory->min_amt),
'location' => ($accessory->location) ? e($accessory->location->name): '',
'purchase_date' => e($accessory->purchase_date),
'purchase_cost' => number_format($accessory->purchase_cost, 2),
'numRemaining' => $accessory->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),
'manufacturer' => $accessory->manufacturer ? (string) link_to('/admin/settings/manufacturers/'.$accessory->manufacturer_id.'/view', $accessory->manufacturer->name) : ''
);
}
$data = array('total'=>$accessCount, 'rows'=>$rows);
return $data;
}
public function getDataConsumablesView($manufacturer)
{
$consumables = $manufacturer->consumables;
if (Input::has('search')) {
$consumables = $consumables->TextSearch(e(Input::get('search')));
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
} else {
$limit = 50;
}
$consumCount = $consumables->count();
$rows = array();
foreach ($consumables as $consumable) {
$actions = '<nobr>';
if (Gate::allows('consumables.checkout')) {
$actions .= '<a href="' . route('checkout/consumable',
$consumable->id) . '" style="margin-right:5px;" class="btn btn-info btn-sm" ' . (($consumable->numRemaining() > 0) ? '' : ' disabled') . '>' . trans('general.checkout') . '</a>';
}
if (Gate::allows('consumables.edit')) {
$actions .= '<a href="' . route('update/consumable',
$consumable->id) . '" class="btn btn-warning btn-sm" style="margin-right:5px;"><i class="fa fa-pencil icon-white"></i></a>';
}
if (Gate::allows('consumables.delete')) {
$actions .= '<a data-html="false" class="btn delete-asset btn-danger btn-sm" data-toggle="modal" href="' . route('delete/consumable',
$consumable->id) . '" data-content="' . trans('admin/consumables/message.delete.confirm') . '" data-title="' . trans('general.delete') . ' ' . htmlspecialchars($consumable->name) . '?" onClick="return false;"><i class="fa fa-trash icon-white"></i></a>';
}
$actions .='</nobr>';
$company = $consumable->company;
$rows[] = array(
'id' => $consumable->id,
'name' => (string)link_to('admin/consumables/'.$consumable->id.'/view', e($consumable->name)),
'location' => ($consumable->location) ? e($consumable->location->name) : '',
'min_amt' => e($consumable->min_amt),
'qty' => e($consumable->qty),
'manufacturer' => ($consumable->manufacturer) ? (string) link_to('/admin/settings/manufacturers/'.$consumable->manufacturer_id.'/view', $consumable->manufacturer->name): '',
'model_no' => e($consumable->model_no),
'item_no' => e($consumable->item_no),
'category' => ($consumable->category) ? (string) link_to('/admin/settings/categories/'.$consumable->category_id.'/view', $consumable->category->name) : 'Missing category',
'order_number' => e($consumable->order_number),
'purchase_date' => e($consumable->purchase_date),
'purchase_cost' => ($consumable->purchase_cost!='') ? number_format($consumable->purchase_cost, 2): '' ,
'numRemaining' => $consumable->numRemaining(),
'actions' => $actions,
'companyName' => is_null($company) ? '' : e($company->name),
);
}
$data = array('total' => $consumCount, 'rows' => $rows);
return $data;
}
}

View File

@@ -55,7 +55,7 @@ class ProfileController extends Controller
if (Input::file('avatar')) {
$image = Input::file('avatar');
$file_name = $user->first_name."-".$user->last_name.".".$image->getClientOriginalExtension();
$file_name = str_slug($user->first_name."-".$user->last_name).".".$image->getClientOriginalExtension();
$path = public_path('uploads/avatars/'.$file_name);
Image::make($image->getRealPath())->resize(84, 84)->save($path);
$user->avatar = $file_name;

View File

@@ -1,25 +1,27 @@
<?php
namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use Carbon\Carbon;
use App\Models\AssetModel;
use App\Models\Company;
use App\Models\CustomField;
use App\Models\License;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
use Input;
use League\Csv\Reader;
use App\Models\License;
use App\Models\Location;
use App\Models\AssetModel;
use App\Models\CustomField;
use Redirect;
use App\Models\Setting;
use App\Models\User;
use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* This controller handles all actions related to Reports for
@@ -31,7 +33,7 @@ class ReportsController extends Controller
{
/**
* Returns a view that displaysthe accessories report.
* Returns a view that displays the accessories report.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
@@ -87,7 +89,7 @@ class ReportsController extends Controller
}
/**
* Display asset report.
* Display asset report view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
@@ -96,23 +98,11 @@ class ReportsController extends Controller
public function getAssetsReport()
{
$settings = \App\Models\Setting::first();
// Grab all the assets
$assets = Asset::with(
'model',
'assigneduser.userLoc',
'assetstatus',
'defaultLoc',
'assetlog',
'supplier',
'model.manufacturer',
'company'
)
->orderBy('created_at', 'DESC')
->get();
return View::make('reports/asset', compact('assets'))->with('settings', $settings);
}
/**
* Exports the assets to CSV
*
@@ -122,103 +112,76 @@ class ReportsController extends Controller
*/
public function exportAssetReport()
{
// Grab all the assets
$assets = Asset::orderBy('created_at', 'DESC')->get();
$rows = [ ];
\Debugbar::disable();
// Create the header row
$header = [
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('admin/hardware/form.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('admin/hardware/table.location'),
trans('general.notes'),
];
$header = array_map('trim', $header);
$rows[] = implode($header, ',');
$customfields = CustomField::get();
// Create a row per asset
foreach ($assets as $asset) {
$row = [ ];
$row[] = e($asset->asset_tag);
if ($asset->model->manufacturer) {
$row[] = e($asset->model->manufacturer->name);
} else {
$row[] = '';
}
$row[] = '"' . e($asset->model->name) . '"';
$row[] = '"' . e($asset->model->modelno) . '"';
$row[] = e($asset->name);
$row[] = e($asset->serial);
if ($asset->assetstatus) {
$row[] = e($asset->assetstatus->name);
} else {
$row[] = '';
}
$row[] = $asset->purchase_date;
$row[] = '"' . number_format($asset->purchase_cost, 2) . '"';
if ($asset->order_number) {
$row[] = e($asset->order_number);
} else {
$row[] = '';
}
if ($asset->supplier_id) {
$row[] = e($asset->supplier->name);
} else {
$row[] = '';
}
$response = new StreamedResponse(function() use ($customfields) {
// Open output stream
$handle = fopen('php://output', 'w');
if ($asset->assigned_to > 0) {
$user = User::find($asset->assigned_to);
$row[] = e($user->fullName());
} else {
$row[] = ''; // Empty string if unassigned
}
if (( $asset->assigned_to > 0 ) && ( $asset->assigneduser->location_id > 0 )) {
$location = Location::find($asset->assigneduser->location_id);
if ($location) {
$row[] = e($location->name);
} else {
$row[] = '';
Asset::with('assigneduser', 'assetloc','defaultLoc','assigneduser.userloc','model','supplier','assetstatus','model.manufacturer')->orderBy('created_at', 'DESC')->chunk(500, function($assets) use($handle, $customfields) {
$headers=[
trans('general.company'),
trans('admin/hardware/table.asset_tag'),
trans('admin/hardware/form.manufacturer'),
trans('admin/hardware/form.model'),
trans('general.model_no'),
trans('general.name'),
trans('admin/hardware/table.serial'),
trans('general.status'),
trans('admin/hardware/table.purchase_date'),
trans('admin/hardware/table.purchase_cost'),
trans('admin/hardware/form.order'),
trans('admin/hardware/form.supplier'),
trans('admin/hardware/table.checkoutto'),
trans('admin/hardware/table.checkout_date'),
trans('admin/hardware/table.location'),
trans('general.notes'),
];
foreach($customfields as $field) {
$headers[]=$field->name;
}
} elseif ($asset->rtd_location_id) {
$location = Location::find($asset->rtd_location_id);
if ($location->name) {
$row[] = e($location->name);
} else {
$row[] = '';
fputcsv($handle, $headers);
foreach ($assets as $asset) {
// Add a new row with data
$values=[
($asset->company) ? $asset->company->name : '',
$asset->asset_tag,
($asset->model->manufacturer) ? $asset->model->manufacturer->name : '',
($asset->model) ? $asset->model->name : '',
($asset->model->modelno) ? $asset->model->modelno : '',
($asset->name) ? $asset->name : '',
($asset->serial) ? $asset->serial : '',
($asset->assetstatus) ? e($asset->assetstatus->name) : '',
($asset->purchase_date) ? e($asset->purchase_date) : '',
($asset->purchase_cost > 0) ? Helper::formatCurrencyOutput($asset->purchase_cost) : '',
($asset->order_number) ? e($asset->order_number) : '',
($asset->supplier) ? e($asset->supplier->name) : '',
($asset->assigneduser) ? e($asset->assigneduser->fullName()) : '',
($asset->last_checkout!='') ? e($asset->last_checkout) : '',
($asset->assigneduser && $asset->assigneduser->userloc!='') ?
e($asset->assigneduser->userloc->name) : ( ($asset->defaultLoc!='') ? e($asset->defaultLoc->name) : ''),
($asset->notes) ? e($asset->notes) : '',
];
foreach($customfields as $field) {
$values[]=$asset->{$field->db_column_name()};
}
fputcsv($handle, $values);
}
} else {
$row[] = ''; // Empty string if location is not set
}
});
if ($asset->notes) {
$row[] = '"' . e($asset->notes) . '"';
} else {
$row[] = '';
}
$rows[] = implode($row, ',');
}
// spit out a csv
$csv = implode($rows, "\n");
$response = Response::make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
// Close the output stream
fclose($handle);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="assets-'.date('Y-m-d-his').'.csv"',
]);
return $response;
}
/**
@@ -308,9 +271,9 @@ class ReportsController extends Controller
}
$row[] = $asset->purchase_date;
$row[] = $currency . number_format($asset->purchase_cost, 2);
$row[] = $currency . number_format($asset->getDepreciatedValue(), 2);
$row[] = $currency . number_format(( $asset->purchase_cost - $asset->getDepreciatedValue() ), 2);
$row[] = $currency . Helper::formatCurrencyOutput($asset->purchase_cost);
$row[] = $currency . Helper::formatCurrencyOutput($asset->getDepreciatedValue());
$row[] = $currency . Helper::formatCurrencyOutput(( $asset->purchase_cost - $asset->getDepreciatedValue() ));
$csv->insertOne($row);
}
@@ -329,11 +292,7 @@ class ReportsController extends Controller
public function getActivityReport()
{
$log_actions = Actionlog::orderBy('created_at', 'DESC')
->with('adminlog')
->with('accessorylog')
->with('assetlog')
->with('licenselog')
->with('userlog')
->with('item')
->orderBy('created_at', 'DESC')
->get();
@@ -341,16 +300,114 @@ class ReportsController extends Controller
}
/**
* Displays license report
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
* Returns Activity Report JSON.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getActivityReportDataTable()
{
$activitylogs = Company::scopeCompanyables(Actionlog::with('item', 'user', 'target'))->orderBy('created_at', 'DESC');
if (Input::has('search')) {
$activity = $activity->TextSearch(e(Input::get('search')));
}
if (Input::has('offset')) {
$offset = e(Input::get('offset'));
} else {
$offset = 0;
}
if (Input::has('limit')) {
$limit = e(Input::get('limit'));
} else {
$limit = 50;
}
$allowed_columns = ['created_at'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e(Input::get('sort')) : 'created_at';
$activityCount = $activitylogs->count();
// dd("Offset:" . $offset . " Limit " . $limit);
$activitylogs = $activitylogs->offset($offset)->limit($limit)->get();
$rows = array();
foreach ($activitylogs as $activity) {
if ($activity->itemType() == "asset") {
$activity_icons = '<i class="fa fa-barcode"></i>';
} elseif ($activity->itemType() == "accessory") {
$activity_icons = '<i class="fa fa-keyboard-o"></i>';
} elseif ($activity->itemType()=="consumable") {
$activity_icons = '<i class="fa fa-tint"></i>';
} elseif ($activity->itemType()=="license"){
$activity_icons = '<i class="fa fa-floppy-o"></i>';
} elseif ($activity->itemType()=="component") {
$activity_icons = '<i class="fa fa-hdd-o"></i>';
} else {
$activity_icons = '<i class="fa fa-paperclip"></i>';
}
if (($activity->item) && ($activity->itemType()=="asset")) {
$activity_item = '<a href="'.route('view/hardware', $activity->item_id).'">'.e($activity->item->asset_tag).' - '. e($activity->item->showAssetName()).'</a>';
$item_type = 'asset';
} elseif ($activity->item()) {
$activity_item = '<a href="'.route('view/'. $activity->itemType(), $activity->item_id).'">'.e($activity->item->name).'</a>';
$item_type = $activity->itemType();
} else {
$activity_item = "unkonwn";
$item_type = "null";
}
if (($activity->user) && ($activity->action_type=="uploaded") && ($activity->itemType()=="user")) {
$activity_target = '<a href="'.route('view/user', $activity->target_id).'">'.$activity->user->fullName().'</a>';
} elseif (($activity->item) && ($activity->target_type === "App\Models\Asset")) {
$activity_target = '<a href="'.route('view/hardware', $activity->target_id).'">'.$activity->target->showAssetName().'</a>';
} elseif ( $activity->target_type === "App\Models\User") {
$activity_target = '<a href="'.route('view/user', $activity->target_id).'">'.$activity->target->fullName().'</a>';
} elseif ($activity->action_type=='requested') {
$activity_target = '<a href="'.route('view/user', $activity->user_id).'">'.$activity->user->fullName().'</a>';
} else {
$activity_target = $activity->target->id;
}
$rows[] = array(
'icon' => $activity_icons,
'created_at' => date("M d, Y g:iA", strtotime($activity->created_at)),
'action_type' => strtolower(trans('general.'.str_replace(' ','_',$activity->action_type))),
'admin' => $activity->user ? (string) link_to('/admin/users/'.$activity->user_id.'/view', $activity->user->fullName()) : '',
'target' => $activity_target,
'item' => $activity_item,
'item_type' => $item_type,
'note' => e($activity->note),
);
}
$data = array('total'=>$activityCount, 'rows'=>$rows);
return $data;
}
/**
* Displays license report
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return View
*/
public function getLicenseReport()
{
$licenses = License::orderBy('created_at', 'DESC')
$licenses = License::with('depreciation')->orderBy('created_at', 'DESC')
->with('company')
->get();
@@ -377,6 +434,7 @@ class ReportsController extends Controller
trans('admin/licenses/form.remaining_seats'),
trans('admin/licenses/form.expiration'),
trans('admin/licenses/form.date'),
trans('admin/licenses/form.depreciation'),
trans('admin/licenses/form.cost')
];
@@ -392,7 +450,8 @@ class ReportsController extends Controller
$row[] = $license->remaincount();
$row[] = $license->expiration_date;
$row[] = $license->purchase_date;
$row[] = '"' . number_format($license->purchase_cost, 2) . '"';
$row[] = ($license->depreciation!='') ? '' : e($license->depreciation->name);
$row[] = '"' . Helper::formatCurrencyOutput($license->purchase_cost) . '"';
$rows[] = implode($row, ',');
}
@@ -416,25 +475,29 @@ class ReportsController extends Controller
public function getCustomReport()
{
$customfields = CustomField::get();
return View::make('reports/custom')->with('customfields',$customfields);
return View::make('reports/custom')->with('customfields', $customfields);
}
/**
* Exports the custom report to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::getCustomReport() method that generates form view
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
* Exports the custom report to CSV
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see ReportsController::getCustomReport() method that generates form view
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
public function postCustom()
{
$assets = Asset::orderBy('created_at', 'DESC')->get();
$assets = Asset::orderBy('created_at', 'DESC')->with('company','assigneduser', 'assetloc','defaultLoc','assigneduser.userloc','model','supplier','assetstatus','model.manufacturer')->get();
$customfields = CustomField::get();
$rows = [ ];
$header = [ ];
if (e(Input::get('company')) == '1') {
$header[] = 'Company Name';
}
if (e(Input::get('asset_name')) == '1') {
$header[] = 'Asset Name';
}
@@ -500,6 +563,11 @@ class ReportsController extends Controller
foreach ($assets as $asset) {
$row = [ ];
if (e(Input::get('company')) == '1') {
$row[] = is_null($asset->company) ? '' : '"'.$asset->company->name.'"';
}
if (e(Input::get('asset_name')) == '1') {
$row[] = '"' .e($asset->name) . '"';
}
@@ -528,7 +596,7 @@ class ReportsController extends Controller
$row[] = e($asset->purchase_date);
}
if (e(Input::get('purchase_cost')) == '1' && ( e(Input::get('depreciation')) != '1' )) {
$row[] = '"' . number_format($asset->purchase_cost, 2) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
}
if (e(Input::get('order')) == '1') {
if ($asset->order_number) {
@@ -605,9 +673,9 @@ class ReportsController extends Controller
}
if (e(Input::get('depreciation')) == '1') {
$depreciation = $asset->getDepreciatedValue();
$row[] = '"' . number_format($asset->purchase_cost, 2) . '"';
$row[] = '"' . number_format($depreciation, 2) . '"';
$row[] = '"' . number_format($asset->purchase_cost - $depreciation, 2) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($depreciation) . '"';
$row[] = '"' . Helper::formatCurrencyOutput($asset->purchase_cost) . '"';
}
foreach ($customfields as $customfield) {
@@ -626,14 +694,15 @@ class ReportsController extends Controller
$csv = implode($rows, "\n");
$response = Response::make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
$response->header('Content-disposition', 'attachment;filename='.date('Y-m-d-His').'-custom-asset-report.csv');
return $response;
} else {
return redirect()->to("reports/custom")
->with('error', trans('admin/reports/message.error'));
->with('error', trans('admin/reports/message.error'));
}
}
/**
* getImprovementsReport
@@ -698,7 +767,7 @@ class ReportsController extends Controller
$improvementTime = intval($assetMaintenance->asset_maintenance_time);
}
$row[] = $improvementTime;
$row[] = trans('general.currency') . number_format($assetMaintenance->cost, 2);
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($assetMaintenance->cost);
$rows[] = implode($row, ',');
}

View File

@@ -52,29 +52,18 @@ class SettingsController extends Controller
$protocol = array_key_exists('HTTPS', $_SERVER) && ( $_SERVER['HTTPS'] == "on") ? 'https://' : 'http://';
$pageURL = $protocol;
if ($_SERVER["SERVER_PORT"] != "80") {
$main_page = $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"];
$pageURL .= $main_page.$_SERVER["REQUEST_URI"];
} else {
$main_page = $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
$pageURL .= $main_page;
$host = $_SERVER['SERVER_NAME'];
if (($protocol === 'http://' && $_SERVER['SERVER_PORT'] != '80') || ($protocol === 'https://' && $_SERVER['SERVER_PORT'] != '443')) {
$host .= ':' . $_SERVER['SERVER_PORT'];
}
$pageURL = $protocol . $host . $_SERVER['REQUEST_URI'];
$start_settings['env_location'] = $pageURL.'../.env';
$start_settings['url_valid'] = (config('app.url').'/setup' === $pageURL);
$start_settings['url_config'] = config('app.url');
$start_settings['real_url'] = $pageURL;
if (config('app.url').'/setup'!=$pageURL) {
$start_settings['url_valid']= false;
} else {
$start_settings['url_valid']= true;
}
$start_settings['url_config']= config('app.url');
$start_settings['real_url']= $pageURL;
$exposed_env = @file_get_contents($main_page.'/.env');
$exposed_env = @file_get_contents($protocol . $host.'/.env');
if ($exposed_env) {
$start_settings['env_exposed'] = true;
@@ -147,7 +136,8 @@ class SettingsController extends Controller
try {
Mail::send('emails.test', [], function ($m) {
$m->to(config('mail.from.address'), config('mail.from.name'));
$m->subject('Test Email from Snipe-IT');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.test_email'));
});
return 'success';
} catch (Exception $e) {
@@ -195,11 +185,12 @@ class SettingsController extends Controller
} else {
$user->save();
$settings->save();
if (Input::get('email_creds')=='1') {
Mail::send(['text' => 'emails.firstadmin'], $data, function ($m) use ($data) {
$m->to($data['email'], $data['first_name']);
$m->subject('Your Snipe-IT credentials');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.your_credentials'));
});
}
@@ -323,7 +314,7 @@ class SettingsController extends Controller
$setting->logo = $file_name;
}
}
if (config('app.lock_passwords')==false) {
$setting->site_name = e(Input::get('site_name'));
@@ -482,7 +473,7 @@ class SettingsController extends Controller
}
closedir($handle);
$files = array_reverse($files);
rsort($files);
}

View File

@@ -120,6 +120,7 @@ class StatuslabelsController extends Controller
$statuslabel->pending = $statustype['pending'];
$statuslabel->archived = $statustype['archived'];
$statuslabel->color = e(Input::get('color'));
$statuslabel->show_in_nav = e(Input::get('show_in_nav'),0);
// Was the asset created?
@@ -208,6 +209,7 @@ class StatuslabelsController extends Controller
$statuslabel->pending = $statustype['pending'];
$statuslabel->archived = $statustype['archived'];
$statuslabel->color = e(Input::get('color'));
$statuslabel->show_in_nav = e(Input::get('show_in_nav'),0);
// Was the asset created?
@@ -258,7 +260,7 @@ class StatuslabelsController extends Controller
public function getDatatable()
{
$statuslabels = Statuslabel::select(array('id','name','deployable','pending','archived','color'))
$statuslabels = Statuslabel::select(array('id','name','deployable','pending','archived','color','show_in_nav'))
->whereNull('deleted_at');
if (Input::has('search')) {
@@ -314,6 +316,7 @@ class StatuslabelsController extends Controller
'type' => e($label_type),
'name' => e($statuslabel->name),
'color' => $color,
'show_in_nav' => ($statuslabel->show_in_nav=='1') ? trans('general.yes') : trans('general.no'),
'actions' => $actions
);
}

View File

@@ -157,7 +157,8 @@ class UsersController extends Controller
Mail::send('emails.send-login', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Welcome ' . $user->first_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.welcome', ['name' => $user->first_name]));
});
}
return redirect::route('users')->with('success', trans('admin/users/message.success.create'));
@@ -209,7 +210,8 @@ class UsersController extends Controller
Mail::send('emails.send-login', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Welcome ' . $user->first_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.welcome', ['name' => $user->first_name]));
});
}
@@ -495,9 +497,10 @@ class UsersController extends Controller
// Update the asset log
$logaction = new Actionlog();
$logaction->asset_id = $asset->id;
$logaction->checkedout_to = $asset->assigned_to;
$logaction->asset_type = 'hardware';
$logaction->item_id = $asset->id;
$logaction->item_type = Asset::class;
$logaction->target_id = $asset->assigned_to;
$logaction->target_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = 'Bulk checkin asset and delete user';
$logaction->logaction('checkin from');
@@ -514,9 +517,10 @@ class UsersController extends Controller
$accessory_array[] = $accessory->accessory_id;
// Update the asset log
$logaction = new Actionlog();
$logaction->accessory_id = $accessory->id;
$logaction->checkedout_to = $accessory->assigned_to;
$logaction->asset_type = 'accessory';
$logaction->item_id = $accessory->id;
$logaction->item_type = Accessory::class;
$logaction->target_id = $accessory->assigned_to;
$logaction->target_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = 'Bulk checkin accessory and delete user';
$logaction->logaction('checkin from');
@@ -528,9 +532,10 @@ class UsersController extends Controller
$license_array[] = $license->id;
// Update the asset log
$logaction = new Actionlog();
$logaction->asset_id = $license->id;
$logaction->checkedout_to = $license->assigned_to;
$logaction->asset_type = 'software';
$logaction->item_id = $license->id;
$logaction->item_type = License::class;
$logaction->target_id = $license->assigned_to;
$logaction->target_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = 'Bulk checkin license and delete user';
$logaction->logaction('checkin from');
@@ -598,7 +603,7 @@ class UsersController extends Controller
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($userId);
$userlog = $user->userlog->load('assetlog', 'consumablelog', 'assetlog.model', 'licenselog', 'accessorylog', 'userlog', 'adminlog');
$userlog = $user->userlog->load('item');
if (isset($user->id)) {
@@ -829,7 +834,8 @@ class UsersController extends Controller
if ($newuser['email']) {
Mail::send('emails.send-login', $data, function ($m) use ($newuser) {
$m->to($newuser['email'], $newuser['first_name'] . ' ' . $newuser['last_name']);
$m->subject('Welcome ' . $newuser['first_name']);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.welcome', ['name' => $newuser['first_name']]));
});
}
}
@@ -1017,12 +1023,12 @@ class UsersController extends Controller
//Log the deletion of seats to the log
$logaction = new Actionlog();
$logaction->asset_id = $user->id;
$logaction->asset_type = 'user';
$logaction->item_id = $user->id;
$logaction->item_type = User::class;
$logaction->user_id = Auth::user()->id;
$logaction->note = e(Input::get('notes'));
$logaction->checkedout_to = null;
$logaction->created_at = date("Y-m-d h:i:s");
$logaction->target_id = null;
$logaction->created_at = date("Y-m-d H:i:s");
$logaction->filename = $filename;
$logaction->action_type = 'uploaded';
$logaction->save();

View File

@@ -4,12 +4,14 @@ namespace App\Http\Controllers;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\CheckoutRequest;
use App\Models\Company;
use App\Models\Consumable;
use App\Models\Component;
use App\Models\Consumable;
use App\Models\License;
use App\Models\Setting;
use App\Models\User;
use App\Models\License;
use Auth;
use Config;
use DB;
@@ -37,11 +39,18 @@ class ViewAssetsController extends Controller
public function getIndex()
{
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find(Auth::user()->id);
$userlog = $user->userlog->load('assetlog', 'consumablelog', 'assetlog.model', 'licenselog', 'accessorylog', 'userlog', 'adminlog');
$user = User::with(
'assets',
'assets.model',
'consumables',
'accessories',
'licenses',
'userloc',
'userlog'
)->withTrashed()->find(Auth::user()->id);
$userlog = $user->userlog->load('item', 'user', 'target');
if (isset($user->id)) {
return View::make('account/view-assets', compact('user', 'userlog'));
@@ -60,11 +69,132 @@ class ViewAssetsController extends Controller
{
$assets = Asset::with('model', 'defaultLoc', 'assetloc', 'assigneduser')->Hardware()->RequestableAssets()->get();
$models = AssetModel::with('category')->RequestableModels()->get();
return View::make('account/requestable-assets', compact('user', 'assets'));
return View::make('account/requestable-assets', compact('user', 'assets', 'models'));
}
public function getRequestedIndex()
{
$requestedItems = CheckoutRequest::with('user', 'requestedItem')->get();
return View::make('admin/requested-assets', compact('requestedItems'));
}
public function getRequestItem($itemType, $itemId = null)
{
$item = null;
$fullItemType = 'App\\Models\\' . studly_case($itemType);
if ($itemType == "asset_model") {
$itemType = "model";
}
$item = call_user_func(array($fullItemType, 'find'), $itemId);
$user = Auth::user();
$quantity = $data['item_quantity'] = Input::has('request-quantity') ? e(Input::get('request-quantity')) : 1;
$logaction = new Actionlog();
$logaction->item_id = $data['asset_id'] = $item->id;
$logaction->item_type = $fullItemType;
$logaction->created_at = $data['requested_date'] = date("Y-m-d H:i:s");
if ($user->location_id) {
$logaction->location_id = $user->location_id;
}
$logaction->target_id = $data['user_id'] = Auth::user()->id;
$logaction->target_type = User::class;
$data['requested_by'] = $user->fullName();
$data['item_name'] = $item->name;
$data['item_type'] = $itemType;
if ($fullItemType == Asset::class) {
$data['item_url'] = route('view/hardware', $item->id);
$slackMessage = ' Asset <'.config('app.url').'/hardware/'.$item->id.'/view'.'|'.$item->showAssetName().'> requested by <'.config('app.url').'/users/'.$item->user_id.'/view'.'|'.$user->fullName().'>.';
} else {
$data['item_url'] = route("view/${itemType}", $item->id);
$slackMessage = $quantity. ' ' . class_basename(strtoupper($logaction->item_type)).' <'.$data['item_url'].'|'.$item->name.'> requested by <'.config('app.url').'/user/'.$item->id.'/view'.'|'.$user->fullName().'>.';
}
$settings = Setting::getSettings();
if ($settings->slack_endpoint) {
$slack_settings = [
'username' => $settings->botname,
'channel' => $settings->slack_channel,
'link_names' => true
];
$slackClient = new \Maknz\Slack\Client($settings->slack_endpoint, $slack_settings);
}
if ($item->isRequestedBy($user)) {
$item->cancelRequest();
$log = $logaction->logaction('request_canceled');
if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) {
Mail::send('emails.asset-canceled', $data, function ($m) use ($user, $settings) {
$m->to(explode(',', $settings->alert_email), $settings->site_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Item_Request_Canceled'));
});
}
if ($settings->slack_endpoint) {
try {
$slackClient->attach([
'color' => 'good',
'fields' => [
[
'title' => 'CANCELED:',
'value' => $slackMessage
]
]
])->send('Item Request Canceled');
} catch (Exception $e) {
}
}
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
} else {
$item->request();
$log = $logaction->logaction('requested');
if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) {
Mail::send('emails.asset-requested', $data, function ($m) use ($user, $settings) {
$m->to(explode(',', $settings->alert_email), $settings->site_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Item_Requested'));
});
}
if ($settings->slack_endpoint) {
try {
$slackClient->attach([
'color' => 'good',
'fields' => [
[
'title' => 'REQUESTED:',
'value' => $slackMessage
]
]
])->send('Item Requested');
} catch (Exception $e) {
}
}
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
}
}
public function getRequestAsset($assetId = null)
{
@@ -76,17 +206,23 @@ class ViewAssetsController extends Controller
return redirect()->route('requestable-assets')->with('error', trans('admin/hardware/message.does_not_exist_or_not_requestable'));
} elseif (!Company::isCurrentUserHasAccess($asset)) {
return redirect()->route('requestable-assets')->with('error', trans('general.insufficient_permissions'));
}
// If it's requested, cancel the request.
if ($asset->isRequestedBy(Auth::user())) {
$asset->cancelRequest();
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
} else {
$logaction = new Actionlog();
$logaction->asset_id = $data['asset_id'] = $asset->id;
$logaction->asset_type = $data['asset_type'] = 'hardware';
$logaction->created_at = $data['requested_date'] = date("Y-m-d h:i:s");
$logaction->item_id = $data['asset_id'] = $asset->id;
$logaction->item_type = Asset::class;
$logaction->created_at = $data['requested_date'] = date("Y-m-d H:i:s");
$data['asset_type'] = 'hardware';
if ($user->location_id) {
$logaction->location_id = $user->location_id;
}
$logaction->user_id = $data['user_id'] = Auth::user()->id;
$logaction->target_id = $data['user_id'] = Auth::user()->id;
$logaction->target_type = User::class;
$log = $logaction->logaction('requested');
$data['requested_by'] = $user->fullName();
@@ -97,10 +233,13 @@ class ViewAssetsController extends Controller
if (($settings->alert_email!='') && ($settings->alerts_enabled=='1') && (!config('app.lock_passwords'))) {
Mail::send('emails.asset-requested', $data, function ($m) use ($user, $settings) {
$m->to(explode(',', $settings->alert_email), $settings->site_name);
$m->subject('Asset Requested');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.asset_requested'));
});
}
$asset->request();
if ($settings->slack_endpoint) {
@@ -119,7 +258,7 @@ class ViewAssetsController extends Controller
'fields' => [
[
'title' => 'REQUESTED:',
'value' => strtoupper($logaction->asset_type).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.$asset->showAssetName().'> requested by <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.Auth::user()->fullName().'>.'
'value' => class_basename(strtoupper($logaction->item_type)).' asset <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.$asset->showAssetName().'> requested by <'.config('app.url').'/hardware/'.$asset->id.'/view'.'|'.Auth::user()->fullName().'>.'
]
]
@@ -137,13 +276,20 @@ class ViewAssetsController extends Controller
}
public function getRequestedAssets()
{
$checkoutrequests = CheckoutRequest::all();
return View::make('account/requested-items', compact($checkoutrequests));
}
// Get the acceptance screen
public function getAcceptAsset($logID = null)
{
if (!$findlog = DB::table('asset_logs')->where('id', '=', $logID)->first()) {
if (!$findlog = Actionlog::where('id', $logID)->first()) {
echo 'no record';
//return redirect()->to('account')->with('error', trans('admin/hardware/message.does_not_exist'));
}
@@ -155,23 +301,7 @@ class ViewAssetsController extends Controller
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
// Asset
if (($findlog->asset_id!='') && ($findlog->asset_type=='hardware')) {
$item = Asset::find($findlog->asset_id);
// software
} elseif (($findlog->asset_id!='') && ($findlog->asset_type=='software')) {
$item = License::find($findlog->asset_id);
// accessories
} elseif ($findlog->accessory_id!='') {
$item = Accessory::find($findlog->accessory_id);
// consumable
} elseif ($findlog->consumable_id!='') {
$item = Consumable::find($findlog->consumable_id);
// components
} elseif ($findlog->component_id!='') {
$item = Component::find($findlog->component_id);
}
$item = $findlog->item;
// Check if the asset exists
if (is_null($item)) {
@@ -189,11 +319,11 @@ class ViewAssetsController extends Controller
{
// Check if the asset exists
if (is_null($findlog = DB::table('asset_logs')->where('id', '=', $logID)->first())) {
if (is_null($findlog = Actionlog::where('id', $logID)->first())) {
// Redirect to the asset management page
return redirect()->to('account/view-assets')->with('error', trans('admin/hardware/message.does_not_exist'));
}
if ($findlog->accepted_id!='') {
// Redirect to the asset management page
@@ -221,56 +351,24 @@ class ViewAssetsController extends Controller
$accepted="rejected";
$return_msg = trans('admin/users/message.declined');
}
$logaction->item_id = $findlog->item_id;
$logaction->item_type = $findlog->item_type;
// Asset
if (($findlog->asset_id!='') && ($findlog->asset_type=='hardware')) {
$logaction->asset_id = $findlog->asset_id;
$logaction->accessory_id = null;
$logaction->asset_type = 'hardware';
if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) {
if (Input::get('asset_acceptance')!='accepted') {
DB::table('assets')
->where('id', $findlog->asset_id)
->where('id', $findlog->item_id)
->update(array('assigned_to' => null));
}
// software
} elseif (($findlog->asset_id!='') && ($findlog->asset_type=='software')) {
$logaction->asset_id = $findlog->asset_id;
$logaction->accessory_id = null;
$logaction->component_id = null;
$logaction->asset_type = 'software';
// accessories
} elseif ($findlog->accessory_id!='') {
$logaction->asset_id = null;
$logaction->component_id = null;
$logaction->accessory_id = $findlog->accessory_id;
$logaction->asset_type = 'accessory';
// accessories
} elseif ($findlog->consumable_id!='') {
$logaction->asset_id = null;
$logaction->accessory_id = null;
$logaction->component_id = null;
$logaction->consumable_id = $findlog->consumable_id;
$logaction->asset_type = 'consumable';
} elseif ($findlog->component_id!='') {
$logaction->asset_id = null;
$logaction->accessory_id = null;
$logaction->consumable_id = null;
$logaction->component_id = $findlog->component_id;
$logaction->asset_type = 'component';
}
$logaction->checkedout_to = $findlog->checkedout_to;
$logaction->target_id = $findlog->target_id;
$logaction->note = e(Input::get('note'));
$logaction->user_id = $user->id;
$logaction->accepted_at = date("Y-m-d h:i:s");
$logaction->accepted_at = date("Y-m-d H:i:s");
$log = $logaction->logaction($logaction_msg);
$update_checkout = DB::table('asset_logs')
$update_checkout = DB::table('action_logs')
->where('id', $findlog->id)
->update(array('accepted_id' => $logaction->id));

View File

@@ -15,7 +15,10 @@ class FrameGuard
public function handle($request, Closure $next)
{
$response = $next($request);
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
if (config('app.allow_iframing') == false) {
$response->headers->set('X-Frame-Options', 'SAMEORIGIN', false);
}
return $response;
}
}

View File

@@ -37,6 +37,7 @@ class AssetRequest extends Request
'supplier_id' => 'integer',
'status' => 'integer',
'asset_tag' => 'required',
'purchase_cost' => 'numeric',
];

View File

@@ -25,10 +25,10 @@ class SaveUserRequest extends Request
{
return [
'first_name' => 'required|string|min:1',
'last_name' => 'required|string|min:1',
'email' => 'email',
'password' => 'required|min:6',
'password_confirm' => 'sometimes|required_with:password',
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
];
}
}

View File

@@ -1,6 +1,7 @@
<?php
use App\Models\Statuslabel;
use App\Models\CheckoutRequest;
use App\Models\Location;
use App\Models\Statuslabel;
/*
|--------------------------------------------------------------------------
@@ -78,7 +79,7 @@ Route::group([ 'prefix' => 'api', 'middleware' => 'auth' ], function () {
/*---Manufacturers API---*/
Route::group(array('prefix'=>'manufacturers'), function () {
Route::get('list', array('as'=>'api.manufacturers.list', 'uses'=>'ManufacturersController@getDatatable'));
Route::get('{manufacturerID}/view', array('as'=>'api.manufacturers.view', 'uses'=>'ManufacturersController@getDataView'));
Route::get('{manufacturerID}/view/{itemtype}', array('as'=>'api.manufacturers.view', 'uses'=>'ManufacturersController@getDataView'));
});
/*---Suppliers API---*/
@@ -293,9 +294,13 @@ Route::group(
'uses' => 'AssetsController@getDeleteImportFile'
]);
Route::get( 'import/process/{filename}', [ 'as' => 'assets/import/process-file',
Route::post( 'import/process/', [ 'as' => 'assets/import/process-file',
'middleware' => 'authorize:assets.create',
'uses' => 'AssetsController@getProcessImportFile'
'uses' => 'AssetsController@postProcessImportFile'
]);
Route::get( 'import/delete/{filename}', [ 'as' => 'assets/import/delete-file',
'middleware' => 'authorize:assets.create', // TODO What permissions should this require?
'uses' => 'AssetsController@getDeleteImportFile'
]);
Route::get('import',[
@@ -384,6 +389,14 @@ Route::group(
Route::group([ 'prefix' => 'admin','middleware' => ['web','auth']], function () {
Route::get('requests',
// foreach( CheckoutRequest::with('user')->get() as $requestedItem) {
// echo $requestedItem->user->username . ' requested ' . $requestedItem->requestedItem->name;
[
'as' => 'requests',
'middleware' => 'authorize:admin',
'uses' => 'ViewAssetsController@getRequestedIndex'
]);
# Licenses
Route::group([ 'prefix' => 'licenses', 'middleware'=>'authorize:licenses.view' ], function () {
@@ -854,6 +867,11 @@ Route::group([ 'prefix' => 'account', 'middleware' => ['web', 'auth']], function
[ 'as' => 'account/request-asset', 'uses' => 'ViewAssetsController@getRequestAsset' ]
);
Route::post(
'request/{itemType}/{itemId}',
[ 'as' => 'account/request-item', 'uses' => 'ViewAssetsController@getRequestItem']
);
# Account Dashboard
Route::get('/', [ 'as' => 'account', 'uses' => 'ViewAssetsController@getIndex' ]);
@@ -906,6 +924,12 @@ Route::group(['middleware' => ['web','auth','authorize:reports.view']], function
'reports/activity',
[ 'as' => 'reports/activity', 'uses' => 'ReportsController@getActivityReport' ]
);
Route::get(
'reports/activity/json',
[ 'as' => 'api.activity.list', 'uses' => 'ReportsController@getActivityReportDataTable' ]
);
Route::get(
'reports/unaccepted_assets',
[ 'as' => 'reports/unaccepted_assets', 'uses' => 'ReportsController@getAssetAcceptanceReport' ]

View File

@@ -1,6 +1,7 @@
<?php
namespace App\Models;
use App\Models\Loggable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -12,8 +13,9 @@ use Watson\Validating\ValidatingTrait;
*/
class Accessory extends Model
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'accessories';
@@ -22,11 +24,12 @@ class Accessory extends Model
* Accessory validation rules
*/
public $rules = array(
'name' => 'required|min:3|max:255',
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer',
'company_id' => 'integer',
'min_amt' => 'integer|min:1',
'name' => 'required|min:3|max:255',
'qty' => 'required|integer|min:1',
'category_id' => 'required|integer',
'company_id' => 'integer',
'min_amt' => 'integer|min:1',
'purchase_cost' => 'numeric',
);
@@ -67,7 +70,7 @@ class Accessory extends Model
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'accessory_id')->where('asset_type', '=', 'accessory')->orderBy('created_at', 'desc')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Accessory::class)->orderBy('created_at', 'desc')->withTrashed();
}
@@ -81,6 +84,11 @@ class Accessory extends Model
return $this->belongsToMany('\App\Models\User', 'accessories_users', 'accessory_id', 'assigned_to')->count();
}
public function manufacturer()
{
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
}
public function checkin_email()
{
return $this->category->checkin_email;

View File

@@ -2,9 +2,10 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Model for the Actionlog (the table that keeps a historical log of
@@ -12,95 +13,74 @@ use Illuminate\Database\Eloquent\SoftDeletes;
*
* @version v1.0
*/
class Actionlog extends Model implements ICompanyableChild
class Actionlog extends Model
{
use SoftDeletes;
use CompanyableChildTrait;
protected $dates = [ 'deleted_at' ];
protected $table = 'asset_logs';
protected $table = 'action_logs';
public $timestamps = true;
protected $fillable = [ 'created_at', 'asset_type','user_id','asset_id','action_type','note','checkedout_to' ];
protected $fillable = [ 'created_at', 'item_type','user_id','item_id','action_type','note','target_id', 'target_type' ];
public function getCompanyableParents()
// Overridden from Builder to automatically add the company
public static function boot()
{
return [ 'accessorylog', 'assetlog', 'licenselog', 'consumablelog' ];
parent::boot();
static::creating( function (Actionlog $actionlog) {
// If the admin is a superadmin, let's see if the target instead has a company.
if (Auth::user() && Auth::user()->isSuperUser()) {
$actionlog->company_id = $actionlog->target->company_id;
} else if (Auth::user() && Auth::user()->company) {
$actionlog->company_id = Auth::user()->company_id;
}
});
}
// Eloquent Relationships below
public function item()
{
return $this->morphTo('item')->withTrashed();
}
public function assetlog()
public function itemType()
{
return $this->belongsTo('\App\Models\Asset', 'asset_id')
->withTrashed();
if($this->item_type == AssetModel::class) {
return "model";
}
return camel_case(class_basename($this->item_type));
}
public function uploads()
{
return $this->belongsTo('\App\Models\Asset', 'asset_id')
return $this->morphTo('item')
->where('action_type', '=', 'uploaded')
->withTrashed();
}
public function licenselog()
{
return $this->belongsTo('\App\Models\License', 'asset_id')
->withTrashed();
}
public function componentlog()
{
return $this->belongsTo('\App\Models\Component', 'component_id')
->withTrashed();
}
public function accessorylog()
{
return $this->belongsTo('\App\Models\Accessory', 'accessory_id')
->withTrashed();
}
public function consumablelog()
{
return $this->belongsTo('\App\Models\Consumable', 'consumable_id')
->withTrashed();
}
public function adminlog()
{
return $this->belongsTo('\App\Models\User', 'user_id')
->withTrashed();
}
public function userlog()
{
return $this->target();
}
return $this->belongsTo('\App\Models\User', 'checkedout_to')
public function user()
{
return $this->belongsTo(User::class, 'user_id')
->withTrashed();
}
public function userasassetlog()
public function target()
{
return $this->belongsTo('\App\Models\User', 'asset_id')
->withTrashed();
return $this->morphTo('target');
}
public function childlogs()
{
return $this->hasMany('\App\Models\ActionLog', 'thread_id');
}
public function parentlog()
{
return $this->belongsTo('\App\Models\ActionLog', 'thread_id');
}
@@ -141,44 +121,10 @@ class Actionlog extends Model implements ICompanyableChild
public function getListingOfActionLogsChronologicalOrder()
{
return DB::table('asset_logs')
->select('*')
return $this->all()
->where('action_type', '!=', 'uploaded')
->orderBy('asset_id', 'asc')
->orderBy('item_id', 'asc')
->orderBy('created_at', 'asc')
->get();
}
/**
* getLatestCheckoutActionForAssets
*
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function getLatestCheckoutActionForAssets()
{
return DB::table('asset_logs')
->select(DB::raw('asset_id, MAX(created_at) as last_created'))
->where('action_type', '=', 'checkout')
->groupBy('asset_id')
->get();
}
/**
* scopeCheckoutWithoutAcceptance
*
* @param $query
*
* @return mixed
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
*/
public function scopeCheckoutWithoutAcceptance($query)
{
return $query->where('action_type', '=', 'checkout')
->where('accepted_id', '=', null);
}
}

View File

@@ -1,20 +1,22 @@
<?php
namespace App\Models;
use App\Helpers\Helper;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\Actionlog;
use App\Models\Company;
use App\Models\Location;
use App\Models\Loggable;
use App\Models\Requestable;
use App\Models\Setting;
use Auth;
use Config;
use DateTime;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Log;
use Parsedown;
use Watson\Validating\ValidatingTrait;
use App\Http\Traits\UniqueUndeletedTrait;
use DateTime;
use App\Models\Setting;
use App\Helpers\Helper;
use Auth;
/**
* Model for Assets.
@@ -23,7 +25,9 @@ use Auth;
*/
class Asset extends Depreciable
{
use Loggable;
use SoftDeletes;
use Requestable;
/**
* The database table used by the model.
@@ -55,6 +59,7 @@ class Asset extends Depreciable
'supplier_id' => 'integer',
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
'status' => 'integer',
'purchase_cost' => 'numeric',
];
@@ -72,22 +77,36 @@ class Asset extends Depreciable
}
public function availableForCheckout()
{
return (
empty($this->assigned_to) &&
$this->assetstatus->deployable == 1 &&
empty($this->deleted_at)
);
}
/**
* Checkout asset
*/
public function checkOutToUser($user, $admin, $checkout_at = null, $expected_checkin = null, $note = null, $name = null)
{
if (!$user) {
return false;
}
if ($expected_checkin) {
$this->expected_checkin = $expected_checkin ;
$this->expected_checkin = $expected_checkin;
}
$this->last_checkout = $checkout_at;
$this->assigneduser()->associate($user);
$this->name = $name;
if($name != null)
{
$this->name = $name;
}
$settings = Setting::getSettings();
@@ -95,9 +114,7 @@ class Asset extends Depreciable
$this->accepted="pending";
}
if (!$user) {
return false;
}
if ($this->save()) {
@@ -135,7 +152,8 @@ class Asset extends Depreciable
\Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->subject('Confirm asset delivery');
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_asset_delivery'));
});
}
@@ -196,10 +214,12 @@ class Asset extends Depreciable
{
$logaction = new Actionlog();
$logaction->asset_id = $this->id;
$logaction->checkedout_to = $this->assigned_to;
$logaction->asset_type = 'hardware';
$logaction->item_type = Asset::class;
$logaction->item_id = $this->id;
$logaction->target_type = User::class;
$logaction->target_id = $this->assigned_to;
$logaction->note = $note;
$logaction->user_id = $admin->id;
if ($checkout_at!='') {
$logaction->created_at = \Carbon\Carbon::createFromFormat('Y-m-d H:i:s', date('Y-m-d H:i:s', strtotime($checkout_at)));
} else {
@@ -212,15 +232,10 @@ class Asset extends Depreciable
}
} else {
// Update the asset data to null, since it's being checked in
$logaction->checkedout_to = $asset->assigned_to;
$logaction->checkedout_to = '';
$logaction->asset_id = $asset->id;
$logaction->target_id = '';
$logaction->location_id = null;
$logaction->asset_type = 'hardware';
$logaction->note = $note;
$logaction->user_id = $admin->id;
}
$logaction->adminlog()->associate($admin);
$logaction->user()->associate($admin);
$log = $logaction->logaction($action);
return $logaction;
@@ -257,8 +272,8 @@ class Asset extends Depreciable
public function uploads()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'hardware')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', Asset::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
@@ -295,8 +310,8 @@ class Asset extends Depreciable
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'hardware')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', Asset::class)
->orderBy('created_at', 'desc')
->withTrashed();
}
@@ -563,12 +578,12 @@ public function checkin_email()
public function scopeAssetsByLocation($query, $location)
{
return $query->where(function ($query) use ($location) {
$query->whereHas('assigneduser', function ($query) use ($location) {
$query->where('users.location_id', '=', $location->id);
})->orWhere(function ($query) use ($location) {
$query->where('assets.rtd_location_id', '=', $location->id);
$query->whereNull('assets.assigned_to');
});
@@ -615,6 +630,23 @@ public function checkin_email()
});
}
/**
* Query builder scope for non-Archived assets
*
* @param Illuminate\Database\Query\Builder $query Query builder instance
*
* @return Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeNotArchived($query)
{
return $query->whereHas('assetstatus', function ($query) {
$query->where('archived', '=', 0);
});
}
/**
* Query builder scope for Archived assets
*

View File

@@ -1,6 +1,7 @@
<?php
namespace App\Models;
use App\Models\Requestable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -14,6 +15,7 @@ use Watson\Validating\ValidatingTrait;
class AssetModel extends Model
{
use SoftDeletes;
use Requestable;
protected $dates = ['deleted_at'];
protected $table = 'models';
@@ -131,6 +133,22 @@ class AssetModel extends Model
return $query->whereIn('category_id', $categoryIdListing);
}
/**
* scopeRequestable
* Get all models that are requestable by a user.
*
* @param $query
*
* @return $query
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @version v3.5
*/
public function scopeRequestableModels($query)
{
return $query->where('requestable', '1');
}
/**
* Query builder scope to search on text
*

View File

@@ -0,0 +1,59 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CheckoutRequest extends Model
{
//
protected $fillable = ['user_id'];
protected $table = 'checkout_requests';
public function user()
{
return $this->belongsTo(User::class);
}
public function requestingUser()
{
return $this->user()->first();
}
public function requestedItem()
{
return $this->morphTo('requestable');
}
public function itemRequested() // Workaround for laravel polymorphic issue that's not being solved :(
{
return $this->requestedItem()->first();
}
public function itemType()
{
return snake_case(class_basename($this->requestable_type));
}
public function location()
{
if ($this->itemType() == "asset") {
$asset = $this->itemRequested();
if ($asset->assigneduser && $asset->assetloc) {
return $asset->assetloc;
} elseif ($asset->defaultLoc) {
return $asset->defaultLoc;
}
}
return $this->itemRequested()->location;
}
public function name()
{
if ($this->itemType() == "asset") {
return $this->itemRequested()->showAssetName();
}
return $this->itemRequested()->name;
}
}

View File

@@ -136,7 +136,8 @@ final class Company extends Model
public static function scopeCompanyables($query, $column = 'company_id')
{
if (!static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser())) {
// If not logged in and hitting this, assume we are on the command line and don't scope?'
if (!static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser()) || (!Auth::check())) {
return $query;
} else {
return static::scopeCompanyablesDirectly($query, $column);
@@ -176,4 +177,27 @@ final class Company extends Model
return e($company->name);
}
}
public function users() {
return $this->hasMany(User::class);
}
public function assets() {
return $this->hasMany(Asset::class);
}
public function licenses() {
return $this->hasMany(License::class);
}
public function accessories() {
return $this->hasMany(Accessory::class);
}
public function consumables() {
return $this->hasMany(Consumable::class);
}
public function components() {
return $this->hasMany(Component::class);
}
}

View File

@@ -1,12 +1,13 @@
<?php
namespace App\Models;
use App\Models\User;
use App\Models\ConsumableAssignment;
use App\Models\Company;
use App\Models\Location;
use App\Models\Category;
use App\Models\ActionLog;
use App\Models\Category;
use App\Models\Company;
use App\Models\ConsumableAssignment;
use App\Models\Location;
use App\Models\Loggable;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
@@ -18,8 +19,9 @@ use Watson\Validating\ValidatingTrait;
*/
class Component extends Model
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'components';
@@ -34,6 +36,7 @@ class Component extends Model
'category_id' => 'required|integer',
'company_id' => 'integer',
'purchase_date' => 'date',
'purchase_cost' => 'numeric',
);
/**
@@ -84,7 +87,7 @@ class Component extends Model
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'component_id')->where('asset_type', '=', 'component')->orderBy('created_at', 'desc')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Component::class)->orderBy('created_at', 'desc')->withTrashed();
}

View File

@@ -1,20 +1,22 @@
<?php
namespace App\Models;
use App\Models\User;
use App\Models\ConsumableAssignment;
use App\Models\Company;
use App\Models\Location;
use App\Models\Category;
use App\Models\ActionLog;
use App\Models\Category;
use App\Models\Company;
use App\Models\ConsumableAssignment;
use App\Models\Location;
use App\Models\Loggable;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class Consumable extends Model
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
use SoftDeletes;
protected $dates = ['deleted_at'];
protected $table = 'consumables';
@@ -29,6 +31,7 @@ class Consumable extends Model
'category_id' => 'required|integer',
'company_id' => 'integer',
'min_amt' => 'integer|min:1',
'purchase_cost' => 'numeric',
);
/**
@@ -84,7 +87,7 @@ class Consumable extends Model
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'consumable_id')->where('asset_type', '=', 'consumable')->orderBy('created_at', 'desc')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Consumable::class)->orderBy('created_at', 'desc')->withTrashed();
}

View File

@@ -11,14 +11,14 @@ class CustomField extends Model
*/
public static $PredefinedFormats=[
"ANY" => "",
"ALPHA" => "alpha",
"EMAIL" => "email",
"DATE" => "date",
"URL" => "url",
"NUMERIC" => "numeric",
"MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/",
"IP" => "ip"
"ANY" => "",
"ALPHA" => "alpha",
"EMAIL" => "email",
"DATE" => "date",
"URL" => "url",
"NUMERIC" => "numeric",
"MAC" => "regex:/^[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}:[a-fA-F0-9]{2}$/",
"IP" => "ip",
];
public $rules=[
@@ -109,4 +109,43 @@ class CustomField extends Model
$this->attributes['format']=$value;
}
}
/**
* Format a value string as an array for select boxes and checkboxes.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v3.4]
* @return Array
*/
public function formatFieldValuesAsArray() {
$arr = preg_split("/\\r\\n|\\r|\\n/", $this->field_values);
$result[''] = 'Select '.strtolower($this->format);
for ($x = 0; $x < count($arr); $x++) {
$arr_parts = explode('|', $arr[$x]);
if ($arr_parts[0]!='') {
if (key_exists('1',$arr_parts)) {
$result[$arr_parts[0]] = $arr_parts[1];
} else {
$result[$arr_parts[0]] = $arr_parts[0];
}
}
}
return $result;
}
public function isFieldDecryptable($string) {
if (($this->field_encrypted=='1') && ($string!='')) {
return true;
}
return false;
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Gate;
class CustomFieldset extends Model
{
@@ -30,16 +31,21 @@ class CustomFieldset extends Model
{
$rules=[];
foreach ($this->fields as $field) {
$rule=[];
if ($field->pivot->required) {
$rule[]="required";
$rule = [];
if (($field->field_encrypted!='1') ||
(($field->field_encrypted =='1') && (Gate::allows('admin')) ))
{
if ($field->pivot->required) {
$rule[]="required";
}
}
array_push($rule, $field->attributes['format']);
$rules[$field->db_column_name()]=$rule;
}
return $rules;
}
//requiredness goes *here*
//sequence goes here?
}

View File

@@ -81,11 +81,18 @@ class Ldap extends Model
if ($settings->is_ad =='1')
{
// In case they haven't added an AD domain
if ($settings->ad_domain == '') {
$userDn = $username.'@'.$settings->email_domain;
// Check if they are using the userprincipalname for the username field.
// If they are, we can skip building the UPN to authenticate against AD
if ($ldap_username_field=='userprincipalname')
{
$userDn = $username;
} else {
$userDn = $username.'@'.$settings->ad_domain;
// In case they haven't added an AD domain
if ($settings->ad_domain == '') {
$userDn = $username.'@'.$settings->email_domain;
} else {
$userDn = $username.'@'.$settings->ad_domain;
}
}
} else {
@@ -247,8 +254,12 @@ class Ldap extends Model
// Perform the search
do {
// Paginate (non-critical, if not supported by server)
ldap_control_paged_result($ldapconn, $page_size, false, $cookie);
if (!$ldap_paging = @ldap_control_paged_result($ldapconn, $page_size, false, $cookie)) {
throw new Exception('Problem with your LDAP connection. Try checking the Use TLS setting in Admin > Settings. ');
}
$search_results = ldap_search($ldapconn, $base_dn, '('.$filter.')');

View File

@@ -2,15 +2,16 @@
namespace App\Models;
use App\Models\Company;
use App\Models\Loggable;
use DB;
use Watson\Validating\ValidatingTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class License extends Depreciable
{
use SoftDeletes;
use CompanyableTrait;
use Loggable;
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
@@ -36,6 +37,11 @@ class License extends Depreciable
return $this->belongsTo('\App\Models\Company', 'company_id');
}
public function manufacturer()
{
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
}
/**
* Get the assigned user
*/
@@ -49,8 +55,8 @@ class License extends Depreciable
*/
public function assetlog()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'software')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', License::class)
->orderBy('created_at', 'desc');
}
@@ -59,8 +65,8 @@ class License extends Depreciable
*/
public function uploads()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'software')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', '=', License::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
@@ -208,6 +214,7 @@ class License extends Depreciable
->orWhere('serial', 'LIKE', '%'.$search.'%')
->orWhere('notes', 'LIKE', '%'.$search.'%')
->orWhere('order_number', 'LIKE', '%'.$search.'%')
->orWhere('purchase_order', 'LIKE', '%'.$search.'%')
->orWhere('purchase_date', 'LIKE', '%'.$search.'%')
->orWhere('purchase_cost', 'LIKE', '%'.$search.'%');
});

View File

@@ -1,6 +1,7 @@
<?php
namespace App\Models;
use App\Models\Loggable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -8,6 +9,7 @@ class LicenseSeat extends Model implements ICompanyableChild
{
use CompanyableChildTrait;
use SoftDeletes;
use Loggable;
protected $dates = ['deleted_at'];
protected $guarded = 'id';

108
app/Models/Loggable.php Normal file
View File

@@ -0,0 +1,108 @@
<?php
namespace App\Models;
use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\CheckoutRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
trait Loggable
{
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function log()
{
return $this->morphMany(Actionlog::class, 'item');
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function logCheckout($note, $target = null /*target is overridable for components*/)
{
$log = new Actionlog;
// We need to special case licenses because of license_seat vs license. So much for clean polymorphism :)
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->user_id = Auth::user()->id;
if (!is_null($this->asset_id) || isset($target)) {
$log->target_type = Asset::class;
$log->target_id = $this->asset_id;
} else if (!is_null($this->assigned_to)) {
$log->target_type = User::class;
$log->target_id = $this->assigned_to;
}
$item = call_user_func(array($log->target_type, 'find'), $log->target_id);
$log->location_id = $item->location_id;
$log->note = $note;
$log->logaction('checkout');
return $log;
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function logCheckin($note)
{
$log = new Actionlog;
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->location_id = null;
$log->note = $note;
$log->user_id = Auth::user()->id;
$log->logaction('checkin from');
return $log;
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @since [v3.4]
* @return \App\Models\Actionlog
*/
public function logUpload($filename, $note)
{
$log = new Actionlog;
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->user_id = Auth::user()->id;
$log->note = $note;
$log->target_id = null;
$log->created_at = date("Y-m-d h:i:s");
$log->filename = $filename;
$log->logaction('uploaded');
return $log;
}
}

View File

@@ -46,6 +46,21 @@ class Manufacturer extends Model
return $this->hasManyThrough('\App\Models\Asset', '\App\Models\AssetModel', 'manufacturer_id', 'model_id');
}
public function licenses()
{
return $this->hasMany('\App\Models\License', 'manufacturer_id');
}
public function accessories()
{
return $this->hasMany('\App\Models\Accessory', 'manufacturer_id');
}
public function consumables()
{
return $this->hasMany('\App\Models\Consumable', 'manufacturer_id');
}
/**
* Query builder scope to search on text
*

View File

@@ -0,0 +1,45 @@
<?php
namespace App\Models;
use App\Models\CheckoutRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
// $asset->requests
// $asset->isRequestedBy($user)
// $asset->whereRequestedBy($user)
trait Requestable
{
public function requests()
{
return $this->morphMany(CheckoutRequest::class, 'requestable');
}
public function isRequestedBy(User $user)
{
return $this->requests()
->where('user_id', $user->id)
->exists();
}
public function scopeRequestedBy($query, User $user)
{
return $query->whereHas('requests', function ($query) use ($user) {
$query->where('user_id', $user->id);
});
}
public function request()
{
$this->requests()->save(
new CheckoutRequest(['user_id' => Auth::id()])
);
}
public function cancelRequest()
{
$this->requests()->where('user_id', Auth::id())->delete();
}
}

View File

@@ -9,6 +9,7 @@ use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Watson\Validating\ValidatingTrait;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Models\Setting;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract
{
@@ -67,7 +68,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
// Loop through the groups to see if any of them grant this permission
foreach ($user_groups as $user_group) {
$group_permissions = json_decode($user_group->permissions, true);
$group_permissions = (array) json_decode($user_group->permissions, true);
if (((array_key_exists($section, $group_permissions)) && ($group_permissions[$section]=='1'))) {
return true;
}
@@ -84,7 +85,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
foreach ($this->groups as $user_group) {
$group_permissions = json_decode($user_group->permissions, true);
$group_array = $group_permissions;
$group_array = (array)$group_permissions;
if ((array_key_exists('superuser', $group_array)) && ($group_permissions['superuser']=='1')) {
return true;
}
@@ -146,10 +147,8 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return config('app.url').'/uploads/avatars/'.$this->avatar;
}
if ($this->email) {
// Generate the Gravatar hash
if ((Setting::getSettings()->load_remote=='1') && ($this->email!='')) {
$gravatar = md5(strtolower(trim($this->email)));
// Return the Gravatar url
return "//gravatar.com/avatar/".$gravatar;
}
@@ -202,7 +201,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public function userlog()
{
return $this->hasMany('\App\Models\Actionlog', 'checkedout_to')->orderBy('created_at', 'DESC')->withTrashed();
return $this->hasMany('\App\Models\Actionlog', 'target_id')->orderBy('created_at', 'DESC')->withTrashed();
}
/**
@@ -255,13 +254,21 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
*/
public function uploads()
{
return $this->hasMany('\App\Models\Actionlog', 'asset_id')
->where('asset_type', '=', 'user')
return $this->hasMany('\App\Models\Actionlog', 'item_id')
->where('item_type', User::class)
->where('action_type', '=', 'uploaded')
->whereNotNull('filename')
->orderBy('created_at', 'desc');
}
/**
* Fetch Items User has requested
*/
public function checkoutRequests()
{
return $this->belongsToMany(Asset::class, 'checkout_requests');
}
public function throttle()
{
return $this->hasOne('\App\Models\Throttle');

View File

@@ -255,6 +255,18 @@ class AuthServiceProvider extends ServiceProvider
}
});
$gate->define('components.checkout', function ($user) {
if (($user->hasAccess('components.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
$gate->define('components.checkout', function ($user) {
if (($user->hasAccess('components.checkout')) || ($user->hasAccess('admin'))) {
return true;
}
});
// Checks for some level of management
$gate->define('components.manage', function ($user) {
if (($user->hasAccess('components.edit')) || ($user->hasAccess('components.delete')) || ($user->hasAccess('components.checkout')) || ($user->hasAccess('admin'))) {

View File

@@ -22,7 +22,8 @@
"doctrine/dbal": "v2.4.2",
"barryvdh/laravel-debugbar": "^2.1",
"spatie/laravel-backup": "3.8.1",
"misterphilip/maintenance-mode": "1.0.*"
"misterphilip/maintenance-mode": "1.0.*",
"neitanod/forceutf8": "dev-master"
},
"require-dev": {
"fzaninotto/faker": "~1.4",

165
composer.lock generated
View File

@@ -4,21 +4,21 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "a770010d0ebb93a2e1b5f4acadd5a7f3",
"content-hash": "59772418a4612685eea10dde38ca77b7",
"hash": "ed9f8700f2dcd943ff662a82e4d8314f",
"content-hash": "9c0251ddc1a110d83a762483abeea079",
"packages": [
{
"name": "aws/aws-sdk-php",
"version": "3.18.39",
"version": "3.19.2",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "85f1fddaeb40b95106b2a2764268e9c89fc258ce"
"reference": "3cb90413129da42c9d3289d542bee0ae1049892c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/85f1fddaeb40b95106b2a2764268e9c89fc258ce",
"reference": "85f1fddaeb40b95106b2a2764268e9c89fc258ce",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/3cb90413129da42c9d3289d542bee0ae1049892c",
"reference": "3cb90413129da42c9d3289d542bee0ae1049892c",
"shasum": ""
},
"require": {
@@ -85,7 +85,7 @@
"s3",
"sdk"
],
"time": "2016-08-11 16:40:35"
"time": "2016-08-23 20:58:48"
},
{
"name": "aws/aws-sdk-php-laravel",
@@ -145,21 +145,21 @@
},
{
"name": "barryvdh/laravel-debugbar",
"version": "v2.2.2",
"version": "V2.2.3",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "c291e58d0a13953e0f68d99182ee77ebc693edc0"
"reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/c291e58d0a13953e0f68d99182ee77ebc693edc0",
"reference": "c291e58d0a13953e0f68d99182ee77ebc693edc0",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd",
"reference": "ecd1ce5c4a827e2f6a8fb41bcf67713beb1c1cbd",
"shasum": ""
},
"require": {
"illuminate/support": "5.1.*|5.2.*",
"maximebf/debugbar": "~1.11.0",
"illuminate/support": "5.1.*|5.2.*|5.3.*",
"maximebf/debugbar": "~1.11.0|~1.12.0",
"php": ">=5.5.9",
"symfony/finder": "~2.7|~3.0"
},
@@ -195,7 +195,7 @@
"profiler",
"webprofiler"
],
"time": "2016-05-11 13:54:43"
"time": "2016-07-29 15:00:36"
},
{
"name": "classpreloader/classpreloader",
@@ -1018,12 +1018,12 @@
"source": {
"type": "git",
"url": "https://github.com/Intervention/image.git",
"reference": "6886d43f5babe6900c29c59640ca81401fe71c80"
"reference": "45a41a38bd1e5290cd51ab773013e6f041b2b711"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Intervention/image/zipball/6886d43f5babe6900c29c59640ca81401fe71c80",
"reference": "6886d43f5babe6900c29c59640ca81401fe71c80",
"url": "https://api.github.com/repos/Intervention/image/zipball/45a41a38bd1e5290cd51ab773013e6f041b2b711",
"reference": "45a41a38bd1e5290cd51ab773013e6f041b2b711",
"shasum": ""
},
"require": {
@@ -1072,7 +1072,7 @@
"thumbnail",
"watermark"
],
"time": "2016-06-22 08:03:11"
"time": "2016-08-19 14:41:12"
},
{
"name": "jakub-onderka/php-console-color",
@@ -1221,16 +1221,16 @@
},
{
"name": "laravel/framework",
"version": "v5.2.43",
"version": "v5.2.45",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "5490b8f00564bb60839002f86828e27edd1e5610"
"reference": "2a79f920d5584ec6df7cf996d922a742d11095d1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/5490b8f00564bb60839002f86828e27edd1e5610",
"reference": "5490b8f00564bb60839002f86828e27edd1e5610",
"url": "https://api.github.com/repos/laravel/framework/zipball/2a79f920d5584ec6df7cf996d922a742d11095d1",
"reference": "2a79f920d5584ec6df7cf996d922a742d11095d1",
"shasum": ""
},
"require": {
@@ -1311,7 +1311,7 @@
"pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0).",
"symfony/css-selector": "Required to use some of the crawler integration testing tools (2.8.*|3.0.*).",
"symfony/dom-crawler": "Required to use most of the crawler integration testing tools (2.8.*|3.0.*).",
"symfony/psr-http-message-bridge": "Required to psr7 bridging features (0.2.*)."
"symfony/psr-http-message-bridge": "Required to use psr7 bridging features (0.2.*)."
},
"type": "library",
"extra": {
@@ -1347,7 +1347,7 @@
"framework",
"laravel"
],
"time": "2016-08-10 12:23:59"
"time": "2016-08-26 11:44:52"
},
{
"name": "laravelcollective/html",
@@ -1595,16 +1595,16 @@
},
{
"name": "maximebf/debugbar",
"version": "v1.11.1",
"version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/maximebf/php-debugbar.git",
"reference": "d9302891c1f0a0ac5a4f66725163a00537c6359f"
"reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/d9302891c1f0a0ac5a4f66725163a00537c6359f",
"reference": "d9302891c1f0a0ac5a4f66725163a00537c6359f",
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988",
"reference": "e634fbd32cd6bc3fa0e8c972b52d4bf49bab3988",
"shasum": ""
},
"require": {
@@ -1623,7 +1623,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.11-dev"
"dev-master": "1.12-dev"
}
},
"autoload": {
@@ -1652,7 +1652,7 @@
"debug",
"debugbar"
],
"time": "2016-01-22 12:22:23"
"time": "2016-05-15 13:11:34"
},
{
"name": "misterphilip/maintenance-mode",
@@ -1876,6 +1876,40 @@
],
"time": "2016-01-05 18:25:05"
},
{
"name": "neitanod/forceutf8",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/neitanod/forceutf8.git",
"reference": "2c1b21e00ed16b2b083ae4e27901cb5f2856db90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/neitanod/forceutf8/zipball/2c1b21e00ed16b2b083ae4e27901cb5f2856db90",
"reference": "2c1b21e00ed16b2b083ae4e27901cb5f2856db90",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"autoload": {
"psr-0": {
"ForceUTF8\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"authors": [
{
"name": "Sebastián Grignoli",
"email": "grignoli@gmail.com"
}
],
"description": "PHP Class Encoding featuring popular Encoding::toUTF8() function --formerly known as forceUTF8()-- that fixes mixed encoded strings.",
"homepage": "https://github.com/neitanod/forceutf8",
"time": "2015-05-07 16:37:23"
},
{
"name": "nesbot/carbon",
"version": "1.21.0",
@@ -3132,17 +3166,17 @@
"source": {
"type": "git",
"url": "https://github.com/tecnickcom/tc-lib-barcode.git",
"reference": "220728e5f659b935348442e8d1d3e46fd5f9e178"
"reference": "df69541618a0ebc24bc8f938e52f76a471f2e018"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tecnickcom/tc-lib-barcode/zipball/220728e5f659b935348442e8d1d3e46fd5f9e178",
"reference": "220728e5f659b935348442e8d1d3e46fd5f9e178",
"url": "https://api.github.com/repos/tecnickcom/tc-lib-barcode/zipball/df69541618a0ebc24bc8f938e52f76a471f2e018",
"reference": "df69541618a0ebc24bc8f938e52f76a471f2e018",
"shasum": ""
},
"require": {
"php": ">=5.4",
"tecnickcom/tc-lib-color": "^1.11.0"
"tecnickcom/tc-lib-color": "^1.12.0"
},
"require-dev": {
"apigen/apigen": "^4.1.2",
@@ -3210,20 +3244,20 @@
"tc-lib-barcode",
"upc"
],
"time": "2016-07-10 18:29:15"
"time": "2016-08-25 12:36:23"
},
{
"name": "tecnickcom/tc-lib-color",
"version": "1.11.0",
"version": "1.12.0",
"source": {
"type": "git",
"url": "https://github.com/tecnickcom/tc-lib-color.git",
"reference": "6a000b658758e271bf4c41bbc1ce4c685d8a7160"
"reference": "176464ae7ad0256c1dfd9d742ee2461d0b660f7c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tecnickcom/tc-lib-color/zipball/6a000b658758e271bf4c41bbc1ce4c685d8a7160",
"reference": "6a000b658758e271bf4c41bbc1ce4c685d8a7160",
"url": "https://api.github.com/repos/tecnickcom/tc-lib-color/zipball/176464ae7ad0256c1dfd9d742ee2461d0b660f7c",
"reference": "176464ae7ad0256c1dfd9d742ee2461d0b660f7c",
"shasum": ""
},
"require": {
@@ -3272,7 +3306,7 @@
"tc-lib-color",
"web"
],
"time": "2016-06-13 14:31:19"
"time": "2016-08-25 11:56:01"
},
{
"name": "vlucas/phpdotenv",
@@ -3326,24 +3360,24 @@
},
{
"name": "watson/validating",
"version": "2.2.1",
"version": "2.2.2",
"source": {
"type": "git",
"url": "https://github.com/dwightwatson/validating.git",
"reference": "64dc3d211372576d468e2bfaf3c7b7ace66ee970"
"reference": "8f37e416aaf02129c8ad57a446a6ef7080019687"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/dwightwatson/validating/zipball/64dc3d211372576d468e2bfaf3c7b7ace66ee970",
"reference": "64dc3d211372576d468e2bfaf3c7b7ace66ee970",
"url": "https://api.github.com/repos/dwightwatson/validating/zipball/8f37e416aaf02129c8ad57a446a6ef7080019687",
"reference": "8f37e416aaf02129c8ad57a446a6ef7080019687",
"shasum": ""
},
"require": {
"illuminate/contracts": "~5.0",
"illuminate/database": "~5.0 || >=5.1.27",
"illuminate/events": "~5.0",
"illuminate/support": "~5.0",
"illuminate/validation": "~5.0",
"illuminate/contracts": "~5.0 <5.3",
"illuminate/database": "~5.0 <5.3 || >=5.1.27",
"illuminate/events": "~5.0 <5.3",
"illuminate/support": "~5.0 <5.3",
"illuminate/validation": "~5.0 <5.3",
"php": ">=5.4.0"
},
"require-dev": {
@@ -3377,7 +3411,7 @@
"laravel",
"validation"
],
"time": "2016-04-07 14:59:06"
"time": "2016-08-28 07:54:32"
}
],
"packages-dev": [
@@ -3571,16 +3605,16 @@
},
{
"name": "facebook/webdriver",
"version": "1.1.2",
"version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/facebook/php-webdriver.git",
"reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986"
"reference": "b7186fb1bcfda956d237f59face250d06ef47253"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/0b889d7de7461439f8a3bbcca46e0f696cb27986",
"reference": "0b889d7de7461439f8a3bbcca46e0f696cb27986",
"url": "https://api.github.com/repos/facebook/php-webdriver/zipball/b7186fb1bcfda956d237f59face250d06ef47253",
"reference": "b7186fb1bcfda956d237f59face250d06ef47253",
"shasum": ""
},
"require": {
@@ -3588,7 +3622,9 @@
"php": ">=5.3.19"
},
"require-dev": {
"phpunit/phpunit": "4.6.*"
"friendsofphp/php-cs-fixer": "^1.11",
"phpunit/phpunit": "4.6.* || ~5.0",
"squizlabs/php_codesniffer": "^2.6"
},
"suggest": {
"phpdocumentor/phpdocumentor": "2.*"
@@ -3611,7 +3647,7 @@
"selenium",
"webdriver"
],
"time": "2016-06-04 00:02:34"
"time": "2016-08-10 00:44:08"
},
{
"name": "fzaninotto/faker",
@@ -4580,23 +4616,23 @@
},
{
"name": "sebastian/environment",
"version": "1.3.7",
"version": "1.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
"reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
"php": "^5.3.3 || ^7.0"
},
"require-dev": {
"phpunit/phpunit": "~4.4"
"phpunit/phpunit": "^4.8 || ^5.0"
},
"type": "library",
"extra": {
@@ -4626,7 +4662,7 @@
"environment",
"hhvm"
],
"time": "2016-05-17 03:18:57"
"time": "2016-08-18 05:49:44"
},
{
"name": "sebastian/exporter",
@@ -5184,7 +5220,8 @@
"intervention/image": 20,
"maknz/slack": 20,
"erusev/parsedown": 20,
"tecnickcom/tc-lib-barcode": 20
"tecnickcom/tc-lib-barcode": 20,
"neitanod/forceutf8": 20
},
"prefer-stable": false,
"prefer-lowest": false,

15
config/app.php Normal file → Executable file
View File

@@ -127,6 +127,20 @@ return [
'private_uploads' => storage_path().'/private_uploads',
/*
|--------------------------------------------------------------------------
| ALLOW I-FRAMING
|--------------------------------------------------------------------------
|
| Normal users will never need to edit this. This option lets you run
| Snipe-IT within an I-Frame, which is normally disabled by default for
| security reasons, to prevent clickjacking. It should normally be set to false.
|
*/
'allow_iframing' => env('ALLOW_IFRAMING', false),
/*
|--------------------------------------------------------------------------
| Demo Mode Lockdown
@@ -140,7 +154,6 @@ return [
'lock_passwords' => env('APP_LOCKED', false),
/*
|--------------------------------------------------------------------------
| Autoloaded Service Providers

0
config/database.php Normal file → Executable file
View File

24
config/mail.php Normal file → Executable file
View File

@@ -3,6 +3,12 @@
return [
/*
| ***************************************************************************
| DO NOT MAKE CHANGES DIRECTLY TO THIS FILE.
|
| Instead use your .env file to set your application configuration settings.
| See https://snipe-it.readme.io/docs/configuration for more info.
|
|--------------------------------------------------------------------------
| Mail Driver
|--------------------------------------------------------------------------
@@ -11,6 +17,7 @@ return [
| sending of e-mail. You may specify which one you're using throughout
| your application here. By default, Laravel is setup for SMTP mail.
|
|
| Supported: "smtp", "mail", "sendmail", "mailgun", "mandrill", "ses", "log"
|
*/
@@ -56,6 +63,23 @@ return [
'from' => ['address' => env('MAIL_FROM_ADDR', null), 'name' => env('MAIL_FROM_NAME', null)],
/*
|--------------------------------------------------------------------------
| Global "Reply-To" Address
|--------------------------------------------------------------------------
|
| You may wish for all e-mails sent by your application to have a different "Reply-to"
| address than the "From" address. If this is left blank, the application will use
| your MAIL_FROM information.
|
*/
'reply_to' => [
'address' => env('MAIL_REPLYTO_ADDR', env('MAIL_FROM_ADDR', null)),
'name' => env('MAIL_REPLYTO_NAME', env('MAIL_FROM_NAME', null))
],
/*
|--------------------------------------------------------------------------
| E-Mail Encryption Protocol

View File

@@ -1,5 +1,5 @@
<?php
return array (
'app_version' => '3.3.0-beta',
'hash_version' => '3.3.0-beta-19-g7a0843e',
'app_version' => 'v3.5.0-beta2',
'hash_version' => 'v3.5.0-beta2-53-g87f50df',
);

View File

@@ -25,6 +25,7 @@ $factory->defineAs(App\Models\Asset::class, 'asset', function (Faker\Generator $
'order_number' => $faker->numberBetween(1000000,50000000),
'supplier_id' => $faker->numberBetween(1,5),
'requestable' => $faker->numberBetween(0,1),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -96,6 +97,7 @@ $factory->defineAs(App\Models\Component::class, 'component', function (Faker\Gen
'category_id' => $faker->numberBetween(21,25),
'total_qty' => $faker->numberBetween(3, 10),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -113,6 +115,7 @@ $factory->defineAs(App\Models\Accessory::class, 'accessory', function (Faker\Gen
'qty' => $faker->numberBetween(5, 10),
'location_id' => $faker->numberBetween(1,5),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -138,6 +141,7 @@ $factory->defineAs(App\Models\Consumable::class, 'consumable', function (Faker\G
'company_id' => $faker->numberBetween(1, 10),
'qty' => $faker->numberBetween(5, 10),
'min_amt' => $faker->numberBetween($min = 1, $max = 2),
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -251,6 +255,7 @@ $factory->defineAs(App\Models\License::class, 'license', function (Faker\Generat
'purchase_date' => $faker->dateTime(),
'purchase_cost' => $faker->randomFloat(2),
'notes' => $faker->sentence,
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});
@@ -265,18 +270,82 @@ $factory->defineAs(App\Models\LicenseSeat::class, 'license-seat', function (Fake
});
$factory->defineAs(App\Models\Actionlog::class, 'asset-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('assets')->inRandomOrder()->first();
return [
'user_id' => 1,
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'asset_id' => $faker->numberBetween(1, 10),
'checkedout_to' => 1,
'item_id' => $company->assets()->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'asset_type' => 'hardware',
'item_type' => 'App\\Models\\Asset',
'note' => $faker->sentence,
'user_id' => '1',
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'license-checkout-asset', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('licenses')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->licenses()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->assets()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\Asset',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\License',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'accessory-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('accessories')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->accessories()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\Accessory',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'consumable-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('consumables')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->consumables()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\Consumable',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\Actionlog::class, 'component-checkout', function (Faker\Generator $faker) {
$company = \App\Models\Company::has('users')->has('components')->inRandomOrder()->first();
return [
'user_id' => $company->users()->inRandomOrder()->first()->id,
'action_type' => 'checkout',
'item_id' => $company->components()->whereNotNull('company_id')->inRandomOrder()->first()->id,
'target_id' => $company->users()->inRandomOrder()->first()->id,
'target_type' => 'App\\Models\\User',
'created_at' => $faker->dateTime(),
'item_type' => 'App\\Models\\Component',
'note' => $faker->sentence,
'company_id' => $company->id
];
});
$factory->defineAs(App\Models\CustomField::class, 'customfield-ip', function (Faker\Generator $faker) {
return [
@@ -294,5 +363,6 @@ $factory->defineAs(App\Models\User::class, 'valid-user', function (Faker\Generat
'email' => $faker->safeEmail,
'password' => $faker->password,
'username' => $faker->username,
'company_id' => \App\Models\Company::inRandomOrder()->first()->id
];
});

View File

@@ -64,39 +64,39 @@
public function up()
{
if (!Schema::hasColumn('asset_logs', 'thread_id')) {
// if (!Schema::hasColumn('asset_logs', 'thread_id')) {
Schema::table( 'asset_logs', function ( Blueprint $table ) {
// Schema::table( 'asset_logs', function ( Blueprint $table ) {
$table->integer( 'thread_id' )
->nullable()
->default( null );
$table->index( 'thread_id' );
} );
}
// $table->integer( 'thread_id' )
// ->nullable()
// ->default( null );
// $table->index( 'thread_id' );
// } );
// }
$this->actionlog = new App\Models\Actionlog();
$this->assetLogs = $this->actionlog->getListingOfActionLogsChronologicalOrder();
// $this->actionlog = new App\Models\Actionlog();
// $this->assetLogs = $this->actionlog->getListingOfActionLogsChronologicalOrder();
foreach ($this->assetLogs as $assetLog) {
// foreach ($this->assetLogs as $assetLog) {
if ($this->hasAssetChanged( $assetLog )) {
$this->resetCurrentAssetInformation( $assetLog );
}
// if ($this->hasAssetChanged( $assetLog )) {
// $this->resetCurrentAssetInformation( $assetLog );
// }
if ($this->hasBegunNewChain( $assetLog )) {
$this->startOfCurrentThread = false;
continue;
}
// if ($this->hasBegunNewChain( $assetLog )) {
// $this->startOfCurrentThread = false;
// continue;
// }
$this->updateAssetLogWithThreadInformation( $assetLog );
// $this->updateAssetLogWithThreadInformation( $assetLog );
if ($this->hasReachedEndOfChain( $assetLog )
) {
$this->clearCurrentAssetInformation();
}
// if ($this->hasReachedEndOfChain( $assetLog )
// ) {
// $this->clearCurrentAssetInformation();
// }
}
// }
}

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddManufacturerToLicenses extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('licenses', function (Blueprint $table) {
//
$table->integer('manufacturer_id')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('licenses', function (Blueprint $table) {
//
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddManufacturerToAccessoriesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accessories', function (Blueprint $table) {
//
$table->integer('manufacturer_id')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('accessories', function (Blueprint $table) {
//
$table->dropColumn('manufacturer_id');
});
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddNewFieldsToCustomFields extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('custom_fields', function (Blueprint $table) {
//
$table->string('field_values')->nullable()->default(null);
$table->boolean('field_encrypted')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('custom_fields', function (Blueprint $table) {
//
$table->dropColumn('field_values', 'field_encrypted');
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddShowInNavToStatusLabels extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('status_labels', function (Blueprint $table) {
$table->boolean('show_in_nav')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('status_labels', function (Blueprint $table) {
$table->dropColumn('show_in_nav', 'field_encrypted');
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class MakePurchaseCostNullable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
Schema::table('assets', function ($table) {
$table->decimal('purchase_cost',8,2)->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddRequestableToAssetModel extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
Schema::table('models', function ($table) {
$table->tinyInteger('requestable')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
Schema::table('models', function ($table) {
$table->dropColumn('requestable');
});
}
}

View File

@@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCheckoutRequestsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('checkout_requests', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id');
$table->integer('requestable_id');
$table->string('requestable_type');
$table->integer('quantity')->default(1);
$table->timestamps();
$table->unique(['user_id', 'requestable_id', 'requestable_type']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('checkout_requests');
}
}

View File

@@ -0,0 +1,49 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateActionlogTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!Schema::hasTable('action_logs')) {
Schema::create('action_logs', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->nullable();
$table->string('action_type');
$table->integer('target_id')->nullable(); // Was checkedout_to
$table->string('target_type')->nullable(); // For polymorphic thingies
$table->integer('location_id')->nullable();
$table->text('note')->nullable();
$table->text('filename')->nullable();
$table->string('item_type');
$table->integer('item_id'); // Replaces asset_id, accessory_id, etc.
$table->date('expected_checkin')->nullable()->default(null);
$table->integer('accepted_id')->nullable();
$table->timestamps();
$table->softDeletes();
$table->integer('thread_id')
->nullable()
->default(null);
$table->index('thread_id');
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('action_logs');
}
}

View File

@@ -0,0 +1,78 @@
<?php
use App\Models\Actionlog;
use App\Models\User;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class MigrateAssetLogToActionLog extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
//
$logs = DB::table('asset_logs')->get();
foreach ($logs as $log) {
// protected $fillable = [ 'created_at', 'asset_type','user_id','asset_id','action_type','note','checkedout_to' ];
$a = new Actionlog(compact($log));
// var_dump($log);
$a->user_id = $log->user_id;
if (!is_null($log->asset_id)) {
$a->item_id = $log->asset_id;
if ($log->asset_type == "hardware") {
$a->item_type = 'App\\Models\\Asset';
} else {
$a->item_type = 'App\\Models\\License';
}
}
if (!is_null($log->accessory_id)) {
$a->item_id = $log->accessory_id;
$a->item_type = 'App\\Models\\Accessory';
} else if (!is_null($log->consumable_id)) {
$a->item_id = $log->consumable_id;
$a->item_type = 'App\\Models\\Consumable';
} else if (!is_null($log->component_id)) {
$a->item_id = $log->component_id;
$a->item_type = 'App\\Models\\Component';
}
$a->action_type = $log->action_type;
// $a->checkout_to = $log->checkout_to;
if(!is_null($log->checkedout_to)) {
$a->target_id = $log->checkedout_to;
$a->target_type = User::class;
}
if(!is_null($log->accepted_id)) {
$a->target_id = $log->accepted_id;
$a->target_type = User::class;
}
$a->location_id = $log->location_id;
$a->created_at = $log->created_at;
$a->updated_at = $log->updated_at;
$a->deleted_at = $log->deleted_at;
$a->note = $log->note;
$a->expected_checkin = $log->expected_checkin;
$a->thread_id = $log->thread_id;
$a->accepted_id = $log->accepted_id;
$a->save();
}
// dd($logs);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class FixFieldtypeForTargetType extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('action_logs', function ($table) {
$table->string('target_type')->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('action_logs', function ($table) {
$table->integer('target_type')->nullable()->default(null)->change();
});
}
}

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class FixModelnoInConsumablesToString extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('consumables', function ($table) {
$table->string('model_no')->nullable()->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('consumables', function ($table) {
$table->integer('model_no')->nullable()->default(null)->change();
});
}
}

View File

@@ -0,0 +1,44 @@
<?php
use App\Models\Actionlog;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddCompanyToLogs extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('action_logs', function (Blueprint $table) {
//
$table->integer('company_id')->nullable()->default(null);
});
$logs = Actionlog::with('item')->get();
foreach ($logs as $log) {
if($log->item) {
$log->company_id = $log->item->company_id;
$log->save();
} else {
var_dump($log);
}
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('action_logs', function (Blueprint $table) {
//
$table->dropColumn('company_id');
});
}
}

View File

@@ -7,6 +7,10 @@ class ActionlogSeeder extends Seeder
public function run()
{
Actionlog::truncate();
factory(Actionlog::class, 'asset-checkout',5)->create();
factory(Actionlog::class, 'asset-checkout',25)->create();
factory(Actionlog::class, 'accessory-checkout',15)->create();
factory(Actionlog::class, 'consumable-checkout', 15)->create();
factory(Actionlog::class, 'component-checkout', 15)->create();
factory(Actionlog::class, 'license-checkout-asset', 15)->create();
}
}

View File

@@ -0,0 +1,19 @@
<?php
use App\Models\Company;
use Illuminate\Database\Seeder;
class CompanySeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
//
Company::truncate();
factory(Company::class, 'company', 4)->create();
}
}

View File

@@ -14,9 +14,12 @@ class DatabaseSeeder extends Seeder
{
Model::unguard();
$this->call(CompanySeeder::class);
$this->call(UserSeeder::class);
$this->call(AssetModelSeeder::class);
$this->call(AccessorySeeder::class);
$this->call(AssetSeeder::class);
$this->call(ComponentSeeder::class);
$this->call(ConsumableSeeder::class);
$this->call(StatuslabelSeeder::class);
$this->call(SupplierSeeder::class);
@@ -27,7 +30,6 @@ class DatabaseSeeder extends Seeder
$this->call(ManufacturerSeeder::class);
$this->call(LocationSeeder::class);
$this->call(CustomFieldSeeder::class);
$this->call(ComponentSeeder::class);
Model::reguard();
}

View File

@@ -0,0 +1,18 @@
<?php
use App\Models\User;
use Illuminate\Database\Seeder;
class UserSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
// Don't truncate the user column, that might suck.
factory(User::class, 'valid-user', 10)->create();
}
}

View File

@@ -14,6 +14,8 @@ MAIL_ENV_FROM_NAME=Brady Wetherington
MAIL_ENV_ENCRYPTION=tcp
MAIL_ENV_USERNAME=uberbrady@gmail.com
MAIL_ENV_PASSWORD=N7AqLufTZMULWHWYwJ0ZCw
MAIL_ENV_REPLYTO_ADDR=you@example.com
MAIL_ENV_REPLYTO_NAME='Snipe-IT'
#SNIPE-IT Variables
APP_ENV=develop
@@ -22,3 +24,5 @@ APP_KEY=Y5hJeC7x1i7OxhDrvrQPlB9KvCorvRdO
APP_URL=http://127.0.0.1:32782
APP_TIMEZONE=US/Pacific
APP_LOCALE=en
ALLOW_IFRAMING=false

View File

@@ -50,7 +50,7 @@
# when the CA certificates are directly appended to the server
# certificate for convinience.
#SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt
SSLCertificateChainFile /etc/ssl/private/snipeit-ssl.crt
SSLCertificateChainFile /var/lib/snipeit/ssl/snipeit-ssl.crt
# Certificate Authority (CA):
# Set the CA certificate verification path where to find CA

View File

@@ -18,6 +18,7 @@ DB_DATABASE=${MYSQL_DATABASE}
DB_USERNAME=${MYSQL_USER}
DB_PASSWORD=${MYSQL_PASSWORD}
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
# --------------------------------------------

4
public/assets/js/html5shiv.js vendored Normal file
View File

@@ -0,0 +1,4 @@
/**
* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
*/
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);

View File

View File

@@ -36,6 +36,11 @@ include '../c3.php';
$app = require_once __DIR__.'/../bootstrap/app.php';
// set the public path to this directory
$app->bind('path.public', function() {
return __DIR__;
});
/*
|--------------------------------------------------------------------------
| Run The Application

View File

@@ -3,13 +3,14 @@
return array(
'about_consumables_title' => 'حول المواد الاستهلاكية',
'about_consumables_text' => 'المواد الاستهلاكية هي الأشياء المشتراة والتي ستستخدم مع مرور الوقت. على سبيل المثال، حبر الطابعة أو ورق الناسخة.',
'consumable_name' => 'اسم المادة الإستهلاكية',
'cost' => 'تكلفة الشراء',
'create' => 'إنشاء مادة إستهلاكية',
'date' => 'تاريخ الشراء',
'item_no' => 'رقم القطعة.',
'order' => 'رقم طلب الشراء',
'remaining' => 'المتبقية',
'total' => 'المجموع',
'checkout' => 'Checkout Consumable to User',
'consumable_name' => 'اسم المادة الإستهلاكية',
'cost' => 'تكلفة الشراء',
'create' => 'إنشاء مادة إستهلاكية',
'date' => 'تاريخ الشراء',
'item_no' => 'رقم القطعة.',
'order' => 'رقم طلب الشراء',
'remaining' => 'المتبقية',
'total' => 'المجموع',
'update' => 'تحديث المادة الإستهلاكية',
);

View File

@@ -5,11 +5,17 @@ return array(
'field' => 'حقل',
'about_fieldsets_title' => 'حول مجموعة الحقول',
'about_fieldsets_text' => 'مجموعات-الحقول تسمح لك بإنشاء مجموعات من الحقول اللتي يمكن إعادة إستخدامها مع أنواع موديل محدد.',
'custom_format' => 'Custom format...',
'encrypt_field' => 'Encrypt the value of this field in the database for each asset. The decrypted value of this field will only be viewable by admins.',
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
'encrypted' => 'Encrypted',
'fieldset' => 'مجموعة-حقول',
'qty_fields' => 'الحقول الكمية',
'fieldsets' => 'مجموعات-الحقول',
'fieldset_name' => 'إسم مجموعة-الحقل',
'field_name' => 'إسم الحقل',
'field_values' => 'Field Values',
'field_values_help' => 'Add selectable options, one per line. Blank lines other than the first line will be ignored. Separate values and labels by pipes on each line (optional).',
'field_element' => 'عنصر النموذج',
'field_element_short' => 'عنصر',
'field_format' => 'صيغة',
@@ -20,4 +26,5 @@ return array(
'order' => 'Order',
'create_fieldset' => 'مجموعة-حقول جديدة',
'create_field' => 'حقل جديد مخصص',
'value_encrypted' => 'The value of this field is encrypted in the database. Only admin users will be able to view the decrypted value',
);

View File

@@ -12,7 +12,8 @@ return array(
'edit' => 'Edit Asset',
'filetype_info' => 'Allowed filetypes are png, gif, jpg, jpeg, doc, docx, pdf, txt, zip, and rar.',
'model_deleted' => 'This Assets model has been deleted. You must restore the model before you can restore the Asset.<br/> <a href="/hardware/models/:model_id/restore">Click here to restore the model</a>.',
'requestable' => 'Requestable',
'requestable' => 'Requestable',
'requested' => 'Requested',
'restore' => 'Restore Asset',
'pending' => 'Pending',
'undeployable' => 'Undeployable',

View File

@@ -37,9 +37,11 @@ return array(
),
'import' => array(
'error' => 'Some Items did not import Correctly.',
'errorDetail' => 'The Following Items were not imported because of errors.',
'success' => "Your File has been imported",
'error' => 'Some items did not import correctly.',
'errorDetail' => 'The following Items were not imported because of errors.',
'success' => "Your file has been imported",
'file_delete_success' => "Your file has been been successfully deleted",
'file_delete_error' => "The file was unable to be deleted",
),
@@ -52,7 +54,8 @@ return array(
'checkout' => array(
'error' => 'Asset was not checked out, please try again',
'success' => 'Asset checked out successfully.',
'user_does_not_exist' => 'That user is invalid. Please try again.'
'user_does_not_exist' => 'That user is invalid. Please try again.',
'not_available' => 'That asset is not available for checkout!'
),
'checkin' => array(
@@ -66,6 +69,7 @@ return array(
'requests' => array(
'error' => 'Asset was not requested, please try again',
'success' => 'Asset requested successfully.',
'canceled' => 'Checkout request successfully canceled'
)
);

View File

@@ -23,7 +23,7 @@ return array(
'error' => 'File(s) not uploaded. Please try again.',
'success' => 'File(s) successfully uploaded.',
'nofiles' => 'You did not select any files for upload, or the file you are trying to upload is too large',
'invalidfiles' => 'One or more of your files is too large or is a filetype that is not allowed. Allowed filetypes are png, gif, jpg, doc, docx, pdf, and txt.',
'invalidfiles' => 'One or more of your files is too large or is a filetype that is not allowed. Allowed filetypes are png, gif, jpg, doc, docx, pdf, txt, zip, rar, and rtf.',
),
'update' => array(

View File

@@ -4,6 +4,7 @@ return array(
'deleted' => 'This model has been deleted. <a href="/hardware/models/:model_id/restore">Click here to restore it</a>.',
'restore' => 'Restore Model',
'requestable' => 'Users may request this model',
'show_mac_address' => 'Show MAC address field in assets in this model',
'view_deleted' => 'View Deleted',
'view_models' => 'View Models',

View File

@@ -51,6 +51,8 @@ return array(
'ldap_pword' => 'LDAP Bind Password',
'ldap_basedn' => 'Base Bind DN',
'ldap_filter' => 'LDAP Filter',
'ldap_pw_sync' => 'LDAP Password Sync',
'ldap_pw_sync_help' => 'Uncheck this box if you do not wish to keep LDAP passwords synced with local passwords. Disabling this means that your users may not be able to login if your LDAP server is unreachable for some reason.',
'ldap_username_field' => 'Username Field',
'ldap_lname_field' => 'Last Name',
'ldap_fname_field' => 'LDAP First Name',

View File

@@ -4,11 +4,13 @@ return array(
'about' => 'About Status Labels',
'archived' => 'Archived',
'create' => 'Create Status Label',
'color' => 'Chart Color',
'deployable' => 'Deployable',
'info' => 'Status labels are used to describe the various states your assets could be in. They may be out for repair, lost/stolen, etc. You can create new status labels for deployable, pending and archived assets.',
'name' => 'Status Name',
'pending' => 'Pending',
'status_type' => 'Status Type',
'show_in_nav' => 'Show in side nav',
'title' => 'Status Labels',
'undeployable' => 'Undeployable',
'update' => 'Update Status Label',

View File

@@ -76,6 +76,7 @@
'image_delete' => 'حذف الصورة',
'image_upload' => 'رفع صورة',
'import' => 'Import',
'import-history' => 'Import History',
'asset_maintenance' => 'Asset Maintenance',
'asset_maintenance_report' => 'Asset Maintenance Report',
'asset_maintenances' => 'Asset Maintenances',
@@ -126,6 +127,7 @@
'remove_company' => 'Remove Company Association',
'reports' => 'التقارير',
'requested' => 'Requested',
'request_canceled' => 'Request Canceled',
'save' => 'حفظ',
'select' => 'Select',
'search' => 'Search',

View File

@@ -0,0 +1,74 @@
<?php
return array(
'a_user_canceled' => 'A user has canceled an item request on the website',
'a_user_requested' => 'A user has requested an item on the website',
'accessory_name' => 'Accessory Name:',
'additional_notes' => 'Additional Notes:',
'admin_has_created' => 'An administrator has created an account for you on the :web website.',
'asset' => 'Asset:',
'asset_name' => 'Asset Name:',
'asset_requested' => 'Asset requested',
'asset_tag' => 'Asset Tag:',
'assets_warrantee_expiring' => '{1} asset with warrantee expiring in the next 60 days.|[2,Inf] assets with warrantees
expiring in the next 60 days.',
'assigned_to' => 'Assigned To',
'best_regards' => 'Best regards,',
'canceled' => 'Canceled:',
'checkin_date' => 'Checkin Date:',
'checkout_date' => 'Checkout Date:',
'click_to_confirm' => 'Please click on the following link to confirm your :web account:',
'click_on_the_link_accessory' => 'Please click on the link at the bottom to confirm that you have received the accessory.',
'click_on_the_link_asset' => 'Please click on the link at the bottom to confirm that you have received the asset.',
'Confirm_Asset_Checkin' => 'Confirm Asset Checkin.',
'Confirm_Accessory_Checkin' => 'Confirm Accessory Checkin.',
'Confirm_accessory_delivery' => 'Confirm accessory delivery.',
'Confirm_asset_delivery' => 'Confirm asset delivery.',
'Confirm_consumable_delivery' => 'Confirm consumable delivery.',
'current_QTY' => 'Current QTY',
'Days' => 'Days',
'days' => 'Days',
'expecting_checkin_date' => 'Expected Checkin Date:',
'expires' => 'Expires',
'Expiring_Assets_Report' => 'Expiring Assets Report.',
'Expiring_Licenses_Report' => 'Expiring Licenses Report.',
'hello' => 'Hello',
'hi' => 'Hi',
'i_have_read' => 'I have read and agree to the terms of use, and have received this item.',
'item' => 'Item:',
'items_below_minimum' => '{1} item that is below minimum inventory or will soon be low.|[2,Inf] items that are below minimum
inventory or will soon be low.',
'Item_Request_Canceled' => 'Item Request Canceled',
'Item_Requested' => 'Item Requested',
'licenses_expiring' => '{1} license expiring next 60 days.|[2,Inf] licenses expiring next 60 days.',
'link_to_update_password' => 'Please click on the following link to update your :web password:',
'login_first_admin' => 'Login to your new Snipe-IT installation using the credentials below:',
'login' => 'Login:',
'Low_Inventory_Report' => 'Low Inventory Report',
'min_QTY' => 'Min QTY',
'name' => 'Name',
'new_item_checked' => 'A new item has been checked out under your name, details are below.',
'password' => 'Password:',
'password_reset' => 'Password Reset',
'read_the_terms' => 'Please read the terms of use below.',
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read
and agree to the terms of use, and have received the asset.',
'requested' => 'Requested:',
'reset_link' => 'Your Password Reset Link',
'reset_password' => 'Click here to reset your password:',
'serial' => 'Serial:',
'supplier' => 'Supplier',
'tag' => 'Tag',
'test_email' => 'Test Email from Snipe-IT',
'test_mail_text' => 'This is a test from the Snipe-IT Asset Management System. If you got this, mail is working :)',
'the_following_item' => 'The following item has been checked in: ',
'There_are' => '{1} There is|[2,Inf] There are',
'to_reset' => 'To reset your :web password, complete this form:',
'type' => 'Type',
'user' => 'User:',
'username' => 'Username:',
'welcome' => 'Welcome :name',
'welcome_to' => 'Welcome to :web!',
'your_credentials' => 'Your Snipe-IT credentials',
);

View File

@@ -3,13 +3,14 @@
return array(
'about_consumables_title' => 'Относно консумативите',
'about_consumables_text' => 'Консумативите са всички неща, купувани във времето. Например тонер за принтер или хартия.',
'consumable_name' => 'Консуматив',
'cost' => 'Стойност на закупуване',
'create' => 'Създаване на консуматив',
'date' => 'Дата на закупуване',
'item_no' => 'Item No.',
'order' => 'Номер на поръчка',
'remaining' => 'Остава',
'total' => 'Oбщо',
'checkout' => 'Checkout Consumable to User',
'consumable_name' => 'Консуматив',
'cost' => 'Стойност на закупуване',
'create' => 'Създаване на консуматив',
'date' => 'Дата на закупуване',
'item_no' => 'Item No.',
'order' => 'Номер на поръчка',
'remaining' => 'Остава',
'total' => 'Oбщо',
'update' => 'Обновяване на консуматив',
);

View File

@@ -4,12 +4,18 @@ return array(
'custom_fields' => 'Потребителски полета',
'field' => 'Поле',
'about_fieldsets_title' => 'About Fieldsets',
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used used for specific asset model types.',
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
'custom_format' => 'Custom format...',
'encrypt_field' => 'Encrypt the value of this field in the database for each asset. The decrypted value of this field will only be viewable by admins.',
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
'encrypted' => 'Encrypted',
'fieldset' => 'Fieldset',
'qty_fields' => 'Qty Fields',
'fieldsets' => 'Fieldsets',
'fieldset_name' => 'Fieldset Name',
'field_name' => 'Field Name',
'field_values' => 'Field Values',
'field_values_help' => 'Add selectable options, one per line. Blank lines other than the first line will be ignored. Separate values and labels by pipes on each line (optional).',
'field_element' => 'Form Element',
'field_element_short' => 'Element',
'field_format' => 'Format',
@@ -20,4 +26,5 @@ return array(
'order' => 'Order',
'create_fieldset' => 'New Fieldset',
'create_field' => 'New Custom Field',
'value_encrypted' => 'The value of this field is encrypted in the database. Only admin users will be able to view the decrypted value',
);

View File

@@ -12,7 +12,8 @@ return array(
'edit' => 'Редакция на актив',
'filetype_info' => 'Позволените типове файлове са png, gif, jpg, jpeg, doc, docx, pdf, txt, zip, и rar.',
'model_deleted' => 'Моделът актив беше изтрит.Необходимо е да възстановите моделът, преди да възстановите актива.<br/> <a href="/hardware/models/:model_id/restore">Възстановяване на модел</a>.',
'requestable' => 'Може да бъде изискван',
'requestable' => 'Може да бъде изискван',
'requested' => 'Requested',
'restore' => 'Възстановяване на актив',
'pending' => 'Предстоящ',
'undeployable' => 'Не може да бъде предоставян',

View File

@@ -36,9 +36,11 @@ return array(
),
'import' => array(
'error' => 'Some Items did not import Correctly.',
'errorDetail' => 'The Following Items were not imported because of errors.',
'success' => "Your File has been imported",
'error' => 'Some items did not import correctly.',
'errorDetail' => 'The following Items were not imported because of errors.',
'success' => "Your file has been imported",
'file_delete_success' => "Your file has been been successfully deleted",
'file_delete_error' => "The file was unable to be deleted",
),
@@ -51,7 +53,8 @@ return array(
'checkout' => array(
'error' => 'Активът не беше изписан. Моля опитайте отново.',
'success' => 'Активът изписан успешно.',
'user_does_not_exist' => 'Невалиден потребител. Моля опитайте отново.'
'user_does_not_exist' => 'Невалиден потребител. Моля опитайте отново.',
'not_available' => 'That asset is not available for checkout!'
),
'checkin' => array(
@@ -65,6 +68,7 @@ return array(
'requests' => array(
'error' => 'Активът не беше изискан. Моля опитайте отново.',
'success' => 'Активът изискан успешно.',
'canceled' => 'Checkout request successfully canceled'
)
);

View File

@@ -23,7 +23,7 @@ return array(
'error' => 'Файлът (файловете) не е качен. Моля, опитайте отново.',
'success' => 'Файлът (файловете) е качен.',
'nofiles' => 'Не сте избрали файл за качване или файлът, който се опитвате да качите е твърде голям',
'invalidfiles' => 'Един или повече файлове са твърде големи или с неразрешен тип. Разрешените типове файлове са png, gif, jpg, doc, docx, pdf, и txt.',
'invalidfiles' => 'One or more of your files is too large or is a filetype that is not allowed. Allowed filetypes are png, gif, jpg, doc, docx, pdf, txt, zip, rar, and rtf.',
),
'update' => array(

View File

@@ -4,6 +4,7 @@ return array(
'deleted' => 'Моделът беше изтрит. <a href="/hardware/models/:model_id/restore">Възстановяване</a>.',
'restore' => 'Възстановяване на модел',
'requestable' => 'Users may request this model',
'show_mac_address' => 'Визуализиране на поле за MAC адрес в активите за този модел',
'view_deleted' => 'Преглед на изтритите',
'view_models' => 'Преглед на моделите',

View File

@@ -51,6 +51,8 @@ return array(
'ldap_pword' => 'LDAP парола на потребител за връзка',
'ldap_basedn' => 'Базов DN',
'ldap_filter' => 'LDAP филтър',
'ldap_pw_sync' => 'LDAP Password Sync',
'ldap_pw_sync_help' => 'Uncheck this box if you do not wish to keep LDAP passwords synced with local passwords. Disabling this means that your users may not be able to login if your LDAP server is unreachable for some reason.',
'ldap_username_field' => 'Поле за потребителско име',
'ldap_lname_field' => 'Фамилия',
'ldap_fname_field' => 'LDAP собствено име',

View File

@@ -4,11 +4,13 @@ return array(
'about' => 'Относно статус етикетите',
'archived' => 'Архивирани',
'create' => 'Създаване на статус етикет',
'color' => 'Chart Color',
'deployable' => 'Може да бъде предоставен',
'info' => 'Статусите се използват за описване на различните състояния на Вашите активи. Например, това са Предаден за ремонт, Изгубен/откраднат и др. Можете да създавате нови статуси за активите, които могат да бъдат предоставяни, очакващи набавяне и архивирани.',
'name' => 'Статус',
'pending' => 'Изчакване',
'status_type' => 'Тип на статуса',
'show_in_nav' => 'Show in side nav',
'title' => 'Заглавия на статуси',
'undeployable' => 'Не може да бъде предоставян',
'update' => 'Обновяване на статус',

View File

@@ -76,6 +76,7 @@
'image_delete' => 'Изтриване на изображението',
'image_upload' => 'Качване на изображение',
'import' => 'Зареждане',
'import-history' => 'Import History',
'asset_maintenance' => 'Поддръжка на активи',
'asset_maintenance_report' => 'Справка за поддръжка на активи',
'asset_maintenances' => 'Поддръжки на активи',
@@ -126,6 +127,7 @@
'remove_company' => 'Премахване на асоциация към компания',
'reports' => 'Справки',
'requested' => 'Изискан',
'request_canceled' => 'Request Canceled',
'save' => 'Запис',
'select' => 'Избор',
'search' => 'Търсене',

View File

@@ -0,0 +1,74 @@
<?php
return array(
'a_user_canceled' => 'A user has canceled an item request on the website',
'a_user_requested' => 'A user has requested an item on the website',
'accessory_name' => 'Accessory Name:',
'additional_notes' => 'Additional Notes:',
'admin_has_created' => 'An administrator has created an account for you on the :web website.',
'asset' => 'Asset:',
'asset_name' => 'Asset Name:',
'asset_requested' => 'Asset requested',
'asset_tag' => 'Asset Tag:',
'assets_warrantee_expiring' => '{1} asset with warrantee expiring in the next 60 days.|[2,Inf] assets with warrantees
expiring in the next 60 days.',
'assigned_to' => 'Assigned To',
'best_regards' => 'Best regards,',
'canceled' => 'Canceled:',
'checkin_date' => 'Checkin Date:',
'checkout_date' => 'Checkout Date:',
'click_to_confirm' => 'Please click on the following link to confirm your :web account:',
'click_on_the_link_accessory' => 'Please click on the link at the bottom to confirm that you have received the accessory.',
'click_on_the_link_asset' => 'Please click on the link at the bottom to confirm that you have received the asset.',
'Confirm_Asset_Checkin' => 'Confirm Asset Checkin.',
'Confirm_Accessory_Checkin' => 'Confirm Accessory Checkin.',
'Confirm_accessory_delivery' => 'Confirm accessory delivery.',
'Confirm_asset_delivery' => 'Confirm asset delivery.',
'Confirm_consumable_delivery' => 'Confirm consumable delivery.',
'current_QTY' => 'Current QTY',
'Days' => 'Days',
'days' => 'Days',
'expecting_checkin_date' => 'Expected Checkin Date:',
'expires' => 'Expires',
'Expiring_Assets_Report' => 'Expiring Assets Report.',
'Expiring_Licenses_Report' => 'Expiring Licenses Report.',
'hello' => 'Hello',
'hi' => 'Hi',
'i_have_read' => 'I have read and agree to the terms of use, and have received this item.',
'item' => 'Item:',
'items_below_minimum' => '{1} item that is below minimum inventory or will soon be low.|[2,Inf] items that are below minimum
inventory or will soon be low.',
'Item_Request_Canceled' => 'Item Request Canceled',
'Item_Requested' => 'Item Requested',
'licenses_expiring' => '{1} license expiring next 60 days.|[2,Inf] licenses expiring next 60 days.',
'link_to_update_password' => 'Please click on the following link to update your :web password:',
'login_first_admin' => 'Login to your new Snipe-IT installation using the credentials below:',
'login' => 'Login:',
'Low_Inventory_Report' => 'Low Inventory Report',
'min_QTY' => 'Min QTY',
'name' => 'Name',
'new_item_checked' => 'A new item has been checked out under your name, details are below.',
'password' => 'Password:',
'password_reset' => 'Password Reset',
'read_the_terms' => 'Please read the terms of use below.',
'read_the_terms_and_click' => 'Please read the terms of use below, and click on the link at the bottom to confirm that you read
and agree to the terms of use, and have received the asset.',
'requested' => 'Requested:',
'reset_link' => 'Your Password Reset Link',
'reset_password' => 'Click here to reset your password:',
'serial' => 'Serial:',
'supplier' => 'Supplier',
'tag' => 'Tag',
'test_email' => 'Test Email from Snipe-IT',
'test_mail_text' => 'This is a test from the Snipe-IT Asset Management System. If you got this, mail is working :)',
'the_following_item' => 'The following item has been checked in: ',
'There_are' => '{1} There is|[2,Inf] There are',
'to_reset' => 'To reset your :web password, complete this form:',
'type' => 'Type',
'user' => 'User:',
'username' => 'Username:',
'welcome' => 'Welcome :name',
'welcome_to' => 'Welcome to :web!',
'your_credentials' => 'Your Snipe-IT credentials',
);

View File

@@ -3,13 +3,14 @@
return array(
'about_consumables_title' => 'O spotřebním materiálu',
'about_consumables_text' => 'Spotřební materiál jsou takové položky, které jsou v čase spotřebovávány, jako např. toner, inkoust či papír do tiskáren.',
'consumable_name' => 'Název sp. materiálu',
'cost' => 'Náklady',
'create' => 'Vytvořit sp. materiál',
'date' => 'Datum pořízení',
'item_no' => 'Položka č.',
'order' => 'Číslo objednávky',
'remaining' => 'Zbývá',
'total' => 'Celkem',
'checkout' => 'Checkout Consumable to User',
'consumable_name' => 'Název sp. materiálu',
'cost' => 'Náklady',
'create' => 'Vytvořit sp. materiál',
'date' => 'Datum pořízení',
'item_no' => 'Položka č.',
'order' => 'Číslo objednávky',
'remaining' => 'Zbývá',
'total' => 'Celkem',
'update' => 'Upravit sp. materiál',
);

View File

@@ -5,11 +5,17 @@ return array(
'field' => 'Pole',
'about_fieldsets_title' => 'O sadách polí',
'about_fieldsets_text' => 'Sady polí Vám umožňují vytvořit si vlastní hodnoty, které chcete evidovat u modelů majetku.',
'custom_format' => 'Custom format...',
'encrypt_field' => 'Encrypt the value of this field in the database for each asset. The decrypted value of this field will only be viewable by admins.',
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
'encrypted' => 'Encrypted',
'fieldset' => 'Sada',
'qty_fields' => 'Počet',
'fieldsets' => 'Sady',
'fieldset_name' => 'Název sady',
'field_name' => 'Název pole',
'field_values' => 'Field Values',
'field_values_help' => 'Add selectable options, one per line. Blank lines other than the first line will be ignored. Separate values and labels by pipes on each line (optional).',
'field_element' => 'Typ pole',
'field_element_short' => 'Typ',
'field_format' => 'Formát',
@@ -20,4 +26,5 @@ return array(
'order' => 'Pořadí',
'create_fieldset' => 'Nová sada',
'create_field' => 'Nové vlastní pole',
'value_encrypted' => 'The value of this field is encrypted in the database. Only admin users will be able to view the decrypted value',
);

Some files were not shown because too many files have changed in this diff Show More