Skip to content
Snippets Groups Projects
Commit a5f5a400 authored by Maximilian Hofmann's avatar Maximilian Hofmann
Browse files

merged master into DSGVO

parents 2b48d547 3145fbec
No related branches found
No related tags found
No related merge requests found
Showing
with 366 additions and 106 deletions
......@@ -197,7 +197,7 @@
<include relativeToChangelogFile="true" file="longerProductName_Code.xml"/>
<include relativeToChangelogFile="true" file="BulkMail/create_bulkMail.xml"/>
<include relativeToChangelogFile="true" file="BulkMail/create_bulkmail.xml"/>
<include relativeToChangelogFile="true" file="BulkMail/create_bulkMailRecipient.xml"/>
<include relativeToChangelogFile="true" file="DSGVO/create_DSGVO.xml"/>
......
......@@ -6,7 +6,7 @@
<column name="OBJECT_TYPE" type="NVARCHAR(63)">
</column>
</addColumn>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="OFFER"/>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="OFFER" columnDataType="CHAR(36)"/>
<update tableName="OFFER">
<column name="OBJECT_TYPE" value="Salesproject" />
<where>OBJECT_ROWID = '0833465c-8851-4fbb-b7e3-8c1d73c903da' </where>
......@@ -17,7 +17,8 @@
<addNotNullConstraint
tableName="OFFER"
columnName="OBJECT_TYPE"/>
columnName="OBJECT_TYPE"
columnDataType="NVARCHAR(63)"/>
</changeSet>
</databaseChangeLog>
\ No newline at end of file
......@@ -6,8 +6,8 @@
<column name="OBJECT_TYPE" type="NVARCHAR(63)">
</column>
</addColumn>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="SALESPROJECT_COMPETITION"/>
<renameColumn newColumnName="COMPETITIONID" oldColumnName="SALESPROJECT_COMPETITIONID" tableName="SALESPROJECT_COMPETITION"/>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="SALESPROJECT_COMPETITION" columnDataType="CHAR(36)"/>
<renameColumn newColumnName="COMPETITIONID" oldColumnName="SALESPROJECT_COMPETITIONID" tableName="SALESPROJECT_COMPETITION" columnDataType="CHAR(36)"/>
<update tableName="SALESPROJECT_COMPETITION">
<column name="OBJECT_TYPE" value="Salesproject" />
<where>OBJECT_ROWID = '0833465c-8851-4fbb-b7e3-8c1d73c903da' </where>
......@@ -15,7 +15,8 @@
<addNotNullConstraint
tableName="SALESPROJECT_COMPETITION"
columnName="OBJECT_TYPE"/>
columnName="OBJECT_TYPE"
columnDataType="NVARCHAR(63)"/>
<renameTable oldTableName="SALESPROJECT_COMPETITION" newTableName="COMPETITION"/>
......
......@@ -6,8 +6,8 @@
<column name="OBJECT_TYPE" type="NVARCHAR(63)">
</column>
</addColumn>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="SALESPROJECT_FORECAST"/>
<renameColumn newColumnName="FORECASTID" oldColumnName="SALESPROJECT_FORECASTID" tableName="SALESPROJECT_FORECAST"/>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="SALESPROJECT_FORECAST" columnDataType="CHAR(36)"/>
<renameColumn newColumnName="FORECASTID" oldColumnName="SALESPROJECT_FORECASTID" tableName="SALESPROJECT_FORECAST" columnDataType="CHAR(36)"/>
<update tableName="SALESPROJECT_FORECAST">
<column name="OBJECT_TYPE" value="Salesproject" />
<where>OBJECT_ROWID = '0833465c-8851-4fbb-b7e3-8c1d73c903da' </where>
......@@ -15,7 +15,8 @@
<addNotNullConstraint
tableName="SALESPROJECT_FORECAST"
columnName="OBJECT_TYPE"/>
columnName="OBJECT_TYPE"
columnDataType="NVARCHAR(63)"/>
<renameTable oldTableName="SALESPROJECT_FORECAST" newTableName="FORECAST"/>
......
......@@ -6,9 +6,9 @@
<column name="OBJECT_TYPE" type="NVARCHAR(63)"/>
<column name="DECIDER" type="BOOLEAN"/>
</addColumn>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="SALESPROJECT_MEMBER"/>
<renameColumn newColumnName="MEMBERID" oldColumnName="SALESPROJECT_MEMBERID" tableName="SALESPROJECT_MEMBER"/>
<renameColumn newColumnName="ROLE" oldColumnName="SALESPROJECT_ROLE" tableName="SALESPROJECT_MEMBER"/>
<renameColumn newColumnName="OBJECT_ROWID" oldColumnName="SALESPROJECT_ID" tableName="SALESPROJECT_MEMBER" columnDataType="CHAR(36)"/>
<renameColumn newColumnName="MEMBERID" oldColumnName="SALESPROJECT_MEMBERID" tableName="SALESPROJECT_MEMBER" columnDataType="CHAR(36)"/>
<renameColumn newColumnName="ROLE" oldColumnName="SALESPROJECT_ROLE" tableName="SALESPROJECT_MEMBER" columnDataType="CHAR(36)"/>
<update tableName="SALESPROJECT_MEMBER">
<column name="OBJECT_TYPE" value="Salesproject" />
<where>OBJECT_ROWID = '0833465c-8851-4fbb-b7e3-8c1d73c903da'</where>
......@@ -16,7 +16,8 @@
<addNotNullConstraint
tableName="SALESPROJECT_MEMBER"
columnName="OBJECT_TYPE"/>
columnName="OBJECT_TYPE"
columnDataType="NVARCHAR(63)"/>
<renameTable oldTableName="SALESPROJECT_MEMBER" newTableName="MEMBER"/>
......
......@@ -43,6 +43,12 @@
<entityParameter>
<name>ObjectType_param</name>
<valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/organisationobjects/children/objecttype_param/valueProcess.js</valueProcess>
<expose v="false" />
</entityParameter>
<entityParameter>
<name>BaseContextId_param</name>
<valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/organisationobjects/children/basecontextid_param/valueProcess.js</valueProcess>
<expose v="false" />
</entityParameter>
</children>
</entityProvider>
......@@ -82,6 +88,12 @@
<entityParameter>
<name>ObjectType_param</name>
<valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/personobjects/children/objecttype_param/valueProcess.js</valueProcess>
<expose v="false" />
</entityParameter>
<entityParameter>
<name>BaseContextId_param</name>
<valueProcess>%aditoprj%/entity/360Degree_entity/entityfields/personobjects/children/basecontextid_param/valueProcess.js</valueProcess>
<expose v="false" />
</entityParameter>
</children>
</entityProvider>
......@@ -142,6 +154,10 @@
<dropDownProcess>%aditoprj%/entity/360Degree_entity/entityfields/active/dropDownProcess.js</dropDownProcess>
<searchable v="true" />
</entityField>
<entityParameter>
<name>BaseContextId_param</name>
<expose v="true" />
</entityParameter>
</entityFields>
<recordContainers>
<jDitoRecordContainer>
......
import("system.result");
result.string("Organisation");
\ No newline at end of file
import("system.result");
result.string("Person");
\ No newline at end of file
......@@ -6,12 +6,11 @@ import("system.result");
import("Context_lib");
import("system.translate");
var resultList = [];
if (vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param") && vars.exists("$param.ObjectRowId_param") && vars.get("$param.ObjectRowId_param"))
{
var active;
var selectMap = ContextUtils.getSelectMap ()
var selectMap = ContextUtils.getSelectMap();
if(vars.exists("$local.filter") && vars.get("$local.filter") )
{
var filter = vars.get("$local.filter");
......@@ -27,9 +26,37 @@ if (vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param"
}
var contextList = JSON.parse(vars.getString("$param.ObjectType_param"));
contextList.forEach(function (context)
var contactId = vars.get("$param.ObjectRowId_param");
var baseContext = vars.exists("$param.BaseContextId_param") ? vars.get("$param.BaseContextId_param") : undefined;
result.object(_get360Data(selectMap, baseContext, contactId, contextList, active, undefined, baseContext != undefined));
}
else
{
result.object([]);
}
/**
* load all data for the 360Degree tree.
* @param {Object} pSelectMap the select map (result of ContextUtils.getSelectMap())
* @param {String} pBaseContextId the ContextId in which this 360 Degree tree is located / for which the data should be loaded
* @param {String[]} pContactId the Contactid the 360 Degree tree should be loaded for
* @param {String[]} pContextList list of contexts to load. Note that subcontexts use their own list, defined in ContextUtils
* @param {Boolean} [pActive=undefined] if not undefined: it select only for active / inactive state
* @param {String[]} [pExcludedObjectIds=undefined] if set: this contextIds are filtered out.
* @param {Boolean} [pAlsoAddFromSubcontexts=false] if true also load data from contexts which are configured as subcontexts.
* A subcontext is for example used by Organisations, which also load the data from all Persons in this organisation into the 360°-view.
* Does not include subcontexts of subcontexts
*
* @return {String[][]} the resulting data
*/
function _get360Data(pSelectMap, pBaseContextId, pContactId, pContextList, pActive, pExcludedObjectIds, pAlsoAddFromSubcontexts)
{
var resultList = [];
pContextList.forEach(function (context)
{
var data = db.table(ContextUtils.getContextDataSql(context, vars.get("$param.ObjectRowId_param"), true, active, true));
var data = db.table(ContextUtils.getContextDataSql(context, pContactId, true, pActive, true, pExcludedObjectIds));
data.forEach(function (row)
{
var record = [];
......@@ -38,22 +65,43 @@ if (vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param"
record[2] = context; // TARGET_CONTEXT
record[3] = row[1]; // TITLE
record[4] = row[2]; //DATE
if(active != undefined) //ACTIVE
record[5] = translate.text(active);
if(pActive != undefined) //ACTIVE
record[5] = translate.text(pActive);
else
{
if(selectMap[context].activeStates.indexOf(row[3]) > -1)
if(pSelectMap[context].activeStates.indexOf(row[3]) > -1)
record[5] = translate.text("true");
else
record[5] = translate.text("false");
}
resultList.push(record);
});
});
result.object(resultList)
}
else
{
result.object(resultList);
});
});
if (pAlsoAddFromSubcontexts)
{
var baseContextData = pSelectMap[pBaseContextId];
var subContexts = baseContextData.getSubContexts(pContactId);
if (!pExcludedObjectIds)
pExcludedObjectIds = [];
pExcludedObjectIds.push(pBaseContextId);
for (subContextId in subContexts)
{
var subContextSql = subContexts[subContextId][0];
// select Ids from subcontexts
var subContextContactIds = db.array(db.COLUMN, subContextSql);
subContextContactIds.forEach(function(pId) {
// V-- do not add subcontexts deeper than one layer
var subcontextRes = _get360Data(pSelectMap, pBaseContextId, pId, subContexts[subContextId][1], pActive, pExcludedObjectIds, false);
logging.log(subcontextRes.toSource())
resultList = resultList.concat(subcontextRes);
});
}
}
return resultList;
}
\ No newline at end of file
import("system.logging");
import("system.datetime");
import("system.translate");
import("Util_lib");
import("JditoFilter_lib");
......@@ -10,20 +11,24 @@ import("system.result");
import("Sql_lib");
import("Attribute_lib");
var t = datetime.date()
var getGroups = vars.exists("$param.GetGroups_param") && vars.get("$param.GetGroups_param");
var objectType = vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param");
var parentType = vars.exists("$param.AttrParentType_param") && vars.get("$param.AttrParentType_param");
logging.log([getGroups, objectType, parentType])
var fetchUsages = true;
var uidTableAlias = "UIDROW";
var sqlSelect = "select UIDROW.AB_ATTRIBUTEID, UIDROW.ATTRIBUTE_PARENT_ID, UIDROW.ATTRIBUTE_ACTIVE, UIDROW.DROPDOWNDEFINITION, UIDROW.SORTING, UIDROW.ATTRIBUTE_TYPE, "
+ KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.attributeType(), "UIDROW.ATTRIBUTE_TYPE") //3
+ ", '', UIDROW.ATTRIBUTE_NAME, PARENT1.ATTRIBUTE_NAME, PARENT2.ATTRIBUTE_NAME, PARENT3.ATTRIBUTE_NAME, PARENT3.ATTRIBUTE_PARENT_ID "
+ "from AB_ATTRIBUTE UIDROW "
+ "left join AB_ATTRIBUTE PARENT1 on UIDROW.ATTRIBUTE_PARENT_ID = PARENT1.AB_ATTRIBUTEID " //always select the names of the next 3 parents so that less queries
+ "left join AB_ATTRIBUTE PARENT2 ON PARENT1.ATTRIBUTE_PARENT_ID = PARENT2.AB_ATTRIBUTEID " //are required later when buildung the full name
+ "left join AB_ATTRIBUTE PARENT3 ON PARENT2.ATTRIBUTE_PARENT_ID = PARENT3.AB_ATTRIBUTEID";
+ ", '', UIDROW.ATTRIBUTE_NAME, PARENT1.ATTRIBUTE_NAME, PARENT2.ATTRIBUTE_NAME, PARENT3.ATTRIBUTE_NAME, PARENT3.ATTRIBUTE_PARENT_ID \n\
from AB_ATTRIBUTE UIDROW \n\
left join AB_ATTRIBUTE PARENT1 on UIDROW.ATTRIBUTE_PARENT_ID = PARENT1.AB_ATTRIBUTEID \n\
left join AB_ATTRIBUTE PARENT2 ON PARENT1.ATTRIBUTE_PARENT_ID = PARENT2.AB_ATTRIBUTEID \n\
left join AB_ATTRIBUTE PARENT3 ON PARENT2.ATTRIBUTE_PARENT_ID = PARENT3.AB_ATTRIBUTEID";
/* always select the names of the next 3 parents so that less queries
are required later when buildung the full name */
var sqlOrder = " order by UIDROW.ATTRIBUTE_PARENT_ID asc, UIDROW.SORTING asc";
......@@ -69,18 +74,7 @@ else if (objectType) //if there's an objectType, it comes from the AttributeRel
else // do not return anything, if parameter is there but an empty array
condition.and("1=2");
}
else if (parentType) //condition for all subordinate attributes of an attribute (for the tree of subordinate attributes in an attribute)
{
if (AttributeTypeUtil.isGroupType(parentType))
{
var parentId = vars.exists("$param.AttrParentId_param") && vars.get("$param.AttrParentId_param");
if (parentId)
condition.and("UIDROW.AB_ATTRIBUTEID in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')");
}
else
condition.and("1=2");
fetchUsages = false;
}
//when there are filters selected, add them to the conditon
......@@ -91,21 +85,26 @@ if (vars.exists("$local.filter") && vars.get("$local.filter"))
condition.andSqlCondition(JditoFilterUtils.getSqlCondition(filter.filter, "AB_ATTRIBUTE", uidTableAlias));
}
var usagesSelect = "select AB_ATTRIBUTE_ID, OBJECT_TYPE from AB_ATTRIBUTEUSAGE \n\
join AB_ATTRIBUTE UIDROW on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = UIDROW.AB_ATTRIBUTEID";
var usageTbl = db.table(condition.buildSql(usagesSelect, "1=1"));
var usages = {};
for (let i = 0, l = usageTbl.length; i < l; i++)
var usages;
if (fetchUsages) //this query is only necessary in Attribute, not in AttributeRelation
{
let attrId = usageTbl[i][0];
if (attrId in usages)
usages[attrId].push(usageTbl[i][1]);
else
usages[attrId] = [usageTbl[i][1]];
var usagesSelect = "select AB_ATTRIBUTE_ID, OBJECT_TYPE from AB_ATTRIBUTEUSAGE \n\
join AB_ATTRIBUTE UIDROW on AB_ATTRIBUTEUSAGE.AB_ATTRIBUTE_ID = UIDROW.AB_ATTRIBUTEID";
var usageTbl = db.table(condition.buildSql(usagesSelect, "1=1"));
usages = {};
for (let i = 0, l = usageTbl.length; i < l; i++)
{
let attrId = usageTbl[i][0];
if (attrId in usages)
usages[attrId].push(usageTbl[i][1]);
else
usages[attrId] = [usageTbl[i][1]];
}
}
var attributes = db.table(condition.buildSql(sqlSelect, "1=1", sqlOrder));
var nameCache = {};
result.object(_buildAttributeTable(attributes, usages));
......@@ -140,7 +139,7 @@ function _buildAttributeTable (pAttributes, pUsages)
for (let i in rows)
{
let rowData = rows[i].data;
if (rowData[5].trim() != $AttributeTypes.COMBOVALUE && i in pUsages)
if (pUsages && rowData[5].trim() != $AttributeTypes.COMBOVALUE && i in pUsages)
{
rowData[7] = pUsages[i].map(function (usage)
{
......@@ -163,8 +162,17 @@ function _buildAttributeTable (pAttributes, pUsages)
*/
function _getFullName (pAttributeName, pParent1Name, pParent2Name, pParent3Name, pParent4Id)
{
var parent4FullName = pParent4Id ? AttributeUtil.getFullAttributeName(pParent4Id) : null;
var parent4FullName;
if (pParent4Id && pParent4Id in nameCache)
parent4FullName = nameCache[pParent4Id];
else
{
parent4FullName = pParent4Id ? AttributeUtil.getFullAttributeName(pParent4Id) : null;
nameCache[pParent4Id] = parent4FullName;
}
pAttributeName = ArrayUtils.joinNonEmptyFields([parent4FullName, pParent3Name, pParent2Name, pParent1Name, pAttributeName], " / ");
return pAttributeName;
}
\ No newline at end of file
}
logging.log(datetime.date() - t)
\ No newline at end of file
......@@ -2,7 +2,7 @@ import("system.logging");
import("system.result");
import("system.neon");
import("system.vars");
import("PostalAddress_lib");
import("Address_lib");
if (vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW && !vars.get("$this.value"))
{
......
<?xml version="1.0" encoding="UTF-8"?>
<process xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.2.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.2.1">
<name>Bulkmail_lib</name>
<name>BulkMail_lib</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<process>%aditoprj%/process/Bulkmail_lib/process.js</process>
<variants>
......
import("KeywordRegistry_basic");
import("Sql_lib");
import("system.db");
import("DocumentTemplate_lib");
import("Email_lib");
function Bulkmail ()
function BulkMailUtils () {}
BulkMailUtils.sendBulkMail = function (pBulkMailId)
{
var templateId = db.cell(SqlCondition.begin()
.andPrepare("BULKMAIL.BULKMAILID", pBulkMailId)
.buildSql("select DOCUMENTTEMPLATE_ID from BULKMAIL", "1=2")
);
var template = DocumentTemplate.loadTemplate(templateId);
var emailSender;
var recipientData = db.table(SqlCondition.begin()
.andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
//TODO: more condition
.buildSql("select BULKMAILRECIPIENTID, CONTACT_ID, '' from BULKMAILRECIPIENT", "1=2")
);
var successIds = [];
var failedIds = [];
var mails = template.getReplacedEmailsByContactIds(recipientData.map(function (e) {return e[0];}));
for (let i = 0, l = recipientData.length; i < l; i++)
{
let contactId = recipientData[i][1];
let email = mails[contactId];
email.toRecipients = [recipientData[i][1]];
email.sender = emailSender;
let isSuccess = email.send();
if (isSuccess)
successIds.push(recipientData[i][0]); //set the recipient status to 'sent'
else
failedIds.push(recipientData[i][0]); //set the recipient status to 'failed'
}
db.updateData("BULKMAILRECIPIENT", ["STATUS"], null, [$KeywordRegistry.bulkMailSentStatus$sent()],
SqlCondition.begin()
.andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", successIds)
.build("1=2")
);
db.updateData("BULKMAILRECIPIENT", ["STATUS"], null, [$KeywordRegistry.bulkMailSentStatus$failed()],
SqlCondition.begin()
.andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", failedIds)
.build("1=2")
);
}
\ No newline at end of file
......@@ -237,6 +237,19 @@ function ContextSelector(pTableName, pIdField, pTitleExpression)
*/
this.activeStates = null; ProtoPropertyUtils.makeSemiReadOnly(this, "activeStates");
this.condition = null; ProtoPropertyUtils.makeSemiReadOnly(this, "condition");
/**
* an object which contains the subcontexts and the prepared select to get the contactIds of them.
* V--With Tablename!
* { V-- before id-condition | add "and", if needed --V V-IdCollumn name V-- optional after-condition SQL (e.g. group by etc.)
* "Person": ["select PERSON_ID from CONTACT where PERSON_ID is not null and", "CONTACT.ORGANISATION_ID", '', ["Offer", "Contract"]],
* // the contexts to show for this subcontext
* "Offer" ... // you can add as many subcontexts as you wish
* }
* read-only property; set it with a matching setter
* @property
*/
this.subContexts = null; ProtoPropertyUtils.makeSemiReadOnly(this, "subContexts");
}
/**
* creates a new instance of a ContextSelector and returns it
......@@ -275,6 +288,28 @@ ContextSelector.prototype.getFullFromClause = function()
else
return this.tableName;
};
/**
* @return {String} full from-expression with tablename and join-part
*/
ContextSelector.prototype.getSubContexts = function(pParentRowId)
{
if (this.subContexts)
{
var sqls = {};
for (contextId in this.subContexts)
{
sqls[contextId] = [SqlCondition.begin()
.andPrepare(this.subContexts[contextId][1], pParentRowId)
.buildSql(this.subContexts[contextId][0], "1=2", this.subContexts[contextId][2], false), this.subContexts[contextId][3]];
}
return sqls;
}
else
return {};
};
//setters which to nothing special; no need to document them
ContextSelector.prototype.setTitleExpression = function(pValue)
......@@ -326,6 +361,11 @@ ContextSelector.prototype.setCondition = function(pSqlCondition)
this._condition = pSqlCondition;
return this;
};
ContextSelector.prototype.setSubContexts = function(pContexts)
{
this._subContexts = pContexts;
return this;
};
/**
* TODO: !!!temporary function until you can get fields from another Entity!!!
......@@ -337,6 +377,9 @@ ContextUtils.getSelectMap = function()
"Organisation": ContextSelector.create("ORGANISATION", "CONTACT.CONTACTID", "ORGANISATION.NAME")
.setJoinExpression("join CONTACT on ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID and CONTACT.PERSON_ID is null")
.setCondition(SqlCondition.begin().and("ORGANISATION.ORGANISATIONID != '0'"))
.setSubContexts({
"Person": ["select CONTACTID from CONTACT where PERSON_ID is not null and", "CONTACT.ORGANISATION_ID", '', ["Offer", "Contract"]]
})
,"Person": ContextSelector.create("CONTACT", "CONTACTID")
.setTitleExpression(maskingUtils.concat([
new ContactTitleRenderer(Contact.createWithColumnPreset()).asSql()
......
import("system.logging");
import("Communication_lib");
import("system.neon");
import("Employee_lib");
......@@ -147,67 +146,103 @@ DocumentTemplate.prototype.getReplacedContent = function (pReplacements)
/**
* replaces the placeholders with data from the contact and returns the result
*/
DocumentTemplate.prototype.getReplacedContentByContactId = function (pContactId) //TODO: function required for mass replacing (for bulkmails)
DocumentTemplate.prototype.getReplacedContentByContactId = function (pContactId)
{
var replacements = this._getReplacementsByContactId(pContactId);
return this.getReplacedContent(replacements);
var replacements = this._getReplacementsByContactIds([pContactId]);
return this.getReplacedContent(replacements[pContactId]);
}
/**
* @private
* replaces the placeholders with data from the contacts and returns the result
*
* @param {Array} pContactIds contact ids
*
* @return {Object} replaced content for every contactId
*/
DocumentTemplate.prototype._getReplacementsByContactId = function (pContactId)
DocumentTemplate.prototype.getReplacedContentByContactIds = function (pContactIds)
{
var config = this._getRequiredPlaceholders();
var addressData = getAddressesData([pContactId], config, EmployeeUtils.getCurrentContactId()); //TODO: add sender selection
var replacements = {};
for (let i = 0, l = addressData[0].length; i < l; i++)
var replacements = this._getReplacementsByContactIds(pContactIds);
var contents = {};
for (let contactId in replacements)
{
replacements[addressData[0][i]] = addressData[1][i];
contents[contactId] = this.getReplacedContent(replacements[contactId]);
}
return replacements;
return contents;
}
/**
* loads data into an Email object from a template
* replaces the placeholders with data from the contacts and returns the result
*
* @param {Email} pEmail email object to change
* @param {String} pContactId contactId of the recipient
* @param {Array} pContactIds contact ids
*
* @return {Object} emails for every contactId
*/
DocumentTemplate.prototype.setEmailTemplateByContactId = function (pEmail, pContactId)
DocumentTemplate.prototype.getReplacedEmailsByContactIds = function (pContactIds)
{
if (this.type != DocumentTemplate.types.EML && this.type != DocumentTemplate.types.HTML && this.type != DocumentTemplate.types.TXT)
throw new Error("Invalid document type for an email template");
var replacements = DocumentTemplate._getReplacementsByContactId(pContactId);
if (this.type == DocumentTemplate.types.EML) //special treatment because eml contains more information than just the body
var replacements = this._getReplacementsByContactIds(pContactIds);
var emailObj = {};
for (let contactId in replacements)
{
let email = mail.parseRFC(util.decodeBase64String(this.content));
pEmail.sender = DocumentTemplate._replaceText(email[mail.MAIL_SENDER], replacements);
pEmail.subject = DocumentTemplate._replaceText(email[mail.MAIL_SUBJECT], replacements);
pEmail.body = DocumentTemplate._replaceText(email[mail.MAIL_HTMLTEXT], replacements);
if (this.type == DocumentTemplate.types.EML)
emailObj[contactId] = this._getReplacedEML(replacements[contactId], true);
else
{
let body = this.getReplacedContent(replacements[contactId]);
emailObj[contactId] = new Email(null, null, null, body);
}
}
else
pEmail.body = this.getReplacedContent(replacements);
return emailObj;
}
/**
* Replaces placeholders for EML. This function only works for the email body,
* so if you also need the subject, sender, etc use DocumentTemplate.prototype.setEmailTemplateByContactId.
* @private
*/
DocumentTemplate.prototype._getReplacementsByContactIds = function (pContactIds)
{
var config = this._getRequiredPlaceholders();
var contactIdPlaceholder = new Placeholder("contactId", Placeholder.types.SQLPART, "CONTACT.CONTACTID");
config = [contactIdPlaceholder].concat(config);
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 {Object} pReplacements mapping with replacements for every placeholder
* @param {boolean} [pGetEmail] if true, return Email object
*
* @return {String} the replaced content
* @return {String|Email} the replaced content
*
* @private
*/
DocumentTemplate.prototype._getReplacedEML = function (pReplacements)
DocumentTemplate.prototype._getReplacedEML = function (pReplacements, pGetEmail)
{
var email = mail.parseRFC(util.decodeBase64String(this.content));
var htmlText = email[mail.MAIL_HTMLTEXT];
return DocumentTemplate._replaceText(htmlText, pReplacements);
var mailData = mail.parseRFC(util.decodeBase64String(this.content));
var email;
var body = DocumentTemplate._replaceText(mailData[mail.MAIL_HTMLTEXT], pReplacements);
if (pGetEmail)
{
var sender = DocumentTemplate._replaceText(mailData[mail.MAIL_SENDER], pReplacements);
var subject = DocumentTemplate._replaceText(mailData[mail.MAIL_SUBJECT], pReplacements);
email = new Email(null, sender, subject, body);
}
else
email = body;
return email;
}
/*
......@@ -297,7 +332,7 @@ DocumentTemplate.prototype._getReplacedODT = function (pReplacements)
DocumentTemplate.prototype._getReplacedDOCX = function (pReplacements)
{
var replacements = {};
for (let placeholder in pReplacements)
for (let placeholder in pReplacements) //removes the prefix and postfix, the process needs it like this
replacements[placeholder.slice(3, -3)] = pReplacements[placeholder];
//this is executed as a process because of better performance
......
......@@ -24,9 +24,9 @@ function EmailUtils () {}
EmailUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId)
{
var email = new Email(pToRecipients);
email.setSender(pSenderContactId);
if (pTemplateId)
email.setTemplate(pTemplateId, pRecipientContactId);
email.setSender(pSenderContactId);
email.downloadEML();
}
......@@ -74,13 +74,14 @@ function Email (pToRecipients, pSender, pSubject, pBody, pCcRecipients, pBccReci
*
* @param {String} pTemplateId the id of the template
* @param {String} pContactId the id of the template
*
* @throws {Error} if the type of the template is invalid
*/
Email.prototype.setTemplate = function (pTemplateId, pContactId)
{
var template = DocumentTemplate.loadTemplate(pTemplateId);
template.setEmailTemplateByContactId(this, pContactId);
var email = template.getReplacedEmailsByContactIds([pContactId])[pContactId];
this.sender = email.sender;
this.body = email.body;
this.subject = email.subject;
}
/**
......@@ -186,4 +187,52 @@ Email.prototype.downloadEML = function()
{
neon.download(util.encodeBase64String(this.getRFCmail(), null), (this.subject || translate.text("Email Template")) + ".eml");
}
\ No newline at end of file
/**
* sends the email object
*
* @return {boolean} true, if the mail was sent sucessfully
*/
Email.prototype.send = function ()
{
var ENCODING = "UTF-8";
var mailId;
try
{
mailId = mail.newMail();
}
catch(ex)
{
//TODO: fix this dirty workaround [waiting for #1038963], since newMail causes an error on the first call after a user logged in
logging.log(ex);
util.sleep(1500);
mailId = mail.newMail();
}
if (this.toRecipients.length)
mail.addRecipients(mailId, mail.RECIPIENT_TO, this.toRecipients);
if (this.ccRecipients.length)
mail.addRecipients(mailId, mail.RECIPIENT_CC, this.ccRecipients);
if (this.bccRecipients.length)
mail.addRecipients(mailId, mail.RECIPIENT_BCC, this.bccRecipients);
if (this.subject)
mail.setSubject(mailId, this.subject, ENCODING);
if (this.body)
mail.addText(mailId, this.body, "text/html", ENCODING, null);
else
mail.addText(mailId, "", "text/html", ENCODING, null);
try
{
mail.sendMail(mailId);
return true;
}
catch (ex)
{
return false;
}
}
\ No newline at end of file
......@@ -107,6 +107,11 @@ $KeywordRegistry.permissionCondType = function(){return "PermissionCondType";};
$KeywordRegistry.permissionAccessType = function(){return "PermissionAccessType";};
$KeywordRegistry.purpose = function(){return "Purpose";};
$KeywordRegistry.statuoritysource = function(){return "Statuoritysource";};
$KeywordRegistry.DSGVOTablename = function() {return "DSGVOTablename";};
$KeywordRegistry.textPlaceholder = function(){return "textPlaceholder";};
$KeywordRegistry.communicationMediumCampaign = function(){return "CommunicationMediumCampaign";};
$KeywordRegistry.DSGVOTablename = function() {return "DSGVOTablename";};
$KeywordRegistry.bulkMailSentStatus = function(){return "BulkMailSentStatus";};
$KeywordRegistry.bulkMailSentStatus$pending = function(){return "9a0c5608-070e-49fb-92cd-f6abece9242d";};
$KeywordRegistry.bulkMailSentStatus$sent = function(){return "147211fb-a1cf-49c8-8e08-c3cfe0404f9b";};
$KeywordRegistry.bulkMailSentStatus$failed = function(){return "353e27e9-7491-4bfd-b9f9-f18f2cb2a36c";};
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment