Program: 59075
Project: 59075
Buggy source:
/** 
 * Confirms the payment voucher if the selected lines PiToPay 2nd O2M belongs to different companies -> error I - Payment with an amount If we pay a classical moveLine (invoice, reject ..) -> just create a payment If we pay a schedule 2 payments are created 1st reconciled with the invoice and the second reconciled with the schedule II - Payment with an excess Payment If we pay a moveLine having the same account, we just reconcile If we pay a with different account -> 1- switch money to the good account 2- reconcile then
 * @param paymentVoucher
 */
@Transactional(rollbackOn={AxelorException.class,Exception.class}) public void confirmPaymentVoucher(PaymentVoucher paymentVoucher,boolean updateCustomerAccount) throws AxelorException {
  LOG.debug("String_Node_Str");
  paymentVoucherSequenceService.setReference(paymentVoucher);
  Partner payerPartner=paymentVoucher.getPartner();
  PaymentMode paymentMode=paymentVoucher.getPaymentMode();
  Company company=paymentVoucher.getCompany();
  Journal journal=paymentMode.getBankJournal();
  LocalDate paymentDate=paymentVoucher.getPaymentDateTime().toLocalDate();
  boolean scheduleToBePaid=false;
  Account paymentModeAccount=paymentModeService.getCompanyAccount(paymentMode,company);
  paymentVoucherControlService.checkPaymentVoucherField(paymentVoucher,company,paymentModeAccount,journal);
  if (paymentVoucher.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0 && !journal.getExcessPaymentOk()) {
    throw new AxelorException(String.format("String_Node_Str",GeneralService.getExceptionAccountingMsg()),IException.INCONSISTENCY);
  }
  if (paymentVoucher.getPayboxPaidOk()) {
    paymentVoucherControlService.checkPayboxAmount(paymentVoucher);
  }
  Currency currencyToPay=null;
  boolean allRight=paymentVoucherControlService.checkIfSameAccount(paymentVoucher.getPaymentInvoiceToPayList(),paymentVoucher.getMoveLine());
  LOG.debug("String_Node_Str",allRight);
  if (allRight) {
    scheduleToBePaid=this.toPayWithExcessPayment(paymentVoucher.getPaymentInvoiceToPayList(),paymentVoucher.getMoveLine(),scheduleToBePaid,paymentDate);
  }
  if (paymentVoucher.getMoveLine() == null || (paymentVoucher.getMoveLine() != null && !allRight) || (scheduleToBePaid && !allRight && paymentVoucher.getMoveLine() != null)) {
    PaymentScheduleLine lastPaymentScheduleLine=null;
    Move move=moveService.createMove(paymentVoucher.getPaymentMode().getBankJournal(),company,null,payerPartner,paymentDate,paymentMode,false,paymentVoucher.getCashRegister());
    move.setPaymentVoucher(paymentVoucher);
    paymentVoucher.setGeneratedMove(move);
    BigDecimal paidLineTotal=BigDecimal.ZERO;
    int moveLineNo=1;
    boolean isDebitToPay=paymentVoucherToolService.isDebitToPay(paymentVoucher);
    for (    PaymentInvoiceToPay paymentInvoiceToPay : this.getPaymentInvoiceToPayList(paymentVoucher)) {
      MoveLine moveLineToPay=paymentInvoiceToPay.getMoveLine();
      LOG.debug("String_Node_Str",moveLineToPay.getDebit());
      LOG.debug("String_Node_Str",moveLineToPay.getAmountPaid());
      BigDecimal amountToPay=this.getAmountCurrencyConverted(moveLineToPay,paymentVoucher,paymentInvoiceToPay.getAmountToPay());
      if (amountToPay.compareTo(BigDecimal.ZERO) > 0) {
        paidLineTotal=paidLineTotal.add(amountToPay);
        this.payMoveLine(move,moveLineNo,payerPartner,moveLineToPay,amountToPay,paymentInvoiceToPay,isDebitToPay,paymentDate,updateCustomerAccount);
        moveLineNo+=1;
      }
    }
    MoveLine moveLine=null;
    if (paymentVoucher.getMoveLine() != null) {
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),paymentVoucher.getMoveLine().getAccount(),paymentVoucher.getPaidAmount(),isDebitToPay,false,paymentDate,moveLineNo,null);
      Reconcile reconcile=reconcileService.createReconcile(moveLine,paymentVoucher.getMoveLine(),moveLine.getDebit(),!isDebitToPay);
      reconcileService.confirmReconcile(reconcile,updateCustomerAccount);
    }
 else {
      moveLine=moveLineService.createMoveLine(move,payerPartner,paymentModeAccount,paymentVoucher.getPaidAmount(),isDebitToPay,false,paymentDate,moveLineNo,null);
    }
    move.getMoveLineList().add(moveLine);
    if (paymentVoucher.getPaidAmount().compareTo(paidLineTotal) > 0) {
      BigDecimal remainingPaidAmount=paymentVoucher.getRemainingAmount();
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),company.getAccountConfig().getCustomerAccount(),remainingPaidAmount,!isDebitToPay,false,paymentDate,moveLineNo++,null);
      move.getMoveLineList().add(moveLine);
      if (lastPaymentScheduleLine == null || paymentScheduleService.isLastSchedule(lastPaymentScheduleLine)) {
        if (isDebitToPay) {
          reconcileService.balanceCredit(moveLine,company,updateCustomerAccount);
        }
      }
    }
    moveService.validateMove(move);
    paymentVoucher.setGeneratedMove(move);
  }
  paymentVoucher.setStateSelect(IPaymentVoucher.STATE_CONFIRMED);
  paymentVoucherSequenceService.setReceiptNo(paymentVoucher,company,journal);
  paymentVoucher.save();
}

