using System; using System.Linq; using Microsoft.EntityFrameworkCore; using TakeoutSaaS.Domain.Stores.Entities; using TakeoutSaaS.Domain.Stores.Enums; using TakeoutSaaS.Domain.Stores.Repositories; using TakeoutSaaS.Infrastructure.App.Persistence; namespace TakeoutSaaS.Infrastructure.App.Repositories; /// /// 门店聚合的 EF Core 仓储实现。 /// /// /// 初始化仓储。 /// public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepository { /// public Task FindByIdAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { return context.Stores .AsNoTracking() .Where(x => x.TenantId == tenantId && x.Id == storeId) .FirstOrDefaultAsync(cancellationToken); } /// public async Task> GetByMerchantIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default) { return await context.Stores .AsNoTracking() .Where(x => x.TenantId == tenantId && x.MerchantId == merchantId) .OrderBy(x => x.Name) .ToListAsync(cancellationToken); } /// public async Task> SearchAsync(long tenantId, StoreStatus? status, CancellationToken cancellationToken = default) { var query = context.Stores .AsNoTracking() .Where(x => x.TenantId == tenantId); if (status.HasValue) { query = query.Where(x => x.Status == status.Value); } var stores = await query .OrderBy(x => x.Name) .ToListAsync(cancellationToken); return stores; } /// public async Task> GetStoreCountsAsync(long? tenantId, IReadOnlyCollection merchantIds, CancellationToken cancellationToken = default) { if (merchantIds.Count == 0) { return new Dictionary(); } var query = context.Stores.AsNoTracking(); if (!tenantId.HasValue || tenantId.Value <= 0) { query = query.IgnoreQueryFilters(); } else { query = query.Where(x => x.TenantId == tenantId.Value); } return await query .Where(x => merchantIds.Contains(x.MerchantId)) .GroupBy(x => x.MerchantId) .Select(group => new { group.Key, Count = group.Count() }) .ToDictionaryAsync(x => x.Key, x => x.Count, cancellationToken); } /// public async Task> GetBusinessHoursAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { var hours = await context.StoreBusinessHours .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == storeId) .OrderBy(x => x.DayOfWeek) .ThenBy(x => x.StartTime) .ToListAsync(cancellationToken); return hours; } /// public Task FindBusinessHourByIdAsync(long businessHourId, long tenantId, CancellationToken cancellationToken = default) { return context.StoreBusinessHours .Where(x => x.TenantId == tenantId && x.Id == businessHourId) .FirstOrDefaultAsync(cancellationToken); } /// public async Task> GetDeliveryZonesAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { var zones = await context.StoreDeliveryZones .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == storeId) .OrderBy(x => x.SortOrder) .ToListAsync(cancellationToken); return zones; } /// public Task FindDeliveryZoneByIdAsync(long deliveryZoneId, long tenantId, CancellationToken cancellationToken = default) { return context.StoreDeliveryZones .Where(x => x.TenantId == tenantId && x.Id == deliveryZoneId) .FirstOrDefaultAsync(cancellationToken); } /// public async Task> GetHolidaysAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { var holidays = await context.StoreHolidays .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == storeId) .OrderBy(x => x.Date) .ToListAsync(cancellationToken); return holidays; } /// public Task FindHolidayByIdAsync(long holidayId, long tenantId, CancellationToken cancellationToken = default) { return context.StoreHolidays .Where(x => x.TenantId == tenantId && x.Id == holidayId) .FirstOrDefaultAsync(cancellationToken); } /// public async Task> GetTableAreasAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { var areas = await context.StoreTableAreas .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == storeId) .OrderBy(x => x.SortOrder) .ToListAsync(cancellationToken); return areas; } /// public Task FindTableAreaByIdAsync(long areaId, long tenantId, CancellationToken cancellationToken = default) { return context.StoreTableAreas .Where(x => x.TenantId == tenantId && x.Id == areaId) .FirstOrDefaultAsync(cancellationToken); } /// public async Task> GetTablesAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { var tables = await context.StoreTables .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == storeId) .OrderBy(x => x.TableCode) .ToListAsync(cancellationToken); return tables; } /// public Task FindTableByIdAsync(long tableId, long tenantId, CancellationToken cancellationToken = default) { return context.StoreTables .Where(x => x.TenantId == tenantId && x.Id == tableId) .FirstOrDefaultAsync(cancellationToken); } /// public Task FindTableByCodeAsync(string tableCode, long tenantId, CancellationToken cancellationToken = default) { return context.StoreTables .Where(x => x.TenantId == tenantId && x.TableCode == tableCode) .FirstOrDefaultAsync(cancellationToken); } /// public Task GetPickupSettingAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { return context.StorePickupSettings .Where(x => x.TenantId == tenantId && x.StoreId == storeId) .FirstOrDefaultAsync(cancellationToken); } /// public Task AddPickupSettingAsync(StorePickupSetting setting, CancellationToken cancellationToken = default) { return context.StorePickupSettings.AddAsync(setting, cancellationToken).AsTask(); } /// public Task UpdatePickupSettingAsync(StorePickupSetting setting, CancellationToken cancellationToken = default) { context.StorePickupSettings.Update(setting); return Task.CompletedTask; } /// public async Task> GetPickupSlotsAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { var slots = await context.StorePickupSlots .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == storeId) .OrderBy(x => x.StartTime) .ToListAsync(cancellationToken); return slots; } /// public Task FindPickupSlotByIdAsync(long slotId, long tenantId, CancellationToken cancellationToken = default) { return context.StorePickupSlots .Where(x => x.TenantId == tenantId && x.Id == slotId) .FirstOrDefaultAsync(cancellationToken); } /// public Task AddPickupSlotsAsync(IEnumerable slots, CancellationToken cancellationToken = default) { return context.StorePickupSlots.AddRangeAsync(slots, cancellationToken); } /// public Task UpdatePickupSlotAsync(StorePickupSlot slot, CancellationToken cancellationToken = default) { context.StorePickupSlots.Update(slot); return Task.CompletedTask; } /// public async Task> GetShiftsAsync(long storeId, long tenantId, DateTime? from = null, DateTime? to = null, CancellationToken cancellationToken = default) { var query = context.StoreEmployeeShifts .AsNoTracking() .Where(x => x.TenantId == tenantId && x.StoreId == storeId); if (from.HasValue) { query = query.Where(x => x.ShiftDate >= from.Value.Date); } if (to.HasValue) { query = query.Where(x => x.ShiftDate <= to.Value.Date); } var shifts = await query .OrderBy(x => x.ShiftDate) .ThenBy(x => x.StartTime) .ToListAsync(cancellationToken); return shifts; } /// public Task FindShiftByIdAsync(long shiftId, long tenantId, CancellationToken cancellationToken = default) { return context.StoreEmployeeShifts .Where(x => x.TenantId == tenantId && x.Id == shiftId) .FirstOrDefaultAsync(cancellationToken); } /// public Task AddStoreAsync(Store store, CancellationToken cancellationToken = default) { return context.Stores.AddAsync(store, cancellationToken).AsTask(); } /// public Task AddBusinessHoursAsync(IEnumerable hours, CancellationToken cancellationToken = default) { return context.StoreBusinessHours.AddRangeAsync(hours, cancellationToken); } /// public Task UpdateBusinessHourAsync(StoreBusinessHour hour, CancellationToken cancellationToken = default) { context.StoreBusinessHours.Update(hour); return Task.CompletedTask; } /// public Task AddDeliveryZonesAsync(IEnumerable zones, CancellationToken cancellationToken = default) { return context.StoreDeliveryZones.AddRangeAsync(zones, cancellationToken); } /// public Task UpdateDeliveryZoneAsync(StoreDeliveryZone zone, CancellationToken cancellationToken = default) { context.StoreDeliveryZones.Update(zone); return Task.CompletedTask; } /// public Task AddHolidaysAsync(IEnumerable holidays, CancellationToken cancellationToken = default) { return context.StoreHolidays.AddRangeAsync(holidays, cancellationToken); } /// public Task UpdateHolidayAsync(StoreHoliday holiday, CancellationToken cancellationToken = default) { context.StoreHolidays.Update(holiday); return Task.CompletedTask; } /// public Task AddTableAreasAsync(IEnumerable areas, CancellationToken cancellationToken = default) { return context.StoreTableAreas.AddRangeAsync(areas, cancellationToken); } /// public Task UpdateTableAreaAsync(StoreTableArea area, CancellationToken cancellationToken = default) { context.StoreTableAreas.Update(area); return Task.CompletedTask; } /// public Task AddTablesAsync(IEnumerable tables, CancellationToken cancellationToken = default) { return context.StoreTables.AddRangeAsync(tables, cancellationToken); } /// public Task UpdateTableAsync(StoreTable table, CancellationToken cancellationToken = default) { context.StoreTables.Update(table); return Task.CompletedTask; } /// public Task AddShiftsAsync(IEnumerable shifts, CancellationToken cancellationToken = default) { return context.StoreEmployeeShifts.AddRangeAsync(shifts, cancellationToken); } /// public Task UpdateShiftAsync(StoreEmployeeShift shift, CancellationToken cancellationToken = default) { context.StoreEmployeeShifts.Update(shift); return Task.CompletedTask; } /// public Task SaveChangesAsync(CancellationToken cancellationToken = default) { return context.SaveChangesAsync(cancellationToken); } /// public async Task DeleteBusinessHourAsync(long businessHourId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.StoreBusinessHours .Where(x => x.TenantId == tenantId && x.Id == businessHourId) .FirstOrDefaultAsync(cancellationToken); if (existing != null) { context.StoreBusinessHours.Remove(existing); } } /// public async Task DeleteDeliveryZoneAsync(long deliveryZoneId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.StoreDeliveryZones .Where(x => x.TenantId == tenantId && x.Id == deliveryZoneId) .FirstOrDefaultAsync(cancellationToken); if (existing != null) { context.StoreDeliveryZones.Remove(existing); } } /// public async Task DeleteHolidayAsync(long holidayId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.StoreHolidays .Where(x => x.TenantId == tenantId && x.Id == holidayId) .FirstOrDefaultAsync(cancellationToken); if (existing != null) { context.StoreHolidays.Remove(existing); } } /// public async Task DeleteTableAreaAsync(long areaId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.StoreTableAreas .Where(x => x.TenantId == tenantId && x.Id == areaId) .FirstOrDefaultAsync(cancellationToken); if (existing != null) { context.StoreTableAreas.Remove(existing); } } /// public async Task DeleteTableAsync(long tableId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.StoreTables .Where(x => x.TenantId == tenantId && x.Id == tableId) .FirstOrDefaultAsync(cancellationToken); if (existing != null) { context.StoreTables.Remove(existing); } } /// public async Task DeletePickupSlotAsync(long slotId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.StorePickupSlots .Where(x => x.TenantId == tenantId && x.Id == slotId) .FirstOrDefaultAsync(cancellationToken); if (existing != null) { context.StorePickupSlots.Remove(existing); } } /// public async Task DeleteShiftAsync(long shiftId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.StoreEmployeeShifts .Where(x => x.TenantId == tenantId && x.Id == shiftId) .FirstOrDefaultAsync(cancellationToken); if (existing != null) { context.StoreEmployeeShifts.Remove(existing); } } /// public Task UpdateStoreAsync(Store store, CancellationToken cancellationToken = default) { context.Stores.Update(store); return Task.CompletedTask; } /// public async Task DeleteStoreAsync(long storeId, long tenantId, CancellationToken cancellationToken = default) { var existing = await context.Stores .Where(x => x.TenantId == tenantId && x.Id == storeId) .FirstOrDefaultAsync(cancellationToken); if (existing == null) { return; } context.Stores.Remove(existing); } }