IDEMPIERE-3947:add interface to easy implement FA depreciation method

Fixed Asset bugs and enhancements
This commit is contained in:
hieplq 2019-08-15 22:03:59 +07:00
parent 9a6ab2b562
commit d7cddaa9f2
8 changed files with 215 additions and 8 deletions

View File

@ -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))"

View File

@ -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.
@ -516,5 +519,26 @@ 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;
}
} }

View File

@ -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);
} }

View File

@ -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;
@ -656,34 +683,42 @@ public class MDepreciationWorkfile extends X_A_Depreciation_Workfile
String help = "" + accumDep_C + "|" + accumDep_F + " + "; String help = "" + accumDep_C + "|" + accumDep_F + " + ";
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
exp_C = assetCost.subtract(accumDep_C); if (depreciationMethod != null && depreciationMethod.isPeriodAdjustment()) {
exp_C = depreciation_C.invoke(this, assetacct, currentPeriod, accumDep_C, depreciationMethod);
}else {
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)
exp_F = assetCost.subtract(accumDep_F); if (depreciationMethod != null && depreciationMethod.isPeriodAdjustment()) {
exp_C = depreciation_C.invoke(this, assetacct, currentPeriod, accumDep_C, depreciationMethod);
}else {
exp_F = assetCost.subtract(accumDep_F);
}
accumDep_F = assetCost; accumDep_F = assetCost;
} }
help += "" + exp_C + "|" + exp_F + " = " + accumDep_C + "|" + accumDep_F; help += "" + exp_C + "|" + exp_F + " = " + accumDep_C + "|" + accumDep_F;
// added by zuhri // added by zuhri
int months = 0; int months = 0;
months = months + (currentPeriod - A_Current_Period); months = months + (currentPeriod - A_Current_Period);
Timestamp dateAcct = TimeUtil.getMonthLastDay(TimeUtil.addMonths(getDateAcct(), months)); Timestamp dateAcct = TimeUtil.getMonthLastDay(TimeUtil.addMonths(getDateAcct(), months));

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 ();
}

View File

@ -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);
}