using Fake.DependencyInjection; using Fake.Application; using Oms.Domain.CustomersAggregate.Consts; using Oms.Domain.CustomersAggregate.Entities; using Oms.Domain.CustomersAggregate.Repositories; namespace Oms.Application.Shared; /// /// 佣金账户变动与流水。 /// public class CommissionBalanceMutator : IScopedDependency { private readonly ICustomerRepository _customerRepository; private readonly ICustomerAccountFlowRepository _flowRepository; private readonly CustomerBalanceMutator _balanceMutator; public CommissionBalanceMutator( ICustomerRepository customerRepository, ICustomerAccountFlowRepository flowRepository, CustomerBalanceMutator balanceMutator) { _customerRepository = customerRepository; _flowRepository = flowRepository; _balanceMutator = balanceMutator; } public async Task CreditCommissionAsync( Customer customer, decimal amount, int detailId, string? orderNo, string? remark, CancellationToken cancellationToken = default) { await ApplyCommissionAsync(customer, amount, CustomerAccountFlowBizTypes.ReferralCommission, detailId, orderNo, remark, cancellationToken); } public async Task DebitForTransferToBalanceAsync( Customer customer, decimal amount, int withdrawRequestId, string serialNumber, string? remark, CancellationToken cancellationToken = default) { await ApplyCommissionAsync(customer, -amount, CustomerAccountFlowBizTypes.CommissionToBalance, withdrawRequestId, serialNumber, remark, cancellationToken); await _balanceMutator.CreditRechargeAsync(customer, amount, withdrawRequestId, serialNumber, remark ?? "佣金转余额", cancellationToken); } public async Task DebitForWithdrawAsync( Customer customer, decimal amount, int withdrawRequestId, string serialNumber, string? remark, CancellationToken cancellationToken = default) { await ApplyCommissionAsync(customer, -amount, CustomerAccountFlowBizTypes.CommissionWithdraw, withdrawRequestId, serialNumber, remark, cancellationToken); } public async Task AdjustCommissionAsync( Customer customer, decimal signedAmount, int? detailId, string? remark, CancellationToken cancellationToken = default) { await ApplyCommissionAsync( customer, signedAmount, CustomerAccountFlowBizTypes.MarketingAdjust, detailId, null, remark, cancellationToken); } private async Task ApplyCommissionAsync( Customer customer, decimal signedAmount, string bizType, int? bizId, string? bizNo, string? remark, CancellationToken cancellationToken) { if (signedAmount == 0) { throw new BusinessException("佣金变动金额不能为 0"); } var before = customer.CommissionBalance; var after = before + signedAmount; if (after < 0) { throw new BusinessException("佣金余额不足"); } customer.CommissionBalance = after; await _customerRepository.UpdateAsync(customer, cancellationToken); var flow = new CustomerAccountFlow { CustomerId = customer.Id, SerialNumber = await GenerateSerialNumberAsync(cancellationToken), BizType = bizType, BizId = bizId, BizNo = bizNo, Amount = signedAmount, BalanceBefore = customer.Balance, BalanceAfter = customer.Balance, Currency = "CNY", Remark = remark }; await _flowRepository.InsertAsync(flow, cancellationToken); } private async Task GenerateSerialNumberAsync(CancellationToken cancellationToken) { for (var i = 0; i < 5; i++) { var serialNumber = $"CMF{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(100000, 999999)}"; if (!await _flowRepository.ExistsSerialNumberAsync(serialNumber, cancellationToken)) { return serialNumber; } } throw new BusinessException("佣金流水号生成失败"); } }