// model - from UI, loan - from DB
		public void UpdateLoan(EditLoanDetailsModel model, Loan loan) {
			var actual = CreateLoan(model);

			UpdateInstallments(loan, actual);
			UpdateFees(loan, actual);
			// loan - from DB, actual - from UI
			CancelPayments(loan, actual);

			loan.Modified = true;
		}
		public EditLoanDetailsModel BuildModel(Loan loan) {
			var model = new EditLoanDetailsModel {
				Amount = loan.LoanAmount,
				InterestRate = loan.InterestRate,
				SetupFee = loan.SetupFee,
				Date = loan.Date,
				Id = loan.Id,
				LoanType = loan.LoanType.Type
			};

			model.LoanStatus = Enum.GetName(typeof(LoanStatus), loan.Status);

			if (loan.CashRequest != null)
				model.CashRequestId = loan.CashRequest.Id;

			model.Items = new List<SchedultItemModel>();

			AddInstallments(loan.Schedule, model.Items);
			AddTransactions(loan.PacnetTransactions, model.Items);
			AddPaypointTransactions(loan.TransactionsWithPaypointSuccesefull, model.Items);
			AddFees(loan.Charges, model.Items);

			model.Items = model.Items.OrderBy(i => i.Date).ToList();

			DateTime now = DateTime.UtcNow;

			var loanFutureScheduleItems = loan.Schedule.Where(x => x.Date > now)
					 .OrderBy(x => x.Date)
					 .ToDictionary(pair => pair.Date.ToString("dd/MM/yyyy"), pair => pair.Id.ToString());

			model.LoanFutureScheduleItems = new Dictionary<string, string>();
			model.LoanFutureScheduleItems.Add("Immediately Stop...", "-1");

			for (int i = 0; i <= loanFutureScheduleItems.Count - 1; i++) {
				model.LoanFutureScheduleItems.Add(string.Format("{0} : {1}", i + 1, loanFutureScheduleItems.ElementAt(i)
					.Key), loanFutureScheduleItems.ElementAt(i)
						.Value);
			}

			model.SInterestFreeze = loan.InterestFreeze.OrderBy(f => f.StartDate).Select(f => f.ToString()).ToList();

			foreach (LoanInterestFreeze fr in loan.InterestFreeze.OrderBy(fr => fr.StartDate).Where(fr => fr.DeactivationDate == null)) {
				model.InterestFreeze.Add(new InterestFreezeModel {
					Id = fr.Id,
					StartDate = fr.StartDate,
					EndDate = fr.EndDate,
					InterestRate = fr.InterestRate,
					ActivationDate = fr.ActivationDate,
					DeactivationDate = fr.DeactivationDate
				});
			}

			return model;
		}
        public int ReCalculateRepaymentPeriod(CashRequest cashRequest)
        {
            var result = cashRequest.RepaymentPeriod;

            if (!string.IsNullOrEmpty(cashRequest.LoanTemplate))
            {
                var model = EditLoanDetailsModel.Parse(cashRequest.LoanTemplate);
                var loan  = _builder.CreateLoan(model);
                var start = DateTime.UtcNow;
                var end   = loan.Schedule.Last().Date;
                result = GetTotalMonts(start, end);
            }
            return(result);
        }
        public int CalculateCountRepayment(Loan loan)
        {
            int result;

            if (string.IsNullOrEmpty(loan.CashRequest.LoanTemplate))
            {
                result = loan.Schedule.Count;
            }
            else
            {
                var model   = EditLoanDetailsModel.Parse(loan.CashRequest.LoanTemplate);
                var newLoan = _builder.CreateLoan(model);
                result = newLoan.Schedule.Count;
            }
            return(result);
        }
		public Loan CreateLoan(EditLoanDetailsModel model) {
			var loan = new Loan {
				Id = model.Id,
				LoanAmount = model.Amount,
				InterestRate = model.InterestRate,
				SetupFee = model.SetupFee,
				Date = model.Date
			};

			foreach (var item in model.Items.Where(i => i.Type == "Installment").OrderBy(i => i.Date)) {
				var x = CreateInstallment(item);
				x.Loan = loan;
				loan.Schedule.Add(x);
			}

			foreach (var item in model.Items.Where(i => i.Type == "Pacnet").OrderBy(i => i.Date)) {
				var x = CreatePacnetTransaction(item);
				x.Loan = loan;
				loan.Transactions.Add(x);
			}

			foreach (var item in model.Items.Where(i => i.Type == "Paypoint").OrderBy(i => i.Date)) {
				var x = CreatePaypointTransaction(item);
				x.Loan = loan;
				loan.Transactions.Add(x);
			}

			foreach (var item in model.Items.Where(i => i.Type == "Fee").OrderBy(i => i.Date)) {
				var x = CreateFee(item);
				x.Loan = loan;
				loan.Charges.Add(x);
			}

			loan.InterestFreeze = model.InterestFreeze.Select(item => new LoanInterestFreeze() {
				StartDate = item.StartDate,
				EndDate = item.EndDate,
				ActivationDate = item.ActivationDate,
				DeactivationDate = item.DeactivationDate,
				InterestRate = item.InterestRate,
				Id = item.Id
			}).ToList();

			return loan;
		}
		public bool IsAmountChangingAllowed(CashRequest cr) {
			if (cr == null || string.IsNullOrEmpty(cr.LoanTemplate))
				return true;

			var model = EditLoanDetailsModel.Parse(cr.LoanTemplate);

			//compare number of installments/other actions
			if (model.Items.Count(i => i.Type == "Installment") != cr.RepaymentPeriod)
				return false;
			if (model.Items.Count != cr.RepaymentPeriod)
				return false;

			//compare template balances with actual
			var expectedBalances = cr.LoanType.GetBalances(cr.ApprovedSum(), cr.RepaymentPeriod);
			var actualBalances = model.Items.Where(i => i.Type == "Installment").Select(i => i.Balance);
			if (expectedBalances.Except(actualBalances).Any())
				return false;

			return true;
		}