Commit 450d4d8bdef369111268bd024377b8f7c5c3bc84
1 parent
7200c7ad
refactor: 废弃 lq_mdxx.kjb,科技部门店改由 lq_md_target 按月份获取
- LqReportService: 门店基础信息/数据分析/对比分析 科技部归属及同组织门店改为 lq_md_target - LqTechGeneralManagerSalaryService: 科技部总经理管理门店改为 lq_md_target 按统计月 - LqShareStatisticsTechDeptService: 科技部股份统计收入成本按 lq_md_target 取科技部门店 - LqZjlMdsmxszService: GetManagedStores 科技一部/二部门店改为 lq_md_target 按当前月 - LqAnnualSummaryService: 移除对 Kjb 的 Select 依赖 - 新增接口测试脚本 test-kjb-removal-apis.sh - 新增 SQL: 根据产品平均单价更新库存领取金额
Showing
7 changed files
with
281 additions
and
50 deletions
netcore/src/Modularity/Extend/NCC.Extend/LqAnnualSummaryService.cs
| ... | ... | @@ -82,7 +82,7 @@ namespace NCC.Extend |
| 82 | 82 | var storeIds = list.list.Select(x => x.StoreId).Distinct().ToList(); |
| 83 | 83 | var stores = await _db.Queryable<LqMdxxEntity>() |
| 84 | 84 | .Where(x => storeIds.Contains(x.Id)) |
| 85 | - .Select(x => new { x.Id, x.Syb, x.Kjb }) | |
| 85 | + .Select(x => new { x.Id, x.Syb }) | |
| 86 | 86 | .ToListAsync(); |
| 87 | 87 | var storeDict = stores.ToDictionary(x => x.Id, x => x); |
| 88 | 88 | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqReportService.cs
| ... | ... | @@ -4653,7 +4653,7 @@ namespace NCC.Extend |
| 4653 | 4653 | |
| 4654 | 4654 | // 从门店目标表获取归属ID |
| 4655 | 4655 | var businessUnitId = target?.BusinessUnit ?? store.Syb; |
| 4656 | - var techDepartmentId = target?.TechDepartment ?? store.Kjb; | |
| 4656 | + var techDepartmentId = target?.TechDepartment; | |
| 4657 | 4657 | var educationDepartmentId = target?.EducationDepartment ?? store.Jyb; |
| 4658 | 4658 | var majorProjectDepartmentId = target?.MajorProjectDepartment ?? store.Dxmb; |
| 4659 | 4659 | |
| ... | ... | @@ -4783,7 +4783,7 @@ namespace NCC.Extend |
| 4783 | 4783 | |
| 4784 | 4784 | // 从门店目标表获取归属ID |
| 4785 | 4785 | var businessUnitId = target?.BusinessUnit ?? store.Syb; |
| 4786 | - var techDepartmentId = target?.TechDepartment ?? store.Kjb; | |
| 4786 | + var techDepartmentId = target?.TechDepartment; | |
| 4787 | 4787 | var educationDepartmentId = target?.EducationDepartment ?? store.Jyb; |
| 4788 | 4788 | var majorProjectDepartmentId = target?.MajorProjectDepartment ?? store.Dxmb; |
| 4789 | 4789 | |
| ... | ... | @@ -5353,11 +5353,13 @@ namespace NCC.Extend |
| 5353 | 5353 | .Select(x => x.Id) |
| 5354 | 5354 | .ToListAsync(); |
| 5355 | 5355 | } |
| 5356 | - else if (!string.IsNullOrWhiteSpace(store.Kjb)) | |
| 5356 | + else if (target != null && !string.IsNullOrWhiteSpace(target.TechDepartment)) | |
| 5357 | 5357 | { |
| 5358 | - sameOrgStoreIds = await _db.Queryable<LqMdxxEntity>() | |
| 5359 | - .Where(x => x.Kjb == store.Kjb && x.Zxzt == "开店" && x.Id != input.StoreId) | |
| 5360 | - .Select(x => x.Id) | |
| 5358 | + // 科技部已废弃 lq_mdxx.kjb,按统计月份从门店目标表取同科技部门店(且开店) | |
| 5359 | + sameOrgStoreIds = await _db.Queryable<LqMdTargetEntity, LqMdxxEntity>((t, m) => t.StoreId == m.Id && m.Zxzt == "开店") | |
| 5360 | + .Where((t, m) => t.Month == statisticsMonth && t.TechDepartment == target.TechDepartment && t.StoreId != input.StoreId) | |
| 5361 | + .Select((t, m) => t.StoreId) | |
| 5362 | + .Distinct() | |
| 5361 | 5363 | .ToListAsync(); |
| 5362 | 5364 | } |
| 5363 | 5365 | |
| ... | ... | @@ -6212,6 +6214,11 @@ namespace NCC.Extend |
| 6212 | 6214 | throw NCCException.Oh("门店不存在"); |
| 6213 | 6215 | } |
| 6214 | 6216 | |
| 6217 | + // 获取当月门店目标(用于同组织门店-科技部从 lq_md_target 取) | |
| 6218 | + var target = await _db.Queryable<LqMdTargetEntity>() | |
| 6219 | + .Where(x => x.StoreId == input.StoreId && x.Month == statisticsMonth) | |
| 6220 | + .FirstAsync(); | |
| 6221 | + | |
| 6215 | 6222 | // 获取业绩排名 |
| 6216 | 6223 | var allStoresPerformance = await _db.Ado.SqlQueryAsync<dynamic>($@" |
| 6217 | 6224 | SELECT |
| ... | ... | @@ -6302,11 +6309,13 @@ namespace NCC.Extend |
| 6302 | 6309 | .Select(x => x.Id) |
| 6303 | 6310 | .ToListAsync(); |
| 6304 | 6311 | } |
| 6305 | - else if (!string.IsNullOrWhiteSpace(store.Kjb)) | |
| 6312 | + else if (target != null && !string.IsNullOrWhiteSpace(target.TechDepartment)) | |
| 6306 | 6313 | { |
| 6307 | - sameOrgStoreIds = await _db.Queryable<LqMdxxEntity>() | |
| 6308 | - .Where(x => x.Kjb == store.Kjb && x.Zxzt == "开店" && x.Id != input.StoreId) | |
| 6309 | - .Select(x => x.Id) | |
| 6314 | + // 科技部已废弃 lq_mdxx.kjb,按统计月份从门店目标表取同科技部门店(且开店) | |
| 6315 | + sameOrgStoreIds = await _db.Queryable<LqMdTargetEntity, LqMdxxEntity>((t, m) => t.StoreId == m.Id && m.Zxzt == "开店") | |
| 6316 | + .Where((t, m) => t.Month == statisticsMonth && t.TechDepartment == target.TechDepartment && t.StoreId != input.StoreId) | |
| 6317 | + .Select((t, m) => t.StoreId) | |
| 6318 | + .Distinct() | |
| 6310 | 6319 | .ToListAsync(); |
| 6311 | 6320 | } |
| 6312 | 6321 | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqShareStatisticsTechDeptService.cs
| ... | ... | @@ -4,6 +4,7 @@ using NCC.Dependency; |
| 4 | 4 | using NCC.DynamicApiController; |
| 5 | 5 | using NCC.Extend.Entitys.Dto.LqShareStatisticsTechDept; |
| 6 | 6 | using NCC.Extend.Entitys.lq_share_statistics_tech_dept; |
| 7 | +using NCC.Extend.Entitys.lq_md_target; | |
| 7 | 8 | using NCC.Extend.Entitys.lq_mdxx; |
| 8 | 9 | using NCC.Extend.Entitys.lq_kd_pxmx; |
| 9 | 10 | using NCC.Extend.Entitys.lq_kd_kdjlb; |
| ... | ... | @@ -88,7 +89,7 @@ namespace NCC.Extend |
| 88 | 89 | }; |
| 89 | 90 | |
| 90 | 91 | // 计算各项数据 |
| 91 | - await CalculateIncome(entity, deptName, startDate, endDate); | |
| 92 | + await CalculateIncome(entity, deptName, startDate, endDate, input.StatisticsMonth); | |
| 92 | 93 | await CalculateCost(entity, deptName, startDate, endDate, input.StatisticsMonth); |
| 93 | 94 | CalculateProfit(entity); |
| 94 | 95 | |
| ... | ... | @@ -175,7 +176,7 @@ namespace NCC.Extend |
| 175 | 176 | /// <summary> |
| 176 | 177 | /// 计算收入部分 |
| 177 | 178 | /// </summary> |
| 178 | - private async Task CalculateIncome(LqShareStatisticsTechDeptEntity entity, string deptName, DateTime startDate, DateTime endDate) | |
| 179 | + private async Task CalculateIncome(LqShareStatisticsTechDeptEntity entity, string deptName, DateTime startDate, DateTime endDate, string statisticsMonth) | |
| 179 | 180 | { |
| 180 | 181 | // 1. 通过组织名称找到组织ID |
| 181 | 182 | var organize = await _db.Queryable<OrganizeEntity>() |
| ... | ... | @@ -188,10 +189,11 @@ namespace NCC.Extend |
| 188 | 189 | return; |
| 189 | 190 | } |
| 190 | 191 | |
| 191 | - // 2. 找到该科技部管辖的所有门店(通过组织ID) | |
| 192 | - var stores = await _db.Queryable<LqMdxxEntity>() | |
| 193 | - .Where(x => x.Kjb == organize.Id) | |
| 194 | - .Select(x => x.Id) | |
| 192 | + // 2. 找到该科技部当月管辖的门店(lq_mdxx.kjb 已废弃,从 lq_md_target 按月份取) | |
| 193 | + var stores = await _db.Queryable<LqMdTargetEntity>() | |
| 194 | + .Where(x => x.Month == statisticsMonth && x.TechDepartment == organize.Id) | |
| 195 | + .Select(x => x.StoreId) | |
| 196 | + .Distinct() | |
| 195 | 197 | .ToListAsync(); |
| 196 | 198 | |
| 197 | 199 | if (stores.Count == 0) |
| ... | ... | @@ -282,10 +284,11 @@ namespace NCC.Extend |
| 282 | 284 | return; |
| 283 | 285 | } |
| 284 | 286 | |
| 285 | - // 2. 找到该科技部管辖的所有门店(通过组织ID) | |
| 286 | - var stores = await _db.Queryable<LqMdxxEntity>() | |
| 287 | - .Where(x => x.Kjb == organize.Id) | |
| 288 | - .Select(x => x.Id) | |
| 287 | + // 2. 找到该科技部当月管辖的门店(lq_mdxx.kjb 已废弃,从 lq_md_target 按月份取) | |
| 288 | + var stores = await _db.Queryable<LqMdTargetEntity>() | |
| 289 | + .Where(x => x.Month == statisticsMonth && x.TechDepartment == organize.Id) | |
| 290 | + .Select(x => x.StoreId) | |
| 291 | + .Distinct() | |
| 289 | 292 | .ToListAsync(); |
| 290 | 293 | |
| 291 | 294 | // 1. 成本-报销:筛选一级分类为"科技部费用"的申请,根据申请门店的归属区分一部/二部 | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqTechGeneralManagerSalaryService.cs
| ... | ... | @@ -15,6 +15,7 @@ using NCC.Extend.Entitys.lq_kd_jksyj; |
| 15 | 15 | using NCC.Extend.Entitys.lq_kd_kdjlb; |
| 16 | 16 | using NCC.Extend.Entitys.lq_kd_pxmx; |
| 17 | 17 | using NCC.Extend.Entitys.lq_md_general_manager_lifeline; |
| 18 | +using NCC.Extend.Entitys.lq_md_target; | |
| 18 | 19 | using NCC.Extend.Entitys.lq_mdxx; |
| 19 | 20 | using NCC.Extend.Entitys.lq_tech_general_manager_salary_statistics; |
| 20 | 21 | using NCC.Extend.Entitys.lq_xmzl; |
| ... | ... | @@ -273,35 +274,30 @@ namespace NCC.Extend |
| 273 | 274 | } |
| 274 | 275 | |
| 275 | 276 | // 1.3 获取科技部总经理归属信息(从lq_md_general_manager_lifeline表) |
| 276 | - // 通过门店的科技部组织ID(kjb字段)找到科技一部或科技二部管理的门店 | |
| 277 | - // 然后在lifeline表中找到这些门店的记录,这些记录对应的总经理就是科技部总经理 | |
| 278 | - var lifelineList = await _db.Queryable<LqMdGeneralManagerLifelineEntity, LqMdxxEntity>( | |
| 279 | - (lifeline, store) => lifeline.StoreId == store.Id) | |
| 280 | - .Where((lifeline, store) => | |
| 281 | - lifeline.Month == monthStr | |
| 282 | - && techOrganizeIds.Contains(store.Kjb)) | |
| 283 | - .Select((lifeline, store) => lifeline) | |
| 277 | + // lq_mdxx.kjb 已废弃,按统计月份从 lq_md_target 取科技一部/二部管理的门店,再关联 lifeline | |
| 278 | + var techManagedStoreIdsForMonth = await _db.Queryable<LqMdTargetEntity>() | |
| 279 | + .Where(x => x.Month == monthStr && techOrganizeIds.Contains(x.TechDepartment)) | |
| 280 | + .Select(x => x.StoreId) | |
| 281 | + .Distinct() | |
| 284 | 282 | .ToListAsync(); |
| 285 | - | |
| 286 | - // 1.4 获取科技一部和科技二部管理的门店(通过门店的kjb字段) | |
| 287 | - var techManagedStoreIds = await _db.Queryable<LqMdxxEntity>() | |
| 288 | - .Where(x => techOrganizeIds.Contains(x.Kjb)) | |
| 289 | - .Select(x => x.Id) | |
| 283 | + var lifelineList = await _db.Queryable<LqMdGeneralManagerLifelineEntity>() | |
| 284 | + .Where(x => x.Month == monthStr && techManagedStoreIdsForMonth.Contains(x.StoreId)) | |
| 290 | 285 | .ToListAsync(); |
| 291 | 286 | |
| 292 | - // 1.5 按科技部总经理ID分组,获取每个科技部总经理管理的门店 | |
| 293 | - // 科技部总经理管理的门店 = 科技一部/科技二部管理的所有门店(通过门店的kjb字段确定) | |
| 287 | + // 1.4 获取科技一部和科技二部当月管理的门店(从 lq_md_target) | |
| 288 | + var techManagedStoreIds = techManagedStoreIdsForMonth; | |
| 289 | + | |
| 290 | + // 1.5 按科技部总经理ID分组,获取每个科技部总经理当月管理的门店(从 lq_md_target) | |
| 294 | 291 | var managerStoreDict = new Dictionary<string, List<string>>(); |
| 295 | 292 | foreach (var managerUser in techGeneralManagerUserList) |
| 296 | 293 | { |
| 297 | 294 | var managerId = managerUser.Id; |
| 298 | 295 | var managerOrganizeId = managerUser.OrganizeId; |
| 299 | 296 | |
| 300 | - // 如果该总经理属于科技一部,则管理所有科技一部的门店 | |
| 301 | - // 如果该总经理属于科技二部,则管理所有科技二部的门店 | |
| 302 | - var managedStores = await _db.Queryable<LqMdxxEntity>() | |
| 303 | - .Where(x => x.Kjb == managerOrganizeId) | |
| 304 | - .Select(x => x.Id) | |
| 297 | + var managedStores = await _db.Queryable<LqMdTargetEntity>() | |
| 298 | + .Where(x => x.Month == monthStr && x.TechDepartment == managerOrganizeId) | |
| 299 | + .Select(x => x.StoreId) | |
| 300 | + .Distinct() | |
| 305 | 301 | .ToListAsync(); |
| 306 | 302 | |
| 307 | 303 | managerStoreDict[managerId] = managedStores; |
| ... | ... | @@ -415,6 +411,15 @@ namespace NCC.Extend |
| 415 | 411 | } |
| 416 | 412 | } |
| 417 | 413 | |
| 414 | + // 批量查询当月门店科技部归属(lq_md_target),避免循环内查询 | |
| 415 | + var storeTechDeptList = await _db.Queryable<LqMdTargetEntity>() | |
| 416 | + .Where(x => x.Month == monthStr && allManagedStoreIds.Contains(x.StoreId)) | |
| 417 | + .Select(x => new { x.StoreId, x.TechDepartment }) | |
| 418 | + .ToListAsync(); | |
| 419 | + var storeTechDeptDict = storeTechDeptList | |
| 420 | + .GroupBy(x => x.StoreId) | |
| 421 | + .ToDictionary(g => g.Key, g => g.First().TechDepartment); | |
| 422 | + | |
| 418 | 423 | // 遍历所有门店,构建门店明细 |
| 419 | 424 | foreach (var storeId in allManagedStoreIds) |
| 420 | 425 | { |
| ... | ... | @@ -429,16 +434,14 @@ namespace NCC.Extend |
| 429 | 434 | _logger.LogInformation($"[科技部总经理工资计算] 门店ID: {storeId}, 开单Cell金额: {storeCellBilling}, 退卡Cell金额: {storeCellRefund}, Cell金额: {storeCellBilling - storeCellRefund}"); |
| 430 | 435 | } |
| 431 | 436 | |
| 432 | - // 获取该门店属于哪些科技部总经理 | |
| 433 | - // 通过门店的kjb字段确定:如果门店的kjb等于科技一部的组织ID,则该门店属于科技一部总经理 | |
| 437 | + // 获取该门店属于哪些科技部总经理(按当月 lq_md_target 的科技部归属) | |
| 434 | 438 | var store = storeDict.ContainsKey(storeId) ? storeDict[storeId] : null; |
| 435 | 439 | var managersOfStore = new List<string>(); |
| 436 | - | |
| 437 | - if (store != null && !string.IsNullOrEmpty(store.Kjb)) | |
| 440 | + var storeTechDept = storeTechDeptDict.ContainsKey(storeId) ? storeTechDeptDict[storeId] : null; | |
| 441 | + if (!string.IsNullOrEmpty(storeTechDept)) | |
| 438 | 442 | { |
| 439 | - // 找到组织ID等于门店kjb的科技部总经理 | |
| 440 | 443 | var managers = techGeneralManagerUserList |
| 441 | - .Where(x => x.OrganizeId == store.Kjb) | |
| 444 | + .Where(x => x.OrganizeId == storeTechDept) | |
| 442 | 445 | .Select(x => x.Id) |
| 443 | 446 | .ToList(); |
| 444 | 447 | managersOfStore.AddRange(managers); | ... | ... |
netcore/src/Modularity/Extend/NCC.Extend/LqZjlMdsmxszService.cs
| ... | ... | @@ -8,6 +8,7 @@ using NCC.Extend.Entitys.Dto.LqZjlMdsmxsz; |
| 8 | 8 | using NCC.Extend.Entitys.Entity.lq_zjl_mdsmxsz; |
| 9 | 9 | using NCC.Extend.Interfaces.LqZjlMdsmxsz; |
| 10 | 10 | using NCC.System.Entitys.Permission; |
| 11 | +using NCC.Extend.Entitys.lq_md_target; | |
| 11 | 12 | using NCC.Extend.Entitys.lq_mdxx; |
| 12 | 13 | using SqlSugar; |
| 13 | 14 | using System; |
| ... | ... | @@ -263,10 +264,38 @@ namespace NCC.Extend |
| 263 | 264 | public async Task<dynamic> GetManagedStores(string userid) |
| 264 | 265 | { |
| 265 | 266 | var userOrganizeId = await _db.Queryable<UserEntity>().Where(x => x.Id == userid && x.DeleteMark == null).Select(x => x.OrganizeId).FirstAsync(); |
| 266 | - // 根据组织权限获取门店 | |
| 267 | - var stores = await _db.Queryable<LqMdxxEntity>() | |
| 268 | - .Where(s => s.Syb == userOrganizeId || s.Jyb == userOrganizeId || s.Kjb == userOrganizeId || s.Dxmb == userOrganizeId) | |
| 267 | + if (string.IsNullOrEmpty(userOrganizeId)) | |
| 268 | + { | |
| 269 | + return new { list = new List<LqMdxxEntity>() }; | |
| 270 | + } | |
| 271 | + | |
| 272 | + // 科技部(科技一部/科技二部)已废弃 lq_mdxx.kjb,按当月 lq_md_target 取管理门店 | |
| 273 | + var techOrganizeIds = await _db.Queryable<OrganizeEntity>() | |
| 274 | + .Where(x => x.FullName != null && (x.FullName.Contains("科技一部") || x.FullName.Contains("科技二部")) && x.DeleteMark == null && x.EnabledMark == 1) | |
| 275 | + .Select(x => x.Id) | |
| 269 | 276 | .ToListAsync(); |
| 277 | + | |
| 278 | + List<LqMdxxEntity> stores; | |
| 279 | + if (techOrganizeIds.Contains(userOrganizeId)) | |
| 280 | + { | |
| 281 | + var monthStr = DateTime.Now.ToString("yyyyMM"); | |
| 282 | + var storeIds = await _db.Queryable<LqMdTargetEntity>() | |
| 283 | + .Where(x => x.Month == monthStr && x.TechDepartment == userOrganizeId) | |
| 284 | + .Select(x => x.StoreId) | |
| 285 | + .Distinct() | |
| 286 | + .ToListAsync(); | |
| 287 | + stores = storeIds.Any() | |
| 288 | + ? await _db.Queryable<LqMdxxEntity>().Where(s => storeIds.Contains(s.Id)).ToListAsync() | |
| 289 | + : new List<LqMdxxEntity>(); | |
| 290 | + } | |
| 291 | + else | |
| 292 | + { | |
| 293 | + // 事业部、教育部、大项目部:按门店表当前归属(不再使用已废弃的 Kjb) | |
| 294 | + stores = await _db.Queryable<LqMdxxEntity>() | |
| 295 | + .Where(s => s.Syb == userOrganizeId || s.Jyb == userOrganizeId || s.Dxmb == userOrganizeId) | |
| 296 | + .ToListAsync(); | |
| 297 | + } | |
| 298 | + | |
| 270 | 299 | return new { list = stores }; |
| 271 | 300 | } |
| 272 | 301 | #endregion | ... | ... |
netcore/test-kjb-removal-apis.sh
0 → 100755
| 1 | +#!/bin/bash | |
| 2 | +# 测试废弃 kjb 后修改的接口是否返回正确 | |
| 3 | +# 使用方式: ./test-kjb-removal-apis.sh [BASE_URL],默认 http://localhost:2011 | |
| 4 | + | |
| 5 | +set -e | |
| 6 | +BASE_URL="${1:-http://localhost:2011}" | |
| 7 | +echo "=== 使用 API 地址: $BASE_URL ===" | |
| 8 | + | |
| 9 | +# 1. 登录获取 token | |
| 10 | +echo "" | |
| 11 | +echo ">>> 1. 登录获取 token..." | |
| 12 | +LOGIN_RESP=$(curl -s -X POST "$BASE_URL/api/oauth/Login" \ | |
| 13 | + -H "Content-Type: application/x-www-form-urlencoded" \ | |
| 14 | + -d "account=admin&password=e10adc3949ba59abbe56e057f20f883e") | |
| 15 | +TOKEN=$(echo "$LOGIN_RESP" | grep -o '"token":"[^"]*"' | sed 's/"token":"//;s/"$//') | |
| 16 | +if [ -z "$TOKEN" ]; then | |
| 17 | + echo "登录失败,响应: $LOGIN_RESP" | |
| 18 | + exit 1 | |
| 19 | +fi | |
| 20 | +echo "登录成功,已获取 token" | |
| 21 | + | |
| 22 | +# 2. LqReport - get-store-base-info(空 storeId 校验 + 可选真实门店校验) | |
| 23 | +echo "" | |
| 24 | +echo ">>> 2. POST /api/Extend/LqReport/get-store-base-info (空 storeId 校验)" | |
| 25 | +RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/api/Extend/LqReport/get-store-base-info" \ | |
| 26 | + -H "Content-Type: application/json" \ | |
| 27 | + -H "Authorization: $TOKEN" \ | |
| 28 | + -d '{"storeId":"","statisticsMonth":"202601"}') | |
| 29 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 30 | +BODY=$(echo "$RESP" | sed '$d') | |
| 31 | +if [ "$HTTP_CODE" = "400" ] || echo "$BODY" | grep -q "门店ID不能为空"; then | |
| 32 | + echo " [预期] 未传 storeId 时返回 400 或提示门店ID不能为空: HTTP $HTTP_CODE" | |
| 33 | +else | |
| 34 | + echo " HTTP $HTTP_CODE (若为200且 body 含 code 非200 也为参数校验行为)" | |
| 35 | + echo "$BODY" | head -c 400 | |
| 36 | + echo "" | |
| 37 | +fi | |
| 38 | +# 使用真实门店ID验证归属来自 lq_md_target(如 绿纤龙湖店) | |
| 39 | +if [ -n "${STORE_ID:-}" ]; then | |
| 40 | + echo ">>> 2b. get-store-base-info (真实 storeId=$STORE_ID)" | |
| 41 | + curl -s -X POST "$BASE_URL/api/Extend/LqReport/get-store-base-info" \ | |
| 42 | + -H "Content-Type: application/json" -H "Authorization: $TOKEN" \ | |
| 43 | + -d "{\"storeId\":\"$STORE_ID\",\"statisticsMonth\":\"202601\"}" | head -c 600 | |
| 44 | + echo "" | |
| 45 | +fi | |
| 46 | + | |
| 47 | +# 3. LqReport get-store-data-analysis(同上,验证接口可调通) | |
| 48 | +echo "" | |
| 49 | +echo ">>> 3. POST /api/Extend/LqReport/get-store-data-analysis" | |
| 50 | +RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/api/Extend/LqReport/get-store-data-analysis" \ | |
| 51 | + -H "Content-Type: application/json" \ | |
| 52 | + -H "Authorization: $TOKEN" \ | |
| 53 | + -d '{"storeId":"","statisticsMonth":"202601"}') | |
| 54 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 55 | +BODY=$(echo "$RESP" | sed '$d') | |
| 56 | +if [ "$HTTP_CODE" = "400" ] || echo "$BODY" | grep -q "门店ID不能为空"; then | |
| 57 | + echo " [预期] 未传 storeId 时返回 400 或提示门店ID不能为空: HTTP $HTTP_CODE" | |
| 58 | +else | |
| 59 | + echo " HTTP $HTTP_CODE" | |
| 60 | + echo "$BODY" | head -c 500 | |
| 61 | + echo "" | |
| 62 | +fi | |
| 63 | + | |
| 64 | +# 4. LqReport get-store-comparison-analysis | |
| 65 | +echo "" | |
| 66 | +echo ">>> 4. POST /api/Extend/LqReport/get-store-comparison-analysis" | |
| 67 | +RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/api/Extend/LqReport/get-store-comparison-analysis" \ | |
| 68 | + -H "Content-Type: application/json" \ | |
| 69 | + -H "Authorization: $TOKEN" \ | |
| 70 | + -d '{"storeId":"","statisticsMonth":"202601"}') | |
| 71 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 72 | +BODY=$(echo "$RESP" | sed '$d') | |
| 73 | +if [ "$HTTP_CODE" = "400" ] || echo "$BODY" | grep -q "门店ID不能为空"; then | |
| 74 | + echo " [预期] 未传 storeId 时返回 400 或提示门店ID不能为空: HTTP $HTTP_CODE" | |
| 75 | +else | |
| 76 | + echo " HTTP $HTTP_CODE" | |
| 77 | + echo "$BODY" | head -c 500 | |
| 78 | + echo "" | |
| 79 | +fi | |
| 80 | + | |
| 81 | +# 5. LqTechGeneralManagerSalary - GET tech-general-manager | |
| 82 | +echo "" | |
| 83 | +echo ">>> 5. GET /api/Extend/LqTechGeneralManagerSalary/tech-general-manager (2026年1月)" | |
| 84 | +RESP=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/api/Extend/LqTechGeneralManagerSalary/tech-general-manager?Year=2026&Month=1¤tPage=1&pageSize=10" \ | |
| 85 | + -H "Authorization: $TOKEN") | |
| 86 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 87 | +BODY=$(echo "$RESP" | sed '$d') | |
| 88 | +echo " HTTP $HTTP_CODE" | |
| 89 | +echo "$BODY" | head -c 800 | |
| 90 | +echo "" | |
| 91 | + | |
| 92 | +# 6. LqTechGeneralManagerSalary - POST calculate/tech-general-manager(仅触发计算,不校验结果) | |
| 93 | +echo "" | |
| 94 | +echo ">>> 6. POST /api/Extend/LqTechGeneralManagerSalary/calculate/tech-general-manager (year=2026, month=1)" | |
| 95 | +RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/api/Extend/LqTechGeneralManagerSalary/calculate/tech-general-manager?year=2026&month=1" \ | |
| 96 | + -H "Authorization: $TOKEN") | |
| 97 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 98 | +BODY=$(echo "$RESP" | sed '$d') | |
| 99 | +echo " HTTP $HTTP_CODE" | |
| 100 | +echo "$BODY" | head -c 400 | |
| 101 | +echo "" | |
| 102 | + | |
| 103 | +# 7. LqShareStatisticsTechDept - generate | |
| 104 | +echo "" | |
| 105 | +echo ">>> 7. POST /api/Extend/LqShareStatisticsTechDept/generate (statisticsMonth=202601)" | |
| 106 | +RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/api/Extend/LqShareStatisticsTechDept/generate" \ | |
| 107 | + -H "Content-Type: application/json" \ | |
| 108 | + -H "Authorization: $TOKEN" \ | |
| 109 | + -d '{"statisticsMonth":"202601"}') | |
| 110 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 111 | +BODY=$(echo "$RESP" | sed '$d') | |
| 112 | +echo " HTTP $HTTP_CODE" | |
| 113 | +echo "$BODY" | |
| 114 | +echo "" | |
| 115 | + | |
| 116 | +# 8. LqZjlMdsmxsz - GET ManagedStores/{userid}(科技部总经理 userid 需从系统获取,这里用占位验证 404/200) | |
| 117 | +echo "" | |
| 118 | +echo ">>> 8. GET /api/Extend/LqZjlMdsmxsz/ManagedStores/{userid} (使用占位 userid 验证路由与逻辑)" | |
| 119 | +RESP=$(curl -s -w "\n%{http_code}" -X GET "$BASE_URL/api/Extend/LqZjlMdsmxsz/ManagedStores/000000000000000001" \ | |
| 120 | + -H "Authorization: $TOKEN") | |
| 121 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 122 | +BODY=$(echo "$RESP" | sed '$d') | |
| 123 | +echo " HTTP $HTTP_CODE" | |
| 124 | +echo "$BODY" | head -c 500 | |
| 125 | +echo "" | |
| 126 | + | |
| 127 | +# 9. LqMdTarget GetManagedStores(未改 kjb 逻辑,但可顺带验证科技部按 lq_md_target 返回) | |
| 128 | +echo "" | |
| 129 | +echo ">>> 9. POST /api/Extend/LqMdTarget/GetManagedStores (科技部+月份 202601,需有效 DepartmentId)" | |
| 130 | +RESP=$(curl -s -w "\n%{http_code}" -X POST "$BASE_URL/api/Extend/LqMdTarget/GetManagedStores" \ | |
| 131 | + -H "Content-Type: application/json" \ | |
| 132 | + -H "Authorization: $TOKEN" \ | |
| 133 | + -d '{"month":"202601","organizationType":"科技部","departmentId":""}') | |
| 134 | +HTTP_CODE=$(echo "$RESP" | tail -n1) | |
| 135 | +BODY=$(echo "$RESP" | sed '$d') | |
| 136 | +echo " HTTP $HTTP_CODE" | |
| 137 | +if echo "$BODY" | grep -q "部门ID不能为空"; then | |
| 138 | + echo " [预期] departmentId 为空时返回错误提示" | |
| 139 | +else | |
| 140 | + echo "$BODY" | head -c 500 | |
| 141 | +fi | |
| 142 | +echo "" | |
| 143 | + | |
| 144 | +echo "=== 接口测试脚本执行完毕 ===" | ... | ... |
sql/根据产品平均单价更新库存领取金额.sql
0 → 100644
| 1 | +-- ============================================================ | |
| 2 | +-- 根据产品 F_AveragePrice 更新库存领取的单价、总价 | |
| 3 | +-- 说明:领取记录在 lq_inventory_usage,单价 F_UnitPrice、总价 F_TotalAmount; | |
| 4 | +-- 单价取产品 F_AveragePrice,若为 0 或 NULL 则取 F_Price;总价 = 单价 × 领取数量。 | |
| 5 | +-- 同时按批次汇总,回写 lq_inventory_usage_application 的 F_TotalAmount。 | |
| 6 | +-- ============================================================ | |
| 7 | + | |
| 8 | +-- 一、预览:将要更新的使用记录条数及金额变化(不修改数据) | |
| 9 | +SELECT | |
| 10 | + u.F_Id AS 使用记录ID, | |
| 11 | + u.F_ProductId AS 产品ID, | |
| 12 | + p.F_ProductName AS 产品名称, | |
| 13 | + u.F_UsageQuantity AS 领取数量, | |
| 14 | + u.F_UnitPrice AS 当前单价, | |
| 15 | + u.F_TotalAmount AS 当前总价, | |
| 16 | + IFNULL(NULLIF(p.F_AveragePrice, 0), p.F_Price) AS 新单价_取自产品, | |
| 17 | + IFNULL(NULLIF(p.F_AveragePrice, 0), p.F_Price) * u.F_UsageQuantity AS 新总价 | |
| 18 | +FROM lq_inventory_usage u | |
| 19 | +INNER JOIN lq_product p ON u.F_ProductId = p.F_Id | |
| 20 | +WHERE u.F_IsEffective = 1 | |
| 21 | + AND (u.F_UnitPrice != IFNULL(NULLIF(p.F_AveragePrice, 0), p.F_Price) | |
| 22 | + OR u.F_TotalAmount != IFNULL(NULLIF(p.F_AveragePrice, 0), p.F_Price) * u.F_UsageQuantity) | |
| 23 | +LIMIT 500; | |
| 24 | + | |
| 25 | +-- 二、更新库存使用记录:单价、总价(按产品 F_AveragePrice,否则 F_Price) | |
| 26 | +UPDATE lq_inventory_usage u | |
| 27 | +INNER JOIN lq_product p ON u.F_ProductId = p.F_Id | |
| 28 | +SET | |
| 29 | + u.F_UnitPrice = IFNULL(NULLIF(p.F_AveragePrice, 0), p.F_Price), | |
| 30 | + u.F_TotalAmount = IFNULL(NULLIF(p.F_AveragePrice, 0), p.F_Price) * u.F_UsageQuantity, | |
| 31 | + u.F_UpdateTime = NOW() | |
| 32 | +WHERE u.F_IsEffective = 1; | |
| 33 | + | |
| 34 | +-- 三、按批次汇总,更新申请表的 F_TotalAmount | |
| 35 | +UPDATE lq_inventory_usage_application a | |
| 36 | +INNER JOIN ( | |
| 37 | + SELECT F_UsageBatchId, SUM(F_TotalAmount) AS batch_total | |
| 38 | + FROM lq_inventory_usage | |
| 39 | + WHERE F_IsEffective = 1 | |
| 40 | + GROUP BY F_UsageBatchId | |
| 41 | +) t ON a.F_UsageBatchId = t.F_UsageBatchId | |
| 42 | +SET a.F_TotalAmount = t.batch_total | |
| 43 | +WHERE a.F_IsEffective = 1; | ... | ... |