var HampLoanerUtils = Class.create(); HampLoanerUtils.prototype = { initialize: function () { }, getModelsWithLoanerAssets: function (location) { var filter; var modelsarray = []; var assetsGa = new GlideAggregate('alm_asset'); HampLoanerUtils.addLoanerBaseQuery(assetsGa, location); assetsGa.addQuery('install_status', 'NOT IN', HampLoanerUtils.ASSET_IN_USE_STATUSES); assetsGa.addQuery('excluded_from_ham', false); assetsGa.setGroup(true); assetsGa.groupBy('model.sys_id'); assetsGa.query(); while (assetsGa.next()) { modelsarray.push(assetsGa.getValue('model.sys_id')); } var loanerOrdersGa = new GlideAggregate(HampLoanerUtils.LOANER_ORDER_TABLE); HampLoanerUtils.addInUseFunctioningAssetsQuery(loanerOrdersGa, location, ''); loanerOrdersGa.setGroup(true); loanerOrdersGa.groupBy('model.sys_id'); loanerOrdersGa.query(); while (loanerOrdersGa.next()) { modelsarray.push(loanerOrdersGa.getValue('model.sys_id')); } if(HAMUtils.HAS_ONLY_TNI_ENTITLEMENT) { var filteredModels = HAMUtils.filterOutNonTNIModels(modelsarray); filter = 'sys_idIN' + filteredModels; } else { filter = 'sys_idIN' + modelsarray; } return filter; }, getAllLoanerAssetsOfStockroom: function (stockroomGr) { var assets = []; assets = assets.concat(this.getAllLoanerAssetsInStockroom(stockroomGr)); assets = assets.concat(this.getAllInUseLoanerAssetsOfAStockroom(stockroomGr)); return assets; }, getAllLoanerAssetsInStockroom: function (stockroomGr) { var eamModelExt = HAMUtils.getEAMModelClasses(); var eamAssetExt = HAMUtils.getEAMAssetClasses(); var assetsGa = new GlideAggregate('alm_asset'); assetsGa.addQuery('asset_function', 'loaner'); assetsGa.addQuery('stockroom', stockroomGr.getUniqueValue()); // Exclude EAM assets and EAM models assetsGa.addQuery('model.sys_class_name', 'NOT IN', eamModelExt); assetsGa.addQuery('sys_class_name', 'NOT IN', eamAssetExt); assetsGa.setGroup(true); assetsGa.groupBy('sys_id'); assetsGa.query(); var assetsarray = []; while (assetsGa.next()) { assetsarray.push(assetsGa.getValue('sys_id')); } return assetsarray; }, getAllInUseLoanerAssetsOfAStockroom: function (stockroomGr) { var loanerOrdersGa = new GlideAggregate(HampLoanerUtils.LOANER_ORDER_TABLE); loanerOrdersGa.addQuery('asset_stockroom', stockroomGr.getUniqueValue()); loanerOrdersGa.addQuery('asset.install_status', HAMConstants.ASSET_STATUSES.IN_USE); loanerOrdersGa.addQuery('asset.asset_function', 'loaner'); loanerOrdersGa.addQuery('stage', HampLoanerUtils.STAGE_DEPLOYED); loanerOrdersGa.setGroup(true); loanerOrdersGa.groupBy('asset.sys_id'); loanerOrdersGa.query(); var assetsarray = []; while (loanerOrdersGa.next()) { assetsarray.push(loanerOrdersGa.getValue('asset.sys_id')); } return assetsarray; }, getFunctioningAssets: function (location, model) { var functioningAssets = []; functioningAssets = functioningAssets.concat(this.getInStockFunctioningAssets(location, model)); functioningAssets = functioningAssets.concat(this.getInUseFunctioningAssets(location, model)); return functioningAssets; }, getInStockFunctioningAssets: function (location, model) { var assetsGa = new GlideAggregate('alm_asset'); HampLoanerUtils.addLoanerBaseQuery(assetsGa, location, model); HampLoanerUtils.addInStockFunctioningAssetsQuery(assetsGa); assetsGa.setGroup(true); assetsGa.groupBy('sys_id'); assetsGa.query(); var assetsarray = []; while (assetsGa.next()) { assetsarray.push(assetsGa.getValue('sys_id')); } return assetsarray; }, getInUseFunctioningAssets: function (location, model) { var loanerOrdersGa = new GlideAggregate(HampLoanerUtils.LOANER_ORDER_TABLE); HampLoanerUtils.addInUseFunctioningAssetsQuery(loanerOrdersGa, location, model); loanerOrdersGa.setGroup(true); loanerOrdersGa.groupBy('asset.sys_id'); loanerOrdersGa.query(); var assetsarray = []; while (loanerOrdersGa.next()) { assetsarray.push(loanerOrdersGa.getValue('asset.sys_id')); } return assetsarray; }, getActiveAssetAllocations: function (location, model, startDate, returnDate, leadTime, forLoanerOrder) { var loanerOrdersGa = new GlideAggregate(HampLoanerUtils.LOANER_ORDER_TABLE); loanerOrdersGa.addQuery('location', location); loanerOrdersGa.addQuery('model', model); if (forLoanerOrder) { loanerOrdersGa.addQuery('sys_id', '!=', forLoanerOrder); } HampLoanerUtils.addLoanerOrdersOverlapQuery(loanerOrdersGa, startDate, returnDate, leadTime); HampLoanerUtils.addDomainFilterQuery(loanerOrdersGa); var activeStages = [HampLoanerUtils.STAGE_NEW, HampLoanerUtils.STAGE_PREPARE, HampLoanerUtils.STAGE_DEPLOYED]; loanerOrdersGa.addQuery('stage', activeStages); loanerOrdersGa.setGroup(true); loanerOrdersGa.groupBy('asset.sys_id'); loanerOrdersGa.query(); var assetsarray = []; while (loanerOrdersGa.next()) { assetsarray.push(loanerOrdersGa.getValue('asset.sys_id')); } return assetsarray; }, getAssetsAvailableToAllocate: function (location, model, startDate, returnDate, leadTime, forLoanerOrder) { var functioningAssets = this.getFunctioningAssets(location, model); // eslint-disable-next-line max-len var activeAllocations = this.getActiveAssetAllocations(location, model, startDate, returnDate, leadTime, forLoanerOrder); var availableAssets = []; for (var i = 0; i < functioningAssets.length; i++) { if (activeAllocations.indexOf(functioningAssets[i]) === -1) { availableAssets.push(functioningAssets[i]); } } return availableAssets; }, getLoanerAssets: function (current) { var loanerOrderGr = null; if (current.getTableName() === HampLoanerUtils.LOANER_ORDER_TABLE) { loanerOrderGr = current; } else if (current.getTableName() === HampLoanerUtils.LOANER_TASK_TABLE) { loanerOrderGr = current.loaner_order; } if (gs.nil(loanerOrderGr)) { return ''; } var location = loanerOrderGr.location; var model = loanerOrderGr.model; var startDate = loanerOrderGr.start_date; var returnDate = loanerOrderGr.return_date; var leadTime = loanerOrderGr.lead_time; var assetsarray = this.getAssetsAvailableToAllocate(location, model, startDate, returnDate, leadTime); var filter = 'sys_idIN' + assetsarray; return filter; }, updateAssetPrepared: function (current) { new global.GlideQuery('sn_hamp_loaner_asset_order') .where('sys_id', current.loaner_order) .update({ asset_prepared: true, }); }, updateAssetStockroomOnLoanerOrder: function (loanerTaskGr) { var assetStockroom = loanerTaskGr.loaner_order.asset.stockroom; if (!gs.nil(assetStockroom)) { new global.GlideQuery(HampLoanerUtils.LOANER_ORDER_TABLE) .where('sys_id', loanerTaskGr.loaner_order) .update({ asset_stockroom: assetStockroom, }); } }, updateReturnedOn: function (current) { var gDate = new GlideDateTime(); new global.GlideQuery('sn_hamp_loaner_asset_order') .where('sys_id', current.loaner_order) .update({ returned_on: gDate.getLocalDate(), }); }, updateAsset: function (assetId, assetData, isConsumable) { if (isConsumable) { delete assetData.work_notes; } new global.GlideQuery('alm_asset') .where('sys_id', assetId) .update(assetData); if (assetData.work_notes) { var assetGr = HAMUtils.getAsGlideRecord(HAMConstants.ALM_ASSET_TABLE, assetId); assetGr.work_notes = assetData.work_notes; assetGr.update(); } }, cancelLoanerOrder: function (loanerOrderId) { var isAssetDeployed = new global.GlideQuery(HampLoanerUtils.LOANER_TASK_TABLE) .where('loaner_order', loanerOrderId) .where('task_name', 'deploy') .where('state', 3) .selectOne() .isPresent(); if (isAssetDeployed) { gs.addErrorMessage(gs.getMessage('Loaner asset order cannot be cancelled once the asset is deployed')); return; } var loanerOrderGr = new global.GlideQuery('sn_hamp_loaner_asset_order') .where('sys_id', loanerOrderId) .toGlideRecord(); loanerOrderGr.query(); loanerOrderGr.next(); loanerOrderGr.stage = 'cancelled'; loanerOrderGr.work_notes = gs.getMessage('Loaner order is cancelled by {0}', gs.getUserDisplayName()); loanerOrderGr.update(); new global.GlideQuery('sn_hamp_loaner_asset_task') .where('loaner_order', loanerOrderId) .where('active', true) .updateMultiple({ state: 4, }); }, triggerLoanerFlow: function (loanerOrder) { var defaultFlow = 'sn_hamp.loaner_asset_request_flow'; var LOANER_DECISION_ID = 'f9a23e38739310107e88ef66fbf6a7db'; var decisionInputs = {}; decisionInputs.loaner_asset_order = loanerOrder.sys_id; var flow = HAMUtils.getFlowFromDecisionTable(LOANER_DECISION_ID, decisionInputs, defaultFlow); var inputs = {}; inputs.current = loanerOrder; inputs.table_name = 'sn_hamp_loaner_asset_order'; var flowContextID = sn_hamp.HAMUtils.triggerFlowAsyncronously(flow, inputs); if (!gs.nil(flowContextID)) { new global.GlideQuery(HampLoanerUtils.LOANER_ORDER_TABLE) .where('sys_id', loanerOrder.sys_id) .update({ flow_context: flowContextID, }); } }, earlyReturnLoanerAsset: function (loanerOrder, loanerAsset, returnedOn, stockroom, isAssetFunctional) { var loanerGq = new global.GlideQuery(HampLoanerUtils.LOANER_ORDER_TABLE) .where('sys_id', loanerOrder); var loanerGr = loanerGq.toGlideRecord(); loanerGr.query(); loanerGr.next(); var returnedOnInternalFormat = HAMUtils.getDateInInternalFormat(returnedOn); loanerGq.update({ asset_returned: 'Y', returned_on: returnedOnInternalFormat, is_asset_functional: isAssetFunctional, }); var reclaimTaskId; new global.GlideQuery(HampLoanerUtils.LOANER_TASK_TABLE) .where('loaner_order', loanerOrder) .where('task_name', 'reclaim') .selectOne('sys_id') .ifPresent(function (task) { reclaimTaskId = task.sys_id; }); if (!gs.nil(reclaimTaskId)) { new global.GlideQuery(HampLoanerUtils.LOANER_TASK_TABLE) .where('sys_id', reclaimTaskId) .update({ state: 3, assigned_to: gs.getUserID(), return_stockroom: stockroom, }); } else { var loanerTaskGr = new GlideRecord('sn_hamp_loaner_asset_task'); loanerTaskGr.initialize(); loanerTaskGr.setValue('parent', loanerOrder); loanerTaskGr.setValue('loaner_order', loanerOrder); loanerTaskGr.setValue('task_name', 'reclaim'); loanerTaskGr.setValue('state', 3); loanerTaskGr.setValue('assigned_to', gs.getUserID()); loanerTaskGr.setValue('return_stockroom', stockroom); loanerTaskGr.setValue('short_description', gs.getMessage('Reclaim loaner asset from user')); // eslint-disable-next-line max-len loanerTaskGr.setValue('description', gs.getMessage('Reclaim loaner asset from user and return to loaner pool')); reclaimTaskId = loanerTaskGr.insert(); } var reclaimLoanerTaskGr = HAMUtils.getAsGlideRecord(HampLoanerUtils.LOANER_TASK_TABLE, reclaimTaskId); this.updateAssetOnReturn(reclaimLoanerTaskGr); }, updateAssetOnReturn: function (loanerTaskGr /* reclaim task */) { var returnStockroom = String(loanerTaskGr.return_stockroom); var loanerOrderGr = loanerTaskGr.loaner_order; var isAssetFunctional = String(loanerOrderGr.is_asset_functional); var loanerAssetGr = loanerOrderGr.asset; var loanerAssetID = loanerAssetGr.sys_id; var assetUpdateJSON = {}; assetUpdateJSON = { install_status: parseInt(HAMConstants.ASSET_STATUSES.IN_STOCK, 10), substatus: HAMConstants.ASSET_SUB_STATUSES.AVAILABLE, stockroom: returnStockroom, reserved_for: null, assigned_to: null, assigned: null, install_date: null, managed_by: null, }; var msgParams = [loanerAssetGr.getDisplayValue(), loanerTaskGr.getDisplayValue()]; if (isAssetFunctional === 'N') { assetUpdateJSON.substatus = HAMConstants.ASSET_SUB_STATUSES.PENDING_REPAIR; // eslint-disable-next-line max-len assetUpdateJSON.work_notes = gs.getMessage('Asset {0} updated to state In stock and substate Pending repair as part of task {1}', msgParams); } else { // eslint-disable-next-line max-len assetUpdateJSON.work_notes = gs.getMessage('Asset {0} updated to state In stock and substate Available as part of task {1}', msgParams); } // Check if the asset is part of another loaner order var otherLoanerOrder = HampLoanerUtils.getAnotherLoanerOrderWithAsset(loanerAssetID, loanerOrderGr); // If asset is part of another loaner orders, then do not clear process fields // as it would result in consumable records getting merged. if (gs.nil(otherLoanerOrder)) { assetUpdateJSON.process_table = null; assetUpdateJSON.process_id = null; } this.updateAsset(loanerAssetID, assetUpdateJSON, HAMUtils.isConsumableClassAsset(loanerAssetGr)); // If not part of another loaner order, return. Else stamp other loaner order details on asset if (gs.nil(otherLoanerOrder)) { return; } var otherLoanerOrderStage = String(otherLoanerOrder.stage); if (otherLoanerOrderStage === HampLoanerUtils.STAGE_NEW || otherLoanerOrderStage === HampLoanerUtils.STAGE_PREPARE) { assetUpdateJSON = { install_status: parseInt(HAMConstants.ASSET_STATUSES.IN_STOCK, 10), substatus: HAMConstants.ASSET_SUB_STATUSES.RESERVED, stockroom: returnStockroom, reserved_for: String(otherLoanerOrder.requested_for), assigned_to: null, assigned: null, install_date: null, managed_by: null, process_table: otherLoanerOrder.getTableName(), process_id: otherLoanerOrder.getUniqueValue(), }; if (isAssetFunctional === 'N') { assetUpdateJSON.substatus = HAMConstants.ASSET_SUB_STATUSES.PENDING_REPAIR; } else { assetUpdateJSON.work_notes = this.getAssetReservedWorkNote(loanerAssetGr, otherLoanerOrder); } this.updateAsset(loanerAssetID, assetUpdateJSON, HAMUtils.isConsumableClassAsset(loanerAssetGr)); } }, updateAssetOnPrepareCompletion: function (prepareTaskGr) { var loanerOrderGr = prepareTaskGr.loaner_order; var requestedFor = String(loanerOrderGr.requested_for); var loanerAssetGr = loanerOrderGr.asset; var loanerAssetID = String(loanerAssetGr.sys_id); var msgParams = [loanerAssetGr.getDisplayValue(), prepareTaskGr.getDisplayValue()]; // eslint-disable-next-line max-len var preparedWorkNote = gs.getMessage('Asset {0} updated to state In stock and substate Pending install as part of task {1}', msgParams); var assetUpdateJSON = { install_status: parseInt(HAMConstants.ASSET_STATUSES.IN_STOCK, 10), substatus: HAMConstants.ASSET_SUB_STATUSES.PENDING_INSTALL, reserved_for: requestedFor, process_table: HampLoanerUtils.LOANER_ORDER_TABLE, process_id: String(loanerOrderGr.sys_id), work_notes: preparedWorkNote, }; this.updateAsset(loanerAssetID, assetUpdateJSON, HAMUtils.isConsumableClassAsset(loanerAssetGr)); }, updateAssetOnDeployCompletion: function (deployTaskGr) { var loanerOrderGr = deployTaskGr.loaner_order; var loanerAssetGr = loanerOrderGr.asset; var loanerAssetID = String(loanerAssetGr.sys_id); var msgParams = [loanerAssetGr.getDisplayValue(), deployTaskGr.getDisplayValue()]; var deployedWorkNote = gs.getMessage('Asset {0} updated to state In Use as part of task {1}', msgParams); var installStatus; if (HAMUtils.isConsumableClassAsset(loanerAssetGr)) { installStatus = parseInt(HAMConstants.ASSET_STATUSES.CONSUMED, 10); } else { installStatus = parseInt(HAMConstants.ASSET_STATUSES.IN_USE, 10); } var timeNow = new GlideDateTime().toString(); var assetUpdateJSON = { install_status: installStatus, substatus: null, location: String(loanerOrderGr.location), work_notes: deployedWorkNote, assigned: timeNow, install_date: timeNow, process_table: HampLoanerUtils.LOANER_ORDER_TABLE, process_id: String(loanerOrderGr.sys_id), }; if (String(loanerOrderGr.request_type) !== HampLoanerUtils.LOANER_ORDER_TYPE_THIRD_PARTY) { assetUpdateJSON.assigned_to = String(loanerOrderGr.requested_for); } if (String(loanerOrderGr.request_type) === HampLoanerUtils.LOANER_ORDER_TYPE_THIRD_PARTY) { // Explictily marking null to overcome glidequery issue. // current.reserved_for.nil() returns false even though reserved_for is null assetUpdateJSON.managed_by = String(loanerOrderGr.opened_by); assetUpdateJSON.assigned_to = null; assetUpdateJSON.reserved_for = null; } this.updateAsset(loanerAssetID, assetUpdateJSON, HAMUtils.isConsumableClassAsset(loanerAssetGr)); }, canOrderBeCancelled: function (loanerOrder) { if (gs.hasRole('inventory_user')) { return true; } var canCancel = false; new global.GlideQuery('sn_hamp_loaner_asset_order') .where('sys_id', loanerOrder) .selectOne('opened_by', 'requested_for') .ifPresent(function (rec) { if (rec.opened_by === gs.getUserID() || rec.requested_for === gs.getUserID()) { canCancel = true; } }); return canCancel; }, isAssetAvailable: function (current) { var loanerOrderGr; if (current.getTableName() === HampLoanerUtils.LOANER_ORDER_TABLE) { loanerOrderGr = current; } else if (current.getTableName() === HampLoanerUtils.LOANER_TASK_TABLE) { loanerOrderGr = current.loaner_order; } var selectedAsset = String(loanerOrderGr.asset); var availableAssets = this.getAssetsAvailableToAllocate( loanerOrderGr.location, loanerOrderGr.model, loanerOrderGr.start_date, loanerOrderGr.return_date, loanerOrderGr.lead_time, loanerOrderGr.sys_id ); if (availableAssets.indexOf(selectedAsset) !== -1) { return true; } return false; }, canAccess: function (loanerOrder) { var res = new global.GlideQuery(HampLoanerUtils.LOANER_TASK_TABLE) .where('loaner_order', loanerOrder.sys_id) .where('assigned_to', gs.getUserID()) .selectOne() .isPresent(); return res; }, isLoanerAssetExist: function (location, model) { var assets = new GlideRecord('alm_asset'); HampLoanerUtils.addLoanerBaseQuery(assets, location, model); assets.addQuery('install_status', 'NOT IN', HampLoanerUtils.ASSET_IN_USE_STATUSES); assets.addQuery('excluded_from_ham', false) assets.query(); if (assets.hasNext()) { return true; } var loanerOrdersGa = new GlideAggregate(HampLoanerUtils.LOANER_ORDER_TABLE); HampLoanerUtils.addInUseFunctioningAssetsQuery(loanerOrdersGa, location, ''); loanerOrdersGa.query(); return loanerOrdersGa.hasNext(); }, getFunctioningLoanerAssetsCount: function (location, model) { var inStockFunctioningAssets = this.getInStockFunctioningLoanerAssetsCount(location, model); var inUseFunctioningAssets = this.getInUseFunctioningLoanerAssetsCount(location, model); return (inStockFunctioningAssets + inUseFunctioningAssets); }, getInStockFunctioningLoanerAssetsCount: function (location, model) { var assetsGa = new GlideAggregate('alm_asset'); HampLoanerUtils.addLoanerBaseQuery(assetsGa, location, model); HampLoanerUtils.addInStockFunctioningAssetsQuery(assetsGa); assetsGa.addQuery('excluded_from_ham', false); assetsGa.addAggregate('SUM', 'quantity'); assetsGa.groupBy('model'); assetsGa.query(); if (assetsGa.next()) { return (parseInt(assetsGa.getAggregate('SUM', 'quantity'), 10)); } return 0; }, getInUseFunctioningLoanerAssetsCount: function (location, model) { var loanerOrdersGa = new GlideAggregate(HampLoanerUtils.LOANER_ORDER_TABLE); HampLoanerUtils.addInUseFunctioningAssetsQuery(loanerOrdersGa, location, model); loanerOrdersGa.addAggregate('COUNT'); loanerOrdersGa.query(); if (loanerOrdersGa.next()) { return (parseInt(loanerOrdersGa.getAggregate('COUNT'), 10)); } return 0; }, isWaitlistedEditable: function (loanerOrderGr) { var stage = loanerOrderGr.getValue('stage'); if (stage === HampLoanerUtils.STAGE_NEW) { return true; } if (stage === HampLoanerUtils.STAGE_PREPARE) { var prepareTask = new global.GlideQuery(HampLoanerUtils.LOANER_TASK_TABLE) .where('loaner_order', loanerOrderGr.getUniqueValue()) .where('task_name', HampLoanerUtils.TASK_PREPARE) .select('state') .toArray(1); if (prepareTask[0] && parseInt(prepareTask[0].state, 10) === HampLoanerUtils.TASK_CLOSED_COMPLETE) { return false; } return true; } return false; }, isPrepareTaskClosedComplete: function (loanerOrderGr) { var stage = loanerOrderGr.getValue('stage'); if (stage === HampLoanerUtils.STAGE_NEW) { return false; } var prepareTask = new global.GlideQuery(HampLoanerUtils.LOANER_TASK_TABLE) .where('loaner_order', loanerOrderGr.getUniqueValue()) .where('task_name', HampLoanerUtils.TASK_PREPARE) .select('state') .toArray(1); if (prepareTask[0] && parseInt(prepareTask[0].state, 10) === HampLoanerUtils.TASK_CLOSED_COMPLETE) { return true; } return false; }, isLoanerFieldEditable: function (loanerOrderGr, field) { switch (field) { case 'asset': return !this.isPrepareTaskClosedComplete(loanerOrderGr); case 'model': return !this.isPrepareTaskClosedComplete(loanerOrderGr); default: return true; } }, getAssetReservedWorkNote: function (assetGr, loanerOrderGr) { var msgParams = [assetGr.getDisplayValue(), loanerOrderGr.getDisplayValue()]; // eslint-disable-next-line max-len var workNote = gs.getMessage('Asset {0} updated to state In stock and substate Reserved due to selection on loaner asset order {1}', msgParams); return workNote; }, compareOrdersStartDates: function (loanerOrder1, loanerOrder2) { return HAMUtils.compareDates(String(loanerOrder1.start_date), String(loanerOrder2.start_date)); }, setAssetStatusOnSelection: function (loanerOrderGr, selectedAssetGr) { var selectedAssetID = selectedAssetGr.sys_id.toString(); var selectionWorkNote = this.getAssetReservedWorkNote(selectedAssetGr, loanerOrderGr); var otherLoanerOrder; var assetUpdateJSON = {}; if (HAMUtils.isConsumableClassAsset(selectedAssetGr)) { var processedConsumableID = HampLoanerUtils.splitConsumableOnLoanerOrder(loanerOrderGr); if (selectedAssetID !== processedConsumableID) { // A new consumable with required attributes record is created in this case. loanerOrderGr.setValue('asset', processedConsumableID); } } var setAssetID = loanerOrderGr.getValue('asset'); // Check if selected asset is already part of another loaner order. otherLoanerOrder = HampLoanerUtils.getAnotherLoanerOrderWithAsset(selectedAssetID, loanerOrderGr); // If it is part of another loaner order, but the other loaner order start date comes first, do nothing. // Else update the consumable with incoming loaner asset order details. if (!gs.nil(otherLoanerOrder) && this.compareOrdersStartDates(loanerOrderGr, otherLoanerOrder) !== '>') { return; } assetUpdateJSON = { install_status: parseInt(HAMConstants.ASSET_STATUSES.IN_STOCK, 10), substatus: HAMConstants.ASSET_SUB_STATUSES.RESERVED, reserved_for: String(loanerOrderGr.requested_for), process_table: HampLoanerUtils.LOANER_ORDER_TABLE, process_id: loanerOrderGr.getUniqueValue(), work_notes: selectionWorkNote, }; this.updateAsset(setAssetID, assetUpdateJSON, HAMUtils.isConsumableClassAsset(selectedAssetGr)); }, setAssetStatusOnRemoval: function (loanerOrderGr, assetGr, isCancelledOrDeleted) { // If loaner asset orders not in New, Prepare are deleted, do nothing. if (isCancelledOrDeleted === HampLoanerUtils.LOANER_ORDER_ACTION_DELETED) { var loanerOrderStage = String(loanerOrderGr.stage); if (!((loanerOrderStage === HampLoanerUtils.STAGE_NEW) || (loanerOrderStage === HampLoanerUtils.STAGE_PREPARE))) { return; } } var assetId = assetGr.sys_id.toString(); var otherLoanerOrderStage; var dateComp; // If the asset is removed from the loaner asset order which is not the one with earliest start date // do nothing var otherLoanerOrder = HampLoanerUtils.getAnotherLoanerOrderWithAsset(assetId, loanerOrderGr); if (!gs.nil(otherLoanerOrder)) { otherLoanerOrderStage = String(otherLoanerOrder.stage); if (otherLoanerOrderStage === HampLoanerUtils.STAGE_DEPLOYED) { return; } dateComp = this.compareOrdersStartDates(loanerOrderGr, otherLoanerOrder); if (dateComp === '<' && (otherLoanerOrderStage === HampLoanerUtils.STAGE_NEW || otherLoanerOrderStage === HampLoanerUtils.STAGE_PREPARE)) { return; } } // If the asset is removed from the loaner asset order with the earliest start date // move the asset to a state of available var msgParams = [assetGr.getDisplayValue(), loanerOrderGr.getDisplayValue()]; var removalWorkNote; if (isCancelledOrDeleted === HampLoanerUtils.LOANER_ORDER_ACTION_CANCELLED) { // eslint-disable-next-line max-len removalWorkNote = gs.getMessage('Asset {0} updated to state In stock and substate Available due to cancellation of loaner asset order {1}', msgParams); } else if (isCancelledOrDeleted === HampLoanerUtils.LOANER_ORDER_ACTION_DELETED) { // eslint-disable-next-line max-len removalWorkNote = gs.getMessage('Asset {0} updated to state In stock and substate Available due to deletion of loaner asset order {1}', msgParams); } else { // eslint-disable-next-line max-len removalWorkNote = gs.getMessage('Asset {0} updated to state In stock and substate Available due to removal from loaner asset order {1}', msgParams); } var assetUpdateJSON = {}; assetUpdateJSON = { install_status: parseInt(HAMConstants.ASSET_STATUSES.IN_STOCK, 10), substatus: HAMConstants.ASSET_SUB_STATUSES.AVAILABLE, reserved_for: null, process_table: null, process_id: null, work_notes: removalWorkNote, }; this.updateAsset(assetId, assetUpdateJSON, HAMUtils.isConsumableClassAsset(assetGr)); // If the asset is part of another active loaner order with a greater start date, // set the asset as reserved for that order. if (!gs.nil(otherLoanerOrder)) { otherLoanerOrderStage = String(otherLoanerOrder.stage); if (dateComp === '>' && (otherLoanerOrderStage === HampLoanerUtils.STAGE_NEW || otherLoanerOrderStage === HampLoanerUtils.STAGE_PREPARE)) { var selectionWorkNote = this.getAssetReservedWorkNote(assetGr, otherLoanerOrder); assetUpdateJSON = { install_status: parseInt(HAMConstants.ASSET_STATUSES.IN_STOCK, 10), substatus: HAMConstants.ASSET_SUB_STATUSES.RESERVED, reserved_for: String(otherLoanerOrder.requested_for), work_notes: selectionWorkNote, process_table: otherLoanerOrder.getTableName(), process_id: otherLoanerOrder.getUniqueValue(), }; this.updateAsset(assetId, assetUpdateJSON, HAMUtils.isConsumableClassAsset(assetGr)); } } }, showLoanerAssetOrdersListOnAsset: function (assetGr) { /** *********************************************************************************** * Hiding loaner order related list for consumables if they are not supported by process columns *********************************************************************************** */ if (HAMUtils.isConsumableClassAsset(assetGr) && !HAMUtils.isConsumablesSupportedByProcess()) { return false; } if (assetGr.getValue('asset_function') === HAMConstants.ASSET_FUNCTION.LOANER) { return true; } var showLoanerAssetOrders = false; if (HAMUtils.isConsumableClassAsset(assetGr)) { /** *********************************************************************************** * Consumable history can only be got in conjunction with install status and stockroom. *********************************************************************************** */ if (assetGr.getValue('install_status') === HAMConstants.ASSET_STATUSES.IN_STOCK) { showLoanerAssetOrders = new global.GlideQuery(HampLoanerUtils.LOANER_ORDER_TABLE) .whereNotNull('asset') .where('model', assetGr.getValue('model')) .where('asset_stockroom', assetGr.getValue('stockroom')) .selectOne() .isPresent(); } return showLoanerAssetOrders; } /** *********************************************************************************** * In case of Asset, Hardware, Facility, Bundle class, check if record is in orders. *********************************************************************************** */ showLoanerAssetOrders = new global.GlideQuery(HampLoanerUtils.LOANER_ORDER_TABLE) .where('asset', assetGr.getUniqueValue()) .selectOne() .isPresent(); return showLoanerAssetOrders; }, type: 'HampLoanerUtils', }; HampLoanerUtils.addDomainFilterQuery = function (records) { if (global.ModelUtils.isDomainSeparationEnabled()) { var domainID = new global.AssetManagementBaseJob().getCurrentDomainSysId(); records.addQuery('sys_domain', domainID); } }; HampLoanerUtils.getLoanerCommonBaseQuery = function (location, model) { var assets = new GlideAggregate('alm_asset'); assets.addQuery('asset_function', 'loaner'); if (!(HAMUtils.isConsumablesSupportedByProcess())) { var consumableExt = HAMUtils.getTableExtensions(HAMConstants.ALM_CONSUMABLE_TABLE); assets.addQuery('sys_class_name', 'NOT IN', consumableExt); } // Exclude EAM assets and EAM models var eamModelExt = HAMUtils.getEAMModelClasses(); assets.addQuery('model.sys_class_name', 'NOT IN', eamModelExt); var eamAssetExt = HAMUtils.getEAMAssetClasses(); assets.addQuery('sys_class_name', 'NOT IN', eamAssetExt); assets.addQuery('sys_class_name', '!=', 'alm_license'); if (!gs.nil(model)) { assets.addQuery('model', model); } HampLoanerUtils.addDomainFilterQuery(assets); return assets.getEncodedQuery(); }; HampLoanerUtils.getLoanerBaseQueryWithLocation = function (location, commonBaseQuery) { var baseQueryWithLocation = commonBaseQuery; if (!gs.nil(location)) { baseQueryWithLocation += '^location=' + location; baseQueryWithLocation += '^NQ' + commonBaseQuery + '^locationISEMPTY^stockroom.location=' + location; } return baseQueryWithLocation; }; HampLoanerUtils.addLoanerBaseQuery = function (assets, location, model) { var commonBaseQuery = HampLoanerUtils.getLoanerCommonBaseQuery(location, model); var baseQueryWithLocation = HampLoanerUtils.getLoanerBaseQueryWithLocation(location, commonBaseQuery); assets.addEncodedQuery(baseQueryWithLocation); }; HampLoanerUtils.addInStockFunctioningAssetsQuery = function (assets) { // Assets are considered functioning if the state and substatus are: // state: in_stock (6) | substatus: available, reserved, pending_install // OR state: in_use (1) var validInstallStatus = HAMConstants.ASSET_STATUSES.IN_STOCK; var validSubstatus = [ HAMConstants.ASSET_SUB_STATUSES.AVAILABLE, HAMConstants.ASSET_SUB_STATUSES.RESERVED, HAMConstants.ASSET_SUB_STATUSES.PENDING_INSTALL, ]; assets.addQuery('install_status', validInstallStatus); assets.addQuery('substatus', validSubstatus) .addOrCondition('substatus', ''); HampLoanerUtils.addDomainFilterQuery(assets); }; HampLoanerUtils.addInUseFunctioningAssetsQuery = function (loanerOrders, location, model) { var validStatus = [HAMConstants.ASSET_STATUSES.IN_USE]; if (HAMUtils.isConsumablesSupportedByProcess()) { validStatus.push(HAMConstants.ASSET_STATUSES.CONSUMED); } loanerOrders.addQuery('location', location); if (!gs.nil(model)) { loanerOrders.addQuery('model', model); } loanerOrders.addQuery('asset.install_status', validStatus); loanerOrders.addQuery('asset.asset_function', 'loaner'); loanerOrders.addQuery('stage', HampLoanerUtils.STAGE_DEPLOYED); HampLoanerUtils.addDomainFilterQuery(loanerOrders); }; HampLoanerUtils.convertDateStringToDateObj = function (dateString) { var date = new Date(); date.setFullYear(dateString.substring(0, 4)); date.setMonth(dateString.substring(5, 7) - 1); date.setDate(dateString.substring(8, 10)); date.setHours(0, 0, 0, 0); return date; }; HampLoanerUtils.convertDateObjToDateString = function (date) { var yearStr = String(date.getFullYear()); var monthStr = String(date.getMonth() + 1); if (monthStr.length === 1) { monthStr = '0' + monthStr; } var dateStr = String(date.getDate()); if (dateStr.length === 1) { dateStr = '0' + dateStr; } return yearStr + '-' + monthStr + '-' + dateStr; }; HampLoanerUtils.getPreparationStartDate = function (startDate, leadTime) { var leadTimeInDays = parseInt(leadTime, 10); var minusDays = 0 - leadTimeInDays; var preparationStartDateObj = HampLoanerUtils.convertDateStringToDateObj(String(startDate)); if (leadTimeInDays > 0) { preparationStartDateObj.setDate(preparationStartDateObj.getDate() + minusDays); } var preparationStartDateStr = HampLoanerUtils.convertDateObjToDateString(preparationStartDateObj); var currentDateStr = new GlideDateTime().getLocalDate().toString(); var currentDateObj = HampLoanerUtils.convertDateStringToDateObj(currentDateStr); if ((preparationStartDateObj.getTime() - currentDateObj.getTime()) <= 0) { return currentDateStr; } return preparationStartDateStr; }; HampLoanerUtils.addLoanerOrdersOverlapQuery = function (loanerOrders, startDate, returnDate, leadTime, isGlideQuery) { var preparationStartDate = HampLoanerUtils.getPreparationStartDate(startDate, leadTime); if (isGlideQuery) { var enhancedQuery = loanerOrders.where('preparation_start_date', '<=', returnDate); enhancedQuery = enhancedQuery.where('return_date', '>=', preparationStartDate); return enhancedQuery; } loanerOrders.addQuery('start_date', '<=', returnDate); loanerOrders.addQuery('return_date', '>=', preparationStartDate); return loanerOrders; }; HampLoanerUtils.convertUTCtoTimezone = function (utcTime, timeZone) { if (!gs.nil(timeZone)) { var gr = new GlideScheduleDateTime(utcTime); var currentTime = gr.convertTimeZone('UTC', timeZone); return new GlideDateTime(currentTime); } return utcTime; }; HampLoanerUtils.getTimezoneOfLocation = function (location) { var locObj = new global.GlideQuery('cmn_location') .get(location, ['time_zone']); if (!gs.nil(locObj) && !gs.nil(locObj._value) && !gs.nil(locObj._value.time_zone)) { return locObj._value.time_zone; } return ''; }; HampLoanerUtils.splitConsumableOnLoanerOrder = function (loanerOrderGr) { var quantity = 1; // Only consumables with quantity 1 can be requested as of now. var consumableID = loanerOrderGr.getValue('asset'); var consumableGr = HAMUtils.getAsGlideRecord(HAMConstants.ALM_ASSET_TABLE, consumableID); var newConsumableID = consumableID; if (quantity < parseInt(consumableGr.getValue('quantity'), 10)) { newConsumableID = new global.Consumables().split( consumableID, quantity, consumableGr.getValue('install_status'), HAMConstants.ASSET_SUB_STATUSES.RESERVED, '', consumableGr.getValue('stockroom'), consumableGr.getValue('location'), '', 'loaner', { process_table: loanerOrderGr.getTableName(), process_id: loanerOrderGr.getUniqueValue(), reserved_for: loanerOrderGr.getValue('requested_for'), } ); } return newConsumableID; }; HampLoanerUtils.consumableMergeConditionCheck = function (consumableGr) { var canMerge = true; if (consumableGr.getValue('process_table') === HampLoanerUtils.LOANER_ORDER_TABLE && !gs.nil(consumableGr.getValue('process_id'))) { canMerge = false; } return canMerge; }; HampLoanerUtils.getAnotherLoanerOrderWithAsset = function (assetId, excludeLoanerOrderGr) { var loanerOrder = ''; var assetExists = new global.GlideQuery(HampLoanerUtils.LOANER_ORDER_TABLE) .where('asset', assetId) .where('sys_id', '!=', String(excludeLoanerOrderGr.sys_id)) .where('stage', 'IN', [ HampLoanerUtils.STAGE_NEW, HampLoanerUtils.STAGE_PREPARE, HampLoanerUtils.STAGE_DEPLOYED, ]) .where('is_waitlisted', false) .orderBy('start_date') .toGlideRecord(); assetExists.setLimit(1); assetExists.query(); if (assetExists.next()) { loanerOrder = assetExists; } return loanerOrder; }; HampLoanerUtils.canCloseLoanerTask = function (loanerTaskGr) { var hasAccess = gs.getUser().hasRole('itil') || gs.hasRole('inventory_user') || String(loanerTaskGr.assigned_to) === gs.getUserID(); return (hasAccess && (loanerTaskGr.getValue('state') === '1' || loanerTaskGr.getValue('state') === '2')); }; HampLoanerUtils.validateFieldsForLoaner = function (loanerTaskGr) { var message; var msgParams = []; if ((loanerTaskGr.getValue('task_name') === 'prepare') && loanerTaskGr.getValue('state') !== '4') { // check mandatory fields are filled on Prepare task if (!loanerTaskGr.loaner_order.asset) { msgParams.push(loanerTaskGr.loaner_order.asset.getLabel()); } if (msgParams.length > 0) { message = gs.getMessage('The following mandatory fields are not filled in: {0}', msgParams.join(', ')); gs.addErrorMessage(message); } if (loanerTaskGr.loaner_order.asset) { message = (new sn_hamp.HAMLicensingUtility()).getExcludedAssetErrorMessage(loanerTaskGr.loaner_order.asset); if(!gs.nil(message)) { msgParams.push(message); //Next 2 lines have been added as a workaround to avoid 2 error messages from appearing in Classic workspace, will be removed once platform fix is done. var inputURL = String(gs.action.getGlideURI()); if (inputURL.indexOf('.do?') === -1) { gs.addErrorMessage(message); } } } } else if ((loanerTaskGr.getValue('task_name') === 'reclaim') && loanerTaskGr.getValue('state') !== '4') { // check mandatory fields are filled on Reclaim task if (!loanerTaskGr.getValue('return_stockroom')) { msgParams.push(loanerTaskGr.return_stockroom.getLabel()); } if (msgParams.length > 0) { message = gs.getMessage('The following mandatory fields are not filled in: {0}', msgParams.join(', ')); gs.addErrorMessage(message); } var msg; if (loanerTaskGr.loaner_order.asset_returned.toString() === 'N') { // eslint-disable-next-line max-len msg = gs.getMessage('To complete the task, update {0} value to Yes', loanerTaskGr.loaner_order.asset_returned.getLabel()); msgParams.push(loanerTaskGr.loaner_order.asset_returned.getLabel()); gs.addErrorMessage(msg); } if (loanerTaskGr.loaner_order.is_asset_functional.toString() === '') { // eslint-disable-next-line max-len msg = gs.getMessage('To complete the task, update {0} value to either Yes or No', loanerTaskGr.loaner_order.is_asset_functional.getLabel()); msgParams.push(loanerTaskGr.loaner_order.is_asset_functional.getLabel()); gs.addErrorMessage(msg); } } if (msgParams.length === 0) { if (loanerTaskGr.getValue('state') !== '4') { loanerTaskGr.state = 3; } loanerTaskGr.update(); } if (loanerTaskGr.getValue('state') !== '3') { // redirect to task page only if its incomplete return loanerTaskGr; } return loanerTaskGr.loaner_order.getRefRecord(); }; HampLoanerUtils.LOANER_ORDER_TABLE = 'sn_hamp_loaner_asset_order'; HampLoanerUtils.LOANER_TASK_TABLE = 'sn_hamp_loaner_asset_task'; HampLoanerUtils.STAGE_NEW = 'new'; HampLoanerUtils.STAGE_PREPARE = 'prepare'; HampLoanerUtils.STAGE_DEPLOYED = 'deployed'; HampLoanerUtils.STAGE_COMPLETED = 'completed'; HampLoanerUtils.STAGE_CANCELLED = 'cancelled'; HampLoanerUtils.TASK_CLOSED_COMPLETE = 3; HampLoanerUtils.TASK_PREPARE = 'prepare'; HampLoanerUtils.LOANER_ORDER_ACTION_CANCELLED = 'cancelled'; HampLoanerUtils.LOANER_ORDER_ACTION_DELETED = 'deleted'; HampLoanerUtils.LOANER_ORDER_TYPE_THIRD_PARTY = 'for_third_party_user'; HampLoanerUtils.ASSET_IN_USE_STATUSES = [HAMConstants.ASSET_STATUSES.IN_USE, HAMConstants.ASSET_STATUSES.CONSUMED];