/**
   * Procédure permettant de récupérer l'objet de gestion déjà créé lors du prélèvement d'une autre
   * facture
   *
   * @param mlList La liste des lignes d'écriture de facture à prélever
   * @param ml Une ligne d'écriture de facture ) prélever
   * @return L'objet de gestion trouvé
   */
  public DirectDebitManagement getDirectDebitManagement(
      List<MoveLine> moveLineList, MoveLine ml, long directDebitManagementMaxId) {

    Partner partner = ml.getPartner();

    log.debug("Récupération de l'objet de prélèvement du tiers {}", partner.getFullName());

    List<MoveLine> moveLineListResult =
        moveLineRepo
            .all()
            .filter("self IN (?1) and self.partner = ?2", moveLineList, partner)
            .fetch();

    for (MoveLine moveLine : moveLineListResult) {
      Invoice invoice = cfonbExportService.getInvoice(moveLine);

      DirectDebitManagement directDebitManagement = invoice.getDirectDebitManagement();
      if (directDebitManagement != null
          && directDebitManagement.getId() > directDebitManagementMaxId) {

        log.debug("Objet de prélèvement trouvé : {} pour le tiers {}", partner.getFullName());
        return invoice.getDirectDebitManagement();
      }
    }

    log.debug("Aucun objet de prélèvement trouvé pour le tiers {}", partner.getFullName());

    return null;
  }
  @Transactional(rollbackOn = {AxelorException.class, Exception.class})
  public Move createOppositeExportMensuMoveLine(Move move, Account bankAccount, int ref)
      throws AxelorException {
    log.debug("Montant de la contrepartie : {}", totalAmount(move));

    MoveLine moveLine =
        moveLineServices.createMoveLine(
            move, null, bankAccount, this.totalAmount(move), true, today, ref, null);

    move.getMoveLineList().add(moveLine);
    moveLineRepo.save(moveLine);
    return move;
  }
 /**
  * Méthode permettant de récupérer les factures d'échéance mensu grand compte d'un échéancier
  *
  * @param paymentSchedule Un échéancier
  * @return
  */
 public List<MoveLine> getInvoiceMoveLineListToReconcile(PaymentSchedule paymentSchedule) {
   return moveLineRepo
       .all()
       .filter(
           "self.move.statusSelect = ?1 AND self.exportedDirectDebitOk = 'false' "
               + "AND self.account.reconcileOk = ?2 AND self.amountRemaining > 0 "
               + "AND self.move.invoice.operationTypeSelect = ?3 "
               + "AND self.move.invoice.schedulePaymentOk = 'true' "
               + "AND self.move.invoice.paymentSchedule = ?4 "
               + "ORDER BY self.date",
           MoveRepository.STATUS_VALIDATED,
           true,
           InvoiceRepository.OPERATION_TYPE_CLIENT_SALE,
           paymentSchedule)
       .fetch();
 }
  public void createPaymentMoveLine(Move paymentMove, MoveLine moveLine, int ref)
      throws AxelorException {
    BigDecimal amountExported = moveLine.getAmountRemaining();

    // On assigne le montant exporté pour pouvoir l'utiliser lors de la création du fichier d'export
    // CFONB
    moveLine.setAmountExportedInDirectDebit(amountExported);

    // creation d'une ecriture de paiement

    log.debug("generateAllExportInvoice - Création de la première ligne d'écriture");
    String invoiceName = "";
    if (moveLine.getMove().getInvoice() != null) {
      invoiceName = moveLine.getMove().getInvoice().getInvoiceId();
    }
    MoveLine moveLineGenerated =
        moveLineServices.createMoveLine(
            paymentMove,
            moveLine.getPartner(),
            moveLine.getAccount(),
            amountExported,
            false,
            today,
            ref,
            invoiceName);

    paymentMove.getMoveLineList().add(moveLineGenerated);

    moveLineRepo.save(moveLineGenerated);

    // Lettrage de la ligne 411 avec la ligne 411 de la facture
    log.debug("Creation du lettrage de la ligne 411 avec la ligne 411 de la facture");

    reconcileService.reconcile(moveLine, moveLineGenerated);

    log.debug("generateAllExportInvoice - Sauvegarde de l'écriture");

    moveRepo.save(paymentMove);
  }
  /**
   * Procédure permettant de créer une écriture de paiement d'une facture
   *
   * @param company Une société
   * @param moveLine Une ligne d'écriture
   * @param pm Un mode de paiement
   * @param pse Un Export des prélèvement
   * @throws AxelorException
   */
  public Move createPaymentMove(Company company, MoveLine moveLine, PaymentMode paymentMode)
      throws AxelorException {

    log.debug("Create payment move");

    Move paymentMove =
        moveService
            .getMoveCreateService()
            .createMove(
                paymentModeService.getPaymentModeJournal(paymentMode, company),
                company,
                null,
                null,
                paymentMode);

    BigDecimal amountExported = moveLine.getAmountRemaining();

    this.createPaymentMoveLine(paymentMove, moveLine, 1);

    log.debug("Create payment move line");

    Account paymentModeAccount = paymentModeService.getCompanyAccount(paymentMode, company);

    String invoiceName = "";
    if (moveLine.getMove().getInvoice() != null) {
      invoiceName = moveLine.getMove().getInvoice().getInvoiceId();
    }
    MoveLine moveLineGenerated2 =
        moveLineServices.createMoveLine(
            paymentMove, null, paymentModeAccount, amountExported, true, today, 2, invoiceName);

    paymentMove.getMoveLineList().add(moveLineGenerated2);
    moveLineRepo.save(moveLineGenerated2);

    moveService.getMoveValidateService().validateMove(paymentMove);
    moveRepo.save(paymentMove);

    return paymentMove;
  }
  public List<MoveLine> getInvoiceToExport(
      Company company, LocalDate scheduleDate, Currency currency) {

    List<MoveLine> moveLineInvoiceList = new ArrayList<MoveLine>();

    PaymentMode paymentMode = company.getAccountConfig().getDirectDebitPaymentMode();

    /**
     * Selection des lignes d'écritures dont : - l'état est validé - la société est celle
     * selectionnée sur l'objet export - le compte est lettrable - le montant restant à payer est
     * supérieur à 0 et débit supérieur à 0 (équivaut à une facture et non un avoir) - le mode de
     * règlement de la facture est en prélèvement - la date d'échéance est passée - la facture est
     * remplie sur l'écriture - la facture n'est pas selectionnée sur un échéancier
     */
    List<MoveLine> moveLineList =
        moveLineRepo
            .all()
            .filter(
                "self.move.statusSelect = ?1 AND self.exportedDirectDebitOk = 'false' "
                    + "AND self.move.company = ?2 "
                    + "AND self.account.reconcileOk = ?3 AND self.amountRemaining > 0 "
                    + "AND self.debit > 0 "
                    + "AND self.dueDate <= ?5 AND self.move.invoice IS NOT NULL "
                    + "AND self.move.invoice.paymentMode = ?4 "
                    + "AND self.move.invoice.schedulePaymentOk = 'false' "
                    + "AND self.move.invoice.currency = ?5",
                MoveRepository.STATUS_VALIDATED,
                company,
                true,
                paymentMode,
                currency)
            .fetch();

    // Ajout des factures
    for (MoveLine moveLine : moveLineList) {
      if (!this.isDebitBlocking(moveLine.getMove().getInvoice())) {
        moveLineInvoiceList.add(moveLine);
      }
    }

    // Récupération des factures rejetées
    List<Invoice> invoiceRejectList =
        invoiceRepo
            .all()
            .filter(
                "self.rejectMoveLine IS NOT NULL AND self.rejectMoveLine.amountRemaining > 0 AND self.rejectMoveLine.debit > 0"
                    + " AND self.paymentMode = ?1 AND self.company = ?2 AND self.rejectMoveLine.exportedDirectDebitOk = 'false' AND self.move.statusSelect = ?3"
                    + " AND self.rejectMoveLine.account.reconcileOk = 'true' "
                    + " AND self.rejectMoveLine.invoiceReject IS NOT NULL"
                    + " AND self.currency = ?4",
                paymentMode,
                company,
                MoveRepository.STATUS_VALIDATED,
                currency)
            .fetch();

    // Ajout des factures rejetées
    for (Invoice invoice : invoiceRejectList) {

      if (!this.isDebitBlocking(invoice)) {
        moveLineInvoiceList.add(invoice.getRejectMoveLine());
      }
    }

    return moveLineInvoiceList;
  }
  @Transactional(rollbackOn = {AxelorException.class, Exception.class})
  public PaymentScheduleLine generateExportMensu(
      PaymentScheduleLine paymentScheduleLine,
      List<PaymentScheduleLine> paymentScheduleLineList,
      Company company)
      throws AxelorException {

    PaymentSchedule paymentSchedule = paymentScheduleLine.getPaymentSchedule();

    this.testBankDetails(paymentSchedule);

    AccountConfig accountConfig = company.getAccountConfig();

    Account account = accountConfig.getCustomerAccount();
    PaymentMode paymentMode = accountConfig.getDirectDebitPaymentMode();

    BigDecimal amount = paymentScheduleLine.getInTaxAmount();
    Partner partner = paymentSchedule.getPartner();

    Move move =
        moveService
            .getMoveCreateService()
            .createMove(
                paymentModeService.getPaymentModeJournal(paymentMode, company),
                company,
                null,
                partner,
                paymentMode);

    this.setDebitNumber(paymentScheduleLineList, paymentScheduleLine, company);

    MoveLine moveLine =
        moveLineRepo.save(
            moveLineServices.createMoveLine(
                move, partner, account, amount, false, today, 1, paymentScheduleLine.getName()));

    move.addMoveLineListItem(moveLine);

    if (paymentScheduleLine.getFromReject()) {
      // lettrage avec le rejet
      PaymentScheduleLine rejectedPaymentScheduleLine =
          this.getPaymentScheduleLineRejectOrigin(paymentScheduleLine);
      if (rejectedPaymentScheduleLine.getRejectMoveLine() != null
          && rejectedPaymentScheduleLine
                  .getRejectMoveLine()
                  .getAmountRemaining()
                  .compareTo(BigDecimal.ZERO)
              == 1) {
        reconcileService.reconcile(rejectedPaymentScheduleLine.getRejectMoveLine(), moveLine);
      }
    } else {
      // Lettrage du paiement avec les factures d'échéances
      this.reconcileDirectDebit(moveLine, paymentSchedule);
    }

    move.addMoveLineListItem(
        moveLineServices.createMoveLine(
            move,
            partner,
            paymentModeService.getCompanyAccount(paymentMode, company),
            amount,
            true,
            today,
            2,
            null));

    this.validateMove(move);

    paymentScheduleLine.setDirectDebitAmount(amount);
    paymentScheduleLine.setInTaxAmountPaid(amount);
    paymentScheduleLine.setAdvanceOrPaymentMove(moveRepo.find(move.getId()));
    paymentScheduleLine.setAdvanceMoveLine(moveLine);
    paymentScheduleLine.setStatusSelect(PaymentScheduleLineRepository.STATUS_VALIDATED);
    return paymentScheduleLineRepo.save(paymentScheduleLine);
  }