/* * @(#)RegularAcquisitionProcess.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; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.stream.Collectors; import org.fenixedu.bennu.core.domain.User; import org.joda.time.LocalDate; import module.finance.util.Money; import pt.ist.expenditureTrackingSystem._development.Bundle; import pt.ist.expenditureTrackingSystem.domain.ExpenditureTrackingSystem; import pt.ist.expenditureTrackingSystem.domain.acquisitions.simplified.activities.FundAllocationExpirationDate.FundAllocationNotAllowedException; 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; /** * * @author Paulo Abrantes * @author Luis Cruz * */ public abstract class RegularAcquisitionProcess extends RegularAcquisitionProcess_Base { public enum ActivityScope { REQUEST_INFORMATION, REQUEST_ITEM; } public RegularAcquisitionProcess() { super(); } public boolean isSimplifiedAcquisitionProcess() { return false; } public boolean isStandardAcquisitionProcess() { return false; } public Set<AcquisitionInvoice> getConfirmedInvoices(Person person) { return getAcquisitionRequest().getAcquisitionRequestItemStream().flatMap(i -> i.getConfirmedInvoices(person).stream()) .collect(Collectors.toSet()); } public Set<AcquisitionInvoice> getUnconfirmedInvoices(Person person) { return getAcquisitionRequest().getAcquisitionRequestItemStream().filter(i -> i.isResponsible(person)) .flatMap(i -> i.getUnconfirmedInvoices(person).stream()).collect(Collectors.toSet()); } public Set<AcquisitionInvoice> getAllUnconfirmedInvoices() { return getAcquisitionRequest().getAcquisitionRequestItemStream().flatMap(i -> i.getAllUnconfirmedInvoices().stream()) .collect(Collectors.toSet()); } public void confirmInvoiceBy(Person person) { getAcquisitionRequest().confirmInvoiceFor(person); if (getAcquisitionRequest().isInvoiceConfirmedBy() && getLastAcquisitionProcessState().isPendingInvoiceConfirmation()) { confirmInvoice(); } } public void cancelInvoiceConfirmationBy(final Person person) { getAcquisitionRequest().unconfirmInvoiceFor(person); if (getLastAcquisitionProcessState().isInvoiceConfirmed()) { cancelInvoiceConfirmation(); } } public void unconfirmInvoiceForAll() { getAcquisitionRequest().unconfirmInvoiceForAll(); cancelInvoiceConfirmation(); } @Override public void allocateFundsPermanently() { new AcquisitionProcessState(this, AcquisitionProcessStateType.FUNDS_ALLOCATED_PERMANENTLY); } public void cancel() { new AcquisitionProcessState(this, AcquisitionProcessStateType.CANCELED); } @Override protected void authorize() { final AcquisitionProcessStateType type; if (ExpenditureTrackingSystem.isInvoiceAllowedToStartAcquisitionProcess() && hasInvoiceFile()) { type = AcquisitionProcessStateType.INVOICE_RECEIVED; getRequest().processReceivedInvoice(); } else { type = AcquisitionProcessStateType.AUTHORIZED; } new AcquisitionProcessState(this, type); } protected void cancelInvoiceConfirmation() { new AcquisitionProcessState(this, AcquisitionProcessStateType.SUBMITTED_FOR_CONFIRM_INVOICE); } protected void confirmInvoice() { new AcquisitionProcessState(this, AcquisitionProcessStateType.INVOICE_CONFIRMED); } @Override public void allocateFundsToUnit() { new AcquisitionProcessState(this, AcquisitionProcessStateType.FUNDS_ALLOCATED); } public void allocateFundsToSupplier() { new AcquisitionProcessState(this, AcquisitionProcessStateType.FUNDS_ALLOCATED_TO_SERVICE_PROVIDER); } public void acquisitionPayed() { new AcquisitionProcessState(this, AcquisitionProcessStateType.ACQUISITION_PAYED); } public void invoiceReceived() { new AcquisitionProcessState(this, AcquisitionProcessStateType.INVOICE_RECEIVED); } public void reject() { new AcquisitionProcessState(this, AcquisitionProcessStateType.REJECTED); } public void inGenesis() { new AcquisitionProcessState(this, AcquisitionProcessStateType.IN_GENESIS); } @Override public void submitForApproval() { new AcquisitionProcessState(this, AcquisitionProcessStateType.SUBMITTED_FOR_APPROVAL); } public void processAcquisition() { new AcquisitionProcessState(this, AcquisitionProcessStateType.ACQUISITION_PROCESSED); } public void revertProcessedAcquisition() { new AcquisitionProcessState(this, AcquisitionProcessStateType.AUTHORIZED); } public void submitedForInvoiceConfirmation() { new AcquisitionProcessState(this, AcquisitionProcessStateType.SUBMITTED_FOR_CONFIRM_INVOICE); if (getAllUnconfirmedInvoices().isEmpty()) { confirmInvoice(); } } @Override public void submitForFundAllocation() { final AcquisitionProcessStateType type; if (ExpenditureTrackingSystem.isInvoiceAllowedToStartAcquisitionProcess() && hasInvoiceFile()) { type = AcquisitionProcessStateType.FUNDS_ALLOCATED_TO_SERVICE_PROVIDER; createFundAllocationRequest(false); } else { type = AcquisitionProcessStateType.SUBMITTED_FOR_FUNDS_ALLOCATION; } new AcquisitionProcessState(this, type); } public void skipFundAllocation() { new AcquisitionProcessState(this, AcquisitionProcessStateType.FUNDS_ALLOCATED_TO_SERVICE_PROVIDER); } @Override public void resetEffectiveFundAllocationId() { getAcquisitionRequest().resetEffectiveFundAllocationId(); confirmInvoice(); } @Override public boolean isProcessFlowCharAvailable() { return true; } @Override public void setSkipSupplierFundAllocation(Boolean skipSupplierFundAllocation) { throw new DomainException(Bundle.EXPENDITURE, "error.illegal.method.use"); } public void unSkipSupplierFundAllocation() { checkSupplierLimit(); super.setSkipSupplierFundAllocation(Boolean.FALSE); if (!getAcquisitionProcessState().isInGenesis()) { LocalDate now = new LocalDate(); setFundAllocationExpirationDate(now.plusDays(90)); } } public void skipSupplierFundAllocation() { super.setSkipSupplierFundAllocation(Boolean.TRUE); setFundAllocationExpirationDate(null); } public boolean isFinanceByAnyUnit(List<Unit> fromUnits) { for (Financer financer : getAcquisitionRequest().getFinancers()) { if (fromUnits.contains(financer.getUnit())) { return true; } } return false; } public boolean isPersonAbleToDirectlyAuthorize(Person person) { return isFinanceByAnyUnit(person.getDirectResponsibleUnits()) ? true : getRequestingUnit() .isMostDirectAuthorization(person, getAcquisitionRequest().getTotalItemValueWithAdditionalCostsAndVat()); } public List<Unit> getFinancingUnits() { List<Unit> units = new ArrayList<Unit>(); for (Financer financer : getAcquisitionRequest().getFinancers()) { units.add(financer.getUnit()); } return units; } @Override public boolean isInAuthorizedState() { return getAcquisitionProcessState().isAuthorized(); } public boolean isPendingInvoiceConfirmation() { return getAcquisitionProcessState().isPendingInvoiceConfirmation(); } public void removeFundAllocationExpirationDate() { setFundAllocationExpirationDate(null); if (!getAcquisitionProcessState().isCanceled()) { submitForFundAllocation(); } } @Override public boolean isInAllocatedToUnitState() { return getAcquisitionProcessState().isInAllocatedToUnitState(); } @Override public Money getTotalValue() { return getAcquisitionRequest().getCurrentTotalValue(); } @Override public Set<CPVReference> getCPVReferences() { final AcquisitionRequest acquisitionRequest = getRequest(); return acquisitionRequest.getCPVReferences(); } public void createFundAllocationRequest(final boolean isFinalFundAllocation) { final AcquisitionRequest acquisitionRequest = getAcquisitionRequest(); acquisitionRequest.createFundAllocationRequest(isFinalFundAllocation); } public void cancelFundAllocationRequest(final boolean isFinalFundAllocation) { final AcquisitionRequest acquisitionRequest = getAcquisitionRequest(); acquisitionRequest.cancelFundAllocationRequest(isFinalFundAllocation); } public boolean hasInvoiceFile() { return false; } public boolean isCommitted() { final ExpenditureTrackingSystem instance = ExpenditureTrackingSystem.getInstance(); if (instance.getRequireCommitmentNumber() != null && instance.getRequireCommitmentNumber().booleanValue()) { final AcquisitionRequest acquisitionRequest = getAcquisitionRequest(); return acquisitionRequest.isCommitted(); } return true; } public boolean isPendingCommitmentByUser(final User user) { final ExpenditureTrackingSystem instance = ExpenditureTrackingSystem.getInstance(); if (instance.getRequireCommitmentNumber() != null && instance.getRequireCommitmentNumber().booleanValue()) { final AcquisitionRequest acquisitionRequest = getAcquisitionRequest(); return acquisitionRequest.isPendingCommitmentByUser(user); } return false; } public boolean hasCommitmentByUser(final User user) { final ExpenditureTrackingSystem instance = ExpenditureTrackingSystem.getInstance(); if (instance.getRequireCommitmentNumber() != null && instance.getRequireCommitmentNumber().booleanValue()) { final AcquisitionRequest acquisitionRequest = getAcquisitionRequest(); return acquisitionRequest.hasCommitmentByUser(user); } return false; } public void checkSupplierLimit() { final Map<Supplier, Map<CPVReference, Money>> allocationMap = new HashMap<Supplier, Map<CPVReference, Money>>(); for (final RequestItem requestItem : getRequest().getRequestItemsSet()) { final AcquisitionRequestItem acquisitionRequestItem = (AcquisitionRequestItem) requestItem; final CPVReference cpvReference = requestItem.getCPVReference(); final Money value = acquisitionRequestItem.getCurrentSupplierAllocationValue(); for (final Supplier supplier : getSuppliers()) { final String key = cpvReference.getExternalId() + supplier.getExternalId(); if (!allocationMap.containsKey(supplier)) { allocationMap.put(supplier, new HashMap<CPVReference, Money>()); } final Map<CPVReference, Money> map = allocationMap.get(supplier); if (map.containsKey(cpvReference)) { map.put(cpvReference, value.add(map.get(cpvReference))); } else { map.put(cpvReference, value); } } } final boolean checkSupplierLimitsByCPV = ExpenditureTrackingSystem.getInstance().checkSupplierLimitsByCPV(); for (final Entry<Supplier, Map<CPVReference, Money>> entry : allocationMap.entrySet()) { final Supplier supplier = entry.getKey(); final Map<CPVReference, Money> map = entry.getValue(); Money total = Money.ZERO; for (final Entry<CPVReference, Money> centry : map.entrySet()) { final CPVReference cpvReference = centry.getKey(); final Money value = centry.getValue(); if (checkSupplierLimitsByCPV && !supplier.isFundAllocationAllowed(cpvReference.getCode(), value)) { throw new FundAllocationNotAllowedException(); } total = total.add(value); } if (!checkSupplierLimitsByCPV && !supplier.isFundAllocationAllowed(total)) { throw new FundAllocationNotAllowedException(); } } } public boolean isReverifiedAfterCommitment() { final Boolean b = getProcessNeedsReverification(); return b == null || !b.booleanValue(); } public void reverifiedAfterCommitment() { setProcessNeedsReverification(Boolean.FALSE); } }