IDEMPIERE-4587 Wrong ordered qty when reactivating a purchase order and setting a line to zero (#445)
This commit is contained in:
parent
9ed69583e8
commit
d654ed5791
|
@ -1416,7 +1416,7 @@ public class MInOut extends X_M_InOut implements DocAction
|
|||
}
|
||||
}
|
||||
|
||||
if (oLine!=null && mtrx!=null && oLine.getQtyOrdered().signum() > 0)
|
||||
if (oLine!=null && mtrx!=null && oLine.getQtyOrdered().signum() >= 0)
|
||||
{
|
||||
if (sLine.getC_OrderLine_ID() != 0)
|
||||
{
|
||||
|
@ -1467,7 +1467,7 @@ public class MInOut extends X_M_InOut implements DocAction
|
|||
m_processMsg = "Cannot correct Inventory OnHand [" + product.getValue() + "] - " + lastError;
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
if (oLine!=null && oLine.getQtyOrdered().signum() > 0)
|
||||
if (oLine!=null && oLine.getQtyOrdered().signum() >= 0)
|
||||
{
|
||||
if (!MStorageReservation.add(getCtx(), oLine.getM_Warehouse_ID(),
|
||||
sLine.getM_Product_ID(),
|
||||
|
@ -1496,7 +1496,7 @@ public class MInOut extends X_M_InOut implements DocAction
|
|||
// Correct Order Line
|
||||
if (product != null && oLine != null) // other in VMatch.createMatchRecord
|
||||
{
|
||||
if (oLine.getQtyOrdered().signum() > 0)
|
||||
if (oLine.getQtyOrdered().signum() >= 0)
|
||||
{
|
||||
oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty().subtract(sLine.getQtyOverReceipt())));
|
||||
|
||||
|
|
|
@ -2188,6 +2188,10 @@ public class MOrder extends X_C_Order implements DocAction
|
|||
MInOutLine ioLine = new MInOutLine(shipment);
|
||||
// Qty = Ordered - Delivered
|
||||
BigDecimal MovementQty = oLine.getQtyOrdered().subtract(oLine.getQtyDelivered());
|
||||
if (MovementQty.signum() == 0 && getProcessedOn().signum() != 0) {
|
||||
// do not create lines with qty = 0 when the order is reactivated and completed again
|
||||
continue;
|
||||
}
|
||||
// Location
|
||||
int M_Locator_ID = MStorageOnHand.getM_Locator_ID (oLine.getM_Warehouse_ID(),
|
||||
oLine.getM_Product_ID(), oLine.getM_AttributeSetInstance_ID(),
|
||||
|
|
|
@ -39,6 +39,8 @@ import org.compiere.model.MInvoiceLine;
|
|||
import org.compiere.model.MOrder;
|
||||
import org.compiere.model.MOrderLine;
|
||||
import org.compiere.model.MProduct;
|
||||
import org.compiere.model.MStorageOnHand;
|
||||
import org.compiere.model.MStorageReservation;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.ProcessInfo;
|
||||
import org.compiere.util.Env;
|
||||
|
@ -61,7 +63,10 @@ public class PurchaseOrderTest extends AbstractTestCase {
|
|||
private static final int DOCTYPE_AP_INVOICE = 123;
|
||||
private static final int PRODUCT_SEEDER = 143;
|
||||
private static final int PRODUCT_WEEDER = 141;
|
||||
private static final int PRODUCT_MULCH = 137;
|
||||
private static final int USER_GARDENADMIN = 101;
|
||||
private static final BigDecimal THREE = new BigDecimal("3");
|
||||
private static final BigDecimal MINUS_THREE = new BigDecimal("-3");
|
||||
|
||||
/**
|
||||
* https://idempiere.atlassian.net/browse/IDEMPIERE-4575
|
||||
|
@ -198,4 +203,118 @@ public class PurchaseOrderTest extends AbstractTestCase {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* IDEMPIERE-4587
|
||||
*/
|
||||
@Test
|
||||
public void testOrderedStorageForReactivatedOrder() {
|
||||
Properties ctx = Env.getCtx();
|
||||
String trxName = getTrxName();
|
||||
|
||||
BigDecimal qtyOrderedOriginal = getQtyOrdered(ctx, PRODUCT_MULCH, trxName);
|
||||
|
||||
MOrder order = new MOrder(ctx, 0, trxName);
|
||||
order.setBPartner(MBPartner.get(ctx, BP_PATIO));
|
||||
order.setC_DocTypeTarget_ID(DOCTYPE_PO);
|
||||
order.setIsSOTrx(false);
|
||||
order.setSalesRep_ID(USER_GARDENADMIN);
|
||||
order.setDocStatus(DocAction.STATUS_Drafted);
|
||||
order.setDocAction(DocAction.ACTION_Complete);
|
||||
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
|
||||
order.setDateOrdered(today);
|
||||
order.setDatePromised(today);
|
||||
order.saveEx();
|
||||
|
||||
MOrderLine line1 = new MOrderLine(order);
|
||||
line1.setLine(10);
|
||||
line1.setProduct(MProduct.get(ctx, PRODUCT_MULCH));
|
||||
line1.setQty(THREE);
|
||||
line1.setDatePromised(today);
|
||||
line1.saveEx();
|
||||
|
||||
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError());
|
||||
order.load(trxName);
|
||||
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
|
||||
line1.load(trxName);
|
||||
assertEquals(0, line1.getQtyReserved().compareTo(THREE));
|
||||
|
||||
BigDecimal newQtyOrdered = getQtyOrdered(ctx, PRODUCT_MULCH, trxName);
|
||||
assertEquals(0, qtyOrderedOriginal.add(THREE).compareTo(newQtyOrdered));
|
||||
|
||||
MInOut receipt1 = new MInOut(order, DOCTYPE_RECEIPT, order.getDateOrdered());
|
||||
receipt1.setDocStatus(DocAction.STATUS_Drafted);
|
||||
receipt1.setDocAction(DocAction.ACTION_Complete);
|
||||
receipt1.saveEx();
|
||||
|
||||
MInOutLine receiptLine1 = new MInOutLine(receipt1);
|
||||
receiptLine1.setOrderLine(line1, 0, THREE);
|
||||
receiptLine1.setQty(THREE);
|
||||
receiptLine1.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(receipt1, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError());
|
||||
receipt1.load(trxName);
|
||||
assertEquals(DocAction.STATUS_Completed, receipt1.getDocStatus());
|
||||
|
||||
line1.load(trxName);
|
||||
assertEquals(0, line1.getQtyReserved().compareTo(Env.ZERO));
|
||||
|
||||
newQtyOrdered = getQtyOrdered(ctx, PRODUCT_MULCH, trxName);
|
||||
assertEquals(0, qtyOrderedOriginal.compareTo(newQtyOrdered));
|
||||
|
||||
// reactivate the purchase order
|
||||
info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_ReActivate);
|
||||
assertFalse(info.isError());
|
||||
order.load(trxName);
|
||||
assertEquals(DocAction.STATUS_InProgress, order.getDocStatus());
|
||||
|
||||
// change the line quantity to zero
|
||||
line1.load(trxName);
|
||||
line1.setQty(Env.ZERO);
|
||||
line1.saveEx();
|
||||
|
||||
// complete the order again
|
||||
info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError());
|
||||
order.load(trxName);
|
||||
assertEquals(DocAction.STATUS_Completed, order.getDocStatus());
|
||||
line1.load(trxName);
|
||||
assertEquals(0, line1.getQtyReserved().compareTo(MINUS_THREE));
|
||||
|
||||
newQtyOrdered = getQtyOrdered(ctx, PRODUCT_MULCH, trxName);
|
||||
assertEquals(0, qtyOrderedOriginal.add(MINUS_THREE).compareTo(newQtyOrdered));
|
||||
|
||||
// create a new material receipt for the -3 reversed
|
||||
MInOut receipt2 = new MInOut(order, DOCTYPE_RECEIPT, order.getDateOrdered());
|
||||
receipt2.setDocStatus(DocAction.STATUS_Drafted);
|
||||
receipt2.setDocAction(DocAction.ACTION_Complete);
|
||||
receipt2.saveEx();
|
||||
|
||||
MInOutLine receiptLine2 = new MInOutLine(receipt2);
|
||||
receiptLine2.setOrderLine(line1, 0, MINUS_THREE);
|
||||
receiptLine2.setQty(MINUS_THREE);
|
||||
receiptLine2.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(receipt2, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError());
|
||||
receipt2.load(trxName);
|
||||
assertEquals(DocAction.STATUS_Completed, receipt2.getDocStatus());
|
||||
|
||||
line1.load(trxName);
|
||||
assertEquals(0, line1.getQtyReserved().compareTo(Env.ZERO));
|
||||
|
||||
newQtyOrdered = getQtyOrdered(ctx, PRODUCT_MULCH, trxName);
|
||||
assertEquals(0, qtyOrderedOriginal.compareTo(newQtyOrdered));
|
||||
}
|
||||
|
||||
private BigDecimal getQtyOrdered(Properties ctx, int M_Product_ID, String trxName) {
|
||||
BigDecimal qtyOrdered = Env.ZERO;
|
||||
for (MStorageReservation rs : MStorageReservation.getOfProduct(ctx, M_Product_ID, trxName)) {
|
||||
if (! rs.isSOTrx())
|
||||
qtyOrdered = qtyOrdered.add(rs.getQty());
|
||||
}
|
||||
return qtyOrdered;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue