diff --git a/entity/Salesproject_entity/Salesproject_entity.aod b/entity/Salesproject_entity/Salesproject_entity.aod index 6ed29045095d9f06f042d66f43da31888a7defa5..2e65295c1f03ee662216df811a02d44554d43785 100644 --- a/entity/Salesproject_entity/Salesproject_entity.aod +++ b/entity/Salesproject_entity/Salesproject_entity.aod @@ -380,7 +380,6 @@ <title>Days inactive</title> <contentType>NUMBER</contentType> <state>READONLY</state> - <valueProcess>%aditoprj%/entity/Salesproject_entity/entityfields/inactivetime/valueProcess.js</valueProcess> </entityField> <entityConsumer> <name>KeywordWonLost</name> @@ -1003,6 +1002,11 @@ <recordfield>SALESPROJECT.PROBABILITY</recordfield> <aggregateType>AVG</aggregateType> </aggregateFieldDbMapping> + <dbRecordFieldMapping> + <name>InactiveTime.value</name> + <expression>%aditoprj%/entity/Salesproject_entity/recordcontainers/db/recordfieldmappings/inactivetime.value/expression.js</expression> + <isFilterable v="true" /> + </dbRecordFieldMapping> </recordFieldMappings> <linkInformation> <linkInformation> diff --git a/entity/Salesproject_entity/entityfields/inactivetime/valueProcess.js b/entity/Salesproject_entity/entityfields/inactivetime/valueProcess.js deleted file mode 100644 index 0daeae79aa840b4f4acaa4c0f65adcdcbdab2858..0000000000000000000000000000000000000000 --- a/entity/Salesproject_entity/entityfields/inactivetime/valueProcess.js +++ /dev/null @@ -1,28 +0,0 @@ -import("system.datetime"); -import("system.translate"); -import("system.result"); -import("system.vars"); -import("ActivityTask_lib"); -import("Date_lib"); - -var entryDate = ActivityUtils.getLastActivityDate(vars.get("$field.SALESPROJECTID")); -if (!entryDate) -{ - entryDate = vars.get("$field.DATE_NEW"); -} - -var roleoutDate = vars.getString("$field.ENDDATE"); -var daysPassed ; -if (!roleoutDate || roleoutDate < datetime.date()) -{ - daysPassed = 0; -} -else -{ - daysPassed = DateUtils.getDayDifference(entryDate); -} - -if (daysPassed != null) -{ - result.string(daysPassed); -} \ No newline at end of file diff --git a/entity/Salesproject_entity/recordcontainers/db/recordfieldmappings/inactivetime.value/expression.js b/entity/Salesproject_entity/recordcontainers/db/recordfieldmappings/inactivetime.value/expression.js new file mode 100644 index 0000000000000000000000000000000000000000..b590c9b4aae70ba5ea597df6f85a9eaafec27c26 --- /dev/null +++ b/entity/Salesproject_entity/recordcontainers/db/recordfieldmappings/inactivetime.value/expression.js @@ -0,0 +1,16 @@ +import("system.result"); +import("system.SQLTYPES"); +import("Sql_lib"); +import("ActivityTask_lib"); + +var maskingUtils = new SqlMaskingUtils(); +var dateDiff = maskingUtils.dayDateDifference( + SqlUtils.nullableWithDefault( + ActivityUtils.getLastActivityDateSql("SALESPROJECT.SALESPROJECTID"), + "SALESPROJECT.DATE_NEW" + ) +); +result.string( + SqlBuilder.caseWhen("SALESPROJECT.ENDDATE is null or SALESPROJECT.ENDDATE < current_timestamp") + .then("0").elseValue(dateDiff) +); diff --git a/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod b/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod index 888b2580c7beec222342d1498e8d057d6717eacf..9a5e4d17919402b83f14067c64751bf09399fbdf 100644 --- a/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod +++ b/neonView/SalesprojectFilter_view/SalesprojectFilter_view.aod @@ -88,6 +88,10 @@ <name>88e6bebb-e83d-43ec-82f1-cc778fac458e</name> <entityField>CLASSIFICATIONVALUE</entityField> </neonTableColumn> + <neonTableColumn> + <name>cdacc33b-1f40-4f1f-8541-d52309414c16</name> + <entityField>InactiveTime</entityField> + </neonTableColumn> <neonTableColumn> <name>c00e5148-54c8-488d-817a-2938e124871b</name> <entityField>DATE_NEW</entityField> @@ -141,6 +145,10 @@ <name>6d9d1365-985a-4357-8ecc-16ddcc201ea8</name> <entityField>CLASSIFICATIONVALUE</entityField> </neonTreeTableColumn> + <neonTreeTableColumn> + <name>82185629-f065-448a-bd20-ad4b12a179bf</name> + <entityField>InactiveTime</entityField> + </neonTreeTableColumn> <neonTreeTableColumn> <name>c5e66669-4e12-4933-94e9-7db5c7688250</name> <entityField>DATE_NEW</entityField> diff --git a/process/ActivityTask_lib/process.js b/process/ActivityTask_lib/process.js index 5ac3bb56f561036dbeeb1ad4755f1c3d41c5c376..c15bd585547241bd78663f68a4335a8ae86b07b3 100644 --- a/process/ActivityTask_lib/process.js +++ b/process/ActivityTask_lib/process.js @@ -372,21 +372,32 @@ ActivityUtils.createNewActivity = function(pRowId, pAdditionalLinks, pParentCont */ ActivityUtils.getLastActivityDate = function(pRowId) { - var context = ContextUtils.getCurrentContextId(); - var sqlUtil = new SqlMaskingUtils(); - - var entryDate = newSelect(sqlUtil.max("ENTRYDATE")) - .from("ACTIVITY") - .join("ACTIVITYLINK", "ACTIVITY.ACTIVITYID = ACTIVITYLINK.ACTIVITY_ID") - .where("ACTIVITYLINK.OBJECT_TYPE", context) - .and("ACTIVITYLINK.OBJECT_ROWID", pRowId) - .cell(); - + var entryDate = ActivityUtils.getLastActivityDateSql("'" + pRowId + "'").cell(); if (entryDate != "") return parseInt(entryDate); return null; } +/* + * Returns an subsql that resolves to the date of the last activity. + * + * @param {String} pRowIdField <p> + * The field holding the rowid of the dataset.<br> + * @return {SqlBuilder} <p> + * An subsql that resolves to the date of the last activity. + */ +ActivityUtils.getLastActivityDateSql = function(pRowIdField) +{ + var context = ContextUtils.getCurrentContextId(); + var maskingUtils = new SqlMaskingUtils(); + return newSelect(maskingUtils.max("ENTRYDATE")) + .from("ACTIVITY") + .join("ACTIVITYLINK", "ACTIVITY.ACTIVITYID = ACTIVITYLINK.ACTIVITY_ID") + .where("ACTIVITYLINK.OBJECT_TYPE", context) + // direct concationation because pRowIdField is a field + .and("ACTIVITYLINK.OBJECT_ROWID = " + pRowIdField); +} + /** * Add the links to the link-table in new mode. * diff --git a/process/Sql_lib/process.js b/process/Sql_lib/process.js index 2e20ae0d4b062631b3b3b76ba9aa498498258ce5..b07dfb76f76c4283923f963a3260586e3b4342dd 100644 --- a/process/Sql_lib/process.js +++ b/process/Sql_lib/process.js @@ -3310,6 +3310,65 @@ function SqlMaskingUtils (pAlias) this.alias = pAlias; } +/** + * Returns the reminder of: arg1 / arg2 + * + * @param {string|SqlBuilder} pField1 arg1 + * @param {string|SqlBuilder} pField2 arg2 + * + * @returns the reminder of the division + */ +SqlMaskingUtils.prototype.modulo = function(pField1, pField2) +{ + switch(this.dbType) + { + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_ORACLE10_THIN: + case db.DBTYPE_DERBY10: + case db.DBTYPE_POSTGRESQL8: + return "mod((" + pField1.toString() + "), (" + pField2.toString() + "))"; + case db.DBTYPE_SQLSERVER2000: + case db.DBTYPE_MARIADB10: + case db.DBTYPE_MYSQL4: + return "((" + pField1.toString() + ") % (" + pField2.toString() + "))"; + } +} + +/** + * Returns an sql expression resolving into the diffrence between 2 dates in days + * Notet that pDate2Field is optional it will default to the current date + * + * @param {string|SqlBuilder} pDateField1 the first date + * @param {string|SqlBuilder} pDateField2 the optional second date, defaults to the current date + * + * @returns the diffrence between the two dates in days + */ +SqlMaskingUtils.prototype.dayDateDifference = function(pDateField1, pDateField2) +{ + var maskingUtils = new SqlMaskingUtils(); + + var date1 = maskingUtils.cast("(" + pDateField1.toString() + ")", SQLTYPES.DATE); + var date2 = pDateField2 ? maskingUtils.cast("(" + pDateField2.toString() + ")", SQLTYPES.DATE) : "current_date"; + + switch(this.dbType) + { + case db.DBTYPE_DERBY10: + // JDBC escape systax is required for timestampdiff + return "{fn timestampdiff(SQL_TSI_DAY, " + date1 + ", " + date2 + ")}"; + case db.DBTYPE_POSTGRESQL8: + case db.DBTYPE_SQLSERVER2000: + return "datediff(day, " + date1 + ", " + date2 + ")"; + case db.DBTYPE_MYSQL4: + case db.DBTYPE_MARIADB10: + return "datediff(" + date1 + ", " + date2 + ")"; + case db.DBTYPE_ORACLE10_CLUSTER: + case db.DBTYPE_ORACLE10_OCI: + case db.DBTYPE_ORACLE10_THIN: + return "(" + date1 + " - " + date2 + ")"; + } +} + /** * returns the concat symbol depending on database type * @return {String} Concat Symbol @@ -4721,3 +4780,19 @@ SqlUtils.getSqlConditionalOperator = function(pOperator) throw new Error("Unsupported operator " + pOperator); } } + +/** + * Returns the pNullableExpr if pNullableExpr is not null + * otherwise it returns pDefaultExpr + * + * @param {string|SqlBuilder} pNullableExpr a nullable expression + * @param {string|SqlBuilder} pDefaultExpr the default expression if pNullableExpr is null + * + * @returns {SqlBuilder._CaseStatement} pNullableExpr with pDefaultExpr as fallback + */ +SqlUtils.nullableWithDefault = function(pNullableExpr, pDefaultExpr) +{ + return SqlBuilder.caseStatement() + .when("(" + pNullableExpr.toString() + ") is null").then(pDefaultExpr) + .elseValue(pNullableExpr); +}