Refactor custom form - ID: 2787613
This commit is contained in:
parent
a890145e50
commit
0d919012ce
|
@ -0,0 +1,781 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2009 Low Heng Sin *
|
||||||
|
* Copyright (C) 2009 Idalica Corporation *
|
||||||
|
* 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.apps.form;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Vector;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.exceptions.AdempiereException;
|
||||||
|
import org.compiere.minigrid.IMiniTable;
|
||||||
|
import org.compiere.model.MAllocationHdr;
|
||||||
|
import org.compiere.model.MAllocationLine;
|
||||||
|
import org.compiere.model.MInvoice;
|
||||||
|
import org.compiere.model.MPayment;
|
||||||
|
import org.compiere.model.MRole;
|
||||||
|
import org.compiere.process.DocAction;
|
||||||
|
import org.compiere.util.CLogger;
|
||||||
|
import org.compiere.util.DB;
|
||||||
|
import org.compiere.util.DisplayType;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.KeyNamePair;
|
||||||
|
import org.compiere.util.Msg;
|
||||||
|
import org.compiere.util.TimeUtil;
|
||||||
|
import org.compiere.util.Util;
|
||||||
|
|
||||||
|
public class Allocation
|
||||||
|
{
|
||||||
|
public DecimalFormat format = DisplayType.getNumberFormat(DisplayType.Amount);
|
||||||
|
|
||||||
|
/** Logger */
|
||||||
|
public static CLogger log = CLogger.getCLogger(Allocation.class);
|
||||||
|
|
||||||
|
private boolean m_calculating = false;
|
||||||
|
public int m_C_Currency_ID = 0;
|
||||||
|
public int m_C_BPartner_ID = 0;
|
||||||
|
private int m_noInvoices = 0;
|
||||||
|
private int m_noPayments = 0;
|
||||||
|
public BigDecimal totalInv = new BigDecimal(0.0);
|
||||||
|
public BigDecimal totalPay = new BigDecimal(0.0);
|
||||||
|
public BigDecimal totalDiff = new BigDecimal(0.0);
|
||||||
|
|
||||||
|
public Timestamp allocDate = null;
|
||||||
|
|
||||||
|
// Index changed if multi-currency
|
||||||
|
private int i_payment = 7;
|
||||||
|
//
|
||||||
|
private int i_open = 6;
|
||||||
|
private int i_discount = 7;
|
||||||
|
private int i_writeOff = 8;
|
||||||
|
private int i_applied = 9;
|
||||||
|
private int i_overUnder = 10;
|
||||||
|
// private int i_multiplier = 10;
|
||||||
|
|
||||||
|
public int m_AD_Org_ID = 0;
|
||||||
|
|
||||||
|
private ArrayList<Integer> m_bpartnerCheck = new ArrayList<Integer>();
|
||||||
|
|
||||||
|
public void dynInit() throws Exception
|
||||||
|
{
|
||||||
|
m_C_Currency_ID = Env.getContextAsInt(Env.getCtx(), "$C_Currency_ID"); // default
|
||||||
|
//
|
||||||
|
log.info("Currency=" + m_C_Currency_ID);
|
||||||
|
|
||||||
|
m_AD_Org_ID = Env.getAD_Org_ID(Env.getCtx());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load Business Partner Info
|
||||||
|
* - Payments
|
||||||
|
* - Invoices
|
||||||
|
*/
|
||||||
|
public void checkBPartner()
|
||||||
|
{
|
||||||
|
log.config("BPartner=" + m_C_BPartner_ID + ", Cur=" + m_C_Currency_ID);
|
||||||
|
// Need to have both values
|
||||||
|
if (m_C_BPartner_ID == 0 || m_C_Currency_ID == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Async BPartner Test
|
||||||
|
Integer key = new Integer(m_C_BPartner_ID);
|
||||||
|
if (!m_bpartnerCheck.contains(key))
|
||||||
|
{
|
||||||
|
new Thread()
|
||||||
|
{
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
MPayment.setIsAllocated (Env.getCtx(), m_C_BPartner_ID, null);
|
||||||
|
MInvoice.setIsPaid (Env.getCtx(), m_C_BPartner_ID, null);
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
|
m_bpartnerCheck.add(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector<Vector<Object>> getPaymentData(boolean isMultiCurrency, Object date, IMiniTable paymentTable)
|
||||||
|
{
|
||||||
|
/********************************
|
||||||
|
* Load unallocated Payments
|
||||||
|
* 1-TrxDate, 2-DocumentNo, (3-Currency, 4-PayAmt,)
|
||||||
|
* 5-ConvAmt, 6-ConvOpen, 7-Allocated
|
||||||
|
*/
|
||||||
|
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
|
||||||
|
StringBuffer sql = new StringBuffer("SELECT p.DateTrx,p.DocumentNo,p.C_Payment_ID," // 1..3
|
||||||
|
+ "c.ISO_Code,p.PayAmt," // 4..5
|
||||||
|
+ "currencyConvert(p.PayAmt,p.C_Currency_ID,?,?,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID),"// 6 #1, #2
|
||||||
|
+ "currencyConvert(paymentAvailable(C_Payment_ID),p.C_Currency_ID,?,?,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID)," // 7 #3, #4
|
||||||
|
+ "p.MultiplierAP "
|
||||||
|
+ "FROM C_Payment_v p" // Corrected for AP/AR
|
||||||
|
+ " INNER JOIN C_Currency c ON (p.C_Currency_ID=c.C_Currency_ID) "
|
||||||
|
+ "WHERE p.IsAllocated='N' AND p.Processed='Y'"
|
||||||
|
+ " AND p.C_Charge_ID IS NULL" // Prepayments OK
|
||||||
|
+ " AND p.C_BPartner_ID=?"); // #5
|
||||||
|
if (!isMultiCurrency)
|
||||||
|
sql.append(" AND p.C_Currency_ID=?"); // #6
|
||||||
|
if (m_AD_Org_ID != 0 )
|
||||||
|
sql.append(" AND p.AD_Org_ID=" + m_AD_Org_ID);
|
||||||
|
sql.append(" ORDER BY p.DateTrx,p.DocumentNo");
|
||||||
|
|
||||||
|
// role security
|
||||||
|
sql = new StringBuffer( MRole.getDefault(Env.getCtx(), false).addAccessSQL( sql.toString(), "p", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO ) );
|
||||||
|
|
||||||
|
log.fine("PaySQL=" + sql.toString());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null);
|
||||||
|
pstmt.setInt(1, m_C_Currency_ID);
|
||||||
|
pstmt.setTimestamp(2, (Timestamp)date);
|
||||||
|
pstmt.setInt(3, m_C_Currency_ID);
|
||||||
|
pstmt.setTimestamp(4, (Timestamp)date);
|
||||||
|
pstmt.setInt(5, m_C_BPartner_ID);
|
||||||
|
if (!isMultiCurrency)
|
||||||
|
pstmt.setInt(6, m_C_Currency_ID);
|
||||||
|
ResultSet rs = pstmt.executeQuery();
|
||||||
|
while (rs.next())
|
||||||
|
{
|
||||||
|
Vector<Object> line = new Vector<Object>();
|
||||||
|
line.add(new Boolean(false)); // 0-Selection
|
||||||
|
line.add(rs.getTimestamp(1)); // 1-TrxDate
|
||||||
|
KeyNamePair pp = new KeyNamePair(rs.getInt(3), rs.getString(2));
|
||||||
|
line.add(pp); // 2-DocumentNo
|
||||||
|
if (isMultiCurrency)
|
||||||
|
{
|
||||||
|
line.add(rs.getString(4)); // 3-Currency
|
||||||
|
line.add(rs.getBigDecimal(5)); // 4-PayAmt
|
||||||
|
}
|
||||||
|
line.add(rs.getBigDecimal(6)); // 3/5-ConvAmt
|
||||||
|
BigDecimal available = rs.getBigDecimal(7);
|
||||||
|
if (available == null || available.signum() == 0) // nothing available
|
||||||
|
continue;
|
||||||
|
line.add(available); // 4/6-ConvOpen/Available
|
||||||
|
line.add(Env.ZERO); // 5/7-Payment
|
||||||
|
// line.add(rs.getBigDecimal(8)); // 6/8-Multiplier
|
||||||
|
//
|
||||||
|
data.add(line);
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
pstmt.close();
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
log.log(Level.SEVERE, sql.toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector<String> getPaymentColumnNames(boolean isMultiCurrency)
|
||||||
|
{
|
||||||
|
// Header Info
|
||||||
|
Vector<String> columnNames = new Vector<String>();
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "Select"));
|
||||||
|
columnNames.add(Msg.translate(Env.getCtx(), "Date"));
|
||||||
|
columnNames.add(Util.cleanAmp(Msg.translate(Env.getCtx(), "DocumentNo")));
|
||||||
|
if (isMultiCurrency)
|
||||||
|
{
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "TrxCurrency"));
|
||||||
|
columnNames.add(Msg.translate(Env.getCtx(), "Amount"));
|
||||||
|
}
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "ConvertedAmount"));
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "OpenAmt"));
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "AppliedAmt"));
|
||||||
|
// columnNames.add(" "); // Multiplier
|
||||||
|
|
||||||
|
return columnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPaymentColumnClass(IMiniTable paymentTable, boolean isMultiCurrency)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
paymentTable.setColumnClass(i++, Boolean.class, false); // 0-Selection
|
||||||
|
paymentTable.setColumnClass(i++, Timestamp.class, true); // 1-TrxDate
|
||||||
|
paymentTable.setColumnClass(i++, String.class, true); // 2-Value
|
||||||
|
if (isMultiCurrency)
|
||||||
|
{
|
||||||
|
paymentTable.setColumnClass(i++, String.class, true); // 3-Currency
|
||||||
|
paymentTable.setColumnClass(i++, BigDecimal.class, true); // 4-PayAmt
|
||||||
|
}
|
||||||
|
paymentTable.setColumnClass(i++, BigDecimal.class, true); // 5-ConvAmt
|
||||||
|
paymentTable.setColumnClass(i++, BigDecimal.class, true); // 6-ConvOpen
|
||||||
|
paymentTable.setColumnClass(i++, BigDecimal.class, false); // 7-Allocated
|
||||||
|
// paymentTable.setColumnClass(i++, BigDecimal.class, true); // 8-Multiplier
|
||||||
|
|
||||||
|
//
|
||||||
|
i_payment = isMultiCurrency ? 7 : 5;
|
||||||
|
|
||||||
|
|
||||||
|
// Table UI
|
||||||
|
paymentTable.autoSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector<Vector<Object>> getInvoiceData(boolean isMultiCurrency, Object date, IMiniTable invoiceTable)
|
||||||
|
{
|
||||||
|
/********************************
|
||||||
|
* Load unpaid Invoices
|
||||||
|
* 1-TrxDate, 2-Value, (3-Currency, 4-InvAmt,)
|
||||||
|
* 5-ConvAmt, 6-ConvOpen, 7-ConvDisc, 8-WriteOff, 9-Applied
|
||||||
|
*
|
||||||
|
SELECT i.DateInvoiced,i.DocumentNo,i.C_Invoice_ID,c.ISO_Code,
|
||||||
|
i.GrandTotal*i.MultiplierAP "GrandTotal",
|
||||||
|
currencyConvert(i.GrandTotal*i.MultiplierAP,i.C_Currency_ID,i.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID) "GrandTotal $",
|
||||||
|
invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID) "Open",
|
||||||
|
currencyConvert(invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID),i.C_Currency_ID,i.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.MultiplierAP "Open $",
|
||||||
|
invoiceDiscount(i.C_Invoice_ID,SysDate,C_InvoicePaySchedule_ID) "Discount",
|
||||||
|
currencyConvert(invoiceDiscount(i.C_Invoice_ID,SysDate,C_InvoicePaySchedule_ID),i.C_Currency_ID,i.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.Multiplier*i.MultiplierAP "Discount $",
|
||||||
|
i.MultiplierAP, i.Multiplier
|
||||||
|
FROM C_Invoice_v i INNER JOIN C_Currency c ON (i.C_Currency_ID=c.C_Currency_ID)
|
||||||
|
WHERE -- i.IsPaid='N' AND i.Processed='Y' AND i.C_BPartner_ID=1000001
|
||||||
|
*/
|
||||||
|
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
|
||||||
|
StringBuffer sql = new StringBuffer("SELECT i.DateInvoiced,i.DocumentNo,i.C_Invoice_ID," // 1..3
|
||||||
|
+ "c.ISO_Code,i.GrandTotal*i.MultiplierAP, " // 4..5 Orig Currency
|
||||||
|
+ "currencyConvert(i.GrandTotal*i.MultiplierAP,i.C_Currency_ID,?,?,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID), " // 6 #1 Converted, #2 Date
|
||||||
|
+ "currencyConvert(invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,?,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.MultiplierAP, " // 7 #3, #4 Converted Open
|
||||||
|
+ "currencyConvert(invoiceDiscount" // 8 AllowedDiscount
|
||||||
|
+ "(i.C_Invoice_ID,?,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.Multiplier*i.MultiplierAP," // #5, #6
|
||||||
|
+ "i.MultiplierAP "
|
||||||
|
+ "FROM C_Invoice_v i" // corrected for CM/Split
|
||||||
|
+ " INNER JOIN C_Currency c ON (i.C_Currency_ID=c.C_Currency_ID) "
|
||||||
|
+ "WHERE i.IsPaid='N' AND i.Processed='Y'"
|
||||||
|
+ " AND i.C_BPartner_ID=?"); // #7
|
||||||
|
if (!isMultiCurrency)
|
||||||
|
sql.append(" AND i.C_Currency_ID=?"); // #8
|
||||||
|
if (m_AD_Org_ID != 0 )
|
||||||
|
sql.append(" AND i.AD_Org_ID=" + m_AD_Org_ID);
|
||||||
|
sql.append(" ORDER BY i.DateInvoiced, i.DocumentNo");
|
||||||
|
log.fine("InvSQL=" + sql.toString());
|
||||||
|
|
||||||
|
// role security
|
||||||
|
sql = new StringBuffer( MRole.getDefault(Env.getCtx(), false).addAccessSQL( sql.toString(), "i", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO ) );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null);
|
||||||
|
pstmt.setInt(1, m_C_Currency_ID);
|
||||||
|
pstmt.setTimestamp(2, (Timestamp)date);
|
||||||
|
pstmt.setInt(3, m_C_Currency_ID);
|
||||||
|
pstmt.setTimestamp(4, (Timestamp)date);
|
||||||
|
pstmt.setTimestamp(5, (Timestamp)date);
|
||||||
|
pstmt.setInt(6, m_C_Currency_ID);
|
||||||
|
pstmt.setInt(7, m_C_BPartner_ID);
|
||||||
|
if (!isMultiCurrency)
|
||||||
|
pstmt.setInt(8, m_C_Currency_ID);
|
||||||
|
ResultSet rs = pstmt.executeQuery();
|
||||||
|
while (rs.next())
|
||||||
|
{
|
||||||
|
Vector<Object> line = new Vector<Object>();
|
||||||
|
line.add(new Boolean(false)); // 0-Selection
|
||||||
|
line.add(rs.getTimestamp(1)); // 1-TrxDate
|
||||||
|
KeyNamePair pp = new KeyNamePair(rs.getInt(3), rs.getString(2));
|
||||||
|
line.add(pp); // 2-Value
|
||||||
|
if (isMultiCurrency)
|
||||||
|
{
|
||||||
|
line.add(rs.getString(4)); // 3-Currency
|
||||||
|
line.add(rs.getBigDecimal(5)); // 4-Orig Amount
|
||||||
|
}
|
||||||
|
line.add(rs.getBigDecimal(6)); // 3/5-ConvAmt
|
||||||
|
BigDecimal open = rs.getBigDecimal(7);
|
||||||
|
if (open == null) // no conversion rate
|
||||||
|
open = Env.ZERO;
|
||||||
|
line.add(open); // 4/6-ConvOpen
|
||||||
|
BigDecimal discount = rs.getBigDecimal(8);
|
||||||
|
if (discount == null) // no concersion rate
|
||||||
|
discount = Env.ZERO;
|
||||||
|
line.add(discount); // 5/7-ConvAllowedDisc
|
||||||
|
line.add(Env.ZERO); // 6/8-WriteOff
|
||||||
|
line.add(Env.ZERO); // 7/9-Applied
|
||||||
|
line.add(open); // 8/10-OverUnder
|
||||||
|
|
||||||
|
// line.add(rs.getBigDecimal(9)); // 8/10-Multiplier
|
||||||
|
// Add when open <> 0 (i.e. not if no conversion rate)
|
||||||
|
if (Env.ZERO.compareTo(open) != 0)
|
||||||
|
data.add(line);
|
||||||
|
}
|
||||||
|
rs.close();
|
||||||
|
pstmt.close();
|
||||||
|
}
|
||||||
|
catch (SQLException e)
|
||||||
|
{
|
||||||
|
log.log(Level.SEVERE, sql.toString(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector<String> getInvoiceColumnNames(boolean isMultiCurrency)
|
||||||
|
{
|
||||||
|
// Header Info
|
||||||
|
Vector<String> columnNames = new Vector<String>();
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "Select"));
|
||||||
|
columnNames.add(Msg.translate(Env.getCtx(), "Date"));
|
||||||
|
columnNames.add(Util.cleanAmp(Msg.translate(Env.getCtx(), "DocumentNo")));
|
||||||
|
if (isMultiCurrency)
|
||||||
|
{
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "TrxCurrency"));
|
||||||
|
columnNames.add(Msg.translate(Env.getCtx(), "Amount"));
|
||||||
|
}
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "ConvertedAmount"));
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "OpenAmt"));
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "Discount"));
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "WriteOff"));
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "AppliedAmt"));
|
||||||
|
columnNames.add(Msg.getMsg(Env.getCtx(), "OverUnderAmt"));
|
||||||
|
// columnNames.add(" "); // Multiplier
|
||||||
|
|
||||||
|
return columnNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInvoiceColumnClass(IMiniTable invoiceTable, boolean isMultiCurrency)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
invoiceTable.setColumnClass(i++, Boolean.class, false); // 0-Selection
|
||||||
|
invoiceTable.setColumnClass(i++, Timestamp.class, true); // 1-TrxDate
|
||||||
|
invoiceTable.setColumnClass(i++, String.class, true); // 2-Value
|
||||||
|
if (isMultiCurrency)
|
||||||
|
{
|
||||||
|
invoiceTable.setColumnClass(i++, String.class, true); // 3-Currency
|
||||||
|
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 4-Amt
|
||||||
|
}
|
||||||
|
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 5-ConvAmt
|
||||||
|
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 6-ConvAmt Open
|
||||||
|
invoiceTable.setColumnClass(i++, BigDecimal.class, false); // 7-Conv Discount
|
||||||
|
invoiceTable.setColumnClass(i++, BigDecimal.class, false); // 8-Conv WriteOff
|
||||||
|
invoiceTable.setColumnClass(i++, BigDecimal.class, false); // 9-Conv OverUnder
|
||||||
|
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 10-Conv Applied
|
||||||
|
// invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 10-Multiplier
|
||||||
|
// Table UI
|
||||||
|
invoiceTable.autoSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculate(boolean isMultiCurrency)
|
||||||
|
{
|
||||||
|
i_open = isMultiCurrency ? 6 : 4;
|
||||||
|
i_discount = isMultiCurrency ? 7 : 5;
|
||||||
|
i_writeOff = isMultiCurrency ? 8 : 6;
|
||||||
|
i_applied = isMultiCurrency ? 9 : 7;
|
||||||
|
i_overUnder = isMultiCurrency ? 10 : 8;
|
||||||
|
// i_multiplier = isMultiCurrency ? 10 : 8;
|
||||||
|
} // loadBPartner
|
||||||
|
|
||||||
|
public String writeOff(int row, int col, boolean isInvoice, IMiniTable payment, IMiniTable invoice, boolean isAutoWriteOff)
|
||||||
|
{
|
||||||
|
String msg = "";
|
||||||
|
/**
|
||||||
|
* Setting defaults
|
||||||
|
*/
|
||||||
|
if (m_calculating) // Avoid recursive calls
|
||||||
|
return msg;
|
||||||
|
m_calculating = true;
|
||||||
|
|
||||||
|
log.config("Row=" + row
|
||||||
|
+ ", Col=" + col + ", InvoiceTable=" + isInvoice);
|
||||||
|
|
||||||
|
// Payments
|
||||||
|
if (!isInvoice)
|
||||||
|
{
|
||||||
|
BigDecimal open = (BigDecimal)payment.getValueAt(row, i_open);
|
||||||
|
BigDecimal applied = (BigDecimal)payment.getValueAt(row, i_payment);
|
||||||
|
|
||||||
|
if (col == 0)
|
||||||
|
{
|
||||||
|
// selection of payment row
|
||||||
|
if (((Boolean)payment.getValueAt(row, 0)).booleanValue())
|
||||||
|
{
|
||||||
|
applied = open; // Open Amount
|
||||||
|
if (totalDiff.abs().compareTo(applied.abs()) < 0 // where less is available to allocate than open
|
||||||
|
&& totalDiff.signum() == -applied.signum() ) // and the available amount has the opposite sign
|
||||||
|
applied = totalDiff.negate(); // reduce the amount applied to what's available
|
||||||
|
|
||||||
|
}
|
||||||
|
else // de-selected
|
||||||
|
applied = Env.ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (col == i_payment)
|
||||||
|
{
|
||||||
|
if ( applied.signum() == -open.signum() )
|
||||||
|
applied = applied.negate();
|
||||||
|
if ( open.abs().compareTo( applied.abs() ) < 0 )
|
||||||
|
applied = open;
|
||||||
|
}
|
||||||
|
|
||||||
|
payment.setValueAt(applied, row, i_payment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoice
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boolean selected = ((Boolean) invoice.getValueAt(row, 0)).booleanValue();
|
||||||
|
BigDecimal open = (BigDecimal)invoice.getValueAt(row, i_open);
|
||||||
|
BigDecimal discount = (BigDecimal)invoice.getValueAt(row, i_discount);
|
||||||
|
BigDecimal applied = (BigDecimal)invoice.getValueAt(row, i_applied);
|
||||||
|
BigDecimal writeOff = (BigDecimal) invoice.getValueAt(row, i_writeOff);
|
||||||
|
BigDecimal overUnder = (BigDecimal) invoice.getValueAt(row, i_overUnder);
|
||||||
|
int openSign = open.signum();
|
||||||
|
|
||||||
|
if (col == 0) //selection
|
||||||
|
{
|
||||||
|
// selected - set applied amount
|
||||||
|
if ( selected )
|
||||||
|
{
|
||||||
|
applied = open; // Open Amount
|
||||||
|
applied = applied.subtract(discount);
|
||||||
|
writeOff = Env.ZERO; // to be sure
|
||||||
|
overUnder = Env.ZERO;
|
||||||
|
|
||||||
|
if (totalDiff.abs().compareTo(applied.abs()) < 0 // where less is available to allocate than open
|
||||||
|
&& totalDiff.signum() == applied.signum() ) // and the available amount has the same sign
|
||||||
|
applied = totalDiff; // reduce the amount applied to what's available
|
||||||
|
|
||||||
|
if ( isAutoWriteOff )
|
||||||
|
writeOff = open.subtract(applied.add(discount));
|
||||||
|
else
|
||||||
|
overUnder = open.subtract(applied.add(discount));
|
||||||
|
}
|
||||||
|
else // de-selected
|
||||||
|
{
|
||||||
|
writeOff = Env.ZERO;
|
||||||
|
applied = Env.ZERO;
|
||||||
|
overUnder = Env.ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check entered values are sensible and possibly auto write-off
|
||||||
|
if ( selected && col != 0 )
|
||||||
|
{
|
||||||
|
|
||||||
|
// values should have same sign as open except possibly over/under
|
||||||
|
if ( discount.signum() == -openSign )
|
||||||
|
discount = discount.negate();
|
||||||
|
if ( writeOff.signum() == -openSign)
|
||||||
|
writeOff = writeOff.negate();
|
||||||
|
if ( applied.signum() == -openSign )
|
||||||
|
applied = applied.negate();
|
||||||
|
|
||||||
|
// discount and write-off must be less than open amount
|
||||||
|
if ( discount.abs().compareTo(open.abs()) > 0)
|
||||||
|
discount = open;
|
||||||
|
if ( writeOff.abs().compareTo(open.abs()) > 0)
|
||||||
|
writeOff = open;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Two rules to maintain:
|
||||||
|
*
|
||||||
|
* 1) |writeOff + discount| < |open|
|
||||||
|
* 2) discount + writeOff + overUnder + applied = 0
|
||||||
|
*
|
||||||
|
* As only one column is edited at a time and the initial position was one of compliance
|
||||||
|
* with the rules, we only need to redistribute the increase/decrease in the edited column to
|
||||||
|
* the others.
|
||||||
|
*/
|
||||||
|
BigDecimal newTotal = discount.add(writeOff).add(applied).add(overUnder); // all have same sign
|
||||||
|
BigDecimal difference = newTotal.subtract(open);
|
||||||
|
|
||||||
|
// rule 2
|
||||||
|
BigDecimal diffWOD = writeOff.add(discount).subtract(open);
|
||||||
|
|
||||||
|
if ( diffWOD.signum() == open.signum() ) // writeOff and discount are too large
|
||||||
|
{
|
||||||
|
if ( col == i_discount ) // then edit writeoff
|
||||||
|
{
|
||||||
|
writeOff = writeOff.subtract(diffWOD);
|
||||||
|
}
|
||||||
|
else // col = i_writeoff
|
||||||
|
{
|
||||||
|
discount = discount.subtract(diffWOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
difference = difference.subtract(diffWOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rule 1
|
||||||
|
if ( col == i_applied )
|
||||||
|
overUnder = overUnder.subtract(difference);
|
||||||
|
else
|
||||||
|
applied = applied.subtract(difference);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warning if write Off > 30%
|
||||||
|
if (isAutoWriteOff && writeOff.doubleValue()/open.doubleValue() > .30)
|
||||||
|
msg = "AllocationWriteOffWarn";
|
||||||
|
|
||||||
|
invoice.setValueAt(discount, row, i_discount);
|
||||||
|
invoice.setValueAt(applied, row, i_applied);
|
||||||
|
invoice.setValueAt(writeOff, row, i_writeOff);
|
||||||
|
invoice.setValueAt(overUnder, row, i_overUnder);
|
||||||
|
|
||||||
|
invoice.repaint(); // update r/o
|
||||||
|
}
|
||||||
|
|
||||||
|
m_calculating = false;
|
||||||
|
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate Allocation info
|
||||||
|
*/
|
||||||
|
public String calculatePayment(IMiniTable payment, boolean isMultiCurrency)
|
||||||
|
{
|
||||||
|
log.config("");
|
||||||
|
|
||||||
|
// Payment
|
||||||
|
totalPay = new BigDecimal(0.0);
|
||||||
|
int rows = payment.getRowCount();
|
||||||
|
m_noPayments = 0;
|
||||||
|
for (int i = 0; i < rows; i++)
|
||||||
|
{
|
||||||
|
if (((Boolean)payment.getValueAt(i, 0)).booleanValue())
|
||||||
|
{
|
||||||
|
Timestamp ts = (Timestamp)payment.getValueAt(i, 1);
|
||||||
|
if ( !isMultiCurrency ) // the converted amounts are only valid for the selected date
|
||||||
|
allocDate = TimeUtil.max(allocDate, ts);
|
||||||
|
BigDecimal bd = (BigDecimal)payment.getValueAt(i, i_payment);
|
||||||
|
totalPay = totalPay.add(bd); // Applied Pay
|
||||||
|
m_noPayments++;
|
||||||
|
log.fine("Payment_" + i + " = " + bd + " - Total=" + totalPay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return String.valueOf(m_noPayments) + " - "
|
||||||
|
+ Msg.getMsg(Env.getCtx(), "Sum") + " " + format.format(totalPay) + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String calculateInvoice(IMiniTable invoice, boolean isMultiCurrency)
|
||||||
|
{
|
||||||
|
// Invoices
|
||||||
|
totalInv = new BigDecimal(0.0);
|
||||||
|
int rows = invoice.getRowCount();
|
||||||
|
m_noInvoices = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < rows; i++)
|
||||||
|
{
|
||||||
|
if (((Boolean)invoice.getValueAt(i, 0)).booleanValue())
|
||||||
|
{
|
||||||
|
Timestamp ts = (Timestamp)invoice.getValueAt(i, 1);
|
||||||
|
if ( !isMultiCurrency ) // converted amounts only valid for selected date
|
||||||
|
allocDate = TimeUtil.max(allocDate, ts);
|
||||||
|
BigDecimal bd = (BigDecimal)invoice.getValueAt(i, i_applied);
|
||||||
|
totalInv = totalInv.add(bd); // Applied Inv
|
||||||
|
m_noInvoices++;
|
||||||
|
log.fine("Invoice_" + i + " = " + bd + " - Total=" + totalPay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return String.valueOf(m_noInvoices) + " - "
|
||||||
|
+ Msg.getMsg(Env.getCtx(), "Sum") + " " + format.format(totalInv) + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Save Data
|
||||||
|
*/
|
||||||
|
public String saveData(int m_WindowNo, Object date, IMiniTable payment, IMiniTable invoice, String trxName)
|
||||||
|
{
|
||||||
|
if (m_noInvoices + m_noPayments == 0)
|
||||||
|
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)date;
|
||||||
|
int C_Currency_ID = m_C_Currency_ID; // the allocation currency
|
||||||
|
//
|
||||||
|
if (AD_Org_ID == 0)
|
||||||
|
{
|
||||||
|
//ADialog.error(m_WindowNo, this, "Org0NotAllowed", null);
|
||||||
|
new AdempiereException("@Org0NotAllowed@");
|
||||||
|
}
|
||||||
|
//
|
||||||
|
log.config("Client=" + AD_Client_ID + ", Org=" + AD_Org_ID
|
||||||
|
+ ", BPartner=" + C_BPartner_ID + ", Date=" + DateTrx);
|
||||||
|
|
||||||
|
// Payment - Loop and add them to paymentList/amountList
|
||||||
|
int pRows = payment.getRowCount();
|
||||||
|
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
|
||||||
|
if (((Boolean)payment.getValueAt(i, 0)).booleanValue())
|
||||||
|
{
|
||||||
|
KeyNamePair pp = (KeyNamePair)payment.getValueAt(i, 2); // Value
|
||||||
|
// 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 = invoice.getRowCount();
|
||||||
|
|
||||||
|
// Create Allocation
|
||||||
|
MAllocationHdr alloc = new MAllocationHdr (Env.getCtx(), true, // manual
|
||||||
|
DateTrx, C_Currency_ID, Env.getContext(Env.getCtx(), "#AD_User_Name"), trxName);
|
||||||
|
alloc.setAD_Org_ID(AD_Org_ID);
|
||||||
|
alloc.saveEx();
|
||||||
|
// 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();
|
||||||
|
BigDecimal PaymentAmt = (BigDecimal)amountList.get(j);
|
||||||
|
if (PaymentAmt.signum() == AppliedAmt.signum()) // only match same sign (otherwise appliedAmt increases)
|
||||||
|
{ // and not zero (appliedAmt was checked earlier)
|
||||||
|
log.config(".. with payment #" + j + ", Amt=" + PaymentAmt);
|
||||||
|
|
||||||
|
BigDecimal amount = AppliedAmt;
|
||||||
|
if (amount.abs().compareTo(PaymentAmt.abs()) > 0) // if there's more open on the invoice
|
||||||
|
amount = PaymentAmt; // than left in the payment
|
||||||
|
|
||||||
|
// Allocation Line
|
||||||
|
MAllocationLine aLine = new MAllocationLine (alloc, amount,
|
||||||
|
DiscountAmt, WriteOffAmt, OverUnderAmt);
|
||||||
|
aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID);
|
||||||
|
aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID);
|
||||||
|
aLine.saveEx();
|
||||||
|
|
||||||
|
// Apply Discounts and WriteOff only first time
|
||||||
|
DiscountAmt = Env.ZERO;
|
||||||
|
WriteOffAmt = Env.ZERO;
|
||||||
|
// subtract amount from Payment/Invoice
|
||||||
|
AppliedAmt = AppliedAmt.subtract(amount);
|
||||||
|
PaymentAmt = PaymentAmt.subtract(amount);
|
||||||
|
log.fine("Allocation Amount=" + amount + " - Remaining Applied=" + AppliedAmt + ", Payment=" + PaymentAmt);
|
||||||
|
amountList.set(j, PaymentAmt); // update
|
||||||
|
} // for all applied amounts
|
||||||
|
} // loop through payments for invoice
|
||||||
|
|
||||||
|
if ( AppliedAmt.signum() == 0 && DiscountAmt.signum() == 0 && WriteOffAmt.signum() == 0)
|
||||||
|
continue;
|
||||||
|
else { // remainder will need to match against other invoices
|
||||||
|
int C_Payment_ID = 0;
|
||||||
|
|
||||||
|
// Allocation Line
|
||||||
|
MAllocationLine aLine = new MAllocationLine (alloc, AppliedAmt,
|
||||||
|
DiscountAmt, WriteOffAmt, OverUnderAmt);
|
||||||
|
aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID);
|
||||||
|
aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID);
|
||||||
|
aLine.saveEx();
|
||||||
|
log.fine("Allocation Amount=" + AppliedAmt);
|
||||||
|
unmatchedApplied = unmatchedApplied.add(AppliedAmt);
|
||||||
|
}
|
||||||
|
} // invoice selected
|
||||||
|
} // invoice loop
|
||||||
|
|
||||||
|
// check for unapplied payment amounts (eg from payment reversals)
|
||||||
|
for (int i = 0; i < paymentList.size(); i++) {
|
||||||
|
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();
|
||||||
|
|
||||||
|
return alloc.getDocumentNo();
|
||||||
|
} // saveData
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Product: Adempiere ERP & CRM Smart Business Solution *
|
* Copyright (C) 2009 Low Heng Sin *
|
||||||
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
|
* Copyright (C) 2009 Idalica Corporation *
|
||||||
* This program is free software; you can redistribute it and/or modify it *
|
* 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 *
|
* 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 *
|
* by the Free Software Foundation. This program is distributed in the hope *
|
||||||
|
@ -10,9 +10,6 @@
|
||||||
* You should have received a copy of the GNU General Public License along *
|
* 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., *
|
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. *
|
||||||
* For the text or an alternative of this public license, you may reach us *
|
|
||||||
* ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA *
|
|
||||||
* or via info@compiere.org or http://www.compiere.org/license.html *
|
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package org.compiere.apps.form;
|
package org.compiere.apps.form;
|
||||||
|
|
||||||
|
@ -26,12 +23,6 @@ import java.awt.event.ActionListener;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.VetoableChangeListener;
|
import java.beans.VetoableChangeListener;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
@ -45,49 +36,25 @@ import javax.swing.SwingConstants;
|
||||||
import javax.swing.event.TableModelEvent;
|
import javax.swing.event.TableModelEvent;
|
||||||
import javax.swing.event.TableModelListener;
|
import javax.swing.event.TableModelListener;
|
||||||
import javax.swing.table.DefaultTableModel;
|
import javax.swing.table.DefaultTableModel;
|
||||||
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;
|
||||||
import org.compiere.grid.ed.VDate;
|
import org.compiere.grid.ed.VDate;
|
||||||
import org.compiere.grid.ed.VLookup;
|
import org.compiere.grid.ed.VLookup;
|
||||||
import org.compiere.minigrid.MiniTable;
|
import org.compiere.minigrid.MiniTable;
|
||||||
import org.compiere.model.MAllocationHdr;
|
|
||||||
import org.compiere.model.MAllocationLine;
|
|
||||||
import org.compiere.model.MInvoice;
|
|
||||||
import org.compiere.model.MLookup;
|
import org.compiere.model.MLookup;
|
||||||
import org.compiere.model.MLookupFactory;
|
import org.compiere.model.MLookupFactory;
|
||||||
import org.compiere.model.MPayment;
|
|
||||||
import org.compiere.model.MRole;
|
|
||||||
import org.compiere.plaf.CompiereColor;
|
import org.compiere.plaf.CompiereColor;
|
||||||
import org.compiere.process.DocAction;
|
|
||||||
import org.compiere.swing.CPanel;
|
import org.compiere.swing.CPanel;
|
||||||
import org.compiere.swing.CTextField;
|
import org.compiere.swing.CTextField;
|
||||||
import org.compiere.util.CLogger;
|
|
||||||
import org.compiere.util.DB;
|
|
||||||
import org.compiere.util.DisplayType;
|
import org.compiere.util.DisplayType;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.util.KeyNamePair;
|
|
||||||
import org.compiere.util.Msg;
|
import org.compiere.util.Msg;
|
||||||
import org.compiere.util.TimeUtil;
|
|
||||||
import org.compiere.util.Trx;
|
import org.compiere.util.Trx;
|
||||||
import org.compiere.util.TrxRunnable;
|
import org.compiere.util.TrxRunnable;
|
||||||
import org.compiere.util.Util;
|
|
||||||
|
|
||||||
/**
|
public class VAllocation extends Allocation
|
||||||
* Allocation Form
|
|
||||||
*
|
|
||||||
* @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 $
|
|
||||||
*
|
|
||||||
* Contributor : Fabian Aguilar - OFBConsulting - Multiallocation
|
|
||||||
*/
|
|
||||||
public class VAllocation extends CPanel
|
|
||||||
implements FormPanel, ActionListener, TableModelListener, VetoableChangeListener
|
implements FormPanel, ActionListener, TableModelListener, VetoableChangeListener
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -96,6 +63,8 @@ public class VAllocation extends CPanel
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -5322824600164192235L;
|
private static final long serialVersionUID = -5322824600164192235L;
|
||||||
|
|
||||||
|
private CPanel panel = new CPanel();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize Panel
|
* Initialize Panel
|
||||||
* @param WindowNo window
|
* @param WindowNo window
|
||||||
|
@ -106,11 +75,9 @@ public class VAllocation extends CPanel
|
||||||
m_WindowNo = WindowNo;
|
m_WindowNo = WindowNo;
|
||||||
m_frame = frame;
|
m_frame = frame;
|
||||||
Env.setContext(Env.getCtx(), m_WindowNo, "IsSOTrx", "Y"); // defaults to no
|
Env.setContext(Env.getCtx(), m_WindowNo, "IsSOTrx", "Y"); // defaults to no
|
||||||
m_C_Currency_ID = Env.getContextAsInt(Env.getCtx(), "$C_Currency_ID"); // default
|
|
||||||
//
|
|
||||||
log.info("Currency=" + m_C_Currency_ID);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
super.dynInit();
|
||||||
dynInit();
|
dynInit();
|
||||||
jbInit();
|
jbInit();
|
||||||
calculate();
|
calculate();
|
||||||
|
@ -127,28 +94,7 @@ public class VAllocation extends CPanel
|
||||||
private int m_WindowNo = 0;
|
private int m_WindowNo = 0;
|
||||||
/** FormFrame */
|
/** FormFrame */
|
||||||
private FormFrame m_frame;
|
private FormFrame m_frame;
|
||||||
/** Logger */
|
|
||||||
private static CLogger log = CLogger.getCLogger(VAllocation.class);
|
|
||||||
|
|
||||||
private boolean m_calculating = false;
|
|
||||||
private int m_C_Currency_ID = 0;
|
|
||||||
private int m_C_BPartner_ID = 0;
|
|
||||||
private int m_noInvoices = 0;
|
|
||||||
private int m_noPayments = 0;
|
|
||||||
private BigDecimal totalInv = new BigDecimal(0.0);
|
|
||||||
private BigDecimal totalPay = new BigDecimal(0.0);
|
|
||||||
private BigDecimal totalDiff = new BigDecimal(0.0);
|
|
||||||
|
|
||||||
// Index changed if multi-currency
|
|
||||||
private int i_payment = 7;
|
|
||||||
//
|
|
||||||
private int i_open = 6;
|
|
||||||
private int i_discount = 7;
|
|
||||||
private int i_writeOff = 8;
|
|
||||||
private int i_applied = 9;
|
|
||||||
private int i_overUnder = 10;
|
|
||||||
// private int i_multiplier = 10;
|
|
||||||
//
|
|
||||||
private CPanel mainPanel = new CPanel();
|
private CPanel mainPanel = new CPanel();
|
||||||
private BorderLayout mainLayout = new BorderLayout();
|
private BorderLayout mainLayout = new BorderLayout();
|
||||||
private CPanel parameterPanel = new CPanel();
|
private CPanel parameterPanel = new CPanel();
|
||||||
|
@ -181,19 +127,16 @@ public class VAllocation extends CPanel
|
||||||
private JLabel dateLabel = new JLabel();
|
private JLabel dateLabel = new JLabel();
|
||||||
private VDate dateField = new VDate();
|
private VDate dateField = new VDate();
|
||||||
private JCheckBox autoWriteOff = new JCheckBox();
|
private JCheckBox autoWriteOff = new JCheckBox();
|
||||||
private int m_AD_Org_ID = 0;
|
|
||||||
private JLabel organizationLabel = new JLabel();
|
private JLabel organizationLabel = new JLabel();
|
||||||
private VLookup organizationPick = null;
|
private VLookup organizationPick = null;
|
||||||
|
|
||||||
private ArrayList<Integer> m_bpartnerCheck = new ArrayList<Integer>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Static Init
|
* Static Init
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private void jbInit() throws Exception
|
private void jbInit() throws Exception
|
||||||
{
|
{
|
||||||
CompiereColor.setBackground(this);
|
CompiereColor.setBackground(panel);
|
||||||
//
|
//
|
||||||
mainPanel.setLayout(mainLayout);
|
mainPanel.setLayout(mainLayout);
|
||||||
dateLabel.setText(Msg.getMsg(Env.getCtx(), "Date"));
|
dateLabel.setText(Msg.getMsg(Env.getCtx(), "Date"));
|
||||||
|
@ -300,7 +243,7 @@ public class VAllocation extends CPanel
|
||||||
* Dynamic Init (prepare dynamic fields)
|
* Dynamic Init (prepare dynamic fields)
|
||||||
* @throws Exception if Lookups cannot be initialized
|
* @throws Exception if Lookups cannot be initialized
|
||||||
*/
|
*/
|
||||||
private void dynInit() throws Exception
|
public void dynInit() throws Exception
|
||||||
{
|
{
|
||||||
// Currency
|
// Currency
|
||||||
int AD_Column_ID = 3505; // C_Invoice.C_Currency_ID
|
int AD_Column_ID = 3505; // C_Invoice.C_Currency_ID
|
||||||
|
@ -316,8 +259,6 @@ public class VAllocation extends CPanel
|
||||||
organizationPick.setValue(Env.getAD_Org_ID(Env.getCtx()));
|
organizationPick.setValue(Env.getAD_Org_ID(Env.getCtx()));
|
||||||
organizationPick.addVetoableChangeListener(this);
|
organizationPick.addVetoableChangeListener(this);
|
||||||
|
|
||||||
m_AD_Org_ID = Env.getAD_Org_ID(Env.getCtx());
|
|
||||||
|
|
||||||
// BPartner
|
// BPartner
|
||||||
AD_Column_ID = 3499; // C_Invoice.C_BPartner_ID
|
AD_Column_ID = 3499; // C_Invoice.C_BPartner_ID
|
||||||
MLookup lookupBP = MLookupFactory.get (Env.getCtx(), m_WindowNo, 0, AD_Column_ID, DisplayType.Search);
|
MLookup lookupBP = MLookupFactory.get (Env.getCtx(), m_WindowNo, 0, AD_Column_ID, DisplayType.Search);
|
||||||
|
@ -333,289 +274,6 @@ public class VAllocation extends CPanel
|
||||||
dateField.addVetoableChangeListener(this);
|
dateField.addVetoableChangeListener(this);
|
||||||
} // dynInit
|
} // dynInit
|
||||||
|
|
||||||
/**
|
|
||||||
* Load Business Partner Info
|
|
||||||
* - Payments
|
|
||||||
* - Invoices
|
|
||||||
*/
|
|
||||||
private void loadBPartner ()
|
|
||||||
{
|
|
||||||
log.config("BPartner=" + m_C_BPartner_ID + ", Cur=" + m_C_Currency_ID);
|
|
||||||
// Need to have both values
|
|
||||||
if (m_C_BPartner_ID == 0 || m_C_Currency_ID == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Async BPartner Test
|
|
||||||
Integer key = new Integer(m_C_BPartner_ID);
|
|
||||||
if (!m_bpartnerCheck.contains(key))
|
|
||||||
{
|
|
||||||
new Thread()
|
|
||||||
{
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
MPayment.setIsAllocated (Env.getCtx(), m_C_BPartner_ID, null);
|
|
||||||
MInvoice.setIsPaid (Env.getCtx(), m_C_BPartner_ID, null);
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
m_bpartnerCheck.add(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/********************************
|
|
||||||
* Load unallocated Payments
|
|
||||||
* 1-TrxDate, 2-DocumentNo, (3-Currency, 4-PayAmt,)
|
|
||||||
* 5-ConvAmt, 6-ConvOpen, 7-Allocated
|
|
||||||
*/
|
|
||||||
Vector<Vector<Object>> data = new Vector<Vector<Object>>();
|
|
||||||
StringBuffer sql = new StringBuffer("SELECT p.DateTrx,p.DocumentNo,p.C_Payment_ID," // 1..3
|
|
||||||
+ "c.ISO_Code,p.PayAmt," // 4..5
|
|
||||||
+ "currencyConvert(p.PayAmt,p.C_Currency_ID,?,?,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID),"// 6 #1, #2
|
|
||||||
+ "currencyConvert(paymentAvailable(C_Payment_ID),p.C_Currency_ID,?,?,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID)," // 7 #3, #4
|
|
||||||
+ "p.MultiplierAP "
|
|
||||||
+ "FROM C_Payment_v p" // Corrected for AP/AR
|
|
||||||
+ " INNER JOIN C_Currency c ON (p.C_Currency_ID=c.C_Currency_ID) "
|
|
||||||
+ "WHERE p.IsAllocated='N' AND p.Processed='Y'"
|
|
||||||
+ " AND p.C_Charge_ID IS NULL" // Prepayments OK
|
|
||||||
+ " AND p.C_BPartner_ID=?"); // #5
|
|
||||||
if (!multiCurrency.isSelected())
|
|
||||||
sql.append(" AND p.C_Currency_ID=?"); // #6
|
|
||||||
if (m_AD_Org_ID != 0 )
|
|
||||||
sql.append(" AND p.AD_Org_ID=" + m_AD_Org_ID);
|
|
||||||
sql.append(" ORDER BY p.DateTrx,p.DocumentNo");
|
|
||||||
|
|
||||||
// role security
|
|
||||||
sql = new StringBuffer( MRole.getDefault(Env.getCtx(), false).addAccessSQL( sql.toString(), "p", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO ) );
|
|
||||||
|
|
||||||
log.fine("PaySQL=" + sql.toString());
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null);
|
|
||||||
pstmt.setInt(1, m_C_Currency_ID);
|
|
||||||
pstmt.setTimestamp(2, (Timestamp)dateField.getValue());
|
|
||||||
pstmt.setInt(3, m_C_Currency_ID);
|
|
||||||
pstmt.setTimestamp(4, (Timestamp)dateField.getValue());
|
|
||||||
pstmt.setInt(5, m_C_BPartner_ID);
|
|
||||||
if (!multiCurrency.isSelected())
|
|
||||||
pstmt.setInt(6, m_C_Currency_ID);
|
|
||||||
ResultSet rs = pstmt.executeQuery();
|
|
||||||
while (rs.next())
|
|
||||||
{
|
|
||||||
Vector<Object> line = new Vector<Object>();
|
|
||||||
line.add(new Boolean(false)); // 0-Selection
|
|
||||||
line.add(rs.getTimestamp(1)); // 1-TrxDate
|
|
||||||
KeyNamePair pp = new KeyNamePair(rs.getInt(3), rs.getString(2));
|
|
||||||
line.add(pp); // 2-DocumentNo
|
|
||||||
if (multiCurrency.isSelected())
|
|
||||||
{
|
|
||||||
line.add(rs.getString(4)); // 3-Currency
|
|
||||||
line.add(rs.getBigDecimal(5)); // 4-PayAmt
|
|
||||||
}
|
|
||||||
line.add(rs.getBigDecimal(6)); // 3/5-ConvAmt
|
|
||||||
BigDecimal available = rs.getBigDecimal(7);
|
|
||||||
if (available == null || available.signum() == 0) // nothing available
|
|
||||||
continue;
|
|
||||||
line.add(available); // 4/6-ConvOpen/Available
|
|
||||||
line.add(Env.ZERO); // 5/7-Payment
|
|
||||||
// line.add(rs.getBigDecimal(8)); // 6/8-Multiplier
|
|
||||||
//
|
|
||||||
data.add(line);
|
|
||||||
}
|
|
||||||
rs.close();
|
|
||||||
pstmt.close();
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{
|
|
||||||
log.log(Level.SEVERE, sql.toString(), e);
|
|
||||||
}
|
|
||||||
// Remove previous listeners
|
|
||||||
paymentTable.getModel().removeTableModelListener(this);
|
|
||||||
// Header Info
|
|
||||||
Vector<String> columnNames = new Vector<String>();
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "Select"));
|
|
||||||
columnNames.add(Msg.translate(Env.getCtx(), "Date"));
|
|
||||||
columnNames.add(Util.cleanAmp(Msg.translate(Env.getCtx(), "DocumentNo")));
|
|
||||||
if (multiCurrency.isSelected())
|
|
||||||
{
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "TrxCurrency"));
|
|
||||||
columnNames.add(Msg.translate(Env.getCtx(), "Amount"));
|
|
||||||
}
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "ConvertedAmount"));
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "OpenAmt"));
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "AppliedAmt"));
|
|
||||||
// columnNames.add(" "); // Multiplier
|
|
||||||
|
|
||||||
// Set Model
|
|
||||||
DefaultTableModel modelP = new DefaultTableModel(data, columnNames);
|
|
||||||
modelP.addTableModelListener(this);
|
|
||||||
paymentTable.setModel(modelP);
|
|
||||||
//
|
|
||||||
int i = 0;
|
|
||||||
paymentTable.setColumnClass(i++, Boolean.class, false); // 0-Selection
|
|
||||||
paymentTable.setColumnClass(i++, Timestamp.class, true); // 1-TrxDate
|
|
||||||
paymentTable.setColumnClass(i++, String.class, true); // 2-Value
|
|
||||||
if (multiCurrency.isSelected())
|
|
||||||
{
|
|
||||||
paymentTable.setColumnClass(i++, String.class, true); // 3-Currency
|
|
||||||
paymentTable.setColumnClass(i++, BigDecimal.class, true); // 4-PayAmt
|
|
||||||
}
|
|
||||||
paymentTable.setColumnClass(i++, BigDecimal.class, true); // 5-ConvAmt
|
|
||||||
paymentTable.setColumnClass(i++, BigDecimal.class, true); // 6-ConvOpen
|
|
||||||
paymentTable.setColumnClass(i++, BigDecimal.class, false); // 7-Allocated
|
|
||||||
// paymentTable.setColumnClass(i++, BigDecimal.class, true); // 8-Multiplier
|
|
||||||
|
|
||||||
//
|
|
||||||
i_payment = multiCurrency.isSelected() ? 7 : 5;
|
|
||||||
|
|
||||||
|
|
||||||
// Table UI
|
|
||||||
paymentTable.autoSize();
|
|
||||||
|
|
||||||
|
|
||||||
/********************************
|
|
||||||
* Load unpaid Invoices
|
|
||||||
* 1-TrxDate, 2-Value, (3-Currency, 4-InvAmt,)
|
|
||||||
* 5-ConvAmt, 6-ConvOpen, 7-ConvDisc, 8-WriteOff, 9-Applied
|
|
||||||
*
|
|
||||||
SELECT i.DateInvoiced,i.DocumentNo,i.C_Invoice_ID,c.ISO_Code,
|
|
||||||
i.GrandTotal*i.MultiplierAP "GrandTotal",
|
|
||||||
currencyConvert(i.GrandTotal*i.MultiplierAP,i.C_Currency_ID,i.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID) "GrandTotal $",
|
|
||||||
invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID) "Open",
|
|
||||||
currencyConvert(invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID),i.C_Currency_ID,i.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.MultiplierAP "Open $",
|
|
||||||
invoiceDiscount(i.C_Invoice_ID,SysDate,C_InvoicePaySchedule_ID) "Discount",
|
|
||||||
currencyConvert(invoiceDiscount(i.C_Invoice_ID,SysDate,C_InvoicePaySchedule_ID),i.C_Currency_ID,i.C_Currency_ID,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.Multiplier*i.MultiplierAP "Discount $",
|
|
||||||
i.MultiplierAP, i.Multiplier
|
|
||||||
FROM C_Invoice_v i INNER JOIN C_Currency c ON (i.C_Currency_ID=c.C_Currency_ID)
|
|
||||||
WHERE -- i.IsPaid='N' AND i.Processed='Y' AND i.C_BPartner_ID=1000001
|
|
||||||
*/
|
|
||||||
data = new Vector<Vector<Object>>();
|
|
||||||
sql = new StringBuffer("SELECT i.DateInvoiced,i.DocumentNo,i.C_Invoice_ID," // 1..3
|
|
||||||
+ "c.ISO_Code,i.GrandTotal*i.MultiplierAP, " // 4..5 Orig Currency
|
|
||||||
+ "currencyConvert(i.GrandTotal*i.MultiplierAP,i.C_Currency_ID,?,?,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID), " // 6 #1 Converted, #2 Date
|
|
||||||
+ "currencyConvert(invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,?,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.MultiplierAP, " // 7 #3, #4 Converted Open
|
|
||||||
+ "currencyConvert(invoiceDiscount" // 8 AllowedDiscount
|
|
||||||
+ "(i.C_Invoice_ID,?,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.Multiplier*i.MultiplierAP," // #5, #6
|
|
||||||
+ "i.MultiplierAP "
|
|
||||||
+ "FROM C_Invoice_v i" // corrected for CM/Split
|
|
||||||
+ " INNER JOIN C_Currency c ON (i.C_Currency_ID=c.C_Currency_ID) "
|
|
||||||
+ "WHERE i.IsPaid='N' AND i.Processed='Y'"
|
|
||||||
+ " AND i.C_BPartner_ID=?"); // #7
|
|
||||||
if (!multiCurrency.isSelected())
|
|
||||||
sql.append(" AND i.C_Currency_ID=?"); // #8
|
|
||||||
if (m_AD_Org_ID != 0 )
|
|
||||||
sql.append(" AND i.AD_Org_ID=" + m_AD_Org_ID);
|
|
||||||
sql.append(" ORDER BY i.DateInvoiced, i.DocumentNo");
|
|
||||||
log.fine("InvSQL=" + sql.toString());
|
|
||||||
|
|
||||||
// role security
|
|
||||||
sql = new StringBuffer( MRole.getDefault(Env.getCtx(), false).addAccessSQL( sql.toString(), "i", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO ) );
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null);
|
|
||||||
pstmt.setInt(1, m_C_Currency_ID);
|
|
||||||
pstmt.setTimestamp(2, (Timestamp)dateField.getValue());
|
|
||||||
pstmt.setInt(3, m_C_Currency_ID);
|
|
||||||
pstmt.setTimestamp(4, (Timestamp)dateField.getValue());
|
|
||||||
pstmt.setTimestamp(5, (Timestamp)dateField.getValue());
|
|
||||||
pstmt.setInt(6, m_C_Currency_ID);
|
|
||||||
pstmt.setInt(7, m_C_BPartner_ID);
|
|
||||||
if (!multiCurrency.isSelected())
|
|
||||||
pstmt.setInt(8, m_C_Currency_ID);
|
|
||||||
ResultSet rs = pstmt.executeQuery();
|
|
||||||
while (rs.next())
|
|
||||||
{
|
|
||||||
Vector<Object> line = new Vector<Object>();
|
|
||||||
line.add(new Boolean(false)); // 0-Selection
|
|
||||||
line.add(rs.getTimestamp(1)); // 1-TrxDate
|
|
||||||
KeyNamePair pp = new KeyNamePair(rs.getInt(3), rs.getString(2));
|
|
||||||
line.add(pp); // 2-Value
|
|
||||||
if (multiCurrency.isSelected())
|
|
||||||
{
|
|
||||||
line.add(rs.getString(4)); // 3-Currency
|
|
||||||
line.add(rs.getBigDecimal(5)); // 4-Orig Amount
|
|
||||||
}
|
|
||||||
line.add(rs.getBigDecimal(6)); // 3/5-ConvAmt
|
|
||||||
BigDecimal open = rs.getBigDecimal(7);
|
|
||||||
if (open == null) // no conversion rate
|
|
||||||
open = Env.ZERO;
|
|
||||||
line.add(open); // 4/6-ConvOpen
|
|
||||||
BigDecimal discount = rs.getBigDecimal(8);
|
|
||||||
if (discount == null) // no concersion rate
|
|
||||||
discount = Env.ZERO;
|
|
||||||
line.add(discount); // 5/7-ConvAllowedDisc
|
|
||||||
line.add(Env.ZERO); // 6/8-WriteOff
|
|
||||||
line.add(Env.ZERO); // 7/9-Applied
|
|
||||||
line.add(open); // 8/10-OverUnder
|
|
||||||
|
|
||||||
// line.add(rs.getBigDecimal(9)); // 8/10-Multiplier
|
|
||||||
// Add when open <> 0 (i.e. not if no conversion rate)
|
|
||||||
if (Env.ZERO.compareTo(open) != 0)
|
|
||||||
data.add(line);
|
|
||||||
}
|
|
||||||
rs.close();
|
|
||||||
pstmt.close();
|
|
||||||
}
|
|
||||||
catch (SQLException e)
|
|
||||||
{
|
|
||||||
log.log(Level.SEVERE, sql.toString(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove previous listeners
|
|
||||||
invoiceTable.getModel().removeTableModelListener(this);
|
|
||||||
// Header Info
|
|
||||||
columnNames = new Vector<String>();
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "Select"));
|
|
||||||
columnNames.add(Msg.translate(Env.getCtx(), "Date"));
|
|
||||||
columnNames.add(Util.cleanAmp(Msg.translate(Env.getCtx(), "DocumentNo")));
|
|
||||||
if (multiCurrency.isSelected())
|
|
||||||
{
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "TrxCurrency"));
|
|
||||||
columnNames.add(Msg.translate(Env.getCtx(), "Amount"));
|
|
||||||
}
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "ConvertedAmount"));
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "OpenAmt"));
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "Discount"));
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "WriteOff"));
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "AppliedAmt"));
|
|
||||||
columnNames.add(Msg.getMsg(Env.getCtx(), "OverUnderAmt"));
|
|
||||||
// columnNames.add(" "); // Multiplier
|
|
||||||
|
|
||||||
// Set Model
|
|
||||||
DefaultTableModel modelI = new DefaultTableModel(data, columnNames);
|
|
||||||
modelI.addTableModelListener(this);
|
|
||||||
invoiceTable.setModel(modelI);
|
|
||||||
//
|
|
||||||
i = 0;
|
|
||||||
invoiceTable.setColumnClass(i++, Boolean.class, false); // 0-Selection
|
|
||||||
invoiceTable.setColumnClass(i++, Timestamp.class, true); // 1-TrxDate
|
|
||||||
invoiceTable.setColumnClass(i++, String.class, true); // 2-Value
|
|
||||||
if (multiCurrency.isSelected())
|
|
||||||
{
|
|
||||||
invoiceTable.setColumnClass(i++, String.class, true); // 3-Currency
|
|
||||||
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 4-Amt
|
|
||||||
}
|
|
||||||
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 5-ConvAmt
|
|
||||||
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 6-ConvAmt Open
|
|
||||||
invoiceTable.setColumnClass(i++, BigDecimal.class, false); // 7-Conv Discount
|
|
||||||
invoiceTable.setColumnClass(i++, BigDecimal.class, false); // 8-Conv WriteOff
|
|
||||||
invoiceTable.setColumnClass(i++, BigDecimal.class, false); // 9-Conv OverUnder
|
|
||||||
invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 10-Conv Applied
|
|
||||||
// invoiceTable.setColumnClass(i++, BigDecimal.class, true); // 10-Multiplier
|
|
||||||
// Table UI
|
|
||||||
invoiceTable.autoSize();
|
|
||||||
|
|
||||||
i_open = multiCurrency.isSelected() ? 6 : 4;
|
|
||||||
i_discount = multiCurrency.isSelected() ? 7 : 5;
|
|
||||||
i_writeOff = multiCurrency.isSelected() ? 8 : 6;
|
|
||||||
i_applied = multiCurrency.isSelected() ? 9 : 7;
|
|
||||||
i_overUnder = multiCurrency.isSelected() ? 10 : 8;
|
|
||||||
// i_multiplier = multiCurrency.isSelected() ? 10 : 8;
|
|
||||||
|
|
||||||
// Calculate Totals
|
|
||||||
calculate();
|
|
||||||
} // loadBPartner
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Action Listener.
|
* Action Listener.
|
||||||
* - MultiCurrency
|
* - MultiCurrency
|
||||||
|
@ -652,239 +310,18 @@ public class VAllocation extends CPanel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Setting defaults
|
|
||||||
*/
|
|
||||||
if (m_calculating) // Avoid recursive calls
|
|
||||||
return;
|
|
||||||
m_calculating = true;
|
|
||||||
int row = e.getFirstRow();
|
int row = e.getFirstRow();
|
||||||
int col = e.getColumn();
|
int col = e.getColumn();
|
||||||
boolean isInvoice = (e.getSource().equals(invoiceTable.getModel()));
|
boolean isInvoice = (e.getSource().equals(invoiceTable.getModel()));
|
||||||
log.config("Row=" + row
|
boolean isAutoWriteOff = autoWriteOff.isSelected();
|
||||||
+ ", Col=" + col + ", InvoiceTable=" + isInvoice);
|
|
||||||
|
|
||||||
// Payments
|
String msg = writeOff(row, col, isInvoice, paymentTable, invoiceTable, isAutoWriteOff);
|
||||||
if (!isInvoice)
|
if(msg != null && msg.length() > 0)
|
||||||
{
|
ADialog.warn(m_WindowNo, panel, "AllocationWriteOffWarn");
|
||||||
TableModel payment = paymentTable.getModel();
|
|
||||||
|
|
||||||
BigDecimal open = (BigDecimal)payment.getValueAt(row, i_open);
|
|
||||||
BigDecimal applied = (BigDecimal)payment.getValueAt(row, i_payment);
|
|
||||||
|
|
||||||
if (col == 0)
|
|
||||||
{
|
|
||||||
// selection of payment row
|
|
||||||
if (((Boolean)payment.getValueAt(row, 0)).booleanValue())
|
|
||||||
{
|
|
||||||
applied = open; // Open Amount
|
|
||||||
if (totalDiff.abs().compareTo(applied.abs()) < 0 // where less is available to allocate than open
|
|
||||||
&& totalDiff.signum() == -applied.signum() ) // and the available amount has the opposite sign
|
|
||||||
applied = totalDiff.negate(); // reduce the amount applied to what's available
|
|
||||||
|
|
||||||
}
|
|
||||||
else // de-selected
|
|
||||||
applied = Env.ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (col == i_payment)
|
|
||||||
{
|
|
||||||
if ( applied.signum() == -open.signum() )
|
|
||||||
applied = applied.negate();
|
|
||||||
if ( open.abs().compareTo( applied.abs() ) < 0 )
|
|
||||||
applied = open;
|
|
||||||
}
|
|
||||||
|
|
||||||
payment.setValueAt(applied, row, i_payment);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoice
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TableModel invoice = invoiceTable.getModel();
|
|
||||||
boolean selected = ((Boolean) invoice.getValueAt(row, 0)).booleanValue();
|
|
||||||
BigDecimal open = (BigDecimal)invoice.getValueAt(row, i_open);
|
|
||||||
BigDecimal discount = (BigDecimal)invoice.getValueAt(row, i_discount);
|
|
||||||
BigDecimal applied = (BigDecimal)invoice.getValueAt(row, i_applied);
|
|
||||||
BigDecimal writeOff = (BigDecimal) invoice.getValueAt(row, i_writeOff);
|
|
||||||
BigDecimal overUnder = (BigDecimal) invoice.getValueAt(row, i_overUnder);
|
|
||||||
int openSign = open.signum();
|
|
||||||
|
|
||||||
if (col == 0) //selection
|
|
||||||
{
|
|
||||||
// selected - set applied amount
|
|
||||||
if ( selected )
|
|
||||||
{
|
|
||||||
applied = open; // Open Amount
|
|
||||||
applied = applied.subtract(discount);
|
|
||||||
writeOff = Env.ZERO; // to be sure
|
|
||||||
overUnder = Env.ZERO;
|
|
||||||
|
|
||||||
if (totalDiff.abs().compareTo(applied.abs()) < 0 // where less is available to allocate than open
|
|
||||||
&& totalDiff.signum() == applied.signum() ) // and the available amount has the same sign
|
|
||||||
applied = totalDiff; // reduce the amount applied to what's available
|
|
||||||
|
|
||||||
if ( autoWriteOff.isSelected() )
|
|
||||||
writeOff = open.subtract(applied.add(discount));
|
|
||||||
else
|
|
||||||
overUnder = open.subtract(applied.add(discount));
|
|
||||||
}
|
|
||||||
else // de-selected
|
|
||||||
{
|
|
||||||
writeOff = Env.ZERO;
|
|
||||||
applied = Env.ZERO;
|
|
||||||
overUnder = Env.ZERO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check entered values are sensible and possibly auto write-off
|
|
||||||
if ( selected && col != 0 )
|
|
||||||
{
|
|
||||||
|
|
||||||
// values should have same sign as open except possibly over/under
|
|
||||||
if ( discount.signum() == -openSign )
|
|
||||||
discount = discount.negate();
|
|
||||||
if ( writeOff.signum() == -openSign)
|
|
||||||
writeOff = writeOff.negate();
|
|
||||||
if ( applied.signum() == -openSign )
|
|
||||||
applied = applied.negate();
|
|
||||||
|
|
||||||
// discount and write-off must be less than open amount
|
|
||||||
if ( discount.abs().compareTo(open.abs()) > 0)
|
|
||||||
discount = open;
|
|
||||||
if ( writeOff.abs().compareTo(open.abs()) > 0)
|
|
||||||
writeOff = open;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Two rules to maintain:
|
|
||||||
*
|
|
||||||
* 1) |writeOff + discount| < |open|
|
|
||||||
* 2) discount + writeOff + overUnder + applied = 0
|
|
||||||
*
|
|
||||||
* As only one column is edited at a time and the initial position was one of compliance
|
|
||||||
* with the rules, we only need to redistribute the increase/decrease in the edited column to
|
|
||||||
* the others.
|
|
||||||
*/
|
|
||||||
BigDecimal newTotal = discount.add(writeOff).add(applied).add(overUnder); // all have same sign
|
|
||||||
BigDecimal difference = newTotal.subtract(open);
|
|
||||||
|
|
||||||
// rule 2
|
|
||||||
BigDecimal diffWOD = writeOff.add(discount).subtract(open);
|
|
||||||
|
|
||||||
if ( diffWOD.signum() == open.signum() ) // writeOff and discount are too large
|
|
||||||
{
|
|
||||||
if ( col == i_discount ) // then edit writeoff
|
|
||||||
{
|
|
||||||
writeOff = writeOff.subtract(diffWOD);
|
|
||||||
}
|
|
||||||
else // col = i_writeoff
|
|
||||||
{
|
|
||||||
discount = discount.subtract(diffWOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
difference = difference.subtract(diffWOD);
|
|
||||||
}
|
|
||||||
|
|
||||||
// rule 1
|
|
||||||
if ( col == i_applied )
|
|
||||||
overUnder = overUnder.subtract(difference);
|
|
||||||
else
|
|
||||||
applied = applied.subtract(difference);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warning if write Off > 30%
|
|
||||||
if (autoWriteOff.isSelected() && writeOff.doubleValue()/open.doubleValue() > .30)
|
|
||||||
ADialog.warn(m_WindowNo, this, "AllocationWriteOffWarn");
|
|
||||||
|
|
||||||
|
|
||||||
invoice.setValueAt(discount, row, i_discount);
|
|
||||||
invoice.setValueAt(applied, row, i_applied);
|
|
||||||
invoice.setValueAt(writeOff, row, i_writeOff);
|
|
||||||
invoice.setValueAt(overUnder, row, i_overUnder);
|
|
||||||
|
|
||||||
invoiceTable.repaint(); // update r/o
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
m_calculating = false;
|
|
||||||
calculate();
|
calculate();
|
||||||
} // tableChanged
|
} // tableChanged
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate Allocation info
|
|
||||||
*/
|
|
||||||
private void calculate ()
|
|
||||||
{
|
|
||||||
log.config("");
|
|
||||||
//
|
|
||||||
DecimalFormat format = DisplayType.getNumberFormat(DisplayType.Amount);
|
|
||||||
Timestamp allocDate = null;
|
|
||||||
|
|
||||||
// Payment
|
|
||||||
TableModel payment = paymentTable.getModel();
|
|
||||||
totalPay = new BigDecimal(0.0);
|
|
||||||
int rows = payment.getRowCount();
|
|
||||||
m_noPayments = 0;
|
|
||||||
for (int i = 0; i < rows; i++)
|
|
||||||
{
|
|
||||||
if (((Boolean)payment.getValueAt(i, 0)).booleanValue())
|
|
||||||
{
|
|
||||||
Timestamp ts = (Timestamp)payment.getValueAt(i, 1);
|
|
||||||
if ( !multiCurrency.isSelected() ) // the converted amounts are only valid for the selected date
|
|
||||||
allocDate = TimeUtil.max(allocDate, ts);
|
|
||||||
BigDecimal bd = (BigDecimal)payment.getValueAt(i, i_payment);
|
|
||||||
totalPay = totalPay.add(bd); // Applied Pay
|
|
||||||
m_noPayments++;
|
|
||||||
log.fine("Payment_" + i + " = " + bd + " - Total=" + totalPay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paymentInfo.setText(String.valueOf(m_noPayments) + " - "
|
|
||||||
+ Msg.getMsg(Env.getCtx(), "Sum") + " " + format.format(totalPay) + " ");
|
|
||||||
|
|
||||||
// Invoices
|
|
||||||
TableModel invoice = invoiceTable.getModel();
|
|
||||||
totalInv = new BigDecimal(0.0);
|
|
||||||
rows = invoice.getRowCount();
|
|
||||||
m_noInvoices = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < rows; i++)
|
|
||||||
{
|
|
||||||
if (((Boolean)invoice.getValueAt(i, 0)).booleanValue())
|
|
||||||
{
|
|
||||||
Timestamp ts = (Timestamp)invoice.getValueAt(i, 1);
|
|
||||||
if ( !multiCurrency.isSelected() ) // converted amounts only valid for selected date
|
|
||||||
allocDate = TimeUtil.max(allocDate, ts);
|
|
||||||
BigDecimal bd = (BigDecimal)invoice.getValueAt(i, i_applied);
|
|
||||||
totalInv = totalInv.add(bd); // Applied Inv
|
|
||||||
m_noInvoices++;
|
|
||||||
log.fine("Invoice_" + i + " = " + bd + " - Total=" + totalPay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
invoiceInfo.setText(String.valueOf(m_noInvoices) + " - "
|
|
||||||
+ Msg.getMsg(Env.getCtx(), "Sum") + " " + format.format(totalInv) + " ");
|
|
||||||
|
|
||||||
// Set AllocationDate
|
|
||||||
if (allocDate != null)
|
|
||||||
dateField.setValue(allocDate);
|
|
||||||
// Set Allocation Currency
|
|
||||||
allocCurrencyLabel.setText(currencyPick.getDisplay());
|
|
||||||
// Difference
|
|
||||||
totalDiff = totalPay.subtract(totalInv);
|
|
||||||
differenceField.setText(format.format(totalDiff));
|
|
||||||
|
|
||||||
if (totalDiff.compareTo(new BigDecimal(0.0)) == 0)
|
|
||||||
allocateButton.setEnabled(true);
|
|
||||||
else
|
|
||||||
allocateButton.setEnabled(false);
|
|
||||||
|
|
||||||
} // calculate
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Vetoable Change Listener.
|
* Vetoable Change Listener.
|
||||||
* - Business Partner
|
* - Business Partner
|
||||||
|
@ -898,6 +335,9 @@ public class VAllocation extends CPanel
|
||||||
Object value = e.getNewValue();
|
Object value = e.getNewValue();
|
||||||
log.config(name + "=" + value);
|
log.config(name + "=" + value);
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
return;
|
||||||
|
|
||||||
// Organization
|
// Organization
|
||||||
if (name.equals("AD_Org_ID"))
|
if (name.equals("AD_Org_ID"))
|
||||||
{
|
{
|
||||||
|
@ -909,9 +349,6 @@ public class VAllocation extends CPanel
|
||||||
loadBPartner();
|
loadBPartner();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// BPartner
|
// BPartner
|
||||||
if (name.equals("C_BPartner_ID"))
|
if (name.equals("C_BPartner_ID"))
|
||||||
{
|
{
|
||||||
|
@ -930,216 +367,83 @@ public class VAllocation extends CPanel
|
||||||
loadBPartner();
|
loadBPartner();
|
||||||
} // vetoableChange
|
} // vetoableChange
|
||||||
|
|
||||||
|
public void loadBPartner()
|
||||||
|
{
|
||||||
|
checkBPartner();
|
||||||
|
|
||||||
|
Vector<Vector<Object>> data = getPaymentData(multiCurrency.isSelected(), dateField.getValue(), paymentTable);
|
||||||
|
Vector<String> columnNames = getPaymentColumnNames(multiCurrency.isSelected());
|
||||||
|
|
||||||
|
// Remove previous listeners
|
||||||
|
paymentTable.getModel().removeTableModelListener(this);
|
||||||
|
|
||||||
|
// Set Model
|
||||||
|
DefaultTableModel modelP = new DefaultTableModel(data, columnNames);
|
||||||
|
modelP.addTableModelListener(this);
|
||||||
|
paymentTable.setModel(modelP);
|
||||||
|
setPaymentColumnClass(paymentTable, multiCurrency.isSelected());
|
||||||
|
//
|
||||||
|
|
||||||
|
data = getInvoiceData(multiCurrency.isSelected(), dateField.getValue(), invoiceTable);
|
||||||
|
columnNames = getInvoiceColumnNames(multiCurrency.isSelected());
|
||||||
|
|
||||||
|
// Remove previous listeners
|
||||||
|
invoiceTable.getModel().removeTableModelListener(this);
|
||||||
|
|
||||||
|
// Set Model
|
||||||
|
DefaultTableModel modelI = new DefaultTableModel(data, columnNames);
|
||||||
|
modelI.addTableModelListener(this);
|
||||||
|
invoiceTable.setModel(modelI);
|
||||||
|
setInvoiceColumnClass(invoiceTable, multiCurrency.isSelected());
|
||||||
|
//
|
||||||
|
|
||||||
|
calculate(multiCurrency.isSelected());
|
||||||
|
|
||||||
|
// Calculate Totals
|
||||||
|
calculate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void calculate()
|
||||||
|
{
|
||||||
|
allocDate = null;
|
||||||
|
|
||||||
|
paymentInfo.setText(calculatePayment(paymentTable, multiCurrency.isSelected()));
|
||||||
|
invoiceInfo.setText(calculateInvoice(invoiceTable, multiCurrency.isSelected()));
|
||||||
|
|
||||||
|
// Set AllocationDate
|
||||||
|
if (allocDate != null)
|
||||||
|
dateField.setValue(allocDate);
|
||||||
|
// Set Allocation Currency
|
||||||
|
allocCurrencyLabel.setText(currencyPick.getDisplay());
|
||||||
|
// Difference
|
||||||
|
totalDiff = totalPay.subtract(totalInv);
|
||||||
|
differenceField.setText(format.format(totalDiff));
|
||||||
|
|
||||||
|
if (totalDiff.compareTo(new BigDecimal(0.0)) == 0)
|
||||||
|
allocateButton.setEnabled(true);
|
||||||
|
else
|
||||||
|
allocateButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Save Data
|
* Save Data
|
||||||
*/
|
*/
|
||||||
private void saveData()
|
public void saveData()
|
||||||
{
|
{
|
||||||
if (m_noInvoices + m_noPayments == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Trx.run(new TrxRunnable()
|
Trx.run(new TrxRunnable()
|
||||||
{
|
{
|
||||||
public void run(String trxName)
|
public void run(String trxName)
|
||||||
{
|
{
|
||||||
// fixed fields
|
statusBar.setStatusLine(saveData(m_WindowNo, dateField.getValue(), paymentTable, invoiceTable, trxName));
|
||||||
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);
|
|
||||||
new AdempiereException("@Org0NotAllowed@");
|
|
||||||
}
|
}
|
||||||
//
|
});
|
||||||
log.config("Client=" + AD_Client_ID + ", Org=" + AD_Org_ID
|
|
||||||
+ ", BPartner=" + C_BPartner_ID + ", Date=" + DateTrx);
|
|
||||||
|
|
||||||
// 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
|
|
||||||
if (((Boolean)payment.getValueAt(i, 0)).booleanValue())
|
|
||||||
{
|
|
||||||
KeyNamePair pp = (KeyNamePair)payment.getValueAt(i, 2); // Value
|
|
||||||
// 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"), trxName);
|
|
||||||
alloc.setAD_Org_ID(AD_Org_ID);
|
|
||||||
alloc.saveEx();
|
|
||||||
// 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();
|
|
||||||
BigDecimal PaymentAmt = (BigDecimal)amountList.get(j);
|
|
||||||
if (PaymentAmt.signum() == AppliedAmt.signum()) // only match same sign (otherwise appliedAmt increases)
|
|
||||||
{ // and not zero (appliedAmt was checked earlier)
|
|
||||||
log.config(".. with payment #" + j + ", Amt=" + PaymentAmt);
|
|
||||||
|
|
||||||
BigDecimal amount = AppliedAmt;
|
|
||||||
if (amount.abs().compareTo(PaymentAmt.abs()) > 0) // if there's more open on the invoice
|
|
||||||
amount = PaymentAmt; // than left in the payment
|
|
||||||
|
|
||||||
// Allocation Line
|
|
||||||
MAllocationLine aLine = new MAllocationLine (alloc, amount,
|
|
||||||
DiscountAmt, WriteOffAmt, OverUnderAmt);
|
|
||||||
aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID);
|
|
||||||
aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID);
|
|
||||||
aLine.saveEx();
|
|
||||||
|
|
||||||
// Apply Discounts and WriteOff only first time
|
|
||||||
DiscountAmt = Env.ZERO;
|
|
||||||
WriteOffAmt = Env.ZERO;
|
|
||||||
// subtract amount from Payment/Invoice
|
|
||||||
AppliedAmt = AppliedAmt.subtract(amount);
|
|
||||||
PaymentAmt = PaymentAmt.subtract(amount);
|
|
||||||
log.fine("Allocation Amount=" + amount + " - Remaining Applied=" + AppliedAmt + ", Payment=" + PaymentAmt);
|
|
||||||
amountList.set(j, PaymentAmt); // update
|
|
||||||
} // for all applied amounts
|
|
||||||
} // loop through payments for invoice
|
|
||||||
|
|
||||||
if ( AppliedAmt.signum() == 0 && DiscountAmt.signum() == 0 && WriteOffAmt.signum() == 0)
|
|
||||||
continue;
|
|
||||||
else { // remainder will need to match against other invoices
|
|
||||||
int C_Payment_ID = 0;
|
|
||||||
|
|
||||||
// Allocation Line
|
|
||||||
MAllocationLine aLine = new MAllocationLine (alloc, AppliedAmt,
|
|
||||||
DiscountAmt, WriteOffAmt, OverUnderAmt);
|
|
||||||
aLine.setDocInfo(C_BPartner_ID, C_Order_ID, C_Invoice_ID);
|
|
||||||
aLine.setPaymentInfo(C_Payment_ID, C_CashLine_ID);
|
|
||||||
aLine.saveEx();
|
|
||||||
log.fine("Allocation Amount=" + AppliedAmt);
|
|
||||||
unmatchedApplied = unmatchedApplied.add(AppliedAmt);
|
|
||||||
}
|
|
||||||
} // invoice selected
|
|
||||||
} // invoice loop
|
|
||||||
|
|
||||||
// check for unapplied payment amounts (eg from payment reversals)
|
|
||||||
for (int i = 0; i < paymentList.size(); i++) {
|
|
||||||
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());
|
|
||||||
}});
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
ADialog.error(m_WindowNo, this, "Error", e.getLocalizedMessage());
|
ADialog.error(m_WindowNo, panel, "Error", e.getLocalizedMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} // saveData
|
} // saveData
|
||||||
|
}
|
||||||
|
|
||||||
} // VAllocation
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue