using MediatR; using TakeoutSaaS.Application.App.Coupons.NewCustomer.Commands; using TakeoutSaaS.Application.App.Coupons.NewCustomer.Dto; using TakeoutSaaS.Domain.Coupons.Entities; using TakeoutSaaS.Domain.Coupons.Enums; using TakeoutSaaS.Domain.Coupons.Repositories; using TakeoutSaaS.Shared.Abstractions.Constants; using TakeoutSaaS.Shared.Abstractions.Exceptions; using TakeoutSaaS.Shared.Abstractions.Tenancy; namespace TakeoutSaaS.Application.App.Coupons.NewCustomer.Handlers; /// /// 保存新客有礼配置处理器。 /// public sealed class SaveNewCustomerSettingsCommandHandler( INewCustomerGiftRepository repository, ITenantProvider tenantProvider) : IRequestHandler { /// public async Task Handle( SaveNewCustomerSettingsCommand request, CancellationToken cancellationToken) { if (request.StoreId <= 0) { throw new BusinessException(ErrorCodes.BadRequest, "storeId 参数不合法"); } var tenantId = tenantProvider.GetCurrentTenantId(); var giftType = NewCustomerMapping.ParseGiftType(request.GiftType); var shareChannels = NewCustomerMapping.NormalizeShareChannels(request.ShareChannels); var welcomeRules = NewCustomerMapping.NormalizeCouponRulesForSave( request.StoreId, NewCustomerCouponScene.Welcome, request.WelcomeCoupons); var inviterRules = NewCustomerMapping.NormalizeCouponRulesForSave( request.StoreId, NewCustomerCouponScene.InviterReward, request.InviterCoupons); var inviteeRules = NewCustomerMapping.NormalizeCouponRulesForSave( request.StoreId, NewCustomerCouponScene.InviteeReward, request.InviteeCoupons); if (giftType == NewCustomerGiftType.Coupon && welcomeRules.Count == 0) { throw new BusinessException(ErrorCodes.BadRequest, "优惠券包至少需要一张券"); } if (giftType == NewCustomerGiftType.Direct) { if (!request.DirectReduceAmount.HasValue || request.DirectReduceAmount.Value <= 0m) { throw new BusinessException(ErrorCodes.BadRequest, "directReduceAmount 必须大于 0"); } if (!request.DirectMinimumSpend.HasValue || request.DirectMinimumSpend.Value < 0m) { throw new BusinessException(ErrorCodes.BadRequest, "directMinimumSpend 不能小于 0"); } } if (request.InviteEnabled && (inviterRules.Count == 0 || inviteeRules.Count == 0)) { throw new BusinessException(ErrorCodes.BadRequest, "开启邀请后必须配置邀请人和被邀请人奖励券"); } var setting = await repository.FindSettingByStoreIdAsync(tenantId, request.StoreId, cancellationToken); var isNewSetting = setting is null; if (setting is null) { setting = new NewCustomerGiftSetting { StoreId = request.StoreId }; await repository.AddSettingAsync(setting, cancellationToken); } setting.GiftEnabled = request.GiftEnabled; setting.GiftType = giftType; setting.DirectReduceAmount = giftType == NewCustomerGiftType.Direct ? decimal.Round(request.DirectReduceAmount!.Value, 2, MidpointRounding.AwayFromZero) : null; setting.DirectMinimumSpend = giftType == NewCustomerGiftType.Direct ? decimal.Round(request.DirectMinimumSpend!.Value, 2, MidpointRounding.AwayFromZero) : null; setting.InviteEnabled = request.InviteEnabled; setting.ShareChannelsJson = NewCustomerMapping.SerializeShareChannels(shareChannels); if (!isNewSetting) { await repository.UpdateSettingAsync(setting, cancellationToken); } var allRules = new List(welcomeRules.Count + inviterRules.Count + inviteeRules.Count); allRules.AddRange(welcomeRules); allRules.AddRange(inviterRules); allRules.AddRange(inviteeRules); await repository.ReplaceCouponRulesAsync( tenantId, request.StoreId, allRules, cancellationToken); await repository.SaveChangesAsync(cancellationToken); return new NewCustomerSettingsDto { StoreId = request.StoreId, GiftEnabled = setting.GiftEnabled, GiftType = NewCustomerMapping.ToGiftTypeText(setting.GiftType), DirectReduceAmount = setting.DirectReduceAmount, DirectMinimumSpend = setting.DirectMinimumSpend, InviteEnabled = setting.InviteEnabled, ShareChannels = shareChannels, WelcomeCoupons = welcomeRules.Select(NewCustomerMapping.ToCouponRuleDto).ToList(), InviterCoupons = inviterRules.Select(NewCustomerMapping.ToCouponRuleDto).ToList(), InviteeCoupons = inviteeRules.Select(NewCustomerMapping.ToCouponRuleDto).ToList(), UpdatedAt = DateTime.UtcNow }; } }