Includes the currency format in the expenses module, and

in the report of order cost per resource.

FEA: ItEr76S24AdapatingProjectsToExpenses
This commit is contained in:
Susana Montes Pedreira 2012-05-07 19:47:20 +01:00
parent d7ca618627
commit 369874f7ee
10 changed files with 142 additions and 58 deletions

View file

@ -27,6 +27,7 @@ import org.libreplan.business.orders.entities.OrderElement;
* Interface to calculate the money cost of a {@link TaskElement}.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
public interface IMoneyCostCalculator {
@ -44,11 +45,14 @@ public interface IMoneyCostCalculator {
* the cost categories, the price used is the default one for the type of
* hour.
*
* In addition, it includes the costs because of expenses.
*
* @param The
* {@link OrderElement} to calculate the money cost
* @return Money cost of the order element and all its children
* @return Money cost of the order element and all its children, including the
* costs because of hours and because of expenses.
*/
// BigDecimal getMoneyCost(OrderElement orderElement);
BigDecimal getTotalMoneyCost(OrderElement orderElement);
/**
* Resets the map used to save cached values of money cost for each
@ -56,10 +60,44 @@ public interface IMoneyCostCalculator {
*/
void resetMoneyCostMap();
BigDecimal getCostOfHours(OrderElement orderElement);
/**
* Returns the money cost of a {@link OrderElement} taking into account all
* its children.<br />
*
* It uses the {@link OrderElement} in order to calculate the cost using the
* following formula:<br />
* <tt>Sum of all the hours devoted to a task multiplied by the cost of
* each hour according to these parameters (type of hour, cost category of
* the resource, date of the work report)</tt><br />
*
* If there is not relationship between resource and type of hour through
* the cost categories, the price used is the default one for the type of
* hour.
*
* @param The
* {@link OrderElement} to calculate the money cost according
* to the hours
* @return Money cost of the order element and all its children
*/
BigDecimal getHoursMoneyCost(OrderElement orderElement);
BigDecimal getCostOfExpenses(OrderElement orderElement);
BigDecimal getMoneyCostTotal(OrderElement orderElement);
/**
* Returns the money cost of a {@link OrderElement} taking into account all
* its children.<br />
*
* It uses the {@link OrderElement} in order to calculate the cost using the
* following formula:<br />
* <tt>Sum of its direct expenses and its indirect expenses according to its
* relationship with @{SumExpenses}
*
* If there is not relationship between orderElement and any SumExpenses
* the cost will be zero.
*
* @param The
* {@link OrderElement} to calculate the money cost according to
* the expenses.
* @return Money cost of the order element and all its children
*/
BigDecimal getExpensesMoneyCost(OrderElement orderElement);
}

View file

@ -44,6 +44,7 @@ import org.springframework.stereotype.Component;
* be reseted when needed with method {@code resetMoneyCostMap}.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
@ -57,7 +58,7 @@ public class MoneyCostCalculator implements IMoneyCostCalculator {
private Map<OrderElement, MoneyCost> moneyCostTotalMap = new HashMap<OrderElement, MoneyCost>();
public class MoneyCost {
private class MoneyCost {
private BigDecimal costOfHours;
private BigDecimal costOfExpenses;
@ -88,21 +89,24 @@ public class MoneyCostCalculator implements IMoneyCostCalculator {
}
@Override
public BigDecimal getMoneyCostTotal(OrderElement orderElement) {
public BigDecimal getTotalMoneyCost(OrderElement orderElement) {
BigDecimal result = BigDecimal.ZERO.setScale(2);
BigDecimal moneyCostOfHours = getCostOfHours(orderElement);
BigDecimal moneyCostOfHours = getHoursMoneyCost(orderElement);
if (moneyCostOfHours != null) {
result = result.add(moneyCostOfHours);
}
BigDecimal moneyCostOfExpenses = getCostOfExpenses(orderElement);
BigDecimal moneyCostOfExpenses = getExpensesMoneyCost(orderElement);
if (moneyCostOfExpenses != null) {
result = result.add(moneyCostOfExpenses).setScale(2, RoundingMode.HALF_UP);
result = result.add(moneyCostOfExpenses);
}
if (result != null) {
result = result.setScale(2, RoundingMode.HALF_UP);
}
return result;
}
@Override
public BigDecimal getCostOfHours(OrderElement orderElement) {
public BigDecimal getHoursMoneyCost(OrderElement orderElement) {
MoneyCost moneyCost = moneyCostTotalMap.get(orderElement);
if (moneyCost != null) {
BigDecimal result = moneyCost.getCostOfHours();
@ -113,7 +117,7 @@ public class MoneyCostCalculator implements IMoneyCostCalculator {
BigDecimal result = BigDecimal.ZERO.setScale(2);
for (OrderElement each : orderElement.getChildren()) {
result = result.add(getCostOfHours(each));
result = result.add(getHoursMoneyCost(each));
}
result = result.add(getMoneyCostFromOwnWorkReportLines(orderElement))
@ -169,7 +173,7 @@ public class MoneyCostCalculator implements IMoneyCostCalculator {
}
@Override
public BigDecimal getCostOfExpenses(OrderElement orderElement) {
public BigDecimal getExpensesMoneyCost(OrderElement orderElement) {
MoneyCost moneyCost = moneyCostTotalMap.get(orderElement);
if (moneyCost != null) {
BigDecimal result = moneyCost.getCostOfExpenses();

View file

@ -2,6 +2,7 @@
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report1" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" resourceBundle="orderCostsPerResource">
<reportFont name="FreeSans" isDefault="true" fontName="FreeSans" size="9"/>
<subDataset name="dataset1"/>
<parameter name="currencySymbol" class="java.lang.String"/>
<field name="date" class="java.util.Date"/>
<field name="value" class="java.math.BigDecimal"/>
<field name="concept" class="java.lang.String"/>
@ -31,10 +32,10 @@
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$R{total.task}]]></textFieldExpression>
</textField>
<textField evaluationTime="Report" pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
<textField evaluationTime="Report" isBlankWhenNull="true">
<reportElement x="422" y="0" width="110" height="20"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumValuePerTask}]]></textFieldExpression>
<textFieldExpression class="java.lang.String"><![CDATA[$V{sumValuePerTask}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField>
</band>
</groupFooter>
@ -130,10 +131,10 @@
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{resource}]]></textFieldExpression>
</textField>
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
<textField isBlankWhenNull="true">
<reportElement x="434" y="0" width="98" height="14"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{value}]]></textFieldExpression>
<textFieldExpression class="java.lang.String"><![CDATA[$F{value}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField>
</band>
</detail>

View file

@ -2,6 +2,7 @@
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="report1" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" resourceBundle="orderCostsPerResource">
<reportFont name="FreeSans" isDefault="true" fontName="FreeSans" size="9"/>
<subDataset name="dataset1"/>
<parameter name="currencySymbol" class="java.lang.String"/>
<field name="workerName" class="java.lang.String"/>
<field name="date" class="java.util.Date"/>
<field name="clockStart" class="java.util.Date"/>
@ -63,10 +64,10 @@
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerTask}]]></textFieldExpression>
</textField>
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
<textField isBlankWhenNull="true">
<reportElement x="408" y="2" width="119" height="20"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumCostsPerTask}]]></textFieldExpression>
<textFieldExpression class="java.lang.String"><![CDATA[$V{sumCostsPerTask}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField>
</band>
</groupFooter>
@ -159,7 +160,7 @@
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
<reportElement x="408" y="2" width="119" height="20"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumCosts}]]></textFieldExpression>
<textFieldExpression class="java.lang.String"><![CDATA[$V{sumCosts}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="57" y="2" width="258" height="20"/>
@ -192,20 +193,20 @@
</groupHeader>
<groupFooter>
<band height="15">
<textField pattern="###0.00 €;-###0.00 €" isBlankWhenNull="true">
<textField isBlankWhenNull="true">
<reportElement x="409" y="0" width="119" height="14"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumCostsPerWorkerandCost}]]></textFieldExpression>
<textFieldExpression class="java.lang.String"><![CDATA[$V{sumCostsPerWorkerandCost}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField>
<textField pattern="###0.00 h">
<reportElement x="316" y="0" width="93" height="14"/>
<textElement textAlignment="Right" verticalAlignment="Middle"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$V{sumHoursPerWorkerandCost}]]></textFieldExpression>
</textField>
<textField pattern="###0.00 €/h;-###0.00 €/h" isBlankWhenNull="true">
<textField isBlankWhenNull="true">
<reportElement x="238" y="0" width="78" height="14"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.math.BigDecimal"><![CDATA[$F{costPerHour}]]></textFieldExpression>
<textFieldExpression class="java.lang.String"><![CDATA[$F{costPerHour}.setScale(2, RoundingMode.HALF_UP) + " " + $P{currencySymbol}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="96" y="0" width="141" height="14"/>

View file

@ -142,6 +142,9 @@
</textField>
<subreport>
<reportElement key="subreport" positionType="Float" x="2" y="31" width="490" height="47"/>
<subreportParameter name="currencySymbol">
<subreportParameterExpression><![CDATA[$P{currencySymbol}]]></subreportParameterExpression>
</subreportParameter>
<dataSourceExpression><![CDATA[$F{listWorkReportLineDTO}]]></dataSourceExpression>
<returnValue subreportVariable="sumCostsPerTask" toVariable="sumTotalCostsByHours" calculation="Sum"/>
<returnValue subreportVariable="sumHoursPerTask" toVariable="sumTotalHours" calculation="Sum"/>
@ -151,6 +154,9 @@
<reportElement key="subreport" positionType="Float" x="2" y="78" width="490" height="47">
<printWhenExpression><![CDATA[$F{listExpensesDTO} != null]]></printWhenExpression>
</reportElement>
<subreportParameter name="currencySymbol">
<subreportParameterExpression><![CDATA[$P{currencySymbol}]]></subreportParameterExpression>
</subreportParameter>
<dataSourceExpression><![CDATA[$F{listExpensesDTO}]]></dataSourceExpression>
<returnValue subreportVariable="sumValuePerTask" toVariable="sumTotalExpenses" calculation="Sum"/>
<subreportExpression class="java.lang.String"><![CDATA[$P{subReportES}]]></subreportExpression>

View file

@ -478,6 +478,7 @@ public class ExpenseSheetCRUDController extends BaseCRUDController<ExpenseSheet>
});
dbValue.setConstraint(checkConstraintExpenseValue());
dbValue.setFormat(Util.getMoneyFormat());
row.appendChild(dbValue);
}
@ -626,4 +627,8 @@ public class ExpenseSheetCRUDController extends BaseCRUDController<ExpenseSheet>
return _("Expense sheets");
}
public String getCurrencySymbol() {
return Util.getCurrencySymbol();
}
}

