diff --git a/entity/Offer_entity/entityfields/offercode/onValidation.js b/entity/Offer_entity/entityfields/offercode/onValidation.js index d74d0c362ec05c34da6d48e6ce3b2d3eb1e408d7..bd2b194002b0d21613c000b876f6038fd5eb53ae 100644 --- a/entity/Offer_entity/entityfields/offercode/onValidation.js +++ b/entity/Offer_entity/entityfields/offercode/onValidation.js @@ -1,7 +1,7 @@ import("system.vars"); import("system.result"); import("system.neon"); -import("Offer_lib"); +import("OfferOrder_lib"); import("Util_lib"); var OfferUtils = new OfferUtils(); diff --git a/entity/Offer_entity/entityfields/offercode/valueProcess.js b/entity/Offer_entity/entityfields/offercode/valueProcess.js index 05581ec804c4ae88d831274152f6242f692357e3..a962e8d4fb7c605ff2ebd4e2b9aecac6020413fd 100644 --- a/entity/Offer_entity/entityfields/offercode/valueProcess.js +++ b/entity/Offer_entity/entityfields/offercode/valueProcess.js @@ -1,7 +1,7 @@ import("system.vars"); import("system.result"); import("system.neon"); -import("Offer_lib"); +import("OfferOrder_lib"); if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) { diff --git a/entity/Offer_entity/grantDeleteProcess.js b/entity/Offer_entity/grantDeleteProcess.js index 1d03536547d440e7d624bcfe337c802c4cfacd5e..302a4d7ba366d82b054bb83ca678e2c89d48988f 100644 --- a/entity/Offer_entity/grantDeleteProcess.js +++ b/entity/Offer_entity/grantDeleteProcess.js @@ -1,6 +1,6 @@ import("system.vars"); import("system.result"); -import("Offer_lib"); +import("OfferOrder_lib"); var oUtils = new OfferUtils(); result.string(oUtils.isEditable(vars.get("$field.STATUS"))); \ No newline at end of file diff --git a/entity/Offer_entity/grantUpdateProcess.js b/entity/Offer_entity/grantUpdateProcess.js index 1d03536547d440e7d624bcfe337c802c4cfacd5e..302a4d7ba366d82b054bb83ca678e2c89d48988f 100644 --- a/entity/Offer_entity/grantUpdateProcess.js +++ b/entity/Offer_entity/grantUpdateProcess.js @@ -1,6 +1,6 @@ import("system.vars"); import("system.result"); -import("Offer_lib"); +import("OfferOrder_lib"); var oUtils = new OfferUtils(); result.string(oUtils.isEditable(vars.get("$field.STATUS"))); \ No newline at end of file diff --git a/entity/Offeritem_entity/Offeritem_entity.aod b/entity/Offeritem_entity/Offeritem_entity.aod index c28e322e3bdf2c00d7a2fe7f240b4bb7129a8ee0..3adf52ce78a9faa5a7586f2b64624e7ab98ce9ae 100644 --- a/entity/Offeritem_entity/Offeritem_entity.aod +++ b/entity/Offeritem_entity/Offeritem_entity.aod @@ -3,16 +3,18 @@ <name>Offeritem_entity</name> <title>Offeritem</title> <majorModelMode>DISTRIBUTED</majorModelMode> - <alias>Data_alias</alias> - <conditionProcess>%aditoprj%/entity/Offeritem_entity/conditionProcess.js</conditionProcess> - <onDBInsert>%aditoprj%/entity/Offeritem_entity/onDBInsert.js</onDBInsert> - <onDBUpdate>%aditoprj%/entity/Offeritem_entity/onDBUpdate.js</onDBUpdate> - <onDBDelete>%aditoprj%/entity/Offeritem_entity/onDBDelete.js</onDBDelete> <grantCreateProcess>%aditoprj%/entity/Offeritem_entity/grantCreateProcess.js</grantCreateProcess> <grantUpdateProcess>%aditoprj%/entity/Offeritem_entity/grantUpdateProcess.js</grantUpdateProcess> <grantDeleteProcess>%aditoprj%/entity/Offeritem_entity/grantDeleteProcess.js</grantDeleteProcess> <recordContainerType>DB</recordContainerType> <caption>Offeritem</caption> + <afterOperatingState>%aditoprj%/entity/Offeritem_entity/afterOperatingState.js</afterOperatingState> + <alias>Data_alias</alias> + <conditionProcess>%aditoprj%/entity/Offeritem_entity/conditionProcess.js</conditionProcess> + <orderClauseProcess>%aditoprj%/entity/Offeritem_entity/orderClauseProcess.js</orderClauseProcess> + <onDBInsert>%aditoprj%/entity/Offeritem_entity/onDBInsert.js</onDBInsert> + <onDBUpdate>%aditoprj%/entity/Offeritem_entity/onDBUpdate.js</onDBUpdate> + <onDBDelete>%aditoprj%/entity/Offeritem_entity/onDBDelete.js</onDBDelete> <entityFields> <entityIncomingField> <name>#INCOMING</name> @@ -29,6 +31,7 @@ <name>ASSIGNEDTO</name> <tableName>OFFERITEM</tableName> <columnName>ASSIGNEDTO</columnName> + <valueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/assignedto/valueProcess.js</valueProcess> </entityField> <entityField> <name>DATE_EDIT</name> @@ -78,6 +81,8 @@ <columnName>ITEMPOSITION</columnName> <caption>Position</caption> <state>READONLY</state> + <valueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/itemposition/valueProcess.js</valueProcess> + <onValidation>%aditoprj%/entity/Offeritem_entity/entityfields/itemposition/onValidation.js</onValidation> </entityField> <entityField> <name>ITEMSORT</name> @@ -153,7 +158,7 @@ <tableName>OFFERITEM</tableName> <columnName>VAT</columnName> <caption>VAT</caption> - <state>READONLY</state> + <state>AUTO</state> </entityField> <entityParameter> <name>OfferId_param</name> @@ -181,6 +186,7 @@ <outputFormat>#,##0.00</outputFormat> <state>READONLY</state> <valueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js</valueProcess> + <onValidation>%aditoprj%/entity/Offeritem_entity/entityfields/totalprice/onValidation.js</onValidation> </entityField> <entityField> <name>IMAGE</name> diff --git a/entity/Offeritem_entity/afterOperatingState.js b/entity/Offeritem_entity/afterOperatingState.js new file mode 100644 index 0000000000000000000000000000000000000000..bd495944d606c9ad734c9fbbccba84b962c2a94d --- /dev/null +++ b/entity/Offeritem_entity/afterOperatingState.js @@ -0,0 +1,14 @@ +import("system.neon"); +import("system.vars"); +import("OfferOrder_lib"); + +var opState = vars.get("$sys.operatingstate"); + +if(opState == neon.OPERATINGSTATE_NEW) +{ + var offerId = vars.get("$field.OFFER_ID"); + var oiUtils = new OfferItemUtils(offerId); + + vars.set("$field.ITEMSORT", oiUtils.getNextItemSort()); + vars.set("$field.ITEMPOSITION", oiUtils.getNextItemPosition(vars.get("$field.ASSIGNEDTO"))); +} \ No newline at end of file diff --git a/entity/Offeritem_entity/entityfields/assignedto/valueProcess.js b/entity/Offeritem_entity/entityfields/assignedto/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/entity/Offeritem_entity/entityfields/itemposition/onValidation.js b/entity/Offeritem_entity/entityfields/itemposition/onValidation.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/entity/Offeritem_entity/entityfields/itemposition/valueProcess.js b/entity/Offeritem_entity/entityfields/itemposition/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/entity/Offeritem_entity/entityfields/product_id/onValidation.js b/entity/Offeritem_entity/entityfields/product_id/onValidation.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/entity/Offeritem_entity/entityfields/product_id/onValueChange.js b/entity/Offeritem_entity/entityfields/product_id/onValueChange.js index 0c8a79b2abb8d956b67f815a638f02ba7fbd9afa..196b4ab169ea3cbfdb3f6e1feb6d341ce6a008ae 100644 --- a/entity/Offeritem_entity/entityfields/product_id/onValueChange.js +++ b/entity/Offeritem_entity/entityfields/product_id/onValueChange.js @@ -14,16 +14,17 @@ if(pid != "") var PriceListFilter = { currency: curr, quantity: vars.get("$field.QUANTITY"), relationId: relid }; var ProductDetails = pUtils.getProductDetails(pid, PriceListFilter); - if(ProductDetails[pid] != undefined) + + if(ProductDetails.productId != undefined) { - vars.set("$field.GROUPCODEID", ProductDetails[pid].groupCode); - vars.set("$field.UNIT", ProductDetails[pid].unit); - vars.set("$field.ITEMNAME", ProductDetails[pid].productName); + vars.set("$field.GROUPCODEID", ProductDetails.groupCode); + vars.set("$field.UNIT", ProductDetails.unit); + vars.set("$field.ITEMNAME", ProductDetails.productName); - if(ProductDetails[pid].PriceListToUse != null) + if(ProductDetails.PriceListToUse != null) { - vars.set("$field.PRICE", ProductDetails[pid].PriceListToUse.price); - vars.set("$field.VAT", ProductDetails[pid].PriceListToUse.vat); + vars.set("$field.PRICE", ProductDetails.PriceListToUse.price); + vars.set("$field.VAT", ProductDetails.PriceListToUse.vat); } } } \ No newline at end of file diff --git a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js index ac528c67dd26229929cab15ec0a41face28ff66f..d605b64c6f8ad78ba76189a0333d426011f7e337 100644 --- a/entity/Offeritem_entity/entityfields/quantity/onValueChange.js +++ b/entity/Offeritem_entity/entityfields/quantity/onValueChange.js @@ -16,9 +16,9 @@ if(pid != "" && newQuantity != "") var ProductDetails = pUtils.getProductDetails(pid, PriceListFilter); - if(ProductDetails[pid] != undefined && ProductDetails[pid].PriceListToUse != null) + if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null) { - vars.set("$field.PRICE", ProductDetails[pid].PriceListToUse.price); - vars.set("$field.VAT", ProductDetails[pid].PriceListToUse.vat); + vars.set("$field.PRICE", ProductDetails.PriceListToUse.price); + vars.set("$field.VAT", ProductDetails.PriceListToUse.vat); } } \ No newline at end of file diff --git a/entity/Offeritem_entity/entityfields/totalprice/onValidation.js b/entity/Offeritem_entity/entityfields/totalprice/onValidation.js new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js b/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js index 7fff82a426deedb7c0729b258be6c55dda0b19f7..cbd08ae1d7bed2b4a02d9263d77242a424f047ec 100644 --- a/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js +++ b/entity/Offeritem_entity/entityfields/totalprice/valueProcess.js @@ -1,8 +1,8 @@ import("system.result"); import("system.vars"); -import("Offer_lib"); +import("OfferOrder_lib"); -var oiUtils = new OfferItemUtils(); +var oiUtils = new OfferItemUtils(vars.get("$field.OFFER_ID")); result.string(oiUtils.roundPrice(oiUtils.getItemSum(vars.get("$field.QUANTITY"), vars.get("$field.PRICE") , vars.get("$field.DISCOUNT"), vars.get("$field.OPTIONAL")))); \ No newline at end of file diff --git a/entity/Offeritem_entity/grantCreateProcess.js b/entity/Offeritem_entity/grantCreateProcess.js index 5d45e991a5d09799e02589b926edf9236cabfc9c..6651ef933bfc198121e93bd5f48dcaec406c812b 100644 --- a/entity/Offeritem_entity/grantCreateProcess.js +++ b/entity/Offeritem_entity/grantCreateProcess.js @@ -1,6 +1,6 @@ import("system.vars"); import("system.result"); -import("Offer_lib"); +import("OfferOrder_lib"); var oUtils = new OfferUtils(); result.string(oUtils.isEditable(vars.get("$param.OfferStatus_param"))); \ No newline at end of file diff --git a/entity/Offeritem_entity/grantDeleteProcess.js b/entity/Offeritem_entity/grantDeleteProcess.js index 5d45e991a5d09799e02589b926edf9236cabfc9c..6651ef933bfc198121e93bd5f48dcaec406c812b 100644 --- a/entity/Offeritem_entity/grantDeleteProcess.js +++ b/entity/Offeritem_entity/grantDeleteProcess.js @@ -1,6 +1,6 @@ import("system.vars"); import("system.result"); -import("Offer_lib"); +import("OfferOrder_lib"); var oUtils = new OfferUtils(); result.string(oUtils.isEditable(vars.get("$param.OfferStatus_param"))); \ No newline at end of file diff --git a/entity/Offeritem_entity/grantUpdateProcess.js b/entity/Offeritem_entity/grantUpdateProcess.js index 5d45e991a5d09799e02589b926edf9236cabfc9c..6651ef933bfc198121e93bd5f48dcaec406c812b 100644 --- a/entity/Offeritem_entity/grantUpdateProcess.js +++ b/entity/Offeritem_entity/grantUpdateProcess.js @@ -1,6 +1,6 @@ import("system.vars"); import("system.result"); -import("Offer_lib"); +import("OfferOrder_lib"); var oUtils = new OfferUtils(); result.string(oUtils.isEditable(vars.get("$param.OfferStatus_param"))); \ No newline at end of file diff --git a/entity/Offeritem_entity/onDBDelete.js b/entity/Offeritem_entity/onDBDelete.js index e7ce64e15311337b8b619f36dc75edd10eeb3c52..ffa39a020f6ea87a1fbe7186a8ad3d97fb30416c 100644 --- a/entity/Offeritem_entity/onDBDelete.js +++ b/entity/Offeritem_entity/onDBDelete.js @@ -1,15 +1,21 @@ import("system.neon"); import("system.vars"); import("system.db"); -import("Offer_lib"); +import("OfferOrder_lib"); var oid = vars.get("$field.OFFER_ID"); if(oid != "") { + var oiid = vars.get("$field.OFFERITEMID"); + var oiUtils = new OfferItemUtils(oid); + var deletedIds = oiUtils.deletePartsList(oiid); + oiUtils.reOrgItems(); + + deletedIds.push(oiid); var cols = ["NET", "VAT"]; var colTypes = db.getColumnTypes("OFFER", cols); var oUtils = new OfferUtils(); - var vals = oUtils.getOfferNetAndVAT(oid, vars.get("$field.OFFERITEMID")); + var vals = oUtils.getOfferNetAndVAT(oid, deletedIds); db.updateData("OFFER", cols, colTypes, vals, "OFFERID = '" + oid + "'"); diff --git a/entity/Offeritem_entity/onDBInsert.js b/entity/Offeritem_entity/onDBInsert.js index 786f099d48efaac62e22dec935b785dadc53c195..1f39458fda42d203b809fe743a332c419a08dadb 100644 --- a/entity/Offeritem_entity/onDBInsert.js +++ b/entity/Offeritem_entity/onDBInsert.js @@ -3,44 +3,18 @@ import("system.neon"); import("system.vars"); import("system.db"); import("system.util"); -import("Offer_lib"); +import("OfferOrder_lib"); import("Product_lib"); var oid = vars.get("$field.OFFER_ID"); if(oid != "") { - //insert parts list - var rootProdId = vars.get("$field.PRODUCT_ID"); - if(rootProdId != "") - { - var p2pUtils = new Prod2prodUtils(); - var pUtils = new ProductUtils(); - var partsList = p2pUtils.getSubordinatedObject(rootProdId); - var statements = []; - var cols = ["OFFERITEMID" - , "OFFER_ID" - , "PRODUCT_ID" - , "GROUPCODEID" - , "ASSIGNEDTO" - , "ITEMNAME" - , "UNIT" - , "PRICE" - , "VAT" - , "QUANTITY" - , "OPTIONAL" - , "ITEMPOSITION" - , "ITEMSORT" - , "DATE_NEW" - , "USER_NEW"]; - - var colTypes = db.getColumnTypes("OFFERITEM", cols); - - __offeritemInsertStatement(partsList.root, vars.get("$field.OFFERITEMID"), vars.get("$field.ITEMPOSITION")); - - if(statements.length > 0) - db.inserts(statements); - } + var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; + var relid = vars.exists("$param.RelationId_param") ? vars.get("$param.RelationId_param") : ""; + var oiUtils = new OfferItemUtils(vars.get("$field.OFFER_ID")); + oiUtils.insertPartsList(vars.get("$field.PRODUCT_ID"), vars.get("$field.OFFERITEMID"), curr, relid); + oiUtils.reOrgItems(); //update offer price var cols = ["NET", "VAT"]; @@ -51,50 +25,4 @@ if(oid != "") db.updateData("OFFER", cols, colTypes, vals, "OFFERID = '" + oid + "'"); neon.refresh("Offer_entity"); -} - -function __offeritemInsertStatement(pPartsListObj, pAssignedTo, pPos) -{ - for(var i = 0; i < pPartsListObj.ids.length; i++) - { - var p2pid = pPartsListObj.ids[i]; - var newid = util.getNewUUID(); - - var Prod2prodObj = partsList[p2pid]; - var prodid = partsList[p2pid].prodid; - - var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; - var relid = vars.exists("$param.RelationId_param") ? vars.get("$param.RelationId_param") : ""; - - var ProdDetails = pUtils.getProductDetails(prodid, { currency: curr, quantity: Prod2prodObj.quantity, relationId: relid } ) - - var price = ""; - var vat = ""; - if(Prod2prodObj.takeprice == "Y" && ProdDetails.PriceListToUse != null) - { - price = ProdDetails.PriceListToUse.price; - vat = ProdDetails.PriceListToUse.vat; - } - - var vals = [newid - , oid - , prodid - , ProdDetails.groupCode - , pAssignedTo - , ProdDetails.productName - , ProdDetails.unit - , price - , vat - , Prod2prodObj.quantity - , Prod2prodObj.optional - , Prod2prodObj.pos //TODO: Pos - , "" //TODO: Itemsort - , datetime.date() - , vars.get("$sys.user") - ]; - - statements.push(["OFFERITEM", cols, colTypes, vals]); - - __offeritemInsertStatement(partsList[p2pid], newid); - } } \ No newline at end of file diff --git a/entity/Offeritem_entity/onDBUpdate.js b/entity/Offeritem_entity/onDBUpdate.js index 15e362e109713c274f3b53bc35fe30a3a99bb3ab..2634bf71937e1fd62009316a61e3cf7be2b2c986 100644 --- a/entity/Offeritem_entity/onDBUpdate.js +++ b/entity/Offeritem_entity/onDBUpdate.js @@ -2,7 +2,7 @@ import("system.logging"); import("system.vars"); import("system.db"); import("system.neon"); -import("Offer_lib"); +import("OfferOrder_lib"); var oid = vars.get("$field.OFFER_ID"); if(oid != "") diff --git a/entity/Offeritem_entity/orderClauseProcess.js b/entity/Offeritem_entity/orderClauseProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..8eebb296c78c7eda5d7830306cb75551f522943a --- /dev/null +++ b/entity/Offeritem_entity/orderClauseProcess.js @@ -0,0 +1,3 @@ +import("system.result"); + +result.object( {"OFFERITEM.ITEMSORT": "up"} ); \ No newline at end of file diff --git a/entity/Prod2prod_entity/Prod2prod_entity.aod b/entity/Prod2prod_entity/Prod2prod_entity.aod index 837bb6c123f160be178354f2485b8c6a1e9e14d0..2299428d6bbd9067abc60a61ece3694129e40495 100644 --- a/entity/Prod2prod_entity/Prod2prod_entity.aod +++ b/entity/Prod2prod_entity/Prod2prod_entity.aod @@ -3,17 +3,18 @@ <name>Prod2prod_entity</name> <majorModelMode>DISTRIBUTED</majorModelMode> <externalOpenAction>%aditoprj%/entity/Prod2prod_entity/externalOpenAction.js</externalOpenAction> + <recordContainerType>JDITO</recordContainerType> <alias>Data_alias</alias> <jDitoRecordAlias>Data_alias</jDitoRecordAlias> <fields> <element>UID</element> + <element>PARENTID</element> + <element>PROD2PRODID</element> <element>DEST_ID</element> <element>SOURCE_ID</element> <element>QUANTITY</element> <element>OPTIONAL</element> <element>TAKEPRICE</element> - <element>POS</element> - <element>PARENTID</element> </fields> <contentProcess>%aditoprj%/entity/Prod2prod_entity/contentProcess.js</contentProcess> <isPageable v="false" /> @@ -21,7 +22,6 @@ <onInsert>%aditoprj%/entity/Prod2prod_entity/onInsert.js</onInsert> <onUpdate>%aditoprj%/entity/Prod2prod_entity/onUpdate.js</onUpdate> <onDelete>%aditoprj%/entity/Prod2prod_entity/onDelete.js</onDelete> - <recordContainerType>JDITO</recordContainerType> <entityFields> <entityIncomingField> <name>#INCOMING</name> @@ -116,16 +116,16 @@ <triggerRecalculation v="true" /> <description>PARAMETER</description> </entityParameter> - <entityField> - <name>POS</name> - <fieldName>POS</fieldName> - <caption>Pos</caption> - </entityField> <entityField> <name>PARENTID</name> <fieldName>PARENTID</fieldName> <caption>Parent</caption> </entityField> + <entityField> + <name>PROD2PRODID</name> + <fieldName>PROD2PRODID</fieldName> + <valueProcess>%aditoprj%/entity/Prod2prod_entity/entityfields/prod2prodid/valueProcess.js</valueProcess> + </entityField> </entityFields> <linkInformation> <linkInformation> diff --git a/entity/Prod2prod_entity/contentProcess.js b/entity/Prod2prod_entity/contentProcess.js index 922c7492f54a3b07d8bb0e4f1d095edcdc3d59d5..912ab1f560dfdc682fc116a76e7c9a87bd0dc1d6 100644 --- a/entity/Prod2prod_entity/contentProcess.js +++ b/entity/Prod2prod_entity/contentProcess.js @@ -1,6 +1,7 @@ import("system.result"); import("system.vars"); import("system.db"); +import("system.util"); import("Product_lib"); var prodid = vars.exists("$param.ProductId_param") @@ -8,7 +9,6 @@ var prodid = vars.exists("$param.ProductId_param") if(prodid != "") { - var p2pUtils = new Prod2prodUtils(); - - result.object(p2pUtils.getSubordinatedData2DArray(prodid)); + var p2pUtils = new Prod2ProdUtils(prodid); + result.object(p2pUtils.getPartsListForRecordContainer()); } \ No newline at end of file diff --git a/entity/Prod2prod_entity/entityfields/prod2prodid/valueProcess.js b/entity/Prod2prod_entity/entityfields/prod2prodid/valueProcess.js new file mode 100644 index 0000000000000000000000000000000000000000..5be18c39832eee52e38b7147961d7db4bab5a588 --- /dev/null +++ b/entity/Prod2prod_entity/entityfields/prod2prodid/valueProcess.js @@ -0,0 +1,7 @@ +import("system.util"); +import("system.vars"); +import("system.result"); +import("system.neon"); + +if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) + result.string(util.getNewUUID()); \ No newline at end of file diff --git a/entity/Prod2prod_entity/entityfields/source_id/onValidation.js b/entity/Prod2prod_entity/entityfields/source_id/onValidation.js index 09a093be99f72fe4c9a5ac8f09ab463fec1c9172..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/entity/Prod2prod_entity/entityfields/source_id/onValidation.js +++ b/entity/Prod2prod_entity/entityfields/source_id/onValidation.js @@ -1,29 +0,0 @@ -//import("system.vars"); -//import("system.result"); -//import("system.db"); -//import("system.neon"); -//import("Keyword_lib"); -//import("Product_lib"); -// -//var kwUtils = new KeywordUtils(); -// -//var condition = ""; -//if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT || vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW) -//{ -// var prodid = vars.get("$field.DEST_ID"); -// var excludeableProds = [prodid]; -// -// var p2pUtils = new Prod2prodUtils(); -// excludeableProds = excludeableProds.concat(p2pUtils.getSubordinatedProdIds(prodid)); -// -// condition += " where PRODUCTID not in ('" + excludeableProds.join("','") + "')"; -//} -// -//var prods = db.table("select PRODUCTID, GROUPCODEID, PRODUCTNAME, PRODUCTCODE from PRODUCT " + condition); -//var res = []; -//for(var i = 0; i < prods.length; i++) -//{ -// res.push([prods[i][0], kwUtils.getViewValue("GROUPCODE", prods[i][1]) + " / " + prods[i][2] + " / " + prods[i][3]]); -//} -// -//result.object(res); \ No newline at end of file diff --git a/entity/Prod2prod_entity/entityfields/source_id/possibleItemsProcess.js b/entity/Prod2prod_entity/entityfields/source_id/possibleItemsProcess.js index bee5aec9a2b8b4f3239e0ca296aa2f0b8afbb012..5f303b272357e2020d24ce9b94083b9af79f5f61 100644 --- a/entity/Prod2prod_entity/entityfields/source_id/possibleItemsProcess.js +++ b/entity/Prod2prod_entity/entityfields/source_id/possibleItemsProcess.js @@ -2,6 +2,7 @@ import("system.vars"); import("system.result"); import("system.db"); import("system.neon"); +import("system.logging"); import("Keyword_lib"); import("Product_lib"); @@ -13,9 +14,14 @@ if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT || vars.get("$sys var prodid = vars.get("$field.DEST_ID"); var excludeableProds = [prodid]; - var p2pUtils = new Prod2prodUtils(); - excludeableProds = excludeableProds.concat(p2pUtils.getSubordinatedProdIds(prodid)); - excludeableProds = excludeableProds.concat(p2pUtils.getSupervisedProdIds(prodid)); + var p2pUtils = new Prod2ProdUtils(prodid); + + logging.log("partslist:" + p2pUtils.getPartsListProdIds()); + logging.log("parentlist:" + p2pUtils.getParentProdIds()); + + + excludeableProds = excludeableProds.concat(p2pUtils.getPartsListProdIds()); + excludeableProds = excludeableProds.concat(p2pUtils.getParentProdIds()); condition += " where PRODUCTID not in ('" + excludeableProds.join("','") + "')"; } diff --git a/process/Offer_lib/Offer_lib.aod b/process/OfferOrder_lib/OfferOrder_lib.aod similarity index 76% rename from process/Offer_lib/Offer_lib.aod rename to process/OfferOrder_lib/OfferOrder_lib.aod index ae2ae4230f73ba0dd50f29dcb7d4273254ea4d4b..54e028a23f677ac96df89949f20fe6efc4fe5f55 100644 --- a/process/Offer_lib/Offer_lib.aod +++ b/process/OfferOrder_lib/OfferOrder_lib.aod @@ -1,6 +1,6 @@ <?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>Offer_lib</name> + <name>OfferOrder_lib</name> <majorModelMode>DISTRIBUTED</majorModelMode> - <process>%aditoprj%/process/Offer_lib/process.js</process> + <process>%aditoprj%/process/OfferOrder_lib/process.js</process> </process> diff --git a/process/OfferOrder_lib/process.js b/process/OfferOrder_lib/process.js new file mode 100644 index 0000000000000000000000000000000000000000..67d8e8a9dfa0f75733b24983eaa3809d82bc7be6 --- /dev/null +++ b/process/OfferOrder_lib/process.js @@ -0,0 +1,619 @@ +import("system.translate"); +import("system.db"); +import("system.eMath"); +import("system.tools"); +import("Util_lib"); +import("Product_lib"); + +function OfferUtils() +{ + var that = this; + /** + * Delivers the next valid offer number (has to be unique) + * + * @return {String} next valid offer number + */ + this.getNextOfferNumber = function() + { + var JdUtils = new JDitoUtils(); + return JdUtils.getNextUniqueNumber("OFFERCODE", "OFFER"); + } + + /** + * Checks if the passed offer number is valid (has to be unique) + * + * @param {String} pOfferNumber offer number to check + * + * @return {boolean} passed number is valid + */ + this.validateOfferNumber = function(pOfferNumber) + { + var JdUtils = new JDitoUtils(); + return JdUtils.validateUniqueNumber(pOfferNumber, "OFFERCODE", "OFFER"); + } + + this.getOfferNumberValidationFailString = function() + { + return translate.text("The offer number already exists!"); + } + + this.getOfferNetAndVAT = function(pOfferId, pOfferitemIdsToDel) + { + //TODO: Bessere Möglichkeit als per SQL die zugehörigen Posten aus der DB zu holen? + var sum = 0; + var vat = 0; + var oiUtils = new OfferItemUtils(pOfferId); + + var condition = "where OFFER_ID = '" + pOfferId + "'"; + if(pOfferitemIdsToDel != undefined) + condition += " and OFFERITEMID not in ('" + pOfferitemIdsToDel.join("','") + "')"; + + var offerItems = db.table("select QUANTITY, PRICE, DISCOUNT, VAT, OPTIONAL " + + "from OFFERITEM " + condition); + + for(var i = 0; i < offerItems.length; i++) + { + sum += oiUtils.getItemSum(offerItems[i][0], offerItems[i][1], offerItems[i][2], offerItems[i][4]); + vat += oiUtils.getItemVAT(offerItems[i][0], offerItems[i][1], offerItems[i][2], offerItems[i][3], offerItems[i][4]); + } + + return [sum, vat]; + } + + this.isEditable = function(pStatus) + { + + //TODO: Administrator darf immer ändern, warten auf neue Berechtigungslogik? + + //Offer should be editable if offer state not equals "Sent", "Won" or "Lost" + return pStatus != "2" && pStatus != "3" && pStatus != "4"; + } +} + +/**OfferItemUtils + * + * Instance class that provides methods for dealing with offer / order items. + * Inherits method from abstract class ItemUtils. + * For documentation, see class ItemUtils. + * + ******************************************************************************/ +function OfferItemUtils(pOfferId) //constructor +{ + ItemUtils.apply(this, [pOfferId]); + OfferItemUtils.prototype = Object.create(ItemUtils.prototype); + OfferItemUtils.prototype.constructor = OfferItemUtils; +} + +OfferItemUtils.prototype.initItemTree = function() +{ + ItemUtils.prototype.initItemTree.apply(this, ["OFFERITEM", "OFFER_ID"]); +} + +OfferItemUtils.prototype.getItemSum = function(pQuantity, pPrice, pDiscount, pOptional) +{ + return ItemUtils.prototype.getItemSum.apply(this, [pQuantity, pPrice, pDiscount, pOptional]); +} + +OfferItemUtils.prototype.getItemVAT = function(pQuantity, pPrice, pDiscount, pVAT, pOptional) +{ + return ItemUtils.prototype.getItemVAT.apply(this, [pQuantity, pPrice, pDiscount, pVAT, pOptional]); +} + +OfferItemUtils.prototype.roundPrice = function(pPrice) +{ + return ItemUtils.prototype.roundPrice.apply(this, [pPrice]); +} + +OfferItemUtils.prototype.insertPartsList = function(pProductId, pAssignedTo, pCurrency, pRelationId) +{ + this.initItemTree(); + + var cols = ["OFFERITEMID" + , "OFFER_ID" + , "PRODUCT_ID" + , "GROUPCODEID" + , "ASSIGNEDTO" + , "ITEMNAME" + , "UNIT" + , "PRICE" + , "VAT" + , "QUANTITY" + , "OPTIONAL" + , "ITEMPOSITION" + , "ITEMSORT" + , "DATE_NEW" + , "USER_NEW"]; + + var table = "OFFERITEM"; + + return ItemUtils.prototype.insertPartsList.apply(this, [cols, table, pProductId, pAssignedTo, pCurrency, pRelationId]); +} + +OfferItemUtils.prototype.deletePartsList = function(pItemId) +{ + this.initItemTree(); + + return ItemUtils.prototype.deletePartsList.apply(this, [pItemId, "OFFERITEM"]); +} + +OfferItemUtils.prototype.getNextItemSort = function(pIds) +{ + this.initItemTree(); + + return ItemUtils.prototype.getNextItemSort.apply(this, [pIds]); +} + +OfferItemUtils.prototype.getNextItemPosition = function(pAssignedTo, pTree, pIds) +{ + this.initItemTree(); + + return ItemUtils.prototype.getNextItemPosition.apply(this, [pAssignedTo, pTree, pIds]); +} + +OfferItemUtils.prototype.reOrgItems = function() +{ + this.initItemTree(); + + ItemUtils.prototype.reOrgItems.apply(this, ["OFFERITEM"]); +} + +/* + * OfferItemUtils ************************************************************** + */ + +/**ItemUtils + * + * @abstract + * + * Abstract class that provides methods for dealing with offer / order items. + * Do not instantiate! + * Create a subclass like OfferItemUtils above to use methods of this class. + * + ******************************************************************************* + */ +function ItemUtils(pOfferOrderId) +{ + if(this.constructor === ItemUtils) + throw new Error("Can't instantiate abstract class ItemUtils!"); + + + this.offerOrderId = pOfferOrderId; + this.ItemTree = undefined;//object for dealing with hierarchical structure of Items, item position and item order + this.ItemIds = undefined;//contains all ItemIDs to save the order + + this._getItemTreeNodeObject = function(pAssignedTo, pPos, pItemSort) + { + return { + ids:[] + , assignedto: pAssignedTo + , pos: pPos + , itemsort: pItemSort + }; + } + + /** + *Adds a node to an ItemTree Object. <br> + *If no ItemTree Object is passed, the class variable this.ItemTree will be used. + * + *@param {String} pItemId req UID of item + *@param {String} pAssignedTo opt Parent UID of item + *@param {Object} pTree opt ItemTree Object to append + *@param {[]} pIds opt pIds Array for all ItemIDs to save order + * + */ + this._appendNode = function(pItemId, pAssignedTo, pTree, pIds) + { + if(pTree == undefined) + pTree = this.ItemTree; + if(pIds == undefined) + pIds = this.ItemIds; + + pTree[pItemId] = this._getItemTreeNodeObject(pAssignedTo + , this.getNextItemPosition(pAssignedTo, pTree, pIds) + , this.getNextItemSort(pIds)); + pIds.push(pItemId); + + if(pAssignedTo != "") + { + pTree[pAssignedTo].ids.push(pItemId); + } + } + + /** + *Deletes a node from an ItemTree Object within its subnodes. <br> + *If no ItemTree Object is passed, the class variable this.ItemTree will be used. + * + *@param {String} pItemId req UID of item + *@param {Object} pTree opt ItemTree Object to delete from + *@param {[]} pIds opt pIds Array for all ItemIDs to save order + * + */ + this._deleteNodes = function(pItemId, pTree, pIds) + { + if(pTree == undefined) + pTree = this.ItemTree; + if(pIds == undefined) + pIds = this.ItemIds; + + __delete(pTree[pItemId]); + + _deleteNode(pItemId); + + function __delete(pNode) + { + for(var i = 0; i < pNode.ids.length; i++) + { + __delete(pTree[pNode.ids[i]]); + _deleteNode(pNode.ids[i]); + } + } + + function _deleteNode(pItemId) + { + //delete Object property + delete pTree[pItemId]; + + //delete id in global Array "ItemIds" + var idx = pIds.indexOf(pItemId); + if(idx > -1) + pIds.splice(idx, 1); + + //delete id in Array from property "ids" of Tree + for(var oiid in pTree) + { + idx = pTree[oiid].ids.indexOf(pItemId); + if(idx > -1) + pTree[oiid].ids.splice(idx, 1); + } + } + } + + /** + *Compares Positions & Sort of the passed ItemTree Object with the class variable this.ItemTree <br> + *and updates differences in database. + * + * + *@param {String} pTable req DB-Table of Items + *@param {Object} pCompTree req ItemTree Object to compare with this.ItemTree + * + */ + this._updateReOrgItemChangesInDB = function(pTable, pCompTree) + { + var statements = []; + var cols = ["ITEMSORT", "ITEMPOSITION"]; + var colTypes = db.getColumnTypes(pTable, cols); + + var oiTree = this.ItemTree; + for(var oiid in pCompTree) + { + if(oiTree[oiid] != undefined) + { + //check if itemsort/pos has been changed + if(oiTree[oiid].itemsort != pCompTree[oiid].itemsort || oiTree[oiid].pos != pCompTree[oiid].pos) + { + var vals = [pCompTree[oiid].itemsort, pCompTree[oiid].pos]; + statements.push([pTable, cols, colTypes, vals, pTable + "ID = '" + oiid + "'"]); + } + } + } + + if(statements.length > 0) + db.updates(statements); + } +} + +/** + *Initializes ItemTree Object for class variable this.ItemTree <br> + *with items already stored in database. + * + *@abstract + * + *@param {String} pTable req DB-Table of Items + *@param {String} pForeignKeyColumn req DB-Column that contains foreign key Items belong to + * + */ +ItemUtils.prototype.initItemTree = function(pTable, pForeignKeyColumn) +{ + if(this.ItemTree == undefined) + { + this.ItemTree = {}; + this.ItemIds = []; + + var data = db.table("select " + pTable + "ID, ASSIGNEDTO, ITEMPOSITION, ITEMSORT from " + pTable + + " where " + pForeignKeyColumn + " = '" + this.offerOrderId + "' order by ITEMSORT"); + + for(var i = 0; i < data.length; i++) + { + this.ItemTree[data[i][0]] = this._getItemTreeNodeObject(data[i][1], data[i][2], data[i][3]); + this.ItemIds.push(data[i][0]); + } + + for(var oiid in this.ItemTree) + { + if(this.ItemTree[oiid].assignedto != "") + this.ItemTree[ this.ItemTree[oiid].assignedto ].ids.push(oiid); + } + } +} + +ItemUtils.prototype.getItemSum = function(pQuantity, pPrice, pDiscount, pOptional) +{ + pQuantity = pQuantity || 0; + pPrice = pPrice || 0; + pDiscount = pDiscount || 0; + + return Number(pOptional) * parseFloat(pQuantity) * parseFloat(pPrice) * ((100 - parseFloat(pDiscount)) / 100); +} + +ItemUtils.prototype.getItemVAT = function(pQuantity, pPrice, pDiscount, pVAT, pOptional) +{ + pQuantity = pQuantity || 0; + pPrice = pPrice || 0; + pDiscount = pDiscount || 0; + pVAT = pVAT || 0; + + return Number(pOptional) * parseFloat(pQuantity) * parseFloat(pPrice) * ((100 - parseFloat(pDiscount)) / 100) * (parseFloat(pVAT) / 100); +} + +ItemUtils.prototype.roundPrice = function(pPrice) +{ + return eMath.roundDec(pPrice, 2, eMath.ROUND_HALF_UP); +} + +/** +* Inserts parts list of the passed product into database. +* +* @abstract +* +* @param {[]} pColumns req Array of Item DB Columns +* @param {String} pTable req DB Table of Items +* @param {String} pProductId req UID of root product (selected product) +* @param {String} pAssignedTo opt UID of parent item +* @param {String} pCurrency opt currency for price list to use +* @param {String} pRelationId opt relationid for price list to use (custom price list) +* +* @return {[]} Array of inserted ItemIDs +*/ +ItemUtils.prototype.insertPartsList = function(pColumns, pTable, pProductId, pAssignedTo, pCurrency, pRelationId) +{ + var insertedItemIds = []; + + //save address for this here to call methods in recursive sub function __itemInsertStatement + var self = this; + + if(pAssignedTo == undefined) + pAssignedTo = ""; + if(pCurrency == undefined) + pCurrency = ""; + if(pRelationId == undefined) + pRelationId = ""; + + var rootProdId = pProductId; + if(rootProdId != "") + { + var pUtils = new ProductUtils(); + + var p2pUtils = new Prod2ProdUtils(rootProdId); + var partsList = p2pUtils.getPartsListObject(); + + var statements = []; + var colTypes = db.getColumnTypes(pTable, pColumns); + + __itemInsertStatement(partsList.root, pAssignedTo, pCurrency, pRelationId); + + if(statements.length > 0) + db.inserts(statements); + } + + return insertedItemIds; + + //recursive function for building item insert statements + function __itemInsertStatement(pPartsListObj, pAssignedTo, pCurrency, pRelationId) + { + for(var i = 0; i < pPartsListObj.ids.length; i++) + { + var newid = util.getNewUUID(); + self._appendNode(newid, pAssignedTo); + var pos = self.ItemTree[newid].pos; + var itemsort = self.ItemTree[newid].itemsort; + + var p2pid = pPartsListObj.ids[i]; + var P2pObject = partsList[p2pid]; + var prodid = partsList[p2pid].sourceid; + var ProductDetails = pUtils.getProductDetails(prodid, { currency: pCurrency, quantity: P2pObject.quantity, relationId: pRelationId } ) + + var price = ""; + var vat = ""; + if(P2pObject.takeprice == "Y" && ProductDetails.productId && ProductDetails.PriceListToUse) + { + price = ProductDetails.PriceListToUse.price; + vat = ProductDetails.PriceListToUse.vat; + } + + var vals = [newid + , self.offerOrderId + , prodid + , ProductDetails.groupCode + , pAssignedTo + , ProductDetails.productName + , ProductDetails.unit + , price + , vat + , P2pObject.quantity + , P2pObject.optional + , pos + , itemsort + , datetime.date() + , vars.get("$sys.user")]; + + statements.push([pTable, pColumns, colTypes, vals]); + insertedItemIds.push(newid); + + __itemInsertStatement(partsList[p2pid], newid); + } + } +} + +/** +* Deletes parts list of the passed item from database. +* +* @abstract +* +* @param {String} pItemId req UID of item that will be deleted +* @param {String} pTable req DB Table of Items +* +* @return {[]} Array of deleted ItemIDs +*/ +ItemUtils.prototype.deletePartsList = function(pItemId, pTable) +{ + var deletedItemIds = []; + + //save address for this here to get class variables in recursive sub function __itemDeleteStatement + var self = this; + + var statements = []; + + __itemDeleteStatement(pItemId); + + if(statements.length > 0) + db.deletes(statements); + + self._deleteNodes(pItemId); + + return deletedItemIds; + + //recursive function for building item delete statements + function __itemDeleteStatement(pItemId) + { + var itemsToDelete = self.ItemTree[pItemId].ids; + + for(var i = 0; i < itemsToDelete.length; i++) + { + //unshift due to foreign key constraints (Delete hierarchically starting at the bottom) + statements.unshift([pTable, pTable + "ID = '" + itemsToDelete[i] + "'"]); + deletedItemIds.push(itemsToDelete[i]); + __itemDeleteStatement(itemsToDelete[i]); + } + } +} + +/** +* Delivers next item sort value by passed ItemID-Array. <br> +* If no parameter is passed the class variable this.ItemIds will be used. +* +* @abstract +* +* @param {[]} pIds opt Array for all ItemIDs to save order +* +* @return {String} Next item sort value +*/ +ItemUtils.prototype.getNextItemSort = function(pIds) +{ + if(pIds == undefined) + pIds = this.ItemIds; + + return (pIds.length + 1).toString(); +} + +/** +* Delivers next item position value by passed ItemTree Object. <br> +* If no parameter is passed the class variable this.ItemTree will be used. <br> +* <br> +* Item position is generated according to the following pattern: <br> +* 1 (Parent ItemID (AssignedTo) is empty) <br> +* 1.1 (Parent ItemID (AssignedTo) = ItemID of Pos 1) <br> +* 1.2 <br> +* 1.2.1 (Parent ItemID (AssignedTo) = ItemID of Pos 1.2) <br> +* ... <br> +* 2 <br> +* 2.1 <br> +* 2.1.1 <br> +* ... <br> +* 3 <br> +* ... <br> +* +* @abstract +* +* @param {String} pAssignedTo Parent ItemID +* @param {Object} pTree opt ItemTree Object to get next position from +* @param {[]} pIds opt Array for all ItemIDs to save order +* +* @return {String} Next item position value +*/ +ItemUtils.prototype.getNextItemPosition = function(pAssignedTo, pTree, pIds) +{ + if(pAssignedTo == undefined) + pAssignedTo = ""; + if(pTree == undefined) + pTree = this.ItemTree; + if(pIds == undefined) + pIds = this.ItemIds; + + var maxPos = ["0"]; + + if(pAssignedTo != "") + { + if(pTree[pAssignedTo].ids.length < 1) //first item in this level + { + maxPos = pTree[pAssignedTo].pos.split("."); + maxPos = maxPos.concat(["0"]); //next level pos + } + else + { + var childIds = pTree[pAssignedTo].ids; + maxPos = pTree[childIds[childIds.length-1]].pos.split("."); + } + } + else + { + if(pIds.length > 0) + { + maxPos[0] = this.ItemTree[pIds[pIds.length-1]].pos; + } + } + + maxPos[maxPos.length-1] = (Number(maxPos[maxPos.length-1]) + 1).toString(); + + return maxPos.join("."); +} + +/** +* Reorganizes hierarchical structure of Items, item position and item order. <br> +* Changes will be updated in database. <br> +* This function has to be executed after items have been added or deleted. <br> +* +* @abstract +* +* @param {String} pTable req DB Table of Items +* +*/ +ItemUtils.prototype.reOrgItems = function(pTable) +{ + //save address for this here to get methods in recursive sub function __reorg + var self = this; + + var newTree = {}; + var newIds = []; + + __reorg(self.ItemIds, ""); + + self._updateReOrgItemChangesInDB(pTable, newTree); + + //recursive function to build new ItemTree Structure + function __reorg(pIds, pAssignedTo) + { + for(var i = 0; i < pIds.length; i++) + { + if(newTree[pIds[i]] == undefined) + { + //build new tree + self._appendNode(pIds[i], pAssignedTo, newTree, newIds); + + __reorg(self.ItemTree[pIds[i]].ids, pIds[i]); + } + } + } +} +/* + * ItemUtils ******************************************************************* + */ \ No newline at end of file diff --git a/process/Offer_lib/process.js b/process/Offer_lib/process.js deleted file mode 100644 index e83df959577b45e8fcaa37f102eb45f294356e5d..0000000000000000000000000000000000000000 --- a/process/Offer_lib/process.js +++ /dev/null @@ -1,96 +0,0 @@ -import("system.translate"); -import("system.db"); -import("system.eMath"); -import("system.tools"); -import("Util_lib"); - -function OfferUtils(){ - var that = this; - /** - * Delivers the next valid offer number (has to be unique) - * - * @result {String} next valid offer number - */ - this.getNextOfferNumber = function(){ - var JdUtils = new JDitoUtils(); - return JdUtils.getNextUniqueNumber("OFFERCODE", "OFFER"); - } - - /** - * Checks if the passed offer number is valid (has to be unique) - * - * @param {String} pOfferNumber offer number to check - * - * @result {boolean} passed number is valid - */ - this.validateOfferNumber = function(pOfferNumber){ - var JdUtils = new JDitoUtils(); - return JdUtils.validateUniqueNumber(pOfferNumber, "OFFERCODE", "OFFER"); - } - - this.getOfferNumberValidationFailString = function(){ - return translate.text("The offer number already exists!"); - } - - this.getOfferNetAndVAT = function(pOfferId, pOfferitemIdToDel){ - //TODO: Bessere Möglichkeit als per SQL die zugehörigen Posten aus der DB zu holen? - var sum = 0; - var vat = 0; - var oiUtils = new OfferItemUtils(); - - var condition = "where OFFER_ID = '" + pOfferId + "'"; - if(pOfferitemIdToDel != undefined) - condition += " and OFFERITEMID <> '" + pOfferitemIdToDel + "'"; - - var offerItems = db.table("select QUANTITY, PRICE, DISCOUNT, VAT, OPTIONAL " - + "from OFFERITEM " + condition); - - for(var i = 0; i < offerItems.length; i++){ - sum += oiUtils.getItemSum(offerItems[i][0], offerItems[i][1], offerItems[i][2], offerItems[i][4]); - vat += oiUtils.getItemVAT(offerItems[i][0], offerItems[i][1], offerItems[i][2], offerItems[i][3], offerItems[i][4]); - } - - return [sum, vat]; - } - - this.isEditable = function(pStatus){ - - //TODO: Administrator darf immer ändern, warten auf neue Berechtigungslogik? - - //Offer should be editable if offer state not equals "Sent", "Won" or "Lost" - return pStatus != "2" && pStatus != "3" && pStatus != "4"; - } -} - -function OfferItemUtils(){ - - this.getItemSum = function(pQuantity, pPrice, pDiscount, pOptional){ - - pQuantity = pQuantity || 0; - pPrice = pPrice || 0; - pDiscount = pDiscount || 0; - - return Number(pOptional) * parseFloat(pQuantity) * parseFloat(pPrice) * ((100 - parseFloat(pDiscount)) / 100); - } - - this.getItemVAT = function(pQuantity, pPrice, pDiscount, pVAT, pOptional){ - - pQuantity = pQuantity || 0; - pPrice = pPrice || 0; - pDiscount = pDiscount || 0; - pVAT = pVAT || 0; - - return Number(pOptional) * parseFloat(pQuantity) * parseFloat(pPrice) * ((100 - parseFloat(pDiscount)) / 100) * (parseFloat(pVAT) / 100); - } - - this.roundPrice = function(pPrice){ - return eMath.roundDec(pPrice, 2, eMath.ROUND_HALF_UP); - } - - this.insertPartsList = function() - { - - - - } -} \ No newline at end of file diff --git a/process/Product_lib/process.js b/process/Product_lib/process.js index 11c08a74625c6d7c46a194a40d5bf5e589c37d49..161c665d32d38340cba27e1bb437dd318b2b30b8 100644 --- a/process/Product_lib/process.js +++ b/process/Product_lib/process.js @@ -5,6 +5,12 @@ import("system.db"); import("system.vars"); import("Util_lib"); +/** + * Class containing utility functions for products + * + * @class + * + */ function ProductUtils() { var that = this; @@ -68,13 +74,63 @@ function ProductUtils() } /** - * Delivers the stock + * Delivers metadata and price lists of the passed product. + * If parameter "pPriceListFilter" is passed valid price lists and the + * current price list to use for offer/order are delivered. * - * @param pPid {String} ProductID + * @param pPid {String} req ProductID + * @param pPriceListFilter {Object} opt { currency: "currencyValue", quantity: "quantityValue", relationId: "relationIdValue (for custom price lists)" } * - * @example productUtils.getStockCount(vars.get("$field.PRODUCTID")) + * @example //Product_entity, Field: PRODUCT_ID, Process: onValueChange + * var pid = ProcessHandlingUtil.getOnValidationValue(vars.get("$field.PRODUCT_ID")); + * var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : ""; + * var relid = vars.exists("$param.RelationId_param") ? vars.get("$param.RelationId_param") : ""; + * var pUtils = new ProductUtils(); + * var PriceListFilter = { currency: curr, quantity: vars.get("$field.QUANTITY"), relationId: relid }; + * var ProductDetails = pUtils.getProductDetails(pid, PriceListFilter); * - * @result {String} stock count + * @return {Object} { <br> + * productId: "productid" <br> + * , productName: "product name" <br> + * , groupCode: "keyvalue of keyword 'GROUPCODE'" <br> + * , unit: "keyvalue of keyword 'UNIT'" <br> + * , PriceLists: {$pricelistid$ { <br> + * priceListId: "pricelistid" <br> + * , relationId: "relationid" when filled -> custom price list <br> + * , priceList: "keyvalue of keyword 'PRICELIST'" <br> + * , price: "price" <br> + * , vat: "vat" <br> + * , validFrom: TIMESTAMP <br> + * , validTo: TIMESTAMP <br> + * , buySell: "SP" / "PP" <br> + * , fromQuantity: "fromquantity" <br> + * , currency: "keyvalue of keyword 'CURRENCY'" <br> + * } } <br> + * , CurrentValidPriceLists: {$pricelistid$ { <br> + * priceListId: "pricelistid" <br> + * , relationId: "relationid" when filled -> custom price list <br> + * , priceList: "keyvalue of keyword 'PRICELIST'" <br> + * , price: "price" <br> + * , vat: "vat" <br> + * , validFrom: TIMESTAMP <br> + * , validTo: TIMESTAMP <br> + * , buySell: "SP" / "PP" <br> + * , fromQuantity: "fromquantity" <br> + * , currency: "keyvalue of keyword 'CURRENCY'" <br> + * } } <br> + * , PriceListToUse: {$pricelistid$ { <br> + * priceListId: "pricelistid" <br> + * , relationId: "relationid" when filled -> custom price list <br> + * , priceList: "keyvalue of keyword 'PRICELIST'" <br> + * , price: "price" <br> + * , vat: "vat" <br> + * , validFrom: TIMESTAMP <br> + * , validTo: TIMESTAMP <br> + * , buySell: "SP" / "PP" <br> + * , fromQuantity: "fromquantity" <br> + * , currency: "keyvalue of keyword 'CURRENCY'" <br> + * } } <br> + * } */ this.getProductDetails = function( pPid, pPriceListFilter ) { @@ -103,7 +159,9 @@ function ProductUtils() && pPriceListFilter.quantity != undefined && pPriceListFilter.quantity != "") { validPriceLists = true; - var colsPricelistValid = ["validPP.PRODUCTPRICEID", "validPP.RELATION_ID", "validPP.PRICELIST", "validPP.PRICE", "validPP.VAT"]; + var colsPricelistValid = ["validPP.PRODUCTPRICEID", "validPP.RELATION_ID", "validPP.PRICELIST", "validPP.PRICE", "validPP.VAT" + , "validPP.VALID_FROM", "validPP.VALID_TO", "validPP.BUYSELL", "validPP.FROMQUANTITY", "validPP.CURRENCY"]; + cols = cols.concat(colsPricelistValid); joins.push(" left join PRODUCTPRICE validPP on validPP.PRODUCT_ID = PRODUCTID " + " and validPP.CURRENCY = " + pPriceListFilter.currency @@ -144,18 +202,7 @@ function ProductUtils() var colIdx = colsProduct.length; if(ProductData[i][colIdx] != "" && ProductDetails.PriceLists[ProductData[i][colIdx]] == undefined) //Pricelist found { - ProductDetails.PriceLists[ProductData[i][colIdx]] = { - priceListId: ProductData[i][colIdx++] - , relationId: ProductData[i][colIdx++] - , priceList: ProductData[i][colIdx++] - , price: ProductData[i][colIdx++] - , vat: ProductData[i][colIdx++] - , validFrom: ProductData[i][colIdx++] - , validTo: ProductData[i][colIdx++] - , buySell: ProductData[i][colIdx++] - , fromQuantity: ProductData[i][colIdx++] - , currency: ProductData[i][colIdx++] - } + ProductDetails.PriceLists[ProductData[i][colIdx]] = _getPriceListObject(); } //Pricelist (currently valid) @@ -164,13 +211,7 @@ function ProductUtils() { if(ProductData[i][colIdx] != "" && ProductDetails.CurrentValidPriceLists[ProductData[i][colIdx]] == undefined) //Pricelist found { - ProductDetails.CurrentValidPriceLists[ProductData[i][colIdx]] = { - priceListId: ProductData[i][colIdx++] - , relationId: ProductData[i][colIdx++] - , priceList: ProductData[i][colIdx++] - , price: ProductData[i][colIdx++] - , vat: ProductData[i][colIdx++] - } + ProductDetails.CurrentValidPriceLists[ProductData[i][colIdx]] = _getPriceListObject(); } } } @@ -180,12 +221,28 @@ function ProductUtils() return ProductDetails; + function _getPriceListObject() + { + return { + priceListId: ProductData[i][colIdx++] + , relationId: ProductData[i][colIdx++] + , priceList: ProductData[i][colIdx++] + , price: ProductData[i][colIdx++] + , vat: ProductData[i][colIdx++] + , validFrom: ProductData[i][colIdx++] + , validTo: ProductData[i][colIdx++] + , buySell: ProductData[i][colIdx++] + , fromQuantity: ProductData[i][colIdx++] + , currency: ProductData[i][colIdx++] + }; + } + //price list to use for offer/order function _getPriceListToUse(pPriceLists, pPriceListFilter) { for(var list in pPriceLists) { - //customer specific price (defined in Org -> Conditions) + //custom price (defined in Org -> Conditions) if(pPriceListFilter.relationId != "" && pPriceListFilter.relationId == pPriceLists[list].relationId) { return pPriceLists[list]; @@ -207,21 +264,59 @@ function ProductUtils() } } - //pPriceList Object beschreiben + /** + * Checks if there is already an existing price list identical to the passed price list + * + * @param pPid {String} req ProductID + * @param pPriceList {Object} req { <br> + * priceList: "keyvalue of keyword 'PRICELIST'" <br> + * , validFrom: TIMESTAMP <br> + * , validTo: TIMESTAMP <br> + * , buySell: "SP" / "PP" <br> + * , fromQuantity: "fromquantity" <br> + * , currency: "keyvalue of keyword 'CURRENCY'" <br> + * } + * + * @example //Productprice_entity, Field: PRICELIST, Process: onValidation + * var pUtils = new ProductUtils(); + * var priceList = { + * priceList: ProcessHandlingUtil.getOnValidationValue(vars.get("$field.PRICELIST")) + * , fromQuantity: vars.get("$field.FROMQUANTITY") + * , buySell: vars.get("$field.BUYSELL") + * , currency: vars.get("$field.CURRENCY") + * , validFrom: vars.get("$field.VALID_FROM") + * , validTo: vars.get("$field.VALID_TO") + * }; + * + * var identicalPriceList = pUtils.checkForIndenticalPriceLists(vars.get("$field.PRODUCT_ID"), priceList); + * if(identicalPriceList != null) + * { + * result.string(translate.text("Identical price list found!")); + * } + * + * @return {Object | null} null if no identical price list was found, otherwise the found price list + */ this.checkForIndenticalPriceLists = function(pPid, pPriceList) { var PriceLists = that.getProductDetails(pPid).PriceLists; for(var pricelist in PriceLists) { - + //equal price list + //equal fromquantity + //equal currency + //equal pp/sp if( pPriceList.priceList == PriceLists[pricelist].priceList && pPriceList.fromQuantity == PriceLists[pricelist].fromQuantity && pPriceList.buySell == PriceLists[pricelist].buySell && pPriceList.currency == PriceLists[pricelist].currency ) { - + //identical validFrom & validTo + // OR NOT [ validFrom_new <= validFrom & validTo_new <= validTo + // OR validFrom_new >= validFrom & validTo_new >= validTo + // OR validFrom_new < validFrom & validTo_new > validTo + // ] if( pPriceList.validFrom == PriceLists[pricelist].validFrom && pPriceList.validTo == PriceLists[pricelist].validTo || ! ( pPriceList.validFrom <= PriceLists[pricelist].validFrom && pPriceList.validTo <= PriceLists[pricelist].validTo || pPriceList.validFrom >= PriceLists[pricelist].validFrom && pPriceList.validTo >= PriceLists[pricelist].validTo @@ -234,193 +329,224 @@ function ProductUtils() } } - return null; - - //equal price list - - //identical fromquantity - //identical currency - //identical pp/sp - - //identical validFrom & validTo - // OR NOT [ validFrom_new <= validFrom & validTo_new <= validTo - // OR validFrom_new >= validFrom & validTo_new >= validTo - // OR validFrom_new < validFrom & validTo_new > validTo - // ] - + //no identical price list found + return null; } - } -function Prod2prodUtils() +/** + * Class containing utility functions for Prod2Prod (Parts list) + * + * @param pProductId req ProductID + * + * @class + * + */ +function Prod2ProdUtils(pProductId) { - var data = getProd2prodData(); + var data; - function getProd2prodData() + /** + * Delivers an Object containing parts list structure for passed product "pProductId" (Constructor parameter) + * + * @return {Object} { $prod2prodid$ { <br> + * ids: [ Array containing child Prod2ProdIds for passed product "pProductId" (Constructor parameter) ] <br> + * , rowdata: [ "PROD2PRODID", "DEST_ID", "SOURCE_ID", "QUANTITY", "OPTIONAL", "TAKEPRICE" ] from DB-Table PROD2PROD <br> + * , destid: "Parent ProductID" <br> + * , sourceid: "Child ProductID" <br> + * , quantity: "Quantity" <br> + * , optional: "1" = not optional, "0" = optional (for easier calculation) <br> + * , takeprice: "Y" = price, "N" = no price <br> + * } } + */ + this.getPartsListObject = function() { - var sqlStr = "select PROD2PRODID, DEST_ID, SOURCE_ID, QUANTITY, OPTIONAL, TAKEPRICE " - + "from PROD2PROD join PRODUCT on PROD2PROD.SOURCE_ID = PRODUCTID " - + "order by PRODUCTCODE "; - - return db.table(sqlStr); + return _relateChilds(); } - function _buildTree(pPid, pSupervised) + /** + * Delivers a 2D-Array for RecordContainer of Entity "Prod2prod_entity" + * containing parts list for passed product "pProductId" (Constructor parameter). + * + * It is necessary to generate a specifically UID for the RecordContainer because + * the same data record can be listed several times. Therefore the primary key "PROD2PRODID" + * can not be used for UID because this must be unique. + * + * @return {[ [] ]} [ ["UID" + * , "PARENTID" (equals "DEST_ID") + * , "PROD2PRODID" + * , "DEST_ID" + * , "SOURCE_ID" + * , "QUANTITY" + * , "OPTIONAL" + * , "TAKEPRICE"] ] + */ + this.getPartsListForRecordContainer = function() { - /* object tree to relate products by DEST_ID / SOURCE_ID. - * Parts list shows subordinated products. - **/ - var tree = { root: {ids: [], sourceid: pPid } }; + var ret = []; + var childs = _relateChilds(); - if(pSupervised) - tree = { root: {ids: [], destid: pPid } }; - - for (var i = 0; i < data.length; i++) + __push(childs.root); + + function __push(pObj) { - var prod2prodid = data[i][0]; - if ( tree[prod2prodid] == undefined ) - tree[prod2prodid] = { - ids: [] - , prodid: "" - , rowdata: data[i].slice(0)//copy to get NativeArray for concatenation - , destid: data[i][1] - , sourceid: data[i][2] - , quantity: data[i][3] - , optional: data[i][4] - , takeprice: data[i][5] - , pos: 0 - , parentid: "" - }; + for(var i = 0; i < pObj.ids.length; i++) + { + var rowdata = childs[pObj.ids[i]].rowdata; + var UID = util.getNewUUID(); + var PARENTID = childs[pObj.ids[i]].destid; + + rowdata = [UID, PARENTID].concat(rowdata); + ret.push(rowdata); + __push( childs[pObj.ids[i]] ); + } } - return tree; + return ret; } - function _getSubordinated(pPid) + /** + * Delivers an Array containing productids of the parts list + * for passed product "pProductId" (Constructor parameter). + * + * + * @return {[]} [ "SOURCE_ID" ] + */ + this.getPartsListProdIds = function() { - var tree = _buildTree(pPid, false); - - __relate("root", ["0"]); + var ret = []; + var childs = _relateChilds(); - return tree; + __push(childs.root); + return ret; - function __relate(pID, pPos) + function __push(pObj) { - for ( var id in tree ) + for(var i = 0; i < pObj.ids.length; i++) { - if ( tree[id].destid == tree[pID].sourceid && tree[pID].ids.indexOf(id) == -1 ) - { - tree[pID].ids.push(id); - - var rowdata = tree[id].rowdata; - pPos[pPos.length-1] = (Number(pPos[pPos.length-1]) + 1).toString(); - //POS, PARENTID - rowdata = rowdata.concat([pPos.join("."), pID]); - - tree[id].rowdata = rowdata; - tree[id].prodid = tree[id].sourceid; - tree[id].pos = rowdata[6]; - tree[id].parentid = rowdata[7]; - - __relate(id, pPos.concat([0])); - } + ret.push(childs[pObj.ids[i]].sourceid); + __push( childs[pObj.ids[i]] ); } } } - this.getSubordinatedObject = function(pPid) - { - return _getSubordinated(pPid); - } - - this.getSubordinatedData2DArray = function(pPid) + /** + * Delivers an Array containing productids of the parent list + * for passed product "pProductId" (Constructor parameter). + * + * + * @return {[]} [ "DEST_ID" ] + */ + this.getParentProdIds = function() { var ret = []; - var so = _getSubordinated(pPid); + var parents = _relateParents(); - __push(so.root); + __push(parents.root); + + return ret; function __push(pObj) { for(var i = 0; i < pObj.ids.length; i++) { - ret.push(so[pObj.ids[i]].rowdata); - __push( so[pObj.ids[i]] ); + ret.push(parents[pObj.ids[i]].destid); + __push( parents[pObj.ids[i]] ); } } - - var dUtils = new DataUtils(); - dUtils.array_mDimSort(ret, 6, true); - - return ret; } - this.getSubordinatedProdIds = function(pPid) + /** + * Function to initalize class variable "data" containing complete Prod2Prod-Data.<br> + * It guarantees a unique load of data per instance. + * + */ + function _initProd2ProdData() { - var ret = []; - var so = _getSubordinated(pPid); - for(var p2pid in so) - ret.push(so[p2pid].prodid); - - return ret; + if(data == undefined) + { + var sqlStr = "select PROD2PRODID, DEST_ID, SOURCE_ID, QUANTITY, OPTIONAL, TAKEPRICE " + + "from PROD2PROD join PRODUCT on PROD2PROD.SOURCE_ID = PRODUCTID " + + "order by PRODUCTCODE "; + + data = db.table(sqlStr); + } } - function _getSupervised(pPid) + /* object tree to relate products by DEST_ID / SOURCE_ID. + * + **/ + function _buildTree(pSupervised) { - var SuperVised = {}; + _initProd2ProdData(); + + var tree = { root: {ids: [], sourceid: pProductId } }; - var tree = _buildTree(pPid, true); + if(pSupervised) + tree = { root: {ids: [], destid: pProductId } }; - __relate("root", ["0"]); + for (var i = 0; i < data.length; i++) + { + var prod2prodid = data[i][0]; + if ( tree[prod2prodid] == undefined ) + { + tree[prod2prodid] = { + ids: [] + , rowdata: data[i].slice(0)//copy to get NativeArray for concatenation + , destid: data[i][1] + , sourceid: data[i][2] + , quantity: data[i][3] + , optional: data[i][4] + , takeprice: data[i][5] + }; + } + } - return SuperVised; + return tree; + } + + function _relateChilds() + { + var tree = _buildTree(false); + + __relate("root"); + + return tree; - function __relate(pID, pPos) + function __relate(pID) { for ( var id in tree ) { - if ( tree[id].sourceid == tree[pID].destid && tree[pID].ids.indexOf(id) == -1 ) + if ( tree[id].destid == tree[pID].sourceid && tree[pID].ids.indexOf(id) == -1 ) { - var rowdata = tree[id].data; - pPos[pPos.length-1] = (Number(pPos[pPos.length-1]) + 1).toString(); - //POS, PARENTID - rowdata = rowdata.concat([pPos.join("."), pID]); - - SuperVised[id] = { prodid: tree[id].destid, data: rowdata }; - - __relate(id, pPos.concat([0])); + tree[pID].ids.push(id); + __relate(id); } } } } - this.getSupervisedData = function(pPid) + function _relateParents() { - return _getSupervised(pPid); - } - - this.getSupervisedData2DArray = function(pPid) - { - var ret = []; - var so = _getSupervised(pPid); - for(var p2pid in so) - ret.push(so[p2pid].data); - - var dUtils = new DataUtils(); - dUtils.array_mDimSort(ret, 6, true); - - return ret; - } - - this.getSupervisedProdIds = function(pPid) - { - var ret = []; - var so = _getSupervised(pPid); - for(var p2pid in so) - ret.push(so[p2pid].prodid); + var tree = _buildTree(true); + + __relate("root"); - return ret; + return tree; + + + function __relate(pID) + { + for ( var id in tree ) + { + if ( tree[id].sourceid == tree[pID].destid && tree[pID].ids.indexOf(id) == -1 ) + { + tree[pID].ids.push(id); + __relate(id); + } + } + } } } \ No newline at end of file diff --git a/process/Util_lib/process.js b/process/Util_lib/process.js index 9a02ca2d3e870c8097d693452698ca47d85ee93a..e88d7781f555fe19c7ffc6fba6611a4f7cead70c 100644 --- a/process/Util_lib/process.js +++ b/process/Util_lib/process.js @@ -11,7 +11,7 @@ import("system.swing"); import("system.question"); import("system.eMath"); import("system.datetime"); -import("Offer_lib"); +import("OfferOrder_lib"); import("Date_lib"); /** @@ -910,11 +910,12 @@ function JDitoUtils() * @param {String} pColumn req database column that contains unique numbers * @param {String} pTable req database table * @param {Number} pStartNumber opt number to start numeration + * @param {String} pCondition opt SQL Where Conditon * * @result {String} next valid number */ - this.getNextUniqueNumber = function(pColumn, pTable, pStartNumber){ - var maxNum = that.getMaxUniqueNumber(pColumn, pTable); + this.getNextUniqueNumber = function(pColumn, pTable, pStartNumber, pCondition){ + var maxNum = that.getMaxUniqueNumber(pColumn, pTable, pCondition); if(maxNum == "0") { @@ -931,11 +932,12 @@ function JDitoUtils() * @param {String} pNumber number to check * @param {String} pColumn req database column that contains unique numbers * @param {String} pTable req database table + * @param {String} pCondition opt SQL Where Conditon * * @result {boolean} passed number is valid */ - this.validateUniqueNumber = function(pNumber, pColumn, pTable){ - var maxNum = that.getMaxUniqueNumber(pColumn, pTable); + this.validateUniqueNumber = function(pNumber, pColumn, pTable, pCondition){ + var maxNum = that.getMaxUniqueNumber(pColumn, pTable, pCondition); return Number(pNumber) > Number(maxNum); } @@ -945,11 +947,17 @@ function JDitoUtils() * * @param {String} pColumn req database column that contains unique numbers * @param {String} pTable req database table + * @param {String} pCondition opt SQL Where Conditon * * @result {String} hightest number */ - this.getMaxUniqueNumber = function(pColumn, pTable){ - var maxNum = db.cell("select max(" + pColumn + ") from " + pTable); + this.getMaxUniqueNumber = function(pColumn, pTable, pCondition){ + + var condition = ""; + if(pCondition != undefined) + condition += " where " + pCondition; + + var maxNum = db.cell("select max(" + pColumn + ") from " + pTable + condition); return maxNum == "" ? "0" : maxNum; }