feat: 门店模块移除租户上下文依赖
This commit is contained in:
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,28 +14,27 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class CreateStoreBusinessHourCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<CreateStoreBusinessHourCommandHandler> logger)
|
||||
: IRequestHandler<CreateStoreBusinessHourCommand, StoreBusinessHourDto>
|
||||
{
|
||||
private readonly IStoreRepository _storeRepository = storeRepository;
|
||||
private readonly ITenantProvider _tenantProvider = tenantProvider;
|
||||
private readonly ILogger<CreateStoreBusinessHourCommandHandler> _logger = logger;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<StoreBusinessHourDto> Handle(CreateStoreBusinessHourCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = _tenantProvider.GetCurrentTenantId();
|
||||
var store = await _storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await _storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 构建实体
|
||||
// 2. (空行后) 构建实体并写入租户
|
||||
var hour = new StoreBusinessHour
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = request.StoreId,
|
||||
DayOfWeek = request.DayOfWeek,
|
||||
HourType = request.HourType,
|
||||
@@ -46,12 +44,12 @@ public sealed class CreateStoreBusinessHourCommandHandler(
|
||||
Notes = request.Notes?.Trim()
|
||||
};
|
||||
|
||||
// 3. 持久化
|
||||
// 3. (空行后) 持久化
|
||||
await _storeRepository.AddBusinessHoursAsync(new[] { hour }, cancellationToken);
|
||||
await _storeRepository.SaveChangesAsync(cancellationToken);
|
||||
_logger.LogInformation("创建营业时段 {BusinessHourId} 对应门店 {StoreId}", hour.Id, request.StoreId);
|
||||
|
||||
// 4. 返回 DTO
|
||||
// 4. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(hour);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -17,7 +16,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
public sealed class CreateStoreEmployeeShiftCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
IMerchantRepository merchantRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<CreateStoreEmployeeShiftCommandHandler> logger)
|
||||
: IRequestHandler<CreateStoreEmployeeShiftCommand, StoreEmployeeShiftDto>
|
||||
{
|
||||
@@ -25,21 +23,21 @@ public sealed class CreateStoreEmployeeShiftCommandHandler(
|
||||
public async Task<StoreEmployeeShiftDto> Handle(CreateStoreEmployeeShiftCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 校验员工归属与状态
|
||||
// 2. (空行后) 校验员工归属与状态
|
||||
var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken);
|
||||
if (staff is null || (staff.StoreId.HasValue && staff.StoreId != request.StoreId))
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "员工不存在或不属于该门店");
|
||||
}
|
||||
|
||||
// 3. 校验日期与冲突
|
||||
// 3. (空行后) 校验日期与冲突
|
||||
var from = request.ShiftDate.Date;
|
||||
var to = request.ShiftDate.Date;
|
||||
var shifts = await storeRepository.GetShiftsAsync(request.StoreId, tenantId, from, to, cancellationToken);
|
||||
@@ -49,9 +47,10 @@ public sealed class CreateStoreEmployeeShiftCommandHandler(
|
||||
throw new BusinessException(ErrorCodes.Conflict, "该员工当日已存在排班");
|
||||
}
|
||||
|
||||
// 4. 构建实体
|
||||
// 4. (空行后) 构建实体并写入租户
|
||||
var shift = new StoreEmployeeShift
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = request.StoreId,
|
||||
StaffId = request.StaffId,
|
||||
ShiftDate = request.ShiftDate.Date,
|
||||
@@ -61,12 +60,12 @@ public sealed class CreateStoreEmployeeShiftCommandHandler(
|
||||
Notes = request.Notes?.Trim()
|
||||
};
|
||||
|
||||
// 5. 持久化
|
||||
// 5. (空行后) 持久化
|
||||
await storeRepository.AddShiftsAsync(new[] { shift }, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("创建排班 {ShiftId} 员工 {StaffId} 门店 {StoreId}", shift.Id, shift.StaffId, shift.StoreId);
|
||||
|
||||
// 6. 返回 DTO
|
||||
// 6. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(shift);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class CreateStorePickupSlotCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<CreateStorePickupSlotCommandHandler> logger)
|
||||
: IRequestHandler<CreateStorePickupSlotCommand, StorePickupSlotDto>
|
||||
{
|
||||
@@ -23,14 +21,14 @@ public sealed class CreateStorePickupSlotCommandHandler(
|
||||
public async Task<StorePickupSlotDto> Handle(CreateStorePickupSlotCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 新建档期
|
||||
// 2. (空行后) 新建档期
|
||||
var slot = new StorePickupSlot
|
||||
{
|
||||
TenantId = tenantId,
|
||||
|
||||
@@ -7,7 +7,6 @@ using TakeoutSaaS.Domain.Stores.Enums;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -16,7 +15,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class CreateStoreQualificationCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<CreateStoreQualificationCommandHandler> logger)
|
||||
: IRequestHandler<CreateStoreQualificationCommand, StoreQualificationDto>
|
||||
{
|
||||
@@ -24,12 +22,12 @@ public sealed class CreateStoreQualificationCommandHandler(
|
||||
public async Task<StoreQualificationDto> Handle(CreateStoreQualificationCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 审核中门店禁止修改资质
|
||||
if (store.AuditStatus == StoreAuditStatus.Pending)
|
||||
@@ -49,6 +47,7 @@ public sealed class CreateStoreQualificationCommandHandler(
|
||||
{
|
||||
existing = new StoreQualification
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = request.StoreId,
|
||||
QualificationType = request.QualificationType,
|
||||
FileUrl = request.FileUrl.Trim(),
|
||||
|
||||
@@ -8,7 +8,6 @@ using TakeoutSaaS.Domain.Merchants.Repositories;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -18,7 +17,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
public sealed class CreateStoreStaffCommandHandler(
|
||||
IMerchantRepository merchantRepository,
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<CreateStoreStaffCommandHandler> logger)
|
||||
: IRequestHandler<CreateStoreStaffCommand, StoreStaffDto>
|
||||
{
|
||||
@@ -26,16 +24,17 @@ public sealed class CreateStoreStaffCommandHandler(
|
||||
public async Task<StoreStaffDto> Handle(CreateStoreStaffCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 组装员工
|
||||
// 2. (空行后) 组装员工并写入租户
|
||||
var staff = new MerchantStaff
|
||||
{
|
||||
TenantId = tenantId,
|
||||
MerchantId = store.MerchantId,
|
||||
StoreId = request.StoreId,
|
||||
Name = request.Name.Trim(),
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class CreateStoreTableAreaCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<CreateStoreTableAreaCommandHandler> logger)
|
||||
: IRequestHandler<CreateStoreTableAreaCommand, StoreTableAreaDto>
|
||||
{
|
||||
@@ -23,14 +21,14 @@ public sealed class CreateStoreTableAreaCommandHandler(
|
||||
public async Task<StoreTableAreaDto> Handle(CreateStoreTableAreaCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 校验区域名称唯一
|
||||
// 2. (空行后) 校验区域名称唯一
|
||||
var existingAreas = await storeRepository.GetTableAreasAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var hasDuplicate = existingAreas.Any(x => x.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
|
||||
if (hasDuplicate)
|
||||
@@ -38,21 +36,22 @@ public sealed class CreateStoreTableAreaCommandHandler(
|
||||
throw new BusinessException(ErrorCodes.Conflict, "区域名称已存在");
|
||||
}
|
||||
|
||||
// 3. 构建实体
|
||||
// 3. (空行后) 构建实体并写入租户
|
||||
var area = new StoreTableArea
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = request.StoreId,
|
||||
Name = request.Name.Trim(),
|
||||
Description = request.Description?.Trim(),
|
||||
SortOrder = request.SortOrder
|
||||
};
|
||||
|
||||
// 4. 持久化
|
||||
// 4. (空行后) 持久化
|
||||
await storeRepository.AddTableAreasAsync(new[] { area }, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("创建桌台区域 {AreaId} 对应门店 {StoreId}", area.Id, request.StoreId);
|
||||
|
||||
// 5. 返回 DTO
|
||||
// 5. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(area);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,32 +10,37 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreBusinessHourCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<DeleteStoreBusinessHourCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStoreBusinessHourCommand, bool>
|
||||
{
|
||||
private readonly IStoreRepository _storeRepository = storeRepository;
|
||||
private readonly ITenantProvider _tenantProvider = tenantProvider;
|
||||
private readonly ILogger<DeleteStoreBusinessHourCommandHandler> _logger = logger;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> Handle(DeleteStoreBusinessHourCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取时段
|
||||
var tenantId = _tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await _storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取时段
|
||||
var existing = await _storeRepository.FindBusinessHourByIdAsync(request.BusinessHourId, tenantId, cancellationToken);
|
||||
if (existing is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 校验门店归属
|
||||
// 3. (空行后) 校验门店归属
|
||||
if (existing.StoreId != request.StoreId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 删除
|
||||
// 4. (空行后) 删除
|
||||
await _storeRepository.DeleteBusinessHourAsync(request.BusinessHourId, tenantId, cancellationToken);
|
||||
await _storeRepository.SaveChangesAsync(cancellationToken);
|
||||
_logger.LogInformation("删除营业时段 {BusinessHourId} 对应门店 {StoreId}", request.BusinessHourId, request.StoreId);
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,26 +10,24 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<DeleteStoreCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStoreCommand, bool>
|
||||
{
|
||||
private readonly IStoreRepository _storeRepository = storeRepository;
|
||||
private readonly ITenantProvider _tenantProvider = tenantProvider;
|
||||
private readonly ILogger<DeleteStoreCommandHandler> _logger = logger;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> Handle(DeleteStoreCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验存在性
|
||||
var tenantId = _tenantProvider.GetCurrentTenantId();
|
||||
var existing = await _storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
// 1. 校验存在性(跨租户)
|
||||
var existing = await _storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (existing == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tenantId = existing.TenantId;
|
||||
|
||||
// 2. 删除
|
||||
// 2. (空行后) 删除
|
||||
await _storeRepository.DeleteStoreAsync(request.StoreId, tenantId, cancellationToken);
|
||||
await _storeRepository.SaveChangesAsync(cancellationToken);
|
||||
_logger.LogInformation("删除门店 {StoreId}", request.StoreId);
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,22 +10,28 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreEmployeeShiftCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<DeleteStoreEmployeeShiftCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStoreEmployeeShiftCommand, bool>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> Handle(DeleteStoreEmployeeShiftCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取排班
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取排班
|
||||
var shift = await storeRepository.FindShiftByIdAsync(request.ShiftId, tenantId, cancellationToken);
|
||||
if (shift is null || shift.StoreId != request.StoreId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 删除
|
||||
// 3. (空行后) 删除
|
||||
await storeRepository.DeleteShiftAsync(request.ShiftId, tenantId, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("删除排班 {ShiftId} 门店 {StoreId}", request.ShiftId, request.StoreId);
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,15 +10,28 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStorePickupSlotCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<DeleteStorePickupSlotCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStorePickupSlotCommand, bool>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> Handle(DeleteStorePickupSlotCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 删除档期
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 校验档期归属
|
||||
var slot = await storeRepository.FindPickupSlotByIdAsync(request.SlotId, tenantId, cancellationToken);
|
||||
if (slot is null || slot.StoreId != request.StoreId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. (空行后) 删除档期
|
||||
await storeRepository.DeletePickupSlotAsync(request.SlotId, tenantId, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("删除自提档期 {SlotId}", request.SlotId);
|
||||
|
||||
@@ -5,7 +5,6 @@ using TakeoutSaaS.Domain.Stores.Enums;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -14,7 +13,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreQualificationCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<DeleteStoreQualificationCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStoreQualificationCommand, bool>
|
||||
{
|
||||
@@ -22,12 +20,12 @@ public sealed class DeleteStoreQualificationCommandHandler(
|
||||
public async Task<bool> Handle(DeleteStoreQualificationCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 审核中门店禁止删除资质
|
||||
if (store.AuditStatus == StoreAuditStatus.Pending)
|
||||
|
||||
@@ -2,7 +2,7 @@ using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Merchants.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,21 +11,29 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreStaffCommandHandler(
|
||||
IMerchantRepository merchantRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
IStoreRepository storeRepository,
|
||||
ILogger<DeleteStoreStaffCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStoreStaffCommand, bool>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> Handle(DeleteStoreStaffCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 校验员工归属
|
||||
var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken);
|
||||
if (staff is null || staff.StoreId != request.StoreId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 逻辑删除未定义,直接物理删除
|
||||
// 3. (空行后) 逻辑删除未定义,直接物理删除
|
||||
await merchantRepository.DeleteStaffAsync(staff.Id, tenantId, cancellationToken);
|
||||
await merchantRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("删除门店员工 {StaffId} 门店 {StoreId}", request.StaffId, request.StoreId);
|
||||
|
||||
@@ -4,7 +4,6 @@ using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -13,28 +12,34 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreTableAreaCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<DeleteStoreTableAreaCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStoreTableAreaCommand, bool>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> Handle(DeleteStoreTableAreaCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取区域
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取区域
|
||||
var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId, tenantId, cancellationToken);
|
||||
if (area is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 校验门店归属
|
||||
// 3. (空行后) 校验门店归属
|
||||
if (area.StoreId != request.StoreId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3. 校验区域下无桌码
|
||||
// 4. (空行后) 校验区域下无桌码
|
||||
var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var hasTable = tables.Any(x => x.AreaId == request.AreaId);
|
||||
if (hasTable)
|
||||
@@ -42,7 +47,7 @@ public sealed class DeleteStoreTableAreaCommandHandler(
|
||||
throw new BusinessException(ErrorCodes.Conflict, "区域下仍有桌码,无法删除");
|
||||
}
|
||||
|
||||
// 4. 删除
|
||||
// 5. (空行后) 删除
|
||||
await storeRepository.DeleteTableAreaAsync(request.AreaId, tenantId, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("删除桌台区域 {AreaId} 对应门店 {StoreId}", request.AreaId, request.StoreId);
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,22 +10,28 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreTableCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<DeleteStoreTableCommandHandler> logger)
|
||||
: IRequestHandler<DeleteStoreTableCommand, bool>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> Handle(DeleteStoreTableCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取桌码
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取桌码
|
||||
var table = await storeRepository.FindTableByIdAsync(request.TableId, tenantId, cancellationToken);
|
||||
if (table is null || table.StoreId != request.StoreId)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. 删除
|
||||
// 3. (空行后) 删除
|
||||
await storeRepository.DeleteTableAsync(request.TableId, tenantId, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("删除桌码 {TableId} 对应门店 {StoreId}", request.TableId, request.StoreId);
|
||||
|
||||
@@ -7,7 +7,6 @@ using QRCoder;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -16,7 +15,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ExportStoreTableQRCodesQueryHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<ExportStoreTableQRCodesQueryHandler> logger)
|
||||
: IRequestHandler<ExportStoreTableQRCodesQuery, StoreTableExportResult?>
|
||||
{
|
||||
@@ -24,14 +22,14 @@ public sealed class ExportStoreTableQRCodesQueryHandler(
|
||||
public async Task<StoreTableExportResult?> Handle(ExportStoreTableQRCodesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 获取桌码列表
|
||||
// 2. (空行后) 获取桌码列表
|
||||
var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken);
|
||||
if (request.AreaId.HasValue)
|
||||
{
|
||||
|
||||
@@ -7,7 +7,6 @@ using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -16,7 +15,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class GenerateStoreTablesCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<GenerateStoreTablesCommandHandler> logger)
|
||||
: IRequestHandler<GenerateStoreTablesCommand, IReadOnlyList<StoreTableDto>>
|
||||
{
|
||||
@@ -24,14 +22,14 @@ public sealed class GenerateStoreTablesCommandHandler(
|
||||
public async Task<IReadOnlyList<StoreTableDto>> Handle(GenerateStoreTablesCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 校验区域归属
|
||||
// 2. (空行后) 校验区域归属
|
||||
if (request.AreaId.HasValue)
|
||||
{
|
||||
var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId.Value, tenantId, cancellationToken);
|
||||
@@ -41,7 +39,7 @@ public sealed class GenerateStoreTablesCommandHandler(
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 校验桌码唯一性
|
||||
// 3. (空行后) 校验桌码唯一性
|
||||
var existingTables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var newCodes = Enumerable.Range(request.StartNumber, request.Count)
|
||||
.Select(i => $"{request.TableCodePrefix.Trim()}{i}")
|
||||
@@ -52,9 +50,10 @@ public sealed class GenerateStoreTablesCommandHandler(
|
||||
throw new BusinessException(ErrorCodes.Conflict, "桌码已存在,生成失败");
|
||||
}
|
||||
|
||||
// 4. 构建实体
|
||||
// 4. (空行后) 构建实体并写入租户
|
||||
var tables = newCodes.Select(code => new StoreTable
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = request.StoreId,
|
||||
AreaId = request.AreaId,
|
||||
TableCode = code,
|
||||
@@ -62,12 +61,12 @@ public sealed class GenerateStoreTablesCommandHandler(
|
||||
Tags = request.Tags?.Trim()
|
||||
}).ToList();
|
||||
|
||||
// 5. 持久化
|
||||
// 5. (空行后) 持久化
|
||||
await storeRepository.AddTablesAsync(tables, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("批量创建桌码 {Count} 条 对应门店 {StoreId}", tables.Count, request.StoreId);
|
||||
|
||||
// 6. 返回 DTO
|
||||
// 6. (空行后) 返回 DTO
|
||||
return tables.Select(StoreMapping.ToDto).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -10,22 +9,27 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// 可用自提档期查询处理器。
|
||||
/// </summary>
|
||||
public sealed class GetAvailablePickupSlotsQueryHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
IStoreRepository storeRepository)
|
||||
: IRequestHandler<GetAvailablePickupSlotsQuery, IReadOnlyList<StorePickupSlotDto>>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StorePickupSlotDto>> Handle(GetAvailablePickupSlotsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
var date = request.Date.Date;
|
||||
// 1. 读取配置
|
||||
// 2. (空行后) 读取配置
|
||||
var setting = await storeRepository.GetPickupSettingAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var allowDays = setting?.AllowDaysAhead ?? 0;
|
||||
var allowToday = setting?.AllowToday ?? false;
|
||||
var defaultCutoff = setting?.DefaultCutoffMinutes ?? 30;
|
||||
|
||||
// 2. 校验日期范围
|
||||
// 3. (空行后) 校验日期范围
|
||||
if (!allowToday && date == DateTime.UtcNow.Date)
|
||||
{
|
||||
return [];
|
||||
@@ -36,13 +40,13 @@ public sealed class GetAvailablePickupSlotsQueryHandler(
|
||||
return [];
|
||||
}
|
||||
|
||||
// 3. 读取档期
|
||||
// 4. (空行后) 读取档期
|
||||
var slots = await storeRepository.GetPickupSlotsAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var weekday = (int)date.DayOfWeek;
|
||||
weekday = weekday == 0 ? 7 : weekday;
|
||||
var nowUtc = DateTime.UtcNow;
|
||||
|
||||
// 4. 过滤可用
|
||||
// 5. (空行后) 过滤可用
|
||||
var available = slots
|
||||
.Where(x => x.IsEnabled && ContainsDay(x.Weekdays, weekday))
|
||||
.Select(slot =>
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -10,20 +9,28 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// 获取自提配置处理器。
|
||||
/// </summary>
|
||||
public sealed class GetStorePickupSettingQueryHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
IStoreRepository storeRepository)
|
||||
: IRequestHandler<GetStorePickupSettingQuery, StorePickupSettingDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<StorePickupSettingDto?> Handle(GetStorePickupSettingQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取配置
|
||||
var setting = await storeRepository.GetPickupSettingAsync(request.StoreId, tenantId, cancellationToken);
|
||||
if (setting is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. (空行后) 返回 DTO
|
||||
return new StorePickupSettingDto
|
||||
{
|
||||
Id = setting.Id,
|
||||
|
||||
@@ -5,7 +5,6 @@ using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -14,7 +13,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class GetStoreTableContextQueryHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<GetStoreTableContextQueryHandler> logger)
|
||||
: IRequestHandler<GetStoreTableContextQuery, StoreTableContextDto?>
|
||||
{
|
||||
@@ -22,7 +20,7 @@ public sealed class GetStoreTableContextQueryHandler(
|
||||
public async Task<StoreTableContextDto?> Handle(GetStoreTableContextQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询桌码
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var tenantId = request.TenantId;
|
||||
var table = await storeRepository.FindTableByCodeAsync(request.TableCode, tenantId, cancellationToken);
|
||||
if (table is null)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@ using MediatR;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,8 +10,7 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// 排班列表查询处理器。
|
||||
/// </summary>
|
||||
public sealed class ListStoreEmployeeShiftsQueryHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
IStoreRepository storeRepository)
|
||||
: IRequestHandler<ListStoreEmployeeShiftsQuery, IReadOnlyList<StoreEmployeeShiftDto>>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -21,9 +19,14 @@ public sealed class ListStoreEmployeeShiftsQueryHandler(
|
||||
// 1. 时间范围
|
||||
var from = request.From ?? DateTime.UtcNow.Date;
|
||||
var to = request.To ?? from.AddDays(7);
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 查询排班
|
||||
// 2. (空行后) 查询排班
|
||||
var shifts = await storeRepository.GetShiftsAsync(request.StoreId, tenantId, from, to, cancellationToken);
|
||||
|
||||
if (request.StaffId.HasValue)
|
||||
@@ -31,7 +34,7 @@ public sealed class ListStoreEmployeeShiftsQueryHandler(
|
||||
shifts = shifts.Where(x => x.StaffId == request.StaffId.Value).ToList();
|
||||
}
|
||||
|
||||
// 3. 映射 DTO
|
||||
// 3. (空行后) 映射 DTO
|
||||
return shifts.Select(StoreMapping.ToDto).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ using MediatR;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -10,14 +9,21 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// 自提档期列表查询处理器。
|
||||
/// </summary>
|
||||
public sealed class ListStorePickupSlotsQueryHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
IStoreRepository storeRepository)
|
||||
: IRequestHandler<ListStorePickupSlotsQuery, IReadOnlyList<StorePickupSlotDto>>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StorePickupSlotDto>> Handle(ListStorePickupSlotsQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 查询档期列表
|
||||
var slots = await storeRepository.GetPickupSlotsAsync(request.StoreId, tenantId, cancellationToken);
|
||||
return slots
|
||||
.Select(x => new StorePickupSlotDto
|
||||
|
||||
@@ -4,7 +4,6 @@ using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Merchants.Repositories;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -13,22 +12,21 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ListStoreStaffQueryHandler(
|
||||
IMerchantRepository merchantRepository,
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
IStoreRepository storeRepository)
|
||||
: IRequestHandler<ListStoreStaffQuery, IReadOnlyList<StoreStaffDto>>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreStaffDto>> Handle(ListStoreStaffQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 查询员工
|
||||
// 2. (空行后) 查询员工
|
||||
var staffs = await merchantRepository.GetStaffByStoreAsync(request.StoreId, tenantId, cancellationToken);
|
||||
|
||||
if (request.RoleType.HasValue)
|
||||
@@ -41,7 +39,7 @@ public sealed class ListStoreStaffQueryHandler(
|
||||
staffs = staffs.Where(x => x.Status == request.Status.Value).ToList();
|
||||
}
|
||||
|
||||
// 3. 映射 DTO
|
||||
// 3. (空行后) 映射 DTO
|
||||
return staffs.Select(StoreMapping.ToDto).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,24 +3,30 @@ using MediatR;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 桌台区域列表查询处理器。
|
||||
/// </summary>
|
||||
public sealed class ListStoreTableAreasQueryHandler(IStoreRepository storeRepository, ITenantProvider tenantProvider)
|
||||
public sealed class ListStoreTableAreasQueryHandler(IStoreRepository storeRepository)
|
||||
: IRequestHandler<ListStoreTableAreasQuery, IReadOnlyList<StoreTableAreaDto>>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreTableAreaDto>> Handle(ListStoreTableAreasQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询区域列表
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 查询门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 查询区域列表
|
||||
var areas = await storeRepository.GetTableAreasAsync(request.StoreId, tenantId, cancellationToken);
|
||||
|
||||
// 2. 映射 DTO
|
||||
// 3. (空行后) 映射 DTO
|
||||
return areas.Select(StoreMapping.ToDto).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ using MediatR;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -11,18 +10,24 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// 桌码列表查询处理器。
|
||||
/// </summary>
|
||||
public sealed class ListStoreTablesQueryHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider)
|
||||
IStoreRepository storeRepository)
|
||||
: IRequestHandler<ListStoreTablesQuery, IReadOnlyList<StoreTableDto>>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<IReadOnlyList<StoreTableDto>> Handle(ListStoreTablesQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询桌码列表
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 查询门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 查询桌码列表
|
||||
var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken);
|
||||
|
||||
// 2. 过滤
|
||||
// 3. (空行后) 过滤
|
||||
if (request.AreaId.HasValue)
|
||||
{
|
||||
tables = tables.Where(x => x.AreaId == request.AreaId.Value).ToList();
|
||||
@@ -33,7 +38,7 @@ public sealed class ListStoreTablesQueryHandler(
|
||||
tables = tables.Where(x => x.Status == request.Status.Value).ToList();
|
||||
}
|
||||
|
||||
// 3. 映射 DTO
|
||||
// 4. (空行后) 映射 DTO
|
||||
return tables.Select(StoreMapping.ToDto).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Security;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -17,7 +16,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class SubmitStoreAuditCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ICurrentUserAccessor currentUserAccessor,
|
||||
IMediator mediator,
|
||||
ILogger<SubmitStoreAuditCommandHandler> logger)
|
||||
@@ -27,12 +25,12 @@ public sealed class SubmitStoreAuditCommandHandler(
|
||||
public async Task<bool> Handle(SubmitStoreAuditCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
if (store.AuditStatus is not StoreAuditStatus.Draft and not StoreAuditStatus.Rejected)
|
||||
{
|
||||
@@ -53,6 +51,7 @@ public sealed class SubmitStoreAuditCommandHandler(
|
||||
await storeRepository.UpdateStoreAsync(store, cancellationToken);
|
||||
await storeRepository.AddAuditRecordAsync(new StoreAuditRecord
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = store.Id,
|
||||
Action = StoreAuditAction.AutoActivate,
|
||||
PreviousStatus = previousStatus,
|
||||
@@ -87,6 +86,7 @@ public sealed class SubmitStoreAuditCommandHandler(
|
||||
await storeRepository.UpdateStoreAsync(store, cancellationToken);
|
||||
await storeRepository.AddAuditRecordAsync(new StoreAuditRecord
|
||||
{
|
||||
TenantId = tenantId,
|
||||
StoreId = store.Id,
|
||||
Action = action,
|
||||
PreviousStatus = previous,
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Stores.Enums;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ToggleBusinessStatusCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<ToggleBusinessStatusCommandHandler> logger)
|
||||
: IRequestHandler<ToggleBusinessStatusCommand, StoreDto>
|
||||
{
|
||||
@@ -23,8 +21,7 @@ public sealed class ToggleBusinessStatusCommandHandler(
|
||||
public async Task<StoreDto> Handle(ToggleBusinessStatusCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,32 +14,37 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpdateStoreBusinessHourCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpdateStoreBusinessHourCommandHandler> logger)
|
||||
: IRequestHandler<UpdateStoreBusinessHourCommand, StoreBusinessHourDto?>
|
||||
{
|
||||
private readonly IStoreRepository _storeRepository = storeRepository;
|
||||
private readonly ITenantProvider _tenantProvider = tenantProvider;
|
||||
private readonly ILogger<UpdateStoreBusinessHourCommandHandler> _logger = logger;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<StoreBusinessHourDto?> Handle(UpdateStoreBusinessHourCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取时段
|
||||
var tenantId = _tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await _storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取时段
|
||||
var existing = await _storeRepository.FindBusinessHourByIdAsync(request.BusinessHourId, tenantId, cancellationToken);
|
||||
if (existing is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 校验门店归属
|
||||
// 3. (空行后) 校验门店归属
|
||||
if (existing.StoreId != request.StoreId)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "营业时段不属于该门店");
|
||||
}
|
||||
|
||||
// 3. 更新字段
|
||||
// 4. (空行后) 更新字段
|
||||
existing.DayOfWeek = request.DayOfWeek;
|
||||
existing.HourType = request.HourType;
|
||||
existing.StartTime = request.StartTime;
|
||||
@@ -48,12 +52,12 @@ public sealed class UpdateStoreBusinessHourCommandHandler(
|
||||
existing.CapacityLimit = request.CapacityLimit;
|
||||
existing.Notes = request.Notes?.Trim();
|
||||
|
||||
// 4. 持久化
|
||||
// 5. (空行后) 持久化
|
||||
await _storeRepository.UpdateBusinessHourAsync(existing, cancellationToken);
|
||||
await _storeRepository.SaveChangesAsync(cancellationToken);
|
||||
_logger.LogInformation("更新营业时段 {BusinessHourId} 对应门店 {StoreId}", existing.Id, existing.StoreId);
|
||||
|
||||
// 5. 返回 DTO
|
||||
// 6. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(existing);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Merchants.Repositories;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -16,35 +15,41 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
public sealed class UpdateStoreEmployeeShiftCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
IMerchantRepository merchantRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpdateStoreEmployeeShiftCommandHandler> logger)
|
||||
: IRequestHandler<UpdateStoreEmployeeShiftCommand, StoreEmployeeShiftDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<StoreEmployeeShiftDto?> Handle(UpdateStoreEmployeeShiftCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取排班
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取排班
|
||||
var shift = await storeRepository.FindShiftByIdAsync(request.ShiftId, tenantId, cancellationToken);
|
||||
if (shift is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 校验门店归属
|
||||
// 3. (空行后) 校验门店归属
|
||||
if (shift.StoreId != request.StoreId)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "排班不属于该门店");
|
||||
}
|
||||
|
||||
// 3. 校验员工归属
|
||||
// 4. (空行后) 校验员工归属
|
||||
var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken);
|
||||
if (staff is null || (staff.StoreId.HasValue && staff.StoreId != request.StoreId))
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "员工不存在或不属于该门店");
|
||||
}
|
||||
|
||||
// 4. 冲突校验
|
||||
// 5. (空行后) 冲突校验
|
||||
var shifts = await storeRepository.GetShiftsAsync(request.StoreId, tenantId, request.ShiftDate.Date, request.ShiftDate.Date, cancellationToken);
|
||||
var hasConflict = shifts.Any(x => x.Id != request.ShiftId && x.StaffId == request.StaffId && x.ShiftDate == request.ShiftDate);
|
||||
if (hasConflict)
|
||||
@@ -52,7 +57,7 @@ public sealed class UpdateStoreEmployeeShiftCommandHandler(
|
||||
throw new BusinessException(ErrorCodes.Conflict, "该员工当日已存在排班");
|
||||
}
|
||||
|
||||
// 5. 更新字段
|
||||
// 6. (空行后) 更新字段
|
||||
shift.StaffId = request.StaffId;
|
||||
shift.ShiftDate = request.ShiftDate.Date;
|
||||
shift.StartTime = request.StartTime;
|
||||
@@ -60,12 +65,12 @@ public sealed class UpdateStoreEmployeeShiftCommandHandler(
|
||||
shift.RoleType = request.RoleType;
|
||||
shift.Notes = request.Notes?.Trim();
|
||||
|
||||
// 6. 持久化
|
||||
// 7. (空行后) 持久化
|
||||
await storeRepository.UpdateShiftAsync(shift, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("更新排班 {ShiftId} 员工 {StaffId} 门店 {StoreId}", shift.Id, shift.StaffId, shift.StoreId);
|
||||
|
||||
// 7. 返回 DTO
|
||||
// 8. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(shift);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -14,22 +13,28 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpdateStorePickupSlotCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpdateStorePickupSlotCommandHandler> logger)
|
||||
: IRequestHandler<UpdateStorePickupSlotCommand, StorePickupSlotDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<StorePickupSlotDto?> Handle(UpdateStorePickupSlotCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 查询档期
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 查询档期
|
||||
var slot = await storeRepository.FindPickupSlotByIdAsync(request.SlotId, tenantId, cancellationToken);
|
||||
if (slot is null || slot.StoreId != request.StoreId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 更新字段
|
||||
// 3. (空行后) 更新字段
|
||||
slot.Name = request.Name.Trim();
|
||||
slot.StartTime = request.StartTime;
|
||||
slot.EndTime = request.EndTime;
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Stores.Enums;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpdateStoreQualificationCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpdateStoreQualificationCommandHandler> logger)
|
||||
: IRequestHandler<UpdateStoreQualificationCommand, StoreQualificationDto?>
|
||||
{
|
||||
@@ -23,12 +21,12 @@ public sealed class UpdateStoreQualificationCommandHandler(
|
||||
public async Task<StoreQualificationDto?> Handle(UpdateStoreQualificationCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 审核中门店禁止修改资质
|
||||
if (store.AuditStatus == StoreAuditStatus.Pending)
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Merchants.Repositories;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -16,7 +15,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
public sealed class UpdateStoreStaffCommandHandler(
|
||||
IMerchantRepository merchantRepository,
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpdateStoreStaffCommandHandler> logger)
|
||||
: IRequestHandler<UpdateStoreStaffCommand, StoreStaffDto?>
|
||||
{
|
||||
@@ -24,32 +22,32 @@ public sealed class UpdateStoreStaffCommandHandler(
|
||||
public async Task<StoreStaffDto?> Handle(UpdateStoreStaffCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 读取员工
|
||||
// 2. (空行后) 读取员工
|
||||
var staff = await merchantRepository.FindStaffByIdAsync(request.StaffId, tenantId, cancellationToken);
|
||||
if (staff is null || staff.StoreId != request.StoreId)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 3. 更新字段
|
||||
// 3. (空行后) 更新字段
|
||||
staff.Name = request.Name.Trim();
|
||||
staff.Phone = request.Phone.Trim();
|
||||
staff.Email = request.Email?.Trim();
|
||||
staff.RoleType = request.RoleType;
|
||||
staff.Status = request.Status;
|
||||
|
||||
// 4. 持久化
|
||||
// 4. (空行后) 持久化
|
||||
await merchantRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("更新门店员工 {StaffId} 门店 {StoreId}", staff.Id, staff.StoreId);
|
||||
|
||||
// 5. 返回 DTO
|
||||
// 5. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(staff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -14,28 +13,34 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpdateStoreTableAreaCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpdateStoreTableAreaCommandHandler> logger)
|
||||
: IRequestHandler<UpdateStoreTableAreaCommand, StoreTableAreaDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<StoreTableAreaDto?> Handle(UpdateStoreTableAreaCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取区域
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取区域
|
||||
var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId, tenantId, cancellationToken);
|
||||
if (area is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 校验门店归属
|
||||
// 3. (空行后) 校验门店归属
|
||||
if (area.StoreId != request.StoreId)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "区域不属于该门店");
|
||||
}
|
||||
|
||||
// 3. 名称唯一校验
|
||||
// 4. (空行后) 名称唯一校验
|
||||
var areas = await storeRepository.GetTableAreasAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var hasDuplicate = areas.Any(x => x.Id != request.AreaId && x.Name.Equals(request.Name, StringComparison.OrdinalIgnoreCase));
|
||||
if (hasDuplicate)
|
||||
@@ -43,17 +48,17 @@ public sealed class UpdateStoreTableAreaCommandHandler(
|
||||
throw new BusinessException(ErrorCodes.Conflict, "区域名称已存在");
|
||||
}
|
||||
|
||||
// 4. 更新字段
|
||||
// 5. (空行后) 更新字段
|
||||
area.Name = request.Name.Trim();
|
||||
area.Description = request.Description?.Trim();
|
||||
area.SortOrder = request.SortOrder;
|
||||
|
||||
// 5. 持久化
|
||||
// 6. (空行后) 持久化
|
||||
await storeRepository.UpdateTableAreaAsync(area, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("更新桌台区域 {AreaId} 对应门店 {StoreId}", area.Id, area.StoreId);
|
||||
|
||||
// 6. 返回 DTO
|
||||
// 7. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(area);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,28 +14,34 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpdateStoreTableCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpdateStoreTableCommandHandler> logger)
|
||||
: IRequestHandler<UpdateStoreTableCommand, StoreTableDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<StoreTableDto?> Handle(UpdateStoreTableCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 读取桌码
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
// 1. 读取门店并解析租户
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. (空行后) 读取桌码
|
||||
var table = await storeRepository.FindTableByIdAsync(request.TableId, tenantId, cancellationToken);
|
||||
if (table is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// 2. 校验门店归属
|
||||
// 3. (空行后) 校验门店归属
|
||||
if (table.StoreId != request.StoreId)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.ValidationFailed, "桌码不属于该门店");
|
||||
}
|
||||
|
||||
// 3. 校验区域归属
|
||||
// 4. (空行后) 校验区域归属
|
||||
if (request.AreaId.HasValue)
|
||||
{
|
||||
var area = await storeRepository.FindTableAreaByIdAsync(request.AreaId.Value, tenantId, cancellationToken);
|
||||
@@ -46,7 +51,7 @@ public sealed class UpdateStoreTableCommandHandler(
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 校验桌码唯一
|
||||
// 5. (空行后) 校验桌码唯一
|
||||
var tables = await storeRepository.GetTablesAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var exists = tables.Any(x => x.Id != request.TableId && x.TableCode.Equals(request.TableCode, StringComparison.OrdinalIgnoreCase));
|
||||
if (exists)
|
||||
@@ -54,19 +59,19 @@ public sealed class UpdateStoreTableCommandHandler(
|
||||
throw new BusinessException(ErrorCodes.Conflict, "桌码已存在");
|
||||
}
|
||||
|
||||
// 5. 更新字段
|
||||
// 6. (空行后) 更新字段
|
||||
table.AreaId = request.AreaId;
|
||||
table.TableCode = request.TableCode.Trim();
|
||||
table.Capacity = request.Capacity;
|
||||
table.Tags = request.Tags?.Trim();
|
||||
table.Status = request.Status;
|
||||
|
||||
// 6. 持久化
|
||||
// 7. (空行后) 持久化
|
||||
await storeRepository.UpdateTableAsync(table, cancellationToken);
|
||||
await storeRepository.SaveChangesAsync(cancellationToken);
|
||||
logger.LogInformation("更新桌码 {TableId} 对应门店 {StoreId}", table.Id, table.StoreId);
|
||||
|
||||
// 7. 返回 DTO
|
||||
// 8. (空行后) 返回 DTO
|
||||
return StoreMapping.ToDto(table);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using TakeoutSaaS.Domain.Stores.Entities;
|
||||
using TakeoutSaaS.Domain.Stores.Repositories;
|
||||
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpsertStorePickupSettingCommandHandler(
|
||||
IStoreRepository storeRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ILogger<UpsertStorePickupSettingCommandHandler> logger)
|
||||
: IRequestHandler<UpsertStorePickupSettingCommand, StorePickupSettingDto>
|
||||
{
|
||||
@@ -23,14 +21,14 @@ public sealed class UpsertStorePickupSettingCommandHandler(
|
||||
public async Task<StorePickupSettingDto> Handle(UpsertStorePickupSettingCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
// 1. 校验门店存在
|
||||
var tenantId = tenantProvider.GetCurrentTenantId();
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken);
|
||||
var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId: null, cancellationToken);
|
||||
if (store is null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.NotFound, "门店不存在");
|
||||
}
|
||||
var tenantId = store.TenantId;
|
||||
|
||||
// 2. 读取或创建配置
|
||||
// 2. (空行后) 读取或创建配置
|
||||
var setting = await storeRepository.GetPickupSettingAsync(request.StoreId, tenantId, cancellationToken);
|
||||
if (setting is null)
|
||||
{
|
||||
@@ -42,7 +40,7 @@ public sealed class UpsertStorePickupSettingCommandHandler(
|
||||
await storeRepository.AddPickupSettingAsync(setting, cancellationToken);
|
||||
}
|
||||
|
||||
// 3. 更新字段
|
||||
// 3. (空行后) 更新字段
|
||||
setting.AllowToday = request.AllowToday;
|
||||
setting.AllowDaysAhead = request.AllowDaysAhead;
|
||||
setting.DefaultCutoffMinutes = request.DefaultCutoffMinutes;
|
||||
|
||||
@@ -8,6 +8,11 @@ namespace TakeoutSaaS.Application.App.Stores.Queries;
|
||||
/// </summary>
|
||||
public sealed record GetStoreTableContextQuery : IRequest<StoreTableContextDto?>
|
||||
{
|
||||
/// <summary>
|
||||
/// 租户 ID。
|
||||
/// </summary>
|
||||
public long TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 桌码。
|
||||
/// </summary>
|
||||
|
||||
@@ -13,6 +13,7 @@ public sealed class GetStoreTableContextQueryValidator : AbstractValidator<GetSt
|
||||
/// </summary>
|
||||
public GetStoreTableContextQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.TenantId).GreaterThan(0);
|
||||
RuleFor(x => x.TableCode).NotEmpty().MaximumLength(32);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user