/* * @(#)OtherPersonelExpenseItem.java * * Copyright 2010 Instituto Superior Tecnico * Founding Authors: Luis Cruz, Nuno Ochoa, Paulo Abrantes * * https://fenix-ashes.ist.utl.pt/ * * This file is part of the Expenditure Tracking Module. * * The Expenditure Tracking Module is free software: you can * redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation, either version * 3 of the License, or (at your option) any later version. * * The Expenditure Tracking Module 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Expenditure Tracking Module. If not, see <http://www.gnu.org/licenses/>. * */ package module.mission.domain; import java.math.BigDecimal; import module.finance.util.Money; import module.organization.domain.Person; import org.joda.time.Days; import org.joda.time.LocalDate; /** * * @author Luis Cruz * */ public class OtherPersonelExpenseItem extends OtherPersonelExpenseItem_Base { public OtherPersonelExpenseItem() { super(); } @Override protected MissionItem createNewVersionInstance(final MissionVersion missionVersion) { return new OtherPersonelExpenseItem(); } @Override protected void setNewVersionInformation(final MissionItem missionItem) { super.setNewVersionInformation(missionItem); final OtherPersonelExpenseItem otherPersonelExpenseItem = (OtherPersonelExpenseItem) missionItem; otherPersonelExpenseItem.setValue(getValue()); } @Deprecated public boolean hasValue() { return getValue() != null; } @Override public boolean isConsistent() { return super.isConsistent() && doesNotExceedMaximumPossiblePersonelExpenseValue(); } public boolean doesNotExceedMaximumPossiblePersonelExpenseValue() { final Money value = getValue(); final MockPersonelExpenseItem mock = getMissionVersion().getMission().getAccommodationItems().isEmpty() ? new MockFullPersonelExpenseItem(this) : new MockWithAccommodationPersonelExpenseItem( this); return value.isLessThanOrEqual(mock.getValue()); } public static abstract class MockPersonelExpenseItem { final OtherPersonelExpenseItem missionItem; public MockPersonelExpenseItem(final OtherPersonelExpenseItem missionItem) { this.missionItem = missionItem; } public Money getValue() { return Money.ZERO; } public int calculateNumberOfDays() { final LocalDate startDate = missionItem.getStart().toLocalDate(); final LocalDate endDate = missionItem.getEnd().toLocalDate().plusDays(1); return Days.daysBetween(startDate, endDate).getDays(); } public double getWeightedExpenseFactor() { return getExpenseFactor(); } public double getExpenseFactor() { double result = 0.0; for (final Person person : missionItem.getPeopleSet()) { result += getExpenseFactor(person); } return result; } public double getExpenseFactor(final Person person) { double result = 0.0; if (missionItem.getPeopleSet().contains(person)) { final Mission mission = missionItem.getMissionVersion().getMission(); final PersonelExpenseItem firstPersonelExpenseItem = findFirstPersonelExpenseItemFor(mission, person); final PersonelExpenseItem lastPersonelExpenseItem = findLastPersonelExpenseItemFor(mission, person); int numberOfDays = calculateNumberOfDays(); if (missionItem == firstPersonelExpenseItem) { numberOfDays--; result += mission.getFirstDayPersonelDayExpensePercentage(missionItem); } if (missionItem == lastPersonelExpenseItem && numberOfDays > 0) { numberOfDays--; result += mission.getLastDayPersonelDayExpensePercentage(missionItem); } result += (numberOfDays * mission.getMiddleDayPersonelDayExpensePercentage(firstPersonelExpenseItem)); } return result; } private static PersonelExpenseItem findFirstPersonelExpenseItemFor(final Mission mission, final Person person) { PersonelExpenseItem result = null; for (final MissionItem missionItem : mission.getMissionItemsSet()) { if (missionItem.isPersonelExpenseItem()) { final PersonelExpenseItem personelExpenseItem = (PersonelExpenseItem) missionItem; if (personelExpenseItem.getPeopleSet().contains(person)) { if (result == null || personelExpenseItem.getStart().isBefore(result.getStart())) { result = personelExpenseItem; } } } } return result; } private static PersonelExpenseItem findLastPersonelExpenseItemFor(final Mission mission, final Person person) { PersonelExpenseItem result = null; for (final MissionItem missionItem : mission.getMissionItemsSet()) { if (missionItem.isPersonelExpenseItem()) { final PersonelExpenseItem personelExpenseItem = (PersonelExpenseItem) missionItem; if (personelExpenseItem.getPeopleSet().contains(person)) { if (result == null || personelExpenseItem.getStart().isAfter(result.getStart())) { result = personelExpenseItem; } } } } return result; } } public static class MockFullPersonelExpenseItem extends MockPersonelExpenseItem { public MockFullPersonelExpenseItem(final OtherPersonelExpenseItem missionItem) { super(missionItem); } @Override public Money getValue() { final DailyPersonelExpenseCategory dailyPersonelExpenseCategory = missionItem.getDailyPersonelExpenseCategory(); final double expenseFactor = getWeightedExpenseFactor(); return dailyPersonelExpenseCategory.getValue().multiplyAndRound(new BigDecimal(expenseFactor)); } } public static class MockNoPersonelExpenseItem extends MockPersonelExpenseItem { public MockNoPersonelExpenseItem(final OtherPersonelExpenseItem missionItem) { super(missionItem); } } public static class MockWithAccommodationPersonelExpenseItem extends MockPersonelExpenseItem { public MockWithAccommodationPersonelExpenseItem(final OtherPersonelExpenseItem missionItem) { super(missionItem); } @Override public double getWeightedExpenseFactor() { return getExpenseFactor() * 0.7; } @Override public Money getValue() { final DailyPersonelExpenseCategory dailyPersonelExpenseCategory = missionItem.getDailyPersonelExpenseCategory(); final double expenseFactor = getWeightedExpenseFactor(); return dailyPersonelExpenseCategory.getValue().multiplyAndRound(new BigDecimal(expenseFactor)); } } public class MockWithAccommodationAndOneMealPersonelExpenseItem extends MockWithAccommodationPersonelExpenseItem { public MockWithAccommodationAndOneMealPersonelExpenseItem(final OtherPersonelExpenseItem missionItem) { super(missionItem); } @Override public double getWeightedExpenseFactor() { return getExpenseFactor() * 0.4; } @Override public Money getValue() { final DailyPersonelExpenseCategory dailyPersonelExpenseCategory = missionItem.getDailyPersonelExpenseCategory(); final double expenseFactor = getWeightedExpenseFactor(); return dailyPersonelExpenseCategory.getValue().multiplyAndRound(new BigDecimal(expenseFactor)); } } public class MockWithAccommodationAndTwoMealsPersonelExpenseItem extends MockWithAccommodationPersonelExpenseItem { public MockWithAccommodationAndTwoMealsPersonelExpenseItem(final OtherPersonelExpenseItem missionItem) { super(missionItem); } @Override public double getWeightedExpenseFactor() { return getExpenseFactor() * 0.2; } @Override public Money getValue() { final DailyPersonelExpenseCategory dailyPersonelExpenseCategory = missionItem.getDailyPersonelExpenseCategory(); final double expenseFactor = getWeightedExpenseFactor(); return dailyPersonelExpenseCategory.getValue().multiplyAndRound(new BigDecimal(expenseFactor)); } } }