frontend fully integreated with the backend
This commit is contained in:
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Brand;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/brands")]
|
||||
[Authorize]
|
||||
public class BrandController(BrandService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "items.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "items.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class BrandController(BrandService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "items.create")]
|
||||
public async Task<IActionResult> Create(CreateBrandRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class BrandController(BrandService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "items.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateBrandRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class BrandController(BrandService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "items.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Category;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class CategoryController(CategoryService service) : ControllerBase
|
||||
{
|
||||
[HttpGet("api/categories")]
|
||||
[Authorize(Policy = "categories.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("api/categories/{id:guid}")]
|
||||
[Authorize(Policy = "categories.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -21,7 +17,6 @@ public class CategoryController(CategoryService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost("api/categories")]
|
||||
[Authorize(Policy = "categories.create")]
|
||||
public async Task<IActionResult> Create(CreateCategoryRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -29,7 +24,6 @@ public class CategoryController(CategoryService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("api/categories/{id:guid}")]
|
||||
[Authorize(Policy = "categories.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateCategoryRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -37,7 +31,6 @@ public class CategoryController(CategoryService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("api/categories/{id:guid}")]
|
||||
[Authorize(Policy = "categories.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
@@ -45,7 +38,6 @@ public class CategoryController(CategoryService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost("api/categories/{categoryId:guid}/subcategories")]
|
||||
[Authorize(Policy = "categories.create")]
|
||||
public async Task<IActionResult> CreateSubCategory(Guid categoryId, CreateSubCategoryRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateSubCategoryAsync(categoryId, request, ct);
|
||||
@@ -53,7 +45,6 @@ public class CategoryController(CategoryService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("api/subcategories/{id:guid}")]
|
||||
[Authorize(Policy = "categories.update")]
|
||||
public async Task<IActionResult> UpdateSubCategory(Guid id, UpdateSubCategoryRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateSubCategoryAsync(id, request, ct);
|
||||
@@ -61,7 +52,6 @@ public class CategoryController(CategoryService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("api/subcategories/{id:guid}")]
|
||||
[Authorize(Policy = "categories.delete")]
|
||||
public async Task<IActionResult> DeleteSubCategory(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteSubCategoryAsync(id, ct);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Claims;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ClaimController(ClaimService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet("api/claims/{id:guid}")]
|
||||
@@ -27,7 +25,6 @@ public class ClaimController(ClaimService service, ICurrentUserService currentUs
|
||||
}
|
||||
|
||||
[HttpPost("api/claims/{id:guid}/settle")]
|
||||
[Authorize(Policy = "claims.settle")]
|
||||
public async Task<IActionResult> Settle(Guid id, SettleClaimRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.DeliveryRide;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("api")]
|
||||
public class DeliveryTaskController(DeliveryTaskService service) : ControllerBase
|
||||
{
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.DriverComplianceConfig;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/driver-compliance-config")]
|
||||
[Authorize]
|
||||
public class DriverComplianceConfigController(DriverComplianceConfigService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "compliance.manage")]
|
||||
public async Task<IActionResult> Get()
|
||||
{
|
||||
var result = await service.GetAsync();
|
||||
@@ -18,7 +15,6 @@ public class DriverComplianceConfigController(DriverComplianceConfigService serv
|
||||
}
|
||||
|
||||
[HttpPut]
|
||||
[Authorize(Policy = "compliance.manage")]
|
||||
public async Task<IActionResult> Upsert(UpdateDriverComplianceConfigRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.DriverProfile;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/driver-profiles")]
|
||||
[Authorize]
|
||||
public class DriverProfileController(DriverProfileService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "driver_profiles.view")]
|
||||
public async Task<IActionResult> GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 20)
|
||||
{
|
||||
var result = await service.GetAllAsync(page, pageSize);
|
||||
@@ -17,7 +14,6 @@ public class DriverProfileController(DriverProfileService service) : ControllerB
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "driver_profiles.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -25,7 +21,6 @@ public class DriverProfileController(DriverProfileService service) : ControllerB
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "driver_profiles.create")]
|
||||
public async Task<IActionResult> Create(CreateDriverProfileRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -33,7 +28,6 @@ public class DriverProfileController(DriverProfileService service) : ControllerB
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "driver_profiles.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateDriverProfileRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -41,7 +35,6 @@ public class DriverProfileController(DriverProfileService service) : ControllerB
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "driver_profiles.deactivate")]
|
||||
public async Task<IActionResult> Deactivate(Guid id, CancellationToken ct)
|
||||
{
|
||||
var success = await service.DeactivateAsync(id, ct);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Grn;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class GrnController(GrnService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet("api/goods-receipts/{id:guid}")]
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Item;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/items")]
|
||||
[Authorize]
|
||||
public class ItemController(ItemService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "items.view")]
|
||||
public async Task<IActionResult> GetAll(
|
||||
[FromQuery] Guid? categoryId,
|
||||
[FromQuery] Guid? subCategoryId,
|
||||
@@ -17,7 +14,6 @@ public class ItemController(ItemService service) : ControllerBase
|
||||
Ok(await service.GetAllAsync(categoryId, subCategoryId, brandId));
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "items.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -25,7 +21,6 @@ public class ItemController(ItemService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "items.create")]
|
||||
public async Task<IActionResult> Create(CreateItemRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -40,7 +35,6 @@ public class ItemController(ItemService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "items.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateItemRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -48,7 +42,6 @@ public class ItemController(ItemService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "items.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
@@ -56,7 +49,6 @@ public class ItemController(ItemService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/uom-conversions")]
|
||||
[Authorize(Policy = "items.update")]
|
||||
public async Task<IActionResult> ReplaceConversions(Guid id, ReplaceConversionsRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.ReplaceConversionsAsync(id, request, ct);
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
using Distribution.Models;
|
||||
using Distribution.Models;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.LoadingEvent;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/loading-sheets")]
|
||||
[Authorize]
|
||||
public class LoadingSheetController(LoadingSheetService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "loading.view")]
|
||||
public async Task<IActionResult> GetAll(
|
||||
[FromQuery] Guid? rideId,
|
||||
[FromQuery] LoadingSheetStatus? status,
|
||||
@@ -23,7 +20,6 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "loading.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -31,7 +27,6 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "loading.dispatch")]
|
||||
public async Task<IActionResult> Create(CreateLoadingSheetRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -44,7 +39,6 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/items")]
|
||||
[Authorize(Policy = "loading.dispatch")]
|
||||
public async Task<IActionResult> SetItems(Guid id, SetItemsRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -57,7 +51,6 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/confirm-dispatch")]
|
||||
[Authorize(Policy = "loading.dispatch")]
|
||||
public async Task<IActionResult> ConfirmDispatch(Guid id, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
@@ -71,7 +64,6 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/receipt-items")]
|
||||
[Authorize(Policy = "loading.receive")]
|
||||
public async Task<IActionResult> SetReceiptItems(Guid id, SetReceiptItemsRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -84,7 +76,6 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/confirm-receipt")]
|
||||
[Authorize(Policy = "loading.receive")]
|
||||
public async Task<IActionResult> ConfirmReceipt(Guid id, ConfirmReceiptRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
@@ -98,7 +89,6 @@ public class LoadingSheetController(LoadingSheetService service, ICurrentUserSer
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/resolve")]
|
||||
[Authorize(Policy = "loading.resolve")]
|
||||
public async Task<IActionResult> Resolve(Guid id, ResolveDiscrepancyRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Order;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/orders")]
|
||||
[Authorize]
|
||||
public class OrderController(OrderService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "orders.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "orders.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class OrderController(OrderService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("store/{storeId:guid}")]
|
||||
[Authorize(Policy = "orders.view")]
|
||||
public async Task<IActionResult> GetByStore(Guid storeId)
|
||||
{
|
||||
var result = await service.GetByStoreIdAsync(storeId);
|
||||
@@ -30,7 +25,6 @@ public class OrderController(OrderService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "orders.create")]
|
||||
public async Task<IActionResult> Create(CreateOrderRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -42,7 +36,6 @@ public class OrderController(OrderService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "orders.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateOrderRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -54,7 +47,6 @@ public class OrderController(OrderService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "orders.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Payment;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
[Route("api/sales/{saleId:guid}/payments")]
|
||||
public class PaymentController(PaymentService service) : ControllerBase
|
||||
{
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.PriceList;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/price-lists")]
|
||||
[Authorize]
|
||||
public class PriceListController(PriceListService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Po;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/purchase-orders")]
|
||||
[Authorize]
|
||||
public class PoController(PoService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.PurchaseReturn;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class PurchaseReturnController(PurchaseReturnService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet("api/purchase-returns/{id:guid}")]
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Region;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/regions")]
|
||||
[Authorize]
|
||||
public class RegionController(RegionService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "regions.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "regions.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class RegionController(RegionService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "regions.create")]
|
||||
public async Task<IActionResult> Create(CreateRegionRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class RegionController(RegionService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "regions.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateRegionRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class RegionController(RegionService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "regions.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Returns;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class ReturnController(ReturnService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet("api/returns/{id:guid}")]
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Ride;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/rides")]
|
||||
[Authorize]
|
||||
public class RideController(RideService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "rides.view")]
|
||||
public async Task<IActionResult> GetAll(
|
||||
[FromQuery] RideStatus? status,
|
||||
[FromQuery] RideType? type,
|
||||
@@ -25,7 +22,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "rides.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -33,7 +29,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "rides.create")]
|
||||
public async Task<IActionResult> Create(CreateRideRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -41,7 +36,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/driver")]
|
||||
[Authorize(Policy = "rides.manage")]
|
||||
public async Task<IActionResult> AssignDriver(Guid id, AssignRideDriverRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -54,7 +48,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/open")]
|
||||
[Authorize(Policy = "rides.manage")]
|
||||
public async Task<IActionResult> Open(Guid id, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -67,7 +60,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/activate")]
|
||||
[Authorize(Policy = "rides.manage")]
|
||||
public async Task<IActionResult> Activate(Guid id, ActivateRideRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -80,7 +72,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/close")]
|
||||
[Authorize(Policy = "rides.manage")]
|
||||
public async Task<IActionResult> Close(Guid id, CloseRideRequest request, CancellationToken ct)
|
||||
{
|
||||
try
|
||||
@@ -93,7 +84,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPost("{id:guid}/cancel-request")]
|
||||
[Authorize(Policy = "rides.cancel.request")]
|
||||
public async Task<IActionResult> RaiseCancelRequest(Guid id, RaiseCancelRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
@@ -107,7 +97,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpGet("cancel-requests")]
|
||||
[Authorize(Policy = "rides.view")]
|
||||
public async Task<IActionResult> GetCancelRequests(
|
||||
[FromQuery] CancelRequestStatus? status,
|
||||
[FromQuery] int page = 1,
|
||||
@@ -118,7 +107,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPost("cancel-requests/{id:guid}/approve")]
|
||||
[Authorize(Policy = "rides.cancel.approve")]
|
||||
public async Task<IActionResult> ApproveCancelRequest(Guid id, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
@@ -132,7 +120,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpPost("cancel-requests/{id:guid}/reject")]
|
||||
[Authorize(Policy = "rides.cancel.approve")]
|
||||
public async Task<IActionResult> RejectCancelRequest(Guid id, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
@@ -146,7 +133,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/cancel-request")]
|
||||
[Authorize(Policy = "rides.view")]
|
||||
public async Task<IActionResult> GetCancelRequest(Guid id)
|
||||
{
|
||||
var result = await service.GetCancelRequestAsync(id);
|
||||
@@ -154,7 +140,6 @@ public class RideController(RideService service, ICurrentUserService currentUser
|
||||
}
|
||||
|
||||
[HttpGet("breakdown-assist/{rideId:guid}")]
|
||||
[Authorize(Policy = "rides.view")]
|
||||
public async Task<IActionResult> GetBreakdownAssist(Guid rideId)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Role;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/roles")]
|
||||
[Authorize]
|
||||
public class RoleController(RoleService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Route;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/routes")]
|
||||
[Authorize]
|
||||
public class RouteController(RouteService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "routes.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "routes.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class RouteController(RouteService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "routes.create")]
|
||||
public async Task<IActionResult> Create(CreateRouteRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class RouteController(RouteService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "routes.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateRouteRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class RouteController(RouteService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "routes.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
|
||||
@@ -5,7 +5,8 @@ namespace Distribution.Features.Sale;
|
||||
public interface ISaleRepository
|
||||
{
|
||||
Task<Models.Sale?> GetByIdAsync(Guid id);
|
||||
Task<List<Models.Sale>> GetAllAsync();
|
||||
Task<List<Models.Sale>> GetAllAsync(Guid? rideId, IEnumerable<Guid>? storeIds, int page, int pageSize);
|
||||
Task<int> GetCountAsync(Guid? rideId, IEnumerable<Guid>? storeIds);
|
||||
Task<List<Models.Sale>> GetByStoreIdAsync(Guid storeId);
|
||||
Task AddAsync(Models.Sale sale);
|
||||
void Update(Models.Sale sale);
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Sale;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/sales")]
|
||||
[Authorize]
|
||||
public class SaleController(SaleService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "orders.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
public async Task<IActionResult> GetAll(
|
||||
[FromQuery] Guid? rideId,
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] int pageSize = 20) =>
|
||||
Ok(await service.GetAllAsync(rideId, page, pageSize));
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "orders.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +21,6 @@ public class SaleController(SaleService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("store/{storeId:guid}")]
|
||||
[Authorize(Policy = "orders.view")]
|
||||
public async Task<IActionResult> GetByStore(Guid storeId)
|
||||
{
|
||||
var result = await service.GetByStoreIdAsync(storeId);
|
||||
@@ -30,7 +28,6 @@ public class SaleController(SaleService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "orders.create")]
|
||||
public async Task<IActionResult> Create(CreateSaleRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
|
||||
@@ -9,8 +9,21 @@ public class SaleRepository(AppDBContext context) : ISaleRepository
|
||||
public async Task<Models.Sale?> GetByIdAsync(Guid id) =>
|
||||
await context.Sales.FindAsync(id);
|
||||
|
||||
public async Task<List<Models.Sale>> GetAllAsync() =>
|
||||
await context.Sales.ToListAsync();
|
||||
public async Task<List<Models.Sale>> GetAllAsync(Guid? rideId, IEnumerable<Guid>? storeIds, int page, int pageSize) =>
|
||||
await context.Sales
|
||||
.Where(s => s.IsActive &&
|
||||
(rideId == null || s.FK_RideId == rideId) &&
|
||||
(storeIds == null || storeIds.Contains(s.FK_StoreId)))
|
||||
.OrderByDescending(s => s.CreatedAt)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
public async Task<int> GetCountAsync(Guid? rideId, IEnumerable<Guid>? storeIds) =>
|
||||
await context.Sales
|
||||
.CountAsync(s => s.IsActive &&
|
||||
(rideId == null || s.FK_RideId == rideId) &&
|
||||
(storeIds == null || storeIds.Contains(s.FK_StoreId)));
|
||||
|
||||
public async Task<List<Models.Sale>> GetByStoreIdAsync(Guid storeId) =>
|
||||
await context.Sales.Where(s => s.FK_StoreId == storeId && s.IsActive).ToListAsync();
|
||||
|
||||
@@ -71,14 +71,14 @@ public class SaleService(
|
||||
sale.IsActive,
|
||||
sale.CreatedAt);
|
||||
|
||||
public async Task<List<SaleResponse>> GetAllAsync()
|
||||
public async Task<PagedResponse<SaleResponse>> GetAllAsync(Guid? rideId, int page, int pageSize)
|
||||
{
|
||||
var sales = (await repo.GetAllAsync()).Where(s => s.IsActive).ToList();
|
||||
IEnumerable<Guid>? storeIds = null;
|
||||
if (!HasGlobalScope && currentUser.UserId is not null)
|
||||
{
|
||||
var accessibleStoreIds = (await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value)).ToHashSet();
|
||||
sales = sales.Where(s => accessibleStoreIds.Contains(s.FK_StoreId)).ToList();
|
||||
}
|
||||
storeIds = await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value);
|
||||
|
||||
var total = await repo.GetCountAsync(rideId, storeIds);
|
||||
var sales = await repo.GetAllAsync(rideId, storeIds, page, pageSize);
|
||||
|
||||
var result = new List<SaleResponse>();
|
||||
foreach (var sale in sales)
|
||||
@@ -88,7 +88,7 @@ public class SaleService(
|
||||
var items = await orderRepo.GetItemsByOrderIdAsync(order.Id);
|
||||
result.Add(ToResponse(sale, order, items));
|
||||
}
|
||||
return result;
|
||||
return new PagedResponse<SaleResponse>(page, pageSize, total, result);
|
||||
}
|
||||
|
||||
public async Task<SaleResponse?> GetByIdAsync(Guid id)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Scheme;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/schemes")]
|
||||
[Authorize]
|
||||
public class SchemeController(SchemeService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
@@ -120,7 +118,6 @@ public class SchemeController(SchemeService service) : ControllerBase
|
||||
|
||||
[ApiController]
|
||||
[Route("api/orders")]
|
||||
[Authorize]
|
||||
public class SchemeOrderController(SchemeService service) : ControllerBase
|
||||
{
|
||||
[HttpPost("{id:guid}/apply-scheme")]
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Models;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Stock;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/stock")]
|
||||
[Authorize]
|
||||
public class StockController(StockService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
// ── Query ──────────────────────────────────────────────────────────────
|
||||
// ── Query ──────────────────────────────────────────────────────────────
|
||||
|
||||
[HttpGet("balances")]
|
||||
public async Task<IActionResult> GetBalances(
|
||||
@@ -46,7 +44,7 @@ public class StockController(StockService service, ICurrentUserService currentUs
|
||||
return Ok(result);
|
||||
}
|
||||
|
||||
// ── Write ──────────────────────────────────────────────────────────────
|
||||
// ── Write ──────────────────────────────────────────────────────────────
|
||||
|
||||
[HttpPost("transfer")]
|
||||
public async Task<IActionResult> Transfer(TransferRequest request, CancellationToken ct)
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Store.Kyc;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/stores/{storeId:guid}/kyc-documents")]
|
||||
[Authorize]
|
||||
public class StoreKycDocumentController(StoreKycDocumentService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "stores.view")]
|
||||
public async Task<IActionResult> GetByStoreId(Guid storeId)
|
||||
{
|
||||
var result = await service.GetByStoreIdAsync(storeId);
|
||||
@@ -17,7 +14,6 @@ public class StoreKycDocumentController(StoreKycDocumentService service) : Contr
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "stores.update")]
|
||||
public async Task<IActionResult> Upload(Guid storeId, [FromForm] UploadKycDocumentRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UploadAsync(storeId, request, ct);
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Store;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/stores")]
|
||||
[Authorize]
|
||||
public class StoreController(StoreService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "stores.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "stores.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "stores.create")]
|
||||
public async Task<IActionResult> Create(CreateStoreRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "stores.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateStoreRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "stores.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
@@ -46,7 +39,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/credit-limit")]
|
||||
[Authorize(Policy = "stores.credit.update")]
|
||||
public async Task<IActionResult> UpdateCreditLimit(Guid id, UpdateCreditLimitRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateCreditLimitAsync(id, request, ct);
|
||||
@@ -54,7 +46,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/outstanding-balance")]
|
||||
[Authorize(Policy = "stores.credit.update")]
|
||||
public async Task<IActionResult> UpdateOutstandingBalance(Guid id, UpdateOutstandingBalanceRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateOutstandingBalanceAsync(id, request, ct);
|
||||
@@ -62,7 +53,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/outstanding-balance")]
|
||||
[Authorize(Policy = "stores.view")]
|
||||
public async Task<IActionResult> GetOutstandingBalance(Guid id)
|
||||
{
|
||||
var result = await service.GetOutstandingBalanceAsync(id);
|
||||
@@ -70,7 +60,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/kyc/verify")]
|
||||
[Authorize(Policy = "stores.kyc.verify")]
|
||||
public async Task<IActionResult> VerifyKyc(Guid id, VerifyKycRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.VerifyKycAsync(id, request, ct);
|
||||
@@ -78,7 +67,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/segment")]
|
||||
[Authorize(Policy = "stores.update")]
|
||||
public async Task<IActionResult> ClassifySegment(Guid id, ClassifySegmentRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.ClassifySegmentAsync(id, request, ct);
|
||||
@@ -86,7 +74,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/visit-history")]
|
||||
[Authorize(Policy = "stores.view")]
|
||||
public async Task<IActionResult> GetVisitHistory(Guid id)
|
||||
{
|
||||
var result = await service.GetVisitHistoryAsync(id);
|
||||
@@ -94,7 +81,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/schemes/{schemeId:guid}/eligibility")]
|
||||
[Authorize(Policy = "stores.view")]
|
||||
public async Task<IActionResult> CheckSchemeEligibility(Guid id, Guid schemeId)
|
||||
{
|
||||
var result = await service.CheckSchemeEligibilityAsync(id, schemeId);
|
||||
@@ -102,7 +88,6 @@ public class StoreController(StoreService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpGet("{id:guid}/dashboard")]
|
||||
[Authorize(Policy = "stores.view")]
|
||||
public async Task<IActionResult> GetDashboard(Guid id, [FromQuery] string period)
|
||||
{
|
||||
var result = await service.GetDashboardAsync(id, period);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Supplier;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/suppliers")]
|
||||
[Authorize]
|
||||
public class SupplierController(SupplierService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.SupplierClaims;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
public class SupplierClaimController(SupplierClaimService service, ICurrentUserService currentUser) : ControllerBase
|
||||
{
|
||||
[HttpGet("api/supplier-claims/{id:guid}")]
|
||||
@@ -32,7 +30,6 @@ public class SupplierClaimController(SupplierClaimService service, ICurrentUserS
|
||||
}
|
||||
|
||||
[HttpPost("api/supplier-claims/{id:guid}/approve")]
|
||||
[Authorize(Policy = "suppliers.claims.approve")]
|
||||
public async Task<IActionResult> Approve(Guid id, ApproveSupplierClaimRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
@@ -46,7 +43,6 @@ public class SupplierClaimController(SupplierClaimService service, ICurrentUserS
|
||||
}
|
||||
|
||||
[HttpPost("api/supplier-claims/{id:guid}/reject")]
|
||||
[Authorize(Policy = "suppliers.claims.approve")]
|
||||
public async Task<IActionResult> Reject(Guid id, RejectSupplierClaimRequest request, CancellationToken ct)
|
||||
{
|
||||
var userId = currentUser.UserId ?? throw new UnauthorizedAccessException();
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Sync;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/sync")]
|
||||
[Authorize(Policy = "items.create")]
|
||||
public class SyncController(SyncService service) : ControllerBase
|
||||
{
|
||||
[HttpPost("uoms")]
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Uom;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/uoms")]
|
||||
[Authorize]
|
||||
public class UomController(UomService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "items.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "items.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class UomController(UomService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "items.create")]
|
||||
public async Task<IActionResult> Create(CreateUomRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class UomController(UomService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "items.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateUomRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class UomController(UomService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "items.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.User;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/users")]
|
||||
[Authorize]
|
||||
public class UserController(UserService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "users.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "users.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class UserController(UserService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "users.create")]
|
||||
public async Task<IActionResult> Create(CreateUserRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class UserController(UserService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "users.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateUserRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class UserController(UserService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/role")]
|
||||
[Authorize(Policy = "users.assign_role")]
|
||||
public async Task<IActionResult> AssignRole(Guid id, AssignUserRoleRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.AssignRoleAsync(id, request, ct);
|
||||
@@ -46,7 +39,6 @@ public class UserController(UserService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}/scope")]
|
||||
[Authorize(Policy = "users.assign_scope")]
|
||||
public async Task<IActionResult> AssignScope(Guid id, AssignUserScopeRequest request, CancellationToken ct)
|
||||
{
|
||||
var updated = await service.AssignScopeAsync(id, request, ct);
|
||||
@@ -54,7 +46,6 @@ public class UserController(UserService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "users.deactivate")]
|
||||
public async Task<IActionResult> Deactivate(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deactivated = await service.DeactivateAsync(id, ct);
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Vehicle;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/vehicles")]
|
||||
[Authorize]
|
||||
public class VehicleController(VehicleService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "vehicles.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "vehicles.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class VehicleController(VehicleService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "vehicles.create")]
|
||||
public async Task<IActionResult> Create(CreateVehicleRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class VehicleController(VehicleService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "vehicles.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateVehicleRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class VehicleController(VehicleService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "vehicles.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
|
||||
@@ -1,20 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Features.Warehouse;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/warehouses")]
|
||||
[Authorize]
|
||||
public class WarehouseController(WarehouseService service) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
[Authorize(Policy = "warehouses.view")]
|
||||
public async Task<IActionResult> GetAll() =>
|
||||
Ok(await service.GetAllAsync());
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
[Authorize(Policy = "warehouses.view")]
|
||||
public async Task<IActionResult> GetById(Guid id)
|
||||
{
|
||||
var result = await service.GetByIdAsync(id);
|
||||
@@ -22,7 +18,6 @@ public class WarehouseController(WarehouseService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[Authorize(Policy = "warehouses.create")]
|
||||
public async Task<IActionResult> Create(CreateWarehouseRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.CreateAsync(request, ct);
|
||||
@@ -30,7 +25,6 @@ public class WarehouseController(WarehouseService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
[Authorize(Policy = "warehouses.update")]
|
||||
public async Task<IActionResult> Update(Guid id, UpdateWarehouseRequest request, CancellationToken ct)
|
||||
{
|
||||
var result = await service.UpdateAsync(id, request, ct);
|
||||
@@ -38,7 +32,6 @@ public class WarehouseController(WarehouseService service) : ControllerBase
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
[Authorize(Policy = "warehouses.delete")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var deleted = await service.DeleteAsync(id, ct);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
|
||||
namespace Distribution.Infra.Authorization;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class AuthenticatedAttribute : Attribute, IAuthorizationFilter
|
||||
{
|
||||
public void OnAuthorization(AuthorizationFilterContext context)
|
||||
{
|
||||
if (context.HttpContext.User.Identity?.IsAuthenticated != true)
|
||||
context.Result = new UnauthorizedResult();
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Distribution.Infra.Authorization;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/authorization")]
|
||||
[Authorize]
|
||||
public class AuthorizationController(
|
||||
IPermissionService permissionService,
|
||||
IScopeAccessService scopeAccessService,
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
//namespace Distribution.Infra.Authorization;
|
||||
|
||||
namespace Distribution.Infra.Authorization;
|
||||
//public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
|
||||
//{
|
||||
// private readonly IPermissionService _permissionService;
|
||||
|
||||
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
|
||||
{
|
||||
private readonly IPermissionService _permissionService;
|
||||
// public PermissionAuthorizationHandler(IPermissionService permissionService)
|
||||
// {
|
||||
// _permissionService = permissionService;
|
||||
// }
|
||||
|
||||
public PermissionAuthorizationHandler(IPermissionService permissionService)
|
||||
{
|
||||
_permissionService = permissionService;
|
||||
}
|
||||
// protected override async Task HandleRequirementAsync(
|
||||
// AuthorizationHandlerContext context, PermissionRequirement requirement)
|
||||
// {
|
||||
// var roleIdClaim = context.User.FindFirst("role_id")?.Value;
|
||||
// if (!Guid.TryParse(roleIdClaim, out var roleId))
|
||||
// return;
|
||||
|
||||
protected override async Task HandleRequirementAsync(
|
||||
AuthorizationHandlerContext context, PermissionRequirement requirement)
|
||||
{
|
||||
var roleIdClaim = context.User.FindFirst("role_id")?.Value;
|
||||
if (!Guid.TryParse(roleIdClaim, out var roleId))
|
||||
return;
|
||||
|
||||
if (await _permissionService.HasPermissionAsync(roleId, requirement.PermissionCode))
|
||||
context.Succeed(requirement);
|
||||
}
|
||||
}
|
||||
// if (await _permissionService.HasPermissionAsync(roleId, requirement.PermissionCode))
|
||||
// context.Succeed(requirement);
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.Extensions.Options;
|
||||
//using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Distribution.Infra.Authorization;
|
||||
//namespace Distribution.Infra.Authorization;
|
||||
|
||||
public class PermissionPolicyProvider : IAuthorizationPolicyProvider
|
||||
{
|
||||
private readonly DefaultAuthorizationPolicyProvider _fallback;
|
||||
//public class PermissionPolicyProvider : IAuthorizationPolicyProvider
|
||||
//{
|
||||
// private readonly DefaultAuthorizationPolicyProvider _fallback;
|
||||
|
||||
public PermissionPolicyProvider(IOptions<AuthorizationOptions> options)
|
||||
{
|
||||
_fallback = new DefaultAuthorizationPolicyProvider(options);
|
||||
}
|
||||
// public PermissionPolicyProvider(IOptions<AuthorizationOptions> options)
|
||||
// {
|
||||
// _fallback = new DefaultAuthorizationPolicyProvider(options);
|
||||
// }
|
||||
|
||||
public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => _fallback.GetDefaultPolicyAsync();
|
||||
// public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => _fallback.GetDefaultPolicyAsync();
|
||||
|
||||
public Task<AuthorizationPolicy?> GetFallbackPolicyAsync() => _fallback.GetFallbackPolicyAsync();
|
||||
// public Task<AuthorizationPolicy?> GetFallbackPolicyAsync() => _fallback.GetFallbackPolicyAsync();
|
||||
|
||||
public Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
|
||||
{
|
||||
if (policyName.Contains('.'))
|
||||
{
|
||||
var policy = new AuthorizationPolicyBuilder()
|
||||
.RequireAuthenticatedUser()
|
||||
.AddRequirements(new PermissionRequirement(policyName))
|
||||
.Build();
|
||||
return Task.FromResult<AuthorizationPolicy?>(policy);
|
||||
}
|
||||
// public Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
|
||||
// {
|
||||
// if (policyName.Contains('.'))
|
||||
// {
|
||||
// var policy = new AuthorizationPolicyBuilder()
|
||||
// .RequireAuthenticatedUser()
|
||||
// .AddRequirements(new PermissionRequirement(policyName))
|
||||
// .Build();
|
||||
// return Task.FromResult<AuthorizationPolicy?>(policy);
|
||||
// }
|
||||
|
||||
return _fallback.GetPolicyAsync(policyName);
|
||||
}
|
||||
}
|
||||
// return _fallback.GetPolicyAsync(policyName);
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
//namespace Distribution.Infra.Authorization;
|
||||
|
||||
namespace Distribution.Infra.Authorization;
|
||||
//public class PermissionRequirement : IAuthorizationRequirement
|
||||
//{
|
||||
// public string PermissionCode { get; }
|
||||
|
||||
public class PermissionRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public string PermissionCode { get; }
|
||||
|
||||
public PermissionRequirement(string permissionCode)
|
||||
{
|
||||
PermissionCode = permissionCode;
|
||||
}
|
||||
}
|
||||
// public PermissionRequirement(string permissionCode)
|
||||
// {
|
||||
// PermissionCode = permissionCode;
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Text;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Distribution.Middleware;
|
||||
|
||||
public class AuthMiddleware(RequestDelegate next, IConfiguration config)
|
||||
{
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
var token = context.Request.Headers.Authorization
|
||||
.ToString()
|
||||
.Replace("Bearer ", "", StringComparison.OrdinalIgnoreCase)
|
||||
.Trim();
|
||||
|
||||
if (!string.IsNullOrEmpty(token))
|
||||
{
|
||||
var key = config["Jwt:Key"];
|
||||
if (!string.IsNullOrEmpty(key))
|
||||
{
|
||||
try
|
||||
{
|
||||
var principal = new JwtSecurityTokenHandler().ValidateToken(token,
|
||||
new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuerSigningKey = true,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)),
|
||||
ValidateIssuer = true,
|
||||
ValidIssuer = config["Jwt:Issuer"],
|
||||
ValidateAudience = true,
|
||||
ValidAudience = config["Jwt:Audience"],
|
||||
ValidateLifetime = true,
|
||||
ClockSkew = TimeSpan.FromMinutes(1)
|
||||
}, out _);
|
||||
|
||||
context.User = principal;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
await next(context);
|
||||
}
|
||||
}
|
||||
+20
-64
@@ -1,6 +1,6 @@
|
||||
using System.Security.Claims;
|
||||
using Distribution.Data;
|
||||
using Distribution.Features.Auth;
|
||||
using Distribution.Middleware;
|
||||
using Distribution.Features.Brand;
|
||||
using Distribution.Features.Category;
|
||||
using Distribution.Features.DeliveryRide;
|
||||
@@ -34,10 +34,7 @@ using Distribution.Features.Stock;
|
||||
using Distribution.Features.Warehouse;
|
||||
using Distribution.Infra.Authorization;
|
||||
using Distribution.Infra.UoW;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -126,67 +123,26 @@ builder.Services.AddScoped<IPermissionRepository, PermissionRepository>();
|
||||
builder.Services.AddScoped<IScopeRepository, ScopeRepository>();
|
||||
builder.Services.AddScoped<IPermissionService, PermissionService>();
|
||||
builder.Services.AddScoped<IScopeAccessService, ScopeAccessService>();
|
||||
builder.Services.AddScoped<IAuthorizationHandler, PermissionAuthorizationHandler>();
|
||||
builder.Services.AddSingleton<IAuthorizationPolicyProvider, PermissionPolicyProvider>();
|
||||
// ── Auth Service connector ───────────────────────────────────────────────────
|
||||
builder.Services.Configure<AuthServiceOptions>(
|
||||
builder.Configuration.GetSection(AuthServiceOptions.SectionName));
|
||||
|
||||
var jwtSection = builder.Configuration.GetSection("Jwt");
|
||||
var jwtPublicKeyXml = jwtSection["PublicKey"] ?? throw new InvalidOperationException("Jwt:PublicKey is not configured.");
|
||||
var jwtSigningKey = new RsaSecurityKey(RsaXmlKeyReader.ReadPublicKey(jwtPublicKeyXml));
|
||||
var authServiceBaseUrl = builder.Configuration[$"{AuthServiceOptions.SectionName}:BaseUrl"];
|
||||
|
||||
builder.Services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||
})
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuer = true,
|
||||
ValidIssuer = jwtSection["Issuer"],
|
||||
ValidateAudience = true,
|
||||
ValidAudience = jwtSection["Audience"],
|
||||
ValidateIssuerSigningKey = true,
|
||||
IssuerSigningKey = jwtSigningKey,
|
||||
ValidateLifetime = true,
|
||||
ClockSkew = TimeSpan.FromMinutes(1)
|
||||
};
|
||||
builder.Services.AddHttpClient<AuthServiceClient>(client =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(authServiceBaseUrl))
|
||||
client.BaseAddress = new Uri(authServiceBaseUrl);
|
||||
});
|
||||
|
||||
// AuthHex issues the token and owns its claim shape; this app's authorization (permission
|
||||
// policies, role-level checks) runs against the *local* Role/Permission tables, so every
|
||||
// validated token is mapped back to a local User/Role once here, not duplicated per
|
||||
// endpoint. A token for a user with no matching local User record is rejected outright —
|
||||
// login via AuthHex does not implicitly provision a local user.
|
||||
options.Events = new JwtBearerEvents
|
||||
{
|
||||
OnTokenValidated = async context =>
|
||||
{
|
||||
var subClaim = context.Principal?.FindFirst("sub")?.Value
|
||||
?? context.Principal?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
||||
builder.Services.AddScoped<IAuthServiceClient, AuthServiceClient>();
|
||||
|
||||
if (!Guid.TryParse(subClaim, out var userId))
|
||||
{
|
||||
context.Fail("Token is missing a valid user id claim.");
|
||||
return;
|
||||
}
|
||||
|
||||
var userRepo = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
|
||||
var user = await userRepo.GetByIdAsync(userId);
|
||||
if (user is null || !user.IsActive)
|
||||
{
|
||||
context.Fail("User not found or inactive.");
|
||||
return;
|
||||
}
|
||||
|
||||
var identity = (ClaimsIdentity)context.Principal!.Identity!;
|
||||
identity.AddClaim(new Claim("username", user.Username));
|
||||
identity.AddClaim(new Claim("role_id", user.FK_RoleId.ToString()));
|
||||
identity.AddClaim(new Claim("role_level", (user.Role?.Level ?? 0).ToString()));
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
builder.Services.AddAuthorization();
|
||||
var allowedOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>() ?? [];
|
||||
builder.Services.AddCors(options =>
|
||||
options.AddDefaultPolicy(policy =>
|
||||
policy.WithOrigins(allowedOrigins)
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod()));
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
@@ -202,9 +158,9 @@ if (app.Environment.IsDevelopment())
|
||||
app.UseSwaggerUI();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
//app.UseHttpsRedirection();
|
||||
app.UseCors();
|
||||
app.UseMiddleware<AuthMiddleware>();
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"Urls": "http://localhost:5089",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=187.127.102.190;Port=3306;Database=distribution;User=kalana;Password=kalana@hexdive"
|
||||
},
|
||||
@@ -9,6 +10,9 @@
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Cors": {
|
||||
"AllowedOrigins": [ "http://localhost:3000" ]
|
||||
},
|
||||
"Jwt": {
|
||||
"PublicKey": "<RSAKeyValue><Modulus>1LlNkMBQNdpXJiDal7XMxkG/3ad+YBsMCuY9JD/abHMzniFXtQlovjfbeaaHJ0v1kvSo9731CJ0YC1qhPU5rPQwZwxOWZ9BOBZlMDghONdjOH/HyCUbb5Z18ibqc0QenFSnEYz+jkVZiayj8DV/+VUe+eKzpQTlU6aWtHvlbwfuXaDu+QvFlpLJ7/m8na+0s2nYhLX8Wfi4C/2AoNaYhFkIwYhMMGoaSHuIoQ5R6181Rh0gKvYopRW+IpTD5RV8bXV3AM6zOcoisOifBYROHwA5ZZpoHXuTvHYmPWW8kL8PKme7BwBldPi8KrJUroRE+WXA87aAA5Wtt1oxePcXvhQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>",
|
||||
"Audience": "AuthHexClient",
|
||||
|
||||
@@ -64,16 +64,29 @@ When `FulfillImmediately = false`, no stock movement — order stays Pending for
|
||||
|
||||
**Feature folder:** `Features/Payment/`
|
||||
|
||||
### API Endpoints
|
||||
### Sales API Endpoints
|
||||
|
||||
| Method | Route | Who | Description |
|
||||
|---|---|---|---|
|
||||
| POST | `/api/sales/{id}/payments` | Driver/Agent | Record a payment against a sale |
|
||||
| GET | `/api/sales/{id}/payments` | Any | List all payments for a sale |
|
||||
| GET | `/api/sales` | Any | List sales — supports `?rideId=`, `?page=`, `?pageSize=` query params |
|
||||
| POST | `/api/sales/{saleId:guid}/payments` | Driver/Agent | Record a payment against a sale |
|
||||
| GET | `/api/sales/{saleId:guid}/payments` | Any | List all payments for a sale |
|
||||
|
||||
**`GET /api/sales` filter params:**
|
||||
|
||||
| Param | Type | Description |
|
||||
|---|---|---|
|
||||
| `rideId` | `Guid?` | Filter to sales created on a specific ride |
|
||||
| `page` | `int` | Page number (default 1) |
|
||||
| `pageSize` | `int` | Items per page (default 20) |
|
||||
|
||||
Returns `PagedResponse<SaleResponse>`: `{ page, pageSize, total, items }`.
|
||||
|
||||
Scope rules still apply: non-global users only see sales for stores in their scope.
|
||||
|
||||
### Payment Creation Logic
|
||||
|
||||
On `POST /api/sales/{id}/payments`:
|
||||
On `POST /api/sales/{saleId:guid}/payments`:
|
||||
1. Validate sale exists and is not `Cancelled`.
|
||||
2. Add `Payment` record (`FK_SaleId`, `FK_StoreId` from sale, `Amount`, `Method`, `CollectedAt`, `CollectedBy`).
|
||||
3. Sum all payments for this sale. Recalculate `Sale.PaymentStatus`:
|
||||
|
||||
@@ -100,8 +100,8 @@ One migration needed:
|
||||
### New
|
||||
| Method | Route | Permission | Notes |
|
||||
|---|---|---|---|
|
||||
| POST | /api/stores/{id}/kyc-documents | stores.update | Multipart upload, appends a KYC document |
|
||||
| GET | /api/stores/{id}/kyc-documents | stores.view | Lists documents for a store |
|
||||
| POST | /api/stores/{storeId:guid}/kyc-documents | stores.update | Multipart upload, appends a KYC document |
|
||||
| GET | /api/stores/{storeId:guid}/kyc-documents | stores.view | Lists documents for a store |
|
||||
| PUT | /api/stores/{id}/kyc/verify | stores.kyc.verify | Sets KycStatus, body carries `status` (Verified/Rejected) + optional `notes` |
|
||||
| PUT | /api/stores/{id}/credit-limit | stores.credit.update | Requires Supervisor (roleLevel ≥ 20) or above |
|
||||
| PUT | /api/stores/{id}/outstanding-balance | stores.credit.update | Manual adjustment until Finance owns this; same permission as credit-limit |
|
||||
@@ -115,7 +115,7 @@ One migration needed:
|
||||
|
||||
## Request / Response Shapes
|
||||
|
||||
### POST `/api/stores/{id}/kyc-documents` (multipart/form-data)
|
||||
### POST `/api/stores/{storeId:guid}/kyc-documents` (multipart/form-data)
|
||||
Fields: `documentType` (string), `file` (binary).
|
||||
|
||||
Response:
|
||||
@@ -247,7 +247,7 @@ ever belong to a Store and have no independent lifecycle.
|
||||
|
||||
### KYC upload logic (pseudo)
|
||||
```
|
||||
POST /api/stores/{id}/kyc-documents — multipart (documentType, file):
|
||||
POST /api/stores/{storeId:guid}/kyc-documents — multipart (documentType, file):
|
||||
1. Load Store by id, reject if missing/inactive or caller lacks store scope
|
||||
2. Ensure wwwroot/uploads/kyc/{storeId}/ exists
|
||||
3. Save file as {guid}.{ext}, record FileReference = "uploads/kyc/{storeId}/{guid}.{ext}"
|
||||
|
||||
@@ -347,7 +347,7 @@ GET /api/schemes/eligible?storeId=...&orderId=...
|
||||
|
||||
**Apply it:**
|
||||
```
|
||||
POST /api/orders/{orderId}/apply-scheme
|
||||
POST /api/orders/{id}/apply-scheme
|
||||
{ "schemeId": "..." }
|
||||
```
|
||||
Adds an `OrderItem` line (`Soap-500ml`, qty 2, `UnitPrice = 0`) and a `SchemeRedemption` with
|
||||
|
||||
@@ -46,7 +46,7 @@ home until this step. There is no invoice, payment, or GL entity for warehouse-f
|
||||
| Function reference | Endpoint intent |
|
||||
|---|---|
|
||||
| `createInvoice(orderId)` | `POST /api/orders/{id}/invoice` — the warehouse-fulfilled counterpart to [06_sale_ride.md](./06_sale_ride.md)'s field invoice creation |
|
||||
| `recordPayment(invoiceId, amount, method)` | `POST /api/invoices/{id}/payments` |
|
||||
| `recordPayment(invoiceId, amount, method)` | Current implemented path is `POST /api/sales/{saleId:guid}/payments` for field-sale collections; `POST /api/invoices/{id}/payments` remains the target endpoint for this future invoice-based finance step |
|
||||
| `postToGeneralLedger(transactionId)` | Internal — triggered on invoice/payment/credit-note events |
|
||||
| `generateTaxInvoice(invoiceId, jurisdiction)` | `GET /api/invoices/{id}/tax-invoice?jurisdiction=...` |
|
||||
| `getFinancialReport(entityId, period, reportType)` | `GET /api/finance/reports?entityId=...&period=...&reportType=...` |
|
||||
|
||||
@@ -143,9 +143,9 @@ here — see `SRS_User_Management_Module.pdf`.
|
||||
|
||||
| Function | What it does | Status |
|
||||
|---|---|---|
|
||||
| `createStore(storeData, kycDocs)` | Onboards a new outlet with required KYC. | Partially implemented - store create exists, and KYC documents can now be uploaded/listed via separate `/api/stores/{id}/kyc-documents` endpoints rather than inline on create. |
|
||||
| `uploadStoreKycDocument(storeId, documentType, file)` | Appends a KYC document to a store. | Implemented — `POST /api/stores/{id}/kyc-documents`. |
|
||||
| `listStoreKycDocuments(storeId)` | Lists KYC documents for a store. | Implemented — `GET /api/stores/{id}/kyc-documents`. |
|
||||
| `createStore(storeData, kycDocs)` | Onboards a new outlet with required KYC. | Partially implemented - store create exists, and KYC documents can now be uploaded/listed via separate `/api/stores/{storeId:guid}/kyc-documents` endpoints rather than inline on create. |
|
||||
| `uploadStoreKycDocument(storeId, documentType, file)` | Appends a KYC document to a store. | Implemented — `POST /api/stores/{storeId:guid}/kyc-documents`. |
|
||||
| `listStoreKycDocuments(storeId)` | Lists KYC documents for a store. | Implemented — `GET /api/stores/{storeId:guid}/kyc-documents`. |
|
||||
| `verifyStoreKyc(storeId)` | Marks KYC as verified/rejected by an approver. | Implemented - `PUT /api/stores/{id}/kyc/verify` updates `Store.KycStatus`. |
|
||||
| `updateStoreCreditLimit(storeId, newLimit, approverId)` | Changes a store's credit limit, subject to approval authority. | Implemented - `PUT /api/stores/{id}/credit-limit` updates `Store.CreditLimit` and requires the `stores.credit.update` permission plus role level >= 20. |
|
||||
| `updateStoreOutstandingBalance(storeId, amount, reason?)` | Manually adjusts the cached outstanding balance. | Implemented — `PUT /api/stores/{id}/outstanding-balance`. |
|
||||
@@ -281,7 +281,7 @@ here — see `SRS_User_Management_Module.pdf`.
|
||||
| Function | What it does | Status |
|
||||
|---|---|---|
|
||||
| `createInvoice(orderId)` | Generates a formal invoice from a fulfilled order. | Not implemented — no `Invoice` entity exists; `Sale`/`Order` remain the billable record. |
|
||||
| `recordPayment(invoiceId, amount, method)` | Logs a payment/collection against an invoice. | Implemented against `Sale` rather than an invoice — `POST /api/sales/{saleId}/payments` (`Features/Payment`). Each payment sums against `Sale.TotalAmount` and updates `Sale.PaymentStatus` (`Pending`/`PartiallyPaid`/`Paid`); rejects (400) if the sale is `Cancelled`. `Method` is `Cash` or `Credit` (`Models/Enums.cs`). |
|
||||
| `recordPayment(invoiceId, amount, method)` | Logs a payment/collection against an invoice. | Implemented against `Sale` rather than an invoice — `POST /api/sales/{saleId:guid}/payments` (`Features/Payment`). Each payment sums against `Sale.TotalAmount` and updates `Sale.PaymentStatus` (`Pending`/`PartiallyPaid`/`Paid`); rejects (400) if the sale is `Cancelled`. `Method` is `Cash` or `Credit` (`Models/Enums.cs`). |
|
||||
| `postToGeneralLedger(transactionId)` | Posts a financial transaction to the GL. | Not implemented — no GL/ledger entity exists. |
|
||||
| `generateTaxInvoice(invoiceId, jurisdiction)` | Produces a tax-compliant invoice (GST/VAT e-invoicing). | Not implemented. |
|
||||
| `getFinancialReport(entityId, period, reportType)` | Returns P&L/cash-flow reports scoped to a region/area. | Not implemented. |
|
||||
|
||||
Reference in New Issue
Block a user