src/Modules/SimplCommerce.Module.Orders/Areas/Orders/Controllers/CheckoutController.cs (158 lines of code) (raw):

using System; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using Newtonsoft.Json; using SimplCommerce.Infrastructure.Data; using SimplCommerce.Module.Core.Extensions; using SimplCommerce.Module.Core.Models; using SimplCommerce.Module.Orders.Areas.Orders.ViewModels; using SimplCommerce.Module.Orders.Services; using SimplCommerce.Module.ShippingPrices.Services; using SimplCommerce.Module.ShoppingCart.Models; using SimplCommerce.Module.ShoppingCart.Services; namespace SimplCommerce.Module.Orders.Areas.Orders.Controllers { [Area("Orders")] [Route("checkout")] [Authorize] [ApiExplorerSettings(IgnoreApi = true)] public class CheckoutController : Controller { private readonly IOrderService _orderService; private readonly IRepositoryWithTypedId<Country, string> _countryRepository; private readonly IRepository<StateOrProvince> _stateOrProvinceRepository; private readonly IRepository<UserAddress> _userAddressRepository; private readonly IShippingPriceService _shippingPriceService; private readonly ICartService _cartService; private readonly IWorkContext _workContext; private readonly IRepository<Cart> _cartRepository; public CheckoutController( IRepository<StateOrProvince> stateOrProvinceRepository, IRepositoryWithTypedId<Country, string> countryRepository, IRepository<UserAddress> userAddressRepository, IShippingPriceService shippingPriceService, IOrderService orderService, ICartService cartService, IWorkContext workContext, IRepository<Cart> cartRepository) { _stateOrProvinceRepository = stateOrProvinceRepository; _countryRepository = countryRepository; _userAddressRepository = userAddressRepository; _shippingPriceService = shippingPriceService; _orderService = orderService; _cartService = cartService; _workContext = workContext; _cartRepository = cartRepository; } [HttpGet("shipping")] public async Task<IActionResult> Shipping() { var currentUser = await _workContext.GetCurrentUser(); var cart = await _cartService.GetActiveCartDetails(currentUser.Id); if(cart == null || !cart.Items.Any()) { return Redirect("~/"); } var model = new DeliveryInformationVm(); PopulateShippingForm(model, currentUser); return View(model); } [HttpPost("shipping")] public async Task<IActionResult> Shipping(DeliveryInformationVm model) { var currentUser = await _workContext.GetCurrentUser(); // TODO Handle error messages if ((!model.NewAddressForm.IsValid() && model.ShippingAddressId == 0) || (!model.NewBillingAddressForm.IsValid() && !model.UseShippingAddressAsBillingAddress && model.BillingAddressId == 0)) { PopulateShippingForm(model, currentUser); return View(model); } var cart = await _cartService.GetActiveCart(currentUser.Id); if (cart == null) { throw new ApplicationException($"Cart of user {currentUser.Id} cannot be found"); } cart.ShippingData = JsonConvert.SerializeObject(model); await _cartRepository.SaveChangesAsync(); return Redirect("~/checkout/payment"); } [HttpPost("update-tax-and-shipping-prices")] public async Task<IActionResult> UpdateTaxAndShippingPrices([FromBody] TaxAndShippingPriceRequestVm model) { var currentUser = await _workContext.GetCurrentUser(); var cart = await _cartService.GetActiveCart(currentUser.Id); var orderTaxAndShippingPrice = await _orderService.UpdateTaxAndShippingPrices(cart.Id, model); return Ok(orderTaxAndShippingPrice); } [HttpGet("success")] public IActionResult Success(long orderId) { return View(orderId); } [HttpGet("error")] public IActionResult Error(long orderId) { return View(orderId); } [HttpPost("cancel")] public async Task<IActionResult> Cancel() { var currentUser = await _workContext.GetCurrentUser(); var cart = await _cartService.GetActiveCart(currentUser.Id); if(cart != null && cart.LockedOnCheckout) { cart.LockedOnCheckout = false; await _cartRepository.SaveChangesAsync(); } return Redirect("~/"); } private void PopulateShippingForm(DeliveryInformationVm model, User currentUser) { model.ExistingShippingAddresses = _userAddressRepository .Query() .Where(x => (x.AddressType == AddressType.Shipping) && (x.UserId == currentUser.Id)) .Select(x => new ShippingAddressVm { UserAddressId = x.Id, ContactName = x.Address.ContactName, Phone = x.Address.Phone, AddressLine1 = x.Address.AddressLine1, CityName = x.Address.City, ZipCode = x.Address.ZipCode, DistrictName = x.Address.District.Name, StateOrProvinceName = x.Address.StateOrProvince.Name, CountryName = x.Address.Country.Name, IsCityEnabled = x.Address.Country.IsCityEnabled, IsZipCodeEnabled = x.Address.Country.IsZipCodeEnabled, IsDistrictEnabled = x.Address.Country.IsDistrictEnabled }).ToList(); model.ShippingAddressId = currentUser.DefaultShippingAddressId ?? 0; model.UseShippingAddressAsBillingAddress = true; model.NewAddressForm.ShipableContries = _countryRepository.Query() .Where(x => x.IsShippingEnabled) .OrderBy(x => x.Name) .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }).ToList(); if (model.NewAddressForm.ShipableContries.Count == 1) { var onlyShipableCountryId = model.NewAddressForm.ShipableContries.First().Value; model.NewAddressForm.StateOrProvinces = _stateOrProvinceRepository .Query() .Where(x => x.CountryId == onlyShipableCountryId) .OrderBy(x => x.Name) .Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }).ToList(); } } } }