From 875ebe8c4aaf958b4fbb579b0f186ad5fae4e166 Mon Sep 17 00:00:00 2001 From: "S.Listl" <S.Listl@SLISTL.aditosoftware.local> Date: Tue, 28 May 2019 15:04:40 +0200 Subject: [PATCH] Document Template placeholder --- .../DocuTemplatePlaceholder_Keywords.xml | 57 ++ process/DocumentTemplate_lib/process.js | 585 +++++++----------- process/Email_lib/process.js | 9 +- process/KeywordRegistry_basic/process.js | 4 +- 4 files changed, 285 insertions(+), 370 deletions(-) create mode 100644 .liquibase/Data_alias/basic/2019.2/DocuTemplatePlaceholder_Keywords.xml diff --git a/.liquibase/Data_alias/basic/2019.2/DocuTemplatePlaceholder_Keywords.xml b/.liquibase/Data_alias/basic/2019.2/DocuTemplatePlaceholder_Keywords.xml new file mode 100644 index 00000000000..6c892fd2a03 --- /dev/null +++ b/.liquibase/Data_alias/basic/2019.2/DocuTemplatePlaceholder_Keywords.xml @@ -0,0 +1,57 @@ +<?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/process/DocumentTemplate_lib/process.js b/process/DocumentTemplate_lib/process.js index e92069a69a6..e764b2a2d93 100644 --- a/process/DocumentTemplate_lib/process.js +++ b/process/DocumentTemplate_lib/process.js @@ -1,3 +1,7 @@ +import("KeywordRegistry_basic"); +import("Document_lib"); +import("KeywordData_lib"); +import("Sql_lib"); import("Address_lib"); import("system.process"); import("system.vars"); @@ -13,383 +17,88 @@ import("system.logging"); import("system.text"); import("system.eMath"); import("system.mail"); - +import("Keyword_lib"); /** - * Provides functions for document templates + * Object for working with document templates */ -function DocumentTemplateUtils () {} - - - - -/* -* Liefert ausgewählte DocumentID zurück -* -* @param {Integer []} pType req DocumentenTypes -* @param {String} pLanguage opt Sprache -* @param {String} pTemplateName opt Name der Vorlage -* @param {Boolean} pOnlyHTML opt default: false; sollen nur Vorlagen zur Auswahl stehen, die nach der neuen Vorlagen-Methode einen HTML Text hinterlegt haben -* -* @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.chooseTemplate = function (pType, pLanguage, pTemplateName, pOnlyHTML) +function DocumentTemplate (pTemplateContent, pType) { - var langcondition = ""; - var templatelist; - var templatename = "" - var condition = "AOTYPE in (" + pType.join(", ") + ")"; - if ( pLanguage != undefined && pLanguage != "" ) - { - langcondition = " and LANG = " + pLanguage; - } - if ( pTemplateName != undefined && pTemplateName != "" ) - { - condition += " and NAME like '" + pTemplateName + "%'"; - } - // die zum Frame gehörigen und die Vorlagen ohne Zugehörigkeit anzuzeigen - if ( vars.exists("$image.Frame") ) - { - var fd = new FrameData(); - var frame = fd.getData("id", vars.get("$image.Frame").Id, ["name"]); - condition += " and ( DOCUMENTID in (select ROW_ID from ATTRLINK join ATTR on ATTRID = VALUE_ID and OBJECT_ID = 9 and ATTRNAME = '" + frame + "')" - + " or DOCUMENTID not in (select ROW_ID from ATTRLINK join ATTR on ATTRID = ATTRLINK.ATTR_ID and OBJECT_ID = 9 and ATTRNAME = 'Doku Vorlagen Verwendung')) "; - } - condition = getGrantCondition( "DOCUMENT", condition); - templatelist = db.array(db.COLUMN, "select NAME from DOCUMENT where " + (pOnlyHTML != undefined && pOnlyHTML == true ? " HTMLTEXT is not null and " : "") + condition + langcondition + " order by NAME"); - var questionText = ""; - if ( templatelist[0] == undefined || pLanguage == "" ) // keine passende Sprache beim Kontakt hinterlegt - { - // Benutzer wählt sich jetzt seine gewünschte Sprache aus... - questionText = translate.text("Keine Vorlage in der gewünschten Sprache gefunden.\nBitte eine Sprache auswählen."); - var availableLangs = db.array(db.COLUMN, "select distinct(keyname1) from keyword join document on document.lang = keyword.keyvalue where" + getKeyTypeSQL("SPRACHE")); - if(vars.get("$sys.scope") == "vaadin") - { - // Liest die verfügbaren Sprachen aus, die in den Dokumenten vorhanden sind, und zwar ausgeschrieben - availableLangs = db.table("select distinct(keyname1), keyname1 from keyword join document on document.lang = keyword.keyvalue where" + getKeyTypeSQL("SPRACHE")); - //@TODO evtl noch ein Label in den Dialog zur Textanzeige? - pLanguage = openCMBDialog( questionText, availableLangs).cmb_Data; - } - else - { - pLanguage = swing.askQuestion(questionText, swing.QUESTION_COMBOBOX, "|" + availableLangs.join("|")); - } - if (pLanguage == null ) return false; - // ...und JDito setzt die ausgeschriebene Sprache wieder in das Keyword um, z.B. 'de' - pLanguage = db.cell("select distinct(lang) from document join keyword on keyword.keyname1 = '" + pLanguage + "' and keyword.keyvalue = document.lang where" + getKeyTypeSQL("SPRACHE")); - langcondition = " and LANG = " + pLanguage; - - templatelist = db.array(db.COLUMN, "select NAME from DOCUMENT where " + condition + langcondition + " order by NAME"); - } + this.content = pTemplateContent; + this.type = pType; +} - if (templatelist.length > 1) - { - questionText = translate.text("Vorlage wählen"); - if(vars.get("$sys.scope") == "vaadin") - { - templatelistChoose = db.table("select NAME, NAME from DOCUMENT where " - + (pOnlyHTML != undefined && pOnlyHTML == true ? " HTMLTEXT is not null and " : "") - + condition + langcondition + " order by NAME"); - templatename = openCMBDialog(questionText, templatelistChoose).cmb_Data; - } - else - { - templatename = swing.askQuestion(questionText, swing.QUESTION_COMBOBOX, "|" + templatelist.join("|")); - } - if (templatename == null)return false; - } - else templatename = templatelist[0]; - // 0 1 2 3 4 5 6 7 8 9 10 11 - var data = db.array(db.ROW, "select NAME, LANG, HTMLTEXT, FIELDIDS, OPENWITHEXPORT, EXPORTFILE, FIELDSEPERATOR, FIELDLIMIT, RECORDSEPERATOR, DOCUMENTID, MODULEEXPORTQUERY, AOTYPE " - + " from DOCUMENT where NAME = '" + templatename + "' and " + condition + langcondition); +/** + * The types a DocumentTemplate can have. Depending on the type, + * the correct method for replacing the placeholders can be chosen + */ +DocumentTemplate.types = { + TXT : "TXT", + HTML : "HTML", + ODT : "ODT", + DOCX : "DOCX" +}; - if (data.length > 0) - { - // if type is 7, it uses exportfields. They use the table DOCUMENTLINK and not the column FIELDIDS - if (data[11] == 7) - { - data[3] = getLinkedKeywords(data[9]); - } - - var template = false; - // get metadata for attachments - var metadata = db.getBinaryMetadata("DOCUMENT", "Vorlage", data[9], false, null); - var attachments = []; - // fill rows of [ filname, bindata ] into the array - for( var i = 0; i < metadata.length; i++ ) - { - attachments.push( [ metadata[i].filename, db.getBinaryContent(metadata[i].id, null) ] ); - } - - if ( data[2] != "" ) // Vorlage aus HTML-Text - { - template = - { - data:data[2] - }; - } - else if ( attachments.length > 0 ) // Vorlage aus Anhang - { - template = - { - filename: attachments[0][0], - data: attachments[0][1] - }; - //do not add the documents text to the attachments - attachments = attachments.filter(function (row){ - //use filename and the b64-date because the user is able to control whether the message-text should be in the attachments or not, - //by simply adding the message-text in another document - return row[0] + "/" + row[1] != template.filename + "/" + template.data; - }); - } - var exportoption = { - fieldids:data[3], - open:data[4], - file:data[5], - fieldseperator:data[6], - fieldlimit:data[7], - recordseperator: data[8], - exportquery: data[10] - }; - return { - id:data[9], - aotype:data[11], - name:data[0], - language:data[1], - template:template, - attachments:attachments, - exportoption:exportoption - }; - } - else return false; +DocumentTemplate.loadTemplate = function (pTemplateId) +{ + var alias = "_____SYSTEMALIAS"; + var templateDocument = db.getBinaryMetadata("DOCUMENTTEMPLATE", "DOCUMENT", pTemplateId, false, alias, null); + if (!templateDocument[0]) + return null; + var binaryId = templateDocument[0][db.BINARY_ID]; + var type = DocumentUtil.getFileExtensionFromUpload(templateDocument[0][db.BINARY_FILENAME]); + var typeMap = { + txt : DocumentTemplate.types.TXT, + html : DocumentTemplate.types.HTML, + odt : DocumentTemplate.types.ODT, + docx : DocumentTemplate.types.DOCX + }; + type = typeMap[type]; //choose the document type depending on the file extension + if (binaryId) + return new DocumentTemplate(util.decodeBase64String(db.getBinaryContent(binaryId, alias)), type); + return null; } -/* -* ersetzt die Platzhalter in ODT-Datei -* -* @param {String} pCondition req Condition -* @param {String} pODTFile req Filename des odt-Datei -* @param {String} pAddressID opt ID von der die Adressdaten geholt werden -* @param {[]} pAdditionalData opt zusätzliche Daten -* -* pAdditionalData = {Fields: ["RELID", "Platzhalter1","Platzhalter2"], -* SQLStr: "select RELATION_ID, ADDR, MEDIUM_ID from COMM", -* statt SQLStr Data: [[]], -* ID: "RELATION_ID" }; -* -* @param {[]} pTableData opt Tabellendaten -* -* pTableData = [{ 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", -* statt SQLStr Data: [[]], -* optional SQLOrder: "STATE, ZIP", -* ID: "RELATION_ID" }]; -* -* @return {void} -*/ -DocumentTemplateUtils.replaceODTFile = function ( pCondition, pODTFile, pAddressID, pAdditionalData, pTableData ) +DocumentTemplate.prototype.toString = function () { - var i; - var textS; - var ti; - var z; - if ( pTableData == undefined ) pTableData = []; - if ( pAdditionalData == undefined ) pAdditionalData = {}; - // Configuration für die Platzhalter - var config = [["RELATIONID","fieldname","RELATION.RELATIONID"]] - config = config.concat( db.table("select KEYNAME1, KEYNAME2, KEYDETAIL from KEYWORD where " + getKeyTypeSQL("EXPORTFIELDS"))); - var senderRelId = getSendRelID(); - if (senderRelId == null) - return false; - var addrdata = getAddressesData( pCondition, config, senderRelId, pAddressID ); - if ( addrdata.length > 1 ) - { - var relationids = []; - for (i=1; i < addrdata.length; i++ ) relationids.push(addrdata[i][0]); - // pTableData aufbereiten - for (ti = 0; ti < pTableData.length; ti++) - { - if( pTableData[ti].SQLStr != undefined ) - { - if ( pTableData[ti].ID != undefined ) pTableData[ti].SQLStr += " where " + pTableData[ti].ID + " in ('" + relationids.join("','") + "')"; - if ( pTableData[ti].SQLOrder != undefined ) pTableData[ti].SQLStr += " order by " + pTableData[ti].SQLOrder; - pTableData[ti].Data = db.table(pTableData[ti].SQLStr ); - } - pTableData[ti].TableData = []; - for (i=0; i < pTableData[ti].Data.length; i++ ) - { - if ( pTableData[ti].TableData[pTableData[ti].Data[i][0]] == undefined ) pTableData[ti].TableData[pTableData[ti].Data[i][0]] = []; - pTableData[ti].TableData[pTableData[ti].Data[i][0]].push( pTableData[ti].Data[i] ); - } - } - // pAdditionalData aufbereiten - if ( pAdditionalData.SQLStr != undefined ) - { - if ( pAdditionalData.ID != undefined ) pAdditionalData.SQLStr += " where " + pAdditionalData.ID + " in ('" + relationids.join("','") + "')"; - pAdditionalData.Data = db.table( pAdditionalData.SQLStr ); - } - pAdditionalData.AddData = []; - if ( pAdditionalData.Data != undefined ) - for (i=0; i < pAdditionalData.Data.length; i++ ) pAdditionalData.AddData[pAdditionalData.Data[i][0]] = pAdditionalData.Data[i]; - - // ersetzen Platzhalter in content.xml - - 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 (i = 1; i < addrdata.length; i++) - { - var bulkbody = body; - for (z = 0; z < addrdata[0].length; z++) - { - bulkbody = bulkbody.replace( new RegExp( getDefaultODTplaceholer(addrdata[0][z]), "ig"), - addrdata[i][z].replace( new RegExp( "\n", "ig"), "<text:line-break/>").replace( new RegExp( "&", "ig"), "&") ); - } - if ( pAdditionalData.AddData[addrdata[i][0]] != undefined ) - { - bulkbody = relaceAdditionValues( bulkbody, pAdditionalData.Fields, pAdditionalData.AddData[addrdata[i][0]], "" ); - } - // Tabellen füllen - for (ti = 0; ti < pTableData.length; ti++) - { - var tablepos = bulkbody.indexOf( getDefaultODTplaceholer(pTableData[ti].Table, true)); - if ( tablepos != -1 ) - { - var tablebegin = bulkbody.lastIndexOf("<table:table-row", tablepos); - var tableend = bulkbody.indexOf("</table:table-row>", tablepos ) + 18; - var lasttable = bulkbody.substr( tableend ); - var tablerow = bulkbody.substring( tablebegin, tableend ); - bulkbody = bulkbody.substring( 0, tablebegin ); - var tabledata = pTableData[ti].TableData[addrdata[i][0]]; - if ( tabledata != undefined ) - { - for (var tz = 0; tz < tabledata.length; tz++) - { - var table = tablerow; - bulkbody += relaceAdditionValues( table, pTableData[ti].Fields, tabledata[tz], pTableData[ti].Table + "." ); - } - } - bulkbody += lasttable; - } - } - 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 (z = 0; z < addrdata[0].length; z++) - { - styles = styles.replace( new RegExp( getDefaultODTplaceholer(addrdata[0][z]), "ig"), - addrdata[1][z].replace( new RegExp( "\n", "ig"), "<text:line-break/>").replace( new RegExp( "&", "ig"), "&") ); - } - if ( pAdditionalData.AddData[addrdata[1][0]] != undefined ) - { - styles = relaceAdditionValues( styles, pAdditionalData.Fields, pAdditionalData.AddData[addrdata[1][0]], "" ); - } - pack.addToZip(pODTFile, "styles.xml", util.encodeBase64String(styles)); - return true; - } - return false; - - function relaceAdditionValues( pText, pFields, pValues, pTable ) - { - for (var sp = 0; sp < pFields.length; sp++) - { - var ph = pFields[sp]; - var value = pValues[sp].toString(); - if ( typeof( ph ) == "object") - { - ph = pFields[sp][0]; - if ( value != "" ) - switch( pFields[sp][1] ) // Formatierung - { - case "date": - value = datetime.toDate(value, pFields[sp][2]); - break; - case "long": - value = text.formatLong(value, pFields[sp][2]); - break; - case "double": - value = text.formatDouble(value, translate.text(pFields[sp][2]), true); - break; - } - } - pText = pText.replace( new RegExp(getDefaultODTplaceholer(pTable + ph) , "ig"), - value.replace( new RegExp( "\n", "ig"), "<text:line-break/>").replace( new RegExp( "&", "ig"), "&") ); - } - return pText; - } + return this.templateText; } -/* -* Liefert Vorlage mit ersetzen Platzhalter durch den jeweiligen Text. -* -* @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 -* @param {[]} pAdditionalValues opt Weitere Platzhalter mit Werten -* -* @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.getTextTemplate = function ( pContactId, pDocuType, pLanguage, pAddressID, pSenderID, pTemplateName, pAdditionalValues ) +/** + * returns the template text with replaced placeholders + * + * @param {Object} pReplacements map, the structure is {placeholder : value} (the placeholder should have the prefix @@) + */ +DocumentTemplate.prototype.getReplacedText = function (pReplacements) { - var value = ""; - var document = chooseTemplate( pDocuType, pLanguage, pTemplateName ); - if ( !document ) return false; - - if ( pAdditionalValues == undefined ) pAdditionalValues = ""; - var html = 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 = db.table("select KEYNAME1, KEYNAME2, KEYDETAIL from KEYWORD where " + getKeyTypeSQL("EXPORTFIELDS")); - var addrdata = getAddressesData( [pContactId], config, pSenderID, pAddressID ); - for (var i = 0; i < addrdata[0].length; i++) - { - if (html) value = addrdata[1][i].replace( new RegExp( "\n", "ig"), "<br>" ); - else value = addrdata[1][i]; - document.template.data = document.template.data.replace( new RegExp( "@@" + addrdata[0][i], "ig"), value ); - } - for (i = 0; i < pAdditionalValues.length; i++) + switch (this.type) { - document.template.data = document.template.data.replace( new RegExp( "@@" + pAdditionalValues[i][0], "ig"), pAdditionalValues[i][1] ); + case DocumentTemplate.types.HTML: + for (let i in pReplacements) + pReplacements[i] = text.replaceAll(pReplacements[i], {"\n" : "<br>"}); + case DocumentTemplate.types.TXT: + return text.replaceAll(this.content, pReplacements); + case DocumentTemplate.types.ODT: + return this._getReplacedODT(pReplacements); + case DocumentTemplate.types.DOCX: + return this._getReplacedDOCX(pReplacements); + default: + return null; } - 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 - * - * @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) +DocumentTemplate.prototype.getReplacedTextByContactId = function (pContactId) { - if (pOnlyStart) - return "{@" + pPlaceholderName; - return "{@" + pPlaceholderName + "@}"; + var config = DocumentTemplate._getPlaceholderConfig(); + var replacements = getAddressesData([pContactId], config, pSenderID, pAddressID); + //TODO: build the replacement map here + return this.getReplacedText(replacements); } /* * 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 @@ -469,20 +178,174 @@ DocumentTemplateUtils.getReplacedODT = function (pTemplateData, pTemplateName, p return replacedFileData; } +DocumentTemplate.prototype._getReplacedODT = function (pReplacements) +{ + +} + /* * This function is used to replace placeholders via DocXTemplater - * @param {String} pInputB64 - BASE64 coded String of the document, which holds the placeholders - * @param {Object} pPlaceholder - Must contain an object, which holds the placeholders + * + * @param {Object} pReplacements - Must contain an object, which holds the placeholders * * @return {String} returns the modified document in a BASE64 coded string */ -DocumentTemplateUtils.getReplacedDocXDocumentB64 = function (pInputB64, pPlaceholder) +DocumentTemplate.prototype._getReplacedDOCX = function (pReplacements) { //this is executed as a process because of better performance var documentData = process.execute("getDocxDocument_serverProcess", { - templateb64: pInputB64 - ,placeholderConfig: JSON.stringify(pPlaceholder)//process.execute is only able to handle strings + templateb64: this.templateText, + placeholderConfig: JSON.stringify(pPlaceholder) //process.execute is only able to handle strings }); return documentData; } + +/** + * Provides functions for document templates + */ +function DocumentTemplateUtils () {} + +/** + * loads a document template and replaces the placeholders + */ +DocumentTemplateUtils.getSingleReplacedDocument = function (pTemplateId, pContactId) +{ + var template = DocumentTemplate.loadTemplate(pTemplateId); + return template.getReplacedTextByContactId(pContactId); +} + +/** + * @return {Object} map with placeholders and their definition + */ +DocumentTemplateUtils._getPlaceholderConfig = function () +{ + return KeywordData.getKeywordAttributeRelations($KeywordRegistry.textPlaceholder()); +} + + +/* +* 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 + + 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; +} + +/* +* 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) +{ + var document = chooseTemplate( pDocuType, pLanguage, pTemplateName); + if (!document) return null; + + 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++) + { + 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); + } + + 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 + "@}"; +} + + + + diff --git a/process/Email_lib/process.js b/process/Email_lib/process.js index c1e2613524f..7a75d85055b 100644 --- a/process/Email_lib/process.js +++ b/process/Email_lib/process.js @@ -73,14 +73,7 @@ function Email (pToRecipients, pSender, pSubject, pBody, pCcRecipients, pBccReci */ Email.prototype.setTemplate = function (pTemplateId) { - var alias = "_____SYSTEMALIAS"; - var templateDocument = db.getBinaryMetadata("DOCUMENTTEMPLATE", "DOCUMENT", pTemplateId, false, alias, null); - if (!templateDocument[0]) - return null; - var binaryId = templateDocument[0][db.BINARY_ID]; - if (binaryId) - this.body = util.decodeBase64String(db.getBinaryContent(binaryId, alias)); - return null; + this.body = DocumentTemplateUtils.getTemplateText(pTemplateId); } /** diff --git a/process/KeywordRegistry_basic/process.js b/process/KeywordRegistry_basic/process.js index 807d14d1482..a7c6e865b3f 100644 --- a/process/KeywordRegistry_basic/process.js +++ b/process/KeywordRegistry_basic/process.js @@ -101,4 +101,6 @@ $KeywordRegistry.classificationType$salesproject = function(){return "968eafa3-3 $KeywordRegistry.personGender = function(){return "PersonGender";}; $KeywordRegistry.personGender$other = function(){return "o";}; $KeywordRegistry.permissionCondType = function(){return "PermissionCondType";}; -$KeywordRegistry.permissionAccessType = function(){return "PermissionAccessType";}; \ No newline at end of file +$KeywordRegistry.permissionAccessType = function(){return "PermissionAccessType";}; + +$KeywordRegistry.textPlaceholder = function(){return "textPlaceholder";}; \ No newline at end of file -- GitLab