/**
* 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.batch;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.axelor.apps.account.db.Account;
import com.axelor.apps.account.db.AccountConfig;
import com.axelor.apps.account.db.InterbankCodeLine;
import com.axelor.apps.account.db.Invoice;
import com.axelor.apps.account.db.Move;
import com.axelor.apps.account.db.MoveLine;
import com.axelor.apps.account.db.PaymentScheduleLine;
import com.axelor.apps.account.db.repo.AccountRepository;
import com.axelor.apps.account.db.repo.InterbankCodeLineRepository;
import com.axelor.apps.account.db.repo.InvoiceRepository;
import com.axelor.apps.account.db.repo.PaymentScheduleLineRepository;
import com.axelor.apps.account.exception.IExceptionMessage;
import com.axelor.apps.account.service.AccountingService;
import com.axelor.apps.account.service.PaymentScheduleImportService;
import com.axelor.apps.account.service.RejectImportService;
import com.axelor.apps.base.db.Company;
import com.axelor.apps.base.service.administration.GeneralServiceImpl;
import com.axelor.db.JPA;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.IException;
import com.axelor.exception.service.TraceBackService;
import com.axelor.i18n.I18n;
import com.google.inject.persist.Transactional;
public class BatchPaymentScheduleImport extends BatchStrategy {
private final Logger log = LoggerFactory.getLogger( getClass() );
protected boolean stop = false;
protected BigDecimal totalAmount = BigDecimal.ZERO;
protected String updateCustomerAccountLog = "";
protected InterbankCodeLineRepository interbankCodeLineRepo;
protected AccountRepository accountRepo;
protected InvoiceRepository invoiceRepo;
protected PaymentScheduleLineRepository paymentScheduleLineRepo;
@Inject
public BatchPaymentScheduleImport(PaymentScheduleImportService paymentScheduleImportService, RejectImportService rejectImportService, BatchAccountCustomer batchAccountCustomer,
InterbankCodeLineRepository interbankCodeLineRepo, AccountRepository accountRepo, InvoiceRepository invoiceRepo, PaymentScheduleLineRepository paymentScheduleLineRepo) {
super(paymentScheduleImportService, rejectImportService, batchAccountCustomer);
this.interbankCodeLineRepo = interbankCodeLineRepo;
this.accountRepo = accountRepo;
this.invoiceRepo = invoiceRepo;
this.paymentScheduleLineRepo = paymentScheduleLineRepo;
AccountingService.setUpdateCustomerAccount(false);
}
@Override
protected void start() throws IllegalArgumentException, IllegalAccessException, AxelorException {
super.start();
Company company = batch.getAccountingBatch().getCompany();
try{
paymentScheduleImportService.checkCompanyFields(company);
} catch (AxelorException e) {
TraceBackService.trace(new AxelorException("", e, e.getcategory()), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
stop = true;
}
checkPoint();
}
@Override
protected void process() {
if(!stop) {
this.runImportProcess(batch.getAccountingBatch().getCompany());
updateCustomerAccountLog += batchAccountCustomer.updateAccountingSituationMarked(null);
}
}
public void runImportProcess(Company company) {
Map<List<String[]>,String> data = null;
try {
company = companyRepo.find(company.getId());
AccountConfig accountConfig = company.getAccountConfig();
data = rejectImportService.getCFONBFileByLot(accountConfig.getRejectImportPathAndFileName(), accountConfig.getTempImportPathAndFileName(), company, 1);
} catch (AxelorException e) {
TraceBackService.trace(new AxelorException(String.format(I18n.get("Batch")+" %s", batch.getId()), e, e.getcategory()), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
stop = true;
} catch (Exception e) {
TraceBackService.trace(new Exception(String.format(I18n.get("Batch")+" %s", batch.getId()), e), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
stop = true;
log.error("Bug(Anomalie) généré(e) pour l'import des rejets de prélèvement {}", batch.getId());
}
int i=0;
if(!stop) {
for(List<String[]> rejectList : data.keySet()) {
LocalDate rejectDate = rejectImportService.createRejectDate(data.get(rejectList));
paymentScheduleImportService.initialiseCollection();
for(String[] reject : rejectList) {
try {
String refDebitReject = reject[1].replaceAll(" ", "_");
BigDecimal amountReject = new BigDecimal(reject[2]);
InterbankCodeLine causeReject = rejectImportService.getInterbankCodeLine(reject[3], 1);
List<PaymentScheduleLine> paymentScheduleLineRejectedList = paymentScheduleImportService.importRejectPaymentScheduleLine(rejectDate, refDebitReject, amountReject, interbankCodeLineRepo.find(causeReject.getId()), companyRepo.find(company.getId()));
List<Invoice> invoiceRejectedList = paymentScheduleImportService.importRejectInvoice(rejectDate, refDebitReject, amountReject, interbankCodeLineRepo.find(causeReject.getId()), companyRepo.find(company.getId()));
/*** Aucun échéancier ou facture trouvé(e) pour le numéro de prélèvement ***/
if((invoiceRejectedList == null || invoiceRejectedList.isEmpty()) && (paymentScheduleLineRejectedList == null || paymentScheduleLineRejectedList.isEmpty())) {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_8),
GeneralServiceImpl.EXCEPTION,refDebitReject), IException.NO_VALUE);
}
else {
i++;
}
} catch (AxelorException e) {
TraceBackService.trace(new AxelorException(String.format(I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_9), reject[1]), e, e.getcategory()), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
} catch (Exception e) {
TraceBackService.trace(new Exception(String.format(I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_9), reject[1]), e), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
log.error("Bug(Anomalie) généré(e) pour l'import du rejet {}", reject[1]);
} finally {
if (i % 10 == 0) { JPA.clear(); }
}
}
this.createRejectMove(companyRepo.find(company.getId()),
paymentScheduleImportService.getPaymentScheduleLineMajorAccountList(),
paymentScheduleImportService.getInvoiceList(), rejectDate);
}
}
}
/**
* Fonction permettant de créer l'écriture des rejets pour l'ensembles des rejets (echéance de paiement,
* mensu masse, mensu grand compte et facture) d'une société
*
* @param company
* Une société
* @param pslList
* @param pslListGC
* @param pslListPayment
* @param pslListNewPayment
* @param pslListMonthlyPaymentAfterVentilateInvoice
* @param invoiceList
* @param invoiceRejectReasonList
* @return
* L'écriture des rejets
* @throws AxelorException
*/
@Transactional(rollbackOn = {AxelorException.class, Exception.class})
public Move createRejectMove(Company company, List<PaymentScheduleLine> pslListGC, List<Invoice> invoiceList, LocalDate rejectDate) {
// Création de l'écriture d'extourne par société
Move move = this.createRejectMove(company, rejectDate);
if(!stop) {
int ref = 1; // Initialisation du compteur d'échéances
/*** Echéancier de Lissage de paiement en PRLVT ***/
if(pslListGC != null && pslListGC.size()!=0 ) {
log.debug("Création des écritures de rejets : Echéancier de lissage de paiement");
ref = this.createMajorAccountRejectMoveLines(pslListGC, companyRepo.find(company.getId()),
companyRepo.find(company.getId()).getAccountConfig().getCustomerAccount(), moveRepo.find(move.getId()), ref);
}
/*** Facture en PRLVT ***/
if(invoiceList != null && invoiceList.size()!=0) {
log.debug("Création des écritures de rejets : Facture");
ref = this.createInvoiceRejectMoveLines(invoiceList, companyRepo.find(company.getId()),
companyRepo.find(company.getId()).getAccountConfig().getCustomerAccount(), moveRepo.find(move.getId()), ref);
}
this.validateRejectMove(companyRepo.find(company.getId()), moveRepo.find(move.getId()), ref, rejectDate);
}
return move;
}
public Move createRejectMove(Company company, LocalDate date) {
Move move = null;
try {
move = paymentScheduleImportService.createRejectMove(company, date);
} catch (AxelorException e) {
TraceBackService.trace(new AxelorException(String.format(I18n.get("Batch")+" %s", batch.getId()), e, e.getcategory()), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
stop = true;
} catch (Exception e) {
TraceBackService.trace(new Exception(String.format(I18n.get("Batch")+" %s", batch.getId()), e), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
stop = true;
log.error("Bug(Anomalie) généré(e) pour l'import des rejets de prélèvement {}", batch.getId());
}
return move;
}
public void validateRejectMove(Company company, Move move, int ref, LocalDate rejectDate) {
try {
if(ref > 1) {
MoveLine oppositeMoveLine = paymentScheduleImportService.createRejectOppositeMoveLine(company, moveRepo.find(move.getId()), ref, rejectDate);
paymentScheduleImportService.validateMove(moveRepo.find(move.getId()));
this.totalAmount = moveLineRepo.find(oppositeMoveLine.getId()).getCredit();
}
else {
paymentScheduleImportService.deleteMove(moveRepo.find(move.getId()));
}
} catch (AxelorException e) {
TraceBackService.trace(new AxelorException(String.format(I18n.get("Batch")+" %s", batch.getId()), e, e.getcategory()), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
} catch (Exception e) {
TraceBackService.trace(new Exception(String.format(I18n.get("Batch")+" %s", batch.getId()), e), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
log.error("Bug(Anomalie) généré(e) pour l'import des rejets de prélèvement {}", batch.getId());
}
}
/**
*
* @param pslListGC
* Une liste de ligne d'échéancier de Mensu grand compte
* @param company
* Une société
* @param customerAccount
* Un compte client
* @param move
* L'écriture de rejet
* @param ref
* Le numéro de ligne d'écriture
* @return
* Le numéro de ligne d'écriture incrémenté
* @throws AxelorException
*/
public int createMajorAccountRejectMoveLines(List<PaymentScheduleLine> pslListGC, Company company, Account customerAccount, Move move, int ref) {
int ref2 = ref;
for(PaymentScheduleLine paymentScheduleLine : pslListGC) {
try {
MoveLine moveLine = paymentScheduleImportService.createMajorAccountRejectMoveLine(paymentScheduleLineRepo.find(paymentScheduleLine.getId()), companyRepo.find(company.getId()),
accountRepo.find(customerAccount.getId()), moveRepo.find(move.getId()), ref);
if(moveLine != null) {
ref2++;
updatePaymentScheduleLine(paymentScheduleLineRepo.find(paymentScheduleLine.getId()));
}
} catch (AxelorException e) {
TraceBackService.trace(new AxelorException(String.format(I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_10), paymentScheduleLine.getName()), e, e.getcategory()), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
} catch (Exception e) {
TraceBackService.trace(new Exception(String.format(I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_10), paymentScheduleLine.getName()), e), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
log.error("Bug(Anomalie) généré(e) pour la création de l'écriture de rejet de l'échéance {}", paymentScheduleLine.getName());
} finally {
if (ref2 % 10 == 0) { JPA.clear(); }
}
}
return ref2;
}
/**
*
* @param invoiceList
* @param company
* @param move
* @param ref
* @return
* @throws AxelorException
*/
public int createInvoiceRejectMoveLines(List<Invoice> invoiceList, Company company, Account customerAccount, Move move, int ref) {
int ref2 = ref;
for(Invoice invoice : invoiceList) {
try {
MoveLine moveLine = paymentScheduleImportService.createInvoiceRejectMoveLine(invoiceRepo.find(invoice.getId()), companyRepo.find(company.getId()),
accountRepo.find(customerAccount.getId()), moveRepo.find(move.getId()), ref2);
if(moveLine != null) {
ref2++;
updateInvoice(invoice);
}
} catch (AxelorException e) {
TraceBackService.trace(new AxelorException(String.format(I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_11), invoice.getInvoiceId()), e, e.getcategory()), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
} catch (Exception e) {
TraceBackService.trace(new Exception(String.format(I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_11), invoice.getInvoiceId()), e), IException.DIRECT_DEBIT, batch.getId());
incrementAnomaly();
log.error("Bug(Anomalie) généré(e) pour la création de l'écriture de rejet de la facture {}", invoice.getInvoiceId());
} finally {
if (ref2 % 10 == 0) { JPA.clear(); }
}
}
return ref2;
}
public void updateAllInvoice(List<Invoice> invoiceList) {
for(Invoice invoice : invoiceList) {
updateInvoice(invoice);
}
}
public void updateAllPaymentScheduleLine(List<PaymentScheduleLine> paymentScheduleLineList) {
for(PaymentScheduleLine paymentScheduleLine : paymentScheduleLineList) {
updatePaymentScheduleLine(paymentScheduleLine);
}
}
/**
* As {@code batch} entity can be detached from the session, call {@code Batch.find()} get the entity in the persistant context.
* Warning : {@code batch} entity have to be saved before.
*/
@Override
protected void stop() {
String comment = "";
comment = I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_12);
comment += String.format("\t* %s "+I18n.get(IExceptionMessage.BATCH_PAYMENT_SCHEDULE_13)+"\n", batch.getDone());
comment += String.format("\t* "+I18n.get(IExceptionMessage.BATCH_INTERBANK_PO_IMPORT_5)+" : %s \n", this.totalAmount);
comment += String.format(I18n.get(com.axelor.apps.base.exceptions.IExceptionMessage.ALARM_ENGINE_BATCH_4), batch.getAnomaly());
comment += String.format("\t* ------------------------------- \n");
comment += String.format("\t* %s ", updateCustomerAccountLog);
super.stop();
addComment(comment);
}
}