Skip to content
Snippets Groups Projects
Commit 2c5dec63 authored by S.Listl's avatar S.Listl
Browse files

Serial letter download

parent d87baeaf
No related branches found
No related tags found
No related merge requests found
Showing
with 1047 additions and 941 deletions
......@@ -2,7 +2,11 @@
<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.10" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.10">
<name>AttributeRelation_entity</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<title>Attribute</title>
<titlePlural>Attributes</ti<grantDeleteProcess>%aditoprj%/entity/AttributeRelation_entity/grantDeleteProcess.js</grantDeleteProcess>
tlePlural>
<recordContainer>jdito</recordContainer>
<entityFields>
<entityProvider>
<titlePlural>Attributes</titlePlural>
<recordContainer>jdito</recordContainer>
<entityFields>
......
import("Attribute_lib");
import("system.result");
import("system.vars");
var objectType = vars.exists("$param.ObjectType_param") && vars.get("$param.ObjectType_param");
var rowId = vars.exists("$param.ObjectRowId_param") && vars.get("$param.ObjectRowId_param");
if (vars.get("$param.GetTree_param") == "true" && rowId)
result.object(AttributeRelationUtils.countAttributeRelations(rowId, objectType));
\ No newline at end of file
import("system.translate");
import("Util_lib");
import("JditoFilter_lib");
import("KeywordRegistry_basic");
import("Keyword_lib");
import("system.db");
import("system.vars");
import("system.result");
import("Sql_lib");
import("Attribute_lib");
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");
var fetchUsages = true;
var translateName = false;
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 \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";
var condition = SqlCondition.begin();
if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
{
condition.and("UIDROW.AB_ATTRIBUTEID in ('" + vars.get("$local.idvalues").join("','") + "')");
}
else if (getGroups) //if getGroups == true, it is the lookup for selecting the superordinate attribute
{
//this condition filters out the own id and the children to prevent loops
var isGroupCondition = SqlCondition.begin();
for (let type in $AttributeTypes)
if ($AttributeTypes[type].isGroup)
{
isGroupCondition.orPrepare(["AB_ATTRIBUTE", "ATTRIBUTE_TYPE", uidTableAlias], $AttributeTypes[type]);
}
condition.andSqlCondition(SqlCondition.begin()
.andSqlCondition(isGroupCondition)
.andPrepareVars(["AB_ATTRIBUTE", "AB_ATTRIBUTEID", uidTableAlias], "$param.AttrParentId_param", "# != ?")
.and("UIDROW.AB_ATTRIBUTEID not in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')")
);
}
else if (objectType) //if there's an objectType, it comes from the AttributeRelation entity (lookup for the attribute selection)
{
var filteredAttributes = null;
if (vars.exists("$param.FilteredAttributeIds_param") && vars.getString("$param.FilteredAttributeIds_param")) {
filteredAttributes = JSON.parse(vars.getString("$param.FilteredAttributeIds_param"));
}
var attributeCount;
if (vars.exists("$param.AttributeCount_param") && vars.get("$param.AttributeCount_param"))
attributeCount = JSON.parse(vars.getString("$param.AttributeCount_param"));
var ids = AttributeUtil.getPossibleAttributes(objectType, false, filteredAttributes, attributeCount);
if (ids.length > 0)
condition.and("UIDROW.AB_ATTRIBUTEID in ('" + ids.join("','") + "')");
else // do not return anything, if parameter is there but an empty array
condition.and("1=2");
fetchUsages = false;
translateName = true;
}
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");
translateName = true;
}
//when there are filters selected, add them to the conditon
if (vars.exists("$local.filter") && vars.get("$local.filter"))
{
var filter = vars.get("$local.filter");
if (filter.filter)
condition.andSqlCondition(JditoFilterUtils.getSqlCondition(filter.filter, "AB_ATTRIBUTE", uidTableAlias));
}
var usages;
if (fetchUsages) //this query is only necessary in Attribute, not in AttributeRelation
{
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, translateName));
//sorts the records in a way that a tree can be built and adds values
function _buildAttributeTable (pAttributes, pUsages, pTranslate)
{
var rows = {};
var allIds = {};
//fills the allIds object, the object is used for checking if a parent exists in the array
for (let i = 0, l = pAttributes.length; i < l; i++)
allIds[pAttributes[i][0]] = true;
var arrayIndex = 0;
do {
var oldIndex = arrayIndex;
pAttributes.forEach(function (row)
{
//item will be added if the id is not already in the object and
//the parent is already added (or the parent is not in the array)
if (!(row[0] in this) && (row[1] in this || !allIds[row[1]]))
this[row[0]] = {
data : row,
index : arrayIndex++
};
}, rows);
} while (oldIndex != arrayIndex); //stops the loop when no new items were added so that recursive relations between attributes don't cause an infinite loop
var displaySimpleName = vars.exists("$param.DisplaySimpleName_param") && vars.get("$param.DisplaySimpleName_param");
var sortedArray = new Array(Object.keys(rows).length);
for (let i in rows)
{
let rowData = rows[i].data;
if (pUsages && rowData[5].trim() != $AttributeTypes.COMBOVALUE && i in pUsages)
{
rowData[7] = pUsages[i].map(function (usage)
{
return translate.text(usage);
}).join(", ");
}
var fullName;
if (displaySimpleName)
fullName = pTranslate
? translate.text(rowData[8])
: rowData[8];
else
fullName = _getFullName(rowData[8], rowData[9], rowData[10], rowData[11], rowData[12], pTranslate);
rowData.splice(10, 3, fullName);
sortedArray[rows[i].index] = rowData;
}
return sortedArray;
/**
* builds the full attribute name from the pre-loaded parent names and adds all parent names
* if required
*/
function _getFullName (pAttributeName, pParent1Name, pParent2Name, pParent3Name, pParent4Id)
{
var parent4FullName;
if (pParent4Id && pParent4Id in nameCache)
parent4FullName = nameCache[pParent4Id];
else
{
parent4FullName = pParent4Id ? AttributeUtil.getFullAttributeName(pParent4Id, false, pTranslate) : null;
nameCache[pParent4Id] = parent4FullName;
}
if (pTranslate)
{
pAttributeName = translate.text(pAttributeName);
pParent1Name = translate.text(pParent1Name);
pParent2Name = translate.text(pParent2Name);
pParent3Name = translate.text(pParent3Name);
}
pAttributeName = ArrayUtils.joinNonEmptyFields([parent4FullName, pParent3Name, pParent2Name, pParent1Name, pAttributeName], " / ");
return pAttributeName;
}
}
import("system.translate");
import("Util_lib");
import("JditoFilter_lib");
import("KeywordRegistry_basic");
import("Keyword_lib");
import("system.db");
import("system.vars");
import("system.result");
import("Sql_lib");
import("Attribute_lib");
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");
var fetchUsages = true;
var translateName = false;
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 \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";
var condition = SqlCondition.begin();
if (vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
{
condition.and("UIDROW.AB_ATTRIBUTEID in ('" + vars.get("$local.idvalues").join("','") + "')");
}
else if (getGroups) //if getGroups == true, it is the lookup for selecting the superordinate attribute
{
//this condition filters out the own id and the children to prevent loops
var isGroupCondition = SqlCondition.begin();
for (let type in $AttributeTypes)
if ($AttributeTypes[type].isGroup)
{
isGroupCondition.orPrepare(["AB_ATTRIBUTE", "ATTRIBUTE_TYPE", uidTableAlias], $AttributeTypes[type]);
}
condition.andSqlCondition(SqlCondition.begin()
.andSqlCondition(isGroupCondition)
.andPrepareVars(["AB_ATTRIBUTE", "AB_ATTRIBUTEID", uidTableAlias], "$param.AttrParentId_param", "# != ?")
.and("UIDROW.AB_ATTRIBUTEID not in ('" + AttributeUtil.getAllChildren(vars.getString("$param.AttrParentId_param")).join("','") + "')")
);
}
else if (objectType) //if there's an objectType, it comes from the AttributeRelation entity (lookup for the attribute selection)
{
var filteredAttributes = null;
if (vars.exists("$param.FilteredAttributeIds_param") && vars.getString("$param.FilteredAttributeIds_param")) {
filteredAttributes = JSON.parse(vars.getString("$param.FilteredAttributeIds_param"));
}
var attributeCount;
if (vars.exists("$param.AttributeCount_param") && vars.get("$param.AttributeCount_param"))
attributeCount = JSON.parse(vars.getString("$param.AttributeCount_param"));
var ids = AttributeUtil.getPossibleAttributes(objectType, false, filteredAttributes, attributeCount);
if (ids.length > 0)
condition.and("UIDROW.AB_ATTRIBUTEID in ('" + ids.join("','") + "')");
else // do not return anything, if parameter is there but an empty array
condition.and("1=2");
fetchUsages = false;
translateName = true;
}
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");
translateName = true;
}
//when there are filters selected, add them to the conditon
if (vars.exists("$local.filter") && vars.get("$local.filter"))
{
var filter = vars.get("$local.filter");
if (filter.filter)
condition.andSqlCondition(JditoFilterUtils.getSqlCondition(filter.filter, "AB_ATTRIBUTE", uidTableAlias));
}
var usages;
if (fetchUsages) //this query is only necessary in Attribute, not in AttributeRelation
{
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, translateName));
//sorts the records in a way that a tree can be built and adds values
function _buildAttributeTable (pAttributes, pUsages, pTranslate)
{
var rows = {};
var allIds = {};
//fills the allIds object, the object is used for checking if a parent exists in the array
for (let i = 0, l = pAttributes.length; i < l; i++)
allIds[pAttributes[i][0]] = true;
var arrayIndex = 0;
do {
var oldIndex = arrayIndex;
pAttributes.forEach(function (row)
{
//item will be added if the id is not already in the object and
//the parent is already added (or the parent is not in the array)
if (!(row[0] in this) && (row[1] in this || !allIds[row[1]]))
this[row[0]] = {
data : row,
index : arrayIndex++
};
}, rows);
} while (oldIndex != arrayIndex); //stops the loop when no new items were added so that recursive relations between attributes don't cause an infinite loop
var displaySimpleName = vars.exists("$param.DisplaySimpleName_param") && vars.get("$param.DisplaySimpleName_param");
var sortedArray = new Array(Object.keys(rows).length);
for (let i in rows)
{
let rowData = rows[i].data;
if (pUsages && rowData[5].trim() != $AttributeTypes.COMBOVALUE && i in pUsages)
{
rowData[7] = pUsages[i].map(function (usage)
{
return translate.text(usage);
}).join(", ");
}
var fullName;
if (displaySimpleName)
fullName = pTranslate
? translate.text(rowData[8])
: rowData[8];
else
fullName = _getFullName(rowData[8], rowData[9], rowData[10], rowData[11], rowData[12], pTranslate);
rowData.splice(10, 3, fullName);
sortedArray[rows[i].index] = rowData;
}
return sortedArray;
/**
* builds the full attribute name from the pre-loaded parent names and adds all parent names
* if required
*/
function _getFullName (pAttributeName, pParent1Name, pParent2Name, pParent3Name, pParent4Id)
{
var parent4FullName;
if (pParent4Id && pParent4Id in nameCache)
parent4FullName = nameCache[pParent4Id];
else
{
parent4FullName = pParent4Id ? AttributeUtil.getFullAttributeName(pParent4Id, false, pTranslate) : null;
nameCache[pParent4Id] = parent4FullName;
}
if (pTranslate)
{
pAttributeName = translate.text(pAttributeName);
pParent1Name = translate.text(pParent1Name);
pParent2Name = translate.text(pParent2Name);
pParent3Name = translate.text(pParent3Name);
}
pAttributeName = ArrayUtils.joinNonEmptyFields([parent4FullName, pParent3Name, pParent2Name, pParent1Name, pAttributeName], " / ");
return pAttributeName;
}
}
......@@ -84,6 +84,7 @@
<name>SENDER</name>
<title>Sender address</title>
<mandatory v="true" />
<onValidation>%aditoprj%/entity/BulkMail_entity/entityfields/sender/onValidation.js</onValidation>
</entityField>
<entityActionField>
<name>sendMail</name>
......@@ -95,11 +96,13 @@
<entityField>
<name>ICON</name>
<contentType>IMAGE</contentType>
<searchable v="false" />
<valueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/icon/valueProcess.js</valueProcess>
</entityField>
<entityField>
<name>preview</name>
<contentType>HTML</contentType>
<searchable v="false" />
<state>READONLY</state>
<displayValueProcess>%aditoprj%/entity/BulkMail_entity/entityfields/preview/displayValueProcess.js</displayValueProcess>
</entityField>
......@@ -120,6 +123,7 @@
<entityField>
<name>BINDATA</name>
<contentType>FILE</contentType>
<searchable v="false" />
<stateProcess>%aditoprj%/entity/BulkMail_entity/entityfields/bindata/stateProcess.js</stateProcess>
</entityField>
<entityFieldGroup>
......@@ -143,6 +147,7 @@
<alias>Data_alias</alias>
<fromClauseProcess>%aditoprj%/entity/BulkMail_entity/recordcontainers/db/fromClauseProcess.js</fromClauseProcess>
<onDBInsert>%aditoprj%/entity/BulkMail_entity/recordcontainers/db/onDBInsert.js</onDBInsert>
<onDBUpdate>%aditoprj%/entity/BulkMail_entity/recordcontainers/db/onDBUpdate.js</onDBUpdate>
<onDBDelete>%aditoprj%/entity/BulkMail_entity/recordcontainers/db/onDBDelete.js</onDBDelete>
<linkInformation>
<linkInformation>
......
import("system.result");
import("Communication_lib");
import("Entity_lib");
var message;
var sender = ProcessHandlingUtils.getOnValidationValue();
var fn = CommValidationUtil.makeValidationFn("EMAIL");
if (fn !== null)
message = fn.call(null, sender);
if (message)
result.string(message);
\ No newline at end of file
import("Sql_lib");
import("system.result");
import("system.vars");
import("system.db");
import("system.util");
import("Document_lib");
//TODO - Function
var upload = vars.get("$field.BINDATA");
var bindataUpload = DocumentUtil.getBindataFromUpload(upload);
var filename = "";
var bindata = "";
if(bindataUpload != "")
{
filename = DocumentUtil.getFilenameFromUpload(upload);
bindata = bindataUpload;
}
if(bindata != "" && filename != "")
{
let sysAlias = "_____SYSTEMALIAS";
var binaryId = db.cell(SqlCondition.begin(sysAlias)
.andPrepareVars("ASYS_BINARIES.ROW_ID", "$field.BULKMAILID")
.buildSql("select ID from ASYS_BINARIES", "1=2"), sysAlias);
db.updateBinary(binaryId, "", bindata, filename, "", "", sysAlias);
}
\ No newline at end of file
import("KeywordRegistry_basic");
import("Contact_lib");
import("Sql_lib");
import("system.db");
import("system.neon");
import("system.vars");
import("DocumentTemplate_lib");
var template = DocumentTemplate.loadTemplate(vars.get("$field.DOCUMENTTEMPLATE_ID"));
var contactIds = db.table(SqlCondition.begin()
.andPrepareVars("LETTERRECIPIENT.SERIALLETTER_ID", "$field.SERIALLETTERID")
.andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$letter(), true))
.buildSql("select CONTACT_ID from LETTERRECIPIENT join CONTACT on LETTERRECIPIENT.CONTACT_ID = CONTACT.CONTACTID", "1=2")
);
var document = template.getSerialLetterByContactIds(contactIds);
if (document)
neon.download(document, template.filename);
\ No newline at end of file
import("DocumentTemplate_lib");
import("system.neon");
import("Bulkmail_lib");
import("system.vars");
var document = SerialLetterUtils.buildSerialLetter(vars.get("$field.SERIALLETTERID"));
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<neonNotificationType xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonNotificationType/1.1.0">
<name>BulkMailSent</name>
<title>Bulk mail sent</title>
<majorModelMode>DISTRIBUTED</majorModelMode>
<icon>VAADIN:ENVELOPES</icon>
</neonNotificationType>
<?xml version="1.0" encoding="UTF-8"?>
<neonNotificationType xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonNotificationType/1.1.0">
<name>BulkMailSent</name>
<title>Bulk mail sent</title>
<majorModelMode>DISTRIBUTED</majorModelMode>
<icon>VAADIN:ENVELOPES</icon>
</neonNotificationType>
<?xml version="1.0" encoding="UTF-8"?>
<neonNotificationType xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonNotificationType/1.1.0">
<name>DownloadReady</name>
<title>Download ready</title>
<majorModelMode>DISTRIBUTED</majorModelMode>
<icon>VAADIN:DOWNLOAD_ALT</icon>
<archivable v="false" />
<onResultOpen>%aditoprj%/neonNotificationType/DownloadReady/onResultOpen.js</onResultOpen>
</neonNotificationType>
import("system.logging");
import("system.vars");
var varses = ["$"];
var existses = {};
varses.forEach(function (v) {
this[v] = vars.exists(v);
}, existses);
logging.log(JSON.stringify(existses, null, "\t"))
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
<name>BulkMailAddRecipientsEdit_view</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<isSmall v="true" />
<layout>
<noneLayout>
<name>layout</name>
</noneLayout>
</layout>
<children>
<genericViewTemplate>
<name>Generic</name>
<editMode v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>96932894-43f2-471f-b511-3b38bd5f93cb</name>
<entityField>BULKMAIL_ID</entityField>
</entityFieldLink>
</fields>
</genericViewTemplate>
<genericViewTemplate>
<name>Message</name>
<hideLabels v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>e29ba637-3638-4c72-bdb7-65034636a882</name>
<entityField>recipientCountMessage</entityField>
</entityFieldLink>
</fields>
</genericViewTemplate>
</children>
</neonView>
<?xml version="1.0" encoding="UTF-8"?>
<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
<name>BulkMailAddRecipientsEdit_view</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<isSmall v="true" />
<layout>
<noneLayout>
<name>layout</name>
</noneLayout>
</layout>
<children>
<genericViewTemplate>
<name>Generic</name>
<editMode v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>96932894-43f2-471f-b511-3b38bd5f93cb</name>
<entityField>BULKMAIL_ID</entityField>
</entityFieldLink>
</fields>
</genericViewTemplate>
<genericViewTemplate>
<name>Message</name>
<hideLabels v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>e29ba637-3638-4c72-bdb7-65034636a882</name>
<entityField>recipientCountMessage</entityField>
</entityFieldLink>
</fields>
</genericViewTemplate>
</children>
</neonView>
<?xml version="1.0" encoding="UTF-8"?>
<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
<name>BulkMailEdit_view</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<layout>
<boxLayout>
<name>layout</name>
</boxLayout>
</layout>
<children>
<genericViewTemplate>
<name>BulkMail</name>
<editMode v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>b68c65de-4ecd-4a23-9242-f85e7b708b1e</name>
<entityField>DOCUMENTTEMPLATE_ID</entityField>
</entityFieldLink>
<entityFieldLink>
<name>f040d032-823c-4199-8314-01d784fdc167</name>
<entityField>BINDATA</entityField>
</entityFieldLink>
<entityFieldLink>
<name>e363bda2-d8bf-456e-bcae-d1870408022a</name>
<entityField>NAME</entityField>
</entityFieldLink>
<entityFieldLink>
<name>06f08869-5a81-41cb-8c7e-51be6a7041a7</name>
<entityField>DESCRIPTION</entityField>
</entityFieldLink>
<entityFieldLink>
<name>c73d0fb7-b740-48ac-8f3e-fd4199f169da</name>
<entityField>SUBJECT</entityField>
</entityFieldLink>
<entityFieldLink>
<name>e4ec09c2-3815-4a3b-bce8-c12d5b919b04</name>
<entityField>SENDER</entityField>
</entityFieldLink>
</fields>
</genericViewTemplate>
</children>
</neonView>
<?xml version="1.0" encoding="UTF-8"?>
<neonView xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.1.1" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.1.1">
<name>BulkMailEdit_view</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<layout>
<boxLayout>
<name>layout</name>
</boxLayout>
</layout>
<children>
<genericViewTemplate>
<name>BulkMail</name>
<editMode v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>b68c65de-4ecd-4a23-9242-f85e7b708b1e</name>
<entityField>DOCUMENTTEMPLATE_ID</entityField>
</entityFieldLink>
<entityFieldLink>
<name>f040d032-823c-4199-8314-01d784fdc167</name>
<entityField>BINDATA</entityField>
</entityFieldLink>
<entityFieldLink>
<name>e363bda2-d8bf-456e-bcae-d1870408022a</name>
<entityField>NAME</entityField>
</entityFieldLink>
<entityFieldLink>
<name>06f08869-5a81-41cb-8c7e-51be6a7041a7</name>
<entityField>DESCRIPTION</entityField>
</entityFieldLink>
<entityFieldLink>
<name>c73d0fb7-b740-48ac-8f3e-fd4199f169da</name>
<entityField>SUBJECT</entityField>
</entityFieldLink>
<entityFieldLink>
<name>e4ec09c2-3815-4a3b-bce8-c12d5b919b04</name>
<entityField>SENDER</entityField>
</entityFieldLink>
</fields>
</genericViewTemplate>
</children>
</neonView>
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("Email_lib");
import("system.process");
/**
* 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 {String} [pUser=currentUser] User that will get the notification, if null (not undefined!), no notification
* will be created.
*/
BulkMailUtils.sendBulkMailOnServer = function (pBulkMailId, pUser)
{
if (pUser === undefined)
pUser = EmployeeUtils.getCurrentUserId();
process.execute("sendBulkMail_serverProcess",
{
bulkMailId : pBulkMailId,
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
*
* @return {Object} count of sucessful and failed mails
*/
BulkMailUtils.sendBulkMail = function (pBulkMailId)
{
//TODO: Mailbridge, Werbesperre beachten
var [templateId, subject, sender] = db.array(db.ROW, SqlCondition.begin()
.andPrepare("BULKMAIL.BULKMAILID", pBulkMailId)
.buildSql("select DOCUMENTTEMPLATE_ID, SUBJECT, SENDER from BULKMAIL", "1=2")
);
var template;
if (templateId)
template = DocumentTemplate.loadTemplate(templateId);
else
template = DocumentTemplate.loadTemplate(pBulkMailId, "BULKMAIL");
var emailSender;
var recipientData = db.table(SqlCondition.begin()
.andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
.andPrepare("BULKMAILRECIPIENT.STATUS", $KeywordRegistry.bulkMailRecipientStatus$sent(), "# != ?")
.andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$mail(), true))
.buildSql("select BULKMAILRECIPIENTID, BULKMAILRECIPIENT.CONTACT_ID, '' from BULKMAILRECIPIENT \n\
join CONTACT on BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID", "1=2")
);
var contactIds = recipientData.map(function (e) {return e[1];});
var successIds = [];
var failedIds = [];
var sentDate = vars.get("$sys.date");
var mails = template.getReplacedEmailsByContactIds(contactIds);
var subjectTemplate = new DocumentTemplate(subject, DocumentTemplate.types.PLAIN);
var subjects = subjectTemplate.getReplacedContentByContactIds(contactIds);
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]]; //TODO: email address missing
email.sender = emailSender;
email.subject = subjects[contactId];
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", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$sent(), sentDate],
SqlCondition.begin()
.andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", successIds)
.build("1=2")
);
db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$failed(), sentDate],
SqlCondition.begin()
.andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", failedIds)
.build("1=2")
);
db.updateData("BULKMAIL", ["STATUS"], null, [$KeywordRegistry.bulkMailStatus$sent()],
SqlCondition.equals("BULKMAIL.BULKMAILID", pBulkMailId, "1=2"));
return {
sucessful : successIds.length,
failed : failedIds.length
};
}
BulkMailUtils.openAddRecipientView = function (pContactIds)
{
var params = {
"ContactIds_param" : pContactIds
};
neon.openContext("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
}
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"));
}
}
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);
}
function SerialLetterUtils () {}
SerialLetterUtils.addRecipients = function (pBulkMailId, 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(), pBulkMailId, pContactIds[i]]]);
}
db.inserts(inserts);
}
SerialLetterUtils.openAddRecipientView = function (pContactIds)
{
var params = {
"ContactIds_param" : pContactIds
};
neon.openContext("SerialLetterAddRecipients", "SerialLetterAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
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("Email_lib");
import("system.process");
/**
* 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 {String} [pUser=currentUser] User that will get the notification, if null (not undefined!), no notification
* will be created.
*/
BulkMailUtils.sendBulkMailOnServer = function (pBulkMailId, pUser)
{
if (pUser === undefined)
pUser = EmployeeUtils.getCurrentUserId();
process.execute("sendBulkMail_serverProcess",
{
bulkMailId : pBulkMailId,
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
*
* @return {Object} count of sucessful and failed mails
*/
BulkMailUtils.sendBulkMail = function (pBulkMailId)
{
//TODO: Mailbridge, Werbesperre beachten
var [templateId, subject, emailSender] = db.array(db.ROW, SqlCondition.begin()
.andPrepare("BULKMAIL.BULKMAILID", pBulkMailId)
.buildSql("select DOCUMENTTEMPLATE_ID, SUBJECT, SENDER from BULKMAIL", "1=2")
);
var template;
if (templateId)
template = DocumentTemplate.loadTemplate(templateId);
else
template = DocumentTemplate.loadTemplate(pBulkMailId, "BULKMAIL");
var recipientData = db.table(SqlCondition.begin()
.andPrepare("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
.andPrepare("BULKMAILRECIPIENT.STATUS", $KeywordRegistry.bulkMailRecipientStatus$sent(), "# != ?")
.andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$mail(), true))
.buildSql("select BULKMAILRECIPIENTID, BULKMAILRECIPIENT.CONTACT_ID, '' from BULKMAILRECIPIENT \n\
join CONTACT on BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID", "1=2")
);
var contactIds = recipientData.map(function (e) {return e[1];});
var successIds = [];
var failedIds = [];
var sentDate = vars.get("$sys.date");
var mails = template.getReplacedEmailsByContactIds(contactIds);
var subjectTemplate = new DocumentTemplate(subject, DocumentTemplate.types.PLAIN);
var subjects = subjectTemplate.getReplacedContentByContactIds(contactIds);
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]]; //TODO: email address missing
email.sender = emailSender;
email.subject = subjects[contactId];
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", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$sent(), sentDate],
SqlCondition.begin()
.andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", successIds)
.build("1=2")
);
db.updateData("BULKMAILRECIPIENT", ["STATUS", "SENTDATE"], null, [$KeywordRegistry.bulkMailRecipientStatus$failed(), sentDate],
SqlCondition.begin()
.andIn("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", failedIds)
.build("1=2")
);
db.updateData("BULKMAIL", ["STATUS"], null, [$KeywordRegistry.bulkMailStatus$sent()],
SqlCondition.equals("BULKMAIL.BULKMAILID", pBulkMailId, "1=2"));
return {
sucessful : successIds.length,
failed : failedIds.length
};
}
BulkMailUtils.openAddRecipientView = function (pContactIds)
{
var params = {
"ContactIds_param" : pContactIds
};
neon.openContext("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
}
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"));
}
}
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);
}
function SerialLetterUtils () {}
SerialLetterUtils.addRecipients = function (pBulkMailId, 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(), pBulkMailId, pContactIds[i]]]);
}
db.inserts(inserts);
}
SerialLetterUtils.openAddRecipientView = function (pContactIds)
{
var params = {
"ContactIds_param" : pContactIds
};
neon.openContext("SerialLetterAddRecipients", "SerialLetterAddRecipientsEdit_view", null, neon.OPERATINGSTATE_NEW, params);
}
SerialLetterUtils.buildSerialLetter = function (pSerialLetterId)
{
process.executeAsync("buildSerialLetter_serverProcess", {
"serialLetterId" : pSerialLetterId
}, false, "_____USER_bcdfb521-c7d0-4ef1-8916-78e7d3232046", process.THREADPRIORITY_VERYHIGH);
}
\ No newline at end of file
This diff is collapsed.
<?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>buildSerialLetter_serverProcess</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<process>%aditoprj%/process/buildSerialLetter_serverProcess/process.js</process>
<alias>Data_alias</alias>
<variants>
<element>EXECUTABLE</element>
</variants>
</process>
import("system.logging");
import("system.result");
import("system.vars");
import("KeywordRegistry_basic");
import("Contact_lib");
import("Sql_lib");
import("system.db");
import("system.neon");
import("DocumentTemplate_lib");
var letterId = vars.get("$local.serialLetterId");
var templateId = db.cell(SqlCondition.begin()
.andPrepare("SERIALLETTER.SERIALLETTERID", letterId)
.buildSql("select DOCUMENTTEMPLATE_ID from SERIALLETTER", "1=2"));
var template = DocumentTemplate.loadTemplate(templateId);
var contactIds = db.table(SqlCondition.begin()
.andPrepare("LETTERRECIPIENT.SERIALLETTER_ID", letterId)
.andSqlCondition(ContactUtils.getCommRestrictionCondition($KeywordRegistry.communicationMediumCampaign$letter(), true))
.buildSql("select CONTACT_ID from LETTERRECIPIENT join CONTACT on LETTERRECIPIENT.CONTACT_ID = CONTACT.CONTACTID", "1=2")
);
var document = template.getSerialLetterByContactIds(contactIds);
logging.log("ja")
if (document)
neon.download(document, template.filename);
\ No newline at end of file
import("system.datetime");
import("Sql_lib");
import("system.db");
import("system.util");
import("system.translate");
import("Bulkmail_lib");
import("system.vars");
import("system.notification");
var startTime = datetime.date();
var bulkMailId = vars.get("$local.bulkMailId");
var user = vars.get("$local.user");
var res = BulkMailUtils.sendBulkMail(bulkMailId);
if (user)
{
var mailName = db.cell(SqlCondition.begin()
.andPrepare("BULKMAIL.BULKMAILID", bulkMailId)
.buildSql("select NAME from BULKMAIL")
);
var message = translate.withArguments("Bulk mail \"%0\" was sent!", [mailName]);
var description = translate.withArguments("%0 mails sent sucessfully, %1 mails failed. Process took %2 s.",
[res.sucessful, res.failed, Math.round((datetime.date() - startTime) / datetime.ONE_SECOND)]);
notification.addNotification(util.getNewUUID(), null, null, null, "BulkMailSent", notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);
import("system.datetime");
import("Sql_lib");
import("system.db");
import("system.util");
import("system.translate");
import("Bulkmail_lib");
import("system.vars");
import("system.notification");
var startTime = datetime.date();
var bulkMailId = vars.get("$local.bulkMailId");
var user = vars.get("$local.user");
var res = BulkMailUtils.sendBulkMail(bulkMailId);
if (user)
{
var mailName = db.cell(SqlCondition.begin()
.andPrepare("BULKMAIL.BULKMAILID", bulkMailId)
.buildSql("select NAME from BULKMAIL")
);
var message = translate.withArguments("Bulk mail \"%0\" was sent!", [mailName]);
var description = translate.withArguments("%0 mails sent sucessfully, %1 mails failed. Process took %2 s.",
[res.sucessful, res.failed, Math.round((datetime.date() - startTime) / datetime.ONE_SECOND)]);
notification.addNotification(util.getNewUUID(), null, null, null, "BulkMailSent", notification.PRIO_NORMAL, 2, notification.STATE_UNSEEN, [user], message, description);
}
\ 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