Merge branch 'develop' into snipeit_v7

This commit is contained in:
Brady Wetherington 2023-07-19 11:47:51 +01:00
commit 605d267fe8
77 changed files with 737 additions and 167 deletions

View file

@ -15,15 +15,15 @@ on:
- develop
pull_request:
branches:
- master
- develop
branches: .*
pipeline:
- name: Setup
cmd: |
cp -v .env.example .env
# This is simply to allow passing the guard in TestCase@setUp()
# https://chipperci.com/docs/builds/env
touch .env.testing
composer install --no-interaction --prefer-dist --optimize-autoloader
- name: Generate Key

View file

@ -85,6 +85,7 @@ COOKIE_NAME=snipeit_session
COOKIE_DOMAIN=null
SECURE_COOKIES=false
API_TOKEN_EXPIRATION_YEARS=15
BS_TABLE_STORAGE=cookieStorage
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS

View file

@ -212,9 +212,12 @@ class LdapSync extends Command
$item['manager'] = $results[$i][$ldap_result_manager][0] ?? '';
$item['location'] = $results[$i][$ldap_result_location][0] ?? '';
// ONLY if you are using the "ldap_location" option *AND* you have an actual result
if ($ldap_result_location && $item['location']) {
$location = Location::firstOrCreate([
'name' => $item['location'],
]);
}
$department = Department::firstOrCreate([
'name' => $item['department'],
]);

View file

@ -33,6 +33,16 @@ class Helper
}
}
public static function parseEscapedMarkedownInline($str = null)
{
$Parsedown = new \Parsedown();
$Parsedown->setSafeMode(true);
if ($str) {
return $Parsedown->line($str);
}
}
/**
* The importer has formatted number strings since v3,
* so the value might be a string, or an integer.
@ -544,7 +554,7 @@ class Helper
];
if ($selection != null){
return $category_types[$selection];
return $category_types[strtolower($selection)];
}
else
return $category_types;

View file

@ -545,7 +545,8 @@ class AssetsController extends Controller
$asset->model_id = $request->get('model_id');
$asset->order_number = $request->get('order_number');
$asset->notes = $request->get('notes');
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset());
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset()); //yup, problem :/
// NO IT IS NOT!!! This is never firing; we SHOW the asset_tag you're going to get, so it *will* be filled in!
$asset->user_id = Auth::id();
$asset->archived = '0';
$asset->physical = '1';

View file

@ -27,6 +27,8 @@ class CompaniesController extends Controller
$allowed_columns = [
'id',
'name',
'phone',
'fax',
'created_at',
'updated_at',
'users_count',

View file

@ -30,6 +30,8 @@ class DepartmentsController extends Controller
$departments = Company::scopeCompanyables(Department::select(
'departments.id',
'departments.name',
'departments.phone',
'departments.fax',
'departments.location_id',
'departments.company_id',
'departments.manager_id',

View file

@ -37,6 +37,8 @@ class LocationsController extends Controller
'locations.city',
'locations.state',
'locations.zip',
'locations.phone',
'locations.fax',
'locations.country',
'locations.parent_id',
'locations.manager_id',
@ -251,8 +253,12 @@ class LocationsController extends Controller
*/
public function selectlist(Request $request)
{
$this->authorize('view.selectlists');
// If a user is in the process of editing their profile, as determined by the referrer,
// then we check that they have permission to edit their own location.
// Otherwise, we do our normal check that they can view select lists.
$request->headers->get('referer') === route('profile')
? $this->authorize('self.edit_location')
: $this->authorize('view.selectlists');
$locations = Location::select([
'locations.id',

View file

@ -78,12 +78,6 @@ class UsersController extends Controller
$users = Company::scopeCompanyables($users);
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
$users = $users->onlyTrashed();
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
$users = $users->withTrashed();
}
if ($request->filled('activated')) {
$users = $users->where('users.activated', '=', $request->input('activated'));
}
@ -272,6 +266,12 @@ class UsersController extends Controller
break;
}
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
$users = $users->onlyTrashed();
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
$users = $users->withTrashed();
}
$total = $users->count();
$users = $users->skip($offset)->take($limit)->get();

View file

@ -94,14 +94,18 @@ class AssetCheckinController extends Controller
\Log::debug('Manually override the location IDs');
\Log::debug('Original Location ID: '.$asset->location_id);
$asset->location_id = '';
\Log::debug('New RTD Location ID: '.$asset->location_id);
\Log::debug('New Location ID: '.$asset->location_id);
}
$asset->location_id = $asset->rtd_location_id;
if ($request->filled('location_id')) {
\Log::debug('NEW Location ID: '.$request->get('location_id'));
$asset->location_id = e($request->get('location_id'));
$asset->location_id = $request->get('location_id');
if ($request->get('update_default_location') == 0){
$asset->rtd_location_id = $request->get('location_id');
}
}
$checkin_at = date('Y-m-d H:i:s');

View file

@ -60,6 +60,8 @@ final class CompaniesController extends Controller
$company = new Company;
$company->name = $request->input('name');
$company->phone = $request->input('phone');
$company->fax = $request->input('fax');
$company = $request->handleImages($company);
@ -111,6 +113,8 @@ final class CompaniesController extends Controller
$this->authorize('update', $company);
$company->name = $request->input('name');
$company->phone = $request->input('phone');
$company->fax = $request->input('fax');
$company = $request->handleImages($company);

View file

@ -109,6 +109,7 @@ class CustomFieldsController extends Controller
"is_unique" => $request->get("is_unique", 0),
"display_in_user_view" => $display_in_user_view,
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
"show_in_listview" => $request->get("show_in_listview", 0),
"user_id" => Auth::id()
]);
@ -265,6 +266,7 @@ class CustomFieldsController extends Controller
$field->is_unique = $request->get("is_unique", 0);
$field->display_in_user_view = $display_in_user_view;
$field->auto_add_to_fieldsets = $request->get("auto_add_to_fieldsets", 0);
$field->show_in_listview = $request->get("show_in_listview", 0);
if ($request->get('format') == 'CUSTOM REGEX') {
$field->format = e($request->get('custom_format'));

View file

@ -170,6 +170,8 @@ class DepartmentsController extends Controller
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
$department->location_id = ($request->filled('location_id') ? $request->input('location_id') : null);
$department->company_id = ($request->filled('company_id') ? $request->input('company_id') : null);
$department->phone = $request->input('phone');
$department->fax = $request->input('fax');
$department = $request->handleImages($department);

View file

@ -79,6 +79,8 @@ class LocationsController extends Controller
$location->ldap_ou = $request->input('ldap_ou');
$location->manager_id = $request->input('manager_id');
$location->user_id = Auth::id();
$location->phone = request('phone');
$location->fax = request('fax');
$location = $request->handleImages($location);
@ -139,6 +141,8 @@ class LocationsController extends Controller
$location->state = $request->input('state');
$location->country = $request->input('country');
$location->zip = $request->input('zip');
$location->phone = request('phone');
$location->fax = request('fax');
$location->ldap_ou = $request->input('ldap_ou');
$location->manager_id = $request->input('manager_id');

View file

@ -284,6 +284,8 @@ class Importer extends Component
'maintained' => trans('admin/licenses/form.maintained'),
'checkout_class' => trans('general.importer.checkout_type'),
'serial' => trans('general.license_serial'),
'email' => trans('general.importer.checked_out_to_email'),
'username' => trans('general.importer.checked_out_to_username'),
];
$this->users_fields = [
@ -313,7 +315,7 @@ class Importer extends Component
'gravatar' => trans('general.importer.gravatar'),
'start_date' => trans('general.start_date'),
'end_date' => trans('general.end_date'),
'employee_number' => trans('general.employee_number'),
'employee_num' => trans('general.employee_number'),
];
$this->locations_fields = [

View file

@ -32,7 +32,7 @@ class AccessoriesTransformer
'model_number' => ($accessory->model_number) ? e($accessory->model_number) : null,
'category' => ($accessory->category) ? ['id' => $accessory->category->id, 'name'=> e($accessory->category->name)] : null,
'location' => ($accessory->location) ? ['id' => $accessory->location->id, 'name'=> e($accessory->location->name)] : null,
'notes' => ($accessory->notes) ? Helper::parseEscapedMarkedown($accessory->notes) : null,
'notes' => ($accessory->notes) ? Helper::parseEscapedMarkedownInline($accessory->notes) : null,
'qty' => ($accessory->qty) ? (int) $accessory->qty : null,
'purchase_date' => ($accessory->purchase_date) ? Helper::getFormattedDateObject($accessory->purchase_date, 'date') : null,
'purchase_cost' => Helper::formatCurrencyOutput($accessory->purchase_cost),

View file

@ -110,7 +110,7 @@ class ActionlogsTransformer
'type' => e($actionlog->targetType()),
] : null,
'note' => ($actionlog->note) ? Helper::parseEscapedMarkedown($actionlog->note): null,
'note' => ($actionlog->note) ? Helper::parseEscapedMarkedownInline($actionlog->note): null,
'signature_file' => ($actionlog->accept_signature) ? route('log.signature.view', ['filename' => $actionlog->accept_signature ]) : null,
'log_meta' => ((isset($clean_meta)) && (is_array($clean_meta))) ? $clean_meta: null,
'action_date' => ($actionlog->action_date) ? Helper::getFormattedDateObject($actionlog->action_date, 'datetime'): Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),

