From 6a06875b3ca59bf1c86d1fa82f2f1027f6780640 Mon Sep 17 00:00:00 2001 From: mikeburg Date: Sun, 17 Nov 2024 12:41:48 -0800 Subject: [PATCH] Implemented asset expiry. --- app/components/asset-checkout-form.hbs | 11 +++ app/components/asset-checkout-form.js | 13 +++ app/controllers/ops/assets.js | 52 +++++++++++- app/models/asset.js | 3 + app/templates/ops/assets.hbs | 107 +++++++++++++++---------- 5 files changed, 144 insertions(+), 42 deletions(-) diff --git a/app/components/asset-checkout-form.hbs b/app/components/asset-checkout-form.hbs index fc5ec8b6b..eca9cfe12 100644 --- a/app/components/asset-checkout-form.hbs +++ b/app/components/asset-checkout-form.hbs @@ -32,6 +32,17 @@ Show Asset History + {{else if this.assetExpired}} + + Asset Has Expired + + Asset {{this.assetExpired.barcode}} has expired and should not be handed out. Please place it + in the designated pile for return to the vendor. + + + + + {{else}}
{{/if}} diff --git a/app/components/asset-checkout-form.js b/app/components/asset-checkout-form.js index 4a47e817e..100686667 100644 --- a/app/components/asset-checkout-form.js +++ b/app/components/asset-checkout-form.js @@ -17,6 +17,8 @@ export default class AssetCheckoutFormComponent extends Component { @tracked isSubmitting = false; @tracked showHistory = false; + @tracked assetExpired = null; + constructor() { super(...arguments); @@ -33,6 +35,7 @@ export default class AssetCheckoutFormComponent extends Component { clearErrors() { this.barcodeNotFound = false; this.barcodeCheckedOut = null; + this.assetExpired = null; } /** @@ -74,6 +77,8 @@ export default class AssetCheckoutFormComponent extends Component { this.barcodeCheckedOut = result; this.barcodeCheckedOut.barcode = barcode; break; + case 'expired': + this.assetExpired = result; } } catch (response) { this.house.handleErrorResponse(response) @@ -116,4 +121,12 @@ export default class AssetCheckoutFormComponent extends Component { this.modal.info('Asset not checked out', 'A barcode was entered, yet was not checked out. Either complete the check out process, or blank the barcode field before clicking on another tab.'); } + /** + * Close up the expired asset dialog + */ + + @action + closeExpiredDialog() { + this.assetExpired = null; + } } diff --git a/app/controllers/ops/assets.js b/app/controllers/ops/assets.js index 023523ff3..ac2509652 100644 --- a/app/controllers/ops/assets.js +++ b/app/controllers/ops/assets.js @@ -13,11 +13,26 @@ import { TYPE_VEHICLE } from "clubhouse/models/asset"; +const CSV_COLUMNS = [ + {title: 'Barcode', key: 'barcode'}, + {title: 'Type', key: 'type'}, + {title: 'Description', key: 'description'}, + {title: 'Assignment', key: 'assigned'}, + {title: 'Category', key: 'category'}, + {title: 'Notes', key: 'notes'}, + {title: 'Year', key: 'year'}, + {title: 'Expires On', key: 'expires_on', format: 'date'}, + {title: 'Has Expired', key: 'has_expired'}, + {title: 'Created At', key: 'created_at'}, +]; + export default class OpsAssetsController extends ClubhouseController { queryParams = ['year']; @tracked descriptionFilter = 'All'; @tracked typeFilter = 'All'; + @tracked expireFilter = 'all'; + @tracked assets; @tracked assetForHistory; @@ -79,6 +94,20 @@ export default class OpsAssetsController extends ClubhouseController { } } + switch (this.expireFilter) { + case 'all': + break; + case 'expired': + assets = assets.filter((asset) => asset.has_expired); + break; + case 'not-expired': + assets = assets.filter((asset) => !asset.has_expired); + break; + default: + assets = assets.filter((asset) => asset.expires_on === this.expireFilter); + break; + } + assets.sort((a, b) => a.barcode.localeCompare(b.barcode)); return assets; @@ -96,12 +125,22 @@ export default class OpsAssetsController extends ClubhouseController { } get typeOptions() { - const options = _.uniqBy(this.assets, 'type').map((a) =>[a.typeLabel, a.type]); + const options = _.uniqBy(this.assets, 'type').map((a) => [a.typeLabel, a.type]); options.sort((a, b) => a[0].localeCompare(b[0])); options.unshift('All'); return options; } + get expireFilterOptions() { + const options = _.sortBy(_.uniqBy(this.assets.filter((a) => a.expires_on !== null), 'expires_on'), 'expires_on') + .map((a) => [a.expires_on, a.expires_on]); + + options.unshift(['Not Expired', 'not-expired']); + options.unshift(['Expired', 'expired']); + options.unshift(['All', 'all']); + return options; + } + @action async assetHistoryAction(asset) { this.assetForHistory = asset; @@ -238,4 +277,15 @@ export default class OpsAssetsController extends ClubhouseController { } }); } + + @action + exportToCSV() { + const assets = [...this.viewAssets]; + assets.forEach((asset) => { + asset.assigned = asset.perm_assign ? 'Event' : 'Shift'; + asset.has_expired = asset.has_expired ? 'Y' : '-'; + }); + + this.house.downloadCsv(`${this.year}-assets-csv`, CSV_COLUMNS, assets); + } } diff --git a/app/models/asset.js b/app/models/asset.js index a1be67010..ad3707fb2 100644 --- a/app/models/asset.js +++ b/app/models/asset.js @@ -30,6 +30,9 @@ export default class AssetModel extends Model { @attr('number') year; @attr('string', {readOnly: true}) created_at; + @attr('string') expires_on; + @attr('boolean', { readOnly: true}) has_expired; + get isRadio() { return this.type === TYPE_RADIO; } diff --git a/app/templates/ops/assets.hbs b/app/templates/ops/assets.hbs index 000c3d3d4..b0ea505d1 100644 --- a/app/templates/ops/assets.hbs +++ b/app/templates/ops/assets.hbs @@ -5,7 +5,7 @@ @skipPandemic={{true}} @onChange={{set-value this 'year'}} /> - Type Filter + Type
- Description Filter + Description
+ Expired? +
+ +
Action
New Asset
- Showing {{this.viewAssets.length}} of {{pluralize this.assets.length "asset"}} - - - - Barcode - Type - Description - Assigned - Actions - - - - - {{#each this.viewAssets key="id" as |asset|}} - - {{asset.barcode}} - {{asset.typeLabel}} - - - - {{asset.assignmentLabel}} - - - {{fa-icon "rectangle-list" right=1}} History - - - {{fa-icon "edit" right=1}} Edit - - - - {{else if this.assets}} - - No assets matched. - - {{else}} - No assets were found for {{this.year}}?!? - {{/each}} - - + + <:title> Showing {{this.viewAssets.length}} of {{pluralize this.assets.length "asset"}} + <:body> + + + + + Barcode + Type + Description + Assigned + Expires On + Actions + + + + {{#each this.viewAssets key="id" as |asset|}} + + {{asset.barcode}} + {{asset.typeLabel}} + + + + {{asset.assignmentLabel}} + + {{#if asset.expires_on}} + {{ymd-format asset.expires_on}} + {{#if asset.has_expired}} + expired + {{/if}} + {{else}} + - + {{/if}} + + + + {{fa-icon "rectangle-list" right=1}} History + + + {{fa-icon "edit" right=1}} Edit + + + + {{else if this.assets}} + + No assets matched. + + {{else}} + No assets were found for {{this.year}}?!? + {{/each}} + + + + {{#if this.entry}} + + +