/***********************************************************************
* This file is part of iDempiere ERP Open Source *
* http://www.idempiere.org *
* *
* Copyright (C) Contributors *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* *
* 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., 51 Franklin Street, Fifth Floor, Boston, *
* MA 02110-1301, USA. *
**********************************************************************/
package org.compiere.model;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Properties;
import java.util.logging.Level;
import javax.servlet.http.HttpServletRequest;
import org.compiere.util.DB;
import org.compiere.util.EMail;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.compiere.util.Util;
/**
* Asset Model
* @author Teo Sarca, SC ARHIPAC SERVICE SRL
*/
@SuppressWarnings("serial")
public class MAsset extends X_A_Asset {
/** ChangeType - Asset Group changed */
public static final int CHANGETYPE_setAssetGroup = Table_ID * 100 + 1;
/**
* Get Asset
* @param ctx context
* @param A_Asset_ID asset
* @param trxName
*/
public static MAsset get (Properties ctx, int A_Asset_ID, String trxName)
{
return (MAsset)MTable.get(ctx, MAsset.Table_Name).getPO(A_Asset_ID, trxName);
} // get
/**
* Get Assets from given M_Product_ID and M_ASI_ID.
*
Note: The A_Asset_Product table is not checked !!!
* @param ctx
* @param M_Product_ID (optional)
* @param M_ASI_ID
* @return collection of MAsset
*/
public static Collection forASI(Properties ctx, int M_Product_ID, int M_ASI_ID)
{
ArrayList params = new ArrayList();
String whereClause = COLUMNNAME_M_AttributeSetInstance_ID + "=?";
params.add(M_ASI_ID);
if (M_Product_ID > 0) {
whereClause += " AND " + COLUMNNAME_M_Product_ID + "=?";
params.add(M_Product_ID);
}
//
return new Query(ctx, MAsset.Table_Name, whereClause, null)
.setParameters(params)
.list();
}
/**
* UUID based Constructor
* @param ctx Context
* @param A_Asset_UU UUID key
* @param trxName Transaction
*/
public MAsset(Properties ctx, String A_Asset_UU, String trxName) {
super(ctx, A_Asset_UU, trxName);
if (Util.isEmpty(A_Asset_UU))
setInitialDefaults();
}
/**
* @param ctx
* @param A_Asset_ID
* @param trxName
*/
public MAsset (Properties ctx, int A_Asset_ID, String trxName)
{
super (ctx, A_Asset_ID,trxName);
if (A_Asset_ID == 0)
setInitialDefaults();
} // MAsset
/**
* Set the initial defaults for a new record
*/
private void setInitialDefaults() {
setA_Asset_Status(A_ASSET_STATUS_New);
}
/**
* Load Constructor
* @param ctx context
* @param rs result set record
*/
public MAsset (Properties ctx, ResultSet rs, String trxName)
{
super (ctx, rs, trxName);
} // MAsset
/**
* Construct from MMatchInv
* @param match match invoice
*/
protected MAsset (MMatchInv match)
{
this(match.getCtx(), 0, match.get_TrxName());
MInvoiceLine invoiceLine = new MInvoiceLine(getCtx(), match.getC_InvoiceLine_ID(), get_TrxName());
MInOutLine inoutLine = new MInOutLine(getCtx(), match.getM_InOutLine_ID(), get_TrxName());
setIsOwned(true);
setIsInPosession(true);
setA_Asset_CreateDate(inoutLine.getM_InOut().getMovementDate());
//Fixed Asset should created in Organization as per the PO, MR, invoice and the asset addition document was recorded in.
setAD_Org_ID(invoiceLine.getAD_Org_ID());
// Asset Group:
int A_Asset_Group_ID = invoiceLine.getA_Asset_Group_ID();
MProduct product = MProduct.get(getCtx(), invoiceLine.getM_Product_ID());
if (A_Asset_Group_ID <= 0) {
A_Asset_Group_ID = product.getA_Asset_Group_ID();
}
setA_Asset_Group_ID(A_Asset_Group_ID);
setHelp(Msg.getMsg(MClient.get(getCtx()).getAD_Language(), "CreatedFromInvoiceLine",
new Object[] {invoiceLine.getC_Invoice().getDocumentNo(), invoiceLine.getLine()}));
String name = "";
if (inoutLine.getM_Product_ID()>0)
{
name += product.getName() + "-";
setM_Product_ID(inoutLine.getM_Product_ID());
setM_AttributeSetInstance_ID(inoutLine.getM_AttributeSetInstance_ID());
}
MBPartner bp = new MBPartner(getCtx(), invoiceLine.getC_Invoice().getC_BPartner_ID(), null);
name += bp.getName()+"-"+invoiceLine.getC_Invoice().getDocumentNo();
if (log.isLoggable(Level.FINE)) log.fine("name=" + name);
setValue(name);
setName(name);
setDescription(invoiceLine.getDescription());
}
/**
* Construct from MIFixedAsset (import)
* @param ifa
*/
protected MAsset (MIFixedAsset ifa)
{
this(ifa.getCtx(), 0, ifa.get_TrxName());
setAD_Org_ID(ifa.getAD_Org_ID()); //added by @win
setIsOwned(true);
setIsInPosession(true);
String inventoryNo = ifa.getInventoryNo();
if (inventoryNo != null) {
inventoryNo = inventoryNo.trim();
setInventoryNo(inventoryNo);
setValue(inventoryNo);
}
setA_Asset_CreateDate(ifa.getAssetServiceDate());
MProduct product = ifa.getProduct();
if (product != null) {
setM_Product_ID(product.getM_Product_ID());
setA_Asset_Group_ID(ifa.getA_Asset_Group_ID());
MAttributeSetInstance asi = MAttributeSetInstance.create(getCtx(), product, get_TrxName());
setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID());
}
setDateAcct(ifa.getDateAcct());
setName(ifa.getName());
setDescription(ifa.getDescription());
setI_FixedAsset(ifa);
}
/**
* author Edwin Ang
* @param project
*/
protected MAsset (MProject project)
{
this(project.getCtx(), 0, project.get_TrxName());
setIsOwned(true);
setIsInPosession(true);
setA_Asset_CreateDate(new Timestamp(System.currentTimeMillis()));
setHelp(Msg.getMsg(MClient.get(getCtx()).getAD_Language(), "CreatedFromProject", new Object[] { project.getName()}));
setDateAcct(new Timestamp(System.currentTimeMillis()));
setDescription(project.getDescription());
}
/**
* Create asset from material receipt line
* @param mInOut
* @param sLine
* @param deliveryCount
*/
public MAsset(MInOut mInOut, MInOutLine sLine, int deliveryCount) {
this(mInOut.getCtx(), 0, mInOut.get_TrxName());
setIsOwned(false);
setIsInPosession(false);
setA_Asset_CreateDate(new Timestamp(System.currentTimeMillis()));
setHelp(Msg.getMsg(MClient.get(getCtx()).getAD_Language(), "CreatedFromShipment: ", new Object[] { mInOut.getDocumentNo()}));
setDateAcct(new Timestamp(System.currentTimeMillis()));
setDescription(sLine.getDescription());
}
/**
* Create Asset from Inventory
* @param inventory inventory
* @param invLine inventory line
* @param qty
* @param costs
*/
public MAsset (MInventory inventory, MInventoryLine invLine, BigDecimal qty, BigDecimal costs)
{
super(invLine.getCtx(), 0, invLine.get_TrxName());
setClientOrg(invLine);
MProduct product = MProduct.get(getCtx(), invLine.getM_Product_ID());
// Defaults from group:
MAssetGroup assetGroup = MAssetGroup.get(invLine.getCtx(), invLine.getM_Product().getM_Product_Category().getA_Asset_Group_ID());
if (assetGroup == null)
assetGroup = MAssetGroup.get(invLine.getCtx(), product.getA_Asset_Group_ID());
setAssetGroup(assetGroup);
//setValue(prod)
setName(product.getName());
setHelp(invLine.getDescription());
// Header
setAssetServiceDate(inventory.getMovementDate());
setIsOwned(true);
setIsInPosession(true);
// Product
setM_Product_ID(product.getM_Product_ID());
setVersionNo(product.getVersionNo());
// ASI
if (invLine.getM_AttributeSetInstance_ID() != 0)
{
MAttributeSetInstance asi = new MAttributeSetInstance (getCtx(), invLine.getM_AttributeSetInstance_ID(), get_TrxName());
setASI(asi);
}
//setSerNo(invLine.getSerNo());
setQty(qty);
if (inventory.getC_Activity_ID() > 0)
setC_Activity_ID(inventory.getC_Activity_ID());
//
if (MAssetType.isFixedAsset(this)) {
setA_Asset_Status(A_ASSET_STATUS_New);
}
else {
setA_Asset_Status(A_ASSET_STATUS_Activated);
setProcessed(true);
}
setA_Asset_Status(A_ASSET_STATUS_New);
}
/**
* Copy constructor
* @param copy
*/
public MAsset(MAsset copy)
{
this(Env.getCtx(), copy);
}
/**
* Copy constructor
* @param ctx
* @param copy
*/
public MAsset(Properties ctx, MAsset copy)
{
this(ctx, copy, (String) null);
}
/**
* Copy constructor
* @param ctx
* @param copy
* @param trxName
*/
public MAsset(Properties ctx, MAsset copy, String trxName)
{
this(ctx, 0, trxName);
copyPO(copy);
this.m_DateAcct = copy.m_DateAcct;
}
public MAsset(Properties ctx, int A_Asset_ID, String trxName, String... virtualColumns) {
super(ctx, A_Asset_ID, trxName, virtualColumns);
}
/**
* Set Asset Group
* @param assetGroup
*/
public void setAssetGroup(MAssetGroup assetGroup) {
setA_Asset_Group_ID(assetGroup.getA_Asset_Group_ID());
}
/**
* @return MAssetGroup
*/
public MAssetGroup getAssetGroup() {
return MAssetGroup.getCopy(getCtx(), getA_Asset_Group_ID(), get_TrxName());
}
/**
* Set ASI Info (M_AttributeSetInstance_ID, Lot, SerNo)
* @param asi
*/
public void setASI(MAttributeSetInstance asi) {
setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID());
setLot(asi.getLot());
setSerNo(asi.getSerNo());
}
/**
* Before Save
* @param newRecord new
* @return true
*/
@Override
protected boolean beforeSave (boolean newRecord)
{
// Set parent asset:
if (getA_Parent_Asset_ID() <= 0)
{
setA_Parent_Asset_ID(getA_Asset_ID());
}
// Fix inventory number:
String invNo = getInventoryNo();
if(invNo != null)
{
setInventoryNo(invNo.trim());
}
// If no asset group, than set the default one:
if(getA_Asset_Group_ID() <= 0)
{
setA_Asset_Group_ID(MAssetGroup.getDefault_ID(SetGetUtil.wrap(this)));
}
// Copy fields from C_BPartner_Location
if (is_ValueChanged(COLUMNNAME_C_BPartner_Location_ID) && getC_BPartner_Location_ID() > 0)
{
// Goodwill BF: Error: org.compiere.model.MAsset cannot be cast to org.compiere.model.SetGetModel
SetGetUtil.copyValues(SetGetUtil.wrap(this), MBPartnerLocation.Table_Name, getC_BPartner_Location_ID(),
new String[]{MBPartnerLocation.COLUMNNAME_C_Location_ID}
);
}
//
// Create ASI if not exist:
if (getM_Product_ID() > 0 && getM_AttributeSetInstance_ID() <= 0)
{
MProduct product = MProduct.get(getCtx(), getM_Product_ID());
MAttributeSetInstance asi = new MAttributeSetInstance(getCtx(), 0, product.getM_AttributeSet_ID(), get_TrxName());
asi.setSerNo(getSerNo());
asi.setDescription();
asi.saveEx();
setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID());
}
// Update status
updateStatus();
return true;
} // beforeSave
@Override
protected boolean afterSave (boolean newRecord, boolean success)
{
if(!success)
{
return success;
}
//
// Set parent
if(getA_Parent_Asset_ID() <= 0)
{
int A_Asset_ID = getA_Asset_ID();
setA_Parent_Asset_ID(A_Asset_ID);
DB.executeUpdateEx("UPDATE A_Asset SET A_Parent_Asset_ID=A_Asset_ID WHERE A_Asset_ID=" + A_Asset_ID, get_TrxName());
if (log.isLoggable(Level.FINE)) log.fine("A_Parent_Asset_ID=" + getA_Parent_Asset_ID());
}
//
// Set inventory number:
String invNo = getInventoryNo();
if(invNo == null || invNo.trim().length() == 0)
{
invNo = "" + get_ID();
setInventoryNo(invNo);
DB.executeUpdateEx("UPDATE A_Asset SET InventoryNo=" + DB.TO_STRING(invNo) + " WHERE A_Asset_ID=" + getA_Asset_ID(), get_TrxName());
if (log.isLoggable(Level.FINE)) log.fine("InventoryNo=" + getInventoryNo());
}
// If new record, create accounting and workfile
if (newRecord)
{
//@win: set value at asset group as default value for asset
MAssetGroup assetgroup = new MAssetGroup(getCtx(), getA_Asset_Group_ID(), get_TrxName());
String isDepreciated = (assetgroup.isDepreciated()) ? "Y" : "N";
String isOwned = (assetgroup.isOwned()) ? "Y" : "N";
setIsDepreciated(assetgroup.isDepreciated());
setIsOwned(assetgroup.isOwned());
DB.executeUpdateEx("UPDATE A_Asset SET IsDepreciated='" + isDepreciated + "', isOwned ='" + isOwned + "' WHERE A_Asset_ID=" + getA_Asset_ID(), get_TrxName());
//end @win
// for each asset group accounting create an asset accounting and a workfile too
for (MAssetGroupAcct assetgrpacct : MAssetGroupAcct.forA_Asset_Group_ID(getCtx(), getA_Asset_Group_ID(), null, get_TrxName()))
{
if (assetgrpacct.getAD_Org_ID() == 0 || assetgrpacct.getAD_Org_ID() == getAD_Org_ID())
{
if (getI_FixedAsset() != null && assetgrpacct.getC_AcctSchema_ID() != getI_FixedAsset().getC_AcctSchema_ID())
continue;
// Asset Accounting
MAssetAcct assetacct = new MAssetAcct(this, assetgrpacct);
assetacct.setAD_Org_ID(getAD_Org_ID()); //added by @win
assetacct.saveEx();
// Asset Depreciation Workfile
MDepreciationWorkfile assetwk = new MDepreciationWorkfile(this, assetacct.getPostingType(), assetgrpacct);
assetwk.setAD_Org_ID(getAD_Org_ID()); //added by @win
assetwk.setUseLifeYears(assetgrpacct.getUseLifeYears());
assetwk.setUseLifeMonths(assetgrpacct.getUseLifeMonths());
assetwk.setUseLifeYears_F(assetgrpacct.getUseLifeYears_F());
assetwk.setUseLifeMonths_F(assetgrpacct.getUseLifeMonths_F());
assetwk.saveEx();
// Change Log
MAssetChange.createAndSave(getCtx(), "CRT", new PO[]{this, assetwk, assetacct}, null);
}
}
}
else
{
MAssetChange.createAndSave(getCtx(), "UPD", new PO[]{this}, null);
}
//
// Update child.IsDepreciated flag
if (!newRecord && is_ValueChanged(COLUMNNAME_IsDepreciated))
{
final String sql = "UPDATE " + MDepreciationWorkfile.Table_Name
+" SET " + MDepreciationWorkfile.COLUMNNAME_IsDepreciated+"=?"
+" WHERE " + MDepreciationWorkfile.COLUMNNAME_A_Asset_ID+"=?";
DB.executeUpdateEx(sql, new Object[]{isDepreciated(), getA_Asset_ID()}, get_TrxName());
}
return true;
} // afterSave
@Override
protected boolean beforeDelete()
{
// delete addition
{
String sql = "DELETE FROM "+MAssetAddition.Table_Name+" WHERE "+MAssetAddition.COLUMNNAME_Processed+"=? AND "+MAssetAddition.COLUMNNAME_A_Asset_ID+"=?";
int no = DB.executeUpdateEx(sql, new Object[]{false, getA_Asset_ID()}, get_TrxName());
if (log.isLoggable(Level.INFO)) log.info("@A_Asset_Addition@ @Deleted@ #" + no);
}
//
// update invoice line
{
final String sql = "UPDATE "+MInvoiceLine.Table_Name+" SET "
+" "+MInvoiceLine.COLUMNNAME_A_Asset_ID+"=?"
+","+MInvoiceLine.COLUMNNAME_A_Processed+"=?"
+" WHERE "+MInvoiceLine.COLUMNNAME_A_Asset_ID+"=?";
int no = DB.executeUpdateEx(sql, new Object[]{null, false, getA_Asset_ID()}, get_TrxName());
if (log.isLoggable(Level.INFO)) log.info("@C_InvoiceLine@ @Updated@ #" + no);
}
return true;
} // beforeDelete
/**
* Update various status related flag
* @see #beforeSave(boolean)
*/
public void updateStatus()
{
String status = getA_Asset_Status();
setProcessed(!status.equals(A_ASSET_STATUS_New));
setIsDisposed(status.equals(A_ASSET_STATUS_Disposed));
setIsFullyDepreciated(status.equals(A_ASSET_STATUS_Depreciated));
if(isFullyDepreciated() || status.equals(A_ASSET_STATUS_Disposed))
{
setIsDepreciated(false);
}
if (status.equals(A_ASSET_STATUS_Activated) || getAssetActivationDate() == null)
{
setAssetActivationDate(getAssetServiceDate());
}
}
/**
* Change asset status to newStatus
* @param newStatus see A_ASSET_STATUS_
* @param date state change date; if null context "#Date" will be used
*/
public void changeStatus(String newStatus, Timestamp date)
{
String status = getA_Asset_Status();
if (log.isLoggable(Level.FINEST)) log.finest("Entering: " + status + "->" + newStatus + ", date=" + date);
//
// If date is null, use context #Date
if(date == null) {
date = Env.getContextAsDate(getCtx(), Env.DATE);
}
//
// Activation/Addition
if(newStatus.equals(A_ASSET_STATUS_Activated))
{
setAssetActivationDate(date);
}
//
// Preservation
if(newStatus.equals(A_ASSET_STATUS_Preservation))
{
setAssetDisposalDate(date);
// TODO: move to MAsetDisposal
Collection workFiles = MDepreciationWorkfile.forA_Asset_ID(getCtx(), getA_Asset_ID(), get_TrxName());
for(MDepreciationWorkfile assetwk : workFiles) {
assetwk.truncDepreciation();
assetwk.saveEx();
}
}
// Disposal
if(newStatus.equals(A_ASSET_STATUS_Disposed))
{
setAssetDisposalDate(date);
}
// Set new status
setA_Asset_Status(newStatus);
} // changeStatus
/** Temporary variables for {@link MDepreciationWorkfile}: */
/** useful life in months */
private int m_UseLifeMonths_F = 0;
public int getUseLifeMonths_F() { return m_UseLifeMonths_F; }
public void setUseLifeMonths_F(int UseLifeMonths_F) { m_UseLifeMonths_F = UseLifeMonths_F; }
/** current period id */
private int m_A_Current_Period = 0;
public int getA_Current_Period() { return m_A_Current_Period; }
public void setA_Current_Period(int A_Current_Period) { m_A_Current_Period = A_Current_Period; }
/** accounting date */
private Timestamp m_DateAcct = null;
public Timestamp getDateAcct() { return m_DateAcct; }
public void setDateAcct(Timestamp DateAcct) { m_DateAcct = DateAcct; }
/** A_Depreciation_ID */
private int m_A_Depreciation_ID = 0;
public int getA_Depreciation_ID() { return m_A_Depreciation_ID; }
public void setA_Depreciation_ID(int A_Depreciation_ID) { m_A_Depreciation_ID = A_Depreciation_ID; }
/** A_Depreciation_Forecast_ID */
private int m_A_Depreciation_F_ID = 0;
public int getA_Depreciation_F_ID() { return m_A_Depreciation_F_ID; }
public void setA_Depreciation_F_ID(int A_Depreciation_F_ID) { m_A_Depreciation_F_ID = A_Depreciation_F_ID; }
/** Asset cost */
private BigDecimal m_A_Asset_Cost = Env.ZERO;
public BigDecimal getA_Asset_Cost() { return m_A_Asset_Cost; }
public void setA_Asset_Cost(BigDecimal A_Asset_Cost) { m_A_Asset_Cost = A_Asset_Cost; }
/** Accumulated depreciation */
private BigDecimal m_A_Accumulated_Depr = Env.ZERO;
public BigDecimal getA_Accumulated_Depr() { return m_A_Accumulated_Depr; }
public void setA_Accumulated_Depr(BigDecimal A_Accumulated_Depr) { m_A_Accumulated_Depr = A_Accumulated_Depr; }
/** Accumulated depreciation forecast */
private BigDecimal m_A_Accumulated_Depr_F = Env.ZERO;
public BigDecimal getA_Accumulated_Depr_F() { return m_A_Accumulated_Depr_F; }
public void setA_Accumulated_Depr_F(BigDecimal A_Accumulated_Depr_F) { m_A_Accumulated_Depr_F = A_Accumulated_Depr_F; }
/** Fixed asset import */
private MIFixedAsset m_I_FixedAsset = null;
public MIFixedAsset getI_FixedAsset() { return m_I_FixedAsset; }
public void setI_FixedAsset(MIFixedAsset I_FixedAsset) { m_I_FixedAsset = I_FixedAsset; }
/**
* Methods below have been created for compilation of org.compiere.process.AssetDelivery and it is not working in any meaningful way.
*/
public MAssetDelivery confirmDelivery(EMail email, int ad_User_ID) {
// TODO Auto-generated method stub
return null;
}
public MProductDownload[] getProductDownloads() {
// TODO Auto-generated method stub
return null;
}
public MAssetDelivery confirmDelivery(HttpServletRequest request,
int ad_User_ID) {
// TODO Auto-generated method stub
return null;
}
public MAssetDelivery[] getDeliveries() {
// TODO Auto-generated method stub
return null;
}
public static MAsset getFromShipment(Properties ctx, int i, String trxName) {
// TODO Auto-generated method stub
return null;
}
public int getProductR_MailText_ID() {
// IDEMPIERE-197 Stabilize Fixed Assets
// AssetDelivery is requiring this missing column
// TODO: Adding this method to compile correctly and future research,
// but the process AssetDelivery will fail with error "** Product Mail Text"
return 0;
}
public boolean isDownloadable() {
// IDEMPIERE-197 Stabilize Fixed Assets
// AssetServlet is requiring this missing column
// TODO: Adding this method to compile correctly and future research
return false;
}
}