Skip to content
Snippets Groups Projects
process.js 14.6 KiB
Newer Older
Johannes Hörmann's avatar
Johannes Hörmann committed
import("system.translate");
import("ActivityTask_lib");
import("system.util");
import("Contact_lib");
import("system.datetime");
import("system.neon");
import("Employee_lib");
import("system.vars");
import("KeywordRegistry_basic");
import("Sql_lib");
import("system.db");
import("DocumentTemplate_lib");
import("Communication_lib");
import("Email_lib");
import("system.process");
import("system.notification");

/**
 * functions for bulk mails
 */
function BulkMailUtils () {}

/**
 * Executes a process to send bulk mails on the server and creates a notification when finished.
 * 
 * @param {String} pBulkMailId id of the bulk mail
 * @param {Array} [pTestRecipients] overwrite the recipients (e.g. for testing)
 * @param {String} [pUser=currentUser] User that will get the notification, if null (not undefined!), no notification
 *                                      will be created.
 */
BulkMailUtils.sendBulkMailOnServer = function (pBulkMailId, pTestRecipients, pUser)
{
    if (pUser === undefined)
        pUser = EmployeeUtils.getCurrentUserId();
    process.execute("sendBulkMail_serverProcess", 
        {
            bulkMailId : pBulkMailId,
            testRecipients : JSON.stringify(pTestRecipients),
            user : pUser || ""
        }
    );
}

/**
 * Sends a bulk mail. You should only call this function on the server because it
 * can take some time to execute, use BulkMailUtils.sendBulkMailOnServer instead.
 * 
 * @param {String} pBulkMailId id of the bulk mail 
 * @param {Array} [pTestRecipients] overwrite the recipients (e.g. for testing)
 * 
 * @return {Object} count of sucessful and failed mails 
 */
BulkMailUtils.sendBulkMail = function (pBulkMailId, pTestRecipients)
{
    var [templateId, subject, emailSender, createActivity, bulkMailName] = db.array(db.ROW, SqlCondition.begin()
        .andPrepare("BULKMAIL.BULKMAILID", pBulkMailId)
        .buildSql("select DOCUMENTTEMPLATE_ID, SUBJECT, SENDER, CREATEACTIVITIES, NAME from BULKMAIL", "1=2")
    );
    var template = BulkMailUtils.getBulkMailTemplate(pBulkMailId, templateId, true);
Johannes Hörmann's avatar
Johannes Hörmann committed
    var recipientData;
    if (pTestRecipients)
    {
        recipientData = pTestRecipients.map(function (row)
        {
            return ["", row[0], row[1], "", ""];
        });
    }
    else
    {
        recipientData = db.table(SqlBuilder.begin()
            .select("BULKMAILRECIPIENTID, BULKMAILRECIPIENT.CONTACT_ID, (" + CommUtil.getStandardSubSqlMail() + "), PERSON_ID, ORGANISATION_ID")
            .from("CONTACT")
            .join("BULKMAILRECIPIENT", "BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
            .where(SqlCondition.begin()
                .andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
                .andPrepare("BULKMAILRECIPIENT.STATUS", $KeywordRegistry.bulkMailRecipientStatus$sent(), "# != ?")
                .andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$mail(), true)))
            .build()
        );
    }
    var contactIds = recipientData.map(function (e) {return e[1];});
    var successIds = [];
    var failedIds = [];
    var sentDate = vars.get("$sys.date");
    var mails = Email.getReplacedBulkEmails(template, contactIds);
Johannes Hörmann's avatar
Johannes Hörmann committed
    
    var subjectTemplate = new DocumentTemplate(subject, DocumentTemplate.types.PLAIN);
    var subjects = subjectTemplate.getReplacedContentByContactIds(contactIds);
    
    var bulkMailLink = [["BulkMail", pBulkMailId]];
    var activitySubject = translate.withArguments("Bulk mail \"%0\" sent", [bulkMailName]);
    
    for (let i = 0, l = recipientData.length; i < l; i++)
    {
        let isSuccess = false;
        let contactId = recipientData[i][1];
        let email = mails[contactId];
        if (email !== undefined && recipientData[i][2])
        {
            email.toRecipients = [recipientData[i][2]];
            email.sender = emailSender;
            email.subject = subjects[contactId];

            isSuccess = email.send();
        }
        if (recipientData[i][0])    //set the recipient status to 'sent' or 'failed'
        {
            Array.prototype.push.call(isSuccess ? successIds : failedIds, recipientData[i][0]);
            if (isSuccess && createActivity == "1")
            {
                let activityData = {
                    categoryKeywordId : $KeywordRegistry.activityCategory$mail(),
                    directionKeywordId : $KeywordRegistry.activityDirection$outgoing(),
                    subject : activitySubject,
                    content : email.body
                };
                let contactLink = [[ContactUtils.getContextByPersOrg(recipientData[i][3], recipientData[i][4]), recipientData[i][1]]];
                ActivityUtils.insertNewActivity(activityData, bulkMailLink.concat(contactLink));
            }
        }
    }
    if (successIds.length > 0)
        db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$sent(), sentDate], 
            SqlCondition.begin()
                .andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", successIds)
                .build("1=2")
        );
    if (failedIds.length > 0)
        db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$failed(), sentDate], 
            SqlCondition.begin()
                .andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", failedIds)
                .build("1=2")
        );
    
    if (!pTestRecipients) //if its just a test run, don't set the status to sent
        db.updateData("BULKMAIL", ["STATUS"], null, [$KeywordRegistry.bulkMailStatus$sent()], 
            SqlCondition.equals("BULKMAIL.BULKMAILID", pBulkMailId, "1=2"));
        
    return {
        sucessful : successIds.length,
        failed : failedIds.length
    };
}

