/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* 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. *
* 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.model;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.Properties;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
/**
* Cash Line Model
*
* @author Jorg Janke
* @version $Id: MCashLine.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $
*
* @author Teo Sarca, SC ARHIPAC SERVICE SRL
*
BF [ 1760240 ] CashLine bank account is filled even if is not bank transfer
* BF [ 1918266 ] MCashLine.updateHeader should ignore not active lines
* BF [ 1918290 ] MCashLine.createReversal should inactivate if not processed
*/
public class MCashLine extends X_C_CashLine
{
/**
* generated serial id
*/
private static final long serialVersionUID = 5023249596033465923L;
/**
* UUID based Constructor
* @param ctx Context
* @param C_CashLine_UU UUID key
* @param trxName Transaction
*/
public MCashLine(Properties ctx, String C_CashLine_UU, String trxName) {
super(ctx, C_CashLine_UU, trxName);
if (Util.isEmpty(C_CashLine_UU))
setInitialDefaults();
}
/**
* Standard Constructor
* @param ctx context
* @param C_CashLine_ID id
* @param trxName transaction
*/
public MCashLine (Properties ctx, int C_CashLine_ID, String trxName)
{
super (ctx, C_CashLine_ID, trxName);
if (C_CashLine_ID == 0)
setInitialDefaults();
} // MCashLine
/**
* Set the initial defaults for a new record
*/
private void setInitialDefaults() {
setAmount (Env.ZERO);
setDiscountAmt(Env.ZERO);
setWriteOffAmt(Env.ZERO);
setIsGenerated(false);
}
/**
* Load Constructor
* @param ctx context
* @param rs result set
* @param trxName transaction
*/
public MCashLine (Properties ctx, ResultSet rs, String trxName)
{
super(ctx, rs, trxName);
} // MCashLine
/**
* Parent Constructor
* @param cash parent
*/
public MCashLine (MCash cash)
{
this (cash.getCtx(), 0, cash.get_TrxName());
setClientOrg(cash);
setC_Cash_ID(cash.getC_Cash_ID());
m_parent = cash;
} // MCashLine
/**
* @param ctx
* @param C_CashLine_ID
* @param trxName
* @param virtualColumns
*/
public MCashLine(Properties ctx, int C_CashLine_ID, String trxName, String... virtualColumns) {
super(ctx, C_CashLine_ID, trxName, virtualColumns);
}
/** Parent */
protected MCash m_parent = null;
/** Bank Account */
protected MBankAccount m_bankAccount = null;
/** Invoice */
protected MInvoice m_invoice = null;
/**
* Add to Description
* @param description text
*/
public void addDescription (String description)
{
String desc = getDescription();
if (desc == null)
setDescription(description);
else
setDescription(desc + " | " + description);
} // addDescription
/**
* Set Invoice - no discount
* @param invoice invoice
*/
public void setInvoice (MInvoice invoice)
{
setC_Invoice_ID(invoice.getC_Invoice_ID());
setCashType (CASHTYPE_Invoice);
setC_Currency_ID(invoice.getC_Currency_ID());
// Amount
MDocType dt = MDocType.get(getCtx(), invoice.getC_DocType_ID());
BigDecimal amt = invoice.getGrandTotal();
if (MDocType.DOCBASETYPE_APInvoice.equals(dt.getDocBaseType())
|| MDocType.DOCBASETYPE_ARCreditMemo.equals(dt.getDocBaseType()) )
amt = amt.negate();
setAmount (amt);
//
setDiscountAmt(Env.ZERO);
setWriteOffAmt(Env.ZERO);
setIsGenerated(true);
m_invoice = invoice;
} // setInvoiceLine
/**
* Set Order - no discount
* @param order order
* @param trxName transaction
*/
public void setOrder (MOrder order, String trxName)
{
setCashType (CASHTYPE_Invoice);
setC_Currency_ID(order.getC_Currency_ID());
// Amount
BigDecimal amt = order.getGrandTotal();
setAmount (amt);
setDiscountAmt(Env.ZERO);
setWriteOffAmt(Env.ZERO);
setIsGenerated(true);
//
if (MOrder.DOCSTATUS_WaitingPayment.equals(order.getDocStatus()))
{
saveEx(trxName);
order.setC_CashLine_ID(getC_CashLine_ID());
// added AdempiereException by Zuhri
if (!order.processIt(MOrder.ACTION_WaitComplete))
throw new AdempiereException(Msg.getMsg(getCtx(), "FailedProcessingDocument") + " - " + order.getProcessMsg());
// end added
order.saveEx(trxName);
// Set Invoice
MInvoice[] invoices = order.getInvoices();
int length = invoices.length;
if (length > 0) // get last invoice
{
m_invoice = invoices[length-1];
setC_Invoice_ID (m_invoice.getC_Invoice_ID());
}
}
} // setOrder
/**
* Get Statement Date from header
* @return date
*/
public Timestamp getStatementDate()
{
return getParent().getStatementDate();
} // getStatementDate
/**
* Create Line Reversal or inactivate this line if it is not processed
* @return new reversed CashLine or this instance if not processed
*/
public MCashLine createReversal()
{
MCash parent = getParent();
if (parent.isProcessed())
{ // saved
parent = MCash.get(getCtx(), parent.getAD_Org_ID(),
parent.getStatementDate(), parent.getC_Currency_ID(), get_TrxName());
}
// Inactivate not processed lines - teo_sarca BF [ 1918290 ]
else
{
this.setIsActive(false);
return this;
}
//
MCashLine reversal = new MCashLine (parent);
reversal.setClientOrg(this);
reversal.setC_BankAccount_ID(getC_BankAccount_ID());
reversal.setC_Charge_ID(getC_Charge_ID());
reversal.setC_Currency_ID(getC_Currency_ID());
reversal.setC_Invoice_ID(getC_Invoice_ID());
reversal.setCashType(getCashType());
reversal.setDescription(getDescription());
reversal.setIsGenerated(true);
//
reversal.setAmount(getAmount().negate());
if (getDiscountAmt() == null)
setDiscountAmt(Env.ZERO);
else
reversal.setDiscountAmt(getDiscountAmt().negate());
if (getWriteOffAmt() == null)
setWriteOffAmt(Env.ZERO);
else
reversal.setWriteOffAmt(getWriteOffAmt().negate());
reversal.addDescription("(" + getLine() + ")");
return reversal;
} // reverse
/**
* Get MCash (parent)
* @return MCash
*/
public MCash getParent()
{
if (m_parent == null)
m_parent = new MCash (getCtx(), getC_Cash_ID(), get_TrxName());
return m_parent;
} // getCash
/**
* Get CashBook
* @return cash book
*/
public MCashBook getCashBook()
{
return getParent().getCashBook();
} // getCashBook
/**
* Get Bank Account
* @return bank account
*/
public MBankAccount getBankAccount()
{
if (m_bankAccount == null && getC_BankAccount_ID() != 0)
m_bankAccount = MBankAccount.getCopy(getCtx(), getC_BankAccount_ID(), get_TrxName());
return m_bankAccount;
} // getBankAccount
/**
* Get Invoice
* @return invoice
*/
public MInvoice getInvoice()
{
if (m_invoice == null && getC_Invoice_ID() != 0)
m_invoice = MInvoice.get(getCtx(), getC_Invoice_ID());
return m_invoice;
} // getInvoice
/**
* Before Delete
* @return true/false
*/
@Override
protected boolean beforeDelete ()
{
// Cannot Delete generated Invoices
Boolean generated = (Boolean)get_ValueOld("IsGenerated");
if (generated != null && generated.booleanValue())
{
if (get_ValueOld("C_Invoice_ID") != null)
{
log.saveError("Error", Msg.getMsg(getCtx(), "CannotDeleteCashGenInvoice"));
return false;
}
}
return true;
} // beforeDelete
/**
* After Delete
* @param success
* @return true/false
*/
@Override
protected boolean afterDelete (boolean success)
{
if (!success)
return success;
return updateHeader();
} // afterDelete
/**
* Before Save
* @param newRecord
* @return true/false
*/
@Override
protected boolean beforeSave (boolean newRecord)
{
if (newRecord && getParent().isProcessed()) {
log.saveError("ParentComplete", Msg.translate(getCtx(), "C_Cash_ID"));
return false;
}
// Cannot change generated Invoices
if (is_ValueChanged(COLUMNNAME_C_Invoice_ID))
{
Object generated = get_ValueOld(COLUMNNAME_IsGenerated);
if (generated != null && ((Boolean)generated).booleanValue())
{
log.saveError("Error", Msg.getMsg(getCtx(), "CannotChangeCashGenInvoice"));
return false;
}
}
// Verify CashType
if (CASHTYPE_Invoice.equals(getCashType()) && getC_Invoice_ID() == 0)
setCashType(CASHTYPE_GeneralExpense);
if (CASHTYPE_BankAccountTransfer.equals(getCashType()) && getC_BankAccount_ID() == 0)
setCashType(CASHTYPE_GeneralExpense);
if (CASHTYPE_Charge.equals(getCashType()) && getC_Charge_ID() == 0)
setCashType(CASHTYPE_GeneralExpense);
boolean verify = newRecord
|| is_ValueChanged("CashType")
|| is_ValueChanged("C_Invoice_ID")
|| is_ValueChanged("C_BankAccount_ID");
if (verify)
{
// Verify Currency
if (CASHTYPE_BankAccountTransfer.equals(getCashType()))
setC_Currency_ID(getBankAccount().getC_Currency_ID());
else if (CASHTYPE_Invoice.equals(getCashType()))
setC_Currency_ID(getInvoice().getC_Currency_ID());
else // Cash
setC_Currency_ID(getCashBook().getC_Currency_ID());
// Set Organization
if (CASHTYPE_BankAccountTransfer.equals(getCashType()))
setAD_Org_ID(getBankAccount().getAD_Org_ID());
// Cash Book
else if (CASHTYPE_Invoice.equals(getCashType()))
setAD_Org_ID(getCashBook().getAD_Org_ID());
// otherwise (charge) - leave it
// Enforce Org
if (getAD_Org_ID() == 0)
setAD_Org_ID(getParent().getAD_Org_ID());
}
// If CashType is not Bank Account Transfer, set C_BankAccount_ID to null - teo_sarca BF [ 1760240 ]
if (!CASHTYPE_BankAccountTransfer.equals(getCashType()))
setC_BankAccount_ID(I_ZERO);
// Get Line No
if (getLine() == 0)
{
String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM C_CashLine WHERE C_Cash_ID=?";
int ii = DB.getSQLValue (get_TrxName(), sql, getC_Cash_ID());
setLine (ii);
}
return true;
} // beforeSave
/**
* After Save
* @param newRecord
* @param success
* @return success
*/
@Override
protected boolean afterSave (boolean newRecord, boolean success)
{
if (!success)
return success;
return updateHeader();
} // afterSave
/**
* Update Cash Header (C_Cash).
* - Statement Difference, Ending Balance.
* @return true if success
*/
protected boolean updateHeader()
{
String sql = "UPDATE C_Cash c"
+ " SET StatementDifference="
//replace null with 0 there is no difference with this
+ "(SELECT COALESCE(SUM(currencyConvert(cl.Amount, cl.C_Currency_ID, cb.C_Currency_ID, c.DateAcct, 0, c.AD_Client_ID, c.AD_Org_ID)),0) "
+ "FROM C_CashLine cl, C_CashBook cb "
+ "WHERE cb.C_CashBook_ID=c.C_CashBook_ID"
+ " AND cl.C_Cash_ID=c.C_Cash_ID"
+ " AND cl.IsActive='Y'"
+") "
+ "WHERE C_Cash_ID=" + getC_Cash_ID();
int no = DB.executeUpdate(sql, get_TrxName());
if (no != 1)
log.warning("Difference #" + no);
// Ending Balance
sql = "UPDATE C_Cash"
+ " SET EndingBalance = BeginningBalance + StatementDifference "
+ "WHERE C_Cash_ID=" + getC_Cash_ID();
no = DB.executeUpdate(sql, get_TrxName());
if (no != 1)
log.warning("Balance #" + no);
return no == 1;
} // updateHeader
} // MCashLine