View file

@ -49,7 +49,7 @@ class AssetMaintenancesTransformer
'id' => (int) $assetmaintenance->asset->defaultLoc->id,
'name'=> e($assetmaintenance->asset->defaultLoc->name),
] : null,
'notes' => ($assetmaintenance->notes) ? Helper::parseEscapedMarkedown($assetmaintenance->notes) : null,
'notes' => ($assetmaintenance->notes) ? Helper::parseEscapedMarkedownInline($assetmaintenance->notes) : null,
'supplier' => ($assetmaintenance->supplier) ? ['id' => $assetmaintenance->supplier->id, 'name'=> e($assetmaintenance->supplier->name)] : null,
'cost' => Helper::formatCurrencyOutput($assetmaintenance->cost),
'asset_maintenance_type' => e($assetmaintenance->asset_maintenance_type),

View file

@ -63,7 +63,7 @@ class AssetModelsTransformer
'default_fieldset_values' => $default_field_values,
'eol' => ($assetmodel->eol > 0) ? $assetmodel->eol.' months' : 'None',
'requestable' => ($assetmodel->requestable == '1') ? true : false,
'notes' => Helper::parseEscapedMarkedown($assetmodel->notes),
'notes' => Helper::parseEscapedMarkedownInline($assetmodel->notes),
'created_at' => Helper::getFormattedDateObject($assetmodel->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmodel->updated_at, 'datetime'),
'deleted_at' => Helper::getFormattedDateObject($assetmodel->deleted_at, 'datetime'),

View file

@ -58,7 +58,7 @@ class AssetsTransformer
'id' => (int) $asset->supplier->id,
'name'=> e($asset->supplier->name),
] : null,
'notes' => ($asset->notes) ? Helper::parseEscapedMarkedown($asset->notes) : null,
'notes' => ($asset->notes) ? Helper::parseEscapedMarkedownInline($asset->notes) : null,
'order_number' => ($asset->order_number) ? e($asset->order_number) : null,
'company' => ($asset->company) ? [
'id' => (int) $asset->company->id,

View file

@ -26,6 +26,8 @@ class CompaniesTransformer
$array = [
'id' => (int) $company->id,
'name' => e($company->name),
'phone' => ($company->phone!='') ? e($company->phone): null,
'fax' => ($company->fax!='') ? e($company->fax): null,
'image' => ($company->image) ? Storage::disk('public')->url('companies/'.e($company->image)) : null,
'created_at' => Helper::getFormattedDateObject($company->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($company->updated_at, 'datetime'),

View file

@ -46,7 +46,7 @@ class ComponentsTransformer
'id' => (int) $component->company->id,
'name' => e($component->company->name),
] : null,
'notes' => ($component->notes) ? Helper::parseEscapedMarkedown($component->notes) : null,
'notes' => ($component->notes) ? Helper::parseEscapedMarkedownInline($component->notes) : null,
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
'user_can_checkout' => ($component->numRemaining() > 0) ? 1 : 0,

View file

@ -39,7 +39,7 @@ class ConsumablesTransformer
'purchase_cost' => Helper::formatCurrencyOutput($consumable->purchase_cost),
'purchase_date' => Helper::getFormattedDateObject($consumable->purchase_date, 'date'),
'qty' => (int) $consumable->qty,
'notes' => ($consumable->notes) ? Helper::parseEscapedMarkedown($consumable->notes) : null,
'notes' => ($consumable->notes) ? Helper::parseEscapedMarkedownInline($consumable->notes) : null,
'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'),
];

View file

@ -49,6 +49,7 @@ class CustomFieldsTransformer
'required' => (($field->pivot) && ($field->pivot->required=='1')) ? true : false,
'display_in_user_view' => ($field->display_in_user_view =='1') ? true : false,
'auto_add_to_fieldsets' => ($field->auto_add_to_fieldsets == '1') ? true : false,
'show_in_listview' => ($field->show_in_listview == '1') ? true : false,
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
];

View file

