Skip to content
Snippets Groups Projects
process.js 27.7 KiB
Newer Older
Johannes Hörmann's avatar
Johannes Hörmann committed
import("system.logging");
S.Listl's avatar
S.Listl committed
import("Binary_lib");
S.Listl's avatar
S.Listl committed
import("Communication_lib");
import("system.neon");
import("Employee_lib");
import("KeywordRegistry_basic");
import("Document_lib");
import("KeywordData_lib");
import("Sql_lib");
import("Address_lib");
import("system.process");
import("system.vars");
import("system.db");
import("system.util");
import("system.pack");
import("system.fileIO");
import("system.translate");
import("system.datetime");
import("system.text");
import("system.mail");
import("Keyword_lib");
import("Placeholder_lib");
import("Email_lib");
import("MimeType_lib");
S.Listl's avatar
S.Listl committed

/**
 * Object for working with document templates, holds the content and type of the template.
 * Provides functions to replace placeholders in the content.
 * 
 * @class
 */
var DocumentTemplate = (function ()
{

/**
 * constructor for DocumentTemplate
 * 
 * @param {String} pTemplateContent content, as base64 string (except for DocumentTemplate.types.PLAIN, then it's a normal string)
 * @param {String} pType type of the template, use the DocumentTemplate.types constants here
Johannes Hörmann's avatar
Johannes Hörmann committed
 * @param {String} [pFilename=undefined] file name of the template 
 * @param {Boolean} [pResolveSubtemplates=false] if true subtemplates are resolved (if the type fits)
S.Listl's avatar
S.Listl committed
 */
Johannes Hörmann's avatar
Johannes Hörmann committed
function DocumentTemplate(pTemplateContent, pType, pFilename, pResolveSubtemplates)
S.Listl's avatar
S.Listl committed
{
    this.content = pTemplateContent;
    this.type = pType;
    this.filename = pFilename;
Johannes Hörmann's avatar
Johannes Hörmann committed
    this._stringCache = null;
    
    if (pResolveSubtemplates)
        this._resolveEmbeddedTemplate();
S.Listl's avatar
S.Listl committed
}

/**
 * @return {String} the text of the content
 */
DocumentTemplate.prototype.toString = function ()
Johannes Hörmann's avatar
Johannes Hörmann committed
{    
    if (this._stringCache == null)
    {
        if (this.type == DocumentTemplate.types.PLAIN)
            this._stringCache = this.content;
        else
            this._stringCache = text.parseDocument(this.content);
    }
    return this._stringCache;
}

DocumentTemplate.prototype._resolveEmbeddedTemplate = function ()
{    
    if (this.type == DocumentTemplate.types.PLAIN || this.type == DocumentTemplate.types.TXT || this.type == DocumentTemplate.types.HTML)
    {
        var replacedContent = "";
        if (this.type == DocumentTemplate.types.PLAIN)
        {
            replacedContent = this.content;
        }
        else
        {
            replacedContent = util.decodeBase64String(this.content);
        }
        
        var templates = [];
        // then load the possible replacement names
        if (this.type == DocumentTemplate.types.PLAIN || this.type == DocumentTemplate.types.TXT)
        {
            templates = db.table(SqlCondition.begin()
                        .andPrepare("DOCUMENTTEMPLATE.KIND", $KeywordRegistry.documentTemplateType$textModular())
                        .andPrepare("DOCUMENTTEMPLATE.CLASSIFICATION", $KeywordRegistry.documentTemplateTypeCategory$textTemplate())
                        .buildSql("select DOCUMENTTEMPLATEID, REPLACEMENTNAME from DOCUMENTTEMPLATE"));

        }
        else if (this.type == DocumentTemplate.types.HTML)
        {
            templates = db.table(SqlCondition.begin()
                        .andPrepare("DOCUMENTTEMPLATE.KIND", $KeywordRegistry.documentTemplateType$textModular())
                        .andPrepare("DOCUMENTTEMPLATE.CLASSIFICATION", $KeywordRegistry.documentTemplateTypeCategory$htmlTemplate())
                        .buildSql("select DOCUMENTTEMPLATEID, REPLACEMENTNAME from DOCUMENTTEMPLATE"));
        }
        
        var alias = SqlUtils.getSystemAlias();

        // We use callbacks which are called by pString.replace
        placeholders = templates.map(function(pTemplate) {
            // add function for each placeholder so that the db.getBinaryContent is only called, if the placeholder is replaced.
            return [pTemplate[1], function(matched, index, original) {
                var templateDocument = db.getBinaryMetadata("DOCUMENTTEMPLATE", "DOCUMENT", pTemplate[0], false, alias, null);
                var binaryId = templateDocument[0][db.BINARY_ID];
                return util.decodeBase64String(db.getBinaryContent(binaryId, alias));
            }];
        });

        // Note: some embedded templates in embedded templates may be replaced, but this is NOT SUPPORTED, as it only works if the second template is not already replaced at that time.
        placeholders.forEach(function(pPlaceholder) {
            replacedContent = replacedContent.replace("{@" + pPlaceholder[0] + "@}", pPlaceholder[1])
        }, this);
        
        this.content = util.encodeBase64String(replacedContent);
    }
S.Listl's avatar
S.Listl committed
}

/**
 * The types a DocumentTemplate can have. Depending on the type,
 * the correct method for replacing the placeholders can be chosen
 * 
 * @enum {String}
 */
DocumentTemplate.types = {
    TXT : "txt",
    HTML : "html",
    EML : "eml",
    ODT : "odt",
    DOCX : "docx",
    PLAIN : "plain", //for simple strings
    
    /**
     * chooses the type depending on the file extension
     */
S.Listl's avatar
S.Listl committed
    fromFileExtension : function (pFileExtension)
    {
        switch (pFileExtension)
        {
            case "html":
            case "htm":
                return this.HTML;
            case "eml":
                return this.EML;
            case "odt":
                return this.ODT;
            case "docx":
                return this.DOCX;
            case "txt":
                return this.TXT;
            case "msg":
            case "oft":
            default:
                return null;
S.Listl's avatar
S.Listl committed
        }
    },
    /**
     * chooses the type depending on the mime type
     */
S.Listl's avatar
S.Listl committed
    fromMimeType : function (pMimetype)
    {
        switch (pMimetype)
        {
            case MimeTypes.HTML():
S.Listl's avatar
S.Listl committed
                return this.HTML;
            case MimeTypes.EML():
S.Listl's avatar
S.Listl committed
                return this.EML;
            case MimeTypes.ODT():
S.Listl's avatar
S.Listl committed
                return this.ODT;
            case MimeTypes.DOCX():
S.Listl's avatar
S.Listl committed
                return this.DOCX;
            case MimeTypes.TXT():
S.Listl's avatar
S.Listl committed
                return this.TXT;
            case MimeTypes.MSG():
            default:
                return null;
S.Listl's avatar
S.Listl committed
        }
    }
};

/**
 * Loads the content of a document template and creates a new DocumentTemplate object with that.
 * 
 * @param {String} pAssignmentRowId id of the assignment (in most cases the document template id)
 * @param {String} [pAssignmentTable="DOCUMENTTEMPLATE"] the LOB assignment table
 * 
 * @return {DocumentTemplate} template object
 */
DocumentTemplate.loadTemplate = function (pAssignmentRowId, pAssignmentTable)
{
    var alias = SqlUtils.getSystemAlias();
S.Listl's avatar
S.Listl committed
    if (!pAssignmentTable)
        pAssignmentTable = "DOCUMENTTEMPLATE";
    var templateDocument = db.getBinaryMetadata(pAssignmentTable, "DOCUMENT", pAssignmentRowId, false, alias, null);
    if (!templateDocument[0])
        return new DocumentTemplate();
    var binaryId = templateDocument[0][db.BINARY_ID];
    var filename = templateDocument[0][db.BINARY_FILENAME];
    var mimetype = templateDocument[0][db.BINARY_MIMETYPE];
    var type = DocumentTemplate.types.fromMimeType(mimetype);
    
Johannes Hörmann's avatar
Johannes Hörmann committed
    return new DocumentTemplate(db.getBinaryContent(binaryId, alias), type, filename, true);
S.Listl's avatar
S.Listl committed
}

/**
 * makes a DocumentTemplate from a upload value
 * 
S.Listl's avatar
S.Listl committed
 * @param {FileUpload} pDocumentUpload FileUpload object
 * @return {DocumentTemplate} a document template
 */
S.Listl's avatar
S.Listl committed
DocumentTemplate.fromUpload = function (pDocumentUpload)
S.Listl's avatar
S.Listl committed
    var type;
    
    //if the mimetype couldn't be determined, check the file extension
S.Listl's avatar
S.Listl committed
    if (pDocumentUpload.mimeType == MimeTypes.BIN())
        type = DocumentTemplate.types.fromFileExtension(pDocumentUpload.fileExtension);
S.Listl's avatar
S.Listl committed
    else
S.Listl's avatar
S.Listl committed
        type = DocumentTemplate.types.fromMimeType(pDocumentUpload.mimeType);
Johannes Hörmann's avatar
Johannes Hörmann committed
    return new DocumentTemplate(pDocumentUpload.bindata, type, pDocumentUpload.filename, true);
}

/**
 * Function that helps to get the correct template when editing a bulk mail.
 * pUploadValue is preferred over pTemplateId, and if pEditedContent is provided,
 * it will overwrite the content of the template (but the type will remain the same as
 * defined by the upload or templateId, if both are empty, pDefaultType is used)
S.Listl's avatar
S.Listl committed
 * 
 * @param {String} pTemplateId
 * @param {FileUpload} pDocumentUpload
 * @param {String} [pEditedContent]
 * @param {String} [pDefaultType]
 * @return {DocumentTemplate} the document template
S.Listl's avatar
S.Listl committed
DocumentTemplate.getSelectedTemplate = function (pTemplateId, pDocumentUpload, pEditedContent, pDefaultType)
S.Listl's avatar
S.Listl committed
    if (pDocumentUpload.isFilled())
        template = DocumentTemplate.fromUpload(pDocumentUpload);
    else if (pTemplateId)
        template = DocumentTemplate.loadTemplate(pTemplateId);
    else
Johannes Hörmann's avatar
Johannes Hörmann committed
        template = new DocumentTemplate(null, pDefaultType || DocumentTemplate.types.TXT, null, true);
    
    if (pEditedContent)
    {
        if (template.type == DocumentTemplate.types.EML || template.type == DocumentTemplate.types.HTML)
            pEditedContent = "<html>" + pEditedContent + "</html>";
        template.content = util.encodeBase64String(pEditedContent);
    }
    return template;
}

S.Listl's avatar
S.Listl committed
/** 
 * Returns the template content with replaced placeholders by choosing the right
 * replace function for the type.
 * 
 * @param {Object} pReplacements map, the structure is {placeholder : value}
 * @param {boolean} pEncoded if the replaced content should be base64 encoded
 *                            (doesn't affect odt/docx)
 * 
 * @return {String} the replaced content
 */
DocumentTemplate.prototype.getReplacedContent = function (pReplacements, pEncoded)
{
Johannes Hörmann's avatar
Johannes Hörmann committed
    // if there exists a _subtemplatedContent we use it because then I assume that the replacements are already based on content + subtemplates
    var content;
    if (this._subtemplatedContent == null)
        content = this.content
    else
        content = this._subtemplatedContent
    
S.Listl's avatar
S.Listl committed
    switch (this.type)
    {
        case DocumentTemplate.types.HTML:
            for (let i in pReplacements)
                pReplacements[i] = text.text2html(pReplacements[i], false);
        case DocumentTemplate.types.TXT:
Johannes Hörmann's avatar
Johannes Hörmann committed
            let decodedContent = util.decodeBase64String(content);
S.Listl's avatar
S.Listl committed
            let encodedContent = TemplateHelper._replaceText(decodedContent, pReplacements);
            if (pEncoded)
                encodedContent = util.encodeBase64String(encodedContent);
            return encodedContent;
        case DocumentTemplate.types.EML:
Johannes Hörmann's avatar
Johannes Hörmann committed
            let emlContent = TemplateHelper._getReplacedEML(this, pReplacements);
S.Listl's avatar
S.Listl committed
            if (pEncoded)
Johannes Hörmann's avatar
Johannes Hörmann committed
                emlContent = util.encodeBase64String(emlContent);
            return emlContent;
S.Listl's avatar
S.Listl committed
        case DocumentTemplate.types.ODT:
            return TemplateHelper._getReplacedODT(this, pReplacements);
        case DocumentTemplate.types.DOCX:
            return TemplateHelper._getReplacedDOCX(this, pReplacements);
        case DocumentTemplate.types.PLAIN:
            let plainText = TemplateHelper._replaceText(this.content, pReplacements);
            if (pEncoded)
                plainText = util.encodeBase64String(plainText);
            return plainText;
        default:
            return null;
    }
}

/**
 * replaces the placeholders with data from one contact and returns the result
 */
DocumentTemplate.prototype.getReplacedContentByContactId = function (pContactId, pEncoded) 
{
    var replacements = TemplateHelper._getReplacementsByContactIds(this, [pContactId]); 
    var content = this.getReplacedContent(replacements[pContactId], pEncoded);
    
    return content;
}

/**
 * replaces the placeholders with data from the contacts and returns the result
 * 
 * @param {Array} pContactIds contact ids
 * @param {boolean} pEncoded if the replaced content should be base64 encoded
 * 
 * @return {Object} replaced content for every contactId
 */
DocumentTemplate.prototype.getReplacedContentByContactIds = function (pContactIds, pEncoded) 
{
    var replacements = TemplateHelper._getReplacementsByContactIds(this, pContactIds);
    var contents = {};
    for (let contactId in replacements)
    {
        contents[contactId] = this.getReplacedContent(replacements[contactId], pEncoded);
    }
    return contents;
}

/**
 * Replaces the placeholders with data from the contacts and returns a serial letter, works
 * only for ODT
 * 
 * @param {Array} pContactIds contact ids
 * @param {Object[][][]} pTableData Table data for the document, as a three-dimensional array 
 *          of objects (dimensions are: document, table in that document, rows of the table). For the format, see example.
 * 
 * @example 
 * var contactSql = SqlCondition.begin()
 *       .andPrepare("CONTACT.ORGANISATION_ID", orgId)
 *       .buildSql("select FIRSTNAME, LASTNAME from CONTACT join PERSON on CONTACT.PERSON_ID = PERSON.PERSONID");
 *
 *   var contacts = db.table(contactSql);
 *   var tblRows = [];
 *   fnamePlaceholder = PlaceholderUtils.formatPlaceholder("fname");
 *   lnamePlaceholder = PlaceholderUtils.formatPlaceholder("lname");
 *
 *   for (let i = 0; i < contacts.length; i++)
 *   {
 *       let names = {};
 *       names[fnamePlaceholder] = contacts[i][0];
 *       names[lnamePlaceholder] = contacts[i][1];
 *       tblRows.push(names);
 *   }
 *
 *   var tables = [tblRows];
 *   var template = DocumentTemplate.loadTEmplate(templateId);
 *   var letter = template.getSerialLetterByContactIds([contactId], [tables]);
 * 
 * @return {Object} the content of the replaced ODT
 */
DocumentTemplate.prototype.getSerialLetterByContactIds = function (pContactIds, pTableData)
{
    if (this.type == DocumentTemplate.types.ODT)
    {
        let replacements = TemplateHelper._getReplacementsByContactIds(this, pContactIds);
        let replaceArray = [];
        for (let i = 0, l = pContactIds.length; i < l; i++)
            replaceArray.push(replacements[pContactIds[i]]);
        return TemplateHelper._getReplacedODT(this, replaceArray, pTableData);
    }
    return null;
}

/**
 * Replaces the placeholders with data from the contacts and returns the resulting Emails.
 * 
 * @param {Array} pContactIds contact ids
 * 
 * @return {Object} Object containing the contact ids as keys and the corresponding Email
 *                   objects as values
 */
DocumentTemplate.prototype.getReplacedEmailsByContactIds = function (pContactIds) 
{
    var replacements = TemplateHelper._getReplacementsByContactIds(this, pContactIds);
    var emailObj = {};
    for (let contactId in replacements)
    {
        if (this.type == DocumentTemplate.types.EML)
        {
            //use the special function for EML to also fill subject and sender
            emailObj[contactId] = TemplateHelper._getReplacedEML(this, replacements[contactId], true);
        }
        else
        {
            let body = this.getReplacedContent(replacements[contactId]);
            if (this.type == DocumentTemplate.types.TXT || this.type == DocumentTemplate.types.PLAIN)
                body = text.text2html(body, false);
            emailObj[contactId] = new Email(null, null, null, body);
        }
    }
    return emailObj;
}

/**
 * Provides functions for the DocumentTemplate object that aren't accessible from outside
 */
function TemplateHelper () {}
/**
 * Replace function that works with strings instead of regular expressions
 * so that control characters (for example '{', '}') don't have to be escaped.
 */
TemplateHelper._replaceText = function (pText, pReplacements)
{
    for (let placeholder in pReplacements)
        pText = pText.replace(placeholder, pReplacements[placeholder], "ig");
    return pText;
}

/**
 * returns the 'simpleName' of all placeholders that are used in the template
 * 
 * @private
 */
TemplateHelper._getRequiredPlaceholders = function (pTemplate)
{
    var allPlaceholders = PlaceholderUtils.getPlaceholders();
    var plainText = pTemplate.toString();
    var usedPlaceholders = [];
    for (let i = 0, l = allPlaceholders.length; i < l; i++)
    {
        if (plainText.indexOf(allPlaceholders[i]) !== -1)
            usedPlaceholders.push(allPlaceholders[i]);
    }
    return usedPlaceholders; 
}

/**
 * Builds an object with the placeholder data for multiple contacts
 * 
 * @param {DocumentTemplate} pTemplate document template
 * @param {Array} pContactIds contact ids
 * 
 * @return {Object} Object containing the data. The structure is like {contactId : {placeholderName : replacementValue, ...}, ...}
 * 
 * @private
 */
TemplateHelper._getReplacementsByContactIds = function (pTemplate, pContactIds)
S.Listl's avatar
S.Listl committed
    var config = TemplateHelper._getRequiredPlaceholders(pTemplate);
    var contactIdPlaceholder = new Placeholder("contactId", Placeholder.types.SQLPART, "CONTACT.CONTACTID");
    config = [contactIdPlaceholder].concat(config);
S.Listl's avatar
S.Listl committed
    var addressData = getAddressesData(pContactIds, config, EmployeeUtils.getCurrentContactId()); //TODO: add sender selection
    var replacements = {};
    var placeholderNames = addressData[0];
    var contactIdIndex = placeholderNames.indexOf(contactIdPlaceholder.toString());
    for (let i = 1; i < addressData.length; i++)
    {
        let contactId = addressData[i][contactIdIndex];
        for (let ii = 0, ll = placeholderNames.length; ii < ll; ii++)
        {
            if (!(contactId in replacements))
                replacements[contactId] = {};
            replacements[contactId][placeholderNames[ii]] = addressData[i][ii];
        }
    }
    return replacements;
}

