Java tutorial
/** * This file was created by Quorum Born IT <http://www.qub-it.com/> and its * copyright terms are bind to the legal agreement regulating the FenixEdu@ULisboa * software development project between Quorum Born IT and Servios Partilhados da * Universidade de Lisboa: * - Copyright 2015 Quorum Born IT (until any Go-Live phase) * - Copyright 2015 Universidade de Lisboa (after any Go-Live phase) * * Contributors: ricardo.pedro@qub-it.com, anil.mamede@qub-it.com * * * This file is part of FenixEdu Treasury. * * FenixEdu Treasury 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 Treasury 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 Treasury. If not, see <http://www.gnu.org/licenses/>. */ package org.fenixedu.treasury.ui.document.managepayments; import java.io.IOException; import java.math.BigDecimal; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; import org.fenixedu.bennu.core.i18n.BundleUtil; import org.fenixedu.bennu.spring.portal.SpringFunctionality; import org.fenixedu.commons.StringNormalizer; import org.fenixedu.treasury.domain.Currency; import org.fenixedu.treasury.domain.FinantialInstitution; import org.fenixedu.treasury.domain.PaymentMethod; import org.fenixedu.treasury.domain.debt.DebtAccount; import org.fenixedu.treasury.domain.document.DocumentNumberSeries; import org.fenixedu.treasury.domain.document.FinantialDocument; import org.fenixedu.treasury.domain.document.FinantialDocumentStateType; import org.fenixedu.treasury.domain.document.FinantialDocumentType; import org.fenixedu.treasury.domain.document.PaymentEntry; import org.fenixedu.treasury.domain.document.ReimbursementEntry; import org.fenixedu.treasury.domain.document.SettlementEntry; import org.fenixedu.treasury.domain.document.SettlementNote; import org.fenixedu.treasury.domain.exceptions.TreasuryDomainException; import org.fenixedu.treasury.domain.integration.ERPExportOperation; import org.fenixedu.treasury.dto.InterestRateBean; import org.fenixedu.treasury.dto.SettlementNoteBean; import org.fenixedu.treasury.dto.SettlementNoteBean.CreditEntryBean; import org.fenixedu.treasury.dto.SettlementNoteBean.DebitEntryBean; import org.fenixedu.treasury.dto.SettlementNoteBean.InterestEntryBean; import org.fenixedu.treasury.services.integration.erp.ERPExporter; import org.fenixedu.treasury.ui.TreasuryBaseController; import org.fenixedu.treasury.ui.TreasuryController; import org.fenixedu.treasury.ui.accounting.managecustomer.DebtAccountController; import org.fenixedu.treasury.ui.integration.erp.ERPExportOperationController; import org.fenixedu.treasury.util.Constants; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import pt.ist.fenixframework.Atomic; //@Component("org.fenixedu.treasury.ui.document.managePayments") <-- Use for duplicate controller name disambiguation @SpringFunctionality(app = TreasuryController.class, title = "label.title.document.managePayments", accessGroup = "treasuryFrontOffice") @RequestMapping(SettlementNoteController.CONTROLLER_URL) public class SettlementNoteController extends TreasuryBaseController { public static final String CONTROLLER_URL = "/treasury/document/managepayments/settlementnote"; private static final String SEARCH_URI = "/"; public static final String SEARCH_URL = CONTROLLER_URL + SEARCH_URI; private static final String UPDATE_URI = "/update/"; public static final String UPDATE_URL = CONTROLLER_URL + UPDATE_URI; private static final String CREATE_URI = "/create"; public static final String CREATE_URL = CONTROLLER_URL + CREATE_URI; private static final String READ_URI = "/read/"; public static final String READ_URL = CONTROLLER_URL + READ_URI; private static final String DELETE_URI = "/delete/"; public static final String DELETE_URL = CONTROLLER_URL + DELETE_URI; private static final String CHOOSE_INVOICE_ENTRIES_URI = "/chooseInvoiceEntries/"; public static final String CHOOSE_INVOICE_ENTRIES_URL = CONTROLLER_URL + CHOOSE_INVOICE_ENTRIES_URI; private static final String CALCULATE_INTEREST_URI = "/calculateInterest/"; public static final String CALCULATE_INTEREST_URL = CONTROLLER_URL + CALCULATE_INTEREST_URI; private static final String CREATE_DEBIT_NOTE_URI = "/createDebitNote/"; public static final String CREATE_DEBIT_NOTE_URL = CONTROLLER_URL + CREATE_DEBIT_NOTE_URI; private static final String INSERT_PAYMENT_URI = "/insertpayment/"; public static final String INSERT_PAYMENT_URL = CONTROLLER_URL + INSERT_PAYMENT_URI; private static final String SUMMARY_URI = "/summary/"; public static final String SUMMARY_URL = CONTROLLER_URL + SUMMARY_URI; private static final String TRANSACTIONS_SUMMARY_URI = "/transactions/summary/"; public static final String TRANSACTIONS_SUMMARY_URL = CONTROLLER_URL + TRANSACTIONS_SUMMARY_URI; public static final long SEARCH_SETTLEMENT_NOTE_LIST_LIMIT_SIZE = 500; public static final long SEARCH_SETTLEMENT_ENTRY_LIMIT_DAYS_PERIOD = 30; @RequestMapping public String home(Model model) { return "forward:" + SEARCH_URL; } private void setSettlementNoteBean(SettlementNoteBean bean, Model model) { model.addAttribute("settlementNoteBeanJson", getBeanJson(bean)); model.addAttribute("settlementNoteBean", bean); } private SettlementNote getSettlementNote(Model model) { return (SettlementNote) model.asMap().get("settlementNote"); } private void setSettlementNote(SettlementNote settlementNote, Model model) { model.addAttribute("settlementNote", settlementNote); } @Atomic public void deleteSettlementNote(SettlementNote settlementNote) { settlementNote.delete(true); } @RequestMapping(value = CHOOSE_INVOICE_ENTRIES_URI + "{debtAccountId}/{reimbursementNote}") public String chooseInvoiceEntries(@PathVariable(value = "debtAccountId") DebtAccount debtAccount, @PathVariable(value = "reimbursementNote") boolean reimbursementNote, @RequestParam(value = "bean", required = false) SettlementNoteBean bean, Model model) { assertUserIsAllowToModifySettlements(debtAccount.getFinantialInstitution(), model); if (bean == null) { bean = new SettlementNoteBean(debtAccount, reimbursementNote); } setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/chooseInvoiceEntries"; } @RequestMapping(value = CHOOSE_INVOICE_ENTRIES_URI, method = RequestMethod.POST) public String chooseInvoiceEntries(@RequestParam(value = "bean", required = true) SettlementNoteBean bean, Model model) { BigDecimal debitSum = BigDecimal.ZERO; BigDecimal creditSum = BigDecimal.ZERO; boolean error = false; assertUserIsAllowToModifySettlements(bean.getDebtAccount().getFinantialInstitution(), model); for (int i = 0; i < bean.getDebitEntries().size(); i++) { DebitEntryBean debitEntryBean = bean.getDebitEntries().get(i); if (debitEntryBean.isIncluded()) { if (debitEntryBean.getDebtAmountWithVat().compareTo(BigDecimal.ZERO) == 0) { debitEntryBean.setNotValid(true); error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.DebitEntry.debtAmount.equal.zero", Integer.toString(i + 1)), model); } else if (debitEntryBean.getDebtAmountWithVat() .compareTo(debitEntryBean.getDebitEntry().getOpenAmount()) > 0) { debitEntryBean.setNotValid(true); error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.DebitEntry.exceeded.openAmount", Integer.toString(i + 1)), model); } else { debitEntryBean.setNotValid(false); } //Always perform the sum, in order to verify if creditSum is not higher than debitSum debitSum = debitSum.add(debitEntryBean.getDebtAmountWithVat()); } else { debitEntryBean.setNotValid(false); } } for (CreditEntryBean creditEntryBean : bean.getCreditEntries()) { if (creditEntryBean.isIncluded()) { creditSum = creditSum.add(creditEntryBean.getCreditEntry().getOpenAmount()); } } if (bean.isReimbursementNote() && creditSum.compareTo(debitSum) < 0) { error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.SettlementNote.positive.payment.value"), model); } if (!bean.isReimbursementNote() && creditSum.compareTo(debitSum) > 0) { error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.SettlementNote.negative.payment.value"), model); } if (bean.isReimbursementNote() && creditSum.compareTo(BigDecimal.ZERO) == 0) { error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.CreditEntry.no.creditEntries.selected"), model); } if (!bean.isReimbursementNote() && debitSum.compareTo(BigDecimal.ZERO) == 0) { error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.DebiEntry.no.debitEntries.selected"), model); } if (bean.getDate().isAfter(new LocalDate())) { error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.SettlementNote.date.is.after"), model); } if (bean.getDocNumSeries() == null) { error = true; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.SettlementNote.need.documentSeries"), model); } if (error) { setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/chooseInvoiceEntries"; } bean.setInterestEntries(new ArrayList<InterestEntryBean>()); for (DebitEntryBean debitEntryBean : bean.getDebitEntries()) { if (debitEntryBean.isIncluded() && Constants.isEqual(debitEntryBean.getDebitEntry().getOpenAmount(), debitEntryBean.getDebtAmount())) { //Calculate interest only if we are making a FullPayment InterestRateBean debitInterest = debitEntryBean.getDebitEntry() .calculateUndebitedInterestValue(bean.getDate()); if (debitInterest.getInterestAmount().compareTo(BigDecimal.ZERO) != 0) { InterestEntryBean interestEntryBean = bean.new InterestEntryBean(debitEntryBean.getDebitEntry(), debitInterest); bean.getInterestEntries().add(interestEntryBean); } } } if (bean.getInterestEntries().size() == 0) { return calculateInterest(bean, model); } setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/calculateInterest"; } @RequestMapping(value = CALCULATE_INTEREST_URI, method = RequestMethod.POST) public String calculateInterest(@RequestParam(value = "bean", required = true) SettlementNoteBean bean, Model model) { try { assertUserIsAllowToModifySettlements(bean.getDebtAccount().getFinantialInstitution(), model); for (DebitEntryBean debitEntryBean : bean.getDebitEntries()) { if (debitEntryBean.isIncluded() && debitEntryBean.getDebitEntry().getFinantialDocument() == null) { setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/createDebitNote"; } } for (InterestEntryBean interestEntryBean : bean.getInterestEntries()) { if (interestEntryBean.isIncluded()) { setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/createDebitNote"; } } } catch (TreasuryDomainException tde) { addErrorMessage( BundleUtil.getString(Constants.BUNDLE, "label.error.delete") + tde.getLocalizedMessage(), model); } catch (Exception ex) { addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "label.error.delete") + ex.getLocalizedMessage(), model); } return createDebitNote(bean, model); } @RequestMapping(value = CREATE_DEBIT_NOTE_URI, method = RequestMethod.POST) public String createDebitNote(@RequestParam(value = "bean", required = true) SettlementNoteBean bean, Model model) { setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/insertPayment"; } @RequestMapping(value = INSERT_PAYMENT_URI, method = RequestMethod.POST) public String insertPayment(@RequestParam(value = "bean", required = true) SettlementNoteBean bean, Model model) { assertUserIsAllowToModifySettlements(bean.getDebtAccount().getFinantialInstitution(), model); BigDecimal debitSum = bean.isReimbursementNote() ? bean.getDebtAmountWithVat().negate() : bean.getDebtAmountWithVat(); BigDecimal paymentSum = bean.getPaymentAmount(); boolean error = false; if (bean.getPaymentEntries().stream() .anyMatch(peb -> peb.getPaymentAmount().compareTo(BigDecimal.ZERO) == 0)) { error = true; String errorMessage = bean.isReimbursementNote() ? "error.SettlementNote.reimbursement.equal.zero" : "error.SettlementNote.payment.equal.zero"; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, errorMessage), model); } if (debitSum.compareTo(paymentSum) != 0) { error = true; String errorMessage = bean.isReimbursementNote() ? "error.SettlementNote.no.match.reimbursement.credit" : "error.SettlementNote.no.match.payment.debit"; addErrorMessage(BundleUtil.getString(Constants.BUNDLE, errorMessage), model); } if (error) { setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/insertPayment"; } setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/summary"; } @RequestMapping(value = SUMMARY_URI, method = RequestMethod.POST) public String summary(@RequestParam(value = "bean", required = true) SettlementNoteBean bean, Model model, RedirectAttributes redirectAttributes) { try { assertUserIsAllowToModifySettlements(bean.getDebtAccount().getFinantialInstitution(), model); SettlementNote settlementNote = processSettlementNoteCreation(bean); addInfoMessage(BundleUtil.getString(Constants.BUNDLE, "label.SettlementNote.create.success"), model); return redirect(READ_URL + settlementNote.getExternalId(), model, redirectAttributes); } catch (final TreasuryDomainException tde) { addErrorMessage(tde.getLocalizedMessage(), model); } setSettlementNoteBean(bean, model); return "treasury/document/managepayments/settlementnote/summary"; } @Atomic public SettlementNote processSettlementNoteCreation(SettlementNoteBean bean) { SettlementNote settlementNote = SettlementNote.create(bean.getDebtAccount(), bean.getDocNumSeries(), bean.getDate().toDateTimeAtStartOfDay(), bean.getOriginDocumentNumber()); settlementNote.processSettlementNoteCreation(bean); return settlementNote; } @RequestMapping(value = SEARCH_URI) public String search(@RequestParam(value = "debtaccount", required = false) DebtAccount debtAccount, @RequestParam(value = "documentnumberseries", required = false) DocumentNumberSeries documentNumberSeries, @RequestParam(value = "currency", required = false) Currency currency, @RequestParam(value = "documentnumber", required = false) String documentNumber, @RequestParam(value = "documentdatefrom", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate documentDateFrom, @RequestParam(value = "documentdateto", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate documentDateTo, @RequestParam(value = "documentduedate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") DateTime documentDueDate, @RequestParam(value = "origindocumentnumber", required = false) String originDocumentNumber, @RequestParam(value = "state", required = false) FinantialDocumentStateType state, Model model) { List<SettlementNote> searchsettlementnoteResultsDataSet = filterSearchSettlementNote(debtAccount, documentNumberSeries, currency, documentNumber, documentDateFrom, documentDateTo, documentDueDate, originDocumentNumber, state); // add the results dataSet to the model model.addAttribute("listSize", searchsettlementnoteResultsDataSet.size()); model.addAttribute("searchsettlementnoteResultsDataSet", searchsettlementnoteResultsDataSet); searchsettlementnoteResultsDataSet = searchsettlementnoteResultsDataSet.stream() .limit(SEARCH_SETTLEMENT_NOTE_LIST_LIMIT_SIZE).collect(Collectors.toList()); model.addAttribute("SettlementNote_finantialDocumentType_options", FinantialDocumentType.findAll().collect(Collectors.toList())); model.addAttribute("SettlementNote_debtAccount_options", DebtAccount.findAll().collect(Collectors.toList())); model.addAttribute("SettlementNote_documentNumberSeries_options", org.fenixedu.treasury.domain.document.DocumentNumberSeries.findAll().filter( dNS -> dNS.getFinantialDocumentType().equals(FinantialDocumentType.findForSettlementNote())) .filter(x -> x.getSeries().getActive() == true).collect(Collectors.toList())); model.addAttribute("SettlementNote_currency_options", org.fenixedu.treasury.domain.Currency.findAll().collect(Collectors.toList())); model.addAttribute("stateValues", org.fenixedu.treasury.domain.document.FinantialDocumentStateType.values()); return "treasury/document/managepayments/settlementnote/search"; } private List<SettlementNote> getSearchUniverseSearchSettlementNoteDataSet() { return SettlementNote.findAll().collect(Collectors.toList()); } private List<SettlementNote> filterSearchSettlementNote(DebtAccount debtAccount, DocumentNumberSeries documentNumberSeries, Currency currency, String documentNumber, LocalDate documentDateFrom, LocalDate documentDateTo, DateTime documentDueDate, String originDocumentNumber, FinantialDocumentStateType state) { return getSearchUniverseSearchSettlementNoteDataSet().stream() .filter(settlementNote -> FinantialDocumentType.findForSettlementNote() == settlementNote .getFinantialDocumentType() || FinantialDocumentType.findForReimbursementNote() == settlementNote .getFinantialDocumentType()) .filter(settlementNote -> debtAccount == null || debtAccount == settlementNote.getDebtAccount()) .filter(settlementNote -> documentNumberSeries == null || documentNumberSeries == settlementNote.getDocumentNumberSeries()) .filter(settlementNote -> currency == null || currency == settlementNote.getCurrency()) .filter(settlementNote -> documentNumber == null || documentNumber.length() == 0 || settlementNote.getDocumentNumber() != null && settlementNote.getDocumentNumber().length() > 0 && settlementNote.getUiDocumentNumber().toLowerCase() .contains(documentNumber.toLowerCase())) .filter(creditNote -> documentDateFrom == null || creditNote.getDocumentDate().toLocalDate().isEqual(documentDateFrom) || creditNote.getDocumentDate().toLocalDate().isAfter(documentDateFrom)) .filter(creditNote -> documentDateTo == null || creditNote.getDocumentDate().toLocalDate().isEqual(documentDateTo) || creditNote.getDocumentDate().toLocalDate().isBefore(documentDateTo)) .filter(settlementNote -> documentDueDate == null || documentDueDate.equals(settlementNote.getDocumentDueDate())) .filter(settlementNote -> originDocumentNumber == null || originDocumentNumber.length() == 0 || settlementNote.getOriginDocumentNumber() != null && settlementNote.getOriginDocumentNumber().length() > 0 && settlementNote.getOriginDocumentNumber().toLowerCase() .contains(originDocumentNumber.toLowerCase())) .filter(settlementNote -> state == null || state.equals(settlementNote.getState())) .collect(Collectors.toList()); } @RequestMapping(value = "/search/view/{oid}") public String processSearchToViewAction(@PathVariable("oid") SettlementNote settlementNote, Model model, RedirectAttributes redirectAttributes) { return redirect(READ_URL + settlementNote.getExternalId(), model, redirectAttributes); } @RequestMapping(value = READ_URI + "{oid}") public String read(@PathVariable("oid") SettlementNote settlementNote, Model model) { setSettlementNote(settlementNote, model); return "treasury/document/managepayments/settlementnote/read"; } @RequestMapping(value = DELETE_URI + "{oid}", method = RequestMethod.POST) public String delete(@PathVariable("oid") SettlementNote settlementNote, Model model, RedirectAttributes redirectAttributes) { setSettlementNote(settlementNote, model); try { DebtAccount debtAccount = settlementNote.getDebtAccount(); assertUserIsAllowToModifySettlements(debtAccount.getFinantialInstitution(), model); deleteSettlementNote(settlementNote); addInfoMessage(BundleUtil.getString(Constants.BUNDLE, "label.success.delete"), model); return redirect(DebtAccountController.READ_URL + debtAccount.getExternalId(), model, redirectAttributes); } catch (TreasuryDomainException tde) { addErrorMessage( BundleUtil.getString(Constants.BUNDLE, "label.error.delete") + tde.getLocalizedMessage(), model); } catch (Exception ex) { addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "label.error.delete") + ex.getLocalizedMessage(), model); } return redirect(READ_URL + getSettlementNote(model).getExternalId(), model, redirectAttributes); } @RequestMapping(value = UPDATE_URI + "{oid}", method = RequestMethod.GET) public String update(@PathVariable("oid") SettlementNote settlementNote, Model model) { model.addAttribute("SettlementNote_finantialDocumentType_options", org.fenixedu.treasury.domain.document.FinantialDocumentType.findAll()); model.addAttribute("SettlementNote_debtAccount_options", new ArrayList<org.fenixedu.treasury.domain.debt.DebtAccount>()); // CHANGE_ME model.addAttribute("SettlementNote_documentNumberSeries_options", org.fenixedu.treasury.domain.document.DocumentNumberSeries.findAll()); model.addAttribute("SettlementNote_currency_options", org.fenixedu.treasury.domain.Currency.findAll()); model.addAttribute("stateValues", org.fenixedu.treasury.domain.document.FinantialDocumentStateType.values()); setSettlementNote(settlementNote, model); return "treasury/document/managepayments/settlementnote/update"; } // @RequestMapping(value = UPDATE_URI + "{oid}", method = RequestMethod.POST) public String update(@PathVariable("oid") SettlementNote settlementNote, @RequestParam(value = "origindocumentnumber", required = false) java.lang.String originDocumentNumber, @RequestParam(value = "documentobservations", required = false) java.lang.String documentObservations, Model model, RedirectAttributes redirectAttributes) { setSettlementNote(settlementNote, model); try { assertUserIsAllowToModifySettlements(settlementNote.getDebtAccount().getFinantialInstitution(), model); updateSettlementNote(originDocumentNumber, documentObservations, model); return redirect(READ_URL + getSettlementNote(model).getExternalId(), model, redirectAttributes); } catch (TreasuryDomainException tde) { addErrorMessage( BundleUtil.getString(Constants.BUNDLE, "label.error.update") + tde.getLocalizedMessage(), model); } catch (Exception ex) { addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "label.error.update") + ex.getLocalizedMessage(), model); } return update(settlementNote, model); } @Atomic public void updateSettlementNote(java.lang.String originDocumentNumber, String documentObservations, Model model) { getSettlementNote(model).setOriginDocumentNumber(originDocumentNumber); getSettlementNote(model).setDocumentObservations(documentObservations); } @RequestMapping(value = "/read/{oid}/anullsettlement", method = RequestMethod.POST) public String processReadToAnullSettlementNote(@PathVariable("oid") SettlementNote settlementNote, @RequestParam("anullReason") String anullReason, Model model, RedirectAttributes redirectAttributes) { setSettlementNote(settlementNote, model); try { assertUserIsAllowToModifySettlements(settlementNote.getDebtAccount().getFinantialInstitution(), model); settlementNote.changeState(FinantialDocumentStateType.ANNULED, anullReason); addInfoMessage(BundleUtil.getString(Constants.BUNDLE, "label.document.managepayments.SettlementNote.document.anulled.sucess"), model); } catch (Exception ex) { addErrorMessage(ex.getLocalizedMessage(), model); } return redirect(READ_URL + getSettlementNote(model).getExternalId(), model, redirectAttributes); } @RequestMapping(value = "/read/{oid}/exportintegrationfile", produces = "text/xml;charset=Windows-1252") public void processReadToExportIntegrationFile(@PathVariable("oid") SettlementNote settlementNote, Model model, RedirectAttributes redirectAttributes, HttpServletResponse response) { try { assertUserIsFrontOfficeMember(settlementNote.getDebtAccount().getFinantialInstitution(), model); String output = ERPExporter.exportFinantialDocumentToXML( settlementNote.getDebtAccount().getFinantialInstitution(), settlementNote .findRelatedDocuments(new HashSet<FinantialDocument>(), settlementNote.getDebtAccount().getFinantialInstitution() .getErpIntegrationConfiguration().getExportAnnulledRelatedDocuments()) .stream().collect(Collectors.toList())); response.setContentType("text/xml"); response.setCharacterEncoding("Windows-1252"); String filename = URLEncoder.encode(StringNormalizer.normalizePreservingCapitalizedLetters( (settlementNote.getDebtAccount().getFinantialInstitution().getFiscalNumber() + "_" + settlementNote.getUiDocumentNumber() + ".xml").replaceAll("/", "_") .replaceAll("\\s", "_").replaceAll(" ", "_")), "Windows-1252"); response.setHeader("Content-disposition", "attachment; filename=" + filename); response.getOutputStream().write(output.getBytes("Windows-1252")); } catch (Exception ex) { addErrorMessage(ex.getLocalizedMessage(), model); try { response.sendRedirect( redirect(READ_URL + settlementNote.getExternalId(), model, redirectAttributes)); } catch (IOException e) { e.printStackTrace(); } } } @RequestMapping(value = "/read/{oid}/closesettlementnote", method = RequestMethod.POST) public String processReadToCloseDebitNote(@PathVariable("oid") SettlementNote settlementNote, Model model, RedirectAttributes redirectAttributes) { setSettlementNote(settlementNote, model); try { assertUserIsFrontOfficeMember(settlementNote.getDebtAccount().getFinantialInstitution(), model); settlementNote.changeState(FinantialDocumentStateType.CLOSED, ""); addInfoMessage(BundleUtil.getString(Constants.BUNDLE, "label.document.manageinvoice.Settlement.document.closed.sucess"), model); } catch (Exception ex) { addErrorMessage(ex.getLocalizedMessage(), model); } return redirect(SettlementNoteController.READ_URL + getSettlementNote(model).getExternalId(), model, redirectAttributes); } @RequestMapping(value = TRANSACTIONS_SUMMARY_URI, method = RequestMethod.GET) public String transactionsSummary(Model model) { model.addAttribute("finantial_institutions_options", FinantialInstitution.findAll().collect(Collectors.toList())); return "treasury/document/managepayments/settlementnote/transactionsSummary"; } @RequestMapping(value = TRANSACTIONS_SUMMARY_URI, method = RequestMethod.POST) public String transactionsSummary( @RequestParam(value = "finantialInstitution", required = true) FinantialInstitution finantialInstitution, @RequestParam(value = "documentdatefrom", required = true) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate documentDateFrom, @RequestParam(value = "documentdateto", required = true) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate documentDateTo, Model model) { if (Days.daysBetween(documentDateFrom, documentDateTo) .getDays() > SEARCH_SETTLEMENT_ENTRY_LIMIT_DAYS_PERIOD) { addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "error.SettlementNote.day.limit.exceeded", String.valueOf(SEARCH_SETTLEMENT_ENTRY_LIMIT_DAYS_PERIOD)), model); } else { List<SettlementNote> notes = filterSearchSettlementNote(finantialInstitution, documentDateFrom, documentDateTo); model.addAttribute("settlementEntriesDataSet", getSettlementEntriesDataSet(notes)); model.addAttribute("finantialInstitution", finantialInstitution); populateSummaryTransactions(model, notes); } model.addAttribute("finantial_institutions_options", FinantialInstitution.findAll().collect(Collectors.toList())); return "treasury/document/managepayments/settlementnote/transactionsSummary"; } private void populateSummaryTransactions(Model model, List<SettlementNote> notes) { Map<PaymentMethod, BigDecimal> payments = getPaymentEntriesDataSet(notes).stream() .collect(Collectors.groupingBy(PaymentEntry::getPaymentMethod, Collectors.reducing(BigDecimal.ZERO, PaymentEntry::getPayedAmount, BigDecimal::add))); Map<PaymentMethod, BigDecimal> reimbursements = getReimbursementEntriesDataSet(notes).stream() .collect(Collectors.groupingBy(ReimbursementEntry::getPaymentMethod, Collectors .reducing(BigDecimal.ZERO, ReimbursementEntry::getReimbursedAmount, BigDecimal::add))); PaymentMethod.findAll().forEach(pm -> { if (payments.get(pm) == null) { payments.put(pm, BigDecimal.ZERO); } if (reimbursements.get(pm) == null) { reimbursements.put(pm, BigDecimal.ZERO); } }); model.addAttribute("paymentsDataSet", payments); model.addAttribute("reimbursementsDataSet", reimbursements); } private List<SettlementNote> filterSearchSettlementNote(FinantialInstitution finantialInstitution, LocalDate documentDateFrom, LocalDate documentDateTo) { return SettlementNote.findAll().filter(note -> note.isClosed()) .filter(note -> note.getDebtAccount().getFinantialInstitution().equals(finantialInstitution)) .filter(note -> note.getDocumentDate().toLocalDate().isAfter(documentDateFrom) || note.getDocumentDate().toLocalDate().isEqual(documentDateFrom)) .filter(note -> note.getDocumentDate().toLocalDate().isBefore(documentDateTo) || note.getDocumentDate().toLocalDate().isEqual(documentDateTo)) .collect(Collectors.toList()); } private List<SettlementEntry> getSettlementEntriesDataSet(List<SettlementNote> notes) { return notes.stream().map(note -> note.getSettlemetEntries().collect(Collectors.toList())) .reduce(new ArrayList<SettlementEntry>(), (t, u) -> { t.addAll(u); return t; }); } private List<PaymentEntry> getPaymentEntriesDataSet(List<SettlementNote> notes) { return notes.stream().map(note -> note.getPaymentEntriesSet().stream().collect(Collectors.toList())) .reduce(new ArrayList<PaymentEntry>(), (t, u) -> { t.addAll(u); return t; }); } private List<ReimbursementEntry> getReimbursementEntriesDataSet(List<SettlementNote> notes) { return notes.stream().map(note -> note.getReimbursementEntriesSet().stream().collect(Collectors.toList())) .reduce(new ArrayList<ReimbursementEntry>(), (t, u) -> { t.addAll(u); return t; }); } @RequestMapping(value = "/read/{oid}/exportintegrationonline") public String processReadToExportIntegrationOnline(@PathVariable("oid") SettlementNote settlementNote, Model model, RedirectAttributes redirectAttributes) { try { assertUserIsFrontOfficeMember(settlementNote.getDebtAccount().getFinantialInstitution(), model); try { //Force a check status first of the document ERPExporter.checkIntegrationDocumentStatus(settlementNote); } catch (Exception ex) { } List<FinantialDocument> documentsToExport = Collections.singletonList(settlementNote); ERPExportOperation output = ERPExporter.exportFinantialDocumentToIntegration( settlementNote.getDebtAccount().getFinantialInstitution(), documentsToExport); addInfoMessage(BundleUtil.getString(Constants.BUNDLE, "label.integration.erp.exportoperation.success"), model); return redirect(ERPExportOperationController.READ_URL + output.getExternalId(), model, redirectAttributes); } catch (Exception ex) { addErrorMessage(BundleUtil.getString(Constants.BUNDLE, "label.integration.erp.exportoperation.error") + ex.getLocalizedMessage(), model); } return read(settlementNote, model); } }