diff --git a/docs/Usage-Guide.md b/docs/Usage-Guide.md index d8471a1b..226b9bb4 100644 --- a/docs/Usage-Guide.md +++ b/docs/Usage-Guide.md @@ -75,10 +75,12 @@ Not all cart's data can be changed, e.g. custom data (properties like ShoppingCa via API. ### Orders -- Endpoint `api/store/order/list` for retrieving list of orders based on request (supports paging) +- Endpoint `api/store/order/list` for retrieving list of orders for current customer based on request (supports paging) +- Endpoint `api/store/order/admin/list` for retrieving list of orders (for all customers) based on request (supports paging) to display in XbyK administration (supports paging) ### Customers -- Endpoint `api/store/customer/addresses` for retrieving customer's addresses +- Endpoint `api/store/customer/addresses` for retrieving current customer's addresses +- Endpoint `api/store/customer/admin/addresses` for retrieving addresses of specific customer to display in XbyK administration ### Store site - Endpoint `api/store/site/cultures` returns all enabled site cultures diff --git a/examples/DancingGoat-K13Ecommerce/Controllers/TestController.cs b/examples/DancingGoat-K13Ecommerce/Controllers/TestController.cs index 9afa6500..de833ceb 100644 --- a/examples/DancingGoat-K13Ecommerce/Controllers/TestController.cs +++ b/examples/DancingGoat-K13Ecommerce/Controllers/TestController.cs @@ -28,6 +28,6 @@ public async Task TestSetCurrency(string currencyCode) } public async Task TestOrders([FromServices] IOrderService orderService) - => Json(await orderService.GetOrderList(new OrderListRequest { Page = 1, PageSize = 10, OrderBy = "OrderID DESC" })); + => Json(await orderService.GetCurrentCustomerOrderList(new OrderListRequest { Page = 1, PageSize = 10, OrderBy = "OrderID DESC" })); } #endif diff --git a/examples/DancingGoat-K13Ecommerce/Services/CheckoutService.cs b/examples/DancingGoat-K13Ecommerce/Services/CheckoutService.cs index 99f5a220..bd083e87 100644 --- a/examples/DancingGoat-K13Ecommerce/Services/CheckoutService.cs +++ b/examples/DancingGoat-K13Ecommerce/Services/CheckoutService.cs @@ -65,7 +65,7 @@ public async Task PrepareDeliveryDetailsViewModel(Cust customer ??= new CustomerViewModel(await shoppingService.GetCustomerOrCreateFromAuthenticatedUser(cartDetails.Customer)); var addresses = (cartDetails.Customer != null) - ? await customerService.GetCustomerAddresses(cartDetails.Customer.CustomerId) + ? await customerService.GetCurrentCustomerAddresses() : Enumerable.Empty(); var billingAddresses = new SelectList(addresses, nameof(KAddress.AddressId), nameof(KAddress.AddressName)); @@ -114,7 +114,7 @@ public async Task IsStateValid(int countryId, int? stateId) public async Task GetAddress(int customerId, int addressId) => customerId > 0 && addressId > 0 - ? (await customerService.GetCustomerAddresses(customerId)).FirstOrDefault(a => a.AddressId == addressId) + ? (await customerService.GetCurrentCustomerAddresses()).FirstOrDefault(a => a.AddressId == addressId) : null; diff --git a/src/Kentico.Xperience.K13Ecommerce/Customers/CustomerService.cs b/src/Kentico.Xperience.K13Ecommerce/Customers/CustomerService.cs index 725a3881..1674f1dc 100644 --- a/src/Kentico.Xperience.K13Ecommerce/Customers/CustomerService.cs +++ b/src/Kentico.Xperience.K13Ecommerce/Customers/CustomerService.cs @@ -5,6 +5,11 @@ namespace Kentico.Xperience.K13Ecommerce.Customers; internal class CustomerService(IKenticoStoreApiClient apiClient) : ICustomerService { /// - public async Task> GetCustomerAddresses(int customerId) => - await apiClient.CustomerAddressesAsync(customerId); + public async Task> GetCurrentCustomerAddresses() => + await apiClient.CurrentCustomerAddressesAsync(); + + + /// + public async Task> GetAdminCustomerAddresses(int customerId) => + await apiClient.AdminCustomerAddressesAsync(customerId); } diff --git a/src/Kentico.Xperience.K13Ecommerce/Customers/ICustomerService.cs b/src/Kentico.Xperience.K13Ecommerce/Customers/ICustomerService.cs index 2b4ea632..8c857c89 100644 --- a/src/Kentico.Xperience.K13Ecommerce/Customers/ICustomerService.cs +++ b/src/Kentico.Xperience.K13Ecommerce/Customers/ICustomerService.cs @@ -8,9 +8,14 @@ namespace Kentico.Xperience.K13Ecommerce.Customers; public interface ICustomerService { /// - /// Get list of addresses for given customer. + /// Get list of addresses for current customer. + /// + Task> GetCurrentCustomerAddresses(); + + + /// + /// Get list of addresses for customer with specified ID to display in XByK administration. /// - /// Customer ID. - /// - Task> GetCustomerAddresses(int customerId); + /// Customer ID. + Task> GetAdminCustomerAddresses(int customerId); } diff --git a/src/Kentico.Xperience.K13Ecommerce/Orders/IOrderService.cs b/src/Kentico.Xperience.K13Ecommerce/Orders/IOrderService.cs index 8f2ed855..fd397946 100644 --- a/src/Kentico.Xperience.K13Ecommerce/Orders/IOrderService.cs +++ b/src/Kentico.Xperience.K13Ecommerce/Orders/IOrderService.cs @@ -8,9 +8,17 @@ namespace Kentico.Xperience.K13Ecommerce.Orders; public interface IOrderService { /// - /// Get orders based on parameters. + /// Get orders based on parameters for current customer. /// /// Request parameters for order listing. /// Paged list of orders. - Task GetOrderList(OrderListRequest request); + Task GetCurrentCustomerOrderList(OrderListRequest request); + + + /// + /// Get orders based on parameters to display in XbyK administration (for all customers). + /// + /// Request parameters for order listing. + /// Paged list of orders. + Task GetAdminOrderList(OrderListRequest request); } diff --git a/src/Kentico.Xperience.K13Ecommerce/Orders/OrderService.cs b/src/Kentico.Xperience.K13Ecommerce/Orders/OrderService.cs index daf1786a..4680615e 100644 --- a/src/Kentico.Xperience.K13Ecommerce/Orders/OrderService.cs +++ b/src/Kentico.Xperience.K13Ecommerce/Orders/OrderService.cs @@ -5,6 +5,11 @@ namespace Kentico.Xperience.K13Ecommerce.Orders; internal class OrderService(IKenticoStoreApiClient storeApiClient) : IOrderService { /// - public async Task GetOrderList(OrderListRequest request) - => await storeApiClient.OrderListAsync(request.Page, request.PageSize, request.OrderBy); + public async Task GetCurrentCustomerOrderList(OrderListRequest request) + => await storeApiClient.CurrentCustomerOrderListAsync(request.Page, request.PageSize, request.OrderBy); + + + /// + public async Task GetAdminOrderList(OrderListRequest request) + => await storeApiClient.AdminOrderListAsync(request.Page, request.PageSize, request.OrderBy); } diff --git a/src/Kentico.Xperience.K13Ecommerce/StoreApi/swagger.json b/src/Kentico.Xperience.K13Ecommerce/StoreApi/swagger.json index 008536d7..ba166abd 100644 --- a/src/Kentico.Xperience.K13Ecommerce/StoreApi/swagger.json +++ b/src/Kentico.Xperience.K13Ecommerce/StoreApi/swagger.json @@ -136,13 +136,47 @@ "tags": [ "Customer" ], - "summary": "Endpoint for customer addresses.", - "operationId": "CustomerAddresses", + "summary": "Endpoint for current customer addresses.", + "operationId": "CurrentCustomerAddresses", + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/KAddress" + } + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + } + } + }, + "/api/store/customer/admin/addresses": { + "get": { + "tags": [ + "Customer" + ], + "summary": "Endpoint for given customer addresses to display in XbyK administration.", + "operationId": "AdminCustomerAddresses", "parameters": [ { "name": "customerId", "in": "query", - "description": "", + "description": "Customer ID", "required": true, "schema": { "type": "integer", @@ -182,8 +216,66 @@ "tags": [ "Order" ], - "summary": "Endpoint for getting list of orders based on request.", - "operationId": "OrderList", + "summary": "Endpoint for getting list of current customer's orders based on request.", + "operationId": "CurrentCustomerOrderList", + "parameters": [ + { + "name": "Page", + "in": "query", + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "name": "PageSize", + "in": "query", + "schema": { + "maximum": 100, + "minimum": 1, + "type": "integer", + "format": "int32" + } + }, + { + "name": "OrderBy", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/OrderListResponse" + } + } + } + }, + "401": { + "description": "Unauthorized", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ProblemDetails" + } + } + } + } + } + } + }, + "/api/store/order/admin/list": { + "get": { + "tags": [ + "Order" + ], + "summary": "Endpoint for getting list of orders based on request to display in XbyK administration.", + "operationId": "AdminOrderList", "parameters": [ { "name": "Page", diff --git a/src/Kentico.Xperience.StoreApi/Customers/CustomerController.cs b/src/Kentico.Xperience.StoreApi/Customers/CustomerController.cs index 214be365..2880b84f 100644 --- a/src/Kentico.Xperience.StoreApi/Customers/CustomerController.cs +++ b/src/Kentico.Xperience.StoreApi/Customers/CustomerController.cs @@ -23,20 +23,39 @@ public class CustomerController : ControllerBase { private readonly IAddressInfoProvider addressInfoProvider; private readonly IMapper mapper; + private readonly IShoppingService shoppingService; - public CustomerController(IAddressInfoProvider addressInfoProvider, IMapper mapper) + public CustomerController(IAddressInfoProvider addressInfoProvider, IMapper mapper, IShoppingService shoppingService) { this.addressInfoProvider = addressInfoProvider; this.mapper = mapper; + this.shoppingService = shoppingService; } /// - /// Endpoint for customer addresses. + /// Endpoint for current customer addresses. /// - /// /// - [HttpGet("addresses", Name = nameof(CustomerAddresses))] - public ActionResult> CustomerAddresses([FromQuery][Required] int customerId) + [HttpGet("addresses", Name = nameof(CurrentCustomerAddresses))] + public ActionResult> CurrentCustomerAddresses() + { + var cart = shoppingService.GetCurrentShoppingCart(); + if (cart.Customer is null) + { + return Ok(Enumerable.Empty()); + } + var addresses = mapper.Map>(addressInfoProvider.GetByCustomer(cart.Customer.CustomerID)); + return Ok(addresses); + } + + + /// + /// Endpoint for given customer addresses to display in XbyK administration. + /// + /// Customer ID + /// + [HttpGet("admin/addresses", Name = nameof(AdminCustomerAddresses))] + public ActionResult> AdminCustomerAddresses([FromQuery][Required] int customerId) { var addresses = mapper.Map>(addressInfoProvider.GetByCustomer(customerId)); return Ok(addresses); diff --git a/src/Kentico.Xperience.StoreApi/Orders/OrderController.cs b/src/Kentico.Xperience.StoreApi/Orders/OrderController.cs index 138796b5..2a0b78d2 100644 --- a/src/Kentico.Xperience.StoreApi/Orders/OrderController.cs +++ b/src/Kentico.Xperience.StoreApi/Orders/OrderController.cs @@ -24,21 +24,69 @@ public class OrderController : ControllerBase private readonly IOrderInfoProvider orderInfoProvider; private readonly IMapper mapper; private readonly ISiteService siteService; + private readonly IShoppingService shoppingService; - public OrderController(IOrderInfoProvider orderInfoProvider, IMapper mapper, ISiteService siteService) + public OrderController( + IOrderInfoProvider orderInfoProvider, + IMapper mapper, + ISiteService siteService, + IShoppingService shoppingService) { this.orderInfoProvider = orderInfoProvider; this.mapper = mapper; this.siteService = siteService; + this.shoppingService = shoppingService; } /// - /// Endpoint for getting list of orders based on request. + /// Endpoint for getting list of current customer's orders based on request. /// /// /// - [HttpGet("list", Name = nameof(OrderList))] - public async Task> OrderList([FromQuery] OrderListRequest request) + [HttpGet("list", Name = nameof(CurrentCustomerOrderList))] + public async Task> CurrentCustomerOrderList([FromQuery] OrderListRequest request) + { + int page = request.Page > 0 ? request.Page - 1 : 0; + if (string.IsNullOrWhiteSpace(request.OrderBy)) + { + request.OrderBy = $"{nameof(OrderInfo.OrderDate)} DESC"; + } + + var cart = shoppingService.GetCurrentShoppingCart(); + if (cart.Customer is null) + { + return Ok(new OrderListResponse + { + Orders = Enumerable.Empty(), + MaxPage = 1, + Page = 1 + }); + } + + var orderQuery = orderInfoProvider.Get() + .WhereEquals(nameof(OrderInfo.OrderCustomerID), cart.Customer.CustomerID) + .OnSite(siteService.CurrentSite.SiteID) + .Page(page, request.PageSize) + .OrderBy(request.OrderBy); + + var orders = mapper.Map>(await orderQuery.GetEnumerableTypedResultAsync()); + + return Ok(new OrderListResponse + { + Orders = orders, + Page = page + 1, + MaxPage = (orderQuery.TotalRecords / request.PageSize) + 1 + }); + } + + + /// + /// Endpoint for getting list of orders based on request to display in XbyK administration. + /// + /// + /// + [HttpGet("admin/list", Name = nameof(AdminOrderList))] + public async Task> AdminOrderList([FromQuery] OrderListRequest request) { int page = request.Page > 0 ? request.Page - 1 : 0; if (string.IsNullOrWhiteSpace(request.OrderBy))