📄 doc_allocation.java
字号:
/******************************************************************************
* The contents of this file are subject to the Compiere License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.compiere.org/license.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Original Code is Compiere ERP & CRM Smart Business Solution. The Initial
* Developer of the Original Code is Jorg Janke. Portions created by Jorg Janke
* are Copyright (C) 1999-2005 Jorg Janke.
* All parts are Copyright (C) 1999-2005 ComPiere, Inc. All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
package org.compiere.acct;
import java.math.*;
import java.sql.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.model.*;
import org.compiere.util.*;
/**
* Post Allocation Documents.
* <pre>
* Table: C_AllocationHdr
* Document Types: CMA
* </pre>
* @author Jorg Janke
* @version $Id: Doc_Allocation.java,v 1.17 2005/10/28 01:00:53 jjanke Exp $
*/
public class Doc_Allocation extends Doc
{
/**
* Constructor
* @param ass accounting schemata
* @param rs record
* @parem trxName trx
*/
protected Doc_Allocation (MAcctSchema[] ass, ResultSet rs, String trxName)
{
super (ass, MAllocationHdr.class, rs, DOCTYPE_Allocation, trxName);
} // Doc_Allocation
/** Tolearance G&L */
private static final BigDecimal TOLERANCE = new BigDecimal (0.02);
/** Facts */
private ArrayList<Fact> m_facts = null;
/**
* Load Specific Document Details
* @return error message or null
*/
protected String loadDocumentDetails ()
{
MAllocationHdr alloc = (MAllocationHdr)getPO();
setDateDoc(alloc.getDateTrx());
// Contained Objects
p_lines = loadLines(alloc);
return null;
} // loadDocumentDetails
/**
* Load Invoice Line
* @return DocLine Array
*/
private DocLine[] loadLines(MAllocationHdr alloc)
{
ArrayList<DocLine> list = new ArrayList<DocLine>();
MAllocationLine[] lines = alloc.getLines(false);
for (int i = 0; i < lines.length; i++)
{
MAllocationLine line = lines[i];
DocLine_Allocation docLine = new DocLine_Allocation(line, this);
// Get Payment Conversion Rate
if (line.getC_Payment_ID() != 0)
{
MPayment payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
int C_ConversionType_ID = payment.getC_ConversionType_ID();
docLine.setC_ConversionType_ID(C_ConversionType_ID);
}
//
log.fine(docLine.toString());
list.add (docLine);
}
// Return Array
DocLine[] dls = new DocLine[list.size()];
list.toArray(dls);
return dls;
} // loadLines
/**************************************************************************
* Get Source Currency Balance - subtracts line and tax amounts from total - no rounding
* @return positive amount, if total invoice is bigger than lines
*/
public BigDecimal getBalance()
{
BigDecimal retValue = Env.ZERO;
return retValue;
} // getBalance
/**
* Create Facts (the accounting logic) for
* CMA.
* <pre>
* AR_Invoice_Payment
* UnAllocatedCash DR
* or C_Prepayment
* DiscountExp DR
* WriteOff DR
* Receivables CR
* AR_Invoice_Cash
* CashTransfer DR
* DiscountExp DR
* WriteOff DR
* Receivables CR
*
* AP_Invoice_Payment
* Liability DR
* DiscountRev CR
* WriteOff CR
* PaymentSelect CR
* or V_Prepayment
* AP_Invoice_Cash
* Liability DR
* DiscountRev CR
* WriteOff CR
* CashTransfer CR
* CashBankTransfer
* -
* ==============================
* Realized Gain & Loss
* AR/AP DR CR
* Realized G/L DR CR
*
*
* </pre>
* Tax needs to be corrected for discount & write-off;
* Currency gain & loss is realized here.
* @param as accounting schema
* @return Fact
*/
public ArrayList<Fact> createFacts (MAcctSchema as)
{
m_facts = new ArrayList<Fact>();
// create Fact Header
Fact fact = new Fact(this, as, Fact.POST_Actual);
for (int i = 0; i < p_lines.length; i++)
{
DocLine_Allocation line = (DocLine_Allocation)p_lines[i];
setC_BPartner_ID(line.getC_BPartner_ID());
// CashBankTransfer - all references null and Discount/WriteOff = 0
if (line.getC_Payment_ID() != 0
&& line.getC_Invoice_ID() == 0 && line.getC_Order_ID() == 0
&& line.getC_CashLine_ID() == 0 && line.getC_BPartner_ID() == 0
&& Env.ZERO.compareTo(line.getDiscountAmt()) == 0
&& Env.ZERO.compareTo(line.getWriteOffAmt()) == 0)
continue;
// Receivables/Liability Amt
BigDecimal allocationSource = line.getAmtSource()
.add(line.getDiscountAmt())
.add(line.getWriteOffAmt());
BigDecimal allocationAccounted = null; // AR/AP balance corrected
FactLine fl = null;
MAccount bpAcct = null; // Liability/Receivables
//
MPayment payment = null;
if (line.getC_Payment_ID() != 0)
payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
MInvoice invoice = null;
if (line.getC_Invoice_ID() != 0)
invoice = new MInvoice (getCtx(), line.getC_Invoice_ID(), null);
// No Invoice
if (invoice == null)
{
// Payment Only
if (line.getC_Invoice_ID() == 0 && line.getC_Payment_ID() != 0)
{
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
getC_Currency_ID(), line.getAmtSource(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
else
{
p_Error = "Cannot determine SO/PO";
log.log(Level.SEVERE, p_Error);
return null;
}
}
// Sales Invoice
else if (invoice.isSOTrx())
{
// Payment/Cash DR
if (line.getC_Payment_ID() != 0)
{
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
getC_Currency_ID(), line.getAmtSource(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
else if (line.getC_CashLine_ID() != 0)
{
fl = fact.createLine (line, getCashAcct(as, line.getC_CashLine_ID()),
getC_Currency_ID(), line.getAmtSource(), null);
MCashLine cashLine = new MCashLine (getCtx(), line.getC_CashLine_ID(), getTrxName());
if (fl != null && cashLine.get_ID() != 0)
fl.setAD_Org_ID(cashLine.getAD_Org_ID());
}
// Discount DR
if (Env.ZERO.compareTo(line.getDiscountAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_DiscountExp, as),
getC_Currency_ID(), line.getDiscountAmt(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// Write off DR
if (Env.ZERO.compareTo(line.getWriteOffAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_WriteOff, as),
getC_Currency_ID(), line.getWriteOffAmt(), null);
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// AR Invoice Amount CR
if (as.isAccrual())
{
bpAcct = getAccount(Doc.ACCTTYPE_C_Receivable, as);
fl = fact.createLine (line, bpAcct,
getC_Currency_ID(), null, allocationSource); // payment currency
if (fl != null)
allocationAccounted = fl.getAcctBalance().negate();
if (fl != null && invoice != null)
fl.setAD_Org_ID(invoice.getAD_Org_ID());
}
else // Cash Based
{
allocationAccounted = createCashBasedAcct (as, fact,
invoice, allocationSource);
}
}
// Purchase Invoice
else
{
allocationSource = allocationSource.negate(); // allocation is negative
// AP Invoice Amount DR
if (as.isAccrual())
{
bpAcct = getAccount(Doc.ACCTTYPE_V_Liability, as);
fl = fact.createLine (line, bpAcct,
getC_Currency_ID(), allocationSource, null); // payment currency
if (fl != null)
allocationAccounted = fl.getAcctBalance();
if (fl != null && invoice != null)
fl.setAD_Org_ID(invoice.getAD_Org_ID());
}
else // Cash Based
{
allocationAccounted = createCashBasedAcct (as, fact,
invoice, allocationSource);
}
// Discount CR
if (Env.ZERO.compareTo(line.getDiscountAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_DiscountRev, as),
getC_Currency_ID(), null, line.getDiscountAmt().negate());
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// Write off CR
if (Env.ZERO.compareTo(line.getWriteOffAmt()) != 0)
{
fl = fact.createLine (line, getAccount(Doc.ACCTTYPE_WriteOff, as),
getC_Currency_ID(), null, line.getWriteOffAmt().negate());
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
// Payment/Cash CR
if (line.getC_Payment_ID() != 0)
{
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
getC_Currency_ID(), null, line.getAmtSource().negate());
if (fl != null && payment != null)
fl.setAD_Org_ID(payment.getAD_Org_ID());
}
else if (line.getC_CashLine_ID() != 0)
{
fl = fact.createLine (line, getCashAcct(as, line.getC_CashLine_ID()),
getC_Currency_ID(), null, line.getAmtSource().negate());
MCashLine cashLine = new MCashLine (getCtx(), line.getC_CashLine_ID(), getTrxName());
if (fl != null && cashLine.get_ID() != 0)
fl.setAD_Org_ID(cashLine.getAD_Org_ID());
}
}
// VAT Tax Correction
if (as.isDiscountCorrectsTax() && invoice != null)
{
BigDecimal taxCorrectionAmt = line.getDiscountAmt()
.add(line.getWriteOffAmt());
if (as.isDiscountCorrectsTax() && Env.ZERO.compareTo(taxCorrectionAmt) != 0)
{
if (!createTaxCorrection(as, fact, line,
getAccount(invoice.isSOTrx() ? Doc.ACCTTYPE_DiscountExp : Doc.ACCTTYPE_DiscountRev, as),
getAccount(Doc.ACCTTYPE_WriteOff, as)))
{
p_Error = "Cannot create Tax correction";
return null;
}
}
}
// Realized Gain & Loss
if (invoice != null
&& (getC_Currency_ID() != as.getC_Currency_ID() // payment allocation in foreign currency
|| getC_Currency_ID() != line.getInvoiceC_Currency_ID())) // allocation <> invoice currency
{
p_Error = createRealizedGainLoss (as, fact, bpAcct, invoice,
allocationSource, allocationAccounted);
if (p_Error != null)
return null;
}
} // for all lines
// reset line info
setC_BPartner_ID(0);
//
m_facts.add(fact);
return m_facts;
} // createFact
/**
* Create Cash Based Acct
* @param fact fact
* @param invoice invoice
* @param allocationSource allocation amount (incl discount, writeoff)
* @return Accounted Amt
*/
private BigDecimal createCashBasedAcct (MAcctSchema as, Fact fact, MInvoice invoice,
BigDecimal allocationSource)
{
BigDecimal allocationAccounted = Env.ZERO;
// Multiplier
double percent = invoice.getGrandTotal().doubleValue() / allocationSource.doubleValue();
if (percent > 0.99 && percent < 1.01)
percent = 1.0;
log.config("Multiplier=" + percent + " - GrandTotal=" + invoice.getGrandTotal()
+ " - Allocation Source=" + allocationSource);
// Get Invoice Postings
Doc_Invoice docInvoice = (Doc_Invoice)Doc.get(new MAcctSchema[]{as},
MInvoice.Table_ID, invoice.getC_Invoice_ID(), getTrxName());
docInvoice.loadDocumentDetails();
allocationAccounted = docInvoice.createFactCash(as, fact, new BigDecimal(percent));
log.config("Allocation Accounted=" + allocationAccounted);
// Cash Based Commitment Release
if (as.isCreateCommitment() && !invoice.isSOTrx())
{
MInvoiceLine[] lines = invoice.getLines();
for (int i = 0; i < lines.length; i++)
{
Fact factC = Doc_Order.getCommitmentRelease(as, this,
lines[i].getQtyInvoiced(), lines[i].getC_InvoiceLine_ID(), new BigDecimal(percent));
if (factC == null)
return null;
m_facts.add(factC);
}
} // Commitment
return allocationAccounted;
} // createCashBasedAcct
/**
* Get Payment (Unallocated Payment or Payment Selection) Acct of Bank Account
* @param as accounting schema
* @param C_Payment_ID payment
* @return acct
*/
private MAccount getPaymentAcct (MAcctSchema as, int C_Payment_ID)
{
setC_BankAccount_ID(0);
// Doc.ACCTTYPE_UnallocatedCash (AR) or C_Prepayment
// or Doc.ACCTTYPE_PaymentSelect (AP) or V_Prepayment
int accountType = Doc.ACCTTYPE_UnallocatedCash;
//
String sql = "SELECT p.C_BankAccount_ID, d.DocBaseType, p.IsReceipt, p.IsPrepayment "
+ "FROM C_Payment p INNER JOIN C_DocType d ON (p.C_DocType_ID=d.C_DocType_ID) "
+ "WHERE C_Payment_ID=?";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, getTrxName());
pstmt.setInt (1, C_Payment_ID);
ResultSet rs = pstmt.executeQuery ();
if (rs.next ())
{
setC_BankAccount_ID(rs.getInt(1));
if (DOCTYPE_APPayment.equals(rs.getString(2)))
accountType = Doc.ACCTTYPE_PaymentSelect;
// Prepayment
if ("Y".equals(rs.getString(4))) // Prepayment
{
if ("Y".equals(rs.getString(3))) // Receipt
accountType = Doc.ACCTTYPE_C_Prepayment;
else
accountType = Doc.ACCTTYPE_V_Prepayment;
}
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
log.log(Level.SEVERE, sql, e);
}
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -