From 0d8d9e161501fb0a4eda9a4b9706ba8e0a9e3459 Mon Sep 17 00:00:00 2001 From: "j.goderbauer" <j.goderbauer@adito.de> Date: Fri, 5 Oct 2018 13:52:38 +0200 Subject: [PATCH] [Projekt: Entwicklung - Neon][TicketNr.: 1023713][COMM - Standard setzten (Aktion, Button, Darstellung)] --- .../is_standard/possibleItemsProcess.js | 12 +- entity/Comm_entity/Comm_entity.aod | 32 +- entity/Comm_entity/conditionProcess.js | 35 +- .../entityfields/commid/valueProcess.js | 2 + .../entityfields/is_standard/valueProcess.js | 8 +- .../medium_id/possibleItemsProcess.js | 28 +- .../medium_id/valueMappingProcess.js | 8 + entity/Pers_entity/Pers_entity.aod | 60 + .../mediumcategoriesfilter_param/code.js | 4 + .../children/relid_param/code.js | 4 + .../mediumcategoriesfilter_param/code.js | 4 + .../children/relid_param/code.js | 4 + .../mediumcategoriesfilter_param/code.js | 4 + .../children/relid_param/code.js | 4 + .../_____LANGUAGE_EXTRA.aod | 616 ++--- .../_____LANGUAGE_de/_____LANGUAGE_de.aod | 764 +++--- .../_____LANGUAGE_en/_____LANGUAGE_en.aod | 608 ++--- .../PersPreview_view/PersPreview_view.aod | 134 +- process/Keyword_lib/process.js | 479 ++-- process/Sql_lib/process.js | 2070 +++++++++-------- 20 files changed, 2572 insertions(+), 2308 deletions(-) create mode 100644 entity/Comm_entity/entityfields/commid/valueProcess.js create mode 100644 entity/Comm_entity/entityfields/medium_id/valueMappingProcess.js create mode 100644 entity/Pers_entity/entityfields/perscommemail_dfo/children/mediumcategoriesfilter_param/code.js create mode 100644 entity/Pers_entity/entityfields/perscommemail_dfo/children/relid_param/code.js create mode 100644 entity/Pers_entity/entityfields/perscommothers_dfo/children/mediumcategoriesfilter_param/code.js create mode 100644 entity/Pers_entity/entityfields/perscommothers_dfo/children/relid_param/code.js create mode 100644 entity/Pers_entity/entityfields/perscommphone_dfo/children/mediumcategoriesfilter_param/code.js create mode 100644 entity/Pers_entity/entityfields/perscommphone_dfo/children/relid_param/code.js diff --git a/entity/Address_entity/entityfields/is_standard/possibleItemsProcess.js b/entity/Address_entity/entityfields/is_standard/possibleItemsProcess.js index b429686afd5..11676c10f99 100644 --- a/entity/Address_entity/entityfields/is_standard/possibleItemsProcess.js +++ b/entity/Address_entity/entityfields/is_standard/possibleItemsProcess.js @@ -1,7 +1,7 @@ -import("system.translate"); -import("system.result"); - -result.object([ - ["true", translate.text("Standardadresse")] - ,["false", ""] +import("system.translate"); +import("system.result"); + +result.object([ + ["true", translate.text("standard address")] + ,["false", ""] ]); \ No newline at end of file diff --git a/entity/Comm_entity/Comm_entity.aod b/entity/Comm_entity/Comm_entity.aod index 6cee6425031..3841980aa55 100644 --- a/entity/Comm_entity/Comm_entity.aod +++ b/entity/Comm_entity/Comm_entity.aod @@ -15,11 +15,13 @@ <columnName>ADDR</columnName> <caption>${COMM_ADDRESS}</caption> <contentTypeProcess>%aditoprj%/entity/Comm_entity/entityfields/addr/contentTypeProcess.js</contentTypeProcess> + <valueProcess>%aditoprj%/entity/Comm_entity/entityfields/addr/valueProcess.js</valueProcess> </entityField> <entityField> <name>COMMID</name> <tableName>COMM</tableName> <columnName>COMMID</columnName> + <valueProcess>%aditoprj%/entity/Comm_entity/entityfields/commid/valueProcess.js</valueProcess> </entityField> <entityField> <name>DATE_EDIT</name> @@ -39,6 +41,7 @@ <columnName>MEDIUM_ID</columnName> <caption>Medium</caption> <possibleItemsProcess>%aditoprj%/entity/Comm_entity/entityfields/medium_id/possibleItemsProcess.js</possibleItemsProcess> + <valueMappingProcess>%aditoprj%/entity/Comm_entity/entityfields/medium_id/valueMappingProcess.js</valueMappingProcess> </entityField> <entityField> <name>RELATION_ID</name> @@ -66,7 +69,8 @@ <entityParameter> <name>RelId_param</name> <expose v="true" /> - <description>PARAMETER</description> + <description>This parameter is used for specifing a related &quot;RELATIONID&quot; to a COMM-entry. +Usually this is used for filtering COMM-entires by a specified contact or creating a new entry that is related to a contact.</description> </entityParameter> <entityIncomingField> <name>PersComm_dfi</name> @@ -78,6 +82,24 @@ <fieldName>PersComm_dfo</fieldName> <isOutgoing v="false" /> </entityDependency> + <entityDependency> + <name>6bee4be4-34bd-47fc-a909-8e8bbf2f45f2</name> + <entityName>Pers_entity</entityName> + <fieldName>PersCommPhone_dfo</fieldName> + <isOutgoing v="false" /> + </entityDependency> + <entityDependency> + <name>89ff88fa-029f-4b0d-a358-b7b310a6e72c</name> + <entityName>Pers_entity</entityName> + <fieldName>PersCommOthers_dfo</fieldName> + <isOutgoing v="false" /> + </entityDependency> + <entityDependency> + <name>90c0436e-3a46-40ec-ae73-b4aaded95bbc</name> + <entityName>Pers_entity</entityName> + <fieldName>PersCommEmail_dfo</fieldName> + <isOutgoing v="false" /> + </entityDependency> </dependencies> </entityIncomingField> <entityIncomingField> @@ -97,6 +119,14 @@ <contentType>BOOLEAN</contentType> <valueProcess>%aditoprj%/entity/Comm_entity/entityfields/is_standard/valueProcess.js</valueProcess> </entityField> + <entityParameter> + <name>MediumCategoriesFilter_param</name> + <expose v="true" /> + <mandatory v="false" /> + <description>This param is used for filtering the categories of MEDIUM_IDs. For example share mobile-phone and in-house-telephone the same category (it&apos;s a telephone-number). +So, for only showing telephone-types you&apos;ve to specify this parameter with it&apos;s phone-number-category. +</description> + </entityParameter> </entityFields> <linkInformation> <linkInformation> diff --git a/entity/Comm_entity/conditionProcess.js b/entity/Comm_entity/conditionProcess.js index 0d4b526962a..6693257607e 100644 --- a/entity/Comm_entity/conditionProcess.js +++ b/entity/Comm_entity/conditionProcess.js @@ -1,8 +1,27 @@ -import("system.logging"); -import("system.result"); -import("system.vars"); - -if(vars.exists("$param.RelId_param") && vars.get("$param.RelId_param") != null) - result.string("COMM.RELATION_ID = ('" + vars.getString("$param.RelId_param") + "')"); -else - result.string("1 = 2"); \ No newline at end of file +import("system.text"); +import("system.result"); +import("system.vars"); +import("Sql_lib"); +import("Keyword_lib"); + +var cond, relId, mediumCategories, keywordUtil; + +cond = ""; +if(vars.exists("$param.RelId_param") && (relId = vars.get("$param.RelId_param")) != null){ + cond += " and COMM.RELATION_ID in ('" + relId + "')";//TODO: quoting/prevent sql-injection +} +if (vars.exists("$param.MediumCategoriesFilter_param") && (mediumCategories = vars.get("$param.MediumCategoriesFilter_param")) != null){ + mediumCategories = text.decodeMS(mediumCategories); + keywordUtil = new KeywordUtils(); + var kwd = keywordUtil.createKeyword("COMM.MEDIUM"); + kwd.filter(function(id, name, customs){ + return mediumCategories.indexOf(customs.category) > -1; + }); + mediumIds = kwd.toArray("id"); + if (mediumIds.length == 0) + throw new Error();//TODO: add message + + cond += " and COMM.MEDIUM_ID in (" + mediumIds.join(", ") + ")"; +} + +result.string(cond ? "1 = 1 " + cond: "1 = 2"); \ No newline at end of file diff --git a/entity/Comm_entity/entityfields/commid/valueProcess.js b/entity/Comm_entity/entityfields/commid/valueProcess.js new file mode 100644 index 00000000000..7a874732d3c --- /dev/null +++ b/entity/Comm_entity/entityfields/commid/valueProcess.js @@ -0,0 +1,2 @@ +import("system.vars"); +vars.get("$param.RelId_param") \ No newline at end of file diff --git a/entity/Comm_entity/entityfields/is_standard/valueProcess.js b/entity/Comm_entity/entityfields/is_standard/valueProcess.js index 64cb76b496b..c973c9d87af 100644 --- a/entity/Comm_entity/entityfields/is_standard/valueProcess.js +++ b/entity/Comm_entity/entityfields/is_standard/valueProcess.js @@ -1,4 +1,6 @@ -import("system.vars"); -import("system.result"); - +import("system.logging"); +import("system.vars"); +import("system.result"); + +logging.log("STANDARD.valueProcess|changedVal:" + vars.get("$this.value") + ">for>" + vars.get("$field.COMMID") + ">" + vars.get("$field.ADDR")); result.string(vars.get("$field.STANDARD") == "1"); \ No newline at end of file diff --git a/entity/Comm_entity/entityfields/medium_id/possibleItemsProcess.js b/entity/Comm_entity/entityfields/medium_id/possibleItemsProcess.js index aa20876613e..f73dccbca86 100644 --- a/entity/Comm_entity/entityfields/medium_id/possibleItemsProcess.js +++ b/entity/Comm_entity/entityfields/medium_id/possibleItemsProcess.js @@ -1,8 +1,20 @@ -import("system.result"); -import("Keyword_lib"); - -var kwdUtils, items; - -kwdUtils = new KeywordUtils(); -items = kwdUtils.getStandardArray("COMM.MEDIUM"); -result.object(items); \ No newline at end of file +import("system.text"); +import("system.vars"); +import("system.result"); +import("Keyword_lib"); + +var mediumCategories, kwdUtils, kwd, items; + +kwdUtils = new KeywordUtils(); +if (vars.exists("$param.MediumCategoriesFilter_param") && (mediumCategories = vars.get("$param.MediumCategoriesFilter_param")) != null){ + mediumCategories = text.decodeMS(mediumCategories); + kwd = kwdUtils.createKeyword("COMM.MEDIUM"); + kwd.filter(function(id, name, customs){ + return mediumCategories.indexOf(customs.category) > -1; + }); + items = kwd.toArray(); +} +else { + items = kwdUtils.getStandardArray("COMM.MEDIUM"); +} +result.object(items); diff --git a/entity/Comm_entity/entityfields/medium_id/valueMappingProcess.js b/entity/Comm_entity/entityfields/medium_id/valueMappingProcess.js new file mode 100644 index 00000000000..aa610615b48 --- /dev/null +++ b/entity/Comm_entity/entityfields/medium_id/valueMappingProcess.js @@ -0,0 +1,8 @@ +import("system.result"); +import("Keyword_lib"); + +var kwdUtils, items; + +kwdUtils = new KeywordUtils(); +items = kwdUtils.getStandardArray("COMM.MEDIUM"); +result.object(items); \ No newline at end of file diff --git a/entity/Pers_entity/Pers_entity.aod b/entity/Pers_entity/Pers_entity.aod index 81aaf1e8d13..448e4826911 100644 --- a/entity/Pers_entity/Pers_entity.aod +++ b/entity/Pers_entity/Pers_entity.aod @@ -283,6 +283,66 @@ <fieldName>Org_dfi</fieldName> </dependency> </entityOutgoingField> + <entityOutgoingField> + <name>PersCommPhone_dfo</name> + <fieldType>DEPENDENCY_OUT</fieldType> + <caption>Communication Phone</caption> + <dependency> + <name>dependency</name> + <entityName>Comm_entity</entityName> + <fieldName>PersComm_dfi</fieldName> + </dependency> + <children> + <entityParameter> + <name>RelId_param</name> + <code>%aditoprj%/entity/Pers_entity/entityfields/perscommphone_dfo/children/relid_param/code.js</code> + </entityParameter> + <entityParameter> + <name>MediumCategoriesFilter_param</name> + <code>%aditoprj%/entity/Pers_entity/entityfields/perscommphone_dfo/children/mediumcategoriesfilter_param/code.js</code> + </entityParameter> + </children> + </entityOutgoingField> + <entityOutgoingField> + <name>PersCommEmail_dfo</name> + <fieldType>DEPENDENCY_OUT</fieldType> + <caption>Communication E-Mail</caption> + <dependency> + <name>dependency</name> + <entityName>Comm_entity</entityName> + <fieldName>PersComm_dfi</fieldName> + </dependency> + <children> + <entityParameter> + <name>RelId_param</name> + <code>%aditoprj%/entity/Pers_entity/entityfields/perscommemail_dfo/children/relid_param/code.js</code> + </entityParameter> + <entityParameter> + <name>MediumCategoriesFilter_param</name> + <code>%aditoprj%/entity/Pers_entity/entityfields/perscommemail_dfo/children/mediumcategoriesfilter_param/code.js</code> + </entityParameter> + </children> + </entityOutgoingField> + <entityOutgoingField> + <name>PersCommOthers_dfo</name> + <fieldType>DEPENDENCY_OUT</fieldType> + <caption>Communication Other</caption> + <dependency> + <name>dependency</name> + <entityName>Comm_entity</entityName> + <fieldName>PersComm_dfi</fieldName> + </dependency> + <children> + <entityParameter> + <name>RelId_param</name> + <code>%aditoprj%/entity/Pers_entity/entityfields/perscommothers_dfo/children/relid_param/code.js</code> + </entityParameter> + <entityParameter> + <name>MediumCategoriesFilter_param</name> + <code>%aditoprj%/entity/Pers_entity/entityfields/perscommothers_dfo/children/mediumcategoriesfilter_param/code.js</code> + </entityParameter> + </children> + </entityOutgoingField> </entityFields> <linkInformation> <linkInformation> diff --git a/entity/Pers_entity/entityfields/perscommemail_dfo/children/mediumcategoriesfilter_param/code.js b/entity/Pers_entity/entityfields/perscommemail_dfo/children/mediumcategoriesfilter_param/code.js new file mode 100644 index 00000000000..aaff61e4c88 --- /dev/null +++ b/entity/Pers_entity/entityfields/perscommemail_dfo/children/mediumcategoriesfilter_param/code.js @@ -0,0 +1,4 @@ +import("system.text"); +import("system.result"); + +result.string(text.encodeMS(["EMAIL"])); diff --git a/entity/Pers_entity/entityfields/perscommemail_dfo/children/relid_param/code.js b/entity/Pers_entity/entityfields/perscommemail_dfo/children/relid_param/code.js new file mode 100644 index 00000000000..c618e8d6e5c --- /dev/null +++ b/entity/Pers_entity/entityfields/perscommemail_dfo/children/relid_param/code.js @@ -0,0 +1,4 @@ +import("system.result"); +import("system.vars"); + +result.string(vars.get("$field.RELATIONID")); \ No newline at end of file diff --git a/entity/Pers_entity/entityfields/perscommothers_dfo/children/mediumcategoriesfilter_param/code.js b/entity/Pers_entity/entityfields/perscommothers_dfo/children/mediumcategoriesfilter_param/code.js new file mode 100644 index 00000000000..4f54b7ffc8a --- /dev/null +++ b/entity/Pers_entity/entityfields/perscommothers_dfo/children/mediumcategoriesfilter_param/code.js @@ -0,0 +1,4 @@ +import("system.text"); +import("system.result"); + +result.string(text.encodeMS(["OTHER"])); diff --git a/entity/Pers_entity/entityfields/perscommothers_dfo/children/relid_param/code.js b/entity/Pers_entity/entityfields/perscommothers_dfo/children/relid_param/code.js new file mode 100644 index 00000000000..c618e8d6e5c --- /dev/null +++ b/entity/Pers_entity/entityfields/perscommothers_dfo/children/relid_param/code.js @@ -0,0 +1,4 @@ +import("system.result"); +import("system.vars"); + +result.string(vars.get("$field.RELATIONID")); \ No newline at end of file diff --git a/entity/Pers_entity/entityfields/perscommphone_dfo/children/mediumcategoriesfilter_param/code.js b/entity/Pers_entity/entityfields/perscommphone_dfo/children/mediumcategoriesfilter_param/code.js new file mode 100644 index 00000000000..10d8f95a842 --- /dev/null +++ b/entity/Pers_entity/entityfields/perscommphone_dfo/children/mediumcategoriesfilter_param/code.js @@ -0,0 +1,4 @@ +import("system.text"); +import("system.result"); + +result.string(text.encodeMS(["PHONE"])); diff --git a/entity/Pers_entity/entityfields/perscommphone_dfo/children/relid_param/code.js b/entity/Pers_entity/entityfields/perscommphone_dfo/children/relid_param/code.js new file mode 100644 index 00000000000..c618e8d6e5c --- /dev/null +++ b/entity/Pers_entity/entityfields/perscommphone_dfo/children/relid_param/code.js @@ -0,0 +1,4 @@ +import("system.result"); +import("system.vars"); + +result.string(vars.get("$field.RELATIONID")); \ No newline at end of file diff --git a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod index 92d2227e33e..c7ad60356ce 100644 --- a/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod +++ b/language/_____LANGUAGE_EXTRA/_____LANGUAGE_EXTRA.aod @@ -1,305 +1,311 @@ -<?xml version="1.0" encoding="UTF-8"?> -<language xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.3" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/language/1.1.3"> - <name>_____LANGUAGE_EXTRA</name> - <majorModelMode>DISTRIBUTED</majorModelMode> - <keyValueMap> - <entry> - <key>Company</key> - </entry> - <entry> - <key>German (Austria)</key> - </entry> - <entry> - <key>E-Mail</key> - </entry> - <entry> - <key>Customer</key> - </entry> - <entry> - <key>Internal</key> - </entry> - <entry> - <key>Male</key> - </entry> - <entry> - <key>Outgoing</key> - </entry> - <entry> - <key>History</key> - </entry> - <entry> - <key>Name</key> - </entry> - <entry> - <key>Austria</key> - </entry> - <entry> - <key>Der Alias \&quot;%0\&quot; konnte nicht geladen werden. Eventuell wurde er nicht konfiguriert</key> - </entry> - <entry> - <key>Customercode</key> - </entry> - <entry> - <key>Norwegian</key> - </entry> - <entry> - <key>Status</key> - </entry> - <entry> - <key>German (Germany)</key> - </entry> - <entry> - <key>Incoming</key> - </entry> - <entry> - <key>Active</key> - </entry> - <entry> - <key>${GENDER_OTHER}</key> - </entry> - <entry> - <key>Medium</key> - </entry> - <entry> - <key>Internet</key> - </entry> - <entry> - <key>Germany</key> - </entry> - <entry> - <key>Online-Meeting</key> - </entry> - <entry> - <key>Social Media</key> - </entry> - <entry> - <key>Visit</key> - </entry> - <entry> - <key>In review</key> - </entry> - <entry> - <key>German</key> - </entry> - <entry> - <key>Information</key> - </entry> - <entry> - <key>Language</key> - </entry> - <entry> - <key>Phone</key> - </entry> - <entry> - <key>[%0]the given keyword \&quot;%1\&quot; has no match with the possible keywordlist</key> - </entry> - <entry> - <key>Histories</key> - </entry> - <entry> - <key>Female</key> - </entry> - <entry> - <key>Supplier</key> - </entry> - <entry> - <key>English (United Kingdom)</key> - </entry> - <entry> - <key>Social</key> - </entry> - <entry> - <key>Contactmanagement</key> - </entry> - <entry> - <key>United Kingdom</key> - </entry> - <entry> - <key>Mobile</key> - </entry> - <entry> - <key>Office address</key> - </entry> - <entry> - <key>Contact</key> - </entry> - <entry> - <key>English</key> - </entry> - <entry> - <key>Home address</key> - </entry> - <entry> - <key>Type</key> - </entry> - <entry> - <key>Contacts</key> - </entry> - <entry> - <key>Norway</key> - </entry> - <entry> - <key>Prospect</key> - </entry> - <entry> - <key>the param \&quot;%0\&quot; in \&quot;%1\&quot; is mandatory and has to be set</key> - </entry> - <entry> - <key>Other</key> - </entry> - <entry> - <key>yyyy-MM-dd</key> - </entry> - <entry> - <key>Address</key> - </entry> - <entry> - <key>Addresses</key> - </entry> - <entry> - <key>${COMM_ADDRESS}</key> - </entry> - <entry> - <key>Gender</key> - </entry> - <entry> - <key>Date of birth</key> - </entry> - <entry> - <key>Lastname</key> - </entry> - <entry> - <key>Salutation</key> - </entry> - <entry> - <key>Middlename</key> - </entry> - <entry> - <key>Title</key> - </entry> - <entry> - <key>Addresstype</key> - </entry> - <entry> - <key>Firstname</key> - </entry> - <entry> - <key>Description</key> - </entry> - <entry> - <key>Direction</key> - </entry> - <entry> - <key>Entrydate</key> - </entry> - <entry> - <key>Subject</key> - </entry> - <entry> - <key>changed on %0 by %1</key> - </entry> - <entry> - <key>Post office box</key> - </entry> - <entry> - <key>created on %0 by %1</key> - </entry> - <entry> - <key>Delivery address</key> - </entry> - <entry> - <key>House number</key> - </entry> - <entry> - <key>Country</key> - </entry> - <entry> - <key>Communication</key> - </entry> - <entry> - <key>postcode</key> - </entry> - <entry> - <key>City</key> - </entry> - <entry> - <key>State</key> - </entry> - <entry> - <key>Region</key> - </entry> - <entry> - <key>District</key> - </entry> - <entry> - <key>Switzerland</key> - </entry> - <entry> - <key>Inactive</key> - </entry> - <entry> - <key>Nein</key> - </entry> - <entry> - <key>Bestätigt</key> - </entry> - <entry> - <key>Benutzer</key> - </entry> - <entry> - <key>frei</key> - </entry> - <entry> - <key>Vorläufig</key> - </entry> - <entry> - <key>Ja</key> - </entry> - <entry> - <key>Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>Betreff</key> - </entry> - <entry> - <key>Internal (2)</key> - </entry> - <entry> - <key>Company Addresses</key> - </entry> - <entry> - <key>Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>Termin</key> - </entry> - <entry> - <key>Außer Haus</key> - </entry> - <entry> - <key>Abgesagt</key> - </entry> - <entry> - <key>Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>yyyyMMdd</key> - </entry> - <entry> - <key>Gebucht</key> - </entry> - <entry> - <key>Ein Gruppentermin kann nur durch den Organisator bearbeitet werden.</key> - </entry> - </keyValueMap> - <font name="Dialog" style="0" size="11" /> - <sqlModels> - <languageSql> - <name>Data_alias</name> - <alias>Data_alias</alias> - <statements> - <element></element> - </statements> - </languageSql> - </sqlModels> -</language> +<?xml version="1.0" encoding="UTF-8"?> +<language xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.3" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/language/1.1.3"> + <name>_____LANGUAGE_EXTRA</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <keyValueMap> + <entry> + <key>Company</key> + </entry> + <entry> + <key>German (Austria)</key> + </entry> + <entry> + <key>E-Mail</key> + </entry> + <entry> + <key>Customer</key> + </entry> + <entry> + <key>Internal</key> + </entry> + <entry> + <key>Male</key> + </entry> + <entry> + <key>Outgoing</key> + </entry> + <entry> + <key>History</key> + </entry> + <entry> + <key>Name</key> + </entry> + <entry> + <key>Austria</key> + </entry> + <entry> + <key>Der Alias \&quot;%0\&quot; konnte nicht geladen werden. Eventuell wurde er nicht konfiguriert</key> + </entry> + <entry> + <key>Customercode</key> + </entry> + <entry> + <key>Norwegian</key> + </entry> + <entry> + <key>Status</key> + </entry> + <entry> + <key>German (Germany)</key> + </entry> + <entry> + <key>Incoming</key> + </entry> + <entry> + <key>Active</key> + </entry> + <entry> + <key>${GENDER_OTHER}</key> + </entry> + <entry> + <key>Medium</key> + </entry> + <entry> + <key>Internet</key> + </entry> + <entry> + <key>Germany</key> + </entry> + <entry> + <key>Online-Meeting</key> + </entry> + <entry> + <key>Social Media</key> + </entry> + <entry> + <key>Visit</key> + </entry> + <entry> + <key>In review</key> + </entry> + <entry> + <key>German</key> + </entry> + <entry> + <key>Information</key> + </entry> + <entry> + <key>Language</key> + </entry> + <entry> + <key>Phone</key> + </entry> + <entry> + <key>[%0]the given keyword \&quot;%1\&quot; has no match with the possible keywordlist</key> + </entry> + <entry> + <key>Histories</key> + </entry> + <entry> + <key>Female</key> + </entry> + <entry> + <key>Supplier</key> + </entry> + <entry> + <key>English (United Kingdom)</key> + </entry> + <entry> + <key>Social</key> + </entry> + <entry> + <key>Contactmanagement</key> + </entry> + <entry> + <key>United Kingdom</key> + </entry> + <entry> + <key>Mobile</key> + </entry> + <entry> + <key>Office address</key> + </entry> + <entry> + <key>Contact</key> + </entry> + <entry> + <key>English</key> + </entry> + <entry> + <key>Home address</key> + </entry> + <entry> + <key>Type</key> + </entry> + <entry> + <key>Contacts</key> + </entry> + <entry> + <key>Norway</key> + </entry> + <entry> + <key>Prospect</key> + </entry> + <entry> + <key>the param \&quot;%0\&quot; in \&quot;%1\&quot; is mandatory and has to be set</key> + </entry> + <entry> + <key>Other</key> + </entry> + <entry> + <key>yyyy-MM-dd</key> + </entry> + <entry> + <key>Address</key> + </entry> + <entry> + <key>Addresses</key> + </entry> + <entry> + <key>${COMM_ADDRESS}</key> + </entry> + <entry> + <key>Gender</key> + </entry> + <entry> + <key>Date of birth</key> + </entry> + <entry> + <key>Lastname</key> + </entry> + <entry> + <key>Salutation</key> + </entry> + <entry> + <key>Middlename</key> + </entry> + <entry> + <key>Title</key> + </entry> + <entry> + <key>Addresstype</key> + </entry> + <entry> + <key>Firstname</key> + </entry> + <entry> + <key>Description</key> + </entry> + <entry> + <key>Direction</key> + </entry> + <entry> + <key>Entrydate</key> + </entry> + <entry> + <key>Subject</key> + </entry> + <entry> + <key>changed on %0 by %1</key> + </entry> + <entry> + <key>Post office box</key> + </entry> + <entry> + <key>created on %0 by %1</key> + </entry> + <entry> + <key>Delivery address</key> + </entry> + <entry> + <key>House number</key> + </entry> + <entry> + <key>Country</key> + </entry> + <entry> + <key>Communication</key> + </entry> + <entry> + <key>postcode</key> + </entry> + <entry> + <key>City</key> + </entry> + <entry> + <key>State</key> + </entry> + <entry> + <key>Region</key> + </entry> + <entry> + <key>District</key> + </entry> + <entry> + <key>Switzerland</key> + </entry> + <entry> + <key>Inactive</key> + </entry> + <entry> + <key>Bestätigt</key> + </entry> + <entry> + <key>Benutzer</key> + </entry> + <entry> + <key>frei</key> + </entry> + <entry> + <key>Vorläufig</key> + </entry> + <entry> + <key>Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>Betreff</key> + </entry> + <entry> + <key>Internal (2)</key> + </entry> + <entry> + <key>Company Addresses</key> + </entry> + <entry> + <key>Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>Termin</key> + </entry> + <entry> + <key>Außer Haus</key> + </entry> + <entry> + <key>Abgesagt</key> + </entry> + <entry> + <key>Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>yyyyMMdd</key> + </entry> + <entry> + <key>Gebucht</key> + </entry> + <entry> + <key>Ein Gruppentermin kann nur durch den Organisator bearbeitet werden.</key> + </entry> + <entry> + <key>Communication Other</key> + </entry> + <entry> + <key>Communication Phone</key> + </entry> + <entry> + <key>Communication E-Mail</key> + </entry> + <entry> + <key>standard address</key> + </entry> + </keyValueMap> + <font name="Dialog" style="0" size="11" /> + <sqlModels> + <languageSql> + <name>Data_alias</name> + <alias>Data_alias</alias> + <statements> + <element></element> + </statements> + </languageSql> + </sqlModels> +</language> diff --git a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod index 39203791eb0..b7dfaee3c09 100644 --- a/language/_____LANGUAGE_de/_____LANGUAGE_de.aod +++ b/language/_____LANGUAGE_de/_____LANGUAGE_de.aod @@ -1,377 +1,387 @@ -<?xml version="1.0" encoding="UTF-8"?> -<language xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.3" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/language/1.1.3"> - <name>_____LANGUAGE_de</name> - <majorModelMode>DISTRIBUTED</majorModelMode> - <language>de</language> - <country></country> - <variant></variant> - <keyValueMap> - <entry> - <key>Company</key> - <value>Firma</value> - </entry> - <entry> - <key>German (Austria)</key> - <value>Deutsch (Österreich)</value> - </entry> - <entry> - <key>E-Mail</key> - <value>E-Mail</value> - </entry> - <entry> - <key>Customer</key> - <value>Kunde</value> - </entry> - <entry> - <key>Internal</key> - <value>Intern</value> - </entry> - <entry> - <key>Male</key> - <value>Männlich</value> - </entry> - <entry> - <key>Outgoing</key> - <value>Ausgehend</value> - </entry> - <entry> - <key>History</key> - <value>Historie</value> - </entry> - <entry> - <key>Name</key> - <value>Name</value> - </entry> - <entry> - <key>Austria</key> - <value>Österreich</value> - </entry> - <entry> - <key>Der Alias \&quot;%0\&quot; konnte nicht geladen werden. Eventuell wurde er nicht konfiguriert</key> - </entry> - <entry> - <key>Customercode</key> - <value>Kundennummer</value> - </entry> - <entry> - <key>Norwegian</key> - <value>Norwegisch</value> - </entry> - <entry> - <key>Status</key> - <value>Status</value> - </entry> - <entry> - <key>German (Germany)</key> - <value>Deutsch (Deutschland)</value> - </entry> - <entry> - <key>Incoming</key> - <value>Eingehend</value> - </entry> - <entry> - <key>Active</key> - <value>Aktiv</value> - </entry> - <entry> - <key>${GENDER_OTHER}</key> - <value>Sonstige</value> - </entry> - <entry> - <key>Medium</key> - <value>Medium</value> - </entry> - <entry> - <key>Internet</key> - <value>Internet</value> - </entry> - <entry> - <key>Germany</key> - <value>Deutschland</value> - </entry> - <entry> - <key>Online-Meeting</key> - <value>Online-Meeting</value> - </entry> - <entry> - <key>Social Media</key> - <value>Social Media</value> - </entry> - <entry> - <key>Visit</key> - <value>Besuch</value> - </entry> - <entry> - <key>In review</key> - <value>zur Prüfung</value> - </entry> - <entry> - <key>German</key> - <value>Deutsch</value> - </entry> - <entry> - <key>Information</key> - <value>Information</value> - </entry> - <entry> - <key>Language</key> - <value>Sprache</value> - </entry> - <entry> - <key>Phone</key> - <value>Telefon</value> - </entry> - <entry> - <key>[%0]the given keyword \&quot;%1\&quot; has no match with the possible keywordlist</key> - </entry> - <entry> - <key>Histories</key> - <value>Historien</value> - </entry> - <entry> - <key>Female</key> - <value>Weiblich</value> - </entry> - <entry> - <key>Supplier</key> - <value>Lieferant</value> - </entry> - <entry> - <key>English (United Kingdom)</key> - <value>Englisch (Vereinigtes Königreich)</value> - </entry> - <entry> - <key>Social</key> - <value></value> - </entry> - <entry> - <key>Contactmanagement</key> - <value>Kontaktmanagement</value> - </entry> - <entry> - <key>United Kingdom</key> - <value>Vereinigtes Königreich</value> - </entry> - <entry> - <key>Mobile</key> - <value>Mobil</value> - </entry> - <entry> - <key>Office address</key> - <value>Firmenadresse</value> - </entry> - <entry> - <key>Contact</key> - <value>Kontakt</value> - </entry> - <entry> - <key>English</key> - <value>Englisch</value> - </entry> - <entry> - <key>Home address</key> - <value>Privatadresse</value> - </entry> - <entry> - <key>Type</key> - <value>Typ</value> - </entry> - <entry> - <key>Contacts</key> - <value>Kontakte</value> - </entry> - <entry> - <key>Norway</key> - <value>Norwegen</value> - </entry> - <entry> - <key>Prospect</key> - <value>Interessent</value> - </entry> - <entry> - <key>the param \&quot;%0\&quot; in \&quot;%1\&quot; is mandatory and has to be set</key> - <value></value> - </entry> - <entry> - <key>Other</key> - <value>Sonstige</value> - </entry> - <entry> - <key>yyyy-MM-dd</key> - <value>dd.MM.yyyy -</value> - </entry> - <entry> - <key>Address</key> - <value>Adresse</value> - </entry> - <entry> - <key>Addresses</key> - <value>Adressen</value> - </entry> - <entry> - <key>${COMM_ADDRESS}</key> - <value>Adresse</value> - </entry> - <entry> - <key>Gender</key> - <value>Geschlecht</value> - </entry> - <entry> - <key>Date of birth</key> - <value>Geburtsdatum</value> - </entry> - <entry> - <key>Lastname</key> - <value>Nachname</value> - </entry> - <entry> - <key>Salutation</key> - <value>Anrede</value> - </entry> - <entry> - <key>Middlename</key> - <value>Zwischenname</value> - </entry> - <entry> - <key>Title</key> - <value>Title</value> - </entry> - <entry> - <key>Addresstype</key> - <value>Adresstyp</value> - </entry> - <entry> - <key>Firstname</key> - <value>Vorname</value> - </entry> - <entry> - <key>Description</key> - <value>Beschreibung</value> - </entry> - <entry> - <key>Direction</key> - <value>Richtung</value> - </entry> - <entry> - <key>Entrydate</key> - <value>Eingangsdatum</value> - </entry> - <entry> - <key>Subject</key> - <value>Betreff</value> - </entry> - <entry> - <key>changed on %0 by %1</key> - <value>Geändert am %0 von %1</value> - </entry> - <entry> - <key>Post office box</key> - <value>Postfach</value> - </entry> - <entry> - <key>created on %0 by %1</key> - <value>Erstellt am %0 von %1</value> - </entry> - <entry> - <key>Delivery address</key> - <value>Lieferadresse</value> - </entry> - <entry> - <key>House number</key> - <value>Hausnummer</value> - </entry> - <entry> - <key>Country</key> - <value>Land</value> - </entry> - <entry> - <key>Communication</key> - <value>Kommunikation</value> - </entry> - <entry> - <key>postcode</key> - <value>Postleitzahl</value> - </entry> - <entry> - <key>City</key> - <value>Ort</value> - </entry> - <entry> - <key>State</key> - <value></value> - </entry> - <entry> - <key>Region</key> - <value>Region</value> - </entry> - <entry> - <key>District</key> - <value></value> - </entry> - <entry> - <key>Switzerland</key> - <value>Schweiz</value> - </entry> - <entry> - <key>Inactive</key> - <value>Inaktiv</value> - </entry> - <entry> - <key>Nein</key> - </entry> - <entry> - <key>Bestätigt</key> - </entry> - <entry> - <key>Benutzer</key> - </entry> - <entry> - <key>frei</key> - </entry> - <entry> - <key>Vorläufig</key> - </entry> - <entry> - <key>Ja</key> - </entry> - <entry> - <key>Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>Betreff</key> - </entry> - <entry> - <key>Internal (2)</key> - </entry> - <entry> - <key>Company Addresses</key> - <value>Firmenadressen</value> - </entry> - <entry> - <key>Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>Termin</key> - </entry> - <entry> - <key>Außer Haus</key> - </entry> - <entry> - <key>Abgesagt</key> - </entry> - <entry> - <key>Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>yyyyMMdd</key> - </entry> - <entry> - <key>Gebucht</key> - </entry> - <entry> - <key>Ein Gruppentermin kann nur durch den Organisator bearbeitet werden.</key> - </entry> - </keyValueMap> - <font name="Dialog" style="0" size="11" /> -</language> +<?xml version="1.0" encoding="UTF-8"?> +<language xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.3" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/language/1.1.3"> + <name>_____LANGUAGE_de</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <language>de</language> + <country></country> + <variant></variant> + <keyValueMap> + <entry> + <key>Company</key> + <value>Firma</value> + </entry> + <entry> + <key>German (Austria)</key> + <value>Deutsch (Österreich)</value> + </entry> + <entry> + <key>E-Mail</key> + <value>E-Mail</value> + </entry> + <entry> + <key>Customer</key> + <value>Kunde</value> + </entry> + <entry> + <key>Internal</key> + <value>Intern</value> + </entry> + <entry> + <key>Male</key> + <value>Männlich</value> + </entry> + <entry> + <key>Outgoing</key> + <value>Ausgehend</value> + </entry> + <entry> + <key>History</key> + <value>Historie</value> + </entry> + <entry> + <key>Name</key> + <value>Name</value> + </entry> + <entry> + <key>Austria</key> + <value>Österreich</value> + </entry> + <entry> + <key>Der Alias \&quot;%0\&quot; konnte nicht geladen werden. Eventuell wurde er nicht konfiguriert</key> + </entry> + <entry> + <key>Customercode</key> + <value>Kundennummer</value> + </entry> + <entry> + <key>Norwegian</key> + <value>Norwegisch</value> + </entry> + <entry> + <key>Status</key> + <value>Status</value> + </entry> + <entry> + <key>German (Germany)</key> + <value>Deutsch (Deutschland)</value> + </entry> + <entry> + <key>Incoming</key> + <value>Eingehend</value> + </entry> + <entry> + <key>Active</key> + <value>Aktiv</value> + </entry> + <entry> + <key>${GENDER_OTHER}</key> + <value>Sonstige</value> + </entry> + <entry> + <key>Medium</key> + <value>Medium</value> + </entry> + <entry> + <key>Internet</key> + <value>Internet</value> + </entry> + <entry> + <key>Germany</key> + <value>Deutschland</value> + </entry> + <entry> + <key>Online-Meeting</key> + <value>Online-Meeting</value> + </entry> + <entry> + <key>Social Media</key> + <value>Social Media</value> + </entry> + <entry> + <key>Visit</key> + <value>Besuch</value> + </entry> + <entry> + <key>In review</key> + <value>zur Prüfung</value> + </entry> + <entry> + <key>German</key> + <value>Deutsch</value> + </entry> + <entry> + <key>Information</key> + <value>Information</value> + </entry> + <entry> + <key>Language</key> + <value>Sprache</value> + </entry> + <entry> + <key>Phone</key> + <value>Telefon</value> + </entry> + <entry> + <key>[%0]the given keyword \&quot;%1\&quot; has no match with the possible keywordlist</key> + </entry> + <entry> + <key>Histories</key> + <value>Historien</value> + </entry> + <entry> + <key>Female</key> + <value>Weiblich</value> + </entry> + <entry> + <key>Supplier</key> + <value>Lieferant</value> + </entry> + <entry> + <key>English (United Kingdom)</key> + <value>Englisch (Vereinigtes Königreich)</value> + </entry> + <entry> + <key>Social</key> + <value></value> + </entry> + <entry> + <key>Contactmanagement</key> + <value>Kontaktmanagement</value> + </entry> + <entry> + <key>United Kingdom</key> + <value>Vereinigtes Königreich</value> + </entry> + <entry> + <key>Mobile</key> + <value>Mobil</value> + </entry> + <entry> + <key>Office address</key> + <value>Firmenadresse</value> + </entry> + <entry> + <key>Contact</key> + <value>Kontakt</value> + </entry> + <entry> + <key>English</key> + <value>Englisch</value> + </entry> + <entry> + <key>Home address</key> + <value>Privatadresse</value> + </entry> + <entry> + <key>Type</key> + <value>Typ</value> + </entry> + <entry> + <key>Contacts</key> + <value>Kontakte</value> + </entry> + <entry> + <key>Norway</key> + <value>Norwegen</value> + </entry> + <entry> + <key>Prospect</key> + <value>Interessent</value> + </entry> + <entry> + <key>the param \&quot;%0\&quot; in \&quot;%1\&quot; is mandatory and has to be set</key> + <value></value> + </entry> + <entry> + <key>Other</key> + <value>Sonstige</value> + </entry> + <entry> + <key>yyyy-MM-dd</key> + <value>dd.MM.yyyy +</value> + </entry> + <entry> + <key>Address</key> + <value>Adresse</value> + </entry> + <entry> + <key>Addresses</key> + <value>Adressen</value> + </entry> + <entry> + <key>${COMM_ADDRESS}</key> + <value>Adresse</value> + </entry> + <entry> + <key>Gender</key> + <value>Geschlecht</value> + </entry> + <entry> + <key>Date of birth</key> + <value>Geburtsdatum</value> + </entry> + <entry> + <key>Lastname</key> + <value>Nachname</value> + </entry> + <entry> + <key>Salutation</key> + <value>Anrede</value> + </entry> + <entry> + <key>Middlename</key> + <value>Zwischenname</value> + </entry> + <entry> + <key>Title</key> + <value>Title</value> + </entry> + <entry> + <key>Addresstype</key> + <value>Adresstyp</value> + </entry> + <entry> + <key>Firstname</key> + <value>Vorname</value> + </entry> + <entry> + <key>Description</key> + <value>Beschreibung</value> + </entry> + <entry> + <key>Direction</key> + <value>Richtung</value> + </entry> + <entry> + <key>Entrydate</key> + <value>Eingangsdatum</value> + </entry> + <entry> + <key>Subject</key> + <value>Betreff</value> + </entry> + <entry> + <key>changed on %0 by %1</key> + <value>Geändert am %0 von %1</value> + </entry> + <entry> + <key>Post office box</key> + <value>Postfach</value> + </entry> + <entry> + <key>created on %0 by %1</key> + <value>Erstellt am %0 von %1</value> + </entry> + <entry> + <key>Delivery address</key> + <value>Lieferadresse</value> + </entry> + <entry> + <key>House number</key> + <value>Hausnummer</value> + </entry> + <entry> + <key>Country</key> + <value>Land</value> + </entry> + <entry> + <key>Communication</key> + <value>Kommunikation</value> + </entry> + <entry> + <key>postcode</key> + <value>Postleitzahl</value> + </entry> + <entry> + <key>City</key> + <value>Ort</value> + </entry> + <entry> + <key>State</key> + <value></value> + </entry> + <entry> + <key>Region</key> + <value>Region</value> + </entry> + <entry> + <key>District</key> + <value></value> + </entry> + <entry> + <key>Switzerland</key> + <value>Schweiz</value> + </entry> + <entry> + <key>Inactive</key> + <value>Inaktiv</value> + </entry> + <entry> + <key>Bestätigt</key> + </entry> + <entry> + <key>Benutzer</key> + </entry> + <entry> + <key>frei</key> + </entry> + <entry> + <key>Vorläufig</key> + </entry> + <entry> + <key>Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>Betreff</key> + </entry> + <entry> + <key>Internal (2)</key> + </entry> + <entry> + <key>Company Addresses</key> + <value>Firmenadressen</value> + </entry> + <entry> + <key>Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>Termin</key> + </entry> + <entry> + <key>Außer Haus</key> + </entry> + <entry> + <key>Abgesagt</key> + </entry> + <entry> + <key>Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>yyyyMMdd</key> + </entry> + <entry> + <key>Gebucht</key> + </entry> + <entry> + <key>Ein Gruppentermin kann nur durch den Organisator bearbeitet werden.</key> + </entry> + <entry> + <key>Communication Other</key> + <value>Kommunikation Sonstige</value> + </entry> + <entry> + <key>Communication Phone</key> + <value>Kommunikation Telefon</value> + </entry> + <entry> + <key>Communication E-Mail</key> + <value>Kommunikation E-Mail</value> + </entry> + <entry> + <key>standard address</key> + <value>Standardadresse</value> + </entry> + </keyValueMap> + <font name="Dialog" style="0" size="11" /> +</language> diff --git a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod index 6364678c597..399a5d44fbc 100644 --- a/language/_____LANGUAGE_en/_____LANGUAGE_en.aod +++ b/language/_____LANGUAGE_en/_____LANGUAGE_en.aod @@ -1,301 +1,307 @@ -<?xml version="1.0" encoding="UTF-8"?> -<language xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.3" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/language/1.1.3"> - <name>_____LANGUAGE_en</name> - <majorModelMode>DISTRIBUTED</majorModelMode> - <language>en</language> - <country></country> - <variant></variant> - <keyValueMap> - <entry> - <key>Company</key> - </entry> - <entry> - <key>German (Austria)</key> - </entry> - <entry> - <key>E-Mail</key> - </entry> - <entry> - <key>Customer</key> - </entry> - <entry> - <key>Internal</key> - </entry> - <entry> - <key>Male</key> - </entry> - <entry> - <key>Outgoing</key> - </entry> - <entry> - <key>History</key> - </entry> - <entry> - <key>Name</key> - </entry> - <entry> - <key>Austria</key> - </entry> - <entry> - <key>Der Alias \&quot;%0\&quot; konnte nicht geladen werden. Eventuell wurde er nicht konfiguriert</key> - </entry> - <entry> - <key>Customercode</key> - </entry> - <entry> - <key>Norwegian</key> - </entry> - <entry> - <key>Status</key> - </entry> - <entry> - <key>German (Germany)</key> - </entry> - <entry> - <key>Incoming</key> - </entry> - <entry> - <key>Active</key> - </entry> - <entry> - <key>${GENDER_OTHER}</key> - <value>Other</value> - </entry> - <entry> - <key>Medium</key> - </entry> - <entry> - <key>Internet</key> - </entry> - <entry> - <key>Germany</key> - </entry> - <entry> - <key>Online-Meeting</key> - </entry> - <entry> - <key>Social Media</key> - </entry> - <entry> - <key>Visit</key> - </entry> - <entry> - <key>In review</key> - </entry> - <entry> - <key>German</key> - </entry> - <entry> - <key>Information</key> - </entry> - <entry> - <key>Language</key> - </entry> - <entry> - <key>Phone</key> - </entry> - <entry> - <key>[%0]the given keyword \&quot;%1\&quot; has no match with the possible keywordlist</key> - </entry> - <entry> - <key>Histories</key> - </entry> - <entry> - <key>Female</key> - </entry> - <entry> - <key>Supplier</key> - </entry> - <entry> - <key>English (United Kingdom)</key> - </entry> - <entry> - <key>Social</key> - </entry> - <entry> - <key>Contactmanagement</key> - </entry> - <entry> - <key>United Kingdom</key> - </entry> - <entry> - <key>Mobile</key> - </entry> - <entry> - <key>Office address</key> - </entry> - <entry> - <key>Contact</key> - </entry> - <entry> - <key>English</key> - </entry> - <entry> - <key>Home address</key> - </entry> - <entry> - <key>Type</key> - </entry> - <entry> - <key>Contacts</key> - </entry> - <entry> - <key>Norway</key> - </entry> - <entry> - <key>Prospect</key> - </entry> - <entry> - <key>the param \&quot;%0\&quot; in \&quot;%1\&quot; is mandatory and has to be set</key> - </entry> - <entry> - <key>Other</key> - </entry> - <entry> - <key>yyyy-MM-dd</key> - </entry> - <entry> - <key>Address</key> - </entry> - <entry> - <key>Addresses</key> - </entry> - <entry> - <key>${COMM_ADDRESS}</key> - <value>Address</value> - </entry> - <entry> - <key>Gender</key> - </entry> - <entry> - <key>Date of birth</key> - </entry> - <entry> - <key>Lastname</key> - </entry> - <entry> - <key>Salutation</key> - </entry> - <entry> - <key>Middlename</key> - </entry> - <entry> - <key>Title</key> - </entry> - <entry> - <key>Addresstype</key> - </entry> - <entry> - <key>Firstname</key> - </entry> - <entry> - <key>Description</key> - </entry> - <entry> - <key>Direction</key> - </entry> - <entry> - <key>Entrydate</key> - </entry> - <entry> - <key>Subject</key> - </entry> - <entry> - <key>changed on %0 by %1</key> - </entry> - <entry> - <key>Post office box</key> - </entry> - <entry> - <key>created on %0 by %1</key> - </entry> - <entry> - <key>Delivery address</key> - </entry> - <entry> - <key>House number</key> - </entry> - <entry> - <key>Country</key> - </entry> - <entry> - <key>Communication</key> - </entry> - <entry> - <key>postcode</key> - </entry> - <entry> - <key>City</key> - </entry> - <entry> - <key>State</key> - </entry> - <entry> - <key>Region</key> - </entry> - <entry> - <key>District</key> - </entry> - <entry> - <key>Switzerland</key> - </entry> - <entry> - <key>Inactive</key> - </entry> - <entry> - <key>Nein</key> - </entry> - <entry> - <key>Bestätigt</key> - </entry> - <entry> - <key>Benutzer</key> - </entry> - <entry> - <key>frei</key> - </entry> - <entry> - <key>Vorläufig</key> - </entry> - <entry> - <key>Ja</key> - </entry> - <entry> - <key>Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>Betreff</key> - </entry> - <entry> - <key>Internal (2)</key> - </entry> - <entry> - <key>Company Addresses</key> - </entry> - <entry> - <key>Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>Termin</key> - </entry> - <entry> - <key>Außer Haus</key> - </entry> - <entry> - <key>Abgesagt</key> - </entry> - <entry> - <key>Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> - </entry> - <entry> - <key>yyyyMMdd</key> - </entry> - <entry> - <key>Gebucht</key> - </entry> - <entry> - <key>Ein Gruppentermin kann nur durch den Organisator bearbeitet werden.</key> - </entry> - </keyValueMap> - <font name="Dialog" style="0" size="11" /> -</language> +<?xml version="1.0" encoding="UTF-8"?> +<language xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.3" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/language/1.1.3"> + <name>_____LANGUAGE_en</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <language>en</language> + <country></country> + <variant></variant> + <keyValueMap> + <entry> + <key>Company</key> + </entry> + <entry> + <key>German (Austria)</key> + </entry> + <entry> + <key>E-Mail</key> + </entry> + <entry> + <key>Customer</key> + </entry> + <entry> + <key>Internal</key> + </entry> + <entry> + <key>Male</key> + </entry> + <entry> + <key>Outgoing</key> + </entry> + <entry> + <key>History</key> + </entry> + <entry> + <key>Name</key> + </entry> + <entry> + <key>Austria</key> + </entry> + <entry> + <key>Der Alias \&quot;%0\&quot; konnte nicht geladen werden. Eventuell wurde er nicht konfiguriert</key> + </entry> + <entry> + <key>Customercode</key> + </entry> + <entry> + <key>Norwegian</key> + </entry> + <entry> + <key>Status</key> + </entry> + <entry> + <key>German (Germany)</key> + </entry> + <entry> + <key>Incoming</key> + </entry> + <entry> + <key>Active</key> + </entry> + <entry> + <key>${GENDER_OTHER}</key> + <value>Other</value> + </entry> + <entry> + <key>Medium</key> + </entry> + <entry> + <key>Internet</key> + </entry> + <entry> + <key>Germany</key> + </entry> + <entry> + <key>Online-Meeting</key> + </entry> + <entry> + <key>Social Media</key> + </entry> + <entry> + <key>Visit</key> + </entry> + <entry> + <key>In review</key> + </entry> + <entry> + <key>German</key> + </entry> + <entry> + <key>Information</key> + </entry> + <entry> + <key>Language</key> + </entry> + <entry> + <key>Phone</key> + </entry> + <entry> + <key>[%0]the given keyword \&quot;%1\&quot; has no match with the possible keywordlist</key> + </entry> + <entry> + <key>Histories</key> + </entry> + <entry> + <key>Female</key> + </entry> + <entry> + <key>Supplier</key> + </entry> + <entry> + <key>English (United Kingdom)</key> + </entry> + <entry> + <key>Social</key> + </entry> + <entry> + <key>Contactmanagement</key> + </entry> + <entry> + <key>United Kingdom</key> + </entry> + <entry> + <key>Mobile</key> + </entry> + <entry> + <key>Office address</key> + </entry> + <entry> + <key>Contact</key> + </entry> + <entry> + <key>English</key> + </entry> + <entry> + <key>Home address</key> + </entry> + <entry> + <key>Type</key> + </entry> + <entry> + <key>Contacts</key> + </entry> + <entry> + <key>Norway</key> + </entry> + <entry> + <key>Prospect</key> + </entry> + <entry> + <key>the param \&quot;%0\&quot; in \&quot;%1\&quot; is mandatory and has to be set</key> + </entry> + <entry> + <key>Other</key> + </entry> + <entry> + <key>yyyy-MM-dd</key> + </entry> + <entry> + <key>Address</key> + </entry> + <entry> + <key>Addresses</key> + </entry> + <entry> + <key>${COMM_ADDRESS}</key> + <value>Address</value> + </entry> + <entry> + <key>Gender</key> + </entry> + <entry> + <key>Date of birth</key> + </entry> + <entry> + <key>Lastname</key> + </entry> + <entry> + <key>Salutation</key> + </entry> + <entry> + <key>Middlename</key> + </entry> + <entry> + <key>Title</key> + </entry> + <entry> + <key>Addresstype</key> + </entry> + <entry> + <key>Firstname</key> + </entry> + <entry> + <key>Description</key> + </entry> + <entry> + <key>Direction</key> + </entry> + <entry> + <key>Entrydate</key> + </entry> + <entry> + <key>Subject</key> + </entry> + <entry> + <key>changed on %0 by %1</key> + </entry> + <entry> + <key>Post office box</key> + </entry> + <entry> + <key>created on %0 by %1</key> + </entry> + <entry> + <key>Delivery address</key> + </entry> + <entry> + <key>House number</key> + </entry> + <entry> + <key>Country</key> + </entry> + <entry> + <key>Communication</key> + </entry> + <entry> + <key>postcode</key> + </entry> + <entry> + <key>City</key> + </entry> + <entry> + <key>State</key> + </entry> + <entry> + <key>Region</key> + </entry> + <entry> + <key>District</key> + </entry> + <entry> + <key>Switzerland</key> + </entry> + <entry> + <key>Inactive</key> + </entry> + <entry> + <key>Bestätigt</key> + </entry> + <entry> + <key>Benutzer</key> + </entry> + <entry> + <key>frei</key> + </entry> + <entry> + <key>Vorläufig</key> + </entry> + <entry> + <key>Monatliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>Betreff</key> + </entry> + <entry> + <key>Internal (2)</key> + </entry> + <entry> + <key>Company Addresses</key> + </entry> + <entry> + <key>Jährliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>Termin</key> + </entry> + <entry> + <key>Außer Haus</key> + </entry> + <entry> + <key>Abgesagt</key> + </entry> + <entry> + <key>Tägliche Serie nicht genauer spezifiziert. Ignoriere Serie.</key> + </entry> + <entry> + <key>yyyyMMdd</key> + </entry> + <entry> + <key>Gebucht</key> + </entry> + <entry> + <key>Ein Gruppentermin kann nur durch den Organisator bearbeitet werden.</key> + </entry> + <entry> + <key>Communication Other</key> + </entry> + <entry> + <key>Communication Phone</key> + </entry> + <entry> + <key>Communication E-Mail</key> + </entry> + <entry> + <key>standard address</key> + </entry> + </keyValueMap> + <font name="Dialog" style="0" size="11" /> +</language> diff --git a/neonView/PersPreview_view/PersPreview_view.aod b/neonView/PersPreview_view/PersPreview_view.aod index 44c36c38d2d..a3b9ca8a3a4 100644 --- a/neonView/PersPreview_view/PersPreview_view.aod +++ b/neonView/PersPreview_view/PersPreview_view.aod @@ -1,62 +1,72 @@ -<?xml version="1.0" encoding="UTF-8"?> -<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.0"> - <name>PersPreview_view</name> - <majorModelMode>DISTRIBUTED</majorModelMode> - <layout> - <boxLayout> - <name>layout</name> - </boxLayout> - </layout> - <children> - <cardViewTemplate> - <name>PersHeader_template</name> - <iconField>IMAGE</iconField> - <titleField>NAME_fieldGroup</titleField> - <descriptionField>ORGNAME</descriptionField> - <entityField>#ENTITY</entityField> - </cardViewTemplate> - <neonViewReference> - <name>4c4b1e66-fdc2-469c-a553-244b6dbffbe0</name> - <entityField>PersAddress_dfo</entityField> - <view>AddressList_view</view> - </neonViewReference> - <neonViewReference> - <name>f4f9ba7d-b969-416b-a4c2-0be82ad1c744</name> - <entityField>OrgAddress_dfo</entityField> - <view>AddressList_view</view> - </neonViewReference> - <neonViewReference> - <name>41e3d75c-0456-4140-b651-eb45ffb53a35</name> - <entityField>PersComm_dfo</entityField> - <view>CommList_view</view> - </neonViewReference> - <genericViewTemplate> - <name>PersInfo_template</name> - <showDrawer v="true" /> - <drawerCaption>weitere Informationen</drawerCaption> - <entityField>#ENTITY</entityField> - <fields> - <entityFieldLink> - <name>b1fae414-9818-48ff-8774-c310caf34d79</name> - <entityField>SALUTATION</entityField> - </entityFieldLink> - <entityFieldLink> - <name>c12f22ff-3536-45b6-b26f-1d8de6b5aea0</name> - <entityField>TITLE</entityField> - </entityFieldLink> - <entityFieldLink> - <name>a224aada-e6cf-4357-b563-d7ccf313d32d</name> - <entityField>MIDDLENAME</entityField> - </entityFieldLink> - <entityFieldLink> - <name>f9875d78-3d72-47d3-b729-9cf80d236f6e</name> - <entityField>GENDER</entityField> - </entityFieldLink> - <entityFieldLink> - <name>5d4e0828-b7fe-4f54-a47a-f9b5838fb1ae</name> - <entityField>DATEOFBIRTH</entityField> - </entityFieldLink> - </fields> - </genericViewTemplate> - </children> -</neonView> +<?xml version="1.0" encoding="UTF-8"?> +<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.0"> + <name>PersPreview_view</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <layout> + <boxLayout> + <name>layout</name> + </boxLayout> + </layout> + <children> + <cardViewTemplate> + <name>PersHeader_template</name> + <iconField>IMAGE</iconField> + <titleField>NAME_fieldGroup</titleField> + <descriptionField>ORGNAME</descriptionField> + <entityField>#ENTITY</entityField> + </cardViewTemplate> + <neonViewReference> + <name>4c4b1e66-fdc2-469c-a553-244b6dbffbe0</name> + <entityField>PersAddress_dfo</entityField> + <view>AddressList_view</view> + </neonViewReference> + <neonViewReference> + <name>f4f9ba7d-b969-416b-a4c2-0be82ad1c744</name> + <entityField>OrgAddress_dfo</entityField> + <view>AddressList_view</view> + </neonViewReference> + <neonViewReference> + <name>45aae3a7-b04e-460f-a68d-8a40c6181528</name> + <entityField>PersCommEmail_dfo</entityField> + <view>CommList_view</view> + </neonViewReference> + <neonViewReference> + <name>83e51f10-a205-409b-9780-a7ee14104cc1</name> + <entityField>PersCommPhone_dfo</entityField> + <view>CommList_view</view> + </neonViewReference> + <neonViewReference> + <name>1dbf2020-a0e9-4f22-a1d7-aad60c9ec7d4</name> + <entityField>PersCommOthers_dfo</entityField> + <view>CommList_view</view> + </neonViewReference> + <genericViewTemplate> + <name>PersInfo_template</name> + <showDrawer v="true" /> + <drawerCaption>weitere Informationen</drawerCaption> + <entityField>#ENTITY</entityField> + <fields> + <entityFieldLink> + <name>b1fae414-9818-48ff-8774-c310caf34d79</name> + <entityField>SALUTATION</entityField> + </entityFieldLink> + <entityFieldLink> + <name>c12f22ff-3536-45b6-b26f-1d8de6b5aea0</name> + <entityField>TITLE</entityField> + </entityFieldLink> + <entityFieldLink> + <name>a224aada-e6cf-4357-b563-d7ccf313d32d</name> + <entityField>MIDDLENAME</entityField> + </entityFieldLink> + <entityFieldLink> + <name>f9875d78-3d72-47d3-b729-9cf80d236f6e</name> + <entityField>GENDER</entityField> + </entityFieldLink> + <entityFieldLink> + <name>5d4e0828-b7fe-4f54-a47a-f9b5838fb1ae</name> + <entityField>DATEOFBIRTH</entityField> + </entityFieldLink> + </fields> + </genericViewTemplate> + </children> +</neonView> diff --git a/process/Keyword_lib/process.js b/process/Keyword_lib/process.js index 85b57553f31..0a8b118c663 100644 --- a/process/Keyword_lib/process.js +++ b/process/Keyword_lib/process.js @@ -1,233 +1,248 @@ -import("system.translate"); - -/** - * provides methods for interactions with keywords - */ -function KeywordUtils(){ - /** - * returns the default case for keyword-arrays (id and translated name) - * @param {String} keywordType specifies the type of the keyword and therefore the list elements; e.g. "COUNTRY" - * @return {Array} a 2D array in form of [["id1", "name1"], ["idN", "nameN"]] - * @example - * var kwdUtils, items; - * - * kwdUtils = new KeywordUtils(); - * items = kwdUtils.getStandardArray("ADDRESS.TYPE"); - * result.object(items); - */ - this.getStandardArray = function(keywordType){ - return this.createKeyword(keywordType).toArray(["id", "name"]); - } - - /** - * returns a specific name (translated) - this is normally the view-value - of a given keyword; - * <br/>if the key could not be found an empty string "" is returned - * @param {String} keywordType specifies the type of the keyword and therefore the list elements; e.g. "COUNTRY" - * @param {String} key id value of the keyword where the view-value shall be searched - * @return {String} representation of the translated name of the keyword-key - * @example - * var kwdUtils, histMedium; - * histMedium = vars.get("$field.MEDIUM"); - * if (histMedium){ - * kwdUtils = new KeywordUtils(); - * result.string(vars.get("$field.SUBJECT") + " (" + kwdUtils.getViewValue("HISTORY.MEDIUM", histMedium) + ")"); - * } - */ - this.getViewValue = function(keywordType, key){ - var k = this.createKeyword(keywordType); - return k.getPropForKey(key, "name") || ""; - } - - /** - * creates an object with methods for interacting with an specific keyword - * @param {String} keywordType specifies the type of the keyword and therefore the list elements; e.g. "COUNTRY" - * @return {Object} object with the following methods: - * <br/>- toArray - * <br/>- getPropForKey - * <br/>- getPropsForKey - */ - this.createKeyword = function(keywordType){ - var valueContainer, _toArrayFn, _getPropForKeyFn, _getPropsForKeyFn; - - switch (keywordType){ - case "RELATION.STATUS": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("0", translate.text("Inactive")) - ,createKeywordEntry("1", translate.text("Active")) - ,createKeywordEntry("2", translate.text("In review")) - ]); - break; - case "COUNTRY": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("DE", translate.text("Germany")) - ,createKeywordEntry("AT", translate.text("Austria")) - ,createKeywordEntry("CH", translate.text("Switzerland")) - ,createKeywordEntry("GB", translate.text("United Kingdom")) - ,createKeywordEntry("NO", translate.text("Norway")) - ]); - break; - case "LANGUAGE": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("de", translate.text("German")) - ,createKeywordEntry("de-DE", translate.text("German (Germany)")) - ,createKeywordEntry("de-AT", translate.text("German (Austria)")) - ,createKeywordEntry("en", translate.text("English")) - ,createKeywordEntry("en-GB", translate.text("English (United Kingdom)")) - ,createKeywordEntry("no-NO", translate.text("Norwegian")) - ]); - break; - case "HISTORY.DIRECTION": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("i", translate.text("Incoming")) - ,createKeywordEntry("o", translate.text("Outgoing")) - ]); - break; - case "HISTORY.MEDIUM": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("0", translate.text("Visit")) - ,createKeywordEntry("1", translate.text("E-Mail")) - ,createKeywordEntry("2", translate.text("Phone")) - ,createKeywordEntry("3", translate.text("Internal")) - ,createKeywordEntry("4", translate.text("Online-Meeting")) - ]); - case "COMM.MEDIUM": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("0", translate.text("Mobile"), null, {category: "PHONE"}) - ,createKeywordEntry("1", translate.text("E-Mail"), null, {category: "EMAIL"}) - ,createKeywordEntry("2", translate.text("Phone"), null, {category: "PHONE"}) - ,createKeywordEntry("3", translate.text("Internet"), null, {category: "WEBSITE"}) - ]); - break; - case "ADDRESS.TYPE": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("1", translate.text("Office address")) - ,createKeywordEntry("2", translate.text("Home address")) - ,createKeywordEntry("3", translate.text("Delivery address")) - ,createKeywordEntry("4", translate.text("Post office box")) - ]); - break; - case "ORG.TYPE": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("0", translate.text("Customer")) - ,createKeywordEntry("1", translate.text("Prospect")) - ,createKeywordEntry("2", translate.text("Supplier")) - ,createKeywordEntry("3", translate.text("Other")) - ]); - break; - case "PERS.GENDER": - valueContainer = createKeywordEntriesContainer([ - createKeywordEntry("f", translate.text("Female")) - ,createKeywordEntry("m", translate.text("Male")) - ,createKeywordEntry("o", translate.text("${GENDER_OTHER}")) - ]); - break; - default: - throw new Error(translate.withArguments("[%0]the given keyword \"%1\" has no match with the possible keywordlist", [ - arguments.callee.name, keywordType - ])); - break; - } - - - _getPropForKeyFn = function(key, field, isCustom) { - var keyObject; - if (isCustom) - keyObject = valueContainer[key]["customProperties"]; - else - keyObject = valueContainer[key]; - - if (keyObject == undefined) - return undefined; - return keyObject[field]; - }; - - _getPropsForKeyFn = function(key, fields) { - var keyObject, i, l, currentRow, currentField; - - keyObject = valueContainer[key]; - if (keyObject == undefined) - return [];//TODO: throw error instead? - l = fields.length; - currentRow = []; - for (i = 0; i < l; i++){ - currentField = fields[i]; - //check if the passed fieldnames match the existing fieldnames (<=> properties in the object) - //to prevent errors and unexpected behaviour - if (keyObject[currentField]) - currentRow.push(keyObject[currentField]); - else - currentRow.push(""); - } - return currentRow; - }; - - _toArrayFn = function(fields){ - var res, id, currentRow; - - res = []; - if (!fields) - fields = ["id", "name"]; - l = fields.length; - for (id in valueContainer){ - currentRow = _getPropsForKeyFn(id, fields); - res.push(currentRow); - } - return res; - }; - - return { - /** - * toArray - */ - toArray: _toArrayFn - ,getPropForKey: _getPropForKeyFn - ,getPropsForKey: _getPropsForKeyFn - }; - }; - - /** - * internal function for creating an object that represents a keyword entry - * @param {String} id represents the key of an entry; a KeywordEntriesContainer can contain the same key only once - * @param {String} name represents the translated name of an entry; this is in most cases the view-value - * @param {String} [description=""] description text for describing the keyword - * @param {Object} [customProperties=null] an Object with additional properties; these can be virtually anything - * @return {Object} object that represents a single keyword entry; normally severel entries are cumulated in a "keywordEntriesContainer" - */ - function createKeywordEntry(id, name, description, customProperties){ - //TODO: verify if mandatory-checks are really that usefull or can at least be made easier - if (!id) - throw new Error(translate.withArguments("the param \"%0\" in \"%1\" is mandatory and has to be set", [ - "id", arguments.callee.name - ])); - if (!name) - throw new Error(translate.withArguments("the param \"%0\" in \"%1\" is mandatory and has to be set", [ - "name", arguments.callee.name - ])); - - return { - id: id - ,name: name - ,description: description || "" - ,customProperties: customProperties - }; - } - - /** - * internal function for creating an object that represents a container of several keywordEntries - * @param {Array} keywordEntries an Array of keywordEntry-objects (as they are created by "createKeywordEntry" - * @return {Object} object that contains several keywordEntries - */ - function createKeywordEntriesContainer(keywordEntries){ - var res, i, l, id; - - res = {}; - for (i = 0, l = keywordEntries.length; i < l; i++){ - id = keywordEntries[i].id; - if (res[id] != undefined){ - throw new Error("the given id is not unique since it already exists"); - } - res[id] = keywordEntries[i]; - } - return res; - } +import("system.translate"); + +/** + * provides methods for interactions with keywords + */ +function KeywordUtils(){ + /** + * returns the default case for keyword-arrays (id and translated name) + * @param {String} keywordType specifies the type of the keyword and therefore the list elements; e.g. "COUNTRY" + * @return {Array} a 2D array in form of [["id1", "name1"], ["idN", "nameN"]] + * @example + * var kwdUtils, items; + * + * kwdUtils = new KeywordUtils(); + * items = kwdUtils.getStandardArray("ADDRESS.TYPE"); + * result.object(items); + */ + this.getStandardArray = function(keywordType){ + return this.createKeyword(keywordType).toArray(["id", "name"]); + } + + /** + * returns a specific name (translated) - this is normally the view-value - of a given keyword; + * <br/>if the key could not be found an empty string "" is returned + * @param {String} keywordType specifies the type of the keyword and therefore the list elements; e.g. "COUNTRY" + * @param {String} key id value of the keyword where the view-value shall be searched + * @return {String} representation of the translated name of the keyword-key + * @example + * var kwdUtils, histMedium; + * histMedium = vars.get("$field.MEDIUM"); + * if (histMedium){ + * kwdUtils = new KeywordUtils(); + * result.string(vars.get("$field.SUBJECT") + " (" + kwdUtils.getViewValue("HISTORY.MEDIUM", histMedium) + ")"); + * } + */ + this.getViewValue = function(keywordType, key){ + var k = this.createKeyword(keywordType); + return k.getPropForKey(key, "name") || ""; + } + + /** + * creates an object with methods for interacting with an specific keyword + * @param {String} keywordType specifies the type of the keyword and therefore the list elements; e.g. "COUNTRY" + * @return {Object} object with the following methods: + * <br/>- toArray + * <br/>- getPropForKey + * <br/>- getPropsForKey + */ + this.createKeyword = function(keywordType){//TODO: rename ot createKeywordObj? + var valueContainer, _toArrayFn, _getPropForKeyFn, _getPropsForKeyFn; + + switch (keywordType){ + case "RELATION.STATUS": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("0", translate.text("Inactive")) + ,createKeywordEntry("1", translate.text("Active")) + ,createKeywordEntry("2", translate.text("In review")) + ]); + break; + case "COUNTRY": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("DE", translate.text("Germany")) + ,createKeywordEntry("AT", translate.text("Austria")) + ,createKeywordEntry("CH", translate.text("Switzerland")) + ,createKeywordEntry("GB", translate.text("United Kingdom")) + ,createKeywordEntry("NO", translate.text("Norway")) + ]); + break; + case "LANGUAGE": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("de", translate.text("German")) + ,createKeywordEntry("de-DE", translate.text("German (Germany)")) + ,createKeywordEntry("de-AT", translate.text("German (Austria)")) + ,createKeywordEntry("en", translate.text("English")) + ,createKeywordEntry("en-GB", translate.text("English (United Kingdom)")) + ,createKeywordEntry("no-NO", translate.text("Norwegian")) + ]); + break; + case "HISTORY.DIRECTION": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("i", translate.text("Incoming")) + ,createKeywordEntry("o", translate.text("Outgoing")) + ]); + break; + case "HISTORY.MEDIUM": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("0", translate.text("Visit")) + ,createKeywordEntry("1", translate.text("E-Mail")) + ,createKeywordEntry("2", translate.text("Phone")) + ,createKeywordEntry("3", translate.text("Internal")) + ,createKeywordEntry("4", translate.text("Online-Meeting")) + ]); + case "COMM.MEDIUM": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("0", translate.text("Mobile"), null, {category: "PHONE"}) + ,createKeywordEntry("1", translate.text("E-Mail"), null, {category: "EMAIL"}) + ,createKeywordEntry("2", translate.text("Phone"), null, {category: "PHONE"}) + ,createKeywordEntry("3", translate.text("Internet"), null, {category: "OTHER"}) + ]); + break; + case "ADDRESS.TYPE": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("1", translate.text("Office address")) + ,createKeywordEntry("2", translate.text("Home address")) + ,createKeywordEntry("3", translate.text("Delivery address")) + ,createKeywordEntry("4", translate.text("Post office box")) + ]); + break; + case "ORG.TYPE": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("0", translate.text("Customer")) + ,createKeywordEntry("1", translate.text("Prospect")) + ,createKeywordEntry("2", translate.text("Supplier")) + ,createKeywordEntry("3", translate.text("Other")) + ]); + break; + case "PERS.GENDER": + valueContainer = createKeywordEntriesContainer([ + createKeywordEntry("f", translate.text("Female")) + ,createKeywordEntry("m", translate.text("Male")) + ,createKeywordEntry("o", translate.text("${GENDER_OTHER}")) + ]); + break; + default: + throw new Error(translate.withArguments("[%0]the given keyword \"%1\" has no match with the possible keywordlist", [ + arguments.callee.name, keywordType + ])); + break; + } + + + _getPropForKeyFn = function(key, field, isCustom) { + var keyObject; + if (isCustom) + keyObject = valueContainer[key]["customProperties"]; + else + keyObject = valueContainer[key]; + + if (keyObject == undefined) + return undefined; + return keyObject[field]; + }; + + _getPropsForKeyFn = function(key, fields) { + var keyObject, i, l, currentRow, currentField; + + keyObject = valueContainer[key]; + if (keyObject == undefined) + return [];//TODO: throw error instead? + l = fields.length; + currentRow = []; + for (i = 0; i < l; i++){ + currentField = fields[i]; + //check if the passed fieldnames match the existing fieldnames (<=> properties in the object) + //to prevent errors and unexpected behaviour + if (keyObject[currentField]) + currentRow.push(keyObject[currentField]); + else + currentRow.push(""); + } + return currentRow; + }; + + _toArrayFn = function(fields){ + var res, id, currentRow; + + res = []; + if (!fields) + fields = ["id", "name"]; + else if (typeof(fields) == "string"){ + for (id in valueContainer){ + res.push(_getPropForKeyFn(id, fields)); + } + return res; + } + + for (id in valueContainer){ + currentRow = _getPropsForKeyFn(id, fields); + res.push(currentRow); + } + return res; + }; + + return { + /** + * toArray + */ + toArray: _toArrayFn + ,getPropForKey: _getPropForKeyFn + ,getPropsForKey: _getPropsForKeyFn + ,filter: function (callbackFn, thisArg){ + for (id in valueContainer){ + if (false == callbackFn.call(thisArg, valueContainer[id].id, valueContainer[id].name, valueContainer[id].customProperties, + valueContainer[id], valueContainer)){ + delete valueContainer[id]; + } + } + return this; + } + }; + }; + + /** + * internal function for creating an object that represents a keyword entry + * @param {String} id represents the key of an entry; a KeywordEntriesContainer can contain the same key only once + * @param {String} name represents the translated name of an entry; this is in most cases the view-value + * @param {String} [description=""] description text for describing the keyword + * @param {Object} [customProperties=null] an Object with additional properties; these can be virtually anything + * @return {Object} object that represents a single keyword entry; normally severel entries are cumulated in a "keywordEntriesContainer" + */ + function createKeywordEntry(id, name, description, customProperties){ + //TODO: verify if mandatory-checks are really that usefull or can at least be made easier + if (!id) + throw new Error(translate.withArguments("the param \"%0\" in \"%1\" is mandatory and has to be set", [ + "id", arguments.callee.name + ])); + if (!name) + throw new Error(translate.withArguments("the param \"%0\" in \"%1\" is mandatory and has to be set", [ + "name", arguments.callee.name + ])); + + return { + id: id + ,name: name + ,description: description || "" + ,customProperties: customProperties + }; + } + + /** + * internal function for creating an object that represents a container of several keywordEntries + * @param {Array} keywordEntries an Array of keywordEntry-objects (as they are created by "createKeywordEntry" + * @return {Object} object that contains several keywordEntries + */ + function createKeywordEntriesContainer(keywordEntries){ + var res, i, l, id; + + res = {}; + for (i = 0, l = keywordEntries.length; i < l; i++){ + id = keywordEntries[i].id; + if (res[id] != undefined){ + throw new Error("the given id is not unique since it already exists"); + } + res[id] = keywordEntries[i]; + } + return res; + } } \ No newline at end of file diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js index 24a50f2516a..9187a8f49e5 100644 --- a/process/Sql_lib/process.js +++ b/process/Sql_lib/process.js @@ -1,1006 +1,1066 @@ -import("system.translate"); -import("system.vars"); -import("system.db"); -import("system.datetime"); -import("system.tools"); -import("system.SQLTYPES"); -import("Util_lib") - -function SqlMaskingUtils(){ - //TODO: use callbacks for different handling? - /** - * masks the function cast of standard sql - * - * @param {String} field name of the database field that shall be castet - * @param {String} [targetDatatype] a SQLTYPES-value of the following: SQLTYPES.CHAR, SQLTYPES.VARCHAR, SQLTYPES.INTEGER, - * SQLTYPES.DECIMAL, SQLTYPES.DATE - * @param {int|int[]} targetLength specifies the length of the target data type; - * <br/>- char/varchar: length - * <br/>- decimal: [length, decimals] - * @param {String} [alias=the current alias] the alias where the statement shall be executed (this is needed to determine the database-type) - * - * @return {String} sql part to be included in sql-statements - */ - this.cast = function (field, targetDatatype, targetLength, alias){ - /* Some informations if you want to add supported databaseTypes or dataTypes: - * You should consider using the _mapDefaults function-expression (details in the functions doc) - * However you shouldn't use the function in a "default"-Block of a switch-case because of the following behaviour: - * If a datatype is not supported you just have to NOT specify "sqlDataType" (leave it "undefined") -> an error is then raised - * Therefore you should explicitly define which Data-type is supported and which is not - */ - var dbType, functionName, sqlPart, sqlDataType, _mapDefaults; - if (alias == undefined) - alias = vars.getString("$sys.dbalias"); - dbType = db.getDatabaseType(alias); - functionName = "cast";//overwrite this in the "switch (dbType)" if needed with your DBMS - - /** - * handles default-scenarios for mapping input-targetDatatype to a string for a sql-statement - * e.g. SQLTYPES.INTEGER --> int - * @param {Number} dataType input as a value of "SQLTYPES." that will be mapped to a string - * @return {String} the mapped dataType for using in a sql-statement - */ - _mapDefaults = function (dataType){ - var res; - switch(dataType) - { - case SQLTYPES.CHAR: - res = "char"; - break; - case SQLTYPES.VARCHAR: - res = "char"; - break; - case SQLTYPES.INTEGER: - res = "int"; - break; - case SQLTYPES.DECIMAL: - res = "decimal"; - break; - case SQLTYPES.DATE: - res = "date"; - break; - } - return res; - } - switch (dbType) { - case db.DBTYPE_DERBY10: - switch(targetDatatype) { - case SQLTYPES.VARCHAR: - // Because of a Derby bug, you can't cast INTEGER into VARCHAR - // Therefor first cast to char then to varchar - // https://issues.apache.org/jira/browse/DERBY-2072 - field = "rtrim(" + cast(field, SQLTYPES.CHAR, targetLength, alias) + ")"; - sqlDataType = "varchar"; - break; - case SQLTYPES.CHAR: - //TODO: throw error if(targetLength > 254)? https://db.apache.org/derby/docs/10.14/ref/rrefsqlj13733.html - sqlDataType = "char"; - break; - case SQLTYPES.DECIMAL: - case SQLTYPES.INTEGER: - case SQLTYPES.DATE: - sqlDataType = _mapDefaults(dataType); - break; - } - break; - case db.DBTYPE_MARIADB10: - case db.DBTYPE_MYSQL4: - switch(targetDatatype) { - case SQLTYPES.VARCHAR: - case SQLTYPES.CHAR: - case SQLTYPES.INTEGER: - case SQLTYPES.DECIMAL: - case SQLTYPES.DATE: - sqlDataType = _mapDefaults(targetDatatype); - break; - } - break; - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - switch(pDatatype) - { - case SQLTYPES.VARCHAR: - datatype = "varchar2"; - break; - case SQLTYPES.INTEGER: - datatype = "number"; - targetLength = "10" - break; - case SQLTYPES.CHAR: - case SQLTYPES.DECIMAL: - case SQLTYPES.DATE: - sqlDataType = _mapDefaults(targetDatatype); - break; - } - break; - case db.DBTYPE_POSTGRESQL8: - switch(pDatatype) - { - case SQLTYPES.DATE: - case SQLTYPES.DECIMAL: - case SQLTYPES.INTEGER: - case SQLTYPES.CHAR: - case SQLTYPES.VARCHAR: - sqlDataType = _mapDefaults(targetDatatype); - break; - } - break; - case db.DBTYPE_SQLSERVER2000: - case SQLTYPES.DATE: - case SQLTYPES.DECIMAL: - case SQLTYPES.INTEGER: - case SQLTYPES.CHAR: - case SQLTYPES.VARCHAR: - sqlDataType = _mapDefaults(targetDatatype); - break; - case db.DBTYPE_FIREBIRD250: - //TODO: firebird support? - break; - } - - if (sqlDataType == undefined) { - throw new Error("sqlDataType");//TODO: add usefull message - } - - if(targetLength == undefined) - targetLength = ""; - else if(targetLength != "") - { - if(typeof(targetLength == "object") && (targetLength instanceof Array)) - targetLength = "(" + targetLength.join(", ") + ")"; - else - targetLength = "(" + targetLength + ")"; - } - - sqlPart = functionName + "(" + field + " as " + sqlDataType + targetLength + ")"; - return sqlPart; - } -} - -/** - *Class containing utilities for SQL - *@deprecated use SqlMaskingUtils - *@class - */ -function LegacySqlUtils() -{ - var that = this; - /** - * masks the cast function for lob datatypes(clob, blob) - * - * @param {String} pField req the data field - * @param {Integer|Interger[]} pLength req the length of the data - * decimal: [length, decimals] - * @param {String} pAlias req the database alias - * - * @return {String} (Teil einer SQL-Anweisung) - */ - this.castLob = function(pField, pLength, pAlias) - { - if(pAlias == undefined) - pAlias = vars.getString("$sys.dbalias"); - - var dbtype = db.getDatabaseType(pAlias); - - switch(Number(dbtype)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - return "DBMS_LOB.SUBSTR(" + pField + ", " + pLength + ", 1)"; - break; - default: - return cast(pField, "varchar", pLength, pAlias); - break; - } - } - /** - * masks the function substring. - * - * @param {String }pExpression req - * @param {Integer} pStart req index of the beginning - * @param {String} pAlias req database alias - * @param {Integer} pLength req - * - * @return {String} - */ - this.substring = function(pExpression, pStart, pLength, pAlias) - { - if(pLength == undefined) - pLength = 100; - if(pAlias == undefined) - pAlias = vars.getString("$sys.dbalias"); - - var dbtype = db.getDatabaseType(pAlias); - var string = ""; - - switch(Number(dbtype)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - string = "substr"; - break; - case db.DBTYPE_DERBY10: - string = "substr"; - break; - case db.DBTYPE_POSTGRESQL8: - string = "substr"; - break; - case db.DBTYPE_SQLSERVER2000: - string = "substring"; - break; - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - string = "substring"; - break; - } - - return string + "(" + pExpression + ", " + pStart + ", " + pLength + ")"; - } - - /** - * masks the function concat. - * - * @param {Array} pFields req fields that should be concatenated - * @param {String} pSeparator opt field separator - * @param {String} pAlias opt database alias - * - * @return {String} part of SQL-querey - */ - this.concat = function(pFields, pSeparator, pAlias) - { - var i; - if(pAlias == undefined || pAlias == "") - pAlias = vars.getString("$sys.dbalias"); - - var dbtype = db.getDatabaseType(pAlias); - var concat_string = " || "; - var retstr = ""; - var blank = "' '"; - - //it must be checked for empty string and null - var isNotEmpty = " != '' "; - var isNotNull = " is not null "; - if(pSeparator == undefined) - pSeparator = " "; - - switch(Number(dbtype)) - { - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - retstr = " concat_ws( '" + pSeparator + "'"; - for(i=0; i<pFields.length; i++) - { - retstr += ", " + pFields[i]; - } - return retstr + ") "; - break; - - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - blank = "trim(' ')"; - isNotEmpty = " is not null "; //needed for oracle - break; - - case db.DBTYPE_SQLSERVER2000: - concat_string = " + "; - break; - } - pSeparator = concat_string + "'" + pSeparator + "'"; - for(i = 0; i < pFields.length; i++) - { - if(retstr != "") - retstr += concat_string; - if ( i < pFields.length - 1 ) //Check if another value follows, if not separator is not needed - retstr += " case when " + pFields[i] + isNotEmpty + " then case when " + this.trimSql(pFields[i+1], pAlias) + isNotEmpty + " and " - + this.trimSql(pFields[i+1], pAlias) + isNotNull + " then " + pFields[i] + pSeparator + " else " + pFields[i] + " end" + " else " + blank + " end "; - else - retstr += " case when " + pFields[i] + isNotEmpty + " then " + pFields[i] + " else " + blank + " end "; - } - return retstr; - } - /** - * builds a condition out of multiple conditions - * - * @param {Array} pArray req Array containing the conditions - * @param {String} pOperator req Operator that concatenates the conditions (AND/OR) - * - * @return {String} concatenated Condition - */ - this.concatConditions = function(pArray, pOperator) - { - var resultCondition = ""; - - for(var i = 0; i < pArray.length; i++) - { - if(pArray[i] != null && pArray[i] != '') - { - if(resultCondition.length > 0) - resultCondition += (" " + pOperator + " "); - - resultCondition += pArray[i]; - } - } - - return resultCondition; - } - /** - * Checks if a new entry already exists - * - * @param {String} pTable req Databasetable(z.B. "comm") - * @param {Array} pColumns req colums, like sqlInsert - * @param {Array} pTypes req die datatypes, like sqlInsert - * @param {Array} pValues req values, like sqlInsert - * @param {Array} pExcludeFields opt columns, that should not be checked - * @param {String} pAlias opt Database alias - * - * @return {Integer} - */ - this.isDuplicat = function(pTable, pColumns, pTypes, pValues, pExcludeFields, pAlias) - { - var col = new Array(); - var typ = new Array(); - var val = new Array(); - var excludefields = ["DATE_NEW" ,"DATE_EDIT" ,"USER_NEW" ,"USER_EDIT", "KEYVALUE", "KEYSORT", pTable.toUpperCase() + "ID"]; - - if(pExcludeFields != undefined) - excludefields = excludefields.concat(pExcludeFields); - if(pAlias == undefined) - pAlias = vars.getString("$sys.dbalias"); - - for(var i = 0; i < pColumns.length; i++) - { - if(!hasElement(excludefields, pColumns[i], true) && pValues[i] != "" && pTypes[i] != SQLTYPES.LONGVARCHAR && pTypes[i] != SQLTYPES.CLOB) - { - col.push(pColumns[i]); - typ.push(pTypes[i]); - val.push(pValues[i]); - } - } - var count = db.getRowCount(pTable, col, typ, val, pAlias); - return count; - } - /** - * returns the trim function depending on the database - * - * @param {String} pField field the should be trimmed - * @param {String} pAlias opt database alias - * - * @return {String} - */ - this.trimSql = function(pField, pAlias) - { - if(pAlias == undefined || pAlias == "") - pAlias = vars.getString("$sys.dbalias"); - - var dbtype = db.getDatabaseType(pAlias); - var string; - - switch(Number(dbtype)) - { - case db.DBTYPE_SQLSERVER2000: - string = "ltrim(rtrim(" + pField + "))"; - break; - default: - string = "trim(" + pField + ")" - break; - } - return string; - } - /** - * returns the day of a date - * - * @param {Datetime} pDate req the date - * @param {String} pAlias req database alias - * - * @return {String} - */ - this.dayFromDate = function(pDate, pAlias) - { - var usedAlias = pAlias; - - if(pAlias == undefined) - usedAlias = vars.getString("$sys.dbalias"); - - var dbAlias = db.getDatabaseType(usedAlias); - var string = ""; - - switch(Number(dbAlias)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - string = "to_char(" + pDate + ",'dd')"; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_SQLSERVER2000: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - string = "DAY(" + pDate + ")"; - break; - case db.DBTYPE_POSTGRESQL8: - string = "EXTRACT (DAY from " + pDate + ")"; - break; - } - return string; - } - /** - * returns the month of a date - * - * @param {Datetime} pDate req the date - * @param {String} pAlias req database alias - * - * @return {String} - */ - this.monthFromDate = function(pDate, pAlias) - { - var usedAlias = pAlias; - if(pAlias == undefined) - usedAlias = vars.getString("$sys.dbalias"); - - var dbAlias = db.getDatabaseType(usedAlias); - var string = ""; - - switch(Number(dbAlias)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - string = "to_char(" + pDate + ",'MM')"; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_SQLSERVER2000: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - string = "MONTH(" + pDate + ")"; - break; - case db.DBTYPE_POSTGRESQL8: - string = "EXTRACT (MONTH FROM " + pDate + ")"; - break; - } - return string; - } - /** - * returns the year of a date - * - * @param {Datetime} pDate req the date - * @param {String} pAlias req database alias - * - * @return {String} - */ - this.yearFromDate = function(pDate, pAlias) - { - var usedAlias = pAlias; - if(pAlias == undefined) - usedAlias = vars.getString("$sys.dbalias"); - - var dbAlias = db.getDatabaseType(usedAlias); - var string = ""; - - switch(Number(dbAlias)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - string = "to_char(" + pDate + ",'yyyy')"; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_SQLSERVER2000: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - string = "YEAR(" + pDate + ")"; - break; - case db.DBTYPE_POSTGRESQL8: - string = "EXTRACT (YEAR FROM " + pDate + ")"; - break; - } - return string; - } - /** - * returns the function for current date depending on database - * - * @return {String} expression - */ - this.currentDate = function() - { - var dbtype = db.getDatabaseType(vars.getString("$sys.dbalias")); - var expression = ""; - - switch (Number(dbtype)) - { - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_DERBY10: - expression = "CURRENT_DATE"; - break; - case db.DBTYPE_SQLSERVER2000: - expression = "GETDATE()"; - break; - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - expression = "NOW()"; - break; - } - return expression; - } - /** - * returns the current search string incl placeholders - * - * @param {String} pfield req the search field - * @param {String} pfind req the search string - * @param {String} pIgnoreCase opt (true/false) - * @param {String} pPlaceHolder opt (Platzhalter config) - * - * @return {String} - */ - this.getPlacerholderCondition = function( pfield, pfind, pIgnoreCase, pPlaceHolder ) - { - var user = tools.getCurrentUser(); - var IgCa; - var PlHo; - - //wenn optoinal IgnoreCase und PlaceHolder vorhanden, dann diese verwenden - if(pIgnoreCase != undefined) - IgCa = pIgnoreCase; - else - IgCa = user[tools.PARAMS][tools.SELECTION_IGNORECASE]; - - if(pPlaceHolder != undefined) - PlHo = pPlaceHolder; - else - PlHo = user[tools.PARAMS][tools.SELECTION_PLACEHOLDER]; - - if ( pfind ) - { - pfind = pfind.replace( new RegExp("\\'", "g"), "''"); - pfind = pfind.replace( new RegExp("\\*", "g"), "%"); - var ic = (IgCa == "true" ? "UPPER" : ""); - var cond = ""; - switch( PlHo ) - { - case "1": - cond = ic + "(" + pfield + ") like " + ic + "('" + pfind + "%')"; - break; - case "2": - cond = ic + "(" + pfield + ") like " + ic + "('%" + pfind + "')"; - break; - case "3": - cond = ic + "(" + pfield + ") like " + ic + "('%" + pfind + "%')"; - break; - case "4": - cond = ic + "(" + pfield + ") like " + ic + "('" + pfind + "')"; - break; - default: - cond = ic + "(" + pfield + ") = " + ic + "('" + pfind + "')"; - break; - } - } - return cond; - } - /** - * returns SQLSystax for a date. - * - * @param {String} pColumn req Column name - * @param {String} pAlias opt Database alias - * @param {Boolean} pWithTime opt if true, then add time hh:mm:ss - * @param {String} pFormat opt type of the format, e.g. yyyy-MM-dd; possible placeholers are: -dd -MM -yyyy - * - *@return {String} sqlstr, fully functional select for sql for different types of databases - */ - this.getSqlFormattedDate = function(pColumn, pAlias, pWithTime, pFormat) - { - if(pAlias == undefined) - pAlias = vars.getString("$sys.dbalias"); - - var pDatabaseType = db.getDatabaseType(pAlias); - - if (pFormat == undefined) - pFormat = translate.text("yyyy-MM-dd"); - - var str = ""; - - switch(Number(pDatabaseType)) - { - case db.DBTYPE_SQLSERVER2000: - day = "right('0' + cast(day(" + pColumn + ") as varchar(2)) , 2)"; - month = "right('0' + cast(month(" + pColumn + ") as varchar(2)) , 2)"; - year = "cast(year(" + pColumn + ") as char(4))"; - time = pWithTime == true? that.concat(["' '","cast(cast(" + pColumn + " as time) as char(8))"], "", pAlias) : ""; - break; - case db.DBTYPE_POSTGRESQL8: - day = "extract(day from " + pColumn + ")"; - month = "extract(month from " + pColumn + ")"; - year = "extract(year from " + pColumn + ")"; - time = pWithTime == true? that.concat(["' '","extract(time from" + pColumn + ")"], "", pAlias) : ""; - break; - case db.DBTYPE_DERBY10: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - // concat will try to have a leading blank space if the number is => 10. This is why we had to use substr. - day = that.substring(that.concat(["case when day(" + pColumn + ") <= 9 then '00' else '0' end " - , " trim(cast(day(" + pColumn + ") as char(2)))"], "", pAlias), 2, 2, pAlias); - month = that.substring(that.concat(["case when month(" + pColumn + ") <= 9 then '00' else '0' end " - , "trim(cast(month(" + pColumn + ") as char(2)))"], "", pAlias), 2, 2, pAlias); - year = "trim(cast(year(" + pColumn + ") as char(4)))"; - time = pWithTime == true? that.concat(["cast(' ' as char(1))", "trim(cast(time(" + pColumn + ") as char(8)))"], "", pAlias) : ""; - break; - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_ORACLE10_THIN: - - day = "to_char(" + pColumn + ", 'dd') "; - month = "to_char(" + pColumn + ", 'MM') "; - year = "to_char(" + pColumn + ", 'yyyy') "; - time = pWithTime == true ? " to_char(" + pColumn + ", ' hh24:mi:ss')" : ""; - break; - default: - str = "cast(" + pColumn + " as varchar (10))"; - return str; - break; - } - - var re = /(dd)|(MM)|(yyyy)/g // Regex to check the date - var matchResult; - var endOfLastMatch = 0; - var res = []; - - while ((matchResult = re.exec(pFormat)) !== null) - { - if( endOfLastMatch != matchResult.index) - { - res.push("'" + db.quote(pFormat.substring(endOfLastMatch, matchResult.index), pAlias) + "'"); // making sure we get the correct amount of quotations - } - switch(matchResult[0]) - { - case "dd": - res.push(day); - break; - case "MM": - res.push(month); - break; - case "yyyy": - res.push(year); - break; - } - endOfLastMatch = re.lastIndex; - } - // making sure we get the correct amount of quotations - // allows us to add custom strings behind the format which will be shown in the output - // e.g. "yyyy-MM-dd 00:00", "date: MM/dd/yyyy" - res.push("'" + db.quote(pFormat.slice(endOfLastMatch), pAlias) + "'"); - - if(time != "") - res.push(time); - - str = concat(res, "", pAlias); - - return str; - } - /** - * returns a SQL operator depending on an integer value, i.e. $local.operator - * - * @param {int} pVal - * - * @return {string} - */ - this.getSQLOperator = function(pVal) - { - var retval = ""; - switch(Number(pVal)) - { - case 1: - retval = "="; - break; //equals - case 2: - retval = "<>"; - break; //not equal - case 3: - retval = ">"; - break; //greater - case 4: - retval = "<"; - break; //lesser - case 5: - retval = "<="; - break; //lesser or equal - case 6: - retval = ">="; - break; //greater or equal - case 7: - retval = "like"; - break; //contains - case 8: - retval = "not like"; - break; //contains not - case 9: - retval = ""; - break; - case 10: - retval = ""; - break; - case 11: - retval = "is not null"; - break; - case 12: - retval = "is null"; - break; - } - return retval; - } - /** - * returns the function which determines the length of binary data, depending on db type - * - * @param {String} pField name of the checked field - * - * @return {String} - */ - this.binDataLength = function(pField) - { - var dbtype = db.getDatabaseType(vars.getString("$sys.dbalias")); - var length; - - switch(Number(dbtype)) - { - case db.DBTYPE_MARIADB10: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_POSTGRESQL8: - case db.DBTYPE_DERBY10: - length = "LENGTH("+pField+")"; - break; - case db.DBTYPE_SQLSERVER2000: - length = "DATALENGTH("+pField+")"; - break; - } - return length; - } - /** - * returns the function for replacing a null value - * - * @param {String} pValue req - * @param {String} pReplaceWith - * - * @return {string} - */ - this.isNull = function(pValue, pReplaceWith) - { - var pAlias = vars.getString("$sys.dbalias"); - - if(pReplaceWith == undefined) - pReplaceWith = 0; - - var pDatabaseType = db.getDatabaseType(pAlias); - - switch(Number(pDatabaseType)) - { - case db.DBTYPE_SQLSERVER2000: - str = "isnull("+ pValue +", " + pReplaceWith+ ")"; - break; - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_ORACLE10_THIN : - str = "NVL("+ pValue +", "+ pReplaceWith+ ")"; - break; - case db.DBTYPE_POSTGRESQL8: - case db.DBTYPE_DERBY10: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_MARIADB10: - default: - str = "COALESCE("+ pValue +", "+ pReplaceWith+ ")"; - break; - } - return str; - } - /** - * returns the concat symbol depending on database type - * - * @param {String} pAlias opt database alias - * - * @return {String} Concat Symbol - */ - this.getConcatSymbol = function(pAlias) - { - if(pAlias == undefined || pAlias == "") - pAlias = vars.getString("$sys.dbalias"); - - var dbtype = db.getDatabaseType(pAlias); - var concatSymbol = " "; - - switch(Number(dbtype)) - { - case db.DBTYPE_SQLSERVER2000: - concatSymbol = " + "; - break; - case db.DBTYPE_MARIADB10: - case db.DBTYPE_MYSQL4: - case db.DBTYPE_ORACLE10_CLUSTER: - case db.DBTYPE_ORACLE10_THIN: - case db.DBTYPE_ORACLE10_OCI: - case db.DBTYPE_POSTGRESQL8: - case db.DBTYPE_DERBY10: - default: - concatSymbol = " || "; - break; - } - - return concatSymbol; - } - /** - * Builds a SQL IN condition, while accounting for the 1000 elements maximum - * Single conditions are concatenated with OR, which can be devastating for performance! - * - * @param {String} pFieldname req name of the field with table alias - * z.B ORGREL.RELATIONID - * @param {String[]|String[][]} pData req Data as ID Array - * @param {String} pQuoteSymbol opt symbol for quoting values, - * Strings i.e.: ' default is no symbol - * - * @return {String} SQL condition: where VALS in (1,2,3) - */ - this.getSqlInStatement = function(pFieldname, pData, pQuoteSymbol) - { - if (pData.length == 0) - return " 1 = 2 "; - - var res = ""; - var qs = pQuoteSymbol || ""; - - var MAX_COUNT = 1000; - //pData.length -1 um für den Fall, dass MAX_COUNT == pData.length ist trotzdem nur einen Aufruf - //zu machen - var count = ((pData.length -1) / MAX_COUNT) >> 0;//aus kommazahl eine ganzzahl machen - //<= verwenden, da bei einer Länge von "126" der Vorgang einmal ausgeführt werden soll - for (var i = 0; i <= count; i++) - { - if (i > 0) - res += "or "; - - res += pFieldname + " in (" + qs + pData.slice(i * MAX_COUNT, i * MAX_COUNT + MAX_COUNT) - .join(qs + ", " + qs) + qs + ") "; - } - - //wenn mehrere Zeilen mit "or" verknüpft wurden nochmal klammern - if (count > 0) - res = "(" + res + ")"; - - return res; - } - /** - * Setzt eine Condition zusammen und liefert sie zurück - * builds a conditions and returns it - * - * @param {Object} pValue req Filtervalue - * @param {String} pCondition req variable in which the condition should be written - * @param {String} pWhere req additional condition - * @param {Integer} pSQLType opt SQLTYPES type of pValue - * @param {Array} pPreparedValues opt Value for the condition, if it's a prepared statement - * - * @return {String} - */ - this.makeCondition = function( pValue, pCondition, pWhere, pSQLType, pPreparedValues) - { - if ( pValue != "" ) - { - if ( pCondition != "" ) - pCondition += " and "; - - pCondition += pWhere; - - if(pPreparedValues != undefined) - { - pPreparedValues.push([pValue, pSQLType]); - } - } - return pCondition; - } - /** - * returns a type of column in the database - * - * @param {String} pTableName req name of a table (e.g. "EVENT") OR if pColumnName is not passed table.column (e.g. "EVENT.STATUS") - * @param {String} pColumnName opt name of column (e.g. "STATUS") if in pTableName only tablename is passed - * @param {String} pAlias opt Alias to the database where the type should be loaded; default is current alias - * - * @return {String} type of column such as SQLTYPES.xyz - */ - this.getSingleColumnType = function(pTableName, pColumnName, pAlias) - { - if (pColumnName == undefined) - { - pColumnName = pTableName.substring(pTableName.indexOf(".") + 1); - pTableName = pTableName.substring(0, pTableName.indexOf(".")); - } - if (pAlias == undefined) - pAlias = db.getCurrentAlias(); - - return db.getColumnTypes(pTableName, [pColumnName], pAlias)[0]; - } - /** - * calls a given function for N blocks of sql-data as long as records are available or the paging-process is manually canceled - * - * @param {Object|String} pSql req sql statement that shall be executed - * String: SQL-query in a simple text form - * Object: prepared-sql-query: [sqlStr, [[value1, type1], [valueN, typeN]]] - * @param {Number} pBlockSize req Amount of records that shall be read per block. (you need to specify an ORDER BY in your SQL-query) - * "0" <=> all records - * @param {Object (function)} pCallback req a callback-function that is called for every block and has the following params: - * myCallback(myDataBlockAs2Darray, myLoopCountThatStartsWith1) - * If "false" is returned sqlPageData will abort the paging process and return false - * @param {String} pDbAlias opt Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias - * @param {Number} pTimeout opt Timeout in milliseconds; When it's reached the SQL-Statement will abort; default is in PREFERENCES configured - * @param {Number} pStartOffset opt Position where to begin with the data-reading-process; default is 0 - * - * - * @return {bool} returns whether the function read all available data or not: - * false if the callback-function returned false, otherwise true - * - * @example - * var varValues = [];//you've got access to variables declared with 'var' - * let letValues = [];//you've got access to variables declared with 'let' - * var count = 0;//you cannot overwrite a variable of 'sqlPageData' by accident - * - * var sql = "select ORGNAME from ORG"; - * var blockSize = 5 * 1000; - * - * var allRows = +db.cell("select count(*) from ORG"); - * - * sqlPageData(sql, blockSize, function (pData, pRunNo){ - * var j = pData.length;//pData is the current block with data - * logging.log(pRunNo.toString() + "#" + j);//pRunNo is the amount how often the func. has been already called - * //you can calculate the progress easily by: progress = (blockSize* (pRunNo-1) + pData.length) / (allRows - startOffset) - * //example in per cent: - * var startOffset = 0;//we did not pass any startOffset to sqlPageData - this is equivalent to zero - * var progress = (blockSize* (pRunNo-1) + pData.length) / (allRows - startOffset); - * logging.log("progess: " + eMath.roundDec(progress * 100, 2, eMath.ROUND_CEILING) + "%"); - * - * for (var i = 0; i < j; i++) - * { - * varValues.push(pData[i][0]); - * letValues.push(pData[i][0]); - * } - * - * count += pRunNo * 100; - * logging.log("count:" + count);//you cannot overwrite a variable of 'sqlPageData' by accident - * }); - * - * logging.show(letValues);//contains orgnames - * logging.show(varValues);//contains orgnames - */ - this.sqlPageData = function(pSql, pBlockSize, pCallback, pDbAlias, pTimeout, pStartOffset) - { - if (pDbAlias == undefined) - pDbAlias = db.getCurrentAlias(); - - if (pStartOffset == undefined) - pStartOffset = 0; - - let count = 0; - while (pStartOffset > -1) - { - let data; - if (pTimeout == undefined) - data = db.tablePage(pSql, pDbAlias, pStartOffset, pBlockSize); - else - data = db.tablePage(pSql, pDbAlias, pStartOffset, pBlockSize, pTimeout); - - pStartOffset += pBlockSize; - - //this happens when all-records % pBlockSize == 0 - //we do not want to call the callback-fn - if (data.length == 0) - return true; - else if (data.length < pBlockSize || pBlockSize == 0)//blocksize 0 is everything - pStartOffset = -1;//call callback the last time - - if (pCallback.call(this, data, ++count) === false) - return false;//callback can return false to manually stop the paging-process - - } - return true; - } +import("system.translate"); +import("system.vars"); +import("system.db"); +import("system.datetime"); +import("system.tools"); +import("system.SQLTYPES"); +import("Util_lib") + +/** + * Object for easier handling of conditions; + * With this object you do not have to check if the string is empty or not; + * you don't need to append a "1=1" condition or similar; + * @example //TODO: add missing example + */ +function SqlCondition(){ + this._sqlStorage = ""; +} +/** + * append with SQL-and; no paranthesize of existing conditions is done + * @param {String} cond the condition string which shall be appended + * @return {Object} current SqlCondition-object + */ +SqlCondition.prototype.and = function(cond){ + if (!cond) + return this; + if (this._sqlStorage) + this._sqlStorage += " and "; + this._sqlStorage += cond; + return this; +} +/** + * append with SQL-or; Also paranthesize the existing conditions + * @param {String} cond the condition string which shall be appended + * @return {Object} current SqlCondition-object + */ +SqlCondition.prototype.or = function(cond){ + if (!cond) + return this; + if (this._sqlStorage) + this._sqlStorage = "(" + this._sqlStorage + ") or (" + cond + ")"; + else + this._sqlStorage = cond; + return this; +} +/** + * ready to use string; does not contain a where keyword at the beginning + * @param {String} alternativeCond condition that is returned when nothing has been appended + * @return {String} concatenated SQL-condition; empty string if nothing has been appended or - if passed - the alternativeCond + */ +SqlCondition.prototype.toString = function(alternativeCond){ + if (!this._sqlStorage && alternativeCond) + return alternativeCond + else + return this._sqlStorage; +} +/** + * ready to use string; does contain a where keyword at the beginning + * @param {String} alternativeCond condition that is returned when nothing has been appended + * @return {String} concatenated SQL-condition; empty string if nothing has been appended or - if passed - the alternativeCond + */ +SqlCondition.prototype.toWhereString = function(alternativeCond){ + var cond = this.toString(alternativeCond); + if (cond) + return " where " + cond; + else + return cond; +} + +function SqlMaskingUtils(){ + //TODO: use callbacks for different handling? + /** + * masks the function cast of standard sql + * + * @param {String} field name of the database field that shall be castet + * @param {String} [targetDatatype] a SQLTYPES-value of the following: SQLTYPES.CHAR, SQLTYPES.VARCHAR, SQLTYPES.INTEGER, + * SQLTYPES.DECIMAL, SQLTYPES.DATE + * @param {int|int[]} targetLength specifies the length of the target data type; + * <br/>- char/varchar: length + * <br/>- decimal: [length, decimals] + * @param {String} [alias=the current alias] the alias where the statement shall be executed (this is needed to determine the database-type) + * + * @return {String} sql part to be included in sql-statements + */ + this.cast = function (field, targetDatatype, targetLength, alias){ + /* Some informations if you want to add supported databaseTypes or dataTypes: + * You should consider using the _mapDefaults function-expression (details in the functions doc) + * However you shouldn't use the function in a "default"-Block of a switch-case because of the following behaviour: + * If a datatype is not supported you just have to NOT specify "sqlDataType" (leave it "undefined") -> an error is then raised + * Therefore you should explicitly define which Data-type is supported and which is not + */ + var dbType, functionName, sqlPart, sqlDataType, _mapDefaults; + if (alias == undefined) + alias = vars.getString("$sys.dbalias"); + dbType = db.getDatabaseType(alias); + functionName = "cast";//overwrite this in the "switch (dbType)" if needed with your DBMS + + /** + * handles default-scenarios for mapping input-targetDatatype to a string for a sql-statement + * e.g. SQLTYPES.INTEGER --> int + * @param {Number} dataType input as a value of "SQLTYPES." that will be mapped to a string + * @return {String} the mapped dataType for using in a sql-statement + */ + _mapDefaults = function (dataType){ + var res; + switch(dataType) + { + case SQLTYPES.CHAR: + res = "char"; + break; + case SQLTYPES.VARCHAR: + res = "char"; + break; + case SQLTYPES.INTEGER: + res = "int"; + break; + case SQLTYPES.DECIMAL: + res = "decimal"; + break; + case SQLTYPES.DATE: + res = "date"; + break; + } + return res; + } + switch (dbType) { + case db.DBTYPE_DERBY10: + switch(targetDatatype) { + case SQLTYPES.VARCHAR: + // Because of a Derby bug, you can't cast INTEGER into VARCHAR + // Therefor first cast to char then to varchar + // https://issues.apache.org/jira/browse/DERBY-2072 + field = "rtrim(" + cast(field, SQLTYPES.CHAR, targetLength, alias) + ")"; + sqlDataType = "varchar"; + break; + case SQLTYPES.CHAR: + //TODO: throw error if(targetLength > 254)? https://db.apache.org/derby/docs/10.14/ref/rrefsqlj13733.html + sqlDataType = "char"; + break; + case SQLTYPES.DECIMAL: + case SQLTYPES.INTEGER: + case SQLTYPES.DATE: + sqlDataType = _mapDefaults(dataType); + break; + } + break; + case db.DBTYPE_MARIADB10: + case db.DBTYPE_MYSQL4: + switch(targetDatatype) { + case SQLTYPES.VARCHAR: + case SQLTYPES.CHAR: + case SQLTYPES.INTEGER: + case SQLTYPES.DECIMAL: + case SQLTYPES.DATE: + sqlDataType = _mapDefaults(targetDatatype); + break; + } + break; + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + switch(pDatatype) + { + case SQLTYPES.VARCHAR: + datatype = "varchar2"; + break; + case SQLTYPES.INTEGER: + datatype = "number"; + targetLength = "10" + break; + case SQLTYPES.CHAR: + case SQLTYPES.DECIMAL: + case SQLTYPES.DATE: + sqlDataType = _mapDefaults(targetDatatype); + break; + } + break; + case db.DBTYPE_POSTGRESQL8: + switch(pDatatype) + { + case SQLTYPES.DATE: + case SQLTYPES.DECIMAL: + case SQLTYPES.INTEGER: + case SQLTYPES.CHAR: + case SQLTYPES.VARCHAR: + sqlDataType = _mapDefaults(targetDatatype); + break; + } + break; + case db.DBTYPE_SQLSERVER2000: + case SQLTYPES.DATE: + case SQLTYPES.DECIMAL: + case SQLTYPES.INTEGER: + case SQLTYPES.CHAR: + case SQLTYPES.VARCHAR: + sqlDataType = _mapDefaults(targetDatatype); + break; + case db.DBTYPE_FIREBIRD250: + //TODO: firebird support? + break; + } + + if (sqlDataType == undefined) { + throw new Error("sqlDataType");//TODO: add usefull message + } + + if(targetLength == undefined) + targetLength = ""; + else if(targetLength != "") + { + if(typeof(targetLength == "object") && (targetLength instanceof Array)) + targetLength = "(" + targetLength.join(", ") + ")"; + else + targetLength = "(" + targetLength + ")"; + } + + sqlPart = functionName + "(" + field + " as " + sqlDataType + targetLength + ")"; + return sqlPart; + } +} + +/** + *Class containing utilities for SQL + *@deprecated use SqlMaskingUtils + *@class + */ +function LegacySqlUtils() +{ + var that = this; + /** + * masks the cast function for lob datatypes(clob, blob) + * + * @param {String} pField req the data field + * @param {Integer|Interger[]} pLength req the length of the data + * decimal: [length, decimals] + * @param {String} pAlias req the database alias + * + * @return {String} (Teil einer SQL-Anweisung) + */ + this.castLob = function(pField, pLength, pAlias) + { + if(pAlias == undefined) + pAlias = vars.getString("$sys.dbalias"); + + var dbtype = db.getDatabaseType(pAlias); + + switch(Number(dbtype)) + { + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + return "DBMS_LOB.SUBSTR(" + pField + ", " + pLength + ", 1)"; + break; + default: + return cast(pField, "varchar", pLength, pAlias); + break; + } + } + /** + * masks the function substring. + * + * @param {String }pExpression req + * @param {Integer} pStart req index of the beginning + * @param {String} pAlias req database alias + * @param {Integer} pLength req + * + * @return {String} + */ + this.substring = function(pExpression, pStart, pLength, pAlias) + { + if(pLength == undefined) + pLength = 100; + if(pAlias == undefined) + pAlias = vars.getString("$sys.dbalias"); + + var dbtype = db.getDatabaseType(pAlias); + var string = ""; + + switch(Number(dbtype)) + { + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + string = "substr"; + break; + case db.DBTYPE_DERBY10: + string = "substr"; + break; + case db.DBTYPE_POSTGRESQL8: + string = "substr"; + break; + case db.DBTYPE_SQLSERVER2000: + string = "substring"; + break; + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + string = "substring"; + break; + } + + return string + "(" + pExpression + ", " + pStart + ", " + pLength + ")"; + } + + /** + * masks the function concat. + * + * @param {Array} pFields req fields that should be concatenated + * @param {String} pSeparator opt field separator + * @param {String} pAlias opt database alias + * + * @return {String} part of SQL-querey + */ + this.concat = function(pFields, pSeparator, pAlias) + { + var i; + if(pAlias == undefined || pAlias == "") + pAlias = vars.getString("$sys.dbalias"); + + var dbtype = db.getDatabaseType(pAlias); + var concat_string = " || "; + var retstr = ""; + var blank = "' '"; + + //it must be checked for empty string and null + var isNotEmpty = " != '' "; + var isNotNull = " is not null "; + if(pSeparator == undefined) + pSeparator = " "; + + switch(Number(dbtype)) + { + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + retstr = " concat_ws( '" + pSeparator + "'"; + for(i=0; i<pFields.length; i++) + { + retstr += ", " + pFields[i]; + } + return retstr + ") "; + break; + + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + blank = "trim(' ')"; + isNotEmpty = " is not null "; //needed for oracle + break; + + case db.DBTYPE_SQLSERVER2000: + concat_string = " + "; + break; + } + pSeparator = concat_string + "'" + pSeparator + "'"; + for(i = 0; i < pFields.length; i++) + { + if(retstr != "") + retstr += concat_string; + if ( i < pFields.length - 1 ) //Check if another value follows, if not separator is not needed + retstr += " case when " + pFields[i] + isNotEmpty + " then case when " + this.trimSql(pFields[i+1], pAlias) + isNotEmpty + " and " + + this.trimSql(pFields[i+1], pAlias) + isNotNull + " then " + pFields[i] + pSeparator + " else " + pFields[i] + " end" + " else " + blank + " end "; + else + retstr += " case when " + pFields[i] + isNotEmpty + " then " + pFields[i] + " else " + blank + " end "; + } + return retstr; + } + /** + * builds a condition out of multiple conditions + * + * @param {Array} pArray req Array containing the conditions + * @param {String} pOperator req Operator that concatenates the conditions (AND/OR) + * + * @return {String} concatenated Condition + */ + this.concatConditions = function(pArray, pOperator) + { + var resultCondition = ""; + + for(var i = 0; i < pArray.length; i++) + { + if(pArray[i] != null && pArray[i] != '') + { + if(resultCondition.length > 0) + resultCondition += (" " + pOperator + " "); + + resultCondition += pArray[i]; + } + } + + return resultCondition; + } + /** + * Checks if a new entry already exists + * + * @param {String} pTable req Databasetable(z.B. "comm") + * @param {Array} pColumns req colums, like sqlInsert + * @param {Array} pTypes req die datatypes, like sqlInsert + * @param {Array} pValues req values, like sqlInsert + * @param {Array} pExcludeFields opt columns, that should not be checked + * @param {String} pAlias opt Database alias + * + * @return {Integer} + */ + this.isDuplicat = function(pTable, pColumns, pTypes, pValues, pExcludeFields, pAlias) + { + var col = new Array(); + var typ = new Array(); + var val = new Array(); + var excludefields = ["DATE_NEW" ,"DATE_EDIT" ,"USER_NEW" ,"USER_EDIT", "KEYVALUE", "KEYSORT", pTable.toUpperCase() + "ID"]; + + if(pExcludeFields != undefined) + excludefields = excludefields.concat(pExcludeFields); + if(pAlias == undefined) + pAlias = vars.getString("$sys.dbalias"); + + for(var i = 0; i < pColumns.length; i++) + { + if(!hasElement(excludefields, pColumns[i], true) && pValues[i] != "" && pTypes[i] != SQLTYPES.LONGVARCHAR && pTypes[i] != SQLTYPES.CLOB) + { + col.push(pColumns[i]); + typ.push(pTypes[i]); + val.push(pValues[i]); + } + } + var count = db.getRowCount(pTable, col, typ, val, pAlias); + return count; + } + /** + * returns the trim function depending on the database + * + * @param {String} pField field the should be trimmed + * @param {String} pAlias opt database alias + * + * @return {String} + */ + this.trimSql = function(pField, pAlias) + { + if(pAlias == undefined || pAlias == "") + pAlias = vars.getString("$sys.dbalias"); + + var dbtype = db.getDatabaseType(pAlias); + var string; + + switch(Number(dbtype)) + { + case db.DBTYPE_SQLSERVER2000: + string = "ltrim(rtrim(" + pField + "))"; + break; + default: + string = "trim(" + pField + ")" + break; + } + return string; + } + /** + * returns the day of a date + * + * @param {Datetime} pDate req the date + * @param {String} pAlias req database alias + * + * @return {String} + */ + this.dayFromDate = function(pDate, pAlias) + { + var usedAlias = pAlias; + + if(pAlias == undefined) + usedAlias = vars.getString("$sys.dbalias"); + + var dbAlias = db.getDatabaseType(usedAlias); + var string = ""; + + switch(Number(dbAlias)) + { + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + string = "to_char(" + pDate + ",'dd')"; + break; + case db.DBTYPE_DERBY10: + case db.DBTYPE_SQLSERVER2000: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + string = "DAY(" + pDate + ")"; + break; + case db.DBTYPE_POSTGRESQL8: + string = "EXTRACT (DAY from " + pDate + ")"; + break; + } + return string; + } + /** + * returns the month of a date + * + * @param {Datetime} pDate req the date + * @param {String} pAlias req database alias + * + * @return {String} + */ + this.monthFromDate = function(pDate, pAlias) + { + var usedAlias = pAlias; + if(pAlias == undefined) + usedAlias = vars.getString("$sys.dbalias"); + + var dbAlias = db.getDatabaseType(usedAlias); + var string = ""; + + switch(Number(dbAlias)) + { + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + string = "to_char(" + pDate + ",'MM')"; + break; + case db.DBTYPE_DERBY10: + case db.DBTYPE_SQLSERVER2000: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + string = "MONTH(" + pDate + ")"; + break; + case db.DBTYPE_POSTGRESQL8: + string = "EXTRACT (MONTH FROM " + pDate + ")"; + break; + } + return string; + } + /** + * returns the year of a date + * + * @param {Datetime} pDate req the date + * @param {String} pAlias req database alias + * + * @return {String} + */ + this.yearFromDate = function(pDate, pAlias) + { + var usedAlias = pAlias; + if(pAlias == undefined) + usedAlias = vars.getString("$sys.dbalias"); + + var dbAlias = db.getDatabaseType(usedAlias); + var string = ""; + + switch(Number(dbAlias)) + { + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + string = "to_char(" + pDate + ",'yyyy')"; + break; + case db.DBTYPE_DERBY10: + case db.DBTYPE_SQLSERVER2000: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + string = "YEAR(" + pDate + ")"; + break; + case db.DBTYPE_POSTGRESQL8: + string = "EXTRACT (YEAR FROM " + pDate + ")"; + break; + } + return string; + } + /** + * returns the function for current date depending on database + * + * @return {String} expression + */ + this.currentDate = function() + { + var dbtype = db.getDatabaseType(vars.getString("$sys.dbalias")); + var expression = ""; + + switch (Number(dbtype)) + { + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_DERBY10: + expression = "CURRENT_DATE"; + break; + case db.DBTYPE_SQLSERVER2000: + expression = "GETDATE()"; + break; + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + expression = "NOW()"; + break; + } + return expression; + } + /** + * returns the current search string incl placeholders + * + * @param {String} pfield req the search field + * @param {String} pfind req the search string + * @param {String} pIgnoreCase opt (true/false) + * @param {String} pPlaceHolder opt (Platzhalter config) + * + * @return {String} + */ + this.getPlacerholderCondition = function( pfield, pfind, pIgnoreCase, pPlaceHolder ) + { + var user = tools.getCurrentUser(); + var IgCa; + var PlHo; + + //wenn optoinal IgnoreCase und PlaceHolder vorhanden, dann diese verwenden + if(pIgnoreCase != undefined) + IgCa = pIgnoreCase; + else + IgCa = user[tools.PARAMS][tools.SELECTION_IGNORECASE]; + + if(pPlaceHolder != undefined) + PlHo = pPlaceHolder; + else + PlHo = user[tools.PARAMS][tools.SELECTION_PLACEHOLDER]; + + if ( pfind ) + { + pfind = pfind.replace( new RegExp("\\'", "g"), "''"); + pfind = pfind.replace( new RegExp("\\*", "g"), "%"); + var ic = (IgCa == "true" ? "UPPER" : ""); + var cond = ""; + switch( PlHo ) + { + case "1": + cond = ic + "(" + pfield + ") like " + ic + "('" + pfind + "%')"; + break; + case "2": + cond = ic + "(" + pfield + ") like " + ic + "('%" + pfind + "')"; + break; + case "3": + cond = ic + "(" + pfield + ") like " + ic + "('%" + pfind + "%')"; + break; + case "4": + cond = ic + "(" + pfield + ") like " + ic + "('" + pfind + "')"; + break; + default: + cond = ic + "(" + pfield + ") = " + ic + "('" + pfind + "')"; + break; + } + } + return cond; + } + /** + * returns SQLSystax for a date. + * + * @param {String} pColumn req Column name + * @param {String} pAlias opt Database alias + * @param {Boolean} pWithTime opt if true, then add time hh:mm:ss + * @param {String} pFormat opt type of the format, e.g. yyyy-MM-dd; possible placeholers are: -dd -MM -yyyy + * + *@return {String} sqlstr, fully functional select for sql for different types of databases + */ + this.getSqlFormattedDate = function(pColumn, pAlias, pWithTime, pFormat) + { + if(pAlias == undefined) + pAlias = vars.getString("$sys.dbalias"); + + var pDatabaseType = db.getDatabaseType(pAlias); + + if (pFormat == undefined) + pFormat = translate.text("yyyy-MM-dd"); + + var str = ""; + + switch(Number(pDatabaseType)) + { + case db.DBTYPE_SQLSERVER2000: + day = "right('0' + cast(day(" + pColumn + ") as varchar(2)) , 2)"; + month = "right('0' + cast(month(" + pColumn + ") as varchar(2)) , 2)"; + year = "cast(year(" + pColumn + ") as char(4))"; + time = pWithTime == true? that.concat(["' '","cast(cast(" + pColumn + " as time) as char(8))"], "", pAlias) : ""; + break; + case db.DBTYPE_POSTGRESQL8: + day = "extract(day from " + pColumn + ")"; + month = "extract(month from " + pColumn + ")"; + year = "extract(year from " + pColumn + ")"; + time = pWithTime == true? that.concat(["' '","extract(time from" + pColumn + ")"], "", pAlias) : ""; + break; + case db.DBTYPE_DERBY10: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + // concat will try to have a leading blank space if the number is => 10. This is why we had to use substr. + day = that.substring(that.concat(["case when day(" + pColumn + ") <= 9 then '00' else '0' end " + , " trim(cast(day(" + pColumn + ") as char(2)))"], "", pAlias), 2, 2, pAlias); + month = that.substring(that.concat(["case when month(" + pColumn + ") <= 9 then '00' else '0' end " + , "trim(cast(month(" + pColumn + ") as char(2)))"], "", pAlias), 2, 2, pAlias); + year = "trim(cast(year(" + pColumn + ") as char(4)))"; + time = pWithTime == true? that.concat(["cast(' ' as char(1))", "trim(cast(time(" + pColumn + ") as char(8)))"], "", pAlias) : ""; + break; + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_ORACLE10_THIN: + + day = "to_char(" + pColumn + ", 'dd') "; + month = "to_char(" + pColumn + ", 'MM') "; + year = "to_char(" + pColumn + ", 'yyyy') "; + time = pWithTime == true ? " to_char(" + pColumn + ", ' hh24:mi:ss')" : ""; + break; + default: + str = "cast(" + pColumn + " as varchar (10))"; + return str; + break; + } + + var re = /(dd)|(MM)|(yyyy)/g // Regex to check the date + var matchResult; + var endOfLastMatch = 0; + var res = []; + + while ((matchResult = re.exec(pFormat)) !== null) + { + if( endOfLastMatch != matchResult.index) + { + res.push("'" + db.quote(pFormat.substring(endOfLastMatch, matchResult.index), pAlias) + "'"); // making sure we get the correct amount of quotations + } + switch(matchResult[0]) + { + case "dd": + res.push(day); + break; + case "MM": + res.push(month); + break; + case "yyyy": + res.push(year); + break; + } + endOfLastMatch = re.lastIndex; + } + // making sure we get the correct amount of quotations + // allows us to add custom strings behind the format which will be shown in the output + // e.g. "yyyy-MM-dd 00:00", "date: MM/dd/yyyy" + res.push("'" + db.quote(pFormat.slice(endOfLastMatch), pAlias) + "'"); + + if(time != "") + res.push(time); + + str = concat(res, "", pAlias); + + return str; + } + /** + * returns a SQL operator depending on an integer value, i.e. $local.operator + * + * @param {int} pVal + * + * @return {string} + */ + this.getSQLOperator = function(pVal) + { + var retval = ""; + switch(Number(pVal)) + { + case 1: + retval = "="; + break; //equals + case 2: + retval = "<>"; + break; //not equal + case 3: + retval = ">"; + break; //greater + case 4: + retval = "<"; + break; //lesser + case 5: + retval = "<="; + break; //lesser or equal + case 6: + retval = ">="; + break; //greater or equal + case 7: + retval = "like"; + break; //contains + case 8: + retval = "not like"; + break; //contains not + case 9: + retval = ""; + break; + case 10: + retval = ""; + break; + case 11: + retval = "is not null"; + break; + case 12: + retval = "is null"; + break; + } + return retval; + } + /** + * returns the function which determines the length of binary data, depending on db type + * + * @param {String} pField name of the checked field + * + * @return {String} + */ + this.binDataLength = function(pField) + { + var dbtype = db.getDatabaseType(vars.getString("$sys.dbalias")); + var length; + + switch(Number(dbtype)) + { + case db.DBTYPE_MARIADB10: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_POSTGRESQL8: + case db.DBTYPE_DERBY10: + length = "LENGTH("+pField+")"; + break; + case db.DBTYPE_SQLSERVER2000: + length = "DATALENGTH("+pField+")"; + break; + } + return length; + } + /** + * returns the function for replacing a null value + * + * @param {String} pValue req + * @param {String} pReplaceWith + * + * @return {string} + */ + this.isNull = function(pValue, pReplaceWith) + { + var pAlias = vars.getString("$sys.dbalias"); + + if(pReplaceWith == undefined) + pReplaceWith = 0; + + var pDatabaseType = db.getDatabaseType(pAlias); + + switch(Number(pDatabaseType)) + { + case db.DBTYPE_SQLSERVER2000: + str = "isnull("+ pValue +", " + pReplaceWith+ ")"; + break; + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_ORACLE10_THIN : + str = "NVL("+ pValue +", "+ pReplaceWith+ ")"; + break; + case db.DBTYPE_POSTGRESQL8: + case db.DBTYPE_DERBY10: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + default: + str = "COALESCE("+ pValue +", "+ pReplaceWith+ ")"; + break; + } + return str; + } + /** + * returns the concat symbol depending on database type + * + * @param {String} pAlias opt database alias + * + * @return {String} Concat Symbol + */ + this.getConcatSymbol = function(pAlias) + { + if(pAlias == undefined || pAlias == "") + pAlias = vars.getString("$sys.dbalias"); + + var dbtype = db.getDatabaseType(pAlias); + var concatSymbol = " "; + + switch(Number(dbtype)) + { + case db.DBTYPE_SQLSERVER2000: + concatSymbol = " + "; + break; + case db.DBTYPE_MARIADB10: + case db.DBTYPE_MYSQL4: + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_POSTGRESQL8: + case db.DBTYPE_DERBY10: + default: + concatSymbol = " || "; + break; + } + + return concatSymbol; + } + /** + * Builds a SQL IN condition, while accounting for the 1000 elements maximum + * Single conditions are concatenated with OR, which can be devastating for performance! + * + * @param {String} pFieldname req name of the field with table alias + * z.B ORGREL.RELATIONID + * @param {String[]|String[][]} pData req Data as ID Array + * @param {String} pQuoteSymbol opt symbol for quoting values, + * Strings i.e.: ' default is no symbol + * + * @return {String} SQL condition: where VALS in (1,2,3) + */ + this.getSqlInStatement = function(pFieldname, pData, pQuoteSymbol) + { + if (pData.length == 0) + return " 1 = 2 "; + + var res = ""; + var qs = pQuoteSymbol || ""; + + var MAX_COUNT = 1000; + //pData.length -1 um für den Fall, dass MAX_COUNT == pData.length ist trotzdem nur einen Aufruf + //zu machen + var count = ((pData.length -1) / MAX_COUNT) >> 0;//aus kommazahl eine ganzzahl machen + //<= verwenden, da bei einer Länge von "126" der Vorgang einmal ausgeführt werden soll + for (var i = 0; i <= count; i++) + { + if (i > 0) + res += "or "; + + res += pFieldname + " in (" + qs + pData.slice(i * MAX_COUNT, i * MAX_COUNT + MAX_COUNT) + .join(qs + ", " + qs) + qs + ") "; + } + + //wenn mehrere Zeilen mit "or" verknüpft wurden nochmal klammern + if (count > 0) + res = "(" + res + ")"; + + return res; + } + /** + * Setzt eine Condition zusammen und liefert sie zurück + * builds a conditions and returns it + * + * @param {Object} pValue req Filtervalue + * @param {String} pCondition req variable in which the condition should be written + * @param {String} pWhere req additional condition + * @param {Integer} pSQLType opt SQLTYPES type of pValue + * @param {Array} pPreparedValues opt Value for the condition, if it's a prepared statement + * + * @return {String} + */ + this.makeCondition = function( pValue, pCondition, pWhere, pSQLType, pPreparedValues) + { + if ( pValue != "" ) + { + if ( pCondition != "" ) + pCondition += " and "; + + pCondition += pWhere; + + if(pPreparedValues != undefined) + { + pPreparedValues.push([pValue, pSQLType]); + } + } + return pCondition; + } + /** + * returns a type of column in the database + * + * @param {String} pTableName req name of a table (e.g. "EVENT") OR if pColumnName is not passed table.column (e.g. "EVENT.STATUS") + * @param {String} pColumnName opt name of column (e.g. "STATUS") if in pTableName only tablename is passed + * @param {String} pAlias opt Alias to the database where the type should be loaded; default is current alias + * + * @return {String} type of column such as SQLTYPES.xyz + */ + this.getSingleColumnType = function(pTableName, pColumnName, pAlias) + { + if (pColumnName == undefined) + { + pColumnName = pTableName.substring(pTableName.indexOf(".") + 1); + pTableName = pTableName.substring(0, pTableName.indexOf(".")); + } + if (pAlias == undefined) + pAlias = db.getCurrentAlias(); + + return db.getColumnTypes(pTableName, [pColumnName], pAlias)[0]; + } + /** + * calls a given function for N blocks of sql-data as long as records are available or the paging-process is manually canceled + * + * @param {Object|String} pSql req sql statement that shall be executed + * String: SQL-query in a simple text form + * Object: prepared-sql-query: [sqlStr, [[value1, type1], [valueN, typeN]]] + * @param {Number} pBlockSize req Amount of records that shall be read per block. (you need to specify an ORDER BY in your SQL-query) + * "0" <=> all records + * @param {Object (function)} pCallback req a callback-function that is called for every block and has the following params: + * myCallback(myDataBlockAs2Darray, myLoopCountThatStartsWith1) + * If "false" is returned sqlPageData will abort the paging process and return false + * @param {String} pDbAlias opt Database-Aliasname, where the SQL-Statement shall be executed; default is the current dbalias + * @param {Number} pTimeout opt Timeout in milliseconds; When it's reached the SQL-Statement will abort; default is in PREFERENCES configured + * @param {Number} pStartOffset opt Position where to begin with the data-reading-process; default is 0 + * + * + * @return {bool} returns whether the function read all available data or not: + * false if the callback-function returned false, otherwise true + * + * @example + * var varValues = [];//you've got access to variables declared with 'var' + * let letValues = [];//you've got access to variables declared with 'let' + * var count = 0;//you cannot overwrite a variable of 'sqlPageData' by accident + * + * var sql = "select ORGNAME from ORG"; + * var blockSize = 5 * 1000; + * + * var allRows = +db.cell("select count(*) from ORG"); + * + * sqlPageData(sql, blockSize, function (pData, pRunNo){ + * var j = pData.length;//pData is the current block with data + * logging.log(pRunNo.toString() + "#" + j);//pRunNo is the amount how often the func. has been already called + * //you can calculate the progress easily by: progress = (blockSize* (pRunNo-1) + pData.length) / (allRows - startOffset) + * //example in per cent: + * var startOffset = 0;//we did not pass any startOffset to sqlPageData - this is equivalent to zero + * var progress = (blockSize* (pRunNo-1) + pData.length) / (allRows - startOffset); + * logging.log("progess: " + eMath.roundDec(progress * 100, 2, eMath.ROUND_CEILING) + "%"); + * + * for (var i = 0; i < j; i++) + * { + * varValues.push(pData[i][0]); + * letValues.push(pData[i][0]); + * } + * + * count += pRunNo * 100; + * logging.log("count:" + count);//you cannot overwrite a variable of 'sqlPageData' by accident + * }); + * + * logging.show(letValues);//contains orgnames + * logging.show(varValues);//contains orgnames + */ + this.sqlPageData = function(pSql, pBlockSize, pCallback, pDbAlias, pTimeout, pStartOffset) + { + if (pDbAlias == undefined) + pDbAlias = db.getCurrentAlias(); + + if (pStartOffset == undefined) + pStartOffset = 0; + + let count = 0; + while (pStartOffset > -1) + { + let data; + if (pTimeout == undefined) + data = db.tablePage(pSql, pDbAlias, pStartOffset, pBlockSize); + else + data = db.tablePage(pSql, pDbAlias, pStartOffset, pBlockSize, pTimeout); + + pStartOffset += pBlockSize; + + //this happens when all-records % pBlockSize == 0 + //we do not want to call the callback-fn + if (data.length == 0) + return true; + else if (data.length < pBlockSize || pBlockSize == 0)//blocksize 0 is everything + pStartOffset = -1;//call callback the last time + + if (pCallback.call(this, data, ++count) === false) + return false;//callback can return false to manually stop the paging-process + + } + return true; + } } \ No newline at end of file -- GitLab