using MediatR; using Microsoft.Extensions.Logging; using TakeoutSaaS.Application.App.Stores.Commands; using TakeoutSaaS.Application.App.Stores.Dto; using TakeoutSaaS.Domain.Merchants.Repositories; 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; /// /// 创建排班处理器。 /// public sealed class CreateStoreEmployeeShiftCommandHandler( IStoreRepository storeRepository, IMerchantRepository merchantRepository, ITenantProvider tenantProvider, ILogger logger) : IRequestHandler { /// public async Task Handle(CreateStoreEmployeeShiftCommand request, CancellationToken cancellationToken) { // 1. 校验门店存在 var tenantId = tenantProvider.GetCurrentTenantId(); var store = await storeRepository.FindByIdAsync(request.StoreId, tenantId, cancellationToken); if (store is null) { throw new BusinessException(ErrorCodes.NotFound, "门店不存在"); } // 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. 校验日期与冲突 var from = request.ShiftDate.Date; var to = request.ShiftDate.Date; var shifts = await storeRepository.GetShiftsAsync(request.StoreId, tenantId, from, to, cancellationToken); var hasConflict = shifts.Any(x => x.StaffId == request.StaffId && x.ShiftDate == request.ShiftDate); if (hasConflict) { throw new BusinessException(ErrorCodes.Conflict, "该员工当日已存在排班"); } // 4. 构建实体 var shift = new StoreEmployeeShift { StoreId = request.StoreId, StaffId = request.StaffId, ShiftDate = request.ShiftDate.Date, StartTime = request.StartTime, EndTime = request.EndTime, RoleType = request.RoleType, Notes = request.Notes?.Trim() }; // 5. 持久化 await storeRepository.AddShiftsAsync(new[] { shift }, cancellationToken); await storeRepository.SaveChangesAsync(cancellationToken); logger.LogInformation("创建排班 {ShiftId} 员工 {StaffId} 门店 {StoreId}", shift.Id, shift.StaffId, shift.StoreId); // 6. 返回 DTO return StoreMapping.ToDto(shift); } }