/******************************************************************************
* 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.grid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Vector;
import java.util.logging.Level;
import org.compiere.apps.IStatusBar;
import org.compiere.minigrid.IMiniTable;
import org.compiere.model.GridTab;
import org.compiere.model.MInOut;
import org.compiere.model.MInvoice;
import org.compiere.model.MOrder;
import org.compiere.model.MProduct;
import org.compiere.model.MRMA;
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;
/**
* Create Invoice Lines from Purchase Order, Material Receipt or Vendor RMA
*
* @author Jorg Janke
* @version $Id: VCreateFromInvoice.java,v 1.4 2006/07/30 00:51:28 jjanke Exp $
*
* @author Teo Sarca, SC ARHIPAC SERVICE SRL
*
BF [ 1896947 ] Generate invoice from Order error
*
BF [ 2007837 ] VCreateFrom.save() should run in trx
*/
public abstract class CreateFromInvoice extends CreateFrom
{
/**
* Constructor
* @param mTab MTab
*/
public CreateFromInvoice(GridTab mTab)
{
super(mTab);
if (log.isLoggable(Level.INFO)) log.info(mTab.toString());
} // CreateFromInvoice
@Override
protected boolean dynInit() throws Exception
{
log.config("");
setTitle(Msg.getElement(Env.getCtx(), "C_Invoice_ID", false) + " .. " + Msg.translate(Env.getCtx(), "CreateFrom"));
return true;
} // dynInit
/**
* Load BPartner related Shipment records.
* @param C_BPartner_ID
* @return list of shipment records
*/
protected ArrayList loadShipmentData (int C_BPartner_ID)
{
String isSOTrxParam = isSOTrx ? "Y":"N";
ArrayList list = new ArrayList();
// Display
StringBuffer display = new StringBuffer("s.DocumentNo||' - '||")
.append(DB.TO_CHAR("s.MovementDate", DisplayType.Date, Env.getAD_Language(Env.getCtx())));
//
StringBuffer sql = new StringBuffer("SELECT s.M_InOut_ID,").append(display)
.append(" FROM M_InOut s "
+ "WHERE s.C_BPartner_ID=? AND s.IsSOTrx=? AND s.DocStatus IN ('CL','CO')"
+ " AND s.M_InOut_ID IN "
+ "(SELECT sl.M_InOut_ID FROM M_InOutLine sl");
if(!isSOTrx)
sql.append(" LEFT OUTER JOIN M_MatchInv mi ON (sl.M_InOutLine_ID=mi.M_InOutLine_ID) "
+ " JOIN M_InOut s2 ON (sl.M_InOut_ID=s2.M_InOut_ID) "
+ " WHERE s2.C_BPartner_ID=? AND s2.IsSOTrx=? AND s2.DocStatus IN ('CL','CO') "
+ " GROUP BY sl.M_InOut_ID,sl.MovementQty,s2.MovementType,mi.M_InOutLine_ID"
+ " HAVING (sl.MovementQty <> SUM(mi.Qty) * CASE WHEN s2.MovementType = 'V-' THEN -1 ELSE 1 END"
+ " AND mi.M_InOutLine_ID IS NOT NULL) OR mi.M_InOutLine_ID IS NULL ");
else
sql.append(" INNER JOIN M_InOut s2 ON (sl.M_InOut_ID=s2.M_InOut_ID)"
+ " LEFT JOIN C_InvoiceLine il ON sl.M_InOutLine_ID = il.M_InOutLine_ID"
+ " WHERE s2.C_BPartner_ID=? AND s2.IsSOTrx=? AND s2.DocStatus IN ('CL','CO')"
+ " GROUP BY sl.M_InOutLine_ID"
+ " HAVING sl.MovementQty - sum(COALESCE(il.QtyInvoiced,0)) > 0");
sql.append(") ORDER BY s.MovementDate");
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement(sql.toString(), getTrxName());
pstmt.setInt(1, C_BPartner_ID);
pstmt.setString(2, isSOTrxParam);
pstmt.setInt(3, C_BPartner_ID);
pstmt.setString(4, isSOTrxParam);
rs = pstmt.executeQuery();
while (rs.next())
{
list.add(new KeyNamePair(rs.getInt(1), rs.getString(2)));
}
}
catch (SQLException e)
{
log.log(Level.SEVERE, sql.toString(), e);
}
finally
{
DB.close(rs, pstmt);
rs = null;
pstmt = null;
}
return list;
}
/**
* Load BPartner related RMA records
* @param C_BPartner_ID BPartner
* @return list of RMA records
*/
protected ArrayList loadRMAData(int C_BPartner_ID) {
ArrayList list = new ArrayList();
String sqlStmt = "SELECT r.M_RMA_ID, r.DocumentNo || '-' || r.Amt from M_RMA r "
+ "INNER JOIN M_RMALine l ON (l.M_RMA_ID = r.M_RMA_ID) "
+ "WHERE ISSOTRX='N' AND r.DocStatus in ('CO', 'CL') "
+ "AND r.C_BPartner_ID=? "
+ "AND COALESCE(l.QtyInvoiced,0) < l.Qty ";
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
pstmt = DB.prepareStatement(sqlStmt, getTrxName());
pstmt.setInt(1, C_BPartner_ID);
rs = pstmt.executeQuery();
while (rs.next()) {
list.add(new KeyNamePair(rs.getInt(1), rs.getString(2)));
}
} catch (SQLException e) {
log.log(Level.SEVERE, sqlStmt.toString(), e);
} finally{
DB.close(rs, pstmt);
rs = null;
pstmt = null;
}
return list;
}
/**
* Load Shipment Lines not invoiced
* @param M_InOut_ID InOut
* @return shipment lines (selection,qty,[c_uom_id,uomSymbol/name],[m_product_id,name],vendorProductNo,[c_orderline_id,.],[m_inoutline_id,line],null)
*/
protected Vector> getShipmentData(int M_InOut_ID)
{
if (log.isLoggable(Level.CONFIG)) log.config("M_InOut_ID=" + M_InOut_ID);
MInOut inout = new MInOut(Env.getCtx(), M_InOut_ID, getTrxName());
p_order = null;
if (inout.getC_Order_ID() != 0)
p_order = new MOrder (Env.getCtx(), inout.getC_Order_ID(), getTrxName());
m_rma = null;
if (inout.getM_RMA_ID() != 0)
m_rma = new MRMA (Env.getCtx(), inout.getM_RMA_ID(), getTrxName());
//
Vector> data = new Vector>();
StringBuilder sql = new StringBuilder("SELECT "); // QtyEntered
if(!isSOTrx)
sql.append("l.Movementqty-SUM(COALESCE(mi.Qty, 0))*CASE WHEN io.MovementType = 'V-' THEN -1 ELSE 1 END,");
else
sql.append("l.MovementQty-SUM(COALESCE(il.QtyInvoiced,0)),");
sql.append(" l.QtyEntered/l.MovementQty,"
+ " l.C_UOM_ID, COALESCE(uom.UOMSymbol, uom.Name)," // 3..4
+ " l.M_Product_ID, p.Name, po.VendorProductNo, l.M_InOutLine_ID, l.Line," // 5..9
+ " l.C_OrderLine_ID " // 10
+ " FROM M_InOutLine l "
);
if (Env.isBaseLanguage(Env.getCtx(), "C_UOM"))
sql.append(" LEFT OUTER JOIN C_UOM uom ON (l.C_UOM_ID=uom.C_UOM_ID)");
else
sql.append(" LEFT OUTER JOIN C_UOM_Trl uom ON (l.C_UOM_ID=uom.C_UOM_ID AND uom.AD_Language='")
.append(Env.getAD_Language(Env.getCtx())).append("')");
sql.append(" LEFT OUTER JOIN M_Product p ON (l.M_Product_ID=p.M_Product_ID)")
.append(" INNER JOIN M_InOut io ON (l.M_InOut_ID=io.M_InOut_ID)");
if(!isSOTrx)
sql.append(" LEFT OUTER JOIN M_MatchInv mi ON (l.M_InOutLine_ID=mi.M_InOutLine_ID)");
else
sql.append(" LEFT JOIN C_InvoiceLine il ON l.M_InOutLine_ID = il.M_InOutLine_ID");
sql.append(" LEFT OUTER JOIN M_Product_PO po ON (l.M_Product_ID = po.M_Product_ID AND io.C_BPartner_ID = po.C_BPartner_ID)")
.append(" WHERE l.M_InOut_ID=? AND l.MovementQty<>0 ")
.append("GROUP BY l.MovementQty, l.QtyEntered/l.MovementQty, "
+ "l.C_UOM_ID, COALESCE(uom.UOMSymbol, uom.Name), "
+ "l.M_Product_ID, p.Name, po.VendorProductNo, l.M_InOutLine_ID, l.Line, l.C_OrderLine_ID, io.MovementType ");
if(!isSOTrx)
sql.append(" HAVING l.MovementQty-SUM(COALESCE(mi.Qty, 0)) <>0");
else
sql.append(" HAVING l.MovementQty-SUM(COALESCE(il.QtyInvoiced,0)) <>0");
sql.append(" ORDER BY l.Line");
PreparedStatement pstmt = null;
ResultSet rs = null;
try
{
pstmt = DB.prepareStatement(sql.toString(), getTrxName());
pstmt.setInt(1, M_InOut_ID);
rs = pstmt.executeQuery();
while (rs.next())
{
Vector