importPackage(Packages.de.elo.ix.client); //@include lib_Class.js //@include lib_sol.common.SordUtils.js //@include lib_sol.common.RepoUtils.js //@include lib_sol.common.WfUtils.js //@include lib_sol.common.StringUtils.js //@include lib_sol.common.ObjectUtils.js //@include lib_sol.common.CounterUtils.js //@include lib_sol.common.Template.js //@include lib_sol.common.TranslateTerms.js //@include lib_sol.common.ObjectFormatter.js //@include lib_sol.common.ix.RfUtils.js //@include lib_sol.common.ix.FunctionBase.js //@include lib_sol.common.ConnectionUtils.js var logger = sol.create("sol.Logger", { scope: "sol.common.ix.functions.Set" }); // eslint-disable-line one-var /** * Edits an existing object by changing the mask or setting different values. * * # As workflow node * * ObjId is set based on the element that the workflow is attached to. * * The timeZone parameter is currently not supported in conjunction with `asAdmin` * because we don't want to rewrite the clientInfo of the adminConnection temporarily * * Following configuration should be applied to the comments field for a mask and field update: * * ## Example * * { * "entries": [{ * "type": "MASK", // changes the mask of the sord, if defined more than once, the first one will be used * "value": "Basic Entry" * }, { * "type": "SORD", * "key": "name", * "value": "Contract {{sord.objKeys.CONTRACT_NAME}} - {{count 'MY_CONTRACT_COUNTER'}}", * "useTemplating": true * }, { * "type": "GRP", * "key": "CONTRACT_STATUS", * "value": "D", * "useDynKwl": true, * "dynKwlCfg": { * "filterColumn": 0, * "returnColumn": 2 * }, * "onlyIfEmpty": true * }, { * "type": "MAP", * "key": "USER", * "value": "Bill Gates", * }, { * "type": "WFMAP", * "key": "USER", * "value": "Steve Jobs" * }, { * "type": "WF", * "key": "STATUS", * "value": "CREATE" * }] * } * * Following configuration should be applied to the comments field and will set a value from the fields KWL starting with '3' * * { * "entries": [{ * "type": "GRP", * "key": "INVOICE_STATUS", * "value": "3", * "useKwl": true * }] * } * * Following configuration will set a field from the fields dynamic KWL staring with 'M' (e.g. M - month) from a localized dynamic KWL * * { * "type": "GRP", * "key": "REMINDER_PERIOD_UNIT", * "value": "M", * "useDynKwl": true, * "dynKwlCfg": { * "returnColumn": 2, * "filterColumn": 0 * } * } * * # As IX function call * * In addition to the workflow node configuration the objId must be passed. * * sol.common.IxUtils.execute("RF_sol_function_Set", { * objId: "4711", * asAdmin: true, * entries: [{ * type: "GRP", * key: "INVOICE_STATUS", * value: "3", * useKwl: true * }] * }); * * * @eloix * @requires sol.Logger * @requires sol.common.SordUtils * @requires sol.common.JsonUtils * @requires sol.common.RepoUtils * @requires sol.common.StringUtils * @requires sol.common.ObjectUtils * @requires sol.common.CounterUtils * @requires sol.common.Template * @requires sol.common.TranslateTerms * @requires sol.common.ObjectFormatter.TemplateSord * @requires sol.common.WfUtils * @requires sol.common.ix.RfUtils * @requires sol.common.ix.FunctionBase * @requires sol.common.ix.ConnectionUtils * */ sol.define("sol.common.ix.functions.Set", { extend: "sol.common.ix.FunctionBase", requiredConfig: ["objId", "entries"], /** * @cfg types which are supported * @private */ types: ["MASK", "SORD", "GRP", "MAP", "FORMBLOB", "WFMAP", "WF"], /** * @cfg {String} objId (required) * Object ID */ /** * @cfg {Object[]} entries (required) * @cfg {String} entries.key field key * @cfg {String} entries.type the type of the field {@link sol.common.ix.functions.Set#types} * @cfg {String} entries.value the value which should be set * @cfg {Boolean} entries.useKwl enable keyword lookup for the current value * @cfg {Boolean} entries.useDynKwl enable dynamic keyword lookup for the current value * @cfg {Object} entries.dynKwlCfg * @cfg {Boolean} entries.onlyIfEmpty the value will only be set when selected field is not empty * * Entries that contains the values to set */ /** * @cfg {String} flowId * Flow ID */ /** * @cfg {String} timeZone * Time zone */ /** * @cfg {Boolean} asAdmin * Execute function in admin context */ initialize: function (config) { var me = this; me.$super("sol.common.ix.FunctionBase", "initialize", [config]); me.sordMaskChanged = false; if (me.asAdmin) { if (me.wfDiagram) { me.checkAdminExecutionContext(function () { sol.common.WfUtils.checkMainAdminWf(me.wfDiagram); }); } else { me.checkAdminExecutionContext(function () { sol.common.ix.RfUtils.checkMainAdminRights(sol.common.IxConnectionUtils.getCurrentUser()); }); } if (me.timeZone) { // We should not change ixConnectAdmin timeZone parameter because this object // is a singleton. throw Error("Use of an admin connection in combination with the timeZone parameter is currently not implemented"); } } me.connection = sol.common.IxConnectionUtils.getConnection(me.asAdmin); }, checkAdminExecutionContext: function (callback) { var me = this; try { if (!callback || !sol.common.ObjectUtils.isFunction(callback)) { throw Error("Callback in `checkAdminExecutionContext` is not a callback function"); } callback.call(me); } catch (ex) { logger.warn("Ignore `asAdmin` parameter", ex); me.asAdmin = false; if (me.$throwError === true) { throw ex; } } }, /** * Sets a field value */ process: function () { var me = this, i, entry, type, func, entries; if (!me.entries) { return; } me.logger.debug(["sol.common.ix.functions.Set: entries={0}", JSON.stringify(me.entries)]); me.entries = sol.common.ObjectUtils.clone(me.entries); me.separatedEntries = {}; me.sordData = []; me.sordMapKeyValues = []; me.sordFormdataValues = []; //blob me.wfMapKeyValues = []; if (me.timeZone) { me.savedTimeZone = ixConnect.loginResult.clientInfo.timeZone; ixConnect.loginResult.clientInfo.timeZone = me.timeZone; me.logger.debug(["user.name={0}, timeZone={1}", ixConnect.loginResult.user.name, ixConnect.loginResult.clientInfo.timeZone]); } me.sord = sol.common.RepoUtils.getSord(me.objId, { sordZ: SordC.mbAllIndex, connection: me.connection }); for (i = 0; i < me.entries.length; i++) { entry = me.entries[i]; type = entry.type.toUpperCase(); if (me.types.indexOf(entry.type) < 0) { throw "Unsupported type: " + entry.type; } if (!me.filterEntry(me.sord, entry)) { me.separatedEntries[type] = me.separatedEntries[type] || []; me.separatedEntries[type].push(entry); } } for (i = 0; i < me.types.length; i++) { type = me.types[i]; func = me["processType" + type]; entries = me.separatedEntries[type]; me.logger.debug(["separatedEntries[{0}]={1}", type, JSON.stringify(entries)]); if (func && entries) { func.call(me, me.separatedEntries[type]); } } me.saveSordValues(); me.saveWorkflowValues(); if (me.savedTimeZone) { ixConnect.loginResult.clientInfo.timeZone = me.savedTimeZone; } }, emptyFilterTypes: ["GRP", "MAP"], filterEntry: function (sord, entry) { var me = this; return !!( ~me.emptyFilterTypes.indexOf(entry.type) && entry.onlyIfEmpty && String(sol.common.SordUtils.getValue(sord, entry) || "") ); }, processTypeMASK: function (maskEntries) { var me = this, mask; if (maskEntries.length > 0) { mask = maskEntries[0].value; if (mask && sol.common.SordUtils.docMaskExists(mask)) { me.sord = me.connection.ix().changeSordMask(me.sord, mask, EditInfoC.mbSord).sord; me.sordMaskChanged = true; } } }, processTypeSORD: function (sordEntries) { var me = this; me.applyTemplates(sordEntries); me.sordData = me.sordData.concat(sordEntries); }, processTypeGRP: function (grpEntries) { var me = this, i, entry; me.applyTemplates(grpEntries); for (i = 0; i < grpEntries.length; i++) { entry = grpEntries[i]; if (entry.useKwl) { entry.value = me.getValueFromKwl(entry.key, entry.value); } else if (entry.useDynKwl) { entry.value = me.getValueFromDynKwl(me.sord.maskName, entry.key, entry.value, entry.dynKwlCfg, entry.useForeignKey); } } me.sordData = me.sordData.concat(grpEntries); }, processTypeMAP: function (sordMapEntries) { var me = this, i, entry; me.applyTemplates(sordMapEntries); for (i = 0; i < sordMapEntries.length; i++) { entry = sordMapEntries[i]; me.sordMapKeyValues.push(new KeyValue(entry.key, entry.value)); } }, processTypeFORMBLOB: function (sordMapEntries) { var me = this, blb, i, entry; me.applyTemplates(sordMapEntries); for (i = 0; i < sordMapEntries.length; i++) { entry = sordMapEntries[i]; if (entry.asJSON) { try { entry.value = JSON.stringify(entry.value); } catch (e) { throw "SET: could not stringify value marked with option 'asJSON'. Writing to FORMBLOB field `" + entry.key + "` failed."; } } blb = new MapValue((new java.lang.String(entry.key)), (new FileData("text/plain", (new java.lang.String(entry.value)).getBytes(java.nio.charset.StandardCharsets.UTF_8)))); me.sordFormdataValues.push(blb); } }, processTypeWFMAP: function (wfMapEntries) { var me = this, i, entry; me.applyTemplates(wfMapEntries); for (i = 0; i < wfMapEntries.length; i++) { entry = wfMapEntries[i]; me.wfMapKeyValues.push(new KeyValue(entry.key, entry.value)); } }, processTypeWF: function (wfEntries) { var me = this, i, entry; if (!me.wfDiagram) { return; } me.applyTemplates(wfEntries); for (i = 0; i < wfEntries.length; i++) { entry = wfEntries[i]; if (entry.key == "STATUS") { sol.common.WfUtils.setWorkflowStatus(me.wfDiagram, entry.value); } } }, applyTemplates: function (entries) { var me = this, maxLength, i, entry; for (i = 0; i < entries.length; i++) { entry = entries[i]; if (entry.useTemplating && entry.value) { me.tplSord = me.tplSord || sol.common.WfUtils.getTemplateSord(me.sord, me.flowId, { formBlobs: entry.useFormBlobs || false }); entry.value = sol.create("sol.common.Template", { source: entry.value }).apply(me.tplSord); } if (entry.truncate === true) { maxLength = entry.maxLength || ixConnect.CONST.SORD.lnName; entry.value = sol.common.StringUtils.truncate(entry.value, maxLength); } } }, /** * @private */ saveSordValues: function () { var me = this, sordDirty = me.sordMaskChanged; if (me.sordData && (me.sordData.length > 0)) { sol.common.SordUtils.updateSord(me.sord, me.sordData); sordDirty = true; } if (sordDirty) { me.connection.ix().checkinSord(me.sord, SordC.mbAllIndex, LockC.NO); } if (me.sordMapKeyValues && (me.sordMapKeyValues.length > 0)) { me.connection.ix().checkinMap(MapDomainC.DOMAIN_SORD, me.sord.id || me.objId, me.sord.id || me.objId, me.sordMapKeyValues, LockC.NO); } if (me.sordFormdataValues && (me.sordFormdataValues.length > 0)) { // blob me.connection.ix().checkinMap("formdata", me.sord.id || me.objId, me.sord.id || me.objId, me.sordFormdataValues, LockC.NO); } }, /** * @private */ saveWorkflowValues: function () { var me = this; if (me.wfMapKeyValues && (me.wfMapKeyValues.length > 0)) { if (!me.flowId) { throw "Flow ID is empty"; } me.connection.ix().checkinMap(MapDomainC.DOMAIN_WORKFLOW_ACTIVE, me.flowId, me.sord.id || me.objId, me.wfMapKeyValues, LockC.NO); } }, /** * @private * Retrieves a value from the keyword list of the specified field. * It checks, if one of the entries in the keyword list starts with the valuePrefix. * @param {String} fieldName * @param {String} valuePrefix * @return {String} The found item from the keyword list or the valuePrefix, if nothing was found */ getValueFromKwl: function (fieldName, valuePrefix) { var me = this, kwl, items, i, item; kwl = me.connection.ix().checkoutKeywordList(fieldName, KeywordC.mbView, 30, LockC.NO); if (kwl) { items = kwl.children; for (i = 0; i < items.length; i++) { item = items[i].text; if (item.startsWith(valuePrefix)) { return item; } } } else { this.logger.warn(["No keywordlist for field '{0}'", fieldName]); } this.logger.warn(["No keywordlist match for: '{0}'", valuePrefix]); return valuePrefix; }, /** * @private * Retrieves a value from the dynamic keyword list of the spezified field. * It checks, if one of the entries in the keyword list starts with the valuePrefix. * @param {String} maskName * @param {String} fieldName * @param {String} valuePrefix * @param {Object} config * @param {Object} foreignKeyConfig * @return {String} The found item from the keyword list or the valuePrefix, if nothing was found */ getValueFromDynKwl: function (maskName, fieldName, valuePrefix, config, foreignKeyConfig) { var me = this, params, result; params = { data: valuePrefix }; if (config) { params.returnColumn = config.returnColumn; params.filterColumn = config.filterColumn; } if (foreignKeyConfig) { foreignKeyConfig.value === undefined && me.entries.some(function (entry) { return (entry.key === foreignKeyConfig.key) && ((foreignKeyConfig.value = entry.value), true); // empty strings are ok }); if (foreignKeyConfig.value === undefined) { throw "No value found for foreignKey " + foreignKeyConfig.key + ". Please define an array-entry having said key or define a value directly in `useForeignKey`"; } params.useForeignKey = foreignKeyConfig; } result = sol.common.SordUtils.getDynamicKeywordlistValue(maskName, fieldName, params); if (result.length <= 0) { this.logger.warn(["No keywordlist match for: '{0}'", valuePrefix]); } else if (result.length > 1) { this.logger.warn(["No unique keywordlist match for: '{0}'", valuePrefix]); } else { valuePrefix = result[0]; } return result; } }); /** * @member sol.common.ix.functions.Set * @static * @inheritdoc sol.common.ix.FunctionBase#onEnterNode */ function onEnterNode(clientInfo, userId, wfDiagram, nodeId) { var params, module; logger.enter("onEnterNode_Set", { flowId: wfDiagram.id, nodeId: nodeId }); params = sol.common.WfUtils.parseAndCheckParams(wfDiagram, nodeId, "entries"); params.objId = wfDiagram.objId; params.flowId = wfDiagram.id; params.wfDiagram = wfDiagram; module = sol.create("sol.common.ix.functions.Set", params); module.process(); logger.exit("onEnterNode_Set"); } /** * @member sol.common.ix.functions.Set * @static * @inheritdoc sol.common.ix.FunctionBase#onExitNode */ function onExitNode(clientInfo, userId, wfDiagram, nodeId) { var params, module; logger.enter("onExitNode_Set", { flowId: wfDiagram.id, nodeId: nodeId }); params = sol.common.WfUtils.parseAndCheckParams(wfDiagram, nodeId, "entries"); params.objId = wfDiagram.objId; params.flowId = wfDiagram.id; params.wfDiagram = wfDiagram; module = sol.create("sol.common.ix.functions.Set", params); module.process(); logger.exit("onExitNode_Set"); } /** * @member sol.common.ix.functions.Set * @method RF_sol_function_Set * @static * @inheritdoc sol.common.ix.FunctionBase#RF_FunctionName */ function RF_sol_function_Set(ec, args) { var params, module; logger.enter("RF_sol_function_Set", args); params = sol.common.ix.RfUtils.parseAndCheckParams(ec, arguments.callee.name, args, "objId", "entries"); // Hint: Must never be true within an Registered function call // because this would result in a security issue because each person can // update each sord object within the repository //params.asAdmin = false; module = sol.create("sol.common.ix.functions.Set", params); module.process(); logger.exit("RF_sol_function_Set"); }