44using Microsoft . AspNetCore . Authorization ;
55using Microsoft . AspNetCore . Mvc ;
66using Microsoft . AspNetCore . Mvc . Rendering ;
7+ using Microsoft . EntityFrameworkCore ;
78using Newtonsoft . Json ;
89using SimplCommerce . Infrastructure . Data ;
10+ using SimplCommerce . Module . Checkouts . Areas . Checkouts . ViewModels ;
11+ using SimplCommerce . Module . Checkouts . Models ;
12+ using SimplCommerce . Module . Checkouts . Services ;
913using SimplCommerce . Module . Core . Extensions ;
1014using SimplCommerce . Module . Core . Models ;
11- using SimplCommerce . Module . Orders . Areas . Orders . ViewModels ;
12- using SimplCommerce . Module . Orders . Services ;
13- using SimplCommerce . Module . ShippingPrices . Services ;
1415using SimplCommerce . Module . ShoppingCart . Models ;
1516using SimplCommerce . Module . ShoppingCart . Services ;
1617
17- namespace SimplCommerce . Module . Orders . Areas . Orders . Controllers
18+ namespace SimplCommerce . Module . Checkouts . Areas . Checkouts . Controllers
1819{
19- [ Area ( "Orders " ) ]
20+ [ Area ( "Checkouts " ) ]
2021 [ Route ( "checkout" ) ]
2122 [ Authorize ]
2223 [ ApiExplorerSettings ( IgnoreApi = true ) ]
2324 public class CheckoutController : Controller
2425 {
25- private readonly IOrderService _orderService ;
2626 private readonly IRepositoryWithTypedId < Country , string > _countryRepository ;
2727 private readonly IRepository < StateOrProvince > _stateOrProvinceRepository ;
2828 private readonly IRepository < UserAddress > _userAddressRepository ;
29- private readonly IShippingPriceService _shippingPriceService ;
30- private readonly ICartService _cartService ;
29+ private readonly ICheckoutService _checkoutService ;
30+ private readonly IRepository < CartItem > _cartItemRepository ;
3131 private readonly IWorkContext _workContext ;
32- private readonly IRepository < Cart > _cartRepository ;
32+ private readonly IRepositoryWithTypedId < Checkout , Guid > _checkoutRepository ;
3333
3434 public CheckoutController (
3535 IRepository < StateOrProvince > stateOrProvinceRepository ,
3636 IRepositoryWithTypedId < Country , string > countryRepository ,
3737 IRepository < UserAddress > userAddressRepository ,
38- IShippingPriceService shippingPriceService ,
39- IOrderService orderService ,
40- ICartService cartService ,
38+ ICheckoutService checkout ,
39+ IRepository < CartItem > cartItemRepository ,
4140 IWorkContext workContext ,
42- IRepository < Cart > cartRepository )
41+ IRepositoryWithTypedId < Checkout , Guid > checkoutRepository )
4342 {
4443 _stateOrProvinceRepository = stateOrProvinceRepository ;
4544 _countryRepository = countryRepository ;
4645 _userAddressRepository = userAddressRepository ;
47- _shippingPriceService = shippingPriceService ;
48- _orderService = orderService ;
49- _cartService = cartService ;
46+ _checkoutService = checkout ;
47+ _cartItemRepository = cartItemRepository ;
5048 _workContext = workContext ;
51- _cartRepository = cartRepository ;
49+ _checkoutRepository = checkoutRepository ;
5250 }
5351
54- [ HttpGet ( "shipping" ) ]
55- public async Task < IActionResult > Shipping ( )
52+ //TODO: Consider to allow customer select a subset of products in cart and pass to this endpoint
53+ [ HttpPost ]
54+ [ AllowAnonymous ]
55+ public async Task < IActionResult > Create ( CheckoutFormVm checkoutFormVm )
56+ {
57+ if ( ! HttpContext . User . Identity . IsAuthenticated )
58+ {
59+ return Redirect ( "/login?ReturnUrl=%2Fcart" ) ;
60+ }
61+ var currentUser = await _workContext . GetCurrentUser ( ) ;
62+ var cartItems = await _cartItemRepository . Query ( ) . Where ( x => x . CustomerId == currentUser . Id ) . ToListAsync ( ) ;
63+ if ( ! cartItems . Any ( ) )
64+ {
65+ return NotFound ( ) ;
66+ }
67+
68+ var cartItemToCheckouts = cartItems . Select ( x => new CartItemToCheckoutVm
69+ {
70+ ProductId = x . ProductId ,
71+ Quantity = x . Quantity
72+ } ) . ToList ( ) ;
73+
74+ var checkout = await _checkoutService . Create ( currentUser . Id , currentUser . Id , cartItemToCheckouts , checkoutFormVm . CouponCode ) ;
75+
76+ return Redirect ( $ "~/checkout/{ checkout . Id } /shipping") ;
77+ }
78+
79+ [ HttpGet ( "{checkoutId}/shipping" ) ]
80+ public async Task < IActionResult > Shipping ( Guid checkoutId )
5681 {
5782 var currentUser = await _workContext . GetCurrentUser ( ) ;
58- var cart = await _cartService . GetActiveCartDetails ( currentUser . Id ) ;
59- if ( cart == null || ! cart . Items . Any ( ) )
83+ var checkout = await _checkoutRepository . Query ( ) . FirstOrDefaultAsync ( x => x . Id == checkoutId ) ;
84+ if ( checkout == null )
6085 {
61- return Redirect ( "~/" ) ;
86+ return NotFound ( ) ;
87+ }
88+
89+ if ( checkout . CreatedBy != currentUser )
90+ {
91+ return Forbid ( ) ;
6292 }
6393
6494 var model = new DeliveryInformationVm ( ) ;
95+ model . CheckoutId = checkoutId ;
6596
6697 PopulateShippingForm ( model , currentUser ) ;
6798
6899 return View ( model ) ;
69100 }
70101
71- [ HttpPost ( "shipping" ) ]
72- public async Task < IActionResult > Shipping ( DeliveryInformationVm model )
102+ [ HttpPost ( "{checkoutId}/ shipping" ) ]
103+ public async Task < IActionResult > Shipping ( Guid checkoutId , DeliveryInformationVm model )
73104 {
74105 var currentUser = await _workContext . GetCurrentUser ( ) ;
75- // TODO Handle error messages
106+ var checkout = await _checkoutRepository . Query ( ) . FirstOrDefaultAsync ( x => x . Id == checkoutId ) ;
107+ if ( checkout == null )
108+ {
109+ return NotFound ( ) ;
110+ }
111+
112+ if ( checkout . CreatedBy != currentUser )
113+ {
114+ return Forbid ( ) ;
115+ }
116+
76117 if ( ( ! model . NewAddressForm . IsValid ( ) && model . ShippingAddressId == 0 ) ||
77118 ( ! model . NewBillingAddressForm . IsValid ( ) && ! model . UseShippingAddressAsBillingAddress && model . BillingAddressId == 0 ) )
78119 {
79120 PopulateShippingForm ( model , currentUser ) ;
80121 return View ( model ) ;
81122 }
82123
83- var cart = await _cartService . GetActiveCart ( currentUser . Id ) ;
124+ checkout . ShippingData = JsonConvert . SerializeObject ( model ) ;
125+ await _checkoutRepository . SaveChangesAsync ( ) ;
126+ return Redirect ( $ "~/checkout/{ checkoutId } /payment") ;
127+ }
84128
85- if ( cart == null )
129+ [ HttpPost ( "{checkoutId}/update-tax-and-shipping-prices" ) ]
130+ public async Task < IActionResult > UpdateTaxAndShippingPrices ( Guid checkoutId , [ FromBody ] TaxAndShippingPriceRequestVm model )
131+ {
132+ var currentUser = await _workContext . GetCurrentUser ( ) ;
133+ var checkout = await _checkoutRepository . Query ( ) . FirstOrDefaultAsync ( x => x . Id == checkoutId ) ;
134+ if ( checkout == null )
86135 {
87- throw new ApplicationException ( $ "Cart of user { currentUser . Id } cannot be found" ) ;
136+ return NotFound ( ) ;
88137 }
89138
90- cart . ShippingData = JsonConvert . SerializeObject ( model ) ;
91- await _cartRepository . SaveChangesAsync ( ) ;
92- return Redirect ( "~/checkout/payment" ) ;
93- }
139+ if ( checkout . CreatedBy != currentUser )
140+ {
141+ return Forbid ( ) ;
142+ }
94143
95- [ HttpPost ( "update-tax-and-shipping-prices" ) ]
96- public async Task < IActionResult > UpdateTaxAndShippingPrices ( [ FromBody ] TaxAndShippingPriceRequestVm model )
97- {
98- var currentUser = await _workContext . GetCurrentUser ( ) ;
99- var cart = await _cartService . GetActiveCart ( currentUser . Id ) ;
100- var orderTaxAndShippingPrice = await _orderService . UpdateTaxAndShippingPrices ( cart . Id , model ) ;
144+ var orderTaxAndShippingPrice = await _checkoutService . UpdateTaxAndShippingPrices ( checkoutId , model ) ;
101145
102146 return Ok ( orderTaxAndShippingPrice ) ;
103147 }
@@ -114,20 +158,6 @@ public IActionResult Error(long orderId)
114158 return View ( orderId ) ;
115159 }
116160
117- [ HttpPost ( "cancel" ) ]
118- public async Task < IActionResult > Cancel ( )
119- {
120- var currentUser = await _workContext . GetCurrentUser ( ) ;
121- var cart = await _cartService . GetActiveCart ( currentUser . Id ) ;
122- if ( cart != null && cart . LockedOnCheckout )
123- {
124- cart . LockedOnCheckout = false ;
125- await _cartRepository . SaveChangesAsync ( ) ;
126- }
127-
128- return Redirect ( "~/" ) ;
129- }
130-
131161 private void PopulateShippingForm ( DeliveryInformationVm model , User currentUser )
132162 {
133163 model . ExistingShippingAddresses = _userAddressRepository
0 commit comments