1 24 package org.ofbiz.product.inventory; 25 26 import java.sql.Timestamp ; 27 import java.util.ArrayList ; 28 import java.util.Calendar ; 29 import java.util.HashMap ; 30 import java.util.Iterator ; 31 import java.util.List ; 32 import java.util.Map ; 33 import java.util.Set ; 34 35 import org.ofbiz.base.util.Debug; 36 import org.ofbiz.base.util.UtilDateTime; 37 import org.ofbiz.base.util.UtilMisc; 38 import org.ofbiz.entity.GenericDelegator; 39 import org.ofbiz.entity.GenericEntityException; 40 import org.ofbiz.entity.GenericValue; 41 import org.ofbiz.entity.condition.EntityExpr; 42 import org.ofbiz.entity.condition.EntityOperator; 43 import org.ofbiz.service.DispatchContext; 44 import org.ofbiz.service.GenericServiceException; 45 import org.ofbiz.service.LocalDispatcher; 46 import org.ofbiz.service.ServiceUtil; 47 48 57 public class InventoryServices { 58 59 public final static String module = InventoryServices.class.getName(); 60 61 public static Map prepareInventoryTransfer(DispatchContext dctx, Map context) { 62 GenericDelegator delegator = dctx.getDelegator(); 63 String inventoryItemId = (String ) context.get("inventoryItemId"); 64 Double xferQty = (Double ) context.get("xferQty"); 65 GenericValue inventoryItem = null; 66 GenericValue newItem = null; 67 GenericValue userLogin = (GenericValue) context.get("userLogin"); 68 69 try { 70 inventoryItem = delegator.findByPrimaryKey("InventoryItem", UtilMisc.toMap("inventoryItemId", inventoryItemId)); 71 } catch (GenericEntityException e) { 72 return ServiceUtil.returnError("Inventory item lookup problem [" + e.getMessage() + "]"); 73 } 74 75 if (inventoryItem == null) { 76 return ServiceUtil.returnError("Cannot locate inventory item."); 77 } 78 79 try { 80 Map results = ServiceUtil.returnSuccess(); 81 82 String inventoryType = inventoryItem.getString("inventoryItemTypeId"); 83 if (inventoryType.equals("NON_SERIAL_INV_ITEM")) { 84 Double atp = inventoryItem.getDouble("availableToPromiseTotal"); 85 Double qoh = inventoryItem.getDouble("quantityOnHandTotal"); 86 87 if (atp == null) { 88 return ServiceUtil.returnError("The request transfer amount is not available, there is no available to promise on the Inventory Item with ID " + inventoryItem.getString("inventoryItemId")); 89 } 90 if (qoh == null) { 91 qoh = atp; 92 } 93 94 if (xferQty.doubleValue() > atp.doubleValue()) { 96 return ServiceUtil.returnError("The request transfer amount is not available, the available to promise [" + atp + "] is not sufficient for the desired transfer quantity [" + xferQty + "] on the Inventory Item with ID " + inventoryItem.getString("inventoryItemId")); 97 } 98 99 104 105 if (xferQty.doubleValue() < atp.doubleValue() || atp.doubleValue() < qoh.doubleValue()) { 109 Double negXferQty = new Double (-xferQty.doubleValue()); 110 newItem = GenericValue.create(inventoryItem); 116 newItem.set("availableToPromiseTotal", new Double (0)); 117 newItem.set("quantityOnHandTotal", new Double (0)); 118 119 String newSeqId = null; 120 try { 121 newSeqId = delegator.getNextSeqId("InventoryItem"); 122 } catch (IllegalArgumentException e) { 123 return ServiceUtil.returnError("ERROR: Could not get next sequence id for InventoryItem, cannot create item."); 124 } 125 126 newItem.set("inventoryItemId", newSeqId); 127 newItem.create(); 128 129 results.put("inventoryItemId", newItem.get("inventoryItemId")); 130 131 Map createNewDetailMap = UtilMisc.toMap("availableToPromiseDiff", xferQty, "quantityOnHandDiff", xferQty, 133 "inventoryItemId", newItem.get("inventoryItemId"), "userLogin", userLogin); 134 Map createUpdateDetailMap = UtilMisc.toMap("availableToPromiseDiff", negXferQty, "quantityOnHandDiff", negXferQty, 135 "inventoryItemId", inventoryItem.get("inventoryItemId"), "userLogin", userLogin); 136 137 try { 138 Map resultNew = dctx.getDispatcher().runSync("createInventoryItemDetail", createNewDetailMap); 139 if (ServiceUtil.isError(resultNew)) { 140 return ServiceUtil.returnError("Inventory Item Detail create problem in prepare inventory transfer", null, null, resultNew); 141 } 142 Map resultUpdate = dctx.getDispatcher().runSync("createInventoryItemDetail", createUpdateDetailMap); 143 if (ServiceUtil.isError(resultNew)) { 144 return ServiceUtil.returnError("Inventory Item Detail create problem in prepare inventory transfer", null, null, resultUpdate); 145 } 146 } catch (GenericServiceException e1) { 147 return ServiceUtil.returnError("Inventory Item Detail create problem in prepare inventory transfer: [" + e1.getMessage() + "]"); 148 } 149 } else { 150 results.put("inventoryItemId", inventoryItem.get("inventoryItemId")); 151 } 152 } else if (inventoryType.equals("SERIALIZED_INV_ITEM")) { 153 if (!"INV_AVAILABLE".equals(inventoryItem.getString("statusId"))) { 154 return ServiceUtil.returnError("Serialized inventory is not available for transfer."); 155 } 156 } 157 158 if (inventoryType.equals("NON_SERIAL_INV_ITEM")) { 161 GenericValue inventoryItemToClear = newItem == null ? inventoryItem : newItem; 163 164 inventoryItemToClear.refresh(); 165 double atp = inventoryItemToClear.get("availableToPromiseTotal") == null ? 0 : inventoryItemToClear.getDouble("availableToPromiseTotal").doubleValue(); 166 if (atp != 0) { 167 Map createDetailMap = UtilMisc.toMap("availableToPromiseDiff", new Double (-atp), 168 "inventoryItemId", inventoryItemToClear.get("inventoryItemId"), "userLogin", userLogin); 169 try { 170 Map result = dctx.getDispatcher().runSync("createInventoryItemDetail", createDetailMap); 171 if (ServiceUtil.isError(result)) { 172 return ServiceUtil.returnError("Inventory Item Detail create problem in complete inventory transfer", null, null, result); 173 } 174 } catch (GenericServiceException e1) { 175 return ServiceUtil.returnError("Inventory Item Detail create problem in complete inventory transfer: [" + e1.getMessage() + "]"); 176 } 177 } 178 } else if (inventoryType.equals("SERIALIZED_INV_ITEM")) { 179 if (newItem != null) { 181 newItem.refresh(); 182 newItem.set("statusId", "INV_BEING_TRANSFERED"); 183 newItem.store(); 184 results.put("inventoryItemId", newItem.get("inventoryItemId")); 185 } else { 186 inventoryItem.refresh(); 187 inventoryItem.set("statusId", "INV_BEING_TRANSFERED"); 188 inventoryItem.store(); 189 results.put("inventoryItemId", inventoryItem.get("inventoryItemId")); 190 } 191 } 192 193 return results; 194 } catch (GenericEntityException e) { 195 return ServiceUtil.returnError("Inventory store/create problem [" + e.getMessage() + "]"); 196 } 197 } 198 199 public static Map completeInventoryTransfer(DispatchContext dctx, Map context) { 200 GenericDelegator delegator = dctx.getDelegator(); 201 String inventoryTransferId = (String ) context.get("inventoryTransferId"); 202 GenericValue inventoryTransfer = null; 203 GenericValue inventoryItem = null; 204 GenericValue destinationFacility = null; 205 GenericValue userLogin = (GenericValue) context.get("userLogin"); 206 207 try { 208 inventoryTransfer = delegator.findByPrimaryKey("InventoryTransfer", 209 UtilMisc.toMap("inventoryTransferId", inventoryTransferId)); 210 inventoryItem = inventoryTransfer.getRelatedOne("InventoryItem"); 211 destinationFacility = inventoryTransfer.getRelatedOne("ToFacility"); 212 } catch (GenericEntityException e) { 213 return ServiceUtil.returnError("Inventory Item/Transfer lookup problem [" + e.getMessage() + "]"); 214 } 215 216 if (inventoryTransfer == null || inventoryItem == null) { 217 return ServiceUtil.returnError("ERROR: Lookup of InventoryTransfer and/or InventoryItem failed!"); 218 } 219 220 String inventoryType = inventoryItem.getString("inventoryItemTypeId"); 221 222 if (inventoryTransfer.get("receiveDate") == null) { 224 inventoryTransfer.set("receiveDate", UtilDateTime.nowTimestamp()); 225 } 226 227 if (inventoryType.equals("NON_SERIAL_INV_ITEM")) { 228 double atp = inventoryItem.get("availableToPromiseTotal") == null ? 0 : inventoryItem.getDouble("availableToPromiseTotal").doubleValue(); 230 double qoh = inventoryItem.get("quantityOnHandTotal") == null ? 0 : inventoryItem.getDouble("quantityOnHandTotal").doubleValue(); 231 Map createDetailMap = UtilMisc.toMap("availableToPromiseDiff", new Double (qoh - atp), 232 "inventoryItemId", inventoryItem.get("inventoryItemId"), "userLogin", userLogin); 233 try { 234 Map result = dctx.getDispatcher().runSync("createInventoryItemDetail", createDetailMap); 235 if (ServiceUtil.isError(result)) { 236 return ServiceUtil.returnError("Inventory Item Detail create problem in complete inventory transfer", null, null, result); 237 } 238 } catch (GenericServiceException e1) { 239 return ServiceUtil.returnError("Inventory Item Detail create problem in complete inventory transfer: [" + e1.getMessage() + "]"); 240 } 241 try { 242 inventoryItem.refresh(); 243 } catch (GenericEntityException e) { 244 return ServiceUtil.returnError("Inventory refresh problem [" + e.getMessage() + "]"); 245 } 246 } else if (inventoryType.equals("SERIALIZED_INV_ITEM")) { 247 inventoryItem.set("statusId", "INV_AVAILABLE"); 248 } 249 250 Map updateInventoryItemMap = UtilMisc.toMap("inventoryItemId", inventoryItem.getString("inventoryItemId"), 252 "facilityId", inventoryTransfer.get("facilityIdTo"), 253 "containerId", inventoryTransfer.get("containerIdTo"), 254 "locationSeqId", inventoryTransfer.get("locationSeqIdTo"), 255 "userLogin", userLogin); 256 if (destinationFacility != null && destinationFacility.get("ownerPartyId") != null) { 260 String fromPartyId = inventoryItem.getString("ownerPartyId"); 261 String toPartyId = destinationFacility.getString("ownerPartyId"); 262 if (fromPartyId == null || !fromPartyId.equals(toPartyId)) { 263 updateInventoryItemMap.put("ownerPartyId", toPartyId); 264 } 265 } 266 try { 267 Map result = dctx.getDispatcher().runSync("updateInventoryItem", updateInventoryItemMap); 268 if (ServiceUtil.isError(result)) { 269 return ServiceUtil.returnError("Inventory item store problem", null, null, result); 270 } 271 } catch (GenericServiceException exc) { 272 return ServiceUtil.returnError("Inventory item store problem [" + exc.getMessage() + "]"); 273 } 274 275 inventoryTransfer.set("statusId", "IXF_COMPLETE"); 277 278 try { 280 inventoryTransfer.store(); 281 } catch (GenericEntityException e) { 282 return ServiceUtil.returnError("Inventory store problem [" + e.getMessage() + "]"); 283 } 284 285 return ServiceUtil.returnSuccess(); 286 } 287 288 public static Map cancelInventoryTransfer(DispatchContext dctx, Map context) { 289 GenericDelegator delegator = dctx.getDelegator(); 290 String inventoryTransferId = (String ) context.get("inventoryTransferId"); 291 GenericValue inventoryTransfer = null; 292 GenericValue inventoryItem = null; 293 GenericValue userLogin = (GenericValue) context.get("userLogin"); 294 295 try { 296 inventoryTransfer = delegator.findByPrimaryKey("InventoryTransfer", 297 UtilMisc.toMap("inventoryTransferId", inventoryTransferId)); 298 inventoryItem = inventoryTransfer.getRelatedOne("InventoryItem"); 299 } catch (GenericEntityException e) { 300 return ServiceUtil.returnError("Inventory Item/Transfer lookup problem [" + e.getMessage() + "]"); 301 } 302 303 if (inventoryTransfer == null || inventoryItem == null) { 304 return ServiceUtil.returnError("ERROR: Lookup of InventoryTransfer and/or InventoryItem failed!"); 305 } 306 307 String inventoryType = inventoryItem.getString("inventoryItemTypeId"); 308 309 if (inventoryType.equals("NON_SERIAL_INV_ITEM")) { 311 double atp = inventoryItem.get("availableToPromiseTotal") == null ? 0 : inventoryItem.getDouble("availableToPromiseTotal").doubleValue(); 313 double qoh = inventoryItem.get("quantityOnHandTotal") == null ? 0 : inventoryItem.getDouble("quantityOnHandTotal").doubleValue(); 314 Map createDetailMap = UtilMisc.toMap("availableToPromiseDiff", new Double (qoh - atp), 315 "inventoryItemId", inventoryItem.get("inventoryItemId"), 316 "userLogin", userLogin); 317 try { 318 Map result = dctx.getDispatcher().runSync("createInventoryItemDetail", createDetailMap); 319 if (ServiceUtil.isError(result)) { 320 return ServiceUtil.returnError("Inventory Item Detail create problem in cancel inventory transfer", null, null, result); 321 } 322 } catch (GenericServiceException e1) { 323 return ServiceUtil.returnError("Inventory Item Detail create problem in cancel inventory transfer: [" + e1.getMessage() + "]"); 324 } 325 } else if (inventoryType.equals("SERIALIZED_INV_ITEM")) { 326 inventoryItem.set("statusId", "INV_AVAILABLE"); 327 try { 329 inventoryItem.store(); 330 } catch (GenericEntityException e) { 331 return ServiceUtil.returnError("Inventory item store problem in cancel inventory transfer: [" + e.getMessage() + "]"); 332 } 333 } 334 335 return ServiceUtil.returnSuccess(); 336 } 337 338 339 public static Map checkInventoryAvailability(DispatchContext dctx, Map context) { 340 GenericDelegator delegator = dctx.getDelegator(); 341 LocalDispatcher dispatcher = dctx.getDispatcher(); 342 GenericValue userLogin = (GenericValue) context.get("userLogin"); 343 344 351 352 Map ordersToUpdate = new HashMap (); 353 Map ordersToCancel = new HashMap (); 354 355 List inventoryItems = null; 357 try { 358 List exprs = UtilMisc.toList(new EntityExpr("availableToPromiseTotal", EntityOperator.LESS_THAN, new Double (0))); 359 inventoryItems = delegator.findByAnd("InventoryItem", exprs); 360 } catch (GenericEntityException e) { 361 Debug.logError(e, "Trouble getting inventory items", module); 362 return ServiceUtil.returnError("Problem getting InventoryItem records"); 363 } 364 365 if (inventoryItems == null) { 366 Debug.logInfo("No items out of stock; no backorders to worry about", module); 367 return ServiceUtil.returnSuccess(); 368 } 369 370 Debug.log("OOS Inventory Items: " + inventoryItems.size(), module); 371 372 Iterator itemsIter = inventoryItems.iterator(); 373 while (itemsIter.hasNext()) { 374 GenericValue inventoryItem = (GenericValue) itemsIter.next(); 375 376 List shipmentAndItems = null; 378 try { 379 List exprs = new ArrayList (); 380 exprs.add(new EntityExpr("productId", EntityOperator.EQUALS, inventoryItem.get("productId"))); 381 exprs.add(new EntityExpr("destinationFacilityId", EntityOperator.EQUALS, inventoryItem.get("facilityId"))); 382 exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "SHIPMENT_DELIVERED")); 383 exprs.add(new EntityExpr("statusId", EntityOperator.NOT_EQUAL, "SHIPMENT_CANCELLED")); 384 shipmentAndItems = delegator.findByAnd("ShipmentAndItem", exprs, UtilMisc.toList("estimatedArrivalDate")); 385 } catch (GenericEntityException e) { 386 Debug.logError(e, "Problem getting ShipmentAndItem records", module); 387 return ServiceUtil.returnError("Problem getting ShipmentAndItem records"); 388 } 389 390 List reservations = null; 392 try { 393 reservations = inventoryItem.getRelated("OrderItemShipGrpInvRes", null, UtilMisc.toList("-reservedDatetime")); 394 } catch (GenericEntityException e) { 395 Debug.logError(e, "Problem getting related reservations", module); 396 return ServiceUtil.returnError("Problem getting related reservations"); 397 } 398 399 if (reservations == null) { 400 Debug.logWarning("No outstanding reservations for this inventory item, why is it negative then?", module); 401 continue; 402 } 403 404 Debug.log("Reservations for item: " + reservations.size(), module); 405 406 double availableBeforeReserved = inventoryItem.getDouble("availableToPromiseTotal").doubleValue(); 408 409 Iterator ri = reservations.iterator(); 411 while (ri.hasNext()) { 412 GenericValue reservation = (GenericValue) ri.next(); 413 String orderId = reservation.getString("orderId"); 414 String orderItemSeqId = reservation.getString("orderItemSeqId"); 415 Timestamp promisedDate = reservation.getTimestamp("promisedDatetime"); 416 Timestamp currentPromiseDate = reservation.getTimestamp("currentPromisedDate"); 417 Timestamp actualPromiseDate = currentPromiseDate; 418 if (actualPromiseDate == null) { 419 if (promisedDate != null) { 420 actualPromiseDate = promisedDate; 421 } else { 422 actualPromiseDate = reservation.getTimestamp("reservedDatetime"); 424 } 425 } 426 427 Debug.log("Promised Date: " + actualPromiseDate, module); 428 429 Timestamp nextShipDate = null; 431 double availableAtTime = 0.00; 432 Iterator si = shipmentAndItems.iterator(); 433 while (si.hasNext()) { 434 GenericValue shipmentItem = (GenericValue) si.next(); 435 availableAtTime += shipmentItem.getDouble("quantity").doubleValue(); 436 if (availableAtTime >= availableBeforeReserved) { 437 nextShipDate = shipmentItem.getTimestamp("estimatedArrivalDate"); 438 break; 439 } 440 } 441 442 Debug.log("Next Ship Date: " + nextShipDate, module); 443 444 Calendar pCal = Calendar.getInstance(); 446 pCal.setTimeInMillis(actualPromiseDate.getTime()); 447 pCal.add(Calendar.DAY_OF_YEAR, -1); 448 Timestamp modifiedPromisedDate = new Timestamp (pCal.getTimeInMillis()); 449 Timestamp now = UtilDateTime.nowTimestamp(); 450 451 Debug.log("Promised Date + 1: " + modifiedPromisedDate, module); 452 Debug.log("Now: " + now, module); 453 454 if (nextShipDate == null || nextShipDate.after(actualPromiseDate)) { 456 if (nextShipDate == null && modifiedPromisedDate.after(now)) { 457 Debug.log("No ship date known yet, but promised date hasn't approached, assuming it will be here on time", module); 459 } else { 460 Debug.log("We won't ship on time, getting notification info", module); 462 Map notifyItems = (Map ) ordersToUpdate.get(orderId); 463 if (notifyItems == null) { 464 notifyItems = new HashMap (); 465 } 466 notifyItems.put(orderItemSeqId, nextShipDate); 467 ordersToUpdate.put(orderId, notifyItems); 468 469 Calendar sCal = Calendar.getInstance(); 471 sCal.setTimeInMillis(actualPromiseDate.getTime()); 472 sCal.add(Calendar.DAY_OF_YEAR, 30); 473 Timestamp farPastPromised = new Timestamp (sCal.getTimeInMillis()); 474 475 boolean needToCancel = false; 477 if (nextShipDate == null || nextShipDate.after(farPastPromised)) { 478 Debug.log("Ship date is >30 past the promised date", module); 480 needToCancel = true; 481 } else if (currentPromiseDate != null && actualPromiseDate.equals(currentPromiseDate)) { 482 needToCancel = true; 484 } 485 486 if (needToCancel) { 488 Debug.log("Flagging the item to auto-cancel", module); 490 Map cancelItems = (Map ) ordersToCancel.get(orderId); 491 if (cancelItems == null) { 492 cancelItems = new HashMap (); 493 } 494 cancelItems.put(orderItemSeqId, farPastPromised); 495 ordersToCancel.put(orderId, cancelItems); 496 } 497 498 try { 500 reservation.set("currentPromisedDate", nextShipDate); 501 reservation.store(); 502 } catch (GenericEntityException e) { 503 Debug.logError(e, "Problem storing reservation : " + reservation, module); 504 } 505 } 506 } 507 508 availableBeforeReserved -= reservation.getDouble("quantity").doubleValue(); 510 } 511 } 512 513 List ordersToNotify = new ArrayList (); 515 Set orderSet = ordersToUpdate.keySet(); 516 Iterator orderIter = orderSet.iterator(); 517 while (orderIter.hasNext()) { 518 String orderId = (String ) orderIter.next(); 519 Map backOrderedItems = (Map ) ordersToUpdate.get(orderId); 520 Map cancelItems = (Map ) ordersToCancel.get(orderId); 521 boolean cancelAll = false; 522 Timestamp cancelAllTime = null; 523 524 List orderItemShipGroups = null; 525 try { 526 orderItemShipGroups= delegator.findByAnd("OrderItemShipGroup", 527 UtilMisc.toMap("orderId", orderId)); 528 } catch (GenericEntityException e) { 529 Debug.logError(e, "Cannot get OrderItemShipGroups from orderId" + orderId, module); 530 } 531 532 Iterator orderItemShipGroupsIter = orderItemShipGroups.iterator(); 533 while (orderItemShipGroupsIter.hasNext()) { 534 GenericValue orderItemShipGroup = (GenericValue)orderItemShipGroupsIter.next(); 535 List orderItems = new java.util.Vector (); 536 List orderItemShipGroupAssoc = null; 537 try { 538 orderItemShipGroupAssoc = 539 delegator.findByAnd("OrderItemShipGroupAssoc", 540 UtilMisc.toMap("shipGroupSeqId", 541 orderItemShipGroup.get("shipGroupSeqId"), 542 "orderId", 543 orderId)); 544 545 Iterator assocIter = orderItemShipGroupAssoc.iterator(); 546 while (assocIter.hasNext()) { 547 GenericValue assoc = (GenericValue)assocIter.next(); 548 GenericValue orderItem = assoc.getRelatedOne("OrderItem"); 549 if (orderItem != null) { 550 orderItems.add(orderItem); 551 } 552 } 553 } catch (GenericEntityException e) { 554 Debug.logError(e, "Problem fetching OrderItemShipGroupAssoc", module); 555 } 556 557 558 559 boolean maySplit = false; 560 if (orderItemShipGroup != null && orderItemShipGroup.get("maySplit") != null) { 561 maySplit = orderItemShipGroup.getBoolean("maySplit").booleanValue(); 562 } 563 564 565 if (!maySplit && cancelItems != null) { 566 cancelAll = true; 567 Set cancelSet = cancelItems.keySet(); 568 cancelAllTime = (Timestamp ) cancelItems.get(cancelSet.iterator().next()); 569 } 570 571 if (cancelItems == null) { 573 cancelItems = new HashMap (); 574 } 575 576 if (orderItems != null) { 577 List toBeStored = new ArrayList (); 578 Iterator orderItemsIter = orderItems.iterator(); 579 while (orderItemsIter.hasNext()) { 580 GenericValue orderItem = (GenericValue) orderItemsIter.next(); 581 String orderItemSeqId = orderItem.getString("orderItemSeqId"); 582 Timestamp shipDate = (Timestamp ) backOrderedItems.get(orderItemSeqId); 583 Timestamp cancelDate = (Timestamp ) cancelItems.get(orderItemSeqId); 584 Timestamp currentCancelDate = (Timestamp ) orderItem.getTimestamp("autoCancelDate"); 585 586 Debug.logError("OI: " + orderId + " SEQID: "+ orderItemSeqId + " cancelAll: " + cancelAll + " cancelDate: " + cancelDate, module); 587 if (backOrderedItems.containsKey(orderItemSeqId)) { 588 orderItem.set("estimatedShipDate", shipDate); 589 590 if (currentCancelDate == null) { 591 if (cancelAll || cancelDate != null) { 592 if (orderItem.get("dontCancelSetUserLogin") == null && orderItem.get("dontCancelSetDate") == null) { 593 if (cancelAllTime != null) { 594 orderItem.set("autoCancelDate", cancelAllTime); 595 } else { 596 orderItem.set("autoCancelDate", cancelDate); 597 } 598 } 599 } 600 ordersToNotify.add(orderId); 602 } 603 toBeStored.add(orderItem); 604 } 605 } 606 if (toBeStored.size() > 0) { 607 try { 608 delegator.storeAll(toBeStored); 609 } catch (GenericEntityException e) { 610 Debug.logError(e, "Problem storing order items", module); 611 } 612 } 613 } 614 615 616 } 617 } 618 619 Iterator orderNotifyIter = ordersToNotify.iterator(); 621 while (orderNotifyIter.hasNext()) { 622 String orderId = (String ) orderNotifyIter.next(); 623 624 try { 625 dispatcher.runAsync("sendOrderBackorderNotification", UtilMisc.toMap("orderId", orderId, "userLogin", userLogin)); 626 } catch (GenericServiceException e) { 627 Debug.logError(e, "Problems sending off the notification", module); 628 continue; 629 } 630 } 631 632 return ServiceUtil.returnSuccess(); 633 } 634 635 639 public static Map getProductInventoryAvailablefromAssocProducts(DispatchContext dctx, Map context) { 640 GenericDelegator delegator = dctx.getDelegator(); 641 LocalDispatcher dispatcher = dctx.getDispatcher(); 642 List productAssocList = (List ) context.get("assocProducts"); 643 644 Double availableToPromiseTotal = new Double (0); 645 Double quantityOnHandTotal = new Double (0); 646 647 if (productAssocList != null && productAssocList.size() > 0) { 648 double minQuantityOnHandTotal = Double.MAX_VALUE; 650 double minAvailableToPromiseTotal = Double.MAX_VALUE; 651 652 for (int i = 0; productAssocList.size() > i; i++) { 654 GenericValue productAssoc = (GenericValue) productAssocList.get(i); 655 String productIdTo = productAssoc.getString("productIdTo"); 656 Double assocQuantity = productAssoc.getDouble("quantity"); 657 658 if (assocQuantity == null) { 660 Debug.logWarning("ProductAssoc from [" + productAssoc.getString("productId") + "] to [" + productAssoc.getString("productIdTo") + "] has no quantity, assuming 1.0", module); 661 assocQuantity = new Double (1.0); 662 } 663 664 Map resultOutput = null; 666 try { 667 resultOutput = dispatcher.runSync("getProductInventoryAvailable", UtilMisc.toMap("productId", productIdTo)); 668 } catch (GenericServiceException e) { 669 Debug.logError(e, "Problems getting inventory available by facility", module); 670 return ServiceUtil.returnError(e.getMessage()); 671 } 672 673 Double currentQuantityOnHandTotal = (Double ) resultOutput.get("quantityOnHandTotal"); 675 Double currentAvailableToPromiseTotal = (Double ) resultOutput.get("availableToPromiseTotal"); 676 double tmpQuantityOnHandTotal = currentQuantityOnHandTotal.doubleValue()/assocQuantity.doubleValue(); 677 double tmpAvailableToPromiseTotal = currentAvailableToPromiseTotal.doubleValue()/assocQuantity.doubleValue(); 678 679 if (tmpQuantityOnHandTotal < minQuantityOnHandTotal) { 681 minQuantityOnHandTotal = tmpQuantityOnHandTotal; 682 } 683 if (tmpAvailableToPromiseTotal < minAvailableToPromiseTotal) { 684 minAvailableToPromiseTotal = tmpAvailableToPromiseTotal; 685 } 686 687 if (Debug.verboseOn()) { 688 Debug.logVerbose("productIdTo = " + productIdTo + " assocQuantity = " + assocQuantity + "current QOH " + currentQuantityOnHandTotal + 689 "currentATP = " + currentAvailableToPromiseTotal + " minQOH = " + minQuantityOnHandTotal + " minATP = " + minAvailableToPromiseTotal, module); 690 } 691 } 692 quantityOnHandTotal = new Double (minQuantityOnHandTotal); 694 availableToPromiseTotal = new Double (minAvailableToPromiseTotal); 695 } 696 697 Map result = ServiceUtil.returnSuccess(); 698 result.put("availableToPromiseTotal", availableToPromiseTotal); 699 result.put("quantityOnHandTotal", quantityOnHandTotal); 700 return result; 701 } 702 703 707 public static Map getProductInventorySummaryForItems(DispatchContext dctx, Map context) { 708 GenericDelegator delegator = dctx.getDelegator(); 709 LocalDispatcher dispatcher = dctx.getDispatcher(); 710 List orderItems = (List ) context.get("orderItems"); 711 Map atpMap = new HashMap (); 712 Map qohMap = new HashMap (); 713 Map results = ServiceUtil.returnSuccess(); 714 results.put("availableToPromiseMap", atpMap); 715 results.put("quantityOnHandMap", qohMap); 716 717 List facilities = null; 718 try { 719 facilities = delegator.findAll("Facility"); 720 } catch (GenericEntityException e) { 721 Debug.logError(e, "Couldn't get list of facilities.", module); 722 return ServiceUtil.returnError("Unable to locate facilities."); 723 } 724 725 Iterator iter = orderItems.iterator(); 726 while (iter.hasNext()) { 727 GenericValue orderItem = (GenericValue) iter.next(); 728 String productId = orderItem.getString("productId"); 729 730 if ((productId == null) || productId.equals("")) continue; 731 732 double atp = 0.0; 733 double qoh = 0.0; 734 Iterator facilityIter = facilities.iterator(); 735 while (facilityIter.hasNext()) { 736 GenericValue facility = (GenericValue) facilityIter.next(); 737 Map params = UtilMisc.toMap("productId", productId, "facilityId", facility.getString("facilityId")); 738 Map invResult = null; 739 try { 740 invResult = dispatcher.runSync("getInventoryAvailableByFacility", params); 741 } catch (GenericServiceException e) { 742 String msg = "Could not find inventory for facility [" + facility.getString("facilityId") + "]"; 743 Debug.logError(e, msg, module); 744 return ServiceUtil.returnError(msg); 745 } 746 Double fatp = (Double ) invResult.get("availableToPromiseTotal"); 747 Double fqoh = (Double ) invResult.get("quantityOnHandTotal"); 748 if (fatp != null) atp += fatp.doubleValue(); 749 if (fqoh != null) qoh += fqoh.doubleValue(); 750 } 751 atpMap.put(productId, new Double (atp)); 752 qohMap.put(productId, new Double (qoh)); 753 } 754 return results; 755 } 756 } 757 | Popular Tags |