Merge pull request #15714 from akemidx/saving_custom_report_template

Saved Custom Report Templates
This commit is contained in:
snipe 2024-12-19 22:43:59 +00:00 committed by GitHub
commit 15296d2b1c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 1581 additions and 200 deletions

View file

@ -0,0 +1,80 @@
<?php
namespace App\Http\Controllers;
use App\Models\CustomField;
use App\Models\ReportTemplate;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
class ReportTemplatesController extends Controller
{
public function store(Request $request): RedirectResponse
{
$this->authorize('reports.view');
// Ignore "options" rules since data does not come in under that key...
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options'));
$report = $request->user()->reportTemplates()->create([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
]);
session()->flash('success', trans('admin/reports/message.create.success'));
return redirect()->route('report-templates.show', $report->id);
}
public function show(ReportTemplate $reportTemplate)
{
$this->authorize('reports.view');
$customfields = CustomField::get();
$report_templates = ReportTemplate::orderBy('name')->get();
return view('reports/custom', [
'customfields' => $customfields,
'report_templates' => $report_templates,
'template' => $reportTemplate,
]);
}
public function edit(ReportTemplate $reportTemplate)
{
$this->authorize('reports.view');
return view('reports/custom', [
'customfields' => CustomField::get(),
'template' => $reportTemplate,
]);
}
public function update(Request $request, ReportTemplate $reportTemplate): RedirectResponse
{
$this->authorize('reports.view');
// Ignore "options" rules since data does not come in under that key...
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options'));
$reportTemplate->update([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
]);
session()->flash('success', trans('admin/reports/message.update.success'));
return redirect()->route('report-templates.show', $reportTemplate->id);
}
public function destroy(ReportTemplate $reportTemplate): RedirectResponse
{
$this->authorize('reports.view');
$reportTemplate->delete();
return redirect()->route('reports/custom')
->with('success', trans('admin/reports/message.delete.success'));
}
}

View file

@ -14,6 +14,7 @@ use App\Models\CheckoutAcceptance;
use App\Models\CustomField;
use App\Models\Depreciation;
use App\Models\License;
use App\Models\ReportTemplate;
use App\Models\Setting;
use App\Notifications\CheckoutAssetNotification;
use Carbon\Carbon;
@ -394,12 +395,27 @@ class ReportsController extends Controller
* @see ReportsController::postCustomReport() method that generates the CSV
* @since [v1.0]
*/
public function getCustomReport() : View
public function getCustomReport(Request $request) : View
{
$this->authorize('reports.view');
$customfields = CustomField::get();
$report_templates = ReportTemplate::orderBy('name')->get();
return view('reports/custom')->with('customfields', $customfields);
// The view needs a template to render correctly, even if it is empty...
$template = new ReportTemplate;
// Set the report's input values in the cases we were redirected back
// with validation errors so the report is populated as expected.
if ($request->old()) {
$template->name = $request->old('name');
$template->options = $request->old();
}
return view('reports/custom', [
'customfields' => $customfields,
'report_templates' => $report_templates,
'template' => $template,
]);
}
/**

View file

@ -0,0 +1,241 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class ReportTemplate extends Model
{
use HasFactory;
use SoftDeletes;
use ValidatingTrait;
protected $casts = [
'options' => 'array',
];
protected $fillable = [
'created_by',
'name',
'options',
];
protected $rules = [
'name' => [
'required',
'string',
],
'options' => [
'required',
'array',
],
];
protected static function booted()
{
// Scope to current user
static::addGlobalScope('current_user', function (Builder $builder) {
if (auth()->check()) {
$builder->where('created_by', auth()->id());
}
});
static::created(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('create');
});
static::updated(function (ReportTemplate $reportTemplate) {
$changed = [];
foreach ($reportTemplate->getDirty() as $key => $value) {
$changed[$key] = [
'old' => $reportTemplate->getOriginal($key),
'new' => $reportTemplate->getAttribute($key),
];
}
$logAction = new Actionlog();
$logAction->item_type = ReportTemplate::class;
$logAction->item_id = $reportTemplate->id;
$logAction->created_by = auth()->id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
});
static::deleted(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('delete');
});
}
/**
* Establishes the report template -> creator relationship.
*
*/
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* Get the value of a checkbox field for the given field name.
*
* @param string $fieldName
* @param string $fallbackValue The value to return if the report template is not saved yet.
*
*/
public function checkmarkValue(string $fieldName, string $fallbackValue = '1'): string
{
// Assuming we're using the null object pattern, and an empty model
// was passed to the view when showing the default report page,
// return the fallback value so that checkboxes are checked by default.
if (is_null($this->id)) {
return $fallbackValue;
}
// If the model does exist then return the value of the field
// or return 0 so the checkbox is unchecked.
// Falling back to 0 here is because checkboxes are not sent
// in the request when unchecked so they are not
// actually saved in the model's options.
return $this->options[$fieldName] ?? '0';
}
/**
* Get the value of a radio field for the given field name.
*
* @param string $fieldName
* @param string $value The value to check against.
* @param bool $isDefault Whether the radio input being checked is the default.
*
*/
public function radioValue(string $fieldName, string $value, bool $isDefault = false): bool
{
$fieldExists = array_has($this->options, $fieldName);
// If the field doesn't exist but the radio input
// being checked is the default then return true.
if (!$fieldExists && $isDefault) {
return true;
}
// If the field exists and matches what we're checking then return true.
if ($fieldExists && $this->options[$fieldName] === $value) {
return true;
}
// Otherwise return false.
return false;
}
/**
* Get the value of a select field for the given field name.
*
* @param string $fieldName
* @param string|null $model The Eloquent model to check against.
*
* @return mixed|null
*
*/
public function selectValue(string $fieldName, string $model = null)
{
// If the field does not exist then return null.
if (!isset($this->options[$fieldName])) {
return null;
}
$value = $this->options[$fieldName];
// If the value was stored as an array, most likely
// due to a previously being a multi-select,
// then return the first value.
if (is_array($value)) {
$value = $value[0];
}
// If a model is provided then we should ensure we only return
// the value if the model still exists.
// Note: It is possible $value is an id that no longer exists and this will return null.
if ($model) {
$foundModel = $model::find($value);
return $foundModel ? $foundModel->id : null;
}
return $value;
}
/**
* Get the values of a multi-select field for the given field name.
*
* @param string $fieldName
* @param string|null $model The Eloquent model to check against.
*
* @return iterable
*
*/
public function selectValues(string $fieldName, string $model = null): iterable
{
// If the field does not exist then return an empty array.
if (!isset($this->options[$fieldName])) {
return [];
}
// If a model is provided then we should ensure we only return
// the ids of models that exist and are not deleted.
if ($model) {
return $model::findMany($this->options[$fieldName])->pluck('id');
}
// Wrap the value in an array if needed. This is to ensure
// values previously stored as a single value,
// most likely from a single select, are returned as an array.
if (!is_array($this->options[$fieldName])) {
return [$this->options[$fieldName]];
}
return $this->options[$fieldName];
}
/**
* Get the value of a text field for the given field name.
*
* @param string $fieldName
* @param string|null $fallbackValue
*
* @return string
*/
public function textValue(string $fieldName, string|null $fallbackValue = ''): string
{
// Assuming we're using the null object pattern,
// return the default value if the object is not saved yet.
if (is_null($this->id)) {
return (string) $fallbackValue;
}
// Return the field's value if it exists
// and return the default value if not.
return $this->options[$fieldName] ?? '';
}
public function getDisplayNameAttribute()
{
return $this->name;
}
}

View file

