@Test public void testHandleStandardPaymentOfflineAuthConfirmed() throws Exception { String label = assertPgFeatures("courierPaymentGateway", false, false, true, true); CustomerOrder customerOrder = createTestOrder(TestOrderType.STANDARD, label, false); assertTrue(pendingHandler.handle( new OrderEventImpl("", customerOrder, null, Collections.EMPTY_MAP))); orderService.update(customerOrder); assertInventory(WAREHOUSE_ID, "CC_TEST1", "9.00", "2.00"); assertInventory(WAREHOUSE_ID, "CC_TEST2", "1.00", "1.00"); assertTrue(confirmHandler.handle( new OrderEventImpl("", customerOrder, null, Collections.EMPTY_MAP))); orderService.update(customerOrder); assertInventory(WAREHOUSE_ID, "CC_TEST1", "9.00", "2.00"); assertInventory(WAREHOUSE_ID, "CC_TEST2", "1.00", "1.00"); assertDeliveryStates(customerOrder.getDelivery(), CustomerOrderDelivery.DELIVERY_STATUS_ALLOCATION_WAIT); assertSinglePaymentEntry(customerOrder.getOrdernum(), "689.74", PaymentGateway.AUTH, Payment.PAYMENT_STATUS_OK, false); assertEquals("689.74", customerOrder.getOrderTotal().toPlainString()); assertEquals("0.00", paymentService.getOrderAmount(customerOrder.getOrdernum()).toPlainString()); assertEquals(CustomerOrder.ORDER_STATUS_IN_PROGRESS, customerOrder.getOrderStatus()); final OrderDeliveryStatusUpdateImpl update1 = new OrderDeliveryStatusUpdateImpl( customerOrder.getOrdernum(), "WAREHOUSE_1", Collections.<OrderDeliveryLineStatusUpdate>singletonList( new OrderDeliveryLineStatusUpdateImpl( null, "CC_TEST1", "packing", date("2017-02-17"), date("2017-02-20"), null, null, null, null, false, null, null ) ) ); assertTrue(handler.handle( new OrderEventImpl("", customerOrder, null, Collections.singletonMap("update", update1)))); orderService.update(customerOrder); CustomerOrder updated = orderService.findByReference(customerOrder.getOrdernum()); assertNotNull(updated); assertEquals(CustomerOrder.ORDER_STATUS_IN_PROGRESS, updated.getOrderStatus()); assertDeliveryStates(updated.getDelivery(), CustomerOrderDelivery.DELIVERY_STATUS_PACKING); assertInventory(WAREHOUSE_ID, "CC_TEST1", "9.00", "0.00"); assertInventory(WAREHOUSE_ID, "CC_TEST2", "1.00", "0.00"); assertEquals(1, updated.getDelivery().size()); final CustomerOrderDelivery delivery1 = updated.getDelivery().iterator().next(); assertEquals(date("2017-02-17"), delivery1.getDeliveryEstimatedMin()); assertNull(delivery1.getDeliveryEstimatedMax()); assertNull(delivery1.getDeliveryGuaranteed()); final Collection<CustomerOrderDeliveryDet> details1 = delivery1.getDetail(); final Map<String, CustomerOrderDeliveryDet> detailsBySKU1 = new HashMap<>(); for (final CustomerOrderDeliveryDet detail : details1) { detailsBySKU1.put(detail.getProductSkuCode(), detail); } final CustomerOrderDeliveryDet test11 = detailsBySKU1.get("CC_TEST1"); assertNotNull(test11); assertEquals(date("2017-02-17"), test11.getDeliveryEstimatedMin()); assertEquals(date("2017-02-20"), test11.getDeliveryEstimatedMax()); assertNull(test11.getDeliveryGuaranteed()); assertEquals("packing", test11.getDeliveryRemarks()); assertNull(test11.getDeliveryConfirmed()); assertFalse(test11.isDeliveryRejected()); assertFalse(test11.isDeliveryDifferent()); final CustomerOrderDeliveryDet test12 = detailsBySKU1.get("CC_TEST2"); assertNotNull(test12); assertNull(test12.getDeliveryEstimatedMin()); assertNull(test12.getDeliveryEstimatedMax()); assertNull(test12.getDeliveryGuaranteed()); assertNull(test12.getDeliveryRemarks()); assertNull(test12.getDeliveryConfirmed()); assertFalse(test12.isDeliveryRejected()); assertFalse(test12.isDeliveryDifferent()); final OrderDeliveryStatusUpdateImpl update2 = new OrderDeliveryStatusUpdateImpl( customerOrder.getOrdernum(), "WAREHOUSE_1", Collections.<OrderDeliveryLineStatusUpdate>singletonList( new OrderDeliveryLineStatusUpdateImpl( null, "CC_TEST2", "packing 2", date("2017-02-17"), date("2017-02-21"), null, null, null, null, false, null, null ) ) ); assertTrue(handler.handle( new OrderEventImpl("", updated, null, Collections.singletonMap("update", update2)))); orderService.update(updated); updated = orderService.findByReference(updated.getOrdernum()); assertNotNull(updated); assertEquals(CustomerOrder.ORDER_STATUS_IN_PROGRESS, updated.getOrderStatus()); assertDeliveryStates(updated.getDelivery(), CustomerOrderDelivery.DELIVERY_STATUS_PACKING); assertInventory(WAREHOUSE_ID, "CC_TEST1", "9.00", "0.00"); assertInventory(WAREHOUSE_ID, "CC_TEST2", "1.00", "0.00"); assertEquals(1, updated.getDelivery().size()); final CustomerOrderDelivery delivery2 = updated.getDelivery().iterator().next(); assertEquals(date("2017-02-17"), delivery2.getDeliveryEstimatedMin()); assertEquals(date("2017-02-21"), delivery2.getDeliveryEstimatedMax()); assertNull(delivery2.getDeliveryGuaranteed()); final Collection<CustomerOrderDeliveryDet> details2 = delivery2.getDetail(); final Map<String, CustomerOrderDeliveryDet> detailsBySKU2 = new HashMap<>(); for (final CustomerOrderDeliveryDet detail : details2) { detailsBySKU2.put(detail.getProductSkuCode(), detail); } final CustomerOrderDeliveryDet test21 = detailsBySKU2.get("CC_TEST1"); assertNotNull(test21); assertEquals(date("2017-02-17"), test21.getDeliveryEstimatedMin()); assertEquals(date("2017-02-20"), test21.getDeliveryEstimatedMax()); assertNull(test21.getDeliveryGuaranteed()); assertEquals("packing", test21.getDeliveryRemarks()); assertNull(test21.getDeliveryConfirmed()); assertFalse(test21.isDeliveryRejected()); assertFalse(test21.isDeliveryDifferent()); final CustomerOrderDeliveryDet test22 = detailsBySKU2.get("CC_TEST2"); assertNotNull(test22); assertEquals(date("2017-02-17"), test22.getDeliveryEstimatedMin()); assertEquals(date("2017-02-21"), test22.getDeliveryEstimatedMax()); assertNull(test22.getDeliveryGuaranteed()); assertEquals("packing 2", test22.getDeliveryRemarks()); assertNull(test22.getDeliveryConfirmed()); assertFalse(test22.isDeliveryRejected()); assertFalse(test22.isDeliveryDifferent()); final OrderDeliveryStatusUpdateImpl update3 = new OrderDeliveryStatusUpdateImpl( customerOrder.getOrdernum(), "WAREHOUSE_1", Arrays.<OrderDeliveryLineStatusUpdate>asList( new OrderDeliveryLineStatusUpdateImpl( null, "CC_TEST1", "delivered 1", null, null, null, date("2017-02-21"), null, new BigDecimal(2), false, "INV-001", date("2017-02-22").toLocalDate() ), new OrderDeliveryLineStatusUpdateImpl( null, "CC_TEST2", "delivered 2", null, null, null, date("2017-02-21"), null, new BigDecimal(1), false, "INV-001", date("2017-02-22").toLocalDate() ) ) ); assertTrue(handler.handle( new OrderEventImpl("", updated, null, Collections.singletonMap("update", update3)))); orderService.update(updated); updated = orderService.findByReference(updated.getOrdernum()); assertNotNull(updated); assertEquals(CustomerOrder.ORDER_STATUS_IN_PROGRESS, updated.getOrderStatus()); assertDeliveryStates(updated.getDelivery(), CustomerOrderDelivery.DELIVERY_STATUS_SHIPMENT_IN_PROGRESS_WAITING_PAYMENT); assertInventory(WAREHOUSE_ID, "CC_TEST1", "9.00", "0.00"); assertInventory(WAREHOUSE_ID, "CC_TEST2", "1.00", "0.00"); assertEquals(1, updated.getDelivery().size()); final CustomerOrderDelivery delivery3 = updated.getDelivery().iterator().next(); assertEquals(date("2017-02-17"), delivery3.getDeliveryEstimatedMin()); assertEquals(date("2017-02-21"), delivery3.getDeliveryEstimatedMax()); assertNull(delivery3.getDeliveryGuaranteed()); assertEquals(date("2017-02-21"), delivery3.getDeliveryConfirmed()); final Collection<CustomerOrderDeliveryDet> details3 = delivery3.getDetail(); final Map<String, CustomerOrderDeliveryDet> detailsBySKU3 = new HashMap<>(); for (final CustomerOrderDeliveryDet detail : details3) { detailsBySKU3.put(detail.getProductSkuCode(), detail); } final CustomerOrderDeliveryDet test31 = detailsBySKU3.get("CC_TEST1"); assertNotNull(test31); assertEquals(date("2017-02-17"), test31.getDeliveryEstimatedMin()); assertEquals(date("2017-02-20"), test31.getDeliveryEstimatedMax()); assertNull(test31.getDeliveryGuaranteed()); assertEquals(date("2017-02-21"), test31.getDeliveryConfirmed()); assertEquals("delivered 1", test31.getDeliveryRemarks()); assertFalse(test31.isDeliveryRejected()); assertFalse(test31.isDeliveryDifferent()); assertEquals("INV-001", test31.getSupplierInvoiceNo()); assertEquals(date("2017-02-22").toLocalDate(), test31.getSupplierInvoiceDate()); final CustomerOrderDeliveryDet test32 = detailsBySKU3.get("CC_TEST2"); assertNotNull(test32); assertEquals(date("2017-02-17"), test32.getDeliveryEstimatedMin()); assertEquals(date("2017-02-21"), test32.getDeliveryEstimatedMax()); assertNull(test32.getDeliveryGuaranteed()); assertEquals(date("2017-02-21"), test32.getDeliveryConfirmed()); assertEquals("delivered 2", test32.getDeliveryRemarks()); assertFalse(test32.isDeliveryRejected()); assertFalse(test32.isDeliveryDifferent()); assertEquals("INV-001", test32.getSupplierInvoiceNo()); assertEquals(date("2017-02-22").toLocalDate(), test32.getSupplierInvoiceDate()); assertSinglePaymentEntry(customerOrder.getOrdernum(), "689.74", PaymentGateway.AUTH, Payment.PAYMENT_STATUS_OK, false); assertEquals("689.74", customerOrder.getOrderTotal().toPlainString()); assertEquals("0.00", paymentService.getOrderAmount(customerOrder.getOrdernum()).toPlainString()); }
@Override public boolean handle(final OrderEvent orderEvent) throws OrderException { synchronized (OrderEventHandler.syncMonitor) { final CustomerOrder customerOrder = orderEvent.getCustomerOrder(); final OrderDeliveryStatusUpdate update = (OrderDeliveryStatusUpdate) orderEvent.getParams().get("update"); LOG.info("Received delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); if (update != null) { final Map<Long, OrderDeliveryLineStatusUpdate> detailsByPk = new HashMap<>(); final Map<String, List<OrderDeliveryLineStatusUpdate>> detailsBySKU = new HashMap<>(); for (final OrderDeliveryLineStatusUpdate lineUpdate : update.getLineStatus()) { if (lineUpdate.getOrderLineRef() != null) { detailsByPk.put(lineUpdate.getOrderLineRef(), lineUpdate); } else if (lineUpdate.getSKU() != null) { final List<OrderDeliveryLineStatusUpdate> skuUpdates = detailsBySKU.computeIfAbsent(lineUpdate.getSKU(), k -> new ArrayList<>()); skuUpdates.add(lineUpdate); } } final boolean allowDeliveryTransitions = CustomerOrder.ORDER_STATUS_IN_PROGRESS.equals(customerOrder.getOrderStatus()) || CustomerOrder.ORDER_STATUS_PARTIALLY_SHIPPED.equals(customerOrder.getOrderStatus()); if (update.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : update.getAdditionalData().entrySet()) { if (data.getValue() != null) { customerOrder.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { customerOrder.putValue(data.getKey(), null, null); } } } for (final CustomerOrderDelivery delivery : customerOrder.getDelivery()) { LocalDateTime estimatedMin = null; LocalDateTime estimatedMax = null; LocalDateTime guaranteed = null; LocalDateTime confirmed = null; boolean notGuaranteed = false; boolean atLeastOneItemIsNotUpdated = false; boolean allItemsDeliveredOrRejected = true; final String deliveryNumber = update.getDeliveryNumber(); if (deliveryNumber == null || deliveryNumber.equals(delivery.getDeliveryNum())) { for (final CustomerOrderDeliveryDet detail : delivery.getDetail()) { OrderDeliveryLineStatusUpdate lineUpdate = detailsByPk.get(detail.getCustomerOrderDeliveryDetId()); if (lineUpdate == null) { if (detail.getSupplierCode().equals(update.getSupplierCode())) { final List<OrderDeliveryLineStatusUpdate> candidates = detailsBySKU.get(detail.getProductSkuCode()); if (CollectionUtils.isNotEmpty(candidates)) { for (final OrderDeliveryLineStatusUpdate candidate : candidates) { if (candidate.getOrderedQty() == null && lineUpdate == null) { lineUpdate = candidate; } else if (MoneyUtils.isFirstEqualToSecond(candidate.getOrderedQty(), detail.getQty())) { lineUpdate = candidate; break; } } if (lineUpdate != null) { candidates.remove(lineUpdate); if (candidates.isEmpty()) { detailsBySKU.remove(detail.getProductSkuCode()); } } } } } else { detailsByPk.remove(detail.getCustomerOrderDeliveryDetId()); } if (lineUpdate != null) { if (lineUpdate.getDeliveryConfirmed() != null) { detail.setDeliveryConfirmed(lineUpdate.getDeliveryConfirmed()); } else { if (lineUpdate.getDeliveryEstimatedMin() != null) { detail.setDeliveryEstimatedMin(lineUpdate.getDeliveryEstimatedMin()); } if (lineUpdate.getDeliveryEstimatedMax() != null) { detail.setDeliveryEstimatedMax(lineUpdate.getDeliveryEstimatedMax()); } if (lineUpdate.getDeliveryGuaranteed() != null) { detail.setDeliveryGuaranteed(lineUpdate.getDeliveryGuaranteed()); } } if (StringUtils.isNotBlank(lineUpdate.getOrderDeliveryStatus())) { detail.setDeliveryRemarks(lineUpdate.getOrderDeliveryStatus()); } if (lineUpdate.isRejected()) { detail.setDeliveredQuantity(BigDecimal.ZERO); } else if (lineUpdate.getDeliveredQty() != null) { detail.setDeliveredQuantity(lineUpdate.getDeliveredQty()); } if (StringUtils.isNotBlank(lineUpdate.getSupplierInvoiceNo())) { detail.setSupplierInvoiceNo(lineUpdate.getSupplierInvoiceNo()); } if (lineUpdate.getSupplierInvoiceDate() != null) { detail.setSupplierInvoiceDate(lineUpdate.getSupplierInvoiceDate()); } if (lineUpdate.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : lineUpdate.getAdditionalData().entrySet()) { if (data.getValue() != null) { detail.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { detail.putValue(data.getKey(), null, null); } } } } else { if (detail.getDeliveryEstimatedMin() == null && detail.getDeliveryEstimatedMax() == null && detail.getDeliveryGuaranteed() == null && detail.getDeliveryConfirmed() == null && detail.getDeliveredQuantity() == null) { atLeastOneItemIsNotUpdated = true; } } estimatedMin = chooseLatestDate(estimatedMin, detail.getDeliveryEstimatedMin()); estimatedMax = chooseLatestDate(estimatedMax, detail.getDeliveryEstimatedMax()); if (guaranteed != null) { notGuaranteed = !guaranteed.equals(detail.getDeliveryGuaranteed()); } if (notGuaranteed) { estimatedMin = chooseLatestDate(estimatedMin, guaranteed); estimatedMax = chooseLatestDate(estimatedMax, guaranteed); } else { guaranteed = chooseLatestDate(guaranteed, detail.getDeliveryGuaranteed()); } confirmed = chooseLatestDate(confirmed, detail.getDeliveryConfirmed()); if (detail.getDeliveredQuantity() == null) { allItemsDeliveredOrRejected = false; } } } if (estimatedMin != null || estimatedMax != null) { notGuaranteed = true; } if (notGuaranteed) { if (atLeastOneItemIsNotUpdated) { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(null); } else { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(estimatedMax); delivery.setDeliveryGuaranteed(null); } } else { delivery.setDeliveryEstimatedMin(null); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(guaranteed); } if (allItemsDeliveredOrRejected) { delivery.setDeliveryConfirmed(confirmed); } LOG.info("Attempting to auto-progress delivery {}. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (allowDeliveryTransitions) { if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_RESERVED.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_ALLOCATION_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_DATE_WAIT.equals(delivery.getDeliveryStatus())) { voidReservation(orderEvent, delivery); getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was pending allocation, reservation was voided and delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_ALLOCATED.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was allocated, delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_PACKING.equals(delivery.getDeliveryStatus()) && allItemsDeliveredOrRejected) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_SHIPMENT, customerOrder, delivery)); LOG.info("Delivery {} was in packing, all lines updated, releasing to shipment to take payment. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (CustomerOrderDelivery.DELIVERY_STATUS_SHIPMENT_IN_PROGRESS.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_SHIPMENT_COMPLETE, customerOrder, delivery)); LOG.info("Delivery {} was in shipping (payment successful), marking as complete. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } } } } if (!detailsByPk.isEmpty()) { LOG.error(Markers.alert(), "Not all line specific updates could be processed: {}", detailsByPk); } if (!detailsBySKU.isEmpty()) { LOG.error(Markers.alert(), "Not all SKU updates could be processed: {}", detailsBySKU); } LOG.info("Finished delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); return true; } return false; } }
DeliveryUpdateOrderEventHandlerImpl extends AbstractEventHandlerImpl implements OrderEventHandler, ApplicationContextAware { @Override public boolean handle(final OrderEvent orderEvent) throws OrderException { synchronized (OrderEventHandler.syncMonitor) { final CustomerOrder customerOrder = orderEvent.getCustomerOrder(); final OrderDeliveryStatusUpdate update = (OrderDeliveryStatusUpdate) orderEvent.getParams().get("update"); LOG.info("Received delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); if (update != null) { final Map<Long, OrderDeliveryLineStatusUpdate> detailsByPk = new HashMap<>(); final Map<String, List<OrderDeliveryLineStatusUpdate>> detailsBySKU = new HashMap<>(); for (final OrderDeliveryLineStatusUpdate lineUpdate : update.getLineStatus()) { if (lineUpdate.getOrderLineRef() != null) { detailsByPk.put(lineUpdate.getOrderLineRef(), lineUpdate); } else if (lineUpdate.getSKU() != null) { final List<OrderDeliveryLineStatusUpdate> skuUpdates = detailsBySKU.computeIfAbsent(lineUpdate.getSKU(), k -> new ArrayList<>()); skuUpdates.add(lineUpdate); } } final boolean allowDeliveryTransitions = CustomerOrder.ORDER_STATUS_IN_PROGRESS.equals(customerOrder.getOrderStatus()) || CustomerOrder.ORDER_STATUS_PARTIALLY_SHIPPED.equals(customerOrder.getOrderStatus()); if (update.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : update.getAdditionalData().entrySet()) { if (data.getValue() != null) { customerOrder.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { customerOrder.putValue(data.getKey(), null, null); } } } for (final CustomerOrderDelivery delivery : customerOrder.getDelivery()) { LocalDateTime estimatedMin = null; LocalDateTime estimatedMax = null; LocalDateTime guaranteed = null; LocalDateTime confirmed = null; boolean notGuaranteed = false; boolean atLeastOneItemIsNotUpdated = false; boolean allItemsDeliveredOrRejected = true; final String deliveryNumber = update.getDeliveryNumber(); if (deliveryNumber == null || deliveryNumber.equals(delivery.getDeliveryNum())) { for (final CustomerOrderDeliveryDet detail : delivery.getDetail()) { OrderDeliveryLineStatusUpdate lineUpdate = detailsByPk.get(detail.getCustomerOrderDeliveryDetId()); if (lineUpdate == null) { if (detail.getSupplierCode().equals(update.getSupplierCode())) { final List<OrderDeliveryLineStatusUpdate> candidates = detailsBySKU.get(detail.getProductSkuCode()); if (CollectionUtils.isNotEmpty(candidates)) { for (final OrderDeliveryLineStatusUpdate candidate : candidates) { if (candidate.getOrderedQty() == null && lineUpdate == null) { lineUpdate = candidate; } else if (MoneyUtils.isFirstEqualToSecond(candidate.getOrderedQty(), detail.getQty())) { lineUpdate = candidate; break; } } if (lineUpdate != null) { candidates.remove(lineUpdate); if (candidates.isEmpty()) { detailsBySKU.remove(detail.getProductSkuCode()); } } } } } else { detailsByPk.remove(detail.getCustomerOrderDeliveryDetId()); } if (lineUpdate != null) { if (lineUpdate.getDeliveryConfirmed() != null) { detail.setDeliveryConfirmed(lineUpdate.getDeliveryConfirmed()); } else { if (lineUpdate.getDeliveryEstimatedMin() != null) { detail.setDeliveryEstimatedMin(lineUpdate.getDeliveryEstimatedMin()); } if (lineUpdate.getDeliveryEstimatedMax() != null) { detail.setDeliveryEstimatedMax(lineUpdate.getDeliveryEstimatedMax()); } if (lineUpdate.getDeliveryGuaranteed() != null) { detail.setDeliveryGuaranteed(lineUpdate.getDeliveryGuaranteed()); } } if (StringUtils.isNotBlank(lineUpdate.getOrderDeliveryStatus())) { detail.setDeliveryRemarks(lineUpdate.getOrderDeliveryStatus()); } if (lineUpdate.isRejected()) { detail.setDeliveredQuantity(BigDecimal.ZERO); } else if (lineUpdate.getDeliveredQty() != null) { detail.setDeliveredQuantity(lineUpdate.getDeliveredQty()); } if (StringUtils.isNotBlank(lineUpdate.getSupplierInvoiceNo())) { detail.setSupplierInvoiceNo(lineUpdate.getSupplierInvoiceNo()); } if (lineUpdate.getSupplierInvoiceDate() != null) { detail.setSupplierInvoiceDate(lineUpdate.getSupplierInvoiceDate()); } if (lineUpdate.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : lineUpdate.getAdditionalData().entrySet()) { if (data.getValue() != null) { detail.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { detail.putValue(data.getKey(), null, null); } } } } else { if (detail.getDeliveryEstimatedMin() == null && detail.getDeliveryEstimatedMax() == null && detail.getDeliveryGuaranteed() == null && detail.getDeliveryConfirmed() == null && detail.getDeliveredQuantity() == null) { atLeastOneItemIsNotUpdated = true; } } estimatedMin = chooseLatestDate(estimatedMin, detail.getDeliveryEstimatedMin()); estimatedMax = chooseLatestDate(estimatedMax, detail.getDeliveryEstimatedMax()); if (guaranteed != null) { notGuaranteed = !guaranteed.equals(detail.getDeliveryGuaranteed()); } if (notGuaranteed) { estimatedMin = chooseLatestDate(estimatedMin, guaranteed); estimatedMax = chooseLatestDate(estimatedMax, guaranteed); } else { guaranteed = chooseLatestDate(guaranteed, detail.getDeliveryGuaranteed()); } confirmed = chooseLatestDate(confirmed, detail.getDeliveryConfirmed()); if (detail.getDeliveredQuantity() == null) { allItemsDeliveredOrRejected = false; } } } if (estimatedMin != null || estimatedMax != null) { notGuaranteed = true; } if (notGuaranteed) { if (atLeastOneItemIsNotUpdated) { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(null); } else { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(estimatedMax); delivery.setDeliveryGuaranteed(null); } } else { delivery.setDeliveryEstimatedMin(null); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(guaranteed); } if (allItemsDeliveredOrRejected) { delivery.setDeliveryConfirmed(confirmed); } LOG.info("Attempting to auto-progress delivery {}. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (allowDeliveryTransitions) { if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_RESERVED.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_ALLOCATION_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_DATE_WAIT.equals(delivery.getDeliveryStatus())) { voidReservation(orderEvent, delivery); getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was pending allocation, reservation was voided and delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_ALLOCATED.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was allocated, delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_PACKING.equals(delivery.getDeliveryStatus()) && allItemsDeliveredOrRejected) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_SHIPMENT, customerOrder, delivery)); LOG.info("Delivery {} was in packing, all lines updated, releasing to shipment to take payment. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (CustomerOrderDelivery.DELIVERY_STATUS_SHIPMENT_IN_PROGRESS.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_SHIPMENT_COMPLETE, customerOrder, delivery)); LOG.info("Delivery {} was in shipping (payment successful), marking as complete. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } } } } if (!detailsByPk.isEmpty()) { LOG.error(Markers.alert(), "Not all line specific updates could be processed: {}", detailsByPk); } if (!detailsBySKU.isEmpty()) { LOG.error(Markers.alert(), "Not all SKU updates could be processed: {}", detailsBySKU); } LOG.info("Finished delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); return true; } return false; } } }
DeliveryUpdateOrderEventHandlerImpl extends AbstractEventHandlerImpl implements OrderEventHandler, ApplicationContextAware { @Override public boolean handle(final OrderEvent orderEvent) throws OrderException { synchronized (OrderEventHandler.syncMonitor) { final CustomerOrder customerOrder = orderEvent.getCustomerOrder(); final OrderDeliveryStatusUpdate update = (OrderDeliveryStatusUpdate) orderEvent.getParams().get("update"); LOG.info("Received delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); if (update != null) { final Map<Long, OrderDeliveryLineStatusUpdate> detailsByPk = new HashMap<>(); final Map<String, List<OrderDeliveryLineStatusUpdate>> detailsBySKU = new HashMap<>(); for (final OrderDeliveryLineStatusUpdate lineUpdate : update.getLineStatus()) { if (lineUpdate.getOrderLineRef() != null) { detailsByPk.put(lineUpdate.getOrderLineRef(), lineUpdate); } else if (lineUpdate.getSKU() != null) { final List<OrderDeliveryLineStatusUpdate> skuUpdates = detailsBySKU.computeIfAbsent(lineUpdate.getSKU(), k -> new ArrayList<>()); skuUpdates.add(lineUpdate); } } final boolean allowDeliveryTransitions = CustomerOrder.ORDER_STATUS_IN_PROGRESS.equals(customerOrder.getOrderStatus()) || CustomerOrder.ORDER_STATUS_PARTIALLY_SHIPPED.equals(customerOrder.getOrderStatus()); if (update.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : update.getAdditionalData().entrySet()) { if (data.getValue() != null) { customerOrder.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { customerOrder.putValue(data.getKey(), null, null); } } } for (final CustomerOrderDelivery delivery : customerOrder.getDelivery()) { LocalDateTime estimatedMin = null; LocalDateTime estimatedMax = null; LocalDateTime guaranteed = null; LocalDateTime confirmed = null; boolean notGuaranteed = false; boolean atLeastOneItemIsNotUpdated = false; boolean allItemsDeliveredOrRejected = true; final String deliveryNumber = update.getDeliveryNumber(); if (deliveryNumber == null || deliveryNumber.equals(delivery.getDeliveryNum())) { for (final CustomerOrderDeliveryDet detail : delivery.getDetail()) { OrderDeliveryLineStatusUpdate lineUpdate = detailsByPk.get(detail.getCustomerOrderDeliveryDetId()); if (lineUpdate == null) { if (detail.getSupplierCode().equals(update.getSupplierCode())) { final List<OrderDeliveryLineStatusUpdate> candidates = detailsBySKU.get(detail.getProductSkuCode()); if (CollectionUtils.isNotEmpty(candidates)) { for (final OrderDeliveryLineStatusUpdate candidate : candidates) { if (candidate.getOrderedQty() == null && lineUpdate == null) { lineUpdate = candidate; } else if (MoneyUtils.isFirstEqualToSecond(candidate.getOrderedQty(), detail.getQty())) { lineUpdate = candidate; break; } } if (lineUpdate != null) { candidates.remove(lineUpdate); if (candidates.isEmpty()) { detailsBySKU.remove(detail.getProductSkuCode()); } } } } } else { detailsByPk.remove(detail.getCustomerOrderDeliveryDetId()); } if (lineUpdate != null) { if (lineUpdate.getDeliveryConfirmed() != null) { detail.setDeliveryConfirmed(lineUpdate.getDeliveryConfirmed()); } else { if (lineUpdate.getDeliveryEstimatedMin() != null) { detail.setDeliveryEstimatedMin(lineUpdate.getDeliveryEstimatedMin()); } if (lineUpdate.getDeliveryEstimatedMax() != null) { detail.setDeliveryEstimatedMax(lineUpdate.getDeliveryEstimatedMax()); } if (lineUpdate.getDeliveryGuaranteed() != null) { detail.setDeliveryGuaranteed(lineUpdate.getDeliveryGuaranteed()); } } if (StringUtils.isNotBlank(lineUpdate.getOrderDeliveryStatus())) { detail.setDeliveryRemarks(lineUpdate.getOrderDeliveryStatus()); } if (lineUpdate.isRejected()) { detail.setDeliveredQuantity(BigDecimal.ZERO); } else if (lineUpdate.getDeliveredQty() != null) { detail.setDeliveredQuantity(lineUpdate.getDeliveredQty()); } if (StringUtils.isNotBlank(lineUpdate.getSupplierInvoiceNo())) { detail.setSupplierInvoiceNo(lineUpdate.getSupplierInvoiceNo()); } if (lineUpdate.getSupplierInvoiceDate() != null) { detail.setSupplierInvoiceDate(lineUpdate.getSupplierInvoiceDate()); } if (lineUpdate.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : lineUpdate.getAdditionalData().entrySet()) { if (data.getValue() != null) { detail.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { detail.putValue(data.getKey(), null, null); } } } } else { if (detail.getDeliveryEstimatedMin() == null && detail.getDeliveryEstimatedMax() == null && detail.getDeliveryGuaranteed() == null && detail.getDeliveryConfirmed() == null && detail.getDeliveredQuantity() == null) { atLeastOneItemIsNotUpdated = true; } } estimatedMin = chooseLatestDate(estimatedMin, detail.getDeliveryEstimatedMin()); estimatedMax = chooseLatestDate(estimatedMax, detail.getDeliveryEstimatedMax()); if (guaranteed != null) { notGuaranteed = !guaranteed.equals(detail.getDeliveryGuaranteed()); } if (notGuaranteed) { estimatedMin = chooseLatestDate(estimatedMin, guaranteed); estimatedMax = chooseLatestDate(estimatedMax, guaranteed); } else { guaranteed = chooseLatestDate(guaranteed, detail.getDeliveryGuaranteed()); } confirmed = chooseLatestDate(confirmed, detail.getDeliveryConfirmed()); if (detail.getDeliveredQuantity() == null) { allItemsDeliveredOrRejected = false; } } } if (estimatedMin != null || estimatedMax != null) { notGuaranteed = true; } if (notGuaranteed) { if (atLeastOneItemIsNotUpdated) { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(null); } else { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(estimatedMax); delivery.setDeliveryGuaranteed(null); } } else { delivery.setDeliveryEstimatedMin(null); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(guaranteed); } if (allItemsDeliveredOrRejected) { delivery.setDeliveryConfirmed(confirmed); } LOG.info("Attempting to auto-progress delivery {}. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (allowDeliveryTransitions) { if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_RESERVED.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_ALLOCATION_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_DATE_WAIT.equals(delivery.getDeliveryStatus())) { voidReservation(orderEvent, delivery); getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was pending allocation, reservation was voided and delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_ALLOCATED.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was allocated, delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_PACKING.equals(delivery.getDeliveryStatus()) && allItemsDeliveredOrRejected) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_SHIPMENT, customerOrder, delivery)); LOG.info("Delivery {} was in packing, all lines updated, releasing to shipment to take payment. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (CustomerOrderDelivery.DELIVERY_STATUS_SHIPMENT_IN_PROGRESS.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_SHIPMENT_COMPLETE, customerOrder, delivery)); LOG.info("Delivery {} was in shipping (payment successful), marking as complete. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } } } } if (!detailsByPk.isEmpty()) { LOG.error(Markers.alert(), "Not all line specific updates could be processed: {}", detailsByPk); } if (!detailsBySKU.isEmpty()) { LOG.error(Markers.alert(), "Not all SKU updates could be processed: {}", detailsBySKU); } LOG.info("Finished delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); return true; } return false; } } DeliveryUpdateOrderEventHandlerImpl(final WarehouseService warehouseService,
                                               final InventoryResolver inventoryResolver,
                                               final ProductService productService); }
