Hotfix

The current hotfix version is 4.0.2.3.

Unifi can be patched between releases by using a special Script Include called hotfix. If you find a bug in Unifi we may issue an update to hotfix so you can get the features you need without having to upgrade.

Upgrading

When upgrading Unifi, you can revert to the latest version of hotfix included in the upgrade. We reset hotfix with each release when the fixes become part of the main application.

Patching

We occasionally release a hotfix when minor issues are found. Simply replace the script in the hotfix Script Include with the one shown below and you will instantly have access to the fixes.

These hotfixes will be shipped as real fixes with the next version of Unifi, so make sure you have the correct hotfix for your version.

/**
 * Executes a child function corresponding to the object's type property.
 * The object is passed to the child function so methods and properties can be overridden.
 *
 * @param  {Object} obj The full class object to be patched.
 */
function hotfix(obj) {
  var type = typeof obj === 'function' ? obj.prototype.type : obj.type;
  if (type && typeof hotfix[type] === 'function') {
    hotfix[type](obj);
  }
}

hotfix.version = '4.0.2.3';

hotfix.Dataset = function (Dataset) {
  // Fix import logging
  Dataset.beginTransform = function beginTransform(dataset_id, import_set) {
    var dataset = Dataset.getInstance(dataset_id);
    var request = DatasetRequest.findActive(dataset);
    if (request.isValidRecord()) {
      ActivityLog.setDocument(request.getRecord());
      request.setProcessing();
      request.setStatus('Transform in progress...');
      request.setImportSet(import_set.sys_id);
      request.commit();
    } else {
      ActivityLog.setDocument(dataset);
    }
    if (!dataset.getElement('import_logging')) {
      ws_console.info('Logging is disabled. Please enable import logging on the Dataset to see Activity Logs for import set rows.');
      ws_console.pause();
    }
  };
};

hotfix.AttachmentHandler = function (AttachmentHandler) {
  // Allow multi-table attachment handling
  AttachmentHandler.createBondAttachment = function createBondAttachment(attachment) {
    var send = false,
        bond_gr,
        gr;

    function getBonds(sys_id, table) {
      var gr = new GlideRecord('x_snd_eb_bond');
      gr.addQuery('document', '=', sys_id);
      gr.addQuery('table', '=', table);
      gr.addQuery('state', '!=', 'Closed');
      gr.query();
      return gr;
    }

    function getConfig(bond) {
      return new Process(bond.integration.process).getConfig();
    }

    bond_gr = getBonds(attachment.table_sys_id, attachment.table_name);

    while (bond_gr.next()) {
      if (AttachmentHandler.addToBond([attachment], new Bond(getConfig(bond_gr), bond_gr))) {
        send = true;
      }
    }

    if (send) {
      gr = new GlideRecord(attachment.table_name);
      gr.get(attachment.table_sys_id);
      if (gr.isValidRecord()) {
        Message.processOutbound(gr, {
          attachment_added: true, // only match messages with "Attachment added" condition
          parent_tables: true // search table hierarchy
        });
      } else {
        gs.error(t('Attachment %0 does not have a valid record. Cannot process outbound.', attachment));
      }
    }
  };
};

hotfix.IntegrationTest = function (IntegrationTest) {
  // Fix integration delete from Designer portal
  IntegrationTest.getDeleteStack = function getDeleteStack(config, sys_id) {
    var stack = new Stack('x_snd_eb_integration_test', 'integration_test');

    if (sys_id) {
      stack.filter('sys_id=' + sys_id); // delete this record
    } else {
      stack.filter(function (scope, data) { // deleting parent record
        if (scope.integration) {
          return 'integration=' + scope.integration;
        }
        return 'sys_id=-1';
      });
    }

    stack.each(function (integration_test, scope, data) {
      scope.integration_test = integration_test.sys_id + '';
    });
    stack.afterEach(function (integration_test, scope, data) {
      integration_test.deleteRecord();
    });

    stack.addChild(IntegrationTestScenario.getDeleteStack(config));

    return stack;
  };
};

hotfix.Bond = function (Bond) {
  // UN-1266 Insert the bond when it is created to prevent double bonds from sync updates that 
  // happen before the insert has finished. This only applies to inbound transactions.
  Bond.prototype.create = function create(integration, internal_ref, external_ref, ref_method) {
    var ref;

    if (!external_ref && !internal_ref) {
      throw this.customError('Cannot create bond. No reference given.');
    }

    if (this.locateReference(integration, internal_ref, external_ref, ref_method)) {
      ref = this._getRefText(internal_ref, external_ref);
      throw this.customError('Bond already exists for document. ' + ref + '.');
    }

    this.newRecord();
    this.setValue('integration', integration.getValue('sys_id'));
    this.setValue('internal_reference', internal_ref);
    this.setValue('external_reference', external_ref);
    this.setValue('state', 'Pending');
    this.setValue('status', 'OK');
    this.isNew(true);
    Model.prototype.commit.apply(this);
  };
};

hotfix.Integration = function (Integration) {
  // Fix UN-1298 error messages defined on the Integration are not retrieved properly
  Integration.prototype.getSyncErrorMessage = function getSyncErrorMessage() {
    return Message.getMessageById(this.getConfig(), this.getValue('sync_error_message'));
  };
  Integration.prototype.getAsyncErrorMessage = function getAsyncErrorMessage() {
    return Message.getMessageById(this.getConfig(), this.getValue('async_error_message'));
  };
};

hotfix.DataSetProcessor = function (DataSetProcessor) {
  // Fix UN-1299 prevent DataSetProcessor events from being queued when there is no additional data to process
  DataSetProcessor.prototype._executeQueue = function _executeQueue(callback) {
    var rows = this._execute(callback);
    if (this.event) {
      if (rows == this.limit && this.gr && this.gr.hasNext()) {
        ws_console.info('Event ' + this.event.name + ' processed the maximum ' + this.limit + ' records. Auto queueing next event.');
        this.queueNext(this.event, this.current);
      } else {
        ws_console.info('Event ' + this.event.name + ' processed less than the maximum ' + this.limit + ' records. Processing complete.');
      }
    } else {
      ws_console.warn('Cannot auto queue additional processing; event not found.');
    }
    return rows;
  };
};

Last updated