This commit is contained in:
fuenmao
2025-12-05 11:46:47 +08:00
parent e0ae9bdfc5
commit f96ce8fb07
7 changed files with 147 additions and 8 deletions
@@ -187,7 +187,7 @@ public class MedicinalService : DbRepository<Medicinal>, IMedicinalService
decimal unitPrice = 0m;
if (input.AddWeight > 0)
{
unitPrice = Decimal.Round(input.TotalPrice / input.AddWeight, 2, MidpointRounding.AwayFromZero);
unitPrice = Decimal.Round(input.TotalPrice / input.AddWeight, 5, MidpointRounding.AwayFromZero);
}
// 添加记录
await Context.Insertable(new MedicinalAddLog
@@ -239,7 +239,7 @@ public class MedicinalService : DbRepository<Medicinal>, IMedicinalService
// 更新记录
log.AddWeight = input.AddWeight;
log.TotalPrice = input.TotalPrice;
log.UnitPrice = Decimal.Round(input.TotalPrice / input.AddWeight, 2, MidpointRounding.AwayFromZero);
log.UnitPrice = Decimal.Round(input.TotalPrice / input.AddWeight, 5, MidpointRounding.AwayFromZero);
await Context.Updateable(log).ExecuteCommandAsync();
// 更新药材库存
@@ -26,6 +26,12 @@ namespace SimpleAdmin.Application.Services.Prescription
/// <returns></returns>
Task<SqlSugarPagedList<PrescriptionDto>> GetPrescriptionList(PrescriptionQueryInput input);
/// <summary>
/// 获取所有处方的成本
/// </summary>
/// <returns></returns>
Task<decimal> GetAllPrescriptionTotalCost();
/// <summary>
/// 获取处方详情
/// </summary>
@@ -305,7 +305,8 @@ public class PrescriptionService : DbRepository<Prescription>, IPrescriptionServ
}
}
//var all= prescriptionPage.List.Sum(a => a.TotalMedicineCost);
//var cc = await GetAllPrescriptionTotalCost();
return prescriptionPage;
}
catch (Exception ex)
@@ -314,6 +315,111 @@ public class PrescriptionService : DbRepository<Prescription>, IPrescriptionServ
throw;
}
}
/// <summary>
/// 获取所有处方的总药材成本
/// </summary>
/// <returns></returns>
public async Task<decimal> GetAllPrescriptionTotalCost()
{
// 1) 获取所有处方的 ID(按创建时间升序),并明确类型为 long
var allPrescriptionIds = await Context.Queryable<Prescription>()
.OrderBy(p => p.CreateTime)
.Select(p => p.Id) // 确保这里的 Id 类型是 long 或 long?
.ToListAsync();
if (!allPrescriptionIds.Any())
return 0m;
// 把 id 列表规范为 long 列表(处理可能的 nullable)
var allIdsLong = allPrescriptionIds.Select(id => Convert.ToInt64(id)).ToList();
// 2) 获取所有处方的药材使用明细
var allPrescriptionHerbList = await Context.Queryable<PrescriptionHerb>()
.Where(ph => allIdsLong.Contains(Convert.ToInt64(ph.PrescriptionId)))
.ToListAsync();
var allUsageGroups = allPrescriptionHerbList
.GroupBy(h => new { PrescriptionId = Convert.ToInt64(h.PrescriptionId), h.MedicinalId })
.Select(g => new
{
PrescriptionId = g.Key.PrescriptionId,
g.Key.MedicinalId,
TotalUsedWeight = g.Sum(h => h.AmountG)
})
.ToList();
// 3) 获取所有药材的 FIFO 入库记录
var allMedicinalIds = allUsageGroups.Select(u => u.MedicinalId).Distinct().ToList();
var fifoData = await GetMedicinalFifoData(allMedicinalIds);
// 4) 按处方构建使用分组(key 为 long)
var groupedByPrescriptionAll = allUsageGroups
.GroupBy(u => u.PrescriptionId)
.ToDictionary(g => g.Key, g => g.ToList());
// 5) FIFO 偏移量
var fifoOffsets = new Dictionary<long, decimal>();
decimal totalSum = 0m;
// 6) 获取每张处方的人员类型(IsRelative: bool),并把 key 明确为 long,避免类型不匹配
var personTmp = await Context.Queryable<Prescription>()
.LeftJoin<Person>((p, pe) => p.PersonId == pe.Id)
.Where(p => allIdsLong.Contains(Convert.ToInt64(p.Id)))
.Select((p, pe) => new
{
Id = p.Id,
IsRelative = pe.EmployeeId != null
})
.ToListAsync();
// 明确转换 key 为 long(处理 nullable)
var personInfoDict = personTmp
.ToDictionary(x => Convert.ToInt64(x.Id), x => x.IsRelative);
// 7) FIFO 成本计算(按时间顺序已由 allIdsLong 保持)
foreach (var pidObj in allIdsLong)
{
long pid = pidObj; // 明确 pid 是 long
decimal presCost = 0m;
if (groupedByPrescriptionAll.TryGetValue(pid, out var usages))
{
foreach (var usage in usages)
{
var cost = CalculateHerbCostByFifoWithOffset(
fifoData,
fifoOffsets,
usage.MedicinalId,
usage.TotalUsedWeight
);
presCost += cost;
}
}
// 处方级别保留 4 位小数
presCost = Math.Round(presCost, 4, MidpointRounding.AwayFromZero);
// 家属加价 10%(若字典缺失,默认不是家属)
var isRelative = personInfoDict.TryGetValue(pid, out var rel) && rel;
if (isRelative)
{
presCost = Math.Round(presCost * 1.1m, 2, MidpointRounding.AwayFromZero);
}
else
{
presCost = Math.Round(presCost, 2, MidpointRounding.AwayFromZero);
}
totalSum += presCost;
}
return totalSum;
}
/// <summary>
@@ -181,6 +181,12 @@
<param name="input">筛选条件</param>
<returns></returns>
</member>
<member name="M:SimpleAdmin.Application.Services.Prescription.IPrescriptionService.GetAllPrescriptionTotalCost">
<summary>
获取所有处方的成本
</summary>
<returns></returns>
</member>
<member name="M:SimpleAdmin.Application.Services.Prescription.IPrescriptionService.GetPrescriptionDetail(System.Int64)">
<summary>
获取处方详情
@@ -794,14 +800,20 @@
</summary>
<param name="medicinalIds">需要计算的药材ID列表</param>
</member>
<member name="M:PrescriptionService.GetAllPrescriptionTotalCost">
<summary>
获取所有处方的总药材成本
</summary>
<returns></returns>
</member>
<member name="M:PrescriptionService.GetMedicinalFifoData(System.Collections.Generic.List{System.Int64})">
<summary>
获取药材FIFO计算所需的基础数据(入库记录)
</summary>
</member>
<member name="M:PrescriptionService.CalculateHerbCostByFifo(System.Collections.Generic.Dictionary{System.Int64,System.Collections.Generic.List{SimpleAdmin.Application.Services.Prescription.Dto.MedicinalFifoRecord}},System.Int64,System.Decimal)">
<member name="M:PrescriptionService.CalculateHerbCostByFifoWithOffset(System.Collections.Generic.Dictionary{System.Int64,System.Collections.Generic.List{SimpleAdmin.Application.Services.Prescription.Dto.MedicinalFifoRecord}},System.Collections.Generic.Dictionary{System.Int64,System.Decimal},System.Int64,System.Decimal)">
<summary>
按FIFO规则计算单种药材的使用成本
按FIFO规则计算单种药材的使用成本(累计消耗)
</summary>
</member>
<member name="M:PrescriptionService.GetPrescriptionDetail(System.Int64)">