修复采购规则跨项目人员串入问题

This commit is contained in:
wkc
2026-03-23 15:11:05 +08:00
parent 15d17e4175
commit 63d8904d01
5 changed files with 659 additions and 12 deletions

View File

@@ -30,6 +30,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
NULL AS reasonDetail
</sql>
<sql id="projectScopedDirectStaffSql">
select distinct
cast(staff.staff_id as char) as staffId,
staff.id_card as idCard
from ccdi_bank_statement bs
inner join ccdi_base_staff staff on staff.id_card = bs.cret_no
where bs.project_id = #{projectId}
and bs.cret_no is not null
and trim(bs.cret_no) != ''
</sql>
<sql id="cashDepositPredicate">
(
(
@@ -911,8 +922,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
pt.supplier_name AS supplierName,
pt.actual_amount AS actualAmount
from ccdi_purchase_transaction pt
inner join ccdi_base_staff staff
on CAST(staff.staff_id AS CHAR) = pt.applicant_id
inner join (
<include refid="projectScopedDirectStaffSql"/>
) project_staff on project_staff.staffId = pt.applicant_id
where IFNULL(pt.actual_amount, 0) > 100000
union
select distinct
@@ -921,8 +933,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
pt.supplier_name AS supplierName,
pt.actual_amount AS actualAmount
from ccdi_purchase_transaction pt
inner join ccdi_base_staff staff
on CAST(staff.staff_id AS CHAR) = pt.purchase_leader_id
inner join (
<include refid="projectScopedDirectStaffSql"/>
) project_staff on project_staff.staffId = pt.purchase_leader_id
where pt.purchase_leader_id is not null
and IFNULL(pt.actual_amount, 0) > 100000
) t
@@ -955,24 +968,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
SUM(source.actualAmount) / NULLIF(total_amount.totalAmount, 0) AS supplierRatio
from (
select distinct
staff.id_card AS objectKey,
project_staff.idCard AS objectKey,
pt.purchase_id AS purchaseId,
pt.supplier_name AS supplierName,
IFNULL(pt.actual_amount, 0) AS actualAmount
from ccdi_purchase_transaction pt
inner join ccdi_base_staff staff on CAST(staff.staff_id AS CHAR) = pt.applicant_id
inner join (
<include refid="projectScopedDirectStaffSql"/>
) project_staff on project_staff.staffId = pt.applicant_id
where IFNULL(pt.actual_amount, 0) > 0
and IFNULL(pt.supplier_name, '') &lt;&gt; ''
union
select distinct
staff.id_card AS objectKey,
project_staff.idCard AS objectKey,
pt.purchase_id AS purchaseId,
pt.supplier_name AS supplierName,
IFNULL(pt.actual_amount, 0) AS actualAmount
from ccdi_purchase_transaction pt
inner join ccdi_base_staff staff on CAST(staff.staff_id AS CHAR) = pt.purchase_leader_id
inner join (
<include refid="projectScopedDirectStaffSql"/>
) project_staff on project_staff.staffId = pt.purchase_leader_id
where pt.purchase_leader_id is not null
and IFNULL(pt.actual_amount, 0) > 0
and IFNULL(pt.supplier_name, '') &lt;&gt; ''
@@ -983,21 +1000,25 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
ROUND(SUM(source_total.actualAmount), 2) AS totalAmount
from (
select distinct
staff.id_card AS objectKey,
project_staff.idCard AS objectKey,
pt.purchase_id AS purchaseId,
IFNULL(pt.actual_amount, 0) AS actualAmount
from ccdi_purchase_transaction pt
inner join ccdi_base_staff staff on CAST(staff.staff_id AS CHAR) = pt.applicant_id
inner join (
<include refid="projectScopedDirectStaffSql"/>
) project_staff on project_staff.staffId = pt.applicant_id
where IFNULL(pt.actual_amount, 0) > 0
union
select distinct
staff.id_card AS objectKey,
project_staff.idCard AS objectKey,
pt.purchase_id AS purchaseId,
IFNULL(pt.actual_amount, 0) AS actualAmount
from ccdi_purchase_transaction pt
inner join ccdi_base_staff staff on CAST(staff.staff_id AS CHAR) = pt.purchase_leader_id
inner join (
<include refid="projectScopedDirectStaffSql"/>
) project_staff on project_staff.staffId = pt.purchase_leader_id
where pt.purchase_leader_id is not null
and IFNULL(pt.actual_amount, 0) > 0
) source_total

View File

@@ -138,6 +138,16 @@ class CcdiBankTagAnalysisMapperXmlTest {
}
}
@Test
void purchaseRules_shouldBeScopedToCurrentProjectStaff() throws Exception {
String xml = readXml(RESOURCE);
assertAll(
() -> assertPurchaseRuleScopedByProject(xml, "selectLargePurchaseTransactionStatements"),
() -> assertPurchaseRuleScopedByProject(xml, "selectSupplierConcentrationObjects")
);
}
@Test
void assetRegistrationMismatchRules_shouldUseRealSqlAndAssetTable() throws Exception {
String xml = readXml(RESOURCE);
@@ -192,4 +202,21 @@ class CcdiBankTagAnalysisMapperXmlTest {
assertTrue(selectSql.contains("reasonDetail"), () -> selectId + " 缺少 reasonDetail");
assertTrue(!selectSql.contains("where 1 = 0"), () -> selectId + " 仍是占位 SQL");
}
private void assertPurchaseRuleScopedByProject(String xml, String selectId) {
String selectSql = extractSelectSql(xml, selectId);
String scopeSql = extractSqlFragment(xml, "projectScopedDirectStaffSql");
assertTrue(selectSql.contains("projectScopedDirectStaffSql"), () -> selectId + " 未引用项目员工范围片段");
assertTrue(scopeSql.contains("ccdi_bank_statement"), () -> selectId + " 缺少项目流水范围约束");
assertTrue(scopeSql.contains("#{projectId}"), () -> selectId + " 缺少 projectId 过滤条件");
}
private String extractSqlFragment(String xml, String sqlId) {
Pattern pattern = Pattern.compile(
"<sql\\s+id=\"" + sqlId + "\"[\\s\\S]*?</sql>"
);
Matcher matcher = pattern.matcher(xml);
assertTrue(matcher.find(), () -> "未找到 sql 片段: " + sqlId);
return matcher.group();
}
}