diff --git a/aliasDefinition/Data_alias/Data_alias.aod b/aliasDefinition/Data_alias/Data_alias.aod index 0673fab6659afbf5bfe6e886f9b9de938cdb928f..de3b537eb9c335c04569c56e16867be3faa4b694 100644 --- a/aliasDefinition/Data_alias/Data_alias.aod +++ b/aliasDefinition/Data_alias/Data_alias.aod @@ -15791,7 +15791,7 @@ <description></description> <auditSyncConfig> <name>auditSyncConfig</name> - <auditMode v="0" /> + <auditMode v="1" /> <syncActive v="false" /> <syncComplete v="true" /> <syncDirection v="1" /> @@ -15823,8 +15823,20 @@ <isUnique v="false" /> <index v="false" /> <documentation></documentation> - <title></title> + <title>District assignment status</title> <description></description> + <customProperties> + <customBooleanProperty> + <name>log</name> + <global v="false" /> + <property v="true" /> + </customBooleanProperty> + <customJDitoProperty> + <name>translate4Log</name> + <global v="false" /> + <property>%aditoprj%/aliasDefinition/Data_alias/aliasdefinitionsub/entitygroup/entities/districtcontact/entityfields/status/customproperties/translate4log/property.js</property> + </customJDitoProperty> + </customProperties> </entityFieldDb> <entityFieldDb> <name>ADVISER_ROLE</name> @@ -15895,6 +15907,18 @@ <documentation></documentation> <title></title> <description></description> + <customProperties> + <customBooleanProperty> + <name>log</name> + <global v="false" /> + <property v="false" /> + </customBooleanProperty> + <customStringProperty> + <name>tableRef</name> + <global v="false" /> + <property>CONTACT</property> + </customStringProperty> + </customProperties> </entityFieldDb> <entityFieldDb> <name>VALID_FROM</name> diff --git a/aliasDefinition/Data_alias/aliasdefinitionsub/entitygroup/entities/districtcontact/entityfields/status/customproperties/translate4log/property.js b/aliasDefinition/Data_alias/aliasdefinitionsub/entitygroup/entities/districtcontact/entityfields/status/customproperties/translate4log/property.js new file mode 100644 index 0000000000000000000000000000000000000000..c079c7fd8009ca6915d731ed02160ad0e9d8ecfa --- /dev/null +++ b/aliasDefinition/Data_alias/aliasdefinitionsub/entitygroup/entities/districtcontact/entityfields/status/customproperties/translate4log/property.js @@ -0,0 +1,19 @@ +import("system.translate"); +import("Keyword_lib"); +import("KeywordRegistry_basic"); +import("District_lib"); +import("system.result"); +import("Loghistory_lib"); +import("Contact_lib"); + +var params = Translate4LogParams.load(); + +//Keyword umschlüsseln +var keyname = KeywordUtils.getViewValue($KeywordRegistry.contactStatus(), params.value); + +//Gebiet und Betreur umschlüsseln +var arrDistrictContact = DistrictUtils.getDataFromDistrictContact(params.rowId); +var districtName = DistrictUtils.getDistrictName(arrDistrictContact[0]); +var adviserName = ContactUtils.getFullTitleByContactId(arrDistrictContact[1]) + +result.string(keyname + " (" + translate.text("District") + ": " + districtName + "; " + translate.text("Adviser") + ": " + adviserName + ")"); \ No newline at end of file diff --git a/entity/District_entity/District_entity.aod b/entity/District_entity/District_entity.aod index 659e44b7f874f1d637273ff55d506a446d860841..fa41a81526f5375212d0744b02a25651701dee16 100644 --- a/entity/District_entity/District_entity.aod +++ b/entity/District_entity/District_entity.aod @@ -258,6 +258,11 @@ <dropDownProcess>%aditoprj%/entity/District_entity/entityfields/district_autoadd/dropDownProcess.js</dropDownProcess> <valueProcess>%aditoprj%/entity/District_entity/entityfields/district_autoadd/valueProcess.js</valueProcess> </entityField> + <entityActionField> + <name>assignDistrict</name> + <title>Assign district</title> + <onActionProcess>%aditoprj%/entity/District_entity/entityfields/assigndistrict/onActionProcess.js</onActionProcess> + </entityActionField> </entityFields> <recordContainers> <dbRecordContainer> diff --git a/entity/District_entity/entityfields/assigndistrict/onActionProcess.js b/entity/District_entity/entityfields/assigndistrict/onActionProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..301a4faa165f45602f002d29390ecc7d2a11ec6a --- /dev/null +++ b/entity/District_entity/entityfields/assigndistrict/onActionProcess.js @@ -0,0 +1,13 @@ +import("system.question"); +import("system.util"); +import("system.notification"); +import("system.translate"); +import("District_lib"); +import("system.vars"); + +var districtId = vars.get("$field.DISTRICTID"); +var appliedFilter = vars.get("$field.appliedFilter"); + +question.showMessage(translate.text("District assignment will start now!")) + +DistrictUtils.assignDistrictOnServer(districtId, appliedFilter); diff --git a/neonNotificationType/DistrictAssigned/DistrictAssigned.aod b/neonNotificationType/DistrictAssigned/DistrictAssigned.aod new file mode 100644 index 0000000000000000000000000000000000000000..d3acf304d7d808619faba61d320706818107cb06 --- /dev/null +++ b/neonNotificationType/DistrictAssigned/DistrictAssigned.aod @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonNotificationType xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonNotificationType/1.1.0"> + <name>DistrictAssigned</name> + <title>District assigned</title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <icon>VAADIN:GLOBE</icon> +</neonNotificationType> diff --git a/others/language_DE.txt b/others/language_DE.txt index 08910a399410e73a226c2703be4c1e89f45a345b..7d3a7923a6bf19f212e11be043b80193707f9d8f 100644 --- a/others/language_DE.txt +++ b/others/language_DE.txt @@ -37,4 +37,24 @@ <entry> <key>Field Service</key> <value>Außendienst</value> + </entry> + <entry> + <key>Assign district</key> + <value>Gebiet zuordnen</value> + </entry> + <entry> + <key>District assignment will start now!</key> + <value>Die Gebietszuordnung wird jetzt gestartet!</value> + </entry> + <entry> + <key>Assignment of district \"%0\" is completed!</key> + <value>Zuordnung des Gebietes \"%0\" ist abgeschlossen!</value> + </entry> + <entry> + <key>%0 companies were newley assigned to this district. \n %1 companies are no longer assigned to this district (these assignments got the status 'review'). \n %2 valid assignments were unchanged. \n The Process took %3 seconds. </key> + <value>%0 Firmen wurden dem Gebiet neu hinzugefügt. \n %1 Firmen sind diesem Gebiet nicht länger zugeordnet (diese Zuordnungen wurden auf den Status 'zur Prüfung' gesetzt). \n %2 gültige Zuordnungen blieben unverändert. \n Der Prozess dauert %3 Sekunden. </value> + </entry> + <entry> + <key>District assignment status</key> + <value>Gebietzuordnungstatus</value> </entry> \ No newline at end of file diff --git a/others/language_EN.txt b/others/language_EN.txt index 651df12fdc8a3d948cb68b68178f5c4a1f871d59..7a6da3e4bef09597d2498d577104d3d2b89bf315 100644 --- a/others/language_EN.txt +++ b/others/language_EN.txt @@ -27,4 +27,19 @@ </entry> <entry> <key>Field Service</key> + </entry> + <entry> + <key>Assign district</key> + </entry> + <entry> + <key>District assignment will start now!</key> + </entry> + <entry> + <key>Assignment of district \"%0\" is completed!</key> + </entry> + <entry> + <key>%0 companies were newley assigned to this district. \n %1 companies are no longer assigned to this district (these assignments got the status 'review'). \n %2 valid assignments were unchanged. \n The Process took %3 seconds. </key> + </entry> + <entry> + <key>District assignment status</key> </entry> \ No newline at end of file diff --git a/process/District_lib/District_lib.aod b/process/District_lib/District_lib.aod new file mode 100644 index 0000000000000000000000000000000000000000..e349479bbe39378afa83ce81559bda59e9ad12d6 --- /dev/null +++ b/process/District_lib/District_lib.aod @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1"> + <name>District_lib</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <process>%aditoprj%/process/District_lib/process.js</process> + <alias>Data_alias</alias> + <variants> + <element>LIBRARY</element> + </variants> +</process> diff --git a/process/District_lib/process.js b/process/District_lib/process.js new file mode 100644 index 0000000000000000000000000000000000000000..03abf8d35d1f5bee408a4c4cff09182fbcad1a67 --- /dev/null +++ b/process/District_lib/process.js @@ -0,0 +1,219 @@ +import("KeywordRegistry_basic"); +import("system.vars"); +import("system.util"); +import("Sql_lib"); +import("Util_lib"); +import("system.db"); +import("system.indexsearch"); +import("JditoFilter_lib"); +import("Util_lib"); +import("system.process"); +import("Employee_lib"); + +/** + * Functions for district. + */ +function DistrictUtils () {} + +/** + * Gets the name of a district + * + * @param {String} pDistrictId <p> + * Id of the district.<br> + * @return {String} <p> + * Name of the district.<br> + */ +DistrictUtils.getDistrictName = function (pDistrictId) +{ + var districtName = newSelect("DISTRICT_NAME") + .from("DISTRICT") + .where("DISTRICT.DISTRICTID", pDistrictId) + .cell(true); + + return(districtName) +} + +/** + * Gets the id of a district + * + * @param {String} pDistrictContactId <p> + * Id of the districtcontact.<br> + * @return {Array} <p> + * array of data from one districtcontact dataset <br> + */ +DistrictUtils.getDataFromDistrictContact = function (pDistrictContactId) +{ + var arrData = newSelect("DISTRICT_ID, ADVISER_CONTACT_ID") + .from("DISTRICTCONTACT") + .where("DISTRICTCONTACT.DISTRICTCONTACTID", pDistrictContactId) + .arrayRow(); + + return(arrData); +} + + +/** + * Executes a process to assign districts on the server and creates a notification when finished. + * + * @param {String} pDistrictId <p> + * Id of the district.<br> + * @param {String} pAppliedFilter <p> + * Filter condition to get the assigned companies.<br> + * @param {String} pUser=currentUser (optional) <p> + * User that will get the notification, <br> + * if null (not undefined!), no notification<br> + * will be created.<br> + */ +DistrictUtils.assignDistrictOnServer = function (pDistrictId, pAppliedFilter, pUser) +{ + //pUser hat folgendes Format: _____USER_bcdfb521-c7d0-4ef1-8916-78e7d3232046 + if (pUser === undefined) + pUser = EmployeeUtils.getCurrentUserId(); + var processConfig = process.createStartAsyncConfig() + .setName("assignDistrict_serverProcess") + .setLocalVariables({ + districtId : pDistrictId, + appliedFilter : pAppliedFilter, + user : pUser || "" + }) + .setUser(pUser) + process.startAsync(processConfig); +} + +/** + * Assignes a district to companies. You should only call this function on the server because it + * can take some time to execute, use DistrictUtils.assignDistrictOnServer instead. + * + * @param {String} pDistrictId <p> + * Id of the district.<br> + * @param {String} pAppliedFilter <p> + * Filter condition to get the assigned companies.<br> + * @return {Object} <p> + * Count of new assigned companies and no longer assigned companies.<br> + */ +DistrictUtils.assignDistrict = function (pDistrictId, pAppliedFilter) +{ + var newAssigned = 0; + var unchanged = 0; + var invalid = 0; + + //Einlesen von allen bereits existierenden automatischen Zuordnungen, + //die nicht auf Status 'zur Prüfung' sthen + var arrExistingIds = new SqlBuilder() + .select("DISTRICTCONTACT.DISTRICTCONTACTID, DISTRICTCONTACT.CONTACT_ID, DISTRICTCONTACT.ADVISER_CONTACT_ID") + .from("DISTRICTCONTACT") + .where("DISTRICTCONTACT.DISTRICT_ID", pDistrictId) + .and ("DISTRICTCONTACT.ORIGIN", $KeywordRegistry.districtOrigin$auto()) + .and ("DISTRICTCONTACT.STATUS", $KeywordRegistry.contactStatus$inReview(), SqlBuilder.NOT_EQUAL()) + .table(); + + //Einlesen aller Betreuer, die dem übergebenen Gebiet zugeordnet sind + var arrResponsibleIds = new SqlBuilder() + .select("DISTRICTRESPONSIBLE.EMPLOYEE_CONTACT_ID, DISTRICTRESPONSIBLE.ADVISER_ROLE, " + + "DISTRICTRESPONSIBLE.ADVISER_STATUS, DISTRICTRESPONSIBLE.VALID_FROM, DISTRICTRESPONSIBLE.VALID_UNTIL") + .from("DISTRICTRESPONSIBLE") + .where("DISTRICTRESPONSIBLE.DISTRICT_ID", pDistrictId) + .table(); + + //Aufbereiten des im JSON-Format übergebenen Filters in eine SQL-Condition + var appliedFilterCondition = JSON.parse(pAppliedFilter).filter; + appliedFilterCondition = JSON.stringify(appliedFilterCondition); + var sqlCondition = db.toFilterCondition(appliedFilterCondition, "Organisation_entity") + + //Einlesen der Contact-IDs zu den Firmen, die gemäß Filter diesem Gebiet zugeordnet sind + var arrOrgContactIds = new SqlBuilder() + .selectDistinct("CONTACT.CONTACTID") + .from("ORGANISATION") + .join("CONTACT", newWhere("ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID").and("CONTACT.PERSON_ID is null")) + .leftJoin("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID") + .leftJoin("CLASSIFICATIONSTORAGE", "CLASSIFICATIONSTORAGE.OBJECT_ROWID = CONTACT.CONTACTID") + .whereIfSet(sqlCondition) + .arrayColumn(); + + var insertArray = []; + var colsInsert = [ + "DISTRICTCONTACTID", + "CONTACT_ID", + "DISTRICT_ID", + "ADVISER_CONTACT_ID", + "ADVISER_ROLE", + "STATUS", + "VALID_FROM", + "VALID_UNTIL", + "ORIGIN"/*, + "USER_NEW", + "DATE_NEW"*/ + ]; + var updateArray = []; + var colsUpdate = [ + "STATUS"/*, + "USER_EDIT", + "DATE_EDIT"*/ + ]; + + //Anlegen der Firmen-Betreuer-Datensätze in der Tabelle DISTRICTCONTACT + for (var i=0; i<arrOrgContactIds.length; i++) + { + for (var j=0; j<arrResponsibleIds.length; j++) + { + //Existiert der Firmen-Betreuer-Datensatz bereits? + var found = 'N' + for (var k=0; k<arrExistingIds.length; k++) + { + if (arrExistingIds[k][1] == arrOrgContactIds[i] && arrExistingIds[k][2] == arrResponsibleIds[j][0]) + { + unchanged++; + found = 'Y'; + //Gefundenen Eintrag aus dem Array entfernen + //-> Am Schluss bleiben in dem Array alle ungültigen Datensätze übrig. Bei diesen wird weiter unten der Status geändert + arrExistingIds.splice(k, 1); + break; + } + } + //Firmen-Betreuer-Datensatz existiert noch nicht -> Insert + if (found == 'N') + { + var valsInsert = [ + util.getNewUUID(), + arrOrgContactIds[i], + pDistrictId, + arrResponsibleIds[j][0], + arrResponsibleIds[j][1], + arrResponsibleIds[j][2], + arrResponsibleIds[j][3], + arrResponsibleIds[j][4], + $KeywordRegistry.districtOrigin$auto()/*, + vars.get("$sys.user"), + vars.get("$sys.date")*/ + ]; + insertArray.push(["DISTRICTCONTACT", colsInsert, null, valsInsert]); + } + } + } + newAssigned = insertArray.length; + db.inserts(insertArray); + + //Gibt es noch ungültige Zuordnungen, dann bei diesen den Status auf "zur Prüfung setzen" + if (arrExistingIds.length > 0) + { + invalid = arrExistingIds.length; + for (var l=0; l<arrExistingIds.length; l++) + { + var valsUpdate = [ + $KeywordRegistry.contactStatus$inReview()/*, + vars.get("$sys.user"), + vars.get("$sys.date")*/ + ]; + var condition = newWhere("DISTRICTCONTACT.DISTRICTCONTACTID", arrExistingIds[l][0]); + updateArray.push(["DISTRICTCONTACT", colsUpdate, null, valsUpdate, condition.build()]); + } + db.updates(updateArray) + } + + + return { + newAssigned : newAssigned, + invalid : invalid, + unchanged : unchanged + }; +} diff --git a/process/KeywordRegistry_basic/process.js b/process/KeywordRegistry_basic/process.js index ba80197cd05d9f6c4c66c1c0a95cf557e578fe54..862d3cd9436eb371388fd8befec6406e22b8d280 100644 --- a/process/KeywordRegistry_basic/process.js +++ b/process/KeywordRegistry_basic/process.js @@ -41,6 +41,7 @@ $KeywordRegistry.activityDirection$internal = function(){return "x";}; $KeywordRegistry.contactStatus = function(){return "ContactStatus";}; $KeywordRegistry.contactStatus$active = function(){return "CONTACTSTATACTIVE";}; $KeywordRegistry.contactStatus$inactive = function(){return "CONTACTSTATINACTIVE";}; +$KeywordRegistry.contactStatus$inReview = function(){return "CONTACTSTATREVIEW";}; $KeywordRegistry.currency = function(){return "Currency";}; $KeywordRegistry.currency$eur = function(){return "EUR";}; diff --git a/process/assignDistrict_serverProcess/assignDistrict_serverProcess.aod b/process/assignDistrict_serverProcess/assignDistrict_serverProcess.aod new file mode 100644 index 0000000000000000000000000000000000000000..27ebc6a30b9f8341d70305bbda3555fd2a9e4bc5 --- /dev/null +++ b/process/assignDistrict_serverProcess/assignDistrict_serverProcess.aod @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1"> + <name>assignDistrict_serverProcess</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <process>%aditoprj%/process/assignDistrict_serverProcess/process.js</process> + <alias>Data_alias</alias> + <variants> + <element>EXECUTABLE</element> + </variants> +</process> diff --git a/process/assignDistrict_serverProcess/process.js b/process/assignDistrict_serverProcess/process.js new file mode 100644 index 0000000000000000000000000000000000000000..56666d0afbbbf651f87e3a0ec267fbe4950ecad5 --- /dev/null +++ b/process/assignDistrict_serverProcess/process.js @@ -0,0 +1,27 @@ +import("system.logging"); +import("system.datetime"); +import("Sql_lib"); +import("system.db"); +import("system.util"); +import("system.translate"); +import("system.vars"); +import("system.notification"); +import("District_lib"); + +var startTime = datetime.date(); +var appliedFilter = vars.get("$local.appliedFilter") +var user = vars.get("$local.user"); +var districtId = vars.get("$local.districtId"); +var districtName = DistrictUtils.getDistrictName(districtId); + +//Automatische Zuordnung +var res = DistrictUtils.assignDistrict(districtId, appliedFilter); + +// Benachrichtigung am Ende der Zuordnung +var message = translate.withArguments("Assignment of district \"%0\" is completed!", [districtName]); +var description = translate.withArguments("%0 companies were newley assigned to this district. \n " + + "%1 companies are no longer assigned to this district (these assignments got the status 'review'). \n " + + "%2 valid assignments were unchanged. \n " + + "The Process took %3 seconds. ", + [res.newAssigned, res.invalid, res.unchanged, Math.round((datetime.date() - startTime) / datetime.ONE_SECOND)]) +notification.addNotification(util.getNewUUID(), null, null, null, "DistrictAssigned", notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);