/*
* @(#)RefundItem.java
*
* Copyright 2009 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 pt.ist.expenditureTrackingSystem.domain.acquisitions.refund;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import module.finance.util.Money;
import module.workflow.domain.WorkflowProcess;
import org.joda.time.LocalDate;
import pt.ist.expenditureTrackingSystem._development.Bundle;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.AcquisitionItemClassification;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.CPVReference;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.PaymentProcessInvoice;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.RequestWithPayment;
import pt.ist.expenditureTrackingSystem.domain.acquisitions.UnitItem;
import pt.ist.expenditureTrackingSystem.domain.organization.Person;
import pt.ist.expenditureTrackingSystem.domain.organization.Supplier;
import pt.ist.expenditureTrackingSystem.domain.organization.Unit;
import pt.ist.expenditureTrackingSystem.domain.util.DomainException;
import pt.ist.fenixframework.Atomic;
/**
*
* @author João Neves
* @author Pedro Santos
* @author Paulo Abrantes
* @author Luis Cruz
*
*/
public class RefundItem extends RefundItem_Base {
public static final Comparator<RefundItem> COMPARATOR = new Comparator<RefundItem>() {
@Override
public int compare(RefundItem arg0, RefundItem arg1) {
final int c = arg0.getDescription().compareTo(arg1.getDescription());
return c == 0 ? arg0.getExternalId().compareTo(arg1.getExternalId()) : c;
}
};
public RefundItem(RefundRequest request, Money valueEstimation, CPVReference reference,
AcquisitionItemClassification classification, String description) {
super();
if (description == null || reference == null || valueEstimation == null || valueEstimation.equals(Money.ZERO)) {
throw new DomainException(Bundle.EXPENDITURE, "refundProcess.message.exception.refundItem.invalidArguments");
}
setClassification(classification);
setDescription(description);
setCPVReference(reference);
setValueEstimation(valueEstimation);
setRequest(request);
}
@Override
public Money getRealValue() {
return getValueSpent();
}
@Override
public Money getValue() {
return getValueEstimation();
}
@Override
public Money getValueWithoutVat() {
return getValueEstimation();
}
@Override
public BigDecimal getVatValue() {
return BigDecimal.ZERO;
}
public void edit(Money valueEstimation, CPVReference reference, AcquisitionItemClassification classification,
String description) {
setDescription(description);
setClassification(classification);
setCPVReference(reference);
setValueEstimation(valueEstimation);
}
@Override
public void delete() {
setRequest(null);
super.delete();
}
@Override
public boolean isValueFullyAttributedToUnits() {
Money totalValue = Money.ZERO;
for (UnitItem unitItem : getUnitItems()) {
totalValue = totalValue.add(unitItem.getShareValue());
}
return totalValue.equals(getValueEstimation());
}
public boolean hasAtLeastOneResponsibleApproval() {
for (UnitItem unitItem : getUnitItems()) {
if (unitItem.getItemAuthorized()) {
return true;
}
}
return false;
}
@Override
public void createUnitItem(Unit unit, Money shareValue) {
createUnitItem(getRequest().addPayingUnit(unit), shareValue);
}
@Atomic
public RefundableInvoiceFile createRefundInvoice(String invoiceNumber, LocalDate invoiceDate, Money value,
BigDecimal vatValue, Money refundableValue, byte[] invoiceFile, String filename, Supplier supplier,
WorkflowProcess process) {
RefundableInvoiceFile invoice =
new RefundableInvoiceFile(invoiceNumber, invoiceDate, value, vatValue, refundableValue, invoiceFile, filename,
this, supplier);
Set<Unit> payingUnits = getRequest().getPayingUnits();
if (payingUnits.size() == 1) {
UnitItem unitItemFor = getUnitItemFor(payingUnits.iterator().next());
Money amount = Money.ZERO;
for (RefundableInvoiceFile invoicesToSum : getRefundableInvoices()) {
amount = amount.addAndRound(invoicesToSum.getRefundableValue());
}
clearRealShareValues();
unitItemFor.setRealShareValue(amount);
}
process.addFiles(invoice);
return invoice;
}
public Money getValueSpent() {
Collection<PaymentProcessInvoice> invoicesFiles = getInvoicesFiles();
if (invoicesFiles.isEmpty()) {
return null;
}
Money spent = Money.ZERO;
for (PaymentProcessInvoice invoice : invoicesFiles) {
spent = spent.addAndRound(((RefundableInvoiceFile) invoice).getRefundableValue());
}
return spent;
}
@Override
public boolean isFilledWithRealValues() {
return !getRefundableInvoices().isEmpty();
}
public void getSuppliers(final Set<Supplier> suppliers) {
for (final RefundableInvoiceFile refundInvoice : getRefundableInvoices()) {
final Supplier supplier = refundInvoice.getSupplier();
if (supplier != null) {
suppliers.add(supplier);
}
}
}
@Override
public Money getTotalAmountForCPV(final int year) {
return isAppliableForCPV(year) ? getCurrentSupplierAllocationValue() : Money.ZERO;
}
private Money getCurrentSupplierAllocationValue() {
Money spent = Money.ZERO;
for (RefundableInvoiceFile invoice : getRefundableInvoices()) {
spent = spent.add(invoice.getRefundableValue());
}
return spent;
}
private boolean isAppliableForCPV(final int year) {
final RequestWithPayment requestWithPayment = getRequest();
final RefundProcess refundProcess = requestWithPayment.getProcess();
return refundProcess.isActive() && refundProcess.isAppiableForYear(year);
}
@Override
public void confirmInvoiceBy(Person person) {
for (UnitItem unitItem : getUnitItems()) {
if (getRequest().getProcess().isAccountingEmployee(person)
|| getRequest().getProcess().isProjectAccountingEmployee(person)) {
unitItem.getConfirmedInvoices().clear();
for (PaymentProcessInvoice invoice : getInvoicesFiles()) {
unitItem.addConfirmedInvoices(invoice);
}
}
}
}
@Override
public void unconfirmInvoiceBy(Person person) {
for (UnitItem unitItem : getUnitItems()) {
if (getRequest().getProcess().isAccountingEmployee(person)
|| getRequest().getProcess().isProjectAccountingEmployee(person)) {
unitItem.getConfirmedInvoices().clear();
}
}
}
@Override
public <T extends PaymentProcessInvoice> List<T> getConfirmedInvoices(Person person) {
List<T> invoices = new ArrayList<T>();
for (UnitItem unitItem : getUnitItems()) {
if (person == null || unitItem.getFinancer().getUnit().isAccountingEmployee(person)
|| unitItem.getFinancer().getUnit().isProjectAccountingEmployee(person)) {
invoices.addAll((Collection<T>) unitItem.getConfirmedInvoices());
}
}
return invoices;
}
public boolean isRefundValueBiggerThanEstimateValue() {
Money refundableValue = Money.ZERO;
for (RefundableInvoiceFile invoice : getRefundableInvoices()) {
refundableValue = refundableValue.add(invoice.getRefundableValue());
}
return refundableValue.isGreaterThan(getValueEstimation());
}
public boolean isAnyRefundInvoiceAvailable() {
return !getRefundableInvoices().isEmpty();
}
@Override
public boolean isRealValueFullyAttributedToUnits() {
Money realValue = getRealValue();
if (realValue == null) {
return getRefundableInvoices().isEmpty();
}
Money totalValue = Money.ZERO;
for (UnitItem unitItem : getUnitItems()) {
if (unitItem.getRealShareValue() != null) {
totalValue = totalValue.add(unitItem.getRealShareValue());
}
}
return totalValue.equals(realValue);
}
public List<RefundableInvoiceFile> getRefundableInvoices() {
List<RefundableInvoiceFile> invoices = new ArrayList<RefundableInvoiceFile>();
for (PaymentProcessInvoice invoice : getInvoicesFiles()) {
invoices.add((RefundableInvoiceFile) invoice);
}
return invoices;
}
@Deprecated
public boolean hasValueEstimation() {
return getValueEstimation() != null;
}
@Deprecated
public boolean hasItemNotExecuted() {
return getItemNotExecuted() != null;
}
}