using AutoMapper; using IRaCIS.Application.Interfaces; using IRaCIS.Application.Contracts; using IRaCIS.Application.Contracts.Pay; using IRaCIS.Core.Domain.Share; using System.Linq.Expressions; using IRaCIS.Core.Infra.EFCore; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Infrastructure.Extention; using Panda.DynamicWebApi.Attributes; namespace IRaCIS.Application.Services { public class CalculateService : ICalculateService { private readonly IRepository _paymentRepository; private readonly IRepository _trialPaymentRepository; private readonly IRepository _doctorPayInfoRepository; private readonly IRepository _trialRepository; private readonly IRepository _doctorRepository; private readonly IRepository _doctorWorkloadRepository; private readonly IRepository _rankPriceRepository; private readonly IRepository _paymentDetailRepository; private readonly IVolumeRewardService _volumeRewardPriceService; private readonly IRepository _exchangeRateRepository; private readonly IRepository _payAdjustmentRepository; private readonly IRepository _enrollRepository; private readonly IMapper _mapper; public CalculateService(IRepository paymentRepository, IRepository trialPaymentPriceRepository, IRepository reviewerPayInfoRepository, IRepository trialRepository, IRepository doctorRepository, IRepository workloadRepository, IRepository rankPriceRepository, IRepository paymentDetailRepository, IVolumeRewardService volumeRewardService, IRepository exchangeRateRepository, IRepository EnrollRepository, IRepository paymentAdjustmentRepository, IMapper mapper) { _paymentRepository = paymentRepository; _trialPaymentRepository = trialPaymentPriceRepository; _doctorPayInfoRepository = reviewerPayInfoRepository; _trialRepository = trialRepository; _doctorRepository = doctorRepository; _doctorWorkloadRepository = workloadRepository; _rankPriceRepository = rankPriceRepository; _paymentDetailRepository = paymentDetailRepository; _volumeRewardPriceService = volumeRewardService; _exchangeRateRepository = exchangeRateRepository; _payAdjustmentRepository = paymentAdjustmentRepository; this._enrollRepository = EnrollRepository; _mapper = mapper; } /// /// 获取某个月下的某些医生最终确认的工作量,用于计算月度费用 /// private async Task< List> GetFinalConfirmedWorkloadAndPayPriceList(CalculateDoctorAndMonthDTO calculateFeeParam) { Expression> workloadLambda = x => true; DateTime bTime = new DateTime(calculateFeeParam.CalculateMonth.Year, calculateFeeParam.CalculateMonth.Month, 1); var eTime = bTime.AddMonths(1); workloadLambda = workloadLambda.And(t => t.WorkTime >= bTime && t.WorkTime < eTime); workloadLambda = workloadLambda.And(t => calculateFeeParam.NeedCalculateReviewers.Contains(t.DoctorId) && t.DataFrom == (int)WorkLoadFromStatus.FinalConfirm); var workLoadQueryable = from doctor in _doctorRepository.AsQueryable() join workLoad in _doctorWorkloadRepository.Where(workloadLambda) on doctor.Id equals workLoad.DoctorId join trial in _trialRepository.AsQueryable() on workLoad.TrialId equals trial.Id join trialPay in _trialPaymentRepository.AsQueryable() on trial.Id equals trialPay.TrialId into temp from trialPay in temp.DefaultIfEmpty() join doctorPayInfo in _doctorPayInfoRepository.AsQueryable() on doctor.Id equals doctorPayInfo.DoctorId join rankPrice in _rankPriceRepository.AsQueryable() on doctorPayInfo.RankId equals rankPrice.Id select new CalculatePaymentDTO() { Id = workLoad.Id, DoctorId = workLoad.DoctorId, WorkTime = workLoad.WorkTime, DataFrom = workLoad.DataFrom, TrialId = workLoad.TrialId, TrialCode = trial.TrialCode, Timepoint = workLoad.Timepoint, TimepointIn24H = workLoad.TimepointIn24H, TimepointIn48H = workLoad.TimepointIn48H, Global = workLoad.Global, Adjudication = workLoad.Adjudication, AdjudicationIn24H = workLoad.AdjudicationIn24H, AdjudicationIn48H = workLoad.AdjudicationIn48H, Training = workLoad.Training, RefresherTraining = workLoad.RefresherTraining, Downtime = workLoad.Downtime, TrialAdditional = trialPay.TrialAdditional, PersonalAdditional = doctorPayInfo.Additional, AdjustmentMultiple = trialPay.AdjustmentMultiple, TimepointPrice = rankPrice.Timepoint, TimepointIn24HPrice = rankPrice.TimepointIn24H, TimepointIn48HPrice = rankPrice.TimepointIn48H, AdjudicationPrice = rankPrice.Adjudication, AdjudicationIn24HPrice = rankPrice.AdjudicationIn24H, AdjudicationIn48HPrice = rankPrice.AdjudicationIn48H, DowntimePrice = rankPrice.Downtime, GlobalPrice = rankPrice.Global, TrainingPrice = rankPrice.Training, RefresherTrainingPrice = rankPrice.RefresherTraining }; return await workLoadQueryable.ToListAsync(); } /// /// 计算月度费用,并调用AddOrUpdateMonthlyPayment和AddOrUpdateMonthlyPaymentDetail方法, /// 将费用计算的月度数据及详情保存 /// [NonDynamicMethod] public async Task CalculateMonthlyPayment(CalculateDoctorAndMonthDTO param, string token) { var yearMonth = param.CalculateMonth.ToString("yyyy-MM"); var rate = await _exchangeRateRepository.FirstOrDefaultAsync(u => u.YearMonth == yearMonth); decimal exchangeRate = rate?.Rate ?? 0; var workLoadAndPayPriceList = await GetFinalConfirmedWorkloadAndPayPriceList(param); var volumeRewardPriceList = await _volumeRewardPriceService.GetVolumeRewardPriceList(); #region 奖励数据校验 for (int i = 0; i < volumeRewardPriceList.Count; i++) { if (i == 0 && volumeRewardPriceList[i].Min != 0) { return ResponseOutput.NotOk("Volume reward data error."); } if (i > 0) { if (volumeRewardPriceList[i - 1].Max + 1 != volumeRewardPriceList[i].Min) return ResponseOutput.NotOk("Volume reward data error."); } } #endregion List paymentList = new List(); List reviewerPaymentUSDList = new List(); // 获取所有医生费用 一次从数据库里面全部取出来 var allDoctorList = workLoadAndPayPriceList.Where(x => param.NeedCalculateReviewers.Contains(x.DoctorId)).ToList(); var allDoctorIds = allDoctorList.Select(x => x.DoctorId).Distinct().ToList(); var listTrialId = allDoctorList.Select(x => x.TrialId).Distinct().ToList(); var trialDoctorlist= await (from enroll in _enrollRepository.Where(x=> listTrialId.Contains(x.TrialId)|| allDoctorIds.Contains(x.DoctorId)) join price in _trialPaymentRepository.Where() on enroll.TrialId equals price.TrialId select new DoctorPrice() { IsNewTrial = price.IsNewTrial, AdjustmentMultiple = enroll.AdjustmentMultiple, TrialId=enroll.TrialId, DoctorId = enroll.DoctorId, Training=enroll.Training, Adjudication=enroll.Adjudication, Adjudication24H=enroll.Adjudication24H, Adjudication48H= enroll.Adjudication48H, Downtime=enroll.Downtime, Global=enroll.Global, RefresherTraining=enroll.RefresherTraining, Timepoint= enroll.Timepoint, Timepoint24H=enroll.Timepoint24H, Timepoint48H=enroll.Timepoint48H, }).ToListAsync(); foreach (var doctor in param.NeedCalculateReviewers) { if (await _paymentRepository.AnyAsync(u => u.DoctorId == doctor && u.YearMonth == yearMonth && u.IsLock)) { break; } List paymentDetailList = new List(); decimal totalNormal = 0; //计算单个医生费用统,并且插入到统计表 var doctorWorkloadAndPayPriceList = workLoadAndPayPriceList.Where(u => u.DoctorId == doctor).ToList(); //阅片数量 计算奖励费用 int readCount = 0; int codeOrder = 0; //这里需要改 foreach (var item in doctorWorkloadAndPayPriceList) { var doctordata = trialDoctorlist.Where(x => x.IsNewTrial ?? false && x.Training == item.Training && x.DoctorId == item.DoctorId).FirstOrDefault(); if (doctordata != null) { item.Training = doctordata.Training??0; item.Adjudication = doctordata.Adjudication??0; item.AdjudicationIn24H = doctordata.Adjudication24H??0; item.AdjudicationIn48H = doctordata.Adjudication48H??0; item.Downtime = doctordata.Downtime??0; item.Global = doctordata.Global??0; item.RefresherTraining = doctordata.RefresherTraining??0; item.Timepoint = doctordata.Timepoint??0; item.TimepointIn24H = doctordata.Timepoint24H??0; item.TimepointIn48H = doctordata.Timepoint48H??0; item.PersonalAdditional = 0; } ++codeOrder; readCount += (item.Timepoint + item.TimepointIn24H + item.TimepointIn48H + item.Adjudication + item.AdjudicationIn24H + item.AdjudicationIn48H); decimal trainingTotal = item.Training * item.TrainingPrice; decimal refresherTrainingTotal = item.RefresherTraining * item.RefresherTrainingPrice; decimal downtimeTotal = item.Downtime * item.DowntimePrice; //规则定义 global 的价格是Tp和个人附加的一半 decimal globalTotal = item.Global * (item.TimepointPrice / 2 + item.PersonalAdditional / 2); //项目如果没有添加附加数据 默认为0 decimal timePointTotal = item.Timepoint * (item.TimepointPrice * item.AdjustmentMultiple + item.PersonalAdditional + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional)); decimal timePointIn24HTotal = item.TimepointIn24H * (item.TimepointIn24HPrice * item.AdjustmentMultiple + item.PersonalAdditional); decimal timePointIn48HTotal = item.TimepointIn48H * (item.TimepointIn48HPrice * item.AdjustmentMultiple + item.PersonalAdditional); decimal adjudicationTotal = item.Adjudication * (item.AdjudicationPrice * item.AdjustmentMultiple + item.PersonalAdditional + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional)); decimal adjudicationIn24HTotal = item.AdjudicationIn24H * (item.AdjudicationIn24HPrice * item.AdjustmentMultiple + item.PersonalAdditional); decimal adjudicationIn48HTotal = item.AdjudicationIn48H * (item.AdjudicationIn48HPrice * item.AdjustmentMultiple + item.PersonalAdditional); totalNormal += (trainingTotal + refresherTrainingTotal + downtimeTotal + globalTotal + timePointTotal + timePointIn24HTotal + timePointIn48HTotal + adjudicationTotal + adjudicationIn24HTotal + adjudicationIn48HTotal); #region 统计明细信息 paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Training", Count = item.Training, BasePrice = item.TrainingPrice, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 1, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Training * item.TrainingPrice, PaymentCNY = item.Training * item.TrainingPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Refresher Training", Count = item.RefresherTraining, BasePrice = item.RefresherTrainingPrice, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 2, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.RefresherTraining * item.RefresherTrainingPrice, PaymentCNY = item.RefresherTraining * item.RefresherTrainingPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Downtime", Count = item.Downtime, BasePrice = item.DowntimePrice, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 3, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Downtime * item.DowntimePrice, PaymentCNY = item.Downtime * item.DowntimePrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Timepoint Regular", Count = item.Timepoint, BasePrice = item.TimepointPrice, PersonalAdditional = doctordata!=null?0: item.PersonalAdditional, TrialAdditional = doctordata != null ? 0 : item.TimepointPrice * (item.AdjustmentMultiple - 1) + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional), PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 4, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Timepoint * (item.TimepointPrice * item.AdjustmentMultiple + item.PersonalAdditional + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional)), PaymentCNY = item.Timepoint * (item.TimepointPrice * item.AdjustmentMultiple + item.PersonalAdditional + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional)) * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Timepoint 48-Hour", Count = item.TimepointIn48H, BasePrice = item.TimepointIn48HPrice, PersonalAdditional = doctordata != null ? 0 : item.PersonalAdditional, TrialAdditional = doctordata != null ? 0 : item.TimepointIn48HPrice * (item.AdjustmentMultiple - 1) + 0,//48小时不加项目附加 PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 5, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.TimepointIn48H * (item.TimepointIn48HPrice * item.AdjustmentMultiple + 0 + item.PersonalAdditional), PaymentCNY = item.TimepointIn48H * (item.TimepointIn48HPrice * item.AdjustmentMultiple + 0 + item.PersonalAdditional) * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Timepoint 24-Hour", Count = item.TimepointIn24H, BasePrice = item.TimepointIn24HPrice, PersonalAdditional = doctordata != null ? 0 : item.PersonalAdditional, TrialAdditional = doctordata != null ? 0 : item.TimepointIn24HPrice * (item.AdjustmentMultiple - 1) + 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 6, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.TimepointIn24H * (item.TimepointIn24HPrice * item.AdjustmentMultiple + 0 + item.PersonalAdditional), PaymentCNY = item.TimepointIn24H * (item.TimepointIn24HPrice * item.AdjustmentMultiple + 0 + item.PersonalAdditional) * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Adjudication Regular", Count = item.Adjudication, BasePrice = item.AdjudicationPrice, PersonalAdditional = doctordata != null ? 0 : item.PersonalAdditional, TrialAdditional = doctordata != null ? 0 : item.AdjudicationPrice * (item.AdjustmentMultiple - 1) + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional), PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 7, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Adjudication * (item.AdjudicationPrice * item.AdjustmentMultiple + item.PersonalAdditional + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional)), PaymentCNY = item.Adjudication * (item.AdjudicationPrice * item.AdjustmentMultiple + item.PersonalAdditional + (item.TrialAdditional == null ? 0 : (decimal)item.TrialAdditional)) * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Adjudication 48-Hour", Count = item.AdjudicationIn48H, BasePrice = item.AdjudicationIn48HPrice, PersonalAdditional = doctordata != null ? 0 : item.PersonalAdditional, TrialAdditional = doctordata != null ? 0 : item.AdjudicationIn48HPrice * (item.AdjustmentMultiple - 1) + 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 8, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.AdjudicationIn48H * (item.AdjudicationIn48HPrice * item.AdjustmentMultiple + item.PersonalAdditional + 0), PaymentCNY = item.AdjudicationIn48H * (item.AdjudicationIn48HPrice * item.AdjustmentMultiple + item.PersonalAdditional + 0) * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Adjudication 24-Hour", Count = item.AdjudicationIn24H, BasePrice = item.AdjudicationIn24HPrice, PersonalAdditional = doctordata != null ? 0 : item.PersonalAdditional, TrialAdditional = doctordata != null ? 0 : item.AdjudicationIn24HPrice * (item.AdjustmentMultiple - 1) + 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 9, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.AdjudicationIn24H * (item.AdjudicationIn24HPrice * item.AdjustmentMultiple + 0 + item.PersonalAdditional), PaymentCNY = item.AdjudicationIn24H * (item.AdjudicationIn24HPrice * item.AdjustmentMultiple + 0 + item.PersonalAdditional) * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Global", Count = item.Global, BasePrice = item.TimepointPrice / 2,//item.GlobalPrice, PersonalAdditional = doctordata != null ? 0 : item.PersonalAdditional / 2, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 10, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Global * (item.TimepointPrice / 2 + item.PersonalAdditional / 2), PaymentCNY = item.Global * (item.TimepointPrice / 2 + item.PersonalAdditional / 2) * exchangeRate }); #endregion } int typeOrder = 0; if (readCount > 0) { paymentDetailList.Add(new PaymentDetailCommand { TrialCode = "Volume Reward", PaymentType = "Total TP & AD", Count = readCount, BasePrice = 0, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = doctor, TrialId = Guid.Empty, ShowTypeOrder = typeOrder, ShowCodeOrder = (++codeOrder), ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = 0, PaymentCNY = 0 }); foreach (var awardItem in volumeRewardPriceList) { ++typeOrder; if ((readCount - awardItem.Min + 1) < 0) { break; } if (awardItem.Min == 0) { paymentDetailList.Add(new PaymentDetailCommand { TrialCode = "Volume Reward", PaymentType = awardItem.Min + "-" + awardItem.Max, Count = readCount >= awardItem.Max ? (awardItem.Max - awardItem.Min) : (readCount - awardItem.Min), BasePrice = awardItem.Price, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty,//result.Data, DoctorId = doctor, TrialId = Guid.Empty, ShowTypeOrder = typeOrder, ShowCodeOrder = (++codeOrder), ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = (readCount >= awardItem.Max ? (awardItem.Max - awardItem.Min) : (readCount - awardItem.Min)) * awardItem.Price, PaymentCNY = (readCount >= awardItem.Max ? (awardItem.Max - awardItem.Min) : (readCount - awardItem.Min)) * awardItem.Price * exchangeRate }); } else { paymentDetailList.Add(new PaymentDetailCommand { TrialCode = "Volume Reward", PaymentType = awardItem.Min + "-" + awardItem.Max, Count = readCount >= awardItem.Max ? (awardItem.Max - awardItem.Min + 1) : (readCount - awardItem.Min + 1), BasePrice = awardItem.Price, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = doctor, TrialId = Guid.Empty, ShowTypeOrder = typeOrder, ShowCodeOrder = (++codeOrder), ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = (readCount >= awardItem.Max ? (awardItem.Max - awardItem.Min + 1) : (readCount - awardItem.Min + 1)) * awardItem.Price, PaymentCNY = (readCount >= awardItem.Max ? (awardItem.Max - awardItem.Min + 1) : (readCount - awardItem.Min + 1)) * awardItem.Price * exchangeRate }); } } } decimal award = 0; volumeRewardPriceList = volumeRewardPriceList.OrderBy(u => u.Min).ToList(); var levelTemp = -1; //用来计算属于哪一个挡位 foreach (var awarPriceitem in volumeRewardPriceList) { if (awarPriceitem.Min == 0) { if (readCount > awarPriceitem.Max) { ++levelTemp; award += (awarPriceitem.Max - awarPriceitem.Min) * awarPriceitem.Price; } if (awarPriceitem.Min < readCount && readCount < awarPriceitem.Max) { ++levelTemp; award += (readCount - awarPriceitem.Min) * awarPriceitem.Price; break; ; } } else { if (readCount > awarPriceitem.Max) { ++levelTemp; award += (awarPriceitem.Max - awarPriceitem.Min + 1) * awarPriceitem.Price; } if (awarPriceitem.Min < readCount && readCount < awarPriceitem.Max) { ++levelTemp; award += (readCount - awarPriceitem.Min + 1) * awarPriceitem.Price; break; ; } } } decimal totalUSD = award + totalNormal;//总费用 var result = await AddOrUpdateMonthlyPayment(new PaymentCommand { DoctorId = doctor, Year = param.CalculateMonth.Year, Month = param.CalculateMonth.Month, PaymentUSD = totalUSD, CalculateUser = token, CalculateTime = DateTime.Now, ExchangeRate = exchangeRate, PaymentCNY = exchangeRate * totalUSD, }); reviewerPaymentUSDList.Add(new ReviewerPaymentUSD { DoctorId = doctor, PaymentUSD = totalUSD, RecordId = result.Data }); foreach (var detail in paymentDetailList) { //var data = trialDoctorlist.FirstOrDefault(x => x.DoctorId == detail.DoctorId && x.TrialId == detail.TrialId && x.IsNewTrial == true && (x.AdjustmentMultiple??0) != 0); //if (data != null) //{ // detail.BasePrice = data.AdjustmentMultiple??0; // detail.PersonalAdditional = 0; // detail.TrialAdditional = 0; //} detail.PaymentId = result.Data; } await AddOrUpdateMonthlyPaymentDetail(paymentDetailList, result.Data); await UpdatePaymentAdjustment(doctor, yearMonth); } return ResponseOutput.Ok(reviewerPaymentUSDList); } // 重新计算调整费用 private async Task UpdatePaymentAdjustment(Guid reviewerId, string yearMonth) { var adjustList = await _payAdjustmentRepository.Where(u => u.YearMonth == yearMonth && !u.IsLock && u.ReviewerId == reviewerId).ToListAsync(); var needUpdatePayment = adjustList.GroupBy(t => t.ReviewerId).Select(g => new { ReviewerId = g.Key, AdjustCNY = g.Sum(t => t.AdjustmentCNY), AdjustUSD = g.Sum(t => t.AdjustmentUSD) }); foreach (var reviewer in needUpdatePayment) { await _paymentRepository.BatchUpdateNoTrackingAsync(u => u.YearMonth == yearMonth && !u.IsLock && u.DoctorId == reviewer.ReviewerId, t => new Payment() { AdjustmentUSD = reviewer.AdjustUSD, AdjustmentCNY = reviewer.AdjustCNY }); } } /// /// 保存费用计算的月度数据 /// private async Task> AddOrUpdateMonthlyPayment(PaymentCommand addOrUpdateModel) { var success = false; var paymentModel = await _paymentRepository.FirstOrDefaultAsync(t => t.DoctorId == addOrUpdateModel.DoctorId && t.YearMonth == addOrUpdateModel.YearMonth); //var taxCNY = GetTax(addOrUpdateModel.PaymentCNY); //var actuallyPaidCNY = addOrUpdateModel.PaymentCNY - taxCNY; //var bankTransferCNY = addOrUpdateModel.PaymentCNY - taxCNY; if (paymentModel == null) { var payment = _mapper.Map(addOrUpdateModel); //payment.BankTransferCNY = bankTransferCNY; //payment.TaxCNY= taxCNY; //payment.BankTransferCNY = bankTransferCNY; payment.YearMonthDate = DateTime.Parse(payment.YearMonth); payment =await _paymentRepository.AddAsync(payment); success =await _paymentRepository.SaveChangesAsync(); return ResponseOutput.Result(success, payment.Id); } else { // 如果是 当月计算的工作量费用 和 调整费用都为0,则删除该行记录 if (addOrUpdateModel.PaymentUSD == 0 && paymentModel.AdjustmentUSD == 0) { success =await _paymentRepository.BatchDeleteNoTrackingAsync(u => u.Id == paymentModel.Id); //_paymentDetailRepository.Delete(u=>u.PaymentId==paymentModel.Id); } else { success = await _paymentRepository.BatchUpdateNoTrackingAsync(t => t.Id == paymentModel.Id, u => new Payment() { PaymentUSD = addOrUpdateModel.PaymentUSD, CalculateTime = addOrUpdateModel.CalculateTime, CalculateUser = addOrUpdateModel.CalculateUser, //TaxCNY = taxCNY, //ActuallyPaidCNY = actuallyPaidCNY, //BankTransferCNY = bankTransferCNY, PaymentCNY = addOrUpdateModel.PaymentCNY, ExchangeRate = addOrUpdateModel.ExchangeRate }); } return ResponseOutput.Result(success, paymentModel.Id); } } /// /// 保存费用计算的月度详情 /// private async Task AddOrUpdateMonthlyPaymentDetail(List addOrUpdateList, Guid paymentId) { //var paymentDetailIds = addOrUpdateList.Select(t => t.PaymentId).ToList(); await _paymentDetailRepository.BatchDeleteNoTrackingAsync(t => t.PaymentId == paymentId); await _paymentDetailRepository.AddRangeAsync(_mapper.Map>(addOrUpdateList)); return await _paymentDetailRepository.SaveChangesAsync(); } /// /// 获取待计算费用的Reviewer对应的月份列表 /// public async Task> GetNeedCalculateReviewerList(Guid reviewerId, string yearMonth) { Expression> calculateLambda = u => !u.IsLock; if (reviewerId != Guid.Empty) { calculateLambda = calculateLambda.And(u => u.DoctorId == reviewerId); } if (!string.IsNullOrWhiteSpace(yearMonth)) { calculateLambda = calculateLambda.And(u => u.YearMonth == yearMonth); } return await _paymentRepository.Where(calculateLambda).ProjectTo(_mapper.ConfigurationProvider).ToListAsync(); } /// /// 查询Reviewer某个月的费用是否被锁定 /// public async Task IsLock(Guid reviewerId, string yearMonth) { return await _paymentRepository.AnyAsync(u => u.DoctorId == reviewerId && u.YearMonth == yearMonth && u.IsLock); } //public bool ResetMonthlyPayment(Guid reviewerId, Guid trialId, string yearMonth) //{ // var payment = _paymentRepository.FindSingleOrDefault(u => u.DoctorId == reviewerId && u.YearMonth == yearMonth); // payment.PaymentCNY = 0; // payment.PaymentUSD = 0; // _paymentRepository.Update(payment); // _paymentDetailRepository.Delete(u=>u.DoctorId==reviewerId && u.TrialId==trial) //} } }