Program: 58635
Project: 58635
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) throws AxelorException {
  log.debug("String_Node_Str");
  paymentVoucherSequenceService.setReference(paymentVoucher);
  Partner payerPartner=paymentVoucher.getPartner();
  PaymentMode paymentMode=paymentVoucher.getPaymentMode();
  Company company=paymentVoucher.getCompany();
  Journal journal=paymentModeService.getPaymentModeJournal(paymentMode,company);
  LocalDate paymentDate=paymentVoucher.getPaymentDate();
  boolean scheduleToBePaid=false;
  Account paymentModeAccount=paymentModeService.getPaymentModeAccount(paymentMode,company);
  paymentVoucherControlService.checkPaymentVoucherField(paymentVoucher,company,paymentModeAccount,journal);
  if (paymentVoucher.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0 && !journal.getExcessPaymentOk()) {
    throw new AxelorException(String.format(I18n.get(IExceptionMessage.PAYBOX_3),GeneralServiceImpl.EXCEPTION),IException.INCONSISTENCY);
  }
  if (paymentVoucher.getPayboxPaidOk()) {
    paymentVoucherControlService.checkPayboxAmount(paymentVoucher);
  }
  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.getMoveCreateService().createMove(journal,company,null,payerPartner,paymentDate,paymentMode,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);
        moveLineNo+=1;
      }
    }
    MoveLine moveLine=null;
    if (paymentVoucher.getMoveLine() != null) {
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),paymentVoucher.getMoveLine().getAccount(),paymentVoucher.getPaidAmount(),isDebitToPay,paymentDate,moveLineNo,null);
      Reconcile reconcile=reconcileService.createReconcile(moveLine,paymentVoucher.getMoveLine(),moveLine.getDebit(),!isDebitToPay);
      reconcileService.confirmReconcile(reconcile);
    }
 else {
      moveLine=moveLineService.createMoveLine(move,payerPartner,paymentModeAccount,paymentVoucher.getPaidAmount(),isDebitToPay,paymentDate,moveLineNo,null);
    }
    move.getMoveLineList().add(moveLine);
    if (paymentVoucher.getPaidAmount().compareTo(paidLineTotal) > 0) {
      BigDecimal remainingPaidAmount=paymentVoucher.getRemainingAmount();
      Account partnerAccount=Beans.get(AccountCustomerService.class).getPartnerAccount(payerPartner,company,paymentVoucherToolService.isPurchase(paymentVoucher));
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),partnerAccount,remainingPaidAmount,!isDebitToPay,paymentDate,moveLineNo++,null);
      move.getMoveLineList().add(moveLine);
      if (isDebitToPay) {
        reconcileService.balanceCredit(moveLine);
      }
    }
    moveService.getMoveValidateService().validateMove(move);
    paymentVoucher.setGeneratedMove(move);
  }
  paymentVoucher.setStatusSelect(PaymentVoucherRepository.STATUS_CONFIRMED);
  paymentVoucherSequenceService.setReceiptNo(paymentVoucher,company,journal);
  this.deleteUnPaidLines(paymentVoucher);
  paymentVoucherRepository.save(paymentVoucher);
}

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) throws AxelorException {
  log.debug("String_Node_Str");
  paymentVoucherSequenceService.setReference(paymentVoucher);
  Partner payerPartner=paymentVoucher.getPartner();
  PaymentMode paymentMode=paymentVoucher.getPaymentMode();
  Company company=paymentVoucher.getCompany();
  Journal journal=paymentModeService.getPaymentModeJournal(paymentMode,company);
  LocalDate paymentDate=paymentVoucher.getPaymentDate();
  boolean scheduleToBePaid=false;
  Account paymentModeAccount=paymentModeService.getPaymentModeAccount(paymentMode,company);
  paymentVoucherControlService.checkPaymentVoucherField(paymentVoucher,company,paymentModeAccount,journal);
  if (paymentVoucher.getRemainingAmount().compareTo(BigDecimal.ZERO) > 0 && !journal.getExcessPaymentOk()) {
    throw new AxelorException(String.format(I18n.get(IExceptionMessage.PAYBOX_3),GeneralServiceImpl.EXCEPTION),IException.INCONSISTENCY);
  }
  if (paymentVoucher.getPayboxPaidOk()) {
    paymentVoucherControlService.checkPayboxAmount(paymentVoucher);
  }
  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.getMoveCreateService().createMove(journal,company,null,payerPartner,paymentDate,paymentMode,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);
      }
    }
    MoveLine moveLine=null;
    if (paymentVoucher.getMoveLine() != null) {
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),paymentVoucher.getMoveLine().getAccount(),paymentVoucher.getPaidAmount(),isDebitToPay,paymentDate,moveLineNo++,null);
      Reconcile reconcile=reconcileService.createReconcile(moveLine,paymentVoucher.getMoveLine(),moveLine.getDebit(),!isDebitToPay);
      reconcileService.confirmReconcile(reconcile);
    }
 else {
      moveLine=moveLineService.createMoveLine(move,payerPartner,paymentModeAccount,paymentVoucher.getPaidAmount(),isDebitToPay,paymentDate,moveLineNo++,null);
    }
    move.getMoveLineList().add(moveLine);
    if (paymentVoucher.getPaidAmount().compareTo(paidLineTotal) > 0) {
      BigDecimal remainingPaidAmount=paymentVoucher.getRemainingAmount();
      Account partnerAccount=Beans.get(AccountCustomerService.class).getPartnerAccount(payerPartner,company,paymentVoucherToolService.isPurchase(paymentVoucher));
      moveLine=moveLineService.createMoveLine(move,paymentVoucher.getPartner(),partnerAccount,remainingPaidAmount,!isDebitToPay,paymentDate,moveLineNo++,null);
      move.getMoveLineList().add(moveLine);
      if (isDebitToPay) {
        reconcileService.balanceCredit(moveLine);
      }
    }
    moveService.getMoveValidateService().validateMove(move);
    paymentVoucher.setGeneratedMove(move);
  }
  paymentVoucher.setStatusSelect(PaymentVoucherRepository.STATUS_CONFIRMED);
  paymentVoucherSequenceService.setReceiptNo(paymentVoucher,company,journal);
  this.deleteUnPaidLines(paymentVoucher);
  paymentVoucherRepository.save(paymentVoucher);
}