diff --git a/entity/TurnoverTree_entity/TurnoverTree_entity.aod b/entity/TurnoverTree_entity/TurnoverTree_entity.aod new file mode 100644 index 0000000000000000000000000000000000000000..fdef45bc089615fa9bcedabc31524678826d41f5 --- /dev/null +++ b/entity/TurnoverTree_entity/TurnoverTree_entity.aod @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<entity xmlns="http://www.adito.de/2018/ao/Model" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" VERSION="1.3.4" xsi:schemaLocation="http://www.adito.de/2018/ao/Model adito://models/xsd/entity/1.3.4"> + <name>TurnoverTree_entity</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <title>Tree</title> + <iconId>NEON:LOGO</iconId> + <recordContainer>jdito</recordContainer> + <entityFields> + <entityProvider> + <name>#PROVIDER</name> + </entityProvider> + <entityField> + <name>UID</name> + </entityField> + <entityField> + <name>CATEGORY</name> + <groupable v="true" /> + </entityField> + <entityField> + <name>TURNOVERPRICE</name> + <title>Turnover</title> + <contentType>NUMBER</contentType> + <outputFormat>#,##0.00</outputFormat> + </entityField> + <entityParameter> + <name>YearCountToShow_param</name> + <valueProcess>%aditoprj%/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/valueProcess.js</valueProcess> + <expose v="true" /> + <triggerRecalculation v="true" /> + <mandatory v="false" /> + <documentation>%aditoprj%/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/documentation.adoc</documentation> + <description>PARAMETER</description> + </entityParameter> + <entityParameter> + <name>MaxYear_param</name> + <valueProcess>%aditoprj%/entity/TurnoverTree_entity/entityfields/maxyear_param/valueProcess.js</valueProcess> + <expose v="true" /> + <triggerRecalculation v="true" /> + <mandatory v="false" /> + <documentation>%aditoprj%/entity/TurnoverTree_entity/entityfields/maxyear_param/documentation.adoc</documentation> + <description>PARAMETER</description> + </entityParameter> + <entityProvider> + <name>FilteredTurnovers</name> + <fieldType>DEPENDENCY_IN</fieldType> + <dependencies> + <entityDependency> + <name>0ea4ad47-985b-4a9c-81d8-946be324ae04</name> + <entityName>Turnover_entity</entityName> + <fieldName>Turnover_tree</fieldName> + <isConsumer v="false" /> + </entityDependency> + </dependencies> + <children> + <entityParameter> + <name>YearCountToShow_param</name> + <expose v="true" /> + </entityParameter> + </children> + </entityProvider> + <entityField> + <name>PARENT</name> + </entityField> + <entityField> + <name>GROUP</name> + <title>Product group</title> + </entityField> + <entityField> + <name>FORECASTPRICE</name> + <title>Forecast</title> + <contentType>NUMBER</contentType> + <outputFormat>#,##0.00</outputFormat> + </entityField> + <entityField> + <name>YEAR</name> + </entityField> + <entityField> + <name>MONTH</name> + </entityField> + <entityField> + <name>LAYER</name> + </entityField> + </entityFields> + <recordContainers> + <jDitoRecordContainer> + <name>jdito</name> + <jDitoRecordAlias>Data_alias</jDitoRecordAlias> + <contentProcess>%aditoprj%/entity/TurnoverTree_entity/recordcontainers/jdito/contentProcess.js</contentProcess> + <recordFields> + <element>UID.value</element> + <element>PARENT.value</element> + <element>GROUP.value</element> + <element>CATEGORY.value</element> + <element>TURNOVERPRICE.value</element> + <element>FORECASTPRICE.value</element> + <element>YEAR.value</element> + <element>MONTH.value</element> + <element>LAYER.value</element> + </recordFields> + </jDitoRecordContainer> + </recordContainers> +</entity> diff --git a/entity/TurnoverTree_entity/entityfields/maxyear_param/documentation.adoc b/entity/TurnoverTree_entity/entityfields/maxyear_param/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..fcbd74f60e6720f1d9085e894eb9220ec9ce8e85 --- /dev/null +++ b/entity/TurnoverTree_entity/entityfields/maxyear_param/documentation.adoc @@ -0,0 +1,3 @@ +this parameter is for setting the maximum year to show. + +The default is the current year. \ No newline at end of file diff --git a/entity/TurnoverTree_entity/entityfields/maxyear_param/valueProcess.js b/entity/TurnoverTree_entity/entityfields/maxyear_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..652de6453d7648618499d56b211e46eccefc2493 --- /dev/null +++ b/entity/TurnoverTree_entity/entityfields/maxyear_param/valueProcess.js @@ -0,0 +1,5 @@ +import("system.result"); +import("system.vars"); +import("system.datetime"); + +result.string(datetime.toDate(vars.get("$sys.date"), "yyyy")); \ No newline at end of file diff --git a/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/documentation.adoc b/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/documentation.adoc new file mode 100644 index 0000000000000000000000000000000000000000..a0783738ca4add70cc06867ecfe633dd35f7d086 --- /dev/null +++ b/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/documentation.adoc @@ -0,0 +1,3 @@ +This parameter is for setting the number of years to show. + +Default is 4. \ No newline at end of file diff --git a/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/valueProcess.js b/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..02fc6e39ebb2c279000ffa389aa42a31bc2f6076 --- /dev/null +++ b/entity/TurnoverTree_entity/entityfields/yearcounttoshow_param/valueProcess.js @@ -0,0 +1,3 @@ +import("system.result"); + +result.string("4"); \ No newline at end of file diff --git a/entity/TurnoverTree_entity/recordcontainers/jdito/contentProcess.js b/entity/TurnoverTree_entity/recordcontainers/jdito/contentProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e9ab2d319ba83e196acb2e09e5122e5767c62f30 --- /dev/null +++ b/entity/TurnoverTree_entity/recordcontainers/jdito/contentProcess.js @@ -0,0 +1,106 @@ +import("Turnover_lib"); +import("system.vars"); +import("system.result"); +import("Money_lib"); +import("Util_lib"); +import("system.datetime"); +import("KeywordRegistry_basic"); +import("Keyword_lib"); +import("system.translate"); + +var turnoverCategory = translate.text('Turnover'); +var forecastCategory = translate.text('Forecast'); + +var maxYear = parseInt(vars.get("$param.MaxYear_param")); +var yearCountToShow = parseInt(vars.get("$param.YearCountToShow_param")); +var minYear = maxYear - yearCountToShow + 1; + +var turnover = TurnoverUtil.getTurnoverData(maxYear, yearCountToShow); +var forecast = TurnoverUtil.getForecastData(maxYear, yearCountToShow); + +var columns = { + type: 0, + year: 1, + month: 2, + discount: 3, + vat: 4, + price: 5, + quantity: 6, + groupcodeId: 7, + groupcodeName: 8 +}; + +// combine both data sources + + +var treeData = []; +var countData = {}; + +turnover.forEach(function(row) +{ + var monthDate = new Date(row[columns.year], row[columns.month]-1); + monthDate = datetime.toDate(monthDate.getTime(), "MMM yyyy", "UTC"); + _addCount([row[columns.year], [row[columns.month], monthDate], [row[columns.groupcodeId], row[columns.groupcodeName]]], row[columns.type], row[columns.year], row[columns.month], + MoneyUtils.getGross( + (row[columns.vat] ? parseFloat(row[columns.vat]) : 0.0), + (row[columns.price] ? parseFloat(row[columns.price]) : 0.0), + (row[columns.quantity] ? parseFloat(row[columns.quantity]) : 0.0), + (row[columns.discount] ? parseFloat(row[columns.discount]) : 0.0))); +}); + +forecast.forEach(function(row) +{ + var monthDate = new Date(row[columns.year], row[columns.month]-1); + monthDate = datetime.toDate(monthDate.getTime(), "MMM yyyy", "UTC"); + _addCount([row[columns.year], [row[columns.month], monthDate], [row[columns.groupcodeId], row[columns.groupcodeName]]], row[columns.type], row[columns.year], row[columns.month], row[columns.price]); +}); + +// create tree +for (let key in countData) { + var countDataSet = countData[key]; + treeData.push([key, countDataSet.parent, countDataSet.groupName, countDataSet.category, countDataSet[turnoverCategory], countDataSet[forecastCategory], parseInt(countDataSet.year), parseInt(countDataSet.month), parseInt(countDataSet.layer)]); +} + +treeData = TreeUtils.treeOrderBy(treeData, 8, [[6, true], [7, false], [2, false]]) +result.object(treeData); + +/** + * add the counts to countData for the given key and value + * @param {Array} pKeys an array containing all keys for this value. If the x-value for one key is different from the key-value: add an array [key, value] instead of only the key + * the first key is year + * @param {String} pCategory the category to add + * @param {integer} pYear the year + * @param {integer} pMonth the month + * @param {float} pValue the value to display + */ +function _addCount(pKeys, pCategory, pYear, pMonth, pValue) { + var key = ""; + + for (let i = 0; i < pKeys.length; i++) { + let keyId; + let keyName; + + if (typeof pKeys[i] != "object") + { + keyId = pKeys[i]; + keyName = pKeys[i]; + } + else // handle array: first is id seccond is name for X-value + { + keyId = pKeys[i][0]; + keyName = pKeys[i][1]; + } + var parent = key; + + key += ";" + keyId; + + if (countData[key] == undefined) + { + countData[key] = {parent: parent, category: pCategory, groupName: keyName, data: pKeys[i], year: pYear, month: pMonth, layer: i}; // keys[0] is the category + countData[key][forecastCategory] = 0.0; + countData[key][turnoverCategory] = 0.0; + } + + countData[key][pCategory] += parseFloat(pValue); + } +} \ No newline at end of file diff --git a/entity/Turnover_entity/Turnover_entity.aod b/entity/Turnover_entity/Turnover_entity.aod index 2f8ab9d9f8efd8b691957875730d30abf726283a..ea6be4be71dd3742873344433ca8e1ee34f90239 100644 --- a/entity/Turnover_entity/Turnover_entity.aod +++ b/entity/Turnover_entity/Turnover_entity.aod @@ -64,6 +64,25 @@ </entityParameter> </children> </entityProvider> + <entityConsumer> + <name>Turnover_tree</name> + <fieldType>DEPENDENCY_OUT</fieldType> + <dependency> + <name>dependency</name> + <entityName>TurnoverTree_entity</entityName> + <fieldName>FilteredTurnovers</fieldName> + </dependency> + <children> + <entityParameter> + <name>MaxYear_param</name> + <valueProcess>%aditoprj%/entity/Turnover_entity/entityfields/turnover_tree/children/maxyear_param/valueProcess.js</valueProcess> + </entityParameter> + <entityParameter> + <name>YearCountToShow_param</name> + <valueProcess>%aditoprj%/entity/Turnover_entity/entityfields/turnover_tree/children/yearcounttoshow_param/valueProcess.js</valueProcess> + </entityParameter> + </children> + </entityConsumer> </entityFields> <recordContainers> <jDitoRecordContainer> diff --git a/entity/Turnover_entity/entityfields/turnover_tree/children/maxyear_param/valueProcess.js b/entity/Turnover_entity/entityfields/turnover_tree/children/maxyear_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..55220f39547358d4ac27319394796362654d50fc --- /dev/null +++ b/entity/Turnover_entity/entityfields/turnover_tree/children/maxyear_param/valueProcess.js @@ -0,0 +1,4 @@ +import("system.vars"); +import("system.result"); + +result.string(vars.get("$param.MaxYear_param")); \ No newline at end of file diff --git a/entity/Turnover_entity/entityfields/turnover_tree/children/yearcounttoshow_param/valueProcess.js b/entity/Turnover_entity/entityfields/turnover_tree/children/yearcounttoshow_param/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..6769ee4809dd12cbe5af03ca76deeb956e801965 --- /dev/null +++ b/entity/Turnover_entity/entityfields/turnover_tree/children/yearcounttoshow_param/valueProcess.js @@ -0,0 +1,4 @@ +import("system.vars"); +import("system.result"); + +result.string(vars.get("$param.YearCountToShow_param")); \ No newline at end of file diff --git a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js index df5df1581fcc12c9ca8487eff061760459aa4526..4f94c77a16d4c1158c06232d605d56ad62009d08 100644 --- a/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js +++ b/entity/Turnover_entity/recordcontainers/jdito/contentProcess.js @@ -1,13 +1,11 @@ +import("Turnover_lib"); import("system.vars"); -import("Sql_lib"); import("system.result"); import("Money_lib"); import("system.datetime"); -import("system.db"); import("KeywordRegistry_basic"); import("Keyword_lib"); import("system.translate"); -import("system.SQLTYPES"); var turnoverCategory = translate.text('Turnover'); var forecastCategory = translate.text('Forecast'); @@ -16,19 +14,7 @@ var maxYear = parseInt(vars.get("$param.MaxYear_param")); var yearCountToShow = parseInt(vars.get("$param.YearCountToShow_param")); var minYear = maxYear - yearCountToShow + 1; -// load data -var data = db.table(SqlCondition.begin() - .andPrepare("SALESPROJECT_FORECAST.DATE_START", maxYear, "year(#) <= ?", SQLTYPES.INTEGER) - .andPrepare("SALESPROJECT_FORECAST.DATE_START", minYear, "year(#) >= ?", SQLTYPES.INTEGER) - .buildSql("select 'Forecast', year(DATE_START) yearNum, month(DATE_START) monthNum, 0 discount, 0 vat, sum(VOLUME * 1000) price, 1 quantity, GROUPCODE prodGroup, (" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "GROUPCODE") + ") prodGroupName from SALESPROJECT_FORECAST", "1=2", " group by year(DATE_START), month(DATE_START), GROUPCODE order by yearNum, monthNum")) - .concat(db.table(SqlCondition.begin() - .and("SALESORDERITEM.OPTIONAL <> 1") - .andPrepare("SALESORDER.SALESORDERDATE", maxYear, "year(#) <= ?", SQLTYPES.INTEGER) - .andPrepare("SALESORDER.SALESORDERDATE", minYear, "year(#) >= ?", SQLTYPES.INTEGER) - .buildSql("select 'Turnover', year(SALESORDERDATE) yearNum, month(SALESORDERDATE) monthNum, SALESORDERITEM.DISCOUNT discount, SALESORDERITEM.VAT vat, SALESORDERITEM.PRICE price, sum(SALESORDERITEM.QUANTITY) quantity, SALESORDERITEM.GROUPCODEID prodGroup, (" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "SALESORDERITEM.GROUPCODEID") + ") prodGroupName \n\ - from SALESORDER \n\ - join SALESORDERITEM on SALESORDERITEM.SALESORDER_ID = SALESORDER.SALESORDERID", "1=2", "group by year(SALESORDERDATE), month(SALESORDERDATE), SALESORDERITEM.GROUPCODEID, SALESORDERITEM.DISCOUNT, SALESORDERITEM.VAT, SALESORDERITEM.PRICE \n\ - order by yearNum, monthNum "))) +var data = TurnoverUtil.getTurnoverAndForecastData(maxYear, yearCountToShow); var columns = { type: 0, @@ -54,9 +40,8 @@ for (let y = minYear; y <= maxYear; y++) { monthDate = new Date(y, m-1); monthDate = datetime.toDate(monthDate.getTime(), "MMM yyyy", "UTC"); - logging.log(monthDate) - _addCount(["Forecast", ""+y, [m, monthDate]], 0.0); - _addCount(["Turnover", ""+y, [m, monthDate]], 0.0); + _addCount([forecastCategory, ""+y, [m, monthDate]], 0.0); + _addCount([turnoverCategory, ""+y, [m, monthDate]], 0.0); } } @@ -67,10 +52,10 @@ data.forEach(function(row) switch(row[columns.type]) { - case "Forecast": + case forecastCategory: _addCount([row[columns.type], row[columns.year], [row[columns.month], monthDate], [row[columns.groupcodeId], row[columns.groupcodeName]]], row[columns.price]); break; - case "Turnover": + case turnoverCategory: _addCount([row[columns.type], row[columns.year], [row[columns.month], monthDate], [row[columns.groupcodeId], row[columns.groupcodeName]]], MoneyUtils.getGross( (row[columns.vat] ? parseFloat(row[columns.vat]) : 0.0), diff --git a/neonContext/TurnoverTree/TurnoverTree.aod b/neonContext/TurnoverTree/TurnoverTree.aod new file mode 100644 index 0000000000000000000000000000000000000000..767e00d8da61a3b203763da6fd71cff72bc26537 --- /dev/null +++ b/neonContext/TurnoverTree/TurnoverTree.aod @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<neonContext 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/neonContext/1.1.0"> + <name>TurnoverTree</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <filterview>TurnoverTree_view</filterview> + <entity>TurnoverTree_entity</entity> + <references> + <neonViewReference> + <name>b8135e50-da8e-424c-9073-e721b4822736</name> + <view>TurnoverTree_view</view> + </neonViewReference> + </references> +</neonContext> diff --git a/neonView/TurnoverChart_view/TurnoverChart_view.aod b/neonView/TurnoverChart_view/TurnoverChart_view.aod index 9cb1a002e4c60759b370934cd77a611e9ab5ce18..5b05bdf764f29741f23e6c8a3f21fce8c55a0082 100644 --- a/neonView/TurnoverChart_view/TurnoverChart_view.aod +++ b/neonView/TurnoverChart_view/TurnoverChart_view.aod @@ -1,77 +1,82 @@ -<?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>TurnoverChart_view</name> - <title></title> - <majorModelMode>DISTRIBUTED</majorModelMode> - <dashletConfigurations> - <neonDashletConfiguration> - <name>TurnoverDashlet</name> - <title>Turnover</title> - <fragment>Turnover/full</fragment> - <singleton v="true" /> - <storeRoles> - <element>INTERNAL_ADMINISTRATOR</element> - <element>INTERNAL_DASHBOARDSTOREADMIN</element> - </storeRoles> - <icon>VAADIN:CHART</icon> - <categories> - <neonDashletCategory> - <name>turnover</name> - <title>Turnover</title> - </neonDashletCategory> - </categories> - </neonDashletConfiguration> - </dashletConfigurations> - <layout> - <groupLayout> - <name>layout</name> - </groupLayout> - </layout> - <children> - <multiDataChartViewTemplate> - <name>ColumnChart</name> - <chartType>COLUMN</chartType> - <xAxis>X</xAxis> - <yAxis>Y</yAxis> - <parentField>PARENT</parentField> - <categoryField>CATEGORY</categoryField> - <entityField>#ENTITY</entityField> - </multiDataChartViewTemplate> - <multiDataChartViewTemplate> - <name>LineChart</name> - <chartType>LINE</chartType> - <xAxis>X</xAxis> - <yAxis>Y</yAxis> - <parentField>PARENT</parentField> - <categoryField>CATEGORY</categoryField> - <entityField>#ENTITY</entityField> - </multiDataChartViewTemplate> - <multiDataChartViewTemplate> - <name>AreaChart</name> - <chartType>AREA</chartType> - <xAxis>X</xAxis> - <yAxis>Y</yAxis> - <parentField>PARENT</parentField> - <categoryField>CATEGORY</categoryField> - <entityField>#ENTITY</entityField> - </multiDataChartViewTemplate> - <multiDataChartViewTemplate> - <name>BarChart</name> - <chartType>BAR</chartType> - <xAxis>X</xAxis> - <yAxis>Y</yAxis> - <parentField>PARENT</parentField> - <categoryField>CATEGORY</categoryField> - <entityField>#ENTITY</entityField> - </multiDataChartViewTemplate> - <multiDataChartViewTemplate> - <name>SplineChart</name> - <chartType>SPLINE</chartType> - <xAxis>X</xAxis> - <yAxis>Y</yAxis> - <parentField>PARENT</parentField> - <categoryField>CATEGORY</categoryField> - <entityField>#ENTITY</entityField> - </multiDataChartViewTemplate> - </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>TurnoverChart_view</name> + <title></title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <dashletConfigurations> + <neonDashletConfiguration> + <name>TurnoverDashlet</name> + <title>Turnover</title> + <fragment>Turnover/full</fragment> + <singleton v="true" /> + <storeRoles> + <element>INTERNAL_ADMINISTRATOR</element> + <element>INTERNAL_DASHBOARDSTOREADMIN</element> + </storeRoles> + <icon>VAADIN:CHART</icon> + <categories> + <neonDashletCategory> + <name>turnover</name> + <title>Turnover</title> + </neonDashletCategory> + </categories> + </neonDashletConfiguration> + </dashletConfigurations> + <layout> + <groupLayout> + <name>layout</name> + </groupLayout> + </layout> + <children> + <multiDataChartViewTemplate> + <name>ColumnChart</name> + <chartType>COLUMN</chartType> + <xAxis>X</xAxis> + <yAxis>Y</yAxis> + <parentField>PARENT</parentField> + <categoryField>CATEGORY</categoryField> + <entityField>#ENTITY</entityField> + </multiDataChartViewTemplate> + <multiDataChartViewTemplate> + <name>LineChart</name> + <chartType>LINE</chartType> + <xAxis>X</xAxis> + <yAxis>Y</yAxis> + <parentField>PARENT</parentField> + <categoryField>CATEGORY</categoryField> + <entityField>#ENTITY</entityField> + </multiDataChartViewTemplate> + <multiDataChartViewTemplate> + <name>AreaChart</name> + <chartType>AREA</chartType> + <xAxis>X</xAxis> + <yAxis>Y</yAxis> + <parentField>PARENT</parentField> + <categoryField>CATEGORY</categoryField> + <entityField>#ENTITY</entityField> + </multiDataChartViewTemplate> + <multiDataChartViewTemplate> + <name>BarChart</name> + <chartType>BAR</chartType> + <xAxis>X</xAxis> + <yAxis>Y</yAxis> + <parentField>PARENT</parentField> + <categoryField>CATEGORY</categoryField> + <entityField>#ENTITY</entityField> + </multiDataChartViewTemplate> + <multiDataChartViewTemplate> + <name>SplineChart</name> + <chartType>SPLINE</chartType> + <xAxis>X</xAxis> + <yAxis>Y</yAxis> + <parentField>PARENT</parentField> + <categoryField>CATEGORY</categoryField> + <entityField>#ENTITY</entityField> + </multiDataChartViewTemplate> + <neonViewReference> + <name>b0a9f719-3768-4ce5-9d32-e0f5fa5bf1eb</name> + <entityField>Turnover_tree</entityField> + <view>TurnoverTree_view</view> + </neonViewReference> + </children> +</neonView> diff --git a/neonView/TurnoverTree_view/TurnoverTree_view.aod b/neonView/TurnoverTree_view/TurnoverTree_view.aod new file mode 100644 index 0000000000000000000000000000000000000000..caa1df078ff99337f41287ff7ba3a67511fade52 --- /dev/null +++ b/neonView/TurnoverTree_view/TurnoverTree_view.aod @@ -0,0 +1,33 @@ +<?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>TurnoverTree_view</name> + <title>Tree</title> + <majorModelMode>DISTRIBUTED</majorModelMode> + <layout> + <boxLayout> + <name>layout</name> + </boxLayout> + </layout> + <children> + <treeTableViewTemplate> + <name>turnover</name> + <parentField>PARENT</parentField> + <entityField>#ENTITY</entityField> + <title>Tree</title> + <columns> + <neonTableColumn> + <name>3925d6aa-6a42-4cdc-84c3-e96ce2eff27b</name> + <entityField>GROUP</entityField> + </neonTableColumn> + <neonTableColumn> + <name>bc75d6a3-b226-4b28-8090-7142a264552a</name> + <entityField>FORECASTPRICE</entityField> + </neonTableColumn> + <neonTableColumn> + <name>d56ec015-556a-4fd6-bf43-c127b10b07bc</name> + <entityField>TURNOVERPRICE</entityField> + </neonTableColumn> + </columns> + </treeTableViewTemplate> + </children> +</neonView> diff --git a/process/Turnover_lib/Turnover_lib.aod b/process/Turnover_lib/Turnover_lib.aod new file mode 100644 index 0000000000000000000000000000000000000000..28bacd7d8eaa8d0f3bd01ed7f72c229487b2372e --- /dev/null +++ b/process/Turnover_lib/Turnover_lib.aod @@ -0,0 +1,9 @@ +<?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>Turnover_lib</name> + <majorModelMode>DISTRIBUTED</majorModelMode> + <process>%aditoprj%/process/Turnover_lib/process.js</process> + <variants> + <element>LIBRARY</element> + </variants> +</process> diff --git a/process/Turnover_lib/process.js b/process/Turnover_lib/process.js index d2128cd195542977845b87086fe6bc0da1f74520..0a3a6fa24c6d861ce90733c86d86ab15615b5338 100644 --- a/process/Turnover_lib/process.js +++ b/process/Turnover_lib/process.js @@ -1,62 +1,78 @@ +import("system.translate"); +import("KeywordRegistry_basic"); +import("Keyword_lib"); +import("system.SQLTYPES"); import("system.db"); import("system.neon"); import("Context_lib"); /** - * Methods used for time tracking. + * Methods used for turnover data. * Do not create an instance of this! * * @class */ -function Timetracking() {} +function TurnoverUtil() {} /** - * calculates the total time of all time trackings of the object + * get all turnover data. * - * @param {String} pRowId the rowId + * @param {Number} pMaxYear the maximum year + * @param {Number} pYearCount count of years to select * - * @return {Number} total time in minutes + * @return {String[][]} */ -Timetracking.getTotalTrackingTime = function (pRowId) +TurnoverUtil.getTurnoverData = function (pMaxYear, pYearCount) { - var objectId = ContextUtils.getCurrentContextId(); - var totalMinutes = db.cell(SqlCondition.begin() - .andPrepare("TIMETRACKING.OBJECT_ID", objectId) - .andPrepare("TIMETRACKING.ROW_ID", pRowId) - .buildSql("select sum(MINUTES) from TIMETRACKING", "1=0")); + var turnoverCategory = translate.text('Turnover'); + + var minYear = pMaxYear - pYearCount + 1; + + // load data + var data = db.table(SqlCondition.begin() + .and("SALESORDERITEM.OPTIONAL <> 1") + .andPrepare("SALESORDER.SALESORDERDATE", pMaxYear, "year(#) <= ?", SQLTYPES.INTEGER) + .andPrepare("SALESORDER.SALESORDERDATE", minYear, "year(#) >= ?", SQLTYPES.INTEGER) + .buildSql("select '" + turnoverCategory + "', year(SALESORDERDATE) yearNum, month(SALESORDERDATE) monthNum, SALESORDERITEM.DISCOUNT discount, SALESORDERITEM.VAT vat, SALESORDERITEM.PRICE price, sum(SALESORDERITEM.QUANTITY) quantity, SALESORDERITEM.GROUPCODEID prodGroup, (" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "SALESORDERITEM.GROUPCODEID") + ") prodGroupName \n\ + from SALESORDER \n\ + join SALESORDERITEM on SALESORDERITEM.SALESORDER_ID = SALESORDER.SALESORDERID", "1=2", "group by year(SALESORDERDATE), month(SALESORDERDATE), SALESORDERITEM.GROUPCODEID, SALESORDERITEM.DISCOUNT, SALESORDERITEM.VAT, SALESORDERITEM.PRICE \n\ + order by yearNum, monthNum ")); - return Number(totalMinutes); + return data; } /** - * Create a new time tracking + * get forecast data * - * @param {String} pRowId the rowId + * @param {Number} pMaxYear the maximum year + * @param {Number} pYearCount count of years to select * - * @return {Number} total time in minutes + * @return {String[][]} */ -Timetracking.createNewTimeTracking = function (pRowId) +TurnoverUtil.getForecastData = function (pMaxYear, pYearCount) { - var objectId = ContextUtils.getCurrentContextId(); - var params = { - "ObjectId_param" : objectId, - "RowId_param" : pRowId - }; + var forecastCategory = translate.text('Forecast'); + + var minYear = pMaxYear - pYearCount + 1; + + // load data + var data = db.table(SqlCondition.begin() + .andPrepare("SALESPROJECT_FORECAST.DATE_START", pMaxYear, "year(#) <= ?", SQLTYPES.INTEGER) + .andPrepare("SALESPROJECT_FORECAST.DATE_START", minYear, "year(#) >= ?", SQLTYPES.INTEGER) + .buildSql("select '" + forecastCategory + "', year(DATE_START) yearNum, month(DATE_START) monthNum, 0 discount, 0 vat, sum(VOLUME * 1000) price, 1 quantity, GROUPCODE prodGroup, (" + KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.productGroupcode(), "GROUPCODE") + ") prodGroupName from SALESPROJECT_FORECAST", "1=2", " group by year(DATE_START), month(DATE_START), GROUPCODE order by yearNum, monthNum")) - neon.openContext("Timetracking", null, null, neon.OPERATINGSTATE_NEW, params); + return data; } -/* - * converts minutes tho hours and minuets. e.g. 105 to 1:45 +/** + * get turnover data * - * @param {integer} pMinutes req + * @param {Number} pMaxYear the maximum year + * @param {Number} pYearCount count of years to select * - * @return {String} Hours:Minutes + * @return {String[][]} */ -Timetracking.minutesToReadableHour = function(pMinutes) -{ - var timeHour = parseInt(pMinutes / 60); - var minutes = parseInt(pMinutes % 60); - - return "" + timeHour + ":" + ((minutes <= 9) ? "0" + minutes : minutes); +TurnoverUtil.getTurnoverAndForecastData = function (pMaxYear, pYearCount) +{ + return TurnoverUtil.getTurnoverData(pMaxYear, pYearCount).concat(TurnoverUtil.getForecastData(pMaxYear, pYearCount)); } \ No newline at end of file diff --git a/process/Util_lib/process.js b/process/Util_lib/process.js index a09c5ac5bb0049ca0f665e12fa6f9cce0c82bb87..ddbb258a847462214bdf71f3c3870b3974d65e65 100644 --- a/process/Util_lib/process.js +++ b/process/Util_lib/process.js @@ -547,7 +547,10 @@ NumberSequencingUtils.getMaxUniqueNumber = function(pColumn, pTable, pCondition) function TreeUtils () {} /** - * sorts an array in a way that a tree(-table) can be built + * sorts an array in a way that a tree(-table) can be built (parents are added before children) + * This function does not garantee that the order of the children stays the same. If you need this, use TreeUtils.treeOrderBy + * + * consider the use of TreeUtils.treeOrderBy as it may be more performant, but it needs the layernumber of each row. * * @param {Array} pArray two-dimensional array to sort * @param {Number} pUidIndex the index of the uid in a row @@ -583,4 +586,32 @@ TreeUtils.sortArrayForTree = function (pArray, pUidIndex, pParentIdIndex) for (let i in rows) sortedArray[rows[i].index] = rows[i].data; return sortedArray; +} + +/** + * like TreeUtils.sortArrayForTree, this function garantees that parents are added before children + * But it works in a different way based on the layer number. + * + * It can also sort all children based on the given orderBys. For this you can Probvide an array of Indexes and direction (pOrderByIndexes) + * + * @param {Array} pData two-dimensional array to sort + * @param {Number} pLayerIndex The index of the layernumber-Field + * @param {Array[][]} pOrderByIndexes Array containing arrays of [field-index, direction]. The direction can be true (desc) or false (asc). + * + * @return {Array} the sorted array + */ +TreeUtils.treeOrderBy = function(pData, pLayerIndex, pOrderByIndexes) +{ + pOrderByIndexes = [[pLayerIndex, false]].concat(pOrderByIndexes) + + return pData.sort(function(pRow1, pRow2) + { + for (let i = 0; i < pOrderByIndexes.length; i++) { + var orderBy = pOrderByIndexes[i]; + if (pRow1[orderBy[0]] > pRow2[orderBy[0]]) return (orderBy[1] ? -1 : 1); + if (pRow1[orderBy[0]] < pRow2[orderBy[0]]) return (orderBy[1] ? 1 : -1); + } + + return 0; + }) } \ No newline at end of file