Skip to content
Snippets Groups Projects
Commit 15e213e6 authored by Benjamin Ulrich's avatar Benjamin Ulrich :speech_balloon: Committed by Sebastian Pongratz
Browse files

[Projekt: xRM-Sales][TicketNr.: 1075819][Preise korrekt aus Stückliste...

[Projekt: xRM-Sales][TicketNr.: 1075819][Preise korrekt aus Stückliste berechnen-> Bei Neuanlage von Angebotsposten, Belegposten und Preislisten]
parent f813d5d2
No related branches found
No related tags found
No related merge requests found
Showing
with 228 additions and 215 deletions
......@@ -10193,8 +10193,8 @@
<name>REASON</name>
<dbName></dbName>
<primaryKey v="false" />
<columnType v="12" />
<size v="36" />
<columnType v="2005" />
<size v="2147483647" />
<scale v="0" />
<notNull v="false" />
<isUnique v="false" />
......
import("system.vars");
import("system.neon");
//reload the field on save to make sure the offercode is really unique, otherwise the offercode could be the same for two offers created at
//the same time
neon.refresh(["$field.OFFERCODE"]);
\ No newline at end of file
if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW)
{
neon.refresh(["$field.OFFERCODE"]);
}
\ No newline at end of file
......@@ -73,8 +73,9 @@
<contentType>NUMBER</contentType>
<outputFormat>#,##0.00</outputFormat>
<inputFormat>#,##0.00</inputFormat>
<mandatory v="true" />
<valueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/price/valueProcess.js</valueProcess>
<displayValueProcess>%aditoprj%/entity/Offeritem_entity/entityfields/price/displayValueProcess.js</displayValueProcess>
<onValidation>%aditoprj%/entity/Offeritem_entity/entityfields/price/onValidation.js</onValidation>
</entityField>
<entityField>
<name>PRODUCT_ID</name>
......@@ -292,6 +293,10 @@
</entityActionField>
</children>
</entityActionGroup>
<entityField>
<name>itemInsertStatements</name>
<documentation>%aditoprj%/entity/Offeritem_entity/entityfields/iteminsertstatements/documentation.adoc</documentation>
</entityField>
</entityFields>
<recordContainers>
<dbRecordContainer>
......
= itemInsertStatements
Helper field to store the statements for the childitems (statements get built with the correct amounts when changing the product or the quantity).
Statements get stored as stringified object.
And parsed and inserted in the onInsertProcess
\ No newline at end of file
import("system.translate");
import("system.result");
import("system.vars");
var localValue = vars.get("$local.value");
if(!localValue || parseFloat(localValue) <= 0)
{
result.string(translate.text("Price could not be determined"));
}
import("system.neon");
import("system.vars");
import("OfferOrder_lib");
import("Offer_lib");
var pId = vars.get("$local.value");
var uid = vars.get("$field.OFFERITEMID");
var entity = vars.get("$sys.currententityname");
if(pId != "")
if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
{
var uid = vars.get("$field.OFFERITEMID");
var entity = vars.get("$sys.currententityname");
ItemUtils.product_IdOnValueChange(pId, uid, entity);
}
\ No newline at end of file
var oiUtils = new OfferItemUtils(vars.get("$field.OFFER_ID"));
var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
var language = vars.exists("$param.Language_param") ? vars.get("$param.Language_param") : "";
var quantity = vars.get("$field.QUANTITY");
var sumUpTop = false;
var price = vars.get("$field.PRICE");
if(!price)
{
sumUpTop = true;
}
var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.OFFERITEMID"), curr, contactid, language, quantity, true, vars.get("$field.OFFER_ID"), sumUpTop);
neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"]));
if(sumUpTop)//only sum-up this price if there is no valid Price
{
neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]*quantity);
neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]);
}
}
import("AttributeRegistry_basic");
import("system.vars");
import("system.neon");
import("Product_lib");
import("Util_lib");
import("Entity_lib");
import("Attribute_lib");
import("OfferOrder_lib");
import("Offer_lib");
var pid = vars.get("$field.PRODUCT_ID");
var newQuantity = vars.get("local.value");
if(pid != "" && newQuantity != "")
var pId = vars.get("$field.PRODUCT_ID");
if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
{
var uid = vars.get("$field.OFFERITEMID");
var entity = vars.get("$sys.currententityname");
ItemUtils.product_IdOnValueChange(pId, uid, entity);
var oiUtils = new OfferItemUtils(vars.get("$field.OFFER_ID"));
var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
var pricelist = new AttributeRelationQuery(contactid, $AttributeRegistry.pricelist()).getSingleAttributeValue() || "";
var PriceListFilter = { currency: curr, quantity: newQuantity, relationId: contactid, priceList: pricelist };
var language = vars.exists("$param.Language_param") ? vars.get("$param.Language_param") : "";
var quantity = vars.get("$local.value");
var sumUpTop = false;
var price = vars.get("$field.PRICE");
if(!price)
{
sumUpTop = true;
}
var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter);
var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.OFFERITEMID"), curr, contactid, language, quantity, true, vars.get("$field.OFFER_ID"), sumUpTop);
neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"]));
if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null)
if(sumUpTop)//only sum-up this price if there is no valid Price
{
neon.setFieldValue("$field.PRICE", ProductDetails.PriceListToUse.price);
neon.setFieldValue("$field.VAT", ProductDetails.PriceListToUse.vat);
neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]);
neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]);
}
}
//checks if the value is <= 0, if so fallback to 1
var quatity = vars.get("$local.value") ? vars.get("$local.value") : "";
if (parseInt(quatity) <= 0)
{
neon.setFieldValue("local.value", "1");
}
\ No newline at end of file
}
\ No newline at end of file
import("system.eMath");
import("system.db");
import("OfferOrder_lib");
import("system.entities");
import("system.datetime");
import("system.neon");
import("system.vars");
import("system.db");
import("system.util");
import("Offer_lib");
import("Product_lib");
import("Sql_lib");
var rowdata = vars.get("$local.rowdata");
var oid = rowdata["OFFERITEM.OFFER_ID"];
if(oid != "")
{
var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
var discount = vars.exists("$param.Discount_param") ? vars.get("$param.Discount_param"): "";
var quantity = vars.get("$field.QUANTITY");
var oiUtils = new OfferItemUtils(rowdata["OFFERITEM.OFFER_ID"]);
var insertParts = oiUtils.insertPartsList(rowdata["OFFERITEM.PRODUCT_ID"], vars.get("$local.uid"), curr, contactid, vars.get("$param.Language_param"), quantity, true);
oiUtils.reOrgItems();
var calculatedPrices = {};
var priceObj = insertParts["priceObject"];
var treeStructure = insertParts["treeStructure"][rowdata["OFFERITEM.OFFERITEMID"]];
var productsWithSumUpPrices = insertParts["productsWithSumUpPrices"]
var correctOrder = insertParts["insertedItemIds"];
_handleSumUpPricesOfItems(correctOrder, treeStructure, productsWithSumUpPrices, priceObj);
var price = rowdata["OFFERITEM.PRICE"];
if(price === "" || price === undefined || price === null)
var insertStatements = JSON.parse(vars.get("$field.itemInsertStatements"));//insert statements get set by insertPartsList in the onvalueChanges of product_id and quantity
var statements = [];
if(insertStatements)
{
var calcPrice = 0;
var vat = 0;
for(var id in treeStructure)
{
calcPrice = eMath.addDec(priceObj[id]["price"], calcPrice);
if(priceObj[id]["vat"] !== null && priceObj[id]["vat"] !== undefined && priceObj[id]["vat"] > 0)
{
vat = priceObj[id]["vat"];
}
}
var config = entities.createConfigForUpdatingRows()
.entity("Offeritem_entity")
.addParameter("OfferId_param", oid)
.addParameter("IgnoreOnUpdateProcess_param", true)
.uid(rowdata["OFFERITEM.OFFERITEMID"])
.fieldValues({
"PRICE": calcPrice,
"VAT": vat
});
entities.updateRow(config);
statements = statements.concat(insertStatements);
}
//update offer price
var vals = oiUtils.getNetAndVat();
var discountedVals = OfferItemUtils.getDiscountedNet(null, oid, discount);
let config = entities.createConfigForUpdatingRows()
config.entity("Offer_entity");
if(discountedVals)
{
config.fieldValues({
"NET": vals[0],
"VAT": vals[1],
"DISCOUNTED_NET": discountedVals[0],
"DISCOUNTED_VAT": discountedVals[1]
});
insertStatements.push(
newWhere("OFFERITEM.OFFERITEMID", rowdata["OFFERITEM.OFFERITEMID"]).buildUpdateStatement({
"NET": vals[0],
"VAT": vals[1],
"DISCOUNTED_NET": discountedVals[0],
"DISCOUNTED_VAT": discountedVals[1]
})
)
}
else
{
config.fieldValues({
"NET": vals[0],
"VAT": vals[1]
});
}
config.uid(oid);
entities.updateRow(config);
}
//We want to sum up the prices directly under the current item to calculate the price if we don't have an valid price for them
function _handleSumUpPricesOfItems(pOrder, pTreestruct, pSumUpPrices, pPriceObj)
{
var currentStruc = pTreestruct;
var sumUpPrices = pSumUpPrices;
var order = pOrder;
var summandObject = {};
for (var i = order.length; i > -1; i--)//we do this backwards because otherwiese we would run into problems when trying to build the sum (we could have items without an price yet)
{
if(sumUpPrices.hasOwnProperty(order[i]))
{
summandObject[order[i]] = _getNode(pTreestruct, order[i], Object.keys(pTreestruct)[0]);
}
}
for(var offerItem in summandObject)
{
var calcPrice = 0;
var vat = null;
for (var child in summandObject[offerItem])
{
var childPrice;
if(priceObj[child] != undefined)
{
childPrice = priceObj[child]["price"]
}
else if(summandObject[child][child] != undefined)
{
childPrice = priceObj[Object.keys(summandObject[child][child])[0]]["price"]
vat = priceObj[Object.keys(summandObject[child][child])[0]]["vat"]
}
else
{
childPrice = 0;
vat = 0;
}
calcPrice = eMath.addDec(childPrice, calcPrice);
if(!vat)
{
vat = priceObj[child]["vat"];
}
}
calculatedPrices[offerItem] = {};
calculatedPrices[offerItem]["price"] = calcPrice;
calculatedPrices[offerItem]["vat"] = vat;
priceObj[offerItem] = {};
priceObj[offerItem]["price"] = calcPrice;
priceObj[offerItem]["vat"] = vat;
}
//ToDo: Document
function _getNode(pObject, pName, pCurrName){
if(pCurrName == pName)
{
return pObject;
}
else if (pObject != undefined)
{
let x;
let res = null;
for(var obj in pObject)
{
if(res == null)
{
res = _getNode(pObject[obj], pName, obj);
}
else
{
break;
}
}
return res;
}
return null;
insertStatements.push(
newWhere("OFFERITEMID", rowdata["OFFERITEM.OFFERITEMID"])
.buildUpdateStatement({
"NET": vals[0],
"VAT": vals[1]
})
)
}
var config = entities.createConfigForUpdatingRows().entity("Offeritem_entity").addParameter("OfferId_param", oid).addParameter("IgnoreOnUpdateProcess_param", true);
for(var oiId in productsWithSumUpPrices)
{
config.uid(oiId)
.fieldValues({
"PRICE": priceObj[oiId]["price"],
"VAT": priceObj[oiId]["vat"]
});
entities.updateRow(config);
}
db.execute(statements, "Data_alias", 10000000);
}
\ No newline at end of file
......@@ -51,10 +51,10 @@ if(oid != "")
var potentialAsignees = {};
var offerItemsToUpdate = {};
var stop = false;
while(stop == false)
while(stop == false)//we have too loop forall the rows for each row that needs updating, since those are also pontially asignees
{
stop = true;
for(var offeritem in rows)
for(var offeritem in rows)//loop trough all the rows and build offerItemsToUpdate
{
if(!(rows[offeritem]["OFFERITEMID"] in offerItemsToUpdate) &&(rows[offeritem]["ASSIGNEDTO"] == offerItemId || rows[offeritem]["ASSIGNEDTO"] in potentialAsignees))
{
......
import("system.vars");
import("system.neon");
//reload the field on save to make sure the salesordercode is really unique, otherwise the salesordercode could be the same for two salesorders
//created at the same time
neon.refresh(["$field.SALESORDERCODE"]);
\ No newline at end of file
if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW)
{
neon.refresh(["$field.SALESORDERCODE"]);
}
\ No newline at end of file
......@@ -60,6 +60,7 @@
<contentType>NUMBER</contentType>
<outputFormat>#,##0.00</outputFormat>
<inputFormat>#,##0.00</inputFormat>
<mandatory v="true" />
<displayValueProcess>%aditoprj%/entity/Orderitem_entity/entityfields/price/displayValueProcess.js</displayValueProcess>
</entityField>
<entityField>
......@@ -272,6 +273,15 @@
</entityActionField>
</children>
</entityActionGroup>
<entityParameter>
<name>IgnoreOnUpdateProcess_param</name>
<expose v="true" />
<documentation>%aditoprj%/entity/Orderitem_entity/entityfields/ignoreonupdateprocess_param/documentation.adoc</documentation>
</entityParameter>
<entityField>
<name>itemInsertStatements</name>
<documentation>%aditoprj%/entity/Orderitem_entity/entityfields/iteminsertstatements/documentation.adoc</documentation>
</entityField>
</entityFields>
<recordContainers>
<dbRecordContainer>
......
=IgnoreOnUpdateProcess_param
This param only exists because we use writeEntiy in the onUpdateProcess and don't want to execute parts of it again for the updates we trigger for the children.
\ No newline at end of file
= itemInsertStatements
Helper field to store the statements for the childitems (statements get built with the correct amounts when changing the product or the quantity).
Statements get stored as stringified object.
And parsed and inserted in the onInsertProcess
\ No newline at end of file
import("system.neon");
import("system.vars");
import("OfferOrder_lib");
import("Order_lib");
var pId = vars.get("$local.value");
if(pId != "")
if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
{
ItemUtils.product_IdOnValueChange(pId);
}
\ No newline at end of file
var uid = vars.get("$field.SALESORDERITEMID");
var entity = vars.get("$sys.currententityname");
ItemUtils.product_IdOnValueChange(pId, uid, entity);
var oiUtils = new OrderItemUtils(vars.get("$field.SALESORDER_ID"));
var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
var quantity = vars.get("$field.QUANTITY");
var sumUpTop = false;
var price = vars.get("$field.PRICE");
if(!price)
{
sumUpTop = true;
}
var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.SALESORDERITEMID"), curr, contactid, quantity, true, vars.get("$field.SALESORDER_ID"), sumUpTop);
neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"]));
if(sumUpTop)//only sum-up this price if there is no valid Price
{
neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]*quantity);
neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]);
}
}
import("system.vars");
import("system.neon");
import("Product_lib");
import("Util_lib");
import("Entity_lib");
import("OfferOrder_lib");
import("Order_lib");
var pid = vars.get("$field.PRODUCT_ID");
var newQuantity = vars.get("local.value");
if(pid != "" && newQuantity != "")
var pId = vars.get("$field.PRODUCT_ID");
if(pId != "" && vars.get("$sys.recordstate") == neon.OPERATINGSTATE_NEW)
{
var uid = vars.get("$field.SALESORDERITEMID");
var entity = vars.get("$sys.currententityname");
ItemUtils.product_IdOnValueChange(pId, uid, entity);
var oiUtils = new OrderItemUtils(vars.get("$field.SALESORDER_ID"));
var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
var quantity = vars.get("$local.value");
var sumUpTop = false;
var price = vars.get("$field.PRICE");
if(!price)
{
sumUpTop = true;
}
var PriceListFilter = { currency: curr, quantity: newQuantity, relationId: contactid };
var ProductDetails = ProductUtils.getProductDetails(pid, PriceListFilter);
var partsListObject = oiUtils.insertPartsList(pId, vars.get("$field.SALESORDERITEMID"), curr, contactid, quantity, true, vars.get("$field.SALESORDER_ID"), sumUpTop);
neon.setFieldValue("$field.itemInsertStatements", JSON.stringify(partsListObject["partsList"]));
if(ProductDetails.productId != undefined && ProductDetails.PriceListToUse != null)
if(sumUpTop)//only sum-up this price if there is no valid Price
{
vars.set("$field.PRICE", ProductDetails.PriceListToUse.price);
vars.set("$field.VAT", ProductDetails.PriceListToUse.vat);
neon.setFieldValue("$field.PRICE", partsListObject["topProductInfo"]["price"]);
neon.setFieldValue("$field.VAT", partsListObject["topProductInfo"]["vat"]);
}
}
\ No newline at end of file
import("system.db");
import("OfferOrder_lib");
import("system.entities");
import("system.datetime");
import("system.neon");
import("system.vars");
import("system.db");
import("system.util");
import("Order_lib");
import("Product_lib");
import("Sql_lib");
var rowdata = vars.get("$local.rowdata");
var oid = rowdata["SALESORDERITEM.SALESORDER_ID"];
if(oid != "")
{
var curr = vars.exists("$param.Currency_param") ? vars.get("$param.Currency_param") : "";
var contactid = vars.exists("$param.ContactId_param") ? vars.get("$param.ContactId_param") : "";
var discount = vars.exists("$param.Discount_param") ? vars.get("$param.Discount_param"): "";
var oiUtils = new OrderItemUtils(oid);
oiUtils.insertPartsList(rowdata["SALESORDERITEM.PRODUCT_ID"], vars.get("$local.uid"), curr, contactid, vars.get("$param.Language_param"));
oiUtils.reOrgItems();
var insertStatements = JSON.parse(vars.get("$field.itemInsertStatements"));//insert statements get set by insertPartsList in the onvalueChanges of product_id and quantity
if(insertStatements)
{
db.inserts(insertStatements);
}
//update order price
var vals = oiUtils.getNetAndVat();
......@@ -42,7 +43,6 @@ if(oid != "")
"NET": vals[0],
"VAT": vals[1]
});
}
config.uid(oid);
entities.updateRow(config);
......
......@@ -33,4 +33,44 @@ if(oid != "")
}
config.uid(oid);
entities.updateRow(config);
//this process get's executed for every child of this offerItem since we use writeEntiy, so we use the param to make sure we don't execute it for the children
if(vars.getString("$param.IgnoreOnUpdateProcess_param") != "true")
{
var newQuanitity = parseFloat(vars.get("$field.QUANTITY"));
var oldQuantity = parseFloat(vars.get("$local.initialRowdata")["SALESORDERITEM.QUANTITY"]);
var offerItemId = vars.get("$field.SALESORDERITEMID");
if(newQuanitity != oldQuantity) //quantity changed -> change quantities of the childitems accordingly
{
var multiplier = newQuanitity/oldQuantity;
var loadConfig = entities.createConfigForLoadingRows().entity("Orderitem_entity").addParameter("OrderId_param", oid).fields(["SALESORDERITEMID", "ASSIGNEDTO", "PRODUCT_ID", "QUANTITY"])
var rows = entities.getRows(loadConfig);
var potentialAsignees = {};
var offerItemsToUpdate = {};
var stop = false;
while(stop == false)//we have too loop forall the rows for each row that needs updating, since those are also pontially asignees
{
stop = true;
for(var offeritem in rows)//loop trough all the rows and build offerItemsToUpdate
{
if(!(rows[offeritem]["SALESORDERITEMID"] in offerItemsToUpdate) &&(rows[offeritem]["ASSIGNEDTO"] == offerItemId || rows[offeritem]["ASSIGNEDTO"] in potentialAsignees))
{
offerItemsToUpdate[rows[offeritem]["SALESORDERITEMID"]] = parseInt(rows[offeritem]["QUANTITY"])*multiplier;
potentialAsignees[rows[offeritem]["SALESORDERITEMID"]] = "";
stop = false;
}
}
}
var updateConfig = entities.createConfigForUpdatingRows().entity("Orderitem_entity").addParameter("OrderId_param", oid).addParameter("IgnoreOnUpdateProcess_param", true);
for(var object_Id in offerItemsToUpdate)
{
entities.updateRow(updateConfig.fieldValues({"QUANTITY": offerItemsToUpdate[object_Id]}).uid(object_Id))
}
}
}
}
\ No newline at end of file
......@@ -20,6 +20,7 @@
<dropDownProcess>%aditoprj%/entity/Productprice_entity/entityfields/buysell/dropDownProcess.js</dropDownProcess>
<stateProcess>%aditoprj%/entity/Productprice_entity/entityfields/buysell/stateProcess.js</stateProcess>
<valueProcess>%aditoprj%/entity/Productprice_entity/entityfields/buysell/valueProcess.js</valueProcess>
<onValueChange>%aditoprj%/entity/Productprice_entity/entityfields/buysell/onValueChange.js</onValueChange>
</entityField>
<entityField>
<name>CURRENCY</name>
......@@ -112,6 +113,7 @@
<titleProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/titleProcess.js</titleProcess>
<valueProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/valueProcess.js</valueProcess>
<displayValueProcess>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/displayValueProcess.js</displayValueProcess>
<onValueChange>%aditoprj%/entity/Productprice_entity/entityfields/pricelist/onValueChange.js</onValueChange>
</entityField>
<entityParameter>
<name>ProductId_param</name>
......
import("system.neon");
import("Product_lib");
import("system.vars");
if(vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_NEW || vars.get("$sys.operatingstate") == neon.OPERATINGSTATE_EDIT)
{
var productId = vars.get("$field.PRODUCT_ID");
ProductUtils.presetPriceAndVat(vars.get("$field.PRODUCT_ID"), vars.get("$field.VAT"),vars.get("$field.PRICELIST") , vars.get("$this.value"));
}
\ No newline at end of file
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