diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php index b26887b6ce..c672781e6f 100644 --- a/app/Http/Controllers/Api/AssetsController.php +++ b/app/Http/Controllers/Api/AssetsController.php @@ -613,7 +613,7 @@ class AssetsController extends Controller $asset->image = $asset->getImageUrl(); } - return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success'))); + return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.create.success'))); } return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200); @@ -692,7 +692,7 @@ class AssetsController extends Controller $asset->image = $asset->getImageUrl(); } - return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success'))); + return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.update.success'))); } return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200); diff --git a/app/Http/Requests/StoreAssetRequest.php b/app/Http/Requests/StoreAssetRequest.php index 74988b6c62..8e7559673e 100644 --- a/app/Http/Requests/StoreAssetRequest.php +++ b/app/Http/Requests/StoreAssetRequest.php @@ -4,6 +4,8 @@ namespace App\Http\Requests; use App\Models\Asset; use App\Models\Company; +use Carbon\Carbon; +use Carbon\Exceptions\InvalidFormatException; use Illuminate\Support\Facades\Gate; class StoreAssetRequest extends ImageUploadRequest @@ -27,6 +29,8 @@ class StoreAssetRequest extends ImageUploadRequest ? Company::getIdForCurrentUser($this->company_id) : $this->company_id; + $this->parseLastAuditDate(); + $this->merge([ 'asset_tag' => $this->asset_tag ?? Asset::autoincrement_asset(), 'company_id' => $idForCurrentUser, @@ -48,4 +52,21 @@ class StoreAssetRequest extends ImageUploadRequest return $rules; } + + private function parseLastAuditDate(): void + { + if ($this->input('last_audit_date')) { + try { + $lastAuditDate = Carbon::parse($this->input('last_audit_date')); + + $this->merge([ + 'last_audit_date' => $lastAuditDate->startOfDay()->format('Y-m-d H:i:s'), + ]); + } catch (InvalidFormatException $e) { + // we don't need to do anything here... + // we'll keep the provided date in an + // invalid format so validation picks it up later + } + } + } } diff --git a/app/Models/Asset.php b/app/Models/Asset.php index c2a2a8d995..2830eca7e5 100644 --- a/app/Models/Asset.php +++ b/app/Models/Asset.php @@ -97,6 +97,8 @@ class Asset extends Depreciable 'warranty_months' => 'nullable|numeric|digits_between:0,240', 'last_checkout' => 'nullable|date_format:Y-m-d H:i:s', 'expected_checkin' => 'nullable|date', + 'last_audit_date' => 'nullable|date_format:Y-m-d H:i:s', + 'next_audit_date' => 'nullable|date|after:last_audit_date', 'location_id' => 'nullable|exists:locations,id', 'rtd_location_id' => 'nullable|exists:locations,id', 'purchase_date' => 'nullable|date|date_format:Y-m-d', diff --git a/app/Models/Labels/Tapes/Dymo/Label_Writer_2112283.php b/app/Models/Labels/Tapes/Dymo/Label_Writer_2112283.php new file mode 100644 index 0000000000..e1305bd068 --- /dev/null +++ b/app/Models/Labels/Tapes/Dymo/Label_Writer_2112283.php @@ -0,0 +1,89 @@ +getPrintableArea(); + + $currentX = $pa->x1; + $currentY = $pa->y1; + $usableWidth = $pa->w; + + $barcodeSize = $pa->h - self::TAG_SIZE; + + if ($record->has('barcode2d')) { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y2 - self::TAG_SIZE, + 'freesans', 'b', self::TAG_SIZE, 'C', + $barcodeSize, self::TAG_SIZE, true, 0 + ); + static::write2DBarcode( + $pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type, + $currentX, $currentY, + $barcodeSize, $barcodeSize + ); + $currentX += $barcodeSize + self::BARCODE_MARGIN; + $usableWidth -= $barcodeSize + self::BARCODE_MARGIN; + } else { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y2 - self::TAG_SIZE, + 'freesans', 'b', self::TAG_SIZE, 'R', + $usableWidth, self::TAG_SIZE, true, 0 + ); + } + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $currentX, $currentY, + 'freesans', 'b', self::TITLE_SIZE, 'L', + $usableWidth, self::TITLE_SIZE, true, 0 + ); + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, (($field['label']) ? $field['label'].' ' : '') . $field['value'], + $currentX, $currentY, + 'freesans', '', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.3 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + + if ($record->has('barcode1d')) { + static::write1DBarcode( + $pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type, + $currentX, $barcodeSize + self::BARCODE_MARGIN, $usableWidth - self::TAG_SIZE, self::TAG_SIZE + ); + } + } + +} diff --git a/resources/views/hardware/view.blade.php b/resources/views/hardware/view.blade.php index a32503d7ea..ce814d5c76 100755 --- a/resources/views/hardware/view.blade.php +++ b/resources/views/hardware/view.blade.php @@ -904,27 +904,18 @@ @endcan @can('delete', $asset) - @if ($asset->deleted_at=='') -
- +
+ @if ($asset->deleted_at=='') + {{ trans('general.delete') }} -
- @endif + @else +
+ @csrf + +
+ @endif @endcan - @if ($asset->deleted_at!='') -
-
- @csrf - -
-
- @endif - - @if ($snipeSettings->qr_code=='1') - QR code for {{ $asset->getDisplayNameAttribute() }} - @endif - @if (($asset->assignedTo) && ($asset->deleted_at==''))

{{ trans('admin/hardware/form.checkedout_to') }}

@@ -982,6 +973,13 @@
@endif + + @if ($snipeSettings->qr_code=='1') +
+ QR code for {{ $asset->getDisplayNameAttribute() }} +
+ @endif +
diff --git a/resources/views/models/view.blade.php b/resources/views/models/view.blade.php index 91f112d8aa..76d3322998 100755 --- a/resources/views/models/view.blade.php +++ b/resources/views/models/view.blade.php @@ -236,6 +236,12 @@ @endif + @if ($model->created_at) +
  • {{ trans('general.created_at') }}: + {{ Helper::getFormattedDateObject($model->created_at, 'datetime', false) }} +
  • + @endif + @if ($model->min_amt)
  • {{ trans('general.min_amt') }}: {{$model->min_amt }} @@ -313,11 +319,6 @@
  • @endif - - - @if ($model->deleted_at!='') -

  • {{ trans('admin/models/general.restore') }}
  • - @endif @if ($model->note) @@ -337,22 +338,32 @@ @can('create', \App\Models\AssetModel::class)
    - {{ trans('admin/models/table.clone') }} + {{ trans('admin/models/table.clone') }}
    @endcan @can('delete', \App\Models\AssetModel::class) @if ($model->assets_count > 0) -
    - +
    @else -
    - - {{ trans('general.delete') }} -
    + @endif + + +
    + @if ($model->deleted_at!='') +
    + @csrf + +
    + @else + + {{ trans('general.delete') }} + @endif +
    + @endcan diff --git a/tests/Feature/Api/Assets/AssetStoreTest.php b/tests/Feature/Api/Assets/AssetStoreTest.php index ceae053648..e98da36cf9 100644 --- a/tests/Feature/Api/Assets/AssetStoreTest.php +++ b/tests/Feature/Api/Assets/AssetStoreTest.php @@ -65,8 +65,7 @@ class AssetStoreTest extends TestCase $this->assertEquals('random_string', $asset->asset_tag); $this->assertEquals($userAssigned->id, $asset->assigned_to); $this->assertTrue($asset->company->is($company)); - // I don't see this on the GUI side either, but it's in the docs so I'm guessing that's a mistake? It wasn't in the controller. - // $this->assertEquals('2023-09-03', $asset->last_audit_date); + $this->assertEquals('2023-09-03 00:00:00', $asset->last_audit_date->format('Y-m-d H:i:s')); $this->assertTrue($asset->location->is($location)); $this->assertTrue($asset->model->is($model)); $this->assertEquals('A New Asset', $asset->name); @@ -82,6 +81,52 @@ class AssetStoreTest extends TestCase $this->assertEquals(10, $asset->warranty_months); } + public function testSetsLastAuditDateToMidnightOfProvidedDate() + { + $response = $this->actingAsForApi(User::factory()->superuser()->create()) + ->postJson(route('api.assets.store'), [ + 'last_audit_date' => '2023-09-03 12:23:45', + 'asset_tag' => '1234', + 'model_id' => AssetModel::factory()->create()->id, + 'status_id' => Statuslabel::factory()->create()->id, + ]) + ->assertOk() + ->assertStatusMessageIs('success'); + + $asset = Asset::find($response['payload']['id']); + $this->assertEquals('00:00:00', $asset->last_audit_date->format('H:i:s')); + } + + public function testLastAuditDateCanBeNull() + { + $response = $this->actingAsForApi(User::factory()->superuser()->create()) + ->postJson(route('api.assets.store'), [ + // 'last_audit_date' => '2023-09-03 12:23:45', + 'asset_tag' => '1234', + 'model_id' => AssetModel::factory()->create()->id, + 'status_id' => Statuslabel::factory()->create()->id, + ]) + ->assertOk() + ->assertStatusMessageIs('success'); + + $asset = Asset::find($response['payload']['id']); + $this->assertNull($asset->last_audit_date); + } + + public function testNonDateUsedForLastAuditDateReturnsValidationError() + { + $response = $this->actingAsForApi(User::factory()->superuser()->create()) + ->postJson(route('api.assets.store'), [ + 'last_audit_date' => 'this-is-not-valid', + 'asset_tag' => '1234', + 'model_id' => AssetModel::factory()->create()->id, + 'status_id' => Statuslabel::factory()->create()->id, + ]) + ->assertStatusMessageIs('error'); + + $this->assertNotNull($response->json('messages.last_audit_date')); + } + public function testArchivedDepreciateAndPhysicalCanBeNull() { $model = AssetModel::factory()->ipadModel()->create();