public override bool IsValid()
 {
     if (!base.IsValid())
     {
         return(false);
     }
     if (AccountPrice < 0)
     {
         return(false);
     }
     if (!AccountToPay.IsValid())
     {
         return(false);
     }
     return(true);
 }
        public ActionResult Create(AccountToPay accountToPay)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    // se é conta mensal não possuí parcelas
                    if (accountToPay.MonthlyAccount)
                    {
                        accountToPay.NumberOfInstallments = 0;
                    }

                    var valueInstallment = accountToPay.NumberOfInstallments == 0 ?
                                           accountToPay.Value : accountToPay.Value / accountToPay.NumberOfInstallments;

                    // criação das parcelas
                    for (var i = 0; i < accountToPay.NumberOfInstallments; i++)
                    {
                        var installment = new Installment
                        {
                            MaturityDate = accountToPay.MaturityDate.AddMonths(i),
                            Value        = valueInstallment,
                        };

                        accountToPay.Installments.Add(installment);
                    }

                    accountToPay.ApplicationUserId = User.Identity.GetUserId <int>();

                    _accountToPayRepository.Add(accountToPay);

                    this.AddToastMessage("Conta salva", $"A conta {accountToPay.Description} foi salva com sucesso", ToastType.Success);

                    return(RedirectToAction("Index"));
                }
                catch
                {
                    this.AddToastMessage("Erro no salvamento", $"Erro ao salvar a conta {accountToPay.Description}, favor tentar novamente", ToastType.Error);
                }
            }

            return(Create());
        }
        public ActionResult PayAccount(int id, int installment_id, PaymentType paymentType, int?internalBankAccount_id,
                                       int?providerBankAccount_id)
        {
            if (id == 0)
            {
                return(new HttpStatusCodeResult(HttpStatusCode.BadRequest));
            }

            var accountToPay = _accountToPayRepository.FindActive(id);

            try
            {
                var amountDue = 0M;

                //não possuí parcelas
                if (!accountToPay.Installments.Any())
                {
                    //conta em atraso
                    if (accountToPay.MaturityDate < DateTime.Now && accountToPay.PaidValue < accountToPay.Value)
                    {
                        var daysPastDue = (int)DateTime.Now.Subtract(accountToPay.MaturityDate).TotalDays;

                        amountDue = Math.Round(accountToPay.Value - accountToPay.Installments
                                               .Where(i => i.PaidValue >= i.Value)
                                               .Sum(i => i.Value), 2);

                        amountDue += Math.Round(amountDue * accountToPay.Penalty / 100, 2);
                        amountDue += Math.Round(amountDue * daysPastDue * accountToPay.DailyInterest / 100, 2);
                    }
                    //conta em dia
                    else
                    {
                        accountToPay.PaidValue = accountToPay.Value;
                    }

                    if (accountToPay.MonthlyAccount)
                    {
                        var newAccountToPay = new AccountToPay
                        {
                            MaturityDate         = accountToPay.MaturityDate.AddMonths(1),
                            ApplicationUserId    = User.Identity.GetUserId <int>(),
                            DailyInterest        = accountToPay.DailyInterest,
                            Description          = accountToPay.Description,
                            DocumentNumber       = accountToPay.DocumentNumber,
                            MonthlyAccount       = accountToPay.MonthlyAccount,
                            NumberOfInstallments = accountToPay.NumberOfInstallments,
                            PaymentSimulators    = accountToPay.PaymentSimulators,
                            Penalty    = accountToPay.Penalty,
                            Priority   = accountToPay.Priority,
                            ProviderId = accountToPay.ProviderId,
                            Value      = accountToPay.Value
                        };

                        _accountToPayRepository.Add(newAccountToPay);
                    }
                }
                //possuí parcelas
                else
                {
                    //vai pagar a conta inteira
                    if (installment_id == 0)
                    {
                        //parcelas vencidas
                        var overdueInstallments = accountToPay.Installments
                                                  .Where(i => i.MaturityDate < DateTime.Now && !i.PaymentDate.HasValue)
                                                  .ToList();

                        //parcelas em dia e ainda não pagas
                        var installmentsOk = accountToPay.Installments
                                             .Except(overdueInstallments)
                                             .Where(i => !i.PaymentDate.HasValue)
                                             .ToList();

                        //valor total pago sem juros e mora
                        var withoutDue = Math.Round(amountDue = accountToPay.Value - accountToPay.Installments
                                                                .Except(overdueInstallments)
                                                                .Except(installmentsOk)
                                                                .Sum(i => i.Value), 2);

                        overdueInstallments.ForEach(o =>
                        {
                            var daysPastDue = (int)DateTime.Now.Subtract(o.MaturityDate).TotalDays;

                            amountDue += Math.Round(amountDue * accountToPay.Penalty / 100, 2);
                            amountDue += Math.Round(amountDue * daysPastDue * accountToPay.DailyInterest / 100, 2);
                        });

                        //parcelas em atraso
                        overdueInstallments.ForEach(i =>
                        {
                            i.PaymentDate = DateTime.Now;
                            i.PaidValue   = Math.Round((amountDue - withoutDue) / overdueInstallments.Count, 2);
                        });

                        installmentsOk.ForEach(i =>
                        {
                            i.PaymentDate = DateTime.Now;
                            i.PaidValue   = Math.Round(i.Value, 2);
                        });

                        amountDue += Math.Round(installmentsOk.Sum(i => i.Value), 2);
                    }

                    else
                    {
                        var installment = accountToPay.Installments.FirstOrDefault(i => i.Id == installment_id) ?? new Installment();

                        var daysPastDue = (int)DateTime.Now.Subtract(installment.MaturityDate).TotalDays;

                        if (daysPastDue > 0)
                        {
                            amountDue += installment.Value * accountToPay.Penalty / 100;
                            amountDue += amountDue * daysPastDue * accountToPay.DailyInterest / 100;
                        }
                        else
                        {
                            amountDue = installment.Value;
                        }
                    }
                }

                var internalBankAccount = paymentType != PaymentType.BankTransfer ?
                                          _internalBankAccountRepository.InternalBankAccountCaixa :
                                          _internalBankAccountRepository.FindActive(internalBankAccount_id ?? 0);

                accountToPay.PaymentType     = paymentType;
                accountToPay.PaymentDate     = DateTime.Now;
                accountToPay.PaidValue       = amountDue;
                accountToPay.PaymentDate     = accountToPay.Installments.All(i => i.PaymentDate.HasValue) ? DateTime.Now : (DateTime?)null;
                internalBankAccount.Balance -= amountDue;

                _accountToPayRepository.Update(accountToPay);
                _internalBankAccountRepository.Update(internalBankAccount);

                this.AddToastMessage("Conta Paga", $"A Conta {accountToPay.Description} foi paga com sucesso", ToastType.Success);
            }
            catch
            {
                this.AddToastMessage("Conta Paga", $"A Conta {accountToPay.Description} foi paga com sucesso", ToastType.Success);
            }

            return(RedirectToAction("Index"));
        }