IDEMPIERE-5768 : Adding Credit manager factory to override or extend … (#1949)
* IDEMPIERE-5768 : Adding Credit manager factory to override or extend credit management * IDEMPIERE-5768 : Fixing as as per code review comments from Hengsin * IDEMPIERE-5768: Use component annotation instead of xml service definition * IDEMPIERE-5768: Adding Unit tests and Making return type of CheckCreditStatus to be object instead of String. * IDEMPIERE-5768: Fixing as per code review comment. * IDEMPIERE-5768: Removed explicit rollback from test cases
This commit is contained in:
parent
5aba739d37
commit
18f925fd2f
|
@ -48,6 +48,7 @@ import org.compiere.model.MPaymentProcessor;
|
|||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.model.MTaxProvider;
|
||||
import org.compiere.model.ModelValidator;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.model.PaymentInterface;
|
||||
import org.compiere.model.PaymentProcessor;
|
||||
import org.compiere.model.StandardTaxProvider;
|
||||
|
@ -1087,4 +1088,42 @@ public class Core {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* get Credit Manager
|
||||
*
|
||||
* @param PO
|
||||
* @return instance of the ICreditManager
|
||||
*/
|
||||
public static ICreditManager getCreditManager(PO po)
|
||||
{
|
||||
if (po == null)
|
||||
{
|
||||
s_log.log(Level.SEVERE, "Invalid PO");
|
||||
return null;
|
||||
}
|
||||
|
||||
ICreditManager myCreditManager = null;
|
||||
|
||||
List<ICreditManagerFactory> factoryList = Service.locator().list(ICreditManagerFactory.class).getServices();
|
||||
if (factoryList != null)
|
||||
{
|
||||
for (ICreditManagerFactory factory : factoryList)
|
||||
{
|
||||
myCreditManager = factory.getCreditManager(po);
|
||||
if (myCreditManager != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (myCreditManager == null)
|
||||
{
|
||||
s_log.log(Level.CONFIG, "For " + po.get_TableName() + " not found any service/extension registry.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return myCreditManager;
|
||||
} // getCreditManager
|
||||
}
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.base;
|
||||
|
||||
/**
|
||||
* POJO for Credit Status
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since August 04, 2023
|
||||
*/
|
||||
public class CreditStatus
|
||||
{
|
||||
protected String errorMsg;
|
||||
protected boolean isError;
|
||||
|
||||
/**
|
||||
* Credit Status Load Constructor
|
||||
*
|
||||
* @param errorMsg
|
||||
* @param isError
|
||||
*/
|
||||
public CreditStatus(String errorMsg, boolean isError)
|
||||
{
|
||||
super();
|
||||
this.errorMsg = errorMsg;
|
||||
this.isError = isError;
|
||||
}
|
||||
|
||||
public String getErrorMsg()
|
||||
{
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
public void setErrorMsg(String errorMsg)
|
||||
{
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public boolean isError()
|
||||
{
|
||||
return isError;
|
||||
}
|
||||
|
||||
public void setError(boolean isError)
|
||||
{
|
||||
this.isError = isError;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.base;
|
||||
|
||||
import org.compiere.model.MInOut;
|
||||
import org.compiere.model.MInvoice;
|
||||
import org.compiere.model.MOrder;
|
||||
import org.compiere.model.MPayment;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.model.credit.CreditManagerInOut;
|
||||
import org.compiere.model.credit.CreditManagerInvoice;
|
||||
import org.compiere.model.credit.CreditManagerOrder;
|
||||
import org.compiere.model.credit.CreditManagerPayment;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
|
||||
/**
|
||||
* Default Credit Manager Factory
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since June 25, 2023
|
||||
*/
|
||||
@Component(immediate = true, service = ICreditManagerFactory.class)
|
||||
public class DefaultCreditManagerFactory implements ICreditManagerFactory
|
||||
{
|
||||
|
||||
@Override
|
||||
public ICreditManager getCreditManager(PO po)
|
||||
{
|
||||
if (po instanceof MOrder)
|
||||
return new CreditManagerOrder((MOrder) po);
|
||||
else if (po instanceof MInvoice)
|
||||
return new CreditManagerInvoice((MInvoice) po);
|
||||
else if (po instanceof MPayment)
|
||||
return new CreditManagerPayment((MPayment) po);
|
||||
else if (po instanceof MInOut)
|
||||
return new CreditManagerInOut((MInOut) po);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.base;
|
||||
|
||||
/**
|
||||
* Interface for Credit Manager implementor
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since June 25, 2023
|
||||
*/
|
||||
public interface ICreditManager
|
||||
{
|
||||
/**
|
||||
* Check credit status as per document action
|
||||
*
|
||||
* @param docAction Document Action
|
||||
* @return Credit Status POJO
|
||||
*/
|
||||
public CreditStatus checkCreditStatus(String docAction);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.adempiere.base;
|
||||
|
||||
import org.compiere.model.PO;
|
||||
|
||||
/**
|
||||
* Interface for Credit Manager Factory
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since June 25, 2023
|
||||
*/
|
||||
public interface ICreditManagerFactory
|
||||
{
|
||||
/**
|
||||
* get Credit Manager
|
||||
*
|
||||
* @param po Model class
|
||||
* @return instance of the ICreditManager
|
||||
*/
|
||||
public ICreditManager getCreditManager(PO po);
|
||||
}
|
|
@ -29,6 +29,8 @@ import java.util.Properties;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.DBException;
|
||||
import org.adempiere.exceptions.NegativeInventoryDisallowedException;
|
||||
|
@ -1454,41 +1456,15 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
|
|||
}
|
||||
|
||||
// Credit Check
|
||||
if (isSOTrx() && !isReversal() && !isCustomerReturn())
|
||||
ICreditManager creditManager = Core.getCreditManager(this);
|
||||
if (creditManager != null)
|
||||
{
|
||||
I_C_Order order = getC_Order();
|
||||
if (order != null && MDocType.DOCSUBTYPESO_PrepayOrder.equals(order.getC_DocType().getDocSubTypeSO())
|
||||
&& !MSysConfig.getBooleanValue(MSysConfig.CHECK_CREDIT_ON_PREPAY_ORDER, true, getAD_Client_ID(), getAD_Org_ID())) {
|
||||
// ignore -- don't validate Prepay Orders depending on sysconfig parameter
|
||||
} else {
|
||||
MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()))
|
||||
CreditStatus status = creditManager.checkCreditStatus(DOCACTION_Prepare);
|
||||
if (status.isError())
|
||||
{
|
||||
m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
m_processMsg = status.getErrorMsg();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
if (!MBPartner.SOCREDITSTATUS_NoCreditCheck.equals(bp.getSOCreditStatus())
|
||||
&& Env.ZERO.compareTo(bp.getSO_CreditLimit()) != 0)
|
||||
{
|
||||
BigDecimal notInvoicedAmt = MBPartner.getNotInvoicedAmt(getC_BPartner_ID());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(notInvoicedAmt)))
|
||||
{
|
||||
m_processMsg = "@BPartnerOverSCreditHold@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance() + ", @NotInvoicedAmt@=" + notInvoicedAmt
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Lines
|
||||
|
@ -1557,7 +1533,7 @@ public class MInOut extends X_M_InOut implements DocAction, IDocsPostProcess
|
|||
* Check if Document is Customer Return.
|
||||
* @return True if Document is Customer Return
|
||||
*/
|
||||
private boolean isCustomerReturn() {
|
||||
public boolean isCustomerReturn() {
|
||||
MDocType doctype = MDocType.get(getC_DocType_ID());
|
||||
if(isSOTrx() && doctype.getDocBaseType().equals("MMR") && doctype.isSOTrx())
|
||||
return true;
|
||||
|
|
|
@ -32,6 +32,8 @@ import java.util.Vector;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.BPartnerNoAddressException;
|
||||
import org.adempiere.exceptions.DBException;
|
||||
|
@ -1737,24 +1739,16 @@ public class MInvoice extends X_C_Invoice implements DocAction, IDocsPostProcess
|
|||
}
|
||||
|
||||
// Credit Status
|
||||
if (isSOTrx())
|
||||
ICreditManager creditManager = Core.getCreditManager(this);
|
||||
if (creditManager != null)
|
||||
{
|
||||
MDocType doc = (MDocType) getC_DocTypeTarget();
|
||||
// IDEMPIERE-365 - just check credit if is going to increase the debt
|
||||
if ( (doc.getDocBaseType().equals(MDocType.DOCBASETYPE_ARCreditMemo) && getGrandTotal().signum() < 0 ) ||
|
||||
(doc.getDocBaseType().equals(MDocType.DOCBASETYPE_ARInvoice) && getGrandTotal().signum() > 0 )
|
||||
)
|
||||
CreditStatus status = creditManager.checkCreditStatus(DOCACTION_Prepare);
|
||||
if (status.isError())
|
||||
{
|
||||
MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null);
|
||||
if ( MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()) )
|
||||
{
|
||||
m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
m_processMsg = status.getErrorMsg();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Landed Costs
|
||||
if (!isSOTrx())
|
||||
|
@ -2144,76 +2138,15 @@ public class MInvoice extends X_C_Invoice implements DocAction, IDocsPostProcess
|
|||
if (matchPO > 0)
|
||||
info.append(" @M_MatchPO_ID@#").append(matchPO).append(" ");
|
||||
|
||||
|
||||
|
||||
// Update BP Statistics
|
||||
MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName());
|
||||
DB.getDatabase().forUpdate(bp, 0);
|
||||
// Update total revenue and balance / credit limit (reversed on AllocationLine.processIt)
|
||||
BigDecimal invAmt = null;
|
||||
int baseCurrencyId = Env.getContextAsInt(getCtx(), Env.C_CURRENCY_ID);
|
||||
if (getC_Currency_ID() != baseCurrencyId && isOverrideCurrencyRate())
|
||||
ICreditManager creditManager = Core.getCreditManager(this);
|
||||
if (creditManager != null)
|
||||
{
|
||||
invAmt = getGrandTotal(true).multiply(getCurrencyRate());
|
||||
int stdPrecision = MCurrency.getStdPrecision(getCtx(), baseCurrencyId);
|
||||
if (invAmt.scale() > stdPrecision)
|
||||
invAmt = invAmt.setScale(stdPrecision, RoundingMode.HALF_UP);
|
||||
}
|
||||
else
|
||||
CreditStatus status = creditManager.checkCreditStatus(DOCACTION_Complete);
|
||||
if (status.isError())
|
||||
{
|
||||
invAmt = MConversionRate.convertBase(getCtx(), getGrandTotal(true), // CM adjusted
|
||||
getC_Currency_ID(), getDateAcct(), getC_ConversionType_ID(), getAD_Client_ID(), getAD_Org_ID());
|
||||
}
|
||||
if (invAmt == null)
|
||||
{
|
||||
m_processMsg = MConversionRateUtil.getErrorMessage(getCtx(), "ErrorConvertingCurrencyToBaseCurrency",
|
||||
getC_Currency_ID(), MClient.get(getCtx()).getC_Currency_ID(), getC_ConversionType_ID(), getDateAcct(), get_TrxName());
|
||||
m_processMsg = status.getErrorMsg();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
// Total Balance
|
||||
BigDecimal newBalance = bp.getTotalOpenBalance();
|
||||
if (newBalance == null)
|
||||
newBalance = Env.ZERO;
|
||||
if (isSOTrx())
|
||||
{
|
||||
newBalance = newBalance.add(invAmt);
|
||||
//
|
||||
if (bp.getFirstSale() == null)
|
||||
bp.setFirstSale(getDateInvoiced());
|
||||
BigDecimal newLifeAmt = bp.getActualLifeTimeValue();
|
||||
if (newLifeAmt == null)
|
||||
newLifeAmt = invAmt;
|
||||
else
|
||||
newLifeAmt = newLifeAmt.add(invAmt);
|
||||
BigDecimal newCreditAmt = bp.getSO_CreditUsed();
|
||||
if (newCreditAmt == null)
|
||||
newCreditAmt = invAmt;
|
||||
else
|
||||
newCreditAmt = newCreditAmt.add(invAmt);
|
||||
//
|
||||
if (log.isLoggable(Level.FINE)) log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt
|
||||
+ ") BP Life=" + bp.getActualLifeTimeValue() + "->" + newLifeAmt
|
||||
+ ", Credit=" + bp.getSO_CreditUsed() + "->" + newCreditAmt
|
||||
+ ", Balance=" + bp.getTotalOpenBalance() + " -> " + newBalance);
|
||||
bp.setActualLifeTimeValue(newLifeAmt);
|
||||
bp.setSO_CreditUsed(newCreditAmt);
|
||||
} // SO
|
||||
else
|
||||
{
|
||||
newBalance = newBalance.subtract(invAmt);
|
||||
if (log.isLoggable(Level.FINE)) log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt
|
||||
+ ") Balance=" + bp.getTotalOpenBalance() + " -> " + newBalance);
|
||||
}
|
||||
// the payment just created already updated the open balance
|
||||
if ( ! (PAYMENTRULE_Cash.equals(getPaymentRule()) && !fromPOS ) )
|
||||
{
|
||||
bp.setTotalOpenBalance(newBalance);
|
||||
}
|
||||
bp.setSOCreditStatus();
|
||||
if (!bp.save(get_TrxName()))
|
||||
{
|
||||
m_processMsg = "Could not update Business Partner";
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
|
||||
// User - Last Result/Contact
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.util.Properties;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.BPartnerNoBillToAddressException;
|
||||
import org.adempiere.exceptions.BPartnerNoShipToAddressException;
|
||||
|
@ -1683,47 +1685,15 @@ public class MOrder extends X_C_Order implements DocAction
|
|||
}
|
||||
|
||||
// Credit Check
|
||||
if (isSOTrx())
|
||||
ICreditManager creditManager = Core.getCreditManager(this);
|
||||
if (creditManager != null)
|
||||
{
|
||||
if ( MDocType.DOCSUBTYPESO_POSOrder.equals(dt.getDocSubTypeSO())
|
||||
&& PAYMENTRULE_Cash.equals(getPaymentRule())
|
||||
&& !MSysConfig.getBooleanValue(MSysConfig.CHECK_CREDIT_ON_CASH_POS_ORDER, true, getAD_Client_ID(), getAD_Org_ID())) {
|
||||
// ignore -- don't validate for Cash POS Orders depending on sysconfig parameter
|
||||
} else if (MDocType.DOCSUBTYPESO_PrepayOrder.equals(dt.getDocSubTypeSO())
|
||||
&& !MSysConfig.getBooleanValue(MSysConfig.CHECK_CREDIT_ON_PREPAY_ORDER, true, getAD_Client_ID(), getAD_Org_ID())) {
|
||||
// ignore -- don't validate Prepay Orders depending on sysconfig parameter
|
||||
} else {
|
||||
MBPartner bp = new MBPartner (getCtx(), getBill_BPartner_ID(), get_TrxName()); // bill bp is guaranteed on beforeSave
|
||||
|
||||
if (getGrandTotal().signum() > 0) // IDEMPIERE-365 - just check credit if is going to increase the debt
|
||||
CreditStatus status = creditManager.checkCreditStatus(DOCACTION_Prepare);
|
||||
if (status.isError())
|
||||
{
|
||||
|
||||
if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
m_processMsg = status.getErrorMsg();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
BigDecimal grandTotal = MConversionRate.convertBase(getCtx(),
|
||||
getGrandTotal(), getC_Currency_ID(), getDateOrdered(),
|
||||
getC_ConversionType_ID(), getAD_Client_ID(), getAD_Org_ID());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(grandTotal)))
|
||||
{
|
||||
m_processMsg = "@BPartnerOverOCreditHold@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance() + ", @GrandTotal@=" + grandTotal
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_PREPARE);
|
||||
|
|
|
@ -29,6 +29,9 @@ import java.util.Properties;
|
|||
import java.util.Vector;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.base.Core;
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.adempiere.exceptions.PeriodClosedException;
|
||||
import org.adempiere.util.IProcessUI;
|
||||
|
@ -1985,22 +1988,13 @@ public class MPayment extends X_C_Payment
|
|||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
|
||||
// Do not pay when Credit Stop/Hold
|
||||
if (!isReceipt())
|
||||
ICreditManager creditManager = Core.getCreditManager(this);
|
||||
if (creditManager != null)
|
||||
{
|
||||
MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName());
|
||||
if (X_C_BPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()))
|
||||
CreditStatus status = creditManager.checkCreditStatus(DOCACTION_Prepare);
|
||||
if (status.isError())
|
||||
{
|
||||
m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
if (X_C_BPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@="
|
||||
+ bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
m_processMsg = status.getErrorMsg();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
|
@ -2066,53 +2060,21 @@ public class MPayment extends X_C_Payment
|
|||
if (log.isLoggable(Level.INFO)) log.info(toString());
|
||||
|
||||
// Charge Handling
|
||||
boolean createdAllocationRecords = false;
|
||||
if (getC_Charge_ID() != 0)
|
||||
{
|
||||
setIsAllocated(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
createdAllocationRecords = allocateIt(); // Create Allocation Records
|
||||
testAllocation();
|
||||
}
|
||||
|
||||
// Update BP for Prepayments
|
||||
if (getC_BPartner_ID() != 0 && getC_Invoice_ID() == 0 && getC_Charge_ID() == 0 && MPaymentAllocate.get(this).length == 0 && !createdAllocationRecords)
|
||||
ICreditManager creditManager = Core.getCreditManager(this);
|
||||
if (creditManager != null)
|
||||
{
|
||||
MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName());
|
||||
DB.getDatabase().forUpdate(bp, 0);
|
||||
// Update total balance to include this payment
|
||||
BigDecimal payAmt = null;
|
||||
int baseCurrencyId = Env.getContextAsInt(getCtx(), Env.C_CURRENCY_ID);
|
||||
if (getC_Currency_ID() != baseCurrencyId && isOverrideCurrencyRate())
|
||||
CreditStatus status = creditManager.checkCreditStatus(DOCACTION_Complete);
|
||||
if (status.isError())
|
||||
{
|
||||
payAmt = getConvertedAmt();
|
||||
}
|
||||
else
|
||||
{
|
||||
payAmt = MConversionRate.convertBase(getCtx(), getPayAmt(),
|
||||
getC_Currency_ID(), getDateAcct(), getC_ConversionType_ID(), getAD_Client_ID(), getAD_Org_ID());
|
||||
if (payAmt == null)
|
||||
{
|
||||
m_processMsg = MConversionRateUtil.getErrorMessage(getCtx(), "ErrorConvertingCurrencyToBaseCurrency",
|
||||
getC_Currency_ID(), MClient.get(getCtx()).getC_Currency_ID(), getC_ConversionType_ID(), getDateAcct(), get_TrxName());
|
||||
m_processMsg = status.getErrorMsg();
|
||||
return DocAction.STATUS_Invalid;
|
||||
}
|
||||
}
|
||||
// Total Balance
|
||||
BigDecimal newBalance = bp.getTotalOpenBalance();
|
||||
if (newBalance == null)
|
||||
newBalance = Env.ZERO;
|
||||
if (isReceipt())
|
||||
newBalance = newBalance.subtract(payAmt);
|
||||
else
|
||||
newBalance = newBalance.add(payAmt);
|
||||
|
||||
bp.setTotalOpenBalance(newBalance);
|
||||
bp.setSOCreditStatus();
|
||||
bp.saveEx();
|
||||
}
|
||||
|
||||
// Counter Doc
|
||||
MPayment counter = createCounterDoc();
|
||||
|
@ -2832,13 +2794,10 @@ public class MPayment extends X_C_Payment
|
|||
//
|
||||
info.append(" - @C_AllocationHdr_ID@: ").append(alloc.getDocumentNo());
|
||||
|
||||
ICreditManager creditManager = Core.getCreditManager(this);
|
||||
// Update BPartner
|
||||
if (getC_BPartner_ID() != 0)
|
||||
{
|
||||
MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName());
|
||||
bp.setTotalOpenBalance();
|
||||
bp.saveEx(get_TrxName());
|
||||
}
|
||||
if (creditManager != null)
|
||||
creditManager.checkCreditStatus(accrual ? DOCACTION_Reverse_Accrual : DOCACTION_Reverse_Correct);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model.credit;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.compiere.model.I_C_Order;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MDocType;
|
||||
import org.compiere.model.MInOut;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* Credit Manager for InOut
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since June 25, 2023
|
||||
*/
|
||||
public class CreditManagerInOut implements ICreditManager
|
||||
{
|
||||
private MInOut mInOut;
|
||||
|
||||
/**
|
||||
* InOut Credit Manager Load Constructor
|
||||
*
|
||||
* @param po MInOut
|
||||
*/
|
||||
public CreditManagerInOut(MInOut po)
|
||||
{
|
||||
this.mInOut = po;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreditStatus checkCreditStatus(String docAction)
|
||||
{
|
||||
String errorMsg = null;
|
||||
if (MInOut.DOCACTION_Prepare.equals(docAction) && mInOut.isSOTrx() && !mInOut.isReversal() && !mInOut.isCustomerReturn())
|
||||
{
|
||||
I_C_Order order = mInOut.getC_Order();
|
||||
if (order != null
|
||||
&& MDocType.DOCSUBTYPESO_PrepayOrder.equals(order.getC_DocType().getDocSubTypeSO())
|
||||
&& !MSysConfig.getBooleanValue(MSysConfig.CHECK_CREDIT_ON_PREPAY_ORDER, true, mInOut.getAD_Client_ID(), mInOut.getAD_Org_ID()))
|
||||
{
|
||||
// ignore -- don't validate Prepay Orders depending on sysconfig parameter
|
||||
}
|
||||
else
|
||||
{
|
||||
MBPartner bp = new MBPartner(mInOut.getCtx(), mInOut.getC_BPartner_ID(), mInOut.get_TrxName());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
errorMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
errorMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
if (!MBPartner.SOCREDITSTATUS_NoCreditCheck.equals(bp.getSOCreditStatus())
|
||||
&& Env.ZERO.compareTo(bp.getSO_CreditLimit()) != 0)
|
||||
{
|
||||
BigDecimal notInvoicedAmt = MBPartner.getNotInvoicedAmt(mInOut.getC_BPartner_ID());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(notInvoicedAmt)))
|
||||
{
|
||||
errorMsg = "@BPartnerOverSCreditHold@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @NotInvoicedAmt@=" + notInvoicedAmt
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new CreditStatus(errorMsg, !Util.isEmpty(errorMsg));
|
||||
} // creditCheck
|
||||
}
|
|
@ -0,0 +1,168 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model.credit;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MClient;
|
||||
import org.compiere.model.MConversionRate;
|
||||
import org.compiere.model.MConversionRateUtil;
|
||||
import org.compiere.model.MCurrency;
|
||||
import org.compiere.model.MDocType;
|
||||
import org.compiere.model.MInvoice;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* Credit Manager for Invoice
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since June 25, 2023
|
||||
*/
|
||||
public class CreditManagerInvoice implements ICreditManager
|
||||
{
|
||||
/** Logger */
|
||||
protected transient CLogger log = CLogger.getCLogger(CreditManagerInvoice.class);
|
||||
|
||||
private MInvoice mInvoice;
|
||||
|
||||
/**
|
||||
* Invoice Credit Manager Load Constructor
|
||||
*
|
||||
* @param po MInvoice
|
||||
*/
|
||||
public CreditManagerInvoice(MInvoice po)
|
||||
{
|
||||
this.mInvoice = po;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreditStatus checkCreditStatus(String docAction)
|
||||
{
|
||||
String errorMsg = null;
|
||||
if (MInvoice.DOCACTION_Prepare.equals(docAction) && mInvoice.isSOTrx())
|
||||
{
|
||||
MDocType doc = (MDocType) mInvoice.getC_DocTypeTarget();
|
||||
// IDEMPIERE-365 - just check credit if is going to increase the debt
|
||||
if ((doc.getDocBaseType().equals(MDocType.DOCBASETYPE_ARCreditMemo) && mInvoice.getGrandTotal().signum() < 0)
|
||||
|| (doc.getDocBaseType().equals(MDocType.DOCBASETYPE_ARInvoice) && mInvoice.getGrandTotal().signum() > 0))
|
||||
{
|
||||
MBPartner bp = new MBPartner(mInvoice.getCtx(), mInvoice.getC_BPartner_ID(), mInvoice.get_TrxName());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
errorMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (MInvoice.DOCACTION_Complete.equals(docAction))
|
||||
{
|
||||
// POS supports multiple payments
|
||||
boolean fromPOS = false;
|
||||
if (mInvoice.getC_Order_ID() > 0)
|
||||
{
|
||||
fromPOS = mInvoice.getC_Order().getC_POS_ID() > 0;
|
||||
}
|
||||
// Update BP Statistics
|
||||
MBPartner bp = new MBPartner(mInvoice.getCtx(), mInvoice.getC_BPartner_ID(), mInvoice.get_TrxName());
|
||||
DB.getDatabase().forUpdate(bp, 0);
|
||||
// Update total revenue and balance / credit limit (reversed on
|
||||
// AllocationLine.processIt)
|
||||
BigDecimal invAmt = null;
|
||||
int baseCurrencyId = Env.getContextAsInt(mInvoice.getCtx(), Env.C_CURRENCY_ID);
|
||||
if (mInvoice.getC_Currency_ID() != baseCurrencyId && mInvoice.isOverrideCurrencyRate())
|
||||
{
|
||||
invAmt = mInvoice.getGrandTotal(true).multiply(mInvoice.getCurrencyRate());
|
||||
int stdPrecision = MCurrency.getStdPrecision(mInvoice.getCtx(), baseCurrencyId);
|
||||
if (invAmt.scale() > stdPrecision)
|
||||
invAmt = invAmt.setScale(stdPrecision, RoundingMode.HALF_UP);
|
||||
}
|
||||
else
|
||||
{
|
||||
invAmt = MConversionRate.convertBase( mInvoice.getCtx(),
|
||||
mInvoice.getGrandTotal(true), // CM adjusted
|
||||
mInvoice.getC_Currency_ID(),
|
||||
mInvoice.getDateAcct(),
|
||||
mInvoice.getC_ConversionType_ID(),
|
||||
mInvoice.getAD_Client_ID(),
|
||||
mInvoice.getAD_Org_ID());
|
||||
}
|
||||
if (invAmt == null)
|
||||
{
|
||||
errorMsg = MConversionRateUtil.getErrorMessage( mInvoice.getCtx(),
|
||||
"ErrorConvertingCurrencyToBaseCurrency",
|
||||
mInvoice.getC_Currency_ID(),
|
||||
MClient.get(mInvoice.getCtx()).getC_Currency_ID(),
|
||||
mInvoice.getC_ConversionType_ID(),
|
||||
mInvoice.getDateAcct(),
|
||||
mInvoice.get_TrxName());
|
||||
}
|
||||
// Total Balance
|
||||
BigDecimal newBalance = bp.getTotalOpenBalance();
|
||||
if (newBalance == null)
|
||||
newBalance = Env.ZERO;
|
||||
if (mInvoice.isSOTrx())
|
||||
{
|
||||
newBalance = newBalance.add(invAmt);
|
||||
//
|
||||
if (bp.getFirstSale() == null)
|
||||
bp.setFirstSale(mInvoice.getDateInvoiced());
|
||||
|
||||
BigDecimal newLifeAmt = bp.getActualLifeTimeValue();
|
||||
if (newLifeAmt == null)
|
||||
newLifeAmt = invAmt;
|
||||
else
|
||||
newLifeAmt = newLifeAmt.add(invAmt);
|
||||
|
||||
BigDecimal newCreditAmt = bp.getSO_CreditUsed();
|
||||
if (newCreditAmt == null)
|
||||
newCreditAmt = invAmt;
|
||||
else
|
||||
newCreditAmt = newCreditAmt.add(invAmt);
|
||||
//
|
||||
if (log.isLoggable(Level.FINE))
|
||||
log.fine( "GrandTotal=" + mInvoice.getGrandTotal(true) + "(" + invAmt
|
||||
+ ") BP Life=" + bp.getActualLifeTimeValue() + "->" + newLifeAmt
|
||||
+ ", Credit=" + bp.getSO_CreditUsed() + "->" + newCreditAmt
|
||||
+ ", Balance=" + bp.getTotalOpenBalance() + " -> " + newBalance);
|
||||
bp.setActualLifeTimeValue(newLifeAmt);
|
||||
bp.setSO_CreditUsed(newCreditAmt);
|
||||
} // SO
|
||||
else
|
||||
{
|
||||
newBalance = newBalance.subtract(invAmt);
|
||||
if (log.isLoggable(Level.FINE))
|
||||
log.fine( "GrandTotal=" + mInvoice.getGrandTotal(true) + "(" + invAmt
|
||||
+ ") Balance=" + bp.getTotalOpenBalance() + " -> " + newBalance);
|
||||
}
|
||||
// the payment just created already updated the open balance
|
||||
if (!(MInvoice.PAYMENTRULE_Cash.equals(mInvoice.getPaymentRule()) && !fromPOS))
|
||||
{
|
||||
bp.setTotalOpenBalance(newBalance);
|
||||
}
|
||||
bp.setSOCreditStatus();
|
||||
if (!bp.save(mInvoice.get_TrxName()))
|
||||
{
|
||||
errorMsg = "Could not update Business Partner";
|
||||
}
|
||||
}
|
||||
return new CreditStatus(errorMsg, !Util.isEmpty(errorMsg));
|
||||
} // creditCheck
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model.credit;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MConversionRate;
|
||||
import org.compiere.model.MDocType;
|
||||
import org.compiere.model.MOrder;
|
||||
import org.compiere.model.MSysConfig;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* Credit Manager for Order
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since June 25, 2023
|
||||
*/
|
||||
public class CreditManagerOrder implements ICreditManager
|
||||
{
|
||||
|
||||
private MOrder order;
|
||||
|
||||
/**
|
||||
* Order Credit Manager Load Constructor
|
||||
*
|
||||
* @param po MOrder
|
||||
*/
|
||||
public CreditManagerOrder(MOrder po)
|
||||
{
|
||||
this.order = po;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreditStatus checkCreditStatus(String docAction)
|
||||
{
|
||||
String errorMsg = null;
|
||||
if (MOrder.DOCACTION_Prepare.equals(docAction) && order.isSOTrx())
|
||||
{
|
||||
Properties ctx = order.getCtx();
|
||||
MDocType dt = MDocType.get(ctx, order.getC_DocTypeTarget_ID());
|
||||
if (MDocType.DOCSUBTYPESO_POSOrder.equals(dt.getDocSubTypeSO())
|
||||
&& MOrder.PAYMENTRULE_Cash.equals(order.getPaymentRule())
|
||||
&& !MSysConfig.getBooleanValue(MSysConfig.CHECK_CREDIT_ON_CASH_POS_ORDER, true, order.getAD_Client_ID(), order.getAD_Org_ID()))
|
||||
{
|
||||
// ignore -- don't validate for Cash POS Orders depending on sysconfig parameter
|
||||
}
|
||||
else if (MDocType.DOCSUBTYPESO_PrepayOrder.equals(dt.getDocSubTypeSO())
|
||||
&& !MSysConfig.getBooleanValue(MSysConfig.CHECK_CREDIT_ON_PREPAY_ORDER, true, order.getAD_Client_ID(), order.getAD_Org_ID()))
|
||||
{
|
||||
// ignore -- don't validate Prepay Orders depending on sysconfig parameter
|
||||
}
|
||||
else
|
||||
{
|
||||
// bill bp is guaranteed on beforeSave
|
||||
MBPartner bp = new MBPartner(ctx, order.getBill_BPartner_ID(), order.get_TrxName());
|
||||
// IDEMPIERE-365 - just check credit if is going to increase the debt
|
||||
if (order.getGrandTotal().signum() > 0)
|
||||
{
|
||||
if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
errorMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
errorMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
|
||||
BigDecimal grandTotal = MConversionRate.convertBase(ctx, order.getGrandTotal(), order.getC_Currency_ID(),
|
||||
order.getDateOrdered(), order.getC_ConversionType_ID(),
|
||||
order.getAD_Client_ID(), order.getAD_Org_ID());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(grandTotal)))
|
||||
{
|
||||
errorMsg = "@BPartnerOverOCreditHold@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @GrandTotal@=" + grandTotal
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new CreditStatus(errorMsg, !Util.isEmpty(errorMsg));
|
||||
} // creditCheck
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.compiere.model.credit;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.adempiere.base.CreditStatus;
|
||||
import org.adempiere.base.ICreditManager;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MClient;
|
||||
import org.compiere.model.MConversionRate;
|
||||
import org.compiere.model.MConversionRateUtil;
|
||||
import org.compiere.model.MPayment;
|
||||
import org.compiere.model.MPaymentAllocate;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
* Credit Manager for Payment
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since June 25, 2023
|
||||
*/
|
||||
public class CreditManagerPayment implements ICreditManager
|
||||
{
|
||||
private MPayment payment;
|
||||
|
||||
/**
|
||||
* Payment Credit Manager Load Constructor
|
||||
*
|
||||
* @param po MPayment
|
||||
*/
|
||||
public CreditManagerPayment(MPayment po)
|
||||
{
|
||||
this.payment = po;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CreditStatus checkCreditStatus(String docAction)
|
||||
{
|
||||
String errorMsg = null;
|
||||
if (MPayment.DOCACTION_Prepare.equals(docAction) && !payment.isReceipt())
|
||||
{ // Do not pay when Credit Stop/Hold and issue refund to customer
|
||||
MBPartner bp = new MBPartner(payment.getCtx(), payment.getC_BPartner_ID(), payment.get_TrxName());
|
||||
if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
errorMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus()))
|
||||
{
|
||||
errorMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" + bp.getTotalOpenBalance()
|
||||
+ ", @SO_CreditLimit@=" + bp.getSO_CreditLimit();
|
||||
}
|
||||
}
|
||||
else if (MPayment.DOCACTION_Complete.equals(docAction))
|
||||
{
|
||||
// Charge Handling
|
||||
boolean createdAllocationRecords = false;
|
||||
if (payment.getC_Charge_ID() == 0)
|
||||
{
|
||||
createdAllocationRecords = payment.allocateIt(); // Create Allocation Records
|
||||
payment.testAllocation();
|
||||
}
|
||||
// Update BP for Prepayments
|
||||
if (payment.getC_BPartner_ID() != 0
|
||||
&& payment.getC_Invoice_ID() == 0
|
||||
&& payment.getC_Charge_ID() == 0
|
||||
&& MPaymentAllocate.get(payment).length == 0
|
||||
&& !createdAllocationRecords)
|
||||
{
|
||||
Properties ctx = payment.getCtx();
|
||||
MBPartner bp = new MBPartner(ctx, payment.getC_BPartner_ID(), payment.get_TrxName());
|
||||
DB.getDatabase().forUpdate(bp, 0);
|
||||
// Update total balance to include this payment
|
||||
BigDecimal payAmt = null;
|
||||
int baseCurrencyId = Env.getContextAsInt(ctx, Env.C_CURRENCY_ID);
|
||||
if (payment.getC_Currency_ID() != baseCurrencyId && payment.isOverrideCurrencyRate())
|
||||
{
|
||||
payAmt = payment.getConvertedAmt();
|
||||
}
|
||||
else
|
||||
{
|
||||
payAmt = MConversionRate.convertBase( ctx, payment.getPayAmt(),
|
||||
payment.getC_Currency_ID(),
|
||||
payment.getDateAcct(),
|
||||
payment.getC_ConversionType_ID(),
|
||||
payment.getAD_Client_ID(),
|
||||
payment.getAD_Org_ID());
|
||||
|
||||
if (payAmt == null)
|
||||
{
|
||||
errorMsg = MConversionRateUtil.getErrorMessage( ctx, "ErrorConvertingCurrencyToBaseCurrency",
|
||||
payment.getC_Currency_ID(),
|
||||
MClient.get(ctx).getC_Currency_ID(),
|
||||
payment.getC_ConversionType_ID(),
|
||||
payment.getDateAcct(), payment.get_TrxName());
|
||||
}
|
||||
}
|
||||
// Total Balance
|
||||
BigDecimal newBalance = bp.getTotalOpenBalance();
|
||||
if (newBalance == null)
|
||||
newBalance = Env.ZERO;
|
||||
if (payment.isReceipt())
|
||||
newBalance = newBalance.subtract(payAmt);
|
||||
else
|
||||
newBalance = newBalance.add(payAmt);
|
||||
|
||||
bp.setTotalOpenBalance(newBalance);
|
||||
bp.setSOCreditStatus();
|
||||
bp.saveEx();
|
||||
}
|
||||
}
|
||||
else if (MPayment.DOCACTION_Reverse_Accrual.equals(docAction) || MPayment.DOCACTION_Reverse_Correct.equals(docAction))
|
||||
{
|
||||
if (payment.getC_BPartner_ID() != 0)
|
||||
{
|
||||
MBPartner bp = new MBPartner(payment.getCtx(), payment.getC_BPartner_ID(), payment.get_TrxName());
|
||||
bp.setTotalOpenBalance();
|
||||
bp.saveEx(payment.get_TrxName());
|
||||
}
|
||||
}
|
||||
return new CreditStatus(errorMsg, !Util.isEmpty(errorMsg));
|
||||
} // creditCheck
|
||||
}
|
|
@ -121,12 +121,12 @@ public class InOutTest extends AbstractTestCase {
|
|||
try {
|
||||
MOrder order = createPurchaseOrder(bpartner, currentDate, priceList.getM_PriceList_ID(), Company_ConversionType_ID);
|
||||
BigDecimal qtyOrdered = new BigDecimal(500);
|
||||
MOrderLine orderLine = createPurchaseOrderLine(order, 10, product, qtyOrdered, priceInAud);
|
||||
MOrderLine orderLine = createOrderLine(order, 10, product, qtyOrdered, priceInAud);
|
||||
completeDocument(order);
|
||||
|
||||
MInOut receipt = createMMReceipt(order, currentDate);
|
||||
BigDecimal qtyDelivered = new BigDecimal(500);
|
||||
MInOutLine receiptLine = createMMReceiptLine(receipt, orderLine, qtyDelivered);
|
||||
MInOutLine receiptLine = createInOutLine(receipt, orderLine, qtyDelivered);
|
||||
completeDocument(receipt);
|
||||
postDocument(receipt);
|
||||
|
||||
|
@ -162,11 +162,11 @@ public class InOutTest extends AbstractTestCase {
|
|||
}
|
||||
|
||||
order = createPurchaseOrder(bpartner, currentDate, priceList.getM_PriceList_ID(), Spot_ConversionType_ID);
|
||||
orderLine = createPurchaseOrderLine(order, 10, product, qtyOrdered, priceInAud);
|
||||
orderLine = createOrderLine(order, 10, product, qtyOrdered, priceInAud);
|
||||
completeDocument(order);
|
||||
|
||||
receipt = createMMReceipt(order, currentDate);
|
||||
receiptLine = createMMReceiptLine(receipt, orderLine, qtyDelivered);
|
||||
receiptLine = createInOutLine(receipt, orderLine, qtyDelivered);
|
||||
completeDocument(receipt);
|
||||
postDocument(receipt);
|
||||
|
||||
|
@ -251,12 +251,12 @@ public class InOutTest extends AbstractTestCase {
|
|||
try {
|
||||
MOrder order = createPurchaseOrder(bpartner, currentDate, priceList.getM_PriceList_ID(), Company_ConversionType_ID);
|
||||
BigDecimal qtyOrdered = BigDecimal.TEN;
|
||||
MOrderLine orderLine = createPurchaseOrderLine(order, 10, product, qtyOrdered, priceInAud);
|
||||
MOrderLine orderLine = createOrderLine(order, 10, product, qtyOrdered, priceInAud);
|
||||
completeDocument(order);
|
||||
|
||||
MInOut receipt = createMMReceipt(order, currentDate);
|
||||
BigDecimal qtyDelivered = BigDecimal.TEN;
|
||||
MInOutLine receiptLine = createMMReceiptLine(receipt, orderLine, qtyDelivered);
|
||||
MInOutLine receiptLine = createInOutLine(receipt, orderLine, qtyDelivered);
|
||||
completeDocument(receipt);
|
||||
postDocument(receipt);
|
||||
|
||||
|
@ -384,22 +384,35 @@ public class InOutTest extends AbstractTestCase {
|
|||
ConversionRateHelper.deleteConversionRate(cr);
|
||||
}
|
||||
|
||||
private MOrder createPurchaseOrder(MBPartner bpartner, Timestamp date, int M_PriceList_ID, int C_ConversionType_ID) {
|
||||
private MOrder createPurchaseOrder(MBPartner bpartner, Timestamp date, int M_PriceList_ID, int C_ConversionType_ID)
|
||||
{
|
||||
return createOrder(bpartner, date, M_PriceList_ID, C_ConversionType_ID, false);
|
||||
}
|
||||
|
||||
private MOrder createSalseOrder(MBPartner bpartner, Timestamp date, int M_PriceList_ID, int C_ConversionType_ID)
|
||||
{
|
||||
return createOrder(bpartner, date, M_PriceList_ID, C_ConversionType_ID, true);
|
||||
}
|
||||
|
||||
private MOrder createOrder(MBPartner bpartner, Timestamp date, int M_PriceList_ID, int C_ConversionType_ID, boolean isSOTrx)
|
||||
{
|
||||
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
|
||||
order.setAD_Org_ID(DictionaryIDs.AD_Org.HQ.id);
|
||||
order.setBPartner(bpartner);
|
||||
order.setIsSOTrx(false);
|
||||
order.setIsSOTrx(isSOTrx);
|
||||
order.setC_DocTypeTarget_ID();
|
||||
order.setDateOrdered(date);
|
||||
order.setDateAcct(date);
|
||||
order.setM_PriceList_ID(M_PriceList_ID);
|
||||
order.setC_ConversionType_ID(C_ConversionType_ID);
|
||||
order.setM_Warehouse_ID(DictionaryIDs.M_Warehouse.HQ.id);
|
||||
order.setDocStatus(DocAction.STATUS_Drafted);
|
||||
order.setDocAction(DocAction.ACTION_Complete);
|
||||
order.saveEx();
|
||||
return order;
|
||||
}
|
||||
|
||||
private MOrderLine createPurchaseOrderLine(MOrder order, int line, MProduct product, BigDecimal qty, BigDecimal price) {
|
||||
private MOrderLine createOrderLine(MOrder order, int line, MProduct product, BigDecimal qty, BigDecimal price) {
|
||||
MOrderLine orderLine = new MOrderLine(order);
|
||||
orderLine.setLine(line);
|
||||
orderLine.setProduct(product);
|
||||
|
@ -415,13 +428,20 @@ public class InOutTest extends AbstractTestCase {
|
|||
return receipt;
|
||||
}
|
||||
|
||||
private MInOutLine createMMReceiptLine(MInOut receipt, MOrderLine orderLine, BigDecimal qty) {
|
||||
MInOutLine receiptLine = new MInOutLine(receipt);
|
||||
|
||||
private MInOut createShipment(MOrder order, Timestamp date) {
|
||||
MInOut receipt = new MInOut(order, DictionaryIDs.C_DocType.MM_SHIPMENT.id, date); // MM Shipment
|
||||
receipt.saveEx();
|
||||
return receipt;
|
||||
}
|
||||
|
||||
private MInOutLine createInOutLine(MInOut mInOut, MOrderLine orderLine, BigDecimal qty) {
|
||||
MInOutLine receiptLine = new MInOutLine(mInOut);
|
||||
receiptLine.setC_OrderLine_ID(orderLine.get_ID());
|
||||
receiptLine.setLine(orderLine.getLine());
|
||||
receiptLine.setProduct(orderLine.getProduct());
|
||||
receiptLine.setQty(qty);
|
||||
MWarehouse wh = MWarehouse.get(Env.getCtx(), receipt.getM_Warehouse_ID());
|
||||
MWarehouse wh = MWarehouse.get(Env.getCtx(), mInOut.getM_Warehouse_ID());
|
||||
int M_Locator_ID = wh.getDefaultLocator().getM_Locator_ID();
|
||||
receiptLine.setM_Locator_ID(M_Locator_ID);
|
||||
receiptLine.saveEx();
|
||||
|
@ -500,4 +520,46 @@ public class InOutTest extends AbstractTestCase {
|
|||
assertEquals(shipperAccount, inout.getShipperAccount(), "Unexpected shipper account");
|
||||
assertEquals(MInOut.FREIGHTCHARGES_Collect, inout.getFreightCharges(), "Unexpected freight charges rule");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for Credit Check
|
||||
*/
|
||||
@Test
|
||||
public void testCreditCheckInOut()
|
||||
{
|
||||
MBPartner bpartner = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.TREE_FARM.id, getTrxName());
|
||||
bpartner.setSOCreditStatus(MBPartner.SOCREDITSTATUS_NoCreditCheck);
|
||||
bpartner.saveEx();
|
||||
|
||||
MProduct product = MProduct.get(Env.getCtx(), DictionaryIDs.M_Product.ELM.id);
|
||||
Timestamp currentDate = Env.getContextAsDate(Env.getCtx(), "#Date");
|
||||
|
||||
MOrder order = createSalseOrder(bpartner, currentDate, DictionaryIDs.M_PriceList.STANDARD.id, DictionaryIDs.C_ConversionType.COMPANY.id);
|
||||
MOrderLine orderLine = createOrderLine(order, 10, product, new BigDecimal(500), new BigDecimal(23.32));
|
||||
completeDocument(order);
|
||||
|
||||
MInOut receipt = createShipment(order, currentDate);
|
||||
BigDecimal qtyDelivered = new BigDecimal(500);
|
||||
createInOutLine(receipt, orderLine, qtyDelivered);
|
||||
|
||||
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Prepare);
|
||||
receipt.load(getTrxName());
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_InProgress, receipt.getDocStatus());
|
||||
|
||||
bpartner.setSOCreditStatus(MBPartner.SOCREDITSTATUS_CreditStop);
|
||||
bpartner.saveEx();
|
||||
|
||||
receipt.load(getTrxName());
|
||||
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Prepare);
|
||||
assertTrue(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Invalid, receipt.getDocStatus());
|
||||
|
||||
bpartner.setSOCreditStatus(MBPartner.SOCREDITSTATUS_CreditHold);
|
||||
bpartner.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(receipt, DocAction.ACTION_Prepare);
|
||||
assertTrue(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Invalid, receipt.getDocStatus());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/******************************************************************************
|
||||
* Copyright (C) 2016 Logilite Technologies LLP *
|
||||
* This program is free software; you can redistribute it and/or modify it *
|
||||
* under the terms version 2 of the GNU General Public License as published *
|
||||
* by the Free Software Foundation. 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., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||
*****************************************************************************/
|
||||
package org.idempiere.test.base;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MInvoice;
|
||||
import org.compiere.model.MInvoiceLine;
|
||||
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.idempiere.test.DictionaryIDs;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Invoice Test cases.
|
||||
*
|
||||
* @author Logilite Technologies
|
||||
* @since August 07, 2023
|
||||
*/
|
||||
public class InvoiceTest extends AbstractTestCase
|
||||
{
|
||||
|
||||
public InvoiceTest()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for Credit Check
|
||||
*/
|
||||
@Test
|
||||
public void testCreditCheckInvoice()
|
||||
{
|
||||
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
|
||||
// Joe Block
|
||||
MBPartner bp = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.JOE_BLOCK.id, getTrxName());
|
||||
bp.setSOCreditStatus(MBPartner.SOCREDITSTATUS_CreditStop);
|
||||
bp.saveEx();
|
||||
|
||||
MInvoice invoice = new MInvoice(Env.getCtx(), 0, getTrxName());
|
||||
invoice.setBPartner(bp);
|
||||
invoice.setAD_Org_ID(DictionaryIDs.AD_Org.HQ.id);
|
||||
invoice.setC_DocTypeTarget_ID(MInvoice.DOCBASETYPE_ARInvoice);
|
||||
invoice.setDateInvoiced(today);
|
||||
invoice.setDateAcct(today);
|
||||
invoice.setM_PriceList_ID(DictionaryIDs.M_PriceList.STANDARD.id);
|
||||
invoice.setPaymentRule(MInvoice.PAYMENTRULE_OnCredit);
|
||||
invoice.saveEx();
|
||||
|
||||
MInvoiceLine invoiceLine = new MInvoiceLine(Env.getCtx(), 0, getTrxName());
|
||||
invoiceLine.setInvoice(invoice);
|
||||
invoiceLine.setC_Invoice_ID(invoice.getC_Invoice_ID());
|
||||
invoiceLine.setAD_Org_ID(DictionaryIDs.AD_Org.HQ.id);
|
||||
invoiceLine.setLine(10);
|
||||
invoiceLine.setProduct(MProduct.get(Env.getCtx(), DictionaryIDs.M_Product.FERTILIZER_50.id));
|
||||
invoiceLine.setQty(new BigDecimal("1"));
|
||||
invoiceLine.saveEx();
|
||||
|
||||
invoice.load(getTrxName());
|
||||
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Prepare);
|
||||
assertTrue(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Invalid, invoice.getDocStatus());
|
||||
|
||||
bp.setSOCreditStatus(MBPartner.SOCREDITSTATUS_NoCreditCheck);
|
||||
bp.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(invoice, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Completed, invoice.getDocStatus());
|
||||
}
|
||||
}
|
|
@ -25,12 +25,21 @@
|
|||
package org.idempiere.test.model;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MPayment;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.ProcessInfo;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.TimeUtil;
|
||||
import org.compiere.util.Util;
|
||||
import org.compiere.wf.MWorkflow;
|
||||
import org.idempiere.test.AbstractTestCase;
|
||||
import org.idempiere.test.DictionaryIDs;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -63,4 +72,44 @@ public class PaymentTest extends AbstractTestCase {
|
|||
payment.saveEx();
|
||||
assertTrue(Util.isEmpty(payment.getCreditCardVV()), "Credit card verification code not clear after change of tender type: "+payment.getCreditCardVV());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for Credit Check
|
||||
*/
|
||||
@Test
|
||||
public void testCreditCheckPayment()
|
||||
{
|
||||
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
|
||||
// Joe Block
|
||||
MBPartner bp = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.JOE_BLOCK.id, getTrxName());
|
||||
bp.setSOCreditStatus(MBPartner.SOCREDITSTATUS_CreditStop);
|
||||
bp.saveEx();
|
||||
|
||||
MPayment payment = new MPayment(Env.getCtx(), 0, getTrxName());
|
||||
payment.setC_BPartner_ID(bp.getC_BPartner_ID());
|
||||
payment.setC_BankAccount_ID(DictionaryIDs.C_BankAccount.HQ_POS_CASH.id);
|
||||
payment.setC_Currency_ID(DictionaryIDs.C_Currency.USD.id);
|
||||
payment.setAD_Org_ID(DictionaryIDs.AD_Org.HQ.id);
|
||||
payment.setC_DocType_ID(false);
|
||||
payment.setDateTrx(today);
|
||||
payment.setPayAmt(new BigDecimal(1000));
|
||||
payment.setDateAcct(today);
|
||||
payment.saveEx();
|
||||
|
||||
payment.load(getTrxName());
|
||||
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(payment, DocAction.ACTION_Prepare);
|
||||
assertTrue(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Invalid, payment.getDocStatus());
|
||||
|
||||
bp.setSOCreditStatus(MBPartner.SOCREDITSTATUS_NoCreditCheck);
|
||||
bp.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(payment, DocAction.ACTION_Complete);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Completed, payment.getDocStatus());
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(payment, DocAction.ACTION_Reverse_Accrual);
|
||||
assertFalse(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Reversed, payment.getDocStatus());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1596,4 +1596,48 @@ public class SalesOrderTest extends AbstractTestCase {
|
|||
assertFalse(pi.isError(), pi.getSummary());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test cases for Credit Check
|
||||
*/
|
||||
@Test
|
||||
public void testCreditCheckOrder()
|
||||
{
|
||||
Timestamp today = TimeUtil.getDay(System.currentTimeMillis());
|
||||
// Joe Block
|
||||
MBPartner bp = MBPartner.get(Env.getCtx(), DictionaryIDs.C_BPartner.JOE_BLOCK.id, getTrxName());
|
||||
bp.setSOCreditStatus(MBPartner.SOCREDITSTATUS_CreditHold);
|
||||
bp.saveEx();
|
||||
|
||||
// test 2 - credit Check
|
||||
MOrder order = new MOrder(Env.getCtx(), 0, getTrxName());
|
||||
order.setM_Warehouse_ID(DictionaryIDs.AD_Org.HQ.id);
|
||||
order.setBPartner(bp);
|
||||
order.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard);
|
||||
order.setDeliveryRule(MOrder.DELIVERYRULE_Availability);
|
||||
order.setM_Warehouse_ID(DictionaryIDs.M_Warehouse.HQ.id);
|
||||
order.setDocStatus(DocAction.STATUS_Drafted);
|
||||
order.setDocAction(DocAction.ACTION_Prepare);
|
||||
order.setDatePromised(today);
|
||||
order.saveEx();
|
||||
|
||||
MOrderLine line1 = new MOrderLine(order);
|
||||
line1.setLine(10);
|
||||
// Azalea Bush
|
||||
line1.setProduct(MProduct.get(Env.getCtx(), DictionaryIDs.M_Product.AZALEA_BUSH.id));
|
||||
line1.setQty(new BigDecimal("1"));
|
||||
line1.setDatePromised(today);
|
||||
line1.saveEx();
|
||||
|
||||
order.load(getTrxName());
|
||||
ProcessInfo info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Prepare);
|
||||
assertTrue(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Invalid, order.getDocStatus());
|
||||
|
||||
bp.setSOCreditStatus(MBPartner.SOCREDITSTATUS_CreditStop);
|
||||
bp.saveEx();
|
||||
|
||||
info = MWorkflow.runDocumentActionWorkflow(order, DocAction.ACTION_Prepare);
|
||||
assertTrue(info.isError(), info.getSummary());
|
||||
assertEquals(DocAction.STATUS_Invalid, order.getDocStatus());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue