feat: 完成门店管理剩余接口并补齐文档注释
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 46s

This commit is contained in:
2026-02-17 14:54:35 +08:00
parent 3a94348cca
commit 1b185af718
45 changed files with 13333 additions and 91 deletions

View File

@@ -38,6 +38,16 @@ public sealed record CreateStoreDeliveryZoneCommand : IRequest<StoreDeliveryZone
/// </summary>
public int? EstimatedMinutes { get; init; }
/// <summary>
/// 区域颜色。
/// </summary>
public string? Color { get; init; }
/// <summary>
/// 优先级。
/// </summary>
public int Priority { get; init; } = 100;
/// <summary>
/// 排序。
/// </summary>

View File

@@ -43,6 +43,16 @@ public sealed record UpdateStoreDeliveryZoneCommand : IRequest<StoreDeliveryZone
/// </summary>
public int? EstimatedMinutes { get; init; }
/// <summary>
/// 区域颜色。
/// </summary>
public string? Color { get; init; }
/// <summary>
/// 优先级。
/// </summary>
public int Priority { get; init; } = 100;
/// <summary>
/// 排序。
/// </summary>

View File

@@ -48,4 +48,24 @@ public sealed record UpdateStoreFeeCommand : IRequest<StoreFeeDto>
/// 免配送费门槛。
/// </summary>
public decimal? FreeDeliveryThreshold { get; init; }
/// <summary>
/// 餐具费是否启用。
/// </summary>
public bool CutleryFeeEnabled { get; init; }
/// <summary>
/// 餐具费金额。
/// </summary>
public decimal CutleryFeeAmount { get; init; }
/// <summary>
/// 加急费是否启用。
/// </summary>
public bool RushFeeEnabled { get; init; }
/// <summary>
/// 加急费金额。
/// </summary>
public decimal RushFeeAmount { get; init; }
}

View File

@@ -1,5 +1,6 @@
using MediatR;
using TakeoutSaaS.Application.App.Stores.Dto;
using TakeoutSaaS.Domain.Stores.Enums;
namespace TakeoutSaaS.Application.App.Stores.Commands;
@@ -32,4 +33,14 @@ public sealed record UpsertStorePickupSettingCommand : IRequest<StorePickupSetti
/// 单笔最大份数。
/// </summary>
public int? MaxQuantityPerOrder { get; init; }
/// <summary>
/// 自提模式。
/// </summary>
public StorePickupMode Mode { get; init; } = StorePickupMode.Big;
/// <summary>
/// 精细规则 JSON。
/// </summary>
public string? FineRuleJson { get; init; }
}

View File

@@ -51,6 +51,16 @@ public sealed record StoreDeliveryZoneDto
/// </summary>
public int? EstimatedMinutes { get; init; }
/// <summary>
/// 区域颜色。
/// </summary>
public string? Color { get; init; }
/// <summary>
/// 优先级。
/// </summary>
public int Priority { get; init; }
/// <summary>
/// 排序。
/// </summary>

View File

@@ -31,6 +31,26 @@ public sealed record StoreFeeDto
/// </summary>
public decimal DeliveryFee { get; init; }
/// <summary>
/// 餐具费是否启用。
/// </summary>
public bool CutleryFeeEnabled { get; init; }
/// <summary>
/// 餐具费金额。
/// </summary>
public decimal CutleryFeeAmount { get; init; }
/// <summary>
/// 加急费是否启用。
/// </summary>
public bool RushFeeEnabled { get; init; }
/// <summary>
/// 加急费金额。
/// </summary>
public decimal RushFeeAmount { get; init; }
/// <summary>
/// 打包费模式。
/// </summary>

View File

@@ -1,4 +1,5 @@
using System.Text.Json.Serialization;
using TakeoutSaaS.Domain.Stores.Enums;
using TakeoutSaaS.Shared.Abstractions.Serialization;
namespace TakeoutSaaS.Application.App.Stores.Dto;
@@ -39,4 +40,14 @@ public sealed record StorePickupSettingDto
/// 单笔最大自提份数。
/// </summary>
public int? MaxQuantityPerOrder { get; init; }
/// <summary>
/// 自提模式。
/// </summary>
public StorePickupMode Mode { get; init; }
/// <summary>
/// 精细规则 JSON。
/// </summary>
public string? FineRuleJson { get; init; }
}

View File

@@ -51,6 +51,8 @@ public sealed class CreateStoreDeliveryZoneCommandHandler(
MinimumOrderAmount = request.MinimumOrderAmount,
DeliveryFee = request.DeliveryFee,
EstimatedMinutes = request.EstimatedMinutes,
Color = request.Color?.Trim(),
Priority = request.Priority,
SortOrder = request.SortOrder
};

View File

@@ -40,7 +40,11 @@ public sealed class GetStoreFeeQueryHandler(
BaseDeliveryFee = 0m,
PackagingFeeMode = Domain.Stores.Enums.PackagingFeeMode.Fixed,
OrderPackagingFeeMode = Domain.Stores.Enums.OrderPackagingFeeMode.Fixed,
FixedPackagingFee = 0m
FixedPackagingFee = 0m,
CutleryFeeEnabled = false,
CutleryFeeAmount = 0m,
RushFeeEnabled = false,
RushFeeAmount = 0m
};
return StoreMapping.ToDto(fallback);
}

View File

@@ -31,7 +31,9 @@ public sealed class GetStorePickupSettingQueryHandler(
AllowToday = setting.AllowToday,
AllowDaysAhead = setting.AllowDaysAhead,
DefaultCutoffMinutes = setting.DefaultCutoffMinutes,
MaxQuantityPerOrder = setting.MaxQuantityPerOrder
MaxQuantityPerOrder = setting.MaxQuantityPerOrder,
Mode = setting.Mode,
FineRuleJson = setting.FineRuleJson
};
}
}

