private void addPaymentsInstallments(
      Sale sale, List<Payment> payments, List<Installment> installments) {
    if (installments != null) {
      for (Installment i : installments) {
        i.setDate(GenericTools.getDateFromString(i.getDateString()));
        i.setAmount(ServerTools.round(i.getAmount()));
      }
      if (sale.getClient() != null) {
        // Client must be enabled if he has future or pending installments
        sale.getClient().setDisabled(false);
      }
    }

    if (payments != null) {
      for (Payment p : payments) {
        p.setDate(GenericTools.getDateFromString(p.getDateString()));
        p.setScheduleDate(GenericTools.getDateFromString(p.getScheduleDateString()));
        p.setAmount(ServerTools.round(p.getAmount()));
        p.setPaymentMethod(sale.getPaymentMethod());
      }
    }

    sale.setInstallments(installments);
    sale.setPayments(payments);
  }
  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
  public void paymentToInstallment(Long idPayment) {

    Payment payment = (Payment) paymentService.getById(idPayment);
    if (payment == null) {
      log.warn("No payment found with id :" + idPayment);
      return;
    }
    Installment installment = new Installment();
    installment.setDate(
        payment.getScheduleDate() != null ? payment.getScheduleDate() : payment.getDate());
    installment.setAmount(payment.getAmount());
    installment.setSale(payment.getSale());
    installment.setComment(payment.getComment());
    installment.setRequestDetails(payment.getRequestDetails());
    installment.setRequestBeforeDateSent(payment.isRequestBeforeDateSent());
    installment.setRequestAfterDateSent(payment.isRequestAfterDateSent());

    paymentService.remove(payment, true);
    installmentService.save(installment, true);

    trackingService.addTrackingToUserSession(
        TrackingType.paymentReceivedToInstallment, payment.getSale());
  }
  private void addCustomInstallmentsDefinition(Sale sale, List<Installment> installments) {
    if (sale.getInstallmentsDefinition() == null
        || sale.getPaymentType() == PaymentType.onePayment
        || sale.getInstallmentsDefinition().getInstallmentsType() == null
        || sale.getInstallmentsDefinition().getInstallmentsFrequency() == null
        || sale.getInstallmentsDefinition().getInstallmentsFrequency()
                == InstallmentsFrequency.custom
            && GenericTools.isEmpty(installments)) {
      sale.setPaymentType(PaymentType.onePayment);
      sale.setInstallmentsDefinition(null);

    } else {
      InstallmentsDefinition installDef = sale.getInstallmentsDefinition();

      sale.setPaymentMethod(null);

      if (installDef.getInstallmentsFrequency() == InstallmentsFrequency.periodical) {
        installDef.setInstallmentsPeriodicalStartDate(
            GenericTools.getDateFromString(installDef.getInstallmentsPeriodicalStartDateString()));

      } else {
        // Clear periodical values
        installDef.setInstallmentsPeriodicalStartDate(null);
        installDef.setInstallmentsPeriodicalPrice(null);
      }

      if (sale.getInstallmentsDefinition().getInstallmentsFrequency()
          == InstallmentsFrequency.custom) {

        List<Installment> customInstallmentDefList = new ArrayList<Installment>();

        for (Installment installment : installments) {
          Installment customInstallmentDef = new Installment();
          customInstallmentDef.setDate(GenericTools.getDateFromString(installment.getDateString()));
          // In drafts, amount can be null (but in database)
          customInstallmentDef.setAmount(
              installment.getAmount() == null ? 0 : installment.getAmount());
          customInstallmentDef.setInstallmentsDefinition(sale.getInstallmentsDefinition());
          customInstallmentDefList.add(customInstallmentDef);
        }

        sale.getInstallmentsDefinition().setInstallments(customInstallmentDefList);

      } else if (sale.getInstallmentsDefinition().getInstallmentsType()
          == InstallmentsType.undefined) {

        // Clear defined value
        installDef.setInstallmentsNumber(0);

        Date lastInstallmentDate =
            installments.isEmpty()
                ? sale.getInstallmentsDefinition().getInstallmentsPeriodicalStartDate()
                : installments.get(installments.size() - 1).getDate();

        Date nextUndefinedInstallment;
        if (installments.isEmpty()) {
          nextUndefinedInstallment = lastInstallmentDate;

        } else {
          nextUndefinedInstallment =
              sale.getInstallmentsDefinition()
                  .addNToDate(
                      new ServerTools(),
                      lastInstallmentDate,
                      sale.getInstallmentsDefinition().getInstallmentsPeriodicalFrequency(),
                      sale.getInstallmentsDefinition().getInstallmentsPeriodicalFrequencyN());
        }
        sale.getInstallmentsDefinition().setNextUndefinedInstallment(nextUndefinedInstallment);
      }
    }
  }