/**
 * opens a context to select a bulk mail to add recipients to
 * 
 * @param {String[]} pContactIds recipients that should be added
 */
BulkMailUtils.openAddRecipientView = function (pContactIds)
{
    var params = {
        "ContactIds_param" : pContactIds
    };
    neon.openContext("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
}

/**
 * deletes all bulk mail recipients that have a commrestriction for emails
 * 
 * @param {String} pBulkMailId
 */
BulkMailUtils.removeCommRestrictionRecipients = function (pBulkMailId)
{
    var recipientIds = db.array(db.COLUMN, SqlBuilder.begin()
        .select("BULKMAILRECIPIENTID")
        .from("BULKMAILRECIPIENT")
        .join("CONTACT", SqlCondition.begin()
            .and("BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
            .andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$mail())))
        .where(SqlCondition.begin()
            .andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId))
        .build());

    if (recipientIds.length)
    {
        db.deleteData("BULKMAILRECIPIENT", SqlCondition.begin()
            .andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", recipientIds)
            .build("1=2"));
    }
}

/**
 * adds recipients to a bulkmail
 * 
 * @param {String} pBulkMailId bulk mail id
 * @param {String[]} pContactIds contact ids of the recipients
 */
BulkMailUtils.addRecipients = function (pBulkMailId, pContactIds)
{
    var columns = [
        "BULKMAILRECIPIENTID",
        "BULKMAIL_ID",
        "CONTACT_ID",
        "STATUS"
    ];
    var inserts = [];
    for (let i = 0, l = pContactIds.length; i < l; i++)
    {
        inserts.push(["BULKMAILRECIPIENT", columns, null, [util.getNewUUID(), pBulkMailId, pContactIds[i], $KeywordRegistry.bulkMailRecipientStatus$pending()]]);
    }
    db.inserts(inserts);
}

/**
 * Loads the document template of a bulk mail. If the bulk mail itself has a
 * template, it is preferred over the documentTemplate-id.
 * 
 * @param {String} pBulkMailId bulkmail id
 * @param {String} pDocumentTemplateId documentTemplate id
 * @param {Boolean} [pResolveSubtemplates=true] if true subtemplates are resolved (if the type fits)
 * 
 * @return {DocumentTemplate} the document template, null if no content was found.
 */
BulkMailUtils.getBulkMailTemplate = function (pBulkMailId, pDocumentTemplateId, pResolveSubtemplates)
{
    var bulkTemplate = DocumentTemplate.loadTemplate(pBulkMailId, "BULKMAIL", pResolveSubtemplates);
    var documentTemplate = DocumentTemplate.loadTemplate(pDocumentTemplateId, undefined, pResolveSubtemplates);

    if (!bulkTemplate.content)
    {
        return documentTemplate;
    }
    else
    {
        bulkTemplate.setAttachments(documentTemplate.getAttachments());
        return bulkTemplate;
    }
Johannes Hörmann's avatar
Johannes Hörmann committed
}

/**
 * checks if a contact is a recipient of a bulk mail
 * 
 * @param {String} pBulkMailId bulkmail id
 * @param {String} pContactId contact id
 * @param {String} pRecipientId bulkmailrecipient id
 * @return {boolean} true, if the contact is a recipient
 */
BulkMailUtils.isRecipient = function (pBulkMailId, pContactId, pRecipientId)
{
    return db.cell(SqlCondition.begin()
        .andPrepare("BULKMAILRECIPIENT.CONTACT_ID", pContactId)
        .andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
        .andPrepareIfSet("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", pRecipientId, "# != ?")
        .buildSql("select count(*) from BULKMAILRECIPIENT") //TODO: is there a way exists could be used?
    ) != "0";
}

/**
 * opens the BulkMail context in new mode
 * 
 * @param {String[]} [pRecipients] recipients that should be added after creation
 */
BulkMailUtils.newBulkMail = function (pRecipients)
{
    var params = {
        "PresetRecipients_param" : JSON.stringify(pRecipients)
    };
    neon.openContext("BulkMail", "BulkMailEdit_view", null, neon.OPERATINGSTATE_NEW, params);
}

/**
 * Filters the given contactIds if they can be added as new recipients.
 * Checks if a contact is already a recipient or if there is a advertising ban.
 * 
 * @param {String} pBulkMailId id of the bulk mail the contacts should be added to
 * @param {String[]} pContactIds contacts to filter
 * @return {String[]} contacts that can be added as recipients
 */
