From: Hirzel P. <ph...@us...> - 2008-05-14 11:09:22
|
Update of /cvsroot/tcotool/TCO-Tool/src/org/tcotool/tools In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv5108/src/org/tcotool/tools Modified Files: Calculator.java Log Message: Feature: Estimated & Direct costs Index: Calculator.java =================================================================== RCS file: /cvsroot/tcotool/TCO-Tool/src/org/tcotool/tools/Calculator.java,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** Calculator.java 13 Jun 2007 20:17:33 -0000 1.6 --- Calculator.java 14 May 2008 11:09:23 -0000 1.7 *************** *** 28,32 **** import ch.softenvironment.jomm.mvc.model.DbCodeType; import ch.softenvironment.jomm.mvc.model.DbObject; ! import ch.softenvironment.math.MathUtils; import ch.softenvironment.util.AmountFormat; import ch.softenvironment.util.DeveloperException; --- 28,32 ---- import ch.softenvironment.jomm.mvc.model.DbCodeType; import ch.softenvironment.jomm.mvc.model.DbObject; ! import ch.softenvironment.math.FinancialUtils; import ch.softenvironment.util.AmountFormat; import ch.softenvironment.util.DeveloperException; *************** *** 37,41 **** * Service individually. * ! * Costs-Map strucutre: * Map-Key | Values * ----------------------------------------------------------------------------------- --- 37,41 ---- * Service individually. * ! * Costs-Map structure: * Map-Key | Values * ----------------------------------------------------------------------------------- *************** *** 46,50 **** */ public class Calculator { ! // kind of costs public static final String FACT_TCO = "FCTCO_"; public static final String PERSONAL_TCO = "PCTCO_"; --- 46,50 ---- */ public class Calculator { ! // kind of cost-relevance public static final String FACT_TCO = "FCTCO_"; public static final String PERSONAL_TCO = "PCTCO_"; *************** *** 58,72 **** public static final String SITE_UNDEFINED = "SITE_UNDEFINED"; public static final String CATALOGUE_UNDEFINED = "CATALOGUE_UNDEFINED"; ! public static final String ROLE_UNDEFINED = "ROLE_UNDEFINED"; ! public static final String ACTIVITY_UNDEFINED = "ACTIVITY_UNDEFINED"; ! // pseudo Codes ! public static final String ESTIMATED = "ESTIMATED"; ! public static final String KNOWN = "KNOWN"; ! public static final String HOURS_INTERNAL = "INTERNAL"; ! public static final String HOURS_EXTERNAL = "EXTERNAL"; ! public static final String COST_INTERNAL_LUMP = "INTERNAL_LUMP"; ! public static final String COST_EXTERNAL_LUMP = "EXTERNAL_LUMP"; // calculation constants public static final double PERSONAL_HOURS_UNDEFINED = -1.0; private Map costs = new HashMap(); // map to keep costs per service --- 58,92 ---- public static final String SITE_UNDEFINED = "SITE_UNDEFINED"; public static final String CATALOGUE_UNDEFINED = "CATALOGUE_UNDEFINED"; ! public static final String PERSONAL_ROLE_UNDEFINED = "ROLE_UNDEFINED"; ! public static final String PERSONAL_ACTIVITY_UNDEFINED = "ACTIVITY_UNDEFINED"; ! ! // pseudo code ESTIMATED related to Cost#estimated ! public static final String FACT_ESTIMATED = FACT_TCO + "ESTIMATED"; ! public static final String PERSONAL_ESTIMATED = PERSONAL_TCO + "ESTIMATED"; ! public static final String ESTIMATED = "ESTIMATED"; // FACT_ESTIMATED + PERSONAL_ESTIMATED (which is the opposite of KNOWN) ! public static final String FACT_KNOWN = FACT_TCO + "KNOWN"; ! public static final String PERSONAL_KNOWN = PERSONAL_TCO + "KNOWN"; ! public static final String KNOWN = "KNOWN"; // FACT_KNOWN + PERSONAL_KNOWN (which is the opposite of ESTIMATED) ! // pseudo code DIRECT/INDIRECT related to CostCause#direct ! public static final String FACT_DIRECT_UNDEFINED = FACT_TCO + "DIRECT_UNKNOWN"; ! public static final String FACT_DIRECT = FACT_TCO + "DIRECT"; ! public static final String FACT_INDIRECT = FACT_TCO + "INDIRECT"; ! public static final String PERSONAL_DIRECT_UNDEFINED = PERSONAL_TCO + "DIRECT_UNKNOWN"; ! public static final String PERSONAL_DIRECT = PERSONAL_TCO + "DIRECT"; ! public static final String PERSONAL_INDIRECT = PERSONAL_TCO + "INDIRECT"; ! // pseudo code related to PersonalCost ! public static final String PERSONAL_HOURS_INTERNAL = PERSONAL_TCO + "HOURS_INTERNAL"; ! public static final String PERSONAL_HOURS_EXTERNAL = PERSONAL_TCO + "HOURS_EXTERNAL"; ! public static final String PERSONAL_COST_INTERNAL_LUMP = PERSONAL_TCO + "INTERNAL_LUMP"; ! public static final String PERSONAL_COST_EXTERNAL_LUMP = PERSONAL_TCO + "EXTERNAL_LUMP"; ! public static final String PERSONAL_COST_EXTERNAL = PERSONAL_TCO + "EXTERN"; ! public static final String PERSONAL_COST_INTERNAL = PERSONAL_TCO + "INTERN"; ! // calculation constants public static final double PERSONAL_HOURS_UNDEFINED = -1.0; + + // financial/accounting + public static final String DEPRECIATION_LINEAR = "DEPR_LIN_"; + public static final String DEPRECIATION_GEOMETRIC_DEGRESSIVE = "DEPR_DEGR"; private Map costs = new HashMap(); // map to keep costs per service *************** *** 273,279 **** } private static String createCodeKey(final String kind, Object code) { ! if (code instanceof DbObject) { return kind + ((DbObject)code).getId().toString(); } else { return kind + code; } --- 293,302 ---- } private static String createCodeKey(final String kind, Object code) { ! if (code == null) { ! throw new IllegalArgumentException("no key exists for code==null"); ! } else if (code instanceof DbObject) { return kind + ((DbObject)code).getId().toString(); } else { + // <undefined> code return kind + code; } *************** *** 401,405 **** /** * Cummulate the TCO-Costs for given cost' CostType: ! * @paran driver owner of given cost * @param cost * @param factor (including the given Cost's factor) --- 424,428 ---- /** * Cummulate the TCO-Costs for given cost' CostType: ! * @param driver owner of given cost * @param cost * @param factor (including the given Cost's factor) *************** *** 416,420 **** calcTcoRepeatable(service, driver, cost, PERSONAL_TCO, totalCost); } else { ! // at least charge personal Cost in 1st Year cummulateCodes(service, driver, cost, PERSONAL_TCO, INDEX_TOTAL + 1, totalCost); } --- 439,444 ---- calcTcoRepeatable(service, driver, cost, PERSONAL_TCO, totalCost); } else { ! // at least charge personal Cost ONCE ! //TODO find the year of the baseOffset cummulateCodes(service, driver, cost, PERSONAL_TCO, INDEX_TOTAL + 1, totalCost); } *************** *** 438,441 **** --- 462,466 ---- } else { // once in maxUsage for whole UsageDuration + //TODO find the year of the baseOffset long completeYears = fCost.getUsageDuration().longValue() / 12; int year = 0; *************** *** 454,457 **** --- 479,485 ---- } } + private static double getCostInYear(Cost cost, int yearOffset) { + return 0.0; + } /** * Repeatable Cost's must be reconsidered after UsageDuration. *************** *** 471,485 **** } } - /** - * Cummulate costs of financial matters for e.g. Interests, Depreciation and the like - * for the given cost in driver and service. - * Overwrite this method. - * @param service - * @param cost - * @param factor (including the given Cost's factor) - */ - protected void calcFinances(Service service, CostDriver driver, Cost cost, double factor) { - //TODO implement a default implementation - } private Map getServiceMap(Map map, Service key) { if (!map.containsKey(key.getId())) { --- 499,502 ---- *************** *** 489,493 **** } /** ! * Distribute the given costs among all codes involved. * @param year 0=Total at all; 1..n=TCO/Depreciation-distribution * @param amount costs to charge for given year --- 506,510 ---- } /** ! * Cummulate the given cost among all codes involved. * @param year 0=Total at all; 1..n=TCO/Depreciation-distribution * @param amount costs to charge for given year *************** *** 539,551 **** key = COST_CAUSE_UNDEFINED; if (cost.getCause() != null) { ! key = cost.getCause(); } storeIntoCodeList(serviceMap, kind, key, year, amount); - if (cost.getEstimated().booleanValue()) { - storeIntoCodeList(serviceMap, kind, ESTIMATED, year, amount); - } else { - storeIntoCodeList(serviceMap, kind, KNOWN, year, amount); - } if (cost instanceof FactCost) { key = CATALOGUE_UNDEFINED; if (((FactCost)cost).getCatalogue() != null) { --- 556,581 ---- key = COST_CAUSE_UNDEFINED; if (cost.getCause() != null) { ! key = cost.getCause(); } storeIntoCodeList(serviceMap, kind, key, year, amount); if (cost instanceof FactCost) { + // pseudo-code "DIRECT/INDIRECT" + if ((cost.getCause() == null) || (cost.getCause().getDirect() == null)) { + storeIntoCodeList(serviceMap, kind, FACT_DIRECT_UNDEFINED, year, amount); + } else if (cost.getCause().getDirect().booleanValue()) { + storeIntoCodeList(serviceMap, kind, FACT_DIRECT, year, amount); + } else { + storeIntoCodeList(serviceMap, kind, FACT_INDIRECT, year, amount); + } + + // pseudo-code "ESTIMATED/KNOWN" + if (cost.getEstimated().booleanValue()) { + storeIntoCodeList(serviceMap, kind, FACT_ESTIMATED, year, amount); + storeIntoCodeList(serviceMap, kind, ESTIMATED, year, amount); + } else { + storeIntoCodeList(serviceMap, kind, FACT_KNOWN, year, amount); + storeIntoCodeList(serviceMap, kind, KNOWN, year, amount); + } + key = CATALOGUE_UNDEFINED; if (((FactCost)cost).getCatalogue() != null) { *************** *** 554,561 **** storeIntoCodeList(serviceMap, kind, key, year, amount); } else if (cost instanceof PersonalCost) { ! // kind == PERSONAL_TCO PersonalCost pCost = (PersonalCost)cost; ! key = ACTIVITY_UNDEFINED; if (pCost.getActivity() != null) { key = pCost.getActivity(); --- 584,608 ---- storeIntoCodeList(serviceMap, kind, key, year, amount); } else if (cost instanceof PersonalCost) { ! // pseudo-code "DIRECT/INDIRECT" ! if ((cost.getCause() == null) || (cost.getCause().getDirect() == null)) { ! storeIntoCodeList(serviceMap, kind, PERSONAL_DIRECT_UNDEFINED, year, amount); ! } else if (cost.getCause().getDirect().booleanValue()) { ! storeIntoCodeList(serviceMap, kind, PERSONAL_DIRECT, year, amount); ! } else { ! storeIntoCodeList(serviceMap, kind, PERSONAL_INDIRECT, year, amount); ! } ! ! // pseudo-code "ESTIMATED/KNOWN" ! if (cost.getEstimated().booleanValue()) { ! storeIntoCodeList(serviceMap, kind, PERSONAL_ESTIMATED, year, amount); ! storeIntoCodeList(serviceMap, kind, ESTIMATED, year, amount); ! } else { ! storeIntoCodeList(serviceMap, kind, PERSONAL_KNOWN, year, amount); ! storeIntoCodeList(serviceMap, kind, KNOWN, year, amount); ! } ! PersonalCost pCost = (PersonalCost)cost; ! key = PERSONAL_ACTIVITY_UNDEFINED; if (pCost.getActivity() != null) { key = pCost.getActivity(); *************** *** 563,567 **** storeIntoCodeList(serviceMap, kind, key, year, amount); ! key = ROLE_UNDEFINED; if (pCost.getRole() != null) { key = pCost.getRole(); --- 610,614 ---- storeIntoCodeList(serviceMap, kind, key, year, amount); ! key = PERSONAL_ROLE_UNDEFINED; if (pCost.getRole() != null) { key = pCost.getRole(); *************** *** 573,586 **** // just count amount generally (Lump = "Pauschal" (de)) if (pCost.getInternal().booleanValue()) { ! storeIntoCodeList(serviceMap, kind, COST_INTERNAL_LUMP, year, amount); } else { ! storeIntoCodeList(serviceMap, kind, COST_EXTERNAL_LUMP, year, amount); } } else { hours *= utility.getMultitudeFactor(pCost, true); if (pCost.getInternal().booleanValue()) { ! storeIntoCodeList(serviceMap, kind, HOURS_INTERNAL, year, hours); } else { ! storeIntoCodeList(serviceMap, kind, HOURS_EXTERNAL, year, hours); } } --- 620,633 ---- // just count amount generally (Lump = "Pauschal" (de)) if (pCost.getInternal().booleanValue()) { ! storeIntoCodeList(serviceMap, kind, PERSONAL_COST_INTERNAL_LUMP, year, amount); } else { ! storeIntoCodeList(serviceMap, kind, PERSONAL_COST_EXTERNAL_LUMP, year, amount); } } else { hours *= utility.getMultitudeFactor(pCost, true); if (pCost.getInternal().booleanValue()) { ! storeIntoCodeList(serviceMap, kind, PERSONAL_HOURS_INTERNAL, year, hours); } else { ! storeIntoCodeList(serviceMap, kind, PERSONAL_HOURS_EXTERNAL, year, hours); } } *************** *** 613,619 **** /** * Return total costs for given service and code. ! * @param service null for cummulated costs over all services * @param kind ! * @param code * @return [Total_Kind_Code; Year1_Kind_Code;..YearN_Kind_Code] */ --- 660,666 ---- /** * Return total costs for given service and code. ! * @param object null for cummulated costs over all services * @param kind ! * @param code DbCode; String for undefined code; null for * @return [Total_Kind_Code; Year1_Kind_Code;..YearN_Kind_Code] */ *************** *** 737,741 **** } /** ! * */ public int getDurationYears() { --- 784,790 ---- } /** ! * Calculate the duration in years, where last partial year counts ! * as one year more. ! * Useful as title-column count. */ public int getDurationYears() { *************** *** 746,748 **** --- 795,877 ---- return years; } + // finance/accounting + /** + * Cummulate costs of financial matters for e.g. accounting, interests, depreciation and the like + * for the given cost in driver and service. + * @param service + * @param driver + * @param cost Consider FactCost's with a depreciationDuration > 1 year + * @param factor (including the given Cost's factor) + */ + protected void calcFinances(Service service, CostDriver driver, Cost cost, double factor) { + if (cost instanceof FactCost) { + FactCost fCost = (FactCost)cost; + if ((fCost.getDepreciationDuration() != null) && (fCost.getDepreciationDuration().longValue() > 12.0)) { + // [0] total FactCost independent of depreciation + double capital = fCost.getAmount().doubleValue() * factor; + cummulateCodes(service, driver, cost, DEPRECIATION_LINEAR, INDEX_TOTAL, capital); + cummulateCodes(service, driver, cost, DEPRECIATION_GEOMETRIC_DEGRESSIVE, INDEX_TOTAL, capital); + + // [1..fCost.depreciationYears] of first period of FactCost's depreciationDuration + int year = calcDepreciation(service, driver, fCost, capital, INDEX_TOTAL); + + // [after fCost.depreciationYears years] repeatable periods + if ((cost.getRepeatable() != null) && cost.getRepeatable().booleanValue() && (year < getDurationYears())) { + // repeat the costs until maxDuration + while (year < getDurationYears()) { + //TODO Check: probably degressive depreciation costs from duration before are not calculated further on, which would go infinitely down to 0 + year = calcDepreciation(service, driver, fCost, capital, year); + } + } + } + } + } + /** + * Calculate the <b>linear depreciation</b> over the whole FactCost-DepreciationDuration. + * Algorithm: + * - Linear Depreciation + * @param costCapital + * @param costDuration + * @return year of last Cost-entry + */ + private int calcDepreciation(Service service, CostDriver driver, FactCost cost, double costCapital, int yearIndex) { + int duration = cost.getDepreciationDuration().intValue(); + int completeYears = duration / 12; + if (duration % 12 > 0) { + // consider a partial duration after last complete year as one more year + completeYears++; + } + + int year = 0; + for (; year<completeYears; year++) { + int period = year + 1; + double amount /*[de] Buchwert*/ = FinancialUtils.calcDepreciationLinear(costCapital, completeYears, period); + // depreciation over full year + cummulateCodes(service, driver, cost, DEPRECIATION_LINEAR, yearIndex + period, amount); + + amount /*[de] Buchwert*/ = FinancialUtils.calcDepreciationGeometricDegressive(costCapital, utility.getInterestRate(), period); + // depreciation over full year + cummulateCodes(service, driver, cost, DEPRECIATION_GEOMETRIC_DEGRESSIVE, yearIndex + period, amount); + } + + return year + yearIndex; + } + /** + * Return cost-list over given object. + * @param object null for all services + * @return [FactCosts_Total; Depreciation_Year1;.. TCO_YearN] + */ + public List getDepreciationCostBlock(TcoObject object, final String type) { + TcoObject costObject = (object == null ? rootObject : object); + List costs = new ArrayList(); + + List totalFacts = getTotalCosts(costObject, type); + costs.add(new Double(getValue(totalFacts, INDEX_TOTAL))); + for (int i=0; i<getDurationYears(); i++) { + // print Depreciation-Years + int index = i + INDEX_TOTAL + 1; + costs.add(new Double(getValue(totalFacts, index))); + } + return costs; + } } \ No newline at end of file |