View file

@ -242,7 +242,7 @@ public class AssignedHoursToOrderElementModel implements IAssignedHoursToOrderEl
if (orderElement == null) {
return BigDecimal.ZERO;
}
return moneyCostCalculator.getMoneyCostTotal(orderElement);
return moneyCostCalculator.getTotalMoneyCost(orderElement);
}
@Override
@ -267,7 +267,7 @@ public class AssignedHoursToOrderElementModel implements IAssignedHoursToOrderEl
if (orderElement == null) {
return BigDecimal.ZERO.setScale(2);
}
return moneyCostCalculator.getCostOfExpenses(orderElement);
return moneyCostCalculator.getExpensesMoneyCost(orderElement);
}
@Override
@ -276,7 +276,7 @@ public class AssignedHoursToOrderElementModel implements IAssignedHoursToOrderEl
if (orderElement == null) {
return BigDecimal.ZERO.setScale(2);
}
return moneyCostCalculator.getCostOfHours(orderElement);
return moneyCostCalculator.getHoursMoneyCost(orderElement);
}
@Override
@ -286,7 +286,7 @@ public class AssignedHoursToOrderElementModel implements IAssignedHoursToOrderEl
return BigDecimal.ZERO;
}
return MoneyCostCalculator.getMoneyCostProportion(
moneyCostCalculator.getMoneyCostTotal(orderElement), orderElement.getBudget())
moneyCostCalculator.getTotalMoneyCost(orderElement), orderElement.getBudget())
.multiply(
new BigDecimal(100));
}

