/**
* Copyright © 2002 Instituto Superior Técnico
*
* This file is part of FenixEdu Academic.
*
* FenixEdu Academic 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.
*
* FenixEdu Academic 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 FenixEdu Academic. If not, see <http://www.gnu.org/licenses/>.
*/
package org.fenixedu.academic.domain.accounting.installments;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import org.fenixedu.academic.domain.ExecutionSemester;
import org.fenixedu.academic.domain.accounting.Event;
import org.fenixedu.academic.domain.accounting.events.gratuity.GratuityEvent;
import org.fenixedu.academic.domain.accounting.paymentPlans.FullGratuityPaymentPlanForPartialRegime;
import org.fenixedu.academic.domain.exceptions.DomainException;
import org.fenixedu.academic.dto.accounting.paymentPlan.InstallmentBean;
import org.fenixedu.academic.util.Bundle;
import org.fenixedu.academic.util.LabelFormatter;
import org.fenixedu.academic.util.Money;
import org.joda.time.DateTime;
import org.joda.time.YearMonthDay;
public class PartialRegimeInstallment extends PartialRegimeInstallment_Base {
protected PartialRegimeInstallment() {
super();
}
public PartialRegimeInstallment(final FullGratuityPaymentPlanForPartialRegime paymentPlan, final Money amount,
final YearMonthDay startDate, final YearMonthDay endDate, final BigDecimal ectsForAmount,
final List<ExecutionSemester> executionSemesters) {
this();
init(paymentPlan, amount, startDate, endDate, false, null, null, null, ectsForAmount, executionSemesters);
}
private void init(FullGratuityPaymentPlanForPartialRegime paymentPlan, Money amount, YearMonthDay startDate,
YearMonthDay endDate, boolean penaltyAppliable, BigDecimal penaltyPercentage, YearMonthDay whenStartToApplyPenalty,
Integer maxMonthsToApplyPenalty, BigDecimal ectsForAmount, List<ExecutionSemester> executionSemesters) {
if (penaltyAppliable) {
super.init(paymentPlan, amount, startDate, endDate, penaltyPercentage, whenStartToApplyPenalty,
maxMonthsToApplyPenalty);
} else {
super.init(paymentPlan, amount, startDate, endDate);
}
checkParameters(ectsForAmount, executionSemesters);
super.setPenaltyAppliable(penaltyAppliable);
super.setEctsForAmount(ectsForAmount);
for (final ExecutionSemester executionSemester : executionSemesters) {
super.addExecutionSemesters(executionSemester);
}
}
private void checkParameters(final BigDecimal ectsForAmount, final Collection<ExecutionSemester> executionSemesters) {
if (ectsForAmount == null) {
throw new DomainException(
"error.org.fenixedu.academic.domain.accounting.installments.PartialRegimeInstallment.ectsForAmount.cannot.be.null");
}
if (executionSemesters == null || executionSemesters.isEmpty()) {
throw new DomainException(
"error.org.fenixedu.academic.domain.accounting.installments.PartialRegimeInstallment.executionSemesters.cannot.be.null.or.empty");
}
}
public PartialRegimeInstallment(FullGratuityPaymentPlanForPartialRegime paymentPlan, Money amount, YearMonthDay startDate,
YearMonthDay endDate, BigDecimal penaltyPercentage, YearMonthDay whenStartToApplyPenalty,
Integer maxMonthsToApplyPenalty, BigDecimal ectsForAmount, List<ExecutionSemester> executionSemesters) {
this();
init(paymentPlan, amount, startDate, endDate, true, penaltyPercentage, whenStartToApplyPenalty, maxMonthsToApplyPenalty,
ectsForAmount, executionSemesters);
}
/**
* Formula: 0.5 x Amount x (1 + EnroledEcts / ectsForAmount)
*/
@Override
protected Money calculateBaseAmount(Event event) {
final BigDecimal enroledEcts = getEnroledEcts((GratuityEvent) event);
if (enroledEcts.compareTo(BigDecimal.ZERO) == 0) {
return Money.ZERO;
}
final BigDecimal proporcionToPay = enroledEcts.divide(getEctsForAmount());
// TODO: Fix Money limitation of scale = 2 to prevent this type of
// coding
final BigDecimal amount = getAmount().getAmount().setScale(10);
return new Money(amount.multiply(new BigDecimal("0.5")).multiply(BigDecimal.ONE.add(proporcionToPay)));
}
@Override
protected Money calculatePenaltyAmount(Event event, DateTime when, BigDecimal discountPercentage) {
if (isPenaltyAppliable()) {
return super.calculatePenaltyAmount(event, when, discountPercentage);
}
return Money.ZERO;
}
private BigDecimal getEnroledEcts(GratuityEvent gratuityEvent) {
return getExecutionSemestersSet().stream()
.flatMap(es -> gratuityEvent.getStudentCurricularPlan().getCycleCurriculumGroups().stream()
.flatMap(ccg -> ccg.getEnrolmentsBy(es).stream()))
.map(e -> e.getEctsCreditsForCurriculum())
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
@Override
public FullGratuityPaymentPlanForPartialRegime getPaymentPlan() {
return (FullGratuityPaymentPlanForPartialRegime) super.getPaymentPlan();
}
public boolean isPenaltyAppliable() {
return getPenaltyAppliable().booleanValue();
}
@Override
public LabelFormatter getDescription() {
final LabelFormatter labelFormatter = new LabelFormatter();
if (isPenaltyAppliable()) {
labelFormatter.appendLabel(Bundle.APPLICATION, "label.PartialRegimeInstallment.description.with.penalty",
getInstallmentOrder().toString(), getStartDate().toString("dd/MM/yyyy"), getEndDate().toString("dd/MM/yyyy"),
buildExecutionSemesterDescription(), getPenaltyPercentage().multiply(BigDecimal.valueOf(100)).toString(),
getWhenStartToApplyPenalty().toString("dd/MM/yyyy"));
} else {
labelFormatter.appendLabel(Bundle.APPLICATION, "label.PartialRegimeInstallment.description.without.penalty",
getInstallmentOrder().toString(), getStartDate().toString("dd/MM/yyyy"), getEndDate().toString("dd/MM/yyyy"),
buildExecutionSemesterDescription());
}
return labelFormatter;
}
private String buildExecutionSemesterDescription() {
final StringBuilder result = new StringBuilder();
for (final ExecutionSemester executionSemester : getExecutionSemestersSet()) {
result.append(executionSemester.getName()).append(", ");
}
if (result.length() > 0 && result.toString().endsWith(", ")) {
result.delete(result.length() - 2, result.length());
}
return result.toString();
}
@Override
public void delete() {
getExecutionSemestersSet().clear();
super.delete();
}
@Override
public void edit(final InstallmentBean bean) {
final Collection<ExecutionSemester> executionSemesters = bean.getExecutionSemesters();
final BigDecimal ectsForAmount = bean.getEctsForAmount();
checkParameters(ectsForAmount, executionSemesters);
getExecutionSemestersSet().addAll(executionSemesters);
getExecutionSemestersSet().retainAll(executionSemesters);
super.setEctsForAmount(ectsForAmount);
super.edit(bean);
}
}