/**
* 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.cfonb;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import com.axelor.apps.account.db.AccountConfig;
import com.axelor.apps.account.db.CfonbConfig;
import com.axelor.apps.account.db.DirectDebitManagement;
import com.axelor.apps.account.db.Invoice;
import com.axelor.apps.account.db.MoveLine;
import com.axelor.apps.account.db.PaymentSchedule;
import com.axelor.apps.account.db.PaymentScheduleLine;
import com.axelor.apps.account.db.Reimbursement;
import com.axelor.apps.account.db.repo.InvoiceRepository;
import com.axelor.apps.account.db.repo.PaymentScheduleLineRepository;
import com.axelor.apps.account.db.repo.ReimbursementRepository;
import com.axelor.apps.account.exception.IExceptionMessage;
import com.axelor.apps.account.service.config.CfonbConfigService;
import com.axelor.apps.base.db.BankDetails;
import com.axelor.apps.base.db.Company;
import com.axelor.apps.base.db.Partner;
import com.axelor.apps.base.service.PartnerService;
import com.axelor.apps.base.service.administration.GeneralServiceImpl;
import com.axelor.apps.tool.StringTool;
import com.axelor.apps.tool.file.FileTool;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.IException;
import com.axelor.i18n.I18n;
import com.google.inject.Inject;
public class CfonbExportService {
protected CfonbConfig cfonbConfig;
protected CfonbToolService cfonbToolService;
protected CfonbConfigService cfonbConfigService;
protected ReimbursementRepository reimbursementRepo;
protected PaymentScheduleLineRepository paymentScheduleLineRepo;
protected InvoiceRepository invoiceRepo;
protected PartnerService partnerService;
private boolean sepa;
@Inject
public CfonbExportService(CfonbToolService cfonbToolService, CfonbConfigService cfonbConfigService,
ReimbursementRepository reimbursementRepo, PaymentScheduleLineRepository paymentScheduleLineRepo, InvoiceRepository invoiceRepo,
PartnerService partnerService) {
this.cfonbToolService = cfonbToolService;
this.cfonbConfigService = cfonbConfigService;
this.reimbursementRepo = reimbursementRepo;
this.paymentScheduleLineRepo = paymentScheduleLineRepo;
this.invoiceRepo = invoiceRepo;
this.partnerService = partnerService;
}
private void init(CfonbConfig cfonbConfig) {
this.cfonbConfig = cfonbConfig;
}
public void setSepa(boolean sepa) {
this.sepa = sepa;
}
/**************************************** Export CFONB *****************************************************/
/**
* Méthode permettant d'exporter les remboursements au format CFONB
* @param reimbursementExport
* @param dateTime
* @param reimbursementList
* @throws AxelorException
*/
public void exportCFONB(Company company, DateTime dateTime, List<Reimbursement> reimbursementList, BankDetails bankDetails) throws AxelorException {
this.testCompanyExportCFONBField(company);
// paramètre obligatoire : au minimum
// un enregistrement emetteur par date de règlement (code 03)
// un enregistrement destinataire (code 06)
// un enregistrement total (code 08)
String senderCFONB = this.createSenderReimbursementCFONB(dateTime, bankDetails);
List<String> multiRecipientCFONB = new ArrayList<String>();
for(Reimbursement reimbursement : reimbursementList) {
reimbursement = reimbursementRepo.find(reimbursement.getId());
multiRecipientCFONB.add(this.createRecipientCFONB(reimbursement));
}
String totalCFONB = this.createReimbursementTotalCFONB(this.getTotalAmountReimbursementExport(reimbursementList));
cfonbToolService.testLength(senderCFONB, totalCFONB, multiRecipientCFONB, company);
List<String> cFONB = this.createCFONBExport(senderCFONB, multiRecipientCFONB, totalCFONB);
// Mise en majuscule des enregistrement
cFONB = this.toUpperCase(cFONB);
this.createCFONBFile(cFONB, dateTime, company.getAccountConfig().getReimbursementExportFolderPathCFONB(), "virement");
}
/**
* Méthode permettant d'exporter les prélèvements d'échéance de mensu au format CFONB
* @param paymentScheduleExport
* @param paymentScheduleLineList
* @param company
* @throws AxelorException
*/
public void exportPaymentScheduleCFONB(DateTime processingDateTime, LocalDate scheduleDate, List<PaymentScheduleLine> paymentScheduleLineList, Company company, BankDetails bankDetails) throws AxelorException {
if(paymentScheduleLineList == null || paymentScheduleLineList.isEmpty()) { return; }
this.testCompanyExportCFONBField(company);
// paramètre obligatoire : au minimum
// un enregistrement emetteur par date de règlement (code 03)
// un enregistrement destinataire (code 06)
// un enregistrement total (code 08)
String senderCFONB = this.createSenderMonthlyExportCFONB(scheduleDate, bankDetails);
List<String> multiRecipientCFONB = new ArrayList<String>();
List<DirectDebitManagement> directDebitManagementList = new ArrayList<DirectDebitManagement>();
for(PaymentScheduleLine paymentScheduleLine : paymentScheduleLineList) {
paymentScheduleLine = paymentScheduleLineRepo.find(paymentScheduleLine.getId());
if(paymentScheduleLine.getDirectDebitManagement() == null) {
multiRecipientCFONB.add(this.createRecipientCFONB(paymentScheduleLine, true));
}
else {
if(!directDebitManagementList.contains(paymentScheduleLine.getDirectDebitManagement())) {
directDebitManagementList.add(paymentScheduleLine.getDirectDebitManagement());
}
}
}
for(DirectDebitManagement directDebitManagement : directDebitManagementList) {
multiRecipientCFONB.add(this.createRecipientCFONB(directDebitManagement, false));
}
String totalCFONB = this.createPaymentScheduleTotalCFONB(company,this.getTotalAmountPaymentSchedule(paymentScheduleLineList));
cfonbToolService.testLength(senderCFONB, totalCFONB, multiRecipientCFONB, company);
List<String> cFONB = this.createCFONBExport(senderCFONB, multiRecipientCFONB, totalCFONB);
// Mise en majuscule des enregistrement
cFONB = this.toUpperCase(cFONB);
this.createCFONBFile(cFONB, processingDateTime, company.getAccountConfig().getPaymentScheduleExportFolderPathCFONB(), "prelevement");
}
/**
* Méthode permettant d'exporter les prélèvements de facture au format CFONB
* @param paymentScheduleExport
* @param paymentScheduleLineList
* @param invoiceList
* @param company
* @throws AxelorException
*/
public void exportInvoiceCFONB(DateTime processingDateTime, LocalDate scheduleDate, List<Invoice> invoiceList, Company company, BankDetails bankDetails) throws AxelorException {
if((invoiceList == null || invoiceList.isEmpty())) { return; }
this.testCompanyExportCFONBField(company);
// paramètre obligatoire : au minimum
// un enregistrement emetteur par date de règlement (code 03)
// un enregistrement destinataire (code 06)
// un enregistrement total (code 08)
String senderCFONB = this.createSenderMonthlyExportCFONB(scheduleDate, bankDetails);
List<String> multiRecipientCFONB = new ArrayList<String>();
List<DirectDebitManagement> directDebitManagementList = new ArrayList<DirectDebitManagement>();
for(Invoice invoice : invoiceList) {
invoice = invoiceRepo.find(invoice.getId());
if(invoice.getDirectDebitManagement() == null) {
multiRecipientCFONB.add(this.createRecipientCFONB(company, invoice));
}
else {
if(!directDebitManagementList.contains(invoice.getDirectDebitManagement())) {
directDebitManagementList.add(invoice.getDirectDebitManagement());
}
}
}
for(DirectDebitManagement directDebitManagement : directDebitManagementList) {
multiRecipientCFONB.add(this.createRecipientCFONB(directDebitManagement, true));
}
BigDecimal amount = this.getTotalAmountInvoice(invoiceList);
String totalCFONB = this.createPaymentScheduleTotalCFONB(company, amount);
cfonbToolService.testLength(senderCFONB, totalCFONB, multiRecipientCFONB, company);
List<String> cFONB = this.createCFONBExport(senderCFONB, multiRecipientCFONB, totalCFONB);
// Mise en majuscule des enregistrement
cFONB = this.toUpperCase(cFONB);
this.createCFONBFile(cFONB, processingDateTime, company.getAccountConfig().getPaymentScheduleExportFolderPathCFONB(), "prelevement");
}
/**
* Méthode permettant d'exporter les prélèvements de facture et d'échéance de paiement au format CFONB
* @param paymentScheduleExport
* @param paymentScheduleLineList
* @param invoiceList
* @param company
* @throws AxelorException
*/
public void exportCFONB(DateTime processingDateTime, LocalDate scheduleDate, List<PaymentScheduleLine> paymentScheduleLineList, List<Invoice> invoiceList, Company company, BankDetails bankDetails) throws AxelorException {
if((paymentScheduleLineList == null || paymentScheduleLineList.isEmpty())
&& (invoiceList == null || invoiceList.isEmpty())) { return; }
this.testCompanyExportCFONBField(company);
// paramètre obligatoire : au minimum
// un enregistrement emetteur par date de règlement (code 03)
// un enregistrement destinataire (code 06)
// un enregistrement total (code 08)
String senderCFONB = this.createSenderMonthlyExportCFONB(scheduleDate, bankDetails);
List<String> multiRecipientCFONB = new ArrayList<String>();
// Echéanciers
List<DirectDebitManagement> directDebitManagementList = new ArrayList<DirectDebitManagement>();
for(PaymentScheduleLine paymentScheduleLine : paymentScheduleLineList) {
paymentScheduleLine = paymentScheduleLineRepo.find(paymentScheduleLine.getId());
if(paymentScheduleLine.getDirectDebitManagement() == null) {
multiRecipientCFONB.add(this.createRecipientCFONB(paymentScheduleLine, false));
}
else {
if(!directDebitManagementList.contains(paymentScheduleLine.getDirectDebitManagement())) {
directDebitManagementList.add(paymentScheduleLine.getDirectDebitManagement());
}
}
}
for(DirectDebitManagement directDebitManagement : directDebitManagementList) {
multiRecipientCFONB.add(this.createRecipientCFONB(directDebitManagement, false));
}
// Factures
directDebitManagementList = new ArrayList<DirectDebitManagement>();
for(Invoice invoice : invoiceList) {
invoice = invoiceRepo.find(invoice.getId());
if(invoice.getDirectDebitManagement() == null) {
multiRecipientCFONB.add(this.createRecipientCFONB(company, invoice));
}
else {
if(!directDebitManagementList.contains(invoice.getDirectDebitManagement())) {
directDebitManagementList.add(invoice.getDirectDebitManagement());
}
}
}
for(DirectDebitManagement directDebitManagement : directDebitManagementList) {
multiRecipientCFONB.add(this.createRecipientCFONB(directDebitManagement, true));
}
BigDecimal amount = this.getTotalAmountPaymentSchedule(paymentScheduleLineList).add(this.getTotalAmountInvoice(invoiceList));
String totalCFONB = this.createPaymentScheduleTotalCFONB(company,amount);
cfonbToolService.testLength(senderCFONB, totalCFONB, multiRecipientCFONB, company);
List<String> cFONB = this.createCFONBExport(senderCFONB, multiRecipientCFONB, totalCFONB);
// Mise en majuscule des enregistrement
cFONB = this.toUpperCase(cFONB);
this.createCFONBFile(cFONB, processingDateTime, company.getAccountConfig().getPaymentScheduleExportFolderPathCFONB(), "prelevement");
}
/**
* Méthode permettant de mettre en majuscule et sans accent un CFONB
* @param cFONB
* @return
* Le CFONB nettoyé
*/
private List<String> toUpperCase(List<String> cFONB) {
List<String> upperCase = new ArrayList<String>();
for(String s : cFONB) {
upperCase.add(StringTool.deleteAccent(s.toUpperCase()));
}
return upperCase;
}
/**
* Méthode permettant de récupérer la facture depuis une ligne d'écriture de facture ou une ligne d'écriture de rejet de facture
* @param moveLine
* Une ligne d'écriture de facture ou une ligne d'écriture de rejet de facture
* @return
* La facture trouvée
*/
public Invoice getInvoice(MoveLine moveLine) {
Invoice invoice = null;
if(moveLine.getMove().getRejectOk()) {
invoice = moveLine.getInvoiceReject();
}
else {
invoice = moveLine.getMove().getInvoice();
}
return invoice;
}
/**
* Fonction permettant de créer un enregistrement 'émetteur' pour un virement des remboursements
* @param company
* Une société
* @param dateTime
* Une heure
* @return
* Un enregistrement 'emetteur'
* @throws AxelorException
*/
private String createSenderReimbursementCFONB(DateTime dateTime, BankDetails bankDetails) throws AxelorException {
DateFormat ddmmFormat = new SimpleDateFormat("ddMM");
String date = ddmmFormat.format(dateTime.toDate());
date += String.format("%s", StringTool.truncLeft(String.format("%s",dateTime.getYear()), 1));
// Récupération des valeurs
String a = this.cfonbConfig.getSenderRecordCodeExportCFONB(); // Code enregistrement
String b1 = this.cfonbConfig.getTransferOperationCodeExportCFONB(); // Code opération
String b2 = ""; // Zone réservée
String b3 = this.cfonbConfig.getSenderNumExportCFONB(); // Numéro d'émetteur
String c1One = ""; // Code CCD
String c1Two = ""; // Zone réservée
String c1Three = date; // Date d'échéance
String c2 = this.cfonbConfig.getSenderNameCodeExportCFONB(); // Nom/Raison sociale du donneur d'ordre
String d1One = ""; // Référence de la remise
String d1Two = ""; // Zone réservée
String d2One = ""; // Zone réservée
String d2Two = "E"; // Code monnaie
String d2Three = ""; // Zone réservée
String d3 = bankDetails.getSortCode(); // Code guichet de la banque du donneur d'ordre
String d4 = bankDetails.getAccountNbr(); // Numéro de compte du donneur d’ordre
String e = ""; // Identifiant du donneur d'ordre
String f = ""; // Zone réservée
String g1 = bankDetails.getBankCode(); // Code établissement de la banque du donneur d'ordre
String g2 = ""; // Zone réservée
// Tronquage / remplissage à droite (chaine de caractère)
b2 = StringTool.fillStringRight(b2, ' ', 8);
b3 = StringTool.fillStringRight(b3, ' ', 6);
c1One = StringTool.fillStringRight(c1One, ' ', 1);
c1Two = StringTool.fillStringRight(c1Two, ' ', 6);
c2 = StringTool.fillStringRight(c2, ' ', 24);
d1One = StringTool.fillStringRight(d1One, ' ', 7);
d1Two = StringTool.fillStringRight(d1Two, ' ', 17);
d2One = StringTool.fillStringRight(d2One, ' ', 2);
d2Three = StringTool.fillStringRight(d2Three, ' ', 5);
d4 = StringTool.fillStringRight(d4, ' ', 11);
e = StringTool.fillStringRight(e, ' ', 16);
f = StringTool.fillStringRight(f, ' ', 31);
g2 = StringTool.fillStringRight(g2, ' ', 6);
// Tronquage / remplissage à gauche (nombre)
a = StringTool.fillStringLeft(a, '0', 2);
b1 = StringTool.fillStringLeft(b1, '0', 2);
c1Three = StringTool.fillStringLeft(c1Three,'0', 5);
d3 = StringTool.fillStringLeft(d3, '0', 5);
g1 = StringTool.fillStringLeft(g1, '0', 5);
// Vérification AN / N / A
cfonbToolService.testDigital(a, 0);
cfonbToolService.testDigital(b1, 0);
cfonbToolService.testDigital(d3, 0);
cfonbToolService.testDigital(g1, 0);
// création de l'enregistrement
return a+b1+b2+b3+c1One+c1Two+c1Three+c2+d1One+d1Two+d2One+d2Two+d2Three+d3+d4+e+f+g1+g2;
}
/**
* Fonction permettant de créer un enregistrement 'émetteur' pour un export de prélèvement de mensu
* @param company
* Une société
* @param localDate
* Une date
* @return
* Un enregistrement 'emetteur'
* @throws AxelorException
*/
private String createSenderMonthlyExportCFONB(LocalDate localDate, BankDetails bankDetails) throws AxelorException {
DateFormat ddmmFormat = new SimpleDateFormat("ddMM");
String date = ddmmFormat.format(localDate.toDateTimeAtCurrentTime().toDate());
date += String.format("%s", StringTool.truncLeft(String.format("%s",localDate.getYear()), 1));
// Récupération des valeurs
String a = this.cfonbConfig.getSenderRecordCodeExportCFONB(); // Code enregistrement
String b1 = this.cfonbConfig.getDirectDebitOperationCodeExportCFONB(); // Code opération
String b2 = ""; // Zone réservée
String b3 = this.cfonbConfig.getSenderNumExportCFONB(); // Numéro d'émetteur
String c1One = ""; // Zone réservée
String c1Two = date; // Date d'échéance
String c2 = this.cfonbConfig.getSenderNameCodeExportCFONB(); // Nom/Raison sociale du donneur d'ordre
String d1One = ""; // Référence de la remise
String d1Two = ""; // Zone réservée
String d2 = ""; // Zone réservée
String d3 = bankDetails.getSortCode(); // Code guichet de la banque du donneur d'ordre
String d4 = bankDetails.getAccountNbr(); // Numéro de compte du donneur d’ordre
String e = ""; // Zone réservée
String f = ""; // Zone réservée
String g1 = bankDetails.getBankCode(); // Code établissement de la banque du donneur d'ordre
String g2 = ""; // Zone réservée
// Tronquage / remplissage à droite (chaine de caractère)
b2 = StringTool.fillStringRight(b2, ' ', 8);
b3 = StringTool.fillStringRight(b3, ' ', 6);
c1One = StringTool.fillStringRight(c1One, ' ', 7);
c2 = StringTool.fillStringRight(c2, ' ', 24);
d1One = StringTool.fillStringRight(d1One, ' ', 7);
d1Two = StringTool.fillStringRight(d1Two, ' ', 17);
d2 = StringTool.fillStringRight(d2, ' ', 8);
d4 = StringTool.fillStringRight(d4, ' ', 11);
e = StringTool.fillStringRight(e, ' ', 16);
f = StringTool.fillStringRight(f, ' ', 31);
g2 = StringTool.fillStringRight(g2, ' ', 6);
// Tronquage / remplissage à gauche (nombre)
a = StringTool.fillStringLeft(a, '0', 2);
b1 = StringTool.fillStringLeft(b1, '0', 2);
c1Two = StringTool.fillStringLeft(c1Two, '0', 5);
d3 = StringTool.fillStringLeft(d3, '0', 5);
g1 = StringTool.fillStringLeft(g1, '0', 5);
// Vérification AN / N / A
cfonbToolService.testDigital(a, 0);
cfonbToolService.testDigital(b1, 0);
cfonbToolService.testDigital(d3, 0);
cfonbToolService.testDigital(g1, 0);
// création de l'enregistrement
return a+b1+b2+b3+c1One+c1Two+c2+d1One+d1Two+d2+d3+d4+e+f+g1+g2;
}
/**
* Fonction permettant de créer un enregistrement 'destinataire' pour un virement de remboursement
* @param company
* Une société
* @param reimbursement
* Un remboursement
* @return
* Un enregistrement 'destinataire'
* @throws AxelorException
*/
private String createRecipientCFONB(Reimbursement reimbursement) throws AxelorException {
BankDetails bankDetails = reimbursement.getBankDetails();
if(bankDetails == null) {
throw new AxelorException(String.format("%s :\n "+I18n.get(IExceptionMessage.CFONB_EXPORT_1)+" %s",
GeneralServiceImpl.EXCEPTION,reimbursement.getRef()), IException.CONFIGURATION_ERROR);
}
BigDecimal amount = reimbursement.getAmountReimbursed();
String ref = reimbursement.getRef(); // Référence
String partner = this.getPayeurPartnerName(reimbursement.getPartner()); // Nom/Raison sociale du bénéficiaire
String operationCode = this.cfonbConfig.getTransferOperationCodeExportCFONB(); // Code opération
return this.createRecipientCFONB(amount, ref, partner, bankDetails, operationCode);
}
/**
* Fonction permettant de créer un enregistrement 'destinataire' pour un export de prélèvement d'une échéance
* @param company
* Une société
* @param paymentScheduleLine
* Une échéance
* @return
* Un enregistrement 'destinataire'
* @throws AxelorException
*/
private String createRecipientCFONB(PaymentScheduleLine paymentScheduleLine, boolean mensu) throws AxelorException {
Partner partner = paymentScheduleLine.getPaymentSchedule().getPartner();
BankDetails bankDetails = paymentScheduleLine.getPaymentSchedule().getBankDetails();
if(bankDetails == null) {
bankDetails = partnerService.getDefaultBankDetails(partner);
}
if(bankDetails == null) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.PAYMENT_SCHEDULE_2),
GeneralServiceImpl.EXCEPTION,partner.getName()), IException.CONFIGURATION_ERROR);
}
BigDecimal amount = paymentScheduleLine.getDirectDebitAmount();
String ref = paymentScheduleLine.getDebitNumber(); // Référence
String partnerName = this.getPayeurPartnerName(partner); // Nom/Raison sociale du débiteur
String operationCode = this.cfonbConfig.getDirectDebitOperationCodeExportCFONB(); // Code opération
return this.createRecipientCFONB(amount, ref, partnerName, bankDetails, operationCode);
}
/**
* Fonction permettant de créer un enregistrement 'destinataire' pour un export de prélèvement de plusieurs échéances par le biais d'un objet de gestion de prélèvement
* @param company
* Une société
* @param paymentScheduleLine
* Une échéance
* @return
* Un enregistrement 'destinataire'
* @throws AxelorException
*/
private String createRecipientCFONB(DirectDebitManagement directDebitManagement, boolean isForInvoice) throws AxelorException {
BankDetails bankDetails = null;
String partnerName = "";
if(isForInvoice) {
Invoice invoice = (Invoice) directDebitManagement.getInvoiceSet().toArray()[0];
Partner partner = invoice.getPartner();
bankDetails = partnerService.getDefaultBankDetails(partner);
partnerName = this.getPayeurPartnerName(invoice.getPartner()); // Nom/Raison sociale du débiteur
if(bankDetails == null) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.PAYMENT_SCHEDULE_2),
GeneralServiceImpl.EXCEPTION, partner.getName()), IException.CONFIGURATION_ERROR);
}
}
else {
PaymentSchedule paymentSchedule = directDebitManagement.getPaymentScheduleLineList().get(0).getPaymentSchedule();
Partner partner = paymentSchedule.getPartner();
partnerName = this.getPayeurPartnerName(partner); // Nom/Raison sociale du débiteur
bankDetails = paymentSchedule.getBankDetails();
if(bankDetails == null) {
bankDetails = partnerService.getDefaultBankDetails(partner);
}
if(bankDetails == null) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.PAYMENT_SCHEDULE_2),
GeneralServiceImpl.EXCEPTION, partner.getName()), IException.CONFIGURATION_ERROR);
}
}
BigDecimal amount = this.getAmount(directDebitManagement, isForInvoice);
String ref = directDebitManagement.getDebitNumber(); // Référence
String operationCode = this.cfonbConfig.getDirectDebitOperationCodeExportCFONB(); // Code opération
return this.createRecipientCFONB(amount, ref, partnerName, bankDetails, operationCode);
}
private BigDecimal getAmount(DirectDebitManagement directDebitManagement, boolean isForInvoice) {
BigDecimal amount = BigDecimal.ZERO;
if(isForInvoice) {
for(Invoice invoice : directDebitManagement.getInvoiceSet()) {
amount = amount.add(invoice.getDirectDebitAmount());
}
}
else {
for(PaymentScheduleLine paymentScheduleLine : directDebitManagement.getPaymentScheduleLineList()) {
amount = amount.add(paymentScheduleLine.getDirectDebitAmount());
}
}
return amount;
}
/**
* Fonction permettant de créer un enregistrement 'destinataire' pour un export de prélèvement d'une facture
* @param company
* Une société
* @param moveLine
* L' écriture d'export des prélèvement d'une facture
* @return
* Un enregistrement 'destinataire'
* @throws AxelorException
*/
private String createRecipientCFONB(Company company, Invoice invoice) throws AxelorException {
Partner partner = invoice.getPartner();
BankDetails bankDetails = partnerService.getDefaultBankDetails(partner);
if(bankDetails == null) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.PAYMENT_SCHEDULE_2),
GeneralServiceImpl.EXCEPTION,partner.getName()), IException.CONFIGURATION_ERROR);
}
BigDecimal amount = invoice.getDirectDebitAmount();
String ref = invoice.getDebitNumber(); // Référence
String partnerName = this.getPayeurPartnerName(partner); // Nom/Raison sociale du débiteur
String operationCode = this.cfonbConfig.getDirectDebitOperationCodeExportCFONB(); // Code opération
return this.createRecipientCFONB(amount, ref, partnerName, bankDetails, operationCode);
}
/**
* Fonction permettant de créer un enregistrement 'destinataire'
* @param company
* Une société
* @param amount
* Le montant de l'enregistrement
* @param ref
* Une référence de prélèvement
* @param label
* Un libellé
* @param partner
* Un tiers payeur
* @param bankDetails
* Un RIB
* @param operationCode
* Le code d'opération défini par société
* @return
* L'enregistrement 'destinataire'
* @throws AxelorException
*/
private String createRecipientCFONB(BigDecimal amount, String ref, String partner, BankDetails bankDetails, String operationCode) throws AxelorException {
this.testBankDetailsField(bankDetails);
String amountFixed = amount.setScale(2).toString().replace(".","");
// Récupération des valeurs
String a = this.cfonbConfig.getRecipientRecordCodeExportCFONB(); // Code enregistrement
String b1 = operationCode; // Code opération
String b2 = ""; // Zone réservée
String b3 = this.cfonbConfig.getSenderNumExportCFONB(); // Numéro d'émetteur
String c1 = ref; // Référence
String c2 = partner; // Nom/Raison sociale du bénéficiaire
String d1 = bankDetails.getBankAddress(); // Domiciliation
String d2 = ""; // Déclaration de la balance des paiement
String d3 = bankDetails.getSortCode(); // Code guichet de la banque du donneur d'ordre / du débiteur
String d4 = bankDetails.getAccountNbr(); // Numéro de compte du bénéficiaire / du débiteur
String e = amountFixed; // Montant du virement
String f = ref; // Libellé
String g1 = bankDetails.getBankCode(); // Code établissement de la banque du donneur d'ordre / du débiteur
String g2 = ""; // Zone réservée
// Tronquage / remplissage à droite (chaine de caractère)
b2 = StringTool.fillStringRight(b2, ' ', 8);
b3 = StringTool.fillStringRight(b3, ' ', 6);
c1 = StringTool.fillStringRight(c1, ' ', 12);
c2 = StringTool.fillStringRight(c2, ' ', 24);
d1 = StringTool.fillStringRight(d1, ' ', 24);
d2 = StringTool.fillStringRight(d2, ' ', 8);
d4 = StringTool.fillStringRight(d4, ' ', 11);
f = StringTool.fillStringRight(f, ' ', 31);
g2 = StringTool.fillStringRight(g2, ' ', 6);
// Tronquage / remplissage à gauche (nombre)
a = StringTool.fillStringLeft(a, '0', 2);
b1 = StringTool.fillStringLeft(b1, '0', 2);
d3 = StringTool.fillStringLeft(d3, '0', 5);
e = StringTool.fillStringLeft(e, '0', 16);
g1 = StringTool.fillStringLeft(g1, '0', 5);
return a+b1+b2+b3+c1+c2+d1+d2+d3+d4+e+f+g1+g2;
}
/**
* Fonction permettant de créer un enregistrement 'total' au format CFONB pour un remboursement
* @param company
* Une société
* @param amount
* Le montant total des enregistrements 'destinataire'
* @return
*/
private String createReimbursementTotalCFONB(BigDecimal amount) {
// Code opération
String operationCode = this.cfonbConfig.getTransferOperationCodeExportCFONB();
return this.createTotalCFONB(amount, operationCode);
}
/**
* Fonction permettant de créer un enregistrement 'total' au format CFONB pour un échéancier
* @param company
* Une société
* @param amount
* Le montant total des enregistrements 'destinataire'
* @return
* L'enregistrement 'total'
*/
private String createPaymentScheduleTotalCFONB(Company company, BigDecimal amount) {
// Code opération
String operationCode = this.cfonbConfig.getDirectDebitOperationCodeExportCFONB();
return this.createTotalCFONB(amount, operationCode);
}
/**
* Fonction permettant de créer un enregistrement 'total' au format CFONB
* @param company
* Une société
* @param amount
* Le montant total des enregistrements 'destinataire'
* @param operationCode
* Le type d'opération :
* <ul>
* <li>0 = Virement</li>
* <li>1 = Prélèvement</li>
* <li>2 = TIP</li>
* </ul>
* @return
* L'enregistrement 'total'
*/
private String createTotalCFONB(BigDecimal amount, String operationCode) {
String totalAmount = amount.setScale(2).toString().replace(".","");
// Récupération des valeurs
String a = this.cfonbConfig.getTotalRecordCodeExportCFONB(); // Code enregistrement
String b1 = operationCode; // Code opération
String b2 = ""; // Zone réservée
String b3 = this.cfonbConfig.getSenderNumExportCFONB(); // Numéro d'émetteur
String c1 = ""; // Zone réservée
String c2 = ""; // Zone réservée
String d1 = ""; // Zone réservée
String d2 = ""; // Zone réservée
String d3 = ""; // Zone réservée
String d4 = ""; // Zone réservée
String e = totalAmount; // Montant de la remise
String f = ""; // Zone réservée
String g1 = ""; // Zone réservée
String g2 = ""; // Zone réservée
// Tronquage / remplissage à droite (chaine de caractère)
b2 = StringTool.fillStringRight(b2, ' ', 8);
b3 = StringTool.fillStringRight(b3, ' ', 6);
c1 = StringTool.fillStringRight(c1, ' ', 12);
c2 = StringTool.fillStringRight(c2, ' ', 24);
d1 = StringTool.fillStringRight(d1, ' ', 24);
d2 = StringTool.fillStringRight(d2, ' ', 8);
d3 = StringTool.fillStringRight(d3, ' ', 5);
d4 = StringTool.fillStringRight(d4, ' ', 11);
f = StringTool.fillStringRight(f, ' ', 31);
g1 = StringTool.fillStringRight(g1, ' ', 5);
g2 = StringTool.fillStringRight(g2, ' ', 6);
// Tronquage / remplissage à gauche (nombre)
a = StringTool.fillStringLeft(a, '0', 2);
b1 = StringTool.fillStringLeft(b1, '0', 2);
e = StringTool.fillStringLeft(e, '0', 16);
return a+b1+b2+b3+c1+c2+d1+d2+d3+d4+e+f+g1+g2;
}
/**
* Fonction permettant de créer le CFONB
* @param senderCFONB
* Un enregistrement 'émetteur'
* @param recipientCFONB
* Un liste d'enregistrement 'destinataire'
* @param totalCFONB
* Un enregistrement 'total'
* @return
* Le CFONB
*/
private List<String> createCFONBExport(String senderCFONB, List<String> recipientCFONB, String totalCFONB) {
// checker meme compte emetteur
// checker meme type de virement
// checker meme date de règlement
List<String> cFONB = new ArrayList<String>();
cFONB.add(senderCFONB);
cFONB.addAll(recipientCFONB);
cFONB.add(totalCFONB);
return cFONB;
}
/**
* Procédure permettant de créer un fichier CFONB au format .dat
* @param cFONB
* Le contenu du fichier, des enregistrements CFONB
* @param dateTime
* La date permettant de déterminer le nom du fichier créé
* @param destinationFolder
* Le répertoire de destination
* @param prefix
* Le préfix utilisé
* @throws AxelorException
*/
private void createCFONBFile(List<String> cFONB, DateTime dateTime, String destinationFolder, String prefix) throws AxelorException {
DateFormat yyyyMMddHHmmssFormat = new SimpleDateFormat("yyyyMMddHHmmss");
String dateFileName = yyyyMMddHHmmssFormat.format(dateTime.toDate());
String fileName = String.format("%s%s.dat", prefix, dateFileName);
try {
FileTool.writer(destinationFolder, fileName, cFONB);
} catch (IOException e) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.CFONB_EXPORT_2),
GeneralServiceImpl.EXCEPTION,e), IException.CONFIGURATION_ERROR);
}
}
/**
* Méthode permettant de construire le Nom/Raison sociale du tiers payeur d'un mémoire
* @param memory
* Un mémoire
* @return
* Civilité + Nom + Prénom si c'est une personne physique
* Civilité + Nom sinon
*/
private String getPayeurPartnerName(Partner partner) {
if(partner.getTitleSelect() != null ) {
return String.format("%s %s", partner.getTitleSelect(), partner.getName());
}
else {
return String.format("%s", partner.getName());
}
}
/**
* Méthode permettant de calculer le montant total des remboursements
* @param reimbursementList
* Une liste de remboursement
* @return
* Le montant total
*/
private BigDecimal getTotalAmountReimbursementExport(List<Reimbursement> reimbursementList) {
BigDecimal totalAmount = BigDecimal.ZERO;
for(Reimbursement reimbursement : reimbursementList) {
reimbursement = reimbursementRepo.find(reimbursement.getId());
totalAmount = totalAmount.add(reimbursement.getAmountReimbursed());
}
return totalAmount;
}
/**
* Fonction permettant de récupérer le montant total à prélever d'une liste d'échéance de mensu
* @param paymentScheduleLineList
* Une liste d'échéance de mensu
* @return
* Le montant total à prélever
*/
private BigDecimal getTotalAmountPaymentSchedule(List<PaymentScheduleLine> paymentScheduleLineList) {
BigDecimal totalAmount = BigDecimal.ZERO;
for(PaymentScheduleLine paymentScheduleLine : paymentScheduleLineList) {
totalAmount = totalAmount.add(paymentScheduleLineRepo.find(paymentScheduleLine.getId()).getDirectDebitAmount());
}
return totalAmount;
}
/**
* Fonction permettant de récupérer le montant total à prélever d'une liste d'échéance de mensu
* @param paymentScheduleLineList
* Une liste d'échéance de mensu
* @return
* Le montant total à prélever
*/
private BigDecimal getTotalAmountInvoice(List<Invoice> invoiceList) {
BigDecimal totalAmount = BigDecimal.ZERO;
for(Invoice invoice : invoiceList) {
totalAmount = totalAmount.add(invoiceRepo.find(invoice.getId()).getDirectDebitAmount());
}
return totalAmount;
}
/**
* Procédure permettant de vérifier la conformité des champs en rapport avec les exports CFONB d'une société
* @param company
* La société
* @throws AxelorException
*/
public void testCompanyExportCFONBField(Company company) throws AxelorException {
AccountConfig accountConfig = cfonbConfigService.getAccountConfig(company);
cfonbConfigService.getReimbursementExportFolderPathCFONB(accountConfig);
cfonbConfigService.getPaymentScheduleExportFolderPathCFONB(accountConfig);
this.init(cfonbConfigService.getCfonbConfig(company));
cfonbConfigService.getSenderRecordCodeExportCFONB(this.cfonbConfig);
cfonbConfigService.getSenderNumExportCFONB(this.cfonbConfig);
cfonbConfigService.getSenderNameCodeExportCFONB(this.cfonbConfig);
cfonbConfigService.getRecipientRecordCodeExportCFONB(this.cfonbConfig);
cfonbConfigService.getTotalRecordCodeExportCFONB(this.cfonbConfig);
cfonbConfigService.getTransferOperationCodeExportCFONB(this.cfonbConfig);
cfonbConfigService.getDirectDebitOperationCodeExportCFONB(this.cfonbConfig);
}
/**
* Procédure permettant de vérifier la conformité des champs d'un RIB
* @param bankDetails
* Le RIB
* @throws AxelorException
*/
public void testBankDetailsField(BankDetails bankDetails) throws AxelorException {
if(bankDetails.getSortCode() == null || bankDetails.getSortCode().isEmpty()) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.CFONB_EXPORT_3),
GeneralServiceImpl.EXCEPTION,bankDetails.getIban(), bankDetails.getPartner().getName()), IException.CONFIGURATION_ERROR);
}
if(bankDetails.getAccountNbr() == null || bankDetails.getAccountNbr().isEmpty()) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.CFONB_EXPORT_4),
GeneralServiceImpl.EXCEPTION,bankDetails.getIban(), bankDetails.getPartner().getName()), IException.CONFIGURATION_ERROR);
}
if(bankDetails.getBankCode() == null || bankDetails.getBankCode().isEmpty()) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.CFONB_EXPORT_5),
GeneralServiceImpl.EXCEPTION,bankDetails.getIban(), bankDetails.getPartner().getName()), IException.CONFIGURATION_ERROR);
}
if(bankDetails.getBankAddress() == null || bankDetails.getBankAddress().isEmpty()) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.CFONB_EXPORT_6),
GeneralServiceImpl.EXCEPTION,bankDetails.getIban(), bankDetails.getPartner().getName()), IException.CONFIGURATION_ERROR);
}
}
}