DeliveryUpdateOrderEventHandlerImpl extends AbstractEventHandlerImpl implements OrderEventHandler, ApplicationContextAware { @Override public boolean handle(final OrderEvent orderEvent) throws OrderException { synchronized (OrderEventHandler.syncMonitor) { final CustomerOrder customerOrder = orderEvent.getCustomerOrder(); final OrderDeliveryStatusUpdate update = (OrderDeliveryStatusUpdate) orderEvent.getParams().get("update"); LOG.info("Received delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); if (update != null) { final Map<Long, OrderDeliveryLineStatusUpdate> detailsByPk = new HashMap<>(); final Map<String, List<OrderDeliveryLineStatusUpdate>> detailsBySKU = new HashMap<>(); for (final OrderDeliveryLineStatusUpdate lineUpdate : update.getLineStatus()) { if (lineUpdate.getOrderLineRef() != null) { detailsByPk.put(lineUpdate.getOrderLineRef(), lineUpdate); } else if (lineUpdate.getSKU() != null) { final List<OrderDeliveryLineStatusUpdate> skuUpdates = detailsBySKU.computeIfAbsent(lineUpdate.getSKU(), k -> new ArrayList<>()); skuUpdates.add(lineUpdate); } } final boolean allowDeliveryTransitions = CustomerOrder.ORDER_STATUS_IN_PROGRESS.equals(customerOrder.getOrderStatus()) || CustomerOrder.ORDER_STATUS_PARTIALLY_SHIPPED.equals(customerOrder.getOrderStatus()); if (update.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : update.getAdditionalData().entrySet()) { if (data.getValue() != null) { customerOrder.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { customerOrder.putValue(data.getKey(), null, null); } } } for (final CustomerOrderDelivery delivery : customerOrder.getDelivery()) { LocalDateTime estimatedMin = null; LocalDateTime estimatedMax = null; LocalDateTime guaranteed = null; LocalDateTime confirmed = null; boolean notGuaranteed = false; boolean atLeastOneItemIsNotUpdated = false; boolean allItemsDeliveredOrRejected = true; final String deliveryNumber = update.getDeliveryNumber(); if (deliveryNumber == null || deliveryNumber.equals(delivery.getDeliveryNum())) { for (final CustomerOrderDeliveryDet detail : delivery.getDetail()) { OrderDeliveryLineStatusUpdate lineUpdate = detailsByPk.get(detail.getCustomerOrderDeliveryDetId()); if (lineUpdate == null) { if (detail.getSupplierCode().equals(update.getSupplierCode())) { final List<OrderDeliveryLineStatusUpdate> candidates = detailsBySKU.get(detail.getProductSkuCode()); if (CollectionUtils.isNotEmpty(candidates)) { for (final OrderDeliveryLineStatusUpdate candidate : candidates) { if (candidate.getOrderedQty() == null && lineUpdate == null) { lineUpdate = candidate; } else if (MoneyUtils.isFirstEqualToSecond(candidate.getOrderedQty(), detail.getQty())) { lineUpdate = candidate; break; } } if (lineUpdate != null) { candidates.remove(lineUpdate); if (candidates.isEmpty()) { detailsBySKU.remove(detail.getProductSkuCode()); } } } } } else { detailsByPk.remove(detail.getCustomerOrderDeliveryDetId()); } if (lineUpdate != null) { if (lineUpdate.getDeliveryConfirmed() != null) { detail.setDeliveryConfirmed(lineUpdate.getDeliveryConfirmed()); } else { if (lineUpdate.getDeliveryEstimatedMin() != null) { detail.setDeliveryEstimatedMin(lineUpdate.getDeliveryEstimatedMin()); } if (lineUpdate.getDeliveryEstimatedMax() != null) { detail.setDeliveryEstimatedMax(lineUpdate.getDeliveryEstimatedMax()); } if (lineUpdate.getDeliveryGuaranteed() != null) { detail.setDeliveryGuaranteed(lineUpdate.getDeliveryGuaranteed()); } } if (StringUtils.isNotBlank(lineUpdate.getOrderDeliveryStatus())) { detail.setDeliveryRemarks(lineUpdate.getOrderDeliveryStatus()); } if (lineUpdate.isRejected()) { detail.setDeliveredQuantity(BigDecimal.ZERO); } else if (lineUpdate.getDeliveredQty() != null) { detail.setDeliveredQuantity(lineUpdate.getDeliveredQty()); } if (StringUtils.isNotBlank(lineUpdate.getSupplierInvoiceNo())) { detail.setSupplierInvoiceNo(lineUpdate.getSupplierInvoiceNo()); } if (lineUpdate.getSupplierInvoiceDate() != null) { detail.setSupplierInvoiceDate(lineUpdate.getSupplierInvoiceDate()); } if (lineUpdate.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : lineUpdate.getAdditionalData().entrySet()) { if (data.getValue() != null) { detail.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { detail.putValue(data.getKey(), null, null); } } } } else { if (detail.getDeliveryEstimatedMin() == null && detail.getDeliveryEstimatedMax() == null && detail.getDeliveryGuaranteed() == null && detail.getDeliveryConfirmed() == null && detail.getDeliveredQuantity() == null) { atLeastOneItemIsNotUpdated = true; } } estimatedMin = chooseLatestDate(estimatedMin, detail.getDeliveryEstimatedMin()); estimatedMax = chooseLatestDate(estimatedMax, detail.getDeliveryEstimatedMax()); if (guaranteed != null) { notGuaranteed = !guaranteed.equals(detail.getDeliveryGuaranteed()); } if (notGuaranteed) { estimatedMin = chooseLatestDate(estimatedMin, guaranteed); estimatedMax = chooseLatestDate(estimatedMax, guaranteed); } else { guaranteed = chooseLatestDate(guaranteed, detail.getDeliveryGuaranteed()); } confirmed = chooseLatestDate(confirmed, detail.getDeliveryConfirmed()); if (detail.getDeliveredQuantity() == null) { allItemsDeliveredOrRejected = false; } } } if (estimatedMin != null || estimatedMax != null) { notGuaranteed = true; } if (notGuaranteed) { if (atLeastOneItemIsNotUpdated) { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(null); } else { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(estimatedMax); delivery.setDeliveryGuaranteed(null); } } else { delivery.setDeliveryEstimatedMin(null); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(guaranteed); } if (allItemsDeliveredOrRejected) { delivery.setDeliveryConfirmed(confirmed); } LOG.info("Attempting to auto-progress delivery {}. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (allowDeliveryTransitions) { if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_RESERVED.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_ALLOCATION_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_DATE_WAIT.equals(delivery.getDeliveryStatus())) { voidReservation(orderEvent, delivery); getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was pending allocation, reservation was voided and delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_ALLOCATED.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was allocated, delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_PACKING.equals(delivery.getDeliveryStatus()) && allItemsDeliveredOrRejected) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_SHIPMENT, customerOrder, delivery)); LOG.info("Delivery {} was in packing, all lines updated, releasing to shipment to take payment. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (CustomerOrderDelivery.DELIVERY_STATUS_SHIPMENT_IN_PROGRESS.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_SHIPMENT_COMPLETE, customerOrder, delivery)); LOG.info("Delivery {} was in shipping (payment successful), marking as complete. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } } } } if (!detailsByPk.isEmpty()) { LOG.error(Markers.alert(), "Not all line specific updates could be processed: {}", detailsByPk); } if (!detailsBySKU.isEmpty()) { LOG.error(Markers.alert(), "Not all SKU updates could be processed: {}", detailsBySKU); } LOG.info("Finished delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); return true; } return false; } } DeliveryUpdateOrderEventHandlerImpl(final WarehouseService warehouseService,
                                               final InventoryResolver inventoryResolver,
                                               final ProductService productService); @Override void setApplicationContext(final ApplicationContext applicationContext); @Override boolean handle(final OrderEvent orderEvent); }
