private CreditAccountStateDto CloseAccount(CreditAccountDto account, CreditAccountStateDto latestCreditAccountState) { var accountCurrency = account.Currency; account.IsClosed = true; var updateCreditAccountCommand = new UpdateModelCommand <CreditAccountDto>() { ModelDto = account }; _creditAccountCommandRepository.Execute(updateCreditAccountCommand); var zeroPrice = new PriceDto() { Currency = accountCurrency, Value = 0m }; var closingCreditAccountState = new CreditAccountStateDto() { CreditAccount = account, FinesForOverdue = zeroPrice, InterestCounted = zeroPrice, MainDebtRemain = zeroPrice, RemainDebt = zeroPrice, Month = latestCreditAccountState.Month + 1, TotalInterestSumNotPaid = zeroPrice }; var newCreditAccountStateCommand = new CreateModelCommand <CreditAccountStateDto>() { ModelDto = closingCreditAccountState }; _creditAccountStateCommandRepository.Execute(newCreditAccountStateCommand); return(closingCreditAccountState); }
private CreditAccountStateDto UpdateFinesAndGetAccountState(int creditAccountId, DateTime specifiedDate) { var query = new ModelQuery() { Id = creditAccountId }; var account = _creditAccountQueryRepository.Handle(query); var latestCreditAccountStateQuery = new ActualCreditAccountStateQuery() { Id = account.Id }; var latestCreditAccountState = _creditAccountQueryRepository.Handle(latestCreditAccountStateQuery); var creditAccountPaymentsQuery = new CreditPaymentsQuery() { CreditAccountId = account.Id }; var latestCreditAccountStateDate = account.AgreementDate.AddMonths(latestCreditAccountState.Month); var accountPayments = _creditAccountQueryRepository.Handle(creditAccountPaymentsQuery); var paymentsForLatestPeriod = accountPayments.Where(p => latestCreditAccountStateDate < p.Timestamp); var accountCurrency = account.Currency; // S var sumPaidForLatestPeriod = paymentsForLatestPeriod.Sum(p => p.PaymentSum.Value); if (latestCreditAccountState.RemainDebt.Value <= sumPaidForLatestPeriod) { return(CloseAccount(account, latestCreditAccountState)); } // Z var totalDebtRemaining = latestCreditAccountState.RemainDebt.Value; // A var debtForMonth = GetDebtForMonth(latestCreditAccountState); if (latestCreditAccountState.MainDebtRemain.Value > sumPaidForLatestPeriod) { var finesForOverdue = latestCreditAccountState.FinesForOverdue; finesForOverdue.Value += account.CreditType.FineInterest * latestCreditAccountState.MainDebtRemain.Value; var updateFinesCommand = new UpdateModelCommand <PriceDto>() { ModelDto = finesForOverdue }; _priceCommandRepository.Execute(updateFinesCommand); var totalDebt = latestCreditAccountState.RemainDebt; totalDebt.Value += finesForOverdue.Value; var updateTotalDebtCommand = new UpdateModelCommand <PriceDto>() { ModelDto = totalDebt }; _priceCommandRepository.Execute(updateTotalDebtCommand); } if (ShouldAccountUpdate(account, specifiedDate)) { var previousFinesForOverdue = latestCreditAccountState.FinesForOverdue; // B var interestForMonth = (decimal)account.CreditType.InterestRate / 12 * totalDebtRemaining; var totalInterestNotPaid = latestCreditAccountState.TotalInterestSumNotPaid.Value; var newTotalDebtRemaining = totalDebtRemaining; var newTotalInterestNotPaid = totalInterestNotPaid; var mainDebtRemain = latestCreditAccountState.MainDebtRemain.Value; if (sumPaidForLatestPeriod < debtForMonth + mainDebtRemain) { newTotalDebtRemaining -= sumPaidForLatestPeriod; newTotalDebtRemaining += debtForMonth; newTotalInterestNotPaid += interestForMonth; mainDebtRemain = debtForMonth + mainDebtRemain - sumPaidForLatestPeriod; } else if (sumPaidForLatestPeriod < debtForMonth + mainDebtRemain + totalInterestNotPaid + interestForMonth) { newTotalDebtRemaining -= debtForMonth + mainDebtRemain; newTotalInterestNotPaid += interestForMonth - (sumPaidForLatestPeriod - debtForMonth - mainDebtRemain); mainDebtRemain = 0m; } else { newTotalInterestNotPaid = 0m; newTotalDebtRemaining -= sumPaidForLatestPeriod - interestForMonth - totalInterestNotPaid; mainDebtRemain = 0m; } var newCreditAccountState = new CreditAccountStateDto() { CreditAccount = account, Month = latestCreditAccountState.Month + 1, FinesForOverdue = new PriceDto() { Currency = accountCurrency, Value = previousFinesForOverdue.Value }, InterestCounted = new PriceDto() { Currency = accountCurrency, Value = interestForMonth }, RemainDebt = new PriceDto() { Currency = accountCurrency, Value = Math.Max(newTotalDebtRemaining + previousFinesForOverdue.Value, 0m) }, TotalInterestSumNotPaid = new PriceDto() { Currency = accountCurrency, Value = newTotalInterestNotPaid }, MainDebtRemain = new PriceDto() { Currency = accountCurrency, Value = mainDebtRemain } }; return(newCreditAccountState); } return(null); }
private static decimal GetDebtForMonth(CreditAccountStateDto accountState) { var totalDebtRemaining = accountState.RemainDebt.Value; return(totalDebtRemaining / (accountState.CreditAccount.TotalMonthDuration - accountState.Month)); }