blob: b9e048cf8dab4011b6ca8704410f786f7717405d [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*******************************************************************************/
package org.apache.ofbiz.product.product;
import java.math.BigDecimal;
import java.math.MathContext;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.common.geo.GeoWorker;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.condition.EntityCondition;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entity.util.EntityTypeUtil;
import org.apache.ofbiz.entity.util.EntityUtil;
import org.apache.ofbiz.product.config.ProductConfigWrapper;
import org.apache.ofbiz.product.config.ProductConfigWrapper.ConfigOption;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ModelService;
/**
* Product Worker class to reduce code in JSPs.
*/
public final class ProductWorker {
public static final String module = ProductWorker.class.getName();
private static final String resource = "ProductUiLabels";
private static final MathContext generalRounding = new MathContext(10);
private ProductWorker () {}
public static boolean shippingApplies(GenericValue product) {
String errMsg = "";
if (product != null) {
String productTypeId = product.getString("productTypeId");
if ("SERVICE".equals(productTypeId) || "SERVICE_PRODUCT".equals(productTypeId) || (ProductWorker.isDigital(product) && !ProductWorker.isPhysical(product))) {
// don't charge shipping on services or digital goods
return false;
}
Boolean chargeShipping = product.getBoolean("chargeShipping");
if (chargeShipping == null) {
return true;
} else {
return chargeShipping.booleanValue();
}
} else {
throw new IllegalArgumentException(errMsg);
}
}
public static boolean isBillableToAddress(GenericValue product, GenericValue postalAddress) {
return isAllowedToAddress(product, postalAddress, "PG_PURCH_");
}
public static boolean isShippableToAddress(GenericValue product, GenericValue postalAddress) {
return isAllowedToAddress(product, postalAddress, "PG_SHIP_");
}
private static boolean isAllowedToAddress(GenericValue product, GenericValue postalAddress, String productGeoPrefix) {
if (product != null && postalAddress != null) {
Delegator delegator = product.getDelegator();
List<GenericValue> productGeos = null;
try {
productGeos = product.getRelated("ProductGeo", null, null, false);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
List<GenericValue> excludeGeos = EntityUtil.filterByAnd(productGeos, UtilMisc.toMap("productGeoEnumId", productGeoPrefix + "EXCLUDE"));
List<GenericValue> includeGeos = EntityUtil.filterByAnd(productGeos, UtilMisc.toMap("productGeoEnumId", productGeoPrefix + "INCLUDE"));
if (UtilValidate.isEmpty(excludeGeos) && UtilValidate.isEmpty(includeGeos)) {
// If no GEOs are configured the default is TRUE
return true;
}
// exclusion
for (GenericValue productGeo: excludeGeos) {
List<GenericValue> excludeGeoGroup = GeoWorker.expandGeoGroup(productGeo.getString("geoId"), delegator);
if (GeoWorker.containsGeo(excludeGeoGroup, postalAddress.getString("countryGeoId"), delegator) ||
GeoWorker.containsGeo(excludeGeoGroup, postalAddress.getString("stateProvinceGeoId"), delegator) ||
GeoWorker.containsGeo(excludeGeoGroup, postalAddress.getString("postalCodeGeoId"), delegator)) {
return false;
}
}
if (UtilValidate.isEmpty(includeGeos)) {
// If no GEOs are configured the default is TRUE
return true;
}
// inclusion
for (GenericValue productGeo: includeGeos) {
List<GenericValue> includeGeoGroup = GeoWorker.expandGeoGroup(productGeo.getString("geoId"), delegator);
if (GeoWorker.containsGeo(includeGeoGroup, postalAddress.getString("countryGeoId"), delegator) ||
GeoWorker.containsGeo(includeGeoGroup, postalAddress.getString("stateProvinceGeoId"), delegator) ||
GeoWorker.containsGeo(includeGeoGroup, postalAddress.getString("postalCodeGeoId"), delegator)) {
return true;
}
}
} else {
throw new IllegalArgumentException("product and postalAddress cannot be null.");
}
return false;
}
public static boolean isSerialized (Delegator delegator, String productId) {
try {
GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache().queryOne();
if (product != null) {
return "SERIALIZED_INV_ITEM".equals(product.getString("inventoryItemTypeId"));
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
return false;
}
public static boolean taxApplies(GenericValue product) {
String errMsg = "";
if (product != null) {
Boolean taxable = product.getBoolean("taxable");
if (taxable == null) {
return true;
} else {
return taxable.booleanValue();
}
} else {
throw new IllegalArgumentException(errMsg);
}
}
public static String getInstanceAggregatedId(Delegator delegator, String instanceProductId) throws GenericEntityException {
GenericValue instanceProduct = EntityQuery.use(delegator).from("Product").where("productId", instanceProductId).queryOne();
if (instanceProduct != null && EntityTypeUtil.hasParentType(delegator, "ProductType", "productTypeId", instanceProduct.getString("productTypeId"), "parentTypeId", "AGGREGATED")) {
GenericValue productAssoc = EntityUtil.getFirst(EntityUtil.filterByDate(instanceProduct.getRelated("AssocProductAssoc", UtilMisc.toMap("productAssocTypeId", "PRODUCT_CONF"), null, false)));
if (productAssoc != null) {
return productAssoc.getString("productId");
}
}
return null;
}
public static String getAggregatedInstanceId(Delegator delegator, String aggregatedProductId, String configId) throws GenericEntityException {
List<GenericValue> productAssocs = getAggregatedAssocs(delegator, aggregatedProductId);
if (UtilValidate.isNotEmpty(productAssocs) && UtilValidate.isNotEmpty(configId)) {
for (GenericValue productAssoc: productAssocs) {
GenericValue product = productAssoc.getRelatedOne("AssocProduct", false);
if (configId.equals(product.getString("configId"))) {
return productAssoc.getString("productIdTo");
}
}
}
return null;
}
public static List<GenericValue> getAggregatedAssocs(Delegator delegator, String aggregatedProductId) throws GenericEntityException {
GenericValue aggregatedProduct = EntityQuery.use(delegator).from("Product").where("productId", aggregatedProductId).queryOne();
if (aggregatedProduct != null && ("AGGREGATED".equals(aggregatedProduct.getString("productTypeId")) || "AGGREGATED_SERVICE".equals(aggregatedProduct.getString("productTypeId")))) {
List<GenericValue> productAssocs = EntityUtil.filterByDate(aggregatedProduct.getRelated("MainProductAssoc", UtilMisc.toMap("productAssocTypeId", "PRODUCT_CONF"), null, false));
return productAssocs;
}
return null;
}
public static String getVariantVirtualId(GenericValue variantProduct) throws GenericEntityException {
List<GenericValue> productAssocs = getVariantVirtualAssocs(variantProduct);
if (productAssocs == null) {
return null;
}
GenericValue productAssoc = EntityUtil.getFirst(productAssocs);
if (productAssoc != null) {
return productAssoc.getString("productId");
} else {
return null;
}
}
public static List<GenericValue> getVariantVirtualAssocs(GenericValue variantProduct) throws GenericEntityException {
if (variantProduct != null && "Y".equals(variantProduct.getString("isVariant"))) {
List<GenericValue> productAssocs = EntityUtil.filterByDate(variantProduct.getRelated("AssocProductAssoc", UtilMisc.toMap("productAssocTypeId", "PRODUCT_VARIANT"), null, true));
return productAssocs;
}
return null;
}
/**
* invokes the getInventoryAvailableByFacility service, returns true if specified quantity is available, else false
* this is only used in the related method that uses a ProductConfigWrapper, until that is refactored into a service as well...
*/
private static boolean isProductInventoryAvailableByFacility(String productId, String inventoryFacilityId, BigDecimal quantity, LocalDispatcher dispatcher) {
BigDecimal availableToPromise = null;
try {
Map<String, Object> result = dispatcher.runSync("getInventoryAvailableByFacility",
UtilMisc.toMap("productId", productId, "facilityId", inventoryFacilityId));
availableToPromise = (BigDecimal) result.get("availableToPromiseTotal");
if (availableToPromise == null) {
Debug.logWarning("The getInventoryAvailableByFacility service returned a null availableToPromise, the error message was:\n" + result.get(ModelService.ERROR_MESSAGE), module);
return false;
}
} catch (GenericServiceException e) {
Debug.logWarning(e, "Error invoking getInventoryAvailableByFacility service in isCatalogInventoryAvailable", module);
return false;
}
// check to see if we got enough back...
if (availableToPromise.compareTo(quantity) >= 0) {
if (Debug.infoOn()) Debug.logInfo("Inventory IS available in facility with id " + inventoryFacilityId + " for product id " + productId + "; desired quantity is " + quantity + ", available quantity is " + availableToPromise, module);
return true;
} else {
if (Debug.infoOn()) Debug.logInfo("Returning false because there is insufficient inventory available in facility with id " + inventoryFacilityId + " for product id " + productId + "; desired quantity is " + quantity + ", available quantity is " + availableToPromise, module);
return false;
}
}
/**
* Invokes the getInventoryAvailableByFacility service, returns true if specified quantity is available for all the selected parts, else false.
* Also, set the available flag for all the product configuration's options.
**/
public static boolean isProductInventoryAvailableByFacility(ProductConfigWrapper productConfig, String inventoryFacilityId, BigDecimal quantity, LocalDispatcher dispatcher) {
boolean available = true;
List<ConfigOption> options = productConfig.getSelectedOptions();
for (ConfigOption ci: options) {
List<GenericValue> products = ci.getComponents();
for (GenericValue product: products) {
String productId = product.getString("productId");
BigDecimal cmpQuantity = product.getBigDecimal("quantity");
BigDecimal neededQty = BigDecimal.ZERO;
if (cmpQuantity != null) {
neededQty = quantity.multiply(cmpQuantity);
}
if (!isProductInventoryAvailableByFacility(productId, inventoryFacilityId, neededQty, dispatcher)) {
ci.setAvailable(false);
}
}
if (!ci.isAvailable()) {
available = false;
}
}
return available;
}
/**
* Gets ProductFeature GenericValue for all distinguishing features of a variant product.
* Distinguishing means all features that are selectable on the corresponding virtual product and standard on the variant plus all DISTINGUISHING_FEAT assoc type features on the variant.
*/
public static Set<GenericValue> getVariantDistinguishingFeatures(GenericValue variantProduct) throws GenericEntityException {
if (variantProduct == null) {
return new HashSet<GenericValue>();
}
if (!"Y".equals(variantProduct.getString("isVariant"))) {
throw new IllegalArgumentException("Cannot get distinguishing features for a product that is not a variant (ie isVariant!=Y).");
}
Delegator delegator = variantProduct.getDelegator();
String virtualProductId = getVariantVirtualId(variantProduct);
// find all selectable features on the virtual product that are also standard features on the variant
Set<GenericValue> distFeatures = new HashSet<GenericValue>();
List<GenericValue> variantDistinguishingFeatures = EntityQuery.use(delegator).from("ProductFeatureAndAppl").where("productId", variantProduct.get("productId"), "productFeatureApplTypeId", "DISTINGUISHING_FEAT").cache(true).queryList();
for (GenericValue variantDistinguishingFeature: EntityUtil.filterByDate(variantDistinguishingFeatures)) {
GenericValue dummyFeature = delegator.makeValue("ProductFeature");
dummyFeature.setAllFields(variantDistinguishingFeature, true, null, null);
distFeatures.add(dummyFeature);
}
List<GenericValue> virtualSelectableFeatures = EntityQuery.use(delegator).from("ProductFeatureAndAppl").where("productId", virtualProductId, "productFeatureApplTypeId", "SELECTABLE_FEATURE").cache(true).queryList();
Set<String> virtualSelectableFeatureIds = new HashSet<String>();
for (GenericValue virtualSelectableFeature: EntityUtil.filterByDate(virtualSelectableFeatures)) {
virtualSelectableFeatureIds.add(virtualSelectableFeature.getString("productFeatureId"));
}
List<GenericValue> variantStandardFeatures = EntityQuery.use(delegator).from("ProductFeatureAndAppl").where("productId", variantProduct.get("productId"), "productFeatureApplTypeId", "STANDARD_FEATURE").cache(true).queryList();
for (GenericValue variantStandardFeature: EntityUtil.filterByDate(variantStandardFeatures)) {
if (virtualSelectableFeatureIds.contains(variantStandardFeature.get("productFeatureId"))) {
GenericValue dummyFeature = delegator.makeValue("ProductFeature");
dummyFeature.setAllFields(variantStandardFeature, true, null, null);
distFeatures.add(dummyFeature);
}
}
return distFeatures;
}
/**
* Get the name to show to the customer for GWP alternative options.
* If the alternative is a variant, find the distinguishing features and show those instead of the name; if it is not a variant then show the PRODUCT_NAME content.
*/
public static String getGwpAlternativeOptionName(LocalDispatcher dispatcher, Delegator delegator, String alternativeOptionProductId, Locale locale) {
try {
GenericValue alternativeOptionProduct = EntityQuery.use(delegator).from("Product").where("productId", alternativeOptionProductId).cache().queryOne();
if (alternativeOptionProduct != null) {
if ("Y".equals(alternativeOptionProduct.getString("isVariant"))) {
Set<GenericValue> distFeatures = getVariantDistinguishingFeatures(alternativeOptionProduct);
if (UtilValidate.isNotEmpty(distFeatures)) {
StringBuilder nameBuf = new StringBuilder();
for (GenericValue productFeature: distFeatures) {
if (nameBuf.length() > 0) {
nameBuf.append(", ");
}
GenericValue productFeatureType = productFeature.getRelatedOne("ProductFeatureType", true);
if (productFeatureType != null) {
nameBuf.append(productFeatureType.get("description", locale));
nameBuf.append(":");
}
nameBuf.append(productFeature.get("description", locale));
}
return nameBuf.toString();
}
}
// got to here, default to PRODUCT_NAME
String alternativeProductName = ProductContentWrapper.getProductContentAsText(alternativeOptionProduct, "PRODUCT_NAME", locale, dispatcher, "html");
return alternativeProductName;
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
} catch (Exception e) {
Debug.logError(e, module);
}
// finally fall back to the ID in square braces
return "[" + alternativeOptionProductId + "]";
}
/**
* gets productFeatures given a productFeatureApplTypeId
* @param delegator
* @param productId
* @param productFeatureApplTypeId - if null, returns ALL productFeatures, regardless of applType
* @return List
*/
public static List<GenericValue> getProductFeaturesByApplTypeId(Delegator delegator, String productId, String productFeatureApplTypeId) {
if (productId == null) {
return null;
}
try {
return getProductFeaturesByApplTypeId(EntityQuery.use(delegator).from("Product").where("productId", productId).queryOne(),
productFeatureApplTypeId);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return null;
}
public static List<GenericValue> getProductFeaturesByApplTypeId(GenericValue product, String productFeatureApplTypeId) {
if (product == null) {
return null;
}
List<GenericValue> features = null;
try {
List<GenericValue> productAppls;
List<EntityCondition> condList = UtilMisc.toList(
EntityCondition.makeCondition("productId", product.getString("productId")),
EntityUtil.getFilterByDateExpr()
);
if (productFeatureApplTypeId != null) {
condList.add(EntityCondition.makeCondition("productFeatureApplTypeId", productFeatureApplTypeId));
}
EntityCondition cond = EntityCondition.makeCondition(condList);
productAppls = product.getDelegator().findList("ProductFeatureAppl", cond, null, null, null, false);
features = EntityUtil.getRelated("ProductFeature", null, productAppls, false);
features = EntityUtil.orderBy(features, UtilMisc.toList("description"));
} catch (GenericEntityException e) {
Debug.logError(e, module);
features = new LinkedList<GenericValue>();
}
return features;
}
public static String getProductVirtualVariantMethod(Delegator delegator, String productId) {
GenericValue product = null;
try {
product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache().queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (product != null) {
return product.getString("virtualVariantMethodEnum");
} else {
return null;
}
}
/**
*
* @param product
* @return list featureType and related featuresIds, description and feature price for this product ordered by type and sequence
*/
public static List<List<Map<String,String>>> getSelectableProductFeaturesByTypesAndSeq(GenericValue product) {
if (product == null) {
return null;
}
List <List<Map<String,String>>> featureTypeFeatures = new LinkedList<List<Map<String,String>>>();
try {
Delegator delegator = product.getDelegator();
List<GenericValue> featuresSorted = EntityQuery.use(delegator)
.from("ProductFeatureAndAppl")
.where("productId", product.getString("productId"), "productFeatureApplTypeId", "SELECTABLE_FEATURE")
.orderBy("productFeatureTypeId", "sequenceNum")
.cache(true)
.queryList();
String oldType = null;
List<Map<String,String>> featureList = new LinkedList<Map<String,String>>();
for (GenericValue productFeatureAppl: featuresSorted) {
if (oldType == null || !oldType.equals(productFeatureAppl.getString("productFeatureTypeId"))) {
// use first entry for type and description
if (oldType != null) {
featureTypeFeatures.add(featureList);
featureList = new LinkedList<Map<String,String>>();
}
GenericValue productFeatureType = EntityQuery.use(delegator).from("ProductFeatureType").where("productFeatureTypeId", productFeatureAppl.getString("productFeatureTypeId")).queryOne();
featureList.add(UtilMisc.<String, String>toMap("productFeatureTypeId", productFeatureAppl.getString("productFeatureTypeId"),
"description", productFeatureType.getString("description")));
oldType = productFeatureAppl.getString("productFeatureTypeId");
}
// fill other entries with featureId, description and default price and currency
Map<String,String> featureData = UtilMisc.toMap("productFeatureId", productFeatureAppl.getString("productFeatureId"));
if (UtilValidate.isNotEmpty(productFeatureAppl.get("description"))) {
featureData.put("description", productFeatureAppl.getString("description"));
} else {
featureData.put("description", productFeatureAppl.getString("productFeatureId"));
}
List<GenericValue> productFeaturePrices = EntityQuery.use(delegator).from("ProductFeaturePrice")
.where("productFeatureId", productFeatureAppl.getString("productFeatureId"), "productPriceTypeId", "DEFAULT_PRICE")
.filterByDate()
.queryList();
if (UtilValidate.isNotEmpty(productFeaturePrices)) {
GenericValue productFeaturePrice = productFeaturePrices.get(0);
if (UtilValidate.isNotEmpty(productFeaturePrice.get("price"))) {
featureData.put("price", productFeaturePrice.getBigDecimal("price").toString());
featureData.put("currencyUomId", productFeaturePrice.getString("currencyUomId"));
}
}
featureList.add(featureData);
}
if (oldType != null) {
// last map
featureTypeFeatures.add(featureList);
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return featureTypeFeatures;
}
/**
* For a given variant product, returns the list of features that would qualify it for
* selection from the virtual product
* @param variantProduct - the variant from which to derive the selection features
* @return a List of ProductFeature GenericValues
*/
public static List<GenericValue> getVariantSelectionFeatures(GenericValue variantProduct) {
if (variantProduct == null || !"Y".equals(variantProduct.getString("isVariant"))) {
return null;
}
GenericValue virtualProduct = ProductWorker.getParentProduct(variantProduct.getString("productId"), variantProduct.getDelegator());
if (virtualProduct == null || !"Y".equals(virtualProduct.getString("isVirtual"))) {
return null;
}
// The selectable features from the virtual product
List<GenericValue> selectableFeatures = ProductWorker.getProductFeaturesByApplTypeId(virtualProduct, "SELECTABLE_FEATURE");
// A list of distinct ProductFeatureTypes derived from the selectable features
List<String> selectableTypes = EntityUtil.getFieldListFromEntityList(selectableFeatures, "productFeatureTypeId", true);
// The standard features from the variant product
List<GenericValue> standardFeatures = ProductWorker.getProductFeaturesByApplTypeId(variantProduct, "STANDARD_FEATURE");
List<GenericValue> result = new LinkedList<GenericValue>();
for (GenericValue standardFeature : standardFeatures) {
// For each standard variant feature check it is also a virtual selectable feature and
// if a feature of the same type hasn't already been added to the list
if (selectableTypes.contains(standardFeature.getString("productFeatureTypeId")) && selectableFeatures.contains(standardFeature)) {
result.add(standardFeature);
selectableTypes.remove(standardFeature.getString("productFeatureTypeId"));
}
}
return result;
}
public static Map<String, List<GenericValue>> getOptionalProductFeatures(Delegator delegator, String productId) {
Map<String, List<GenericValue>> featureMap = new LinkedHashMap<String, List<GenericValue>>();
List<GenericValue> productFeatureAppls = null;
try {
productFeatureAppls = EntityQuery.use(delegator).from("ProductFeatureAndAppl").where("productId", productId, "productFeatureApplTypeId", "OPTIONAL_FEATURE").orderBy("productFeatureTypeId", "sequenceNum").queryList();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (productFeatureAppls != null) {
for (GenericValue appl: productFeatureAppls) {
String featureType = appl.getString("productFeatureTypeId");
List<GenericValue> features = featureMap.get(featureType);
if (features == null) {
features = new LinkedList<GenericValue>();
}
features.add(appl);
featureMap.put(featureType, features);
}
}
return featureMap;
}
// product calc methods
public static BigDecimal calcOrderAdjustments(List<GenericValue> orderHeaderAdjustments, BigDecimal subTotal, boolean includeOther, boolean includeTax, boolean includeShipping) {
BigDecimal adjTotal = BigDecimal.ZERO;
if (UtilValidate.isNotEmpty(orderHeaderAdjustments)) {
List<GenericValue> filteredAdjs = filterOrderAdjustments(orderHeaderAdjustments, includeOther, includeTax, includeShipping, false, false);
for (GenericValue orderAdjustment: filteredAdjs) {
adjTotal = adjTotal.add(calcOrderAdjustment(orderAdjustment, subTotal));
}
}
return adjTotal;
}
public static BigDecimal calcOrderAdjustment(GenericValue orderAdjustment, BigDecimal orderSubTotal) {
BigDecimal adjustment = BigDecimal.ZERO;
if (orderAdjustment.get("amount") != null) {
adjustment = adjustment.add(orderAdjustment.getBigDecimal("amount"));
}
else if (orderAdjustment.get("sourcePercentage") != null) {
adjustment = adjustment.add(orderAdjustment.getBigDecimal("sourcePercentage").multiply(orderSubTotal));
}
return adjustment;
}
public static List<GenericValue> filterOrderAdjustments(List<GenericValue> adjustments, boolean includeOther, boolean includeTax, boolean includeShipping, boolean forTax, boolean forShipping) {
List<GenericValue> newOrderAdjustmentsList = new LinkedList<GenericValue>();
if (UtilValidate.isNotEmpty(adjustments)) {
for (GenericValue orderAdjustment: adjustments) {
boolean includeAdjustment = false;
if ("SALES_TAX".equals(orderAdjustment.getString("orderAdjustmentTypeId"))) {
if (includeTax) includeAdjustment = true;
} else if ("SHIPPING_CHARGES".equals(orderAdjustment.getString("orderAdjustmentTypeId"))) {
if (includeShipping) includeAdjustment = true;
} else {
if (includeOther) includeAdjustment = true;
}
// default to yes, include for shipping; so only exclude if includeInShipping is N, or false; if Y or null or anything else it will be included
if (forTax && "N".equals(orderAdjustment.getString("includeInTax"))) {
includeAdjustment = false;
}
// default to yes, include for shipping; so only exclude if includeInShipping is N, or false; if Y or null or anything else it will be included
if (forShipping && "N".equals(orderAdjustment.getString("includeInShipping"))) {
includeAdjustment = false;
}
if (includeAdjustment) {
newOrderAdjustmentsList.add(orderAdjustment);
}
}
}
return newOrderAdjustmentsList;
}
public static BigDecimal getAverageProductRating(Delegator delegator, String productId) {
return getAverageProductRating(delegator, productId, null);
}
public static BigDecimal getAverageProductRating(Delegator delegator, String productId, String productStoreId) {
GenericValue product = null;
try {
product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache().queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return ProductWorker.getAverageProductRating(product, productStoreId);
}
public static BigDecimal getAverageProductRating(GenericValue product, String productStoreId) {
return getAverageProductRating(product, null, productStoreId);
}
public static BigDecimal getAverageProductRating(GenericValue product, List<GenericValue> reviews, String productStoreId) {
if (product == null) {
Debug.logWarning("Invalid product entity passed; unable to obtain valid product rating", module);
return BigDecimal.ZERO;
}
BigDecimal productRating = BigDecimal.ZERO;
BigDecimal productEntityRating = product.getBigDecimal("productRating");
String entityFieldType = product.getString("ratingTypeEnum");
// null check
if (productEntityRating == null) {
productEntityRating = BigDecimal.ZERO;
}
if (entityFieldType == null) {
entityFieldType = "";
}
if ("PRDR_FLAT".equals(entityFieldType)) {
productRating = productEntityRating;
} else {
// get the product rating from the ProductReview entity; limit by product store if ID is passed
Map<String, String> reviewByAnd = UtilMisc.toMap("statusId", "PRR_APPROVED");
if (productStoreId != null) {
reviewByAnd.put("productStoreId", productStoreId);
}
// lookup the reviews if we didn't pass them in
if (reviews == null) {
try {
reviews = product.getRelated("ProductReview", reviewByAnd, UtilMisc.toList("-postedDateTime"), true);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
}
// tally the average
BigDecimal ratingTally = BigDecimal.ZERO;
BigDecimal numRatings = BigDecimal.ZERO;
if (reviews != null) {
for (GenericValue productReview: reviews) {
BigDecimal rating = productReview.getBigDecimal("productRating");
if (rating != null) {
ratingTally = ratingTally.add(rating);
numRatings = numRatings.add(BigDecimal.ONE);
}
}
}
if (ratingTally.compareTo(BigDecimal.ZERO) > 0 && numRatings.compareTo(BigDecimal.ZERO) > 0) {
productRating = ratingTally.divide(numRatings, generalRounding);
}
if ("PRDR_MIN".equals(entityFieldType)) {
// check for min
if (productEntityRating.compareTo(productRating) > 0) {
productRating = productEntityRating;
}
} else if ("PRDR_MAX".equals(entityFieldType)) {
// check for max
if (productRating.compareTo(productEntityRating) > 0) {
productRating = productEntityRating;
}
}
}
return productRating;
}
public static List<GenericValue> getCurrentProductCategories(Delegator delegator, String productId) {
GenericValue product = null;
try {
product = EntityQuery.use(delegator).from("Product").where("productId", productId).queryOne();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return getCurrentProductCategories(product);
}
public static List<GenericValue> getCurrentProductCategories(GenericValue product) {
if (product == null) {
return null;
}
List<GenericValue> categories = new LinkedList<GenericValue>();
try {
List<GenericValue> categoryMembers = product.getRelated("ProductCategoryMember", null, null, false);
categoryMembers = EntityUtil.filterByDate(categoryMembers);
categories = EntityUtil.getRelated("ProductCategory", null, categoryMembers, false);
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return categories;
}
//get parent product
public static GenericValue getParentProduct(String productId, Delegator delegator) {
GenericValue _parentProduct = null;
if (productId == null) {
Debug.logWarning("Bad product id", module);
}
try {
List<GenericValue> virtualProductAssocs = EntityQuery.use(delegator).from("ProductAssoc")
.where("productIdTo", productId, "productAssocTypeId", "PRODUCT_VARIANT")
.orderBy("-fromDate")
.cache(true)
.filterByDate()
.queryList();
if (UtilValidate.isEmpty(virtualProductAssocs)) {
//okay, not a variant, try a UNIQUE_ITEM
virtualProductAssocs = EntityQuery.use(delegator).from("ProductAssoc")
.where("productIdTo", productId, "productAssocTypeId", "UNIQUE_ITEM")
.orderBy("-fromDate")
.cache(true)
.filterByDate()
.queryList();
}
if (UtilValidate.isNotEmpty(virtualProductAssocs)) {
//found one, set this first as the parent product
GenericValue productAssoc = EntityUtil.getFirst(virtualProductAssocs);
_parentProduct = productAssoc.getRelatedOne("MainProduct", true);
}
} catch (GenericEntityException e) {
throw new RuntimeException("Entity Engine error getting Parent Product (" + e.getMessage() + ")");
}
return _parentProduct;
}
public static boolean isDigital(GenericValue product) {
boolean isDigital = false;
if (product != null) {
GenericValue productType = null;
try {
productType = product.getRelatedOne("ProductType", true);
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
String isDigitalValue = (productType != null? productType.getString("isDigital"): null);
isDigital = isDigitalValue != null && "Y".equalsIgnoreCase(isDigitalValue);
}
return isDigital;
}
public static boolean isPhysical(GenericValue product) {
boolean isPhysical = false;
if (product != null) {
GenericValue productType = null;
try {
productType = product.getRelatedOne("ProductType", true);
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
String isPhysicalValue = (productType != null? productType.getString("isPhysical"): null);
isPhysical = isPhysicalValue != null && "Y".equalsIgnoreCase(isPhysicalValue);
}
return isPhysical;
}
public static boolean isVirtual(Delegator delegator, String productI) {
try {
GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productI).cache().queryOne();
if (product != null) {
return "Y".equals(product.getString("isVirtual"));
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
return false;
}
public static boolean isAmountRequired(Delegator delegator, String productI) {
try {
GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productI).cache().queryOne();
if (product != null) {
return "Y".equals(product.getString("requireAmount"));
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
return false;
}
public static String getProductTypeId(Delegator delegator, String productId) {
try {
GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache().queryOne();
if (product != null) {
return product.getString("productTypeId");
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
return null;
}
/*
* Returns the product's unit weight converted to the desired Uom. If the weight is null,
* then a check is made for an associated virtual product to retrieve the weight from. If the
* weight is still null then null is returned. If a weight is found and a desiredUomId has
* been supplied and the product specifies a weightUomId then an attempt will be made to
* convert the value otherwise the weight is returned as is.
*/
public static BigDecimal getProductWeight(GenericValue product, String desiredUomId, Delegator delegator, LocalDispatcher dispatcher) {
BigDecimal weight = product.getBigDecimal("productWeight");
String weightUomId = product.getString("weightUomId");
if (weight == null) {
GenericValue parentProduct = getParentProduct(product.getString("productId"), delegator);
if (parentProduct != null) {
weight = parentProduct.getBigDecimal("productWeight");
weightUomId = parentProduct.getString("weightUomId");
}
}
if (weight == null) {
return null;
} else {
// attempt a conversion if necessary
if (desiredUomId != null && product.get("weightUomId") != null && !desiredUomId.equals(product.get("weightUomId"))) {
Map<String, Object> result = new HashMap<String, Object>();
try {
result = dispatcher.runSync("convertUom", UtilMisc.<String, Object>toMap("uomId", weightUomId, "uomIdTo", desiredUomId, "originalValue", weight));
} catch (GenericServiceException e) {
Debug.logError(e, module);
}
if (result.get(ModelService.RESPONSE_MESSAGE).equals(ModelService.RESPOND_SUCCESS) && result.get("convertedValue") != null) {
weight = (BigDecimal) result.get("convertedValue");
} else {
Debug.logError("Unsupported conversion from [" + weightUomId + "] to [" + desiredUomId + "]",module);
return null;
}
}
return weight;
}
}
/**
* Generic service to find product by id.
* By default return the product find by productId
* but you can pass searchProductFirst at false if you want search in goodIdentification before
* or pass searchAllId at true to find all product with this id (product.productId and goodIdentification.idValue)
* @param delegator the delegator
* @param idToFind the product id to find
* @param goodIdentificationTypeId the good identification type id to use
* @param searchProductFirst search first by product id
* @param searchAllId search all product ids
* @return return the list of products founds
* @throws GenericEntityException
*/
public static List<GenericValue> findProductsById(Delegator delegator,
String idToFind, String goodIdentificationTypeId,
boolean searchProductFirst, boolean searchAllId) throws GenericEntityException {
if (Debug.verboseOn()) Debug.logVerbose("Analyze goodIdentification: entered id = " + idToFind + ", goodIdentificationTypeId = " + goodIdentificationTypeId, module);
GenericValue product = null;
List<GenericValue> productsFound = null;
// 1) look if the idToFind given is a real productId
if (searchProductFirst) {
product = EntityQuery.use(delegator).from("Product").where("productId", idToFind).cache().queryOne();
}
if (searchAllId || (searchProductFirst && UtilValidate.isEmpty(product))) {
// 2) Retrieve product in GoodIdentification
Map<String, String> conditions = UtilMisc.toMap("idValue", idToFind);
if (UtilValidate.isNotEmpty(goodIdentificationTypeId)) {
conditions.put("goodIdentificationTypeId", goodIdentificationTypeId);
}
productsFound = EntityQuery.use(delegator).from("GoodIdentificationAndProduct").where(conditions).orderBy("productId").cache(true).queryList();
}
if (! searchProductFirst) {
product = EntityQuery.use(delegator).from("Product").where("productId", idToFind).cache().queryOne();
}
if (product != null) {
if (UtilValidate.isNotEmpty(productsFound)) productsFound.add(product);
else productsFound = UtilMisc.toList(product);
}
if (Debug.verboseOn()) Debug.logVerbose("Analyze goodIdentification: found product.productId = " + product + ", and list : " + productsFound, module);
return productsFound;
}
public static List<GenericValue> findProductsById(Delegator delegator, String idToFind, String goodIdentificationTypeId)
throws GenericEntityException {
return findProductsById(delegator, idToFind, goodIdentificationTypeId, true, false);
}
public static String findProductId(Delegator delegator, String idToFind, String goodIdentificationTypeId) throws GenericEntityException {
GenericValue product = findProduct(delegator, idToFind, goodIdentificationTypeId);
if (product != null) {
return product.getString("productId");
} else {
return null;
}
}
public static String findProductId(Delegator delegator, String idToFind) throws GenericEntityException {
return findProductId(delegator, idToFind, null);
}
public static GenericValue findProduct(Delegator delegator, String idToFind, String goodIdentificationTypeId) throws GenericEntityException {
List<GenericValue> products = findProductsById(delegator, idToFind, goodIdentificationTypeId);
GenericValue product = EntityUtil.getFirst(products);
return product;
}
public static List<GenericValue> findProducts(Delegator delegator, String idToFind, String goodIdentificationTypeId) throws GenericEntityException {
List<GenericValue> productsByIds = findProductsById(delegator, idToFind, goodIdentificationTypeId);
List<GenericValue> products = null;
if (UtilValidate.isNotEmpty(productsByIds)) {
for (GenericValue product : productsByIds) {
GenericValue productToAdd = product;
//retreive product GV if the actual genericValue came from viewEntity
if (! "Product".equals(product.getEntityName())) {
productToAdd = EntityQuery.use(delegator).from("Product").where("productId", product.get("productId")).cache().queryOne();
}
if (UtilValidate.isEmpty(products)) {
products = UtilMisc.toList(productToAdd);
}
else {
products.add(productToAdd);
}
}
}
return products;
}
public static List<GenericValue> findProducts(Delegator delegator, String idToFind) throws GenericEntityException {
return findProducts(delegator, idToFind, null);
}
public static GenericValue findProduct(Delegator delegator, String idToFind) throws GenericEntityException {
return findProduct(delegator, idToFind, null);
}
public static boolean isSellable(Delegator delegator, String productId, Timestamp atTime) throws GenericEntityException {
return isSellable(findProduct(delegator, productId), atTime);
}
public static boolean isSellable(Delegator delegator, String productId) throws GenericEntityException {
return isSellable(findProduct(delegator, productId));
}
public static boolean isSellable(GenericValue product) {
return isSellable(product, UtilDateTime.nowTimestamp());
}
public static boolean isSellable(GenericValue product, Timestamp atTime) {
if (product != null) {
Timestamp introDate = product.getTimestamp("introductionDate");
Timestamp discDate = product.getTimestamp("salesDiscontinuationDate");
if (introDate == null || introDate.before(atTime)) {
if (discDate == null || discDate.after(atTime)) {
return true;
}
}
}
return false;
}
public static Set<String> getRefurbishedProductIdSet(String productId, Delegator delegator) throws GenericEntityException {
Set<String> productIdSet = new HashSet<String>();
// find associated refurb items, we want serial number for main item or any refurb items too
List<GenericValue> refubProductAssocs = EntityQuery.use(delegator).from("ProductAssoc").where("productId", productId, "productAssocTypeId", "PRODUCT_REFURB").filterByDate().queryList();
for (GenericValue refubProductAssoc: refubProductAssocs) {
productIdSet.add(refubProductAssoc.getString("productIdTo"));
}
// see if this is a refurb productId to, and find product(s) it is a refurb of
List<GenericValue> refubProductToAssocs = EntityQuery.use(delegator).from("ProductAssoc").where("productIdTo", productId, "productAssocTypeId", "PRODUCT_REFURB").filterByDate().queryList();
for (GenericValue refubProductToAssoc: refubProductToAssocs) {
productIdSet.add(refubProductToAssoc.getString("productId"));
}
return productIdSet;
}
public static String getVariantFromFeatureTree(String productId, List<String> selectedFeatures, Delegator delegator) {
// all method code moved here from ShoppingCartEvents.addToCart event
String variantProductId = null;
try {
for (String paramValue: selectedFeatures) {
// find incompatibilities..
List<GenericValue> incompatibilityVariants = EntityQuery.use(delegator).from("ProductFeatureIactn")
.where("productId", productId, "productFeatureIactnTypeId","FEATURE_IACTN_INCOMP").cache(true).queryList();
for (GenericValue incompatibilityVariant: incompatibilityVariants) {
String featur = incompatibilityVariant.getString("productFeatureId");
if (paramValue.equals(featur)) {
String featurTo = incompatibilityVariant.getString("productFeatureIdTo");
for (String paramValueTo: selectedFeatures) {
if (featurTo.equals(paramValueTo)) {
Debug.logWarning("Incompatible features", module);
return null;
}
}
}
}
// find dependencies..
List<GenericValue> dependenciesVariants = EntityQuery.use(delegator).from("ProductFeatureIactn")
.where("productId", productId, "productFeatureIactnTypeId","FEATURE_IACTN_DEPEND").cache(true).queryList();
for (GenericValue dpVariant: dependenciesVariants) {
String featur = dpVariant.getString("productFeatureId");
if (paramValue.equals(featur)) {
String featurTo = dpVariant.getString("productFeatureIdTo");
boolean found = false;
for (String paramValueTo: selectedFeatures) {
if (featurTo.equals(paramValueTo)) {
found = true;
break;
}
}
if (!found) {
Debug.logWarning("Dependency features", module);
return null;
}
}
}
}
// find variant
List<GenericValue> productAssocs = EntityQuery.use(delegator).from("ProductAssoc").where("productId", productId, "productAssocTypeId","PRODUCT_VARIANT").filterByDate().queryList();
boolean productFound = false;
nextProd:
for (GenericValue productAssoc: productAssocs) {
for (String featureId: selectedFeatures) {
List<GenericValue> pAppls = EntityQuery.use(delegator).from("ProductFeatureAppl").where("productId", productAssoc.getString("productIdTo"), "productFeatureId", featureId, "productFeatureApplTypeId","STANDARD_FEATURE").cache(true).queryList();
if (UtilValidate.isEmpty(pAppls)) {
continue nextProd;
}
}
productFound = true;
variantProductId = productAssoc.getString("productIdTo");
break;
}
/**
* 1. variant not found so create new variant product and use the virtual product as basis, new one is a variant type and not a virtual type.
* adjust the prices according the selected features
*/
if (!productFound) {
// copy product to be variant
GenericValue product = EntityQuery.use(delegator).from("Product").where("productId", productId).queryOne();
product.put("isVariant", "Y");
product.put("isVirtual", "N");
product.put("productId", delegator.getNextSeqId("Product"));
product.remove("virtualVariantMethodEnum"); // not relevant for a non virtual product.
product.create();
// add the selected/standard features as 'standard features' to the 'ProductFeatureAppl' table
GenericValue productFeatureAppl = delegator.makeValue("ProductFeatureAppl",
UtilMisc.toMap("productId", product.getString("productId"), "productFeatureApplTypeId", "STANDARD_FEATURE"));
productFeatureAppl.put("fromDate", UtilDateTime.nowTimestamp());
for (String productFeatureId: selectedFeatures) {
productFeatureAppl.put("productFeatureId", productFeatureId);
productFeatureAppl.create();
}
//add standard features too
List<GenericValue> stdFeaturesAppls = EntityQuery.use(delegator).from("ProductFeatureAppl").where("productId", productId, "productFeatureApplTypeId", "STANDARD_FEATURE").filterByDate().queryList();
for (GenericValue stdFeaturesAppl: stdFeaturesAppls) {
stdFeaturesAppl.put("productId", product.getString("productId"));
stdFeaturesAppl.create();
}
/* 3. use the price of the virtual product(Entity:ProductPrice) as a basis and adjust according the prices in the feature price table.
* take the default price from the vitual product, go to the productfeature table and retrieve all the prices for the difFerent features
* add these to the price of the virtual product, store the result as the default price on the variant you created.
*/
List<GenericValue> productPrices = EntityQuery.use(delegator).from("ProductPrice").where("productId", productId).filterByDate().queryList();
for (GenericValue productPrice: productPrices) {
for (String selectedFeaturedId: selectedFeatures) {
List<GenericValue> productFeaturePrices = EntityQuery.use(delegator).from("ProductFeaturePrice")
.where("productFeatureId", selectedFeaturedId, "productPriceTypeId", productPrice.getString("productPriceTypeId"))
.filterByDate().queryList();
if (UtilValidate.isNotEmpty(productFeaturePrices)) {
GenericValue productFeaturePrice = productFeaturePrices.get(0);
if (productFeaturePrice != null) {
productPrice.put("price", productPrice.getBigDecimal("price").add(productFeaturePrice.getBigDecimal("price")));
}
}
}
if (productPrice.get("price") == null) {
productPrice.put("price", productPrice.getBigDecimal("price"));
}
productPrice.put("productId", product.getString("productId"));
productPrice.create();
}
// add the product association
GenericValue productAssoc = delegator.makeValue("ProductAssoc", UtilMisc.toMap("productId", productId, "productIdTo", product.getString("productId"), "productAssocTypeId", "PRODUCT_VARIANT"));
productAssoc.put("fromDate", UtilDateTime.nowTimestamp());
productAssoc.create();
Debug.logInfo("set the productId to: " + product.getString("productId"), module);
// copy the supplier
List<GenericValue> supplierProducts = EntityQuery.use(delegator).from("SupplierProduct").where("productId", productId).cache(true).queryList();
for (GenericValue supplierProduct: supplierProducts) {
supplierProduct = (GenericValue) supplierProduct.clone();
supplierProduct.set("productId", product.getString("productId"));
supplierProduct.create();
}
// copy the content
List<GenericValue> productContents = EntityQuery.use(delegator).from("ProductContent").where("productId", productId).cache(true).queryList();
for (GenericValue productContent: productContents) {
productContent = (GenericValue) productContent.clone();
productContent.set("productId", product.getString("productId"));
productContent.create();
}
// finally use the new productId to be added to the cart
variantProductId = product.getString("productId"); // set to the new product
}
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
return variantProductId;
}
public static boolean isAlternativePacking(Delegator delegator, String productId, String virtualVariantId) {
boolean isAlternativePacking = false;
if(productId != null || virtualVariantId != null){
List<GenericValue> alternativePackingProds = null;
try {
List<EntityCondition> condList = new LinkedList<EntityCondition>();
if (UtilValidate.isNotEmpty(productId)) {
condList.add(EntityCondition.makeCondition("productIdTo", productId));
}
if (UtilValidate.isNotEmpty(virtualVariantId)) {
condList.add(EntityCondition.makeCondition("productId", virtualVariantId));
}
condList.add(EntityCondition.makeCondition("productAssocTypeId", "ALTERNATIVE_PACKAGE"));
alternativePackingProds = EntityQuery.use(delegator).from("ProductAssoc").where(condList).cache(true).queryList();
if(UtilValidate.isNotEmpty(alternativePackingProds)) isAlternativePacking = true;
} catch (GenericEntityException e) {
Debug.logWarning(e, "Could not found alternative product: " + e.getMessage(), module);
}
}
return isAlternativePacking;
}
public static String getOriginalProductId(Delegator delegator, String productId){
boolean isAlternativePacking = isAlternativePacking(delegator, null, productId);
if (isAlternativePacking) {
List<GenericValue> productAssocs = null;
try {
productAssocs = EntityQuery.use(delegator).from("ProductAssoc").where("productId", productId , "productAssocTypeId", "ALTERNATIVE_PACKAGE").filterByDate().queryList();
} catch (GenericEntityException e) {
Debug.logError(e, module);
}
if (productAssocs != null) {
GenericValue productAssoc = EntityUtil.getFirst(productAssocs);
return productAssoc.getString("productIdTo");
} else {
return null;
}
}else{
return null;
}
}
/**
* worker to test if product can be order with a decimal quantity
* @param delegator : access to DB
* @param productId : ref. of product
* * @param productStoreId : ref. of store
* @return true if it can be ordered by decimal quantity
* @throws GenericEntityException to catch
*/
public static Boolean isDecimalQuantityOrderAllowed(Delegator delegator, String productId, String productStoreId) throws GenericEntityException{
//sometime productStoreId may be null (ie PO), then return default value which is TRUE
if(UtilValidate.isEmpty(productStoreId)){
return Boolean.TRUE;
}
String allowDecimalStore = EntityQuery.use(delegator).from("ProductStore").where("productStoreId", productStoreId).cache(true).queryOne().getString("orderDecimalQuantity");
String allowDecimalProduct = EntityQuery.use(delegator).from("Product").where("productId", productId).cache(true).queryOne().getString("orderDecimalQuantity");
if("N".equals(allowDecimalProduct) || (UtilValidate.isEmpty(allowDecimalProduct) && "N".equals(allowDecimalStore))){
return Boolean.FALSE;
}
return Boolean.TRUE;
}
public static boolean isAggregateService(Delegator delegator, String aggregatedProductId) {
try {
GenericValue aggregatedProduct = EntityQuery.use(delegator).from("Product").where("productId", aggregatedProductId).cache().queryOne();
if (UtilValidate.isNotEmpty(aggregatedProduct) && "AGGREGATED_SERVICE".equals(aggregatedProduct.getString("productTypeId"))) {
return true;
}
} catch (GenericEntityException e) {
Debug.logWarning(e.getMessage(), module);
}
return false;
}
// Method to filter-out out of stock products
public static List<GenericValue> filterOutOfStockProducts (List<GenericValue> productsToFilter, LocalDispatcher dispatcher, Delegator delegator) throws GeneralException {
List<GenericValue> productsInStock = new ArrayList<GenericValue>();
if (UtilValidate.isNotEmpty(productsToFilter)) {
for (GenericValue genericRecord : productsToFilter) {
String productId = genericRecord.getString("productId");
GenericValue product = null;
product = EntityQuery.use(delegator).from("Product").where("productId", productId).cache(true).queryOne();
Boolean isMarketingPackage = EntityTypeUtil.hasParentType(delegator, "ProductType", "productTypeId", product.getString("productTypeId"), "parentTypeId", "MARKETING_PKG");
if ( UtilValidate.isNotEmpty(isMarketingPackage) && isMarketingPackage) {
Map<String, Object> resultOutput = new HashMap<String, Object>();
resultOutput = dispatcher.runSync("getMktgPackagesAvailable", UtilMisc.toMap("productId" ,productId));
Debug.logWarning("Error getting available marketing package.", module);
BigDecimal availableInventory = (BigDecimal) resultOutput.get("availableToPromiseTotal");
if(availableInventory.compareTo(BigDecimal.ZERO) > 0) {
productsInStock.add(genericRecord);
}
} else {
List<GenericValue> facilities = EntityQuery.use(delegator).from("ProductFacility").where("productId", productId).queryList();
BigDecimal availableInventory = BigDecimal.ZERO;
if (UtilValidate.isNotEmpty(facilities)) {
for (GenericValue facility : facilities) {
BigDecimal lastInventoryCount = facility.getBigDecimal("lastInventoryCount");
if (lastInventoryCount != null) {
availableInventory = lastInventoryCount.add(availableInventory);
}
}
if (availableInventory.compareTo(BigDecimal.ZERO) > 0) {
productsInStock.add(genericRecord);
}
}
}
}
}
return productsInStock;
}
}