001: /*
002: * $Id: ProductStoreWorker.java,v 1.23 2004/02/28 23:35:23 ajzeneski Exp $
003: *
004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
005: *
006: * Permission is hereby granted, free of charge, to any person obtaining a
007: * copy of this software and associated documentation files (the "Software"),
008: * to deal in the Software without restriction, including without limitation
009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
010: * and/or sell copies of the Software, and to permit persons to whom the
011: * Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included
014: * in all copies or substantial portions of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
023: */
024: package org.ofbiz.product.store;
025:
026: import java.util.ArrayList;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.LinkedList;
030: import java.util.List;
031: import java.util.Map;
032:
033: import javax.servlet.ServletRequest;
034: import javax.servlet.http.HttpServletRequest;
035: import javax.servlet.http.HttpSession;
036:
037: import org.ofbiz.base.util.Debug;
038: import org.ofbiz.base.util.UtilMisc;
039: import org.ofbiz.base.util.UtilValidate;
040: import org.ofbiz.common.geo.GeoWorker;
041: import org.ofbiz.entity.GenericDelegator;
042: import org.ofbiz.entity.GenericEntityException;
043: import org.ofbiz.entity.GenericValue;
044: import org.ofbiz.entity.util.EntityUtil;
045: import org.ofbiz.party.contact.ContactMechWorker;
046: import org.ofbiz.product.catalog.CatalogWorker;
047: import org.ofbiz.product.product.ProductWorker;
048: import org.ofbiz.service.GenericServiceException;
049: import org.ofbiz.service.LocalDispatcher;
050:
051: /**
052: * ProductStoreWorker - Worker class for store related functionality
053: *
054: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
055: * @version $Revision: 1.23 $
056: * @since 2.0
057: */
058: public class ProductStoreWorker {
059:
060: public static final String module = ProductStoreWorker.class
061: .getName();
062:
063: public static GenericValue getProductStore(String productStoreId,
064: GenericDelegator delegator) {
065: GenericValue productStore = null;
066: try {
067: productStore = delegator.findByPrimaryKeyCache(
068: "ProductStore", UtilMisc.toMap("productStoreId",
069: productStoreId));
070: } catch (GenericEntityException e) {
071: Debug.logError(e, "Problem getting ProductStore entity",
072: module);
073: }
074: return productStore;
075: }
076:
077: public static GenericValue getProductStore(ServletRequest request) {
078: GenericDelegator delegator = (GenericDelegator) request
079: .getAttribute("delegator");
080: String productStoreId = ProductStoreWorker
081: .getProductStoreId(request);
082: return ProductStoreWorker.getProductStore(productStoreId,
083: delegator);
084: }
085:
086: public static String getProductStoreId(ServletRequest request) {
087: HttpServletRequest httpRequest = (HttpServletRequest) request;
088: HttpSession session = httpRequest.getSession();
089: if (session.getAttribute("productStoreId") != null) {
090: return (String) session.getAttribute("productStoreId");
091: } else {
092: GenericValue webSite = CatalogWorker.getWebSite(request);
093: if (webSite != null) {
094: return webSite.getString("productStoreId");
095: }
096: }
097: return null;
098: }
099:
100: public static String getProductStorePaymentProperties(
101: ServletRequest request, String paymentMethodTypeId,
102: String paymentServiceTypeEnumId, boolean anyServiceType) {
103: GenericDelegator delegator = (GenericDelegator) request
104: .getAttribute("delegator");
105: String productStoreId = ProductStoreWorker
106: .getProductStoreId(request);
107: return ProductStoreWorker.getProductStorePaymentProperties(
108: delegator, productStoreId, paymentMethodTypeId,
109: paymentServiceTypeEnumId, anyServiceType);
110: }
111:
112: public static String getProductStorePaymentProperties(
113: GenericDelegator delegator, String productStoreId,
114: String paymentMethodTypeId,
115: String paymentServiceTypeEnumId, boolean anyServiceType) {
116: GenericValue setting = ProductStoreWorker
117: .getProductStorePaymentSetting(delegator,
118: productStoreId, paymentMethodTypeId,
119: paymentServiceTypeEnumId, anyServiceType);
120:
121: String payProps = "payment.properties";
122: if (setting != null
123: && setting.get("paymentPropertiesPath") != null) {
124: payProps = setting.getString("paymentPropertiesPath");
125: }
126: return payProps;
127: }
128:
129: public static GenericValue getProductStorePaymentSetting(
130: GenericDelegator delegator, String productStoreId,
131: String paymentMethodTypeId,
132: String paymentServiceTypeEnumId, boolean anyServiceType) {
133: GenericValue storePayment = null;
134: try {
135: storePayment = delegator.findByPrimaryKeyCache(
136: "ProductStorePaymentSetting", UtilMisc.toMap(
137: "productStoreId", productStoreId,
138: "paymentMethodTypeId", paymentMethodTypeId,
139: "paymentServiceTypeEnumId",
140: paymentServiceTypeEnumId));
141: } catch (GenericEntityException e) {
142: Debug.logError(e,
143: "Problems looking up store payment settings",
144: module);
145: }
146:
147: if (anyServiceType) {
148: if (storePayment == null) {
149: try {
150: List storePayments = delegator.findByAnd(
151: "ProductStorePaymentSetting", UtilMisc
152: .toMap("productStoreId",
153: productStoreId,
154: "paymentMethodTypeId",
155: paymentMethodTypeId));
156: storePayment = EntityUtil.getFirst(storePayments);
157: } catch (GenericEntityException e) {
158: Debug
159: .logError(
160: e,
161: "Problems looking up store payment settings",
162: module);
163: }
164: }
165:
166: if (storePayment == null) {
167: try {
168: List storePayments = delegator.findByAnd(
169: "ProductStorePaymentSetting", UtilMisc
170: .toMap("productStoreId",
171: productStoreId));
172: storePayment = EntityUtil.getFirst(storePayments);
173: } catch (GenericEntityException e) {
174: Debug
175: .logError(
176: e,
177: "Problems looking up store payment settings",
178: module);
179: }
180: }
181: }
182:
183: return storePayment;
184: }
185:
186: public static List getAvailableStoreShippingMethods(
187: GenericDelegator delegator, String productStoreId,
188: GenericValue shippingAddress, List itemSizes,
189: Map featureIdMap, double weight, double orderTotal) {
190: if (featureIdMap == null) {
191: featureIdMap = new HashMap();
192: }
193: List shippingMethods = null;
194: try {
195: shippingMethods = delegator.findByAndCache(
196: "ProductStoreShipmentMethView", UtilMisc.toMap(
197: "productStoreId", productStoreId), UtilMisc
198: .toList("sequenceNumber"));
199: } catch (GenericEntityException e) {
200: Debug.logError(e,
201: "Unable to get ProductStore shipping methods",
202: module);
203: return null;
204: }
205:
206: // clone the list for concurrent modification
207: List returnShippingMethods = new LinkedList(shippingMethods);
208:
209: if (shippingMethods != null) {
210: Iterator i = shippingMethods.iterator();
211: while (i.hasNext()) {
212: GenericValue method = (GenericValue) i.next();
213: Debug.logInfo("Checking Shipping Method : "
214: + method.getString("shipmentMethodTypeId"),
215: module);
216:
217: // test min/max weight first
218: Double minWeight = method.getDouble("minWeight");
219: Double maxWeight = method.getDouble("maxWeight");
220: if (minWeight != null && minWeight.doubleValue() > 0
221: && minWeight.doubleValue() > weight) {
222: returnShippingMethods.remove(method);
223: Debug
224: .logInfo(
225: "Removed shipping method due to not enough weight",
226: module);
227: continue;
228: }
229: if (maxWeight != null && maxWeight.doubleValue() > 0
230: && maxWeight.doubleValue() < weight) {
231: returnShippingMethods.remove(method);
232: Debug
233: .logInfo(
234: "Removed shipping method due to too much weight",
235: module);
236: continue;
237: }
238:
239: // test order total
240: Double minTotal = method.getDouble("minTotal");
241: Double maxTotal = method.getDouble("maxTotal");
242: if (minTotal != null && minTotal.doubleValue() > 0
243: && minTotal.doubleValue() > orderTotal) {
244: returnShippingMethods.remove(method);
245: Debug
246: .logInfo(
247: "Removed shipping method due to not enough order total",
248: module);
249: continue;
250: }
251: if (maxTotal != null && maxTotal.doubleValue() > 0
252: && maxTotal.doubleValue() < orderTotal) {
253: returnShippingMethods.remove(method);
254: Debug
255: .logInfo(
256: "Removed shipping method due to too much shipping total",
257: module);
258: continue;
259: }
260:
261: // test product sizes
262: Double minSize = method.getDouble("minSize");
263: Double maxSize = method.getDouble("maxSize");
264: if (minSize != null && minSize.doubleValue() > 0) {
265: boolean allMatch = false;
266: if (itemSizes != null) {
267: allMatch = true;
268: Iterator isi = itemSizes.iterator();
269: while (isi.hasNext()) {
270: Double size = (Double) isi.next();
271: if (size.doubleValue() < minSize
272: .doubleValue()) {
273: allMatch = false;
274: }
275: }
276: }
277: if (!allMatch) {
278: returnShippingMethods.remove(method);
279: Debug
280: .logInfo(
281: "Removed shipping method because not all products are less then min size",
282: module);
283: continue;
284: }
285: }
286: if (maxSize != null && maxSize.doubleValue() > 0) {
287: boolean allMatch = false;
288: if (itemSizes != null) {
289: allMatch = true;
290: Iterator isi = itemSizes.iterator();
291: while (isi.hasNext()) {
292: Double size = (Double) isi.next();
293: if (size.doubleValue() > maxSize
294: .doubleValue()) {
295: allMatch = false;
296: }
297: }
298: }
299: if (!allMatch) {
300: returnShippingMethods.remove(method);
301: Debug
302: .logInfo(
303: "Removed shipping method because one or more products were more then max size",
304: module);
305: continue;
306: }
307: }
308:
309: // check USPS address
310: String allowUspsAddr = method
311: .getString("allowUspsAddr");
312: String requireUspsAddr = method
313: .getString("requireUspsAddr");
314: boolean isUspsAddress = ContactMechWorker
315: .isUspsAddress(shippingAddress);
316: if ("N".equals(allowUspsAddr) && isUspsAddress) {
317: returnShippingMethods.remove(method);
318: Debug
319: .logInfo(
320: "Remove shipping method due to USPS address",
321: module);
322: continue;
323: }
324: if ("Y".equals(requireUspsAddr) && !isUspsAddress) {
325: returnShippingMethods.remove(method);
326: Debug
327: .logInfo(
328: "Removed shipping method due to NON-USPS address",
329: module);
330: continue;
331: }
332:
333: // check company address
334: String companyPartyId = method
335: .getString("companyPartyId");
336: String allowCompanyAddr = method
337: .getString("allowCompanyAddr");
338: String requireCompanyAddr = method
339: .getString("requireCompanyAddr");
340: boolean isCompanyAddress = ContactMechWorker
341: .isCompanyAddress(shippingAddress,
342: companyPartyId);
343: if ("N".equals(allowCompanyAddr) && isCompanyAddress) {
344: returnShippingMethods.remove(method);
345: Debug
346: .logInfo(
347: "Removed shipping method due to Company address",
348: module);
349: continue;
350: }
351: if ("Y".equals(requireCompanyAddr) && !isCompanyAddress) {
352: returnShippingMethods.remove(method);
353: Debug
354: .logInfo(
355: "Removed shipping method due to NON-Company address",
356: module);
357: continue;
358: }
359:
360: // check the items excluded from shipping
361: String includeFreeShipping = method
362: .getString("includeNoChargeItems");
363: if (includeFreeShipping != null
364: && "N".equalsIgnoreCase(includeFreeShipping)) {
365: if ((itemSizes == null || itemSizes.size() == 0)
366: && orderTotal == 0) {
367: returnShippingMethods.remove(method);
368: Debug
369: .logInfo(
370: "Removed shipping method due to all items being exempt from shipping",
371: module);
372: continue;
373: }
374: }
375:
376: // check the geos
377: String includeGeoId = method.getString("includeGeoId");
378: String excludeGeoId = method.getString("excludeGeoId");
379: if ((includeGeoId != null && includeGeoId.length() > 0)
380: || (excludeGeoId != null && excludeGeoId
381: .length() > 0)) {
382: if (shippingAddress == null) {
383: returnShippingMethods.remove(method);
384: Debug
385: .logInfo(
386: "Removed shipping method due to empty shipping adresss (may not have been selected yet)",
387: module);
388: continue;
389: }
390: }
391: if (includeGeoId != null && includeGeoId.length() > 0) {
392: List includeGeoGroup = GeoWorker.expandGeoGroup(
393: includeGeoId, delegator);
394: if (!GeoWorker.containsGeo(includeGeoGroup,
395: shippingAddress.getString("countryGeoId"),
396: delegator)
397: && !GeoWorker
398: .containsGeo(
399: includeGeoGroup,
400: shippingAddress
401: .getString("stateProvinceGeoId"),
402: delegator)
403: && !GeoWorker
404: .containsGeo(
405: includeGeoGroup,
406: shippingAddress
407: .getString("postalCodeGeoId"),
408: delegator)) {
409: // not in required included geos
410: returnShippingMethods.remove(method);
411: Debug
412: .logInfo(
413: "Removed shipping method due to being outside the included GEO",
414: module);
415: continue;
416: }
417: }
418: if (excludeGeoId != null && excludeGeoId.length() > 0) {
419: List excludeGeoGroup = GeoWorker.expandGeoGroup(
420: excludeGeoId, delegator);
421: if (GeoWorker.containsGeo(excludeGeoGroup,
422: shippingAddress.getString("countryGeoId"),
423: delegator)
424: || GeoWorker
425: .containsGeo(
426: excludeGeoGroup,
427: shippingAddress
428: .getString("stateProvinceGeoId"),
429: delegator)
430: || GeoWorker
431: .containsGeo(
432: excludeGeoGroup,
433: shippingAddress
434: .getString("postalCodeGeoId"),
435: delegator)) {
436: // in excluded geos
437: returnShippingMethods.remove(method);
438: Debug
439: .logInfo(
440: "Removed shipping method due to being inside the excluded GEO",
441: module);
442: continue;
443: }
444: }
445:
446: // check the features
447: String includeFeatures = method
448: .getString("includeFeatureGroup");
449: String excludeFeatures = method
450: .getString("excludeFeatureGroup");
451: if (includeFeatures != null
452: && includeFeatures.length() > 0) {
453: List includedFeatures = null;
454: try {
455: includedFeatures = delegator.findByAndCache(
456: "ProductFeatureGroupAppl", UtilMisc
457: .toMap("productFeatureGroupId",
458: includeFeatures));
459: } catch (GenericEntityException e) {
460: Debug.logError(e,
461: "Unable to lookup ProductFeatureGroupAppl records for group : "
462: + includeFeatures, module);
463: }
464: if (includedFeatures != null) {
465: boolean foundOne = false;
466: Iterator ifet = includedFeatures.iterator();
467: while (ifet.hasNext()) {
468: GenericValue appl = (GenericValue) ifet
469: .next();
470: if (featureIdMap.containsKey(appl
471: .getString("productFeatureId"))) {
472: foundOne = true;
473: break;
474: }
475: }
476: if (!foundOne) {
477: returnShippingMethods.remove(method);
478: Debug
479: .logInfo(
480: "Removed shipping method due to no required features found",
481: module);
482: continue;
483: }
484: }
485: }
486: if (excludeFeatures != null
487: && excludeFeatures.length() > 0) {
488: List excludedFeatures = null;
489: try {
490: excludedFeatures = delegator.findByAndCache(
491: "ProductFeatureGroupAppl", UtilMisc
492: .toMap("productFeatureGroupId",
493: excludeFeatures));
494: } catch (GenericEntityException e) {
495: Debug.logError(e,
496: "Unable to lookup ProductFeatureGroupAppl records for group : "
497: + excludeFeatures, module);
498: }
499: if (excludedFeatures != null) {
500: Iterator ifet = excludedFeatures.iterator();
501: while (ifet.hasNext()) {
502: GenericValue appl = (GenericValue) ifet
503: .next();
504: if (featureIdMap.containsKey(appl
505: .getString("productFeatureId"))) {
506: returnShippingMethods.remove(method);
507: Debug
508: .logInfo(
509: "Removed shipping method due to an exluded feature being found : "
510: + appl
511: .getString("productFeatureId"),
512: module);
513: continue;
514: }
515: }
516: }
517: }
518: }
519: }
520:
521: return returnShippingMethods;
522: }
523:
524: public static List getProductSurveys(GenericDelegator delegator,
525: String productStoreId, String productId,
526: String surveyApplTypeId) {
527: List surveys = new ArrayList();
528: List storeSurveys = null;
529: try {
530: storeSurveys = delegator.findByAndCache(
531: "ProductStoreSurveyAppl", UtilMisc.toMap(
532: "productStoreId", productStoreId,
533: "surveyApplTypeId", surveyApplTypeId),
534: UtilMisc.toList("sequenceNum"));
535: } catch (GenericEntityException e) {
536: Debug.logError(e,
537: "Unable to get ProductStoreSurveyAppl for store : "
538: + productStoreId, module);
539: }
540: storeSurveys = EntityUtil.filterByDate(storeSurveys);
541:
542: // null productId means get all of this trigger (appl) type
543: if (productId == null) {
544: return storeSurveys;
545: }
546:
547: if (storeSurveys != null && storeSurveys.size() > 0) {
548: Iterator ssi = storeSurveys.iterator();
549: while (ssi.hasNext()) {
550: GenericValue surveyAppl = (GenericValue) ssi.next();
551: if (surveyAppl.get("productId") != null
552: && productId
553: .equals(surveyAppl.get("productId"))) {
554: surveys.add(surveyAppl);
555: } else if (surveyAppl.get("productCategoryId") != null) {
556: List categoryMembers = null;
557: try {
558: categoryMembers = delegator
559: .findByAnd(
560: "ProductCategoryMember",
561: UtilMisc
562: .toMap(
563: "productCategoryId",
564: surveyAppl
565: .get("productCategoryId")));
566: } catch (GenericEntityException e) {
567: Debug.logError(e,
568: "Unable to get ProductCategoryMemebr records for survey application : "
569: + surveyAppl, module);
570: }
571: if (categoryMembers != null) {
572: Iterator cmi = categoryMembers.iterator();
573: while (cmi.hasNext()) {
574: GenericValue member = (GenericValue) cmi
575: .next();
576: if (productId.equals(member
577: .getString("productId"))) {
578: surveys.add(surveyAppl);
579: break;
580: }
581: }
582: }
583: }
584: }
585: }
586:
587: return surveys;
588: }
589:
590: /** Returns the number of responses for this survey by party */
591: public static int checkSurveyResponse(HttpServletRequest request,
592: String surveyId) {
593: GenericDelegator delegator = (GenericDelegator) request
594: .getAttribute("delegator");
595: GenericValue userLogin = (GenericValue) request.getSession()
596: .getAttribute("userLogin");
597: String productStoreId = getProductStoreId(request);
598: if (userLogin == null) {
599: return -1;
600: }
601:
602: return checkSurveyResponse(delegator, userLogin
603: .getString("partyId"), productStoreId, surveyId);
604: }
605:
606: /** Returns the number of responses for this survey by party */
607: public static int checkSurveyResponse(GenericDelegator delegator,
608: String partyId, String productStoreId, String surveyId) {
609: if (delegator == null || partyId == null
610: || productStoreId == null) {
611: return -1;
612: }
613:
614: List surveyResponse = null;
615: try {
616: surveyResponse = delegator.findByAnd("SurveyResponse",
617: UtilMisc.toMap("surveyId", surveyId, "partyId",
618: partyId));
619: } catch (GenericEntityException e) {
620: Debug.logError(e, module);
621: return -1;
622: }
623:
624: if (surveyResponse == null || surveyResponse.size() == 0) {
625: return 0;
626: } else {
627: return surveyResponse.size();
628: }
629: }
630:
631: public static boolean isStoreInventoryRequired(
632: String productStoreId, String productId,
633: GenericDelegator delegator) {
634: GenericValue product = null;
635:
636: if (productId != null) {
637: try {
638: product = delegator.findByPrimaryKeyCache("Product",
639: UtilMisc.toMap("productId", productId));
640: } catch (GenericEntityException e) {
641: Debug
642: .logError(
643: e,
644: "Error looking up product with id "
645: + productId
646: + ", will check the ProdCatalog for inventory required",
647: module);
648: }
649: }
650:
651: return isStoreInventoryRequired(productStoreId, product,
652: delegator);
653: }
654:
655: public static boolean isStoreInventoryRequired(
656: String productStoreId, GenericValue product,
657: GenericDelegator delegator) {
658: // look at the product first since it over-rides the ProductStore setting; if empty or null use the ProductStore setting
659:
660: if (product != null
661: && UtilValidate.isNotEmpty(product
662: .getString("requireInventory"))) {
663: if ("Y".equals(product.getString("requireInventory"))) {
664: return true;
665: } else if ("N"
666: .equals(product.getString("requireInventory"))) {
667: return false;
668: }
669: }
670: // otherwise, check the store...
671:
672: GenericValue productStore = getProductStore(productStoreId,
673: delegator);
674:
675: if (productStore == null) {
676: Debug.logWarning("ProductStore not found with id "
677: + productStoreId
678: + ", returning false for inventory required check",
679: module);
680: return false;
681: }
682:
683: // default to false, so if anything but Y, return false
684: return "Y".equals(productStore.getString("requireInventory"));
685: }
686:
687: public static boolean isStoreInventoryRequired(
688: ServletRequest request, GenericValue product) {
689: GenericValue productStore = getProductStore(request);
690:
691: if (productStore == null) {
692: Debug
693: .logWarning(
694: "No ProductStore found, return false for inventory check",
695: module);
696: return false;
697: }
698:
699: String productStoreId = productStore
700: .getString("productStoreId");
701: GenericDelegator delegator = (GenericDelegator) request
702: .getAttribute("delegator");
703: return isStoreInventoryRequired(productStore
704: .getString("productStoreId"), product, delegator);
705: }
706:
707: /** check inventory availability for the given catalog, product, quantity, etc */
708: public static boolean isStoreInventoryAvailable(
709: String productStoreId, String productId, double quantity,
710: GenericDelegator delegator, LocalDispatcher dispatcher) {
711: GenericValue productStore = getProductStore(productStoreId,
712: delegator);
713:
714: if (productStore == null) {
715: Debug
716: .logWarning(
717: "No ProductStore found with id "
718: + productStoreId
719: + ", returning false for inventory available check",
720: module);
721: return false;
722: }
723:
724: // if prodCatalog is set to not check inventory break here
725: if ("N".equals(productStore.getString("checkInventory"))) {
726: // note: if not set, defaults to yes, check inventory
727: if (Debug.verboseOn())
728: Debug
729: .logVerbose(
730: "ProductStore with id "
731: + productStoreId
732: + ", is set to NOT check inventory, returning true for inventory available check",
733: module);
734: return true;
735: }
736: boolean isInventoryAvailable = false;
737:
738: if ("Y".equals(productStore.getString("oneInventoryFacility"))) {
739: String inventoryFacilityId = productStore
740: .getString("inventoryFacilityId");
741:
742: if (UtilValidate.isEmpty(inventoryFacilityId)) {
743: Debug
744: .logWarning(
745: "ProductStore with id "
746: + productStoreId
747: + " has Y for oneInventoryFacility but inventoryFacilityId is empty, returning false for inventory check",
748: module);
749: return false;
750: }
751:
752: try {
753: isInventoryAvailable = ProductWorker
754: .isProductInventoryAvailableByFacility(
755: productId, inventoryFacilityId,
756: quantity, dispatcher);
757: } catch (GenericServiceException e) {
758: Debug
759: .logWarning(
760: e,
761: "Error invoking isProductInventoryAvailableByFacility in isCatalogInventoryAvailable",
762: module);
763: return false;
764: }
765: return isInventoryAvailable;
766:
767: } else {
768: GenericValue product = null;
769: List productFacilities = null;
770:
771: try {
772: product = delegator.findByPrimaryKeyCache("Product",
773: UtilMisc.toMap("productId", productId));
774: } catch (GenericEntityException e) {
775: Debug
776: .logWarning(
777: e,
778: "Error invoking findByPrimaryKeyCache in isCatalogInventoryAvailable",
779: module);
780: return false;
781: }
782: try {
783: productFacilities = delegator.getRelatedCache(
784: "ProductFacility", product);
785: } catch (GenericEntityException e) {
786: Debug
787: .logWarning(
788: e,
789: "Error invoking getRelatedCache in isCatalogInventoryAvailable",
790: module);
791: return false;
792: }
793:
794: if (productFacilities != null
795: && productFacilities.size() > 0) {
796: Iterator pfIter = productFacilities.iterator();
797:
798: while (pfIter.hasNext()) {
799: try {
800: GenericValue pfValue = (GenericValue) pfIter
801: .next();
802:
803: isInventoryAvailable = ProductWorker
804: .isProductInventoryAvailableByFacility(
805: productId,
806: pfValue.getString("facilityId"),
807: quantity, dispatcher);
808: if (isInventoryAvailable == true) {
809: return isInventoryAvailable;
810: }
811: } catch (GenericServiceException e) {
812: Debug
813: .logWarning(
814: e,
815: "Error invoking isProductInventoryAvailableByFacility in isCatalogInventoryAvailable",
816: module);
817: return false;
818: }
819: }
820: }
821: return false;
822:
823: /* TODO: must entire quantity be available in one location?
824: * Right now the answer is yes, it only succeeds if one facility has sufficient inventory for the order.
825: * When we get into splitting options it is much more complicated. There are various options like:
826: * - allow split between facilities
827: * - in split order facilities by highest quantities
828: * - in split order facilities by lowest quantities
829: * - in split order facilities by order in database, ie sequence numbers on facility-store join table
830: * - in split order facilities by nearest locations to customer (not an easy one there...)
831: */
832:
833: // loop through all facilities attached to this catalog and check for individual or cumulative sufficient inventory
834: }
835: }
836:
837: public static boolean isStoreInventoryAvailable(
838: ServletRequest request, String productId, double quantity) {
839: GenericValue productStore = getProductStore(request);
840:
841: if (productStore == null) {
842: Debug
843: .logWarning(
844: "No ProductStore found, return false for inventory check",
845: module);
846: return false;
847: }
848:
849: String productStoreId = productStore
850: .getString("productStoreId");
851: GenericDelegator delegator = (GenericDelegator) request
852: .getAttribute("delegator");
853: LocalDispatcher dispatcher = (LocalDispatcher) request
854: .getAttribute("dispatcher");
855: return isStoreInventoryAvailable(productStoreId, productId,
856: quantity, delegator, dispatcher);
857: }
858:
859: /** tries to reserve the specified quantity, if fails returns quantity that it could not reserve or zero if there was an error, otherwise returns null */
860: public static Double reserveStoreInventory(String productStoreId,
861: String productId, Double quantity, String orderId,
862: String orderItemSeqId, GenericValue userLogin,
863: GenericDelegator delegator, LocalDispatcher dispatcher) {
864:
865: GenericValue productStore = getProductStore(productStoreId,
866: delegator);
867:
868: if (productStore == null) {
869: Debug.logWarning("No ProductStore found with id "
870: + productStoreId + ", not reserving inventory",
871: module);
872: return new Double(0.0);
873: }
874:
875: // if prodCatalog is set to not reserve inventory, break here
876: if ("N".equals(productStore.getString("reserveInventory"))) {
877: // note: if not set, defaults to yes, reserve inventory
878: if (Debug.verboseOn())
879: Debug
880: .logVerbose(
881: "ProductStore with id "
882: + productStoreId
883: + ", is set to NOT reserve inventory, not reserving inventory",
884: module);
885: return null;
886: }
887: String reserveOrderEnumId = productStore
888: .getString("reserveOrderEnumId");
889: boolean requireInventory = isStoreInventoryRequired(
890: productStoreId, productId, delegator);
891: Double quantityNotReserved = null;
892:
893: if ("Y".equals(productStore.getString("oneInventoryFacility"))) {
894: String inventoryFacilityId = productStore
895: .getString("inventoryFacilityId");
896:
897: if (UtilValidate.isEmpty(inventoryFacilityId)) {
898: Debug
899: .logWarning(
900: "ProductStore with id "
901: + productStoreId
902: + " has Y for oneInventoryFacility but inventoryFacilityId is empty, not reserving inventory",
903: module);
904: return new Double(0.0);
905: }
906:
907: try {
908: quantityNotReserved = ProductWorker
909: .reserveProductInventoryByFacility(productId,
910: quantity, inventoryFacilityId, orderId,
911: reserveOrderEnumId, orderItemSeqId,
912: requireInventory, userLogin, dispatcher);
913: } catch (GenericServiceException e) {
914: Debug
915: .logWarning(
916: e,
917: "Error invoking reserveProductInventoryByFacility service",
918: module);
919: return !requireInventory ? null : new Double(0.0);
920: }
921: return quantityNotReserved;
922:
923: } else {
924: GenericValue product = null;
925: List productFacilities = null;
926:
927: try {
928: product = delegator.findByPrimaryKeyCache("Product",
929: UtilMisc.toMap("productId", productId));
930: } catch (GenericEntityException e) {
931: Debug
932: .logWarning(
933: e,
934: "Error invoking findByPrimaryKeyCache in reserveCatalogInventory",
935: module);
936: return new Double(0.0);
937: }
938: try {
939: productFacilities = delegator.getRelatedCache(
940: "ProductFacility", product);
941: } catch (GenericEntityException e) {
942: Debug
943: .logWarning(
944: e,
945: "Error invoking getRelatedCache in reserveCatalogInventory",
946: module);
947: return new Double(0.0);
948: }
949:
950: if (productFacilities != null
951: && productFacilities.size() > 0) {
952: Iterator pfIter = productFacilities.iterator();
953:
954: while (pfIter.hasNext()) {
955: GenericValue pfValue = (GenericValue) pfIter.next();
956: String inventoryFacilityId = pfValue
957: .getString("facilityId");
958:
959: try {
960: quantityNotReserved = ProductWorker
961: .reserveProductInventoryByFacility(
962: productId, quantity,
963: inventoryFacilityId, orderId,
964: reserveOrderEnumId,
965: orderItemSeqId,
966: requireInventory, userLogin,
967: dispatcher);
968: } catch (GenericServiceException e) {
969: Debug
970: .logWarning(
971: e,
972: "Error invoking reserveProductInventoryByFacility in reserveCatalogInventory",
973: module);
974: return !requireInventory ? null : new Double(
975: 0.0);
976: }
977: if (quantityNotReserved == null) {
978: return null;
979: }
980: }
981: return quantityNotReserved;
982:
983: }
984: return !requireInventory ? null : new Double(0.0);
985: }
986: }
987: }
|