@ -26,6 +26,8 @@ class DepartmentsTransformer
$array = [
'id' => (int) $department->id,
'name' => e($department->name),
'phone' => ($department->phone!='') ? e($department->phone): null,
'fax' => ($department->fax!='') ? e($department->fax): null,
'image' => ($department->image) ? Storage::disk('public')->url(app('departments_upload_url').e($department->image)) : null,
'company' => ($department->company) ? [
'id' => (int) $department->company->id,

View file

@ -34,7 +34,7 @@ class LicensesTransformer
'depreciation' => ($license->depreciation) ? ['id' => (int) $license->depreciation->id,'name'=> e($license->depreciation->name)] : null,
'purchase_cost' => Helper::formatCurrencyOutput($license->purchase_cost),
'purchase_cost_numeric' => $license->purchase_cost,
'notes' => Helper::parseEscapedMarkedown($license->notes),
'notes' => Helper::parseEscapedMarkedownInline($license->notes),
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
'seats' => (int) $license->seats,
'free_seats_count' => (int) $license->free_seats_count,

View file

@ -43,6 +43,8 @@ class LocationsTransformer
'state' => ($location->state) ? e($location->state) : null,
'country' => ($location->country) ? e($location->country) : null,
'zip' => ($location->zip) ? e($location->zip) : null,
'phone' => ($location->phone!='') ? e($location->phone): null,
'fax' => ($location->fax!='') ? e($location->fax): null,
'assigned_assets_count' => (int) $location->assigned_assets_count,
'assets_count' => (int) $location->assets_count,
'rtd_assets_count' => (int) $location->rtd_assets_count,

View file

@ -43,7 +43,7 @@ class SuppliersTransformer
'licenses_count' => (int) $supplier->licenses_count,
'consumables_count' => (int) $supplier->consumables_count,
'components_count' => (int) $supplier->components_count,
'notes' => ($supplier->notes) ? Helper::parseEscapedMarkedown($supplier->notes) : null,
'notes' => ($supplier->notes) ? Helper::parseEscapedMarkedownInline($supplier->notes) : null,
'created_at' => Helper::getFormattedDateObject($supplier->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($supplier->updated_at, 'datetime'),

View file

@ -53,7 +53,7 @@ class UsersTransformer
'id' => (int) $user->userloc->id,
'name'=> e($user->userloc->name),
] : null,
'notes'=> Helper::parseEscapedMarkedown($user->notes),
'notes'=> Helper::parseEscapedMarkedownInline($user->notes),
'permissions' => $user->decodePermissions(),
'activated' => ($user->activated == '1') ? true : false,
'autoassign_licenses' => ($user->autoassign_licenses == '1') ? true : false,

View file

@ -785,24 +785,17 @@ class Asset extends Depreciable
* @since [v4.0]
* @return string | false
*/
public static function autoincrement_asset()
public static function autoincrement_asset(int $additional_increment = 0)
{
$settings = \App\Models\Setting::getSettings();
if ($settings->auto_increment_assets == '1') {
$temp_asset_tag = \DB::table('assets')
->where('physical', '=', '1')
->max('asset_tag');
$asset_tag_digits = preg_replace('/\D/', '', $temp_asset_tag);
$asset_tag = preg_replace('/^0*/', '', $asset_tag_digits);
if ($settings->zerofill_count > 0) {
return $settings->auto_increment_prefix.self::zerofill($settings->next_auto_tag_base, $settings->zerofill_count);
return $settings->auto_increment_prefix.self::zerofill($settings->next_auto_tag_base + $additional_increment, $settings->zerofill_count);
}
return $settings->auto_increment_prefix.$settings->next_auto_tag_base;
return $settings->auto_increment_prefix.($settings->next_auto_tag_base + $additional_increment);
} else {
return false;
}

View file

@ -18,7 +18,7 @@ class CheckoutRequest extends Model
public function requestingUser()
{
return $this->user()->first();
return $this->user()->withTrashed()->first();
}
public function requestedItem()

View file

@ -45,7 +45,7 @@ final class Company extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'created_at', 'updated_at'];
protected $searchableAttributes = ['name', 'phone', 'fax', 'created_at', 'updated_at'];
/**
* The relations and their attributes that should be included when searching the model.
@ -59,7 +59,11 @@ final class Company extends SnipeModel
*
* @var array
*/
protected $fillable = ['name'];
protected $fillable = [
'name',
'phone',
'fax',
];
private static function isFullMultipleCompanySupportEnabled()
{

View file

@ -53,6 +53,7 @@ class CustomField extends Model
'element' => 'required|in:text,listbox,textarea,checkbox,radio',
'field_encrypted' => 'nullable|boolean',
'auto_add_to_fieldsets' => 'boolean',
'show_in_listview' => 'boolean',
];
/**
@ -71,6 +72,7 @@ class CustomField extends Model
'is_unique',
'display_in_user_view',
'auto_add_to_fieldsets',
'show_in_listview',
];

View file

@ -43,6 +43,8 @@ class Department extends SnipeModel
protected $fillable = [
'user_id',
'name',
'phone',
'fax',
'location_id',
'company_id',
'manager_id',
@ -56,7 +58,7 @@ class Department extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'notes'];
protected $searchableAttributes = ['name', 'notes', 'phone', 'fax'];
/**
* The relations and their attributes that should be included when searching the model.

View file

@ -66,6 +66,8 @@ class Location extends SnipeModel
'state',
'country',
'zip',
'phone',
'fax',
'ldap_ou',
'currency',
'manager_id',
@ -80,7 +82,7 @@ class Location extends SnipeModel
*
* @var array
*/
protected $searchableAttributes = ['name', 'address', 'city', 'state', 'zip', 'created_at', 'ldap_ou'];
protected $searchableAttributes = ['name', 'address', 'city', 'state', 'zip', 'created_at', 'ldap_ou', 'phone', 'fax'];
/**
* The relations and their attributes that should be included when searching the model.

View file

@ -71,12 +71,33 @@ class AssetObserver
public function created(Asset $asset)
{
if ($settings = Setting::getSettings()) {
$settings->increment('next_auto_tag_base');
$tag = $asset->asset_tag;
$prefix = $settings->auto_increment_prefix;
$number = substr($tag, strlen($prefix));
// IF - auto_increment_assets is on, AND (the prefix matches the start of the tag OR there is no prefix)
// AND the rest of the string after the prefix is all digits, THEN...
if ($settings->auto_increment_assets && (strpos($tag, $prefix) === 0 || $prefix=='') && preg_match('/\d+/',$number) === 1) {
// new way of auto-trueing-up auto_increment ID's
$next_asset_tag = intval($number, 10) + 1;
// we had to use 'intval' because the $number could be '01234' and
// might get interpreted in Octal instead of decimal
// only modify the 'next' one if it's *bigger* than the stored base
//
if($next_asset_tag > $settings->next_auto_tag_base) {
$settings->next_auto_tag_base = $next_asset_tag;
$settings->save();
}
} else {
// legacy method
$settings->increment('next_auto_tag_base');
$settings->save();
}
}
$logAction = new Actionlog();
$logAction->item_type = Asset::class;
$logAction->item_type = Asset::class; // can we instead say $logAction->item = $asset ?
$logAction->item_id = $asset->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->user_id = Auth::id();

View file

@ -123,6 +123,7 @@ class AssetModelPresenter extends Presenter
'switchable' => true,
'title' => trans('general.notes'),
'visible' => false,
'formatter' => 'notesFormatter',
],
[
'field' => 'created_at',

View file

@ -292,7 +292,7 @@ class AssetPresenter extends Presenter
'formatter'=> 'customFieldsFormatter',
'escape' => true,
'class' => ($field->field_encrypted == '1') ? 'css-padlock' : '',
'visible' => true,
'visible' => ($field->show_in_listview == '1') ? true : false,
];
}

View file

@ -29,6 +29,22 @@ class CompanyPresenter extends Presenter
'title' => trans('admin/companies/table.name'),
'visible' => true,
'formatter' => 'companiesLinkFormatter',
], [
'field' => 'phone',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/users/table.phone'),
'visible' => false,
'formatter' => 'phoneFormatter',
], [
'field' => 'fax',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/suppliers/table.fax'),
'visible' => false,
'formatter' => 'phoneFormatter',
], [
'field' => 'image',
'searchable' => false,

View file

@ -141,6 +141,24 @@ class LocationPresenter extends Presenter
'title' => trans('admin/locations/table.country'),
'visible' => false,
],
[
'field' => 'phone',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/users/table.phone'),
'visible' => false,
'formatter' => 'phoneFormatter',
],
[
'field' => 'fax',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/suppliers/table.fax'),
'visible' => false,
'formatter' => 'phoneFormatter',
],
[
'field' => 'ldap_ou',
'searchable' => true,

View file

@ -79,7 +79,7 @@
"squizlabs/php_codesniffer": "^3.5",
"symfony/css-selector": "^4.4",
"symfony/dom-crawler": "^4.4",
"vimeo/psalm": "^5.6"
"vimeo/psalm": "^5.13"
},
"extra": {
"laravel": {

119
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "e176ce10814f5dda2b4122265d3433b8",
"content-hash": "5d8f11efafbf126fd89eca49f4ce7e29",
"packages": [
{
"name": "alek13/slack",
@ -247,16 +247,16 @@
},
{
"name": "aws/aws-sdk-php",
"version": "3.275.5",
"version": "3.275.9",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "d46961b82e857f77059c0c78160719ecb26f6cc6"
"reference": "1ef08ba5109591751257ad1eaa52c2e2fbd53cf1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d46961b82e857f77059c0c78160719ecb26f6cc6",
"reference": "d46961b82e857f77059c0c78160719ecb26f6cc6",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/1ef08ba5109591751257ad1eaa52c2e2fbd53cf1",
"reference": "1ef08ba5109591751257ad1eaa52c2e2fbd53cf1",
"shasum": ""
},
"require": {
@ -336,9 +336,9 @@
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.275.5"
"source": "https://github.com/aws/aws-sdk-php/tree/3.275.9"
},
"time": "2023-07-07T18:20:11+00:00"
"time": "2023-07-18T18:20:13+00:00"
},
{
"name": "bacon/bacon-qr-code",
@ -1747,16 +1747,16 @@
},
{
"name": "filp/whoops",
"version": "2.15.2",
"version": "2.15.3",
"source": {
"type": "git",
"url": "https://github.com/filp/whoops.git",
"reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73"
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/filp/whoops/zipball/aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
"reference": "aac9304c5ed61bf7b1b7a6064bf9806ab842ce73",
"url": "https://api.github.com/repos/filp/whoops/zipball/c83e88a30524f9360b11f585f71e6b17313b7187",
"reference": "c83e88a30524f9360b11f585f71e6b17313b7187",
"shasum": ""
},
"require": {
@ -1806,7 +1806,7 @@
],
"support": {
"issues": "https://github.com/filp/whoops/issues",
"source": "https://github.com/filp/whoops/tree/2.15.2"
"source": "https://github.com/filp/whoops/tree/2.15.3"
},
"funding": [
{
@ -1814,20 +1814,20 @@
"type": "github"
}
],
"time": "2023-04-12T12:00:00+00:00"
"time": "2023-07-13T12:00:00+00:00"
},
{
"name": "firebase/php-jwt",
"version": "v6.8.0",
"version": "v6.8.1",
"source": {
"type": "git",
"url": "https://github.com/firebase/php-jwt.git",
"reference": "48b0210c51718d682e53210c24d25c5a10a2299b"
"reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/48b0210c51718d682e53210c24d25c5a10a2299b",
"reference": "48b0210c51718d682e53210c24d25c5a10a2299b",
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/5dbc8959427416b8ee09a100d7a8588c00fb2e26",
"reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26",
"shasum": ""
},
"require": {
@ -1875,9 +1875,9 @@
],
"support": {
"issues": "https://github.com/firebase/php-jwt/issues",
"source": "https://github.com/firebase/php-jwt/tree/v6.8.0"
"source": "https://github.com/firebase/php-jwt/tree/v6.8.1"
},
"time": "2023-06-20T16:45:35+00:00"
"time": "2023-07-14T18:33:00+00:00"
},
{
"name": "fruitcake/laravel-cors",
@ -3069,16 +3069,16 @@
},
{
"name": "laravel/socialite",
"version": "v5.6.3",
"version": "v5.8.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/socialite.git",
"reference": "00ea7f8630673ea49304fc8a9fca5a64eb838c7e"
"reference": "50148edf24b6cd3e428aa9bc06a5d915b24376bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/socialite/zipball/00ea7f8630673ea49304fc8a9fca5a64eb838c7e",
"reference": "00ea7f8630673ea49304fc8a9fca5a64eb838c7e",
"url": "https://api.github.com/repos/laravel/socialite/zipball/50148edf24b6cd3e428aa9bc06a5d915b24376bb",
"reference": "50148edf24b6cd3e428aa9bc06a5d915b24376bb",
"shasum": ""
},
"require": {
@ -3135,7 +3135,7 @@
"issues": "https://github.com/laravel/socialite/issues",
"source": "https://github.com/laravel/socialite"
},
"time": "2023-06-06T13:42:43+00:00"
"time": "2023-07-14T14:22:58+00:00"
},
{
"name": "laravel/tinker",
@ -6793,16 +6793,16 @@
},
{
"name": "psy/psysh",
"version": "v0.11.18",
"version": "v0.11.19",
"source": {
"type": "git",
"url": "https://github.com/bobthecow/psysh.git",
"reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec"
"reference": "1724ceff278daeeac5a006744633bacbb2dc4706"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/4f00ee9e236fa6a48f4560d1300b9c961a70a7ec",
"reference": "4f00ee9e236fa6a48f4560d1300b9c961a70a7ec",
"url": "https://api.github.com/repos/bobthecow/psysh/zipball/1724ceff278daeeac5a006744633bacbb2dc4706",
"reference": "1724ceff278daeeac5a006744633bacbb2dc4706",
"shasum": ""
},
"require": {
@ -6863,9 +6863,9 @@
],
"support": {
"issues": "https://github.com/bobthecow/psysh/issues",
"source": "https://github.com/bobthecow/psysh/tree/v0.11.18"
"source": "https://github.com/bobthecow/psysh/tree/v0.11.19"
},
"time": "2023-05-23T02:31:11+00:00"
"time": "2023-07-15T19:42:19+00:00"
},
{
"name": "ralouphie/getallheaders",
@ -12783,16 +12783,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.21.1",
"version": "v3.22.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "229b55b3eae4729a8e2a321441ba40fcb3720b86"
"reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/229b55b3eae4729a8e2a321441ba40fcb3720b86",
"reference": "229b55b3eae4729a8e2a321441ba40fcb3720b86",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/92b019f6c8d79aa26349d0db7671d37440dc0ff3",
"reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3",
"shasum": ""
},
"require": {
@ -12802,7 +12802,7 @@
"doctrine/lexer": "^2 || ^3",
"ext-json": "*",
"ext-tokenizer": "*",
"php": "^8.0.1",
"php": "^7.4 || ^8.0",
"sebastian/diff": "^4.0 || ^5.0",
"symfony/console": "^5.4 || ^6.0",
"symfony/event-dispatcher": "^5.4 || ^6.0",
@ -12816,6 +12816,7 @@
"symfony/stopwatch": "^5.4 || ^6.0"
},
"require-dev": {
"facile-it/paraunit": "^1.3 || ^2.0",
"justinrainbow/json-schema": "^5.2",
"keradus/cli-executor": "^2.0",
"mikey179/vfsstream": "^1.6.11",
@ -12867,7 +12868,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.21.1"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.22.0"
},
"funding": [
{
@ -12875,7 +12876,7 @@
"type": "github"
}
],
"time": "2023-07-05T21:50:25+00:00"
"time": "2023-07-16T23:08:06+00:00"
},
{
"name": "hamcrest/hamcrest-php",
@ -13155,44 +13156,39 @@
},
{
"name": "mockery/mockery",
"version": "1.6.2",
"version": "1.6.3",
"source": {
"type": "git",
"url": "https://github.com/mockery/mockery.git",
"reference": "13a7fa2642c76c58fa2806ef7f565344c817a191"
"reference": "b1be135c1ba7632f0248e07ee5e6e412576a309d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mockery/mockery/zipball/13a7fa2642c76c58fa2806ef7f565344c817a191",
"reference": "13a7fa2642c76c58fa2806ef7f565344c817a191",
"url": "https://api.github.com/repos/mockery/mockery/zipball/b1be135c1ba7632f0248e07ee5e6e412576a309d",
"reference": "b1be135c1ba7632f0248e07ee5e6e412576a309d",
"shasum": ""
},
"require": {
"hamcrest/hamcrest-php": "^2.0.1",
"lib-pcre": ">=7.0",
"php": "^7.4 || ^8.0"
"php": ">=7.4,<8.3"
},
"conflict": {
"phpunit/phpunit": "<8.0"
},
"require-dev": {
"phpunit/phpunit": "^8.5 || ^9.3",
"psalm/plugin-phpunit": "^0.18",
"vimeo/psalm": "^5.9"
"psalm/plugin-phpunit": "^0.18.4",
"vimeo/psalm": "^5.13.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.6.x-dev"
}
},
"autoload": {
"files": [
"library/helpers.php",
"library/Mockery.php"
"src/helpers.php",
"src/Mockery.php"
],
"psr-4": {
"Mockery\\": "library/Mockery"
"Mockery\\": "src/Mockery"
}
},
"notification-url": "https://packagist.org/downloads/",
@ -13203,12 +13199,20 @@
{
"name": "Pádraic Brady",
"email": "padraic.brady@gmail.com",
"homepage": "http://blog.astrumfutura.com"
"homepage": "https://github.com/padraic",
"role": "Author"
},
{
"name": "Dave Marshall",
"email": "dave.marshall@atstsolutions.co.uk",
"homepage": "http://davedevelopment.co.uk"
"homepage": "https://davedevelopment.co.uk",
"role": "Developer"
},
{
"name": "Nathanael Esayeas",
"email": "nathanael.esayeas@protonmail.com",
"homepage": "https://github.com/ghostwriter",
"role": "Lead Developer"
}
],
"description": "Mockery is a simple yet flexible PHP mock object framework",
@ -13226,10 +13230,13 @@
"testing"
],
"support": {
"docs": "https://docs.mockery.io/",
"issues": "https://github.com/mockery/mockery/issues",
"source": "https://github.com/mockery/mockery/tree/1.6.2"
"rss": "https://github.com/mockery/mockery/releases.atom",
"security": "https://github.com/mockery/mockery/security/advisories",
"source": "https://github.com/mockery/mockery"
},
"time": "2023-06-07T09:07:52+00:00"
"time": "2023-07-18T17:47:29+00:00"
},
{
"name": "myclabs/deep-copy",

View file

@ -158,4 +158,20 @@ return [
'secure' => env('SECURE_COOKIES', false),
/*
|--------------------------------------------------------------------------
| Bootstrap Table Storage Type
|--------------------------------------------------------------------------
|
| Set the storage that this Bootstrap Table will use.
| Valid options are:
| - cookieStorage
| - localStorage: use this if you have a LOT of custom fields and are getting a REQUEST TOO LARGE error
| - sessionStorage
|
| More info: https://bootstrap-table.com/docs/extensions/cookie/#cookiestorage
*/
'bs_table_storage' => env('BS_TABLE_STORAGE', 'cookieStorage'),
];

View file

@ -424,4 +424,12 @@ class UserFactory extends Factory
});
}
public function canEditOwnLocation()
{
return $this->state(function () {
return [
'permissions' => '{"self.edit_location":"1"}',
];
});
}
}

