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();
}
}
}
}