lock Trx when you try created a Payment Allocation

http://sourceforge.net/tracker/?func=detail&aid=2792529&group_id=176962&atid=879332
This commit is contained in:
vpj-cd 2009-05-16 00:58:54 +00:00
parent d5e6e6a596
commit 177abceb8b
1 changed files with 199 additions and 194 deletions

View File

@ -47,6 +47,7 @@ import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel; import javax.swing.table.TableModel;
import org.adempiere.exceptions.AdempiereException;
import org.adempiere.plaf.AdempierePLAF; import org.adempiere.plaf.AdempierePLAF;
import org.compiere.apps.ADialog; import org.compiere.apps.ADialog;
import org.compiere.apps.StatusBar; import org.compiere.apps.StatusBar;
@ -72,12 +73,16 @@ import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg; import org.compiere.util.Msg;
import org.compiere.util.TimeUtil; import org.compiere.util.TimeUtil;
import org.compiere.util.Trx; import org.compiere.util.Trx;
import org.compiere.util.TrxRunnable;
import org.compiere.util.Util; import org.compiere.util.Util;
/** /**
* Allocation Form * Allocation Form
* *
* @author Jorg Janke * @author Jorg Janke
* @author Victor Perez, e-Evolucion
* <li> [2792529] lockTrx when you try created a Payment Allocation
* <li> https://sourceforge.net/tracker/?func=detail&aid=2792529&group_id=176962&atid=879332
* @version $Id: VAllocation.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $ * @version $Id: VAllocation.java,v 1.2 2006/07/30 00:51:28 jjanke Exp $
* *
* Contributor : Fabian Aguilar - OFBConsulting - Multiallocation * Contributor : Fabian Aguilar - OFBConsulting - Multiallocation
@ -933,207 +938,207 @@ public class VAllocation extends CPanel
{ {
if (m_noInvoices + m_noPayments == 0) if (m_noInvoices + m_noPayments == 0)
return; return;
// fixed fields
int AD_Client_ID = Env.getContextAsInt(Env.getCtx(), m_WindowNo, "AD_Client_ID");
int AD_Org_ID = Env.getContextAsInt(Env.getCtx(), m_WindowNo, "AD_Org_ID");
int C_BPartner_ID = m_C_BPartner_ID;
int C_Order_ID = 0;
int C_CashLine_ID = 0;
Timestamp DateTrx = (Timestamp)dateField.getValue();
int C_Currency_ID = m_C_Currency_ID; // the allocation currency
//
if (AD_Org_ID == 0)
{
ADialog.error(m_WindowNo, this, "Org0NotAllowed", null);
return;
}
//
log.config("Client=" + AD_Client_ID + ", Org=" + AD_Org_ID
+ ", BPartner=" + C_BPartner_ID + ", Date=" + DateTrx);
Trx trx = Trx.get(Trx.createTrxName("AL"), true); try
// Payment - Loop and add them to paymentList/amountList
int pRows = paymentTable.getRowCount();
TableModel payment = paymentTable.getModel();
ArrayList<Integer> paymentList = new ArrayList<Integer>(pRows);
ArrayList<BigDecimal> amountList = new ArrayList<BigDecimal>(pRows);
BigDecimal paymentAppliedAmt = Env.ZERO;
for (int i = 0; i < pRows; i++)
{ {
// Payment line is selected Trx.run(new TrxRunnable()
if (((Boolean)payment.getValueAt(i, 0)).booleanValue())
{ {
KeyNamePair pp = (KeyNamePair)payment.getValueAt(i, 2); // Value public void run(String trxName)
// Payment variables
int C_Payment_ID = pp.getKey();
paymentList.add(new Integer(C_Payment_ID));
//
BigDecimal PaymentAmt = (BigDecimal)payment.getValueAt(i, i_payment); // Applied Payment
amountList.add(PaymentAmt);
//
paymentAppliedAmt = paymentAppliedAmt.add(PaymentAmt);
//
log.fine("C_Payment_ID=" + C_Payment_ID
+ " - PaymentAmt=" + PaymentAmt); // + " * " + Multiplier + " = " + PaymentAmtAbs);
}
}
log.config("Number of Payments=" + paymentList.size() + " - Total=" + paymentAppliedAmt);
// Invoices - Loop and generate allocations
int iRows = invoiceTable.getRowCount();
TableModel invoice = invoiceTable.getModel();
// Create Allocation
MAllocationHdr alloc = new MAllocationHdr (Env.getCtx(), true, // manual
DateTrx, C_Currency_ID, Env.getContext(Env.getCtx(), "#AD_User_Name"), trx.getTrxName());
alloc.setAD_Org_ID(AD_Org_ID);
if (!alloc.save())
{
log.log(Level.SEVERE, "Allocation not created");
return;
}
// For all invoices
int invoiceLines = 0;
BigDecimal unmatchedApplied = Env.ZERO;
for (int i = 0; i < iRows; i++)
{
// Invoice line is selected
if (((Boolean)invoice.getValueAt(i, 0)).booleanValue())
{
invoiceLines++;
KeyNamePair pp = (KeyNamePair)invoice.getValueAt(i, 2); // Value
// Invoice variables
int C_Invoice_ID = pp.getKey();
BigDecimal AppliedAmt = (BigDecimal)invoice.getValueAt(i, i_applied);
// semi-fixed fields (reset after first invoice)
BigDecimal DiscountAmt = (BigDecimal)invoice.getValueAt(i, i_discount);
BigDecimal WriteOffAmt = (BigDecimal)invoice.getValueAt(i, i_writeOff);
// OverUnderAmt needs to be in Allocation Currency
BigDecimal OverUnderAmt = ((BigDecimal)invoice.getValueAt(i, i_open))
.subtract(AppliedAmt).subtract(DiscountAmt).subtract(WriteOffAmt);
log.config("Invoice #" + i + " - AppliedAmt=" + AppliedAmt);// + " -> " + AppliedAbs);
// loop through all payments until invoice applied
for (int j = 0; j < paymentList.size() && AppliedAmt.signum() != 0; j++)
{ {
int C_Payment_ID = ((Integer)paymentList.get(j)).intValue(); // fixed fields
BigDecimal PaymentAmt = (BigDecimal)amountList.get(j); int AD_Client_ID = Env.getContextAsInt(Env.getCtx(), m_WindowNo, "AD_Client_ID");
if (PaymentAmt.signum() == AppliedAmt.signum()) // only match same sign (otherwise appliedAmt increases) int AD_Org_ID = Env.getContextAsInt(Env.getCtx(), m_WindowNo, "AD_Org_ID");
{ // and not zero (appliedAmt was checked earlier) int C_BPartner_ID = m_C_BPartner_ID;
log.config(".. with payment #" + j + ", Amt=" + PaymentAmt); int C_Order_ID = 0;
int C_CashLine_ID = 0;
BigDecimal amount = AppliedAmt; Timestamp DateTrx = (Timestamp)dateField.getValue();
if (amount.abs().compareTo(PaymentAmt.abs()) > 0) // if there's more open on the invoice int C_Currency_ID = m_C_Currency_ID; // the allocation currency
amount = PaymentAmt; // than left in the payment //
if (AD_Org_ID == 0)
// Allocation Line {
MAllocationLine aLine = new MAllocationLine (alloc, amount, //ADialog.error(m_WindowNo, this, "Org0NotAllowed", null);
DiscountAmt, WriteOffAmt, OverUnderAmt); new AdempiereException("@Org0NotAllowed@");
aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID); }
aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID); //
if (!aLine.save()) log.config("Client=" + AD_Client_ID + ", Org=" + AD_Org_ID
log.log(Level.SEVERE, "Allocation Line not written - Invoice=" + C_Invoice_ID); + ", BPartner=" + C_BPartner_ID + ", Date=" + DateTrx);
// Apply Discounts and WriteOff only first time // Payment - Loop and add them to paymentList/amountList
DiscountAmt = Env.ZERO; int pRows = paymentTable.getRowCount();
WriteOffAmt = Env.ZERO; TableModel payment = paymentTable.getModel();
// subtract amount from Payment/Invoice ArrayList<Integer> paymentList = new ArrayList<Integer>(pRows);
AppliedAmt = AppliedAmt.subtract(amount); ArrayList<BigDecimal> amountList = new ArrayList<BigDecimal>(pRows);
PaymentAmt = PaymentAmt.subtract(amount); BigDecimal paymentAppliedAmt = Env.ZERO;
log.fine("Allocation Amount=" + amount + " - Remaining Applied=" + AppliedAmt + ", Payment=" + PaymentAmt); for (int i = 0; i < pRows; i++)
amountList.set(j, PaymentAmt); // update {
} // for all applied amounts // Payment line is selected
} // loop through payments for invoice if (((Boolean)payment.getValueAt(i, 0)).booleanValue())
{
if ( AppliedAmt.signum() == 0 && DiscountAmt.signum() == 0 && WriteOffAmt.signum() == 0) KeyNamePair pp = (KeyNamePair)payment.getValueAt(i, 2); // Value
continue; // Payment variables
else { // remainder will need to match against other invoices int C_Payment_ID = pp.getKey();
int C_Payment_ID = 0; paymentList.add(new Integer(C_Payment_ID));
//
BigDecimal PaymentAmt = (BigDecimal)payment.getValueAt(i, i_payment); // Applied Payment
amountList.add(PaymentAmt);
//
paymentAppliedAmt = paymentAppliedAmt.add(PaymentAmt);
//
log.fine("C_Payment_ID=" + C_Payment_ID
+ " - PaymentAmt=" + PaymentAmt); // + " * " + Multiplier + " = " + PaymentAmtAbs);
}
}
log.config("Number of Payments=" + paymentList.size() + " - Total=" + paymentAppliedAmt);
// Invoices - Loop and generate allocations
int iRows = invoiceTable.getRowCount();
TableModel invoice = invoiceTable.getModel();
// Allocation Line // Create Allocation
MAllocationLine aLine = new MAllocationLine (alloc, AppliedAmt, MAllocationHdr alloc = new MAllocationHdr (Env.getCtx(), true, // manual
DiscountAmt, WriteOffAmt, OverUnderAmt); DateTrx, C_Currency_ID, Env.getContext(Env.getCtx(), "#AD_User_Name"), trxName);
aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID); alloc.setAD_Org_ID(AD_Org_ID);
aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID); alloc.saveEx();
if (!aLine.save(trx.getTrxName())) // For all invoices
log.log(Level.SEVERE, "Allocation Line not written - Invoice=" + C_Invoice_ID); int invoiceLines = 0;
BigDecimal unmatchedApplied = Env.ZERO;
log.fine("Allocation Amount=" + AppliedAmt); for (int i = 0; i < iRows; i++)
unmatchedApplied = unmatchedApplied.add(AppliedAmt); {
} // Invoice line is selected
} // invoice selected if (((Boolean)invoice.getValueAt(i, 0)).booleanValue())
} // invoice loop {
invoiceLines++;
// check for unapplied payment amounts (eg from payment reversals) KeyNamePair pp = (KeyNamePair)invoice.getValueAt(i, 2); // Value
for (int i = 0; i < paymentList.size(); i++) { // Invoice variables
BigDecimal payAmt = (BigDecimal) amountList.get(i); int C_Invoice_ID = pp.getKey();
if ( payAmt.signum() == 0 ) BigDecimal AppliedAmt = (BigDecimal)invoice.getValueAt(i, i_applied);
continue; // semi-fixed fields (reset after first invoice)
int C_Payment_ID = ((Integer)paymentList.get(i)).intValue(); BigDecimal DiscountAmt = (BigDecimal)invoice.getValueAt(i, i_discount);
log.fine("Payment=" + C_Payment_ID BigDecimal WriteOffAmt = (BigDecimal)invoice.getValueAt(i, i_writeOff);
+ ", Amount=" + payAmt); // OverUnderAmt needs to be in Allocation Currency
BigDecimal OverUnderAmt = ((BigDecimal)invoice.getValueAt(i, i_open))
// Allocation Line .subtract(AppliedAmt).subtract(DiscountAmt).subtract(WriteOffAmt);
MAllocationLine aLine = new MAllocationLine (alloc, payAmt,
Env.ZERO, Env.ZERO, Env.ZERO); log.config("Invoice #" + i + " - AppliedAmt=" + AppliedAmt);// + " -> " + AppliedAbs);
aLine.setDocInfo(C_BPartner_ID, 0, 0); // loop through all payments until invoice applied
aLine.setPaymentInfo(C_Payment_ID, 0);
if (!aLine.save(trx.getTrxName())) for (int j = 0; j < paymentList.size() && AppliedAmt.signum() != 0; j++)
log.log(Level.SEVERE, "Allocation Line not saved - Payment=" + C_Payment_ID); {
unmatchedApplied = unmatchedApplied.subtract(payAmt); int C_Payment_ID = ((Integer)paymentList.get(j)).intValue();
} BigDecimal PaymentAmt = (BigDecimal)amountList.get(j);
if (PaymentAmt.signum() == AppliedAmt.signum()) // only match same sign (otherwise appliedAmt increases)
if ( unmatchedApplied.signum() != 0 ) { // and not zero (appliedAmt was checked earlier)
log.log(Level.SEVERE, "Allocation not balanced -- out by " + unmatchedApplied ); log.config(".. with payment #" + j + ", Amt=" + PaymentAmt);
// Should start WF BigDecimal amount = AppliedAmt;
if (alloc.get_ID() != 0) if (amount.abs().compareTo(PaymentAmt.abs()) > 0) // if there's more open on the invoice
{ amount = PaymentAmt; // than left in the payment
alloc.processIt(DocAction.ACTION_Complete);
alloc.save(); // Allocation Line
} MAllocationLine aLine = new MAllocationLine (alloc, amount,
DiscountAmt, WriteOffAmt, OverUnderAmt);
// Test/Set IsPaid for Invoice - requires that allocation is posted aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID);
for (int i = 0; i < iRows; i++) aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID);
{ aLine.saveEx();
// Invoice line is selected
if (((Boolean)invoice.getValueAt(i, 0)).booleanValue()) // Apply Discounts and WriteOff only first time
{ DiscountAmt = Env.ZERO;
KeyNamePair pp = (KeyNamePair)invoice.getValueAt(i, 2); // Value WriteOffAmt = Env.ZERO;
// Invoice variables // subtract amount from Payment/Invoice
int C_Invoice_ID = pp.getKey(); AppliedAmt = AppliedAmt.subtract(amount);
String sql = "SELECT invoiceOpen(C_Invoice_ID, 0) " PaymentAmt = PaymentAmt.subtract(amount);
+ "FROM C_Invoice WHERE C_Invoice_ID=?"; log.fine("Allocation Amount=" + amount + " - Remaining Applied=" + AppliedAmt + ", Payment=" + PaymentAmt);
BigDecimal open = DB.getSQLValueBD(trx.getTrxName(), sql, C_Invoice_ID); amountList.set(j, PaymentAmt); // update
if (open != null && open.signum() == 0) { } // for all applied amounts
sql = "UPDATE C_Invoice SET IsPaid='Y' " } // loop through payments for invoice
+ "WHERE C_Invoice_ID=" + C_Invoice_ID;
int no = DB.executeUpdate(sql, trx.getTrxName()); if ( AppliedAmt.signum() == 0 && DiscountAmt.signum() == 0 && WriteOffAmt.signum() == 0)
log.config("Invoice #" + i + " is paid - updated=" + no); continue;
} else else { // remainder will need to match against other invoices
log.config("Invoice #" + i + " is not paid - " + open); int C_Payment_ID = 0;
}
} // Allocation Line
// Test/Set Payment is fully allocated MAllocationLine aLine = new MAllocationLine (alloc, AppliedAmt,
for (int i = 0; i < paymentList.size(); i++) DiscountAmt, WriteOffAmt, OverUnderAmt);
{ aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID);
int C_Payment_ID = ((Integer)paymentList.get(i)).intValue(); aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID);
MPayment pay = new MPayment (Env.getCtx(), C_Payment_ID, trx.getTrxName()); aLine.saveEx();
if (pay.testAllocation()) log.fine("Allocation Amount=" + AppliedAmt);
pay.save(); unmatchedApplied = unmatchedApplied.add(AppliedAmt);
log.config("Payment #" + i + (pay.isAllocated() ? " not" : " is") }
+ " fully allocated"); } // invoice selected
} } // invoice loop
paymentList.clear();
amountList.clear(); // check for unapplied payment amounts (eg from payment reversals)
trx.commit(); for (int i = 0; i < paymentList.size(); i++) {
trx.close(); BigDecimal payAmt = (BigDecimal) amountList.get(i);
if ( payAmt.signum() == 0 )
continue;
int C_Payment_ID = ((Integer)paymentList.get(i)).intValue();
log.fine("Payment=" + C_Payment_ID
+ ", Amount=" + payAmt);
// Allocation Line
MAllocationLine aLine = new MAllocationLine (alloc, payAmt,
Env.ZERO, Env.ZERO, Env.ZERO);
aLine.setDocInfo(C_BPartner_ID, 0, 0);
aLine.setPaymentInfo(C_Payment_ID, 0);
aLine.saveEx();
unmatchedApplied = unmatchedApplied.subtract(payAmt);
}
if ( unmatchedApplied.signum() != 0 )
log.log(Level.SEVERE, "Allocation not balanced -- out by " + unmatchedApplied );
// Should start WF
if (alloc.get_ID() != 0)
{
alloc.processIt(DocAction.ACTION_Complete);
alloc.saveEx();
}
// Test/Set IsPaid for Invoice - requires that allocation is posted
for (int i = 0; i < iRows; i++)
{
// Invoice line is selected
if (((Boolean)invoice.getValueAt(i, 0)).booleanValue())
{
KeyNamePair pp = (KeyNamePair)invoice.getValueAt(i, 2); // Value
// Invoice variables
int C_Invoice_ID = pp.getKey();
String sql = "SELECT invoiceOpen(C_Invoice_ID, 0) "
+ "FROM C_Invoice WHERE C_Invoice_ID=?";
BigDecimal open = DB.getSQLValueBD(trxName, sql, C_Invoice_ID);
if (open != null && open.signum() == 0) {
sql = "UPDATE C_Invoice SET IsPaid='Y' "
+ "WHERE C_Invoice_ID=" + C_Invoice_ID;
int no = DB.executeUpdate(sql, trxName);
log.config("Invoice #" + i + " is paid - updated=" + no);
} else
log.config("Invoice #" + i + " is not paid - " + open);
}
}
// Test/Set Payment is fully allocated
for (int i = 0; i < paymentList.size(); i++)
{
int C_Payment_ID = ((Integer)paymentList.get(i)).intValue();
MPayment pay = new MPayment (Env.getCtx(), C_Payment_ID, trxName);
if (pay.testAllocation())
pay.saveEx();
log.config("Payment #" + i + (pay.isAllocated() ? " not" : " is")
+ " fully allocated");
}
paymentList.clear();
amountList.clear();
statusBar.setStatusLine(alloc.getDocumentNo()); statusBar.setStatusLine(alloc.getDocumentNo());
}});
}
catch (Exception e)
{
ADialog.error(m_WindowNo, this, "Error", e.getLocalizedMessage());
return;
}
} // saveData } // saveData