public ActionResult Upgrade(string id) { var mainContract = this.DbPractice.AccountContract; // because each plan has a different set of features, // this is going to be used by the view, to define the partial page that will be shown this.ViewBag.CurrentContractName = mainContract.SYS_ContractType.UrlIdentifier; if (mainContract.SYS_ContractType.IsTrial) { var viewModel = new ChangeContractViewModel { ContractUrlId = id, CurrentDoctorsCount = this.DbPractice.Users.Count(x => x.DoctorId != null), }; return(View(viewModel)); } return(this.HttpNotFound()); }
public ActionResult Upgrade(string id, ChangeContractViewModel viewModel) { var mainContract = this.DbPractice.AccountContract; // because each plan has a different set of features, // this is going to be used by the view, to define the partial page that will be shown this.ViewBag.CurrentContractName = mainContract.SYS_ContractType.UrlIdentifier; if (!viewModel.AcceptedByUser) { this.ModelState.AddModelError( () => viewModel.AcceptedByUser, "A caixa de checagem de aceitação do contrato precisa ser marcada para concluir o processo."); } if (mainContract.SYS_ContractType.IsTrial) { if (id == "ProfessionalPlan") { // calculating values to see if the submited values are correct var unitPrice = Bus.Pro.DOCTOR_PRICE; Func <double, double, double> integ = (x, n) => Math.Pow(n, x) / Math.Log(n); Func <double, double, double> integ0to = (x, n) => (integ(x, n) - integ(0, n)); Func <double, double> priceFactor = x => x * (1.0 - 0.1 * integ0to((x - 1) / 3.0, 0.75)); Func <double, double> price = (extraDoctors) => Math.Round(priceFactor(extraDoctors) * unitPrice * 100) / 100; var dicValues = new Dictionary <string, decimal>(StringComparer.InvariantCultureIgnoreCase) { { "MONTH", Bus.Pro.PRICE_MONTH }, { "3-MONTHS", Bus.Pro.PRICE_QUARTER }, { "6-MONTHS", Bus.Pro.PRICE_SEMESTER }, { "12-MONTHS", Bus.Pro.PRICE_YEAR }, }; var dicDiscount = new Dictionary <string, decimal>(StringComparer.InvariantCultureIgnoreCase) { { "MONTH", 0 }, { "3-MONTHS", Bus.Pro.DISCOUNT_QUARTER }, { "6-MONTHS", Bus.Pro.DISCOUNT_SEMESTER }, { "12-MONTHS", Bus.Pro.DISCOUNT_YEAR }, }; var periodSizesDic = new Dictionary <string, int>(StringComparer.InvariantCultureIgnoreCase) { { "MONTH", 1 }, { "3-MONTHS", 3 }, { "6-MONTHS", 6 }, { "12-MONTHS", 12 }, }; var dicount = 1m - dicDiscount[viewModel.PaymentModelName] / 100m; var accountValue = dicValues[viewModel.PaymentModelName]; var doctorsValueWithoutDiscount = (decimal)Math.Round(price(viewModel.DoctorCount - 1)) * periodSizesDic[viewModel.PaymentModelName]; var finalValue = accountValue + doctorsValueWithoutDiscount * dicount; var finalValueWithoutDiscount = Bus.Pro.PRICE_MONTH * periodSizesDic[viewModel.PaymentModelName] + doctorsValueWithoutDiscount; // tolerance of R$ 0.10 in the final value... maybe the browser could not make the calculations correctly, // but we must use that value, since it is the value that the user saw if (Math.Abs(finalValue - viewModel.FinalValue) >= 0.10m) { this.ModelState.AddModelError( () => viewModel.FinalValue, "Seu browser apresentou um defeito no cálculo do valor final. Não foi possível processar sua requisição de upgrade."); } viewModel.ContractUrlId = id; viewModel.CurrentDoctorsCount = this.DbPractice.Users.Count(x => x.DoctorId != null); if (this.ModelState.IsValid) { // sending e-mail to [email protected] // to remember us to send the payment request var emailViewModel = new InternalUpgradeEmailViewModel(this.DbUser, viewModel); var toAddress = new MailAddress("*****@*****.**", this.DbUser.Person.FullName); var mailMessage = this.CreateEmailMessagePartial("InternalUpgradeEmail", toAddress, emailViewModel); this.SendEmailAsync(mailMessage).ContinueWith(t => { // observing exception so that it is not raised var ex = t.Exception; // todo: should do something when e-mail is not sent // 1) use a schedule table to save a serialized e-mail, and then send it later // 2) log a warning message somewhere stating that this e-mail was not sent // send e-mail again is not an option, SendEmailAsync already tries a lot of times }); var utcNow = this.GetUtcNow(); // terminating the previous contract var currentContract = this.DbPractice.AccountContract; currentContract.EndDate = utcNow; // setting up the professional contract this.DbPractice.AccountContract = new AccountContract { PracticeId = this.DbPractice.Id, IssuanceDate = this.GetUtcNow(), ContractTypeId = (int)ContractTypes.ProfessionalContract, IsTrial = false, StartDate = utcNow, // contract starts NOW... without delays EndDate = null, // this is an unlimited contract CustomText = viewModel.WholeUserAgreement, DoctorsLimit = viewModel.DoctorCount, PatientsLimit = null, // there is no patients limit anymore // billing informations BillingAmount = viewModel.FinalValue, BillingDiscountAmount = finalValueWithoutDiscount - viewModel.FinalValue, BillingDueDay = viewModel.InvoceDueDayOfMonth, BillingPeriodCount = null, // no limit... this contract is valid forever BillingPeriodSize = periodSizesDic[viewModel.PaymentModelName], BillingPeriodType = "M", // same as date-time formatter 'd' for days, 'M' for months, 'y' for years BillingPaymentMethod = "PayPal Invoice", }; this.db.SaveChanges(); return(this.RedirectToAction("UpgradeDone")); } return(this.View(viewModel)); } } return(this.HttpNotFound()); }