View File

@@ -52,6 +52,8 @@ public sealed class UpdateStoreDeliveryZoneCommandHandler(
existing.MinimumOrderAmount = request.MinimumOrderAmount;
existing.DeliveryFee = request.DeliveryFee;
existing.EstimatedMinutes = request.EstimatedMinutes;
existing.Color = request.Color?.Trim();
existing.Priority = request.Priority;
existing.SortOrder = request.SortOrder;
// 5. (空行后) 持久化

View File

@@ -71,6 +71,10 @@ public sealed class UpdateStoreFeeCommandHandler(
fee.PackagingFeeTiersJson = null;
}
fee.FreeDeliveryThreshold = request.FreeDeliveryThreshold;
fee.CutleryFeeEnabled = request.CutleryFeeEnabled;
fee.CutleryFeeAmount = request.CutleryFeeAmount;
fee.RushFeeEnabled = request.RushFeeEnabled;
fee.RushFeeAmount = request.RushFeeAmount;
// 4. (空行后) 保存并返回
if (isNew)

View File

@@ -47,6 +47,8 @@ public sealed class UpsertStorePickupSettingCommandHandler(
setting.AllowDaysAhead = request.AllowDaysAhead;
setting.DefaultCutoffMinutes = request.DefaultCutoffMinutes;
setting.MaxQuantityPerOrder = request.MaxQuantityPerOrder;
setting.Mode = request.Mode;
setting.FineRuleJson = request.FineRuleJson;
await storeRepository.UpdatePickupSettingAsync(setting, cancellationToken);
await storeRepository.SaveChangesAsync(cancellationToken);
logger.LogInformation("更新门店 {StoreId} 自提配置", request.StoreId);
@@ -57,7 +59,9 @@ public sealed class UpsertStorePickupSettingCommandHandler(
AllowToday = setting.AllowToday,
AllowDaysAhead = setting.AllowDaysAhead,
DefaultCutoffMinutes = setting.DefaultCutoffMinutes,
MaxQuantityPerOrder = setting.MaxQuantityPerOrder
MaxQuantityPerOrder = setting.MaxQuantityPerOrder,
Mode = setting.Mode,
FineRuleJson = setting.FineRuleJson
};
}
}

View File

@@ -64,6 +64,10 @@ public static class StoreMapping
StoreId = fee.StoreId,
MinimumOrderAmount = fee.MinimumOrderAmount,
DeliveryFee = fee.BaseDeliveryFee,
CutleryFeeEnabled = fee.CutleryFeeEnabled,
CutleryFeeAmount = fee.CutleryFeeAmount,
RushFeeEnabled = fee.RushFeeEnabled,
RushFeeAmount = fee.RushFeeAmount,
PackagingFeeMode = fee.PackagingFeeMode,
OrderPackagingFeeMode = fee.OrderPackagingFeeMode,
FixedPackagingFee = fee.FixedPackagingFee,
@@ -137,6 +141,8 @@ public static class StoreMapping
MinimumOrderAmount = zone.MinimumOrderAmount,
DeliveryFee = zone.DeliveryFee,
EstimatedMinutes = zone.EstimatedMinutes,
Color = zone.Color,
Priority = zone.Priority,
SortOrder = zone.SortOrder,
CreatedAt = zone.CreatedAt
};

View File

@@ -19,6 +19,8 @@ public sealed class CreateStoreDeliveryZoneCommandValidator : AbstractValidator<
RuleFor(x => x.MinimumOrderAmount).GreaterThanOrEqualTo(0).When(x => x.MinimumOrderAmount.HasValue);
RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).When(x => x.DeliveryFee.HasValue);
RuleFor(x => x.EstimatedMinutes).GreaterThan(0).When(x => x.EstimatedMinutes.HasValue);
RuleFor(x => x.Color).MaximumLength(32);
RuleFor(x => x.Priority).GreaterThanOrEqualTo(0);
RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0);
}
}

View File

@@ -20,6 +20,8 @@ public sealed class UpdateStoreDeliveryZoneCommandValidator : AbstractValidator<
RuleFor(x => x.MinimumOrderAmount).GreaterThanOrEqualTo(0).When(x => x.MinimumOrderAmount.HasValue);
RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).When(x => x.DeliveryFee.HasValue);
RuleFor(x => x.EstimatedMinutes).GreaterThan(0).When(x => x.EstimatedMinutes.HasValue);
RuleFor(x => x.Color).MaximumLength(32);
RuleFor(x => x.Priority).GreaterThanOrEqualTo(0);
RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0);
}
}

View File

@@ -32,6 +32,14 @@ public sealed class UpdateStoreFeeCommandValidator : AbstractValidator<UpdateSto
.Must(fee => !fee.HasValue || fee.Value >= 0)
.WithMessage("固定打包费不能为负数");
RuleFor(x => x.CutleryFeeAmount)
.GreaterThanOrEqualTo(0)
.LessThanOrEqualTo(99.99m);
RuleFor(x => x.RushFeeAmount)
.GreaterThanOrEqualTo(0)
.LessThanOrEqualTo(99.99m);
RuleFor(x => x)
.Custom((command, context) =>
{

View File

@@ -17,5 +17,6 @@ public sealed class UpsertStorePickupSettingCommandValidator : AbstractValidator
RuleFor(x => x.AllowDaysAhead).GreaterThanOrEqualTo(0);
RuleFor(x => x.DefaultCutoffMinutes).GreaterThanOrEqualTo(0);
RuleFor(x => x.MaxQuantityPerOrder).GreaterThan(0).When(x => x.MaxQuantityPerOrder.HasValue);
RuleFor(x => x.FineRuleJson).MaximumLength(20000);
}
}