billService.updateBankAccountAndInvestmentBills(
      fixedCreditSum,
      fixedCreditSum,
      fixedCreditSum,
      0,
    );

    const clientCredit = this.clientCreditRepository.create({
      creditId,
      clientId,
      startCredit: BankInfo.currentBankDate.format(),
      creditSum: fixedCreditSum,
      mainBill,
      percentBill,
      isClosed: false,
    });

    const savedClientCredit = await this.clientCreditRepository.save(
      clientCredit,
    );

    return savedClientCredit;
  }

  public async getClientCreditById(id: number) {
    const clientCredit = await this.clientCreditRepository.findOne({
      where: {
        id,
      },
      relations: ['mainBill', 'percentBill'],
    });
    return this.prepareClientDeposit(clientCredit);
  }

  public async getClientCreditService() {
    const clientCredits = await this.clientCreditRepository.find({
      relations: ['mainBill', 'percentBill'],
    });
    return clientCredits.map((clientCredit) =>
      this.prepareClientDeposit(clientCredit),
    );
  }

  public prepareClientDeposit(clientCredit: ClientCredit) {
    return {
     ...clientCredit,
      creditSum: clientCredit.creditSum / 100,
      credit: {
       ...clientCredit.credit,
        maxSum: clientCredit.credit.maxSum / 100,
      },
      mainBill: {
       ...clientCredit.mainBill,
        debit: new BigNumber(clientCredit.mainBill.debit)
         .dividedBy(100)
         .toString(),
        credit: new BigNumber(clientCredit.mainBill.credit)
         .dividedBy(100)
         .toString(),
        balance: new BigNumber(clientCredit.mainBill.balance)
         .dividedBy(100)
         .toString(),
      },
      percentBill: {
       ...clientCredit.percentBill,
        debit: new BigNumber(clientCredit.percentBill.debit)
         .dividedBy(100)
         .toString(),
        credit: new BigNumber(clientCredit.percentBill.credit)
         .dividedBy(100)
         .toString(),
        balance: new BigNumber(clientCredit.percentBill.balance)
         .dividedBy(100)
         .toString(),
      },
    };
  }

  public async getCreditPaymentPlan(id: number) {
    const clientCredit = await this.getClientCreditById(id);
    const result: { paymentDate: string; paymentPerMonth: number }[] = [];

    const percentPerMonth = clientCredit.credit.percent / (12 * 100);
    const countMonthes = clientCredit.credit.termInMs;
    if (clientCredit.credit.isAnnuity) {
      const annuityCoefficient =
        (percentPerMonth * Math.pow(1 + percentPerMonth, countMonthes)) /
        (Math.pow(1 + percentPerMonth, countMonthes) - 1);

      const paymentPerMonth = annuityCoefficient * clientCredit.creditSum;

      let paymentDate = moment(clientCredit.startCredit).add(1,'months');
      for (let i = 0; i < countMonthes; i++) {
        result.push({
          paymentDate: paymentDate.format('DD-MM-YYYY'),
          paymentPerMonth,
        });

        paymentDate = paymentDate.add(1,'months');
      }
    } else {
      let creditRest = clientCredit.creditSum;
      const monthlyReturningCreditBodyPart =
        clientCredit.creditSum / countMonthes;

      let paymentDate = moment(clientCredit.startCredit).add(1,'months');
      for (let i = 0; i < countMonthes; i++) {
        const thisMonthPayment =
          monthlyReturningCreditBodyPart + creditRest * percentPerMonth;
        result.push({
          paymentDate: paymentDate.format('DD-MM-YYYY'),
          paymentPerMonth: thisMonthPayment,
        });

        creditRest -= monthlyReturningCreditBodyPart;
        paymentDate = paymentDate.add(1,'months');
      }
    }

    return result;
  }

  public accrueCreditPercentage(
    clientCredit: ClientCredit,
    investmentBankAccount: Bill,
  ) {
    let percentAmount = 0;
    const countMonthes = clientCredit.credit.termInMs;
    const percentPerMonth = clientCredit.credit.percent / (12 * 100);
    const dayReturningCreditBodyPart =
      clientCredit.creditSum / (countMonthes * 30);
    let shareCredit = 0;
    let sharePercent = 0;

    if (clientCredit.credit.isAnnuity) {
      const anuityCoefficient =
        (percentPerMonth * Math.pow(1 + percentPerMonth, countMonthes)) /
        (Math.pow(1 + percentPerMonth, countMonthes) - 1);

      const paymentPerMonth = anuityCoefficient * clientCredit.creditSum;

      percentAmount = paymentPerMonth / 30;
      shareCredit = dayReturningCreditBodyPart;
      sharePercent = percentAmount - dayReturningCreditBodyPart;
    } else {
      let creditRest = clientCredit.creditSum;
      const dayReturningCreditBodyPart =
        clientCredit.creditSum / (countMonthes * 30);
      const percentPerDay = percentPerMonth / 30;

      const amoontOfDays = moment
       .duration(
          BankInfo.currentBankDate.diff(moment(clientCredit.startCredit)),
        )
       .asDays();

      for (let i = 0; i < amoontOfDays; i++) {
        creditRest -= dayReturningCreditBodyPart;
      }

      shareCredit = dayReturningCreditBodyPart;
      sharePercent = creditRest * percentPerDay;
    }
    percentAmount = Math.trunc(sharePercent);
    const bigPercentAmount = new BigNumber(percentAmount);
    const bigCreditPart = new BigNumber(Math.trunc(shareCredit));
    investmentBankAccount.credit = new BigNumber(investmentBankAccount.credit)
     .plus(bigPercentAmount)
     .toString();
    const percentBill = clientCredit.percentBill;
    percentBill.credit = new BigNumber(percentBill.credit)
     .plus(bigPercentAmount)
     .toString();
    const mainBill = clientCredit.mainBill;
    mainBill.credit = new BigNumber(mainBill.credit)
     .plus(bigCreditPart)
     .toString();
    this.billService.calculateBalanceForBill(mainBill);
    this.billService.calculateBalanceForBill(percentBill);
    this.billService.calculateBalanceForBill(investmentBankAccount);
    return clientCredit;
  }

  public async closeCredit(id: number) {
    const clientCredit = await this.clientCreditRepository.findOne({
      where: {
        id,
      },
      relations: ['mainBill', 'percentBill'],
    });

    if (clientCredit.isClosed) {
      throw new BadRequestException('could not close already close credit');
    }
    if (
      moment(clientCredit.startCredit)
       .add(clientCredit.credit.termInMs,'months')
       .isAfter(BankInfo.currentBankDate)
    ) {
      throw new BadRequestException('Cannot close credit before term ended');
    }

    const {
      investmentBankAccount,
      bankAccount,
    } = await this.billService.getBankAccountAndInvestmentBills();

    const amount = new BigNumber(clientCredit.mainBill.balance).absoluteValue();
    bankAccount.debit = new BigNumber(bankAccount.debit)
     .plus(amount)
     .toString();
    bankAccount.credit = new BigNumber(bankAccount.credit)
     .plus(amount)
     .toString();
    this.billService.calculateBalanceForBill(bankAccount);
    const mainBill = clientCredit.mainBill;
    mainBill.debit = new BigNumber(mainBill.debit).plus(amount).toString();
    mainBill.credit = new BigNumber(mainBill.credit).plus(amount).toString();
    this.billService.calculateBalanceForBill(mainBill);
    investmentBankAccount.credit = new BigNumber(investmentBankAccount.credit)
     .plus(amount)
     .toString();
    this.billService.calculateBalanceForBill(