DeliveryUpdateOrderEventHandlerImpl extends AbstractEventHandlerImpl implements OrderEventHandler, ApplicationContextAware { @Override public boolean handle(final OrderEvent orderEvent) throws OrderException { synchronized (OrderEventHandler.syncMonitor) { final CustomerOrder customerOrder = orderEvent.getCustomerOrder(); final OrderDeliveryStatusUpdate update = (OrderDeliveryStatusUpdate) orderEvent.getParams().get("update"); LOG.info("Received delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); if (update != null) { final Map<Long, OrderDeliveryLineStatusUpdate> detailsByPk = new HashMap<>(); final Map<String, List<OrderDeliveryLineStatusUpdate>> detailsBySKU = new HashMap<>(); for (final OrderDeliveryLineStatusUpdate lineUpdate : update.getLineStatus()) { if (lineUpdate.getOrderLineRef() != null) { detailsByPk.put(lineUpdate.getOrderLineRef(), lineUpdate); } else if (lineUpdate.getSKU() != null) { final List<OrderDeliveryLineStatusUpdate> skuUpdates = detailsBySKU.computeIfAbsent(lineUpdate.getSKU(), k -> new ArrayList<>()); skuUpdates.add(lineUpdate); } } final boolean allowDeliveryTransitions = CustomerOrder.ORDER_STATUS_IN_PROGRESS.equals(customerOrder.getOrderStatus()) || CustomerOrder.ORDER_STATUS_PARTIALLY_SHIPPED.equals(customerOrder.getOrderStatus()); if (update.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : update.getAdditionalData().entrySet()) { if (data.getValue() != null) { customerOrder.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { customerOrder.putValue(data.getKey(), null, null); } } } for (final CustomerOrderDelivery delivery : customerOrder.getDelivery()) { LocalDateTime estimatedMin = null; LocalDateTime estimatedMax = null; LocalDateTime guaranteed = null; LocalDateTime confirmed = null; boolean notGuaranteed = false; boolean atLeastOneItemIsNotUpdated = false; boolean allItemsDeliveredOrRejected = true; final String deliveryNumber = update.getDeliveryNumber(); if (deliveryNumber == null || deliveryNumber.equals(delivery.getDeliveryNum())) { for (final CustomerOrderDeliveryDet detail : delivery.getDetail()) { OrderDeliveryLineStatusUpdate lineUpdate = detailsByPk.get(detail.getCustomerOrderDeliveryDetId()); if (lineUpdate == null) { if (detail.getSupplierCode().equals(update.getSupplierCode())) { final List<OrderDeliveryLineStatusUpdate> candidates = detailsBySKU.get(detail.getProductSkuCode()); if (CollectionUtils.isNotEmpty(candidates)) { for (final OrderDeliveryLineStatusUpdate candidate : candidates) { if (candidate.getOrderedQty() == null && lineUpdate == null) { lineUpdate = candidate; } else if (MoneyUtils.isFirstEqualToSecond(candidate.getOrderedQty(), detail.getQty())) { lineUpdate = candidate; break; } } if (lineUpdate != null) { candidates.remove(lineUpdate); if (candidates.isEmpty()) { detailsBySKU.remove(detail.getProductSkuCode()); } } } } } else { detailsByPk.remove(detail.getCustomerOrderDeliveryDetId()); } if (lineUpdate != null) { if (lineUpdate.getDeliveryConfirmed() != null) { detail.setDeliveryConfirmed(lineUpdate.getDeliveryConfirmed()); } else { if (lineUpdate.getDeliveryEstimatedMin() != null) { detail.setDeliveryEstimatedMin(lineUpdate.getDeliveryEstimatedMin()); } if (lineUpdate.getDeliveryEstimatedMax() != null) { detail.setDeliveryEstimatedMax(lineUpdate.getDeliveryEstimatedMax()); } if (lineUpdate.getDeliveryGuaranteed() != null) { detail.setDeliveryGuaranteed(lineUpdate.getDeliveryGuaranteed()); } } if (StringUtils.isNotBlank(lineUpdate.getOrderDeliveryStatus())) { detail.setDeliveryRemarks(lineUpdate.getOrderDeliveryStatus()); } if (lineUpdate.isRejected()) { detail.setDeliveredQuantity(BigDecimal.ZERO); } else if (lineUpdate.getDeliveredQty() != null) { detail.setDeliveredQuantity(lineUpdate.getDeliveredQty()); } if (StringUtils.isNotBlank(lineUpdate.getSupplierInvoiceNo())) { detail.setSupplierInvoiceNo(lineUpdate.getSupplierInvoiceNo()); } if (lineUpdate.getSupplierInvoiceDate() != null) { detail.setSupplierInvoiceDate(lineUpdate.getSupplierInvoiceDate()); } if (lineUpdate.getAdditionalData() != null) { for (final Map.Entry<String, Pair<String, I18NModel>> data : lineUpdate.getAdditionalData().entrySet()) { if (data.getValue() != null) { detail.putValue(data.getKey(), data.getValue().getFirst(), data.getValue().getSecond()); } else { detail.putValue(data.getKey(), null, null); } } } } else { if (detail.getDeliveryEstimatedMin() == null && detail.getDeliveryEstimatedMax() == null && detail.getDeliveryGuaranteed() == null && detail.getDeliveryConfirmed() == null && detail.getDeliveredQuantity() == null) { atLeastOneItemIsNotUpdated = true; } } estimatedMin = chooseLatestDate(estimatedMin, detail.getDeliveryEstimatedMin()); estimatedMax = chooseLatestDate(estimatedMax, detail.getDeliveryEstimatedMax()); if (guaranteed != null) { notGuaranteed = !guaranteed.equals(detail.getDeliveryGuaranteed()); } if (notGuaranteed) { estimatedMin = chooseLatestDate(estimatedMin, guaranteed); estimatedMax = chooseLatestDate(estimatedMax, guaranteed); } else { guaranteed = chooseLatestDate(guaranteed, detail.getDeliveryGuaranteed()); } confirmed = chooseLatestDate(confirmed, detail.getDeliveryConfirmed()); if (detail.getDeliveredQuantity() == null) { allItemsDeliveredOrRejected = false; } } } if (estimatedMin != null || estimatedMax != null) { notGuaranteed = true; } if (notGuaranteed) { if (atLeastOneItemIsNotUpdated) { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(null); } else { delivery.setDeliveryEstimatedMin(estimatedMin); delivery.setDeliveryEstimatedMax(estimatedMax); delivery.setDeliveryGuaranteed(null); } } else { delivery.setDeliveryEstimatedMin(null); delivery.setDeliveryEstimatedMax(null); delivery.setDeliveryGuaranteed(guaranteed); } if (allItemsDeliveredOrRejected) { delivery.setDeliveryConfirmed(confirmed); } LOG.info("Attempting to auto-progress delivery {}. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (allowDeliveryTransitions) { if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_RESERVED.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_ALLOCATION_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_WAIT.equals(delivery.getDeliveryStatus()) || CustomerOrderDelivery.DELIVERY_STATUS_DATE_WAIT.equals(delivery.getDeliveryStatus())) { voidReservation(orderEvent, delivery); getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was pending allocation, reservation was voided and delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_INVENTORY_ALLOCATED.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_PACK, customerOrder, delivery)); LOG.info("Delivery {} was allocated, delivery released to pack. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } if (CustomerOrderDelivery.DELIVERY_STATUS_PACKING.equals(delivery.getDeliveryStatus()) && allItemsDeliveredOrRejected) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_RELEASE_TO_SHIPMENT, customerOrder, delivery)); LOG.info("Delivery {} was in packing, all lines updated, releasing to shipment to take payment. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); if (CustomerOrderDelivery.DELIVERY_STATUS_SHIPMENT_IN_PROGRESS.equals(delivery.getDeliveryStatus())) { getOrderStateManager().fireTransition(new OrderEventImpl(OrderStateManager.EVT_SHIPMENT_COMPLETE, customerOrder, delivery)); LOG.info("Delivery {} was in shipping (payment successful), marking as complete. Status: {}", customerOrder.getOrdernum(), delivery.getDeliveryStatus()); } } } } if (!detailsByPk.isEmpty()) { LOG.error(Markers.alert(), "Not all line specific updates could be processed: {}", detailsByPk); } if (!detailsBySKU.isEmpty()) { LOG.error(Markers.alert(), "Not all SKU updates could be processed: {}", detailsBySKU); } LOG.info("Finished delivery update for order {}, status {}:\n{}", customerOrder.getOrdernum(), customerOrder.getOrderStatus(), update); return true; } return false; } } DeliveryUpdateOrderEventHandlerImpl(final WarehouseService warehouseService,
                                               final InventoryResolver inventoryResolver,
                                               final ProductService productService); @Override void setApplicationContext(final ApplicationContext applicationContext); @Override boolean handle(final OrderEvent orderEvent);  }