Skip to content
Snippets Groups Projects
Commit da5ec273 authored by Johannes Goderbauer's avatar Johannes Goderbauer
Browse files

[Projekt: Entwicklung - Neon][TicketNr.: 1023713][COMM - Standard setzten...

[Projekt: Entwicklung - Neon][TicketNr.: 1023713][COMM - Standard setzten (Aktion, Button, Darstellung)]
parent 3436eced
No related branches found
No related tags found
No related merge requests found
Showing
with 775 additions and 465 deletions
......@@ -15,7 +15,7 @@
<columnName>ADDR</columnName>
<caption>${COMM_ADDRESS}</caption>
<contentTypeProcess>%aditoprj%/entity/Comm_entity/entityfields/addr/contentTypeProcess.js</contentTypeProcess>
<valueProcess>%aditoprj%/entity/Comm_entity/entityfields/addr/valueProcess.js</valueProcess>
<onValidation>%aditoprj%/entity/Comm_entity/entityfields/addr/onValidation.js</onValidation>
</entityField>
<entityField>
<name>COMMID</name>
......@@ -41,6 +41,7 @@
<columnName>MEDIUM_ID</columnName>
<caption>Medium</caption>
<possibleItemsProcess>%aditoprj%/entity/Comm_entity/entityfields/medium_id/possibleItemsProcess.js</possibleItemsProcess>
<valueProcess>%aditoprj%/entity/Comm_entity/entityfields/medium_id/valueProcess.js</valueProcess>
</entityField>
<entityField>
<name>RELATION_ID</name>
......@@ -87,6 +88,12 @@ So, for only showing telephone-types you&amp;apos;ve to specify this parameter w
<entityIncomingField>
<name>#INCOMING</name>
</entityIncomingField>
<entityParameter>
<name>RelationsMainCountry_param</name>
<code>%aditoprj%/entity/Comm_entity/entityfields/relationsmaincountry_param/code.js</code>
<mandatory v="false" />
<description>PARAMETER</description>
</entityParameter>
</entityFields>
<linkInformation>
<linkInformation>
......
import("system.logging");
import("system.text");
import("system.result");
import("system.vars");
import("Sql_lib");
import("Keyword_lib");
var cond, relId, mediumCategories, keywordUtil;
cond = "";
if(vars.exists("$param.RelId_param")){
relId = vars.get("$param.RelId_param");
if (relId != null && relId != "" && relId != undefined)
{
cond += " and COMM.RELATION_ID in ('" + relId + "')";//TODO: quoting/prevent sql-injection
}
}
if (vars.exists("$param.MediumCategoriesFilter_param")){
mediumCategories = vars.get("$param.MediumCategoriesFilter_param");
if (mediumCategories != null && mediumCategories != "" && mediumCategories != undefined)
{
mediumCategories = text.decodeMS(mediumCategories);
keywordUtil = new KeywordUtils();
var kwd = keywordUtil.createKeyword("COMM.MEDIUM");
kwd.filter(function(id, name, customs){
return mediumCategories.indexOf(customs.category) > -1;
});
mediumIds = kwd.toArray("id");
if (mediumIds.length == 0)
throw new Error();//TODO: add message
cond += " and COMM.MEDIUM_ID in (" + mediumIds.join(", ") + ")";
}
}
result.string(cond ? "1 = 1 " + cond: "1 = 2");
\ No newline at end of file
import("system.db");
import("system.logging");
import("system.text");
import("system.result");
import("system.vars");
import("Sql_lib");
import("Keyword_lib");
var cond, relId, mediumCategories, keywordUtil, condStr;
cond = new SqlCondition();
if(vars.exists("$param.RelId_param")){
relId = vars.get("$param.RelId_param");
if (relId != null && relId != ""){
cond.andPrepare("COMM.RELATION_ID", "# = ?", relId);
}
}
if (vars.exists("$param.MediumCategoriesFilter_param")){
mediumCategories = vars.get("$param.MediumCategoriesFilter_param");
if (mediumCategories != null && mediumCategories != "") {
mediumCategories = text.decodeMS(mediumCategories);
keywordUtil = new KeywordUtils();
var kwd = keywordUtil.createKeyword("COMM.MEDIUM");
kwd.filter(function(id, name, customs){
return mediumCategories.indexOf(customs.category) > -1;
});
mediumIds = kwd.toArray("id");
if (mediumIds.length == 0)
throw new Error();//TODO: add message
cond.and("COMM.MEDIUM_ID in (" + mediumIds.join(", ") + ")");
}
}
condStr = db.translateCondition([cond.toString("1 = 2"), cond.preparedValues]);//TODO: this should not be necessary in the future
result.string(condStr);
\ No newline at end of file
......@@ -3,26 +3,12 @@ import("system.vars");
import("system.result");
import("system.neon");
var keywordUtils, category, medium, contentType;
var keywordUtils, medium, contentType;
//TODO: add constants for contentTypes #1022547
medium = vars.get("$field.MEDIUM_ID");
if (medium){
keywordUtils = new KeywordUtils();
category = keywordUtils.createKeyword("COMM.MEDIUM").getPropForKey(medium, "category", true);
switch (category) {
case "PHONE":
contentType = "TELEPHONE";
break;
case "EMAIL":
contentType = "EMAIL";
break;
case "WEBSITE":
contentType = "LINK";
break;
default:
contentType = "TEXT";
break;
}
contentType = keywordUtils.createKeyword("COMM.MEDIUM").getPropForKey(medium, "contentType", true) || "TEXT";
}
else {
contentType = "TEXT";
......
import("system.logging");
import("system.translate");
import("system.vars");
import("system.net");
import("system.result");
import("system.mail");
import("Keyword_lib");
import("Comm_lib");
var kwdUtil = new KeywordUtils();
var kwd = kwdUtil.createKeyword("COMM.MEDIUM");
var commMedium = vars.get("$field.MEDIUM_ID");
var commCategory = kwd.getPropForKey(commMedium, "contentType", true);//TODO: maybe accessible via $property - then it's not needed to keep this information within the keyword
var fn = CommValidationUtil.makeValidationFn(commCategory);
if (fn != null){
var commAddr = vars.get("$local.value");//contains the entered value - the field contains the value only after successfull validation
var additional = CommValidationUtil.getExtensionsBlueprint();
additional.countryCode = vars.get("$param.RelationsMainCountry_param");//TODO: try to use users language first and then the companies
var res = fn.call(null, commAddr, additional);
if (res != null)
result.string(res);
}
\ No newline at end of file
import("system.logging");
import("system.text");
import("system.vars");
import("system.result");
......@@ -6,7 +7,7 @@ import("Keyword_lib");
var mediumCategories, kwdUtils, kwd, items;
kwdUtils = new KeywordUtils();
if (vars.exists("$param.MediumCategoriesFilter_param") && (mediumCategories = vars.get("$param.MediumCategoriesFilter_param")) != null){
if (vars.exists("$param.MediumCategoriesFilter_param") && (mediumCategories = vars.get("$param.MediumCategoriesFilter_param")) != ""){
mediumCategories = text.decodeMS(mediumCategories);
kwd = kwdUtils.createKeyword("COMM.MEDIUM");
kwd.filter(function(id, name, customs){
......
import("system.result");
import("system.db");
import("system.logging");
import("system.vars");
import("Sql_lib");
var relId, country;
if (vars.exists("$param.RelId_param")) {
relId = vars.get("$param.RelId_param");
if (relId != "" && relId != null){
var cond = new SqlCondition();
cond.andPrepare("RELATION.RELATIONID", "# = ?", relId);
//TODO: this should happen by 1:1 links instead of manually requesting the data by a select
country = db.cell(["select ADDRESS.COUNTRY from ADDRESS "
+ "join RELATION on RELATION.ADDRESS_ID = ADDRESS.ADDRESSID "
+ cond.toWhereString(), cond.preparedValues]);
if (country != "")
result.string(country);
}
}
\ No newline at end of file
......@@ -260,6 +260,66 @@
</entityParameter>
</children>
</entityOutgoingField>
<entityOutgoingField>
<name>OrgCommEmail_dfo</name>
<fieldType>DEPENDENCY_OUT</fieldType>
<caption>Communication E-Mail</caption>
<dependency>
<name>dependency</name>
<entityName>Comm_entity</entityName>
<fieldName>#INCOMING</fieldName>
</dependency>
<children>
<entityParameter>
<name>RelId_param</name>
<code>%aditoprj%/entity/Org_entity/entityfields/orgcommemail_dfo/children/relid_param/code.js</code>
</entityParameter>
<entityParameter>
<name>MediumCategoriesFilter_param</name>
<code>%aditoprj%/entity/Org_entity/entityfields/orgcommemail_dfo/children/mediumcategoriesfilter_param/code.js</code>
</entityParameter>
</children>
</entityOutgoingField>
<entityOutgoingField>
<name>OrgCommPhone_dfo</name>
<fieldType>DEPENDENCY_OUT</fieldType>
<caption>Communication Phone</caption>
<dependency>
<name>dependency</name>
<entityName>Comm_entity</entityName>
<fieldName>#INCOMING</fieldName>
</dependency>
<children>
<entityParameter>
<name>RelId_param</name>
<code>%aditoprj%/entity/Org_entity/entityfields/orgcommphone_dfo/children/relid_param/code.js</code>
</entityParameter>
<entityParameter>
<name>MediumCategoriesFilter_param</name>
<code>%aditoprj%/entity/Org_entity/entityfields/orgcommphone_dfo/children/mediumcategoriesfilter_param/code.js</code>
</entityParameter>
</children>
</entityOutgoingField>
<entityOutgoingField>
<name>OrgCommOthers_dfo</name>
<fieldType>DEPENDENCY_OUT</fieldType>
<caption>Communication Other</caption>
<dependency>
<name>dependency</name>
<entityName>Comm_entity</entityName>
<fieldName>#INCOMING</fieldName>
</dependency>
<children>
<entityParameter>
<name>RelId_param</name>
<code>%aditoprj%/entity/Org_entity/entityfields/orgcommothers_dfo/children/relid_param/code.js</code>
</entityParameter>
<entityParameter>
<name>MediumCategoriesFilter_param</name>
<code>%aditoprj%/entity/Org_entity/entityfields/orgcommothers_dfo/children/mediumcategoriesfilter_param/code.js</code>
</entityParameter>
</children>
</entityOutgoingField>
<entityOutgoingField>
<name>OrgContract_dfo</name>
<fieldType>DEPENDENCY_OUT</fieldType>
......
import("system.text");
import("system.result");
result.string(text.encodeMS(["EMAIL"]));
import("system.result");
import("system.vars");
result.string(vars.get("$field.RELATIONID"));
\ No newline at end of file
import("system.text");
import("system.result");
result.string(text.encodeMS(["OTHER"]));
import("system.result");
import("system.vars");
result.string(vars.get("$field.RELATIONID"));
\ No newline at end of file
import("system.text");
import("system.result");
result.string(text.encodeMS(["PHONE"]));
import("system.result");
import("system.vars");
result.string(vars.get("$field.RELATIONID"));
\ 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.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.0">
<name>OrgPreview_view</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<layout>
<boxLayout>
<name>layout</name>
</boxLayout>
</layout>
<children>
<cardViewTemplate>
<name>BasicCard_template</name>
<iconField>IMAGE</iconField>
<titleField>NAME</titleField>
<descriptionField>CUSTOMERCODE_DISPLAY_fieldGroup</descriptionField>
<entityField>#ENTITY</entityField>
</cardViewTemplate>
<neonViewReference>
<name>df605bb6-5d18-4233-abc0-1da82e4910ca</name>
<entityField>OrgAddress_dfo</entityField>
<view>AddressList_view</view>
</neonViewReference>
<neonViewReference>
<name>7fbd6034-4213-41f9-bb0d-c73d55b88d82</name>
<entityField>OrgComm_dfo</entityField>
<view>CommList_view</view>
</neonViewReference>
<genericViewTemplate>
<name>OrgInfo_template</name>
<showDrawer v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>4bad7219-1a3a-4e6e-ae5a-533d3acb6845</name>
<entityField>LANGUAGE</entityField>
</entityFieldLink>
<entityFieldLink>
<name>5a397737-2768-4e16-8c58-890b8a26b4a2</name>
<entityField>STATUS</entityField>
</entityFieldLink>
<entityFieldLink>
<name>89e9aa74-1568-4f74-b42a-a02b13752802</name>
<entityField>TYPE</entityField>
</entityFieldLink>
<entityFieldLink>
<name>180e8467-4eb2-4f89-a59f-ff76b8810925</name>
<entityField>INFO</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.0.0" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/neonView/1.0.0">
<name>OrgPreview_view</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<layout>
<boxLayout>
<name>layout</name>
</boxLayout>
</layout>
<children>
<cardViewTemplate>
<name>BasicCard_template</name>
<iconField>IMAGE</iconField>
<titleField>NAME</titleField>
<descriptionField>CUSTOMERCODE_DISPLAY_fieldGroup</descriptionField>
<entityField>#ENTITY</entityField>
</cardViewTemplate>
<neonViewReference>
<name>df605bb6-5d18-4233-abc0-1da82e4910ca</name>
<entityField>OrgAddress_dfo</entityField>
<view>AddressList_view</view>
</neonViewReference>
<genericViewTemplate>
<name>OrgInfo_template</name>
<showDrawer v="true" />
<entityField>#ENTITY</entityField>
<fields>
<entityFieldLink>
<name>4bad7219-1a3a-4e6e-ae5a-533d3acb6845</name>
<entityField>LANGUAGE</entityField>
</entityFieldLink>
<entityFieldLink>
<name>5a397737-2768-4e16-8c58-890b8a26b4a2</name>
<entityField>STATUS</entityField>
</entityFieldLink>
<entityFieldLink>
<name>89e9aa74-1568-4f74-b42a-a02b13752802</name>
<entityField>TYPE</entityField>
</entityFieldLink>
<entityFieldLink>
<name>180e8467-4eb2-4f89-a59f-ff76b8810925</name>
<entityField>INFO</entityField>
</entityFieldLink>
</fields>
</genericViewTemplate>
<neonViewReference>
<name>7b3f1253-f671-4cf4-83ec-81e229910014</name>
<entityField>OrgCommEmail_dfo</entityField>
<view>CommList_view</view>
</neonViewReference>
<neonViewReference>
<name>23f420cb-fd45-433f-b385-55a49e98744f</name>
<entityField>OrgCommPhone_dfo</entityField>
<view>CommList_view</view>
</neonViewReference>
<neonViewReference>
<name>c45d71cf-b81f-4d75-876d-7f9c26b1eb12</name>
<entityField>OrgCommOthers_dfo</entityField>
<view>CommList_view</view>
</neonViewReference>
</children>
</neonView>
<?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.1.7" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/process/1.1.7">
<name>Comm_lib</name>
<majorModelMode>DISTRIBUTED</majorModelMode>
<process>%aditoprj%/process/Comm_lib/process.js</process>
</process>
import("system.translate");
import("system.net");
import("system.mail");
import("system.cti");
/**
* provides somehow static methods for validation of communication data
* do not create an instance of this
*/
function CommValidationUtil(){
}
/**
* creates a function depending on a given COMM-category (like PHONE, EMAIL, etc.) or null if no validation-function was defined for the given category
* @param {string} commCategory category that determines which function shall be created, e.g. "EMAIL"
* @return {function} function that receives the following arguments:
* <br/> - commAddress
* <br/> - extensions
* <br/>the function has to return null if everything is OK or a value with details if validation failed
*/
CommValidationUtil.makeValidationFn = function (commCategory){
var callbackFn;
switch (commCategory) {
case "EMAIL":
callbackFn = function (addrValue){
// if (!mail.isValidMailAddress(addrValue)) //TODO: enable JDito-methods
// return translate.text("no valid mail-address format");
return null;
}
break;
case "LINK":
callbackFn = function (addrValue){
// if (!net.isValidUrl(addrValue, ["http", "https"]))//TODO: enable JDito-methods
// return translate.text("no valid format");
return null;
}
break;
case "TELEPHONE":
callbackFn = function (addrValue, ext){
var country = null;
if (addrValue[0] != "+") //if the number starts with a country-identifier (e.g. +49) no country needs to be specified
country = ext.countryCode;
// if (!cti.isValidPhoneNumber(addrValue, country))//TODO: enable JDito-methods
// return translate.text("no valid phone number");
return null;
}
break;
default:
callbackFn = null;
break;
}
return callbackFn;
}
/**
* returns a blueprint for validation extensions; these extensions are needed for validating comm data and can be passed to other functions
* @return {object} a object with properties that have a specific default value; normally you want to overwrite that value
*/
CommValidationUtil.getExtensionsBlueprint = function(){
return {
countryCode: null
};
}
This diff is collapsed.
......@@ -4,7 +4,8 @@ import("system.db");
import("system.datetime");
import("system.tools");
import("system.SQLTYPES");
import("Util_lib")
import("system.text");
import("Util_lib");
/**
* Object for easier handling of conditions;
......@@ -12,8 +13,10 @@ import("Util_lib")
* you don't need to append a "1=1" condition or similar;
* @example //TODO: add missing example
*/
function SqlCondition(){
function SqlCondition(alias){
this._sqlStorage = "";
this.preparedValues = [];
this.alias = alias;
}
/**
* append with SQL-and; no paranthesize of existing conditions is done
......@@ -28,6 +31,22 @@ SqlCondition.prototype.and = function(cond){
this._sqlStorage += cond;
return this;
}
/**
* same as the "and"-function but with preparedStatement functionality
* @param {String} field the database field as "tablename.columnname"; e.g. "ORG.NAME"
* @param {String} cond the strucutre of the SQL condition as preparedString, you can use a number sign "#" as placeholder for you fieldname;
* e.g. "# > ?"; escaping the number sign is possible with a backslash "\"
* @param {String} value the value that shall be set into the prepared statement
* @param {Numeric} [fieldType] SQL-column-type; if the fieldType is not given it's loaded automatically;
* please note that this can be a performace issue if it happens a lot of times (e.g. in aloop)
* @return {Object} current SqlCondition-object
*/
SqlCondition.prototype.andPrepare = function(field, cond, value, fieldType){
cond = this._prepare(field, cond, value, fieldType);
return this.and(cond);
}
/**
* append with SQL-or; Also paranthesize the existing conditions
* @param {String} cond the condition string which shall be appended
......@@ -42,6 +61,21 @@ SqlCondition.prototype.or = function(cond){
this._sqlStorage = cond;
return this;
}
/**
* same as the "or"-function but with preparedStatement functionality
* @param {String} field the database field as "tablename.columnname"; e.g. "ORG.NAME"
* @param {String} cond the strucutre of the SQL condition as preparedString, you can use a number sign "#" as placeholder for you fieldname;
* e.g. "# > ?"; escaping the number sign is possible with a backslash "\"
* @param {String} value the value that shall be set into the prepared statement
* @param {Numeric} [fieldType] SQL-column-type; if the fieldType is not given it's loaded automatically;
* please note that this can be a performace issue if it happens a lot of times (e.g. in aloop)
* @return {Object} current SqlCondition-object
*/
SqlCondition.prototype.orPrepare = function(field, cond, value, fieldType){
cond = this._prepare(field, cond, value, fieldType);
return this.or(cond);
}
/**
* ready to use string; does not contain a where keyword at the beginning
* @param {String} alternativeCond condition that is returned when nothing has been appended
......@@ -66,6 +100,44 @@ SqlCondition.prototype.toWhereString = function(alternativeCond){
return cond;
}
/**
* hidden function for composing preparedStatements
* @param {String} field the database field as "tablename.columnname"; e.g. "ORG.NAME"
* @param {String} cond the strucutre of the SQL condition as preparedString, you can use a number sign "#" as placeholder for you fieldname;
* e.g. "# > ?"; escaping the number sign is possible with a backslash "\"
* @param {String} value the value that shall be set into the prepared statement
* @param {Numeric} [fieldType] SQL-column-type; if the fieldType is not given it's loaded automatically;
* please note that this can be a performace issue if it happens a lot of times (e.g. in aloop)
* @return {String} the replaced SQL-condition string (replace # by the fieldname)
*/
SqlCondition.prototype._prepare = function(field, cond, value, fieldType){
//this function looks more complex (and slower) than it actually is
/* the following regex looks like this after javascript-escaping of the backslash: (?<!\\)((?:\\\\)*)#
the regexp searches for the unescaped character and these characters are replaced by the field name
examples:
---------------------
| # --match |
| \# --no-match |
| \\# --match |
| \\\# --no-match |
| \\\\# --match |
---------------------
*/
//use replaceAll because it's faster and supports negative lookbehinds
cond = text.replaceAll(cond, {
//manually readd the replaced backslashes by using a group reference, because they a part of the match and therefore replaced by "replaceAll"
//since the field COULD contain already a group reference (I think this is extremely uncommon;
//probably that never happens but better stay save): escape that references within the fieldname
"(?<!\\\\)((?:\\\\\\\\)*)#": "$1" + text.replaceAll(field, {"$1": "\\$1"}),
//now that we've replaced the correct field placeholder let's replace the escaped number sign "\#" to a normal number sign "#"
"\\\\#": "#"
});
type = fieldType || SqlUtils.getSingleColumnType(field, undefined, this.alias);
this.preparedValues.push([value.toString(), type]);
return cond;
}
function SqlMaskingUtils(){
//TODO: use callbacks for different handling?
/**
......@@ -218,6 +290,42 @@ function SqlMaskingUtils(){
}
}
function SqlUtils(){
}
SqlUtils.getSingleColumnType = function(fieldOrTableName, columnName, alias)
{
var tableName, fieldVarType;
if (columnName == undefined){
fieldVarType = typeof(fieldOrTableName);
if (fieldVarType == "string")
fieldOrTableName = text.split(fieldOrTableName, "\\.");
else if (fieldVarType != "object"){
throw new TypeError();//TODO: add message
}
if (fieldOrTableName.hasOwnProperty("length") && fieldOrTableName.length == 2)
{
tableName = fieldOrTableName[0];
columnName = fieldOrTableName[1];
}
else
throw new TypeError();//TODO: add message
}
else
tableName = fieldOrTableName;
if (typeof(columnName) != "string")
throw new TypeError();//TODO: add message
if (typeof(tableName) != "string")
throw new TypeError();//TODO: add message
if (alias == undefined)
alias = db.getCurrentAlias();
return db.getColumnTypes(tableName, [columnName], alias)[0];
}
/**
*Class containing utilities for SQL
*@deprecated use SqlMaskingUtils
......
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