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;
using System.Data;
using System.Linq.Dynamic.Core;
using System.Drawing;
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 IUserTrialRepository _userTrialRepository;
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,
IUserTrialRepository userTrialRepository,
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;
this._userTrialRepository = userTrialRepository;
_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;//总费用
var paymentyearMonth = new DateTime(param.CalculateMonth.Year, param.CalculateMonth.Month, 1).ToString("yyyy-MM");
var paymentModel = _paymentRepository.GetAll().FirstOrDefault(t =>
t.DoctorId == doctor && t.YearMonth == paymentyearMonth);
// 计算金额为0 就不插入
if (totalUSD != 0 || paymentModel != null)
{
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;
// u => u.IsLock==false && u.DataFrom==(int)WorkLoadFromStatus.FinalConfirm;
Expression> workloadLambda = x=>true;
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,
DataFrom=x.DataFrom,
}).Distinct().ToList();
var doctorIds = _enrollRepository.GetAll().Select(x => x.DoctorId).Distinct().ToList();
var doctorList = _doctorRepository.GetAll().Where(x=> doctorIds.Contains(x.Id)).Select(x => x.Id).ToList();
doctorList.ForEach(x =>
{
if (!workloadlist.Any(y => y.DoctorId == x)&& yearMonth!=string.Empty)
{
workloadlist.Add(new CalculateNeededDTO()
{
DoctorId = x,
IsLock = false,
YearMonth = yearMonth,
DataFrom= (int)WorkLoadFromStatus.FinalConfirm
});
}
});
workloadlist= workloadlist.Where(u=>u.IsLock == false && u.DataFrom == (int)WorkLoadFromStatus.FinalConfirm).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)
//}
}
}