View file

@ -0,0 +1,54 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddPhoneFaxToLocations extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('locations', function (Blueprint $table) {
$table->string('phone', 20)->after('zip')->nullable()->default(null);
$table->string('fax', 20)->after('zip')->nullable()->default(null);
});
Schema::table('companies', function (Blueprint $table) {
$table->string('phone', 20)->after('name')->nullable()->default(null);
$table->string('fax', 20)->after('name')->nullable()->default(null);
});
Schema::table('departments', function (Blueprint $table) {
$table->string('phone', 20)->after('name')->nullable()->default(null);
$table->string('fax', 20)->after('name')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('locations', function (Blueprint $table) {
$table->dropColumn('phone');
$table->dropColumn('fax');
});
Schema::table('companies', function (Blueprint $table) {
$table->dropColumn('phone');
$table->dropColumn('fax');
});
Schema::table('departments', function (Blueprint $table) {
$table->dropColumn('phone');
$table->dropColumn('fax');
});
}
}

View file

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

37
package-lock.json generated
View file

@ -6,7 +6,7 @@
"": {
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"acorn": "^8.8.2",
"acorn": "^8.9.0",
"acorn-import-assertions": "^1.9.0",
"admin-lte": "^2.4.18",
"ajv": "^6.12.6",
@ -15,7 +15,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.21.4",
"bootstrap-table": "1.22.0",
"chart.js": "^2.9.4",
"css-loader": "^4.0.0",
"ekko-lightbox": "^5.1.1",
@ -35,7 +35,7 @@
"tableexport.jquery.plugin": "1.27.0",
"tether": "^1.4.0",
"vue-resource": "^1.5.2",
"webpack": "^5.83.1"
"webpack": "^5.87.0"
},
"devDependencies": {
"axios": "^0.27.2",
@ -2460,8 +2460,9 @@
}
},
"node_modules/acorn": {
"version": "8.8.2",
"license": "MIT",
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
"integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
"bin": {
"acorn": "bin/acorn"
},
@ -3531,8 +3532,9 @@
"license": "MIT"
},
"node_modules/bootstrap-table": {
"version": "1.21.4",
"license": "MIT",
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.22.0.tgz",
"integrity": "sha512-N1MLgPcIOa9cfwr7CaoLOekKJ9nHq/z8lk6LsC3mLUZq77VeMC/vTh+EqN7+iT8JADmoAsX7RqQbYfVxF9ZCig==",
"peerDependencies": {
"jquery": "3"
}
@ -5195,9 +5197,9 @@
}
},
"node_modules/enhanced-resolve": {
"version": "5.14.1",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz",
"integrity": "sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==",
"version": "5.15.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
"integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@ -10940,9 +10942,9 @@
}
},
"node_modules/webpack": {
"version": "5.86.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.86.0.tgz",
"integrity": "sha512-3BOvworZ8SO/D4GVP+GoRC3fVeg5MO4vzmq8TJJEkdmopxyazGDxN8ClqN12uzrZW9Tv8EED8v5VSb6Sqyi0pg==",
"version": "5.88.2",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
"integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
@ -10953,7 +10955,7 @@
"acorn-import-assertions": "^1.9.0",
"browserslist": "^4.14.5",
"chrome-trace-event": "^1.0.2",
"enhanced-resolve": "^5.14.1",
"enhanced-resolve": "^5.15.0",
"es-module-lexer": "^1.2.1",
"eslint-scope": "5.1.1",
"events": "^3.2.0",
@ -10963,7 +10965,7 @@
"loader-runner": "^4.2.0",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^3.1.2",
"schema-utils": "^3.2.0",
"tapable": "^2.1.1",
"terser-webpack-plugin": "^5.3.7",
"watchpack": "^2.4.0",
@ -11267,8 +11269,9 @@
}
},
"node_modules/webpack/node_modules/schema-utils": {
"version": "3.1.2",
"license": "MIT",
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
"integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",

View file

@ -25,7 +25,7 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"acorn": "^8.8.2",
"acorn": "^8.9.0",
"acorn-import-assertions": "^1.9.0",
"admin-lte": "^2.4.18",
"ajv": "^6.12.6",
@ -34,7 +34,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.21.4",
"bootstrap-table": "1.22.0",
"chart.js": "^2.9.4",
"css-loader": "^4.0.0",
"ekko-lightbox": "^5.1.1",
@ -54,6 +54,6 @@
"tableexport.jquery.plugin": "1.27.0",
"tether": "^1.4.0",
"vue-resource": "^1.5.2",
"webpack": "^5.83.1"
"webpack": "^5.87.0"
}
}