/**
 * Replaces placeholders for EML
 * 
 * @param {DocumentTemplate} pTemplate document template
 * @param {Object} pReplacements mapping with replacements for every placeholder
 * @param {boolean} [pGetEmail] if true, return an Email object (use this if the sender and subject are required)
 * 
 * @return {String|Email} the replaced content
 * 
 * @private
 */
TemplateHelper._getReplacedEML = function (pTemplate, pReplacements, pGetEmail)
{
    var email = Email.fromRFC(pTemplate.content);
    email.body = TemplateHelper._replaceText(email.body, pReplacements);
    if (!pGetEmail)
        return email.body;
    
    email.sender = TemplateHelper._replaceText(email.sender, pReplacements);
    email.subject = TemplateHelper._replaceText(email.subject, pReplacements);
    
    return email;
}

/*
 * replaces a given Odt-File on the server and returns the replaced base64-file
 *
 * @param {DocumentTemplate} pTemplate document template
 * @param {Object} pReplacements map of placeholders and replacements
 * @param {Array} pTableData
 *
 * @return {String} base64-encoded replaced file
 * 
 * @private
 */
TemplateHelper._getReplacedODT = function (pTemplate, pReplacements, pTableData)
{
    //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() + "/" + pTemplate.filename.replace(/\\/g, "/");
    
    fileIO.storeData(serverFilePath, pTemplate.content, util.DATA_BINARY, false);
    if (!_replaceODTFile(pReplacements, serverFilePath, pTableData))
        return null;

    var replacedFileData = fileIO.getData(serverFilePath, util.DATA_BINARY);
    fileIO.remove(serverFilePath);

    return replacedFileData;
    
    /**
    * replaces placeholders in a odt file
    *
    * @param {Object} pReplacements replacement object
    * @param {String} pODTFileName filename of the odt
    * @param {Array} pTableData
    * 
    * @return {Boolean}
    */
    function _replaceODTFile (pReplacements, pODTFileName, pTableData)
    {
        var senderRelId = EmployeeUtils.getCurrentContactId();
        if (senderRelId == null)
            return false;
        if (pReplacements.length === undefined)
            pReplacements = [pReplacements];
        if (!pTableData)
            pTableData = [];
        
        if (pReplacements.length !== 0)
        {
            //replace placeholders in content.xml
            var contentXml = util.decodeBase64String(pack.getFromZip(pODTFileName, "content.xml"));
            var bodybegin = contentXml.indexOf("<office:body>");
            var bodyend =  contentXml.indexOf("</office:body>") + 14;
            
            var bodyTemplate = contentXml.substring(bodybegin, bodyend);
            var fullBody = "";  //body that contains all pages (required when the replacing is done for several contacts)
            var beforeBody = contentXml.substring(0, bodybegin);
            var afterBody = contentXml.substr(bodyend);
            
            for (let i = 0, l = pReplacements.length; i < l; i++)
            {
                let replacements = pReplacements[i];
                let currentBody = bodyTemplate;
            
                /* This only works if the text of the placeholders in the odt were not edited since they were written.
                 * If you edit the odt and change a placeholder (for example: you change '{@addres@}' to '{@address@}'),
                 * the text is saved in different XML tags and won't be replaced correctly.
                 */
                for (let placeholder in replacements)
                {
                    currentBody = currentBody.replace(placeholder,
                        replacements[placeholder].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&amp;"), "ig");
                }
                
                
                let tables = pTableData[i] || [];
                let fromIndex = 0;
                for (let tblIndex = 0; tblIndex < tables.length; tblIndex++) //iterate over all tables in the document
                {
                    let tableData = tables[tblIndex];
                    if (tableData && tableData.length > 0)
                    {
                        fromIndex = currentBody.indexOf("</table:table>", fromIndex) + 14;
                        if (fromIndex === -1) //stop if there is no table
                            break;
                        
                        let rowBegin = currentBody.lastIndexOf("<table:table-row", fromIndex);
                        let rowEnd =  currentBody.indexOf("</table:table-row>", rowBegin) + 18;
                        
                        let afterTable = currentBody.substr(rowEnd);
                        let tableRow = currentBody.substring(rowBegin, rowEnd);
                        currentBody = currentBody.substring(0, rowBegin);
                        
                        for (let rowIndex = 0; rowIndex < tableData.length; rowIndex++)
                        {
                            let tableRowData = tableData[rowIndex];
                            currentBody += TemplateHelper._replaceText(tableRow, tableRowData);
                        }
                        currentBody += afterTable;
                    }
                }
                fullBody += currentBody;
            }   
            contentXml = beforeBody + fullBody + afterBody;
            pack.addToZip(pODTFileName, "content.xml", util.encodeBase64String(contentXml));
            
            //replace placeholders in styles.xml
            var styles = util.decodeBase64String(pack.getFromZip(pODTFileName, "styles.xml"));
            for (let placeholder in pReplacements[0])
            {
                styles = styles.replace(placeholder,
                    pReplacements[0][placeholder].replace(/\n/ig, "<text:line-break/>").replace(/&/ig, "&amp;"), "ig");
            }
            pack.addToZip(pODTFileName, "styles.xml", util.encodeBase64String(styles));
            return true;
        }
        return false;
    }
}

/*
 * This function is used to replace placeholders via DocXTemplater
 * 
 * @param {DocumentTemplate} pTemplate document template
 * @param {Object} pReplacements - Must contain an object, which holds the placeholders
 * 
 * @return {String} returns the modified document in a BASE64 coded string
 * 
 * @private
 */
TemplateHelper._getReplacedDOCX = function (pTemplate, pReplacements)
{
    var replacements = {};
    for (let placeholder in pReplacements)  //removes the prefix and postfix, the process needs it like this
        replacements[placeholder.slice(2, -2)] = pReplacements[placeholder];

    //this is executed as a process because of better performance
    var documentData = process.execute("getDocxDocument_serverProcess", {
        templateb64: pTemplate.content,
        placeholderConfig: JSON.stringify(replacements) //process.execute is only able to handle strings
    });

    return documentData;
}

    return DocumentTemplate;

})();

