diff --git a/.liquibase/Data_alias/basic/2019.2/DocuTemplatePlaceholder_Keywords.xml b/.liquibase/Data_alias/basic/2019.2/DocuTemplatePlaceholder_Keywords.xml deleted file mode 100644 index 6c892fd2a037f26d7eb31176d465b458b0ff241d..0000000000000000000000000000000000000000 --- a/.liquibase/Data_alias/basic/2019.2/DocuTemplatePlaceholder_Keywords.xml +++ /dev/null @@ -1,57 +0,0 @@ -<?xml version="1.1" encoding="UTF-8" standalone="no"?> -<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> - <changeSet author="s.listl" id="f236804e-e3f2-43e4-8e5a-1ba48522d8c5"> - <insert tableName="AB_KEYWORD_ENTRY"> - <column name="AB_KEYWORD_ENTRYID" value="bdecb990-19ce-4710-afd7-321ed5bae93d"/> - <column name="KEYID" value="letterSalutation"/> - <column name="TITLE" value="Letter salutation"/> - <column name="CONTAINER" value="TextPlaceholder"/> - <column name="SORTING" valueNumeric="0"/> - <column name="ISACTIVE" valueNumeric="1"/> - <column name="ISESSENTIAL" valueNumeric="1"/> - </insert> - <insert tableName="AB_KEYWORD_ENTRY"> - <column name="AB_KEYWORD_ENTRYID" value="5f31c2cd-dce9-4eeb-872c-1a3005ea3210"/> - <column name="KEYID" value="country"/> - <column name="TITLE" value="Country"/> - <column name="CONTAINER" value="TextPlaceholder"/> - <column name="SORTING" valueNumeric="1"/> - <column name="ISACTIVE" valueNumeric="1"/> - <column name="ISESSENTIAL" valueNumeric="1"/> - </insert> - <insert tableName="AB_KEYWORD_ENTRY"> - <column name="AB_KEYWORD_ENTRYID" value="fd9dba2b-92aa-4957-841b-4ec85dc92817"/> - <column name="KEYID" value="zipCode"/> - <column name="TITLE" value="ZIP"/> - <column name="CONTAINER" value="TextPlaceholder"/> - <column name="SORTING" valueNumeric="2"/> - <column name="ISACTIVE" valueNumeric="1"/> - <column name="ISESSENTIAL" valueNumeric="1"/> - </insert> - <insert tableName="AB_KEYWORD_ATTRIBUTE"> - <column name="AB_KEYWORD_ATTRIBUTEID" value="ebf7de02-1873-4068-b551-c5348bab4fc6"/> - <column name="NAME" value="addressFormat"/> - <column name="CONTAINER" value="TextPlaceholder"/> - <column name="TYPE" value="CHAR_VALUE"/> - </insert> - <insert tableName="AB_KEYWORD_ATTRIBUTERELATION"> - <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="4cd39532-0cd1-4828-961d-76165af2f4c3"/> - <column name="AB_KEYWORD_ENTRY_ID" value="bdecb990-19ce-4710-afd7-321ed5bae93d"/> - <column name="AB_KEYWORD_ATTRIBUTE_ID" value="ebf7de02-1873-4068-b551-c5348bab4fc6"/> - <column name="CHAR_VALUE" value=""/> - </insert> - <insert tableName="AB_KEYWORD_ATTRIBUTERELATION"> - <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="dd5279a9-920e-4ed3-9438-56fac9c68f31"/> - <column name="AB_KEYWORD_ENTRY_ID" value="5f31c2cd-dce9-4eeb-872c-1a3005ea3210"/> - <column name="AB_KEYWORD_ATTRIBUTE_ID" value="ebf7de02-1873-4068-b551-c5348bab4fc6"/> - <column name="CHAR_VALUE" value="{cc}"/> - </insert> - <insert tableName="AB_KEYWORD_ATTRIBUTERELATION"> - <column name="AB_KEYWORD_ATTRIBUTERELATIONID" value="54b34ffe-178e-410b-a32e-3519ebf5f550"/> - <column name="AB_KEYWORD_ENTRY_ID" value="fd9dba2b-92aa-4957-841b-4ec85dc92817"/> - <column name="AB_KEYWORD_ATTRIBUTE_ID" value="ebf7de02-1873-4068-b551-c5348bab4fc6"/> - <column name="CHAR_VALUE" value="{zc}"/> - </insert> - </changeSet> -</databaseChangeLog> diff --git a/entity/DocumentTemplate_entity/DocumentTemplate_entity.aod b/entity/DocumentTemplate_entity/DocumentTemplate_entity.aod index af59e8becbcb490ed5a03719311864ac5dff567d..d98456c702c6d1ea45f80b19dfc4dda4d0232055 100644 --- a/entity/DocumentTemplate_entity/DocumentTemplate_entity.aod +++ b/entity/DocumentTemplate_entity/DocumentTemplate_entity.aod @@ -14,7 +14,7 @@ <entityDependency> <name>5cc2e566-309c-4b47-84f3-52376e919b9b</name> <entityName>Email_entity</entityName> - <fieldName>DocumnetTemplates</fieldName> + <fieldName>DocumentTemplates</fieldName> <isConsumer v="false" /> </entityDependency> </dependencies> @@ -233,6 +233,12 @@ <fieldName>DocumentTemplateTexFooter</fieldName> <isConsumer v="false" /> </entityDependency> + <entityDependency> + <name>57f408e3-aeb7-4006-a20d-287dae1f0922</name> + <entityName>Mail_entity</entityName> + <fieldName>DocumentTemplates</fieldName> + <isConsumer v="false" /> + </entityDependency> </dependencies> </entityProvider> <entityParameter> diff --git a/entity/Email_entity/Email_entity.aod b/entity/Email_entity/Email_entity.aod index d681318619470d0f1dc818a390f69ce2c57dbe85..8a3f7dba803446aae2139a84d61f7ea50b86f3cf 100644 --- a/entity/Email_entity/Email_entity.aod +++ b/entity/Email_entity/Email_entity.aod @@ -13,11 +13,11 @@ <entityField> <name>DOCUMENT_TEMPLATE</name> <title>Document Template</title> - <consumer>DocumnetTemplates</consumer> + <consumer>DocumentTemplates</consumer> <linkedContext>DocumentTemplate</linkedContext> </entityField> <entityConsumer> - <name>DocumnetTemplates</name> + <name>DocumentTemplates</name> <dependency> <name>dependency</name> <entityName>DocumentTemplate_entity</entityName> diff --git a/entity/Email_entity/recordcontainers/jdito/onInsert.js b/entity/Email_entity/recordcontainers/jdito/onInsert.js index f838dfce9ecf292a6fa77e741074e5cd60beae8f..857bf055dd9ef564ac8a107327423919f10b0bcc 100644 --- a/entity/Email_entity/recordcontainers/jdito/onInsert.js +++ b/entity/Email_entity/recordcontainers/jdito/onInsert.js @@ -2,4 +2,4 @@ import("Employee_lib"); import("system.vars"); import("Email_lib"); -EmailUtils.openMailTemplate(vars.get("$field.RECIPIENT"), EmployeeUtils.getCurrentContactId(), vars.get("$field.DOCUMENT_TEMPLATE")); \ No newline at end of file +EmailUtils.openMailTemplate(vars.get("$field.RECIPIENT"), EmployeeUtils.getCurrentContactId(), vars.get("$field.DOCUMENT_TEMPLATE"), vars.get("$param.ContactId_param")); \ No newline at end of file diff --git a/entity/Mail_entity/Mail_entity.aod b/entity/Mail_entity/Mail_entity.aod new file mode 100644 index 0000000000000000000000000000000000000000..b986ba28239d31687deb82cbac971b52f7c13cd4 --- /dev/null +++ b/entity/Mail_entity/Mail_entity.aod @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.6" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.6"> + <name>Mail_entity</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <recordContainer>jdito</recordContainer> + <entityFields> + <entityProvider> + <name>#PROVIDER</name> + </entityProvider> + <entityField> + <name>UID</name> + </entityField> + <entityField> + <name>DOCUMENT_TEMPLATE</name> + <consumer>DocumentTemplates</consumer> + <linkedContext>DocumentTemplate</linkedContext> + </entityField> + <entityConsumer> + <name>DocumentTemplates</name> + <dependency> + <name>dependency</name> + <entityName>DocumentTemplate_entity</entityName> + <fieldName>DocumentTemplateProvider</fieldName> + </dependency> + </entityConsumer> + </entityFields> + <recordContainers> + <jDitoRecordContainer> + <name>jdito</name> + <jDitoRecordAlias>Data_alias</jDitoRecordAlias> + <recordFields> + <element>UID.value</element> + </recordFields> + </jDitoRecordContainer> + </recordContainers> +</entity> diff --git a/neonContext/Mail/Mail.aod b/neonContext/Mail/Mail.aod new file mode 100644 index 0000000000000000000000000000000000000000..6c1b4c798c638d24c8953b7635eea0c4b2fa1dee --- /dev/null +++ b/neonContext/Mail/Mail.aod @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonContext xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonContext/1.1.0"> + <name>Mail</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <entity>Mail_entity</entity> +</neonContext> diff --git a/process/Address_lib/process.js b/process/Address_lib/process.js index 2b4406c8124819a4ec41bf95302450c8de6de8c4..5f543024e9ef8cd4876ac36491278caf4ef55070 100644 --- a/process/Address_lib/process.js +++ b/process/Address_lib/process.js @@ -1,473 +1,474 @@ -import("system.swing"); -import("system.text"); -import("system.db"); -import("system.logging"); -import("system.vars"); -import("system.translate"); -import("Attribute_lib"); -import("Sql_lib"); -import("Util_lib"); - -/* -* Creates a Address Object -* -* @param {String} pRelationID req relationid for which address should be retrieved -* @param {String} pAddressID opt addressid for which address should be retrieved -* @param {boolean} pPerson whether the address is from a person, not an organisation -* -* @return {String} the formatted address -*/ - -function AddrObject( pRelationID, pPerson, pAddressID ) -{ - this.Data = fetchAddressData( [ pRelationID ] , [["", "addressformat", ""]], pAddressID, pPerson ); - this.fmt = this.Data[0][0][26]; - - /* - * creates a formatted address - * - * @param {boolean} pCountry whether the country should be displayed - * @param {String} pFormat a fixed format for the address - * - * @return {String} formatted address - */ - this.getFormattedAddress = function( pCountry, pFormat ) - { - return _formatAddrData( _getAddrData( this.Data[0][0] ), pFormat, pCountry ); - } -} - -/* -* creates address data -* -* @param {String} pCondition req SQL-Where-Condition -* @param {String [[]]} pConfig req ( name, functionality, details ) -* @param {String} pSenderID opt UserRelationID -* @param {String} pAddressID opt addressid -* -* @return {[]} Daten -*/ -function getAddressesData( pCondition, pConfig, pSenderID, pAddressID ) -{ - var returndata = []; - var senderconfig = []; - var employeeconfig = []; - var config = []; - for ( var i = 0; i < pConfig.length; i++ ) - { - var type = pConfig[i][1].split("."); - switch( type[0] ) - { - case "employee": - employeeconfig.push([pConfig[i][0], type[1], pConfig[i][2]]); - break; - case "sender": - senderconfig.push([pConfig[i][0], type[1], pConfig[i][2]]); - break; - default: - config.push(pConfig[i]); - break; - } - } - var data = getAddressData( pCondition, config, pAddressID ); - if ( pSenderID == undefined ) pSenderID = vars.get("$global.user").relationid; - if ( senderconfig.length > 0 ) - var senderdata = getAddressData( [ pSenderID ], senderconfig ); - if ( employeeconfig.length > 0 ) - var employeedata = getAddressData( [ vars.get("$global.user").relationid ], employeeconfig ); - if ( data.length > 0 && ( senderconfig.length > 0 || employeeconfig.length > 0 ) ) - { - var ze = data[0]; - if ( employeeconfig.length > 0 ) ze = ze.concat( employeedata[0] ); - if ( senderconfig.length > 0 ) ze = ze.concat( senderdata[0] ); - returndata.push(ze); - for ( i = 1; i < data.length; i++ ) - { - ze = data[i]; - if ( employeeconfig.length > 0 ) ze = ze.concat( employeedata[1] ); - if ( senderconfig.length > 0 ) ze = ze.concat( senderdata[1] ); - returndata.push(ze); - } - return returndata; - } - else return data; -} - -/* -* creates -* -* @param {String} pCondition req SQL-Where-Condition -* @param {String [[]]} pConfig req ( name, functionality, details ) -* @param {String} AddressID opt addressid -* -* @return {[]} Daten -*/ -function getAddressData( pCondition, pConfig, AddressID ) -{ - return setAddressData( fetchAddressData( pCondition, pConfig, AddressID ) ); -} - -/* -* reads data from the database -* -* @param {String} pCondition req SQL-Where-Condition -* @param {String [[]]} pConfig req ( name, functionality, details ) -* @param {String} AddressID opt addressid -* @param {boolean} pPerson opt if private person -* -* @return {[]} data -*/ -function fetchAddressData( pCondition, pConfig, AddressID, pPerson ) -{ - if ( typeof(pCondition) == "object") pCondition = "CONTACT.CONTACTID in ('" + pCondition.join("','") + "')"; - if ( pConfig.length > 0 ) - { - var header = []; - var fields = []; - var output = []; - var pos = 0; - var posaddrfields = -1; - var functionCalls = []; - var addrfields = ["case when CONTACT.PERSON_ID is null then 1 else case when " + SqlMaskingUtils.prototype.trim("CONTACT.ORGANISATION_ID") + " = '0' then 2 else 3 end end", //0 - "ADDRESS.ADDRESS", "ADDRESS.BUILDINGNO", "ADDRESS.ZIP", "ADDRESS.CITY", "ADDRESS.COUNTRY", "ADDRESS.ADDRESSADDITION", // 1-6 - "ADDRESS.ADDRIDENTIFIER", "ADDRESS.DISTRICT", "ADDRESS.REGION", "ADDRESS.STATE", "CONTACT.DEPARTMENT", "CONTACT.CONTACTROLE", // 7-12 - "CONTACT.POSITION", "CONTACT.LETTERSALUTATION", "ORGANISATION.NAME", "PERSON.FIRSTNAME", "PERSON.MIDDLENAME", "PERSON.LASTNAME", // 13-18 - "PERSON.SALUTATION", "PERSON.TITLE", "PERSON.TITLESUFFIX", // 19-21 - "coalesce( CONTACT.LANGUAGE, (select C.LANGUAGE from CONTACT C where C.ORGANISATION_ID = CONTACT.ORGANISATION_ID and PERSON_ID is null))", // 22 - "''", "''", "''", "(select ADDR_FORMAT from AB_COUNTRYINFO where ISO2 = ADDRESS.COUNTRY)", "ADDRESS.ADDR_TYPE"]; // 23-27 - - for (var i=0; i < pConfig.length; i++ ) - { - switch( pConfig[i][1] ) - { - case "fieldname": // database fields - fields.push( pConfig[i][2] ); - output.push([pos++, pConfig[i][1]]); - header.push( pConfig[i][0] ); - break; - case "function": // adito SQL functions - fields.push( evalScript("Address_lib.fetchAddressData", vars.resolveVariables(pConfig[i][2]), {}, ["Attribute_lib", "Sql_lib", "Keyword_lib", "Person_lib"], true) ); - output.push([pos++, pConfig[i][1]]); - header.push( pConfig[i][0] ); - break; - case "afunction": // adito functions - try - { - fields.push( "'" + evalScript("Address_lib.fetchAddressData", vars.resolveVariables(pConfig[i][2]), {}, ["Attribute_lib", "Sql_lib", "Keyword_lib", "Person_lib"], true).replace(new RegExp("'","g"), "''") + "'" ); - output.push([pos++, pConfig[i][1]]); - header.push( pConfig[i][0] ); - } - catch( err ) - { - logging.log( err ) - } - break; - case "select": // Subselects - fields.push( "(" + vars.resolveVariables(pConfig[i][2]) + " )" ); - output.push([pos++, pConfig[i][1]]); - header.push( pConfig[i][0] ); - break; - case "addressformat": // Addressformat - if ( posaddrfields == -1 ) - { - var sortfields = ["ORGANISATION.NAME", "PERSON.LASTNAME"]; - fields.push( addrfields.join(", ") ); - posaddrfields = pos; - pos += addrfields.length; - } - output.push([posaddrfields, pConfig[i][1], pConfig[i][2]]); - header.push( pConfig[i][0] ); - break; - case "resolveIDFunction": - var configJSON = pConfig[i][2]; - fields.push( configJSON.rowIDField ); - - functionCalls.push([pos, - configJSON.resolveFunction, - configJSON.imports, - configJSON.localVars]); - - output.push([pos++, pConfig[i][1]]); - header.push( pConfig[i][0] ); - break; - } - } - if (!pPerson) { - var sqlstr = "select " + fields.join(",") - + " from CONTACT join ORGANISATION on CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID " - + " left join PERSON on CONTACT.PERSON_ID = PERSON.PERSONID " - + " left join ADDRESS on CONTACT.ADDRESS_ID = "; - } else { - - sqlstr = "select " + fields.join(",") - + " from CONTACT join PERSON on CONTACT.PERSON_ID = PERSON.PERSONID " - + " left join ORGANISATION on CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID " - + " left join ADDRESS on CONTACT.ADDRESS_ID = "; - } - - if ( AddressID != undefined && AddressID != "" ) sqlstr += "'" + AddressID + "'"; - else sqlstr += "ADDRESS.ADDRESSID"; - if ( pCondition != "" ) sqlstr += " where " + pCondition; - var data = db.table(sqlstr + (sortfields != undefined ? " order by " + sortfields.join(", ") : "" )); - - // loop over all returned datasets - for( var j = 0; j < data.length; j++) - { - // loop over all possible resolveFunction entries - for( var k = 0; k < functionCalls.length; k++ ) - { - // get the local variables, which should be present in the function call - var localVars = functionCalls[k][3]; - // add the row id value to the localVars Object so the funtion can gather the data for this dataset - localVars.rowIDValue = data[j][ functionCalls[k][0] ]; - // replace the row id with its base64 string - data[j][ functionCalls[k][0] ] = evalScript("Address_lib.fetchAddressData.resolveFunction", - vars.resolveVariables( functionCalls[k][1]+"()" ), - localVars, - functionCalls[k][2], // imports - true); - } - } - - if ( data.length == 0 ) - { - logging.log("Address_lib: " + pCondition, logging.ERROR); - data = [[]]; - for ( i = 0; i < addrfields.length + fields.length; i++ ) data[0].push("Err."); - } - data = [ data, output, header, addrfields ]; - } - return data; -} - -/* -* reads data from the database -* -* @param {String [[]]} pData req array of data -* -* @return {String [[]]} data -*/ -function setAddressData( pData ) -{ - var sqlresult = pData[0]; - var data = []; - if ( sqlresult.length > 0 ) - { - var output = pData[1]; - var header = pData[2]; - var addrfields = pData[3]; - data.push( header ); - for ( var i = 0; i < sqlresult.length; i++ ) - { - var addrdata = []; - var row = []; - for ( var z = 0; z < header.length; z++ ) - { - switch( output[z][1] ) - { - case "fieldname": - case "function": - case "afunction": - case "resolveIDFunction": - case "select": - row[z] = sqlresult[i][output[z][0]]; - break; - case "addressformat": - if (addrdata.length == 0) addrdata = _getAddrData( sqlresult[i].slice(output[z][0], output[z][0] + addrfields.length) ); - row[z] = _formatAddrData( addrdata, output[z][2] ); - break; - } - } - data.push( row ); - } - } - return data; -} -/* -* -* returns formatted address data -* -* @param {String [[]]} pData req data -* -* @return {String [[]]} formatted data -*/ -function _getAddrData( pData ) -{ - var lettersalutation = pData[14]; - var salutation = pData[19]; - var sformat = ""; - switch( Number(pData[0]) ) - { - case 1: - if ( lettersalutation == "" ) - { - sformat = _getSalutation( pData[22] ); - if ( sformat != undefined && sformat[1] != "" ) lettersalutation = _formatAddrData( pData, sformat[1] ); - else lettersalutation = "Sehr geehrte Damen und Herren"; - } - break; - case 2: - // private -> orgname deleted - pData[15] = ""; - case 3: - sformat = _getSalutation( pData[22] + pData[19] + pData[20] ); - //no language defined - if ( sformat == undefined ) sformat = _getSalutation( pData[19] + pData[20] ); - // no language specific entry in salutation - if ( sformat == undefined || sformat[0] == "" || sformat[1] == "" ) sformat = ["{sa} {ti} {fn} {la}", "{sa} {ti} {ln}"]; - salutation = _formatAddrData( pData, sformat[0] ); - // lettersalutation if none existent yet - if( lettersalutation == "" ) lettersalutation = _formatAddrData( pData, sformat[1] ); - } - - pData[23] = salutation; - pData[24] = lettersalutation; - pData[25] = _getCountryName(pData[5]); - return pData; -} - -/* -* returns a formatted salutation -* -* @param {String} pSalutCode req salutation code -* -* @return {String} translated salutation -*/ -function _getSalutation( pSalutCode ) -{ - var salut = new Object(); - if (vars.exists("$global.Salutation")) { - salut = vars.get("$global.Salutation"); - } - else - { - var list = db.table("select LANGUAGE, SALUTATION, TITLE, HEADLINE, LETTERSALUTATION from SALUTATION" ); - for ( var i = 0; i < list.length; i++ ) - { - salut[list[i][0] + list[i][1] + list[i][2]] = [list[i][3], list[i][4]]; - salut[list[i][1] + list[i][2]] = [list[i][3], list[i][4]]; - } - vars.set("$global.Salutation", salut); - } - return salut[pSalutCode]; -} - -/* -* returns country names -* -* @param {String} pCountryCode req countrycode -* -* @return {String} translated countryname -*/ -function _getCountryName(pCountryCode) -{ - var countryname = new Object(); - if ( vars.exists("$global.CountryName")) countryname = vars.get("$global.CountryName"); - else - { - var list = db.table("select ISO2, NAME_NATIVE from AB_COUNTRYINFO" ); - for (var i=0; i < list.length; i++ ) countryname[list[i][0]] = translate.text(list[i][1]); - vars.set("$global.CountryName", countryname); - } - return countryname[pCountryCode]; -} - -/* -* returns a formatted address -* -* @param {String [[]]} pAddrData req Address data -* @param {String} pFormat opt given format -* @param {boolean} pCountry if the country should be displayed -* -* @return {String} formatted address -*/ -function _formatAddrData( pAddrData, pFormat, pCountry ) -{ - var placeholerInfo = { - "street": {dataPosition: 1}, - "buildingno": {dataPosition: 2}, - "zip": {dataPosition: 3}, - "city": {dataPosition: 4}, - "district": {dataPosition: 8}, - "region": {dataPosition: 9}, - "state": {dataPosition: 10}, - "firstname": {dataPosition: 16}, - "middlename": {dataPosition: 17}, - "lastname": {dataPosition: 18}, - "saluation": {dataPosition: 19}, - "title": {dataPosition: 20}, - "suffix": {dataPosition: 21}, - "country": {dataPosition: 25}, - "organisation name": {dataPosition: 15}, - "salutation_name": {dataPosition: 23}, - "letter salutation": {dataPosition: 24} - }; - - var format = pFormat || pAddrData[26]; - format = _mapFormatPlaceholderTitles(format, pAddrData, pCountry); - - var res = format; - for (var placeholder in placeholerInfo) - { - var currentAddrData = pAddrData[placeholerInfo[placeholder].dataPosition]; - if (currentAddrData != undefined) - { - res = res.replace(new RegExp("{" + placeholder + "}", "g"), currentAddrData); - res = res.replace(new RegExp("{" + placeholder.toUpperCase() + "}", "g"), currentAddrData.toUpperCase()); - } - } - - res = res.replace(/^\n/, ""); // CR am Anfang entfernen; - res = res.replace(/ /g, " "); // doppelte leerzeichen entfernen - res = res.replace(/\\n/ig, "\n"); // newline marker ersetzen - res = res.replace(/ *\n */g, "\n");// leerzeichen am ende und Anfang entfernen - res = res.replace(/\s(?=\s)/g, ""); // leerzeilen rauswerfen - return res; -} - -/* -* returns the new format -* -* @param {String [[]]} pAddrData req Daten -* @param {String} pFormat req the format string -* @param {boolean} pCountry if the country should be displayed -* -* @return {String} new formate -* -N – Name - salutation -O – Organisation - orgname -A – Street Address Line(s) - address + buildingno -D – Dependent locality - district / region -C – City or Locality - city -S – Administrative area - state -Z – Zip or postal code - zip -X – Sorting code - not available -*/ -function _mapFormatPlaceholderTitles(pFormat, pAddrData, pCountry) -{ - //gstatic-paceholders - pFormat = pFormat.replace(new RegExp("%N", "g"), "{salutation_name}"); - pFormat = pFormat.replace(new RegExp("%A", "g"), "{address_street buildingno}"); - pFormat = pFormat.replace(new RegExp("%C", "g"), "{city}"); - pFormat = pFormat.replace(new RegExp("%S", "g"), "{state}"); - pFormat = pFormat.replace(new RegExp("%Z", "g"), "{zip}"); - pFormat = pFormat.replace(new RegExp("%O", "g"), "{organisation_name}"); - pFormat = pFormat.replace(new RegExp("%X", "g"), ""); - pFormat = pFormat.replace(new RegExp("%n", "g"), "\n"); - - //shortform adito-placeholders - pFormat = pFormat.replace(new RegExp("{fn}", "g"), "{firstname}"); - pFormat = pFormat.replace(new RegExp("{ln}", "g"), "{lpFormattname}"); - pFormat = pFormat.replace(new RegExp("{ti}", "g"), "{title}"); - pFormat = pFormat.replace(new RegExp("{sa}", "g"), "{salutation}"); - - if (pAddrData[8] == pAddrData[9]) - pFormat = pFormat.replace(new RegExp("%D", "g"), "{district}"); - else - pFormat = pFormat.replace(new RegExp("%D", "g"), "{district} \n {region}"); - - if(pCountry == undefined || pCountry == null || pCountry == true) - pFormat = pFormat + "\n {country}"; - - return pFormat; +import("system.swing"); +import("system.text"); +import("system.db"); +import("system.logging"); +import("system.vars"); +import("system.translate"); +import("Attribute_lib"); +import("Sql_lib"); +import("Util_lib"); +import("DocumentTemplate_lib"); + +/* +* Creates a Address Object +* +* @param {String} pRelationID req relationid for which address should be retrieved +* @param {String} pAddressID opt addressid for which address should be retrieved +* @param {boolean} pPerson whether the address is from a person, not an organisation +* +* @return {String} the formatted address +*/ + +function AddrObject( pRelationID, pPerson, pAddressID ) +{ + this.Data = fetchAddressData( [ pRelationID ] , [["", "addressformat", ""]], pAddressID, pPerson ); + this.fmt = this.Data[0][0][26]; + + /* + * creates a formatted address + * + * @param {boolean} pCountry whether the country should be displayed + * @param {String} pFormat a fixed format for the address + * + * @return {String} formatted address + */ + this.getFormattedAddress = function( pCountry, pFormat ) + { + return _formatAddrData( _getAddrData( this.Data[0][0] ), pFormat, pCountry ); + } +} + +/* +* creates address data +* +* @param {String} pCondition req SQL-Where-Condition +* @param {Object []} pConfig req ( name, functionality, details ) +* @param {String} pSenderID opt UserRelationID +* @param {String} pAddressID opt addressid +* +* @return {[]} Daten +*/ +function getAddressesData( pCondition, pConfig, pSenderID, pAddressID ) +{ + var returndata = []; + var senderconfig = []; + var employeeconfig = []; + var config = []; + for (let i = 0; i < pConfig.length; i++) + { + switch (pConfig[i].target) + { + case PlaceholderUtils.targets.EMPLOYEE: + employeeconfig.push(pConfig[i]); + break; + case PlaceholderUtils.targets.SENDER: + senderconfig.push(pConfig[i]); + break; + case PlaceholderUtils.targets.RECIPIENT: + default: + config.push(pConfig[i]); + break; + } + } + var data = getAddressData(pCondition, config, pAddressID); + if (pSenderID == undefined) pSenderID = vars.get("$global.user").relationid; + if (senderconfig.length > 0) + var senderdata = getAddressData([pSenderID], senderconfig); + if (employeeconfig.length > 0) + var employeedata = getAddressData([vars.get("$global.user").relationid], employeeconfig); + if (data.length > 0 && (senderconfig.length > 0 || employeeconfig.length > 0)) + { + var ze = data[0]; + if (employeeconfig.length > 0) ze = ze.concat(employeedata[0]); + if (senderconfig.length > 0) ze = ze.concat(senderdata[0]); + returndata.push(ze); + for (let i = 1; i < data.length; i++) + { + ze = data[i]; + if (employeeconfig.length > 0) ze = ze.concat(employeedata[1]); + if (senderconfig.length > 0) ze = ze.concat(senderdata[1]); + returndata.push(ze); + } + return returndata; + } + else return data; +} + +/* +* creates +* +* @param {String} pCondition req SQL-Where-Condition +* @param {Placeholder[]} pConfig req array of placeholders +* @param {String} AddressID opt addressid +* +* @return {[]} Daten +*/ +function getAddressData( pCondition, pConfig, AddressID ) +{ + return setAddressData( fetchAddressData( pCondition, pConfig, AddressID ) ); +} + +/* +* reads data from the database +* +* @param {String} pCondition req SQL-Where-Condition +* @param {Placeholder[]} pConfig req array of placeholders +* @param {String} AddressID opt addressid +* @param {boolean} pPerson opt if private person +* +* @return {Array} 2d-Array, structure: [[ data, output, header, addrfields ]] +*/ +function fetchAddressData( pCondition, pConfig, AddressID, pPerson ) +{ + if ( typeof(pCondition) == "object") pCondition = "CONTACT.CONTACTID in ('" + pCondition.join("','") + "')"; + if ( pConfig.length > 0 ) + { + var header = []; + var fields = []; + var output = []; + var pos = 0; + var posaddrfields = -1; + var functionCalls = []; + var addrfields = ["case when CONTACT.PERSON_ID is null then 1 else case when " + SqlMaskingUtils.prototype.trim("CONTACT.ORGANISATION_ID") + " = '0' then 2 else 3 end end", //0 + "ADDRESS.ADDRESS", "ADDRESS.BUILDINGNO", "ADDRESS.ZIP", "ADDRESS.CITY", "ADDRESS.COUNTRY", "ADDRESS.ADDRESSADDITION", // 1-6 + "ADDRESS.ADDRIDENTIFIER", "ADDRESS.DISTRICT", "ADDRESS.REGION", "ADDRESS.STATE", "CONTACT.DEPARTMENT", "CONTACT.CONTACTROLE", // 7-12 + "CONTACT.POSITION", "CONTACT.LETTERSALUTATION", "ORGANISATION.NAME", "PERSON.FIRSTNAME", "PERSON.MIDDLENAME", "PERSON.LASTNAME", // 13-18 + "PERSON.SALUTATION", "PERSON.TITLE", "PERSON.TITLESUFFIX", // 19-21 + "coalesce( CONTACT.LANGUAGE, (select C.LANGUAGE from CONTACT C where C.ORGANISATION_ID = CONTACT.ORGANISATION_ID and PERSON_ID is null))", // 22 + "''", "''", "''", "(select ADDR_FORMAT from AB_COUNTRYINFO where ISO2 = ADDRESS.COUNTRY)", "ADDRESS.ADDR_TYPE"]; // 23-27 + + for (let i=0; i < pConfig.length; i++ ) + { + switch( pConfig[i].type ) + { + case PlaceholderUtils.types.SQLPART: //sql part + fields.push( pConfig[i].valueDefinition ); //TODO: maybe do vars.resolveVariables + output.push([pos++, pConfig[i].type]); + header.push( pConfig[i].placeholderName ); + break; + case PlaceholderUtils.types.SQLPARTFUNCTION: // adito SQL functions + fields.push(pConfig[i].valueDefinition.call()); + output.push([pos++, pConfig[i].type]); + header.push( pConfig[i].placeholderName ); + break; + case "afunction": // adito functions + try + { + fields.push( "'" + evalScript("Address_lib.fetchAddressData", vars.resolveVariables(pConfig[i].valueDefinition), {}, ["Attribute_lib", "Sql_lib", "Keyword_lib", "Person_lib"], true).replace(new RegExp("'","g"), "''") + "'" ); + output.push([pos++, pConfig[i].type]); + header.push( pConfig[i].placeholderName ); + } + catch( err ) + { + logging.log( err ) + } + break; + case "select": // Subselects + fields.push( "(" + vars.resolveVariables(pConfig[i].valueDefinition) + " )" ); + output.push([pos++, pConfig[i].type]); + header.push( pConfig[i].placeholderName ); + break; + case PlaceholderUtils.types.ADDRESSFORMAT: + if ( posaddrfields == -1 ) + { + var sortfields = ["ORGANISATION.NAME", "PERSON.LASTNAME"]; + fields.push( addrfields.join(", ") ); + posaddrfields = pos; + pos += addrfields.length; + } + output.push([posaddrfields, pConfig[i].type, pConfig[i].valueDefinition]); + header.push( pConfig[i].placeholderName ); + break; + case "resolveIDFunction": + var configJSON = pConfig[i].valueDefinition; + fields.push( configJSON.rowIDField ); + + functionCalls.push([pos, + configJSON.resolveFunction, + configJSON.imports, + configJSON.localVars]); + + output.push([pos++, pConfig[i].type]); + header.push( pConfig[i].placeholderName ); + break; + } + } + if (!pPerson) { + var sqlstr = "select " + fields.join(",") + + " from CONTACT join ORGANISATION on CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID " + + " left join PERSON on CONTACT.PERSON_ID = PERSON.PERSONID " + + " left join ADDRESS on CONTACT.ADDRESS_ID = "; + } else { + + sqlstr = "select " + fields.join(",") + + " from CONTACT join PERSON on CONTACT.PERSON_ID = PERSON.PERSONID " + + " left join ORGANISATION on CONTACT.ORGANISATION_ID = ORGANISATION.ORGANISATIONID " + + " left join ADDRESS on CONTACT.ADDRESS_ID = "; + } + + if ( AddressID != undefined && AddressID != "" ) sqlstr += "'" + AddressID + "'"; + else sqlstr += "ADDRESS.ADDRESSID"; + if ( pCondition != "" ) sqlstr += " where " + pCondition; + var data = db.table(sqlstr + (sortfields != undefined ? " order by " + sortfields.join(", ") : "" )); + + // loop over all returned datasets + for(let j = 0; j < data.length; j++) + { + // loop over all possible resolveFunction entries + for(let k = 0; k < functionCalls.length; k++ ) + { + // get the local variables, which should be present in the function call + var localVars = functionCalls[k][3]; + // add the row id value to the localVars Object so the funtion can gather the data for this dataset + localVars.rowIDValue = data[j][ functionCalls[k][0] ]; + // replace the row id with its base64 string + data[j][ functionCalls[k][0] ] = evalScript("Address_lib.fetchAddressData.resolveFunction", + vars.resolveVariables( functionCalls[k][1]+"()" ), + localVars, + functionCalls[k][2], // imports + true); + } + } + + if ( data.length == 0 ) + { + logging.log("Address_lib: " + pCondition, logging.ERROR); + data = [[]]; + for (let i = 0; i < addrfields.length + fields.length; i++ ) data[0].push("Err."); + } + data = [ data, output, header, addrfields ]; + } + return data; +} + +/* +* reads data from the database +* +* @param {String [[]]} pData req array of data +* +* @return {String [[]]} data +*/ +function setAddressData( pData ) +{ + var sqlresult = pData[0]; + var data = []; + if ( sqlresult.length > 0 ) + { + var output = pData[1]; + var header = pData[2]; + var addrfields = pData[3]; + data.push( header ); + for ( var i = 0; i < sqlresult.length; i++ ) + { + var addrdata = []; + var row = []; + for ( var z = 0; z < header.length; z++ ) + { + switch( output[z][1] ) + { + case PlaceholderUtils.types.SQLPART: + case PlaceholderUtils.types.SQLPARTFUNCTION: + case "afunction": + case "resolveIDFunction": + case "select": + row[z] = sqlresult[i][output[z][0]]; + break; + case PlaceholderUtils.types.ADDRESSFORMAT: + if (addrdata.length == 0) addrdata = _getAddrData( sqlresult[i].slice(output[z][0], output[z][0] + addrfields.length) ); + row[z] = _formatAddrData( addrdata, output[z][2] ); + break; + } + } + data.push( row ); + } + } + return data; +} +/* +* +* returns formatted address data +* +* @param {String [[]]} pData req data +* +* @return {String [[]]} formatted data +*/ +function _getAddrData( pData ) +{ + var lettersalutation = pData[14]; + var salutation = pData[19]; + var sformat = ""; + switch( Number(pData[0]) ) + { + case 1: + if ( lettersalutation == "" ) + { + sformat = _getSalutation( pData[22] ); + if ( sformat != undefined && sformat[1] != "" ) lettersalutation = _formatAddrData( pData, sformat[1] ); + else lettersalutation = "Sehr geehrte Damen und Herren"; + } + break; + case 2: + // private -> orgname deleted + pData[15] = ""; + case 3: + sformat = _getSalutation( pData[22] + pData[19] + pData[20] ); + //no language defined + if ( sformat == undefined ) sformat = _getSalutation( pData[19] + pData[20] ); + // no language specific entry in salutation + if ( sformat == undefined || sformat[0] == "" || sformat[1] == "" ) sformat = ["{sa} {ti} {fn} {la}", "{sa} {ti} {ln}"]; + salutation = _formatAddrData( pData, sformat[0] ); + // lettersalutation if none existent yet + if( lettersalutation == "" ) lettersalutation = _formatAddrData( pData, sformat[1] ); + } + + pData[23] = salutation; + pData[24] = lettersalutation; + pData[25] = _getCountryName(pData[5]); + return pData; +} + +/* +* returns a formatted salutation +* +* @param {String} pSalutCode req salutation code +* +* @return {String} translated salutation +*/ +function _getSalutation( pSalutCode ) +{ + var salut = new Object(); + if (vars.exists("$global.Salutation")) { + salut = vars.get("$global.Salutation"); + } + else + { + var list = db.table("select LANGUAGE, SALUTATION, TITLE, HEADLINE, LETTERSALUTATION from SALUTATION" ); + for ( var i = 0; i < list.length; i++ ) + { + salut[list[i][0] + list[i][1] + list[i][2]] = [list[i][3], list[i][4]]; + salut[list[i][1] + list[i][2]] = [list[i][3], list[i][4]]; + } + vars.set("$global.Salutation", salut); + } + return salut[pSalutCode]; +} + +/* +* returns country names +* +* @param {String} pCountryCode req countrycode +* +* @return {String} translated countryname +*/ +function _getCountryName(pCountryCode) +{ + var countryname = new Object(); + if ( vars.exists("$global.CountryName")) countryname = vars.get("$global.CountryName"); + else + { + var list = db.table("select ISO2, NAME_NATIVE from AB_COUNTRYINFO" ); + for (var i=0; i < list.length; i++ ) countryname[list[i][0]] = translate.text(list[i][1]); + vars.set("$global.CountryName", countryname); + } + return countryname[pCountryCode]; +} + +/* +* returns a formatted address +* +* @param {String [[]]} pAddrData req Address data +* @param {String} pFormat opt given format +* @param {boolean} pCountry if the country should be displayed +* +* @return {String} formatted address +*/ +function _formatAddrData( pAddrData, pFormat, pCountry ) +{ + var placeholerInfo = { + "street": {dataPosition: 1}, + "buildingno": {dataPosition: 2}, + "zip": {dataPosition: 3}, + "city": {dataPosition: 4}, + "district": {dataPosition: 8}, + "region": {dataPosition: 9}, + "state": {dataPosition: 10}, + "firstname": {dataPosition: 16}, + "middlename": {dataPosition: 17}, + "lastname": {dataPosition: 18}, + "saluation": {dataPosition: 19}, + "title": {dataPosition: 20}, + "suffix": {dataPosition: 21}, + "country": {dataPosition: 25}, + "organisation_name": {dataPosition: 15}, + "salutation_name": {dataPosition: 23}, + "letter_salutation": {dataPosition: 24} + }; + + var format = pFormat || pAddrData[26]; + format = _mapFormatPlaceholderTitles(format, pAddrData, pCountry); + + var res = format; + for (var placeholder in placeholerInfo) + { + var currentAddrData = pAddrData[placeholerInfo[placeholder].dataPosition]; + if (currentAddrData != undefined) + { + res = res.replace(new RegExp("{" + placeholder + "}", "g"), currentAddrData); + res = res.replace(new RegExp("{" + placeholder.toUpperCase() + "}", "g"), currentAddrData.toUpperCase()); + } + } + + res = res.replace(/^\n/, ""); // CR am Anfang entfernen; + res = res.replace(/ /g, " "); // doppelte leerzeichen entfernen + res = res.replace(/\\n/ig, "\n"); // newline marker ersetzen + res = res.replace(/ *\n */g, "\n");// leerzeichen am ende und Anfang entfernen + res = res.replace(/\s(?=\s)/g, ""); // leerzeilen rauswerfen + return res; +} + +/* +* returns the new format +* +* @param {String [[]]} pAddrData req Daten +* @param {String} pFormat req the format string +* @param {boolean} pCountry if the country should be displayed +* +* @return {String} new formate +* +N – Name - salutation +O – Organisation - orgname +A – Street Address Line(s) - address + buildingno +D – Dependent locality - district / region +C – City or Locality - city +S – Administrative area - state +Z – Zip or postal code - zip +X – Sorting code - not available +*/ +function _mapFormatPlaceholderTitles(pFormat, pAddrData, pCountry) +{ + //gstatic-paceholders + pFormat = pFormat.replace(new RegExp("%N", "g"), "{salutation_name}"); + pFormat = pFormat.replace(new RegExp("%A", "g"), "{street} {buildingno}"); + pFormat = pFormat.replace(new RegExp("%C", "g"), "{city}"); + pFormat = pFormat.replace(new RegExp("%S", "g"), "{state}"); + pFormat = pFormat.replace(new RegExp("%Z", "g"), "{zip}"); + pFormat = pFormat.replace(new RegExp("%O", "g"), "{organisation_name}"); + pFormat = pFormat.replace(new RegExp("%X", "g"), ""); + pFormat = pFormat.replace(new RegExp("%n", "g"), "\n"); + + //shortform adito-placeholders + pFormat = pFormat.replace(new RegExp("{fn}", "g"), "{firstname}"); + pFormat = pFormat.replace(new RegExp("{ln}", "g"), "{lastname}"); + pFormat = pFormat.replace(new RegExp("{ti}", "g"), "{title}"); + pFormat = pFormat.replace(new RegExp("{sa}", "g"), "{salutation}"); + + if (pAddrData[8] == pAddrData[9]) + pFormat = pFormat.replace(new RegExp("%D", "g"), "{district}"); + else + pFormat = pFormat.replace(new RegExp("%D", "g"), "{district} \n {region}"); + + if(pCountry == undefined || pCountry == null || pCountry == true) + pFormat = pFormat + "\n {country}"; + + return pFormat; } \ No newline at end of file diff --git a/process/DataCaching_lib/process.js b/process/DataCaching_lib/process.js index 8410bd42ceceb6760b8bc9645dfe445f23467a8a..2aee0dc32b167e0c11e2765cb44026dd6bbb96bd 100644 --- a/process/DataCaching_lib/process.js +++ b/process/DataCaching_lib/process.js @@ -66,8 +66,8 @@ CachedData.prototype.load = function(pDataCallbackFunction) //currently it's not possible to cache the data within the serer-context, so instead the Data-function is called everytime if (this.runningOnServer) cachingEnabled = false; - else if (JSON.parse(project.getInstanceConfigValue("custom.dataCaching.client.forceDisable")) == true) - cachingEnabled = false; +// else if (JSON.parse(project.getInstanceConfigValue("custom.dataCaching.client.forceDisable")) == true) +// cachingEnabled = false; if (!cachingEnabled) return pDataCallbackFunction.call(this, this.keepPerLanguage, this.locale); diff --git a/process/DocumentTemplate_lib/process.js b/process/DocumentTemplate_lib/process.js index 1d448d37692a606659003910ac72b3c8174d5372..209f427347d35b9dc4a7f6185953ef17cf8103fc 100644 --- a/process/DocumentTemplate_lib/process.js +++ b/process/DocumentTemplate_lib/process.js @@ -1,3 +1,4 @@ +import("Employee_lib"); import("KeywordRegistry_basic"); import("Document_lib"); import("KeywordData_lib"); @@ -6,16 +7,12 @@ import("Address_lib"); import("system.process"); import("system.vars"); import("system.db"); -import("system.swing"); import("system.util"); import("system.pack"); import("system.fileIO"); import("system.translate"); -import("system.question"); import("system.datetime"); -import("system.logging"); import("system.text"); -import("system.eMath"); import("system.mail"); import("Keyword_lib"); @@ -63,15 +60,15 @@ DocumentTemplate.loadTemplate = function (pTemplateId) DocumentTemplate.prototype.toString = function () { - return this.templateText; + return this.content; } /** - * returns the template text with replaced placeholders + * returns the template content with replaced placeholders * - * @param {Object} pReplacements map, the structure is {placeholder : value} (the placeholder should have the prefix @@) + * @param {Object} pReplacements map, the structure is {placeholder : value} */ -DocumentTemplate.prototype.getReplacedText = function (pReplacements) +DocumentTemplate.prototype.getReplacedContent = function (pReplacements) { switch (this.type) { @@ -83,20 +80,24 @@ DocumentTemplate.prototype.getReplacedText = function (pReplacements) case DocumentTemplate.types.EML: return this._getReplacedEML(pReplacements); case DocumentTemplate.types.ODT: -// return this._getReplacedODT(pReplacements); + return this._getReplacedODT(pReplacements); case DocumentTemplate.types.DOCX: -// return this._getReplacedDOCX(pReplacements); + return this._getReplacedDOCX(pReplacements); default: return null; } } -DocumentTemplate.prototype.getReplacedTextByContactId = function (pContactId) +DocumentTemplate.prototype.getReplacedContentByContactId = function (pContactId) { - var config = DocumentTemplate._getPlaceholderConfig(); - var replacements = getAddressesData([pContactId], config, pSenderID, pAddressID); - //TODO: build the replacement map here - return this.getReplacedText(replacements); + var config = PlaceholderUtils.getPlaceholders(); + var addressData = getAddressesData([pContactId], config, EmployeeUtils.getCurrentContactId()); //TODO: add sender selection + var replacements = {}; + for (let i = 0, l = addressData[0].length; i < l; i++) + { + replacements[addressData[0][i]] = addressData[1][i]; + } + return this.getReplacedContent(replacements); } DocumentTemplate.prototype._getReplacedEML = function (pReplacements) @@ -105,92 +106,85 @@ DocumentTemplate.prototype._getReplacedEML = function (pReplacements) } + /* * replaces a given Odt-File on the server and returns the replaced base64-file - * - * @deprecated needs refactoring * - * @param {String} pTemplateData req base64-encoded input file with placeholders - * @param {String} pTemplateName req name of the input file * @param {String|String[]} pAddrDataCondition req a SQL-Condition or an Array of Relation-Ids for reducing the default-placeholders * @param {String} pAddressID opt if you want to use the standard address you can pass undefined, otherwise you need to specify a Address-Id - * @param {Object} pAdditionalData opt additional placeholders with data (e.g. offercode); for format check the example - * @param {Object[]} pTableData opt data for odt-tables; for format check the example * * @return {String} base64-encoded replaced file - * - * @example - * //examples for additionalData: - * //2 Methods: 1) SQL 2) Array - no matter what you're using: the first column has to be the RELATIONID-Value - * //1) you can use a SQL-Statement for passing Data - * additionalData = { - * Fields: ["RELID", "myPlaceholder 1","myPlaceholder N"] - * ,SQLStr: "select RELATION_ID, ADDR, MEDIUM_ID from COMM" - * }; - * //if you pass the (optional) property "ID" a condition with ID in <<relationids>> is added to the SQL-Data-query: - * additionalData.ID = "COMM.RELATION_ID"; - * - * - * //2) another option is to pass data as a 2D-Array like this - * additionalData = { - * Fields: ["RELID", "myPlaceholder 1","myPlaceholder N"] - * ,Data: [ - * ["myRelIdValue 1", "my Value 1", "my Value N"] - * ,["myRelIdValue M", "my other Value 1", "my other Value N"] - * ] - * }; - * - * - * //examples for tableData: - * //you can define multible data-sources - * tableData = []; - * //2 Methods: 1) SQL 2) Array - no matter what you're using: the first column has to be the RELATIONID-Value - * //the placeholder can be accessed by <<Table>>.<<Field>> - * //1) if you use a SQL-Statement for defining the data you've got some optional properties - * var sqlSource = { - * Table: "ADDR" - * ,Fields: ["RELID", "Type", "Strasse", "PLZ", "Ort", "Staat", "Land"], - * ,SQLStr: "select RELATION_ID, ADDR_TYPE, " + concat(["ADDRESS", "BUILDINGNO"]) + ", ZIP, CITY, STATE, NAME_DE from ADDRESS join COUNTRYINFO on COUNTRY = ISO2" - * }; - * //if you pass the (optional) property "ID" a condition with ID in <<relationids>> is added to the SQL-Data-query: - * sqlSource.ID = "ADDRESS.RELATION_ID"; - * - * //if you pass the (optional) property "SQLOrder" an order-by clause is added - * sqlSource.SQLOrder = "ADDRESS.ADDR_TYPE asc, ADDRESS.ZIP desc"; - * - * tableData.push(sqlSource); - * - * //2) pass data as an Array like this - * var arraySource = { - * Table: "myTablePrefix" - * ,Fields: ["RELID", "myPlaceholder 1","myPlaceholder N"] - * ,Data: [ - * ["myRelIdValue 1", "my Value 1", "my Value N"] - * ,["myRelIdValue M", "my other Value 1", "my other Value N"] - * ] - * } - * tableData.push(arraySource); - * */ -DocumentTemplateUtils.getReplacedODT = function (pTemplateData, pTemplateName, pAddrDataCondition, pAddressID, pAdditionalData, pTableData) +DocumentTemplate.prototype._getReplacedODT = function (pAddrDataCondition, pAddressID) { - //save the file on the server, replace it on the server file system, then load it because that works for neon and swing + //save the file on the server so it can be unzipped via pack.getFromZip var serverFilePath = vars.get("$sys.servertemp") + "/clientid_" + vars.get("$sys.clientid") - + "/" + util.getNewUUID() + "/" + pTemplateName.replace(/\\/g, "/"); + + "/" + util.getNewUUID(); - fileIO.storeData(serverFilePath, pTemplateData, util.DATA_BINARY, false); - if ( ! replaceODTFile(pAddrDataCondition, serverFilePath, pAddressID, pAdditionalData, pTableData )) + fileIO.storeData(serverFilePath, this.content, util.DATA_BINARY, false); + if (!_replaceODTFile(pAddrDataCondition, serverFilePath, pAddressID)) return null; var replacedFileData = fileIO.getData(serverFilePath, util.DATA_BINARY); fileIO.remove(serverFilePath); return replacedFileData; -} - -DocumentTemplate.prototype._getReplacedODT = function (pReplacements) -{ + /* + * ersetzt die Platzhalter in ODT-Datei + * + * @param {String} pCondition req Condition + * @param {String} pODTFileName req Filename des odt-Datei + * @param {String} pAddressID opt ID von der die Adressdaten geholt werden + * + * @return {Boolean} + */ + function _replaceODTFile (pCondition, pODTFileName, pAddressID) + { + // Configuration für die Platzhalter + var config = PlaceholderUtils.getPlaceholders(); //["RELATIONID","fieldname","RELATION.RELATIONID"] + var senderRelId = EmployeeUtils.getCurrentContactId(); + if (senderRelId == null) + return false; + var addrdata = getAddressesData(pCondition, config, senderRelId, pAddressID); + if (addrdata.length > 1) + { + var relationids = []; + for (let i = 1; i < addrdata.length; i++ ) + relationids.push(addrdata[i][0]); + + // ersetzen Platzhalter in content.xml + + var textS = util.decodeBase64String(pack.getFromZip(pODTFileName, "content.xml")); + var bodybegin = textS.indexOf("<office:body>"); + var bodyend = textS.indexOf("</office:body>") + 14; + var body = textS.substring( bodybegin, bodyend ); + var lastbody = textS.substr( bodyend ); + textS = textS.substring( 0, bodybegin ); + for (let i = 1; i < addrdata.length; i++) + { + var bulkbody = body; + for (let ii = 0; ii < addrdata[0].length; ii++) + { + bulkbody = bulkbody.replace(new RegExp(getDefaultODTplaceholer(addrdata[0][ii]), "ig"), + addrdata[i][ii].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&") ); + } + textS += bulkbody; + } + textS += lastbody; + pack.addToZip(pODTFile, "content.xml", util.encodeBase64String(textS)) + // ersetzen Platzhalter in styles.xml + var styles = util.decodeBase64String(pack.getFromZip(pODTFileName, "styles.xml")); + for (let i = 0; i < addrdata[0].length; i++) + { + styles = styles.replace(new RegExp( getDefaultODTplaceholer(addrdata[0][i]), "ig"), + addrdata[1][i].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&")); + } + pack.addToZip(pODTFile, "styles.xml", util.encodeBase64String(styles)); + return true; + } + return false; + } } /* @@ -204,8 +198,8 @@ DocumentTemplate.prototype._getReplacedDOCX = function (pReplacements) { //this is executed as a process because of better performance var documentData = process.execute("getDocxDocument_serverProcess", { - templateb64: this.templateText, - placeholderConfig: JSON.stringify(pPlaceholder) //process.execute is only able to handle strings + templateb64: this.content, + placeholderConfig: JSON.stringify(pReplacements) //process.execute is only able to handle strings }); return documentData; @@ -234,128 +228,68 @@ DocumentTemplateUtils._getPlaceholderConfig = function () } -/* -* ersetzt die Platzhalter in ODT-Datei -* -* @deprecated needs refactoring -* -* @param {String} pCondition req Condition -* @param {String} pODTFile req Filename des odt-Datei -* @param {String} pAddressID opt ID von der die Adressdaten geholt werden -* -* @return {void} -*/ -DocumentTemplateUtils.replaceODTFile = function (pCondition, pODTFile, pAddressID) -{ - // Configuration für die Platzhalter - var config = [["RELATIONID","fieldname","RELATION.RELATIONID"]] - config = config.concat(DocumentTemplateUtils._getPlaceholderConfig()); - var senderRelId = getSendRelID(); - if (senderRelId == null) - return false; - var addrdata = getAddressesData(pCondition, config, senderRelId, pAddressID); - if (addrdata.length > 1) - { - var relationids = []; - for (let i = 1; i < addrdata.length; i++ ) - relationids.push(addrdata[i][0]); - - - // ersetzen Platzhalter in content.xml +function PlaceholderUtils () {} - var textS = util.decodeBase64String(pack.getFromZip(pODTFile, "content.xml")); - var bodybegin = textS.indexOf("<office:body>"); - var bodyend = textS.indexOf("</office:body>") + 14; - var body = textS.substring( bodybegin, bodyend ); - var lastbody = textS.substr( bodyend ); - textS = textS.substring( 0, bodybegin ); - for (let i = 1; i < addrdata.length; i++) - { - var bulkbody = body; - for (let ii = 0; ii < addrdata[0].length; ii++) - { - bulkbody = bulkbody.replace( new RegExp( getDefaultODTplaceholer(addrdata[0][ii]), "ig"), - addrdata[i][ii].replace( new RegExp( "\n", "ig"), "<text:line-break/>").replace( new RegExp( "&", "ig"), "&") ); - } - textS += bulkbody; - } - textS += lastbody; - pack.addToZip(pODTFile, "content.xml", util.encodeBase64String(textS)) - // ersetzen Platzhalter in styles.xml - var styles = util.decodeBase64String(pack.getFromZip(pODTFile, "styles.xml")); - for (let i = 0; i < addrdata[0].length; i++) - { - styles = styles.replace( new RegExp( getDefaultODTplaceholer(addrdata[0][i]), "ig"), - addrdata[1][i].replace( new RegExp( "\n", "ig"), "<text:line-break/>").replace( new RegExp( "&", "ig"), "&") ); - } - pack.addToZip(pODTFile, "styles.xml", util.encodeBase64String(styles)); - return true; - } - return false; -} +PlaceholderUtils.types = { + ADDRESSFORMAT : "ADDRESSFORMAT", + SQLPART : "SQLPART", + SQLPARTFUNCTION : "SQLPARTFUNCTION" +}; +PlaceholderUtils.targets = { + RECIPIENT : "RECIPIENT", + SENDER : "SENDER", + EMPLOYEE : "EMPLOYEE" +}; -/* -* Liefert Vorlage mit ersetzen Platzhalter durch den jeweiligen Text. -* -* @deprecated needs refactoring -* -* @param {String} pContactId req RELATIONID der relation, von der die Adressdaten geholt werden - SQL where condition für getAddressesData() -* @param {Integer[]} pDocuType req OATYPE der Vorlage -* @param {String} pLanguage opt Sprache -* @param {String} pAddressID opt pAddressID -* @param {String} pSenderID opt UserRelationID -* @param {String} pTemplateName opt Name der Vorlage -* -* @return {Obj} { id, name, language, attachments:[[Name, Data]], template:{filename, data}, -* exportoption:{fieldids, open, file, fieldseperator, fieldlimit, recordseperator} } -* oder {Boolean:false} wenn keine Vorlage vorhanden ist oder ausgewählt wurde -*/ -DocumentTemplateUtils.getReplacedText = function (pContactId, pDocuType, pLanguage, pAddressID, pSenderID, pTemplateName) +/** + * Returns the placeholder with the required prefix and postfix added. + * This function defines the format for placeholders. + */ +PlaceholderUtils.formatPlaceholder = function (pPlaceholder) { - var document = chooseTemplate( pDocuType, pLanguage, pTemplateName); - if (!document) return null; + return "@@" + pPlaceholder + "@@"; +} - var isHtml = document.template.data.substr(0, 6) == "<html>" - if (document.template.filename != undefined) - document.template.data = decode64(document.template.data); - // Configuration für die Platzhalter - var config = KeywordData.getKeywordAttributeRelations("TextPlaceholder"); //->keyword registry - var addrdata = getAddressesData( [pContactId], config, pSenderID, pAddressID ); - var value; - var prefix = "@@"; - for (let i = 0, l = addrdata[0].length; i < l; i++) +PlaceholderUtils.getPlaceholders = function () +{ + function Placeholder (pName, pType, pValueDef, pTarget) { - if (isHtml) - value = addrdata[1][i].replace(new RegExp( "\n", "ig"), "<br>"); - else - value = addrdata[1][i]; - document.template.data = document.template.data.replace(new RegExp(prefix + addrdata[0][i], "ig"), value); + this.placeholderName = PlaceholderUtils.formatPlaceholder(pName); + this.type = pType; + this.target = pTarget || PlaceholderUtils.targets.RECIPIENT; + this.valueDefinition = pValueDef; } - return document; -} - - - -/* - * transforms a given placeholerformat into the ODT-placeholer thats in the ODT - * if you have to change this (e.g. to @@) you can do this at this 1 position - * - * @deprecated needs refactoring - * - * @param {String} pPlaceholderName req name of the placeholer, e.g. "Anrede" - * @param {bool} pOnlyStart opt if set to true only the leading-symbols are added - * - * @return {String} placeholder with placeholder-symbols, e.g. "{@Anrede@}" - */ -DocumentTemplateUtils.getDefaultODTplaceholer = function (pPlaceholderName, pOnlyStart) -{ - if (pOnlyStart) - return "{@" + pPlaceholderName; - return "{@" + pPlaceholderName + "@}"; + function _addAddressFormat (pName, pFormat, pTarget) + { + placeholders.push(new Placeholder(pName, PlaceholderUtils.types.ADDRESSFORMAT, pFormat, pTarget)); + } + + function _addSqlPart (pName, pSqlPart, pAddBraces) + { + placeholders.push(new Placeholder(pName, PlaceholderUtils.types.SQLPART, pAddBraces ? "(" + pSqlPart + ")" : pSqlPart)); + } + + function _addSqlPartFunction (pName, pSqlPartFunction, pTarget) + { + placeholders.push(new Placeholder(pName, PlaceholderUtils.types.SQLPARTFUNCTION, pSqlPartFunction, pTarget)); + } + + var placeholders = []; + + _addAddressFormat("address", "{street} {buildingno}"); + _addAddressFormat("zipCode", "{zip}"); + _addAddressFormat("city", "{city}"); + _addAddressFormat("district", "{district}"); + _addAddressFormat("region", "{region}"); + _addAddressFormat("country", "{country}"); + _addAddressFormat("letterSalutation", "{letter_salutation}"); + _addAddressFormat("fullAddress", ""); + _addAddressFormat("senderOrgname", "{organisation_name}", PlaceholderUtils.targets.SENDER); + _addAddressFormat("senderAddress", "{street} {buildingno}", PlaceholderUtils.targets.SENDER); + _addAddressFormat("senderZipCity", "{country} - {zip} {city}", PlaceholderUtils.targets.SENDER); + _addAddressFormat("senderFullAddress", "", PlaceholderUtils.targets.SENDER); + + return placeholders; } - - - - diff --git a/process/Email_lib/process.js b/process/Email_lib/process.js index a6002c411cdfae930617ccfbdd96068180e07b59..ac0feee222fabc11b981d42c676b9d48b4bd6019 100644 --- a/process/Email_lib/process.js +++ b/process/Email_lib/process.js @@ -1,3 +1,4 @@ +import("system.logging"); import("system.translate"); import("system.text"); import("system.db"); @@ -16,15 +17,16 @@ function EmailUtils () {} * In Thunderbird the mail is opened in view mode and you've to manually "edit as new" * * @param {String|Array} pToRecipients mailaddresses of the recipients, can either be a 1D-Array with several addresses or a string with one address - * @param {String} pContactId contactId of the sender. the standard mailadress of the contact is used as sender-address + * @param {String} pSenderContactId contactId of the sender. the standard mailadress of the contact is used as sender-address * @param {String} [pTemplateId] if a document-template shall be used, give the templateId here + * @param {String} [pRecipientContactId] contactId of the recipient, required to fill placeholders */ -EmailUtils.openMailTemplate = function (pToRecipients, pContactId, pTemplateId) +EmailUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId) { var email = new Email(pToRecipients); - email.setSender(pContactId); + email.setSender(pSenderContactId); if (pTemplateId) - email.setTemplate(pTemplateId); + email.setTemplate(pTemplateId, pRecipientContactId); email.downloadEML(); } @@ -71,10 +73,15 @@ function Email (pToRecipients, pSender, pSubject, pBody, pCcRecipients, pBccReci * loads a document template into the mail body * * @param {String} pTemplateId the id of the template + * @param {String} pContactId the id of the template */ -Email.prototype.setTemplate = function (pTemplateId) +Email.prototype.setTemplate = function (pTemplateId, pContactId) { - this.body = String(DocumentTemplate.loadTemplate()); + var template = DocumentTemplate.loadTemplate(pTemplateId); + //TODO: also set other properties if the template is a eml + if (template) + this.body = template.getReplacedContentByContactId(pContactId); + logging.log(this.body) } /**