IDEMPIERE-4575 Cannot complete Material Receipt from negative PO (#419)

This commit is contained in:
Carlos Ruiz 2020-11-28 00:09:39 +01:00 committed by GitHub
parent 71a2ee3fe7
commit 0eb4986513
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 5 deletions

View File

@ -1117,16 +1117,24 @@ public class MMatchPO extends X_M_MatchPO
if (validateOrderedQty)
{
MOrderLine line = new MOrderLine(getCtx(), getC_OrderLine_ID(), get_TrxName());
BigDecimal qtyOrdered = line.getQtyOrdered();
BigDecimal invoicedQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchPO WHERE C_InvoiceLine_ID > 0 and C_OrderLine_ID=? AND Reversal_ID IS NULL" , getC_OrderLine_ID());
if (invoicedQty != null && invoicedQty.compareTo(line.getQtyOrdered()) > 0)
if ( invoicedQty != null
&& ( (qtyOrdered.signum() > 0 && invoicedQty.compareTo(qtyOrdered) > 0)
|| (qtyOrdered.signum() < 0 && invoicedQty.compareTo(qtyOrdered) < 0)
)
)
{
throw new IllegalStateException("Total matched invoiced qty > ordered qty. MatchedInvoicedQty="+invoicedQty+", OrderedQty="+line.getQtyOrdered()+", Line="+line);
throw new IllegalStateException("Total matched invoiced qty > ordered qty. MatchedInvoicedQty="+invoicedQty+", OrderedQty="+qtyOrdered+", Line="+line);
}
BigDecimal deliveredQty = DB.getSQLValueBD(get_TrxName(), "SELECT Coalesce(SUM(Qty),0) FROM M_MatchPO WHERE M_InOutLine_ID > 0 and C_OrderLine_ID=? AND Reversal_ID IS NULL" , getC_OrderLine_ID());
if (deliveredQty != null && deliveredQty.compareTo(line.getQtyOrdered()) > 0)
if ( deliveredQty != null
&& ( (qtyOrdered.signum() > 0 && deliveredQty.compareTo(qtyOrdered) > 0)
|| (qtyOrdered.signum() < 0 && deliveredQty.compareTo(qtyOrdered) < 0)
)
)
{
throw new IllegalStateException("Total matched delivered qty > ordered qty. MatchedDeliveredQty="+deliveredQty+", OrderedQty="+line.getQtyOrdered()+", Line="+line);
throw new IllegalStateException("Total matched delivered qty > ordered qty. MatchedDeliveredQty="+deliveredQty+", OrderedQty="+qtyOrdered+", Line="+line);
}
}
}

View File

@ -0,0 +1,116 @@
/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
* *
* Contributors: *
* - Carlos Ruiz - globalqss *
**********************************************************************/
package org.idempiere.test.model;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Properties;
import org.compiere.model.MBPartner;
import org.compiere.model.MInOut;
import org.compiere.model.MInOutLine;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
import org.compiere.model.MProduct;
import org.compiere.process.DocAction;
import org.compiere.process.ProcessInfo;
import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
import org.compiere.wf.MWorkflow;
import org.idempiere.test.AbstractTestCase;
import org.junit.jupiter.api.Test;
/**
* @author Carlos Ruiz - globalqss
*/
public class PurchaseOrderTest extends AbstractTestCase {
public PurchaseOrderTest() {
}
private static final int BP_PATIO = 121;
private static final int DOCTYPE_PO = 126;
private static final int DOCTYPE_RECEIPT = 122;
private static final int PRODUCT_SEEDER = 143;
private static final int USER_GARDENADMIN = 101;
/**
* https://idempiere.atlassian.net/browse/IDEMPIERE-4575
*/
@Test
public void testQtyReservedForNegativeOrderAndReceipt() {
Properties ctx = Env.getCtx();
String trxName = getTrxName();
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_SEEDER));
line1.setQty(new BigDecimal("-1"));
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().intValue());
MInOut receipt = new MInOut(order, DOCTYPE_RECEIPT, order.getDateOrdered());
receipt.setDocStatus(DocAction.STATUS_Drafted);
receipt.setDocAction(DocAction.ACTION_Complete);
receipt.saveEx();
// negative receipt
MInOutLine receiptLine = new MInOutLine(receipt);
receiptLine.setOrderLine(line1, 0, new BigDecimal("-1"));
receiptLine.setQty(new BigDecimal("-1"));
receiptLine.saveEx();
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Complete);
assertFalse(info.isError());
receipt.load(trxName);
assertEquals(DocAction.STATUS_Completed, receipt.getDocStatus());
line1.load(trxName);
assertEquals(0, line1.getQtyReserved().intValue());
}
}