/**
 * functions for working with letters (mails)
 */
function LetterUtils () {}

/**
 * opens a new letter
 * 
 * @param {String} pContactId id of the contact to fetch the data from
 */
LetterUtils.openNewLetter = function (pContactId)
{
    var params = {
        "ContactId_param" : pContactId
    };
    neon.openContext("Letter", "LetterEdit_view", null, neon.OPERATINGSTATE_NEW, params);
S.Listl's avatar
S.Listl committed
}

/**
 * utility functions for the DocumentTemplate_entity
 */
function DocumentTemplateUtils () {}

/**
 * if pText is provided, it is used as template, otherwise pFileUpload
 * 
 * @param {FileUpload} pFileUpload upload value
 * @param {String} pText text input
 * @param {String} pClassification the classification type. Used if pText is not empty. Defines if it is saved as txt or html.
S.Listl's avatar
S.Listl committed
 * @param {String} pTemplateName name of the template
 * @return {FileUpload} a FileUpload object with the data
 */
DocumentTemplateUtils.chooseSuppliedTemplate = function (pFileUpload, pText, pClassification, pTemplateName)
S.Listl's avatar
S.Listl committed
{
    if (!pFileUpload.isFilled() && pText != "")
    {
        pFileUpload.filename = pTemplateName;
Johannes Hörmann's avatar
Johannes Hörmann committed
        // if it is a htmlTemplate save it with the html extension
        if (pClassification == $KeywordRegistry.documentTemplateTypeCategory$htmlTemplate())
            pFileUpload.fileExtension = "html";
        else
            pFileUpload.fileExtension = "txt";
        
S.Listl's avatar
S.Listl committed
        pFileUpload.bindata  = util.encodeBase64String(pText);
    }
    return pFileUpload;
}

