using Distribution.Infra.Auth; using Distribution.Infra.UoW; namespace Distribution.Features.Order; public class OrderService(IOrderRepository repo, IUnitOfWork uow, ICurrentUserService currentUser, IScopeAccessService scopeAccess) { private const int GlobalScopeRoleLevel = 50; private static OrderResponse ToResponse(Models.Order o, List items) => new(o.Id, o.OrderDate, o.FK_StoreId, o.TotalAmount, items.Select(i => new OrderItemResponse(i.FK_ItemId, i.Quantity)).ToList(), o.IsActive, o.CreatedAt); private bool HasGlobalScope => currentUser.RoleLevel >= GlobalScopeRoleLevel; private async Task HasStoreScopeAsync(Guid storeId) { if (HasGlobalScope || currentUser.UserId is null) return HasGlobalScope; return await scopeAccess.HasStoreScopeAsync(currentUser.UserId.Value, storeId); } public async Task> GetAllAsync() { var orders = (await repo.GetAllAsync()).Where(o => o.IsActive).ToList(); if (!HasGlobalScope && currentUser.UserId is not null) { var accessibleStoreIds = (await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value)).ToHashSet(); orders = orders.Where(o => accessibleStoreIds.Contains(o.FK_StoreId)).ToList(); } var result = new List(); foreach (var order in orders) { var items = await repo.GetItemsByOrderIdAsync(order.Id); result.Add(ToResponse(order, items)); } return result; } public async Task GetByIdAsync(Guid id) { var order = await repo.GetByIdAsync(id); if (order is null || !order.IsActive) return null; if (!await HasStoreScopeAsync(order.FK_StoreId)) return null; var items = await repo.GetItemsByOrderIdAsync(id); return ToResponse(order, items); } public async Task?> GetByStoreIdAsync(Guid storeId) { if (!await HasStoreScopeAsync(storeId)) return null; var orders = await repo.GetByStoreIdAsync(storeId); var result = new List(); foreach (var order in orders) { var items = await repo.GetItemsByOrderIdAsync(order.Id); result.Add(ToResponse(order, items)); } return result; } public async Task CreateAsync(CreateOrderRequest request, CancellationToken ct = default) { if (!await HasStoreScopeAsync(request.StoreId)) return null; var order = new Models.Order { FK_StoreId = request.StoreId, OrderDate = request.OrderDate, TotalAmount = request.TotalAmount }; var orderItems = request.Items.Select(i => new Models.OrderItem { FK_OrderId = order.Id, FK_ItemId = i.ItemId, Quantity = i.Quantity }).ToList(); await uow.BeginAsync(ct); try { await repo.AddAsync(order); await repo.AddItemsAsync(orderItems); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return ToResponse(order, orderItems); } public async Task UpdateAsync(Guid id, UpdateOrderRequest request, CancellationToken ct = default) { var order = await repo.GetByIdAsync(id); if (order is null || !order.IsActive) return null; if (!await HasStoreScopeAsync(order.FK_StoreId)) return null; order.OrderDate = request.OrderDate; order.TotalAmount = request.TotalAmount; await uow.BeginAsync(ct); try { repo.Update(order); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } var items = await repo.GetItemsByOrderIdAsync(id); return ToResponse(order, items); } public async Task DeleteAsync(Guid id, CancellationToken ct = default) { var order = await repo.GetByIdAsync(id); if (order is null || !order.IsActive) return false; if (!await HasStoreScopeAsync(order.FK_StoreId)) return false; await uow.BeginAsync(ct); try { repo.Remove(order); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return true; } }