715 lines
38 KiB
C#
715 lines
38 KiB
C#
using AutoMapper;
|
||
using IRaCIS.Application.Interfaces;
|
||
using IRaCIS.Application.Contracts;
|
||
using IRaCIS.Application.Contracts.Pay;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using IRaCIS.Core.Infrastructure.ExpressionExtend;
|
||
using System.Linq.Expressions;
|
||
using IRaCIS.Core.Infra.EFCore;
|
||
using IRaCIS.Core.Domain.Models;
|
||
using IRaCIS.Core.Infrastructure.Extention;
|
||
using Panda.DynamicWebApi.Attributes;
|
||
|
||
namespace IRaCIS.Application.Services
|
||
{
|
||
public class CalculateService : ICalculateService
|
||
{
|
||
private readonly IRepository<Payment> _paymentRepository;
|
||
private readonly IRepository<TrialPaymentPrice> _trialPaymentRepository;
|
||
private readonly IRepository<ReviewerPayInformation> _doctorPayInfoRepository;
|
||
private readonly IRepository<Trial> _trialRepository;
|
||
private readonly IRepository<Doctor> _doctorRepository;
|
||
private readonly IRepository<Workload> _doctorWorkloadRepository;
|
||
private readonly IRepository<RankPrice> _rankPriceRepository;
|
||
private readonly IRepository<PaymentDetail> _paymentDetailRepository;
|
||
private readonly IVolumeRewardService _volumeRewardPriceService;
|
||
private readonly IRepository<ExchangeRate> _exchangeRateRepository;
|
||
private readonly IRepository<PaymentAdjustment> _payAdjustmentRepository;
|
||
private readonly IRepository<Enroll> _enrollRepository;
|
||
private readonly IMapper _mapper;
|
||
|
||
public CalculateService(IRepository<Payment> paymentRepository, IRepository<TrialPaymentPrice> trialPaymentPriceRepository,
|
||
IRepository<ReviewerPayInformation> reviewerPayInfoRepository,
|
||
IRepository<Trial> trialRepository,
|
||
IRepository<Doctor> doctorRepository,
|
||
IRepository<Workload> workloadRepository,
|
||
IRepository<RankPrice> rankPriceRepository,
|
||
IRepository<PaymentDetail> paymentDetailRepository,
|
||
IVolumeRewardService volumeRewardService,
|
||
IRepository<ExchangeRate> exchangeRateRepository,
|
||
IRepository<Enroll> EnrollRepository,
|
||
IRepository<PaymentAdjustment> paymentAdjustmentRepository, IMapper mapper)
|
||
{
|
||
_paymentRepository = paymentRepository;
|
||
_trialPaymentRepository = trialPaymentPriceRepository;
|
||
_doctorPayInfoRepository = reviewerPayInfoRepository;
|
||
_trialRepository = trialRepository;
|
||
_doctorRepository = doctorRepository;
|
||
_doctorWorkloadRepository = workloadRepository;
|
||
_rankPriceRepository = rankPriceRepository;
|
||
_paymentDetailRepository = paymentDetailRepository;
|
||
_volumeRewardPriceService = volumeRewardService;
|
||
_exchangeRateRepository = exchangeRateRepository;
|
||
_payAdjustmentRepository = paymentAdjustmentRepository;
|
||
this._enrollRepository = EnrollRepository;
|
||
_mapper = mapper;
|
||
}
|
||
|
||
/// <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)
|
||
{
|
||
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<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.BatchUpdateAsync(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.BatchDeleteAsync(u => u.Id == paymentModel.Id);
|
||
//_paymentDetailRepository.Delete(u=>u.PaymentId==paymentModel.Id);
|
||
}
|
||
else
|
||
{
|
||
success = await _paymentRepository.BatchUpdateAsync(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.BatchDeleteAsync(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)
|
||
//}
|
||
}
|
||
}
|