@ -13,6 +13,7 @@ use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Notifications\Notifiable;
@ -361,6 +362,15 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return $this->belongsToMany(\App\Models\License::class, 'license_seats', 'assigned_to', 'license_id')->withPivot('id', 'created_at', 'updated_at');
}
/**
* Establishes the user -> reportTemplates relationship
*
*/
public function reportTemplates(): HasMany
{
return $this->hasMany(ReportTemplate::class, 'created_by');
}
/**
* Establishes a count of all items assigned
*

View file

@ -0,0 +1,25 @@
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ReportTemplateFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->word(),
'options' => [
'id' => '1',
],
'created_by' => User::factory(),
];
}
}

View file

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateReportTemplatesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('report_templates', function (Blueprint $table) {
$table->id();
$table->integer('created_by')->nullable();
$table->string('name');
$table->json('options');
$table->softDeletes();
$table->timestamps();
$table->index('created_by');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('report_templates');
}
}

View file

@ -13,5 +13,10 @@ return [
'user_state' => 'User State',
'user_country' => 'User Country',
'user_zip' => 'User Zip'
]
],
'open_saved_template' => 'Open Saved Template',
'save_template' => 'Save Template',
'select_a_template' => 'Select a Template',
'template_name' => 'Template Name',
'update_template' => 'Update Template',
];

View file

@ -1,5 +1,16 @@
<?php
return array(
'error' => 'You must select at least ONE option.'
);
return [
'about_templates' => 'About Saved Templates',
'saving_templates_description' => 'Select your options, then enter the name of your template in the box above and click the \'Save Template\' button. Use the dropdown to select a previously saved template.',
'create' => [
'success' => 'Template saved successfully',
],
'update' => [
'success' => 'Template updated successfully',
],
'delete' => [
'success' => 'Template deleted',
'no_delete_permission' => 'Template does not exist or you do not have permission to delete it.',
],
];

View file

@ -302,6 +302,7 @@ return [
'username_format' => 'Username Format',
'username' => 'Username',
'update' => 'Update',
'updating_item' => 'Updating :item',
'upload_filetypes_help' => 'Allowed filetypes are png, gif, jpg, jpeg, doc, docx, pdf, xls, xlsx, txt, lic, xml, zip, rtf and rar. Max upload size allowed is :size.',
'uploaded' => 'Uploaded',
'user' => 'User',

View file

@ -5,6 +5,18 @@
<div class="col-md-7">
<select class="js-data-ajax" data-endpoint="categories/{{ (isset($category_type)) ? $category_type : 'assets' }}" data-placeholder="{{ trans('general.select_category') }}" name="{{ $fieldname }}" style="width: 100%" id="category_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@isset ($selected)
@if (!is_iterable($selected))
@php
$selected = [$selected];
@endphp
@endif
@foreach ($selected as $category_id)
<option value="{{ $category_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ \App\Models\Category::find($category_id)->name }}
</option>
@endforeach
@endisset
@if ($category_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $category_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Category::find($category_id)) ? \App\Models\Category::find($category_id)->name : '' }}

View file

@ -22,6 +22,13 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-8">
<select class="js-data-ajax" data-endpoint="companies" data-placeholder="{{ trans('general.select_company') }}" name="{{ $fieldname }}" style="width: 100%" id="company_select"{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@isset ($selected)
@foreach ($selected as $company_id)
<option value="{{ $company_id }}" selected="selected" role="option" aria-selected="true">
{{ \App\Models\Company::find($company_id)->name }}
</option>
@endforeach
@endisset
@if ($company_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $company_id }}" selected="selected">
{{ (\App\Models\Company::find($company_id)) ? \App\Models\Company::find($company_id)->name : '' }}

View file

@ -4,6 +4,18 @@
<div class="col-md-6">
<select class="js-data-ajax" data-endpoint="departments" data-placeholder="{{ trans('general.select_department') }}" name="{{ $fieldname }}" style="width: 100%" id="department_select" aria-label="{{ $fieldname }}"{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@isset ($selected)
@if (!is_iterable($selected))
@php
$selected = [$selected];
@endphp
@endif
@foreach ($selected as $department_id)
<option value="{{ $department_id }}" selected="selected" role="option" aria-selected="true">
{{ \App\Models\Department::find($department_id)->name }}
</option>
@endforeach
@endisset
@if ($department_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $department_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Department::find($department_id)) ? \App\Models\Department::find($department_id)->name : '' }}

View file

@ -4,6 +4,13 @@
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<div class="col-md-7">
<select class="js-data-ajax" data-endpoint="locations" data-placeholder="{{ trans('general.select_location') }}" name="{{ $fieldname }}" style="width: 100%" id="{{ $fieldname }}_location_select" aria-label="{{ $fieldname }}"{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}{!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}>
@isset($selected)
@foreach($selected as $location_id)
<option value="{{ $location_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Location::find($location_id))->name }}
</option>
@endforeach
@endisset
@if ($location_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $location_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Location::find($location_id)) ? \App\Models\Location::find($location_id)->name : '' }}

View file

@ -5,6 +5,18 @@
<div class="col-md-7">
<select class="js-data-ajax" data-endpoint="manufacturers" data-placeholder="{{ trans('general.select_manufacturer') }}" name="{{ $fieldname }}" style="width: 100%" id="manufacturer_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@isset ($selected)
@if (!is_iterable($selected))
@php
$selected = [$selected];
@endphp
@endif
@foreach ($selected as $manufacturer_id)
<option value="{{ $manufacturer_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ \App\Models\Manufacturer::find($manufacturer_id)->name }}
</option>
@endforeach
@endisset
@if ($manufacturer_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $manufacturer_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Manufacturer::find($manufacturer_id)) ? \App\Models\Manufacturer::find($manufacturer_id)->name : '' }}

View file

@ -5,6 +5,18 @@
<div class="col-md-7">
<select class="js-data-ajax" data-endpoint="models" data-placeholder="{{ trans('general.select_model') }}" name="{{ $fieldname }}" style="width: 100%" id="model_select_id" aria-label="{{ $fieldname }}"{{ ((isset($field_req)) || ((isset($required) && ($required =='true')))) ? ' required' : '' }}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@isset ($selected)
@if (!is_iterable($selected))
@php
$selected = [$selected];
@endphp
@endif
@foreach ($selected as $model_id)
<option value="{{ $model_id }}" selected="selected" role="option" aria-selected="true">
{{ \App\Models\AssetModel::find($model_id)->name }}
</option>
@endforeach
@endisset
@if ($model_id = old($fieldname, ($item->{$fieldname} ?? request($fieldname) ?? '')))
<option value="{{ $model_id }}" selected="selected">
{{ (\App\Models\AssetModel::find($model_id)) ? \App\Models\AssetModel::find($model_id)->name : '' }}

View file

@ -5,6 +5,13 @@
<div class="col-md-7">
<select class="js-data-ajax" data-endpoint="statuslabels" data-placeholder="{{ trans('general.select_statuslabel') }}" name="{{ $fieldname }}" style="width: 100%" id="status_select_id" aria-label="{{ $fieldname }}" {!! ((isset($item)) && (Helper::checkIfRequired($item, $fieldname))) ? ' required ' : '' !!}{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@isset ($selected)
@foreach ($selected as $status_id)
<option value="{{ $status_id }}" selected="selected" role="option" aria-selected="true">
{{ \App\Models\Statuslabel::find($status_id)->name }}
</option>
@endforeach
@endisset
@if ($status_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $status_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Statuslabel::find($status_id)) ? \App\Models\Statuslabel::find($status_id)->name : '' }}

View file

@ -4,6 +4,13 @@
<div class="col-md-7">
<select class="js-data-ajax" data-endpoint="suppliers" data-placeholder="{{ trans('general.select_supplier') }}" name="{{ $fieldname }}" style="width: 100%" id="supplier_select" aria-label="{{ $fieldname }}"{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}{{ (isset($item) && (Helper::checkIfRequired($item, $fieldname))) ? ' required' : '' }}>
@isset ($selected)
@foreach ($selected as $supplier_id)
<option value="{{ $supplier_id }}" selected="selected" role="option" aria-selected="true">
{{ \App\Models\Supplier::find($supplier_id)->name }}
</option>
@endforeach
@endisset
@if ($supplier_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
<option value="{{ $supplier_id }}" selected="selected" role="option" aria-selected="true" role="option">
{{ (\App\Models\Supplier::find($supplier_id)) ? \App\Models\Supplier::find($supplier_id)->name : '' }}

View file

@ -2,13 +2,30 @@
{{-- Page Title --}}
@section('title')
{{ trans('general.custom_report') }}
@if (request()->routeIs('report-templates.edit'))
{{ trans('general.update') }} {{ $template->name }}
@elseif(request()->routeIs('report-templates.show'))
{{ trans('general.custom_report') }}: {{ $template->name }}
@else
{{ trans('general.custom_report') }}
@endif
@parent
@stop
@section('header_right')
<a href="{{ URL::previous() }}" class="btn btn-primary pull-right">
{{ trans('general.back') }}</a>
@if (request()->routeIs('report-templates.edit'))
<a href="{{ route('report-templates.show', $template) }}" class="btn btn-primary pull-right">
{{ trans('general.back') }}
</a>
@elseif (request()->routeIs('report-templates.show'))
<a href="{{ route('reports/custom') }}" class="btn btn-primary pull-right">
{{ trans('general.back') }}
</a>
@else
<a href="{{ URL::previous() }}" class="btn btn-primary pull-right">
{{ trans('general.back') }}
</a>
@endif
@stop
@ -16,173 +33,231 @@
@section('content')
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="col-md-8 col-md-offset-1">
{{ Form::open(['method' => 'post', 'class' => 'form-horizontal']) }}
{{csrf_field()}}
{{ Form::open([
'method' => 'post',
'class' => 'form-horizontal',
'id' => 'custom-report-form',
'url' => request()->routeIs('report-templates.edit') ? route('report-templates.update', $template) : '/reports/custom',
]) }}
{{csrf_field()}}
<!-- Horizontal Form -->
<div class="box box-default">
<div class="box-header with-border">
<h2 class="box-title">{{ trans('general.customize_report') }}</h2>
<div class="box box-default">
<div class="box-header with-border">
@if (request()->routeIs('reports/custom') || request()->routeIs('report-templates.show'))
<h2 class="box-title">
{{ trans('general.customize_report') }}
</h2>
@endif
@if (request()->routeIs('report-templates.edit'))
<div class="row">
<div class="col-md-7 col-md-offset-5">
<div class="{{ $errors->has('name') ? ' has-error' : '' }}">
<label
for="name"
class="col-md-4 control-label"
>
{{ trans('admin/reports/general.template_name') }}
</label>
<div class="col-md-8">
<input
class="form-control"
placeholder=""
name="name"
type="text"
id="name"
value="{{ $template->name }}"
required
>
</div>
{!! $errors->first('name', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>
</div>
@endif
@if (request()->routeIs('report-templates.show'))
<div class="box-tools pull-right">
<a
href="{{ route('report-templates.edit', $template) }}"
class="btn btn-sm btn-warning"
data-tooltip="true"
title="{{ trans('admin/reports/general.update_template') }}"
>
<i class="fas fa-pencil-alt" aria-hidden="true"></i>
<span class="sr-only">{{ trans('general.update') }}</span>
</a>
<button
class="btn btn-sm btn-danger delete-asset"
data-toggle="modal"
data-title="{{ trans('general.delete') }}"
data-content="{{ trans('general.delete_confirm', ['item' => $template->name]) }}"
data-target="#dataConfirmModal"
type="button"
>
<i class="fas fa-trash" aria-hidden="true"></i><span class="sr-only">{{ trans('general.delete') }}</span>
</button>
</div>
@endif
</div><!-- /.box-header -->
<div class="box-body">
<div class="col-md-4">
<div class="col-md-4" id="included_fields_wrapper">
<label class="form-control">
<input type="checkbox" id="checkAll" checked="checked">
{{ trans('general.select_all') }}
</label>
<label class="form-control">
<input type="checkbox" id="checkAll" checked="checked">
{{ trans('general.select_all') }}
</label>
<label class="form-control">
{{ Form::checkbox('id', '1', '1') }}
{{ trans('general.id') }}
</label>
<label class="form-control">
{{ Form::checkbox('id', '1', $template->checkmarkValue('id')) }}
{{ trans('general.id') }}
</label>
<label class="form-control">
{{ Form::checkbox('company', '1', '1') }}
{{ trans('general.company') }}
</label>
<label class="form-control">
{{ Form::checkbox('company', '1', $template->checkmarkValue('company')) }}
{{ trans('general.company') }}
</label>
<label class="form-control">
{{ Form::checkbox('asset_tag', '1', '1') }}
{{ trans('general.asset_tag') }}
</label>
<label class="form-control">
{{ Form::checkbox('asset_tag', '1', $template->checkmarkValue('asset_tag')) }}
{{ trans('general.asset_tag') }}
</label>
<label class="form-control">
{{ Form::checkbox('asset_name', '1', '1') }}
{{ trans('admin/hardware/form.name') }}
</label>
<label class="form-control">
{{ Form::checkbox('asset_name', '1', $template->checkmarkValue('asset_name')) }}
{{ trans('admin/hardware/form.name') }}
</label>
<label class="form-control">
{{ Form::checkbox('manufacturer', '1', '1') }}
{{ trans('general.manufacturer') }}
</label>
<label class="form-control">
{{ Form::checkbox('manufacturer', '1', $template->checkmarkValue('manufacturer')) }}
{{ trans('general.manufacturer') }}
</label>
<label class="form-control">
{{ Form::checkbox('model', '1', '1') }}
{{ trans('general.asset_models') }}
</label>
<label class="form-control">
{{ Form::checkbox('model', '1', $template->checkmarkValue('model')) }}
{{ trans('general.asset_models') }}
</label>
<label class="form-control">
{{ Form::checkbox('category', '1', '1') }}
{{ trans('general.category') }}
</label>
<label class="form-control">
{{ Form::checkbox('category', '1', $template->checkmarkValue('category')) }}
{{ trans('general.category') }}
</label>
<label class="form-control">
{{ Form::checkbox('serial', '1', '1') }}
{{ trans('admin/hardware/table.serial') }}
</label>
<label class="form-control">
{{ Form::checkbox('serial', '1', $template->checkmarkValue('serial')) }}
{{ trans('admin/hardware/table.serial') }}
</label>
<label class="form-control">
{{ Form::checkbox('purchase_date', '1', '1') }}
{{ trans('admin/licenses/table.purchase_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('purchase_date', '1', $template->checkmarkValue('purchase_date')) }}
{{ trans('admin/licenses/table.purchase_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('purchase_cost', '1', '1') }}
{{ trans('admin/hardware/form.cost') }}
</label>
<label class="form-control">
{{ Form::checkbox('purchase_cost', '1', $template->checkmarkValue('purchase_cost')) }}
{{ trans('admin/hardware/form.cost') }}
</label>
<label class="form-control">
{{ Form::checkbox('eol', '1', '1') }}
{{ trans('admin/hardware/form.eol_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('eol', '1', $template->checkmarkValue('eol')) }}
{{ trans('admin/hardware/form.eol_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('order', '1', '1') }}
{{ trans('admin/hardware/form.order') }}
</label>
<label class="form-control">
{{ Form::checkbox('order', '1', $template->checkmarkValue('order')) }}
{{ trans('admin/hardware/form.order') }}
</label>
<label class="form-control">
{{ Form::checkbox('supplier', '1', '1') }}
{{ trans('general.suppliers') }}
</label>
<label class="form-control">
{{ Form::checkbox('supplier', '1', $template->checkmarkValue('supplier')) }}
{{ trans('general.suppliers') }}
</label>
<label class="form-control">
{{ Form::checkbox('location', '1', '1') }}
{{ trans('general.location') }}
</label>
<label class="form-control">
{{ Form::checkbox('location', '1', $template->checkmarkValue('location')) }}
{{ trans('general.location') }}
</label>
<label class="form-control" style="margin-left: 25px;">
{{ Form::checkbox('location_address', '1', '1') }}
{{ Form::checkbox('location_address', '1', $template->checkmarkValue('location_address')) }}
{{ trans('general.address') }}
</label>
<label class="form-control">
{{ Form::checkbox('rtd_location', '1', '1') }}
{{ trans('admin/hardware/form.default_location') }}
</label>
<label class="form-control">
{{ Form::checkbox('rtd_location', '1', $template->checkmarkValue('rtd_location')) }}
{{ trans('admin/hardware/form.default_location') }}
</label>
<label class="form-control" style="margin-left: 25px;">
{{ Form::checkbox('rtd_location_address', '1', '1') }}
{{ Form::checkbox('rtd_location_address', '1', $template->checkmarkValue('rtd_location_address')) }}
{{ trans('general.address') }}
</label>
<label class="form-control">
{{ Form::checkbox('status', '1', '1') }}
{{ trans('general.status') }}
</label>
<label class="form-control">
{{ Form::checkbox('status', '1', $template->checkmarkValue('status')) }}
{{ trans('general.status') }}
</label>
<label class="form-control">
{{ Form::checkbox('warranty', '1', $template->checkmarkValue('warranty')) }}
{{ trans('admin/hardware/form.warranty') }}
</label>
<label class="form-control">
{{ Form::checkbox('depreciation', '1', $template->checkmarkValue('depreciation')) }}
{{ trans('general.depreciation') }}
</label>
<label class="form-control">
{{ Form::checkbox('checkout_date', '1', $template->checkmarkValue('checkout_date')) }}
{{ trans('admin/hardware/table.checkout_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('warranty', '1', '1') }}
{{ trans('admin/hardware/form.warranty') }}
</label>
<label class="form-control">
{{ Form::checkbox('depreciation', '1', '1') }}
{{ trans('general.depreciation') }}
</label>
<label class="form-control">
{{ Form::checkbox('checkout_date', '1', '1') }}
{{ trans('admin/hardware/table.checkout_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('checkin_date', '1', '1') }}
{{ Form::checkbox('checkin_date', '1', $template->checkmarkValue('checkin_date')) }}
{{ trans('admin/hardware/table.last_checkin_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('expected_checkin', '1', '1') }}
{{ Form::checkbox('expected_checkin', '1', $template->checkmarkValue('expected_checkin')) }}
{{ trans('admin/hardware/form.expected_checkin') }}
</label>
<label class="form-control">
{{ Form::checkbox('created_at', '1', '1') }}
{{ trans('general.created_at') }}
</label>
<label class="form-control">
{{ Form::checkbox('created_at', '1', $template->checkmarkValue('created_at')) }}
{{ trans('general.created_at') }}
</label>
<label class="form-control">
{{ Form::checkbox('updated_at', '1', '1') }}
{{ trans('general.updated_at') }}
</label>
<label class="form-control">
{{ Form::checkbox('updated_at', '1', $template->checkmarkValue('updated_at')) }}
{{ trans('general.updated_at') }}
</label>
<label class="form-control">
{{ Form::checkbox('deleted_at', '1', '1') }}
{{ trans('general.deleted') }}
</label>
<label class="form-control">
{{ Form::checkbox('deleted_at', '1', $template->checkmarkValue('deleted_at')) }}
{{ trans('general.deleted') }}
</label>
<label class="form-control">
{{ Form::checkbox('last_audit_date', '1', '1') }}
{{ trans('general.last_audit') }}
</label>
<label class="form-control">
{{ Form::checkbox('last_audit_date', '1', $template->checkmarkValue('last_audit_date')) }}
{{ trans('general.last_audit') }}
</label>
<label class="form-control">
{{ Form::checkbox('next_audit_date', '1', '1') }}
{{ trans('general.next_audit_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('next_audit_date', '1', $template->checkmarkValue('next_audit_date')) }}
{{ trans('general.next_audit_date') }}
</label>
<label class="form-control">
{{ Form::checkbox('notes', '1', '1') }}
{{ trans('general.notes') }}
</label>
<label class="form-control">
{{ Form::checkbox('notes', '1', $template->checkmarkValue('notes')) }}
{{ trans('general.notes') }}
</label>
<label class="form-control" style="margin-left: 25px;">
{{ Form::checkbox('url', '1', '1') }}
{{ Form::checkbox('url', '1', $template->checkmarkValue('url')) }}
{{ trans('general.url') }}
</label>
@ -192,64 +267,64 @@
<h2>{{ trans('general.checked_out_to_fields') }}: </h2>
<label class="form-control">
{{ Form::checkbox('assigned_to', '1', '1') }}
{{ Form::checkbox('assigned_to', '1', $template->checkmarkValue('assigned_to')) }}
{{ trans('admin/licenses/table.assigned_to') }}
</label>
<label class="form-control">
{{ Form::checkbox('username', '1', '1') }}
{{ Form::checkbox('username', '1', $template->checkmarkValue('username')) }}
{{ trans('admin/users/table.username') }}
</label>
<label class="form-control">
{{ Form::checkbox('employee_num', '1', '1') }}
{{ Form::checkbox('employee_num', '1', $template->checkmarkValue('employee_num')) }}
{{ trans('general.employee_number') }}
</label>
<label class="form-control">
{{ Form::checkbox('manager', '1', '1') }}
{{ Form::checkbox('manager', '1', $template->checkmarkValue('manager')) }}
{{ trans('admin/users/table.manager') }}
</label>
<label class="form-control">
{{ Form::checkbox('department', '1', '1') }}
{{ Form::checkbox('department', '1', $template->checkmarkValue('department')) }}
{{ trans('general.department') }}
</label>
<label class="form-control">
{{ Form::checkbox('title', '1', '1') }}
{{ Form::checkbox('title', '1', $template->checkmarkValue('title')) }}
{{ trans('admin/users/table.title') }}
</label>
<!-- new -->
<label class="form-control">
{{ Form::checkbox('phone', '1', '1') }}
{{ Form::checkbox('phone', '1', $template->checkmarkValue('phone')) }}
{{ trans('admin/users/table.phone') }}
</label>
<label class="form-control">
{{ Form::checkbox('user_address', '1', '1') }}
{{ Form::checkbox('user_address', '1', $template->checkmarkValue('user_address')) }}
{{ trans('general.address') }}
</label>
<label class="form-control">
{{Form::checkbox('user_city', '1', '1')}}
{{Form::checkbox('user_city', '1', $template->checkmarkValue('user_city'))}}
{{ trans('general.city') }}
</label>
<label class="form-control">
{{Form::checkbox('user_state', '1', '1')}}
{{Form::checkbox('user_state', '1', $template->checkmarkValue('user_state'))}}
{{ trans('general.state') }}
</label>
<label class="form-control">
{{Form::checkbox('user_country', '1', '1')}}
{{Form::checkbox('user_country', '1', $template->checkmarkValue('user_country'))}}
{{ trans('general.country') }}
</label>
<label class="form-control">
{{Form::checkbox('user_zip', '1', '1')}}
{{Form::checkbox('user_zip', '1', $template->checkmarkValue('user_zip'))}}
{{ trans('general.zip') }}
</label>
@ -262,7 +337,7 @@
@foreach ($customfields as $customfield)
<label class="form-control">
{{ Form::checkbox($customfield->db_column_name(), '1', '1') }}
{{ Form::checkbox($customfield->db_column_name(), '1', $template->checkmarkValue($customfield->db_column_name())) }}
{{ $customfield->name }}
</label>
@ -283,61 +358,72 @@
'fieldname' =>
'by_company_id[]',
'multiple' => 'true',
'hide_new' => 'true'
])
'hide_new' => 'true',
'selected' => $template->selectValues('by_company_id', \App\Models\Company::class),
])
@include ('partials.forms.edit.location-select', [
'translated_name' => trans('general.location'),
'fieldname' => 'by_location_id[]',
'multiple' => 'true',
'hide_new' => 'true'
])
'hide_new' => 'true',
'selected' => $template->selectValues('by_location_id', \App\Models\Location::class),
])
@include ('partials.forms.edit.location-select', [
'translated_name' => trans('admin/hardware/form.default_location'),
'fieldname' => 'by_rtd_location_id[]',
'multiple' => 'true',
'hide_new' => 'true'
])
'hide_new' => 'true',
'selected' => $template->selectValues('by_rtd_location_id', \App\Models\Location::class),
])
@include ('partials.forms.edit.department-select',[
'translated_name' => trans('general.department'),
'fieldname' => 'by_dept_id[]',
'multiple' => 'true',
'hide_new' => 'true'
])
'hide_new' => 'true',
'selected' => $template->selectValues('by_dept_id', \App\Models\Department::class),
])
@include ('partials.forms.edit.supplier-select', [
'translated_name' => trans('general.supplier'),
'fieldname' => 'by_supplier_id[]',
'multiple' => 'true',
'hide_new' => 'true'
])
'hide_new' => 'true',
'selected' => $template->selectValues('by_supplier_id', \App\Models\Supplier::class),
])
@include ('partials.forms.edit.model-select', [
'translated_name' => trans('general.asset_model'),
'fieldname' => 'by_model_id[]',
'multiple' => 'true',
'hide_new' => 'true'
])
'hide_new' => 'true',
'selected' => $template->selectValues('by_model_id', \App\Models\AssetModel::class),
])
@include ('partials.forms.edit.manufacturer-select', [
'translated_name' => trans('general.manufacturer'),
'fieldname' => 'by_manufacturer_id[]',
'multiple' => 'true',
'hide_new' => 'true'
])
'hide_new' => 'true',
'selected' => $template->selectValues('by_manufacturer_id', \App\Models\Manufacturer::class),
])
@include ('partials.forms.edit.category-select', [
'translated_name' => trans('general.category'),
'fieldname' => 'by_category_id[]',
'multiple' => 'true',
'hide_new' => 'true', 'category_type' => 'asset'
])
@include ('partials.forms.edit.status-select', [
'hide_new' => 'true',
'category_type' => 'asset',
'selected' => $template->selectValues('by_category_id', \App\Models\Category::class),
])
@include ('partials.forms.edit.status-select', [
'translated_name' => trans('admin/hardware/form.status'),
'fieldname' => 'by_status_id[]',
'multiple' => 'true',
'hide_new' => 'true'])
'hide_new' => 'true',
'selected' => $template->selectValues('by_status_id', \App\Models\Statuslabel::class),
])
<!-- Order Number -->
<div class="form-group">
<label for="by_order_number" class="col-md-3 control-label">{{ trans('general.order_number') }}</label>
<div class="col-md-7">
<input class="form-control" type="text" name="by_order_number" value="" aria-label="by_order_number">
<input class="form-control" type="text" name="by_order_number" value="{{ $template->textValue('by_order_number', old('by_order_number')) }}" aria-label="by_order_number">
</div>
</div>
@ -345,9 +431,9 @@
<div class="form-group purchase-range{{ ($errors->has('purchase_start') || $errors->has('purchase_end')) ? ' has-error' : '' }}">
<label for="purchase_start" class="col-md-3 control-label">{{ trans('general.purchase_date') }}</label>
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="purchase_start" aria-label="purchase_start" value="{{ old('purchase_start') }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="purchase_end" aria-label="purchase_end" value="{{ old('purchase_end') }}">
<input type="text" class="form-control" name="purchase_start" aria-label="purchase_start" value="{{ $template->textValue('purchase_start', old('purchase_start')) }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="purchase_end" aria-label="purchase_end" value="{{ $template->textValue('purchase_end', old('purchase_end')) }}">
</div>
@if ($errors->has('purchase_start') || $errors->has('purchase_end'))
@ -363,9 +449,9 @@
<div class="form-group purchase-range{{ ($errors->has('created_start') || $errors->has('created_end')) ? ' has-error' : '' }}">
<label for="created_start" class="col-md-3 control-label">{{ trans('general.created_at') }} </label>
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="created_start" aria-label="created_start" value="{{ old('created_start') }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="created_end" aria-label="created_end" value="{{ old('created_end') }}">
<input type="text" class="form-control" name="created_start" aria-label="created_start" value="{{ $template->textValue('created_start', old('created_start')) }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="created_end" aria-label="created_end" value="{{ $template->textValue('created_end', old('created_end')) }}">
</div>
@if ($errors->has('created_start') || $errors->has('created_end'))
@ -380,9 +466,9 @@
<div class="form-group checkout-range{{ ($errors->has('checkout_date_start') || $errors->has('checkout_date_end')) ? ' has-error' : '' }}">
<label for="checkout_date" class="col-md-3 control-label">{{ trans('general.checkout') }} </label>
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="checkout_date_start" aria-label="checkout_date_start" value="{{ old('checkout_date_start') }}">
<input type="text" class="form-control" name="checkout_date_start" aria-label="checkout_date_start" value="{{ $template->textValue('checkout_date_start', old('checkout_date_start')) }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="checkout_date_end" aria-label="checkout_date_end" value="{{ old('checkout_date_end') }}">
<input type="text" class="form-control" name="checkout_date_end" aria-label="checkout_date_end" value="{{ $template->textValue('checkout_date_end', old('checkout_date_end')) }}">
</div>
@if ($errors->has('checkout_date_start') || $errors->has('checkout_date_end'))
@ -398,9 +484,9 @@
<div class="form-group checkin-range{{ ($errors->has('checkin_date_start') || $errors->has('checkin_date_end')) ? ' has-error' : '' }}">
<label for="checkin_date" class="col-md-3 control-label">{{ trans('admin/hardware/table.last_checkin_date') }}</label>
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="checkin_date_start" aria-label="checkin_date_start" value="{{ old('checkin_date_start') }}">
<input type="text" class="form-control" name="checkin_date_start" aria-label="checkin_date_start" value="{{ $template->textValue('checkin_date_start', old('checkin_date_start')) }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="checkin_date_end" aria-label="checkin_date_end" value="{{ old('checkin_date_end') }}">
<input type="text" class="form-control" name="checkin_date_end" aria-label="checkin_date_end" value="{{ $template->textValue('checkin_date_end', old('checkin_date_end')) }}">
</div>
@if ($errors->has('checkin_date_start') || $errors->has('checkin_date_end'))
@ -415,9 +501,9 @@
<div class="form-group expected_checkin-range{{ ($errors->has('expected_checkin_start') || $errors->has('expected_checkin_end')) ? ' has-error' : '' }}">
<label for="expected_checkin_start" class="col-md-3 control-label">{{ trans('admin/hardware/form.expected_checkin') }}</label>
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="expected_checkin_start" aria-label="expected_checkin_start" value="{{ old('expected_checkin_start') }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="expected_checkin_end" aria-label="expected_checkin_end" value="{{ old('expected_checkin_end') }}">
<input type="text" class="form-control" name="expected_checkin_start" aria-label="expected_checkin_start" value="{{ $template->textValue('expected_checkin_start', old('expected_checkin_start')) }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="expected_checkin_end" aria-label="expected_checkin_end" value="{{ $template->textValue('expected_checkin_end', old('expected_checkin_end')) }}">
</div>
@if ($errors->has('expected_checkin_start') || $errors->has('expected_checkin_end'))
@ -430,22 +516,29 @@
</div>
<!-- EoL Date -->
<div class="form-group asset_eol_date-range">
<div class="form-group asset_eol_date-range {{ ($errors->has('asset_eol_date_start') || $errors->has('asset_eol_date_end')) ? ' has-error' : '' }}">
<label for="asset_eol_date" class="col-md-3 control-label">{{ trans('admin/hardware/form.eol_date') }}</label>
<div class="input-daterange input-group col-md-6" id="datepicker">
<input type="text" class="form-control" name="asset_eol_date_start" aria-label="asset_eol_date_start">
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="asset_eol_date_start" aria-label="asset_eol_date_start" value="{{ $template->textValue('asset_eol_date_start', old('asset_eol_date_start')) }}">
<span class="input-group-addon">to</span>
<input type="text" class="form-control" name="asset_eol_date_end" aria-label="asset_eol_date_end">
<input type="text" class="form-control" name="asset_eol_date_end" aria-label="asset_eol_date_end" value="{{ $template->textValue('asset_eol_date_end', old('asset_eol_date_end')) }}">
</div>
@if ($errors->has('asset_eol_date_start') || $errors->has('asset_eol_date_end'))
<div class="col-md-9 col-lg-offset-3">
{!! $errors->first('asset_eol_date_start', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
{!! $errors->first('asset_eol_date_end', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
@endif
</div>
<!-- Last Audit Date -->
<div class="form-group last_audit-range{{ ($errors->has('last_audit_start') || $errors->has('last_audit_end')) ? ' has-error' : '' }}">
<label for="last_audit_start" class="col-md-3 control-label">{{ trans('general.last_audit') }}</label>
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="last_audit_start" aria-label="last_audit_start" value="{{ old('last_audit_start') }}">
<input type="text" class="form-control" name="last_audit_start" aria-label="last_audit_start" value="{{ $template->textValue('last_audit_start', old('last_audit_start')) }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="last_audit_end" aria-label="last_audit_end" value="{{ old('last_audit_end') }}">
<input type="text" class="form-control" name="last_audit_end" aria-label="last_audit_end" value="{{ $template->textValue('last_audit_end', old('last_audit_end')) }}">
</div>
@if ($errors->has('last_audit_start') || $errors->has('last_audit_end'))
@ -460,9 +553,9 @@
<div class="form-group next_audit-range{{ ($errors->has('next_audit_start') || $errors->has('next_audit_end')) ? ' has-error' : '' }}">
<label for="next_audit_start" class="col-md-3 control-label">{{ trans('general.next_audit_date') }}</label>
<div class="input-daterange input-group col-md-7" id="datepicker">
<input type="text" class="form-control" name="next_audit_start" aria-label="next_audit_start" value="{{ old('next_audit_start') }}">
<input type="text" class="form-control" name="next_audit_start" aria-label="next_audit_start" value="{{ $template->textValue('next_audit_start', old('next_audit_start')) }}">
<span class="input-group-addon">{{ strtolower(trans('general.to')) }}</span>
<input type="text" class="form-control" name="next_audit_end" aria-label="next_audit_end" value="{{ old('next_audit_end') }}">
<input type="text" class="form-control" name="next_audit_end" aria-label="next_audit_end" value="{{ $template->textValue('next_audit_end', old('next_audit_end')) }}">
</div>
@if ($errors->has('next_audit_start') || $errors->has('next_audit_end'))
@ -475,46 +568,104 @@
<div class="col-md-9 col-md-offset-3">
<label class="form-control">
{{ Form::checkbox('exclude_archived', '1', old('exclude_archived')) }}
{{ Form::checkbox('exclude_archived', '1', $template->checkmarkValue('exclude_archived', '0')) }}
{{ trans('general.exclude_archived') }}
</label>
</div>
<div class="col-md-9 col-md-offset-3">
<label class="form-control">
{{ Form::checkbox('use_bom', '1', old('use_bom')) }}
{{ Form::checkbox('use_bom', '1', $template->checkmarkValue('use_bom', '0')) }}
{{ trans('general.bom_remark') }}
</label>
</div>
<div class="col-md-9 col-md-offset-3">
<label class="form-control">
{{ Form::radio('deleted_assets', 'exclude_deleted', true, ['aria-label'=>'deleted_assets', 'id'=>'deleted_assets_exclude_deleted'])}}
{{ Form::radio('deleted_assets', 'exclude_deleted', $template->radioValue('deleted_assets', 'exclude_deleted', true), ['aria-label'=>'deleted_assets', 'id'=>'deleted_assets_exclude_deleted'])}}
{{ trans('general.exclude_deleted') }}
</label>
<label class="form-control">
{{ Form::radio('deleted_assets', 'include_deleted', old('deleted_assets'), ['aria-label'=>'deleted_assets', 'id'=>'deleted_assets_include_deleted']) }}
{{ Form::radio('deleted_assets', 'include_deleted', $template->radioValue('deleted_assets', 'include_deleted'), ['aria-label'=>'deleted_assets', 'id'=>'deleted_assets_include_deleted']) }}
{{ trans('general.include_deleted') }}
</label>
<label class="form-control">
{{ Form::radio('deleted_assets', 'only_deleted', old('deleted_assets'), ['aria-label'=>'deleted_assets','id'=>'deleted_assets_only_deleted']) }}
{{ Form::radio('deleted_assets', 'only_deleted', $template->radioValue('deleted_assets', 'only_deleted'), ['aria-label'=>'deleted_assets','id'=>'deleted_assets_only_deleted']) }}
{{ trans('general.only_deleted') }}
</label>
</div>
</div>
</div> <!-- /.box-body-->
<div class="box-footer text-right">
<button type="submit" class="btn btn-success">
<i class="fas fa-download icon-white" aria-hidden="true"></i>
{{ trans('general.generate') }}
</button>
</div>
</div> <!--/.box.box-default-->
<div class="box-footer text-right">
@if (request()->routeIs('report-templates.edit'))
<button type="submit" class="btn btn-primary">
<i class="fas fa-check icon-white" aria-hidden="true"></i>
{{ trans('general.save') }}
</button>
@else
<button type="submit" class="btn btn-success">
<i class="fas fa-download icon-white" aria-hidden="true"></i>
{{ trans('general.generate') }}
</button>
@endif
</div>
</div> <!--/.box.box-default-->
{{ Form::close() }}
</div>
</div>
<!-- Saved Reports right column -->
<div class="col-md-2">
@if (! request()->routeIs('report-templates.edit'))
<div class="form-group">
<label for="saved_report_select">{{ trans('admin/reports/general.open_saved_template') }}</label>
<select
id="saved_report_select"
class="form-control select2"
data-placeholder="{{ trans('admin/reports/general.select_a_template') }}"
>
<option></option>
@foreach($report_templates as $savedTemplate)
<option value="{{ $savedTemplate->id }}" @selected($savedTemplate->is(request()->route()->parameter('reportTemplate')))>
{{ $savedTemplate->name }}
</option>
@endforeach
</select>
</div>
@endif
@if (request()->routeIs('reports/custom'))
<hr>
<div class="form-group">
<form method="post" id="savetemplateform" action="{{ route("report-templates.store") }}">
@csrf
<input type="hidden" id="savetemplateform" name="options">
<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">
<label for="name">{{ trans('admin/reports/general.template_name') }}</label>
<input
class="form-control"
placeholder=""
name="name"
type="text"
id="name"
value="{{ $template->name }}"
required
>
{!! $errors->first('name', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
<button class="btn btn-primary" style="width: 100%">
{{ trans('admin/reports/general.save_template') }}
</button>
</form>
</div>
<div class="box box-success">
<div class="box-header with-border">
<h4>{{ trans('admin/reports/message.about_templates') }}</h4>
</div>
<div class="box-body">
<p>{!! trans('admin/reports/message.saving_templates_description') !!}</p>
</div>
</div>
@endif
</div>
</div>
@stop
@ -568,8 +719,32 @@
});
$("#checkAll").change(function () {
$("input:checkbox").prop('checked', $(this).prop("checked"));
$("#included_fields_wrapper input:checkbox").prop('checked', $(this).prop("checked"));
});
$("#savetemplateform").submit(function(e) {
e.preventDefault(e);
let form = $('#custom-report-form');
$('<input>').attr({
type: 'hidden',
name: 'name',
value: $('#name').val(),
}).appendTo(form);
form.attr('action', '{{ route('report-templates.store') }}').submit();
});
$('#saved_report_select')
.on('select2:select', function (event) {
window.location.href = '/reports/templates/' + event.params.data.id;
});
$('#dataConfirmModal').on('show.bs.modal', function (event) {
var content = $(event.relatedTarget).data('content');
var title = $(event.relatedTarget).data('title');
$(this).find(".modal-body").text(content);
$(this).find(".modal-header").text(title);
});
</script>
@stop

View file

@ -16,6 +16,7 @@ use App\Http\Controllers\ManufacturersController;
use App\Http\Controllers\ModalController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\ReportsController;
use App\Http\Controllers\ReportTemplatesController;
use App\Http\Controllers\SettingsController;
use App\Http\Controllers\StatuslabelsController;
use App\Http\Controllers\SuppliersController;
@ -376,6 +377,14 @@ Route::group(['middleware' => ['auth']], function () {
Route::get('reports/custom', [ReportsController::class, 'getCustomReport'])->name('reports/custom');
Route::post('reports/custom', [ReportsController::class, 'postCustom']);
Route::prefix('reports/templates')->name('report-templates')->group(function () {
Route::post('/', [ReportTemplatesController::class, 'store'])->name('.store');
Route::get('/{reportTemplate}', [ReportTemplatesController::class, 'show'])->name('.show');
Route::get('/{reportTemplate}/edit', [ReportTemplatesController::class, 'edit'])->name('.edit');
Route::post('/{reportTemplate}', [ReportTemplatesController::class, 'update'])->name('.update');
Route::delete('/{reportTemplate}', [ReportTemplatesController::class, 'destroy'])->name('.destroy');
});
Route::get(
'reports/activity',
[ReportsController::class, 'getActivityReport']

View file

@ -0,0 +1,47 @@
<?php
namespace Tests\Feature\ReportTemplates;
use App\Models\ReportTemplate;
use App\Models\User;
use PHPUnit\Framework\Attributes\Group;
use Tests\Concerns\TestsPermissionsRequirement;
use Tests\TestCase;
#[Group('custom-reporting')]
class DeleteReportTemplateTest extends TestCase implements TestsPermissionsRequirement
{
public function testRequiresPermission()
{
$reportTemplate = ReportTemplate::factory()->create();
$this->actingAs(User::factory()->create())
->post(route('report-templates.destroy', $reportTemplate->id))
->assertNotFound();
$this->assertModelExists($reportTemplate);
}
public function testCannotDeleteAnotherUsersReportTemplate()
{
$reportTemplate = ReportTemplate::factory()->create();
$this->actingAs(User::factory()->canViewReports()->create())
->delete(route('report-templates.destroy', $reportTemplate->id))
->assertNotFound();
$this->assertModelExists($reportTemplate);
}
public function testCanDeleteAReportTemplate()
{
$user = User::factory()->canViewReports()->create();
$reportTemplate = ReportTemplate::factory()->for($user, 'creator')->create();
$this->actingAs($user)
->delete(route('report-templates.destroy', $reportTemplate->id))
->assertRedirect(route('reports/custom'));
$this->assertSoftDeleted($reportTemplate);
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace Tests\Feature\ReportTemplates;
use App\Models\ReportTemplate;
use App\Models\User;
use PHPUnit\Framework\Attributes\Group;
use Tests\Concerns\TestsPermissionsRequirement;
use Tests\TestCase;
#[Group('custom-reporting')]
class EditReportTemplateTest extends TestCase implements TestsPermissionsRequirement
{
public function testRequiresPermission()
{
$this->actingAs(User::factory()->create())
->get(route('report-templates.edit', ReportTemplate::factory()->create()))
->assertNotFound();
}
public function testCannotLoadEditPageForAnotherUsersReportTemplate()
{
$user = User::factory()->canViewReports()->create();
$reportTemplate = ReportTemplate::factory()->create();
$this->actingAs($user)
->get(route('report-templates.edit', $reportTemplate))
->assertNotFound();
}
public function testCanLoadEditReportTemplatePage()
{
$user = User::factory()->canViewReports()->create();
$reportTemplate = ReportTemplate::factory()->for($user, 'creator')->create();
$this->actingAs($user)
->get(route('report-templates.edit', $reportTemplate))
->assertOk();
}
}

View file

@ -0,0 +1,43 @@
<?php
namespace Tests\Feature\ReportTemplates;
use App\Models\ReportTemplate;
use App\Models\User;
use PHPUnit\Framework\Attributes\Group;
use Tests\Concerns\TestsPermissionsRequirement;
use Tests\TestCase;
#[Group('custom-reporting')]
class ShowReportTemplateTest extends TestCase implements TestsPermissionsRequirement
{
public function testRequiresPermission()
{
$this->actingAs(User::factory()->create())
->get(route('report-templates.show', ReportTemplate::factory()->create()))
->assertNotFound();
}
public function testCanLoadASavedReportTemplate()
{
$user = User::factory()->canViewReports()->create();
$reportTemplate = ReportTemplate::factory()->make(['name' => 'My Awesome Template']);
$user->reportTemplates()->save($reportTemplate);
$this->actingAs($user)
->get(route('report-templates.show', $reportTemplate))
->assertOk()
->assertViewHas(['template' => function (ReportTemplate $templatePassedToView) use ($reportTemplate) {
return $templatePassedToView->is($reportTemplate);
}]);
}
public function testCannotLoadAnotherUsersSavedReportTemplate()
{
$reportTemplate = ReportTemplate::factory()->create();
$this->actingAs(User::factory()->canViewReports()->create())
->get(route('report-templates.show', $reportTemplate))
->assertNotFound();
}
}

View file

@ -0,0 +1,66 @@
<?php
namespace Tests\Feature\ReportTemplates;
use App\Models\ReportTemplate;
use App\Models\User;
use PHPUnit\Framework\Attributes\Group;
use Tests\Concerns\TestsPermissionsRequirement;
use Tests\TestCase;
#[Group('custom-reporting')]
class StoreReportTemplateTest extends TestCase implements TestsPermissionsRequirement
{
public function testRequiresPermission()
{
$this->actingAs(User::factory()->create())
->post(route('report-templates.store'))
->assertForbidden();
}
public function testSavingReportTemplateRequiresValidFields()
{
$this->actingAs(User::factory()->canViewReports()->create())
->post(route('report-templates.store'), [
'name' => '',
])
->assertSessionHasErrors('name');
}
public function testRedirectingAfterValidationErrorRestoresInputs()
{
$this->actingAs(User::factory()->canViewReports()->create())
// start on the custom report page
->from(route('reports/custom'))
->followingRedirects()
->post(route('report-templates.store'), [
'name' => '',
// set some values to ensure they are still present
// when returning to the custom report page.
'by_company_id' => [2, 3]
])->assertViewHas(['template' => function (ReportTemplate $reportTemplate) {
return data_get($reportTemplate, 'options.by_company_id') === [2, 3];
}]);
}
public function testCanSaveAReportTemplate()
{
$user = User::factory()->canViewReports()->create();
$this->actingAs($user)
->post(route('report-templates.store'), [
'name' => 'My Awesome Template',
'company' => '1',
'by_company_id' => ['1', '2'],
])
->assertRedirect();
$template = $user->reportTemplates->first(function ($report) {
return $report->name === 'My Awesome Template';
});
$this->assertNotNull($template);
$this->assertEquals('1', $template->options['company']);
$this->assertEquals(['1', '2'], $template->options['by_company_id']);
}
}

View file

@ -0,0 +1,74 @@
<?php
namespace Tests\Feature\ReportTemplates;
use App\Models\ReportTemplate;
use App\Models\User;
use PHPUnit\Framework\Attributes\Group;
use Tests\Concerns\TestsPermissionsRequirement;
use Tests\TestCase;
#[Group('custom-reporting')]
class UpdateReportTemplateTest extends TestCase implements TestsPermissionsRequirement
{
public function testRequiresPermission()
{
$this->actingAs(User::factory()->create())
->post(route('report-templates.update', ReportTemplate::factory()->create()))
->assertNotFound();
}
public function testCannotUpdateAnotherUsersReportTemplate()
{
$this->actingAs(User::factory()->canViewReports()->create())
->post(route('report-templates.update', ReportTemplate::factory()->create()))
->assertNotFound();
}
public function testUpdatingReportTemplateRequiresValidFields()
{
$user = User::factory()->canViewReports()->create();
$reportTemplate = ReportTemplate::factory()->for($user, 'creator')->create();
$this->actingAs($user)
->post(route('report-templates.update', $reportTemplate), [
//
])
->assertSessionHasErrors([
'name' => 'The name field is required.',
]);
}
public function testCanUpdateAReportTemplate()
{
$user = User::factory()->canViewReports()->create();
$reportTemplate = ReportTemplate::factory()->for($user, 'creator')->create([
'name' => 'Original Name',
'options' => [
'id' => 1,
'category' => 1,
'by_category_id' => 2,
'company' => 1,
'by_company_id' => [1, 2],
],
]);
$this->actingAs($user)
->post(route('report-templates.update', $reportTemplate), [
'name' => 'Updated Name',
'id' => 1,
'company' => 1,
'by_company_id' => [3],
]);
$reportTemplate->refresh();
$this->assertEquals('Updated Name', $reportTemplate->name);
$this->assertEquals(1, $reportTemplate->checkmarkValue('id'));
$this->assertEquals(0, $reportTemplate->checkmarkValue('category'));
$this->assertEquals([], $reportTemplate->selectValues('by_category_id'));
$this->assertEquals(1, $reportTemplate->checkmarkValue('company'));
$this->assertEquals([3], $reportTemplate->selectValues('by_company_id'));
}
}

View file

@ -4,13 +4,18 @@ namespace Tests\Feature\Reporting;
use App\Models\Asset;
use App\Models\Company;
use App\Models\ReportTemplate;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Testing\TestResponse;
use League\Csv\Reader;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\Attributes\Group;
use Tests\Concerns\TestsPermissionsRequirement;
use Tests\TestCase;
class CustomReportTest extends TestCase
#[Group('custom-reporting')]
class CustomReportTest extends TestCase implements TestsPermissionsRequirement
{
protected function setUp(): void
{
@ -43,6 +48,47 @@ class CustomReportTest extends TestCase
);
}
public function testRequiresPermission()
{
$this->actingAs(User::factory()->create())
->get(route('reports/custom'))
->assertForbidden();
}
public function testCanLoadCustomReportPage()
{
$this->actingAs(User::factory()->canViewReports()->create())
->get(route('reports/custom'))
->assertOk()
->assertViewHas([
'template' => function (ReportTemplate $template) {
// the view should have an empty report by default
return $template->exists() === false;
}
]);
}
public function testSavedTemplatesOnPageAreScopedToTheUser()
{
// Given there is a saved template for one user
ReportTemplate::factory()->create(['name' => 'Report A']);
// When loading reports/custom while acting as another user that also has a saved template
$user = User::factory()->canViewReports()
->has(ReportTemplate::factory(['name' => 'Report B']))
->create();
// The user should not see the other user's template (in view as 'report_templates')
$this->actingAs($user)
->get(route('reports/custom'))
->assertViewHas([
'report_templates' => function (Collection $reports) {
return $reports->pluck('name')->doesntContain('Report A');
}
]);
}
public function testCustomAssetReport()
{
Asset::factory()->create(['name' => 'Asset A']);

View file

@ -0,0 +1,71 @@
<?php
namespace Tests\Unit\ActionLogTransformer;
use App\Http\Transformers\ActionlogsTransformer;
use App\Models\Actionlog;
use App\Models\ReportTemplate;
use PHPUnit\Framework\Attributes\Group;
use Tests\TestCase;
#[Group('activity-logging')]
class ReportTemplateActionLogTransformerTest extends TestCase
{
public function testLogEntryForCreatingReportTemplateCanBeTransformed()
{
ReportTemplate::factory()->create();
$actionLogs = Actionlog::query()
->whereMorphedTo('item', ReportTemplate::class)
->where('action_type', 'create')
->get();
// should be created when ActionLog is created
$this->assertCount(1, $actionLogs);
$results = (new ActionlogsTransformer())->transformActionlogs($actionLogs, 10);
$this->assertArrayHasKey('rows', $results);
$this->assertCount(1, $results['rows']);
}
public function testLogEntryForUpdatingReportTemplateCanBeDisplayedTransformed()
{
$reportTemplate = ReportTemplate::factory()->create();
$reportTemplate->update([
'options' => ['new' => 'value']
]);
$actionLogs = Actionlog::query()
->whereMorphedTo('item', ReportTemplate::class)
->where('action_type', 'update')
->get();
$this->assertCount(1, $actionLogs);
$results = (new ActionlogsTransformer())->transformActionlogs($actionLogs, 10);
$this->assertArrayHasKey('rows', $results);
$this->assertCount(1, $results['rows']);
}
public function testLogEntryForDeletingReportTemplateCanBeDisplayedTransformed()
{
$reportTemplate = ReportTemplate::factory()->create();
$reportTemplate->delete();
$actionLogs = Actionlog::query()
->whereMorphedTo('item', ReportTemplate::class)
->where('action_type', 'delete')
->get();
$this->assertCount(1, $actionLogs);
$results = (new ActionlogsTransformer())->transformActionlogs($actionLogs, 10);
$this->assertArrayHasKey('rows', $results);
$this->assertCount(1, $results['rows']);
}
}

View file

@ -0,0 +1,100 @@
<?php
namespace Tests\Unit\Models\ReportTemplates;
use App\Models\ReportTemplate;
use App\Models\User;
use PHPUnit\Framework\Attributes\Group;
use Tests\TestCase;
#[Group('custom-reporting')]
#[Group('activity-logging')]
class ReportTemplateActivityLoggingTest extends TestCase
{
public function testCreatingReportTemplateIsLogged()
{
$user = User::factory()->create();
$this->actingAs($user);
$reportTemplate = ReportTemplate::factory()->create();
$this->assertDatabaseHas('action_logs', [
'created_by' => $user->id,
'action_type' => 'create',
'target_id' => null,
'target_type' => null,
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
]);
}
public function testUpdatingReportTemplateIsLogged()
{
$user = User::factory()->create();
$this->actingAs($user);
$reportTemplate = ReportTemplate::factory()->create([
'name' => 'Name A',
'options' => [
'company' => '1',
'location' => '1',
'by_company_id' => ['1'],
'by_location_id' => ['17'],
],
]);
$reportTemplate->update([
'name' => 'Another Name',
'options' => [
'company' => '1',
'by_company_id' => ['1'],
],
]);
$this->assertDatabaseHas('action_logs', [
'created_by' => $user->id,
'action_type' => 'update',
'target_id' => null,
'target_type' => null,
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'log_meta' => json_encode([
'name' => [
'old' => 'Name A',
'new' => 'Another Name'
],
'options' => [
'old' => [
'company' => '1',
'location' => '1',
'by_company_id' => ['1'],
'by_location_id' => ['17'],
],
'new' => [
'company' => '1',
'by_company_id' => ['1'],
],
],
]),
]);
}
public function testDeletingReportTemplateIsLogged()
{
$user = User::factory()->create();
$this->actingAs($user);
$reportTemplate = ReportTemplate::factory()->create();
$reportTemplate->delete();
$this->assertDatabaseHas('action_logs', [
'created_by' => $user->id,
'action_type' => 'delete',
'target_id' => null,
'target_type' => null,
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
]);
}
}

View file

@ -0,0 +1,209 @@
<?php
namespace Tests\Unit\Models\ReportTemplates;
use App\Models\Department;
use App\Models\Location;
use App\Models\ReportTemplate;
use PHPUnit\Framework\Attributes\Group;
use Tests\TestCase;
#[Group('custom-reporting')]
class ReportTemplateParsingValuesTest extends TestCase
{
public function testParsingValuesOnNonExistentReportTemplate()
{
$unsavedTemplate = new ReportTemplate;
// checkmarkValue() should be "checked" (1) by default
$this->assertEquals('1', $unsavedTemplate->checkmarkValue('is_a_checkbox_field'));
// radioValue() defaults to false but can be overridden
$this->assertFalse($unsavedTemplate->radioValue('value_on_unsaved_template', 'can_be_anything'));
$this->assertTrue($unsavedTemplate->radioValue('value_on_unsaved_template', 'can_be_anything', true));
// selectValue() should be null by default
$this->assertNull($unsavedTemplate->selectValue('value_on_unsaved_template'));
$this->assertNull($unsavedTemplate->selectValue('value_on_unsaved_template'), Location::class);
// selectValues() should be an empty array by default
$this->assertIsArray($unsavedTemplate->selectValues('value_on_unsaved_template'));
$this->assertEmpty($unsavedTemplate->selectValues('value_on_unsaved_template'));
$this->assertEmpty($unsavedTemplate->selectValues('value_on_unsaved_template'), Location::class);
// textValue() should be an empty string by default
$this->assertEquals('', $unsavedTemplate->selectValue('value_on_unsaved_template'));
}
public function testParsingCheckmarkValue()
{
$template = ReportTemplate::factory()->create([
'options' => [
'is_a_checkbox_field' => '1',
// This shouldn't happen since unchecked inputs are
// not submitted, but we should handle it anyway
'is_checkbox_field_with_zero' => '0',
],
]);
$this->assertEquals('1', $template->checkmarkValue('is_a_checkbox_field'));
$this->assertEquals('0', $template->checkmarkValue('non_existent_key'));
$this->assertEquals('0', $template->checkmarkValue('is_checkbox_field_with_zero'));
$this->assertEquals('0', (new ReportTemplate)->checkmarkValue('non_existent_key_that_is_overwritten_to_default_to_zero', '0'));
}
public function testParsingTextValue()
{
$template = ReportTemplate::factory()->create([
'options' => [
'is_a_text_field' => 'some text',
],
]);
$this->assertEquals('some text', $template->textValue('is_a_text_field'));
$this->assertEquals('', $template->textValue('non_existent_key'));
$this->assertEquals('', (new ReportTemplate)->textValue('is_a_text_field'));
$this->assertEquals('my fallback', (new ReportTemplate)->textValue('non_existent_key', 'my fallback'));
}
public function testParsingRadioValue()
{
$template = ReportTemplate::factory()->create([
'options' => ['property_that_exists' => '1'],
]);
$this->assertTrue($template->radioValue('property_that_exists', '1'));
// check non-existent key returns false
$this->assertFalse($template->radioValue('non_existent_property', 'doesnt_matter'));
// check can return fallback value
$this->assertTrue($template->radioValue('non_existent_property', 'doesnt_matter', true));
}
public function testParsingSelectValue()
{
$template = ReportTemplate::factory()->create([
'options' => [
'is_a_text_field_as_well' => '4',
'contains_a_null_value' => null,
],
]);
$this->assertEquals('4', $template->selectValue('is_a_text_field_as_well'));
$this->assertEquals('', $template->selectValue('non_existent_key'));
$this->assertNull($template->selectValue('contains_a_null_value'));
}
public function testParsingSelectValues()
{
$template = ReportTemplate::factory()->create([
'options' => [
'an_array' => ['2', '3', '4'],
'an_empty_array' => [],
'an_array_containing_null' => [null],
],
]);
$this->assertEquals(['2', '3', '4'], $template->selectValues('an_array'));
$this->assertEquals([], $template->selectValues('an_empty_array'));
$this->assertEquals([null], $template->selectValues('an_array_containing_null'));
$this->assertEquals([], $template->selectValues('non_existent_key'));
}
public function testSelectValueDoesNotIncludeDeletedOrNonExistentModels()
{
[$locationA, $locationB] = Location::factory()->count(2)->create();
$invalidId = 10000;
$templateWithValidId = ReportTemplate::factory()->create([
'options' => ['single_value' => $locationA->id],
]);
$templateWithDeletedId = ReportTemplate::factory()->create([
'options' => ['single_value' => $locationB->id],
]);
$locationB->delete();
$templateWithInvalidId = ReportTemplate::factory()->create([
'options' => ['single_value' => $invalidId],
]);
$this->assertEquals(
$locationA->id,
$templateWithValidId->selectValue('single_value', Location::class)
);
$this->assertNull($templateWithDeletedId->selectValue('single_value', Location::class));
$this->assertNull($templateWithInvalidId->selectValue('single_value', Location::class));
$this->assertNull((new ReportTemplate)->selectValue('value_on_unsaved_template', Location::class));
}
public function testSelectValuesDoNotIncludeDeletedOrNonExistentModels()
{
[$locationA, $locationB] = Location::factory()->count(2)->create();
$invalidId = 10000;
$template = ReportTemplate::factory()->create([
'options' => [
'array_of_ids' => [
$locationA->id,
$locationB->id,
$invalidId,
],
],
]);
$locationB->delete();
$parsedValues = $template->selectValues('array_of_ids', Location::class);
$this->assertContains($locationA->id, $parsedValues);
$this->assertNotContains($locationB->id, $parsedValues);
$this->assertNotContains($invalidId, $parsedValues);
}
public function testGracefullyHandlesSingleSelectBecomingMultiSelect()
{
$department = Department::factory()->create();
$templateWithValue = ReportTemplate::factory()->create([
'options' => ['single_value' => 'a string'],
]);
$templateWithModelId = ReportTemplate::factory()->create([
'options' => ['by_dept_id' => $department->id],
]);
// If nothing is selected for a single select then it is stored
// as null and should be returned as an empty array.
$templateWithNull = ReportTemplate::factory()->create([
'options' => ['by_dept_id' => null],
]);
$this->assertEquals(['a string'], $templateWithValue->selectValues('single_value'));
$this->assertContains($department->id, $templateWithModelId->selectValues('by_dept_id', Department::class));
$this->assertEquals([], $templateWithNull->selectValues('by_dept_id'));
}
public function testGracefullyHandlesMultiSelectBecomingSingleSelectBySelectingTheFirstValue()
{
[$departmentA, $departmentB] = Department::factory()->count(2)->create();
// Given report templates saved with a property that is an array of values
$templateWithValuesInArray = ReportTemplate::factory()->create([
'options' => ['array_of_values' => [3, 'a string']],
]);
$templateWithModelIdsInArray = ReportTemplate::factory()->create([
'options' => ['array_of_model_ids' => [$departmentA->id, $departmentB->id]],
]);
$this->assertEquals(3, $templateWithValuesInArray->selectValue('array_of_values'));
$this->assertEquals(
$departmentA->id,
$templateWithModelIdsInArray->selectValue('array_of_model_ids', Department::class)
);
}
}