Name

sn_service_builder.ASBCheckoutService

Description

No description available

Script

var ASBCheckoutService = Class.create();
ASBCheckoutService.prototype = {
  initialize: function() {
      this.utils = new sn_service_builder.ASBUtils();
      this.CONSTANTS = new sn_service_builder.ASBConstants();
      this.DPM_ACTIVE = GlidePluginManager.isActive('com.snc.dpm');
  },

  /**
   * checkoutService
   * creates a copy of the published service so that it can be edited
   * without disrupting production data
   *
   * @param {string} serviceTable - the service table ie cmdb_ci_service_business
   * @param {sysId} serviceId - the service that is being checked out to be edited
   * @returns {sysId, offerings[]} - the sysId of the copied service and an array of children offerings
   */
  checkoutService: function(serviceTable, serviceId) {
      var publishedServiceGr = new GlideRecord(serviceTable);
      if (!publishedServiceGr.get(serviceId)) {
          gs.error('[ASB] Could not find record ' + serviceId + ' for table ' + serviceTable);
          return null;
      }

      //don't copy the service if it has already been checked out
      //return the sys id of the service being edited
      if (publishedServiceGr.getValue(this.CONSTANTS.FIELD.CHECKOUT) === this.CONSTANTS.FIELD_VALUE.TRUE) {
          var checkedoutServiceGr = new GlideRecord(serviceTable);
          checkedoutServiceGr.addQuery(this.CONSTANTS.FIELD.PUBLISHED_REF, serviceId);
          checkedoutServiceGr.query();
          if (checkedoutServiceGr.next()) {
              var checkedoutServiceId = checkedoutServiceGr.getUniqueValue();
              return {
                  sysId: checkedoutServiceId,
                  offerings: this._getOfferings(checkedoutServiceId),
              };
          }

          gs.error('[ASB] Service already checked out by could not find draft record');
          return null;
      }

      //don't copy the service if it is the checked out version
      //return the sysId that was passed in since it is the sysId of the draft version
      if (publishedServiceGr.getValue(this.CONSTANTS.FIELD.STATE) === this.CONSTANTS.FIELD_VALUE.DRAFT ||
          publishedServiceGr.getValue(this.CONSTANTS.FIELD.STATE) === this.CONSTANTS.FIELD_VALUE.PUBLISHING)
          return {
              sysId: serviceId,
              offerings: this._getOfferings(serviceId),
          };

      var draftId = null;
      try {
          //create copy of service
          var draftServiceGr = new GlideRecord(serviceTable);
          this.utils.copyFields(publishedServiceGr, draftServiceGr, this.CONSTANTS.EXCLUDED_SERVICE_FIELDS());

          //update state of copied service and insert
          draftId = this._insertCheckoutDraftState(draftServiceGr, serviceId);
          if (draftId === null) {
              gs.error('[ASB] Problem creating a copy of ' + serviceId + ' for table ' + serviceTable);
              return null;
          }

          //create copies of business capabilities if business service
          if (serviceTable === this.CONSTANTS.TABLE.CMDB_CI_SERVICE_BUSINESS) {
              this._checkoutBusinessCapabilities(serviceId, draftId);
          }

          //create copies of records in DPM tables
          if (this.DPM_ACTIVE)
              this._checkoutDPMRecords(serviceId, draftId, serviceTable);

          //set checkout to true on service
          this._updateCheckoutPublishedState(publishedServiceGr);
      } catch (err) {
          var cancelCheckoutUtil = new sn_service_builder.ASBCancelCheckout();
          cancelCheckoutUtil.cancelCheckout(serviceTable, draftId);

          gs.error('[ASB] Error checking out service ' + publishedServiceGr.name + ': ' + err);
          return null;
      }

      return {
          sysId: draftId,
          offerings: this._getOfferings(draftId),
      };
  },

  /**
   * copyOffering
   * creates a copy of an offering with updated name
   * creates copies of references in other tables
   *
   * @param {sysId} offeringIds - comma separated list of offering sys Ids 
   * to be copied
   * @param {JSONObject} overrideFields - fields need to be overriden when copied
   * @return {JSONObject} - arrays of successful and failed offerings that were
   * copied
   */
  copyOfferings: function(offeringIds, overrideFields) {
      var offeringGr = new GlideRecord(this.CONSTANTS.TABLE.SERVICE_OFFERING);
      offeringGr.addQuery('sys_id', 'IN', offeringIds);
      offeringGr.query();

      var result = {
          success: [],
          failure: []
      };
      while (offeringGr.next()) {
          var offeringId = offeringGr.getUniqueValue();
          var copyOfferingId = null;
          try {
              //create copy record and copy values
              var copyOfferingGr = new GlideRecord(this.CONSTANTS.TABLE.SERVICE_OFFERING);
              this.utils.copyFields(offeringGr, copyOfferingGr, this.CONSTANTS.EXCLUDED_COPY_OFFERING_FIELDS());

              //Create new name for copied offering
              var updatedName = gs.getMessage('{0} Copy', offeringGr.getValue(this.CONSTANTS.FIELD.NAME));
              var copyName = updatedName;
              var num = 2;
              var nameFound = true;
              while (nameFound) {
                  var gr = new GlideRecord(this.CONSTANTS.TABLE.SERVICE_OFFERING);
                  gr.addQuery(this.CONSTANTS.FIELD.NAME, copyName);
                  gr.query();
                  if (gr.next())
                      copyName = updatedName + ' ' + num++;
                  else
                      nameFound = false;
              }

              copyOfferingGr.setValue(this.CONSTANTS.FIELD.NAME, copyName);

              if (overrideFields) {
                  Object.keys(overrideFields).forEach(function(fieldName) {
                      copyOfferingGr.setValue(fieldName, overrideFields[fieldName]);
                  });
              }

              copyOfferingId = copyOfferingGr.insert();

              //create copies of subscriptions
              this._checkoutSubscriptions(offeringId, copyOfferingId);

              //create copies of offering commitments
              this._checkoutCommitments(offeringId, copyOfferingId);

              //create copies of records in DPM tables
              if (this.DPM_ACTIVE)
                  this._checkoutDPMRecords(offeringId, copyOfferingId, this.CONSTANTS.TABLE.SERVICE_OFFERING);

              result.success.push(offeringGr.getValue(this.CONSTANTS.FIELD.NAME));
          } catch (err) {
              gs.error('[ASB] Problem while copying offering ' + offeringGr.name + ' ' + err);
              result.failure.push(offeringGr.getValue(this.CONSTANTS.FIELD.NAME));
          }
      }
      return result;
  },

  /**
   * checkoutOffering
   * external method to checkout an offering and the associated service
   * @param {GlideRecord} offeringGr
   * @param {String} draftServiceSysId (optional)
   * @returns {Object}
   */
  checkoutOffering: function(offeringGr, draftServiceSysId) {
      var parentId = this.CONSTANTS.FIELD.PARENT;
      if (!offeringGr || !offeringGr.isValidRecord())
          return null;

      if (draftServiceSysId && typeof draftServiceSysId === 'string') {
          return this._checkoutOffering(offeringGr, draftServiceSysId);
      } else if (!draftServiceSysId && offeringGr.getValue(this.CONSTANTS.FIELD.PARENT)) {
          // find out the draft service to associate with the draft offering
          var draftService = this.utils.getDraftRecord(offeringGr.parent.getRefRecord());
          if (draftService)
              return this._checkoutOffering(offeringGr, draftService.getUniqueValue());
      }
      return null;
  },

  /**
   * _checkoutOffering
   * private method that creates a copy of the published offering so that it can be edited
   * without disrupting production data
   * creates copies of references in other tables
   *
   * @param {GlideRecord} offeringGr - the offering GlideRecord to be copied
   * @param {sysId} serviceId - the service that will be the parent of the copied offering
   */
  _checkoutOffering: function(offeringGr, serviceId) {
      var draftOfferingId = null;
      try {
          //create draft record and copy values
          var draftOfferingGr = new GlideRecord(this.CONSTANTS.TABLE.SERVICE_OFFERING);
          this.utils.copyFields(offeringGr, draftOfferingGr, this.CONSTANTS.EXCLUDED_OFFERING_FIELDS());

          //set parent to the copied service
          draftOfferingGr.setValue(this.CONSTANTS.FIELD.PARENT, serviceId);

          //update state of copied offering and insert
          draftOfferingId = this._insertCheckoutDraftState(draftOfferingGr, offeringGr.getUniqueValue());
          var publishedOfferingId = offeringGr.getUniqueValue();

          //create copies of subscriptions
          this._checkoutSubscriptions(publishedOfferingId, draftOfferingId);

          //create copies of offering commitments
          this._checkoutCommitments(publishedOfferingId, draftOfferingId);

          //create copies of catalog item references
          this._checkoutCatalogItems(publishedOfferingId, draftOfferingId);

          //create copies of dependent offerings
          this._checkoutDependents(publishedOfferingId, draftOfferingId);

          //create copies of records in DPM tables
          if (this.DPM_ACTIVE)
              this._checkoutDPMRecords(publishedOfferingId, draftOfferingId, this.CONSTANTS.TABLE.SERVICE_OFFERING);

          //set checkout to true on offering
          this._updateCheckoutPublishedState(offeringGr);

          return draftOfferingId;
      } catch (err) {
          throw 'Error while checking out offering ' + offeringGr.name + ': ' + err;
      }
  },

  /**
   * _checkoutBusinessCapabilities
   * private method that creates a copy of the business capabilities for the draft service
   *
   * @param {sysId} publishedServiceId - the sys id published service
   * @param {sysId} draftServiceId - the sys id of the draft service
   */
  _checkoutBusinessCapabilities: function(publishedServiceId, draftServiceId) {
      this._copyReferenceTable(this.CONSTANTS.TABLE.CMDB_REL_CI,
          this.CONSTANTS.FIELD.CHILD,
          publishedServiceId,
          draftServiceId,
          this.CONSTANTS.FIELD.TYPE + '=' + this.CONSTANTS.FIELD_VALUE.PROVIDES_BY_PROVIDES);
  },

  /**
   * _checkoutSubscriptions
   * private method that creates a copy of the subscriptions for the draft offering
   *
   * @param {sysId} publishedOfferingId - the sys id published offering
   * @param {sysId} draftOfferingId - the sys id of the draft offering
   */
  _checkoutSubscriptions: function(publishedOfferingId, draftOfferingId) {
      var subscriptionTables = [
          this.CONSTANTS.TABLE.SERVICE_SUBSCRIBE_COMPANY,
          this.CONSTANTS.TABLE.SERVICE_SUBSCRIBE_DEPARTMENT,
          this.CONSTANTS.TABLE.SERVICE_SUBSCRIBE_LOCATION,
          this.CONSTANTS.TABLE.SERVICE_SUBSCRIBE_SYS_USER_GRP,
          this.CONSTANTS.TABLE.SERVICE_SUBSCRIBE_SYS_USER
      ];
      for (var i = 0; i < subscriptionTables.length; i++) {
          this._copyReferenceTable(subscriptionTables[i],
              this.CONSTANTS.FIELD.SERVICE_OFFERING,
              publishedOfferingId,
              draftOfferingId);

      }
  },

  /**
   * _checkoutCommitments
   * private method that creates a copy of the commitments for the draft offering
   *
   * @param {sysId} publishedOfferingId - the sys id published offering
   * @param {sysId} draftOfferingId - the sys id of the draft offering
   */
  _checkoutCommitments: function(publishedOfferingId, draftOfferingId) {
      this._copyReferenceTable(this.CONSTANTS.TABLE.SERVICE_OFFERING_COMMITMENT,
          this.CONSTANTS.FIELD.SERVICE_OFFERING,
          publishedOfferingId,
          draftOfferingId);
  },

  /**
   * _checkoutCatalogItems
   * private method that creates a copy of the catalog items for the draft offering
   *
   * @param {sysId} publishedOfferingId - the sys id published offering
   * @param {sysId} draftOfferingId - the sys id of the draft offering
   */
  _checkoutCatalogItems: function(publishedOfferingId, draftOfferingId) {
      this._copyReferenceTable(this.CONSTANTS.TABLE.SC_CAT_ITEM_SUBSCRIBE_MTOM,
          this.CONSTANTS.FIELD.SERVICE_OFFERING,
          publishedOfferingId,
          draftOfferingId);
  },

  /**
   * _checkoutDPMRecords
   * private method that creates a copy of records in dpm-related tables for the draft service/offering
   *
   * @param {sysId} publishedId - the sys id published service/offering
   * @param {sysId} draftId - the sys id of the draft service/offering 
   * @param {string} table - table of the records 
   */
  _checkoutDPMRecords: function(publishedId, draftId, table) {
      var utilsDPM = new sn_service_builder.ASBUtilsDPM();
      var tableMappings = utilsDPM.getReferenceTableMappings(table);

      for (var tableName in tableMappings) {
          if (tableMappings.hasOwnProperty(tableName)) {
              this._copyReferenceTable(tableName,
                  tableMappings[tableName].field,
                  publishedId,
                  draftId,
                  (tableMappings[tableName].query || null));
          }
      }
  },

  /**
   * _checkoutDependents
   * private method that creates a copy of the cmdb_rel_ci for Depends On::Used by 
   * for the draft offering
   *
   * @param {sysId} publishedOfferingId - the sys id published offering
   * @param {sysId} draftOfferingId - the sys id of the draft offering
   */
  _checkoutDependents: function(publishedOfferingId, draftOfferingId) {
      this._copyReferenceTable(this.CONSTANTS.TABLE.CMDB_REL_CI,
          this.CONSTANTS.FIELD.PARENT,
          publishedOfferingId,
          draftOfferingId,
          this.CONSTANTS.FIELD.TYPE + '=' + this.CONSTANTS.FIELD_VALUE.DEPENDS_ON_USED_BY);
  },

  /**
   * _copyReferenceTable
   * private method that creates copies of the refrences for the draft record
   *
   * @param {string} tableName - the reference Table to copy record from
   * @param {string} referenceField - the field that links to service or offering reference
   * @param {sysId} publishedId - the sysId of the published record
   * @param {sysId} draftId - the sysId of the draft record
   * @param {string} encodedQuery - optional: additional query to filter records on
   */
  _copyReferenceTable: function(tableName, referenceField, publishedId, draftId, encodedQuery) {
      var publishedGr = new GlideRecord(tableName);
      publishedGr.addQuery(referenceField, publishedId);
      if (encodedQuery)
          publishedGr.addEncodedQuery(encodedQuery);
      publishedGr.query();

      while (publishedGr.next()) {
          var draftGr = new GlideRecord(tableName);
          this.utils.copyFields(publishedGr, draftGr, this.CONSTANTS.EXCLUDED_REFERENCE_FIELDS());
          draftGr.setValue(referenceField, draftId);
          var result = draftGr.insert();
          if (result === null)
              throw 'Error while copying ' + tableName;
      }
  },

  /**
   * _insertCheckoutDraftState
   * private method to set state and insert copied record
   *
   * @param {GlideRecord} gr - the GlideRecord to set state and insert
   * @param {sysId} publishedRef - the record that the draft is copied from
   */
  _insertCheckoutDraftState: function(gr, publishedRef) {
      gr.setValue(this.CONSTANTS.FIELD.CHECKOUT, this.CONSTANTS.FIELD_VALUE.FALSE);
      gr.setValue(this.CONSTANTS.FIELD.PUBLISHED_REF, publishedRef);
      gr.setValue(this.CONSTANTS.FIELD.STATE, this.CONSTANTS.FIELD_VALUE.DRAFT);
      var result = gr.insert();
      if (result === null)
          throw 'Error while setting draft state: ' + gr.name;
      return result;
  },

  /**
   * _updateCheckoutPublishedState
   * private method to set state and update published record
   *
   * @param {GlideRecord} gr - the GlideRecord to set state and insert
   */
  _updateCheckoutPublishedState: function(gr) {
      gr.setValue(this.CONSTANTS.FIELD.CHECKOUT, this.CONSTANTS.FIELD_VALUE.TRUE);
      gr.setValue(this.CONSTANTS.FIELD.STATE, this.CONSTANTS.FIELD_VALUE.PUBLISHED);
      var result = gr.update();
      if (result === null)
          throw 'Error while setting published state: ' + gr.name;
      return result;
  },

  /**
   * _getOfferings
   * get the service's offerings sys_ids and published_refs
   *
   * @param {sysId} serviceId - the service that offerings' will be returned
   * @returns {array} - array of children offerings sys_ids and published_refs
   */
  _getOfferings: function(serviceId) {
      var offerings = [];
      var offeringGr = new GlideRecord(this.CONSTANTS.TABLE.SERVICE_OFFERING);
      offeringGr.addQuery(this.CONSTANTS.FIELD.PARENT, serviceId);
      offeringGr.query();

      while (offeringGr.next()) {
          offerings.push({
              sysId: offeringGr.getUniqueValue(),
              publishedRef: offeringGr.getValue(this.CONSTANTS.FIELD.PUBLISHED_REF),
          });
      }

      return offerings;
  },
  type: 'ASBCheckoutService'
};

Sys ID

d76bdd350703201070e493d0fad300e1

Offical Documentation

Official Docs: