事业部开单统计播报问题分析
问题描述:绿纤西站店没有在事业部开单统计数据播报中显示
分析日期:2025年1月
问题类型:数据统计逻辑错误
一、问题定位
1.1 播报流程
触发时机:在创建开单记录时(LqKdKdjlbService.Create 方法)
流程:
- 开单创建成功后,判断
sfyj > 0且kdrq有值 - 调用
LqDailyReportService.GetBusinessUnitBillingStatisticsText获取统计数据文本 - 如果文本不为空且不包含"暂无开单数据",则发送到企业微信群
代码位置:LqKdKdjlbService.cs 第1506-1536行
1.2 统计数据获取逻辑
方法:LqDailyReportService.GetBusinessUnitBillingStatistics
位置:LqDailyReportService.cs 第1513-1604行
当前实现(❌ 错误):
// 2. 查询指定日期的有效开单记录(有金额的)
var billingQuery = _db.Queryable<LqKdKdjlbEntity, LqMdxxEntity, OrganizeEntity>(
(billing, store, org) => billing.Djmd == store.Id && store.Syb == org.Id)
.Where((billing, store, org) => billing.IsEffective == StatusEnum.有效.GetHashCode())
.Where((billing, store, org) => billing.Sfyj > 0)
.Where((billing, store, org) => billing.Kdrq.HasValue && billing.Kdrq.Value.Date == targetDate.Date)
.Where((billing, store, org) => org.Category == "department")
.Where((billing, store, org) => org.FullName.Contains("事业"))
问题:
- ❌ 使用
store.Syb == org.Id直接从lq_mdxx表的syb字段读取事业部归属 - ❌ 没有考虑月份维度,门店归属可能在不同月份发生变化
- ❌ 违反了项目规范:门店归属一律从
lq_md_target按月份维度管理
二、问题根因分析
2.1 项目规范要求
根据项目规范(.cursor/rules/project_rules.mdc):
lq_mdxx_mdgs (门店归属表) 已弃用: 门店归属信息不再从
lq_mdxx直接读取
- 门店归属一律从
lq_md_target按月份维度管理:通过F_StoreId + F_Month获取对应月份的事业部/经营部/科技部/旗舰店等归属信息lq_mdxx中的归属字段(syb、jyb、kjb、dxmb、gsqssj、gszzsj、status)视为历史字段,禁止再作为业务统计或归属判断的依据
2.2 正确的实现方式
在同一个文件的 GetBusinessUnitPerformanceCompletion 方法中(第418-433行),使用了正确的实现方式:
SELECT
target.F_BusinessUnit as BusinessUnitId,
COALESCE(SUM(billing.sfyj), 0) as BillingPerformance
FROM lq_kd_kdjlb billing
INNER JOIN lq_md_target target ON billing.djmd = target.F_StoreId AND target.F_Month = '{month}'
INNER JOIN base_organize o ON target.F_BusinessUnit = o.F_Id
WHERE billing.F_IsEffective = 1
AND target.F_BusinessUnit IS NOT NULL
AND o.F_Category = 'department'
AND (o.F_DeleteMark IS NULL OR o.F_DeleteMark != 1)
AND o.F_FullName IN ('事业一部', '事业二部', '事业三部', '事业四部', '事业五部', '事业六部')
AND DATE(billing.kdrq) >= '{startDate:yyyy-MM-dd}'
AND DATE(billing.kdrq) <= '{endDate:yyyy-MM-dd}'
AND target.F_BusinessUnit IN ('{unitIdsStr}')
GROUP BY target.F_BusinessUnit
关键点:
- ✅ 使用
lq_md_target表获取门店归属 - ✅ 通过
target.F_Month = '{month}'按月份维度筛选 - ✅ 通过
target.F_BusinessUnit获取事业部ID
2.3 为什么绿纤西站店没有被统计
可能的原因:
lq_mdxx.syb字段为空或错误- 如果绿纤西站店在
lq_mdxx表的syb字段中没有正确设置 - 或者
syb字段指向的组织不是"事业X部"(不包含"事业"关键字) - 则不会被统计进去
- 如果绿纤西站店在
lq_md_target表中有正确的归属,但查询没有使用- 如果绿纤西站店在
lq_md_target表中有正确的月份归属记录 - 但查询使用的是
lq_mdxx.syb,导致数据不一致
- 如果绿纤西站店在
月份维度问题
- 如果查询时使用的月份与
lq_md_target表中的月份不匹配 - 或者该门店在查询月份没有
lq_md_target记录
- 如果查询时使用的月份与
三、问题影响
3.1 数据准确性
- ❌ 统计数据不准确,可能遗漏部分门店的开单数据
- ❌ 播报内容不完整,影响决策
3.2 业务影响
- ❌ 绿纤西站店的开单数据没有被播报
- ❌ 可能导致事业部业绩统计不准确
- ❌ 影响数据分析和决策
四、修复方案
4.1 修复思路
核心原则:按照项目规范,门店归属必须从 lq_md_target 表按月份维度获取
修复步骤:
修改查询逻辑:
- 不再使用
lq_mdxx.syb字段 - 改为使用
lq_md_target表,通过F_StoreId + F_Month获取门店归属
- 不再使用
确定月份:
- 根据开单日期(
kdrq)确定月份(YYYYMM格式) - 使用该月份在
lq_md_target表中查找门店归属
- 根据开单日期(
关联查询:
lq_kd_kdjlb←lq_md_target(通过门店ID和月份)lq_md_target←base_organize(通过事业部ID)
4.2 修复后的查询逻辑
方案一:使用 SqlSugar 查询(推荐)
// 1. 根据开单日期确定月份(YYYYMM格式)
var month = targetDate.ToString("yyyyMM");
// 2. 查询指定日期的有效开单记录(有金额的)
var billingQuery = _db.Queryable<LqKdKdjlbEntity, LqMdTargetEntity, OrganizeEntity>(
(billing, target, org) =>
billing.Djmd == target.StoreId
&& target.Month == month
&& target.BusinessUnit == org.Id)
.Where((billing, target, org) => billing.IsEffective == StatusEnum.有效.GetHashCode())
.Where((billing, target, org) => billing.Sfyj > 0)
.Where((billing, target, org) => billing.Kdrq.HasValue && billing.Kdrq.Value.Date == targetDate.Date)
.Where((billing, target, org) => target.BusinessUnit != null && target.BusinessUnit != "")
.Where((billing, target, org) => org.Category == "department")
.Where((billing, target, org) => org.FullName.Contains("事业"))
.Select((billing, target, org) => new
{
OrderId = billing.Id,
StoreName = billing.Djmd, // 需要关联门店表获取门店名称
BusinessUnitId = org.Id,
BusinessUnitName = org.FullName,
Amount = billing.Sfyj,
OrderTime = billing.Kdrq,
})
.ToListAsync();
方案二:使用原生SQL查询(更灵活)
SELECT
billing.F_Id as OrderId,
store.dm as StoreName,
org.F_Id as BusinessUnitId,
org.F_FullName as BusinessUnitName,
billing.sfyj as Amount,
billing.kdrq as OrderTime
FROM lq_kd_kdjlb billing
INNER JOIN lq_md_target target ON billing.djmd = target.F_StoreId AND target.F_Month = '{month}'
INNER JOIN lq_mdxx store ON billing.djmd = store.F_Id
INNER JOIN base_organize org ON target.F_BusinessUnit = org.F_Id
WHERE billing.F_IsEffective = 1
AND billing.sfyj > 0
AND DATE(billing.kdrq) = '{targetDate:yyyy-MM-dd}'
AND target.F_BusinessUnit IS NOT NULL
AND org.F_Category = 'department'
AND (org.F_DeleteMark IS NULL OR org.F_DeleteMark != 1)
AND org.F_FullName IN ('事业一部', '事业二部', '事业三部', '事业四部', '事业五部', '事业六部')
4.3 需要修改的代码
文件:netcore/src/Modularity/Extend/NCC.Extend/LqDailyReportService.cs
方法:GetBusinessUnitBillingStatistics(第1513-1604行)
修改内容:
- 添加月份计算逻辑(根据
targetDate计算月份) - 修改查询逻辑,使用
lq_md_target表替代lq_mdxx.syb - 添加门店名称的关联查询(如果需要)
五、验证方案
5.1 验证步骤
- 检查绿纤西站店的数据: ```sql -- 检查门店基础信息 SELECT F_Id, dm, syb FROM lq_mdxx WHERE dm LIKE '%西站%';
-- 检查门店目标表中的归属信息 SELECT F_StoreId, F_Month, F_BusinessUnit FROM lq_md_target WHERE F_StoreId = (SELECT F_Id FROM lq_mdxx WHERE dm LIKE '%西站%' LIMIT 1) ORDER BY F_Month DESC;
-- 检查该门店的开单记录 SELECT F_Id, djmd, kdrq, sfyj, F_IsEffective FROM lq_kd_kdjlb WHERE djmd = (SELECT F_Id FROM lq_mdxx WHERE dm LIKE '%西站%' LIMIT 1) AND DATE(kdrq) = '2025-01-23' -- 替换为实际日期 AND sfyj > 0 AND F_IsEffective = 1;
2. **对比修复前后的数据**:
- 修复前:使用 `lq_mdxx.syb` 查询
- 修复后:使用 `lq_md_target` 查询
- 验证绿纤西站店是否出现在统计结果中
3. **测试播报功能**:
- 创建一个绿纤西站店的开单记录
- 验证播报内容中是否包含该门店
---
### 5.2 预期结果
修复后:
- ✅ 绿纤西站店的开单数据应该出现在统计结果中
- ✅ 播报内容应该包含该门店的开单信息
- ✅ 统计数据应该与 `lq_md_target` 表中的归属信息一致
---
## 六、风险评估
### 6.1 数据一致性风险
- ⚠️ 如果某些门店在 `lq_md_target` 表中没有对应月份的记录,可能不会被统计
- **建议**:添加容错处理,如果 `lq_md_target` 中没有记录,可以回退到 `lq_mdxx.syb`(但需要记录日志)
### 6.2 性能风险
- ⚠️ 使用 `lq_md_target` 表关联查询可能比直接使用 `lq_mdxx.syb` 稍慢
- **建议**:确保 `lq_md_target` 表有适当的索引(`F_StoreId + F_Month` 唯一索引已存在)
---
## 七、修复优先级
**优先级**:🔴 **高**
**原因**:
1. 影响数据准确性
2. 违反项目规范
3. 导致业务数据不完整
---
## 八、总结
### 8.1 问题根源
**核心问题**:`GetBusinessUnitBillingStatistics` 方法使用了错误的门店归属获取方式
- ❌ 当前实现:从 `lq_mdxx.syb` 字段读取(已弃用的历史字段)
- ✅ 应该使用:从 `lq_md_target` 表按月份维度获取
### 8.2 修复方向
1. **修改查询逻辑**:使用 `lq_md_target` 表替代 `lq_mdxx.syb`
2. **添加月份维度**:根据开单日期确定月份,使用该月份的门店归属
3. **保持一致性**:与其他统计方法(如 `GetBusinessUnitPerformanceCompletion`)保持一致
### 8.3 预期效果
修复后,绿纤西站店(以及其他所有门店)的开单数据将:
- ✅ 根据 `lq_md_target` 表中的月份归属正确统计
- ✅ 出现在对应事业部的播报内容中
- ✅ 符合项目规范要求
---
**文档结束**