Name

global.POReceiveManager

Description

Handles Purchase Order Receive

Script

var POReceiveManager = Class.create();

POReceiveManager.prototype = {
  initialize: function(request) {
      this.failedAssets = [];
      this.request = request;
      this.isSAMPActive = GlidePluginManager.isActive('com.snc.samp');
      this.isHAMPActive = GlidePluginManager.isActive('com.sn_hamp');
      this.isEAMActive = GlidePluginManager.isActive('com.sn_eam');
  },

  getAllStockRoom: function() {
      var stockrooms = this._getRecordObject('alm_stockroom', //table name
          [], //All records
          ['sys_id', 'name', 'localtion']); //Fields
      return (new JSON()).encode(stockrooms);
  },

  _getPreCreatedAssets: function(polineSysid, model) {
      var onOrderAssets = this._getRecordObject('alm_asset', // table name
          [{
              key: 'purchase_line',
              value: polineSysid,
          }, {
              key: 'install_status',
              value: '2',
          }, {
              key: 'model',
              value: model,
          }],
          ['sys_id', 'asset_tag', 'serial_number', 'model', 'license_key'], // Fields
          {
              reserved_for: {
                  table: 'sys_user',
                  fields: ['user_name', 'sys_id', 'name'],
              },
          });

      var assets = onOrderAssets;
      if (this.isHAMPActive || this.isEAMActive) {
          var inTransitAssets = this._getRecordObject('alm_asset', // table name
              [{
                  key: 'purchase_line',
                  value: polineSysid,
              }, {
                  key: 'install_status',
                  value: '9',
              }, {
                  key: 'model',
                  value: model,
              }],
              ['sys_id', 'asset_tag', 'serial_number', 'model', 'license_key'], // Fields
              {
                  reserved_for: {
                      table: 'sys_user',
                      fields: ['user_name', 'sys_id', 'name'],
                  },
              });
          assets = onOrderAssets.concat(inTransitAssets);
      }
      return assets;
  },

  getPOItems: function() {
      var poSysId = this.request.getParameter('sysparm_po_sysid');
      var items = this.getPOItemsWithParams(poSysId);
      return items;
  },

  getPOItemsWithParams: function(poSysId, polSysId) {
      var reqItems = [];
      var refFieldsToRequest = {
          'requested_for': {
              table: 'sys_user',
              fields: ['user_name', 'sys_id', 'name']
          },
          'model': {
              table: 'cmdb_model',
              fields: ['sys_id', 'display_name', 'asset_tracking_strategy', 'sys_class_name']
          },
          'purchase_order': {
              table: 'proc_po',
              fields: ['sys_id', 'number', 'ship_to']
          },
          'vendor': {
              table: 'core_company',
              fields: ['sys_id', 'name']
          }
      };
      if (this.isSAMPActive) {
          refFieldsToRequest.license_metric = {
              table: 'samp_sw_license_metric',
              fields: ['sys_id', 'name']
          };
          refFieldsToRequest.metric_group = {
              table: 'samp_sw_metric_group',
              fields: ['sys_id', 'name']
          };
      }
      var queryParams = [{
              key: "purchase_order",
              value: poSysId
          },
          {
              key: 'remaining_quantity',
              value: '0',
              operator: '>'
          },
          {
              key: 'status',
              value: 'canceled',
              operator: '!='
          }
      ];

      if (!gs.nil(polSysId)) {
          queryParams.push({
              key: 'sys_id',
              value: polSysId
          });
      }

      var items = this._getRecordObject("proc_po_item",
          queryParams,
          [], //Get all fields
          refFieldsToRequest,
          'number');

      /* update pre generated assets for each POline model */
      var createCIUsingIRE = gs.getProperty('glide.asset.create_ci_with_ire');
      var AssetCMDBUtil = new global.AssetCMDBUtil();
      for (var i = 0; i < items.length; i++) {
          var item = items[i];
          item['createCIUsingIRE'] = createCIUsingIRE;
          item['pre_created_assets'] = this._getPreCreatedAssets(item.sys_id, item.model.sys_id);
          item['item_model_type'] = this._getItemModelType(item.model.sys_id);
          var shipTOSysid = item.purchase_order.ship_to;
          /* Need value and displayValue for default selection of ShipTo reference picker at client side */
          if (!gs.nil(shipTOSysid)) {
              var stockRooms = this._getRecordObject('alm_stockroom',
                  [{
                      key: 'sys_id',
                      value: shipTOSysid
                  }],
                  ['sys_id', 'name']);
              if (!gs.nil(stockRooms) && stockRooms.length > 0)
                  item.purchase_order.ship_to = stockRooms[0];
          }
          if (createCIUsingIRE === 'true') {
              var productModel = item.model.sys_id;
              var productModelGr = new GlideRecord('cmdb_model');
              productModelGr.get(productModel);
              var modelCategories = productModelGr.getValue('cmdb_model_category');
              if (!gs.nil(modelCategories) && productModelGr.asset_tracking_strategy != 'track_as_consumable' && productModelGr.asset_tracking_strategy != 'do_not_track') {
                  modelCategories = modelCategories.split(',');
                  var modelCategory = modelCategories[0];
                  item['is_serial_number_mandatory'] = AssetCMDBUtil.isSerialNumberMandatory(modelCategory);

                  if (this.isEAMActive && !item['is_serial_number_mandatory']) {
                      var isMandatory = sn_eam.EAMUtils.isSerialNumberMandatory(modelCategory);
                      item['is_serial_number_mandatory'] = isMandatory;
                  }
              } else {
                  item['is_serial_number_mandatory'] = false;
              }
          } else {
              item['is_serial_number_mandatory'] = false;
          }
      }
      return (new JSON()).encode(items);
  },

  processPOReceive: function() {
      var poSysId = this.request.getParameter('sysparm_po_sysid');
      var data = this.request.getParameter('sysparm_receivedata');
      var batchProcessing = this.request.getParameter('sysparm_batching');
      return this.processPOReceiveWithParams(poSysId, data, batchProcessing);
  },

  processPOReceiveWithParams: function(poSysId, data, batchProcessing) {
      data = (new JSON()).decode(data);
      var response = this._validate(data);
      if (response.status == 'success') {
          /* group polines by destination stockroom to create per stockroom Receiving Slips*/
          var dataByDestination = this._groupbyDestination(data);
          for (var stockroom in dataByDestination) {
              var poLines = dataByDestination[stockroom];
              this._processPOLines(poSysId, poLines, stockroom, batchProcessing);
          }
      }
      var poItemsGr = new GlideRecord('proc_po_item');
      var failedAssetsObj = {};
      for (var i = 0; i < this.failedAssets.length; i++) {
          var polSysId = Object.keys(this.failedAssets[i])[0];
          if (failedAssetsObj[polSysId] == undefined) {
              poItemsGr.get(polSysId);
              failedAssetsObj[polSysId] = {};
              failedAssetsObj[polSysId]['items'] = [this.failedAssets[i][polSysId]];
              failedAssetsObj[polSysId]['received_quantity'] = poItemsGr.getValue('received_quantity');
              failedAssetsObj[polSysId]['remaining_quantity'] = poItemsGr.getValue('remaining_quantity');
          } else {
              failedAssetsObj[polSysId]['items'].push(this.failedAssets[i][polSysId]);
          }
      }
      response['failedAssets'] = failedAssetsObj;
      if (this.failedAssets.length > 0) {
          gs.flushMessages();
      }
      return (new JSON()).encode(response);
  },
  _validate: function(data) {
      var response = {
          status: 'success'
      };
      return response;
  },
  _processPOLines: function(poSysId, poLines, stockroom, batching) {
      var isPOSoftwareLine;
      var poLine;
      var polGr;
      var po = new GlideRecord('proc_po');
      po.get(poSysId);
      var pu = new ProcurementUtils();
      var receivingSlip;
      if (batching == 'in_between' || batching == 'last_batch_call') {
          receivingSlip = new GlideRecord('proc_rec_slip');
          receivingSlip.addQuery('purchase_order', po.sys_id);
          receivingSlip.addQuery('stockroom', stockroom);
          receivingSlip.orderByDesc('sys_created_on');
          receivingSlip.setLimit(1);
          receivingSlip.query();
          receivingSlip.next();
      } else {
          receivingSlip = pu.createReceiptSlip(po, stockroom);
      }
      var receivingSlipLineCreated = 0;
      for (var i = 0; i < poLines.length; i++) {
          poLine = poLines[i];
          poLine.reserved = poLine.reserved || false;
          isPOSoftwareLine = this._isPOSoftwareLine(poLine);
          // var rights;
          polGr = new GlideRecord("proc_po_item");
          polGr.get(poLine.sys_id);
          /* Create only one asset for software PO line */
          // if (this._isPOSoftwareLine(poLine)) {
          //     rights = poLine.receiving_quantity;
          // }
          if (this.isSAMPActive && isPOSoftwareLine) {
              pu.createReceiptSlipLineForSAMP(
                  receivingSlip,
                  polGr,
                  poLine
              );
              receivingSlipLineCreated = 1;
          } else if (poLine.assetTags) {
              // Assets with Tags and/or SN created
              var failedItems = (pu.createReceiptSlipLineWithAssetDetails(
                  receivingSlip,
                  polGr,
                  poLine.receiving_quantity,
                  poLine.cost_with_currency,
                  poLine.reserved_for.value,
                  poLine.assetTags,
                  poLine.reserved,
                  isPOSoftwareLine
              ));
              this.failedAssets = this.failedAssets.concat(failedItems);
              if (failedItems.length != poLine.receiving_quantity) {
                  receivingSlipLineCreated = 1;
              }
          } else {
              // Standard receive without any Asset Tags or SN created in popup
              pu.createReceiptSlipLine(
                  receivingSlip,
                  polGr,
                  poLine.receiving_quantity,
                  poLine.cost_with_currency,
                  poLine.reserved_for.value,
                  '',
                  '',
                  poLine.reserved
              );
              receivingSlipLineCreated = 1;
          }
      }
      // batching will be false if receiving is done from other areas other than PO Receive page
      if (receivingSlipLineCreated === 0 && (batching == 'none' || batching == false)) {
          var procRecSlipGr = new GlideRecord('proc_rec_slip');
          procRecSlipGr.get(receivingSlip.sys_id);
          procRecSlipGr.deleteRecord();
      }
      if (batching == 'last_batch_call') {
          var procRecSlipItemGr = new GlideRecord('proc_rec_slip_item');
          procRecSlipItemGr.addQuery('receiving_slip', receivingSlip.sys_id);
          procRecSlipItemGr.setLimit(1);
          procRecSlipItemGr.query();
          if (!procRecSlipItemGr.hasNext()) {
              receivingSlip.deleteRecord();
          }
      }
  },
  _groupbyDestination: function(data) {
      var dataByDestination = {};
      for (var i = 0; i < data.length; i++) {
          if (gs.nil(dataByDestination[data[i].ship_to.value])) {
              dataByDestination[data[i].ship_to.value] = [];
          }
          dataByDestination[data[i].ship_to.value].push(data[i]);
      }
      return dataByDestination;
  },
  _getRecordObject: function(table, queryParams, fields, refMap, orderBy) {
      var i;
      var records = [];
      var gr = new GlideRecord(table);
      if (queryParams) {
          for (i = 0; i < queryParams.length; i++) {
              var qp = queryParams[i];
              if (qp.operator) {
                  gr.addQuery(qp.key, qp.operator, qp.value);
              } else {
                  gr.addQuery(qp.key, qp.value);
              }
          }
      }
      if (orderBy) {
          gr.orderBy(orderBy);
      }
      gr.query();
      while (gr.next()) {
          var rec = {};
          var glideElements = gr.getFields();
          rec['sys_id'] = gr.sys_id.toString();
          for (i = 0; i < glideElements.size(); i++) {
              var glideElement = glideElements.get(i);
              //gs.info('Processing ' + glideElement.getName() + ' - ' + glideElement.getDisplayValue());
              if (!gs.nil(glideElement.toString()) && /* if no fields given then consider all otherwise consider specific */
                  (fields.length == 0 || (fields.length > 0 && fields.indexOf(glideElement.getName()) >= 0))) {
                  rec[glideElement.getName()] = glideElement.toString();
              }
              if (refMap && !gs.nil(refMap[glideElement.getName()])) {
                  var refDetails = refMap[glideElement.getName()];
                  var refSysid = glideElement.toString();
                  var refObjs = this._getRecordObject(refDetails.table, [{
                      key: 'sys_id',
                      value: refSysid
                  }], refDetails.fields);
                  if (!gs.nil(refObjs) && refObjs.length > 0) {
                      rec[glideElement.getName()] = refObjs[0];
                  }
              }
          }
          records.push(rec);
      }
      return records;
  },
  _isPOSoftwareLine: function(poline) {
      return poline.item_model_type == 'software';
  },
  /* Decide type of item (software/hardware) based on requested item's model*/
  _getItemModelType: function(model) {
      var type = '';
      if (model) {
          var modelGR = new GlideRecord('cmdb_model');
          modelGR.get(model);
          type = (new AssetUtils()).getAssetOrConsumable(modelGR);
      }
      return type;
  },
  getAssetTags: function() {
      var assetTags = [];
      var gr = new GlideRecord('imp_asset_tags');
      /*
      gr.addNotNullQuery('u_asset_tag');
      */
      gr.orderBy('sys_import_row');
      gr.query();
      while (gr.next()) {
          assetTags.push({
              asset_tag: gr.u_asset_tag.toString(),
              serial_number: gr.u_serial_number.toString(),
              reserved_for: gr.u_reserved_for.toString(),
              license_key: gr.u_license_key.toString(),
              rights: gr.u_rights.toString(),
              index: gr.sys_import_row.toString()
          });
          gr.deleteRecord();
      }
      return (new JSON()).encode(assetTags);
  },
  getBatchConfig: function() {
      var cfg = {
          threshold: 500,
          unnecessaryKeys: [
              'discount', // unnecessary to send, not changed in UI
              'errors', // retrieved and used only for UI validations
              'ordered', // unnecessary to send, not changed in UI
              'received_quantity', // retrieved and used only for UI
              'remaining_quantity', // retrieved and used only for UI
              'sys_created_by', // sys parameter, unnecessary to send
              'sys_created_on', // sys parameter, unnecessary to send
              'sys_domain', // sys parameter, unnecessary to send
              'sys_mod_count', // sys parameter, unnecessary to send
              'sys_updated_by', // sys parameter, unnecessary to send
              'sys_updated_on' // sys parameter, unnecessary to send
          ]
      };
      return (new JSON()).encode(cfg);
  },
  log: function(msg) {
      gs.info('[POReceiveManager]: ' + msg);
  },
  type: 'POReceiveManager'
};

Sys ID

c149ac86932012003706dfa5e57ffbfe

Offical Documentation

Official Docs: