use of org.apache.ofbiz.service.GenericServiceException in project ofbiz-framework by apache.
the class InventoryServices method prepareInventoryTransfer.
public static Map<String, Object> prepareInventoryTransfer(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
String inventoryItemId = (String) context.get("inventoryItemId");
BigDecimal xferQty = (BigDecimal) context.get("xferQty");
GenericValue inventoryItem = null;
GenericValue newItem = null;
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
try {
inventoryItem = EntityQuery.use(delegator).from("InventoryItem").where("inventoryItemId", inventoryItemId).queryOne();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductNotFindInventoryItemWithId", locale) + inventoryItemId);
}
if (inventoryItem == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductNotFindInventoryItemWithId", locale) + inventoryItemId);
}
try {
Map<String, Object> results = ServiceUtil.returnSuccess();
String inventoryType = inventoryItem.getString("inventoryItemTypeId");
if ("NON_SERIAL_INV_ITEM".equals(inventoryType)) {
BigDecimal atp = inventoryItem.getBigDecimal("availableToPromiseTotal");
BigDecimal qoh = inventoryItem.getBigDecimal("quantityOnHandTotal");
if (atp == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemATPNotAvailable", UtilMisc.toMap("inventoryItemId", inventoryItem.getString("inventoryItemId")), locale));
}
if (qoh == null) {
qoh = atp;
}
// first make sure we have enough to cover the request transfer amount
if (xferQty.compareTo(atp) > 0) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemATPIsNotSufficient", UtilMisc.toMap("inventoryItemId", inventoryItem.getString("inventoryItemId"), "atp", atp, "xferQty", xferQty), locale));
}
// however, if atp < qoh && atp == xferQty, then we still need to split; oh, but no need to check atp == xferQty in the second part because if it isn't greater and isn't less, then it is equal
if (xferQty.compareTo(atp) < 0 || atp.compareTo(qoh) < 0) {
BigDecimal negXferQty = xferQty.negate();
// NOTE: new inventory items should always be created calling the
// createInventoryItem service because in this way we are sure
// that all the relevant fields are filled with default values.
// However, the code here should work fine because all the values
// for the new inventory item are inerited from the existing item.
newItem = GenericValue.create(inventoryItem);
newItem.set("availableToPromiseTotal", BigDecimal.ZERO);
newItem.set("quantityOnHandTotal", BigDecimal.ZERO);
delegator.createSetNextSeqId(newItem);
results.put("inventoryItemId", newItem.get("inventoryItemId"));
// TODO: how do we get this here: "inventoryTransferId", inventoryTransferId
Map<String, Object> createNewDetailMap = UtilMisc.toMap("availableToPromiseDiff", xferQty, "quantityOnHandDiff", xferQty, "accountingQuantityDiff", xferQty, "inventoryItemId", newItem.get("inventoryItemId"), "userLogin", userLogin);
Map<String, Object> createUpdateDetailMap = UtilMisc.toMap("availableToPromiseDiff", negXferQty, "quantityOnHandDiff", negXferQty, "accountingQuantityDiff", negXferQty, "inventoryItemId", inventoryItem.get("inventoryItemId"), "userLogin", userLogin);
try {
Map<String, Object> resultNew = dctx.getDispatcher().runSync("createInventoryItemDetail", createNewDetailMap);
if (ServiceUtil.isError(resultNew)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemDetailCreateProblem", UtilMisc.toMap("errorString", ""), locale), null, null, resultNew);
}
Map<String, Object> resultUpdate = dctx.getDispatcher().runSync("createInventoryItemDetail", createUpdateDetailMap);
if (ServiceUtil.isError(resultUpdate)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemDetailCreateProblem", UtilMisc.toMap("errorString", ""), locale), null, null, resultUpdate);
}
} catch (GenericServiceException e1) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemDetailCreateProblem", UtilMisc.toMap("errorString", e1.getMessage()), locale));
}
} else {
results.put("inventoryItemId", inventoryItem.get("inventoryItemId"));
}
} else if ("SERIALIZED_INV_ITEM".equals(inventoryType)) {
if (!"INV_AVAILABLE".equals(inventoryItem.getString("statusId"))) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductSerializedInventoryNotAvailable", locale));
}
}
// if newItem is not null, it is the item to be moved, otherwise the original inventoryItem is the one to be moved
if ("NON_SERIAL_INV_ITEM".equals(inventoryType)) {
// set the transfered inventory item's atp to 0 and the qoh to the xferQty; at this point atp and qoh will always be the same, so we can safely zero the atp for now
GenericValue inventoryItemToClear = newItem == null ? inventoryItem : newItem;
inventoryItemToClear.refresh();
BigDecimal atp = inventoryItemToClear.get("availableToPromiseTotal") == null ? BigDecimal.ZERO : inventoryItemToClear.getBigDecimal("availableToPromiseTotal");
if (atp.compareTo(BigDecimal.ZERO) != 0) {
Map<String, Object> createDetailMap = UtilMisc.toMap("availableToPromiseDiff", atp.negate(), "inventoryItemId", inventoryItemToClear.get("inventoryItemId"), "userLogin", userLogin);
try {
Map<String, Object> result = dctx.getDispatcher().runSync("createInventoryItemDetail", createDetailMap);
if (ServiceUtil.isError(result)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemDetailCreateProblem", UtilMisc.toMap("errorString", ""), locale), null, null, result);
}
} catch (GenericServiceException e1) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemDetailCreateProblem", UtilMisc.toMap("errorString", e1.getMessage()), locale));
}
}
} else if ("SERIALIZED_INV_ITEM".equals(inventoryType)) {
// set the status to avoid re-moving or something
if (newItem != null) {
newItem.refresh();
newItem.set("statusId", "INV_BEING_TRANSFERED");
newItem.store();
results.put("inventoryItemId", newItem.get("inventoryItemId"));
} else {
inventoryItem.refresh();
inventoryItem.set("statusId", "INV_BEING_TRANSFERED");
inventoryItem.store();
results.put("inventoryItemId", inventoryItem.get("inventoryItemId"));
}
}
return results;
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemStoreProblem", UtilMisc.toMap("errorString", e.getMessage()), locale));
}
}
use of org.apache.ofbiz.service.GenericServiceException in project ofbiz-framework by apache.
the class InventoryServices method checkInventoryAvailability.
/**
* In spite of the generic name this does the very specific task of checking availability of all back-ordered items and sends notices, etc
*/
public static Map<String, Object> checkInventoryAvailability(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
LocalDispatcher dispatcher = dctx.getDispatcher();
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
Map<String, Map<String, Timestamp>> ordersToUpdate = new HashMap<>();
Map<String, Map<String, Timestamp>> ordersToCancel = new HashMap<>();
// find all inventory items w/ a negative ATP
List<GenericValue> inventoryItems = null;
try {
inventoryItems = EntityQuery.use(delegator).from("InventoryItem").where(EntityCondition.makeCondition("availableToPromiseTotal", EntityOperator.LESS_THAN, BigDecimal.ZERO)).queryList();
} catch (GenericEntityException e) {
Debug.logError(e, "Trouble getting inventory items", module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrieveInventoryItem", locale));
}
if (inventoryItems == null) {
Debug.logInfo("No items out of stock; no backorders to worry about", module);
return ServiceUtil.returnSuccess();
}
Debug.logInfo("OOS Inventory Items: " + inventoryItems.size(), module);
for (GenericValue inventoryItem : inventoryItems) {
// get the incomming shipment information for the item
List<GenericValue> shipmentAndItems = null;
try {
List<EntityExpr> exprs = new ArrayList<>();
exprs.add(EntityCondition.makeCondition("productId", EntityOperator.EQUALS, inventoryItem.get("productId")));
exprs.add(EntityCondition.makeCondition("destinationFacilityId", EntityOperator.EQUALS, inventoryItem.get("facilityId")));
exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "SHIPMENT_DELIVERED"));
exprs.add(EntityCondition.makeCondition("statusId", EntityOperator.NOT_EQUAL, "SHIPMENT_CANCELLED"));
shipmentAndItems = EntityQuery.use(delegator).from("ShipmentAndItem").where(EntityCondition.makeCondition(exprs, EntityOperator.AND)).orderBy("estimatedArrivalDate").queryList();
} catch (GenericEntityException e) {
Debug.logError(e, "Problem getting ShipmentAndItem records", module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrieveShipmentAndItem", locale));
}
// get the reservations in order of newest first
List<GenericValue> reservations = null;
try {
reservations = inventoryItem.getRelated("OrderItemShipGrpInvRes", null, UtilMisc.toList("-reservedDatetime"), false);
} catch (GenericEntityException e) {
Debug.logError(e, "Problem getting related reservations", module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrieveRelativeReservation", locale));
}
if (reservations == null) {
Debug.logWarning("No outstanding reservations for this inventory item, why is it negative then?", module);
continue;
}
Debug.logInfo("Reservations for item: " + reservations.size(), module);
// available at the time of order
BigDecimal availableBeforeReserved = inventoryItem.getBigDecimal("availableToPromiseTotal");
// go through all the reservations in order
for (GenericValue reservation : reservations) {
String orderId = reservation.getString("orderId");
String orderItemSeqId = reservation.getString("orderItemSeqId");
Timestamp promisedDate = reservation.getTimestamp("promisedDatetime");
Timestamp currentPromiseDate = reservation.getTimestamp("currentPromisedDate");
Timestamp actualPromiseDate = currentPromiseDate;
if (actualPromiseDate == null) {
if (promisedDate != null) {
actualPromiseDate = promisedDate;
} else {
// fall back if there is no promised date stored
actualPromiseDate = reservation.getTimestamp("reservedDatetime");
}
}
Debug.logInfo("Promised Date: " + actualPromiseDate, module);
// find the next possible ship date
Timestamp nextShipDate = null;
BigDecimal availableAtTime = BigDecimal.ZERO;
for (GenericValue shipmentItem : shipmentAndItems) {
availableAtTime = availableAtTime.add(shipmentItem.getBigDecimal("quantity"));
if (availableAtTime.compareTo(availableBeforeReserved) >= 0) {
nextShipDate = shipmentItem.getTimestamp("estimatedArrivalDate");
break;
}
}
Debug.logInfo("Next Ship Date: " + nextShipDate, module);
// create a modified promise date (promise date - 1 day)
Calendar pCal = Calendar.getInstance();
pCal.setTimeInMillis(actualPromiseDate.getTime());
pCal.add(Calendar.DAY_OF_YEAR, -1);
Timestamp modifiedPromisedDate = new Timestamp(pCal.getTimeInMillis());
Timestamp now = UtilDateTime.nowTimestamp();
Debug.logInfo("Promised Date + 1: " + modifiedPromisedDate, module);
Debug.logInfo("Now: " + now, module);
// check the promised date vs the next ship date
if (nextShipDate == null || nextShipDate.after(actualPromiseDate)) {
if (nextShipDate == null && modifiedPromisedDate.after(now)) {
// do nothing; we are okay to assume it will be shipped on time
Debug.logInfo("No ship date known yet, but promised date hasn't approached, assuming it will be here on time", module);
} else {
// we cannot ship by the promised date; need to notify the customer
Debug.logInfo("We won't ship on time, getting notification info", module);
Map<String, Timestamp> notifyItems = ordersToUpdate.get(orderId);
if (notifyItems == null) {
notifyItems = new HashMap<>();
}
notifyItems.put(orderItemSeqId, nextShipDate);
ordersToUpdate.put(orderId, notifyItems);
// need to know if nextShipDate is more then 30 days after promised
Calendar sCal = Calendar.getInstance();
sCal.setTimeInMillis(actualPromiseDate.getTime());
sCal.add(Calendar.DAY_OF_YEAR, 30);
Timestamp farPastPromised = new Timestamp(sCal.getTimeInMillis());
// check to see if this is >30 days or second run, if so flag to cancel
boolean needToCancel = false;
if (nextShipDate == null || nextShipDate.after(farPastPromised)) {
// we cannot ship until >30 days after promised; using cancel rule
Debug.logInfo("Ship date is >30 past the promised date", module);
needToCancel = true;
} else if (currentPromiseDate != null && actualPromiseDate.equals(currentPromiseDate)) {
// this is the second notification; using cancel rule
needToCancel = true;
}
// add the info to the cancel map if we need to schedule a cancel
if (needToCancel) {
// queue the item to be cancelled
Debug.logInfo("Flagging the item to auto-cancel", module);
Map<String, Timestamp> cancelItems = ordersToCancel.get(orderId);
if (cancelItems == null) {
cancelItems = new HashMap<>();
}
cancelItems.put(orderItemSeqId, farPastPromised);
ordersToCancel.put(orderId, cancelItems);
}
// store the updated promiseDate as the nextShipDate
try {
reservation.set("currentPromisedDate", nextShipDate);
reservation.store();
} catch (GenericEntityException e) {
Debug.logError(e, "Problem storing reservation : " + reservation, module);
}
}
}
// subtract our qty from reserved to get the next value
availableBeforeReserved = availableBeforeReserved.subtract(reservation.getBigDecimal("quantity"));
}
}
// all items to cancel will also be in the notify list so start with that
List<String> ordersToNotify = new LinkedList<>();
for (Map.Entry<String, Map<String, Timestamp>> entry : ordersToUpdate.entrySet()) {
String orderId = entry.getKey();
Map<String, Timestamp> backOrderedItems = entry.getValue();
Map<String, Timestamp> cancelItems = ordersToCancel.get(orderId);
boolean cancelAll = false;
Timestamp cancelAllTime = null;
List<GenericValue> orderItemShipGroups = null;
try {
orderItemShipGroups = EntityQuery.use(delegator).from("OrderItemShipGroup").where("orderId", orderId).queryList();
} catch (GenericEntityException e) {
Debug.logError(e, "Cannot get OrderItemShipGroups from orderId" + orderId, module);
}
for (GenericValue orderItemShipGroup : orderItemShipGroups) {
List<GenericValue> orderItems = new LinkedList<>();
List<GenericValue> orderItemShipGroupAssoc = null;
try {
orderItemShipGroupAssoc = EntityQuery.use(delegator).from("OrderItemShipGroupAssoc").where("shipGroupSeqId", orderItemShipGroup.get("shipGroupSeqId"), "orderId", orderId).queryList();
for (GenericValue assoc : orderItemShipGroupAssoc) {
GenericValue orderItem = assoc.getRelatedOne("OrderItem", false);
if (orderItem != null) {
orderItems.add(orderItem);
}
}
} catch (GenericEntityException e) {
Debug.logError(e, "Problem fetching OrderItemShipGroupAssoc", module);
}
/* Check the split preference. */
boolean maySplit = false;
if (orderItemShipGroup.get("maySplit") != null) {
maySplit = orderItemShipGroup.getBoolean("maySplit").booleanValue();
}
/* Figure out if we must cancel all items. */
if (!maySplit && cancelItems != null) {
cancelAll = true;
Set<String> cancelSet = cancelItems.keySet();
cancelAllTime = cancelItems.get(cancelSet.iterator().next());
}
// if there are none to cancel just create an empty map
if (cancelItems == null) {
cancelItems = new HashMap<>();
}
List<GenericValue> toBeStored = new LinkedList<>();
for (GenericValue orderItem : orderItems) {
String orderItemSeqId = orderItem.getString("orderItemSeqId");
Timestamp shipDate = backOrderedItems.get(orderItemSeqId);
Timestamp cancelDate = cancelItems.get(orderItemSeqId);
Timestamp currentCancelDate = orderItem.getTimestamp("autoCancelDate");
Debug.logInfo("OI: " + orderId + " SEQID: " + orderItemSeqId + " cancelAll: " + cancelAll + " cancelDate: " + cancelDate, module);
if (backOrderedItems.containsKey(orderItemSeqId)) {
orderItem.set("estimatedShipDate", shipDate);
if (currentCancelDate == null) {
if (cancelAll || cancelDate != null) {
if (orderItem.get("dontCancelSetUserLogin") == null && orderItem.get("dontCancelSetDate") == null) {
if (cancelAllTime != null) {
orderItem.set("autoCancelDate", cancelAllTime);
} else {
orderItem.set("autoCancelDate", cancelDate);
}
}
}
// only notify orders which have not already sent the final notice
ordersToNotify.add(orderId);
}
toBeStored.add(orderItem);
}
if (toBeStored.size() > 0) {
try {
delegator.storeAll(toBeStored);
} catch (GenericEntityException e) {
Debug.logError(e, "Problem storing order items", module);
}
}
}
}
}
// send off a notification for each order
for (String orderId : ordersToNotify) {
try {
dispatcher.runAsync("sendOrderBackorderNotification", UtilMisc.<String, Object>toMap("orderId", orderId, "userLogin", userLogin));
} catch (GenericServiceException e) {
Debug.logError(e, "Problems sending off the notification", module);
continue;
}
}
return ServiceUtil.returnSuccess();
}
use of org.apache.ofbiz.service.GenericServiceException in project ofbiz-framework by apache.
the class InventoryServices method cancelInventoryTransfer.
public static Map<String, Object> cancelInventoryTransfer(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
String inventoryTransferId = (String) context.get("inventoryTransferId");
GenericValue inventoryTransfer = null;
GenericValue inventoryItem = null;
GenericValue userLogin = (GenericValue) context.get("userLogin");
Locale locale = (Locale) context.get("locale");
try {
inventoryTransfer = EntityQuery.use(delegator).from("InventoryTransfer").where("inventoryTransferId", inventoryTransferId).queryOne();
if (UtilValidate.isEmpty(inventoryTransfer)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemTransferNotFound", UtilMisc.toMap("inventoryTransferId", inventoryTransferId), locale));
}
inventoryItem = inventoryTransfer.getRelatedOne("InventoryItem", false);
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemLookupProblem", UtilMisc.toMap("errorString", e.getMessage()), locale));
}
if (inventoryItem == null) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemLookupProblem", UtilMisc.toMap("errorString", ""), locale));
}
String inventoryType = inventoryItem.getString("inventoryItemTypeId");
// re-set the fields on the item
if ("NON_SERIAL_INV_ITEM".equals(inventoryType)) {
// add an adjusting InventoryItemDetail so set ATP back to QOH: ATP = ATP + (QOH - ATP), diff = QOH - ATP
BigDecimal atp = inventoryItem.get("availableToPromiseTotal") == null ? BigDecimal.ZERO : inventoryItem.getBigDecimal("availableToPromiseTotal");
BigDecimal qoh = inventoryItem.get("quantityOnHandTotal") == null ? BigDecimal.ZERO : inventoryItem.getBigDecimal("quantityOnHandTotal");
Map<String, Object> createDetailMap = UtilMisc.toMap("availableToPromiseDiff", qoh.subtract(atp), "inventoryItemId", inventoryItem.get("inventoryItemId"), "userLogin", userLogin);
try {
Map<String, Object> result = dctx.getDispatcher().runSync("createInventoryItemDetail", createDetailMap);
if (ServiceUtil.isError(result)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemDetailCreateProblem", UtilMisc.toMap("errorString", ""), locale), null, null, result);
}
} catch (GenericServiceException e1) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemDetailCreateProblem", UtilMisc.toMap("errorString", e1.getMessage()), locale));
}
} else if ("SERIALIZED_INV_ITEM".equals(inventoryType)) {
inventoryItem.set("statusId", "INV_AVAILABLE");
// store the entity
try {
inventoryItem.store();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemStoreProblem", UtilMisc.toMap("errorString", e.getMessage()), locale));
}
}
// set the inventory transfer record to complete
inventoryTransfer.set("statusId", "IXF_CANCELLED");
// store the entities
try {
inventoryTransfer.store();
} catch (GenericEntityException e) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductInventoryItemStoreProblem", UtilMisc.toMap("errorString", e.getMessage()), locale));
}
return ServiceUtil.returnSuccess();
}
use of org.apache.ofbiz.service.GenericServiceException in project ofbiz-framework by apache.
the class PriceServices method addGeneralResults.
public static Map<String, Object> addGeneralResults(Map<String, Object> result, GenericValue competitivePriceValue, GenericValue specialPromoPriceValue, GenericValue productStore, String checkIncludeVat, String currencyUomId, String productId, BigDecimal quantity, String partyId, LocalDispatcher dispatcher, Locale locale) {
result.put("competitivePrice", competitivePriceValue != null ? competitivePriceValue.getBigDecimal("price") : null);
result.put("specialPromoPrice", specialPromoPriceValue != null ? specialPromoPriceValue.getBigDecimal("price") : null);
result.put("currencyUsed", currencyUomId);
// okay, now we have the calculated price, see if we should add in tax and if so do it
if ("Y".equals(checkIncludeVat) && productStore != null && "Y".equals(productStore.getString("showPricesWithVatTax"))) {
Map<String, Object> calcTaxForDisplayContext = UtilMisc.toMap("productStoreId", productStore.get("productStoreId"), "productId", productId, "quantity", quantity, "basePrice", (BigDecimal) result.get("price"));
if (UtilValidate.isNotEmpty(partyId)) {
calcTaxForDisplayContext.put("billToPartyId", partyId);
}
try {
Map<String, Object> calcTaxForDisplayResult = dispatcher.runSync("calcTaxForDisplay", calcTaxForDisplayContext);
if (ServiceUtil.isError(calcTaxForDisplayResult)) {
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotCalculateVatTax", locale), null, null, calcTaxForDisplayResult);
}
// taxTotal, taxPercentage, priceWithTax
result.put("price", calcTaxForDisplayResult.get("priceWithTax"));
// based on the taxPercentage calculate the other amounts, including: listPrice, defaultPrice, averageCost, promoPrice, competitivePrice
BigDecimal taxPercentage = (BigDecimal) calcTaxForDisplayResult.get("taxPercentage");
BigDecimal taxMultiplier = ONE_BASE.add(taxPercentage.divide(PERCENT_SCALE, taxCalcScale));
if (result.get("listPrice") != null) {
result.put("listPrice", ((BigDecimal) result.get("listPrice")).multiply(taxMultiplier).setScale(taxFinalScale, taxRounding));
}
if (result.get("defaultPrice") != null) {
result.put("defaultPrice", ((BigDecimal) result.get("defaultPrice")).multiply(taxMultiplier).setScale(taxFinalScale, taxRounding));
}
if (result.get("averageCost") != null) {
result.put("averageCost", ((BigDecimal) result.get("averageCost")).multiply(taxMultiplier).setScale(taxFinalScale, taxRounding));
}
if (result.get("promoPrice") != null) {
result.put("promoPrice", ((BigDecimal) result.get("promoPrice")).multiply(taxMultiplier).setScale(taxFinalScale, taxRounding));
}
if (result.get("competitivePrice") != null) {
result.put("competitivePrice", ((BigDecimal) result.get("competitivePrice")).multiply(taxMultiplier).setScale(taxFinalScale, taxRounding));
}
} catch (GenericServiceException e) {
Debug.logError(e, "Error calculating VAT tax (with calcTaxForDisplay service): " + e.toString(), module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotCalculateVatTax", locale));
}
}
return null;
}
use of org.apache.ofbiz.service.GenericServiceException in project ofbiz-framework by apache.
the class PriceServices method calculateProductPrice.
/**
* <p>Calculates the price of a product from pricing rules given the following input, and of course access to the database:</p>
* <ul>
* <li>productId
* <li>partyId
* <li>prodCatalogId
* <li>webSiteId
* <li>productStoreId
* <li>productStoreGroupId
* <li>agreementId
* <li>quantity
* <li>currencyUomId
* <li>checkIncludeVat
* </ul>
*/
public static Map<String, Object> calculateProductPrice(DispatchContext dctx, Map<String, ? extends Object> context) {
Delegator delegator = dctx.getDelegator();
LocalDispatcher dispatcher = dctx.getDispatcher();
Map<String, Object> result = new HashMap<String, Object>();
Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
GenericValue product = (GenericValue) context.get("product");
String productId = product.getString("productId");
String prodCatalogId = (String) context.get("prodCatalogId");
String webSiteId = (String) context.get("webSiteId");
String checkIncludeVat = (String) context.get("checkIncludeVat");
String surveyResponseId = (String) context.get("surveyResponseId");
Map<String, Object> customAttributes = UtilGenerics.checkMap(context.get("customAttributes"));
String findAllQuantityPricesStr = (String) context.get("findAllQuantityPrices");
boolean findAllQuantityPrices = "Y".equals(findAllQuantityPricesStr);
boolean optimizeForLargeRuleSet = "Y".equals(context.get("optimizeForLargeRuleSet"));
String agreementId = (String) context.get("agreementId");
String productStoreId = (String) context.get("productStoreId");
String productStoreGroupId = (String) context.get("productStoreGroupId");
Locale locale = (Locale) context.get("locale");
GenericValue productStore = null;
try {
// we have a productStoreId, if the corresponding ProductStore.primaryStoreGroupId is not empty, use that
productStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).cache().queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, "Error getting product store info from the database while calculating price" + e.toString(), module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrieveProductStore", UtilMisc.toMap("errorString", e.toString()), locale));
}
if (UtilValidate.isEmpty(productStoreGroupId)) {
if (productStore != null) {
try {
if (UtilValidate.isNotEmpty(productStore.getString("primaryStoreGroupId"))) {
productStoreGroupId = productStore.getString("primaryStoreGroupId");
} else {
// no ProductStore.primaryStoreGroupId, try ProductStoreGroupMember
List<GenericValue> productStoreGroupMemberList = EntityQuery.use(delegator).from("ProductStoreGroupMember").where("productStoreId", productStoreId).orderBy("sequenceNum", "-fromDate").cache(true).queryList();
productStoreGroupMemberList = EntityUtil.filterByDate(productStoreGroupMemberList, true);
if (productStoreGroupMemberList.size() > 0) {
GenericValue productStoreGroupMember = EntityUtil.getFirst(productStoreGroupMemberList);
productStoreGroupId = productStoreGroupMember.getString("productStoreGroupId");
}
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error getting product store info from the database while calculating price" + e.toString(), module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrieveProductStore", UtilMisc.toMap("errorString", e.toString()), locale));
}
}
// still empty, default to _NA_
if (UtilValidate.isEmpty(productStoreGroupId)) {
productStoreGroupId = "_NA_";
}
}
// if currencyUomId is null get from properties file, if nothing there assume USD (USD: American Dollar) for now
String currencyDefaultUomId = (String) context.get("currencyUomId");
String currencyUomIdTo = (String) context.get("currencyUomIdTo");
if (UtilValidate.isEmpty(currencyDefaultUomId)) {
if (productStore != null && UtilValidate.isNotEmpty(productStore.getString("defaultCurrencyUomId"))) {
currencyDefaultUomId = productStore.getString("defaultCurrencyUomId");
} else {
currencyDefaultUomId = EntityUtilProperties.getPropertyValue("general", "currency.uom.id.default", "USD", delegator);
}
}
// productPricePurposeId is null assume "PURCHASE", which is equivalent to what prices were before the purpose concept
String productPricePurposeId = (String) context.get("productPricePurposeId");
if (UtilValidate.isEmpty(productPricePurposeId)) {
productPricePurposeId = "PURCHASE";
}
// termUomId, for things like recurring prices specifies the term (time/frequency measure for example) of the recurrence
// if this is empty it will simply not be used to constrain the selection
String termUomId = (String) context.get("termUomId");
// if this product is variant, find the virtual product and apply checks to it as well
String virtualProductId = null;
if ("Y".equals(product.getString("isVariant"))) {
try {
virtualProductId = ProductWorker.getVariantVirtualId(product);
} catch (GenericEntityException e) {
Debug.logError(e, "Error getting virtual product id from the database while calculating price" + e.toString(), module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrieveVirtualProductId", UtilMisc.toMap("errorString", e.toString()), locale));
}
}
// get prices for virtual product if one is found; get all ProductPrice entities for this productId and currencyUomId
List<GenericValue> virtualProductPrices = null;
if (virtualProductId != null) {
try {
virtualProductPrices = EntityQuery.use(delegator).from("ProductPrice").where("productId", virtualProductId, "currencyUomId", currencyDefaultUomId, "productStoreGroupId", productStoreGroupId).orderBy("-fromDate").cache(true).queryList();
} catch (GenericEntityException e) {
Debug.logError(e, "An error occurred while getting the product prices", module);
}
virtualProductPrices = EntityUtil.filterByDate(virtualProductPrices, true);
}
// NOTE: partyId CAN be null
String partyId = (String) context.get("partyId");
if (UtilValidate.isEmpty(partyId) && context.get("userLogin") != null) {
GenericValue userLogin = (GenericValue) context.get("userLogin");
partyId = userLogin.getString("partyId");
}
// check for auto-userlogin for price rules
if (UtilValidate.isEmpty(partyId) && context.get("autoUserLogin") != null) {
GenericValue userLogin = (GenericValue) context.get("autoUserLogin");
partyId = userLogin.getString("partyId");
}
BigDecimal quantity = (BigDecimal) context.get("quantity");
if (quantity == null)
quantity = BigDecimal.ONE;
BigDecimal amount = (BigDecimal) context.get("amount");
List<EntityCondition> productPriceEcList = new LinkedList<EntityCondition>();
productPriceEcList.add(EntityCondition.makeCondition("productId", EntityOperator.EQUALS, productId));
// this funny statement is for backward compatibility purposes; the productPricePurposeId is a new pk field on the ProductPrice entity and in order databases may not be populated, until the pk is updated and such; this will ease the transition somewhat
if ("PURCHASE".equals(productPricePurposeId)) {
productPriceEcList.add(EntityCondition.makeCondition(EntityCondition.makeCondition("productPricePurposeId", EntityOperator.EQUALS, productPricePurposeId), EntityOperator.OR, EntityCondition.makeCondition("productPricePurposeId", EntityOperator.EQUALS, null)));
} else {
productPriceEcList.add(EntityCondition.makeCondition("productPricePurposeId", EntityOperator.EQUALS, productPricePurposeId));
}
productPriceEcList.add(EntityCondition.makeCondition("currencyUomId", EntityOperator.EQUALS, currencyDefaultUomId));
productPriceEcList.add(EntityCondition.makeCondition("productStoreGroupId", EntityOperator.EQUALS, productStoreGroupId));
if (UtilValidate.isNotEmpty(termUomId)) {
productPriceEcList.add(EntityCondition.makeCondition("termUomId", EntityOperator.EQUALS, termUomId));
}
EntityCondition productPriceEc = EntityCondition.makeCondition(productPriceEcList, EntityOperator.AND);
// for prices, get all ProductPrice entities for this productId and currencyUomId
List<GenericValue> productPrices = null;
try {
productPrices = EntityQuery.use(delegator).from("ProductPrice").where(productPriceEc).orderBy("-fromDate").cache(true).queryList();
} catch (GenericEntityException e) {
Debug.logError(e, "An error occurred while getting the product prices", module);
}
productPrices = EntityUtil.filterByDate(productPrices, true);
// ===== get the prices we need: list, default, average cost, promo, min, max =====
// if any of these prices is missing and this product is a variant, default to the corresponding price on the virtual product
GenericValue listPriceValue = getPriceValueForType("LIST_PRICE", productPrices, virtualProductPrices);
GenericValue defaultPriceValue = getPriceValueForType("DEFAULT_PRICE", productPrices, virtualProductPrices);
// ProductPrice entity.
if (UtilValidate.isNotEmpty(agreementId)) {
try {
GenericValue agreementPriceValue = EntityQuery.use(delegator).from("AgreementItemAndProductAppl").where("agreementId", agreementId, "productId", productId, "currencyUomId", currencyDefaultUomId).queryFirst();
if (agreementPriceValue != null && agreementPriceValue.get("price") != null) {
defaultPriceValue = agreementPriceValue;
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error getting agreement info from the database while calculating price" + e.toString(), module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrieveAgreementInfo", UtilMisc.toMap("errorString", e.toString()), locale));
}
}
GenericValue competitivePriceValue = getPriceValueForType("COMPETITIVE_PRICE", productPrices, virtualProductPrices);
GenericValue averageCostValue = getPriceValueForType("AVERAGE_COST", productPrices, virtualProductPrices);
GenericValue promoPriceValue = getPriceValueForType("PROMO_PRICE", productPrices, virtualProductPrices);
GenericValue minimumPriceValue = getPriceValueForType("MINIMUM_PRICE", productPrices, virtualProductPrices);
GenericValue maximumPriceValue = getPriceValueForType("MAXIMUM_PRICE", productPrices, virtualProductPrices);
GenericValue wholesalePriceValue = getPriceValueForType("WHOLESALE_PRICE", productPrices, virtualProductPrices);
GenericValue specialPromoPriceValue = getPriceValueForType("SPECIAL_PROMO_PRICE", productPrices, virtualProductPrices);
// now if this is a virtual product check each price type, if doesn't exist get from variant with lowest DEFAULT_PRICE
if ("Y".equals(product.getString("isVirtual"))) {
// only do this if there is no default price, consider the others optional for performance reasons
if (defaultPriceValue == null) {
// use the cache to find the variant with the lowest default price
try {
List<GenericValue> variantAssocList = EntityQuery.use(delegator).from("ProductAssoc").where("productId", product.get("productId"), "productAssocTypeId", "PRODUCT_VARIANT").orderBy("-fromDate").cache(true).filterByDate().queryList();
BigDecimal minDefaultPrice = null;
List<GenericValue> variantProductPrices = null;
for (GenericValue variantAssoc : variantAssocList) {
String curVariantProductId = variantAssoc.getString("productIdTo");
List<GenericValue> curVariantPriceList = EntityQuery.use(delegator).from("ProductPrice").where("productId", curVariantProductId).orderBy("-fromDate").cache(true).filterByDate(nowTimestamp).queryList();
List<GenericValue> tempDefaultPriceList = EntityUtil.filterByAnd(curVariantPriceList, UtilMisc.toMap("productPriceTypeId", "DEFAULT_PRICE"));
GenericValue curDefaultPriceValue = EntityUtil.getFirst(tempDefaultPriceList);
if (curDefaultPriceValue != null) {
BigDecimal curDefaultPrice = curDefaultPriceValue.getBigDecimal("price");
if (minDefaultPrice == null || curDefaultPrice.compareTo(minDefaultPrice) < 0) {
// check to see if the product is discontinued for sale before considering it the lowest price
GenericValue curVariantProduct = EntityQuery.use(delegator).from("Product").where("productId", curVariantProductId).cache().queryOne();
if (curVariantProduct != null) {
Timestamp salesDiscontinuationDate = curVariantProduct.getTimestamp("salesDiscontinuationDate");
if (salesDiscontinuationDate == null || salesDiscontinuationDate.after(nowTimestamp)) {
minDefaultPrice = curDefaultPrice;
variantProductPrices = curVariantPriceList;
}
}
}
}
}
if (variantProductPrices != null) {
// we have some other options, give 'em a go...
if (listPriceValue == null) {
listPriceValue = getPriceValueForType("LIST_PRICE", variantProductPrices, null);
}
if (competitivePriceValue == null) {
competitivePriceValue = getPriceValueForType("COMPETITIVE_PRICE", variantProductPrices, null);
}
if (averageCostValue == null) {
averageCostValue = getPriceValueForType("AVERAGE_COST", variantProductPrices, null);
}
if (promoPriceValue == null) {
promoPriceValue = getPriceValueForType("PROMO_PRICE", variantProductPrices, null);
}
if (minimumPriceValue == null) {
minimumPriceValue = getPriceValueForType("MINIMUM_PRICE", variantProductPrices, null);
}
if (maximumPriceValue == null) {
maximumPriceValue = getPriceValueForType("MAXIMUM_PRICE", variantProductPrices, null);
}
if (wholesalePriceValue == null) {
wholesalePriceValue = getPriceValueForType("WHOLESALE_PRICE", variantProductPrices, null);
}
if (specialPromoPriceValue == null) {
specialPromoPriceValue = getPriceValueForType("SPECIAL_PROMO_PRICE", variantProductPrices, null);
}
defaultPriceValue = getPriceValueForType("DEFAULT_PRICE", variantProductPrices, null);
}
} catch (GenericEntityException e) {
Debug.logError(e, "An error occurred while getting the product prices", module);
}
}
}
BigDecimal promoPrice = BigDecimal.ZERO;
if (promoPriceValue != null && promoPriceValue.get("price") != null) {
promoPrice = promoPriceValue.getBigDecimal("price");
}
BigDecimal wholesalePrice = BigDecimal.ZERO;
if (wholesalePriceValue != null && wholesalePriceValue.get("price") != null) {
wholesalePrice = wholesalePriceValue.getBigDecimal("price");
}
boolean validPriceFound = false;
BigDecimal defaultPrice = BigDecimal.ZERO;
List<GenericValue> orderItemPriceInfos = new LinkedList<GenericValue>();
if (defaultPriceValue != null) {
// If a price calc formula (service) is specified, then use it to get the unit price
if ("ProductPrice".equals(defaultPriceValue.getEntityName()) && UtilValidate.isNotEmpty(defaultPriceValue.getString("customPriceCalcService"))) {
GenericValue customMethod = null;
try {
customMethod = defaultPriceValue.getRelatedOne("CustomMethod", false);
} catch (GenericEntityException gee) {
Debug.logError(gee, "An error occurred while getting the customPriceCalcService", module);
}
if (customMethod != null && UtilValidate.isNotEmpty(customMethod.getString("customMethodName"))) {
Map<String, Object> inMap = UtilMisc.toMap("userLogin", context.get("userLogin"), "product", product);
inMap.put("initialPrice", defaultPriceValue.getBigDecimal("price"));
inMap.put("currencyUomId", currencyDefaultUomId);
inMap.put("quantity", quantity);
inMap.put("amount", amount);
if (UtilValidate.isNotEmpty(surveyResponseId)) {
inMap.put("surveyResponseId", surveyResponseId);
}
if (UtilValidate.isNotEmpty(customAttributes)) {
inMap.put("customAttributes", customAttributes);
}
try {
Map<String, Object> outMap = dispatcher.runSync(customMethod.getString("customMethodName"), inMap);
if (ServiceUtil.isSuccess(outMap)) {
BigDecimal calculatedDefaultPrice = (BigDecimal) outMap.get("price");
orderItemPriceInfos = UtilGenerics.checkList(outMap.get("orderItemPriceInfos"));
if (UtilValidate.isNotEmpty(calculatedDefaultPrice)) {
defaultPrice = calculatedDefaultPrice;
validPriceFound = true;
}
}
} catch (GenericServiceException gse) {
Debug.logError(gse, "An error occurred while running the customPriceCalcService [" + customMethod.getString("customMethodName") + "]", module);
}
}
}
if (!validPriceFound && defaultPriceValue.get("price") != null) {
defaultPrice = defaultPriceValue.getBigDecimal("price");
validPriceFound = true;
}
}
BigDecimal listPrice = listPriceValue != null ? listPriceValue.getBigDecimal("price") : null;
if (listPrice == null) {
// no list price, use defaultPrice for the final price
// ========= ensure calculated price is not below minSalePrice or above maxSalePrice =========
BigDecimal maxSellPrice = maximumPriceValue != null ? maximumPriceValue.getBigDecimal("price") : null;
if (maxSellPrice != null && defaultPrice.compareTo(maxSellPrice) > 0) {
defaultPrice = maxSellPrice;
}
// min price second to override max price, safety net
BigDecimal minSellPrice = minimumPriceValue != null ? minimumPriceValue.getBigDecimal("price") : null;
if (minSellPrice != null && defaultPrice.compareTo(minSellPrice) < 0) {
defaultPrice = minSellPrice;
// since we have found a minimum price that has overriden a the defaultPrice, even if no valid one was found, we will consider it as if one had been...
validPriceFound = true;
}
result.put("basePrice", defaultPrice);
result.put("price", defaultPrice);
result.put("defaultPrice", defaultPrice);
result.put("competitivePrice", competitivePriceValue != null ? competitivePriceValue.getBigDecimal("price") : null);
result.put("averageCost", averageCostValue != null ? averageCostValue.getBigDecimal("price") : null);
result.put("promoPrice", promoPriceValue != null ? promoPriceValue.getBigDecimal("price") : null);
result.put("specialPromoPrice", specialPromoPriceValue != null ? specialPromoPriceValue.getBigDecimal("price") : null);
result.put("validPriceFound", Boolean.valueOf(validPriceFound));
result.put("isSale", Boolean.FALSE);
result.put("orderItemPriceInfos", orderItemPriceInfos);
Map<String, Object> errorResult = addGeneralResults(result, competitivePriceValue, specialPromoPriceValue, productStore, checkIncludeVat, currencyDefaultUomId, productId, quantity, partyId, dispatcher, locale);
if (errorResult != null)
return errorResult;
} else {
try {
List<GenericValue> allProductPriceRules = makeProducePriceRuleList(delegator, optimizeForLargeRuleSet, productId, virtualProductId, prodCatalogId, productStoreGroupId, webSiteId, partyId, currencyDefaultUomId);
allProductPriceRules = EntityUtil.filterByDate(allProductPriceRules, true);
List<GenericValue> quantityProductPriceRules = null;
List<GenericValue> nonQuantityProductPriceRules = null;
if (findAllQuantityPrices) {
// split into list with quantity conditions and list without, then iterate through each quantity cond one
quantityProductPriceRules = new LinkedList<GenericValue>();
nonQuantityProductPriceRules = new LinkedList<GenericValue>();
for (GenericValue productPriceRule : allProductPriceRules) {
List<GenericValue> productPriceCondList = EntityQuery.use(delegator).from("ProductPriceCond").where("productPriceRuleId", productPriceRule.get("productPriceRuleId")).cache(true).queryList();
boolean foundQuantityInputParam = false;
// only consider a rule if all conditions except the quantity condition are true
boolean allExceptQuantTrue = true;
for (GenericValue productPriceCond : productPriceCondList) {
if ("PRIP_QUANTITY".equals(productPriceCond.getString("inputParamEnumId"))) {
foundQuantityInputParam = true;
} else {
if (!checkPriceCondition(productPriceCond, productId, virtualProductId, prodCatalogId, productStoreGroupId, webSiteId, partyId, quantity, listPrice, currencyDefaultUomId, delegator, nowTimestamp)) {
allExceptQuantTrue = false;
}
}
}
if (foundQuantityInputParam && allExceptQuantTrue) {
quantityProductPriceRules.add(productPriceRule);
} else {
nonQuantityProductPriceRules.add(productPriceRule);
}
}
}
if (findAllQuantityPrices) {
List<Map<String, Object>> allQuantityPrices = new LinkedList<Map<String, Object>>();
// foreach create an entry in the out list and eval that rule and all nonQuantityProductPriceRules rather than a single rule
for (GenericValue quantityProductPriceRule : quantityProductPriceRules) {
List<GenericValue> ruleListToUse = new LinkedList<GenericValue>();
ruleListToUse.add(quantityProductPriceRule);
ruleListToUse.addAll(nonQuantityProductPriceRules);
Map<String, Object> quantCalcResults = calcPriceResultFromRules(ruleListToUse, listPrice, defaultPrice, promoPrice, wholesalePrice, maximumPriceValue, minimumPriceValue, validPriceFound, averageCostValue, productId, virtualProductId, prodCatalogId, productStoreGroupId, webSiteId, partyId, null, currencyDefaultUomId, delegator, nowTimestamp, locale);
Map<String, Object> quantErrorResult = addGeneralResults(quantCalcResults, competitivePriceValue, specialPromoPriceValue, productStore, checkIncludeVat, currencyDefaultUomId, productId, quantity, partyId, dispatcher, locale);
if (quantErrorResult != null)
return quantErrorResult;
// also add the quantityProductPriceRule to the Map so it can be used for quantity break information
quantCalcResults.put("quantityProductPriceRule", quantityProductPriceRule);
allQuantityPrices.add(quantCalcResults);
}
result.put("allQuantityPrices", allQuantityPrices);
// use a quantity 1 to get the main price, then fill in the quantity break prices
Map<String, Object> calcResults = calcPriceResultFromRules(allProductPriceRules, listPrice, defaultPrice, promoPrice, wholesalePrice, maximumPriceValue, minimumPriceValue, validPriceFound, averageCostValue, productId, virtualProductId, prodCatalogId, productStoreGroupId, webSiteId, partyId, BigDecimal.ONE, currencyDefaultUomId, delegator, nowTimestamp, locale);
result.putAll(calcResults);
// The orderItemPriceInfos out parameter requires a special treatment:
// the list of OrderItemPriceInfos generated by the price rule is appended to
// the existing orderItemPriceInfos list and the aggregated list is returned.
List<GenericValue> orderItemPriceInfosFromRule = UtilGenerics.checkList(calcResults.get("orderItemPriceInfos"));
if (UtilValidate.isNotEmpty(orderItemPriceInfosFromRule)) {
orderItemPriceInfos.addAll(orderItemPriceInfosFromRule);
}
result.put("orderItemPriceInfos", orderItemPriceInfos);
Map<String, Object> errorResult = addGeneralResults(result, competitivePriceValue, specialPromoPriceValue, productStore, checkIncludeVat, currencyDefaultUomId, productId, quantity, partyId, dispatcher, locale);
if (errorResult != null)
return errorResult;
} else {
Map<String, Object> calcResults = calcPriceResultFromRules(allProductPriceRules, listPrice, defaultPrice, promoPrice, wholesalePrice, maximumPriceValue, minimumPriceValue, validPriceFound, averageCostValue, productId, virtualProductId, prodCatalogId, productStoreGroupId, webSiteId, partyId, quantity, currencyDefaultUomId, delegator, nowTimestamp, locale);
result.putAll(calcResults);
// The orderItemPriceInfos out parameter requires a special treatment:
// the list of OrderItemPriceInfos generated by the price rule is appended to
// the existing orderItemPriceInfos list and the aggregated list is returned.
List<GenericValue> orderItemPriceInfosFromRule = UtilGenerics.checkList(calcResults.get("orderItemPriceInfos"));
if (UtilValidate.isNotEmpty(orderItemPriceInfosFromRule)) {
orderItemPriceInfos.addAll(orderItemPriceInfosFromRule);
}
result.put("orderItemPriceInfos", orderItemPriceInfos);
Map<String, Object> errorResult = addGeneralResults(result, competitivePriceValue, specialPromoPriceValue, productStore, checkIncludeVat, currencyDefaultUomId, productId, quantity, partyId, dispatcher, locale);
if (errorResult != null)
return errorResult;
}
} catch (GenericEntityException e) {
Debug.logError(e, "Error getting rules from the database while calculating price", module);
return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ProductPriceCannotRetrievePriceRules", UtilMisc.toMap("errorString", e.toString()), locale));
}
}
// Convert the value to the price currency, if required
if ("true".equals(EntityUtilProperties.getPropertyValue("catalog", "convertProductPriceCurrency", delegator))) {
if (UtilValidate.isNotEmpty(currencyDefaultUomId) && UtilValidate.isNotEmpty(currencyUomIdTo) && !currencyDefaultUomId.equals(currencyUomIdTo)) {
if (UtilValidate.isNotEmpty(result)) {
Map<String, Object> convertPriceMap = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : result.entrySet()) {
BigDecimal tempPrice = BigDecimal.ZERO;
switch(entry.getKey()) {
case "basePrice":
tempPrice = (BigDecimal) entry.getValue();
case "price":
tempPrice = (BigDecimal) entry.getValue();
case "defaultPrice":
tempPrice = (BigDecimal) entry.getValue();
case "competitivePrice":
tempPrice = (BigDecimal) entry.getValue();
case "averageCost":
tempPrice = (BigDecimal) entry.getValue();
case "promoPrice":
tempPrice = (BigDecimal) entry.getValue();
case "specialPromoPrice":
tempPrice = (BigDecimal) entry.getValue();
case "listPrice":
tempPrice = (BigDecimal) entry.getValue();
}
if (tempPrice != null && tempPrice != BigDecimal.ZERO) {
Map<String, Object> priceResults = new HashMap<String, Object>();
try {
priceResults = dispatcher.runSync("convertUom", UtilMisc.<String, Object>toMap("uomId", currencyDefaultUomId, "uomIdTo", currencyUomIdTo, "originalValue", tempPrice, "defaultDecimalScale", Long.valueOf(2), "defaultRoundingMode", "HalfUp"));
if (ServiceUtil.isError(priceResults) || (priceResults.get("convertedValue") == null)) {
Debug.logWarning("Unable to convert " + entry.getKey() + " for product " + productId, module);
}
} catch (GenericServiceException e) {
Debug.logError(e, module);
}
convertPriceMap.put(entry.getKey(), priceResults.get("convertedValue"));
} else {
convertPriceMap.put(entry.getKey(), entry.getValue());
}
}
if (UtilValidate.isNotEmpty(convertPriceMap)) {
convertPriceMap.put("currencyUsed", currencyUomIdTo);
result = convertPriceMap;
}
}
}
}
return result;
}
Aggregations