using AutoMapper; using AutoMapper.QueryableExtensions; using IRaCIS.Application.Interfaces; using IRaCIS.Application.ViewModels; using IRaCIS.Application.ViewModels.Pay; using IRaCIS.Core.Application.Contracts.RequestAndResponse; using IRaCIS.Core.Domain.Share; using IRaCIS.Infra.Data.ExpressionExtend; using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using IRaCIS.Core.Domain.Interfaces; using IRaCIS.Core.Domain.Models; namespace IRaCIS.Application.Services { public class CalculateService : ICalculateService { private readonly IPaymentRepository _paymentRepository; private readonly ITrialPaymentPriceRepository _trialPaymentRepository; private readonly IReviewerPayInfoRepository _doctorPayInfoRepository; private readonly ITrialRepository _trialRepository; private readonly IDoctorRepository _doctorRepository; private readonly IWorkloadRepository _doctorWorkloadRepository; private readonly IRankPriceRepository _rankPriceRepository; private readonly IPaymentDetailRepository _paymentDetailRepository; private readonly IVolumeRewardService _volumeRewardPriceService; private readonly IExchangeRateRepository _exchangeRateRepository; private readonly IPaymentAdjustmentRepository _payAdjustmentRepository; private readonly IEnrollRepository _enrollRepository; private readonly IMapper _mapper; public CalculateService(IPaymentRepository paymentRepository, ITrialPaymentPriceRepository trialPaymentPriceRepository, IReviewerPayInfoRepository reviewerPayInfoRepository, ITrialRepository trialRepository, IDoctorRepository doctorRepository, IWorkloadRepository workloadRepository, IRankPriceRepository rankPriceRepository, IPaymentDetailRepository paymentDetailRepository, IVolumeRewardService volumeRewardService, IExchangeRateRepository exchangeRateRepository, IEnrollRepository enrollRepository, IPaymentAdjustmentRepository paymentAdjustmentRepository, IMapper mapper) { _paymentRepository = paymentRepository; _trialPaymentRepository = trialPaymentPriceRepository; _doctorPayInfoRepository = reviewerPayInfoRepository; _trialRepository = trialRepository; _enrollRepository= enrollRepository; _doctorRepository = doctorRepository; _doctorWorkloadRepository = workloadRepository; _rankPriceRepository = rankPriceRepository; _paymentDetailRepository = paymentDetailRepository; _volumeRewardPriceService = volumeRewardService; _exchangeRateRepository = exchangeRateRepository; _payAdjustmentRepository = paymentAdjustmentRepository; _mapper = mapper; } /// /// 获取某个月下的某些医生最终确认的工作量,用于计算月度费用 /// private 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.GetAll() join workLoad in _doctorWorkloadRepository.GetAll().Where(workloadLambda) on doctor.Id equals workLoad.DoctorId join trial in _trialRepository.GetAll() on workLoad.TrialId equals trial.Id join trialPay in _trialPaymentRepository.GetAll() on trial.Id equals trialPay.TrialId into temp from trialPay in temp.DefaultIfEmpty() join doctorPayInfo in _doctorPayInfoRepository.GetAll() on doctor.Id equals doctorPayInfo.DoctorId join rankPrice in _rankPriceRepository.GetAll() 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.Code, 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, IsNewTrial = trialPay.IsNewTrial ?? false, 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 workLoadQueryable.ToList(); } /// /// 计算月度费用,并调用AddOrUpdateMonthlyPayment和AddOrUpdateMonthlyPaymentDetail方法, /// 将费用计算的月度数据及详情保存 /// public IResponseOutput CalculateMonthlyPayment(CalculateDoctorAndMonthDTO param, string token) { var yearMonth = param.CalculateMonth.ToString("yyyy-MM"); var rate = _exchangeRateRepository.FindSingleOrDefault(u => u.YearMonth == yearMonth); decimal exchangeRate = rate?.Rate ?? 0; IResponseOutput result = null; var workLoadAndPayPriceList = GetFinalConfirmedWorkloadAndPayPriceList(param); var volumeRewardPriceList = _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(); foreach (var doctor in param.NeedCalculateReviewers) { if (_paymentRepository.GetAll().Any(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) { if (item.IsNewTrial) { var newPrice = _enrollRepository.GetAll().Where(x => x.TrialId == item.TrialId && x.DoctorId == item.DoctorId).FirstOrDefault(); if (newPrice != null) { item.TrainingPrice = newPrice.Training ?? 0; item.AdjudicationPrice = newPrice.Adjudication ?? 0; item.AdjudicationIn24HPrice = newPrice.Adjudication24H ?? 0; item.AdjudicationIn48HPrice = newPrice.Adjudication48H ?? 0; item.DowntimePrice = newPrice.Downtime ?? 0; item.GlobalPrice = newPrice.Global ?? 0; item.RefresherTrainingPrice = newPrice.RefresherTraining ?? 0; item.TimepointPrice = newPrice.Timepoint ?? 0; item.TimepointIn24HPrice = newPrice.Timepoint24H ?? 0; item.TimepointIn48HPrice = newPrice.Timepoint48H ?? 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; decimal globalTotal = item.Global * (item.GlobalPrice); //项目如果没有添加附加数据 默认为0 decimal timePointTotal = item.Timepoint * item.TimepointPrice; decimal timePointIn24HTotal = item.TimepointIn24H * item.TimepointIn24HPrice; decimal timePointIn48HTotal = item.TimepointIn48H * item.TimepointIn48HPrice; decimal adjudicationTotal = item.Adjudication * item.AdjudicationPrice; decimal adjudicationIn24HTotal = item.AdjudicationIn24H * item.AdjudicationIn24HPrice; decimal adjudicationIn48HTotal = item.AdjudicationIn48H * item.AdjudicationIn48HPrice; 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 =0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 4, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Timepoint * item.TimepointPrice, PaymentCNY = item.Timepoint * item.TimepointPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Timepoint 48-Hour", Count = item.TimepointIn48H, BasePrice = item.TimepointIn48HPrice, PersonalAdditional = 0, TrialAdditional = 0,//48小时不加项目附加 PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 5, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.TimepointIn48H * item.TimepointIn48HPrice, PaymentCNY = item.TimepointIn48H * item.TimepointIn48HPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Timepoint 24-Hour", Count = item.TimepointIn24H, BasePrice = item.TimepointIn24HPrice, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 6, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.TimepointIn24H * item.TimepointIn24HPrice, PaymentCNY = item.TimepointIn24H * item.TimepointIn24HPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Adjudication Regular", Count = item.Adjudication, BasePrice = item.AdjudicationPrice, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 7, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Adjudication * item.AdjudicationPrice, PaymentCNY = item.Adjudication * item.AdjudicationPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Adjudication 48-Hour", Count = item.AdjudicationIn48H, BasePrice = item.AdjudicationIn48HPrice, PersonalAdditional =0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 8, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.AdjudicationIn48H * item.AdjudicationIn48HPrice, PaymentCNY = item.AdjudicationIn48H * item.AdjudicationIn48HPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Adjudication 24-Hour", Count = item.AdjudicationIn24H, BasePrice = item.AdjudicationIn24HPrice, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 9, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.AdjudicationIn24H * item.AdjudicationIn24HPrice, PaymentCNY = item.AdjudicationIn24H * item.AdjudicationIn24HPrice * exchangeRate }); paymentDetailList.Add(new PaymentDetailCommand { TrialCode = item.TrialCode, PaymentType = "Global", Count = item.Global, BasePrice = item.GlobalPrice, PersonalAdditional = 0, TrialAdditional = 0, PaymentId = Guid.Empty, DoctorId = item.DoctorId, TrialId = item.TrialId, ShowTypeOrder = 10, ShowCodeOrder = codeOrder, ExchangeRate = exchangeRate, YearMonth = yearMonth, PaymentUSD = item.Global * item.GlobalPrice, PaymentCNY = item.Global * item.GlobalPrice * exchangeRate }); #endregion } else { ++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 = item.PersonalAdditional, TrialAdditional = 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 = item.PersonalAdditional, TrialAdditional = 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 = item.PersonalAdditional, TrialAdditional = 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 = item.PersonalAdditional, TrialAdditional = 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 = item.PersonalAdditional, TrialAdditional = 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 = item.PersonalAdditional, TrialAdditional = 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 = 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,//result.Data, 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;//总费用 result = 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) { detail.PaymentId = result.Data; } AddOrUpdateMonthlyPaymentDetail(paymentDetailList, result.Data); UpdatePaymentAdjustment(doctor, yearMonth); } return ResponseOutput.Ok(reviewerPaymentUSDList); } // 重新计算调整费用 private void UpdatePaymentAdjustment(Guid reviewerId,string yearMonth) { var adjustList = _payAdjustmentRepository.GetAll().Where(u => u.YearMonth == yearMonth && !u.IsLock&&u.ReviewerId==reviewerId).ToList(); 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) { _paymentRepository.Update(u => u.YearMonth == yearMonth && !u.IsLock && u.DoctorId == reviewer.ReviewerId, t => new Payment() { AdjustmentUSD = reviewer.AdjustUSD, AdjustmentCNY = reviewer.AdjustCNY }); } } /// /// 保存费用计算的月度数据 /// private IResponseOutput AddOrUpdateMonthlyPayment(PaymentCommand addOrUpdateModel) { var success = false; var paymentModel = _paymentRepository.GetAll().FirstOrDefault(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); var lastpayment = _paymentRepository.GetAll().Where(x => x.DoctorId == addOrUpdateModel.DoctorId && x.YearMonthDate == payment.YearMonthDate.AddMonths(-1)).FirstOrDefault(); payment.PaymentMethod = lastpayment == null ? PaymentMethod.CloudPayment : lastpayment.PaymentMethod; payment = _paymentRepository.Add(payment); success = _paymentRepository.SaveChanges(); return ResponseOutput.Result(success, payment.Id); } else { // 如果是 当月计算的工作量费用 和 调整费用都为0,则删除该行记录 if (addOrUpdateModel.PaymentUSD == 0 && paymentModel.AdjustmentUSD == 0) { success = _paymentRepository.Delete(u => u.Id == paymentModel.Id); //_paymentDetailRepository.Delete(u=>u.PaymentId==paymentModel.Id); } else { success = _paymentRepository.Update(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 bool AddOrUpdateMonthlyPaymentDetail(List addOrUpdateList, Guid paymentId) { //var paymentDetailIds = addOrUpdateList.Select(t => t.PaymentId).ToList(); _paymentDetailRepository.Delete(t => t.PaymentId == paymentId); _paymentDetailRepository.AddRange(_mapper.Map>(addOrUpdateList)); return _paymentDetailRepository.SaveChanges(); } /// /// 锁定某个月下的某些医生,医生费用结算后调用锁定 /// public IResponseOutput UpdateLockStatus(List reviewerIds, string yearMonth, bool isLock) { var paymentLockSuccess = _paymentRepository.Update(u => reviewerIds.Contains(u.DoctorId) && u.YearMonth == yearMonth, t => new Payment { IsLock = isLock }); var adjustmentLockSuccess = _payAdjustmentRepository.Update( t => t.YearMonth == yearMonth && reviewerIds.Contains(t.ReviewerId), u => new PaymentAdjustment() { IsLock = true }); _doctorWorkloadRepository.Update(u => reviewerIds.Contains(u.DoctorId) && u.YearMonth == yearMonth, t => new Workload { IsLock = true }); return ResponseOutput.Result(paymentLockSuccess || adjustmentLockSuccess); } /// /// 获取待计算费用的Reviewer对应的月份列表 /// public List GetNeedCalculateReviewerList(Guid reviewerId, string yearMonth) { Expression> calculateLambda = u => !u.IsLock; Expression> workloadLambda = u => u.IsLock==false && u.DataFrom==(int)WorkLoadFromStatus.FinalConfirm; if (reviewerId != Guid.Empty) { calculateLambda = calculateLambda.And(u => u.DoctorId == reviewerId); workloadLambda = workloadLambda.And(u => u.DoctorId == reviewerId); } if (!string.IsNullOrWhiteSpace(yearMonth)) { calculateLambda = calculateLambda.And(u => u.YearMonth == yearMonth); workloadLambda = workloadLambda.And(u => u.YearMonth == yearMonth); } var workloadlist = _doctorWorkloadRepository.GetAll().Where(workloadLambda) .Select(x => new CalculateNeededDTO() { DoctorId = x.DoctorId, YearMonth = x.YearMonth, IsLock = x.IsLock }).Distinct().ToList(); return workloadlist; // return _paymentRepository.Find(calculateLambda).ProjectTo(_mapper.ConfigurationProvider).ToList(); } /// /// 查询Reviewer某个月的费用是否被锁定 /// public bool IsLock(Guid reviewerId, string yearMonth) { return _paymentRepository.GetAll().Any(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) //} } }