Source Code Cross Referenced for PriceServices.java in  » ERP-CRM-Financial » SourceTap-CRM » org » ofbiz » product » price » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » ERP CRM Financial » SourceTap CRM » org.ofbiz.product.price 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: PriceServices.java,v 1.8 2004/02/26 08:34:35 jonesde Exp $
0003:         *
0004:         *  Copyright (c) 2001-2004 The Open For Business Project - www.ofbiz.org
0005:         *
0006:         *  Permission is hereby granted, free of charge, to any person obtaining a
0007:         *  copy of this software and associated documentation files (the "Software"),
0008:         *  to deal in the Software without restriction, including without limitation
0009:         *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010:         *  and/or sell copies of the Software, and to permit persons to whom the
0011:         *  Software is furnished to do so, subject to the following conditions:
0012:         *
0013:         *  The above copyright notice and this permission notice shall be included
0014:         *  in all copies or substantial portions of the Software.
0015:         *
0016:         *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017:         *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018:         *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019:         *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020:         *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021:         *  OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022:         *  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023:         */
0024:        package org.ofbiz.product.price;
0025:
0026:        import java.sql.Timestamp;
0027:        import java.util.Collection;
0028:        import java.util.HashMap;
0029:        import java.util.Iterator;
0030:        import java.util.LinkedList;
0031:        import java.util.List;
0032:        import java.util.Map;
0033:        import java.util.TreeSet;
0034:
0035:        import org.ofbiz.base.util.Debug;
0036:        import org.ofbiz.base.util.UtilDateTime;
0037:        import org.ofbiz.base.util.UtilMisc;
0038:        import org.ofbiz.base.util.UtilProperties;
0039:        import org.ofbiz.base.util.UtilValidate;
0040:        import org.ofbiz.entity.GenericDelegator;
0041:        import org.ofbiz.entity.GenericEntityException;
0042:        import org.ofbiz.entity.GenericValue;
0043:        import org.ofbiz.entity.util.EntityUtil;
0044:        import org.ofbiz.product.product.ProductWorker;
0045:        import org.ofbiz.service.DispatchContext;
0046:        import org.ofbiz.service.ServiceUtil;
0047:
0048:        /**
0049:         * PriceServices - Workers and Services class for product price related functionality
0050:         *
0051:         * @author     <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0052:         * @author     <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0053:         * @version    $Revision: 1.8 $
0054:         * @since      2.0
0055:         */
0056:        public class PriceServices {
0057:            public static final String module = PriceServices.class.getName();
0058:
0059:            /**
0060:             * <p>Calculates the price of a product from pricing rules given the following input, and of course access to the database:</p>
0061:             * <ul>
0062:             *   <li>productId
0063:             *   <li>partyId
0064:             *   <li>prodCatalogId
0065:             *   <li>webSiteId
0066:             *   <li>productStoreGroupId
0067:             *   <li>quantity
0068:             * </ul>
0069:             */
0070:            public static Map calculateProductPrice(DispatchContext dctx,
0071:                    Map context) {
0072:                boolean optimizeForLargeRuleSet = false;
0073:
0074:                // UtilTimer utilTimer = new UtilTimer();
0075:                // utilTimer.timerString("Starting price calc", module);
0076:                // utilTimer.setLog(false);
0077:
0078:                GenericDelegator delegator = dctx.getDelegator();
0079:                Map result = new HashMap();
0080:                Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
0081:
0082:                boolean isSale = false;
0083:                List orderItemPriceInfos = new LinkedList();
0084:
0085:                GenericValue product = (GenericValue) context.get("product");
0086:                String productId = product.getString("productId");
0087:                String prodCatalogId = (String) context.get("prodCatalogId");
0088:                String webSiteId = (String) context.get("webSiteId");
0089:
0090:                String productStoreGroupId = (String) context
0091:                        .get("productStoreGroupId");
0092:                if (UtilValidate.isEmpty(productStoreGroupId))
0093:                    productStoreGroupId = "_NA_";
0094:
0095:                // if currency uom is null get from properties file, if still null assume USD (USD: American Dollar) for now
0096:                String currencyUomId = (String) context.get("currencyUomId");
0097:
0098:                if (currencyUomId == null || currencyUomId.length() == 0) {
0099:                    currencyUomId = UtilProperties.getPropertyValue("general",
0100:                            "currency.uom.id.default", "USD");
0101:                }
0102:
0103:                // if this product is variant, find the virtual product and apply checks to it as well
0104:                String virtualProductId = null;
0105:                if ("Y".equals(product.getString("isVariant"))) {
0106:                    try {
0107:                        virtualProductId = ProductWorker
0108:                                .getVariantVirtualId(product);
0109:                    } catch (GenericEntityException e) {
0110:                        Debug
0111:                                .logError(
0112:                                        e,
0113:                                        "Error getting virtual product id from the database while calculating price",
0114:                                        module);
0115:                        return ServiceUtil
0116:                                .returnError("Error getting virtual product id from the database while calculating price: "
0117:                                        + e.toString());
0118:                    }
0119:                }
0120:
0121:                // get prices for virtual product if one is found; get all ProductPrice entities for this productId and currencyUomId
0122:                List virtualProductPrices = null;
0123:                if (virtualProductId != null) {
0124:                    try {
0125:                        virtualProductPrices = delegator.findByAndCache(
0126:                                "ProductPrice", UtilMisc.toMap("productId",
0127:                                        virtualProductId, "currencyUomId",
0128:                                        currencyUomId, "productStoreGroupId",
0129:                                        productStoreGroupId), UtilMisc
0130:                                        .toList("-fromDate"));
0131:                    } catch (GenericEntityException e) {
0132:                        Debug
0133:                                .logError(
0134:                                        e,
0135:                                        "An error occurred while getting the product prices",
0136:                                        module);
0137:                    }
0138:                    virtualProductPrices = EntityUtil.filterByDate(
0139:                            virtualProductPrices, true);
0140:                }
0141:
0142:                // NOTE: partyId CAN be null
0143:                String partyId = (String) context.get("partyId");
0144:                if (UtilValidate.isEmpty(partyId)
0145:                        && context.get("userLogin") != null) {
0146:                    GenericValue userLogin = (GenericValue) context
0147:                            .get("userLogin");
0148:                    partyId = userLogin.getString("partyId");
0149:                }
0150:
0151:                // check for auto-userlogin for price rules
0152:                if (UtilValidate.isEmpty(partyId)
0153:                        && context.get("autoUserLogin") != null) {
0154:                    GenericValue userLogin = (GenericValue) context
0155:                            .get("autoUserLogin");
0156:                    partyId = userLogin.getString("partyId");
0157:                }
0158:
0159:                Double quantityDbl = (Double) context.get("quantity");
0160:                if (quantityDbl == null)
0161:                    quantityDbl = new Double(1.0);
0162:                double quantity = quantityDbl.doubleValue();
0163:
0164:                // for prices, get all ProductPrice entities for this productId and currencyUomId
0165:                List productPrices = null;
0166:                try {
0167:                    productPrices = delegator
0168:                            .findByAndCache("ProductPrice", UtilMisc.toMap(
0169:                                    "productId", productId, "currencyUomId",
0170:                                    currencyUomId, "productStoreGroupId",
0171:                                    productStoreGroupId), UtilMisc
0172:                                    .toList("-fromDate"));
0173:                } catch (GenericEntityException e) {
0174:                    Debug
0175:                            .logError(
0176:                                    e,
0177:                                    "An error occurred while getting the product prices",
0178:                                    module);
0179:                }
0180:                productPrices = EntityUtil.filterByDate(productPrices, true);
0181:
0182:                // ===== get the prices we need: list, default, average cost, promo, min, max =====
0183:                List listPrices = EntityUtil.filterByAnd(productPrices,
0184:                        UtilMisc.toMap("productPriceTypeId", "LIST_PRICE"));
0185:                GenericValue listPriceValue = EntityUtil.getFirst(listPrices);
0186:                if (listPrices != null && listPrices.size() > 1) {
0187:                    if (Debug.infoOn())
0188:                        Debug
0189:                                .logInfo(
0190:                                        "There is more than one LIST_PRICE with the currencyUomId "
0191:                                                + currencyUomId
0192:                                                + " and productId "
0193:                                                + productId
0194:                                                + ", using the latest found with price: "
0195:                                                + listPriceValue
0196:                                                        .getDouble("price"),
0197:                                        module);
0198:                }
0199:
0200:                List defaultPrices = EntityUtil.filterByAnd(productPrices,
0201:                        UtilMisc.toMap("productPriceTypeId", "DEFAULT_PRICE"));
0202:                GenericValue defaultPriceValue = EntityUtil
0203:                        .getFirst(defaultPrices);
0204:                if (defaultPrices != null && defaultPrices.size() > 1) {
0205:                    if (Debug.infoOn())
0206:                        Debug
0207:                                .logInfo(
0208:                                        "There is more than one DEFAULT_PRICE with the currencyUomId "
0209:                                                + currencyUomId
0210:                                                + " and productId "
0211:                                                + productId
0212:                                                + ", using the latest found with price: "
0213:                                                + defaultPriceValue
0214:                                                        .getDouble("price"),
0215:                                        module);
0216:                }
0217:
0218:                List averageCosts = EntityUtil.filterByAnd(productPrices,
0219:                        UtilMisc.toMap("productPriceTypeId", "AVERAGE_COST"));
0220:                GenericValue averageCostValue = EntityUtil
0221:                        .getFirst(averageCosts);
0222:                if (averageCosts != null && averageCosts.size() > 1) {
0223:                    if (Debug.infoOn())
0224:                        Debug
0225:                                .logInfo(
0226:                                        "There is more than one AVERAGE_COST with the currencyUomId "
0227:                                                + currencyUomId
0228:                                                + " and productId "
0229:                                                + productId
0230:                                                + ", using the latest found with price: "
0231:                                                + averageCostValue
0232:                                                        .getDouble("price"),
0233:                                        module);
0234:                }
0235:
0236:                List promoPrices = EntityUtil.filterByAnd(productPrices,
0237:                        UtilMisc.toMap("productPriceTypeId", "PROMO_PRICE"));
0238:                GenericValue promoPriceValue = EntityUtil.getFirst(promoPrices);
0239:                if (promoPrices != null && promoPrices.size() > 1) {
0240:                    if (Debug.infoOn())
0241:                        Debug
0242:                                .logInfo(
0243:                                        "There is more than one PROMO_PRICE with the currencyUomId "
0244:                                                + currencyUomId
0245:                                                + " and productId "
0246:                                                + productId
0247:                                                + ", using the latest found with price: "
0248:                                                + promoPriceValue
0249:                                                        .getDouble("price"),
0250:                                        module);
0251:                }
0252:
0253:                List minimumPrices = EntityUtil.filterByAnd(productPrices,
0254:                        UtilMisc.toMap("productPriceTypeId", "MINIMUM_PRICE"));
0255:                GenericValue minimumPriceValue = EntityUtil
0256:                        .getFirst(minimumPrices);
0257:                if (minimumPrices != null && minimumPrices.size() > 1) {
0258:                    if (Debug.infoOn())
0259:                        Debug
0260:                                .logInfo(
0261:                                        "There is more than one MINIMUM_PRICE with the currencyUomId "
0262:                                                + currencyUomId
0263:                                                + " and productId "
0264:                                                + productId
0265:                                                + ", using the latest found with price: "
0266:                                                + minimumPriceValue
0267:                                                        .getDouble("price"),
0268:                                        module);
0269:                }
0270:
0271:                List maximumPrices = EntityUtil.filterByAnd(productPrices,
0272:                        UtilMisc.toMap("productPriceTypeId", "MAXIMUM_PRICE"));
0273:                GenericValue maximumPriceValue = EntityUtil
0274:                        .getFirst(maximumPrices);
0275:                if (maximumPrices != null && maximumPrices.size() > 1) {
0276:                    if (Debug.infoOn())
0277:                        Debug
0278:                                .logInfo(
0279:                                        "There is more than one MAXIMUM_PRICE with the currencyUomId "
0280:                                                + currencyUomId
0281:                                                + " and productId "
0282:                                                + productId
0283:                                                + ", using the latest found with price: "
0284:                                                + maximumPriceValue
0285:                                                        .getDouble("price"),
0286:                                        module);
0287:                }
0288:
0289:                // if any of these prices is missing and this product is a variant, default to the corresponding price on the virtual product
0290:                if (virtualProductPrices != null
0291:                        && virtualProductPrices.size() > 0) {
0292:                    if (listPriceValue == null) {
0293:                        List virtualTempPrices = EntityUtil.filterByAnd(
0294:                                virtualProductPrices, UtilMisc.toMap(
0295:                                        "productPriceTypeId", "LIST_PRICE"));
0296:                        listPriceValue = EntityUtil.getFirst(virtualTempPrices);
0297:                        if (virtualTempPrices != null
0298:                                && virtualTempPrices.size() > 1) {
0299:                            if (Debug.infoOn())
0300:                                Debug
0301:                                        .logInfo(
0302:                                                "There is more than one LIST_PRICE with the currencyUomId "
0303:                                                        + currencyUomId
0304:                                                        + " and productId "
0305:                                                        + virtualProductId
0306:                                                        + ", using the latest found with price: "
0307:                                                        + listPriceValue
0308:                                                                .getDouble("price"),
0309:                                                module);
0310:                        }
0311:                    }
0312:                    if (defaultPriceValue == null) {
0313:                        List virtualTempPrices = EntityUtil.filterByAnd(
0314:                                virtualProductPrices, UtilMisc.toMap(
0315:                                        "productPriceTypeId", "DEFAULT_PRICE"));
0316:                        defaultPriceValue = EntityUtil
0317:                                .getFirst(virtualTempPrices);
0318:                        if (virtualTempPrices != null
0319:                                && virtualTempPrices.size() > 1) {
0320:                            if (Debug.infoOn())
0321:                                Debug
0322:                                        .logInfo(
0323:                                                "There is more than one DEFAULT_PRICE with the currencyUomId "
0324:                                                        + currencyUomId
0325:                                                        + " and productId "
0326:                                                        + virtualProductId
0327:                                                        + ", using the latest found with price: "
0328:                                                        + defaultPriceValue
0329:                                                                .getDouble("price"),
0330:                                                module);
0331:                        }
0332:                    }
0333:                    if (averageCostValue == null) {
0334:                        List virtualTempPrices = EntityUtil.filterByAnd(
0335:                                virtualProductPrices, UtilMisc.toMap(
0336:                                        "productPriceTypeId", "AVERAGE_COST"));
0337:                        averageCostValue = EntityUtil
0338:                                .getFirst(virtualTempPrices);
0339:                        if (virtualTempPrices != null
0340:                                && virtualTempPrices.size() > 1) {
0341:                            if (Debug.infoOn())
0342:                                Debug
0343:                                        .logInfo(
0344:                                                "There is more than one AVERAGE_COST with the currencyUomId "
0345:                                                        + currencyUomId
0346:                                                        + " and productId "
0347:                                                        + virtualProductId
0348:                                                        + ", using the latest found with price: "
0349:                                                        + averageCostValue
0350:                                                                .getDouble("price"),
0351:                                                module);
0352:                        }
0353:                    }
0354:                    if (promoPriceValue == null) {
0355:                        List virtualTempPrices = EntityUtil.filterByAnd(
0356:                                virtualProductPrices, UtilMisc.toMap(
0357:                                        "productPriceTypeId", "PROMO_PRICE"));
0358:                        promoPriceValue = EntityUtil
0359:                                .getFirst(virtualTempPrices);
0360:                        if (virtualTempPrices != null
0361:                                && virtualTempPrices.size() > 1) {
0362:                            if (Debug.infoOn())
0363:                                Debug
0364:                                        .logInfo(
0365:                                                "There is more than one PROMO_PRICE with the currencyUomId "
0366:                                                        + currencyUomId
0367:                                                        + " and productId "
0368:                                                        + virtualProductId
0369:                                                        + ", using the latest found with price: "
0370:                                                        + promoPriceValue
0371:                                                                .getDouble("price"),
0372:                                                module);
0373:                        }
0374:                    }
0375:                    if (minimumPriceValue == null) {
0376:                        List virtualTempPrices = EntityUtil.filterByAnd(
0377:                                virtualProductPrices, UtilMisc.toMap(
0378:                                        "productPriceTypeId", "MINIMUM_PRICE"));
0379:                        minimumPriceValue = EntityUtil
0380:                                .getFirst(virtualTempPrices);
0381:                        if (virtualTempPrices != null
0382:                                && virtualTempPrices.size() > 1) {
0383:                            if (Debug.infoOn())
0384:                                Debug
0385:                                        .logInfo(
0386:                                                "There is more than one MINIMUM_PRICE with the currencyUomId "
0387:                                                        + currencyUomId
0388:                                                        + " and productId "
0389:                                                        + virtualProductId
0390:                                                        + ", using the latest found with price: "
0391:                                                        + minimumPriceValue
0392:                                                                .getDouble("price"),
0393:                                                module);
0394:                        }
0395:                    }
0396:                    if (maximumPriceValue == null) {
0397:                        List virtualTempPrices = EntityUtil.filterByAnd(
0398:                                virtualProductPrices, UtilMisc.toMap(
0399:                                        "productPriceTypeId", "MAXIMUM_PRICE"));
0400:                        maximumPriceValue = EntityUtil
0401:                                .getFirst(virtualTempPrices);
0402:                        if (virtualTempPrices != null
0403:                                && virtualTempPrices.size() > 1) {
0404:                            if (Debug.infoOn())
0405:                                Debug
0406:                                        .logInfo(
0407:                                                "There is more than one MAXIMUM_PRICE with the currencyUomId "
0408:                                                        + currencyUomId
0409:                                                        + " and productId "
0410:                                                        + virtualProductId
0411:                                                        + ", using the latest found with price: "
0412:                                                        + maximumPriceValue
0413:                                                                .getDouble("price"),
0414:                                                module);
0415:                        }
0416:                    }
0417:                }
0418:
0419:                // now if this is a virtual product check each price type, if doesn't exist get from variant with lowest DEFAULT_PRICE
0420:                if ("Y".equals(product.getString("isVirtual"))) {
0421:                    // only do this if there is no default price, consider the others optional for performance reasons
0422:                    if (defaultPriceValue == null) {
0423:                        // Debug.logInfo("Product isVirtual and there is no default price for ID " + productId + ", trying variant prices", module);
0424:
0425:                        //use the cache to find the variant with the lowest default price
0426:                        try {
0427:                            List variantAssocList = EntityUtil
0428:                                    .filterByDate(delegator.findByAndCache(
0429:                                            "ProductAssoc", UtilMisc.toMap(
0430:                                                    "productId", product
0431:                                                            .get("productId"),
0432:                                                    "productAssocTypeId",
0433:                                                    "PRODUCT_VARIANT"),
0434:                                            UtilMisc.toList("-fromDate")));
0435:                            Iterator variantAssocIter = variantAssocList
0436:                                    .iterator();
0437:                            double minDefaultPrice = Double.MAX_VALUE;
0438:                            List variantProductPrices = null;
0439:                            String variantProductId = null;
0440:                            while (variantAssocIter.hasNext()) {
0441:                                GenericValue variantAssoc = (GenericValue) variantAssocIter
0442:                                        .next();
0443:                                String curVariantProductId = variantAssoc
0444:                                        .getString("productIdTo");
0445:                                List curVariantPriceList = EntityUtil
0446:                                        .filterByDate(delegator.findByAndCache(
0447:                                                "ProductPrice", UtilMisc.toMap(
0448:                                                        "productId",
0449:                                                        curVariantProductId),
0450:                                                UtilMisc.toList("-fromDate")),
0451:                                                nowTimestamp);
0452:                                List tempDefaultPriceList = EntityUtil
0453:                                        .filterByAnd(curVariantPriceList,
0454:                                                UtilMisc.toMap(
0455:                                                        "productPriceTypeId",
0456:                                                        "DEFAULT_PRICE"));
0457:                                GenericValue curDefaultPriceValue = EntityUtil
0458:                                        .getFirst(tempDefaultPriceList);
0459:                                if (curDefaultPriceValue != null) {
0460:                                    Double curDefaultPrice = curDefaultPriceValue
0461:                                            .getDouble("price");
0462:                                    if (curDefaultPrice.doubleValue() < minDefaultPrice) {
0463:                                        // check to see if the product is discontinued for sale before considering it the lowest price
0464:                                        GenericValue curVariantProduct = delegator
0465:                                                .findByPrimaryKeyCache(
0466:                                                        "Product",
0467:                                                        UtilMisc
0468:                                                                .toMap(
0469:                                                                        "productId",
0470:                                                                        curVariantProductId));
0471:                                        if (curVariantProduct != null) {
0472:                                            Timestamp salesDiscontinuationDate = curVariantProduct
0473:                                                    .getTimestamp("salesDiscontinuationDate");
0474:                                            if (salesDiscontinuationDate == null
0475:                                                    || salesDiscontinuationDate
0476:                                                            .after(nowTimestamp)) {
0477:                                                minDefaultPrice = curDefaultPrice
0478:                                                        .doubleValue();
0479:                                                variantProductPrices = curVariantPriceList;
0480:                                                variantProductId = curVariantProductId;
0481:                                                // Debug.logInfo("Found new lowest price " + minDefaultPrice + " for variant with ID " + variantProductId, module);
0482:                                            }
0483:                                        }
0484:                                    }
0485:                                }
0486:                            }
0487:
0488:                            if (variantProductPrices != null) {
0489:                                // we have some other options, give 'em a go...
0490:                                if (listPriceValue == null) {
0491:                                    List virtualTempPrices = EntityUtil
0492:                                            .filterByAnd(
0493:                                                    variantProductPrices,
0494:                                                    UtilMisc
0495:                                                            .toMap(
0496:                                                                    "productPriceTypeId",
0497:                                                                    "LIST_PRICE"));
0498:                                    listPriceValue = EntityUtil
0499:                                            .getFirst(virtualTempPrices);
0500:                                    if (virtualTempPrices != null
0501:                                            && virtualTempPrices.size() > 1) {
0502:                                        if (Debug.infoOn())
0503:                                            Debug
0504:                                                    .logInfo(
0505:                                                            "There is more than one LIST_PRICE with the currencyUomId "
0506:                                                                    + currencyUomId
0507:                                                                    + " and productId "
0508:                                                                    + variantProductId
0509:                                                                    + ", using the latest found with price: "
0510:                                                                    + listPriceValue
0511:                                                                            .getDouble("price"),
0512:                                                            module);
0513:                                    }
0514:                                }
0515:                                if (defaultPriceValue == null) {
0516:                                    List virtualTempPrices = EntityUtil
0517:                                            .filterByAnd(
0518:                                                    variantProductPrices,
0519:                                                    UtilMisc
0520:                                                            .toMap(
0521:                                                                    "productPriceTypeId",
0522:                                                                    "DEFAULT_PRICE"));
0523:                                    defaultPriceValue = EntityUtil
0524:                                            .getFirst(virtualTempPrices);
0525:                                    if (virtualTempPrices != null
0526:                                            && virtualTempPrices.size() > 1) {
0527:                                        if (Debug.infoOn())
0528:                                            Debug
0529:                                                    .logInfo(
0530:                                                            "There is more than one DEFAULT_PRICE with the currencyUomId "
0531:                                                                    + currencyUomId
0532:                                                                    + " and productId "
0533:                                                                    + variantProductId
0534:                                                                    + ", using the latest found with price: "
0535:                                                                    + defaultPriceValue
0536:                                                                            .getDouble("price"),
0537:                                                            module);
0538:                                    }
0539:                                }
0540:                                if (averageCostValue == null) {
0541:                                    List virtualTempPrices = EntityUtil
0542:                                            .filterByAnd(
0543:                                                    variantProductPrices,
0544:                                                    UtilMisc
0545:                                                            .toMap(
0546:                                                                    "productPriceTypeId",
0547:                                                                    "AVERAGE_COST"));
0548:                                    averageCostValue = EntityUtil
0549:                                            .getFirst(virtualTempPrices);
0550:                                    if (virtualTempPrices != null
0551:                                            && virtualTempPrices.size() > 1) {
0552:                                        if (Debug.infoOn())
0553:                                            Debug
0554:                                                    .logInfo(
0555:                                                            "There is more than one AVERAGE_COST with the currencyUomId "
0556:                                                                    + currencyUomId
0557:                                                                    + " and productId "
0558:                                                                    + variantProductId
0559:                                                                    + ", using the latest found with price: "
0560:                                                                    + averageCostValue
0561:                                                                            .getDouble("price"),
0562:                                                            module);
0563:                                    }
0564:                                }
0565:                                if (promoPriceValue == null) {
0566:                                    List virtualTempPrices = EntityUtil
0567:                                            .filterByAnd(
0568:                                                    variantProductPrices,
0569:                                                    UtilMisc
0570:                                                            .toMap(
0571:                                                                    "productPriceTypeId",
0572:                                                                    "PROMO_PRICE"));
0573:                                    promoPriceValue = EntityUtil
0574:                                            .getFirst(virtualTempPrices);
0575:                                    if (virtualTempPrices != null
0576:                                            && virtualTempPrices.size() > 1) {
0577:                                        if (Debug.infoOn())
0578:                                            Debug
0579:                                                    .logInfo(
0580:                                                            "There is more than one PROMO_PRICE with the currencyUomId "
0581:                                                                    + currencyUomId
0582:                                                                    + " and productId "
0583:                                                                    + variantProductId
0584:                                                                    + ", using the latest found with price: "
0585:                                                                    + promoPriceValue
0586:                                                                            .getDouble("price"),
0587:                                                            module);
0588:                                    }
0589:                                }
0590:                                if (minimumPriceValue == null) {
0591:                                    List virtualTempPrices = EntityUtil
0592:                                            .filterByAnd(
0593:                                                    variantProductPrices,
0594:                                                    UtilMisc
0595:                                                            .toMap(
0596:                                                                    "productPriceTypeId",
0597:                                                                    "MINIMUM_PRICE"));
0598:                                    minimumPriceValue = EntityUtil
0599:                                            .getFirst(virtualTempPrices);
0600:                                    if (virtualTempPrices != null
0601:                                            && virtualTempPrices.size() > 1) {
0602:                                        if (Debug.infoOn())
0603:                                            Debug
0604:                                                    .logInfo(
0605:                                                            "There is more than one MINIMUM_PRICE with the currencyUomId "
0606:                                                                    + currencyUomId
0607:                                                                    + " and productId "
0608:                                                                    + variantProductId
0609:                                                                    + ", using the latest found with price: "
0610:                                                                    + minimumPriceValue
0611:                                                                            .getDouble("price"),
0612:                                                            module);
0613:                                    }
0614:                                }
0615:                                if (maximumPriceValue == null) {
0616:                                    List virtualTempPrices = EntityUtil
0617:                                            .filterByAnd(
0618:                                                    variantProductPrices,
0619:                                                    UtilMisc
0620:                                                            .toMap(
0621:                                                                    "productPriceTypeId",
0622:                                                                    "MAXIMUM_PRICE"));
0623:                                    maximumPriceValue = EntityUtil
0624:                                            .getFirst(virtualTempPrices);
0625:                                    if (virtualTempPrices != null
0626:                                            && virtualTempPrices.size() > 1) {
0627:                                        if (Debug.infoOn())
0628:                                            Debug
0629:                                                    .logInfo(
0630:                                                            "There is more than one MAXIMUM_PRICE with the currencyUomId "
0631:                                                                    + currencyUomId
0632:                                                                    + " and productId "
0633:                                                                    + variantProductId
0634:                                                                    + ", using the latest found with price: "
0635:                                                                    + maximumPriceValue
0636:                                                                            .getDouble("price"),
0637:                                                            module);
0638:                                    }
0639:                                }
0640:                            }
0641:                        } catch (GenericEntityException e) {
0642:                            Debug
0643:                                    .logError(
0644:                                            e,
0645:                                            "An error occurred while getting the product prices",
0646:                                            module);
0647:                        }
0648:                    }
0649:                }
0650:
0651:                double promoPrice = (promoPriceValue != null && promoPriceValue
0652:                        .get("price") != null) ? promoPriceValue.getDouble(
0653:                        "price").doubleValue() : 0;
0654:                double defaultPrice = (defaultPriceValue != null && defaultPriceValue
0655:                        .get("price") != null) ? defaultPriceValue.getDouble(
0656:                        "price").doubleValue() : 0;
0657:                Double listPriceDbl = listPriceValue != null ? listPriceValue
0658:                        .getDouble("price") : null;
0659:
0660:                if (listPriceDbl == null) {
0661:                    // no list price, use defaultPrice for the final price
0662:
0663:                    // ========= ensure calculated price is not below minSalePrice or above maxSalePrice =========
0664:                    Double maxSellPrice = maximumPriceValue != null ? maximumPriceValue
0665:                            .getDouble("price")
0666:                            : null;
0667:
0668:                    if (maxSellPrice != null
0669:                            && defaultPrice > maxSellPrice.doubleValue()) {
0670:                        defaultPrice = maxSellPrice.doubleValue();
0671:                    }
0672:                    // min price second to override max price, safety net
0673:                    Double minSellPrice = minimumPriceValue != null ? minimumPriceValue
0674:                            .getDouble("price")
0675:                            : null;
0676:
0677:                    if (minSellPrice != null
0678:                            && defaultPrice < minSellPrice.doubleValue()) {
0679:                        defaultPrice = minSellPrice.doubleValue();
0680:                    }
0681:
0682:                    result.put("price", new Double(defaultPrice));
0683:                    result.put("defaultPrice", new Double(defaultPrice));
0684:                    result.put("averageCost",
0685:                            averageCostValue != null ? averageCostValue
0686:                                    .getDouble("price") : null);
0687:                } else {
0688:                    try {
0689:                        // get some of the base values to calculate with
0690:                        double listPrice = listPriceDbl.doubleValue();
0691:                        double averageCost = (averageCostValue != null && averageCostValue
0692:                                .get("price") != null) ? averageCostValue
0693:                                .getDouble("price").doubleValue() : listPrice;
0694:                        double margin = listPrice - averageCost;
0695:
0696:                        // calculate running sum based on listPrice and rules found
0697:                        double price = listPrice;
0698:
0699:                        Collection productPriceRules = null;
0700:
0701:                        // At this point we have two options: optimize for large ruleset, or optimize for small ruleset
0702:                        // NOTE: This only effects the way that the rules to be evaluated are selected.
0703:                        // For large rule sets we can do a cached pre-filter to limit the rules that need to be evaled for a specific product.
0704:                        // Genercally I don't think that rule sets will get that big though, so the default is optimize for smaller rule set.
0705:                        if (optimizeForLargeRuleSet) {
0706:                            // ========= find all rules that must be run for each input type; this is kind of like a pre-filter to slim down the rules to run =========
0707:                            // utilTimer.timerString("Before create rule id list", module);
0708:                            TreeSet productPriceRuleIds = new TreeSet();
0709:
0710:                            // ------- These are all of the conditions that DON'T depend on the current inputs -------
0711:
0712:                            // by productCategoryId
0713:                            // for we will always include any rules that go by category, shouldn't be too many to iterate through each time and will save on cache entries
0714:                            // note that we always want to put the category, quantity, etc ones that find all rules with these conditions in separate cache lists so that they can be easily cleared
0715:                            Collection productCategoryIdConds = delegator
0716:                                    .findByAndCache("ProductPriceCond",
0717:                                            UtilMisc.toMap("inputParamEnumId",
0718:                                                    "PRIP_PROD_CAT_ID"));
0719:
0720:                            if (productCategoryIdConds != null
0721:                                    && productCategoryIdConds.size() > 0) {
0722:                                Iterator productCategoryIdCondsIter = productCategoryIdConds
0723:                                        .iterator();
0724:
0725:                                while (productCategoryIdCondsIter.hasNext()) {
0726:                                    GenericValue productCategoryIdCond = (GenericValue) productCategoryIdCondsIter
0727:                                            .next();
0728:
0729:                                    productPriceRuleIds
0730:                                            .add(productCategoryIdCond
0731:                                                    .getString("productPriceRuleId"));
0732:                                }
0733:                            }
0734:
0735:                            // by quantity -- should we really do this one, ie is it necessary?
0736:                            // we could say that all rules with quantity on them must have one of these other values
0737:                            // but, no we'll do it the other way, any that have a quantity will always get compared
0738:                            Collection quantityConds = delegator
0739:                                    .findByAndCache("ProductPriceCond",
0740:                                            UtilMisc.toMap("inputParamEnumId",
0741:                                                    "PRIP_QUANTITY"));
0742:                            if (quantityConds != null
0743:                                    && quantityConds.size() > 0) {
0744:                                Iterator quantityCondsIter = quantityConds
0745:                                        .iterator();
0746:                                while (quantityCondsIter.hasNext()) {
0747:                                    GenericValue quantityCond = (GenericValue) quantityCondsIter
0748:                                            .next();
0749:                                    productPriceRuleIds.add(quantityCond
0750:                                            .getString("productPriceRuleId"));
0751:                                }
0752:                            }
0753:
0754:                            // by roleTypeId
0755:                            Collection roleTypeIdConds = delegator
0756:                                    .findByAndCache("ProductPriceCond",
0757:                                            UtilMisc.toMap("inputParamEnumId",
0758:                                                    "PRIP_ROLE_TYPE"));
0759:                            if (roleTypeIdConds != null
0760:                                    && roleTypeIdConds.size() > 0) {
0761:                                Iterator roleTypeIdCondsIter = roleTypeIdConds
0762:                                        .iterator();
0763:                                while (roleTypeIdCondsIter.hasNext()) {
0764:                                    GenericValue roleTypeIdCond = (GenericValue) roleTypeIdCondsIter
0765:                                            .next();
0766:                                    productPriceRuleIds.add(roleTypeIdCond
0767:                                            .getString("productPriceRuleId"));
0768:                                }
0769:                            }
0770:
0771:                            // TODO, not supported yet: by groupPartyId
0772:                            // TODO, not supported yet: by partyClassificationGroupId
0773:                            // later: (by partyClassificationTypeId)
0774:
0775:                            // by listPrice
0776:                            Collection listPriceConds = delegator
0777:                                    .findByAndCache("ProductPriceCond",
0778:                                            UtilMisc.toMap("inputParamEnumId",
0779:                                                    "PRIP_LIST_PRICE"));
0780:                            if (listPriceConds != null
0781:                                    && listPriceConds.size() > 0) {
0782:                                Iterator listPriceCondsIter = listPriceConds
0783:                                        .iterator();
0784:                                while (listPriceCondsIter.hasNext()) {
0785:                                    GenericValue listPriceCond = (GenericValue) listPriceCondsIter
0786:                                            .next();
0787:                                    productPriceRuleIds.add(listPriceCond
0788:                                            .getString("productPriceRuleId"));
0789:                                }
0790:                            }
0791:
0792:                            // ------- These are all of them that DO depend on the current inputs -------
0793:
0794:                            // by productId
0795:                            Collection productIdConds = delegator
0796:                                    .findByAndCache("ProductPriceCond",
0797:                                            UtilMisc.toMap("inputParamEnumId",
0798:                                                    "PRIP_PRODUCT_ID",
0799:                                                    "condValue", productId));
0800:                            if (productIdConds != null
0801:                                    && productIdConds.size() > 0) {
0802:                                Iterator productIdCondsIter = productIdConds
0803:                                        .iterator();
0804:                                while (productIdCondsIter.hasNext()) {
0805:                                    GenericValue productIdCond = (GenericValue) productIdCondsIter
0806:                                            .next();
0807:                                    productPriceRuleIds.add(productIdCond
0808:                                            .getString("productPriceRuleId"));
0809:                                }
0810:                            }
0811:
0812:                            // by virtualProductId, if not null
0813:                            if (virtualProductId != null) {
0814:                                Collection virtualProductIdConds = delegator
0815:                                        .findByAndCache("ProductPriceCond",
0816:                                                UtilMisc.toMap(
0817:                                                        "inputParamEnumId",
0818:                                                        "PRIP_PRODUCT_ID",
0819:                                                        "condValue",
0820:                                                        virtualProductId));
0821:                                if (virtualProductIdConds != null
0822:                                        && virtualProductIdConds.size() > 0) {
0823:                                    Iterator virtualProductIdCondsIter = virtualProductIdConds
0824:                                            .iterator();
0825:                                    while (virtualProductIdCondsIter.hasNext()) {
0826:                                        GenericValue virtualProductIdCond = (GenericValue) virtualProductIdCondsIter
0827:                                                .next();
0828:                                        productPriceRuleIds
0829:                                                .add(virtualProductIdCond
0830:                                                        .getString("productPriceRuleId"));
0831:                                    }
0832:                                }
0833:                            }
0834:
0835:                            // by prodCatalogId - which is optional in certain cases
0836:                            if (UtilValidate.isNotEmpty(prodCatalogId)) {
0837:                                Collection prodCatalogIdConds = delegator
0838:                                        .findByAndCache("ProductPriceCond",
0839:                                                UtilMisc.toMap(
0840:                                                        "inputParamEnumId",
0841:                                                        "PRIP_PROD_CLG_ID",
0842:                                                        "condValue",
0843:                                                        prodCatalogId));
0844:                                if (prodCatalogIdConds != null
0845:                                        && prodCatalogIdConds.size() > 0) {
0846:                                    Iterator prodCatalogIdCondsIter = prodCatalogIdConds
0847:                                            .iterator();
0848:                                    while (prodCatalogIdCondsIter.hasNext()) {
0849:                                        GenericValue prodCatalogIdCond = (GenericValue) prodCatalogIdCondsIter
0850:                                                .next();
0851:                                        productPriceRuleIds
0852:                                                .add(prodCatalogIdCond
0853:                                                        .getString("productPriceRuleId"));
0854:                                    }
0855:                                }
0856:                            }
0857:
0858:                            // by webSiteId
0859:                            Collection webSiteIdConds = delegator
0860:                                    .findByAndCache("ProductPriceCond",
0861:                                            UtilMisc.toMap("inputParamEnumId",
0862:                                                    "PRIP_WEBSITE_ID",
0863:                                                    "condValue", webSiteId));
0864:                            if (webSiteIdConds != null
0865:                                    && webSiteIdConds.size() > 0) {
0866:                                Iterator webSiteIdCondsIter = webSiteIdConds
0867:                                        .iterator();
0868:                                while (webSiteIdCondsIter.hasNext()) {
0869:                                    GenericValue webSiteIdCond = (GenericValue) webSiteIdCondsIter
0870:                                            .next();
0871:                                    productPriceRuleIds.add(webSiteIdCond
0872:                                            .getString("productPriceRuleId"));
0873:                                }
0874:                            }
0875:
0876:                            // by partyId
0877:                            if (partyId != null) {
0878:                                Collection partyIdConds = delegator
0879:                                        .findByAndCache("ProductPriceCond",
0880:                                                UtilMisc.toMap(
0881:                                                        "inputParamEnumId",
0882:                                                        "PRIP_PARTY_ID",
0883:                                                        "condValue", partyId));
0884:                                if (partyIdConds != null
0885:                                        && partyIdConds.size() > 0) {
0886:                                    Iterator partyIdCondsIter = partyIdConds
0887:                                            .iterator();
0888:                                    while (partyIdCondsIter.hasNext()) {
0889:                                        GenericValue partyIdCond = (GenericValue) partyIdCondsIter
0890:                                                .next();
0891:                                        productPriceRuleIds
0892:                                                .add(partyIdCond
0893:                                                        .getString("productPriceRuleId"));
0894:                                    }
0895:                                }
0896:                            }
0897:
0898:                            // by currencyUomId
0899:                            Collection currencyUomIdConds = delegator
0900:                                    .findByAndCache("ProductPriceCond",
0901:                                            UtilMisc.toMap("inputParamEnumId",
0902:                                                    "PRIP_CURRENCY_UOMID",
0903:                                                    "condValue", currencyUomId));
0904:                            if (currencyUomIdConds != null
0905:                                    && currencyUomIdConds.size() > 0) {
0906:                                Iterator currencyUomIdCondsIter = currencyUomIdConds
0907:                                        .iterator();
0908:                                while (currencyUomIdCondsIter.hasNext()) {
0909:                                    GenericValue currencyUomIdCond = (GenericValue) currencyUomIdCondsIter
0910:                                            .next();
0911:                                    productPriceRuleIds.add(currencyUomIdCond
0912:                                            .getString("productPriceRuleId"));
0913:                                }
0914:                            }
0915:
0916:                            productPriceRules = new LinkedList();
0917:                            Iterator productPriceRuleIdsIter = productPriceRuleIds
0918:                                    .iterator();
0919:                            while (productPriceRuleIdsIter.hasNext()) {
0920:                                String productPriceRuleId = (String) productPriceRuleIdsIter
0921:                                        .next();
0922:                                GenericValue productPriceRule = delegator
0923:                                        .findByPrimaryKeyCache(
0924:                                                "ProductPriceRule",
0925:                                                UtilMisc.toMap(
0926:                                                        "productPriceRuleId",
0927:                                                        productPriceRuleId));
0928:                                if (productPriceRule == null)
0929:                                    continue;
0930:                                productPriceRules.add(productPriceRule);
0931:                            }
0932:                        } else {
0933:                            // this would be nice, but we can't cache this so easily...
0934:                            // List pprExprs = UtilMisc.toList(new EntityExpr("thruDate", EntityOperator.EQUALS, null),
0935:                            // new EntityExpr("thruDate", EntityOperator.GREATER_THAN, UtilDateTime.nowTimestamp()));
0936:                            // productPriceRules = delegator.findByOr("ProductPriceRule", pprExprs);
0937:
0938:                            productPriceRules = delegator
0939:                                    .findAllCache("ProductPriceRule");
0940:                            if (productPriceRules == null)
0941:                                productPriceRules = new LinkedList();
0942:                        }
0943:
0944:                        // ========= go through each price rule by id and eval all conditions =========
0945:                        // utilTimer.timerString("Before eval rules", module);
0946:                        int totalConds = 0;
0947:                        int totalActions = 0;
0948:                        int totalRules = 0;
0949:
0950:                        Iterator productPriceRulesIter = productPriceRules
0951:                                .iterator();
0952:
0953:                        while (productPriceRulesIter.hasNext()) {
0954:                            GenericValue productPriceRule = (GenericValue) productPriceRulesIter
0955:                                    .next();
0956:                            String productPriceRuleId = productPriceRule
0957:                                    .getString("productPriceRuleId");
0958:
0959:                            // check from/thru dates
0960:                            java.sql.Timestamp fromDate = productPriceRule
0961:                                    .getTimestamp("fromDate");
0962:                            java.sql.Timestamp thruDate = productPriceRule
0963:                                    .getTimestamp("thruDate");
0964:
0965:                            if (fromDate != null
0966:                                    && fromDate.after(nowTimestamp)) {
0967:                                // hasn't started yet
0968:                                continue;
0969:                            }
0970:                            if (thruDate != null
0971:                                    && thruDate.before(nowTimestamp)) {
0972:                                // already expired
0973:                                continue;
0974:                            }
0975:
0976:                            // check all conditions
0977:                            boolean allTrue = true;
0978:                            StringBuffer condsDescription = new StringBuffer();
0979:                            Collection productPriceConds = delegator
0980:                                    .findByAndCache("ProductPriceCond",
0981:                                            UtilMisc.toMap(
0982:                                                    "productPriceRuleId",
0983:                                                    productPriceRuleId));
0984:                            Iterator productPriceCondsIter = UtilMisc
0985:                                    .toIterator(productPriceConds);
0986:
0987:                            while (productPriceCondsIter != null
0988:                                    && productPriceCondsIter.hasNext()) {
0989:                                GenericValue productPriceCond = (GenericValue) productPriceCondsIter
0990:                                        .next();
0991:
0992:                                totalConds++;
0993:
0994:                                if (!checkPriceCondition(productPriceCond,
0995:                                        productId, prodCatalogId, webSiteId,
0996:                                        partyId, quantity, listPrice,
0997:                                        currencyUomId, delegator)) {
0998:                                    // if there is a virtualProductId, try that given that this one has failed
0999:                                    if (virtualProductId != null) {
1000:                                        if (!checkPriceCondition(
1001:                                                productPriceCond,
1002:                                                virtualProductId,
1003:                                                prodCatalogId, webSiteId,
1004:                                                partyId, quantity, listPrice,
1005:                                                currencyUomId, delegator)) {
1006:                                            allTrue = false;
1007:                                            break;
1008:                                        }
1009:                                        // otherwise, okay, this one made it so carry on checking
1010:                                    } else {
1011:                                        allTrue = false;
1012:                                        break;
1013:                                    }
1014:                                }
1015:
1016:                                // add condsDescription string entry
1017:                                condsDescription.append("[");
1018:                                GenericValue inputParamEnum = productPriceCond
1019:                                        .getRelatedOneCache("InputParamEnumeration");
1020:
1021:                                condsDescription.append(inputParamEnum
1022:                                        .getString("enumCode"));
1023:                                // condsDescription.append(":");
1024:                                GenericValue operatorEnum = productPriceCond
1025:                                        .getRelatedOneCache("OperatorEnumeration");
1026:
1027:                                condsDescription.append(operatorEnum
1028:                                        .getString("description"));
1029:                                // condsDescription.append(":");
1030:                                condsDescription.append(productPriceCond
1031:                                        .getString("condValue"));
1032:                                condsDescription.append("] ");
1033:                            }
1034:
1035:                            // add some info about the prices we are calculating from
1036:                            condsDescription.append("[list:");
1037:                            condsDescription.append(listPrice);
1038:                            condsDescription.append(";avgCost:");
1039:                            condsDescription.append(averageCost);
1040:                            condsDescription.append(";margin:");
1041:                            condsDescription.append(margin);
1042:                            condsDescription.append("] ");
1043:
1044:                            boolean foundFlatOverride = false;
1045:
1046:                            // if all true, perform all actions
1047:                            if (allTrue) {
1048:                                // check isSale
1049:                                if ("Y".equals(productPriceRule
1050:                                        .getString("isSale"))) {
1051:                                    isSale = true;
1052:                                }
1053:
1054:                                Collection productPriceActions = delegator
1055:                                        .findByAndCache("ProductPriceAction",
1056:                                                UtilMisc.toMap(
1057:                                                        "productPriceRuleId",
1058:                                                        productPriceRuleId));
1059:                                Iterator productPriceActionsIter = UtilMisc
1060:                                        .toIterator(productPriceActions);
1061:
1062:                                while (productPriceActionsIter != null
1063:                                        && productPriceActionsIter.hasNext()) {
1064:                                    GenericValue productPriceAction = (GenericValue) productPriceActionsIter
1065:                                            .next();
1066:
1067:                                    totalActions++;
1068:
1069:                                    // yeah, finally here, perform the action, ie, modify the price
1070:                                    double modifyAmount = 0;
1071:
1072:                                    if ("PRICE_POL"
1073:                                            .equals(productPriceAction
1074:                                                    .getString("productPriceActionTypeId"))) {
1075:                                        if (productPriceAction.get("amount") != null) {
1076:                                            modifyAmount = listPrice
1077:                                                    * (productPriceAction
1078:                                                            .getDouble("amount")
1079:                                                            .doubleValue() / 100.0);
1080:                                        }
1081:                                    } else if ("PRICE_POAC"
1082:                                            .equals(productPriceAction
1083:                                                    .getString("productPriceActionTypeId"))) {
1084:                                        if (productPriceAction.get("amount") != null) {
1085:                                            modifyAmount = averageCost
1086:                                                    * (productPriceAction
1087:                                                            .getDouble("amount")
1088:                                                            .doubleValue() / 100.0);
1089:                                        }
1090:                                    } else if ("PRICE_POM"
1091:                                            .equals(productPriceAction
1092:                                                    .getString("productPriceActionTypeId"))) {
1093:                                        if (productPriceAction.get("amount") != null) {
1094:                                            modifyAmount = margin
1095:                                                    * (productPriceAction
1096:                                                            .getDouble("amount")
1097:                                                            .doubleValue() / 100.0);
1098:                                        }
1099:                                    } else if ("PRICE_FOL"
1100:                                            .equals(productPriceAction
1101:                                                    .getString("productPriceActionTypeId"))) {
1102:                                        if (productPriceAction.get("amount") != null) {
1103:                                            modifyAmount = productPriceAction
1104:                                                    .getDouble("amount")
1105:                                                    .doubleValue();
1106:                                        }
1107:                                    } else if ("PRICE_FLAT"
1108:                                            .equals(productPriceAction
1109:                                                    .getString("productPriceActionTypeId"))) {
1110:                                        // this one is a bit different, break out of the loop because we now have our final price
1111:                                        foundFlatOverride = true;
1112:                                        if (productPriceAction.get("amount") != null) {
1113:                                            price = productPriceAction
1114:                                                    .getDouble("amount")
1115:                                                    .doubleValue();
1116:                                        } else {
1117:                                            Debug
1118:                                                    .logError(
1119:                                                            "ERROR: ProductPriceAction had null amount, using default price: "
1120:                                                                    + defaultPrice
1121:                                                                    + " for product with id "
1122:                                                                    + productId,
1123:                                                            module);
1124:                                            price = defaultPrice;
1125:                                        }
1126:                                    } else if ("PRICE_PFLAT"
1127:                                            .equals(productPriceAction
1128:                                                    .getString("productPriceActionTypeId"))) {
1129:                                        // this one is a bit different too, break out of the loop because we now have our final price
1130:                                        foundFlatOverride = true;
1131:                                        price = promoPrice;
1132:                                        if (productPriceAction.get("amount") != null) {
1133:                                            price += productPriceAction
1134:                                                    .getDouble("amount")
1135:                                                    .doubleValue();
1136:                                        }
1137:                                        if (price == 0.00) {
1138:                                            Debug
1139:                                                    .logError(
1140:                                                            "ERROR: PromoPrice and ProductPriceAction had null amount, using default price: "
1141:                                                                    + defaultPrice
1142:                                                                    + " for product with id "
1143:                                                                    + productId,
1144:                                                            module);
1145:                                            price = defaultPrice;
1146:                                        }
1147:                                    }
1148:
1149:                                    // add a orderItemPriceInfo element too, without orderId or orderItemId
1150:                                    StringBuffer priceInfoDescription = new StringBuffer();
1151:
1152:                                    priceInfoDescription
1153:                                            .append(condsDescription.toString());
1154:                                    priceInfoDescription.append("[type:");
1155:                                    priceInfoDescription
1156:                                            .append(productPriceAction
1157:                                                    .getString("productPriceActionTypeId"));
1158:                                    priceInfoDescription.append("]");
1159:
1160:                                    GenericValue orderItemPriceInfo = delegator
1161:                                            .makeValue("OrderItemPriceInfo",
1162:                                                    null);
1163:
1164:                                    orderItemPriceInfo.set(
1165:                                            "productPriceRuleId",
1166:                                            productPriceAction
1167:                                                    .get("productPriceRuleId"));
1168:                                    orderItemPriceInfo
1169:                                            .set(
1170:                                                    "productPriceActionSeqId",
1171:                                                    productPriceAction
1172:                                                            .get("productPriceActionSeqId"));
1173:                                    orderItemPriceInfo.set("modifyAmount",
1174:                                            new Double(modifyAmount));
1175:                                    // make sure description is <= than 250 chars
1176:                                    String priceInfoDescriptionString = priceInfoDescription
1177:                                            .toString();
1178:
1179:                                    if (priceInfoDescriptionString.length() > 250) {
1180:                                        priceInfoDescriptionString = priceInfoDescriptionString
1181:                                                .substring(0, 250);
1182:                                    }
1183:                                    orderItemPriceInfo.set("description",
1184:                                            priceInfoDescriptionString);
1185:                                    orderItemPriceInfos.add(orderItemPriceInfo);
1186:
1187:                                    if (foundFlatOverride) {
1188:                                        break;
1189:                                    } else {
1190:                                        price += modifyAmount;
1191:                                    }
1192:                                }
1193:                            }
1194:
1195:                            totalRules++;
1196:
1197:                            if (foundFlatOverride) {
1198:                                break;
1199:                            }
1200:                        }
1201:
1202:                        if (Debug.verboseOn()) {
1203:                            Debug.logVerbose("Unchecked Calculated price: "
1204:                                    + price, module);
1205:                            Debug.logVerbose("PriceInfo:", module);
1206:                            Iterator orderItemPriceInfosIter = orderItemPriceInfos
1207:                                    .iterator();
1208:
1209:                            while (orderItemPriceInfosIter.hasNext()) {
1210:                                GenericValue orderItemPriceInfo = (GenericValue) orderItemPriceInfosIter
1211:                                        .next();
1212:
1213:                                Debug
1214:                                        .logVerbose(
1215:                                                " --- "
1216:                                                        + orderItemPriceInfo
1217:                                                                .toString(),
1218:                                                module);
1219:                            }
1220:                        }
1221:
1222:                        // if no actions were run on the list price, then use the default price
1223:                        if (totalActions == 0) {
1224:                            price = defaultPrice;
1225:                        }
1226:
1227:                        // ========= ensure calculated price is not below minSalePrice or above maxSalePrice =========
1228:                        Double maxSellPrice = maximumPriceValue != null ? maximumPriceValue
1229:                                .getDouble("price")
1230:                                : null;
1231:
1232:                        if (maxSellPrice != null
1233:                                && price > maxSellPrice.doubleValue()) {
1234:                            price = maxSellPrice.doubleValue();
1235:                        }
1236:                        // min price second to override max price, safety net
1237:                        Double minSellPrice = minimumPriceValue != null ? minimumPriceValue
1238:                                .getDouble("price")
1239:                                : null;
1240:
1241:                        if (minSellPrice != null
1242:                                && price < minSellPrice.doubleValue()) {
1243:                            price = minSellPrice.doubleValue();
1244:                        }
1245:
1246:                        if (Debug.verboseOn())
1247:                            Debug.logVerbose(
1248:                                    "Final Calculated price: " + price
1249:                                            + ", rules: " + totalRules
1250:                                            + ", conds: " + totalConds
1251:                                            + ", actions: " + totalActions,
1252:                                    module);
1253:
1254:                        result.put("price", new Double(price));
1255:                        result.put("listPrice", new Double(listPrice));
1256:                        result.put("defaultPrice", new Double(defaultPrice));
1257:                        result.put("averageCost", new Double(averageCost));
1258:                    } catch (GenericEntityException e) {
1259:                        Debug
1260:                                .logError(
1261:                                        e,
1262:                                        "Error getting rules from the database while calculating price",
1263:                                        module);
1264:                        return ServiceUtil
1265:                                .returnError("Error getting rules from the database while calculating price: "
1266:                                        + e.toString());
1267:                    }
1268:                }
1269:
1270:                result.put("orderItemPriceInfos", orderItemPriceInfos);
1271:                result.put("isSale", new Boolean(isSale));
1272:                result.put("currencyUsed", currencyUomId);
1273:
1274:                // utilTimer.timerString("Finished price calc [productId=" + productId + "]", module);
1275:                return result;
1276:            }
1277:
1278:            public static boolean checkPriceCondition(
1279:                    GenericValue productPriceCond, String productId,
1280:                    String prodCatalogId, String webSiteId, String partyId,
1281:                    double quantity, double listPrice, String currencyUomId,
1282:                    GenericDelegator delegator) throws GenericEntityException {
1283:                if (Debug.verboseOn())
1284:                    Debug.logVerbose("Checking price condition: "
1285:                            + productPriceCond, module);
1286:                int compare = 0;
1287:
1288:                if ("PRIP_PRODUCT_ID".equals(productPriceCond
1289:                        .getString("inputParamEnumId"))) {
1290:                    compare = productId.compareTo(productPriceCond
1291:                            .getString("condValue"));
1292:                } else if ("PRIP_PROD_CAT_ID".equals(productPriceCond
1293:                        .getString("inputParamEnumId"))) {
1294:                    // if a ProductCategoryMember exists for this productId and the specified productCategoryId
1295:                    List productCategoryMembers = delegator.findByAndCache(
1296:                            "ProductCategoryMember", UtilMisc.toMap(
1297:                                    "productId", productId,
1298:                                    "productCategoryId", productPriceCond
1299:                                            .getString("condValue")));
1300:
1301:                    // and from/thru date within range
1302:                    productCategoryMembers = EntityUtil.filterByDate(
1303:                            productCategoryMembers, true);
1304:                    // then 0 (equals), otherwise 1 (not equals)
1305:                    if (productCategoryMembers != null
1306:                            && productCategoryMembers.size() > 0) {
1307:                        compare = 0;
1308:                    } else {
1309:                        compare = 1;
1310:                    }
1311:                } else if ("PRIP_PROD_CLG_ID".equals(productPriceCond
1312:                        .getString("inputParamEnumId"))) {
1313:                    if (prodCatalogId != null) {
1314:                        compare = prodCatalogId.compareTo(productPriceCond
1315:                                .getString("condValue"));
1316:                    } else {
1317:                        // this shouldn't happen because if prodCatalogId is null no PRIP_PROD_CLG_ID prices will be in the list
1318:                        compare = 1;
1319:                    }
1320:                } else if ("PRIP_WEBSITE_ID".equals(productPriceCond
1321:                        .getString("inputParamEnumId"))) {
1322:                    compare = webSiteId.compareTo(productPriceCond
1323:                            .getString("condValue"));
1324:                } else if ("PRIP_QUANTITY".equals(productPriceCond
1325:                        .getString("inputParamEnumId"))) {
1326:                    Double quantityValue = new Double(quantity);
1327:                    compare = quantityValue.compareTo(Double
1328:                            .valueOf(productPriceCond.getString("condValue")));
1329:                } else if ("PRIP_PARTY_ID".equals(productPriceCond
1330:                        .getString("inputParamEnumId"))) {
1331:                    if (partyId != null) {
1332:                        compare = partyId.compareTo(productPriceCond
1333:                                .getString("condValue"));
1334:                    } else {
1335:                        compare = 1;
1336:                    }
1337:
1338:                    /* These aren't supported yet, ie TODO
1339:                     } else if ("PRIP_PARTY_GRP_MEM".equals(productPriceCond.getString("inputParamEnumId"))) {
1340:                     } else if ("PRIP_PARTY_CLASS".equals(productPriceCond.getString("inputParamEnumId"))) {
1341:                     */
1342:                } else if ("PRIP_ROLE_TYPE".equals(productPriceCond
1343:                        .getString("inputParamEnumId"))) {
1344:                    if (partyId != null) {
1345:                        // if a PartyRole exists for this partyId and the specified roleTypeId
1346:                        GenericValue partyRole = delegator
1347:                                .findByPrimaryKeyCache(
1348:                                        "PartyRole",
1349:                                        UtilMisc
1350:                                                .toMap(
1351:                                                        "partyId",
1352:                                                        partyId,
1353:                                                        "roleTypeId",
1354:                                                        productPriceCond
1355:                                                                .getString("condValue")));
1356:
1357:                        // then 0 (equals), otherwise 1 (not equals)
1358:                        if (partyRole != null) {
1359:                            compare = 0;
1360:                        } else {
1361:                            compare = 1;
1362:                        }
1363:                    } else {
1364:                        compare = 1;
1365:                    }
1366:                } else if ("PRIP_LIST_PRICE".equals(productPriceCond
1367:                        .getString("inputParamEnumId"))) {
1368:                    Double listPriceValue = new Double(listPrice);
1369:
1370:                    compare = listPriceValue.compareTo(Double
1371:                            .valueOf(productPriceCond.getString("condValue")));
1372:                } else if ("PRIP_CURRENCY_UOMID".equals(productPriceCond
1373:                        .getString("inputParamEnumId"))) {
1374:                    compare = currencyUomId.compareTo(productPriceCond
1375:                            .getString("condValue"));
1376:                } else {
1377:                    Debug.logWarning(
1378:                            "An un-supported productPriceCond input parameter (lhs) was used: "
1379:                                    + productPriceCond
1380:                                            .getString("inputParamEnumId")
1381:                                    + ", returning false, ie check failed",
1382:                            module);
1383:                    return false;
1384:                }
1385:
1386:                if (Debug.verboseOn())
1387:                    Debug.logVerbose("Price Condition compare done, compare="
1388:                            + compare, module);
1389:
1390:                if ("PRC_EQ".equals(productPriceCond
1391:                        .getString("operatorEnumId"))) {
1392:                    if (compare == 0)
1393:                        return true;
1394:                } else if ("PRC_NEQ".equals(productPriceCond
1395:                        .getString("operatorEnumId"))) {
1396:                    if (compare != 0)
1397:                        return true;
1398:                } else if ("PRC_LT".equals(productPriceCond
1399:                        .getString("operatorEnumId"))) {
1400:                    if (compare < 0)
1401:                        return true;
1402:                } else if ("PRC_LTE".equals(productPriceCond
1403:                        .getString("operatorEnumId"))) {
1404:                    if (compare <= 0)
1405:                        return true;
1406:                } else if ("PRC_GT".equals(productPriceCond
1407:                        .getString("operatorEnumId"))) {
1408:                    if (compare > 0)
1409:                        return true;
1410:                } else if ("PRC_GTE".equals(productPriceCond
1411:                        .getString("operatorEnumId"))) {
1412:                    if (compare >= 0)
1413:                        return true;
1414:                } else {
1415:                    Debug.logWarning(
1416:                            "An un-supported productPriceCond condition was used: "
1417:                                    + productPriceCond
1418:                                            .getString("operatorEnumId")
1419:                                    + ", returning false, ie check failed",
1420:                            module);
1421:                    return false;
1422:                }
1423:                return false;
1424:            }
1425:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.