Fixed version (ground truth):
/** 
 * Confirms the payment voucher if the selected lines PiToPay 2nd O2M belongs to different companies -> error I - Payment with an amount If we pay a classical moveLine (invoice, reject ..) -> just create a payment If we pay a schedule 2 payments are created 1st reconciled with the invoice and the second reconciled with the schedule II - Payment with an excess Payment If we pay a moveLine having the same account, we just reconcile If we pay a with different account -> 1- switch money to the good account 2- reconcile then
 * @param paymentVoucher
 */
@Transactional(rollbackOn={AxelorException.class,Exception.class}) public void confirmPaymentVoucher(PaymentVoucher paymentVoucher,boolean updateCustomerAccount) throws AxelorException {
  LOG.debug("String_Node_Str");
  paymentVoucherSequenceService.setReference(paymentVoucher);
  Partner payerPartner=paymentVoucher.getPartner();
  PaymentMode paymentMode=paymentVoucher.getPaymentMode();
  Company company=paymentVoucher.getCompany();
  Journal journal=paymentMode.getBankJournal();
  LocalDate paymentDate=paymentVoucher.getPaymentDateTime().toLocalDate();
  boolean scheduleToBePaid=false;
  Account paymentModeAccount=paymentModeService.getCompanyAccount(paymentMode,company);
  paymentVoucherControlService.checkPaymentVoucherField(paymentVoucher,company,paymentModeAccount,journal);
  if (paymentVoucher.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0 && !journal.getExcessPaymentOk()) {
    throw new AxelorException(String.format("String_Node_Str",GeneralService.getExceptionAccountingMsg()),IException.INCONSISTENCY);
  }
  if (paymentVoucher.getPayboxPaidOk()) {
    paymentVoucherControlService.checkPayboxAmount(paymentVoucher);
  }
  Currency currencyToPay=null;
  boolean allRight=paymentVoucherControlService.checkIfSameAccount(paymentVoucher.getPaymentInvoiceToPayList(),paymentVoucher.getMoveLine());
  LOG.debug("String_Node_Str",allRight);
  if (allRight) {
    scheduleToBePaid=this.toPayWithExcessPayment(paymentVoucher.getPaymentInvoiceToPayList(),paymentVoucher.getMoveLine(),scheduleToBePaid,paymentDate);
  }
  if (paymentVoucher.getMoveLine() == null || (paymentVoucher.getMoveLine() != null && !allRight) || (scheduleToBePaid && !allRight && paymentVoucher.getMoveLine() != null)) {
    Move move=moveService.createMove(paymentVoucher.getPaymentMode().getBankJournal(),company,null,payerPartner,paymentDate,paymentMode,false,paymentVoucher.getCashRegister());
    move.setPaymentVoucher(paymentVoucher);
    paymentVoucher.setGeneratedMove(move);
    BigDecimal paidLineTotal=BigDecimal.ZERO;
    int moveLineNo=1;
    boolean isDebitToPay=paymentVoucherToolService.isDebitToPay(paymentVoucher);
    for (    PaymentInvoiceToPay paymentInvoiceToPay : this.getPaymentInvoiceToPayList(paymentVoucher)) {
      MoveLine moveLineToPay=paymentInvoiceToPay.getMoveLine();
      LOG.debug("String_Node_Str",moveLineToPay.getDebit());
      LOG.debug("String_Node_Str",moveLineToPay.getAmountPaid());
      BigDecimal amountToPay=this.getAmountCurrencyConverted(moveLineToPay,paymentVoucher,paymentInvoiceToPay.getAmountToPay());
      if (amountToPay.compareTo(BigDecimal.ZERO) > 0) {
        paidLineTotal=paidLineTotal.add(amountToPay);
        this.payMoveLine(move,moveLineNo,payerPartner,moveLineToPay,amountToPay,paymentInvoiceToPay,isDebitToPay,paymentDate,updateCustomerAccount);
        moveLineNo+=1;
      }
    }
    MoveLine moveLine=null;
    if (paymentVoucher.getMoveLine() != null) {
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),paymentVoucher.getMoveLine().getAccount(),paymentVoucher.getPaidAmount(),isDebitToPay,false,paymentDate,moveLineNo,null);
      Reconcile reconcile=reconcileService.createReconcile(moveLine,paymentVoucher.getMoveLine(),moveLine.getDebit(),!isDebitToPay);
      reconcileService.confirmReconcile(reconcile,updateCustomerAccount);
    }
 else {
      moveLine=moveLineService.createMoveLine(move,payerPartner,paymentModeAccount,paymentVoucher.getPaidAmount(),isDebitToPay,false,paymentDate,moveLineNo,null);
    }
    move.getMoveLineList().add(moveLine);
    if (paymentVoucher.getPaidAmount().compareTo(paidLineTotal) > 0) {
      BigDecimal remainingPaidAmount=paymentVoucher.getRemainingAmount();
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),company.getAccountConfig().getCustomerAccount(),remainingPaidAmount,!isDebitToPay,false,paymentDate,moveLineNo++,null);
      move.getMoveLineList().add(moveLine);
      if (isDebitToPay) {
        reconcileService.balanceCredit(moveLine,company,updateCustomerAccount);
      }
    }
    moveService.validateMove(move);
    paymentVoucher.setGeneratedMove(move);
  }
  paymentVoucher.setStateSelect(IPaymentVoucher.STATE_CONFIRMED);
  paymentVoucherSequenceService.setReceiptNo(paymentVoucher,company,journal);
  paymentVoucher.save();
}