683 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C#
		
	
	
			
		
		
	
	
			683 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C#
		
	
	
using IRaCIS.Application.Contracts;
 | 
						||
using IRaCIS.Application.Contracts.Pay;
 | 
						||
using IRaCIS.Application.Interfaces;
 | 
						||
using IRaCIS.Core.Domain.Share;
 | 
						||
using Panda.DynamicWebApi.Attributes;
 | 
						||
 | 
						||
namespace IRaCIS.Core.Application.Service
 | 
						||
{
 | 
						||
    public class CalculateService(IRepository<Payment> _paymentRepository,
 | 
						||
     IRepository<TrialPaymentPrice> _trialPaymentRepository,
 | 
						||
     IRepository<ReviewerPayInformation> _doctorPayInfoRepository,
 | 
						||
     IRepository<Trial> _trialRepository,
 | 
						||
     IRepository<Doctor> _doctorRepository,
 | 
						||
     IRepository<Workload> _doctorWorkloadRepository,
 | 
						||
     IRepository<RankPrice> _rankPriceRepository,
 | 
						||
     IRepository<PaymentDetail> _paymentDetailRepository,
 | 
						||
     IVolumeRewardService _volumeRewardPriceService,
 | 
						||
     IRepository<ExchangeRate> _exchangeRateRepository,
 | 
						||
     IRepository<PaymentAdjustment> _payAdjustmentRepository,
 | 
						||
     IRepository<Enroll> _enrollRepository, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, ICalculateService
 | 
						||
    {
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 获取某个月下的某些医生最终确认的工作量,用于计算月度费用
 | 
						||
        /// </summary>
 | 
						||
        private async Task<List<CalculatePaymentDTO>> GetFinalConfirmedWorkloadAndPayPriceList(CalculateDoctorAndMonthDTO calculateFeeParam)
 | 
						||
        {
 | 
						||
            Expression<Func<Workload, bool>> 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();
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 计算月度费用,并调用AddOrUpdateMonthlyPayment和AddOrUpdateMonthlyPaymentDetail方法,
 | 
						||
        /// 将费用计算的月度数据及详情保存
 | 
						||
        /// </summary>
 | 
						||
        [NonDynamicMethod]
 | 
						||
        public async Task<IResponseOutput> 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)
 | 
						||
                {
 | 
						||
                    //---Volume reward data error.
 | 
						||
                    return ResponseOutput.NotOk(_localizer["Cal_VolDataErr"]);
 | 
						||
                }
 | 
						||
                if (i > 0)
 | 
						||
                {
 | 
						||
                    if (volumeRewardPriceList[i - 1].Max + 1 != volumeRewardPriceList[i].Min)
 | 
						||
                        //---Volume reward data error.
 | 
						||
                        return ResponseOutput.NotOk(_localizer["Cal_VolDataErr"]);
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
 | 
						||
            #endregion
 | 
						||
 | 
						||
 | 
						||
            List<PaymentModel> paymentList = new List<PaymentModel>();
 | 
						||
            List<ReviewerPaymentUSD> reviewerPaymentUSDList = new List<ReviewerPaymentUSD>();
 | 
						||
 | 
						||
            // 获取所有医生费用   一次从数据库里面全部取出来
 | 
						||
 | 
						||
            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<PaymentDetailCommand> paymentDetailList = new List<PaymentDetailCommand>();
 | 
						||
                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
 | 
						||
 | 
						||
                                                });
 | 
						||
            }
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 保存费用计算的月度数据
 | 
						||
        /// </summary>
 | 
						||
        private async Task<IResponseOutput<Guid>> 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<Payment>(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);
 | 
						||
            }
 | 
						||
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 保存费用计算的月度详情
 | 
						||
        /// </summary>
 | 
						||
        private async Task<bool> AddOrUpdateMonthlyPaymentDetail(List<PaymentDetailCommand> addOrUpdateList, Guid paymentId)
 | 
						||
        {
 | 
						||
            //var paymentDetailIds = addOrUpdateList.Select(t => t.PaymentId).ToList();
 | 
						||
            await _paymentDetailRepository.BatchDeleteNoTrackingAsync(t => t.PaymentId == paymentId);
 | 
						||
            await _paymentDetailRepository.AddRangeAsync(_mapper.Map<List<PaymentDetail>>(addOrUpdateList));
 | 
						||
            return await _paymentDetailRepository.SaveChangesAsync();
 | 
						||
        }
 | 
						||
 | 
						||
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 获取待计算费用的Reviewer对应的月份列表
 | 
						||
        /// </summary>
 | 
						||
        public async Task<List<CalculateNeededDTO>> GetNeedCalculateReviewerList(Guid reviewerId, string yearMonth)
 | 
						||
        {
 | 
						||
            Expression<Func<Payment, bool>> 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<CalculateNeededDTO>(_mapper.ConfigurationProvider).ToListAsync();
 | 
						||
        }
 | 
						||
 | 
						||
        /// <summary>
 | 
						||
        /// 查询Reviewer某个月的费用是否被锁定
 | 
						||
        /// </summary>
 | 
						||
        public async Task<bool> 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)
 | 
						||
        //}
 | 
						||
    }
 | 
						||
}
 |