IDEMPIERE-3947:add interface to easy implement FA depreciation method
Fixed Asset bugs and enhancements
This commit is contained in:
parent
9a6ab2b562
commit
d7cddaa9f2
|
@ -54,6 +54,7 @@ Export-Package: bsh,
|
||||||
org.eevolution.model,
|
org.eevolution.model,
|
||||||
org.idempiere.broadcast,
|
org.idempiere.broadcast,
|
||||||
org.idempiere.distributed,
|
org.idempiere.distributed,
|
||||||
|
org.idempiere.fa.service.api,
|
||||||
org.idempiere.model
|
org.idempiere.model
|
||||||
Comment: Bundle-RequiredExecutionEnvironment: JavaSE-11
|
Comment: Bundle-RequiredExecutionEnvironment: JavaSE-11
|
||||||
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version>=1.11))"
|
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version>=1.11))"
|
||||||
|
|
|
@ -48,6 +48,9 @@ import org.compiere.process.ProcessCall;
|
||||||
import org.compiere.util.CLogger;
|
import org.compiere.util.CLogger;
|
||||||
import org.compiere.util.PaymentExport;
|
import org.compiere.util.PaymentExport;
|
||||||
import org.compiere.util.ReplenishInterface;
|
import org.compiere.util.ReplenishInterface;
|
||||||
|
import org.idempiere.fa.service.api.DepreciationFactoryLookupDTO;
|
||||||
|
import org.idempiere.fa.service.api.IDepreciationMethod;
|
||||||
|
import org.idempiere.fa.service.api.IDepreciationMethodFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a facade class for the Service Locator.
|
* This is a facade class for the Service Locator.
|
||||||
|
@ -517,4 +520,25 @@ public class Core {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lookup implement {@link IDepreciationMethod}
|
||||||
|
* @param factoryLookupDTO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static IDepreciationMethod getDepreciationMethod(DepreciationFactoryLookupDTO factoryLookupDTO) {
|
||||||
|
|
||||||
|
List<IDepreciationMethodFactory> factoryList =
|
||||||
|
Service.locator().list(IDepreciationMethodFactory.class).getServices();
|
||||||
|
if (factoryList != null) {
|
||||||
|
for(IDepreciationMethodFactory factory : factoryList) {
|
||||||
|
IDepreciationMethod depreciationMethod = factory.getDepreciationMethod(factoryLookupDTO);
|
||||||
|
if (depreciationMethod != null) {
|
||||||
|
return depreciationMethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.compiere.model;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -13,6 +14,8 @@ import org.compiere.util.CLogger;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.idempiere.fa.exceptions.AssetNotImplementedException;
|
import org.idempiere.fa.exceptions.AssetNotImplementedException;
|
||||||
import org.idempiere.fa.exceptions.AssetNotSupportedException;
|
import org.idempiere.fa.exceptions.AssetNotSupportedException;
|
||||||
|
import org.idempiere.fa.service.api.DepreciationDTO;
|
||||||
|
import org.idempiere.fa.service.api.IDepreciationMethod;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,7 +147,7 @@ public class MDepreciation extends X_A_Depreciation
|
||||||
* @return amortized value
|
* @return amortized value
|
||||||
*/
|
*/
|
||||||
public BigDecimal invoke(MDepreciationWorkfile assetwk, MAssetAcct assetAcct,
|
public BigDecimal invoke(MDepreciationWorkfile assetwk, MAssetAcct assetAcct,
|
||||||
int A_Current_Period, BigDecimal Accum_Dep)
|
int A_Current_Period, BigDecimal Accum_Dep, IDepreciationMethod depreciationMethod)
|
||||||
{
|
{
|
||||||
String depreciationType = getDepreciationType();
|
String depreciationType = getDepreciationType();
|
||||||
BigDecimal retValue = null;
|
BigDecimal retValue = null;
|
||||||
|
@ -164,7 +167,24 @@ public class MDepreciation extends X_A_Depreciation
|
||||||
{
|
{
|
||||||
return BigDecimal.ZERO;
|
return BigDecimal.ZERO;
|
||||||
}
|
}
|
||||||
if (depreciationType.equalsIgnoreCase("SL"))
|
|
||||||
|
if (depreciationMethod != null) {
|
||||||
|
DepreciationDTO depreciationDTO = new DepreciationDTO();
|
||||||
|
depreciationDTO.period = A_Current_Period;
|
||||||
|
depreciationDTO.salvage = assetwk.getA_Salvage_Value();
|
||||||
|
depreciationDTO.totalAmount = assetwk.getA_Asset_Cost();
|
||||||
|
depreciationDTO.useFullLife = new BigDecimal(assetwk.getA_Life_Period());// at the moment, int is ok for Thai, but for other country BigDecima is suitable, need to change AD
|
||||||
|
depreciationDTO.useFullLifeUnit = Calendar.MONTH;
|
||||||
|
depreciationDTO.trxName = assetwk.get_TrxName();
|
||||||
|
depreciationDTO.depreciationId = assetwk.get_ID();
|
||||||
|
depreciationDTO.inServiceDate = assetwk.getA_Asset().getAssetServiceDate();
|
||||||
|
depreciationDTO.accountDate = assetwk.getDateAcct();
|
||||||
|
depreciationDTO.accumulatedCost = assetwk.getA_Accumulated_Depr();
|
||||||
|
depreciationDTO.startPeriodDepreciation = assetwk.getA_Current_Period();
|
||||||
|
depreciationDTO.scale = getPrecision();
|
||||||
|
// calculate expense use implement of IDepreciationMethod
|
||||||
|
retValue = depreciationMethod.caclulateDepreciation(depreciationDTO);
|
||||||
|
}else if (depreciationType.equalsIgnoreCase("SL"))
|
||||||
{
|
{
|
||||||
retValue = apply_SL(assetwk, assetAcct, A_Current_Period, Accum_Dep);
|
retValue = apply_SL(assetwk, assetAcct, A_Current_Period, Accum_Dep);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,12 @@ package org.compiere.model;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.base.Core;
|
||||||
import org.apache.commons.collections.keyvalue.MultiKey;
|
import org.apache.commons.collections.keyvalue.MultiKey;
|
||||||
import org.compiere.util.CCache;
|
import org.compiere.util.CCache;
|
||||||
import org.compiere.util.CLogMgt;
|
import org.compiere.util.CLogMgt;
|
||||||
|
@ -16,6 +18,9 @@ import org.compiere.util.Env;
|
||||||
import org.compiere.util.TimeUtil;
|
import org.compiere.util.TimeUtil;
|
||||||
import org.idempiere.fa.feature.UseLife;
|
import org.idempiere.fa.feature.UseLife;
|
||||||
import org.idempiere.fa.feature.UseLifeImpl;
|
import org.idempiere.fa.feature.UseLifeImpl;
|
||||||
|
import org.idempiere.fa.service.api.DepreciationDTO;
|
||||||
|
import org.idempiere.fa.service.api.DepreciationFactoryLookupDTO;
|
||||||
|
import org.idempiere.fa.service.api.IDepreciationMethod;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -649,6 +654,28 @@ public class MDepreciationWorkfile extends X_A_Depreciation_Workfile
|
||||||
|
|
||||||
truncDepreciation();
|
truncDepreciation();
|
||||||
int A_Current_Period = getA_Current_Period();
|
int A_Current_Period = getA_Current_Period();
|
||||||
|
|
||||||
|
// lookup for implement of IDepreciationMethod
|
||||||
|
DepreciationFactoryLookupDTO depreciationFactoryLookupDTO = new DepreciationFactoryLookupDTO();
|
||||||
|
depreciationFactoryLookupDTO.depreciationType = depreciation_C.getDepreciationType();
|
||||||
|
IDepreciationMethod depreciationMethod = Core.getDepreciationMethod (depreciationFactoryLookupDTO);
|
||||||
|
|
||||||
|
if(depreciationMethod != null) {
|
||||||
|
DepreciationDTO depreciationDTO = new DepreciationDTO();
|
||||||
|
depreciationDTO.useFullLife = new BigDecimal(this.getA_Life_Period());// at the moment, int is ok for Thai, but for other country BigDecima is suitable, need to change AD
|
||||||
|
depreciationDTO.useFullLifeUnit = Calendar.MONTH;
|
||||||
|
depreciationDTO.depreciationId = this.get_ID();
|
||||||
|
depreciationDTO.inServiceDate = this.getA_Asset().getAssetServiceDate();
|
||||||
|
depreciationDTO.accountDate = this.getDateAcct();
|
||||||
|
depreciationDTO.startPeriodDepreciation = this.getA_Current_Period();
|
||||||
|
lifePeriods = (int)depreciationMethod.getCountPeriod(depreciationDTO);
|
||||||
|
|
||||||
|
// it's safe, at the moment, core disable setting of lifePeriods_F
|
||||||
|
lifePeriods_C = lifePeriods;
|
||||||
|
lifePeriods_F = lifePeriods;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (int currentPeriod = A_Current_Period, cnt = 1; currentPeriod <= lifePeriods; currentPeriod++, cnt++)
|
for (int currentPeriod = A_Current_Period, cnt = 1; currentPeriod <= lifePeriods; currentPeriod++, cnt++)
|
||||||
{
|
{
|
||||||
exp_C = Env.ZERO;
|
exp_C = Env.ZERO;
|
||||||
|
@ -659,24 +686,32 @@ public class MDepreciationWorkfile extends X_A_Depreciation_Workfile
|
||||||
if (lifePeriods_C > currentPeriod || !depreciation_C.requireLastPeriodAdjustment())
|
if (lifePeriods_C > currentPeriod || !depreciation_C.requireLastPeriodAdjustment())
|
||||||
{
|
{
|
||||||
setFiscal(false);
|
setFiscal(false);
|
||||||
exp_C = depreciation_C.invoke(this, assetacct, currentPeriod, accumDep_C);
|
exp_C = depreciation_C.invoke(this, assetacct, currentPeriod, accumDep_C, depreciationMethod);
|
||||||
accumDep_C = accumDep_C.add(exp_C);
|
accumDep_C = accumDep_C.add(exp_C);
|
||||||
}
|
}
|
||||||
else if (lifePeriods_C == currentPeriod)
|
else if (lifePeriods_C == currentPeriod)
|
||||||
{ // last period
|
{ // last period
|
||||||
|
if (depreciationMethod != null && depreciationMethod.isPeriodAdjustment()) {
|
||||||
|
exp_C = depreciation_C.invoke(this, assetacct, currentPeriod, accumDep_C, depreciationMethod);
|
||||||
|
}else {
|
||||||
exp_C = assetCost.subtract(accumDep_C);
|
exp_C = assetCost.subtract(accumDep_C);
|
||||||
|
}
|
||||||
accumDep_C = assetCost;
|
accumDep_C = assetCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lifePeriods_F > currentPeriod || !depreciation_F.requireLastPeriodAdjustment())
|
if (lifePeriods_F > currentPeriod || !depreciation_F.requireLastPeriodAdjustment())
|
||||||
{
|
{
|
||||||
setFiscal(true);
|
setFiscal(true);
|
||||||
exp_F = depreciation_F.invoke(this, assetacct, currentPeriod, accumDep_F);
|
exp_F = depreciation_F.invoke(this, assetacct, currentPeriod, accumDep_F, depreciationMethod);
|
||||||
accumDep_F = accumDep_F.add(exp_F);
|
accumDep_F = accumDep_F.add(exp_F);
|
||||||
}
|
}
|
||||||
else if (lifePeriods_F == currentPeriod)
|
else if (lifePeriods_F == currentPeriod)
|
||||||
{ // last period (fiscal)
|
{ // last period (fiscal)
|
||||||
|
if (depreciationMethod != null && depreciationMethod.isPeriodAdjustment()) {
|
||||||
|
exp_C = depreciation_C.invoke(this, assetacct, currentPeriod, accumDep_C, depreciationMethod);
|
||||||
|
}else {
|
||||||
exp_F = assetCost.subtract(accumDep_F);
|
exp_F = assetCost.subtract(accumDep_F);
|
||||||
|
}
|
||||||
accumDep_F = assetCost;
|
accumDep_F = assetCost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.idempiere.fa.service.api;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parameter to calculate depreciation
|
||||||
|
* @author hieplq
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DepreciationDTO implements Serializable {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -748366297153525253L;
|
||||||
|
/**
|
||||||
|
* period calculate for
|
||||||
|
*/
|
||||||
|
public int period;
|
||||||
|
/**
|
||||||
|
* remain amount after full depreciation
|
||||||
|
*/
|
||||||
|
public BigDecimal salvage;
|
||||||
|
/**
|
||||||
|
* time to depreciation
|
||||||
|
*/
|
||||||
|
public BigDecimal useFullLife;
|
||||||
|
/**
|
||||||
|
* UOM for {@link #useFullLife}, use constant from {@link Calendar}
|
||||||
|
* accept {@link Calendar#YEAR} {@link Calendar#MONTH} {@link Calendar#DATE}
|
||||||
|
*/
|
||||||
|
public int useFullLifeUnit;
|
||||||
|
/**
|
||||||
|
* date start depreciation
|
||||||
|
*/
|
||||||
|
public Timestamp inServiceDate;
|
||||||
|
/**
|
||||||
|
* date booking, at the moment {@link #inServiceDate} isn't mandatory, in case don't input {@link #inServiceDate}, can use accountDate as {@link #inServiceDate}
|
||||||
|
*/
|
||||||
|
public Timestamp accountDate;
|
||||||
|
/**
|
||||||
|
* date asset transfer to other org.
|
||||||
|
* so days to depreciate of last period of source org like end period of life, it can not full month days
|
||||||
|
* so days to depreciate of first period of destination org like start period of life, it can not full month days
|
||||||
|
*/
|
||||||
|
public Timestamp transferDay;
|
||||||
|
/**
|
||||||
|
* period start to calculate depreciate
|
||||||
|
*/
|
||||||
|
public int startPeriodDepreciation;
|
||||||
|
/**
|
||||||
|
* accumulated when start calculate for {@link #startPeriodDepreciation}
|
||||||
|
*/
|
||||||
|
public BigDecimal accumulatedCost;
|
||||||
|
/**
|
||||||
|
* asset cost
|
||||||
|
*/
|
||||||
|
public BigDecimal totalAmount;
|
||||||
|
|
||||||
|
public int scale = 4;
|
||||||
|
/*** idempiere part ****/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* in case DTO isn't enough or not suitable for your method, use depreciationId to get X_A_Depreciation_Workfile so you can get more relate info
|
||||||
|
*/
|
||||||
|
public int depreciationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* name of current transaction
|
||||||
|
*/
|
||||||
|
public String trxName;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.idempiere.fa.service.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pass to {@link IDepreciationMethodFactory} to lookup {@link IDepreciationMethod} implement
|
||||||
|
* @author hieplq
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DepreciationFactoryLookupDTO {
|
||||||
|
public String depreciationType;
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.idempiere.fa.service.api;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* implement this interface to provide depreciate calculate method
|
||||||
|
* @author hieplq
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface IDepreciationMethod {
|
||||||
|
/**
|
||||||
|
* calculate depreciation for each period
|
||||||
|
* @param depreciationDTO
|
||||||
|
* @return amount depreciation for {@link DepreciationDTO#period}
|
||||||
|
*/
|
||||||
|
public BigDecimal caclulateDepreciation (DepreciationDTO depreciationDTO);
|
||||||
|
/**
|
||||||
|
* get num of period to depreciation
|
||||||
|
* @param depreciationDTO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public long getCountPeriod (DepreciationDTO depreciationDTO);
|
||||||
|
/**
|
||||||
|
* support to move all difference by round to end period
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isPeriodAdjustment ();
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.idempiere.fa.service.api;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* factory for {@link IDepreciationMethod}
|
||||||
|
* @author hieplq
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface IDepreciationMethodFactory {
|
||||||
|
/**
|
||||||
|
* lookup {@link IDepreciationMethod}
|
||||||
|
* @param factoryLookupDTO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public IDepreciationMethod getDepreciationMethod(DepreciationFactoryLookupDTO factoryLookupDTO);
|
||||||
|
}
|
Loading…
Reference in New Issue