View file

@ -1,4 +1,5 @@
{
<<<<<<< HEAD
"/js/build/app.js": "/js/build/app.js?id=43fc984e5d0f901e04cef2474972e97f",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=392cc93cfc0be0349bab9697669dd091",
"/css/build/overrides.css": "/css/build/overrides.css?id=eb013ebb79d92e25ce24b0c0b53185e4",
@ -19,6 +20,28 @@
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=f0fbbb0ac729ea092578fb05ca615460",
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=b9a74ec0cd68f83e7480d5ae39919beb",
"/css/dist/all.css": "/css/dist/all.css?id=15ac70d1eb588ad379df3e1911523048",
=======
"/js/build/app.js": "/js/build/app.js?id=82ddaa718cced6fb0be6e8db6f16a0c0",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
"/css/build/overrides.css": "/css/build/overrides.css?id=5166569ede5a36802eadeea982686ca6",
"/css/build/app.css": "/css/build/app.css?id=b612c48e78fece2e1e8042ae24cc5f1e",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=dc383f8560a8d4adb51d44fb4043e03b",
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=e6e53eef152bba01a4c666a4d8b01117",
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=07273f6ca3c698a39e8fc2075af4fa07",
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=c1f33574ecb9d3e69d9b8fe5bd68e101",
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=7d92dea45d94be7e1d4e427c728d335d",
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=6fe68325d5356197672c27bc77cedcb4",
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=8ca888bbc050d9680cbb65021382acba",
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=bdfc704731682c67645a2248b0b8d2d7",
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb",
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=e36e83c2aa3c3afdbb8ebe2c0309e91d",
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=da6c7997d9de2f8329142399f0ce50da",
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898",
"/css/dist/all.css": "/css/dist/all.css?id=ae5d0ce9886bbe4ad4b021c6be19ec36",
>>>>>>> develop
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/css/webfonts/fa-brands-400.ttf": "/css/webfonts/fa-brands-400.ttf?id=e2e2b1797606a266ed55549f5bb5a179",
@ -29,6 +52,7 @@
"/css/webfonts/fa-solid-900.woff2": "/css/webfonts/fa-solid-900.woff2?id=eea38615e7b5dbbaf88c263f2230cc32",
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=6ebbf5afc34f54463abc2b81ca637364",
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=67b8a78b7e80e805cfa4ee0421895ba4",
<<<<<<< HEAD
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=2265e072e44c782c901dce8e037d97fc",
"/js/build/vendor.js": "/js/build/vendor.js?id=8ac1d250496313e93744790e5138305d",
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=a0e44dba789031b34ef150a01318b865",
@ -48,4 +72,25 @@
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=268041e902b019730c23ee3875838005",
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=d409d9b1a3b69247df8b98941ba06e33",
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=f0fbbb0ac729ea092578fb05ca615460"
=======
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=f5935cf8eaf9c1f71da0c9245d730471",
"/js/build/vendor.js": "/js/build/vendor.js?id=3592e07ae9a6d1805a4ea3bd3c034aef",
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=40e2dc8b5b29e244bb545f78e2a3242b",
"/js/dist/all.js": "/js/dist/all.js?id=ba07d399f23b294f7c4983030b757423",
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=e36e83c2aa3c3afdbb8ebe2c0309e91d",
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb",
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=bdfc704731682c67645a2248b0b8d2d7",
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=f677207c6cf9678eb539abecb408c374",
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=07273f6ca3c698a39e8fc2075af4fa07",
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=c1f33574ecb9d3e69d9b8fe5bd68e101",
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=44bf834f2110504a793dadec132a5898",
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=8ca888bbc050d9680cbb65021382acba",
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=6fe68325d5356197672c27bc77cedcb4",
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=7d92dea45d94be7e1d4e427c728d335d",
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=e6e53eef152bba01a4c666a4d8b01117",
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=da6c7997d9de2f8329142399f0ce50da"
>>>>>>> develop
}

