refactor(store): remove fallback config behavior and expose isConfigured
All checks were successful
Build and Deploy TenantApi / build-and-deploy (push) Successful in 43s

This commit is contained in:
2026-02-20 09:55:11 +08:00
parent 938da7469c
commit 8a6fc867c2
10 changed files with 166 additions and 173 deletions

View File

@@ -107,9 +107,13 @@ public sealed class StoreDeliverySettingsDto
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// IsConfigured。
/// </summary>
public bool IsConfigured { get; set; }
/// <summary>
/// Mode。
/// </summary>
public string Mode { get; set; } = "radius";
public string? Mode { get; set; }
/// <summary>
/// RadiusCenterLatitude。
/// </summary>
@@ -129,7 +133,7 @@ public sealed class StoreDeliverySettingsDto
/// <summary>
/// GeneralSettings。
/// </summary>
public DeliveryGeneralSettingsDto GeneralSettings { get; set; } = new();
public DeliveryGeneralSettingsDto? GeneralSettings { get; set; }
}
/// <summary>

View File

@@ -83,9 +83,13 @@ public sealed class StoreDineInSettingsDto
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// IsConfigured。
/// </summary>
public bool IsConfigured { get; set; }
/// <summary>
/// BasicSettings。
/// </summary>
public DineInBasicSettingsDto BasicSettings { get; set; } = new();
public DineInBasicSettingsDto? BasicSettings { get; set; }
/// <summary>
/// Areas。
/// </summary>

View File

@@ -67,6 +67,10 @@ public sealed class StoreFeesSettingsDto
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// IsConfigured。
/// </summary>
public bool IsConfigured { get; set; }
/// <summary>
/// MinimumOrderAmount。
/// </summary>
public decimal MinimumOrderAmount { get; set; }

View File

@@ -145,13 +145,17 @@ public sealed class StorePickupSettingsDto
/// </summary>
public string StoreId { get; set; } = string.Empty;
/// <summary>
/// IsConfigured。
/// </summary>
public bool IsConfigured { get; set; }
/// <summary>
/// Mode。
/// </summary>
public string Mode { get; set; } = "big";
public string? Mode { get; set; }
/// <summary>
/// BasicSettings。
/// </summary>
public PickupBasicSettingsDto BasicSettings { get; set; } = new();
public PickupBasicSettingsDto? BasicSettings { get; set; }
/// <summary>
/// BigSlots。
/// </summary>
@@ -159,7 +163,7 @@ public sealed class StorePickupSettingsDto
/// <summary>
/// FineRule。
/// </summary>
public PickupFineRuleDto FineRule { get; set; } = new();
public PickupFineRuleDto? FineRule { get; set; }
/// <summary>
/// PreviewDays。
/// </summary>

View File

@@ -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<StoreDeliverySettingsDto>.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<ApiResponse<object>> 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<RadiusTierDto> ParseRadiusTiers(string? raw)
{
if (!string.IsNullOrWhiteSpace(raw))
if (string.IsNullOrWhiteSpace(raw))
{
try
{
var parsed = JsonSerializer.Deserialize<List<RadiusTierDto>>(raw, StoreApiHelpers.JsonOptions);
if (parsed is not null && parsed.Count > 0)
{
return NormalizeRadiusTiers(parsed);
}
}
catch
{
// 忽略配置反序列化异常并回落默认值
}
return [];
}
return NormalizeRadiusTiers(new List<RadiusTierDto>
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<List<RadiusTierDto>>(raw, StoreApiHelpers.JsonOptions);
return NormalizeRadiusTiers(parsed);
}
catch
{
return [];
}
}
private static List<RadiusTierDto> NormalizeRadiusTiers(IEnumerable<RadiusTierDto>? 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

View File

@@ -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<StoreDineInSettingsDto>.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)

View File

@@ -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)

View File

@@ -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<PickupFineRuleDto>(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<PickupFineRuleDto>(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()

View File

@@ -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);
}
}

View File

@@ -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;
}
}