Skip to content
Snippets Groups Projects
Commit a07b8fd0 authored by Benjamin Ulrich's avatar Benjamin Ulrich :speech_balloon:
Browse files

Merge branch 'sales_pn_1040659_products_prod2prod' into '2021.0'

[Projekt: xRM-Sales][TicketNr.: 1040659][Produkt - Stückliste: Einträge sollen...

See merge request xrm/basic!877
parents d4393321 668cdd64
No related branches found
No related tags found
No related merge requests found
Showing with 91 additions and 246 deletions
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<majorModelMode>DISTRIBUTED</majorModelMode> <majorModelMode>DISTRIBUTED</majorModelMode>
<documentation>%aditoprj%/entity/Prod2prod_entity/documentation.adoc</documentation> <documentation>%aditoprj%/entity/Prod2prod_entity/documentation.adoc</documentation>
<titlePlural>Parts list</titlePlural> <titlePlural>Parts list</titlePlural>
<recordContainer>jdito</recordContainer> <recordContainer>jDito</recordContainer>
<entityFields> <entityFields>
<entityProvider> <entityProvider>
<name>#PROVIDER</name> <name>#PROVIDER</name>
...@@ -23,10 +23,6 @@ ...@@ -23,10 +23,6 @@
<valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/optional/valueProcess.js</valueProcess> <valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/optional/valueProcess.js</valueProcess>
<onValueChange>%aditoprj%/entity/Prod2prod_entity/entityfields/optional/onValueChange.js</onValueChange> <onValueChange>%aditoprj%/entity/Prod2prod_entity/entityfields/optional/onValueChange.js</onValueChange>
</entityField> </entityField>
<entityField>
<name>UID</name>
<valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/uid/valueProcess.js</valueProcess>
</entityField>
<entityField> <entityField>
<name>QUANTITY</name> <name>QUANTITY</name>
<title>Quantity</title> <title>Quantity</title>
...@@ -42,7 +38,6 @@ ...@@ -42,7 +38,6 @@
<title>Product</title> <title>Product</title>
<consumer>Products</consumer> <consumer>Products</consumer>
<mandatory v="true" /> <mandatory v="true" />
<valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/source_id/valueProcess.js</valueProcess>
<onValueChange>%aditoprj%/entity/Prod2prod_entity/entityfields/source_id/onValueChange.js</onValueChange> <onValueChange>%aditoprj%/entity/Prod2prod_entity/entityfields/source_id/onValueChange.js</onValueChange>
</entityField> </entityField>
<entityField> <entityField>
...@@ -60,7 +55,6 @@ ...@@ -60,7 +55,6 @@
</entityParameter> </entityParameter>
<entityField> <entityField>
<name>PROD2PRODID</name> <name>PROD2PRODID</name>
<valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/prod2prodid/valueProcess.js</valueProcess>
</entityField> </entityField>
<entityProvider> <entityProvider>
<name>ProductLinks</name> <name>ProductLinks</name>
...@@ -138,9 +132,6 @@ ...@@ -138,9 +132,6 @@
<title>Unit</title> <title>Unit</title>
<state>READONLY</state> <state>READONLY</state>
</entityField> </entityField>
<entityField>
<name>vat</name>
</entityField>
<entityField> <entityField>
<name>currentPurchasePrice</name> <name>currentPurchasePrice</name>
<title>Curr. purchase price</title> <title>Curr. purchase price</title>
...@@ -151,13 +142,17 @@ ...@@ -151,13 +142,17 @@
<title>Curr. sales price</title> <title>Curr. sales price</title>
<state>READONLY</state> <state>READONLY</state>
</entityField> </entityField>
<entityField>
<name>PARENT_ID</name>
</entityField>
<entityField>
<name>UID</name>
</entityField>
</entityFields> </entityFields>
<recordContainers> <recordContainers>
<jDitoRecordContainer> <jDitoRecordContainer>
<name>jdito</name> <name>jDito</name>
<jDitoRecordAlias>Data_alias</jDitoRecordAlias> <jDitoRecordAlias>Data_alias</jDitoRecordAlias>
<isRequireContainerFiltering v="true" />
<isSortable v="true" />
<contentProcess>%aditoprj%/entity/Prod2prod_entity/recordcontainers/jdito/contentProcess.js</contentProcess> <contentProcess>%aditoprj%/entity/Prod2prod_entity/recordcontainers/jdito/contentProcess.js</contentProcess>
<hasDependentRecords v="true" /> <hasDependentRecords v="true" />
<onInsert>%aditoprj%/entity/Prod2prod_entity/recordcontainers/jdito/onInsert.js</onInsert> <onInsert>%aditoprj%/entity/Prod2prod_entity/recordcontainers/jdito/onInsert.js</onInsert>
...@@ -168,22 +163,22 @@ ...@@ -168,22 +163,22 @@
<name>UID.value</name> <name>UID.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>SOURCE_ID.value</name> <name>PROD2PRODID.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>DEST_ID.value</name> <name>PARENT_ID.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>QUANTITY.value</name> <name>SOURCE_ID.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>PRODUCTCODE.value</name> <name>SOURCE_ID.displayValue</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>PRODUCTID.value</name> <name>DEST_ID.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>PROD2PRODID.value</name> <name>QUANTITY.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>OPTIONAL.value</name> <name>OPTIONAL.value</name>
...@@ -192,11 +187,17 @@ ...@@ -192,11 +187,17 @@
<name>TAKEPRICE.value</name> <name>TAKEPRICE.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>SOURCE_ID.displayValue</name> <name>PRODUCTID.value</name>
</jDitoRecordFieldMapping>
<jDitoRecordFieldMapping>
<name>PRODUCTCODE.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>unit.value</name> <name>unit.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
<jDitoRecordFieldMapping>
<name>unit.displayValue</name>
</jDitoRecordFieldMapping>
<jDitoRecordFieldMapping> <jDitoRecordFieldMapping>
<name>currentPurchasePrice.value</name> <name>currentPurchasePrice.value</name>
</jDitoRecordFieldMapping> </jDitoRecordFieldMapping>
......
import("system.util");
import("system.vars");
import("system.result");
import("system.neon");
if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
result.string(util.getNewUUID());
\ No newline at end of file
import("system.util");
import("system.vars");
import("system.result");
import("system.neon");
if(vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
result.object([util.getNewUUID(), vars.get("$field.PROD2PRODID")]); // 1. is some random uid for uniqueness 2. is the prod2ProdID
\ No newline at end of file
import("Product_lib");
import("system.text"); import("system.text");
import("KeywordRegistry_basic");
import("Keyword_lib");
import("Sql_lib");
import("system.neon"); import("system.neon");
import("system.result");
import("system.vars"); import("system.vars");
import("system.db"); import("system.result");
import("system.util"); import("Sql_lib");
import("Product_lib"); import("Keyword_lib");
import("KeywordRegistry_basic");
/**
* Calculate the root elements for this tree.
*
* @param productRootID string
* @param rows TreeData[]
* @return string[]
*/
function calculateRootElements (productRootID, rows) {
return rows.filter(function (row) {
// Filter predicate if the DIST_ID matches.
return row[2] === productRootID;
}).map(function (row) {
// Map to PROD2PROD_ID.
return row[0];
});
}
/**
* Calculates a mapping object which has the PROD2PROD_ID as
* key and the full TreeData array as value.
*
* @param rows TreeData[]
* @return {[key: TreeData]}
*/
function buildProd2ProdIDMapping (rows) {
var mapping = {}
rows.forEach(function(row) {
// Create new property which PROD2PROD_ID as key and data
// as value.
mapping[row[0]] = row;
});
return mapping;
}
/**
* Calcualtes the children mapping structure which has the DIST_ID
* as key and an array of PROD2PROD_IDs as value.
*
* @param rows TreeData[]
* @return {[key: string[]]}
*/
function buildChildrenMapping(rows) {
var parrentMapping = {}
rows.forEach(function (row) {
// Create empty array if not created previously.
if (parrentMapping[row[2]] === undefined)
parrentMapping[row[2]] = []
// Push with DIST_ID as key and PROD2PROD_ID as value.
parrentMapping[row[2]].push(row[0]);
})
return parrentMapping
}
/**
* Calculates the graph starting from the given elementID.
*/
function buildGraph (elementID, parentElementID, mappingStructure, prod2prodIdMapping) {
var elements = []
// Get the PROD2PROD data array and copy it.
// Copying is requried due to mutability of arrays.
var elementData = prod2prodIdMapping[elementID].slice(0);
// Just as an error prevention.
if (elementData === undefined)
return elements;
// Generate new PROD2PROD_ID to create a uniqueness between the PROD2PROD objects.
var virtualProd2ProdId = util.getNewUUID();
// Override actual PROD2PROD_ID with new ID.
elementData[0] = JSON.stringify([virtualProd2ProdId, elementData[0]]);
// Override parent id to match overriden prod2prodId of parent
if (parentElementID === null || parentElementID === undefined)
// Describes an root element
elementData[2] = null;
else
elementData[2] = parentElementID;
// Push element data to elements array of this graph.
elements.push(elementData);
// Search for children
var childrens = mappingStructure[elementData[1]];
if (childrens !== undefined && childrens.length > 0) { var query = newSelect([
// Build graph for each children "PROD2PROD.PROD2PRODID", // UID.value
"PROD2PROD.PROD2PRODID", // PROD2PRODID.value
"''", // PARENT_ID.value
"PROD2PROD.SOURCE_ID", // SOURCE_ID.value
"PRODUCT.PRODUCTNAME", // SOURCE_ID.displaValue
"PROD2PROD.DEST_ID", // DEST_ID.value
"PROD2PROD.QUANTITY", // QUANTITY.value
"PROD2PROD.OPTIONAL", // OPTIONAL.value
"PROD2PROD.TAKEPRICE", // TAKEPRICE.value
"PRODUCT.PRODUCTID", // PRODUCT.value
"PRODUCT.PRODUCTCODE", // PRODUCTCODE.value
"PRODUCT.UNIT", // unit.value
KeywordUtils.getResolvedTitleSqlPart( // unit.displaValue
$KeywordRegistry.quantityUnit(),
"PRODUCT.UNIT"
)
]).from("PROD2PROD")
.join("PRODUCT", "PRODUCT.PRODUCTID = PROD2PROD.SOURCE_ID");
childrens.forEach(function(children) { function _returnData(data) {
// Recursive function call (!) for(let i = 0; i < data.length; i++)
{
var graphResult = buildGraph(children, elementData[0], mappingStructure, prod2prodIdMapping); var productId = data[3];
graphResult.forEach(function(res) {elements.push(res)}) // currentPurchasePrice.value
}); var purchasePrice = ProductUtils.getCurrentProductPrice(productId, "PP", true);
data[i].push(
purchasePrice.length == 0 ? "" :
text.formatDouble(purchasePrice[0], "#,##0.00", true) + " " + purchasePrice[1]
);
// currentSalesPrice.value
var salesPrice = ProductUtils.getCurrentProductPrice(productId, "SP", true);
data[i].push(
salesPrice.length == 0 ? "" :
text.formatDouble(salesPrice[0], "#,##0.00", true) + " " + salesPrice[1]
);
} }
result.object(data);
return elements;
} }
/* if(vars.exists("$local.idvalues") && vars.get("$local.idvalues"))
* in the past at this point a check for the "recordstate" was done
* this should not be necessery and in fact causes a problem:
* When adding a new prod2prod entry and performing a cancel an error is raised that the variable does not exist.
*
* So *IF* you need that check for the state, you should check if this error is thrown
* + add a comment why the check is needed here instead of this current comment
*/
if (vars.get("$local.idvalues") && vars.get("$local.idvalues").length > 0)
{ {
var prod2prodId = JSON.parse(vars.get("$local.idvalues")[0])[1]; _returnData(query.where("PROD2PROD.PROD2PRODID", vars.get("$local.idvalues"), SqlBuilder.IN()).table());
if (prod2prodId)
{
var prodData = newSelect(["PROD2PROD.PROD2PRODID",
"PROD2PROD.SOURCE_ID",
"PROD2PROD.DEST_ID",
"PROD2PROD.QUANTITY",
"PRODUCT.PRODUCTCODE",
"PRODUCT.PRODUCTID",
"PROD2PROD.PROD2PRODID",
"PROD2PROD.OPTIONAL",
"PROD2PROD.TAKEPRICE",
"PRODUCT.PRODUCTNAME",
KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.quantityUnit(), "PRODUCT.UNIT")])
.from("PROD2PROD")
.join("PRODUCT", "PROD2PROD.SOURCE_ID = PRODUCTID")
.where("PROD2PROD.PROD2PRODID", prod2prodId)
.arrayRow();
prodData[0] = vars.get("$local.idvalues")[0]; //only first one since whe have single selection as the selection mode
prodData[11] = "";
prodData[12] = "";
let purchasePrice = ProductUtils.getCurrentProductPrice(prodData[5], "PP", true);
if (purchasePrice.length > 0)
{
prodData[11] = text.formatDouble(purchasePrice[0], "#,##0.00", true) + " " + purchasePrice[1];
}
let salesPrice = ProductUtils.getCurrentProductPrice(prodData[5], "SP", true);
if (salesPrice.length > 0)
{
prodData[12] = text.formatDouble(salesPrice[0], "#,##0.00", true) + " " + salesPrice[1];
}
result.object([prodData]);
}
} }
else else
{ {
var prodid = vars.exists("$param.ProductId_param") var prod2prod = query.table();
&& vars.get("$param.ProductId_param") != null ? vars.get("$param.ProductId_param") : ""; function _getChilds(pId, pProductId, pMaxRecursion)
if(prodid != "")
{ {
// First 3 columns are crucial, the rest is optional. if(pMaxRecursion == 0)
var data = newSelect(["PROD2PROD.PROD2PRODID", {
"PROD2PROD.SOURCE_ID", return [];
"PROD2PROD.DEST_ID",
"PROD2PROD.QUANTITY",
"PRODUCT.PRODUCTCODE",
"PRODUCT.PRODUCTID",
"PROD2PROD.PROD2PRODID",
"PROD2PROD.OPTIONAL",
"PROD2PROD.TAKEPRICE",
"PRODUCT.PRODUCTNAME",
KeywordUtils.getResolvedTitleSqlPart($KeywordRegistry.quantityUnit(), "PRODUCT.UNIT")])
.from("PROD2PROD")
.join("PRODUCT", "PROD2PROD.SOURCE_ID = PRODUCTID")
.orderBy("PRODUCTCODE")
.table();
var prod2prodIdMapping = buildProd2ProdIDMapping(data);
var childrenMapping = buildChildrenMapping(data);
var rootElements = calculateRootElements(prodid, data);
var allData = [];
rootElements.forEach(function(rg) {
var graphData = buildGraph(rg, null, childrenMapping, prod2prodIdMapping)
graphData.forEach(function (gd) { allData.push(gd); })
})
for (let i = 0; i < allData.length; i++) {
allData[i][11] = "";
allData[i][12] = "";
let purchasePrice = ProductUtils.getCurrentProductPrice(allData[i][5], "PP", true);
if (purchasePrice.length > 0)
{
allData[i][11] = text.formatDouble(purchasePrice[0], "#,##0.00", true) + " " + purchasePrice[1];
}
let salesPrice = ProductUtils.getCurrentProductPrice(allData[i][5], "SP", true);
if (salesPrice.length > 0)
{
allData[i][12] = text.formatDouble(salesPrice[0], "#,##0.00", true) + " " + salesPrice[1];
}
} }
result.object(allData); var items = prod2prod.filter(function(p2p) {
return p2p[5] == pProductId;
});
var itemChilds = [];
items.forEach(function(p2p) {
p2p[2] = pId;
itemChilds.push(_getChilds(p2p[0], p2p[3], pMaxRecursion - 1));
});
return Array.prototype.concat.apply(items, itemChilds);
} }
} _returnData(_getChilds(null, vars.get("$param.ProductId_param"), 20));
\ No newline at end of file }
import("Sql_lib"); import("Sql_lib");
import("system.vars");
newWhereIfSet("PROD2PROD.PROD2PRODID", "$field.PROD2PRODID").deleteData(); newWhereIfSet("PROD2PROD.PROD2PRODID", vars.get("$local.uid")).deleteData();
\ No newline at end of file
...@@ -10,11 +10,11 @@ var cols = [ "PROD2PRODID" ...@@ -10,11 +10,11 @@ var cols = [ "PROD2PRODID"
, "OPTIONAL" , "OPTIONAL"
, "TAKEPRICE" ]; , "TAKEPRICE" ];
var vals = [ vars.get("$field.PROD2PRODID") var vals = [ vars.get("$local.uid")
, vars.get("$field.DEST_ID") , vars.get("$field.DEST_ID")
, vars.get("$field.SOURCE_ID") , vars.get("$field.SOURCE_ID")
, vars.get("$field.QUANTITY") , vars.get("$field.QUANTITY")
, vars.get("$field.OPTIONAL") , vars.get("$field.OPTIONAL")
, vars.get("$field.TAKEPRICE") ]; , vars.get("$field.TAKEPRICE") ];
db.insertData("PROD2PROD", cols, null, vals); db.insertData("PROD2PROD", cols, null, vals);
\ No newline at end of file
import("Sql_lib");
import("system.datetime");
import("system.vars"); import("system.vars");
import("Sql_lib");
var cols = [ "SOURCE_ID" var cols = [ "SOURCE_ID"
, "QUANTITY" , "QUANTITY"
...@@ -12,5 +11,5 @@ var vals = [ vars.get("$field.SOURCE_ID") ...@@ -12,5 +11,5 @@ var vals = [ vars.get("$field.SOURCE_ID")
, vars.get("$field.OPTIONAL") , vars.get("$field.OPTIONAL")
, vars.get("$field.TAKEPRICE") ]; , vars.get("$field.TAKEPRICE") ];
newWhere("PROD2PROD.PROD2PRODID", "$field.PROD2PRODID") newWhere("PROD2PROD.PROD2PRODID", vars.get("$local.uid"))
.updateData(true, "PROD2PROD", cols, null, vals); .updateData(true, "PROD2PROD", cols, null, vals);
\ No newline at end of file
...@@ -201,6 +201,7 @@ ...@@ -201,6 +201,7 @@
</entityProvider> </entityProvider>
<entityConsumer> <entityConsumer>
<name>ProductLinks</name> <name>ProductLinks</name>
<selectionMode>MULTI</selectionMode>
<dependency> <dependency>
<name>dependency</name> <name>dependency</name>
<entityName>Prod2prod_entity</entityName> <entityName>Prod2prod_entity</entityName>
......
...@@ -11,8 +11,7 @@ ...@@ -11,8 +11,7 @@
<children> <children>
<treeTableViewTemplate> <treeTableViewTemplate>
<name>PartlistTree</name> <name>PartlistTree</name>
<parentField>DEST_ID</parentField> <parentField>PARENT_ID</parentField>
<entityField>#ENTITY</entityField>
<favoriteActionGroup1>alter</favoriteActionGroup1> <favoriteActionGroup1>alter</favoriteActionGroup1>
<devices> <devices>
<element>MOBILE</element> <element>MOBILE</element>
......
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