1305 lines
68 KiB
C#
1305 lines
68 KiB
C#
using IRaCIS.Core.Infrastructure.ExpressionExtend;
|
||
using IRaCIS.Application.Interfaces;
|
||
using IRaCIS.Application.Contracts;
|
||
using IRaCIS.Application.Contracts.Pay;
|
||
using IRaCIS.Core.Domain.Share;
|
||
using System.Linq.Expressions;
|
||
using IRaCIS.Core.Infra.EFCore;
|
||
using IRaCIS.Core.Domain.Models;
|
||
using IRaCIS.Core.Infrastructure.Extention;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using Panda.DynamicWebApi.Attributes;
|
||
|
||
namespace IRaCIS.Application.Services
|
||
{
|
||
[ ApiExplorerSettings(GroupName = "Financial")]
|
||
public class FinancialService : BaseService, IPaymentService
|
||
{
|
||
private readonly IRepository<Payment> _paymentRepository;
|
||
private readonly IRepository<ReviewerPayInformation> _doctorPayInfoRepository;
|
||
private readonly IRepository<TrialPaymentPrice> _TrialPaymentPriceRepository;
|
||
private readonly IRepository<Trial> _trialRepository;
|
||
private readonly IRepository<Doctor> _doctorRepository;
|
||
private readonly IRepository<RankPrice> _rankPriceRepository;
|
||
private readonly IRepository<PaymentDetail> _paymentDetailRepository;
|
||
private readonly IRepository<CRO> _croRepository;
|
||
private readonly IRepository<Workload> _workloadRepository;
|
||
private readonly IRepository<TrialRevenuesPrice> _trialRevenuePriceRepository;
|
||
private readonly IRepository<PaymentAdjustment> _payAdjustmentRepository;
|
||
|
||
private readonly IRepository<Enroll> _enrollRepository;
|
||
|
||
private readonly IRepository<Workload> _doctorWorkloadRepository;
|
||
|
||
public FinancialService(IRepository<Payment> costStatisticsRepository,
|
||
IRepository<ReviewerPayInformation> doctorPayInfoRepository,
|
||
IRepository<Trial> trialRepository,
|
||
IRepository<Doctor> doctorRepository,
|
||
IRepository<RankPrice> rankPriceRepository,
|
||
IRepository<PaymentDetail> costStatisticsDetailRepository,
|
||
IRepository<CRO> croCompanyRepository,
|
||
IRepository<Workload> workloadRepository,
|
||
IRepository<Enroll> intoGroupRepository,
|
||
IRepository<TrialPaymentPrice> trialPaymentPriceRepository,
|
||
IRepository<TrialRevenuesPrice> trialCostRepository,
|
||
IRepository<PaymentAdjustment> costAdjustmentRepository,
|
||
IRepository<Workload> doctoWorkloadRepository
|
||
)
|
||
{
|
||
_TrialPaymentPriceRepository = trialPaymentPriceRepository;
|
||
_paymentRepository = costStatisticsRepository;
|
||
_doctorPayInfoRepository = doctorPayInfoRepository;
|
||
_trialRepository = trialRepository;
|
||
_doctorRepository = doctorRepository;
|
||
_rankPriceRepository = rankPriceRepository;
|
||
_paymentDetailRepository = costStatisticsDetailRepository;
|
||
_croRepository = croCompanyRepository;
|
||
_enrollRepository = intoGroupRepository;
|
||
_workloadRepository = workloadRepository;
|
||
_trialRevenuePriceRepository = trialCostRepository;
|
||
_payAdjustmentRepository = costAdjustmentRepository;
|
||
|
||
_doctorWorkloadRepository = doctoWorkloadRepository;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Financials /MonthlyPayment 列表查询接口
|
||
/// </summary>
|
||
[NonDynamicMethod]
|
||
public async Task<PageOutput<PaymentModel>> GetMonthlyPaymentList(MonthlyPaymentQueryDTO queryParam)
|
||
{
|
||
//var year = queryParam.StatisticsDate.Year;
|
||
//var month = queryParam.StatisticsDate.Month;
|
||
//var searchBeginDateTime = queryParam.StatisticsDate;
|
||
//Expression<Func<Workload, bool>> workloadLambda = t => t.DataFrom == (int)WorkLoadFromStatus.FinalConfirm;
|
||
//workloadLambda = workloadLambda.And(t =>
|
||
// t.WorkTime >= queryParam.StatisticsDate && t.WorkTime <= queryParam.StatisticsDate);
|
||
//var rate = _exchangeRateRepository.FindSingleOrDefault(u => u.YearMonth == yearMonth);
|
||
//var exchangeRate = rate == null ? 0 : rate.Rate;
|
||
|
||
var yearMonth = queryParam.StatisticsDate.ToString("yyyy-MM");
|
||
|
||
Expression<Func<Doctor, bool>> doctorLambda = x => true;
|
||
if (!string.IsNullOrWhiteSpace(queryParam.KeyWord))
|
||
{
|
||
var reviewer = queryParam.KeyWord.Trim();
|
||
doctorLambda = doctorLambda.And(u => u.ChineseName.Contains(reviewer)
|
||
|| u.FirstName.Contains(reviewer)
|
||
|| u.LastName.Contains(reviewer)
|
||
|| u.ReviewerCode.Contains(reviewer));
|
||
}
|
||
|
||
if (queryParam.Nation != null)
|
||
{
|
||
doctorLambda = doctorLambda.And(u => u.Nation == queryParam.Nation);
|
||
}
|
||
|
||
var costStatisticsQueryable =
|
||
|
||
from monthlyPayment in _paymentRepository.Where(t => t.YearMonth == yearMonth)
|
||
join payInfo in _doctorPayInfoRepository.AsQueryable() on monthlyPayment.DoctorId equals payInfo.DoctorId
|
||
into cc
|
||
from payInfo in cc.DefaultIfEmpty()
|
||
join doctor in _doctorRepository.Where(doctorLambda) on monthlyPayment.DoctorId equals doctor.Id
|
||
join rankPrice in _rankPriceRepository.AsQueryable() on payInfo.RankId equals rankPrice.Id into dd
|
||
from rankPriceItem in dd.DefaultIfEmpty()
|
||
select new PaymentModel()
|
||
{
|
||
Id = monthlyPayment.Id,
|
||
DoctorId = monthlyPayment.DoctorId,
|
||
YearMonth = monthlyPayment.YearMonth,
|
||
PaymentUSD = monthlyPayment.PaymentUSD,
|
||
CalculateTime = monthlyPayment.CalculateTime,
|
||
CalculateUser = monthlyPayment.CalculateUser,
|
||
IsLock = monthlyPayment.IsLock,
|
||
ExchangeRate = monthlyPayment.ExchangeRate,
|
||
PaymentCNY = monthlyPayment.PaymentCNY,
|
||
AdjustPaymentCNY = monthlyPayment.AdjustmentCNY,
|
||
AdjustPaymentUSD = monthlyPayment.AdjustmentUSD,
|
||
|
||
TotalPaymentCNY = monthlyPayment.AdjustmentCNY + monthlyPayment.PaymentCNY,
|
||
TotalPaymentUSD = monthlyPayment.AdjustmentUSD + monthlyPayment.PaymentUSD,
|
||
|
||
|
||
Code = doctor.ReviewerCode,
|
||
FirstName = doctor.FirstName,
|
||
LastName = doctor.LastName,
|
||
ChineseName = doctor.ChineseName,
|
||
Phone = doctor.Phone,
|
||
DoctorNameInBank = payInfo.DoctorNameInBank,
|
||
RankName = rankPriceItem.RankName,
|
||
IDCard = payInfo.IDCard,
|
||
BankCardNumber = payInfo.BankCardNumber,
|
||
BankName = payInfo.BankName
|
||
};
|
||
|
||
var propName = string.IsNullOrWhiteSpace(queryParam.SortField) ? "Code" : queryParam.SortField;
|
||
costStatisticsQueryable = queryParam.Asc ? costStatisticsQueryable.OrderBy(propName).ThenBy(u => u.Code)
|
||
: costStatisticsQueryable.OrderByDescending(propName).ThenBy(u => u.Code);
|
||
var count = costStatisticsQueryable.Count();
|
||
costStatisticsQueryable = costStatisticsQueryable.Skip((queryParam.PageIndex - 1) * queryParam.PageSize).Take(queryParam.PageSize);
|
||
var costStatisticsList = await costStatisticsQueryable.ToListAsync();
|
||
|
||
|
||
#region 增加调整费用总计字段之前
|
||
//var doctorIds = costStatisticsList.Select(t => t.DoctorId).ToList();
|
||
|
||
//var adjList = _payAdjustmentRepository.GetAll()
|
||
// .Where(t => t.YearMonth == yearMonth && doctorIds.Contains(t.ReviewerId))
|
||
// .GroupBy(t => t.ReviewerId).Select(g => new
|
||
// {
|
||
// ReviewerId = g.Key,
|
||
// AdjustPaymentCNY = g.Sum(t => t.AdjustPaymentCNY),
|
||
// AdjustPaymentUSD = g.Sum(t => t.AdjustPaymentUSD)
|
||
// }).ToList();
|
||
|
||
//costStatisticsList.ForEach(t =>
|
||
//{
|
||
// var tempAdj = adjList.FirstOrDefault(u => u.ReviewerId == t.DoctorId);
|
||
// if (tempAdj != null)
|
||
// {
|
||
// t.AdjustPaymentUSD = tempAdj.AdjustPaymentUSD;
|
||
// t.AdjustPaymentCNY = tempAdj.AdjustPaymentCNY;
|
||
|
||
// }
|
||
//});
|
||
|
||
|
||
#endregion
|
||
|
||
return new PageOutput<PaymentModel>(queryParam.PageIndex, queryParam.PageSize, count, costStatisticsList);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Financials /MonthlyPaymentDetail 详情查询接口
|
||
/// </summary>
|
||
[HttpPost("{paymentId:guid}/{doctorId:guid}/{yearMonth:datetime}")]
|
||
public async Task<PayDetailDTO> GetMonthlyPaymentDetailList(Guid paymentId, Guid reviewerId, DateTime yearMonth)
|
||
{
|
||
var returnModel = new PayDetailDTO();
|
||
var yearMonthStr = yearMonth.ToString("yyyy-MM");
|
||
|
||
List<PaymentDetailDTO> detailList = new List<PaymentDetailDTO>();
|
||
//有详细表的数据 先查出来
|
||
if (paymentId != Guid.Empty)
|
||
{
|
||
|
||
//from enroll in _enrollRepository.Where(t => t.TrialId == challengeQuery.TrialId)
|
||
//join dociorc in _doctorRepository.Where() on enroll.DoctorId equals dociorc.Id
|
||
//join price in _TrialPaymentPriceRepository.Where() on enroll.TrialId equals price.TrialId
|
||
|
||
|
||
//select new EnrollViewModel()
|
||
//{
|
||
// ChineseName = dociorc.ChineseName,
|
||
// AdjustmentMultiple = enroll.AdjustmentMultiple,
|
||
// FirstName = dociorc.FirstName,
|
||
// LastName = dociorc.LastName,
|
||
// DoctorId = dociorc.Id,
|
||
// TrialId = challengeQuery.TrialId
|
||
|
||
//};
|
||
//detailList = _paymentDetailRepository.AsQueryable()
|
||
// .Where(t => t.PaymentId == paymentId)
|
||
// .OrderBy(t => t.ShowCodeOrder).ThenBy(t => t.ShowTypeOrder).ProjectTo<PaymentDetailDTO>(_mapper.ConfigurationProvider).ToList();
|
||
|
||
|
||
detailList = await (from pay in _paymentDetailRepository.Where(t => t.PaymentId == paymentId)
|
||
join enroll in _enrollRepository.Where() on new { pay.DoctorId, pay.TrialId } equals new { enroll.DoctorId, enroll.TrialId }
|
||
join price in _TrialPaymentPriceRepository.Where() on pay.TrialId equals price.TrialId
|
||
orderby pay.ShowCodeOrder
|
||
orderby pay.ShowTypeOrder
|
||
select new PaymentDetailDTO()
|
||
{
|
||
Id=pay.Id,
|
||
ShowCodeOrder = pay.ShowCodeOrder,
|
||
ShowTypeOrder = pay.ShowTypeOrder,
|
||
PaymentUSD = pay.PaymentUSD,
|
||
BasePrice = pay.BasePrice,
|
||
PersonalAdditional = pay.PersonalAdditional,
|
||
TrialAdditional = pay.TrialAdditional,
|
||
TrialCode = pay.TrialCode,
|
||
PaymentCNY = pay.PaymentCNY,
|
||
DoctorId = pay.DoctorId,
|
||
ExchangeRate = pay.ExchangeRate,
|
||
IsNewTrial = price.IsNewTrial,
|
||
NewPersonalAdditional= enroll.AdjustmentMultiple,
|
||
|
||
}).ToListAsync();
|
||
|
||
}
|
||
//费用调整
|
||
//_payAdjustmentRepository.Where(t => t.YearMonth == yearMonthStr && t.ReviewerId == reviewerId)
|
||
var adjList =
|
||
await (from costAdjustment in _payAdjustmentRepository.Where(t => t.YearMonth == yearMonthStr&& t.ReviewerId == paymentId)
|
||
join enroll in _enrollRepository.Where() on new { costAdjustment.ReviewerId, costAdjustment.TrialId } equals new { ReviewerId= enroll.DoctorId, enroll.TrialId }
|
||
join price in _TrialPaymentPriceRepository.Where() on costAdjustment.TrialId equals price.TrialId
|
||
|
||
|
||
select new PaymentDetailDTO()
|
||
{
|
||
Id=costAdjustment.Id,
|
||
TrialCode = "Adjustment",
|
||
PaymentCNY = costAdjustment.AdjustmentCNY,
|
||
PaymentUSD = costAdjustment.AdjustmentUSD,
|
||
DoctorId = costAdjustment.ReviewerId,
|
||
ExchangeRate = costAdjustment.ExchangeRate,
|
||
AdjustmentView = new AdjustmentDTO()
|
||
{
|
||
AdjustPaymentUSD = costAdjustment.AdjustmentUSD,
|
||
AdjustPaymentCNY = costAdjustment.AdjustmentCNY,
|
||
Note = costAdjustment.Note
|
||
},
|
||
IsNewTrial = price.IsNewTrial,
|
||
NewPersonalAdditional = enroll.AdjustmentMultiple,
|
||
|
||
}).ToListAsync();
|
||
|
||
|
||
|
||
|
||
detailList.AddRange(adjList);
|
||
|
||
detailList.ForEach(x =>
|
||
{
|
||
x.PersonalAdditional = x.IsNewTrial == true && x.NewPersonalAdditional != null ? 0 : x.PersonalAdditional;
|
||
x.TrialAdditional = x.IsNewTrial == true && x.NewPersonalAdditional != null ? 0 : x.TrialAdditional;
|
||
x.BasePrice = x.IsNewTrial == true && x.NewPersonalAdditional != null ? x.NewPersonalAdditional.Value : x.BasePrice;
|
||
|
||
});
|
||
|
||
returnModel.DetailList = detailList;
|
||
|
||
|
||
|
||
var doctorId = returnModel.DetailList.FirstOrDefault()?.DoctorId;
|
||
var query = from doctor in _doctorRepository.AsQueryable()
|
||
.Where(t => t.Id == doctorId)
|
||
join payInfo in _doctorPayInfoRepository.AsQueryable() on doctor.Id equals payInfo.DoctorId
|
||
join rank in _rankPriceRepository.AsQueryable() on payInfo.RankId equals rank.Id
|
||
select new DoctorPayInfo()
|
||
{
|
||
Code = doctor.ReviewerCode,
|
||
ChineseName = doctor.ChineseName,
|
||
FirstName = doctor.FirstName,
|
||
LastName = doctor.LastName,
|
||
Phone = doctor.Phone,
|
||
DoctorId = doctor.Id,
|
||
PayTitle = rank.RankName,
|
||
YearMonth = yearMonthStr
|
||
};
|
||
|
||
returnModel.DoctorInfo =(await query.FirstOrDefaultAsync()).IfNullThrowException();
|
||
|
||
return returnModel;
|
||
}
|
||
|
||
/// <summary>
|
||
/// NEW 导出Excel压缩包 数据获取
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<List<PayDetailDTO>> GetReviewersMonthlyPaymentDetail(List<MonthlyPaymentDetailQuery> manyReviewers)
|
||
{
|
||
List<PayDetailDTO> result = new List<PayDetailDTO>();
|
||
foreach (var t in manyReviewers)
|
||
{
|
||
result.Add(await GetMonthlyPaymentDetailList(t.PaymentId, t.ReviewerId, t.YearMonth));
|
||
}
|
||
|
||
|
||
return result;
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Financials / Payment History 列表查询接口(已经支付锁定的数据,包含调整的)[New]
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<PageOutput<MonthlyPaymentDTO>> GetPaymentHistoryList(PaymentQueryDTO queryParam)
|
||
{
|
||
Expression<Func<Doctor, bool>> doctorLambda = x => true;
|
||
if (!string.IsNullOrWhiteSpace(queryParam.Reviewer))
|
||
{
|
||
var reviewer = queryParam.Reviewer.Trim();
|
||
doctorLambda = doctorLambda.And(u => u.ChineseName.Contains(reviewer)
|
||
|| u.FirstName.Contains(reviewer)
|
||
|| u.LastName.Contains(reviewer)
|
||
|| u.ReviewerCode.Contains(reviewer));
|
||
}
|
||
if (queryParam.Nation != null)
|
||
{
|
||
doctorLambda = doctorLambda.And(u => u.Nation == queryParam.Nation);
|
||
}
|
||
|
||
Expression<Func<Payment, bool>> paymentLambda = x => x.IsLock && x.YearMonthDate >= queryParam.BeginMonth && x.YearMonthDate <= queryParam.EndMonth;
|
||
|
||
#region 在 payment表加 调整总计前
|
||
|
||
//var paymentQueryable = _paymentRepository.Find(paymentLambda)
|
||
// .Select(
|
||
// t => new
|
||
// {
|
||
// ReviewerId = t.DoctorId,
|
||
// t.YearMonth,
|
||
// t.PaymentUSD,
|
||
// t.PaymentCNY,
|
||
// t.AdjustPaymentCNY,
|
||
// t.AdjustPaymentUSD
|
||
// });
|
||
|
||
//Expression<Func<PaymentAdjustment, bool>> payAdjustmentLambda = x => x.IsLock && x.AdjustedYearMonth >= param.BeginMonth && x.AdjustedYearMonth <= param.EndMonth;
|
||
|
||
//var adjQueryable = _payAdjustmentRepository.GetAll()
|
||
// .Where(payAdjustmentLambda)
|
||
// .GroupBy(t => new { t.ReviewerId, t.YearMonth }).Select(g => new
|
||
// {
|
||
// g.Key.ReviewerId,
|
||
// g.Key.YearMonth,
|
||
// PaymentUSD = 0,
|
||
// PaymentCNY = 0,
|
||
// AdjustPaymentCNY = g.Sum(t => t.AdjustPaymentCNY),
|
||
// AdjustPaymentUSD = g.Sum(t => t.AdjustPaymentUSD)
|
||
// });
|
||
|
||
//var query = from pay in (from paymentCost in paymentQueryable
|
||
// join adjCost in adjQueryable on new { paymentCost.YearMonth, paymentCost.ReviewerId } equals new { adjCost.YearMonth, adjCost.ReviewerId } into a
|
||
// from adjCost in a.DefaultIfEmpty()
|
||
// select new
|
||
// {
|
||
// paymentCost.ReviewerId,
|
||
// paymentCost.PaymentUSD,
|
||
// paymentCost.PaymentCNY,
|
||
// AdjustmentCNY = adjCost == null ? 0 : adjCost.AdjustPaymentCNY,
|
||
// AdjustmentUSD = adjCost == null ? 0 : adjCost.AdjustPaymentUSD
|
||
// }
|
||
// ).Union(
|
||
// from adjCost in adjQueryable
|
||
// join paymentCost in paymentQueryable on new { adjCost.YearMonth, adjCost.ReviewerId } equals new { paymentCost.YearMonth, paymentCost.ReviewerId } into a
|
||
// from paymentCost in a.DefaultIfEmpty()
|
||
// select new
|
||
// {
|
||
// ReviewerId = adjCost.ReviewerId,
|
||
// PaymentUSD = paymentCost == null ? 0 : paymentCost.PaymentUSD,
|
||
// PaymentCNY = paymentCost == null ? 0 : paymentCost.PaymentCNY,
|
||
// AdjustmentCNY = adjCost.AdjustPaymentCNY,
|
||
// AdjustmentUSD = adjCost.AdjustPaymentUSD
|
||
// }
|
||
// )
|
||
|
||
#endregion
|
||
|
||
var query = from monthlyPay in _paymentRepository.Where(paymentLambda)
|
||
.GroupBy(t => t.DoctorId).Select(g => new
|
||
{
|
||
ReviewerId = g.Key,
|
||
PaymentUSD = g.Sum(u => u.PaymentUSD),
|
||
PaymentCNY = g.Sum(u => u.PaymentCNY),
|
||
AdjustmentCNY = g.Sum(u => u.AdjustmentCNY),
|
||
AdjustmentUSD = g.Sum(u => u.AdjustmentCNY)
|
||
})
|
||
join doctor in _doctorRepository.Where(doctorLambda) on monthlyPay.ReviewerId equals doctor.Id
|
||
select new MonthlyPaymentDTO
|
||
{
|
||
ReviewerId = doctor.Id,
|
||
ChineseName = doctor.ChineseName,
|
||
FirstName = doctor.FirstName,
|
||
LastName = doctor.LastName,
|
||
ReviewerCode = doctor.ReviewerCode,
|
||
PaymentUSD = monthlyPay.PaymentUSD,
|
||
PaymentCNY = monthlyPay.PaymentCNY,
|
||
AdjustmentCNY = monthlyPay.AdjustmentCNY,
|
||
AdjustmentUSD = monthlyPay.AdjustmentUSD,
|
||
TotalCNY = monthlyPay.AdjustmentCNY + monthlyPay.PaymentCNY,
|
||
TotalUSD = monthlyPay.AdjustmentUSD + monthlyPay.PaymentUSD
|
||
};
|
||
var propName = queryParam.SortField == string.Empty ? "ReviewerCode" : queryParam.SortField;
|
||
query = queryParam.Asc ? query.OrderBy(propName).ThenBy(u => u.ReviewerCode) : query.OrderByDescending(propName).ThenBy(u => u.ReviewerCode);
|
||
if (propName == "FirstName" || propName == "LastName")
|
||
{
|
||
query = queryParam.Asc ? query.OrderBy(t => t.LastName).ThenBy(t => t.FirstName)
|
||
: query.OrderByDescending(t => t.LastName).ThenBy(t => t.FirstName);
|
||
}
|
||
var count = await query.CountAsync();
|
||
query = query.Skip((queryParam.PageIndex - 1) * queryParam.PageSize).Take(queryParam.PageSize);
|
||
var list = await query.ToListAsync();
|
||
return new PageOutput<MonthlyPaymentDTO>(queryParam.PageIndex, queryParam.PageSize, count, list);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// Financials / Payment History 详情接口[New]
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<List<VolumeStatisticsDTO>> GetPaymentHistoryDetailList(VolumeQueryDTO param)
|
||
{
|
||
var beginDate = new DateTime(param.BeginMonth.Year, param.BeginMonth.Month, 1);
|
||
var endDate = new DateTime(param.EndMonth.Year, param.EndMonth.Month, 1);
|
||
|
||
Expression<Func<Payment, bool>> monthlyPayLambda = x => x.IsLock && x.DoctorId == param.ReviewerId && x.YearMonthDate >= beginDate && x.YearMonthDate <= endDate;
|
||
|
||
var query =
|
||
from monthlyPayment in _paymentRepository.Where(monthlyPayLambda)
|
||
|
||
select new VolumeStatisticsDTO
|
||
{
|
||
StatisticsId = monthlyPayment.Id,
|
||
Month = monthlyPayment.YearMonth,
|
||
ExchangeRate = monthlyPayment.ExchangeRate,
|
||
PaymentUSD = monthlyPayment.PaymentUSD,
|
||
PaymentCNY = monthlyPayment.PaymentCNY,
|
||
AdjustmentCNY = monthlyPayment.AdjustmentCNY,
|
||
AdjustmentUSD = monthlyPayment.AdjustmentUSD,
|
||
VolumeReward = 0
|
||
};
|
||
|
||
var payDetailList = await query.OrderBy(t => t.Month).ToListAsync();
|
||
|
||
List<Guid> statisticsIdList = payDetailList.Select(t => t.StatisticsId).ToList();
|
||
|
||
var monthlyPayDetailList = await _paymentDetailRepository.Where(u =>
|
||
statisticsIdList.Contains(u.PaymentId)).Select(t => new
|
||
{
|
||
PaymentId = t.PaymentId,
|
||
t.PaymentUSD,
|
||
t.TrialCode,
|
||
t.PaymentCNY,
|
||
t.YearMonth
|
||
}).ToListAsync();
|
||
|
||
payDetailList.ForEach(t =>
|
||
{
|
||
t.VolumeReward = monthlyPayDetailList
|
||
.Where(u => u.PaymentId == t.StatisticsId && u.TrialCode == "Volume Reward")
|
||
.Sum(k => k.PaymentUSD);
|
||
|
||
t.TrialPaymentList = monthlyPayDetailList
|
||
.Where(u => u.PaymentId == t.StatisticsId && u.TrialCode != "Volume Reward" && u.YearMonth == t.Month)
|
||
.GroupBy(u => u.TrialCode).Select(g => new TrialPaymentDTO
|
||
{
|
||
TrialPayment = g.Sum(k => k.PaymentUSD),
|
||
TrialCode = g.Key
|
||
}).ToList();
|
||
});
|
||
|
||
|
||
#region 改表之前
|
||
|
||
//var tempVolume = _costStatisticsDetailRepository.Find(u =>
|
||
// statisticsIdList.Contains(u.PaymentId)).ToList();
|
||
|
||
//foreach (var item in payDetailList)
|
||
//{
|
||
// var temp = tempVolume.Where(u => u.PaymentId == item.StatisticsId && u.TrialCode == "Volume Reward");
|
||
// var Volume = 0.0;
|
||
// foreach (var t in temp)
|
||
// {
|
||
// Volume += (t.BasePrice * t.Count);
|
||
// }
|
||
// item.VolumeReward = Volume;
|
||
|
||
// var trialCodes = tempVolume.Where(u => u.PaymentId == item.StatisticsId
|
||
// && u.TrialCode != "Volume Reward").GroupBy(u => u.TrialCode).Select(u => u.Key).Distinct();
|
||
|
||
// foreach (var trial in trialCodes)
|
||
// {
|
||
// var trialFee = 0.0;
|
||
// var aa = tempVolume.Where(u => u.PaymentId == item.StatisticsId && u.TrialCode == trial
|
||
// ).ToList();
|
||
|
||
// foreach (var a in aa)
|
||
// {
|
||
// trialFee += (a.Count * (a.BasePrice + a.PersonalAdditional + a.TrialAdditional));
|
||
// }
|
||
// item.TrialFeeList.Add(new TrialFeeViewModel
|
||
// {
|
||
// TrialCode = trial,
|
||
// TrialFee = trialFee
|
||
// });
|
||
// }
|
||
|
||
//}
|
||
|
||
#endregion
|
||
|
||
return payDetailList;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Revenues列表接口,收入统计[New] 0是Detail 1是按照项目 2是按照人 3按照月份
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<PageOutput<RevenuesDTO>> GetRevenuesStatistics(StatisticsQueryDTO queryParam)
|
||
{
|
||
var bDate = new DateTime(queryParam.BeginDate.Year, queryParam.BeginDate.Month, 1);
|
||
var eDate = new DateTime(queryParam.EndDate.Year, queryParam.EndDate.Month, 1);
|
||
Expression<Func<Workload, bool>> workloadLambda = x => x.DataFrom == (int)WorkLoadFromStatus.FinalConfirm;
|
||
workloadLambda = workloadLambda.And(x => x.WorkTime >= bDate && x.WorkTime <= eDate);
|
||
|
||
Expression<Func<Trial, bool>> trialLambda = x => true;
|
||
if (Guid.Empty != queryParam.CroId && queryParam.CroId != null)
|
||
{
|
||
trialLambda = trialLambda.And(u => u.CROId == queryParam.CroId);
|
||
}
|
||
if (!string.IsNullOrWhiteSpace(queryParam.TrialCode))
|
||
{
|
||
var trialCode = queryParam.TrialCode.Trim();
|
||
trialLambda = trialLambda.And(u => u.TrialCode.Contains(trialCode));
|
||
}
|
||
|
||
if (queryParam.AttendedReviewerType != null)
|
||
{
|
||
trialLambda = trialLambda.And(u => u.AttendedReviewerType == queryParam.AttendedReviewerType);
|
||
}
|
||
|
||
Expression<Func<Doctor, bool>> doctorLambda = x => true;
|
||
|
||
if (!string.IsNullOrWhiteSpace(queryParam.Reviewer))
|
||
{
|
||
var reviewer = queryParam.Reviewer.Trim();
|
||
doctorLambda = doctorLambda.And(u => u.ChineseName.Contains(reviewer)
|
||
|| u.FirstName.Contains(reviewer)
|
||
|| u.LastName.Contains(reviewer)
|
||
|| u.ReviewerCode.Contains(reviewer));
|
||
}
|
||
if (queryParam.Nation != null)
|
||
{
|
||
doctorLambda = doctorLambda.And(u => u.Nation == queryParam.Nation);
|
||
}
|
||
|
||
List<RevenuesDTO> incomeList = new List<RevenuesDTO>();
|
||
IQueryable<RevenuesDTO>? query=null ;
|
||
var propName = string.Empty;
|
||
var count = 0;
|
||
|
||
#region 按照详细维度 ReviewId TrialId
|
||
|
||
if (queryParam.StatType == 0)
|
||
{
|
||
query = from workLoad in _workloadRepository.Where(workloadLambda)
|
||
join doctor in _doctorRepository.Where(doctorLambda)
|
||
on workLoad.DoctorId equals doctor.Id
|
||
join trial in _trialRepository.Where(trialLambda)
|
||
on workLoad.TrialId equals trial.Id
|
||
join cro in _croRepository.AsQueryable() on trial.CROId equals cro.Id into ttt
|
||
from croItem in ttt.DefaultIfEmpty()
|
||
join trialCost in _trialRevenuePriceRepository.AsQueryable() on workLoad.TrialId equals trialCost.TrialId into c
|
||
from trialCost in c.DefaultIfEmpty()
|
||
select new RevenuesDTO
|
||
{
|
||
|
||
TrialId = workLoad.TrialId,
|
||
Cro = croItem.CROName,
|
||
ReviewerCode = doctor.ReviewerCode,
|
||
ChineseName = doctor.ChineseName,
|
||
FirstName = doctor.FirstName,
|
||
LastName = doctor.LastName,
|
||
|
||
Indication = trial.Indication,
|
||
TrialCode = trial.TrialCode,
|
||
Expedited = trial.Expedited,
|
||
CroId = trial.CROId,
|
||
|
||
Downtime = workLoad.Downtime * trialCost.Downtime,
|
||
Training = workLoad.Training * trialCost.Training,
|
||
Timepoint = workLoad.Timepoint * trialCost.Timepoint,
|
||
TimepointIn24H = workLoad.TimepointIn24H * trialCost.TimepointIn24H,
|
||
TimepointIn48H = workLoad.TimepointIn48H * trialCost.TimepointIn48H,
|
||
Global = workLoad.Global * trialCost.Global,
|
||
Adjudication = workLoad.Adjudication * trialCost.Adjudication,
|
||
AdjudicationIn24H =
|
||
workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H,
|
||
AdjudicationIn48H = workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H,
|
||
|
||
YearMonth = workLoad.YearMonth,
|
||
|
||
Total = (workLoad.Downtime * trialCost.Downtime +
|
||
workLoad.Training * trialCost.Training +
|
||
workLoad.Timepoint * trialCost.Timepoint +
|
||
workLoad.TimepointIn24H * trialCost.TimepointIn24H +
|
||
workLoad.TimepointIn48H * trialCost.TimepointIn48H +
|
||
workLoad.Global * trialCost.Global +
|
||
workLoad.Adjudication * trialCost.Adjudication +
|
||
workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H +
|
||
workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H +
|
||
workLoad.RefresherTraining * trialCost.RefresherTraining
|
||
)
|
||
|
||
};
|
||
|
||
//处理排序字段
|
||
propName = queryParam.SortField == "" ? "ReviewerCode" : queryParam.SortField;
|
||
|
||
}
|
||
//按照项目维度
|
||
if (queryParam.StatType == 1)
|
||
{
|
||
|
||
var workloadQuery = from workLoad in _workloadRepository.Where(workloadLambda)
|
||
|
||
group workLoad by workLoad.TrialId
|
||
into gWorkLoad
|
||
select new
|
||
{
|
||
TrialId = gWorkLoad.Key,
|
||
Downtime = gWorkLoad.Sum(t => t.Downtime),
|
||
Training = gWorkLoad.Sum(t => t.Training),
|
||
Timepoint = gWorkLoad.Sum(t => t.Timepoint),
|
||
TimepointIn24H = gWorkLoad.Sum(t => t.TimepointIn24H),
|
||
TimepointIn48H = gWorkLoad.Sum(t => t.TimepointIn48H),
|
||
Global = gWorkLoad.Sum(t => t.Global),
|
||
Adjudication = gWorkLoad.Sum(t => t.Adjudication),
|
||
AdjudicationIn24H = gWorkLoad.Sum(t => t.AdjudicationIn24H),
|
||
AdjudicationIn48H = gWorkLoad.Sum(t => t.AdjudicationIn48H),
|
||
RefresherTraining = gWorkLoad.Sum(t => t.RefresherTraining),
|
||
};
|
||
|
||
query = from workLoad in workloadQuery
|
||
join trialCost in _trialRevenuePriceRepository.AsQueryable() on workLoad.TrialId equals trialCost.TrialId
|
||
into c
|
||
from trialCost in c.DefaultIfEmpty()
|
||
join trial in _trialRepository.Where(trialLambda) on workLoad.TrialId equals trial.Id
|
||
join cro in _croRepository.AsQueryable() on trial.CROId equals cro.Id into ttt
|
||
from croItem in ttt.DefaultIfEmpty()
|
||
select new RevenuesDTO
|
||
{
|
||
|
||
TrialId = trial.Id,
|
||
Indication = trial.Indication,
|
||
TrialCode = trial.TrialCode,
|
||
Expedited = trial.Expedited,
|
||
CroId = trial.CROId,
|
||
Cro = croItem.CROName,
|
||
Training = workLoad.Training * trialCost.Training,
|
||
Timepoint = workLoad.Timepoint * trialCost.Timepoint,
|
||
TimepointIn24H = workLoad.TimepointIn24H * trialCost.TimepointIn24H,
|
||
TimepointIn48H = workLoad.TimepointIn48H * trialCost.TimepointIn48H,
|
||
Adjudication = workLoad.Adjudication * trialCost.Adjudication,
|
||
AdjudicationIn24H = workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H,
|
||
AdjudicationIn48H = workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H,
|
||
Global = workLoad.Global * trialCost.Global,
|
||
Downtime = workLoad.Downtime * trialCost.Downtime,
|
||
|
||
Total = (workLoad.Downtime * trialCost.Downtime +
|
||
workLoad.Training * trialCost.Training +
|
||
workLoad.Timepoint * trialCost.Timepoint +
|
||
workLoad.TimepointIn24H * trialCost.TimepointIn24H +
|
||
workLoad.TimepointIn48H * trialCost.TimepointIn48H +
|
||
workLoad.Global * trialCost.Global +
|
||
workLoad.Adjudication * trialCost.Adjudication +
|
||
workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H +
|
||
workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H +
|
||
workLoad.RefresherTraining * trialCost.RefresherTraining
|
||
)
|
||
};
|
||
|
||
//处理排序字段
|
||
propName = queryParam.SortField == "" ? "TrialCode" : queryParam.SortField;
|
||
|
||
}
|
||
|
||
//按照人的维度
|
||
if (queryParam.StatType == 2)
|
||
{
|
||
var workloadQuery = from workLoad in _workloadRepository.Where(workloadLambda)
|
||
join doctor in _doctorRepository.Where(doctorLambda)
|
||
on workLoad.DoctorId equals doctor.Id
|
||
join trial in _trialRepository.Where(trialLambda) on workLoad.TrialId equals trial.Id
|
||
join trialCost in _trialRevenuePriceRepository.AsQueryable() on workLoad.TrialId equals trialCost.TrialId into c
|
||
from trialCost in c.DefaultIfEmpty()
|
||
|
||
select new
|
||
{
|
||
DoctorId = workLoad.DoctorId,
|
||
Downtime = workLoad.Downtime * trialCost.Downtime,
|
||
Training = workLoad.Training * trialCost.Training,
|
||
Timepoint = workLoad.Timepoint * trialCost.Timepoint,
|
||
TimepointIn24H = workLoad.TimepointIn24H * trialCost.TimepointIn24H,
|
||
TimepointIn48H = workLoad.TimepointIn48H * trialCost.TimepointIn48H,
|
||
Global = workLoad.Global * trialCost.Global,
|
||
Adjudication = workLoad.Adjudication * trialCost.Adjudication,
|
||
AdjudicationIn24H =
|
||
workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H,
|
||
AdjudicationIn48H = workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H,
|
||
RefresherTraining = workLoad.RefresherTraining * trialCost.RefresherTraining,
|
||
ReviewerCode = doctor.ReviewerCode,
|
||
ChineseName = doctor.ChineseName,
|
||
FirstName = doctor.FirstName,
|
||
LastName = doctor.LastName,
|
||
|
||
};
|
||
|
||
|
||
query = workloadQuery.GroupBy(t => new { t.DoctorId, t.ReviewerCode, t.ChineseName, t.FirstName, t.LastName }).Select(gWorkLoad => new RevenuesDTO
|
||
{
|
||
ReviewerCode = gWorkLoad.Key.ReviewerCode,
|
||
ChineseName = gWorkLoad.Key.ChineseName,
|
||
FirstName = gWorkLoad.Key.FirstName,
|
||
LastName = gWorkLoad.Key.LastName,
|
||
|
||
Downtime = gWorkLoad.Sum(t => t.Downtime),
|
||
Training = gWorkLoad.Sum(t => t.Training),
|
||
Timepoint = gWorkLoad.Sum(t => t.Timepoint),
|
||
TimepointIn24H = gWorkLoad.Sum(t => t.TimepointIn24H),
|
||
TimepointIn48H = gWorkLoad.Sum(t => t.TimepointIn48H),
|
||
Global = gWorkLoad.Sum(t => t.Global),
|
||
Adjudication = gWorkLoad.Sum(t => t.Adjudication),
|
||
AdjudicationIn24H = gWorkLoad.Sum(t => t.AdjudicationIn24H),
|
||
AdjudicationIn48H = gWorkLoad.Sum(t => t.AdjudicationIn48H),
|
||
|
||
Total = gWorkLoad.Sum(t => t.Downtime) +
|
||
gWorkLoad.Sum(t => t.Training) +
|
||
gWorkLoad.Sum(t => t.Timepoint) +
|
||
gWorkLoad.Sum(t => t.TimepointIn24H) +
|
||
gWorkLoad.Sum(t => t.TimepointIn48H) +
|
||
gWorkLoad.Sum(t => t.Global) +
|
||
gWorkLoad.Sum(t => t.Adjudication) +
|
||
gWorkLoad.Sum(t => t.AdjudicationIn24H) +
|
||
gWorkLoad.Sum(t => t.AdjudicationIn48H) +
|
||
gWorkLoad.Sum(t => t.RefresherTraining)
|
||
|
||
});
|
||
|
||
propName = queryParam.SortField == string.Empty ? "ReviewerCode" : queryParam.SortField;
|
||
|
||
|
||
}
|
||
|
||
//按照月份维度
|
||
if (queryParam.StatType == 3)
|
||
{
|
||
var workloadQuery = from workLoad in _workloadRepository.Where(workloadLambda)
|
||
join trial in _trialRepository.Where(trialLambda)
|
||
on workLoad.TrialId equals trial.Id
|
||
join doctor in _doctorRepository.Where(doctorLambda)
|
||
on workLoad.DoctorId equals doctor.Id
|
||
join trialCost in _trialRevenuePriceRepository.AsQueryable() on workLoad.TrialId equals trialCost.TrialId into c
|
||
from trialCost in c.DefaultIfEmpty()
|
||
|
||
select new
|
||
{
|
||
workLoad.YearMonth,
|
||
Downtime = workLoad.Downtime * trialCost.Downtime,
|
||
Training = workLoad.Training * trialCost.Training,
|
||
Timepoint = workLoad.Timepoint * trialCost.Timepoint,
|
||
TimepointIn24H = workLoad.TimepointIn24H * trialCost.TimepointIn24H,
|
||
TimepointIn48H = workLoad.TimepointIn48H * trialCost.TimepointIn48H,
|
||
Global = workLoad.Global * trialCost.Global,
|
||
Adjudication = workLoad.Adjudication * trialCost.Adjudication,
|
||
AdjudicationIn24H =
|
||
workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H,
|
||
AdjudicationIn48H = workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H,
|
||
RefresherTraining = workLoad.RefresherTraining * trialCost.RefresherTraining,
|
||
|
||
};
|
||
|
||
query = workloadQuery.GroupBy(t => t.YearMonth).Select(gWorkLoad => new RevenuesDTO
|
||
{
|
||
|
||
YearMonth = gWorkLoad.Key,
|
||
Downtime = gWorkLoad.Sum(t => t.Downtime),
|
||
Training = gWorkLoad.Sum(t => t.Training),
|
||
Timepoint = gWorkLoad.Sum(t => t.Timepoint),
|
||
TimepointIn24H = gWorkLoad.Sum(t => t.TimepointIn24H),
|
||
TimepointIn48H = gWorkLoad.Sum(t => t.TimepointIn48H),
|
||
Global = gWorkLoad.Sum(t => t.Global),
|
||
Adjudication = gWorkLoad.Sum(t => t.Adjudication),
|
||
AdjudicationIn24H = gWorkLoad.Sum(t => t.AdjudicationIn24H),
|
||
AdjudicationIn48H = gWorkLoad.Sum(t => t.AdjudicationIn48H),
|
||
Total = gWorkLoad.Sum(t => t.Downtime) +
|
||
gWorkLoad.Sum(t => t.Training) +
|
||
gWorkLoad.Sum(t => t.Timepoint) +
|
||
gWorkLoad.Sum(t => t.TimepointIn24H) +
|
||
gWorkLoad.Sum(t => t.TimepointIn48H) +
|
||
gWorkLoad.Sum(t => t.Global) +
|
||
gWorkLoad.Sum(t => t.Adjudication) +
|
||
gWorkLoad.Sum(t => t.AdjudicationIn24H) +
|
||
gWorkLoad.Sum(t => t.AdjudicationIn48H) +
|
||
gWorkLoad.Sum(t => t.RefresherTraining)
|
||
|
||
});
|
||
propName = queryParam.SortField == string.Empty ? "YearMonth" : queryParam.SortField;
|
||
}
|
||
|
||
|
||
#endregion
|
||
//if (propName == "FirstName" || propName == "LastName")
|
||
//{
|
||
// query = param.Asc
|
||
// ? query.OrderBy(t => t.LastName).ThenBy(t => t.FirstName)
|
||
// : query.OrderByDescending(t => t.LastName).ThenBy(t => t.FirstName);
|
||
//}
|
||
|
||
//非详细 只用单字段排序
|
||
if (queryParam.StatType != 0)
|
||
{
|
||
query = queryParam.Asc ? query.OrderBy(propName) : query.OrderByDescending(propName);
|
||
}
|
||
//详情 多字段排序
|
||
if (queryParam.StatType == 0)
|
||
{
|
||
query = queryParam.Asc ? query.OrderBy(propName).ThenBy(t => t.TrialId).ThenBy(t => t.YearMonth).ThenBy(t => t.ReviewerCode) :
|
||
query.OrderByDescending(propName).ThenBy(t => t.TrialId).ThenBy(t => t.YearMonth).ThenBy(t => t.ReviewerCode)
|
||
;
|
||
}
|
||
|
||
|
||
count = query!.Count();
|
||
query = query!.Skip((queryParam.PageIndex - 1) * queryParam.PageSize).Take(queryParam.PageSize);
|
||
|
||
incomeList = await query.ToListAsync();
|
||
|
||
#region 处理缺失项目价格 按照医生 或者月份维度
|
||
|
||
if (queryParam.StatType == 2 || queryParam.StatType == 3)
|
||
{
|
||
var hasIncomePriceTrialIds = await _trialRevenuePriceRepository.Select(t => t.TrialId).ToListAsync();
|
||
|
||
workloadLambda = workloadLambda.And(t => !hasIncomePriceTrialIds.Contains(t.TrialId));
|
||
var doctorMissingTrialCodesQuery = (from workLoad in _workloadRepository.Where(workloadLambda)
|
||
join trial in _trialRepository.AsQueryable() on workLoad.TrialId equals trial.Id
|
||
select new
|
||
{
|
||
DoctorId = workLoad.DoctorId,
|
||
Month = workLoad.YearMonth,
|
||
TrialCode = trial.TrialCode
|
||
}).Distinct();
|
||
|
||
var doctorMissingTrialCodes = ((await doctorMissingTrialCodesQuery.ToListAsync()).GroupBy(t => t.DoctorId).Select(g => new
|
||
{
|
||
DoctorId = g.Key,
|
||
TrialCodes = g.Select(u => u.TrialCode).Distinct().ToList()
|
||
})).ToList();
|
||
|
||
var monthMissingTrialCode = ((await doctorMissingTrialCodesQuery.ToListAsync()).GroupBy(t => t.Month).Select(g => new
|
||
{
|
||
Month = g.Key,
|
||
TrialCodes = g.Select(u => u.TrialCode).Distinct().ToList()
|
||
})).ToList();
|
||
|
||
incomeList.ForEach(income =>
|
||
{
|
||
var doctor = doctorMissingTrialCodes.FirstOrDefault(t => t.DoctorId == income.Id);
|
||
var month = monthMissingTrialCode.FirstOrDefault(t => t.Month == income.YearMonth);
|
||
|
||
if (queryParam.StatType == 2)
|
||
{
|
||
income.MissingTrialCodes = doctor == null ? new List<string>() : doctor.TrialCodes;
|
||
}
|
||
else
|
||
{
|
||
income.MissingTrialCodes = month == null ? new List<string>() : month.TrialCodes;
|
||
}
|
||
});
|
||
}
|
||
|
||
if (queryParam.StatType == 0 || queryParam.StatType == 1)
|
||
{
|
||
incomeList.ForEach(income =>
|
||
{
|
||
List<string> temp = new List<string>();
|
||
|
||
|
||
|
||
if (Math.Abs(income.Total) < 0.001m)
|
||
{
|
||
temp.Add(income.TrialCode);
|
||
income.MissingTrialCodes = temp;
|
||
}
|
||
|
||
});
|
||
}
|
||
#endregion
|
||
|
||
return new PageOutput<RevenuesDTO>(queryParam.PageIndex, queryParam.PageSize, count, incomeList);
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 收入支出分析接口,按照项目维度分析统计
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<List<TrialAnalysisDTO>> GetTrialAnalysisList(TrialAnalysisQueryDTO param)
|
||
{
|
||
var bDate = new DateTime(param.BeginDate.Year, param.BeginDate.Month, 1);
|
||
var eDate = new DateTime(param.EndDate.Year, param.EndDate.Month, 1);
|
||
|
||
Expression<Func<Workload, bool>> workloadLambda = x => x.DataFrom == (int)WorkLoadFromStatus.FinalConfirm;
|
||
|
||
Expression<Func<Trial, bool>> trialLambda = x => true;
|
||
if (Guid.Empty != param.CroId && param.CroId != null)
|
||
{
|
||
trialLambda = trialLambda.And(u => u.CROId == param.CroId);
|
||
}
|
||
if (!string.IsNullOrWhiteSpace(param.TrialCode))
|
||
{
|
||
var trialCode = param.TrialCode.Trim();
|
||
trialLambda = trialLambda.And(u => u.TrialCode.Contains(trialCode));
|
||
}
|
||
if (param.AttendedReviewerType != null)
|
||
{
|
||
trialLambda = trialLambda.And(u => u.AttendedReviewerType == param.AttendedReviewerType);
|
||
}
|
||
|
||
var lockedPaymentIdAndYearMonth = _paymentRepository.Where(t => t.IsLock && t.YearMonthDate >= bDate && t.YearMonthDate <= eDate).Select(t => new { PaymentId = t.Id, t.YearMonth, t.DoctorId });
|
||
|
||
var costStatisticsIds = await lockedPaymentIdAndYearMonth.Select(t => t.PaymentId).ToListAsync();
|
||
|
||
var lockedDoctorIdAndYearMonthQueryable = lockedPaymentIdAndYearMonth.Select(t => new { t.YearMonth, t.DoctorId });
|
||
|
||
|
||
////工作量过滤查询 锁定得月份
|
||
//workloadLambda = workloadLambda.And(x => lockedDoctorIdAndYearMonthQueryable.Contains());
|
||
|
||
var trialPayQuery = from costStatisticsDetail in _paymentDetailRepository.AsQueryable()
|
||
.Where(t => costStatisticsIds.Contains(t.PaymentId) && t.TrialCode != "Volume Reward")
|
||
group costStatisticsDetail by costStatisticsDetail.TrialId
|
||
into g
|
||
select new
|
||
{
|
||
TrialId = g.Key,
|
||
PaymentUSD = g.Sum(t => t.PaymentUSD)
|
||
};
|
||
|
||
|
||
var workloadQuery = from workLoad in _workloadRepository.Where(workloadLambda)
|
||
join lockedDoctorAndMonth in lockedDoctorIdAndYearMonthQueryable on new { workLoad.DoctorId, YearMonth = workLoad.YearMonth } equals new { lockedDoctorAndMonth.DoctorId, lockedDoctorAndMonth.YearMonth }
|
||
group workLoad by workLoad.TrialId
|
||
|
||
into gWorkLoad
|
||
select new
|
||
{
|
||
TrialId = gWorkLoad.Key,
|
||
Downtime = gWorkLoad.Sum(t => t.Downtime),
|
||
Training = gWorkLoad.Sum(t => t.Training),
|
||
Timepoint = gWorkLoad.Sum(t => t.Timepoint),
|
||
TimepointIn24H = gWorkLoad.Sum(t => t.TimepointIn24H),
|
||
TimepointIn48H = gWorkLoad.Sum(t => t.TimepointIn48H),
|
||
Global = gWorkLoad.Sum(t => t.Global),
|
||
Adjudication = gWorkLoad.Sum(t => t.Adjudication),
|
||
AdjudicationIn24H = gWorkLoad.Sum(t => t.AdjudicationIn24H),
|
||
AdjudicationIn48H = gWorkLoad.Sum(t => t.AdjudicationIn48H)
|
||
|
||
};
|
||
|
||
var workloadIncomeQuery = from workLoad in workloadQuery
|
||
join trialCost in _trialRevenuePriceRepository.AsQueryable() on workLoad.TrialId equals trialCost.TrialId
|
||
into c
|
||
from trialCost in c.DefaultIfEmpty()
|
||
join trial in _trialRepository.Where(trialLambda) on workLoad.TrialId equals trial.Id into t
|
||
from trial in t.DefaultIfEmpty()
|
||
join cro in _croRepository.AsQueryable() on trial.CROId equals cro.Id into ttt
|
||
from croItem in ttt.DefaultIfEmpty()
|
||
select new TrialAnalysisDTO
|
||
{
|
||
TrialId = trial.Id,
|
||
Indication = trial.Indication,
|
||
TrialCode = trial.TrialCode,
|
||
Expedited = trial.Expedited,
|
||
Cro = croItem == null ? "" : croItem.CROName,
|
||
|
||
Type = "Trial",
|
||
|
||
RevenusUSD = (workLoad.Downtime * trialCost.Downtime) +
|
||
(workLoad.Training * trialCost.Training) +
|
||
(workLoad.Timepoint * trialCost.Timepoint)
|
||
+ (workLoad.TimepointIn24H * trialCost.TimepointIn24H)
|
||
+ (workLoad.TimepointIn48H * trialCost.TimepointIn48H)
|
||
+ (workLoad.Adjudication * trialCost.Adjudication)
|
||
+ (workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H)
|
||
+ (workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H)
|
||
+ (workLoad.Global * trialCost.Global),
|
||
|
||
};
|
||
|
||
|
||
var trialPayList = await trialPayQuery.OrderBy(t => t.PaymentUSD).ToListAsync();
|
||
var workloadIncomeList = await workloadIncomeQuery.ToListAsync();
|
||
var returnList = workloadIncomeList;
|
||
returnList.ForEach(t =>
|
||
{
|
||
var pay = trialPayList.FirstOrDefault(u => u.TrialId == t.TrialId);
|
||
t.PaymentUSD = pay == null ? 0 : pay.PaymentUSD;
|
||
});
|
||
|
||
if ((Guid.Empty == param.CroId || null == param.CroId) && string.IsNullOrWhiteSpace(param.TrialCode))
|
||
{
|
||
var volumeReward = _paymentDetailRepository.AsQueryable()
|
||
.Where(t => costStatisticsIds.Contains(t.PaymentId) && t.TrialCode == "Volume Reward")
|
||
.Sum(t => (decimal?)t.PaymentUSD) ?? 0;
|
||
|
||
var adjustment = _payAdjustmentRepository.AsQueryable()
|
||
.Where(t => t.YearMonthDate >= param.BeginDate
|
||
&& t.YearMonthDate <= param.EndDate && t.IsLock)
|
||
.Sum(u => (decimal?)u.AdjustmentUSD) ?? 0;
|
||
|
||
returnList.Add(new TrialAnalysisDTO()
|
||
{
|
||
Type = "Volume Reward",
|
||
RevenusUSD = 0,
|
||
PaymentUSD = volumeReward
|
||
});
|
||
returnList.Add(new TrialAnalysisDTO()
|
||
{
|
||
Type = "Adjustment",
|
||
RevenusUSD = 0,
|
||
PaymentUSD = adjustment
|
||
});
|
||
}
|
||
return returnList;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 收入支出分析接口,按照医生维度分析统计
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<List<ReviewerAnalysisDTO>> GetReviewerAnalysisList(AnalysisQueryDTO param)
|
||
{
|
||
var beginDate = new DateTime(param.BeginDate.Year, param.BeginDate.Month, 1);
|
||
var endDate = new DateTime(param.EndDate.Year, param.EndDate.Month, 1);
|
||
|
||
Expression<Func<Workload, bool>> workloadLambda = x => x.DataFrom == (int)WorkLoadFromStatus.FinalConfirm;
|
||
|
||
Expression<Func<Doctor, bool>> doctorLambda = x => true;
|
||
if (!string.IsNullOrWhiteSpace(param.Reviewer))
|
||
{
|
||
var reviewer = param.Reviewer.Trim();
|
||
doctorLambda = doctorLambda.And(u => u.ChineseName.Contains(reviewer)
|
||
|| u.FirstName.Contains(reviewer)
|
||
|| u.LastName.Contains(reviewer)
|
||
|| u.ReviewerCode.Contains(reviewer));
|
||
}
|
||
if (param.Nation != null)
|
||
{
|
||
doctorLambda = doctorLambda.And(u => u.Nation == param.Nation);
|
||
}
|
||
|
||
var lockedPaymentIdAndYearMonth = _paymentRepository.Where(t => t.IsLock && t.YearMonthDate >= param.BeginDate && t.YearMonthDate <= param.EndDate).Select(t => new { PaymentId = t.Id, t.YearMonth, t.DoctorId });
|
||
|
||
var lockedDoctorIdAndYearMonthQueryable = lockedPaymentIdAndYearMonth.Select(t => new { t.YearMonth, t.DoctorId });
|
||
|
||
|
||
|
||
Expression<Func<Payment, bool>> monthlyPayLambda = x => x.IsLock && x.YearMonthDate >= beginDate && x.YearMonthDate <= endDate;
|
||
var payQuery =
|
||
from monthlyPayment in _paymentRepository.Where(monthlyPayLambda)
|
||
.GroupBy(t => t.DoctorId).Select(g => new
|
||
{
|
||
ReviewerId = g.Key,
|
||
PaymentUSD = g.Sum(u => u.PaymentUSD),
|
||
PaymentCNY = g.Sum(u => u.PaymentCNY),
|
||
AdjustmentCNY = g.Sum(u => u.AdjustmentCNY),
|
||
AdjustmentUSD = g.Sum(u => u.AdjustmentUSD)
|
||
})
|
||
join doctor in _doctorRepository.Where(doctorLambda) on monthlyPayment.ReviewerId equals doctor.Id
|
||
select new MonthlyPaymentDTO
|
||
{
|
||
ReviewerId = doctor.Id,
|
||
ChineseName = doctor.ChineseName,
|
||
FirstName = doctor.FirstName,
|
||
LastName = doctor.LastName,
|
||
ReviewerCode = doctor.ReviewerCode,
|
||
PaymentUSD = monthlyPayment.PaymentUSD,
|
||
PaymentCNY = monthlyPayment.PaymentCNY,
|
||
AdjustmentCNY = monthlyPayment.AdjustmentCNY,
|
||
AdjustmentUSD = monthlyPayment.AdjustmentUSD,
|
||
TotalUSD = monthlyPayment.AdjustmentUSD + monthlyPayment.PaymentUSD,
|
||
TotalCNY = monthlyPayment.AdjustmentCNY + monthlyPayment.PaymentCNY,
|
||
};
|
||
|
||
//获取工作量收入 workloadLambda 已经加入过滤 payment锁定月份
|
||
|
||
////工作量过滤查询 锁定得月份
|
||
|
||
var workloadIncomeQuery = from workLoad in _workloadRepository.Where(workloadLambda)
|
||
join doctor in _doctorRepository.Where(doctorLambda)
|
||
on workLoad.DoctorId equals doctor.Id
|
||
join lockedDoctorAndMonth in lockedDoctorIdAndYearMonthQueryable on new { workLoad.DoctorId, workLoad.YearMonth } equals new { lockedDoctorAndMonth.DoctorId, lockedDoctorAndMonth.YearMonth }
|
||
join trialCost in _trialRevenuePriceRepository.AsQueryable() on workLoad.TrialId equals trialCost.TrialId into c
|
||
from trialCost in c.DefaultIfEmpty()
|
||
|
||
select new
|
||
{
|
||
DoctorId = workLoad.DoctorId,
|
||
Downtime = workLoad.Downtime * trialCost.Downtime,
|
||
Training = workLoad.Training * trialCost.Training,
|
||
Timepoint = workLoad.Timepoint * trialCost.Timepoint,
|
||
TimepointIn24H = workLoad.TimepointIn24H * trialCost.TimepointIn24H,
|
||
TimepointIn48H = workLoad.TimepointIn48H * trialCost.TimepointIn48H,
|
||
Global = workLoad.Global * trialCost.Global,
|
||
Adjudication = workLoad.Adjudication * trialCost.Adjudication,
|
||
AdjudicationIn24H = workLoad.AdjudicationIn24H * trialCost.AdjudicationIn24H,
|
||
AdjudicationIn48H = workLoad.AdjudicationIn48H * trialCost.AdjudicationIn48H
|
||
|
||
|
||
};
|
||
|
||
//工作量收入按照人分组统计
|
||
var workloadIncomeList = await workloadIncomeQuery.GroupBy(t => t.DoctorId).Select(gWorkLoad => new
|
||
{
|
||
|
||
DoctorId = gWorkLoad.Key,
|
||
//TrialId = Guid.Empty,
|
||
Downtime = gWorkLoad.Sum(t => t.Downtime),
|
||
Training = gWorkLoad.Sum(t => t.Training),
|
||
Timepoint = gWorkLoad.Sum(t => t.Timepoint),
|
||
TimepointIn24H = gWorkLoad.Sum(t => t.TimepointIn24H),
|
||
TimepointIn48H = gWorkLoad.Sum(t => t.TimepointIn48H),
|
||
Global = gWorkLoad.Sum(t => t.Global),
|
||
Adjudication = gWorkLoad.Sum(t => t.Adjudication),
|
||
AdjudicationIn24H = gWorkLoad.Sum(t => t.AdjudicationIn24H),
|
||
AdjudicationIn48H = gWorkLoad.Sum(t => t.AdjudicationIn48H),
|
||
}).ToListAsync();
|
||
var workloadPayList = payQuery.ToList();
|
||
//var workloadIncomeList = workloadIncomeQuery.ToList();
|
||
|
||
var returnList = new List<ReviewerAnalysisDTO>();
|
||
|
||
#region 处理找到缺失的项目
|
||
|
||
//有项目价格的trial Id 集合
|
||
var hasIncomePriceTrialIds = await _trialRevenuePriceRepository.Select(t => t.TrialId).ToListAsync();
|
||
|
||
workloadLambda = workloadLambda.And(t => !hasIncomePriceTrialIds.Contains(t.TrialId));
|
||
var doctorMissingTrialCodesQuery = (from workLoad in _workloadRepository.Where(workloadLambda)
|
||
join trial in _trialRepository.AsQueryable() on workLoad.TrialId equals trial.Id
|
||
select new
|
||
{
|
||
DoctorId = workLoad.DoctorId,
|
||
TrialCode = trial.TrialCode
|
||
}).Distinct();
|
||
|
||
var doctorMissingTrialCodes = ((await doctorMissingTrialCodesQuery.ToListAsync()).GroupBy(t => t.DoctorId).Select(g => new
|
||
{
|
||
DoctorId = g.Key,
|
||
TrialCodes = g.Select(u => u.TrialCode).ToList()
|
||
})).ToList();
|
||
|
||
|
||
#endregion
|
||
|
||
workloadPayList.ForEach(pay =>
|
||
{
|
||
var doctor = workloadIncomeList.FirstOrDefault(t => t.DoctorId == pay.ReviewerId);
|
||
|
||
var doctorMissingCode = doctorMissingTrialCodes.FirstOrDefault(t => t.DoctorId == pay.ReviewerId);
|
||
|
||
returnList.Add(new ReviewerAnalysisDTO()
|
||
{
|
||
ReviewerId = pay.ReviewerId,
|
||
ChineseName = pay.ChineseName,
|
||
FirstName = pay.FirstName,
|
||
LastName = pay.LastName,
|
||
ReviewerCode = pay.ReviewerCode,
|
||
PaymentUSD = pay.PaymentUSD + pay.AdjustmentUSD,
|
||
|
||
//付费表的医生数量肯定事全的 工作量的不一定全 (只有调整)
|
||
RevenusUSD = doctor != null
|
||
? doctor.Adjudication + doctor.AdjudicationIn24H + doctor.AdjudicationIn48H + doctor.Global +
|
||
doctor.Downtime + doctor.Training +
|
||
doctor.Timepoint + doctor.TimepointIn24H + doctor.TimepointIn48H
|
||
: 0,
|
||
MissingTrialCodes = doctorMissingCode != null ? doctorMissingCode.TrialCodes : new List<string>()
|
||
});
|
||
});
|
||
return returnList.OrderBy(t => t.ReviewerCode).ToList();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取劳务费用列表
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<List<LaborPayment>> GetLaborPaymentList(List<Guid> paymentIds)
|
||
{
|
||
var query = from payment in _paymentRepository.Where(t => paymentIds.Contains(t.Id))
|
||
join reviewer in _doctorRepository.AsQueryable() on payment.DoctorId equals reviewer.Id
|
||
join payInfo in _doctorPayInfoRepository.AsQueryable() on payment.DoctorId equals payInfo.DoctorId
|
||
select new LaborPayment()
|
||
{
|
||
|
||
ChineseName = reviewer.ChineseName,
|
||
FirstName = reviewer.FirstName,
|
||
LastName = reviewer.LastName,
|
||
ResidentId = payInfo.IDCard,
|
||
PaymentCNY = payment.PaymentCNY + payment.AdjustmentCNY,
|
||
YearMonth = payment.YearMonth,
|
||
Phone = reviewer.Phone,
|
||
AccountNumber = payInfo.BankCardNumber,
|
||
Bank = payInfo.BankName
|
||
|
||
//TaxCNY = payment.TaxCNY,
|
||
//ActuallyPaidCNY = payment.ActuallyPaidCNY,
|
||
//BankTransferCNY = payment.BankTransferCNY,
|
||
};
|
||
var result = await query.ToListAsync();
|
||
|
||
result.ForEach(t =>
|
||
{
|
||
t.TaxCNY =GetTax2(t.PaymentCNY);
|
||
|
||
t.ActuallyPaidCNY = t.PaymentCNY - t.TaxCNY;
|
||
t.BankTransferCNY = t.PaymentCNY - t.TaxCNY;
|
||
});
|
||
|
||
return result;
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 锁定医生费用,锁定后,无法变更该医生对应月份的费用和工作量[New]
|
||
/// </summary>
|
||
[HttpPost]
|
||
public async Task<IResponseOutput> LockMonthlyPayment(LockPaymentDTO param)
|
||
{
|
||
var reviewerIds = param.ReviewerIdList;
|
||
var yearMonth = param.Month.ToString("yyyy-MM");
|
||
var isLock = param.IsLock;
|
||
|
||
|
||
var paymentLockSuccess = await _paymentRepository.BatchUpdateAsync(u => reviewerIds.Contains(u.DoctorId) && u.YearMonth == yearMonth, t => new Payment
|
||
{
|
||
IsLock = isLock
|
||
});
|
||
|
||
var adjustmentLockSuccess = await _payAdjustmentRepository.BatchUpdateAsync(
|
||
t => t.YearMonth == yearMonth && reviewerIds.Contains(t.ReviewerId), u =>
|
||
new PaymentAdjustment()
|
||
{
|
||
IsLock = true
|
||
});
|
||
await _doctorWorkloadRepository.BatchUpdateAsync(u => reviewerIds.Contains(u.DoctorId) && u.YearMonth == yearMonth,
|
||
t => new Workload { IsLock = true });
|
||
|
||
return ResponseOutput.Result(paymentLockSuccess || adjustmentLockSuccess);
|
||
}
|
||
|
||
[NonDynamicMethod]
|
||
private static decimal GetTax2(decimal paymentCNY)
|
||
{
|
||
if (paymentCNY >= 0 && paymentCNY <= 800)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
var calculateTaxPart = paymentCNY <= 4000 ? paymentCNY - 800 : paymentCNY * (1 - 0.2m);
|
||
|
||
|
||
if (calculateTaxPart <= 20000)
|
||
{
|
||
return calculateTaxPart * 0.2m;
|
||
}
|
||
|
||
else if (calculateTaxPart > 20000 && calculateTaxPart <= 50000)
|
||
{
|
||
return calculateTaxPart * 0.3m - 2000;
|
||
}
|
||
|
||
else
|
||
{
|
||
return calculateTaxPart * 0.4m - 7000;
|
||
}
|
||
|
||
|
||
}
|
||
}
|
||
} |