View file

@ -37,7 +37,6 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -658,29 +657,37 @@ public class TaskElementAdapter {
@Override
public BigDecimal execute() {
return moneyCostCalculator.getMoneyCostTotal(taskElement
return moneyCostCalculator.getTotalMoneyCost(taskElement
.getOrderElement());
}
});
}
private Map<String, BigDecimal> getMoneyItemizedCost() {
private BigDecimal getHoursMoneyCost() {
if ((taskElement == null) || (taskElement.getOrderElement() == null)) {
Map<String, BigDecimal> costs = new HashMap<String, BigDecimal>();
costs.put("costHours", BigDecimal.ZERO);
costs.put("costExpenses", BigDecimal.ZERO);
return costs;
return BigDecimal.ZERO;
}
return transactionService
.runOnReadOnlyTransaction(new IOnTransaction<Map<String, BigDecimal>>() {
.runOnReadOnlyTransaction(new IOnTransaction<BigDecimal>() {
@Override
public Map<String, BigDecimal> execute() {
Map<String, BigDecimal> costs = new HashMap<String, BigDecimal>();
costs.put("costHours", moneyCostCalculator
.getCostOfHours(taskElement.getOrderElement()));
costs.put("costExpenses", moneyCostCalculator
.getCostOfExpenses(taskElement.getOrderElement()));
return costs;
public BigDecimal execute() {
return moneyCostCalculator.getHoursMoneyCost(taskElement.getOrderElement());
}
});
}
private BigDecimal getExpensesMoneyCost() {
if ((taskElement == null) || (taskElement.getOrderElement() == null)) {
return BigDecimal.ZERO;
}
return transactionService
.runOnReadOnlyTransaction(new IOnTransaction<BigDecimal>() {
@Override
public BigDecimal execute() {
return moneyCostCalculator.getExpensesMoneyCost(taskElement
.getOrderElement());
}
});
}
@ -1057,15 +1064,16 @@ public class TaskElementAdapter {
} else {
String budget = Util.addCurrencySymbol(getBudget());
String moneyCost = Util.addCurrencySymbol(getMoneyCost());
Map<String, BigDecimal> mapCosts = getMoneyItemizedCost();
String costHours = Util.addCurrencySymbol(mapCosts.get("costHours"));
String costExpenses = Util.addCurrencySymbol(mapCosts.get("costExpenses"));
String costHours = Util.addCurrencySymbol(getHoursMoneyCost());
String costExpenses = Util.addCurrencySymbol(getExpensesMoneyCost());
result.append(
_("Budget: {0}, Consumed: {1} ({2}%)", budget, moneyCost,
getMoneyCostBarPercentage().multiply(new BigDecimal(100))))
.append("<br/>");
result.append(
_("cost because of worked hours: {0}€, cost because of expenses: {1}€",
_(
"cost because of worked hours: {0}, cost because of expenses: {1}",
costHours, costExpenses));
}

View file

@ -64,7 +64,10 @@
<row self="@{each='expensesheet'}" value="@{expensesheet}" onClick="controller.goToEditForm(self.value);">
<label value="@{expensesheet.firstExpense, converter='org.libreplan.web.common.typeconverters.LocalDateConverter'}" />
<label value="@{expensesheet.lastExpense, converter='org.libreplan.web.common.typeconverters.LocalDateConverter'}"/>
<label value="@{expensesheet.total}" />
<hbox>
<label value="@{expensesheet.total}" />
<label value="@{controller.currencySymbol}" />
</hbox>
<label value="@{expensesheet.code}" />
<label value="@{expensesheet.description}" />
<hbox>

View file

@ -91,7 +91,10 @@
<label value="@{expenseSheetLine.date, converter='org.libreplan.web.common.typeconverters.LocalDateConverter'}" />
<label value="@{expenseSheetLine.concept}"/>
<label value="@{expenseSheetLine.resource.getName}"/>
<label value="@{expenseSheetLine.value}"/>
<hbox>
<label value="@{expenseSheetLine.value}"/>
<label value="@{assignedHoursToOrderElementController.currencySymbol}" />
</hbox>
</row>
</rows>
</grid>
@ -104,21 +107,30 @@
<row style="border-top:1px solid black">
<label
value="${i18n:_('Sum of direct expenses')}" />
<label
value="@{assignedHoursToOrderElementController.totalDirectExpenses}" />
<hbox>
<label
value="@{assignedHoursToOrderElementController.totalDirectExpenses}" />
<label value="@{assignedHoursToOrderElementController.currencySymbol}" />
</hbox>
</row>
<row>
<label
value="${i18n:_('Sum of expenses imputed in children tasks')}" />
<label id="totalIDE"
value="@{assignedHoursToOrderElementController.totalIndirectExpenses}" />
<hbox>
<label id="totalIDE"
value="@{assignedHoursToOrderElementController.totalIndirectExpenses}" />
<label value="@{assignedHoursToOrderElementController.currencySymbol}" />
</hbox>
</row>
<row
style="border-top:1px solid black; font-weight: bold;">
<label value="${i18n:_('Total expenses')}"
style="font-weight: bold" />
<label style="font-weight: bold"
value="@{assignedHoursToOrderElementController.totalExpenses}"/>
<hbox>
<label style="font-weight: bold"
value="@{assignedHoursToOrderElementController.totalExpenses}"/>
<label value="@{assignedHoursToOrderElementController.currencySymbol}" />
</hbox>
</row>
</rows>
</grid>
@ -215,11 +227,17 @@
<rows>
<row>
<label value="${i18n:_('Because of hours')}:" />
<label value="@{assignedHoursToOrderElementController.costOfHours}" />
<hbox>
<label value="@{assignedHoursToOrderElementController.costOfHours}" />
<label value="@{assignedHoursToOrderElementController.currencySymbol}" />
</hbox>
</row>
<row>
<label value="${i18n:_('Because of expenses')}:" />
<label value="@{assignedHoursToOrderElementController.costOfExpenses}" />
<hbox>
<label value="@{assignedHoursToOrderElementController.costOfExpenses}" />
<label value="@{assignedHoursToOrderElementController.currencySymbol}" />
</hbox>
</row>
</rows>
</grid>