fix(store): enforce UTC holiday dates and exclude deleted stores
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 42s
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 42s
This commit is contained in:
@@ -95,7 +95,8 @@ internal static class StoreApiHelpers
|
|||||||
throw new BusinessException(ErrorCodes.BadRequest, $"{fieldName} 日期格式必须为 yyyy-MM-dd");
|
throw new BusinessException(ErrorCodes.BadRequest, $"{fieldName} 日期格式必须为 yyyy-MM-dd");
|
||||||
}
|
}
|
||||||
|
|
||||||
return parsed.Date;
|
// PostgreSQL timestamptz 仅接受 UTC,日期输入统一落盘为 UTC 零点。
|
||||||
|
return DateTime.SpecifyKind(parsed.Date, DateTimeKind.Utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToDateOnly(DateTime value)
|
public static string ToDateOnly(DateTime value)
|
||||||
|
|||||||
@@ -33,7 +33,13 @@ public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepos
|
|||||||
query = query.Where(x => x.TenantId == tenantId.Value);
|
query = query.Where(x => x.TenantId == tenantId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. (空行后) 返回门店实体
|
// 3. (空行后) 默认排除已删除门店(双保险)
|
||||||
|
if (!includeDeleted)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.DeletedAt == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. (空行后) 返回门店实体
|
||||||
return query
|
return query
|
||||||
.Where(x => x.Id == storeId)
|
.Where(x => x.Id == storeId)
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
@@ -44,7 +50,10 @@ public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepos
|
|||||||
{
|
{
|
||||||
return await context.Stores
|
return await context.Stores
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(x => x.TenantId == tenantId && x.MerchantId == merchantId)
|
.Where(x =>
|
||||||
|
x.TenantId == tenantId &&
|
||||||
|
x.MerchantId == merchantId &&
|
||||||
|
x.DeletedAt == null)
|
||||||
.OrderBy(x => x.Name)
|
.OrderBy(x => x.Name)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -81,31 +90,37 @@ public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepos
|
|||||||
query = query.Where(x => x.MerchantId == merchantId.Value);
|
query = query.Where(x => x.MerchantId == merchantId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. (空行后) 可选过滤:状态
|
// 4. (空行后) 默认排除已删除门店(双保险)
|
||||||
|
if (!includeDeleted)
|
||||||
|
{
|
||||||
|
query = query.Where(x => x.DeletedAt == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. (空行后) 可选过滤:状态
|
||||||
if (status.HasValue)
|
if (status.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(x => x.Status == status.Value);
|
query = query.Where(x => x.Status == status.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. (空行后) 可选过滤:审核状态
|
// 6. (空行后) 可选过滤:审核状态
|
||||||
if (auditStatus.HasValue)
|
if (auditStatus.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(x => x.AuditStatus == auditStatus.Value);
|
query = query.Where(x => x.AuditStatus == auditStatus.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. (空行后) 可选过滤:经营状态
|
// 7. (空行后) 可选过滤:经营状态
|
||||||
if (businessStatus.HasValue)
|
if (businessStatus.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(x => x.BusinessStatus == businessStatus.Value);
|
query = query.Where(x => x.BusinessStatus == businessStatus.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. (空行后) 可选过滤:主体类型
|
// 8. (空行后) 可选过滤:主体类型
|
||||||
if (ownershipType.HasValue)
|
if (ownershipType.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(x => x.OwnershipType == ownershipType.Value);
|
query = query.Where(x => x.OwnershipType == ownershipType.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. (空行后) 可选过滤:关键词
|
// 9. (空行后) 可选过滤:关键词
|
||||||
if (!string.IsNullOrWhiteSpace(keyword))
|
if (!string.IsNullOrWhiteSpace(keyword))
|
||||||
{
|
{
|
||||||
var trimmed = keyword.Trim();
|
var trimmed = keyword.Trim();
|
||||||
@@ -115,7 +130,7 @@ public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepos
|
|||||||
(x.Phone != null && x.Phone.Contains(trimmed)));
|
(x.Phone != null && x.Phone.Contains(trimmed)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. (空行后) 查询并返回结果
|
// 10. (空行后) 查询并返回结果
|
||||||
var stores = await query
|
var stores = await query
|
||||||
.OrderBy(x => x.Name)
|
.OrderBy(x => x.Name)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
@@ -142,6 +157,7 @@ public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepos
|
|||||||
var coordinates = await context.Stores
|
var coordinates = await context.Stores
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.Where(x => x.TenantId == tenantId && x.MerchantId == merchantId)
|
.Where(x => x.TenantId == tenantId && x.MerchantId == merchantId)
|
||||||
|
.Where(x => x.DeletedAt == null)
|
||||||
.Where(x => x.Longitude.HasValue && x.Latitude.HasValue)
|
.Where(x => x.Longitude.HasValue && x.Latitude.HasValue)
|
||||||
.Select(x => new { Longitude = x.Longitude!.Value, Latitude = x.Latitude!.Value })
|
.Select(x => new { Longitude = x.Longitude!.Value, Latitude = x.Latitude!.Value })
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
@@ -176,7 +192,10 @@ public sealed class EfStoreRepository(TakeoutAppDbContext context) : IStoreRepos
|
|||||||
query = query.Where(x => x.TenantId == tenantId.Value);
|
query = query.Where(x => x.TenantId == tenantId.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. (空行后) 分组统计门店数量
|
// 2. (空行后) 排除已删除门店
|
||||||
|
query = query.Where(x => x.DeletedAt == null);
|
||||||
|
|
||||||
|
// 3. (空行后) 分组统计门店数量
|
||||||
return await query
|
return await query
|
||||||
.Where(x => merchantIds.Contains(x.MerchantId))
|
.Where(x => merchantIds.Contains(x.MerchantId))
|
||||||
.GroupBy(x => x.MerchantId)
|
.GroupBy(x => x.MerchantId)
|
||||||
|
|||||||
Reference in New Issue
Block a user