return true;
}
// ShippingEstimate Calc Service
public static Map<String, Object> calcShipmentCostEstimate(DispatchContext dctx, Map<String, ? extends Object> context) {
GenericDelegator delegator = dctx.getDelegator();
// prepare the data
String productStoreShipMethId = (String) context.get("productStoreShipMethId");
String productStoreId = (String) context.get("productStoreId");
String carrierRoleTypeId = (String) context.get("carrierRoleTypeId");
String carrierPartyId = (String) context.get("carrierPartyId");
String shipmentMethodTypeId = (String) context.get("shipmentMethodTypeId");
String shippingContactMechId = (String) context.get("shippingContactMechId");
String shippingPostalCode = (String) context.get("shippingPostalCode");
String shippingCountryCode = (String) context.get("shippingCountryCode");
List<Map<String, Object>> shippableItemInfo = UtilGenerics.checkList(context.get("shippableItemInfo"));
//Map shippableFeatureMap = (Map) context.get("shippableFeatureMap");
//List shippableItemSizes = (List) context.get("shippableItemSizes");
BigDecimal shippableTotal = (BigDecimal) context.get("shippableTotal");
BigDecimal shippableQuantity = (BigDecimal) context.get("shippableQuantity");
BigDecimal shippableWeight = (BigDecimal) context.get("shippableWeight");
BigDecimal initialEstimateAmt = (BigDecimal) context.get("initialEstimateAmt");
if (shippableTotal == null) {
shippableTotal = BigDecimal.ZERO;
}
if (shippableQuantity == null) {
shippableQuantity = BigDecimal.ZERO;
}
if (shippableWeight == null) {
shippableWeight = BigDecimal.ZERO;
}
if (initialEstimateAmt == null) {
initialEstimateAmt = BigDecimal.ZERO;
}
// get the ShipmentCostEstimate(s)
Map<String, String> estFields = UtilMisc.toMap("productStoreId", productStoreId, "shipmentMethodTypeId", shipmentMethodTypeId,
"carrierPartyId", carrierPartyId, "carrierRoleTypeId", carrierRoleTypeId);
EntityCondition estFieldsCond = EntityCondition.makeCondition(estFields, EntityOperator.AND);
if (UtilValidate.isNotEmpty(productStoreShipMethId)) {
// if the productStoreShipMethId field is passed, then also get estimates that have the field set
List<EntityCondition> condList = UtilMisc.toList(EntityCondition.makeCondition("productStoreShipMethId", EntityOperator.EQUALS, productStoreShipMethId), estFieldsCond);
estFieldsCond = EntityCondition.makeCondition(condList, EntityOperator.OR);
}
Collection<GenericValue> estimates = null;
try {
estimates = delegator.findList("ShipmentCostEstimate", estFieldsCond, null, null, null, true);
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError("Unable to locate estimates from database");
}
if (estimates == null || estimates.size() < 1) {
if (initialEstimateAmt.compareTo(BigDecimal.ZERO) == 0) {
Debug.logWarning("Using the passed context : " + context, module);
Debug.logWarning("No shipping estimates found; the shipping amount returned is 0!", module);
}
Map<String, Object> respNow = ServiceUtil.returnSuccess();
respNow.put("shippingEstimateAmount", BigDecimal.ZERO);
return respNow;
}
// Get the PostalAddress
GenericValue shipAddress = null;
try {
shipAddress = delegator.findByPrimaryKey("PostalAddress", UtilMisc.toMap("contactMechId", shippingContactMechId));
} catch (GenericEntityException e) {
return ServiceUtil.returnFailure("Cannot get shipping address entity");
}
if (shippingContactMechId != null) {
try {
shipAddress = delegator.findByPrimaryKey("PostalAddress", UtilMisc.toMap("contactMechId", shippingContactMechId));
} catch (GenericEntityException e) {
Debug.logError(e, module);
return ServiceUtil.returnError("Cannot get shipping address entity");
}
} else if ( shippingPostalCode != null) {
shipAddress = delegator.makeValue("PostalAddress");
shipAddress.set("countryGeoId", shippingCountryCode);
shipAddress.set("postalCodeGeoId", shippingPostalCode);
}
// Get the possible estimates.
List<GenericValue> estimateList = FastList.newInstance();
for (GenericValue thisEstimate: estimates) {
String toGeo = thisEstimate.getString("geoIdTo");
if (UtilValidate.isNotEmpty(toGeo) && shipAddress ==null) {
// This estimate requires shipping address details. We don't have it so we cannot use this estimate.
continue;
}
List<GenericValue> toGeoList = GeoWorker.expandGeoGroup(toGeo, delegator);
// Make sure we have a valid GEOID.
if (toGeoList == null || toGeoList.size() == 0 ||
GeoWorker.containsGeo(toGeoList, shipAddress.getString("countryGeoId"), delegator) ||
GeoWorker.containsGeo(toGeoList, shipAddress.getString("stateProvinceGeoId"), delegator) ||
GeoWorker.containsGeo(toGeoList, shipAddress.getString("postalCodeGeoId"), delegator)) {
/*
if (toGeo == null || toGeo.equals("") || toGeo.equals(shipAddress.getString("countryGeoId")) ||
toGeo.equals(shipAddress.getString("stateProvinceGeoId")) ||
toGeo.equals(shipAddress.getString("postalCodeGeoId"))) {
*/
GenericValue wv = null;
GenericValue qv = null;
GenericValue pv = null;
try {
wv = thisEstimate.getRelatedOne("WeightQuantityBreak");
} catch (GenericEntityException e) {
}
try {
qv = thisEstimate.getRelatedOne("QuantityQuantityBreak");
} catch (GenericEntityException e) {
}
try {
pv = thisEstimate.getRelatedOne("PriceQuantityBreak");
} catch (GenericEntityException e) {
}
if (wv == null && qv == null && pv == null) {
estimateList.add(thisEstimate);
} else {
// Do some testing.
boolean useWeight = false;
boolean weightValid = false;
boolean useQty = false;
boolean qtyValid = false;
boolean usePrice = false;
boolean priceValid = false;
if (wv != null) {
useWeight = true;
BigDecimal min = BigDecimal.ONE.movePointLeft(4);
BigDecimal max = BigDecimal.ONE.movePointLeft(4);
try {
min = wv.getBigDecimal("fromQuantity");
max = wv.getBigDecimal("thruQuantity");
} catch (Exception e) {
}
if (shippableWeight.compareTo(min) >= 0 && (max.compareTo(BigDecimal.ZERO) == 0 || shippableWeight.compareTo(max) <= 0)) {
weightValid = true;
}
}
if (qv != null) {
useQty = true;
BigDecimal min = BigDecimal.ONE.movePointLeft(4);
BigDecimal max = BigDecimal.ONE.movePointLeft(4);
try {
min = qv.getBigDecimal("fromQuantity");
max = qv.getBigDecimal("thruQuantity");
} catch (Exception e) {
}
if (shippableQuantity.compareTo(min) >= 0 && (max.compareTo(BigDecimal.ZERO) == 0 || shippableQuantity.compareTo(max) <= 0)) {
qtyValid = true;
}
}
if (pv != null) {
usePrice = true;
BigDecimal min = BigDecimal.ONE.movePointLeft(4);
BigDecimal max = BigDecimal.ONE.movePointLeft(4);
try {
min = pv.getBigDecimal("fromQuantity");
max = pv.getBigDecimal("thruQuantity");
} catch (Exception e) {
}
if (shippableTotal.compareTo(min) >= 0 && (max.compareTo(BigDecimal.ZERO) == 0 || shippableTotal.compareTo(max) <= 0)) {
priceValid = true;
}
}
// Now check the tests.
if ((useWeight && weightValid) || (useQty && qtyValid) || (usePrice && priceValid)) {
estimateList.add(thisEstimate);
}
}
}
}
if (estimateList.size() < 1) {
return ServiceUtil.returnFailure("No shipping estimate found for carrier [" + carrierPartyId + "] and shipment method type [" + shipmentMethodTypeId +"]");
}
// make the shippable item size/feature objects
List<BigDecimal> shippableItemSizes = FastList.newInstance();
Map<String, BigDecimal> shippableFeatureMap = FastMap.newInstance();
if (shippableItemInfo != null) {
for (Map<String, Object> itemMap: shippableItemInfo) {
// add the item sizes
BigDecimal itemSize = (BigDecimal) itemMap.get("size");
if (itemSize != null) {
shippableItemSizes.add(itemSize);
}
// add the feature quantities
BigDecimal quantity = (BigDecimal) itemMap.get("quantity");
Set<String> featureSet = UtilGenerics.checkSet(itemMap.get("featureSet"));
if (UtilValidate.isNotEmpty(featureSet)) {
for (String featureId: featureSet) {
BigDecimal featureQuantity = (BigDecimal) shippableFeatureMap.get(featureId);
if (featureQuantity == null) {
featureQuantity = BigDecimal.ZERO;
}
featureQuantity = featureQuantity.add(quantity);
shippableFeatureMap.put(featureId, featureQuantity);
}
}
}
}
// Calculate priority based on available data.
double PRIORITY_PARTY = 9;
double PRIORITY_ROLE = 8;
double PRIORITY_GEO = 4;
double PRIORITY_WEIGHT = 1;
double PRIORITY_QTY = 1;
double PRIORITY_PRICE = 1;
int estimateIndex = 0;
if (estimateList.size() > 1) {
TreeMap<Integer, GenericValue> estimatePriority = new TreeMap<Integer, GenericValue>();
//int estimatePriority[] = new int[estimateList.size()];
for (GenericValue currentEstimate: estimateList) {
int prioritySum = 0;
if (UtilValidate.isNotEmpty(currentEstimate.getString("partyId"))) {
prioritySum += PRIORITY_PARTY;
}
if (UtilValidate.isNotEmpty(currentEstimate.getString("roleTypeId"))) {
prioritySum += PRIORITY_ROLE;
}
if (UtilValidate.isNotEmpty(currentEstimate.getString("geoIdTo"))) {
prioritySum += PRIORITY_GEO;
}
if (UtilValidate.isNotEmpty(currentEstimate.getString("weightBreakId"))) {
prioritySum += PRIORITY_WEIGHT;
}
if (UtilValidate.isNotEmpty(currentEstimate.getString("quantityBreakId"))) {
prioritySum += PRIORITY_QTY;
}
if (UtilValidate.isNotEmpty(currentEstimate.getString("priceBreakId"))) {
prioritySum += PRIORITY_PRICE;
}
// there will be only one of each priority; latest will replace
estimatePriority.put(Integer.valueOf(prioritySum), currentEstimate);
}
// locate the highest priority estimate; or the latest entered
Object[] estimateArray = estimatePriority.values().toArray();
estimateIndex = estimateList.indexOf(estimateArray[estimateArray.length - 1]);
}
// Grab the estimate and work with it.
GenericValue estimate = estimateList.get(estimateIndex);
//Debug.log("[ShippingEvents.getShipEstimate] Working with estimate [" + estimateIndex + "]: " + estimate, module);
// flat fees
BigDecimal orderFlat = BigDecimal.ZERO;
if (estimate.getBigDecimal("orderFlatPrice") != null) {
orderFlat = estimate.getBigDecimal("orderFlatPrice");
}
BigDecimal orderItemFlat = BigDecimal.ZERO;
if (estimate.getBigDecimal("orderItemFlatPrice") != null) {
orderItemFlat = estimate.getBigDecimal("orderItemFlatPrice");
}
BigDecimal orderPercent = BigDecimal.ZERO;
if (estimate.getBigDecimal("orderPricePercent") != null) {
orderPercent = estimate.getBigDecimal("orderPricePercent");
}
BigDecimal itemFlatAmount = shippableQuantity.multiply(orderItemFlat);
BigDecimal orderPercentage = shippableTotal.multiply(orderPercent.movePointLeft(2));
// flat total
BigDecimal flatTotal = orderFlat.add(itemFlatAmount).add(orderPercentage);
// spans
BigDecimal weightUnit = BigDecimal.ZERO;
if (estimate.getBigDecimal("weightUnitPrice") != null) {
weightUnit = estimate.getBigDecimal("weightUnitPrice");
}
BigDecimal qtyUnit = BigDecimal.ZERO;
if (estimate.getBigDecimal("quantityUnitPrice") != null) {
qtyUnit = estimate.getBigDecimal("quantityUnitPrice");
}
BigDecimal priceUnit = BigDecimal.ZERO;
if (estimate.getBigDecimal("priceUnitPrice") != null) {
priceUnit = estimate.getBigDecimal("priceUnitPrice");
}
BigDecimal weightAmount = shippableWeight.multiply(weightUnit);
BigDecimal quantityAmount = shippableQuantity.multiply(qtyUnit);
BigDecimal priceAmount = shippableTotal.multiply(priceUnit);
// span total
BigDecimal spanTotal = weightAmount.add(quantityAmount).add(priceAmount);
// feature surcharges
BigDecimal featureSurcharge = BigDecimal.ZERO;
String featureGroupId = estimate.getString("productFeatureGroupId");
BigDecimal featurePercent = estimate.getBigDecimal("featurePercent");
BigDecimal featurePrice = estimate.getBigDecimal("featurePrice");
if (featurePercent == null) {
featurePercent = BigDecimal.ZERO;
}
if (featurePrice == null) {
featurePrice = BigDecimal.ZERO;
}
if (featureGroupId != null && featureGroupId.length() > 0 && shippableFeatureMap != null) {
for (Map.Entry<String, BigDecimal> entry: shippableFeatureMap.entrySet()) {
String featureId = entry.getKey();
BigDecimal quantity = entry.getValue();
GenericValue appl = null;
Map<String, String> fields = UtilMisc.toMap("productFeatureGroupId", featureGroupId, "productFeatureId", featureId);
try {
List<GenericValue> appls = delegator.findByAndCache("ProductFeatureGroupAppl", fields);
appls = EntityUtil.filterByDate(appls);
appl = EntityUtil.getFirst(appls);
} catch (GenericEntityException e) {
Debug.logError(e, "Unable to lookup feature/group" + fields, module);
}