/**
 * inserts a template from a document template into ASYS_BINARIES
 */
DocumentTemplateUtils.insertTemplateData = function (pTemplateId, pFileUpload, pKind, pText, pClassification, pTemplateName)
    var textInput = pKind == $KeywordRegistry.documentTemplateType$textModular() ? pText : "";

    pFileUpload = DocumentTemplateUtils.chooseSuppliedTemplate(pFileUpload, textInput, pClassification, pTemplateName)
Johannes Hörmann's avatar
Johannes Hörmann committed
    if (pFileUpload.isFilled())
S.Listl's avatar
S.Listl committed
    {
        db.insertBinary("DOCUMENTTEMPLATE", "DOCUMENT", pTemplateId, 
Johannes Hörmann's avatar
Johannes Hörmann committed
            "", pFileUpload.bindata, pFileUpload.filename, "", "", SqlUtils.getSystemAlias());
S.Listl's avatar
S.Listl committed
    }
}

/**
 * updates a template from a document template in ASYS_BINARIES
 */
DocumentTemplateUtils.updateTemplateData = function (pTemplateId, pFileUpload, pKind, pText, pClassification, pTemplateName)
    var textInput = pKind == $KeywordRegistry.documentTemplateType$textModular() ? pText : "";
    pFileUpload = DocumentTemplateUtils.chooseSuppliedTemplate(pFileUpload, textInput, pClassification, pTemplateName)
S.Listl's avatar
S.Listl committed
    if (pFileUpload.isFilled())
    {
        var assignmentTable = "DOCUMENTTEMPLATE";
        var assignmentName= "DOCUMENT";
        var binMeta = db.getBinaryMetadata(assignmentTable, assignmentName, pTemplateId, false, SqlUtils.getSystemAlias(), "MAINDOCUMENT");
        if (binMeta.length == 0)
            SingleBinaryUtils.insertMainDocument(assignmentTable, assignmentName, pTemplateId, pFileUpload.bindata, pFileUpload.filename, null, SqlUtils.getSystemAlias());
        else
            db.updateBinary(binMeta[0][db.BINARY_ID], "", pFileUpload.bindata, pFileUpload.filename, "", "MAINDOCUMENT", SqlUtils.getSystemAlias());
    }
S.Listl's avatar
S.Listl committed
}