using Distribution.Infra.Auth; using Distribution.Infra.UoW; namespace Distribution.Features.Store; public class StoreService(IStoreRepository repo, IUnitOfWork uow, ICurrentUserService currentUser, IScopeAccessService scopeAccess) { private const int GlobalScopeRoleLevel = 50; 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 stores = (await repo.GetAllAsync()).Where(s => s.IsActive).ToList(); if (!HasGlobalScope && currentUser.UserId is not null) { var accessibleStoreIds = (await scopeAccess.GetAccessibleStoreIdsAsync(currentUser.UserId.Value)).ToHashSet(); stores = stores.Where(s => accessibleStoreIds.Contains(s.Id)).ToList(); } return stores.Select(s => new StoreResponse(s.Id, s.FK_RouteId, s.OwnerName, s.StoreName, s.StoreAddress, s.Latitude, s.Longitude, s.OneTimeAmount, s.CreditAmount, s.IsActive, s.CreatedAt)).ToList(); } public async Task GetByIdAsync(Guid id) { var store = await repo.GetByIdAsync(id); if (store is null || !store.IsActive) return null; if (!await HasStoreScopeAsync(id)) return null; return new StoreResponse(store.Id, store.FK_RouteId, store.OwnerName, store.StoreName, store.StoreAddress, store.Latitude, store.Longitude, store.OneTimeAmount, store.CreditAmount, store.IsActive, store.CreatedAt); } public async Task CreateAsync(CreateStoreRequest request, CancellationToken ct = default) { var store = new Models.Store { FK_RouteId = request.RouteId, OwnerName = request.OwnerName, StoreName = request.StoreName, StoreAddress = request.StoreAddress, Latitude = request.Latitude, Longitude = request.Longitude, OneTimeAmount = request.OneTimeAmount, CreditAmount = request.CreditAmount }; await uow.BeginAsync(ct); try { await repo.AddAsync(store); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return new StoreResponse(store.Id, store.FK_RouteId, store.OwnerName, store.StoreName, store.StoreAddress, store.Latitude, store.Longitude, store.OneTimeAmount, store.CreditAmount, store.IsActive, store.CreatedAt); } public async Task UpdateAsync(Guid id, UpdateStoreRequest request, CancellationToken ct = default) { var store = await repo.GetByIdAsync(id); if (store is null || !store.IsActive) return null; if (!await HasStoreScopeAsync(id)) return null; store.FK_RouteId = request.RouteId; store.OwnerName = request.OwnerName; store.StoreName = request.StoreName; store.StoreAddress = request.StoreAddress; store.Latitude = request.Latitude; store.Longitude = request.Longitude; store.OneTimeAmount = request.OneTimeAmount; store.CreditAmount = request.CreditAmount; await uow.BeginAsync(ct); try { repo.Update(store); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return new StoreResponse(store.Id, store.FK_RouteId, store.OwnerName, store.StoreName, store.StoreAddress, store.Latitude, store.Longitude, store.OneTimeAmount, store.CreditAmount, store.IsActive, store.CreatedAt); } public async Task DeleteAsync(Guid id, CancellationToken ct = default) { var store = await repo.GetByIdAsync(id); if (store is null || !store.IsActive) return false; if (!await HasStoreScopeAsync(id)) return false; await uow.BeginAsync(ct); try { repo.Remove(store); await uow.CommitAsync(ct); } catch { await uow.RollbackAsync(ct); throw; } return true; } }