BulkMailUtils.filterNewRecipients = function (pBulkMailId, pContactIds)
{
    var existsQuery = "not exists(select BULKMAILRECIPIENTID from BULKMAILRECIPIENT where BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID and # = ?)";
    var query = SqlCondition.begin()
        .andIn("CONTACT.CONTACTID", pContactIds)
        .andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId, existsQuery) //only add contacts that aren't already recipients
        .andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$mail(), true))  //check if there's a commrestriction
        .buildSql("select CONTACTID from CONTACT");

    return db.array(db.COLUMN, query); 
}

/**
 * opens the given bulk mail
 */
BulkMailUtils.openBulkMail = function (pBulkMailId)
{
    neon.openContext("BulkMail", "BulkMailMain_view", [pBulkMailId], neon.OPERATINGSTATE_VIEW, null);
}

/**
 * checks is the given mime type can be used for a bulk mail
 * 
 * @param {String} pMimeType mime type
 * @return {Boolean} wheter the type is usable or not
 */
BulkMailUtils.isValidMimeType = function (pMimeType)
{
    var templateType = DocumentTemplate.types.fromMimeType(pMimeType);
    return BulkMailUtils.isValidTemplateType(templateType)
}

/**
 * checks is the given template type can be used for a bulk mail
 * 
 * @param {String} pTemplateType template type
 * @return {Boolean} wheter the type is usable or not
 */
BulkMailUtils.isValidTemplateType = function (pTemplateType)
{
    switch (pTemplateType)
Johannes Hörmann's avatar
Johannes Hörmann committed
    {
        case DocumentTemplate.types.EML:
        case DocumentTemplate.types.HTML:
        case DocumentTemplate.types.TXT:
            return true;
        default:
            return false;
    }
}

function SerialLetterUtils () {}

/**
 * adds recipients to a serial letter
 * 
 * @param {String} pSerialLetterId serial letter id
 * @param {String[]} pContactIds contact ids of the recipients
 */
SerialLetterUtils.addRecipients = function (pSerialLetterId, pContactIds)
{
    var columns = [
        "LETTERRECIPIENTID",
        "SERIALLETTER_ID",
        "CONTACT_ID"
    ];
    var inserts = [];
    for (let i = 0, l = pContactIds.length; i < l; i++)
    {
        inserts.push(["LETTERRECIPIENT", columns, null, [util.getNewUUID(), pSerialLetterId, pContactIds[i]]]);
    }
    db.inserts(inserts);
}

/**
 * opens a context to select a serial letter to add recipients to
 * 
 * @param {String[]} pContactIds recipients that should be added
 */
SerialLetterUtils.openAddRecipientView = function (pContactIds)
{
    var params = {
        "ContactIds_param" : pContactIds
    };
    neon.openContext("SerialLetterAddRecipients", "SerialLetterAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
}

/**
 * executes a server process that builds a serial letter
 * 
 * @param {String} pSerialLetterId serial letter id
 * @param {String[]} [pRecipientIds] Letter recipient ids of that should be used.
 *                                    If omitted, all recipients of the letter will be used.
 */
SerialLetterUtils.buildSerialLetter = function (pSerialLetterId, pRecipientIds)
{
    process.execute("buildSerialLetter_serverProcess", {
        "serialLetterId" : pSerialLetterId,
        "recipientIds" : JSON.stringify(pRecipientIds)
    });
}

/**
 * checks if a contact is a recipient of a serial letter
 * 
 * @param {String} pSerialLetterId serial letter id
 * @param {String} pContactId contact id
 * @param {String} [pRecipientId] letter recipient id
 * @return {boolean} true, if the contact is a recipient
 */
SerialLetterUtils.isRecipient = function (pSerialLetterId, pContactId, pRecipientId)
{
    return db.cell(SqlCondition.begin()
        .andPrepare("LETTERRECIPIENT.CONTACT_ID", pContactId)
        .andPrepare("LETTERRECIPIENT.SERIALLETTER_ID", pSerialLetterId)
        .andPrepareIfSet("LETTERRECIPIENT.LETTERRECIPIENTID", pRecipientId, "# != ?")
        .buildSql("select count(*) from LETTERRECIPIENT") //TODO: is there a way exists could be used?
    ) != "0";
}

SerialLetterUtils.openSerialLetter = function (pSerialLetterId)
{
    neon.openContext("SerialLetter", "SerialLetterMain_view", [pSerialLetterId], neon.OPERATINGSTATE_VIEW, null);
}

/**
 * Loads the document template of a serial letter. If the serial letter itself has a
 * template, it is preferred over the documentTemplate-id.
 * 
 * @param {String} pLetterId serial letter id
 * @param {String} pDocumentTemplateId documentTemplate id
 * 
 * @return {DocumentTemplate} the document template
 */
SerialLetterUtils.getSerialLetterTemplate = function (pLetterId, pDocumentTemplateId)
{
    var template = DocumentTemplate.loadTemplate(pLetterId, "SERIALLETTER");
    if (!template.type)
        template = DocumentTemplate.loadTemplate(pDocumentTemplateId);
    return template;
S.Listl's avatar
S.Listl committed
}