using Furion.FriendlyException; using Microsoft.Extensions.Logging; using YD_Event.Application.Auth; using YD_Event.Application.Merchant.Dtos; using YD_Event.Core.Entities; using YD_Event.Core.Enum; namespace YD_Event.Application.Merchant; /// /// 商户管理 /// public class MerchantService : BaseService, ITransient { private readonly ISqlSugarRepository _repository; private readonly ISqlSugarRepository _userCouponRepository; private readonly ISqlSugarRepository _weChatPayConfigRepository; private readonly ISqlSugarRepository _eventRepository; private readonly ISqlSugarRepository _orderRepository; private readonly AuthManager _authManager; private readonly IIdGenerator _idGenerator; private readonly Microsoft.Extensions.Logging.ILogger _logger; public MerchantService(ISqlSugarRepository repository, ISqlSugarRepository userCouponRepository, ISqlSugarRepository weChatPayConfigRepository, ISqlSugarRepository eventRepository, ISqlSugarRepository orderRepository, AuthManager authManager, IIdGenerator idGenerator, Microsoft.Extensions.Logging.ILogger logger) : base(repository) { _repository = repository; _userCouponRepository = userCouponRepository; _weChatPayConfigRepository = weChatPayConfigRepository; _eventRepository = eventRepository; _orderRepository = orderRepository; _authManager = authManager; _idGenerator = idGenerator; _logger = logger; } /// /// 商户分页查询 /// [DisplayName("商户分页查询")] [HttpGet("page")] public async Task> Page([FromQuery] MerchantQueryInput input) { var pageResult = await _repository.AsQueryable() .WhereIF(!string.IsNullOrWhiteSpace(input.MerchantName), x => x.MerchantName.Contains(input.MerchantName)) .WhereIF(!string.IsNullOrWhiteSpace(input.ContactPhone), x => x.ContactPhone.Contains(input.ContactPhone)) .WhereIF(input.AuditStatus.HasValue, x => x.AuditStatus == input.AuditStatus) .WhereIF(input.StartTime.HasValue, x => x.CreatedTime >= input.StartTime) .WhereIF(input.EndTime.HasValue, x => x.CreatedTime <= input.EndTime) .OrderByDescending(x => x.CreatedTime) .Select(x => new MerchantOutput { Id = x.Id, MerchantName = x.MerchantName, CreditCode = x.CreditCode, BankName = x.BankName, AccountNumber = x.AccountNumber, BusinessLicenseUrl = x.BusinessLicenseUrl, ContactPhone = x.ContactPhone, Address = x.Address, AuditStatus = x.AuditStatus, AuditRemark = x.AuditRemark, Status = x.Status, CreatedTime = x.CreatedTime, UpdatedTime = x.UpdatedTime }) .ToPagedListAsync(input); return pageResult; } /// /// 添加商户 /// [DisplayName("添加商户")] [HttpPost("add")] [UnitOfWork] public async Task Add(AddMerchantInput input) { var entity = input.Adapt(); entity.Id = _idGenerator.NextId(); await _repository.InsertAsync(entity); if (input.WeChatPayConfig != null) { var weChatPayConfig = input.WeChatPayConfig.Adapt(); weChatPayConfig.Id = _idGenerator.NextId(); weChatPayConfig.MerchantId = entity.Id; await _weChatPayConfigRepository.InsertAsync(weChatPayConfig); } } /// /// 更新商户 /// [DisplayName("更新商户")] [HttpPut("edit")] [UnitOfWork] public async Task Update(UpdateMerchantInput input) { var entity = await _repository.GetByIdAsync(input.Id); if (entity == null) throw Oops.Bah("商户不存在"); input.Adapt(entity); await _repository.UpdateAsync(entity); var existingWeChatPayConfig = await _weChatPayConfigRepository.GetFirstAsync(c => c.MerchantId == input.Id); if (input.WeChatPayConfig != null) { if (existingWeChatPayConfig != null) { input.WeChatPayConfig.Adapt(existingWeChatPayConfig); await _weChatPayConfigRepository.UpdateAsync(existingWeChatPayConfig); } else { var weChatPayConfig = input.WeChatPayConfig.Adapt(); weChatPayConfig.Id = _idGenerator.NextId(); weChatPayConfig.MerchantId = input.Id; await _weChatPayConfigRepository.InsertAsync(weChatPayConfig); } } else { if (existingWeChatPayConfig != null) { await _weChatPayConfigRepository.DeleteAsync(existingWeChatPayConfig); } } } /// /// 删除商户 /// [DisplayName("删除商户")] [HttpPost("delete")] [UnitOfWork] public async Task Delete([FromBody] List ids) { _logger.LogInformation("开始删除商户:商户ID列表={Ids}", string.Join(",", ids)); if (ids == null || !ids.Any()) { _logger.LogWarning("删除商户失败:未选择商户"); return; } // 检查商户是否被赛事使用 var hasEvents = await _eventRepository.IsAnyAsync(x => x.MerchantId.HasValue && ids.Contains(x.MerchantId.Value) && !x.DeleteMark); if (hasEvents) { _logger.LogWarning("删除商户失败:部分商户正在被赛事使用"); throw Oops.Bah("部分商户正在被赛事使用,无法删除。请先从赛事中移除这些商户。"); } // 检查商户是否有订单记录 var hasOrders = await _orderRepository.IsAnyAsync(x => x.MerchantId.HasValue && ids.Contains(x.MerchantId.Value) && !x.DeleteMark); if (hasOrders) { _logger.LogWarning("删除商户失败:部分商户已有订单记录"); throw Oops.Bah("部分商户已有订单记录,为保证数据完整性,无法删除。"); } // 执行删除 await _repository.DeleteAsync(x => ids.Contains(x.Id)); // 同时删除关联的微信支付配置 await _weChatPayConfigRepository.DeleteAsync(x => ids.Contains(x.MerchantId)); _logger.LogInformation("删除商户成功:商户ID列表={Ids}", string.Join(",", ids)); } /// /// 获取商户详情 /// [DisplayName("获取商户详情")] [HttpGet("detail")] public async Task Detail([FromQuery] long id) { var entity = await _repository.GetByIdAsync(id); if (entity == null) throw Oops.Bah("商户不存在"); var weChatPayConfig = await _weChatPayConfigRepository.GetFirstAsync(c => c.MerchantId == id); return new MerchantOutput { Id = entity.Id, MerchantName = entity.MerchantName, CreditCode = entity.CreditCode, BankName = entity.BankName, AccountNumber = entity.AccountNumber, BusinessLicenseUrl = entity.BusinessLicenseUrl, ContactPhone = entity.ContactPhone, Address = entity.Address, AuditStatus = entity.AuditStatus, AuditRemark = entity.AuditRemark, Status = entity.Status, CreatedTime = entity.CreatedTime, UpdatedTime = entity.UpdatedTime, WeChatPayConfig = weChatPayConfig != null ? weChatPayConfig.Adapt() : null }; } /// /// 发放优惠券 /// [DisplayName("发放优惠券")] [HttpPost("issueCoupon")] [UnitOfWork] public async Task IssueCoupon([FromBody] IssueCouponInput input) { if (input.MerchantIds == null || !input.MerchantIds.Any()) return; if (input.Count <= 0) throw Oops.Bah("发放数量必须大于0"); var merchants = await _repository.GetListAsync(m => input.MerchantIds.Contains(m.Id)); if (!merchants.Any()) return; var coupons = new List(); var now = DateTime.Now; foreach (var merchant in merchants) { for (int i = 0; i < input.Count; i++) { coupons.Add(new UserCoupon { Id = _idGenerator.NextId(), UserId = merchant.CreatedUserId, // Issue to the creator of the merchant CouponId = input.CouponId, Status = 0, // Unused ClaimTime = now, CreatedTime = now, CreatedUserId = _authManager.UserId }); } } await _userCouponRepository.InsertRangeAsync(coupons); } }