1 25 package org.ofbiz.shipment.packing; 26 27 import java.util.ArrayList ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Map ; 31 32 import javolution.util.FastMap; 33 import javolution.util.FastList; 34 35 import org.ofbiz.base.util.Debug; 36 import org.ofbiz.base.util.GeneralException; 37 import org.ofbiz.base.util.UtilFormatOut; 38 import org.ofbiz.base.util.UtilMisc; 39 import org.ofbiz.base.util.UtilValidate; 40 import org.ofbiz.entity.GenericDelegator; 41 import org.ofbiz.entity.GenericValue; 42 import org.ofbiz.entity.util.EntityUtil; 43 import org.ofbiz.service.GenericDispatcher; 44 import org.ofbiz.service.GenericServiceException; 45 import org.ofbiz.service.LocalDispatcher; 46 import org.ofbiz.service.ServiceUtil; 47 import org.ofbiz.product.product.ProductWorker; 48 49 55 public class PackingSession implements java.io.Serializable { 56 57 public static final String module = PackingSession.class.getName(); 58 59 protected GenericValue userLogin = null; 60 protected String primaryOrderId = null; 61 protected String primaryShipGrp = null; 62 protected String dispatcherName = null; 63 protected String delegatorName = null; 64 protected String facilityId = null; 65 protected String shipmentId = null; 66 protected String instructions = null; 67 protected List packEvents = null; 68 protected List packLines = null; 69 protected int packageSeq = -1; 70 protected int status = 1; 71 72 private transient GenericDelegator _delegator = null; 73 private transient LocalDispatcher _dispatcher = null; 74 75 public PackingSession(LocalDispatcher dispatcher, GenericValue userLogin, String facilityId, String orderId, String shipGrp) { 76 this._dispatcher = dispatcher; 77 this.dispatcherName = dispatcher.getName(); 78 79 this._delegator = _dispatcher.getDelegator(); 80 this.delegatorName = _delegator.getDelegatorName(); 81 82 this.primaryOrderId = orderId; 83 this.primaryShipGrp = shipGrp; 84 this.userLogin = userLogin; 85 this.facilityId = facilityId; 86 this.packLines = new ArrayList (); 87 this.packEvents = new ArrayList (); 88 this.packageSeq = 1; 89 } 90 91 public PackingSession(LocalDispatcher dispatcher, GenericValue userLogin, String facilityId) { 92 this(dispatcher, userLogin, facilityId, null, null); 93 } 94 95 public PackingSession(LocalDispatcher dispatcher, GenericValue userLogin) { 96 this(dispatcher, userLogin, null, null, null); 97 } 98 99 public void addOrIncreaseLine(String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, double quantity, int packageSeqId) throws GeneralException { 100 if (status == 0) { 102 throw new GeneralException("Packing session has been completed; be sure to CLEAR before packing a new order! [000]"); 103 } 104 105 productId = ProductWorker.findProductId(this.getDelegator(), productId); 107 108 if (orderId == null) { 110 orderId = primaryOrderId; 111 } 112 if (shipGroupSeqId == null) { 113 shipGroupSeqId = primaryShipGrp; 114 } 115 if (orderItemSeqId == null && productId != null) { 116 orderItemSeqId = this.findOrderItemSeqId(productId, orderId, shipGroupSeqId, quantity); 117 } 118 119 Map invLookup = FastMap.newInstance(); 121 invLookup.put("orderId", orderId); 122 invLookup.put("orderItemSeqId", orderItemSeqId); 123 invLookup.put("shipGroupSeqId", shipGroupSeqId); 124 List reservations = this.getDelegator().findByAnd("OrderItemShipGrpInvRes", invLookup); 125 126 if (UtilValidate.isEmpty(reservations)) { 128 throw new GeneralException("No inventory reservations available; cannot pack this item! [101]"); 129 } 130 131 if (reservations.size() == 1) { 133 GenericValue res = EntityUtil.getFirst(reservations); 134 int checkCode = this.checkLineForAdd(res, orderId, orderItemSeqId, shipGroupSeqId, quantity, packageSeqId); 135 this.createPackLineItem(checkCode, res, orderId, orderItemSeqId, shipGroupSeqId, productId, quantity, packageSeqId); 136 } else { 137 Map toCreateMap = FastMap.newInstance(); 139 Iterator i = reservations.iterator(); 140 double qtyRemain = quantity; 141 142 while (i.hasNext() && qtyRemain > 0) { 143 GenericValue res = (GenericValue) i.next(); 144 double resQty = res.getDouble("quantity").doubleValue(); 145 double thisQty = resQty > qtyRemain ? qtyRemain : resQty; 146 147 int thisCheck = this.checkLineForAdd(res, orderId, orderItemSeqId, shipGroupSeqId, thisQty, packageSeqId); 148 switch (thisCheck) { 149 case 2: 150 Debug.log("Packing check returned '2' - new pack line will be created!", module); 151 toCreateMap.put(res, new Double (resQty)); 152 qtyRemain -= resQty; 153 break; 154 case 1: 155 Debug.log("Packing check returned '1' - existing pack line has been updated!", module); 156 qtyRemain -= resQty; 157 break; 158 case 0: 159 Debug.log("Packing check returned '0' - doing nothing.", module); 160 break; 161 } 162 } 163 164 if (qtyRemain == 0) { 165 Iterator x = toCreateMap.keySet().iterator(); 166 while (x.hasNext()) { 167 GenericValue res = (GenericValue) x.next(); 168 Double qty = (Double ) toCreateMap.get(res); 169 this.createPackLineItem(2, res, orderId, orderItemSeqId, shipGroupSeqId, productId, qty.doubleValue(), packageSeqId); 170 } 171 } else { 172 throw new GeneralException("Not enough inventory reservation available; cannot pack the item! [103]"); 173 } 174 } 175 176 this.runEvents(PackingEvent.EVENT_CODE_ADD); 178 } 179 180 public void addOrIncreaseLine(String orderId, String orderItemSeqId, String shipGroupSeqId, double quantity, int packageSeqId) throws GeneralException { 181 this.addOrIncreaseLine(orderId, orderItemSeqId, shipGroupSeqId, null, quantity, packageSeqId); 182 } 183 184 public void addOrIncreaseLine(String productId, double quantity, int packageSeqId) throws GeneralException { 185 this.addOrIncreaseLine(null, null, null, productId, quantity, packageSeqId); 186 } 187 188 public PackingSessionLine findLine(String orderId, String orderItemSeqId, String shipGroupSeqId, String inventoryItemId, int packageSeq) { 189 List lines = this.getLines(); 190 Iterator i = lines.iterator(); 191 while (i.hasNext()) { 192 PackingSessionLine line = (PackingSessionLine) i.next(); 193 if (orderId.equals(line.getOrderId()) && 194 orderItemSeqId.equals(line.getOrderItemSeqId()) && 195 shipGroupSeqId.equals(line.getShipGroupSeqId()) && 196 inventoryItemId.equals(line.getInventoryItemId()) && 197 packageSeq == line.getPackageSeq()) { 198 return line; 199 } 200 } 201 return null; 202 } 203 204 protected void createPackLineItem(int checkCode, GenericValue res, String orderId, String orderItemSeqId, String shipGroupSeqId, String productId, double quantity, int packageSeqId) throws GeneralException { 205 switch(checkCode) { 207 case 0: 208 throw new GeneralException("Not enough inventory reservation available; cannot pack the item! [201]"); 210 case 1: 211 break; 213 case 2: 214 String invItemId = res.getString("inventoryItemId"); 216 packLines.add(new PackingSessionLine(orderId, orderItemSeqId, shipGroupSeqId, productId, invItemId, quantity, packageSeqId)); 217 break; 218 } 219 220 if (packageSeqId > packageSeq) { 222 this.packageSeq = packageSeqId; 223 } 224 } 225 226 protected String findOrderItemSeqId(String productId, String orderId, String shipGroupSeqId, double quantity) throws GeneralException { 227 Map lookupMap = FastMap.newInstance(); 228 lookupMap.put("orderId", orderId); 229 lookupMap.put("productId", productId); 230 lookupMap.put("shipGroupSeqId", shipGroupSeqId); 231 232 List sort = UtilMisc.toList("-quantity"); 233 List orderItems = this.getDelegator().findByAnd("OrderItemAndShipGroupAssoc", lookupMap, sort); 234 235 String orderItemSeqId = null; 236 if (orderItems != null) { 237 Iterator i = orderItems.iterator(); 238 while (i.hasNext()) { 239 GenericValue item = (GenericValue) i.next(); 240 Double qty = item.getDouble("quantity"); 241 if (quantity <= qty.doubleValue()) { 242 orderItemSeqId = item.getString("orderItemSeqId"); 243 break; 244 } 245 } 246 } 247 248 if (orderItemSeqId != null) { 249 return orderItemSeqId; 250 } else { 251 throw new GeneralException("No valid order item found for product [" + productId + "] with quantity: " + quantity); 252 } 253 } 254 255 protected int checkLineForAdd(GenericValue res, String orderId, String orderItemSeqId, String shipGroupSeqId, double quantity, int packageSeqId) { 256 String invItemId = res.getString("inventoryItemId"); 258 double resQty = res.getDouble("quantity").doubleValue(); 259 260 PackingSessionLine line = this.findLine(orderId, orderItemSeqId, shipGroupSeqId, invItemId, packageSeqId); 261 if (line == null) { 262 Debug.log("No current line found testing [" + invItemId + "] R: " + resQty + " / Q: " + quantity, module); 263 if (resQty < quantity) { 264 return 0; 265 } else { 266 return 2; 267 } 268 } else { 269 double newQty = line.getQuantity() + quantity; 270 Debug.log("Existing line found testing [" + invItemId + "] R: " + resQty + " / Q: " + newQty, module); 271 if (resQty < newQty) { 272 return 0; 273 } else { 274 line.setQuantity(newQty); 275 return 1; 276 } 277 } 278 } 279 280 public String getShipmentId() { 281 return this.shipmentId; 282 } 283 284 public List getLines() { 285 return this.packLines; 286 } 287 288 public int nextPackageSeq() { 289 return ++packageSeq; 290 } 291 292 public int getCurrentPackageSeq() { 293 return packageSeq; 294 } 295 296 public double getPackedQuantity(String orderId, String orderItemSeqId, String shipGroupSeqId) { 297 double total = 0.0; 298 List lines = this.getLines(); 299 Iterator i = lines.iterator(); 300 while (i.hasNext()) { 301 PackingSessionLine line = (PackingSessionLine) i.next(); 302 if (orderId.equals(line.getOrderId()) && orderItemSeqId.equals(line.getOrderItemSeqId()) && 303 shipGroupSeqId.equals(line.getShipGroupSeqId())) { 304 total += line.getQuantity(); 305 } 306 } 307 return total; 308 } 309 310 public void registerEvent(PackingEvent event) { 311 this.packEvents.add(event); 312 this.runEvents(PackingEvent.EVENT_CODE_EREG); 313 } 314 315 public LocalDispatcher getDispatcher() { 316 if (_dispatcher == null) { 317 try { 318 _dispatcher = GenericDispatcher.getLocalDispatcher(dispatcherName, this.getDelegator()); 319 } catch (GenericServiceException e) { 320 throw new RuntimeException (e); 321 } 322 } 323 return _dispatcher; 324 } 325 326 public GenericDelegator getDelegator() { 327 if (_delegator == null) { 328 _delegator = GenericDelegator.getGenericDelegator(delegatorName); 329 } 330 return _delegator; 331 } 332 333 public GenericValue getUserLogin() { 334 return this.userLogin; 335 } 336 337 public int getStatus() { 338 return this.status; 339 } 340 341 public String getFacilityId() { 342 return this.facilityId; 343 } 344 345 public void setFacilityId(String facilityId) { 346 this.facilityId = facilityId; 347 } 348 349 public String getPrimaryOrderId() { 350 return this.primaryOrderId; 351 } 352 353 public void setPrimaryOrderId(String orderId) { 354 this.primaryOrderId = orderId; 355 } 356 357 public String getPrimaryShipGroupSeqId() { 358 return this.primaryShipGrp; 359 } 360 361 public void setPrimaryShipGroupSeqId(String shipGroupSeqId) { 362 this.primaryShipGrp = shipGroupSeqId; 363 } 364 365 public String getHandlingInstructions() { 366 return this.instructions; 367 } 368 369 public void setHandlingInstructions(String instructions) { 370 this.instructions = instructions; 371 } 372 373 public void clearLine(PackingSessionLine line) { 374 this.packLines.remove(line); 375 } 376 377 public void clear() { 378 this.packLines.clear(); 379 this.instructions = null; 380 this.primaryOrderId = null; 381 this.primaryShipGrp = null; 382 this.packageSeq = 1; 383 this.status = 1; 384 this.runEvents(PackingEvent.EVENT_CODE_CLEAR); 385 } 386 387 public String complete(boolean force) throws GeneralException { 388 if (this.getLines().size() == 0) { 389 return "EMPTY"; 390 } 391 392 this.checkReservations(force); 394 this.status = 0; 396 this.createShipment(); 398 this.createPackages(); 400 this.issueItemsToShipment(); 402 this.applyItemsToPackages(); 404 this.setShipmentToPacked(); 406 this.runEvents(PackingEvent.EVENT_CODE_COMPLETE); 408 409 return this.shipmentId; 410 } 411 412 protected void checkReservations(boolean ignore) throws GeneralException { 413 List errors = FastList.newInstance(); 414 Iterator i = this.getLines().iterator(); 415 while (i.hasNext()) { 416 PackingSessionLine line = (PackingSessionLine) i.next(); 417 Map invLookup = FastMap.newInstance(); 418 invLookup.put("orderId", line.getOrderId()); 419 invLookup.put("orderItemSeqId", line.getOrderItemSeqId()); 420 invLookup.put("shipGroupSeqId", line.getShipGroupSeqId()); 421 invLookup.put("inventoryItemId", line.getInventoryItemId()); 422 GenericValue res = this.getDelegator().findByPrimaryKey("OrderItemShipGrpInvRes", invLookup); 423 Double qty = res.getDouble("quantity"); 424 if (qty == null) qty = new Double (0); 425 426 double resQty = qty.doubleValue(); 427 double lineQty = line.getQuantity(); 428 429 if (lineQty != resQty) { 430 errors.add("Packed amount does not match reserved amount for item (" + line.getProductId() + ") [" + lineQty + " / " + resQty + "]"); 431 } 432 } 433 434 if (errors.size() > 0) { 435 if (!ignore) { 436 throw new GeneralException("Attempt to pack order failed. Click COMPLETE again to force.", errors); 437 } else { 438 Debug.logWarning("Packing warnings: " + errors, module); 439 } 440 } 441 } 442 443 protected void runEvents(int eventCode) { 444 if (this.packEvents.size() > 0) { 445 Iterator i = this.packEvents.iterator(); 446 while (i.hasNext()) { 447 PackingEvent event = (PackingEvent) i.next(); 448 event.runEvent(this, eventCode); 449 } 450 } 451 } 452 453 protected void createShipment() throws GeneralException { 454 Map newShipment = FastMap.newInstance(); 456 newShipment.put("originFacilityId", this.facilityId); 457 newShipment.put("primaryShipGroupSeqId", primaryShipGrp); 458 newShipment.put("primaryOrderId", primaryOrderId); 459 newShipment.put("shipmentTypeId", "OUTGOING_SHIPMENT"); 460 newShipment.put("statusId", "SHIPMENT_INPUT"); 461 newShipment.put("handlingInstructions", instructions); 462 newShipment.put("userLogin", userLogin); 463 Debug.log("Creating new shipment with context: " + newShipment, module); 464 Map newShipResp = this.getDispatcher().runSync("createShipment", newShipment); 465 466 if (ServiceUtil.isError(newShipResp)) { 467 throw new GeneralException(ServiceUtil.getErrorMessage(newShipResp)); 468 } 469 this.shipmentId = (String ) newShipResp.get("shipmentId"); 470 } 471 472 protected void issueItemsToShipment() throws GeneralException { 473 List lines = this.getLines(); 474 Iterator i = lines.iterator(); 475 while (i.hasNext()) { 476 PackingSessionLine line = (PackingSessionLine) i.next(); 477 line.issueItemToShipment(shipmentId, userLogin, getDispatcher()); 478 } 479 } 480 481 protected void createPackages() throws GeneralException { 482 for (int i = 0; i < packageSeq; i++) { 483 String shipmentPackageSeqId = UtilFormatOut.formatPaddedNumber(i+1, 5); 484 485 Map pkgCtx = FastMap.newInstance(); 486 pkgCtx.put("shipmentId", shipmentId); 487 pkgCtx.put("shipmentPackageSeqId", shipmentPackageSeqId); 488 pkgCtx.put("userLogin", userLogin); 490 Map newPkgResp = this.getDispatcher().runSync("createShipmentPackage", pkgCtx); 491 492 if (ServiceUtil.isError(newPkgResp)) { 493 throw new GeneralException(ServiceUtil.getErrorMessage(newPkgResp)); 494 } 495 } 496 } 497 498 protected void applyItemsToPackages() throws GeneralException { 499 List lines = this.getLines(); 500 Iterator i = lines.iterator(); 501 while (i.hasNext()) { 502 PackingSessionLine line = (PackingSessionLine) i.next(); 503 line.applyLineToPackage(shipmentId, userLogin, getDispatcher()); 504 } 505 } 506 507 protected void setShipmentToPacked() throws GeneralException { 508 Map packedCtx = UtilMisc.toMap("shipmentId", shipmentId, "statusId", "SHIPMENT_PACKED", "userLogin", userLogin); 509 Map packedResp = this.getDispatcher().runSync("updateShipment", packedCtx); 510 if (packedResp != null && ServiceUtil.isError(packedResp)) { 511 throw new GeneralException(ServiceUtil.getErrorMessage(packedResp)); 512 } 513 } 514 } 515 | Popular Tags |