View file

@ -51,4 +51,7 @@ return [
'display_in_user_view_table' => 'Visible to User',
'auto_add_to_fieldsets' => 'Automatically add this to every new fieldset',
'add_to_preexisting_fieldsets' => 'Add to any existing fieldsets',
'show_in_listview' => 'Show in list views by default. Authorized users will still be able to show/hide via the column selector.',
'show_in_listview_short' => 'Show in lists',
];

View file

@ -45,4 +45,5 @@ return [
'alert_details' => 'Please see below for details.',
'custom_export' => 'Custom Export',
'mfg_warranty_lookup' => ':manufacturer Warranty Status Lookup',
'user_department' => 'User Department',
];

View file

@ -413,7 +413,7 @@ return [
'integration_option' => 'Integration Option',
'log_does_not_exist' => 'No matching log record exists.',
'merge_users' => 'Merge Users',
'merge_information' => 'This will merge the :count users into a single user. Select the user you wish to merge the others into below, and the associated assets, licences, etc will be moved over to the selected user and the other users will be marked as deleted.',
'merge_information' => 'This will merge the :count users into a single user. Select the user you wish to merge the others into below, and the associated assets, licenses, etc will be moved over to the selected user and the other users will be marked as deleted.',
'warning_merge_information' => 'This action CANNOT be undone and should ONLY be used when you need to merge users because of a bad import or sync. Be sure to run a backup first.',
'no_users_selected' => 'No users selected',
'not_enough_users_selected' => 'At least :count users must be selected',

View file

@ -287,7 +287,7 @@
</strong>
</div>
<div class="col-md-9">
{!! nl2br(e($accessory->notes)) !!}
{!! nl2br(Helper::parseEscapedMarkedownInline($accessory->notes)) !!}
</div>
</div>

View file

@ -93,7 +93,7 @@ use Carbon\Carbon;
<div class="row">
<div class="col-md-12 col-sm-12" style="padding-bottom: 10px; margin-left: 15px; word-wrap: break-word;">
<strong>{{ trans('admin/asset_maintenances/form.notes') }}: </strong>
{{ $assetMaintenance->notes }}
{!! nl2br(Helper::parseEscapedMarkedownInline($assetMaintenance->notes)) !!}
</div>
</div>
<!-- 5th Row End -->

View file

@ -9,6 +9,8 @@
{{-- Page content --}}
@section('inputFields')
@include ('partials.forms.edit.name', ['translated_name' => trans('admin/companies/table.name')])
@include ('partials.forms.edit.phone')
@include ('partials.forms.edit.fax')
@include ('partials.forms.edit.image-upload', ['image_path' => app('companies_upload_path')])
@stop

View file

@ -155,7 +155,7 @@
<td>
@if ($file->note)
{{ $file->note }}
{!! nl2br(Helper::parseEscapedMarkedownInline($file->note)) !!}
@endif
</td>
<td>
@ -275,7 +275,7 @@
</strong>
</div>
<div class="col-md-12">
{!! nl2br(e($consumable->notes)) !!}
{!! nl2br(Helper::parseEscapedMarkedownInline($consumable->notes)) !!}
</div>
</div>
@endif

View file

@ -118,6 +118,8 @@
</div>
</div>
<!-- Auto-Add to Future Fieldsets -->
<div class="form-group {{ $errors->has('auto_add_to_fieldsets') ? ' has-error' : '' }}" id="auto_add_to_fieldsets">
<div class="col-md-9 col-md-offset-3">
@ -127,6 +129,13 @@
</label>
</div>
<div class="col-md-9 col-md-offset-3">
<label class="form-control">
<input type="checkbox" name="show_in_listview" aria-label="show_in_listview" value="1"{{ (old('show_in_listview') || $field->show_in_listview) ? ' checked="checked"' : '' }}>
{{ trans('admin/custom_fields/general.show_in_listview') }}
</label>
</div>
@if (!$field->id)
<!-- Encrypted -->
<div class="col-md-9 col-md-offset-3">

View file

@ -145,6 +145,9 @@
<th data-sortable="true"><i class="fa fa-lock" aria-hidden="true"></i>
<span class="hidden-xs hidden-sm hidden-md hidden-lg">{{ trans('admin/custom_fields/general.encrypted') }}</span>
</th>
<th data-sortable="true"><i class="fa fa-list" aria-hidden="true"></i>
<span class="hidden-xs hidden-sm hidden-md hidden-lg">{{ trans('admin/custom_fields/general.show_in_listview_short') }}</span>
</th>
<th data-visible="false" data-sortable="true"><i class="fa fa-eye" aria-hidden="true"><span class="sr-only">Visible to User</span></i></th>
<th data-sortable="true" data-searchable="true"><i class="fa fa-envelope" aria-hidden="true"><span class="sr-only">Show in Email</span></i></th>
<th data-sortable="true" data-searchable="true">{{ trans('admin/custom_fields/general.field_element_short') }}</th>
@ -168,6 +171,7 @@
</td>
<td>{{ $field->format }}</td>
<td>{!! ($field->field_encrypted=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
<td>{!! ($field->show_in_listview=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
<td>{!! ($field->display_in_user_view=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
<td class='text-center'>{!! ($field->show_in_email=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
<td>{{ $field->element }}</td>

View file

@ -16,6 +16,9 @@
<input id="hidden_company_id" type="hidden" name="company_id" value="{{ Auth::user()->company_id }}">
@endif
@include ('partials.forms.edit.phone')
@include ('partials.forms.edit.fax')
<!-- Manager -->
@include ('partials.forms.edit.user-select', ['translated_name' => trans('admin/users/table.manager'), 'fieldname' => 'manager_id'])

View file

@ -73,7 +73,7 @@
</div>
</div>
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id', 'help_text' => ($asset->defaultLoc) ? 'You can choose to check this asset in to a location other than the default location of '.$asset->defaultLoc->name.' if one is set.' : null])
@include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id', 'help_text' => ($asset->defaultLoc) ? 'You can choose to check this asset in to a location other than the default location of '.$asset->defaultLoc->name.' if one is set.' : null, 'hide_location_radio' => true])
<!-- Checkout/Checkin Date -->
<div class="form-group{{ $errors->has('checkin_at') ? ' has-error' : '' }}">

View file

@ -52,7 +52,7 @@ $qr_size = ($settings->alt_barcode_enabled=='1') && ($settings->alt_barcode!='')
}
img.barcode {
display:block;
margin-top:-14px;
margin-top:{{$settings->qr_code=='1' ? '-15px' : '-7px;'}};
width: 100%;
}
div.label-logo {

View file

@ -89,7 +89,7 @@
@endif
</td>
<td>
@if ($request->requestingUser())
@if ($request->requestingUser() && !$request->requestingUser()->trashed())
<a href="{{ config('app.url') }}/users/{{ $request->requestingUser()->id }}">
{{ $request->requestingUser()->present()->fullName() }}
</a>

View file

@ -342,8 +342,9 @@
@if (($asset->model) && ($asset->model->manufacturer->url))
<li>
<i class="fas fa-globe-americas" aria-hidden="true"></i>
<a href="{{ $asset->model->manufacturer->url }}">
<a href="{{ $asset->model->manufacturer->url }}" target="_blank">
{{ $asset->model->manufacturer->url }}
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
</li>
@endif
@ -351,8 +352,19 @@
@if (($asset->model) && ($asset->model->manufacturer->support_url))
<li>
<i class="far fa-life-ring" aria-hidden="true"></i>
<a href="{{ $asset->model->manufacturer->support_url }}">
<a href="{{ $asset->model->manufacturer->support_url }}" target="_blank">
{{ $asset->model->manufacturer->support_url }}
<i class="fa fa-external-link" aria-hidden="true"></i>
</a>
</li>
@endif
@if (($asset->model->manufacturer) && ($asset->model->manufacturer->warranty_lookup_url!=''))
<li>
<i class="far fa-wrench" aria-hidden="true"></i>
<a href="{{ $asset->present()->dynamicWarrantyUrl() }}" target="_blank">
{{ $asset->present()->dynamicWarrantyUrl() }}
<i class="fa fa-external-link" aria-hidden="true"><span class="sr-only">{{ trans('admin/hardware/general.mfg_warranty_lookup', ['manufacturer' => $asset->model->manufacturer->name]) }}</span></i>
</a>
</li>
@endif
@ -730,7 +742,7 @@
</strong>
</div>
<div class="col-md-6">
{!! nl2br(e($asset->notes)) !!}
{!! nl2br(Helper::parseEscapedMarkedownInline($asset->notes)) !!}
</div>
</div>
@ -919,6 +931,10 @@
</li>
@endif
@if((isset($asset->assignedTo)) && ($asset->assignedTo->department))
<li>{{ trans('admin/hardware/general.user_department') }}: {{ $asset->assignedTo->department->name}}</li>
@endif
@if (isset($asset->location))
<li>{{ $asset->location->name }}</li>
<li>{{ $asset->location->address }}

View file

@ -357,7 +357,7 @@
</strong>
</div>
<div class="col-md-9">
{!! nl2br(e($license->notes)) !!}
{!! nl2br(Helper::parseEscapedMarkedownInline($license->notes)) !!}
</div>
</div>
@endif

View file

@ -17,6 +17,9 @@
<!-- Manager-->
@include ('partials.forms.edit.user-select', ['translated_name' => trans('admin/users/table.manager'), 'fieldname' => 'manager_id'])
@include ('partials.forms.edit.phone')
@include ('partials.forms.edit.fax')
<!-- Currency -->
<div class="form-group {{ $errors->has('currency') ? ' has-error' : '' }}">
<label for="currency" class="col-md-3 control-label">

View file

@ -55,6 +55,7 @@
stickyHeaderOffsetY: stickyHeaderOffsetY + 'px',
undefinedText: '',
iconsPrefix: 'fa',
cookieStorage: '{{ config('session.bs_table_storage') }}',
cookie: true,
cookieExpire: '2y',
mobileResponsive: true,

View file

@ -0,0 +1,7 @@
<div class="form-group {{ $errors->has('fax') ? ' has-error' : '' }}">
{{ Form::label('fax', trans('admin/suppliers/table.fax'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7">
{{Form::text('fax', old('fax', $item->fax), array('class' => 'form-control')) }}
{!! $errors->first('fax', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View file

@ -30,6 +30,21 @@
</div>
@endif
@if (isset($hide_location_radio))
<!-- Update actual location -->
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<label class="form-control">
{{ Form::radio('update_default_location', '1', old('update_default_location'), ['checked'=> 'checked', 'aria-label'=>'update_default_location']) }}
{{ trans('admin/hardware/form.asset_location') }}
</label>
<label class="form-control">
{{ Form::radio('update_default_location', '0', old('update_default_location'), ['aria-label'=>'update_default_location']) }}
{{ trans('admin/hardware/form.asset_location_update_default_current') }}
</label>
</div>
</div> <!--/form-group-->
@endif
</div>

View file

@ -22,15 +22,7 @@
</div>
@include ('partials.forms.edit.phone')
<div class="form-group {{ $errors->has('fax') ? ' has-error' : '' }}">
{{ Form::label('fax', trans('admin/suppliers/table.fax'), array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7">
{{Form::text('fax', old('fax', $item->fax), array('class' => 'form-control')) }}
{!! $errors->first('fax', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>
@include ('partials.forms.edit.fax')
@include ('partials.forms.edit.email')
<div class="form-group {{ $errors->has('url') ? ' has-error' : '' }}">

View file

@ -338,7 +338,7 @@
@endif
@if ($supplier->notes!='')
<li><i class="fa fa-comment"></i> {{ $supplier->notes }}</li>
<li><i class="fa fa-comment"></i> {!! nl2br(Helper::parseEscapedMarkedownInline($supplier->notes)) !!}</li>
@endif
</ul>

View file

@ -633,7 +633,7 @@
{{ trans('admin/users/table.notes') }}
</div>
<div class="col-md-9">
{{ $user->notes }}
{!! nl2br(Helper::parseEscapedMarkedownInline($user->notes)) !!}
</div>
</div>

View file

@ -7,6 +7,7 @@ use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\TestCase as BaseTestCase;
use RuntimeException;
abstract class DuskTestCase extends BaseTestCase
{
@ -21,6 +22,12 @@ abstract class DuskTestCase extends BaseTestCase
*/
public static function prepare()
{
if (!file_exists(realpath(__DIR__ . '/../') . '/.env.dusk.local')) {
throw new RuntimeException(
'.env.dusk.local file does not exist. Aborting to avoid wiping your local database'
);
}
if (! static::runningInSail()) {
static::startChromeDriver();
}

View file

@ -0,0 +1,48 @@
<?php
namespace Tests\Feature\Api\Locations;
use App\Models\Location;
use App\Models\User;
use Illuminate\Testing\Fluent\AssertableJson;
use Tests\Support\InteractsWithSettings;
use Tests\TestCase;
class LocationsForSelectListTest extends TestCase
{
use InteractsWithSettings;
public function testGettingLocationListRequiresProperPermission()
{
$this->actingAsForApi(User::factory()->create())
->getJson(route('api.locations.selectlist'))
->assertForbidden();
}
public function testLocationsReturned()
{
Location::factory()->create();
// see the where the "view.selectlists" is defined in the AuthServiceProvider
// for info on why "createUsers()" is used here.
$this->actingAsForApi(User::factory()->createUsers()->create())
->getJson(route('api.locations.selectlist'))
->assertOk()
->assertJsonStructure([
'results',
'pagination',
'total_count',
'page',
'page_count',
])
->assertJson(fn(AssertableJson $json) => $json->has('results', 1)->etc());
}
public function testLocationsAreReturnedWhenUserIsUpdatingTheirProfileAndHasPermissionToUpdateLocation()
{
$this->actingAsForApi(User::factory()->canEditOwnLocation()->create())
->withHeader('referer', route('profile'))
->getJson(route('api.locations.selectlist'))
->assertOk();
}
}

View file

@ -25,4 +25,62 @@ class UsersSearchTest extends TestCase
$this->assertTrue($results->pluck('name')->contains(fn($text) => str_contains($text, 'Luke')));
$this->assertFalse($results->pluck('name')->contains(fn($text) => str_contains($text, 'Darth')));
}
public function testResultsWhenSearchingForActiveUsers()
{
User::factory()->create(['first_name' => 'Active', 'last_name' => 'User']);
User::factory()->create(['first_name' => 'Deleted', 'last_name' => 'User'])->delete();
$response = $this->actingAsForApi(User::factory()->viewUsers()->create())
->getJson(route('api.users.index', [
'deleted' => 'false',
'company_id' => '',
'search' => 'user',
'order' => 'asc',
'offset' => '0',
'limit' => '20',
]))
->assertOk();
$firstNames = collect($response->json('rows'))->pluck('first_name');
$this->assertTrue(
$firstNames->contains('Active'),
'Expected user does not appear in results'
);
$this->assertFalse(
$firstNames->contains('Deleted'),
'Unexpected deleted user appears in results'
);
}
public function testResultsWhenSearchingForDeletedUsers()
{
User::factory()->create(['first_name' => 'Active', 'last_name' => 'User']);
User::factory()->create(['first_name' => 'Deleted', 'last_name' => 'User'])->delete();
$response = $this->actingAsForApi(User::factory()->viewUsers()->create())
->getJson(route('api.users.index', [
'deleted' => 'true',
'company_id' => '',
'search' => 'user',
'order' => 'asc',
'offset' => '0',
'limit' => '20',
]))
->assertOk();
$firstNames = collect($response->json('rows'))->pluck('first_name');
$this->assertFalse(
$firstNames->contains('Active'),
'Unexpected active user appears in results'
);
$this->assertTrue(
$firstNames->contains('Deleted'),
'Expected deleted user does not appear in results'
);
}
}

View file

@ -56,6 +56,17 @@ class Settings
]);
}
public function enableAutoIncrement(): Settings
{
return $this->update([
'auto_increment_assets' => 1,
'auto_increment_prefix' => 'ABCD',
'next_auto_tag_base' => '123',
'zerofill_count' => 5
]);
}
/**
* @param array $attributes Attributes to modify in the application's settings.
*/

View file

@ -5,6 +5,7 @@ namespace Tests;
use App\Http\Middleware\SecurityHeaders;
use Illuminate\Foundation\Testing\LazilyRefreshDatabase;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use RuntimeException;
use Tests\Support\CustomTestMacros;
use Tests\Support\InteractsWithAuthentication;
use Tests\Support\InteractsWithSettings;
@ -22,6 +23,12 @@ abstract class TestCase extends BaseTestCase
protected function setUp(): void
{
if (!file_exists(realpath(__DIR__ . '/../') . '/.env.testing')) {
throw new RuntimeException(
'.env.testing file does not exist. Aborting to avoid wiping your local database'
);
}
parent::setUp();
$this->withoutMiddleware($this->globallyDisabledMiddleware);

View file

@ -12,23 +12,130 @@ class AssetTest extends TestCase
{
use InteractsWithSettings;
// public function testAutoIncrementMixed()
// {
// $expected = '123411';
// $next = Asset::nextAutoIncrement(
// collect([
// ['asset_tag' => '0012345'],
// ['asset_tag' => 'WTF00134'],
// ['asset_tag' => 'WTF-745'],
// ['asset_tag' => '0012346'],
// ['asset_tag' => '00123410'],
// ['asset_tag' => 'U8T7597h77'],
// ])
// );
public function testAutoIncrement()
{
$this->settings->enableAutoIncrement();
// \Log::debug('Next: '.$next);
// $this->assertEquals($expected, $next);
// }
$a = Asset::factory()->create(['asset_tag' => Asset::autoincrement_asset() ]);
$b = Asset::factory()->create(['asset_tag' => Asset::autoincrement_asset() ]);
$this->assertModelExists($a);
$this->assertModelExists($b);
}
public function testAutoIncrementCollision()
{
$this->settings->enableAutoIncrement();
// we have to do this by hand to 'simulate' two web pages being open at the same time
$a = Asset::factory()->make(['asset_tag' => Asset::autoincrement_asset() ]);
$b = Asset::factory()->make(['asset_tag' => Asset::autoincrement_asset() ]);
$this->assertTrue($a->save());
$this->assertFalse($b->save());
}
public function testAutoIncrementDouble()
{
// make one asset with the autoincrement *ONE* higher than the next auto-increment
// make sure you can then still make another
$this->settings->enableAutoIncrement();
$gap_number = Asset::autoincrement_asset(1);
$final_number = Asset::autoincrement_asset(2);
$a = Asset::factory()->make(['asset_tag' => $gap_number]); //make an asset with an ID that is one *over* the next increment
$b = Asset::factory()->make(['asset_tag' => Asset::autoincrement_asset()]); //but also make one with one that is *at* the next increment
$this->assertTrue($a->save());
$this->assertTrue($b->save());
//and ensure a final asset ends up at *two* over what would've been the next increment at the start
$c = Asset::factory()->make(['asset_tag' => Asset::autoincrement_asset()]);
$this->assertTrue($c->save());
$this->assertEquals($c->asset_tag, $final_number);
}
public function testAutoIncrementGapAndBackfill()
{
// make one asset 3 higher than the next auto-increment
// manually make one that's 1 lower than that
// make sure the next one is one higher than the 3 higher one.
$this->settings->enableAutoIncrement();
$big_gap = Asset::autoincrement_asset(3);
$final_result = Asset::autoincrement_asset(4);
$backfill_one = Asset::autoincrement_asset(0);
$backfill_two = Asset::autoincrement_asset(1);
$backfill_three = Asset::autoincrement_asset(2);
$a = Asset::factory()->create(['asset_tag' => $big_gap]);
$this->assertModelExists($a);
$b = Asset::factory()->create(['asset_tag' => $backfill_one]);
$this->assertModelExists($b);
$c = Asset::factory()->create(['asset_tag' => $backfill_two]);
$this->assertModelExists($c);
$d = Asset::factory()->create(['asset_tag' => $backfill_three]);
$this->assertModelExists($d);
$final = Asset::factory()->create(['asset_tag' => Asset::autoincrement_asset()]);
$this->assertModelExists($final);
$this->assertEquals($final->asset_tag, $final_result);
}
public function testPrefixlessAutoincrementBackfill()
{
// TODO: COPYPASTA FROM above, is there a way to still run this test but not have it be so duplicative?
$this->settings->enableAutoIncrement()->set(['auto_increment_prefix' => '']);
$big_gap = Asset::autoincrement_asset(3);
$final_result = Asset::autoincrement_asset(4);
$backfill_one = Asset::autoincrement_asset(0);
$backfill_two = Asset::autoincrement_asset(1);
$backfill_three = Asset::autoincrement_asset(2);
$a = Asset::factory()->create(['asset_tag' => $big_gap]);
$this->assertModelExists($a);
$b = Asset::factory()->create(['asset_tag' => $backfill_one]);
$this->assertModelExists($b);
$c = Asset::factory()->create(['asset_tag' => $backfill_two]);
$this->assertModelExists($c);
$d = Asset::factory()->create(['asset_tag' => $backfill_three]);
$this->assertModelExists($d);
$final = Asset::factory()->create(['asset_tag' => Asset::autoincrement_asset()]);
$this->assertModelExists($final);
$this->assertEquals($final->asset_tag, $final_result);
}
public function testUnzerofilledPrefixlessAutoincrementBackfill()
{
// TODO: COPYPASTA FROM above (AGAIN), is there a way to still run this test but not have it be so duplicative?
$this->settings->enableAutoIncrement()->set(['auto_increment_prefix' => '','zerofill_count' => 0]);
$big_gap = Asset::autoincrement_asset(3);
$final_result = Asset::autoincrement_asset(4);
$backfill_one = Asset::autoincrement_asset(0);
$backfill_two = Asset::autoincrement_asset(1);
$backfill_three = Asset::autoincrement_asset(2);
$a = Asset::factory()->create(['asset_tag' => $big_gap]);
$this->assertModelExists($a);
$b = Asset::factory()->create(['asset_tag' => $backfill_one]);
$this->assertModelExists($b);
$c = Asset::factory()->create(['asset_tag' => $backfill_two]);
$this->assertModelExists($c);
$d = Asset::factory()->create(['asset_tag' => $backfill_three]);
$this->assertModelExists($d);
$final = Asset::factory()->create(['asset_tag' => Asset::autoincrement_asset()]);
$this->assertModelExists($final);
$this->assertEquals($final->asset_tag, $final_result);
}
public function testWarrantyExpiresAttribute()
{