| | |
| | | using ZeroD.Util; |
| | | using LifePayment.Domain; |
| | | using static LifePayment.Domain.Shared.LifePaymentConstant; |
| | | using Newtonsoft.Json; |
| | | using LifePayment.Domain.Common; |
| | | using Spire.Pdf.Exporting.XPS.Schema; |
| | | |
| | | namespace LifePayment.Application.LifePay |
| | | { |
| | |
| | | { |
| | | private readonly IRepository<LifePayRechargeReceipts, Guid> _lifePayRechargeReceiptsRepository; |
| | | private readonly IRepository<LifePayExpensesReceipts, Guid> _lifePayExpensesReceiptsRepository; |
| | | private readonly IRepository<LifePayConsumption, Guid> _lifePayConsumption; |
| | | private readonly IRepository<LifePayChannlesRake, Guid> _lifePayChannlesRakeRepository; |
| | | private readonly IRepository<LifePayOrder, Guid> _lifePayOrderRepository; |
| | | private readonly IAliPayApi _aliPayApi; |
| | | private readonly IWxPayApi _wxPayApi; |
| | | |
| | | public LifePayOrderService( |
| | | IRepository<LifePayRechargeReceipts, Guid> lifePayRechargeReceiptsRepository, |
| | | IRepository<LifePayExpensesReceipts, Guid> lifePayExpensesReceiptsRepository, |
| | | IRepository<LifePayConsumption, Guid> lifePayConsumptionRepository, |
| | | IRepository<LifePayChannlesRake, Guid> lifePayChannlesRakeRepository, |
| | | IRepository<LifePayOrder, Guid> lifePayOrderRepository, |
| | | IAliPayApi aliPayApi, |
| | | IWxPayApi wxPayApi) |
| | | { |
| | | _lifePayRechargeReceiptsRepository = lifePayRechargeReceiptsRepository; |
| | | _lifePayExpensesReceiptsRepository = lifePayExpensesReceiptsRepository; |
| | | _lifePayConsumption = lifePayConsumptionRepository; |
| | | _lifePayChannlesRakeRepository = lifePayChannlesRakeRepository; |
| | | _lifePayOrderRepository = lifePayOrderRepository; |
| | | _aliPayApi = aliPayApi; |
| | | _wxPayApi = wxPayApi; |
| | | } |
| | | |
| | | #region 查询 |
| | | |
| | | /// <summary> |
| | | /// 获取消费流水 |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| | | /// <returns></returns> |
| | | public async Task<PageOutput<LifePayConsumptionListOutput>> GetLifePayConsumptionPage(LifePayConsumptionPageInput input) |
| | | { |
| | | var list = await _lifePayConsumption.Where(x => x.IsDeleted == false) |
| | | .WhereIf(input.KeyWord.IsNotNullOrEmpty(), x => x.OrderNo.Contains(input.KeyWord) || x.OutOrderNo.Contains(input.KeyWord) || x.ChannelId.Contains(input.KeyWord)) |
| | | .WhereIf(input.Flow.HasValue,x => x.Flow == input.Flow) |
| | | .WhereIf(input.TimeBegin.HasValue, x => x.FinishTime >= input.TimeBegin) |
| | | .WhereIf(input.TimeEnd.HasValue, x => x.FinishTime <= input.TimeEnd) |
| | | .Select(x => new LifePayConsumptionListOutput() |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | OutOrderNo = x.OutOrderNo, |
| | | Amount = x.Amount, |
| | | FinishTime = x.FinishTime, |
| | | FrozenStatus = x.FrozenStatus, |
| | | Flow = x.Flow, |
| | | DeductionAmount = x.DeductionAmount, |
| | | }) |
| | | .GetPageResult(input.PageModel); |
| | | |
| | | var total = await _lifePayRechargeReceiptsRepository.Where(x => x.IsDeleted == false).SumAsync(x => x.RechargeAmount); |
| | | LifePayRechargeReceiptsStatistics objectData = new LifePayRechargeReceiptsStatistics(); |
| | | objectData.TotalRechargeAmount = total; |
| | | list.ObjectData = objectData; |
| | | return list; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| | | /// <returns></returns> |
| | | public async Task<LifePayRechargeReceiptsPageOutput<LifePayRechargeReceiptsListOutput>> GetLifePayRechargeReceiptsPage(LifePayRechargeReceiptsPageInput input) |
| | | public async Task<PageOutput<LifePayRechargeReceiptsListOutput>> GetLifePayRechargeReceiptsPage(LifePayRechargeReceiptsPageInput input) |
| | | { |
| | | var list = await _lifePayRechargeReceiptsRepository.Where(x => x.IsDeleted == false) |
| | | .WhereIf(input.KeyWord.IsNotNullOrEmpty(), x => x.OrderNo.Contains(input.KeyWord)) |
| | |
| | | .GetPageResult(input.PageModel); |
| | | |
| | | var total = await _lifePayRechargeReceiptsRepository.Where(x => x.IsDeleted == false).SumAsync(x => x.RechargeAmount); |
| | | LifePayRechargeReceiptsPageOutput<LifePayRechargeReceiptsListOutput> result = new LifePayRechargeReceiptsPageOutput<LifePayRechargeReceiptsListOutput>(); |
| | | result.Data = list.Data; |
| | | result.TotalRechargeAmount = total; |
| | | LifePayRechargeReceiptsStatistics objectData = new LifePayRechargeReceiptsStatistics(); |
| | | objectData.TotalRechargeAmount = total; |
| | | list.ObjectData = objectData; |
| | | return list; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取收支流水 |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| | | /// <returns></returns> |
| | | public async Task<PageOutput<LifePayExpensesReceiptsListOutput>> GetLifePayExpensesReceiptsPage(LifePayExpensesReceiptsPageInput input) |
| | | { |
| | | var list = await _lifePayExpensesReceiptsRepository.Where(x => x.IsDeleted == false) |
| | | .WhereIf(input.KeyWord.IsNotNullOrEmpty(), x => x.OrderNo.Contains(input.KeyWord) || x.OutOrderNo.Contains(input.KeyWord)) |
| | | .WhereIf(input.LifePayType.HasValue, x => x.LifePayType == input.LifePayType) |
| | | .WhereIf(input.ExpensesReceiptsType.HasValue, x => x.ExpensesReceiptsType == input.ExpensesReceiptsType) |
| | | .WhereIf(input.TimeBegin.HasValue, x => x.FinishTime >= input.TimeBegin) |
| | | .WhereIf(input.TimeEnd.HasValue, x => x.FinishTime <= input.TimeEnd) |
| | | |
| | | .Select(x => new LifePayExpensesReceiptsListOutput() |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | OutOrderNo = x.OutOrderNo, |
| | | LifePayType = x.LifePayType, |
| | | ExpensesReceiptsType = x.ExpensesReceiptsType.Value, |
| | | Amount = x.Amount, |
| | | FinishTime = x.FinishTime |
| | | }) |
| | | .GetPageResult(input.PageModel); |
| | | |
| | | var totalIncome = await _lifePayExpensesReceiptsRepository.Where(x => x.IsDeleted == false && x.ExpensesReceiptsType == ExpensesReceiptsTypeEnum.Expenses).SumAsync(x => x.Amount); |
| | | var totalRefund = await _lifePayExpensesReceiptsRepository.Where(x => x.IsDeleted == false && x.ExpensesReceiptsType == ExpensesReceiptsTypeEnum.Receipts).SumAsync(x => x.Amount); |
| | | |
| | | LifePayExpensesReceiptsStatistics objectData = new LifePayExpensesReceiptsStatistics(); |
| | | objectData.TotalIncome = totalIncome; |
| | | objectData.TotalRefund = totalRefund; |
| | | objectData.RealIncome = totalIncome - totalRefund; |
| | | list.ObjectData = objectData; |
| | | return list; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 获取渠道分佣 |
| | | /// </summary> |
| | | /// <param name="input"></param> |
| | | /// <returns></returns> |
| | | public async Task<PageOutput<LifePayChannlesRakeListOutput>> GetLifePayChannlesRakePage(LifePayChannlesRakePageInput input) |
| | | { |
| | | var list = await _lifePayChannlesRakeRepository.Where(x => x.IsDeleted == false) |
| | | .WhereIf(input.ChannelId.IsNotNullOrEmpty(), x => x.ChannelId == input.ChannelId) |
| | | .WhereIf(input.CreationTimeBegin.HasValue, x => x.CreationTime >= input.CreationTimeBegin) |
| | | .WhereIf(input.CreationTimeEnd.HasValue, x => x.CreationTime <= input.CreationTimeEnd) |
| | | .WhereIf(input.FinishTimeBegin.HasValue, x => x.FinishTime >= input.FinishTimeBegin) |
| | | .WhereIf(input.FinishTimeEnd.HasValue, x => x.FinishTime <= input.FinishTimeEnd) |
| | | |
| | | .Select(x => new LifePayChannlesRakeListOutput() |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | PayAmount = x.PayAmount, |
| | | ChannlesRakeRate = x.ChannlesRakeRate, |
| | | ChannlesRakePrice = x.ChannlesRakePrice, |
| | | ChannelId = x.ChannelId, |
| | | FinishTime = x.FinishTime, |
| | | CreationTime = x.CreationTime, |
| | | }) |
| | | .GetPageResult(input.PageModel); |
| | | |
| | | var totalRakePrice = await _lifePayChannlesRakeRepository.Where(x => x.IsDeleted == false).SumAsync(x => x.ChannlesRakePrice); |
| | | |
| | | LifePayLifePayChannlesRakeStatistics objectData = new LifePayLifePayChannlesRakeStatistics(); |
| | | objectData.TotalRakePrice = totalRakePrice; |
| | | list.ObjectData = objectData; |
| | | return list; |
| | | } |
| | | |
| | | public async Task<List<LifePayChannlesRakeListTemplate>> GetLifePayChannlesRakePageExport(LifePayChannlesRakePageInput input) |
| | | { |
| | | var result = await (await GetLifePayChannlesRakeListFilter(input)).Select(x => new LifePayChannlesRakeListTemplate |
| | | { |
| | | CreationTime = x.CreationTime, |
| | | FinishTime = x.FinishTime, |
| | | OrderNo = x.OrderNo, |
| | | PayAmount = x.PayAmount, |
| | | ChannlesRakeRate = x.ChannlesRakeRate, |
| | | ChannlesRakePrice = x.ChannlesRakePrice |
| | | }).OrderByDescending(r => r.CreationTime).ToListAsync(); |
| | | var i = 0; |
| | | result.ForEach(s => |
| | | { |
| | | s.SerialNumber = ++i; |
| | | s.CreationTimeStr = s.CreationTime.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmmss); |
| | | s.PayAmountStr = s.PayAmount.ToString("F2"); |
| | | s.ChannlesRakeRateStr = s.ChannlesRakeRate.ToString("F0") + "%"; |
| | | s.ChannlesRakePriceStr = s.ChannlesRakePrice.ToString("F2"); |
| | | s.FinishTimeStr = s.FinishTime.ToString(LifePaymentConstant.DateTimeFormatStr.yyyyMMddHHmmss); |
| | | }); |
| | | return result; |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | #region 操作 |
| | | |
| | | /// <summary> |
| | | /// 编辑充值流水 |
| | |
| | | } |
| | | |
| | | |
| | | //public async Task<LifePayExpensesReceiptsPageOutput<LifePayExpensesReceiptsListOutput>> GetLifePayExpensesReceiptsPage(LifePayExpensesReceiptsPageInput input) |
| | | //{ |
| | | // var list = await _lifePayExpensesReceiptsRepository.Where(x => x.IsDeleted == false) |
| | | // .WhereIf(input.KeyWord.IsNotNullOrEmpty(), x => x.OrderNo.Contains(input.KeyWord)) |
| | | // .WhereIf(input.CreationTimeBegin.HasValue, x => x.CreationTime >= input.CreationTimeBegin) |
| | | // .WhereIf(input.CreationTimeEnd.HasValue, x => x.CreationTime <= input.CreationTimeEnd) |
| | | // .Select(x => new LifePayRechargeReceiptsListOutput() |
| | | // { |
| | | // Id = x.Id, |
| | | // OrderNo = x.OrderNo, |
| | | // RechargeAmount = x.RechargeAmount, |
| | | // Remark = x.Remark, |
| | | // Voucher = x.Voucher.GetOssPath(), |
| | | // CreationTime = x.CreationTime, |
| | | // }) |
| | | // .GetPageResult(input.PageModel); |
| | | |
| | | // var total = await _lifePayRechargeReceiptsRepository.Where(x => x.IsDeleted == false).SumAsync(x => x.RechargeAmount); |
| | | // LifePayRechargeReceiptsPageOutput<LifePayRechargeReceiptsListOutput> result = new LifePayRechargeReceiptsPageOutput<LifePayRechargeReceiptsListOutput>(); |
| | | // result.Data = list.Data; |
| | | // result.TotalRechargeAmount = total; |
| | | // return result; |
| | | //} |
| | | |
| | | /// <summary> |
| | | /// 插入收支流水 |
| | | /// </summary> |
| | |
| | | var data = new LifePayExpensesReceipts() |
| | | { |
| | | Id = Guid.NewGuid(), |
| | | OrderNo = input.OrderNo, |
| | | OutOrderNo = input.OutOrderNo, |
| | | LifePayType = input.LifePayType, |
| | | ExpensesReceiptsType = input.ExpensesReceiptsType, |
| | | Amount = input.Amount |
| | | }; |
| | | |
| | | switch (input.LifePayType) |
| | |
| | | if (input.ExpensesReceiptsType == ExpensesReceiptsTypeEnum.Expenses) |
| | | { |
| | | var query = await _aliPayApi.OrderInQuiry(new OrderInQuiryInput() { OutTradeNo = input.OrderNo }); |
| | | if (query.Code == AlipayResultCode.Success && query.TradeStatus == AlipayStatus.TRADESUCCESS) |
| | | if (query.Code == AlipayResultCode.Success && (query.TradeStatus == AlipayStatus.TRADESUCCESS |
| | | || query.TradeStatus == AlipayStatus.TRADECLOSED)) |
| | | { |
| | | data.OrderNo = input.OrderNo; |
| | | data.ExtraProperties = JsonConvert.SerializeObject(query); |
| | | data.FinishTime = Convert.ToDateTime(query.SendPayDate); |
| | | data.Amount = Convert.ToDecimal(query.TotalAmount); |
| | | await _lifePayExpensesReceiptsRepository.InsertAsync(data); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var query = await _aliPayApi.QueryAlipayTradeRefund(new OrderInQuiryInput() { OutTradeNo = input.OrderNo }); |
| | | var query = await _aliPayApi.QueryAlipayTradeRefund(new OrderInQuiryInput() { OutTradeNo = input.OrderNo, OutRefundNo = input.OutRefundNo }); |
| | | if (query.Code == AlipayResultCode.Success && query.RefundStatus == AlipayRefundStatus.Success) |
| | | { |
| | | data.OrderNo = input.OutRefundNo; |
| | | data.ExtraProperties = JsonConvert.SerializeObject(query); |
| | | data.FinishTime = Convert.ToDateTime(query.GmtRefundPay); |
| | | data.Amount = Convert.ToDecimal(query.RefundAmount); |
| | | await _lifePayExpensesReceiptsRepository.InsertAsync(data); |
| | | } |
| | | } |
| | |
| | | if (input.ExpensesReceiptsType == ExpensesReceiptsTypeEnum.Expenses) |
| | | { |
| | | var query = await _wxPayApi.WxPayTradeQuery(input.OrderNo); |
| | | if (query.Code == AlipayResultCode.Success && query.Status == WxPayStatus.支付成功) |
| | | if (query.TradeState == WxPayStatus.支付成功 || query.TradeState == WxPayStatus.转入退款) |
| | | { |
| | | data.OrderNo = input.OrderNo; |
| | | data.ExtraProperties = JsonConvert.SerializeObject(query); |
| | | data.FinishTime = Convert.ToDateTime(query.SuccessTime); |
| | | await _lifePayExpensesReceiptsRepository.InsertAsync(data); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | var query = await _wxPayApi.WxPayDomesticRefundsQuery(input.OrderNo); |
| | | if (query.Code == AlipayResultCode.Success && query.RefundStatus == WxPayRefundStatus.退款成功) |
| | | var query = await _wxPayApi.WxPayDomesticRefundsQuery(input.OutRefundNo); |
| | | if (query.Status == WxPayRefundStatus.退款成功) |
| | | { |
| | | data.OrderNo = input.OutRefundNo; |
| | | data.ExtraProperties = JsonConvert.SerializeObject(query); |
| | | data.FinishTime = Convert.ToDateTime(query.SuccessTime); |
| | | await _lifePayExpensesReceiptsRepository.InsertAsync(data); |
| | | } |
| | | } |
| | | break; |
| | | default: break; |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
| | | |
| | | public async Task GetAllLifePayExpensesReceipts() |
| | | { |
| | | var orderlist = await (from a in _lifePayOrderRepository.Where(x => x.PayStatus >= LifePayStatusEnum.已支付) |
| | | join b in _lifePayExpensesReceiptsRepository on a.OrderNo equals b.OrderNo into temp |
| | | from b in temp.DefaultIfEmpty() |
| | | select new LifePayExpensesReceiptsTemp() |
| | | { |
| | | OrderNo = a.OrderNo, |
| | | OutOrderNo = a.OutOrderNo, |
| | | RefundOrderNo = a.RefundOrderNo, |
| | | LifePayType = a.LifePayType.Value, |
| | | Amount = a.PayAmount.Value, |
| | | ExpensesReceiptsType = b.ExpensesReceiptsType |
| | | }).ToListAsync(); |
| | | foreach (var item in orderlist) |
| | | { |
| | | if (!item.ExpensesReceiptsType.HasValue) |
| | | { |
| | | /// 入账 |
| | | AddLifePayExpensesReceiptsInput input = new AddLifePayExpensesReceiptsInput() |
| | | { |
| | | OrderNo = item.OrderNo, |
| | | OutOrderNo = item.OutOrderNo, |
| | | LifePayType = item.LifePayType, |
| | | Amount = item.Amount, |
| | | ExpensesReceiptsType = ExpensesReceiptsTypeEnum.Expenses |
| | | }; |
| | | |
| | | await AddLifePayExpensesReceipts(input); |
| | | |
| | | /// 出账 |
| | | if (item.RefundOrderNo.IsNotNullOrEmpty()) |
| | | { |
| | | input.OutRefundNo = item.OrderNo; |
| | | input.ExpensesReceiptsType = ExpensesReceiptsTypeEnum.Receipts; |
| | | await AddLifePayExpensesReceipts(input); |
| | | |
| | | input.OutRefundNo = item.RefundOrderNo; |
| | | input.ExpensesReceiptsType = ExpensesReceiptsTypeEnum.Receipts; |
| | | await AddLifePayExpensesReceipts(input); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | public async Task GetAllChannlesRake() |
| | | { |
| | | var orderlist = await _lifePayOrderRepository.Where(x => x.IsDeleted == false && x.PayStatus == LifePayStatusEnum.已支付 && x.LifePayOrderStatus == LifePayOrderStatusEnum.已完成).ToListAsync(); |
| | | foreach (var item in orderlist) |
| | | { |
| | | /// 毛利 |
| | | var grossProfit = item.RechargeAmount * (item.ChannleRate - item.PlatformRate) / 100; |
| | | /// 渠道佣金 ((充值面额 * 渠道折扣比例)-(充值面额 * 平台折扣比例))* 佣金比例 |
| | | var channlesRakePrice = grossProfit * (item.ChannlesRakeRate) / 100; |
| | | if (channlesRakePrice.HasValue) |
| | | { |
| | | LifePayChannlesRake lifePayChannlesRake = new LifePayChannlesRake() |
| | | { |
| | | OrderNo = item.OrderNo, |
| | | PayAmount = item.PayAmount.Value, |
| | | ChannlesRakeRate = item.ChannlesRakeRate.Value, |
| | | ChannlesRakePrice = channlesRakePrice.Value, |
| | | FinishTime = item.FinishTime.Value, |
| | | ChannelId = item.ChannelId, |
| | | }; |
| | | var repeat = _lifePayChannlesRakeRepository.Where(x => x.OrderNo == item.OrderNo).FirstOrDefaultAsync(); |
| | | if (repeat != null) |
| | | { |
| | | await _lifePayChannlesRakeRepository.InsertAsync(lifePayChannlesRake); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | #endregion |
| | | |
| | | #region 私有 |
| | | private async Task<IQueryable<LifePayChannlesRakeListOutput>> GetLifePayChannlesRakeListFilter(LifePayChannlesRakePageInput input) |
| | | { |
| | | var list = _lifePayChannlesRakeRepository.Where(x => x.IsDeleted == false) |
| | | .WhereIf(input.ChannelId.IsNotNullOrEmpty(), x => x.ChannelId == input.ChannelId) |
| | | .WhereIf(input.CreationTimeBegin.HasValue, x => x.CreationTime >= input.CreationTimeBegin) |
| | | .WhereIf(input.CreationTimeEnd.HasValue, x => x.CreationTime <= input.CreationTimeEnd) |
| | | .WhereIf(input.FinishTimeBegin.HasValue, x => x.FinishTime >= input.FinishTimeBegin) |
| | | .WhereIf(input.FinishTimeEnd.HasValue, x => x.FinishTime <= input.FinishTimeEnd) |
| | | |
| | | .Select(x => new LifePayChannlesRakeListOutput() |
| | | { |
| | | Id = x.Id, |
| | | OrderNo = x.OrderNo, |
| | | PayAmount = x.PayAmount, |
| | | ChannlesRakeRate = x.ChannlesRakeRate, |
| | | ChannlesRakePrice = x.ChannlesRakePrice, |
| | | ChannelId = x.ChannelId, |
| | | FinishTime = x.FinishTime, |
| | | CreationTime = x.CreationTime, |
| | | }); |
| | | |
| | | |
| | | return list; |
| | | } |
| | | #endregion |
| | | |
| | | } |
| | | } |