From 8a6fc867c24c9ce90179350ebe8316d74dd045a4 Mon Sep 17 00:00:00 2001
From: MSuMshk <2039814060@qq.com>
Date: Fri, 20 Feb 2026 09:55:11 +0800
Subject: [PATCH] refactor(store): remove fallback config behavior and expose
isConfigured
---
.../Contracts/Store/StoreDeliveryContracts.cs | 8 +-
.../Contracts/Store/StoreDineInContracts.cs | 6 +-
.../Contracts/Store/StoreFeesContracts.cs | 4 +
.../Contracts/Store/StorePickupContracts.cs | 10 +-
.../Controllers/StoreDeliveryController.cs | 109 ++++++++----------
.../Controllers/StoreDineInController.cs | 26 +++--
.../Controllers/StoreFeesController.cs | 57 ++++++---
.../Controllers/StorePickupController.cs | 79 +++++++------
.../Handlers/GetStoreFeeQueryHandler.cs | 21 +---
.../App/Stores/StoreListMapping.cs | 19 +--
10 files changed, 166 insertions(+), 173 deletions(-)
diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs
index db6806b..914c362 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDeliveryContracts.cs
@@ -107,9 +107,13 @@ public sealed class StoreDeliverySettingsDto
///
public string StoreId { get; set; } = string.Empty;
///
+ /// IsConfigured。
+ ///
+ public bool IsConfigured { get; set; }
+ ///
/// Mode。
///
- public string Mode { get; set; } = "radius";
+ public string? Mode { get; set; }
///
/// RadiusCenterLatitude。
///
@@ -129,7 +133,7 @@ public sealed class StoreDeliverySettingsDto
///
/// GeneralSettings。
///
- public DeliveryGeneralSettingsDto GeneralSettings { get; set; } = new();
+ public DeliveryGeneralSettingsDto? GeneralSettings { get; set; }
}
///
diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs
index 210108d..79a8aef 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreDineInContracts.cs
@@ -83,9 +83,13 @@ public sealed class StoreDineInSettingsDto
///
public string StoreId { get; set; } = string.Empty;
///
+ /// IsConfigured。
+ ///
+ public bool IsConfigured { get; set; }
+ ///
/// BasicSettings。
///
- public DineInBasicSettingsDto BasicSettings { get; set; } = new();
+ public DineInBasicSettingsDto? BasicSettings { get; set; }
///
/// Areas。
///
diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs
index 7c94586..c6a279d 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StoreFeesContracts.cs
@@ -67,6 +67,10 @@ public sealed class StoreFeesSettingsDto
///
public string StoreId { get; set; } = string.Empty;
///
+ /// IsConfigured。
+ ///
+ public bool IsConfigured { get; set; }
+ ///
/// MinimumOrderAmount。
///
public decimal MinimumOrderAmount { get; set; }
diff --git a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs
index 50e7247..ecc5758 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Contracts/Store/StorePickupContracts.cs
@@ -145,13 +145,17 @@ public sealed class StorePickupSettingsDto
///
public string StoreId { get; set; } = string.Empty;
///
+ /// IsConfigured。
+ ///
+ public bool IsConfigured { get; set; }
+ ///
/// Mode。
///
- public string Mode { get; set; } = "big";
+ public string? Mode { get; set; }
///
/// BasicSettings。
///
- public PickupBasicSettingsDto BasicSettings { get; set; } = new();
+ public PickupBasicSettingsDto? BasicSettings { get; set; }
///
/// BigSlots。
///
@@ -159,7 +163,7 @@ public sealed class StorePickupSettingsDto
///
/// FineRule。
///
- public PickupFineRuleDto FineRule { get; set; } = new();
+ public PickupFineRuleDto? FineRule { get; set; }
///
/// PreviewDays。
///
diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs
index 79ba327..0b97b1e 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDeliveryController.cs
@@ -48,21 +48,25 @@ public sealed class StoreDeliveryController(
.ToListAsync(cancellationToken);
var radiusTiers = ParseRadiusTiers(setting?.RadiusTiersJson);
+ var isConfigured = setting is not null || polygonZones.Count > 0 || radiusTiers.Count > 0;
return ApiResponse.Ok(new StoreDeliverySettingsDto
{
StoreId = parsedStoreId.ToString(),
- Mode = StoreApiHelpers.ToDeliveryModeText(setting?.Mode ?? StoreDeliveryMode.Radius),
+ IsConfigured = isConfigured,
+ Mode = setting is null ? null : StoreApiHelpers.ToDeliveryModeText(setting.Mode),
RadiusCenterLatitude = setting?.RadiusCenterLatitude,
RadiusCenterLongitude = setting?.RadiusCenterLongitude,
RadiusTiers = radiusTiers,
PolygonZones = polygonZones.Select(MapPolygonZone).ToList(),
- GeneralSettings = new DeliveryGeneralSettingsDto
- {
- EtaAdjustmentMinutes = setting?.EtaAdjustmentMinutes ?? 10,
- FreeDeliveryThreshold = setting?.FreeDeliveryThreshold ?? 30m,
- HourlyCapacityLimit = setting?.HourlyCapacityLimit ?? 50,
- MaxDeliveryDistance = setting?.MaxDeliveryDistance ?? 5m
- }
+ GeneralSettings = setting is null
+ ? null
+ : new DeliveryGeneralSettingsDto
+ {
+ EtaAdjustmentMinutes = setting.EtaAdjustmentMinutes,
+ FreeDeliveryThreshold = setting.FreeDeliveryThreshold,
+ HourlyCapacityLimit = setting.HourlyCapacityLimit,
+ MaxDeliveryDistance = setting.MaxDeliveryDistance
+ }
});
}
@@ -98,6 +102,16 @@ public sealed class StoreDeliveryController(
public async Task> Save([FromBody] StoreDeliverySettingsDto request, CancellationToken cancellationToken)
{
var parsedStoreId = StoreApiHelpers.ParseRequiredSnowflake(request.StoreId, "storeId");
+ if (string.IsNullOrWhiteSpace(request.Mode))
+ {
+ throw new BusinessException(ErrorCodes.BadRequest, "mode 不能为空");
+ }
+
+ if (request.GeneralSettings is null)
+ {
+ throw new BusinessException(ErrorCodes.BadRequest, "generalSettings 不能为空");
+ }
+
var (tenantId, merchantId) = StoreApiHelpers.GetTenantMerchantContext(storeContextService);
await StoreApiHelpers.EnsureStoreAccessibleAsync(dbContext, tenantId, merchantId, parsedStoreId, cancellationToken);
@@ -203,6 +217,10 @@ public sealed class StoreDeliveryController(
.AsNoTracking()
.Where(x => x.TenantId == tenantId && x.StoreId == sourceStoreId)
.ToListAsync(cancellationToken);
+ if (sourceSetting is null)
+ {
+ throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置配送设置,无法复制");
+ }
var targetSettings = await dbContext.StoreDeliverySettings
.Where(x => x.TenantId == tenantId && accessibleTargetIds.Contains(x.StoreId))
@@ -220,14 +238,14 @@ public sealed class StoreDeliveryController(
await dbContext.StoreDeliverySettings.AddAsync(targetSetting, cancellationToken);
}
- targetSetting.Mode = sourceSetting?.Mode ?? StoreDeliveryMode.Radius;
- targetSetting.EtaAdjustmentMinutes = sourceSetting?.EtaAdjustmentMinutes ?? 10;
- targetSetting.FreeDeliveryThreshold = sourceSetting?.FreeDeliveryThreshold ?? 30m;
- targetSetting.HourlyCapacityLimit = sourceSetting?.HourlyCapacityLimit ?? 50;
- targetSetting.MaxDeliveryDistance = sourceSetting?.MaxDeliveryDistance ?? 5m;
- targetSetting.RadiusCenterLatitude = sourceSetting?.RadiusCenterLatitude;
- targetSetting.RadiusCenterLongitude = sourceSetting?.RadiusCenterLongitude;
- targetSetting.RadiusTiersJson = sourceSetting?.RadiusTiersJson;
+ targetSetting.Mode = sourceSetting.Mode;
+ targetSetting.EtaAdjustmentMinutes = sourceSetting.EtaAdjustmentMinutes;
+ targetSetting.FreeDeliveryThreshold = sourceSetting.FreeDeliveryThreshold;
+ targetSetting.HourlyCapacityLimit = sourceSetting.HourlyCapacityLimit;
+ targetSetting.MaxDeliveryDistance = sourceSetting.MaxDeliveryDistance;
+ targetSetting.RadiusCenterLatitude = sourceSetting.RadiusCenterLatitude;
+ targetSetting.RadiusCenterLongitude = sourceSetting.RadiusCenterLongitude;
+ targetSetting.RadiusTiersJson = sourceSetting.RadiusTiersJson;
}
var targetZones = await dbContext.StoreDeliveryZones
@@ -264,55 +282,20 @@ public sealed class StoreDeliveryController(
private static List ParseRadiusTiers(string? raw)
{
- if (!string.IsNullOrWhiteSpace(raw))
+ if (string.IsNullOrWhiteSpace(raw))
{
- try
- {
- var parsed = JsonSerializer.Deserialize>(raw, StoreApiHelpers.JsonOptions);
- if (parsed is not null && parsed.Count > 0)
- {
- return NormalizeRadiusTiers(parsed);
- }
- }
- catch
- {
- // 忽略配置反序列化异常并回落默认值
- }
+ return [];
}
- return NormalizeRadiusTiers(new List
+ try
{
- new()
- {
- Id = "tier-1",
- MinDistance = 0m,
- MaxDistance = 1m,
- DeliveryFee = 3m,
- EtaMinutes = 20,
- MinOrderAmount = 15m,
- Color = "#52c41a"
- },
- new()
- {
- Id = "tier-2",
- MinDistance = 1m,
- MaxDistance = 3m,
- DeliveryFee = 5m,
- EtaMinutes = 35,
- MinOrderAmount = 20m,
- Color = "#faad14"
- },
- new()
- {
- Id = "tier-3",
- MinDistance = 3m,
- MaxDistance = 5m,
- DeliveryFee = 8m,
- EtaMinutes = 50,
- MinOrderAmount = 25m,
- Color = "#ff4d4f"
- }
- });
+ var parsed = JsonSerializer.Deserialize>(raw, StoreApiHelpers.JsonOptions);
+ return NormalizeRadiusTiers(parsed);
+ }
+ catch
+ {
+ return [];
+ }
}
private static List NormalizeRadiusTiers(IEnumerable? source)
@@ -343,9 +326,9 @@ public sealed class StoreDeliveryController(
{
Id = source.Id.ToString(),
Name = source.ZoneName,
- Color = source.Color ?? "#1677ff",
+ Color = source.Color ?? string.Empty,
DeliveryFee = source.DeliveryFee ?? 0m,
- EtaMinutes = source.EstimatedMinutes ?? 20,
+ EtaMinutes = source.EstimatedMinutes ?? 0,
MinOrderAmount = source.MinimumOrderAmount ?? 0m,
Priority = source.Priority,
PolygonGeoJson = source.PolygonGeoJson
diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs
index 2dd74da..ea26846 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreDineInController.cs
@@ -47,16 +47,20 @@ public sealed class StoreDineInController(
.Where(x => x.TenantId == tenantId && x.StoreId == parsedStoreId)
.OrderBy(x => x.TableCode)
.ToListAsync(cancellationToken);
+ var isConfigured = basic is not null || areas.Count > 0 || tables.Count > 0;
return ApiResponse.Ok(new StoreDineInSettingsDto
{
StoreId = parsedStoreId.ToString(),
- BasicSettings = new DineInBasicSettingsDto
- {
- Enabled = basic?.Enabled ?? true,
- DefaultDiningMinutes = basic?.DefaultDiningMinutes ?? 90,
- OvertimeReminderMinutes = basic?.OvertimeReminderMinutes ?? 10
- },
+ IsConfigured = isConfigured,
+ BasicSettings = basic is null
+ ? null
+ : new DineInBasicSettingsDto
+ {
+ Enabled = basic.Enabled,
+ DefaultDiningMinutes = basic.DefaultDiningMinutes,
+ OvertimeReminderMinutes = basic.OvertimeReminderMinutes
+ },
Areas = areas.Select(MapArea).ToList(),
Tables = tables.Select(MapTable).ToList()
});
@@ -369,6 +373,10 @@ public sealed class StoreDineInController(
.Where(x => x.TenantId == tenantId && x.StoreId == sourceStoreId)
.OrderBy(x => x.TableCode)
.ToListAsync(cancellationToken);
+ if (sourceBasic is null)
+ {
+ throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置堂食基础设置,无法复制");
+ }
foreach (var targetStoreId in accessibleTargetIds)
{
@@ -383,9 +391,9 @@ public sealed class StoreDineInController(
await dbContext.StoreDineInSettings.AddAsync(targetBasic, cancellationToken);
}
- targetBasic.Enabled = sourceBasic?.Enabled ?? true;
- targetBasic.DefaultDiningMinutes = sourceBasic?.DefaultDiningMinutes ?? 90;
- targetBasic.OvertimeReminderMinutes = sourceBasic?.OvertimeReminderMinutes ?? 10;
+ targetBasic.Enabled = sourceBasic.Enabled;
+ targetBasic.DefaultDiningMinutes = sourceBasic.DefaultDiningMinutes;
+ targetBasic.OvertimeReminderMinutes = sourceBasic.OvertimeReminderMinutes;
var targetTables = await dbContext.StoreTables
.Where(x => x.TenantId == tenantId && x.StoreId == targetStoreId)
diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs
index 5501c83..07eeb28 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StoreFeesController.cs
@@ -9,6 +9,8 @@ using TakeoutSaaS.Application.App.Stores.Services;
using TakeoutSaaS.Domain.Stores.Entities;
using TakeoutSaaS.Domain.Stores.Enums;
using TakeoutSaaS.Infrastructure.App.Persistence;
+using TakeoutSaaS.Shared.Abstractions.Constants;
+using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;
using TakeoutSaaS.TenantApi.Contracts.Store;
@@ -116,6 +118,10 @@ public sealed class StoreFeesController(
var sourceFee = await dbContext.StoreFees
.AsNoTracking()
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.StoreId == sourceStoreId, cancellationToken);
+ if (sourceFee is null)
+ {
+ throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置费用设置,无法复制");
+ }
var targetFees = await dbContext.StoreFees
.Where(x => x.TenantId == tenantId && accessibleTargetIds.Contains(x.StoreId))
@@ -133,17 +139,17 @@ public sealed class StoreFeesController(
await dbContext.StoreFees.AddAsync(targetFee, cancellationToken);
}
- targetFee.MinimumOrderAmount = sourceFee?.MinimumOrderAmount ?? 0m;
- targetFee.BaseDeliveryFee = sourceFee?.BaseDeliveryFee ?? 0m;
- targetFee.FreeDeliveryThreshold = sourceFee?.FreeDeliveryThreshold;
- targetFee.PackagingFeeMode = sourceFee?.PackagingFeeMode ?? PackagingFeeMode.Fixed;
- targetFee.OrderPackagingFeeMode = sourceFee?.OrderPackagingFeeMode ?? OrderPackagingFeeMode.Fixed;
- targetFee.FixedPackagingFee = sourceFee?.FixedPackagingFee ?? 0m;
- targetFee.PackagingFeeTiersJson = sourceFee?.PackagingFeeTiersJson;
- targetFee.CutleryFeeEnabled = sourceFee?.CutleryFeeEnabled ?? false;
- targetFee.CutleryFeeAmount = sourceFee?.CutleryFeeAmount ?? 0m;
- targetFee.RushFeeEnabled = sourceFee?.RushFeeEnabled ?? false;
- targetFee.RushFeeAmount = sourceFee?.RushFeeAmount ?? 0m;
+ targetFee.MinimumOrderAmount = sourceFee.MinimumOrderAmount;
+ targetFee.BaseDeliveryFee = sourceFee.BaseDeliveryFee;
+ targetFee.FreeDeliveryThreshold = sourceFee.FreeDeliveryThreshold;
+ targetFee.PackagingFeeMode = sourceFee.PackagingFeeMode;
+ targetFee.OrderPackagingFeeMode = sourceFee.OrderPackagingFeeMode;
+ targetFee.FixedPackagingFee = sourceFee.FixedPackagingFee;
+ targetFee.PackagingFeeTiersJson = sourceFee.PackagingFeeTiersJson;
+ targetFee.CutleryFeeEnabled = sourceFee.CutleryFeeEnabled;
+ targetFee.CutleryFeeAmount = sourceFee.CutleryFeeAmount;
+ targetFee.RushFeeEnabled = sourceFee.RushFeeEnabled;
+ targetFee.RushFeeAmount = sourceFee.RushFeeAmount;
}
await dbContext.SaveChangesAsync(cancellationToken);
@@ -171,6 +177,7 @@ public sealed class StoreFeesController(
return new StoreFeesSettingsDto
{
StoreId = storeId.ToString(),
+ IsConfigured = source is not null,
MinimumOrderAmount = source?.MinimumOrderAmount ?? 0m,
BaseDeliveryFee = source?.DeliveryFee ?? 0m,
FreeDeliveryThreshold = source?.FreeDeliveryThreshold,
@@ -196,9 +203,17 @@ public sealed class StoreFeesController(
private static PackagingFeeMode ParsePackagingFeeMode(string? value)
{
- return string.Equals(value, "item", StringComparison.OrdinalIgnoreCase)
- ? PackagingFeeMode.PerItem
- : PackagingFeeMode.Fixed;
+ if (string.Equals(value, "item", StringComparison.OrdinalIgnoreCase))
+ {
+ return PackagingFeeMode.PerItem;
+ }
+
+ if (string.Equals(value, "order", StringComparison.OrdinalIgnoreCase))
+ {
+ return PackagingFeeMode.Fixed;
+ }
+
+ throw new BusinessException(ErrorCodes.BadRequest, "packagingFeeMode 非法");
}
private static string ToPackagingFeeModeText(PackagingFeeMode value)
@@ -208,9 +223,17 @@ public sealed class StoreFeesController(
private static OrderPackagingFeeMode ParseOrderPackagingFeeMode(string? value)
{
- return string.Equals(value, "tiered", StringComparison.OrdinalIgnoreCase)
- ? OrderPackagingFeeMode.Tiered
- : OrderPackagingFeeMode.Fixed;
+ if (string.Equals(value, "tiered", StringComparison.OrdinalIgnoreCase))
+ {
+ return OrderPackagingFeeMode.Tiered;
+ }
+
+ if (string.Equals(value, "fixed", StringComparison.OrdinalIgnoreCase))
+ {
+ return OrderPackagingFeeMode.Fixed;
+ }
+
+ throw new BusinessException(ErrorCodes.BadRequest, "orderPackagingFeeMode 非法");
}
private static string ToOrderPackagingFeeModeText(OrderPackagingFeeMode value)
diff --git a/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs b/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs
index 2b0a39e..0266981 100644
--- a/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs
+++ b/src/Api/TakeoutSaaS.TenantApi/Controllers/StorePickupController.cs
@@ -7,6 +7,8 @@ using TakeoutSaaS.Application.App.Stores.Services;
using TakeoutSaaS.Domain.Stores.Entities;
using TakeoutSaaS.Domain.Stores.Enums;
using TakeoutSaaS.Infrastructure.App.Persistence;
+using TakeoutSaaS.Shared.Abstractions.Constants;
+using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Results;
using TakeoutSaaS.Shared.Web.Api;
using TakeoutSaaS.TenantApi.Contracts.Store;
@@ -46,18 +48,22 @@ public sealed class StorePickupController(
.ToListAsync(cancellationToken);
var fineRule = ParseFineRule(setting?.FineRuleJson);
- var previewDays = BuildPreviewDays(fineRule);
+ var previewDays = fineRule is null ? [] : BuildPreviewDays(fineRule);
+ var isConfigured = setting is not null || slots.Count > 0;
var response = new StorePickupSettingsDto
{
StoreId = parsedStoreId.ToString(),
- Mode = StoreApiHelpers.ToPickupModeText(setting?.Mode ?? StorePickupMode.Big),
- BasicSettings = new PickupBasicSettingsDto
- {
- AllowSameDayPickup = setting?.AllowToday ?? true,
- BookingDays = setting?.AllowDaysAhead ?? 3,
- MaxItemsPerOrder = setting?.MaxQuantityPerOrder ?? 20
- },
+ IsConfigured = isConfigured,
+ Mode = setting is null ? null : StoreApiHelpers.ToPickupModeText(setting.Mode),
+ BasicSettings = setting is null
+ ? null
+ : new PickupBasicSettingsDto
+ {
+ AllowSameDayPickup = setting.AllowToday,
+ BookingDays = setting.AllowDaysAhead,
+ MaxItemsPerOrder = setting.MaxQuantityPerOrder
+ },
BigSlots = slots.Select(slot => new PickupSlotDto
{
Id = slot.Id.ToString(),
@@ -211,6 +217,10 @@ public sealed class StorePickupController(
.AsNoTracking()
.Where(x => x.TenantId == tenantId && x.StoreId == sourceStoreId)
.ToListAsync(cancellationToken);
+ if (sourceSetting is null)
+ {
+ throw new BusinessException(ErrorCodes.BadRequest, "源门店未配置自提设置,无法复制");
+ }
var targetSettings = await dbContext.StorePickupSettings
.Where(x => x.TenantId == tenantId && accessibleTargetIds.Contains(x.StoreId))
@@ -229,12 +239,12 @@ public sealed class StorePickupController(
await dbContext.StorePickupSettings.AddAsync(targetSetting, cancellationToken);
}
- targetSetting.AllowToday = sourceSetting?.AllowToday ?? true;
- targetSetting.AllowDaysAhead = sourceSetting?.AllowDaysAhead ?? 3;
- targetSetting.DefaultCutoffMinutes = sourceSetting?.DefaultCutoffMinutes ?? 30;
- targetSetting.MaxQuantityPerOrder = sourceSetting?.MaxQuantityPerOrder ?? 20;
- targetSetting.Mode = sourceSetting?.Mode ?? StorePickupMode.Big;
- targetSetting.FineRuleJson = sourceSetting?.FineRuleJson;
+ targetSetting.AllowToday = sourceSetting.AllowToday;
+ targetSetting.AllowDaysAhead = sourceSetting.AllowDaysAhead;
+ targetSetting.DefaultCutoffMinutes = sourceSetting.DefaultCutoffMinutes;
+ targetSetting.MaxQuantityPerOrder = sourceSetting.MaxQuantityPerOrder;
+ targetSetting.Mode = sourceSetting.Mode;
+ targetSetting.FineRuleJson = sourceSetting.FineRuleJson;
targetSetting.RowVersion = CreateRowVersion();
}
@@ -295,46 +305,35 @@ public sealed class StorePickupController(
return RandomNumberGenerator.GetBytes(16);
}
- private static PickupFineRuleDto ParseFineRule(string? raw)
+ private static PickupFineRuleDto? ParseFineRule(string? raw)
{
- if (!string.IsNullOrWhiteSpace(raw))
+ if (string.IsNullOrWhiteSpace(raw))
{
- try
- {
- var parsed = JsonSerializer.Deserialize(raw, StoreApiHelpers.JsonOptions);
- if (parsed is not null)
- {
- return NormalizeFineRule(parsed);
- }
- }
- catch
- {
- // 忽略反序列化异常,回落默认配置
- }
+ return null;
}
- return new PickupFineRuleDto
+ try
{
- IntervalMinutes = 30,
- SlotCapacity = 5,
- DayStartTime = "09:00",
- DayEndTime = "20:30",
- MinAdvanceHours = 2,
- DayOfWeeks = [0, 1, 2, 3, 4, 5, 6]
- };
+ var parsed = JsonSerializer.Deserialize(raw, StoreApiHelpers.JsonOptions);
+ return parsed is null ? null : NormalizeFineRule(parsed);
+ }
+ catch
+ {
+ return null;
+ }
}
private static PickupFineRuleDto NormalizeFineRule(PickupFineRuleDto source)
{
- var start = string.IsNullOrWhiteSpace(source.DayStartTime) ? "09:00" : source.DayStartTime;
- var end = string.IsNullOrWhiteSpace(source.DayEndTime) ? "20:30" : source.DayEndTime;
+ var start = StoreApiHelpers.ParseRequiredTime(source.DayStartTime, "fineRule.dayStartTime");
+ var end = StoreApiHelpers.ParseRequiredTime(source.DayEndTime, "fineRule.dayEndTime");
return new PickupFineRuleDto
{
IntervalMinutes = Math.Clamp(source.IntervalMinutes, 5, 180),
SlotCapacity = Math.Clamp(source.SlotCapacity, 1, 999),
- DayStartTime = StoreApiHelpers.ToHHmm(StoreApiHelpers.ParseRequiredTime(start, "fineRule.dayStartTime")),
- DayEndTime = StoreApiHelpers.ToHHmm(StoreApiHelpers.ParseRequiredTime(end, "fineRule.dayEndTime")),
+ DayStartTime = StoreApiHelpers.ToHHmm(start),
+ DayEndTime = StoreApiHelpers.ToHHmm(end),
MinAdvanceHours = Math.Clamp(source.MinAdvanceHours, 0, 72),
DayOfWeeks = (source.DayOfWeeks ?? [])
.Distinct()
diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs
index 823466a..ac29821 100644
--- a/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Stores/Handlers/GetStoreFeeQueryHandler.cs
@@ -2,7 +2,6 @@ using MediatR;
using TakeoutSaaS.Application.App.Stores;
using TakeoutSaaS.Application.App.Stores.Dto;
using TakeoutSaaS.Application.App.Stores.Queries;
-using TakeoutSaaS.Domain.Stores.Entities;
using TakeoutSaaS.Domain.Stores.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
@@ -31,25 +30,7 @@ public sealed class GetStoreFeeQueryHandler(
// 2. (空行后) 查询费用配置
var fee = await storeRepository.GetStoreFeeAsync(request.StoreId, tenantId, cancellationToken);
- if (fee is null)
- {
- var fallback = new StoreFee
- {
- StoreId = request.StoreId,
- MinimumOrderAmount = 0m,
- BaseDeliveryFee = 0m,
- PackagingFeeMode = Domain.Stores.Enums.PackagingFeeMode.Fixed,
- OrderPackagingFeeMode = Domain.Stores.Enums.OrderPackagingFeeMode.Fixed,
- FixedPackagingFee = 0m,
- CutleryFeeEnabled = false,
- CutleryFeeAmount = 0m,
- RushFeeEnabled = false,
- RushFeeAmount = 0m
- };
- return StoreMapping.ToDto(fallback);
- }
-
// 3. (空行后) 返回结果
- return StoreMapping.ToDto(fee);
+ return fee is null ? null : StoreMapping.ToDto(fee);
}
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs b/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs
index 0a29b63..9b723e0 100644
--- a/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Stores/StoreListMapping.cs
@@ -101,29 +101,12 @@ public static class StoreListMapping
result.Add(ServiceType.DineIn);
}
- // 2. 兜底默认展示配送服务
- if (result.Count == 0)
- {
- result.Add(ServiceType.Delivery);
- }
-
return result;
}
private static string ResolveAddress(Store store)
{
- // 1. 地址优先返回业务地址字段
- if (!string.IsNullOrWhiteSpace(store.Address))
- {
- return store.Address;
- }
-
- // 2. 兜底拼接省市区
- var parts = new[] { store.Province, store.City, store.District }
- .Where(static part => !string.IsNullOrWhiteSpace(part))
- .ToArray();
-
- return parts.Length == 0 ? string.Empty : string.Join(string.Empty, parts);
+ return string.IsNullOrWhiteSpace(store.Address) ? string.Empty : store.Address;
}
}