feat(store): add quick business toggle endpoint and auto-approve creation
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 42s

This commit is contained in:
2026-02-18 10:03:27 +08:00
parent be701d8cf6
commit dfa2b3ee52
2 changed files with 53 additions and 3 deletions

View File

@@ -108,5 +108,26 @@ public sealed class StoreController(IMediator mediator) : BaseApiController
// 2. 返回成功响应
return ApiResponse<object>.Ok(null);
}
/// <summary>
/// 快速切换门店经营状态。
/// </summary>
/// <param name="command">切换命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>切换后的门店信息。</returns>
[HttpPost("toggle-business-status")]
[ProducesResponseType(typeof(ApiResponse<StoreDto>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<StoreDto>), StatusCodes.Status401Unauthorized)]
[ProducesResponseType(typeof(ApiResponse<StoreDto>), StatusCodes.Status422UnprocessableEntity)]
public async Task<ApiResponse<StoreDto>> ToggleBusinessStatus(
[FromBody] ToggleBusinessStatusCommand command,
CancellationToken cancellationToken)
{
// 1. 执行状态切换
var result = await mediator.Send(command, cancellationToken);
// 2. 返回切换结果
return ApiResponse<StoreDto>.Ok(result);
}
}

View File

@@ -8,6 +8,7 @@ using TakeoutSaaS.Domain.Stores.Enums;
using TakeoutSaaS.Domain.Stores.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;
namespace TakeoutSaaS.Application.App.Stores.Handlers;
@@ -16,7 +17,8 @@ namespace TakeoutSaaS.Application.App.Stores.Handlers;
/// </summary>
public sealed class CreateStoreCommandHandler(
StoreContextService storeContextService,
IStoreRepository storeRepository)
IStoreRepository storeRepository,
ICurrentUserAccessor currentUserAccessor)
: IRequestHandler<CreateStoreCommand>
{
/// <inheritdoc />
@@ -24,6 +26,7 @@ public sealed class CreateStoreCommandHandler(
{
// 1. 解析上下文
var context = storeContextService.GetRequiredContext();
var now = DateTime.UtcNow;
// 2. 生成唯一门店编码
var existingStores = await storeRepository.SearchAsync(
@@ -54,15 +57,29 @@ public sealed class CreateStoreCommandHandler(
CoverImageUrl = request.CoverImage?.Trim(),
SignboardImageUrl = request.CoverImage?.Trim(),
OwnershipType = StoreOwnershipType.SameEntity,
AuditStatus = StoreAuditStatus.Draft,
AuditStatus = StoreAuditStatus.Activated,
BusinessStatus = StoreBusinessStatus.Resting,
SubmittedAt = now,
ActivatedAt = now,
Status = StoreStatus.Operating
};
StoreListMapping.ApplyServiceTypes(store, serviceTypes);
// 4. 持久化
// 4. 持久化门店并记录自动审核通过
await storeRepository.AddStoreAsync(store, cancellationToken);
await storeRepository.SaveChangesAsync(cancellationToken);
await storeRepository.AddAuditRecordAsync(new StoreAuditRecord
{
StoreId = store.Id,
Action = StoreAuditAction.Approve,
PreviousStatus = StoreAuditStatus.Draft,
NewStatus = StoreAuditStatus.Activated,
OperatorId = ResolveOperatorId(currentUserAccessor),
OperatorName = ResolveOperatorName(currentUserAccessor),
Remarks = "系统自动审核通过"
}, cancellationToken);
await storeRepository.SaveChangesAsync(cancellationToken);
}
/// <summary>
@@ -87,4 +104,16 @@ public sealed class CreateStoreCommandHandler(
throw new BusinessException(ErrorCodes.Conflict, "门店编码生成失败,请稍后重试");
}
private static long? ResolveOperatorId(ICurrentUserAccessor currentUserAccessor)
{
var id = currentUserAccessor.UserId;
return id == 0 ? null : id;
}
private static string ResolveOperatorName(ICurrentUserAccessor currentUserAccessor)
{
var id = currentUserAccessor.UserId;
return id == 0 ? "system" : $"user:{id}";
}
}