diff --git a/entity/QuickEntry_entity/QuickEntry_entity.aod b/entity/QuickEntry_entity/QuickEntry_entity.aod index 5a068896ab8baf86702e15f8537324b65f2352b7..8cc3408b69e20ba2382a7e01d2e62a3896f2cbb4 100644 --- a/entity/QuickEntry_entity/QuickEntry_entity.aod +++ b/entity/QuickEntry_entity/QuickEntry_entity.aod @@ -17,6 +17,7 @@ <name>ORGANISATION_NAME</name> <title>Company</title> <contentType>LONG_TEXT</contentType> + <mandatoryProcess>%aditoprj%/entity/QuickEntry_entity/entityfields/organisation_name/mandatoryProcess.js</mandatoryProcess> </entityField> <entityConsumer> <name>Adresses</name> @@ -30,6 +31,10 @@ <name>ContactId_param</name> <valueProcess>%aditoprj%/entity/QuickEntry_entity/entityfields/adresses/children/contactid_param/valueProcess.js</valueProcess> </entityParameter> + <entityParameter> + <name>ContactType_param</name> + <valueProcess>%aditoprj%/entity/QuickEntry_entity/entityfields/adresses/children/contacttype_param/valueProcess.js</valueProcess> + </entityParameter> </children> </entityConsumer> <entityConsumer> diff --git a/entity/QuickEntry_entity/entityfields/organisation_name/mandatoryProcess.js b/entity/QuickEntry_entity/entityfields/organisation_name/mandatoryProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..46000731125e26321ec3f999ce0a1ed25a488019 --- /dev/null +++ b/entity/QuickEntry_entity/entityfields/organisation_name/mandatoryProcess.js @@ -0,0 +1,8 @@ +import("system.result"); +import("system.neon"); +import("system.vars"); + +var address = vars.get("$field.OrgAddresses.insertedRows"); +var isMandatory = address[0] != null || "" ? true : false; + +result.string(isMandatory); \ No newline at end of file diff --git a/process/Entity_lib/process.js b/process/Entity_lib/process.js index 15acae96dcb79034c55ddace8cac74dc9a9f05d8..72e4a77460cc06bc365ec5eb6c2ea4d9b9cacfcb 100644 --- a/process/Entity_lib/process.js +++ b/process/Entity_lib/process.js @@ -1,3 +1,4 @@ +import("system.translate"); import("system.result"); import("system.neon"); import("system.vars"); @@ -173,4 +174,198 @@ FieldChanges._getStorage = function() FieldChanges._setStorage = function(pAllChanges) { return vars.set("$context.FieldChanges", pAllChanges); -}; \ No newline at end of file +}; + +/** + * Object for testing if linked datasets exists. You can add validations with the provided methods, note that these validations will be done in the + * same order you added them until one of them results in false. Therefore, you should add the tests that are most likely to fail first. + * + * @param {String[]} pConsumers names of the consumers to be tested + */ +function HasLinkedObjectTester (pConsumers) +{ + //This array will contain objects that are used for the validation. You can put any object in this array as long as it provides + //a method 'checkForObjects' that can be invoked. + this._validationObjects = []; + + if (pConsumers) + pConsumers.forEach(this.andNoConsumerRows, this); + + Object.defineProperty(this, "length", { + get : function () {return this._validationObjects.length;} + }); +} + +/** + * @ignore + */ +HasLinkedObjectTester._testForEntity = function () +{ + entities.createConfigForLoadingConsumerRows() + var loadConfig = entities.createConfigForLoadingRows() + .entity(this.entity) + .provider(this.provider) + .ignorePermissions(true); + + if (this.parameters) + { + for (let param in this.parameters) + loadConfig.addParameter(param, this.parameters[param]); + } + return entities.getRowCount(loadConfig) == 0; +} + +/** + * @ignore + */ +HasLinkedObjectTester._testForConsumer = function () +{ + //TODO: implement when possible + return false; +} + +/** + * @ignore + */ +HasLinkedObjectTester._testForCallback = function () +{ + fnResult = this.callbackFn(); + return this.failValue + ? fnResult != this.failValue + : fnResult; +} + +/** + * @ignore + */ +HasLinkedObjectTester._testForSqlCount = function () +{ + //also works for empty string because Number("") returns 0 + return Number(this.sqlQuery.cell()) === 0; +} + +/** + * !!! YOU CAN'T USE THIS FUNCTION YET !!! + * + * Adds a consumer to test for rows to the object. + * + * @ignore + * + * @param {String} pConsumer name of the consumer + * @return {HasLinkedObjectTester} current object + */ +HasLinkedObjectTester.prototype.andNoConsumerRows = function (pConsumer) +{ + throw new Error("HasLinkedObjectTester.prototype.andNoConsumerRows does not work yet") + this._validationObjects.push({ + checkForObjects : HasLinkedObjectTester._testForConsumer, + consumer : pConsumer + }); + return this; +} + +/** + * Adds a entity with provider to test for rows. You have to set the parameters by yourself. + * + * @param {String} pEntity name of the entity + * @param {String} pProvider provider that should be used + * @param {Object} [pParameters] parameters to set + * @return {HasLinkedObjectTester} current object + * @example + * new HasLinkedObjectTester() + * .andNoEntityRows("Activity_entity", "LinkedObjects", {ObjectId_param : currentContext, RowId_param : contactId}) + */ +HasLinkedObjectTester.prototype.andNoEntityRows = function (pEntity, pProvider, pParameters) +{ + this._validationObjects.push({ + checkForObjects : HasLinkedObjectTester._testForEntity, + entity : pEntity, + provider : pProvider, + parameters : pParameters + }); + return this; +} + +/** + * Adds a custom callback function that tests for linked objects. The reason for using a callback function here is that it will only be called if + * necessary. + * + * @param {Function} pCallbackFn validation function, it should return true if NO linked objects were found, but the expected value can be changed + * by providing an own 'pFailValue' + * @param {Object} [pFailValue=false] if the given function returns this value, the ovarall validation will fail and return false + * @return {HasLinkedObjectTester} current object + */ +HasLinkedObjectTester.prototype.and = function (pCallbackFn, pFailValue) +{ + if (typeof pCallbackFn !== "function") + throw new TypeError(translate.text("pCallbackFn is not a function")); + + this._validationObjects.push({ + checkForObjects : HasLinkedObjectTester._testForCallback, + callbackFn : pCallbackFn, + failValue : pFailValue + }); + return this; +} + +/** + * Adds a SqlBuilder object to the validation that should return a single number (e. g. "select count(*) ..."). If the result of the SQL is not 0, + * the overall validation will return false. + * + * @param {SqlBuilder} pSqlQuery the SqlBuilder object, the SQL will be executed with SqlBuilder.prototype.cell() and is expected to result in a number + * @return {HasLinkedObjectTester} current object + */ +HasLinkedObjectTester.prototype.andSqlYieldsZero = function (pSqlQuery) +{ + if (!(pSqlQuery instanceof SqlBuilder)) + throw new TypeError(translate.text("pSqlQuery must be of type SqlBuilder")); + + this._validationObjects.push({ + checkForObjects : HasLinkedObjectTester._testForSqlCount, + sqlQuery : pSqlQuery + }); + return this; +} + +/** + * Executes the validation of all tests that have been added to the object. If every test returns true, the result will also be true, + * but if any test returns false, the execution will stop and false is returned. + * + * @return {Boolean} true, if NO linked objects were found + */ +HasLinkedObjectTester.prototype.validate = function () +{ + return this._validationObjects.every(function (duck) + { + return duck.checkForObjects(); + }); +} + +/** + * @return {String} validation result as String, so that .validate() does not always have to be called explicitly + */ +HasLinkedObjectTester.prototype.toString = function () +{ + return String(this.validate()); +}; + +/** +* Provides static methods for special handling of consumer in entities. +* +* @class +*/ +function EntityConsumerUtils(){} + +/** + * Method wich clears all fields behind the consumer. + * @param pConsumer the consumer which fields will be cleared. + * @return {void} + */ +EntityConsumerUtils.rmInsertedConsumerRows = function(pConsumer) +{ + var insertedRows = vars.get("$field." + pConsumer + ".insertedRows"); + insertedRows.forEach(function(row) + { + neon.deleteRecord(pConsumer, row["#UID"]); + }); +};