public InternalUpgradeEmailViewModel(User user, ChangeContractViewModel upgradeData) : base(user) { this.Upgrade = upgradeData; }
public ActionResult SetAccountPaymentInfo(ChangeContractViewModel viewModel) { var mainContract = dbPractice.AccountContract; string planId; Bus.ContractToPlan.TryGetValue(dbPractice.AccountContract.SYS_ContractType.UrlIdentifier, out planId); // 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.IsPartialBillingInfo) { if (planId == "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 = planId; viewModel.CurrentDoctorsCount = 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 //}); // changing the partial contract, to match the new billing settings // Note: the contract will still be partial, and only when the user pays // the partial flag will be removed and the StartDate will be defined. mainContract.CustomText = viewModel.WholeUserAgreement; mainContract.DoctorsLimit = viewModel.DoctorCount; mainContract.BillingAmount = finalValueWithoutDiscount; mainContract.BillingDiscountAmount = finalValueWithoutDiscount - viewModel.FinalValue; mainContract.BillingDueDay = viewModel.InvoceDueDayOfMonth; mainContract.BillingPeriodCount = null; mainContract.BillingPeriodSize = periodSizesDic[viewModel.PaymentModelName]; mainContract.BillingPeriodType = "M"; mainContract.BillingPaymentMethod = "PayPal Invoice"; this.db.SaveChanges(); // Creating the first billing var utcNow = this.GetUtcNow(); var localNow = PracticeController.ConvertToLocalDateTime(dbPractice, utcNow); Billing billing = null; var idSet = string.Format( "CEREB.{1}{2}.{0}", localNow.Year, mainContract.BillingPeriodSize, mainContract.BillingPeriodType); billing = db.Billings.SingleOrDefault(b => b.PracticeId == dbPractice.Id && b.MainAccountContractId == dbPractice.ActiveAccountContractId && b.ReferenceDate == null); if (billing == null) { billing = new Billing { PracticeId = dbPractice.Id, AfterDueMonthlyTax = 1.00m, // 1% AfterDueTax = 2.00m, // 2% IssuanceDate = utcNow, MainAmount = (decimal)mainContract.BillingAmount, MainDiscount = (decimal)mainContract.BillingDiscountAmount, DueDate = PracticeController.ConvertToUtcDateTime(dbPractice, localNow.AddDays(10)), IdentitySetName = idSet, IdentitySetNumber = db.Billings.Count(b => b.PracticeId == dbPractice.Id && b.IdentitySetName == idSet) + 1, ReferenceDate = PracticeController.ConvertToUtcDateTime(dbPractice, null), ReferenceDateEnd = PracticeController.ConvertToUtcDateTime(dbPractice, null), MainAccountContractId = dbPractice.ActiveAccountContractId.Value, }; db.Billings.AddObject(billing); } this.db.SaveChanges(); // Using PayPal API to start an Express Checkout operation, and then redirecting user to PayPal. var operation = new PayPalSetExpressCheckoutOperation(); ConfigAccountController.FillOperationDetails(operation, dbPractice, mainContract, billing); var practice = this.dbPractice.UrlIdentifier; operation.PaymentRequests[0].NotifyUrl = UseExternalIpIfDebug(this.Url.ActionAbsolute("PayPalNotification", new { practice })); var opResult = this.SetExpressCheckout(operation, "PayPalConfirm", "PayPalCancel", new { practice }); if (opResult.Errors != null && opResult.Errors.Any()) return new StatusCodeResult(HttpStatusCode.InternalServerError, opResult.Errors[0].LongMessage); return this.RedirectToCheckout(opResult); } return this.View(viewModel); } } return this.HttpNotFound(); }
public ActionResult SetAccountPaymentInfo() { var contract = dbPractice.AccountContract; var periodTypesDic = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) { { "1M", "MONTH" }, { "3M", "3-MONTHS" }, { "6M", "6-MONTHS" }, { "12M", "12-MONTHS" }, }; string paymentModelName; periodTypesDic.TryGetValue(string.Format("{0}{1}", contract.BillingPeriodSize, contract.BillingPeriodType), out paymentModelName); var viewModel = new ChangeContractViewModel { ContractUrlId = "ProfessionalPlan", CurrentDoctorsCount = dbPractice.Users.Count(x => x.DoctorId != null), DoctorCount = 1, InvoceDueDayOfMonth = PracticeController.ConvertToLocalDateTime(dbPractice, this.GetUtcNow()).Day, PaymentModelName = paymentModelName, }; return this.View(viewModel); }
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(); }
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(); }