diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs index 9505c65..652453e 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/BillingItemDetailListOutput.cs @@ -78,16 +78,26 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb public string storeName { get; set; } /// - /// 合作机构 + /// 合作机构ID /// public string hgjg { get; set; } /// - /// 付款医院 + /// 合作机构名称 + /// + public string hgjgName { get; set; } + + /// + /// 付款医院ID /// public string fkyy { get; set; } /// + /// 付款医院名称 + /// + public string fkyyName { get; set; } + + /// /// 付款方式 /// public string paymentMethod { get; set; } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbUpdateAmountInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbUpdateAmountInput.cs index 93ea226..42f28b9 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbUpdateAmountInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqKdKdjlb/LqKdKdjlbUpdateAmountInput.cs @@ -78,5 +78,10 @@ namespace NCC.Extend.Entitys.Dto.LqKdKdjlb /// [Range(0, double.MaxValue, ErrorMessage = "实付金额必须大于等于0")] public decimal ActualPrice { get; set; } + + /// + /// 备注 + /// + public string Remark { get; set; } } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs index 10c03c7..57e1fc2 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListOutput.cs @@ -11,17 +11,17 @@ namespace NCC.Extend.Entitys.Dto.LqReimbursementApplication /// 申请编号 /// public string id { get; set; } - + /// /// 申请人编号 /// public string applicationUserId { get; set; } - + /// /// 申请人姓名 /// public string applicationUserName { get; set; } - + /// /// 申请门店 /// @@ -31,32 +31,32 @@ namespace NCC.Extend.Entitys.Dto.LqReimbursementApplication /// 申请门店名称 /// public string applicationStoreName { get; set; } - + /// /// 申请时间 /// public DateTime? applicationTime { get; set; } - + /// /// 总金额 /// public string amount { get; set; } - + /// /// 审批人 /// public string approveUser { get; set; } - + /// /// 审批结果 /// public string approveStatus { get; set; } - + /// /// 审批时间 /// public DateTime? approveTime { get; set; } - + /// /// 关联购买编号 /// @@ -76,6 +76,11 @@ namespace NCC.Extend.Entitys.Dto.LqReimbursementApplication /// 节点总数 /// public int? nodeCount { get; set; } - + + /// + /// 完成时间(最后一个审批人通过的时间) + /// + public DateTime? completionTime { get; set; } + } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListQueryInput.cs b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListQueryInput.cs index a668a9f..100c629 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListQueryInput.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend.Entitys/Dto/LqReimbursementApplicationListQueryInput.cs @@ -23,51 +23,56 @@ namespace NCC.Extend.Entitys.Dto.LqReimbursementApplication /// 申请编号 /// public string id { get; set; } - + /// /// 申请人编号 /// public string applicationUserId { get; set; } - + /// /// 申请人姓名 /// public string applicationUserName { get; set; } - + /// /// 申请门店 /// public string applicationStoreId { get; set; } - + /// /// 申请时间 /// public string applicationTime { get; set; } - + /// /// 总金额 /// public string amount { get; set; } - + /// /// 审批人 /// public string approveUser { get; set; } - + /// /// 审批结果 /// public string approveStatus { get; set; } - + /// /// 审批时间 /// public string approveTime { get; set; } - + /// /// 关联购买编号 /// public string purchaseRecordsId { get; set; } - + + /// + /// 完成时间(最后一个审批人通过的时间) + /// + public string completionTime { get; set; } + } } diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs index 0d5d1e3..dcd1681 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqInventoryUsageService.cs @@ -1655,22 +1655,22 @@ namespace NCC.Extend // 查询这些批次的使用记录,关联产品表获取仓库信息,计算总金额 var usageRecordsQuery = _db.Queryable( - (usage, product) => usage.ProductId == product.Id) - .Where((usage, product) => batchIds.Contains(usage.UsageBatchId)) - .Where((usage, product) => usage.IsEffective == StatusEnum.有效.GetHashCode()); + (u, product) => u.ProductId == product.Id) + .Where((u, product) => batchIds.Contains(u.UsageBatchId)) + .Where((u, product) => u.IsEffective == StatusEnum.有效.GetHashCode()); // 如果指定了仓库筛选,添加仓库条件 if (!string.IsNullOrWhiteSpace(input.Warehouse)) { - usageRecordsQuery = usageRecordsQuery.Where((usage, product) => product.Warehouse == input.Warehouse); + usageRecordsQuery = usageRecordsQuery.Where((u, product) => product.Warehouse == input.Warehouse); } var usageRecords = await usageRecordsQuery - .Select((usage, product) => new + .Select((u, product) => new { - usage.UsageBatchId, - usage.StoreId, - usage.TotalAmount, + u.UsageBatchId, + u.StoreId, + u.TotalAmount, product.Warehouse }) .ToListAsync(); diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs index 87aca0b..e1021ed 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqKdKdjlbService.cs @@ -2303,7 +2303,7 @@ namespace NCC.Extend.LqKdKdjlb throw NCCException.Oh("更新开单记录金额失败"); } - // 更新品项明细金额 + // 更新品项明细金额和备注 if (input.ItemDetails != null && input.ItemDetails.Any()) { foreach (var itemDetail in input.ItemDetails) @@ -2312,7 +2312,8 @@ namespace NCC.Extend.LqKdKdjlb { Pxjg = itemDetail.Pxjg, TotalPrice = itemDetail.TotalPrice, - ActualPrice = itemDetail.ActualPrice + ActualPrice = itemDetail.ActualPrice, + Remark = itemDetail.Remark }).Where(w => w.Id == itemDetail.ItemDetailId && w.Glkdbh == input.BillingId).ExecuteCommandAsync(); if (itemUpdateResult <= 0) @@ -3818,6 +3819,20 @@ namespace NCC.Extend.LqKdKdjlb storeDict = stores.ToDictionary(x => x.Id, x => x.Dm ?? ""); } + // 批量查询合作机构和医院名称 + var hgjgIds = billingExtraInfoDict.Values.Where(x => !string.IsNullOrEmpty(x.Hgjg)).Select(x => x.Hgjg).Distinct().ToList(); + var fkyyIds = billingExtraInfoDict.Values.Where(x => !string.IsNullOrEmpty(x.Fkyy)).Select(x => x.Fkyy).Distinct().ToList(); + var hzfIds = hgjgIds.Union(fkyyIds).Distinct().ToList(); + var hzfDict = new Dictionary(); + if (hzfIds.Any()) + { + var hzfList = await _db.Queryable() + .Where(x => hzfIds.Contains(x.Id)) + .Select(x => new { x.Id, x.Hzmc }) + .ToListAsync(); + hzfDict = hzfList.ToDictionary(x => x.Id, x => x.Hzmc ?? ""); + } + // 5. 组装返回数据 var resultList = pagedData.list.Select(pxmx => new BillingItemDetailListOutput { @@ -3836,7 +3851,9 @@ namespace NCC.Extend.LqKdKdjlb storeId = pxmx.Glkdbh != null && billingStoreDict.ContainsKey(pxmx.Glkdbh) ? billingStoreDict[pxmx.Glkdbh] : "", storeName = pxmx.Glkdbh != null && billingStoreDict.ContainsKey(pxmx.Glkdbh) && !string.IsNullOrEmpty(billingStoreDict[pxmx.Glkdbh]) && storeDict.ContainsKey(billingStoreDict[pxmx.Glkdbh]) ? storeDict[billingStoreDict[pxmx.Glkdbh]] : "", hgjg = pxmx.Glkdbh != null && billingExtraInfoDict.ContainsKey(pxmx.Glkdbh) ? billingExtraInfoDict[pxmx.Glkdbh].Hgjg : "", + hgjgName = pxmx.Glkdbh != null && billingExtraInfoDict.ContainsKey(pxmx.Glkdbh) && !string.IsNullOrEmpty(billingExtraInfoDict[pxmx.Glkdbh].Hgjg) && hzfDict.ContainsKey(billingExtraInfoDict[pxmx.Glkdbh].Hgjg) ? hzfDict[billingExtraInfoDict[pxmx.Glkdbh].Hgjg] : "", fkyy = pxmx.Glkdbh != null && billingExtraInfoDict.ContainsKey(pxmx.Glkdbh) ? billingExtraInfoDict[pxmx.Glkdbh].Fkyy : "", + fkyyName = pxmx.Glkdbh != null && billingExtraInfoDict.ContainsKey(pxmx.Glkdbh) && !string.IsNullOrEmpty(billingExtraInfoDict[pxmx.Glkdbh].Fkyy) && hzfDict.ContainsKey(billingExtraInfoDict[pxmx.Glkdbh].Fkyy) ? hzfDict[billingExtraInfoDict[pxmx.Glkdbh].Fkyy] : "", paymentMethod = pxmx.Glkdbh != null && billingExtraInfoDict.ContainsKey(pxmx.Glkdbh) ? billingExtraInfoDict[pxmx.Glkdbh].Fkfs : "" }).ToList(); diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs index 44858f6..3f91552 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqReimbursementApplicationService.cs @@ -188,6 +188,9 @@ namespace NCC.Extend.LqReimbursementApplication List queryApproveTime = input.approveTime != null ? input.approveTime.Split(',').ToObeject>() : null; DateTime? startApproveTime = queryApproveTime != null ? Ext.GetDateTime(queryApproveTime.First()) : null; DateTime? endApproveTime = queryApproveTime != null ? Ext.GetDateTime(queryApproveTime.Last()) : null; + List queryCompletionTime = input.completionTime != null ? input.completionTime.Split(',').ToObeject>() : null; + DateTime? startCompletionTime = queryCompletionTime != null ? Ext.GetDateTime(queryCompletionTime.First()) : null; + DateTime? endCompletionTime = queryCompletionTime != null ? Ext.GetDateTime(queryCompletionTime.Last()) : null; var query = _db.Queryable() .WhereIF(!string.IsNullOrEmpty(input.id), p => p.Id.Contains(input.id)) .WhereIF(!string.IsNullOrEmpty(input.applicationUserId), p => p.ApplicationUserId.Contains(input.applicationUserId)) @@ -269,6 +272,31 @@ namespace NCC.Extend.LqReimbursementApplication .GroupBy(x => (string)x.applicationId) .ToDictionary(g => g.Key, g => string.Join(", ", g.Select(x => (string)x.approverName))); + // 如果提供了完成时间筛选,需要先查询完成时间,然后过滤 + if (queryCompletionTime != null && applicationIds.Any()) + { + var completionTimeRecords = await _db.Queryable() + .Where(x => applicationIds.Contains(x.ApplicationId) && x.ApprovalResult == "通过") + .GroupBy(x => x.ApplicationId) + .Select(x => new + { + ApplicationId = x.ApplicationId, + MaxApprovalTime = SqlFunc.AggregateMax(x.ApprovalTime) + }) + .ToListAsync(); + + var filteredApplicationIds = completionTimeRecords + .Where(x => x.MaxApprovalTime.HasValue && + x.MaxApprovalTime.Value >= new DateTime(startCompletionTime.ToDate().Year, startCompletionTime.ToDate().Month, startCompletionTime.ToDate().Day, 0, 0, 0) && + x.MaxApprovalTime.Value <= new DateTime(endCompletionTime.ToDate().Year, endCompletionTime.ToDate().Month, endCompletionTime.ToDate().Day, 23, 59, 59)) + .Select(x => x.ApplicationId) + .ToList(); + + entities = entities.Where(x => filteredApplicationIds.Contains(x.Id)).ToList(); + total = entities.Count; + applicationIds = entities.Select(x => x.Id).ToList(); + } + // 获取门店名称 var storeIds = entities.Where(x => !string.IsNullOrEmpty(x.ApplicationStoreId)).Select(x => x.ApplicationStoreId).Distinct().ToList(); var storeDict = new Dictionary(); @@ -281,6 +309,23 @@ namespace NCC.Extend.LqReimbursementApplication storeDict = stores.ToDictionary(x => x.Id, x => x.Dm ?? ""); } + // 获取完成时间(最后一个审批通过的时间) + var completionTimeDict = new Dictionary(); + if (applicationIds.Any()) + { + // 查询每个申请的最后一次审批通过的记录 + var completionRecords = await _db.Queryable() + .Where(x => applicationIds.Contains(x.ApplicationId) && x.ApprovalResult == "通过") + .GroupBy(x => x.ApplicationId) + .Select(x => new + { + ApplicationId = x.ApplicationId, + MaxApprovalTime = SqlFunc.AggregateMax(x.ApprovalTime) + }) + .ToListAsync(); + completionTimeDict = completionRecords.ToDictionary(x => x.ApplicationId, x => x.MaxApprovalTime); + } + // 组装返回数据 var result = entities.Select(item => new LqReimbursementApplicationListOutput { @@ -299,7 +344,8 @@ namespace NCC.Extend.LqReimbursementApplication purchaseRecordsId = item.PurchaseRecordsId, currentApprovers = approverDict.ContainsKey(item.Id) ? approverDict[item.Id] : null, currentNodeOrder = item.CurrentNodeOrder, - nodeCount = item.NodeCount + nodeCount = item.NodeCount, + completionTime = completionTimeDict.ContainsKey(item.Id) ? completionTimeDict[item.Id] : null }).ToList(); return PageResult.SqlSugarPageResult( @@ -1515,8 +1561,8 @@ namespace NCC.Extend.LqReimbursementApplication // 查询本月已审核通过的报销申请 var applications = await _db.Queryable() .Where(x => (x.ApprovalStatus ?? x.ApproveStatus) == "已通过") - .Where(x => x.ApplicationTime.HasValue && - x.ApplicationTime.Value.Year == queryYear && + .Where(x => x.ApplicationTime.HasValue && + x.ApplicationTime.Value.Year == queryYear && x.ApplicationTime.Value.Month == int.Parse(queryMonth)) .ToListAsync(); @@ -1552,7 +1598,7 @@ namespace NCC.Extend.LqReimbursementApplication foreach (var app in applications) { var appPurchaseRecords = purchaseRecords.Where(x => x.ApplicationId == app.Id).ToList(); - + if (appPurchaseRecords.Any()) { // 每个购买记录作为一行 diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqStoreExpenseService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqStoreExpenseService.cs index 29892be..0f99860 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqStoreExpenseService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqStoreExpenseService.cs @@ -461,32 +461,46 @@ namespace NCC.Extend.LqStoreExpense try { var row = dataTable.Rows[i]; - var storeId = row[0]?.ToString()?.Trim(); - var storeName = row[1]?.ToString()?.Trim(); - var expenseCategoryId = row[2]?.ToString()?.Trim(); - var expenseCategoryName = row[3]?.ToString()?.Trim(); - var expenseDateText = row[4]?.ToString()?.Trim(); - var unitPriceText = row[5]?.ToString()?.Trim(); - var quantityText = row[6]?.ToString()?.Trim(); - var amountText = row[7]?.ToString()?.Trim(); - var memo = row[8]?.ToString()?.Trim(); - var relatedReimbursementId = row[9]?.ToString()?.Trim(); - var relatedPurchaseRecordId = row[10]?.ToString()?.Trim(); + var storeName = row[0]?.ToString()?.Trim(); // 第0列:门店名称 + var expenseCategoryId = row[1]?.ToString()?.Trim(); // 第1列:支出分类ID(原第2列) + var expenseCategoryName = row[2]?.ToString()?.Trim(); // 第2列:支出分类名称(原第3列) + var expenseDateText = row[3]?.ToString()?.Trim(); // 第3列:支出日期(原第4列) + var unitPriceText = row[4]?.ToString()?.Trim(); // 第4列:单价(原第5列) + var quantityText = row[5]?.ToString()?.Trim(); // 第5列:数量(原第6列) + var amountText = row[6]?.ToString()?.Trim(); // 第6列:金额(原第7列) + var memo = row[7]?.ToString()?.Trim(); // 第7列:备注说明(原第8列) + var relatedReimbursementId = row[8]?.ToString()?.Trim(); // 第8列:关联报销申请ID(原第9列) + var relatedPurchaseRecordId = row[9]?.ToString()?.Trim(); // 第9列:关联购买记录ID(原第10列) // 跳过空行 - if (string.IsNullOrEmpty(storeId) && string.IsNullOrEmpty(storeName)) + if (string.IsNullOrEmpty(storeName)) { continue; } - // 验证必填字段 - if (string.IsNullOrEmpty(storeId)) + // 验证必填字段:门店名称 + if (string.IsNullOrEmpty(storeName)) { - failMessages.Add($"第{i + 1}行:门店ID不能为空"); + failMessages.Add($"第{i + 1}行:门店名称不能为空"); failCount++; continue; } + // 通过门店名称匹配门店ID + var store = await _db.Queryable() + .Where(x => x.Dm == storeName) + .Select(x => new { x.Id, x.Dm }) + .FirstAsync(); + + if (store == null) + { + failMessages.Add($"第{i + 1}行:未找到名称为【{storeName}】的门店"); + failCount++; + continue; + } + + var storeId = store.Id; + if (string.IsNullOrEmpty(expenseDateText) || !DateTime.TryParse(expenseDateText, out DateTime expenseDate)) { failMessages.Add($"第{i + 1}行:支出日期格式错误(应为日期格式,如:2025-01-15)"); @@ -514,15 +528,8 @@ namespace NCC.Extend.LqStoreExpense quantity = qty; } - // 如果未提供门店名称,根据门店ID查询 - if (string.IsNullOrEmpty(storeName)) - { - var store = await _db.Queryable() - .Where(x => x.Id == storeId) - .Select(x => x.Dm) - .FirstAsync(); - storeName = store ?? ""; - } + // 门店名称已从查询中获取 + storeName = store.Dm ?? ""; // 创建记录 var entity = new LqStoreExpenseEntity @@ -588,3 +595,4 @@ namespace NCC.Extend.LqStoreExpense } } + diff --git a/netcore/src/Modularity/Extend/NCC.Extend/LqStoreManagerSalaryService.cs b/netcore/src/Modularity/Extend/NCC.Extend/LqStoreManagerSalaryService.cs index 5763631..75708d2 100644 --- a/netcore/src/Modularity/Extend/NCC.Extend/LqStoreManagerSalaryService.cs +++ b/netcore/src/Modularity/Extend/NCC.Extend/LqStoreManagerSalaryService.cs @@ -597,14 +597,31 @@ namespace NCC.Extend } else { - // 老店:不区分门店分类和门店类型,使用统一比例 - if (performanceReached) + // 老店:根据门店分类和业绩是否达标确定提成比例 + int? storeCategory = salary.StoreCategory; + + if (!storeCategory.HasValue) { - commissionRate = 0.04m; // 4%(业绩达标) + throw new Exception($"老店【{salary.StoreName}】的门店分类未设置,无法计算提成"); } - else + + // 根据门店分类和业绩是否达标确定提成比例 + // A类门店:未达标3%,达标3.5% + // B类门店:未达标3.5%,达标4% + // C类门店:未达标4%,达标4.5% + switch (storeCategory.Value) { - commissionRate = 0.035m; // 3.5%(业绩未达标) + case (int)StoreCategoryEnum.A类门店: // A类门店 + commissionRate = performanceReached ? 0.035m : 0.03m; // 达标3.5%,未达标3% + break; + case (int)StoreCategoryEnum.B类门店: // B类门店 + commissionRate = performanceReached ? 0.04m : 0.035m; // 达标4%,未达标3.5% + break; + case (int)StoreCategoryEnum.C类门店: // C类门店 + commissionRate = performanceReached ? 0.045m : 0.04m; // 达标4.5%,未达标4% + break; + default: + throw new Exception($"门店【{salary.StoreName}】的门店分类值无效:{storeCategory.Value},有效值为1(A类)、2(B类)、3(C类)"); } }