完成门店管理后端接口与任务
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 批量更新营业时段命令验证器。
|
||||
/// </summary>
|
||||
public sealed class BatchUpdateBusinessHoursCommandValidator : AbstractValidator<BatchUpdateBusinessHoursCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public BatchUpdateBusinessHoursCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
|
||||
RuleForEach(x => x.Items).ChildRules(item =>
|
||||
{
|
||||
item.RuleFor(x => x.StartTime).NotNull();
|
||||
item.RuleFor(x => x.EndTime).NotNull();
|
||||
item.RuleFor(x => x.CapacityLimit).GreaterThanOrEqualTo(0).When(x => x.CapacityLimit.HasValue);
|
||||
item.RuleFor(x => x.Notes).MaximumLength(256);
|
||||
});
|
||||
|
||||
RuleFor(x => x.Items).Custom((items, context) =>
|
||||
{
|
||||
if (items == null || items.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var error = BusinessHourValidators.ValidateOverlap(items);
|
||||
if (!string.IsNullOrWhiteSpace(error))
|
||||
{
|
||||
context.AddFailure(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using System.Linq;
|
||||
using TakeoutSaaS.Application.App.Stores.Dto;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 营业时段校验助手。
|
||||
/// </summary>
|
||||
public static class BusinessHourValidators
|
||||
{
|
||||
/// <summary>
|
||||
/// 校验营业时段是否存在重叠。
|
||||
/// </summary>
|
||||
/// <param name="items">营业时段列表。</param>
|
||||
/// <returns>错误信息,若为空表示通过。</returns>
|
||||
public static string? ValidateOverlap(IReadOnlyList<StoreBusinessHourInputDto> items)
|
||||
{
|
||||
if (items.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var segments = new List<(DayOfWeek Day, TimeSpan Start, TimeSpan End)>();
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item.StartTime == item.EndTime)
|
||||
{
|
||||
return "营业时段开始时间不能等于结束时间";
|
||||
}
|
||||
|
||||
if (item.StartTime < item.EndTime)
|
||||
{
|
||||
segments.Add((item.DayOfWeek, item.StartTime, item.EndTime));
|
||||
continue;
|
||||
}
|
||||
|
||||
var nextDay = NextDay(item.DayOfWeek);
|
||||
segments.Add((item.DayOfWeek, item.StartTime, TimeSpan.FromDays(1)));
|
||||
segments.Add((nextDay, TimeSpan.Zero, item.EndTime));
|
||||
}
|
||||
|
||||
var grouped = segments.GroupBy(x => x.Day).ToList();
|
||||
foreach (var group in grouped)
|
||||
{
|
||||
var ordered = group.OrderBy(x => x.Start).ToList();
|
||||
for (var index = 0; index < ordered.Count - 1; index++)
|
||||
{
|
||||
var current = ordered[index];
|
||||
var next = ordered[index + 1];
|
||||
if (next.Start < current.End)
|
||||
{
|
||||
return "营业时段存在重叠,请调整";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static DayOfWeek NextDay(DayOfWeek day)
|
||||
{
|
||||
var next = (int)day + 1;
|
||||
return next > 6 ? DayOfWeek.Sunday : (DayOfWeek)next;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 费用预览计算查询验证器。
|
||||
/// </summary>
|
||||
public sealed class CalculateStoreFeeQueryValidator : AbstractValidator<CalculateStoreFeeQuery>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public CalculateStoreFeeQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.OrderAmount).GreaterThanOrEqualTo(0);
|
||||
|
||||
RuleForEach(x => x.Items).ChildRules(item =>
|
||||
{
|
||||
item.RuleFor(x => x.SkuId).GreaterThan(0);
|
||||
item.RuleFor(x => x.Quantity).GreaterThan(0);
|
||||
item.RuleFor(x => x.PackagingFee).GreaterThanOrEqualTo(0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Queries;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 配送范围检测查询验证器。
|
||||
/// </summary>
|
||||
public sealed class CheckStoreDeliveryZoneQueryValidator : AbstractValidator<CheckStoreDeliveryZoneQuery>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public CheckStoreDeliveryZoneQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.Longitude).InclusiveBetween(-180, 180);
|
||||
RuleFor(x => x.Latitude).InclusiveBetween(-90, 90);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public sealed class CreateStoreBusinessHourCommandValidator : AbstractValidator<
|
||||
public CreateStoreBusinessHourCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.StartTime).LessThan(x => x.EndTime).WithMessage("结束时间必须晚于开始时间");
|
||||
RuleFor(x => x.StartTime).NotEqual(x => x.EndTime).WithMessage("开始时间不能等于结束时间");
|
||||
RuleFor(x => x.CapacityLimit).GreaterThanOrEqualTo(0).When(x => x.CapacityLimit.HasValue);
|
||||
RuleFor(x => x.Notes).MaximumLength(256);
|
||||
}
|
||||
|
||||
@@ -18,10 +18,14 @@ public sealed class CreateStoreCommandValidator : AbstractValidator<CreateStoreC
|
||||
RuleFor(x => x.Name).NotEmpty().MaximumLength(128);
|
||||
RuleFor(x => x.Phone).MaximumLength(32);
|
||||
RuleFor(x => x.ManagerName).MaximumLength(64);
|
||||
RuleFor(x => x.SignboardImageUrl).NotEmpty().MaximumLength(500);
|
||||
RuleFor(x => x.OwnershipType).IsInEnum();
|
||||
RuleFor(x => x.Province).MaximumLength(64);
|
||||
RuleFor(x => x.City).MaximumLength(64);
|
||||
RuleFor(x => x.District).MaximumLength(64);
|
||||
RuleFor(x => x.Address).MaximumLength(256);
|
||||
RuleFor(x => x.Longitude).NotNull();
|
||||
RuleFor(x => x.Latitude).NotNull();
|
||||
RuleFor(x => x.Announcement).MaximumLength(512);
|
||||
RuleFor(x => x.Tags).MaximumLength(256);
|
||||
RuleFor(x => x.DeliveryRadiusKm).GreaterThanOrEqualTo(0);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Enums;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 创建门店资质命令验证器。
|
||||
/// </summary>
|
||||
public sealed class CreateStoreQualificationCommandValidator : AbstractValidator<CreateStoreQualificationCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public CreateStoreQualificationCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.QualificationType).IsInEnum();
|
||||
RuleFor(x => x.FileUrl).NotEmpty().MaximumLength(500);
|
||||
RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0);
|
||||
RuleFor(x => x.DocumentNumber).MaximumLength(100);
|
||||
|
||||
RuleFor(x => x.ExpiresAt)
|
||||
.Must(date => date.HasValue && date.Value.Date > DateTime.UtcNow.Date)
|
||||
.When(x => IsLicenseType(x.QualificationType))
|
||||
.WithMessage("证照有效期必须晚于今天");
|
||||
|
||||
RuleFor(x => x.DocumentNumber)
|
||||
.NotEmpty()
|
||||
.MinimumLength(2)
|
||||
.When(x => IsLicenseType(x.QualificationType))
|
||||
.WithMessage("证照编号不能为空");
|
||||
|
||||
RuleFor(x => x.ExpiresAt)
|
||||
.Must(date => !date.HasValue || date.Value.Date > DateTime.UtcNow.Date)
|
||||
.When(x => !IsLicenseType(x.QualificationType))
|
||||
.WithMessage("证照有效期必须晚于今天");
|
||||
}
|
||||
|
||||
private static bool IsLicenseType(StoreQualificationType type)
|
||||
=> type is StoreQualificationType.BusinessLicense or StoreQualificationType.FoodServiceLicense;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 删除门店资质命令验证器。
|
||||
/// </summary>
|
||||
public sealed class DeleteStoreQualificationCommandValidator : AbstractValidator<DeleteStoreQualificationCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public DeleteStoreQualificationCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.QualificationId).GreaterThan(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 提交门店审核命令验证器。
|
||||
/// </summary>
|
||||
public sealed class SubmitStoreAuditCommandValidator : AbstractValidator<SubmitStoreAuditCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public SubmitStoreAuditCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Enums;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 切换门店经营状态命令验证器。
|
||||
/// </summary>
|
||||
public sealed class ToggleBusinessStatusCommandValidator : AbstractValidator<ToggleBusinessStatusCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public ToggleBusinessStatusCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.BusinessStatus)
|
||||
.Must(status => status is StoreBusinessStatus.Open or StoreBusinessStatus.Resting)
|
||||
.WithMessage("仅允许切换营业中或休息中");
|
||||
|
||||
RuleFor(x => x.ClosureReason)
|
||||
.NotNull()
|
||||
.When(x => x.BusinessStatus == StoreBusinessStatus.Resting)
|
||||
.WithMessage("切换休息中必须选择歇业原因");
|
||||
|
||||
RuleFor(x => x.ClosureReasonText).MaximumLength(500);
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public sealed class UpdateStoreBusinessHourCommandValidator : AbstractValidator<
|
||||
{
|
||||
RuleFor(x => x.BusinessHourId).GreaterThan(0);
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.StartTime).LessThan(x => x.EndTime).WithMessage("结束时间必须晚于开始时间");
|
||||
RuleFor(x => x.StartTime).NotEqual(x => x.EndTime).WithMessage("开始时间不能等于结束时间");
|
||||
RuleFor(x => x.CapacityLimit).GreaterThanOrEqualTo(0).When(x => x.CapacityLimit.HasValue);
|
||||
RuleFor(x => x.Notes).MaximumLength(256);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public sealed class UpdateStoreCommandValidator : AbstractValidator<UpdateStoreC
|
||||
RuleFor(x => x.Name).NotEmpty().MaximumLength(128);
|
||||
RuleFor(x => x.Phone).MaximumLength(32);
|
||||
RuleFor(x => x.ManagerName).MaximumLength(64);
|
||||
RuleFor(x => x.SignboardImageUrl).MaximumLength(500);
|
||||
RuleFor(x => x.Province).MaximumLength(64);
|
||||
RuleFor(x => x.City).MaximumLength(64);
|
||||
RuleFor(x => x.District).MaximumLength(64);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
using TakeoutSaaS.Domain.Stores.Enums;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 更新门店费用配置命令验证器。
|
||||
/// </summary>
|
||||
public sealed class UpdateStoreFeeCommandValidator : AbstractValidator<UpdateStoreFeeCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public UpdateStoreFeeCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.MinimumOrderAmount).GreaterThanOrEqualTo(0).LessThanOrEqualTo(9999.99m);
|
||||
RuleFor(x => x.DeliveryFee).GreaterThanOrEqualTo(0).LessThanOrEqualTo(999.99m);
|
||||
RuleFor(x => x.FreeDeliveryThreshold).GreaterThanOrEqualTo(0).When(x => x.FreeDeliveryThreshold.HasValue);
|
||||
|
||||
RuleFor(x => x.FixedPackagingFee)
|
||||
.NotNull()
|
||||
.When(x => x.PackagingFeeMode == PackagingFeeMode.Fixed)
|
||||
.WithMessage("总计打包费模式下必须填写固定打包费");
|
||||
|
||||
RuleFor(x => x.FixedPackagingFee)
|
||||
.Must(fee => !fee.HasValue || fee.Value <= 99.99m)
|
||||
.WithMessage("固定打包费不能超过 99.99");
|
||||
|
||||
RuleFor(x => x.FixedPackagingFee)
|
||||
.Must(fee => !fee.HasValue || fee.Value >= 0)
|
||||
.WithMessage("固定打包费不能为负数");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using FluentValidation;
|
||||
using TakeoutSaaS.Application.App.Stores.Commands;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Stores.Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 更新门店资质命令验证器。
|
||||
/// </summary>
|
||||
public sealed class UpdateStoreQualificationCommandValidator : AbstractValidator<UpdateStoreQualificationCommand>
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化验证规则。
|
||||
/// </summary>
|
||||
public UpdateStoreQualificationCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.StoreId).GreaterThan(0);
|
||||
RuleFor(x => x.QualificationId).GreaterThan(0);
|
||||
RuleFor(x => x.FileUrl).MaximumLength(500).When(x => !string.IsNullOrWhiteSpace(x.FileUrl));
|
||||
RuleFor(x => x.DocumentNumber).MaximumLength(100).When(x => !string.IsNullOrWhiteSpace(x.DocumentNumber));
|
||||
RuleFor(x => x.SortOrder).GreaterThanOrEqualTo(0).When(x => x.SortOrder.HasValue);
|
||||
RuleFor(x => x.ExpiresAt)
|
||||
.Must(date => !date.HasValue || date.Value.Date > DateTime.UtcNow.Date)
|
||||
.When(x => x.ExpiresAt.HasValue)
|
||||
.WithMessage("证照有效期必须晚于今天");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user