Files
irc-netcore-api/IRaCIS.Core.Application/Service/Financial/CalculateService.cs
T
hang 0206947202
continuous-integration/drone/push Build is passing
移除属性注入改为构造函数注入
2024-10-13 13:31:25 +08:00

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)
//}
}
}