0001: /*******************************************************************************
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: *******************************************************************************/package org.ofbiz.product.inventory;
0019:
0020: import java.sql.Timestamp;
0021: import java.util.ArrayList;
0022: import java.util.Calendar;
0023: import java.util.HashMap;
0024: import java.util.Iterator;
0025: import java.util.List;
0026: import java.util.Map;
0027: import java.util.Set;
0028:
0029: import org.ofbiz.base.util.Debug;
0030: import org.ofbiz.base.util.UtilDateTime;
0031: import org.ofbiz.base.util.UtilMisc;
0032: import org.ofbiz.base.util.UtilValidate;
0033: import org.ofbiz.entity.GenericDelegator;
0034: import org.ofbiz.entity.GenericEntityException;
0035: import org.ofbiz.entity.GenericValue;
0036: import org.ofbiz.entity.condition.EntityConditionList;
0037: import org.ofbiz.entity.condition.EntityExpr;
0038: import org.ofbiz.entity.condition.EntityOperator;
0039: import org.ofbiz.entity.model.DynamicViewEntity;
0040: import org.ofbiz.entity.model.ModelKeyMap;
0041: import org.ofbiz.entity.util.EntityListIterator;
0042: import org.ofbiz.service.DispatchContext;
0043: import org.ofbiz.service.GenericServiceException;
0044: import org.ofbiz.service.LocalDispatcher;
0045: import org.ofbiz.service.ServiceUtil;
0046:
0047: /**
0048: * Inventory Services
0049: */
0050: public class InventoryServices {
0051:
0052: public final static String module = InventoryServices.class
0053: .getName();
0054:
0055: public static Map prepareInventoryTransfer(DispatchContext dctx,
0056: Map context) {
0057: GenericDelegator delegator = dctx.getDelegator();
0058: String inventoryItemId = (String) context
0059: .get("inventoryItemId");
0060: Double xferQty = (Double) context.get("xferQty");
0061: GenericValue inventoryItem = null;
0062: GenericValue newItem = null;
0063: GenericValue userLogin = (GenericValue) context
0064: .get("userLogin");
0065:
0066: try {
0067: inventoryItem = delegator.findByPrimaryKey("InventoryItem",
0068: UtilMisc.toMap("inventoryItemId", inventoryItemId));
0069: } catch (GenericEntityException e) {
0070: return ServiceUtil
0071: .returnError("Inventory item lookup problem ["
0072: + e.getMessage() + "]");
0073: }
0074:
0075: if (inventoryItem == null) {
0076: return ServiceUtil
0077: .returnError("Cannot locate inventory item.");
0078: }
0079:
0080: try {
0081: Map results = ServiceUtil.returnSuccess();
0082:
0083: String inventoryType = inventoryItem
0084: .getString("inventoryItemTypeId");
0085: if (inventoryType.equals("NON_SERIAL_INV_ITEM")) {
0086: Double atp = inventoryItem
0087: .getDouble("availableToPromiseTotal");
0088: Double qoh = inventoryItem
0089: .getDouble("quantityOnHandTotal");
0090:
0091: if (atp == null) {
0092: return ServiceUtil
0093: .returnError("The request transfer amount is not available, there is no available to promise on the Inventory Item with ID "
0094: + inventoryItem
0095: .getString("inventoryItemId"));
0096: }
0097: if (qoh == null) {
0098: qoh = atp;
0099: }
0100:
0101: // first make sure we have enough to cover the request transfer amount
0102: if (xferQty.doubleValue() > atp.doubleValue()) {
0103: return ServiceUtil
0104: .returnError("The request transfer amount is not available, the available to promise ["
0105: + atp
0106: + "] is not sufficient for the desired transfer quantity ["
0107: + xferQty
0108: + "] on the Inventory Item with ID "
0109: + inventoryItem
0110: .getString("inventoryItemId"));
0111: }
0112:
0113: /*
0114: * atp < qoh - split and save the qoh - atp
0115: * xferQty < atp - split and save atp - xferQty
0116: * atp < qoh && xferQty < atp - split and save qoh - atp + atp - xferQty
0117: */
0118:
0119: // at this point we have already made sure that the xferQty is less than or equals to the atp, so if less that just create a new inventory record for the quantity to be moved
0120: // NOTE: atp should always be <= qoh, so if xfer < atp, then xfer < qoh, so no need to check/handle that
0121: // however, if atp < qoh && atp == xferQty, then we still need to split; oh, but no need to check atp == xferQty in the second part because if it isn't greater and isn't less, then it is equal
0122: if (xferQty.doubleValue() < atp.doubleValue()
0123: || atp.doubleValue() < qoh.doubleValue()) {
0124: Double negXferQty = new Double(-xferQty
0125: .doubleValue());
0126: // NOTE: new inventory items should always be created calling the
0127: // createInventoryItem service because in this way we are sure
0128: // that all the relevant fields are filled with default values.
0129: // However, the code here should work fine because all the values
0130: // for the new inventory item are inerited from the existing item.
0131: newItem = GenericValue.create(inventoryItem);
0132: newItem.set("availableToPromiseTotal",
0133: new Double(0));
0134: newItem.set("quantityOnHandTotal", new Double(0));
0135:
0136: String newSeqId = null;
0137: try {
0138: newSeqId = delegator
0139: .getNextSeqId("InventoryItem");
0140: } catch (IllegalArgumentException e) {
0141: return ServiceUtil
0142: .returnError("ERROR: Could not get next sequence id for InventoryItem, cannot create item.");
0143: }
0144:
0145: newItem.set("inventoryItemId", newSeqId);
0146: newItem.create();
0147:
0148: results.put("inventoryItemId", newItem
0149: .get("inventoryItemId"));
0150:
0151: // TODO: how do we get this here: "inventoryTransferId", inventoryTransferId
0152: Map createNewDetailMap = UtilMisc.toMap(
0153: "availableToPromiseDiff", xferQty,
0154: "quantityOnHandDiff", xferQty,
0155: "inventoryItemId", newItem
0156: .get("inventoryItemId"),
0157: "userLogin", userLogin);
0158: Map createUpdateDetailMap = UtilMisc.toMap(
0159: "availableToPromiseDiff", negXferQty,
0160: "quantityOnHandDiff", negXferQty,
0161: "inventoryItemId", inventoryItem
0162: .get("inventoryItemId"),
0163: "userLogin", userLogin);
0164:
0165: try {
0166: Map resultNew = dctx.getDispatcher().runSync(
0167: "createInventoryItemDetail",
0168: createNewDetailMap);
0169: if (ServiceUtil.isError(resultNew)) {
0170: return ServiceUtil
0171: .returnError(
0172: "Inventory Item Detail create problem in prepare inventory transfer",
0173: null, null, resultNew);
0174: }
0175: Map resultUpdate = dctx.getDispatcher()
0176: .runSync("createInventoryItemDetail",
0177: createUpdateDetailMap);
0178: if (ServiceUtil.isError(resultNew)) {
0179: return ServiceUtil
0180: .returnError(
0181: "Inventory Item Detail create problem in prepare inventory transfer",
0182: null, null, resultUpdate);
0183: }
0184: } catch (GenericServiceException e1) {
0185: return ServiceUtil
0186: .returnError("Inventory Item Detail create problem in prepare inventory transfer: ["
0187: + e1.getMessage() + "]");
0188: }
0189: } else {
0190: results.put("inventoryItemId", inventoryItem
0191: .get("inventoryItemId"));
0192: }
0193: } else if (inventoryType.equals("SERIALIZED_INV_ITEM")) {
0194: if (!"INV_AVAILABLE".equals(inventoryItem
0195: .getString("statusId"))) {
0196: return ServiceUtil
0197: .returnError("Serialized inventory is not available for transfer.");
0198: }
0199: }
0200:
0201: // setup values so that no one will grab the inventory during the move
0202: // if newItem is not null, it is the item to be moved, otherwise the original inventoryItem is the one to be moved
0203: if (inventoryType.equals("NON_SERIAL_INV_ITEM")) {
0204: // set the transfered inventory item's atp to 0 and the qoh to the xferQty; at this point atp and qoh will always be the same, so we can safely zero the atp for now
0205: GenericValue inventoryItemToClear = newItem == null ? inventoryItem
0206: : newItem;
0207:
0208: inventoryItemToClear.refresh();
0209: double atp = inventoryItemToClear
0210: .get("availableToPromiseTotal") == null ? 0
0211: : inventoryItemToClear.getDouble(
0212: "availableToPromiseTotal")
0213: .doubleValue();
0214: if (atp != 0) {
0215: Map createDetailMap = UtilMisc.toMap(
0216: "availableToPromiseDiff", new Double(-atp),
0217: "inventoryItemId", inventoryItemToClear
0218: .get("inventoryItemId"),
0219: "userLogin", userLogin);
0220: try {
0221: Map result = dctx.getDispatcher().runSync(
0222: "createInventoryItemDetail",
0223: createDetailMap);
0224: if (ServiceUtil.isError(result)) {
0225: return ServiceUtil
0226: .returnError(
0227: "Inventory Item Detail create problem in complete inventory transfer",
0228: null, null, result);
0229: }
0230: } catch (GenericServiceException e1) {
0231: return ServiceUtil
0232: .returnError("Inventory Item Detail create problem in complete inventory transfer: ["
0233: + e1.getMessage() + "]");
0234: }
0235: }
0236: } else if (inventoryType.equals("SERIALIZED_INV_ITEM")) {
0237: // set the status to avoid re-moving or something
0238: if (newItem != null) {
0239: newItem.refresh();
0240: newItem.set("statusId", "INV_BEING_TRANSFERED");
0241: newItem.store();
0242: results.put("inventoryItemId", newItem
0243: .get("inventoryItemId"));
0244: } else {
0245: inventoryItem.refresh();
0246: inventoryItem.set("statusId",
0247: "INV_BEING_TRANSFERED");
0248: inventoryItem.store();
0249: results.put("inventoryItemId", inventoryItem
0250: .get("inventoryItemId"));
0251: }
0252: }
0253:
0254: return results;
0255: } catch (GenericEntityException e) {
0256: return ServiceUtil
0257: .returnError("Inventory store/create problem ["
0258: + e.getMessage() + "]");
0259: }
0260: }
0261:
0262: public static Map completeInventoryTransfer(DispatchContext dctx,
0263: Map context) {
0264: GenericDelegator delegator = dctx.getDelegator();
0265: String inventoryTransferId = (String) context
0266: .get("inventoryTransferId");
0267: GenericValue inventoryTransfer = null;
0268: GenericValue inventoryItem = null;
0269: GenericValue destinationFacility = null;
0270: GenericValue userLogin = (GenericValue) context
0271: .get("userLogin");
0272:
0273: try {
0274: inventoryTransfer = delegator
0275: .findByPrimaryKey("InventoryTransfer", UtilMisc
0276: .toMap("inventoryTransferId",
0277: inventoryTransferId));
0278: inventoryItem = inventoryTransfer
0279: .getRelatedOne("InventoryItem");
0280: destinationFacility = inventoryTransfer
0281: .getRelatedOne("ToFacility");
0282: } catch (GenericEntityException e) {
0283: return ServiceUtil
0284: .returnError("Inventory Item/Transfer lookup problem ["
0285: + e.getMessage() + "]");
0286: }
0287:
0288: if (inventoryTransfer == null || inventoryItem == null) {
0289: return ServiceUtil
0290: .returnError("ERROR: Lookup of InventoryTransfer and/or InventoryItem failed!");
0291: }
0292:
0293: String inventoryType = inventoryItem
0294: .getString("inventoryItemTypeId");
0295:
0296: // set the fields on the transfer record
0297: if (inventoryTransfer.get("receiveDate") == null) {
0298: inventoryTransfer.set("receiveDate", UtilDateTime
0299: .nowTimestamp());
0300: }
0301:
0302: if (inventoryType.equals("NON_SERIAL_INV_ITEM")) {
0303: // add an adjusting InventoryItemDetail so set ATP back to QOH: ATP = ATP + (QOH - ATP), diff = QOH - ATP
0304: double atp = inventoryItem.get("availableToPromiseTotal") == null ? 0
0305: : inventoryItem
0306: .getDouble("availableToPromiseTotal")
0307: .doubleValue();
0308: double qoh = inventoryItem.get("quantityOnHandTotal") == null ? 0
0309: : inventoryItem.getDouble("quantityOnHandTotal")
0310: .doubleValue();
0311: Map createDetailMap = UtilMisc.toMap(
0312: "availableToPromiseDiff", new Double(qoh - atp),
0313: "inventoryItemId", inventoryItem
0314: .get("inventoryItemId"), "userLogin",
0315: userLogin);
0316: try {
0317: Map result = dctx.getDispatcher().runSync(
0318: "createInventoryItemDetail", createDetailMap);
0319: if (ServiceUtil.isError(result)) {
0320: return ServiceUtil
0321: .returnError(
0322: "Inventory Item Detail create problem in complete inventory transfer",
0323: null, null, result);
0324: }
0325: } catch (GenericServiceException e1) {
0326: return ServiceUtil
0327: .returnError("Inventory Item Detail create problem in complete inventory transfer: ["
0328: + e1.getMessage() + "]");
0329: }
0330: try {
0331: inventoryItem.refresh();
0332: } catch (GenericEntityException e) {
0333: return ServiceUtil
0334: .returnError("Inventory refresh problem ["
0335: + e.getMessage() + "]");
0336: }
0337: }
0338:
0339: // set the fields on the item
0340: Map updateInventoryItemMap = UtilMisc
0341: .toMap("inventoryItemId", inventoryItem
0342: .getString("inventoryItemId"), "facilityId",
0343: inventoryTransfer.get("facilityIdTo"),
0344: "containerId", inventoryTransfer
0345: .get("containerIdTo"), "locationSeqId",
0346: inventoryTransfer.get("locationSeqIdTo"),
0347: "userLogin", userLogin);
0348:
0349: // for serialized items, automatically make them available
0350: if (inventoryType.equals("SERIALIZED_INV_ITEM")) {
0351: updateInventoryItemMap.put("statusId", "INV_AVAILABLE");
0352: }
0353:
0354: // if the destination facility's owner is different
0355: // from the inventory item's ownwer,
0356: // the inventory item is assigned to the new owner.
0357: if (destinationFacility != null
0358: && destinationFacility.get("ownerPartyId") != null) {
0359: String fromPartyId = inventoryItem
0360: .getString("ownerPartyId");
0361: String toPartyId = destinationFacility
0362: .getString("ownerPartyId");
0363: if (fromPartyId == null || !fromPartyId.equals(toPartyId)) {
0364: updateInventoryItemMap.put("ownerPartyId", toPartyId);
0365: }
0366: }
0367: try {
0368: Map result = dctx.getDispatcher().runSync(
0369: "updateInventoryItem", updateInventoryItemMap);
0370: if (ServiceUtil.isError(result)) {
0371: return ServiceUtil.returnError(
0372: "Inventory item store problem", null, null,
0373: result);
0374: }
0375: } catch (GenericServiceException exc) {
0376: return ServiceUtil
0377: .returnError("Inventory item store problem ["
0378: + exc.getMessage() + "]");
0379: }
0380:
0381: // set the inventory transfer record to complete
0382: inventoryTransfer.set("statusId", "IXF_COMPLETE");
0383:
0384: // store the entities
0385: try {
0386: inventoryTransfer.store();
0387: } catch (GenericEntityException e) {
0388: return ServiceUtil.returnError("Inventory store problem ["
0389: + e.getMessage() + "]");
0390: }
0391:
0392: return ServiceUtil.returnSuccess();
0393: }
0394:
0395: public static Map cancelInventoryTransfer(DispatchContext dctx,
0396: Map context) {
0397: GenericDelegator delegator = dctx.getDelegator();
0398: String inventoryTransferId = (String) context
0399: .get("inventoryTransferId");
0400: GenericValue inventoryTransfer = null;
0401: GenericValue inventoryItem = null;
0402: GenericValue userLogin = (GenericValue) context
0403: .get("userLogin");
0404:
0405: try {
0406: inventoryTransfer = delegator
0407: .findByPrimaryKey("InventoryTransfer", UtilMisc
0408: .toMap("inventoryTransferId",
0409: inventoryTransferId));
0410: if (UtilValidate.isEmpty(inventoryTransfer)) {
0411: return ServiceUtil.returnError("Inventory transfer ["
0412: + inventoryTransferId + "] not found");
0413: }
0414: inventoryItem = inventoryTransfer
0415: .getRelatedOne("InventoryItem");
0416: } catch (GenericEntityException e) {
0417: return ServiceUtil
0418: .returnError("Inventory Item/Transfer lookup problem ["
0419: + e.getMessage() + "]");
0420: }
0421:
0422: if (inventoryTransfer == null || inventoryItem == null) {
0423: return ServiceUtil
0424: .returnError("ERROR: Lookup of InventoryTransfer and/or InventoryItem failed!");
0425: }
0426:
0427: String inventoryType = inventoryItem
0428: .getString("inventoryItemTypeId");
0429:
0430: // re-set the fields on the item
0431: if (inventoryType.equals("NON_SERIAL_INV_ITEM")) {
0432: // add an adjusting InventoryItemDetail so set ATP back to QOH: ATP = ATP + (QOH - ATP), diff = QOH - ATP
0433: double atp = inventoryItem.get("availableToPromiseTotal") == null ? 0
0434: : inventoryItem
0435: .getDouble("availableToPromiseTotal")
0436: .doubleValue();
0437: double qoh = inventoryItem.get("quantityOnHandTotal") == null ? 0
0438: : inventoryItem.getDouble("quantityOnHandTotal")
0439: .doubleValue();
0440: Map createDetailMap = UtilMisc.toMap(
0441: "availableToPromiseDiff", new Double(qoh - atp),
0442: "inventoryItemId", inventoryItem
0443: .get("inventoryItemId"), "userLogin",
0444: userLogin);
0445: try {
0446: Map result = dctx.getDispatcher().runSync(
0447: "createInventoryItemDetail", createDetailMap);
0448: if (ServiceUtil.isError(result)) {
0449: return ServiceUtil
0450: .returnError(
0451: "Inventory Item Detail create problem in cancel inventory transfer",
0452: null, null, result);
0453: }
0454: } catch (GenericServiceException e1) {
0455: return ServiceUtil
0456: .returnError("Inventory Item Detail create problem in cancel inventory transfer: ["
0457: + e1.getMessage() + "]");
0458: }
0459: } else if (inventoryType.equals("SERIALIZED_INV_ITEM")) {
0460: inventoryItem.set("statusId", "INV_AVAILABLE");
0461: // store the entity
0462: try {
0463: inventoryItem.store();
0464: } catch (GenericEntityException e) {
0465: return ServiceUtil
0466: .returnError("Inventory item store problem in cancel inventory transfer: ["
0467: + e.getMessage() + "]");
0468: }
0469: }
0470:
0471: // set the inventory transfer record to complete
0472: inventoryTransfer.set("statusId", "IXF_CANCELLED");
0473:
0474: // store the entities
0475: try {
0476: inventoryTransfer.store();
0477: } catch (GenericEntityException e) {
0478: return ServiceUtil.returnError("Inventory store problem ["
0479: + e.getMessage() + "]");
0480: }
0481:
0482: return ServiceUtil.returnSuccess();
0483: }
0484:
0485: /** In spite of the generic name this does the very specific task of checking availability of all back-ordered items and sends notices, etc */
0486: public static Map checkInventoryAvailability(DispatchContext dctx,
0487: Map context) {
0488: GenericDelegator delegator = dctx.getDelegator();
0489: LocalDispatcher dispatcher = dctx.getDispatcher();
0490: GenericValue userLogin = (GenericValue) context
0491: .get("userLogin");
0492:
0493: /* TODO: NOTE: This method has been updated, but testing requires many eyes. See http://jira.undersunconsulting.com/browse/OFBIZ-662
0494: boolean skipThisNeedsUpdating = true;
0495: if (skipThisNeedsUpdating) {
0496: Debug.logWarning("NOT Running the checkInventoryAvailability service, no backorders or such will be automatically created; the reason is that this serice needs to be updated to use OrderItemShipGroup instead of OrderShipmentPreference which it currently does.", module);
0497: return ServiceUtil.returnSuccess();
0498: }
0499: */
0500:
0501: Map ordersToUpdate = new HashMap();
0502: Map ordersToCancel = new HashMap();
0503:
0504: // find all inventory items w/ a negative ATP
0505: List inventoryItems = null;
0506: try {
0507: List exprs = UtilMisc.toList(new EntityExpr(
0508: "availableToPromiseTotal",
0509: EntityOperator.LESS_THAN, new Double(0)));
0510: inventoryItems = delegator
0511: .findByAnd("InventoryItem", exprs);
0512: } catch (GenericEntityException e) {
0513: Debug
0514: .logError(e, "Trouble getting inventory items",
0515: module);
0516: return ServiceUtil
0517: .returnError("Problem getting InventoryItem records");
0518: }
0519:
0520: if (inventoryItems == null) {
0521: Debug
0522: .logInfo(
0523: "No items out of stock; no backorders to worry about",
0524: module);
0525: return ServiceUtil.returnSuccess();
0526: }
0527:
0528: Debug.log("OOS Inventory Items: " + inventoryItems.size(),
0529: module);
0530:
0531: Iterator itemsIter = inventoryItems.iterator();
0532: while (itemsIter.hasNext()) {
0533: GenericValue inventoryItem = (GenericValue) itemsIter
0534: .next();
0535:
0536: // get the incomming shipment information for the item
0537: List shipmentAndItems = null;
0538: try {
0539: List exprs = new ArrayList();
0540: exprs.add(new EntityExpr("productId",
0541: EntityOperator.EQUALS, inventoryItem
0542: .get("productId")));
0543: exprs.add(new EntityExpr("destinationFacilityId",
0544: EntityOperator.EQUALS, inventoryItem
0545: .get("facilityId")));
0546: exprs
0547: .add(new EntityExpr("statusId",
0548: EntityOperator.NOT_EQUAL,
0549: "SHIPMENT_DELIVERED"));
0550: exprs
0551: .add(new EntityExpr("statusId",
0552: EntityOperator.NOT_EQUAL,
0553: "SHIPMENT_CANCELLED"));
0554: shipmentAndItems = delegator.findByAnd(
0555: "ShipmentAndItem", exprs, UtilMisc
0556: .toList("estimatedArrivalDate"));
0557: } catch (GenericEntityException e) {
0558: Debug.logError(e,
0559: "Problem getting ShipmentAndItem records",
0560: module);
0561: return ServiceUtil
0562: .returnError("Problem getting ShipmentAndItem records");
0563: }
0564:
0565: // get the reservations in order of newest first
0566: List reservations = null;
0567: try {
0568: reservations = inventoryItem.getRelated(
0569: "OrderItemShipGrpInvRes", null, UtilMisc
0570: .toList("-reservedDatetime"));
0571: } catch (GenericEntityException e) {
0572: Debug.logError(e,
0573: "Problem getting related reservations", module);
0574: return ServiceUtil
0575: .returnError("Problem getting related reservations");
0576: }
0577:
0578: if (reservations == null) {
0579: Debug
0580: .logWarning(
0581: "No outstanding reservations for this inventory item, why is it negative then?",
0582: module);
0583: continue;
0584: }
0585:
0586: Debug.log("Reservations for item: " + reservations.size(),
0587: module);
0588:
0589: // available at the time of order
0590: double availableBeforeReserved = inventoryItem.getDouble(
0591: "availableToPromiseTotal").doubleValue();
0592:
0593: // go through all the reservations in order
0594: Iterator ri = reservations.iterator();
0595: while (ri.hasNext()) {
0596: GenericValue reservation = (GenericValue) ri.next();
0597: String orderId = reservation.getString("orderId");
0598: String orderItemSeqId = reservation
0599: .getString("orderItemSeqId");
0600: Timestamp promisedDate = reservation
0601: .getTimestamp("promisedDatetime");
0602: Timestamp currentPromiseDate = reservation
0603: .getTimestamp("currentPromisedDate");
0604: Timestamp actualPromiseDate = currentPromiseDate;
0605: if (actualPromiseDate == null) {
0606: if (promisedDate != null) {
0607: actualPromiseDate = promisedDate;
0608: } else {
0609: // fall back if there is no promised date stored
0610: actualPromiseDate = reservation
0611: .getTimestamp("reservedDatetime");
0612: }
0613: }
0614:
0615: Debug
0616: .log("Promised Date: " + actualPromiseDate,
0617: module);
0618:
0619: // find the next possible ship date
0620: Timestamp nextShipDate = null;
0621: double availableAtTime = 0.00;
0622: Iterator si = shipmentAndItems.iterator();
0623: while (si.hasNext()) {
0624: GenericValue shipmentItem = (GenericValue) si
0625: .next();
0626: availableAtTime += shipmentItem.getDouble(
0627: "quantity").doubleValue();
0628: if (availableAtTime >= availableBeforeReserved) {
0629: nextShipDate = shipmentItem
0630: .getTimestamp("estimatedArrivalDate");
0631: break;
0632: }
0633: }
0634:
0635: Debug.log("Next Ship Date: " + nextShipDate, module);
0636:
0637: // create a modified promise date (promise date - 1 day)
0638: Calendar pCal = Calendar.getInstance();
0639: pCal.setTimeInMillis(actualPromiseDate.getTime());
0640: pCal.add(Calendar.DAY_OF_YEAR, -1);
0641: Timestamp modifiedPromisedDate = new Timestamp(pCal
0642: .getTimeInMillis());
0643: Timestamp now = UtilDateTime.nowTimestamp();
0644:
0645: Debug.log("Promised Date + 1: " + modifiedPromisedDate,
0646: module);
0647: Debug.log("Now: " + now, module);
0648:
0649: // check the promised date vs the next ship date
0650: if (nextShipDate == null
0651: || nextShipDate.after(actualPromiseDate)) {
0652: if (nextShipDate == null
0653: && modifiedPromisedDate.after(now)) {
0654: // do nothing; we are okay to assume it will be shipped on time
0655: Debug
0656: .log(
0657: "No ship date known yet, but promised date hasn't approached, assuming it will be here on time",
0658: module);
0659: } else {
0660: // we cannot ship by the promised date; need to notify the customer
0661: Debug
0662: .log(
0663: "We won't ship on time, getting notification info",
0664: module);
0665: Map notifyItems = (Map) ordersToUpdate
0666: .get(orderId);
0667: if (notifyItems == null) {
0668: notifyItems = new HashMap();
0669: }
0670: notifyItems.put(orderItemSeqId, nextShipDate);
0671: ordersToUpdate.put(orderId, notifyItems);
0672:
0673: // need to know if nextShipDate is more then 30 days after promised
0674: Calendar sCal = Calendar.getInstance();
0675: sCal.setTimeInMillis(actualPromiseDate
0676: .getTime());
0677: sCal.add(Calendar.DAY_OF_YEAR, 30);
0678: Timestamp farPastPromised = new Timestamp(sCal
0679: .getTimeInMillis());
0680:
0681: // check to see if this is >30 days or second run, if so flag to cancel
0682: boolean needToCancel = false;
0683: if (nextShipDate == null
0684: || nextShipDate.after(farPastPromised)) {
0685: // we cannot ship until >30 days after promised; using cancel rule
0686: Debug
0687: .log(
0688: "Ship date is >30 past the promised date",
0689: module);
0690: needToCancel = true;
0691: } else if (currentPromiseDate != null
0692: && actualPromiseDate
0693: .equals(currentPromiseDate)) {
0694: // this is the second notification; using cancel rule
0695: needToCancel = true;
0696: }
0697:
0698: // add the info to the cancel map if we need to schedule a cancel
0699: if (needToCancel) {
0700: // queue the item to be cancelled
0701: Debug.log(
0702: "Flagging the item to auto-cancel",
0703: module);
0704: Map cancelItems = (Map) ordersToCancel
0705: .get(orderId);
0706: if (cancelItems == null) {
0707: cancelItems = new HashMap();
0708: }
0709: cancelItems.put(orderItemSeqId,
0710: farPastPromised);
0711: ordersToCancel.put(orderId, cancelItems);
0712: }
0713:
0714: // store the updated promiseDate as the nextShipDate
0715: try {
0716: reservation.set("currentPromisedDate",
0717: nextShipDate);
0718: reservation.store();
0719: } catch (GenericEntityException e) {
0720: Debug.logError(e,
0721: "Problem storing reservation : "
0722: + reservation, module);
0723: }
0724: }
0725: }
0726:
0727: // subtract our qty from reserved to get the next value
0728: availableBeforeReserved -= reservation.getDouble(
0729: "quantity").doubleValue();
0730: }
0731: }
0732:
0733: // all items to cancel will also be in the notify list so start with that
0734: List ordersToNotify = new ArrayList();
0735: Set orderSet = ordersToUpdate.keySet();
0736: Iterator orderIter = orderSet.iterator();
0737: while (orderIter.hasNext()) {
0738: String orderId = (String) orderIter.next();
0739: Map backOrderedItems = (Map) ordersToUpdate.get(orderId);
0740: Map cancelItems = (Map) ordersToCancel.get(orderId);
0741: boolean cancelAll = false;
0742: Timestamp cancelAllTime = null;
0743:
0744: List orderItemShipGroups = null;
0745: try {
0746: orderItemShipGroups = delegator.findByAnd(
0747: "OrderItemShipGroup", UtilMisc.toMap("orderId",
0748: orderId));
0749: } catch (GenericEntityException e) {
0750: Debug.logError(e,
0751: "Cannot get OrderItemShipGroups from orderId"
0752: + orderId, module);
0753: }
0754:
0755: Iterator orderItemShipGroupsIter = orderItemShipGroups
0756: .iterator();
0757: while (orderItemShipGroupsIter.hasNext()) {
0758: GenericValue orderItemShipGroup = (GenericValue) orderItemShipGroupsIter
0759: .next();
0760: List orderItems = new java.util.Vector();
0761: List orderItemShipGroupAssoc = null;
0762: try {
0763: orderItemShipGroupAssoc = delegator.findByAnd(
0764: "OrderItemShipGroupAssoc", UtilMisc.toMap(
0765: "shipGroupSeqId",
0766: orderItemShipGroup
0767: .get("shipGroupSeqId"),
0768: "orderId", orderId));
0769:
0770: Iterator assocIter = orderItemShipGroupAssoc
0771: .iterator();
0772: while (assocIter.hasNext()) {
0773: GenericValue assoc = (GenericValue) assocIter
0774: .next();
0775: GenericValue orderItem = assoc
0776: .getRelatedOne("OrderItem");
0777: if (orderItem != null) {
0778: orderItems.add(orderItem);
0779: }
0780: }
0781: } catch (GenericEntityException e) {
0782: Debug.logError(e,
0783: "Problem fetching OrderItemShipGroupAssoc",
0784: module);
0785: }
0786:
0787: /* Check the split preference. */
0788: boolean maySplit = false;
0789: if (orderItemShipGroup != null
0790: && orderItemShipGroup.get("maySplit") != null) {
0791: maySplit = orderItemShipGroup
0792: .getBoolean("maySplit").booleanValue();
0793: }
0794:
0795: /* Figure out if we must cancel all items. */
0796: if (!maySplit && cancelItems != null) {
0797: cancelAll = true;
0798: Set cancelSet = cancelItems.keySet();
0799: cancelAllTime = (Timestamp) cancelItems
0800: .get(cancelSet.iterator().next());
0801: }
0802:
0803: // if there are none to cancel just create an empty map
0804: if (cancelItems == null) {
0805: cancelItems = new HashMap();
0806: }
0807:
0808: if (orderItems != null) {
0809: List toBeStored = new ArrayList();
0810: Iterator orderItemsIter = orderItems.iterator();
0811: while (orderItemsIter.hasNext()) {
0812: GenericValue orderItem = (GenericValue) orderItemsIter
0813: .next();
0814: String orderItemSeqId = orderItem
0815: .getString("orderItemSeqId");
0816: Timestamp shipDate = (Timestamp) backOrderedItems
0817: .get(orderItemSeqId);
0818: Timestamp cancelDate = (Timestamp) cancelItems
0819: .get(orderItemSeqId);
0820: Timestamp currentCancelDate = orderItem
0821: .getTimestamp("autoCancelDate");
0822:
0823: Debug.logError("OI: " + orderId + " SEQID: "
0824: + orderItemSeqId + " cancelAll: "
0825: + cancelAll + " cancelDate: "
0826: + cancelDate, module);
0827: if (backOrderedItems
0828: .containsKey(orderItemSeqId)) {
0829: orderItem
0830: .set("estimatedShipDate", shipDate);
0831:
0832: if (currentCancelDate == null) {
0833: if (cancelAll || cancelDate != null) {
0834: if (orderItem
0835: .get("dontCancelSetUserLogin") == null
0836: && orderItem
0837: .get("dontCancelSetDate") == null) {
0838: if (cancelAllTime != null) {
0839: orderItem.set(
0840: "autoCancelDate",
0841: cancelAllTime);
0842: } else {
0843: orderItem.set(
0844: "autoCancelDate",
0845: cancelDate);
0846: }
0847: }
0848: }
0849: // only notify orders which have not already sent the final notice
0850: ordersToNotify.add(orderId);
0851: }
0852: toBeStored.add(orderItem);
0853: }
0854: }
0855: if (toBeStored.size() > 0) {
0856: try {
0857: delegator.storeAll(toBeStored);
0858: } catch (GenericEntityException e) {
0859: Debug.logError(e,
0860: "Problem storing order items",
0861: module);
0862: }
0863: }
0864: }
0865:
0866: }
0867: }
0868:
0869: // send off a notification for each order
0870: Iterator orderNotifyIter = ordersToNotify.iterator();
0871: while (orderNotifyIter.hasNext()) {
0872: String orderId = (String) orderNotifyIter.next();
0873:
0874: try {
0875: dispatcher.runAsync("sendOrderBackorderNotification",
0876: UtilMisc.toMap("orderId", orderId, "userLogin",
0877: userLogin));
0878: } catch (GenericServiceException e) {
0879: Debug
0880: .logError(
0881: e,
0882: "Problems sending off the notification",
0883: module);
0884: continue;
0885: }
0886: }
0887:
0888: return ServiceUtil.returnSuccess();
0889: }
0890:
0891: /**
0892: * Get Inventory Available for a Product based on the list of associated products. The final ATP and QOH will
0893: * be the minimum of all the associated products' inventory divided by their ProductAssoc.quantity
0894: * */
0895: public static Map getProductInventoryAvailableFromAssocProducts(
0896: DispatchContext dctx, Map context) {
0897: LocalDispatcher dispatcher = dctx.getDispatcher();
0898: List productAssocList = (List) context.get("assocProducts");
0899: String facilityId = (String) context.get("facilityId");
0900:
0901: Double availableToPromiseTotal = new Double(0);
0902: Double quantityOnHandTotal = new Double(0);
0903:
0904: if (productAssocList != null && productAssocList.size() > 0) {
0905: // minimum QOH and ATP encountered
0906: double minQuantityOnHandTotal = Double.MAX_VALUE;
0907: double minAvailableToPromiseTotal = Double.MAX_VALUE;
0908:
0909: // loop through each associated product.
0910: for (int i = 0; productAssocList.size() > i; i++) {
0911: GenericValue productAssoc = (GenericValue) productAssocList
0912: .get(i);
0913: String productIdTo = productAssoc
0914: .getString("productIdTo");
0915: Double assocQuantity = productAssoc
0916: .getDouble("quantity");
0917:
0918: // if there is no quantity for the associated product in ProductAssoc entity, default it to 1.0
0919: if (assocQuantity == null) {
0920: Debug
0921: .logWarning(
0922: "ProductAssoc from ["
0923: + productAssoc
0924: .getString("productId")
0925: + "] to ["
0926: + productAssoc
0927: .getString("productIdTo")
0928: + "] has no quantity, assuming 1.0",
0929: module);
0930: assocQuantity = new Double(1.0);
0931: }
0932:
0933: // figure out the inventory available for this associated product
0934: Map resultOutput = null;
0935: try {
0936: Map inputMap = UtilMisc.toMap("productId",
0937: productIdTo);
0938: if (facilityId != null) {
0939: inputMap.put("facilityId", facilityId);
0940: resultOutput = dispatcher.runSync(
0941: "getInventoryAvailableByFacility",
0942: inputMap);
0943: } else {
0944: resultOutput = dispatcher.runSync(
0945: "getProductInventoryAvailable",
0946: inputMap);
0947: }
0948: } catch (GenericServiceException e) {
0949: Debug
0950: .logError(
0951: e,
0952: "Problems getting inventory available by facility",
0953: module);
0954: return ServiceUtil.returnError(e.getMessage());
0955: }
0956:
0957: // Figure out what the QOH and ATP inventory would be with this associated product
0958: Double currentQuantityOnHandTotal = (Double) resultOutput
0959: .get("quantityOnHandTotal");
0960: Double currentAvailableToPromiseTotal = (Double) resultOutput
0961: .get("availableToPromiseTotal");
0962: double tmpQuantityOnHandTotal = currentQuantityOnHandTotal
0963: .doubleValue()
0964: / assocQuantity.doubleValue();
0965: double tmpAvailableToPromiseTotal = currentAvailableToPromiseTotal
0966: .doubleValue()
0967: / assocQuantity.doubleValue();
0968:
0969: // reset the minimum QOH and ATP quantities if those quantities for this product are less
0970: if (tmpQuantityOnHandTotal < minQuantityOnHandTotal) {
0971: minQuantityOnHandTotal = tmpQuantityOnHandTotal;
0972: }
0973: if (tmpAvailableToPromiseTotal < minAvailableToPromiseTotal) {
0974: minAvailableToPromiseTotal = tmpAvailableToPromiseTotal;
0975: }
0976:
0977: if (Debug.verboseOn()) {
0978: Debug.logVerbose(
0979: "productIdTo = " + productIdTo
0980: + " assocQuantity = "
0981: + assocQuantity + "current QOH "
0982: + currentQuantityOnHandTotal
0983: + "currentATP = "
0984: + currentAvailableToPromiseTotal
0985: + " minQOH = "
0986: + minQuantityOnHandTotal
0987: + " minATP = "
0988: + minAvailableToPromiseTotal,
0989: module);
0990: }
0991: }
0992: // the final QOH and ATP quantities are the minimum of all the products
0993: quantityOnHandTotal = new Double(minQuantityOnHandTotal);
0994: availableToPromiseTotal = new Double(
0995: minAvailableToPromiseTotal);
0996: }
0997:
0998: Map result = ServiceUtil.returnSuccess();
0999: result.put("availableToPromiseTotal", availableToPromiseTotal);
1000: result.put("quantityOnHandTotal", quantityOnHandTotal);
1001: return result;
1002: }
1003:
1004: public static Map getProductInventorySummaryForItems(
1005: DispatchContext dctx, Map context) {
1006: GenericDelegator delegator = dctx.getDelegator();
1007: LocalDispatcher dispatcher = dctx.getDispatcher();
1008: List orderItems = (List) context.get("orderItems");
1009: Map atpMap = new HashMap();
1010: Map qohMap = new HashMap();
1011: Map mktgPkgAtpMap = new HashMap();
1012: Map mktgPkgQohMap = new HashMap();
1013: Map results = ServiceUtil.returnSuccess();
1014:
1015: // get a list of all available facilities for looping
1016: List facilities = null;
1017: try {
1018: facilities = delegator.findAll("Facility");
1019: } catch (GenericEntityException e) {
1020: Debug.logError(e, "Couldn't get list of facilities.",
1021: module);
1022: return ServiceUtil
1023: .returnError("Unable to locate facilities.");
1024: }
1025:
1026: // loop through all the order items
1027: Iterator iter = orderItems.iterator();
1028: while (iter.hasNext()) {
1029: GenericValue orderItem = (GenericValue) iter.next();
1030: String productId = orderItem.getString("productId");
1031:
1032: if ((productId == null) || productId.equals(""))
1033: continue;
1034:
1035: GenericValue product = null;
1036: try {
1037: product = orderItem.getRelatedOneCache("Product");
1038: } catch (GenericEntityException e) {
1039: Debug.logError(e, "Couldn't get product.", module);
1040: return ServiceUtil
1041: .returnError("Unable to retrive product with id ["
1042: + productId + "]");
1043: }
1044:
1045: double atp = 0.0;
1046: double qoh = 0.0;
1047: double mktgPkgAtp = 0.0;
1048: double mktgPkgQoh = 0.0;
1049: Iterator facilityIter = facilities.iterator();
1050:
1051: // loop through all the facilities
1052: while (facilityIter.hasNext()) {
1053: GenericValue facility = (GenericValue) facilityIter
1054: .next();
1055: Map invResult = null;
1056: Map mktgPkgInvResult = null;
1057:
1058: // get both the real ATP/QOH available and the quantities available from marketing packages
1059: try {
1060: if ("MARKETING_PKG_AUTO".equals(product
1061: .getString("productTypeId"))) {
1062: mktgPkgInvResult = dispatcher
1063: .runSync(
1064: "getMktgPackagesAvailable",
1065: UtilMisc
1066: .toMap(
1067: "productId",
1068: productId,
1069: "facilityId",
1070: facility
1071: .getString("facilityId")));
1072: }
1073: invResult = dispatcher.runSync(
1074: "getInventoryAvailableByFacility",
1075: UtilMisc.toMap("productId", productId,
1076: "facilityId", facility
1077: .getString("facilityId")));
1078: } catch (GenericServiceException e) {
1079: String msg = "Could not find inventory for facility ["
1080: + facility.getString("facilityId") + "]";
1081: Debug.logError(e, msg, module);
1082: return ServiceUtil.returnError(msg);
1083: }
1084:
1085: // add the results for this facility to the ATP/QOH counter for all facilities
1086: if (!ServiceUtil.isError(invResult)) {
1087: Double fatp = (Double) invResult
1088: .get("availableToPromiseTotal");
1089: Double fqoh = (Double) invResult
1090: .get("quantityOnHandTotal");
1091: if (fatp != null)
1092: atp += fatp.doubleValue();
1093: if (fqoh != null)
1094: qoh += fqoh.doubleValue();
1095: }
1096: if (("MARKETING_PKG_AUTO".equals(product
1097: .getString("productTypeId")))
1098: && (!ServiceUtil.isError(mktgPkgInvResult))) {
1099: Double fatp = (Double) mktgPkgInvResult
1100: .get("availableToPromiseTotal");
1101: Double fqoh = (Double) mktgPkgInvResult
1102: .get("quantityOnHandTotal");
1103: if (fatp != null)
1104: mktgPkgAtp += fatp.doubleValue();
1105: if (fqoh != null)
1106: mktgPkgQoh += fqoh.doubleValue();
1107: }
1108: }
1109:
1110: atpMap.put(productId, new Double(atp));
1111: qohMap.put(productId, new Double(qoh));
1112: mktgPkgAtpMap.put(productId, new Double(mktgPkgAtp));
1113: mktgPkgQohMap.put(productId, new Double(mktgPkgQoh));
1114: }
1115:
1116: results.put("availableToPromiseMap", atpMap);
1117: results.put("quantityOnHandMap", qohMap);
1118: results.put("mktgPkgATPMap", mktgPkgAtpMap);
1119: results.put("mktgPkgQOHMap", mktgPkgQohMap);
1120: return results;
1121: }
1122:
1123: public static Map getProductInventoryAndFacilitySummary(
1124: DispatchContext dctx, Map context) {
1125: GenericDelegator delegator = dctx.getDelegator();
1126: LocalDispatcher dispatcher = dctx.getDispatcher();
1127: Timestamp checkTime = (Timestamp) context.get("checkTime");
1128: String facilityId = (String) context.get("facilityId");
1129: String productId = (String) context.get("productId");
1130: String minimumStock = (String) context.get("minimumStock");
1131:
1132: Map result = new HashMap();
1133: Map resultOutput = new HashMap();
1134:
1135: Map contextInput = UtilMisc.toMap("productId", productId,
1136: "facilityId", facilityId);
1137: GenericValue product = null;
1138: try {
1139: product = delegator.findByPrimaryKey("Product", UtilMisc
1140: .toMap("productId", productId));
1141: } catch (GenericEntityException e) {
1142: // TODO Auto-generated catch block
1143: e.printStackTrace();
1144: }
1145: if ("MARKETING_PKG_AUTO".equals(product
1146: .getString("productTypeId"))) {
1147: try {
1148: resultOutput = dispatcher.runSync(
1149: "getMktgPackagesAvailable", contextInput);
1150: } catch (GenericServiceException e) {
1151: // TODO Auto-generated catch block
1152: e.printStackTrace();
1153: }
1154: } else {
1155: try {
1156: resultOutput = dispatcher
1157: .runSync("getInventoryAvailableByFacility",
1158: contextInput);
1159: } catch (GenericServiceException e) {
1160: // TODO Auto-generated catch block
1161: e.printStackTrace();
1162: }
1163: }
1164: // filter for quantities
1165: int minimumStockInt = 0;
1166: if (minimumStock != null) {
1167: minimumStockInt = new Double(minimumStock).intValue();
1168: }
1169:
1170: int quantityOnHandTotalInt = 0;
1171: if (resultOutput.get("quantityOnHandTotal") != null) {
1172: quantityOnHandTotalInt = ((Double) resultOutput
1173: .get("quantityOnHandTotal")).intValue();
1174: }
1175: int offsetQOHQtyAvailable = quantityOnHandTotalInt
1176: - minimumStockInt;
1177:
1178: int availableToPromiseTotalInt = 0;
1179: if (resultOutput.get("availableToPromiseTotal") != null) {
1180: availableToPromiseTotalInt = ((Double) resultOutput
1181: .get("availableToPromiseTotal")).intValue();
1182: }
1183: int offsetATPQtyAvailable = availableToPromiseTotalInt
1184: - minimumStockInt;
1185:
1186: double quantityOnOrder = InventoryWorker
1187: .getOutstandingPurchasedQuantity(productId, delegator);
1188: result.put("totalQuantityOnHand", resultOutput.get(
1189: "quantityOnHandTotal").toString());
1190: result.put("totalAvailableToPromise", resultOutput.get(
1191: "availableToPromiseTotal").toString());
1192: result.put("quantityOnOrder", new Double(quantityOnOrder));
1193:
1194: result.put("offsetQOHQtyAvailable", new Integer(
1195: offsetQOHQtyAvailable));
1196: result.put("offsetATPQtyAvailable", new Integer(
1197: offsetATPQtyAvailable));
1198:
1199: List productPrices = null;
1200: try {
1201: productPrices = (List) delegator.findByAndCache(
1202: "ProductPrice", UtilMisc.toMap("productId",
1203: productId), UtilMisc.toList("-fromDate"));
1204: } catch (GenericEntityException e) {
1205: // TODO Auto-generated catch block
1206: e.printStackTrace();
1207: }
1208: Iterator pricesIt = productPrices.iterator();
1209: //change this for product price
1210: while (pricesIt.hasNext()) {
1211: GenericValue onePrice = (GenericValue) pricesIt.next();
1212: if (onePrice.getString("productPriceTypeId").equals(
1213: "DEFAULT_PRICE")) { //defaultPrice
1214: result.put("defultPrice", onePrice.getDouble("price"));
1215: } else if (onePrice.getString("productPriceTypeId").equals(
1216: "WHOLESALE_PRICE")) {//
1217: result.put("wholeSalePrice", onePrice
1218: .getDouble("price"));
1219: } else if (onePrice.getString("productPriceTypeId").equals(
1220: "LIST_PRICE")) {//listPrice
1221: result.put("listPrice", onePrice.getDouble("price"));
1222: } else {
1223: result.put("defultPrice", onePrice.getDouble("price"));
1224: result.put("listPrice", onePrice.getDouble("price"));
1225: result.put("wholeSalePrice", onePrice
1226: .getDouble("price"));
1227: }
1228: }
1229:
1230: DynamicViewEntity salesUsageViewEntity = new DynamicViewEntity();
1231: DynamicViewEntity productionUsageViewEntity = new DynamicViewEntity();
1232: if (!UtilValidate.isEmpty(checkTime)) {
1233:
1234: // Construct a dynamic view entity to search against for sales usage quantities
1235: salesUsageViewEntity.addMemberEntity("OI", "OrderItem");
1236: salesUsageViewEntity.addMemberEntity("OH", "OrderHeader");
1237: salesUsageViewEntity.addMemberEntity("ItIss",
1238: "ItemIssuance");
1239: salesUsageViewEntity.addMemberEntity("InvIt",
1240: "InventoryItem");
1241: salesUsageViewEntity.addViewLink("OI", "OH", new Boolean(
1242: false), ModelKeyMap.makeKeyMapList("orderId"));
1243: salesUsageViewEntity.addViewLink("OI", "ItIss",
1244: new Boolean(false), ModelKeyMap.makeKeyMapList(
1245: "orderId", "orderId", "orderItemSeqId",
1246: "orderItemSeqId"));
1247: salesUsageViewEntity.addViewLink("ItIss", "InvIt",
1248: new Boolean(false), ModelKeyMap
1249: .makeKeyMapList("inventoryItemId"));
1250: salesUsageViewEntity.addAlias("OI", "productId");
1251: salesUsageViewEntity.addAlias("OH", "statusId");
1252: salesUsageViewEntity.addAlias("OH", "orderTypeId");
1253: salesUsageViewEntity.addAlias("OH", "orderDate");
1254: salesUsageViewEntity.addAlias("ItIss", "inventoryItemId");
1255: salesUsageViewEntity.addAlias("ItIss", "quantity");
1256: salesUsageViewEntity.addAlias("InvIt", "facilityId");
1257:
1258: // Construct a dynamic view entity to search against for production usage quantities
1259: productionUsageViewEntity.addMemberEntity("WEIA",
1260: "WorkEffortInventoryAssign");
1261: productionUsageViewEntity.addMemberEntity("WE",
1262: "WorkEffort");
1263: productionUsageViewEntity.addMemberEntity("II",
1264: "InventoryItem");
1265: productionUsageViewEntity.addViewLink("WEIA", "WE",
1266: new Boolean(false), ModelKeyMap
1267: .makeKeyMapList("workEffortId"));
1268: productionUsageViewEntity.addViewLink("WEIA", "II",
1269: new Boolean(false), ModelKeyMap
1270: .makeKeyMapList("inventoryItemId"));
1271: productionUsageViewEntity.addAlias("WEIA", "quantity");
1272: productionUsageViewEntity.addAlias("WE",
1273: "actualCompletionDate");
1274: productionUsageViewEntity
1275: .addAlias("WE", "workEffortTypeId");
1276: productionUsageViewEntity.addAlias("II", "facilityId");
1277: productionUsageViewEntity.addAlias("II", "productId");
1278:
1279: }
1280: if (!UtilValidate.isEmpty(checkTime)) {
1281:
1282: // Make a query against the sales usage view entity
1283: EntityListIterator salesUsageIt = null;
1284: try {
1285: salesUsageIt = delegator
1286: .findListIteratorByCondition(
1287: salesUsageViewEntity,
1288: new EntityConditionList(
1289: UtilMisc
1290: .toList(
1291: new EntityExpr(
1292: "facilityId",
1293: EntityOperator.EQUALS,
1294: facilityId),
1295: new EntityExpr(
1296: "productId",
1297: EntityOperator.EQUALS,
1298: productId),
1299: new EntityExpr(
1300: "statusId",
1301: EntityOperator.IN,
1302: UtilMisc
1303: .toList(
1304: "ORDER_COMPLETED",
1305: "ORDER_APPROVED",
1306: "ORDER_HELD")),
1307: new EntityExpr(
1308: "orderTypeId",
1309: EntityOperator.EQUALS,
1310: "SALES_ORDER"),
1311: new EntityExpr(
1312: "orderDate",
1313: EntityOperator.GREATER_THAN_EQUAL_TO,
1314: checkTime)),
1315: EntityOperator.AND), null,
1316: null, null, null);
1317: } catch (GenericEntityException e2) {
1318: // TODO Auto-generated catch block
1319: e2.printStackTrace();
1320: }
1321:
1322: // Sum the sales usage quantities found
1323: double salesUsageQuantity = 0;
1324: GenericValue salesUsageItem = null;
1325: while ((salesUsageItem = (GenericValue) salesUsageIt.next()) != null) {
1326: if (salesUsageItem.get("quantity") != null) {
1327: try {
1328: salesUsageQuantity += salesUsageItem.getDouble(
1329: "quantity").doubleValue();
1330: } catch (Exception e) {
1331: // Ignore
1332: }
1333: }
1334: }
1335: try {
1336: salesUsageIt.close();
1337: } catch (GenericEntityException e2) {
1338: // TODO Auto-generated catch block
1339: e2.printStackTrace();
1340: }
1341:
1342: // Make a query against the production usage view entity
1343: EntityListIterator productionUsageIt = null;
1344: try {
1345: productionUsageIt = delegator
1346: .findListIteratorByCondition(
1347: productionUsageViewEntity,
1348: new EntityConditionList(
1349: UtilMisc
1350: .toList(
1351: new EntityExpr(
1352: "facilityId",
1353: EntityOperator.EQUALS,
1354: facilityId),
1355: new EntityExpr(
1356: "productId",
1357: EntityOperator.EQUALS,
1358: productId),
1359: new EntityExpr(
1360: "workEffortTypeId",
1361: EntityOperator.EQUALS,
1362: "PROD_ORDER_TASK"),
1363: new EntityExpr(
1364: "actualCompletionDate",
1365: EntityOperator.GREATER_THAN_EQUAL_TO,
1366: checkTime)),
1367: EntityOperator.AND), null,
1368: null, null, null);
1369: } catch (GenericEntityException e1) {
1370: // TODO Auto-generated catch block
1371: e1.printStackTrace();
1372: }
1373:
1374: // Sum the production usage quantities found
1375: double productionUsageQuantity = 0;
1376: GenericValue productionUsageItem = null;
1377: while ((productionUsageItem = (GenericValue) productionUsageIt
1378: .next()) != null) {
1379: if (productionUsageItem.get("quantity") != null) {
1380: try {
1381: productionUsageQuantity += productionUsageItem
1382: .getDouble("quantity").doubleValue();
1383: } catch (Exception e) {
1384: // Ignore
1385: }
1386: }
1387: }
1388: try {
1389: productionUsageIt.close();
1390: } catch (GenericEntityException e) {
1391: // TODO Auto-generated catch block
1392: e.printStackTrace();
1393: }
1394:
1395: result.put("usageQuantity", new Double(
1396: (salesUsageQuantity + productionUsageQuantity)));
1397:
1398: }
1399: return result;
1400: }
1401:
1402: }
|