/** * Axelor Business Solutions * * Copyright (C) 2016 Axelor (<http://axelor.com>). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.axelor.apps.account.service; import java.math.BigDecimal; import org.joda.time.LocalDate; import com.axelor.apps.account.db.Invoice; import com.axelor.apps.account.db.InvoicePayment; import com.axelor.apps.account.db.Journal; import com.axelor.apps.account.db.Move; import com.axelor.apps.account.db.MoveLine; import com.axelor.apps.account.db.PaymentMode; import com.axelor.apps.account.db.Reconcile; import com.axelor.apps.account.db.repo.InvoicePaymentRepository; import com.axelor.apps.account.db.repo.ReconcileRepository; import com.axelor.apps.account.service.config.AccountConfigService; import com.axelor.apps.account.service.invoice.InvoiceService; import com.axelor.apps.account.service.move.MoveCancelService; import com.axelor.apps.account.service.move.MoveLineService; import com.axelor.apps.account.service.move.MoveService; import com.axelor.apps.account.service.payment.PaymentModeService; import com.axelor.apps.base.db.Company; import com.axelor.apps.base.db.Partner; import com.axelor.apps.base.service.CurrencyService; import com.axelor.exception.AxelorException; import com.axelor.inject.Beans; import com.google.inject.Inject; import com.google.inject.persist.Transactional; public class InvoicePaymentServiceImpl implements InvoicePaymentService { protected PaymentModeService paymentModeService; protected MoveService moveService; protected MoveLineService moveLineService; protected CurrencyService currencyService; protected AccountConfigService accountConfigService; protected InvoicePaymentRepository invoicePaymentRepository; protected MoveCancelService moveCancelService; protected InvoiceService invoiceService; protected ReconcileService reconcileService; @Inject public InvoicePaymentServiceImpl(PaymentModeService paymentModeService, MoveService moveService, MoveLineService moveLineService, CurrencyService currencyService, AccountConfigService accountConfigService, InvoicePaymentRepository invoicePaymentRepository, MoveCancelService moveCancelService, InvoiceService invoiceService, ReconcileService reconcileService) { this.paymentModeService = paymentModeService; this.moveService = moveService; this.moveLineService = moveLineService; this.currencyService = currencyService; this.accountConfigService = accountConfigService; this.invoicePaymentRepository = invoicePaymentRepository; this.moveCancelService = moveCancelService; this.invoiceService = invoiceService; this.reconcileService = reconcileService; } /** * Method to validate an invoice Payment * * Create the eventual move (depending general configuration) and reconcile it with the invoice move * Compute the amount paid on invoice * Change the status to validated * * @param invoicePayment * An invoice payment * * @throws AxelorException * */ @Transactional(rollbackOn = {AxelorException.class, Exception.class}) public void validate(InvoicePayment invoicePayment) throws AxelorException { if(invoicePayment.getStatusSelect() != InvoicePaymentRepository.STATUS_DRAFT) { return; } invoicePayment.setStatusSelect(InvoicePaymentRepository.STATUS_VALIDATED); Company company = invoicePayment.getInvoice().getCompany(); if(accountConfigService.getAccountConfig(company).getGenerateMoveForInvoicePayment()) { this.createMoveForInvoicePayment(invoicePayment); } invoiceService.updateAmountPaid(invoicePayment.getInvoice()); invoicePaymentRepository.save(invoicePayment); } /** * Method to create a payment move for an invoice Payment * * Create a move and reconcile it with the invoice move * * @param invoicePayment * An invoice payment * * @throws AxelorException * */ @Transactional(rollbackOn = {AxelorException.class, Exception.class}) public Move createMoveForInvoicePayment(InvoicePayment invoicePayment) throws AxelorException { Invoice invoice = invoicePayment.getInvoice(); Company company = invoice.getCompany(); PaymentMode paymentMode = invoicePayment.getPaymentMode(); Partner partner = invoice.getPartner(); LocalDate paymentDate = invoicePayment.getPaymentDate(); Journal journal = paymentModeService.getPaymentModeJournal(paymentMode, company); boolean isDebitInvoice = moveService.getMoveToolService().isDebitCustomer(invoice, true); MoveLine invoiceMoveLine = moveService.getMoveToolService().getInvoiceCustomerMoveLineByLoop(invoice); Move move = moveService.getMoveCreateService().createMove(journal, company, null, partner, paymentDate, paymentMode); BigDecimal amountConverted = currencyService.getAmountCurrencyConverted(invoicePayment.getCurrency(), invoice.getCurrency(), invoicePayment.getAmount(), paymentDate); move.addMoveLineListItem(moveLineService.createMoveLine(move, partner, paymentModeService.getPaymentModeAccount(paymentMode, company), amountConverted, isDebitInvoice, paymentDate, null, 1, "")); MoveLine customerMoveLine = moveLineService.createMoveLine(move, partner, invoiceMoveLine.getAccount(), amountConverted, !isDebitInvoice, paymentDate, null, 2, ""); move.addMoveLineListItem(customerMoveLine); moveService.getMoveValidateService().validate(move); Reconcile reconcile = reconcileService.reconcile(invoiceMoveLine, customerMoveLine, true); invoicePayment.setReconcile(reconcile); invoicePayment.setMove(move); invoicePaymentRepository.save(invoicePayment); return move; } /** * Method to cancel an invoice Payment * * Cancel the eventual Move and Reconcile * Compute the total amount paid on the linked invoice * Change the status to cancel * * @param invoicePayment * An invoice payment * * @throws AxelorException * */ @Transactional(rollbackOn = {AxelorException.class, Exception.class}) public void cancel(InvoicePayment invoicePayment) throws AxelorException { Move paymentMove = invoicePayment.getMove(); Reconcile reconcile = invoicePayment.getReconcile(); if(reconcile != null && reconcile.getStatusSelect() == ReconcileRepository.STATUS_CONFIRMED) { reconcileService.unreconcile(reconcile); if(accountConfigService.getAccountConfig(invoicePayment.getInvoice().getCompany()).getAllowRemovalValidatedMove()) { invoicePayment.setReconcile(null); Beans.get(ReconcileRepository.class).remove(reconcile); } } if(paymentMove != null) { invoicePayment.setMove(null); moveCancelService.cancel(paymentMove); } invoicePayment.setStatusSelect(InvoicePaymentRepository.STATUS_CANCELED); invoicePaymentRepository.save(invoicePayment); invoiceService.updateAmountPaid(invoicePayment.getInvoice()); } }