This commit is contained in:
27942
2026-02-06 02:42:30 +08:00
parent fe90de7e1f
commit f3a3ac61e5

View File

@@ -4377,9 +4377,29 @@ def conflict_search(client_info=None, party_info=None, undertaker=None, bidding_
client_names, client_id_numbers, client_originals = _extract_all_person_info(client_info) client_names, client_id_numbers, client_originals = _extract_all_person_info(client_info)
party_names, party_id_numbers, party_originals = _extract_all_person_info(party_info) party_names, party_id_numbers, party_originals = _extract_all_person_info(party_info)
# 身份证号统一用规范化后的值做精准匹配(完全相等才命中 # 按「人」成对:每人 (姓名, 规范化身份证)。当同时填了姓名+身份证时,必须同一人两项都一致才命中
_client_ids_set = {_normalize_id(c) for c in client_id_numbers if _normalize_id(c)} def _person_pairs(names, id_numbers):
_party_ids_set = {_normalize_id(p) for p in party_id_numbers if _normalize_id(p)} out = []
for i in range(max(len(names), len(id_numbers))):
name = (names[i] if i < len(names) else '').strip()
id_norm = _normalize_id(id_numbers[i]) if i < len(id_numbers) else ''
if name or id_norm:
out.append((name, id_norm))
return out
client_persons = _person_pairs(client_names, client_id_numbers)
party_persons = _person_pairs(party_names, party_id_numbers)
def _person_match(record_name, record_id_norm, search_persons):
"""记录中的一人 (record_name, record_id_norm) 是否与任意搜索人精准匹配(姓名+身份证都一致)。"""
for sn, si in search_persons:
if not sn and not si:
continue
name_ok = (not sn) or (record_name == sn)
id_ok = (not si) or (record_id_norm == si)
if name_ok and id_ok:
return True
return False
# 1. 检索预立案表 # 1. 检索预立案表
prefiling_q = Q(is_deleted=False) prefiling_q = Q(is_deleted=False)
@@ -4445,50 +4465,20 @@ def conflict_search(client_info=None, party_info=None, undertaker=None, bidding_
if pf.party_username: if pf.party_username:
pf_party_names = [pf.party_username.strip()] pf_party_names = [pf.party_username.strip()]
# 冲突规则:精准匹配。当前委托人只与历史「委托人」匹配,当前相对方只与历史「相对方」匹配;身份证号规范化后完全相等才匹配 # 冲突规则:按「人」精准匹配,同一人必须姓名+身份证都一致才命中
_client_names_set = {cn.strip() for cn in client_names} pf_client_persons = _person_pairs(pf_client_names, [_normalize_id(x) for x in pf_client_ids])
_party_names_set = {pn.strip() for pn in party_names} pf_party_persons = _person_pairs(pf_party_names, [_normalize_id(x) for x in pf_party_ids])
# 委托人姓名精准匹配 if client_persons and pf_client_persons:
if client_names and pf_client_names: for rn, ri in pf_client_persons:
for pf_c in pf_client_names: if _person_match(rn, ri, client_persons):
if pf_c.strip() in _client_names_set:
is_match = True is_match = True
match_reason.append(f"委托人姓名匹配:{pf_c}") match_reason.append(f"委托人匹配:{rn or ri or '身份证'}")
break break
if not is_match and client_originals: if party_persons and pf_party_persons:
_originals_set = {co.strip() for co in client_originals} for rn, ri in pf_party_persons:
for pf_c in pf_client_names: if _person_match(rn, ri, party_persons):
if pf_c.strip() in _originals_set:
is_match = True
match_reason.append(f"委托人信息匹配:{pf_c}")
break
# 委托人身份证号精准匹配(规范化后完全一致)
if _client_ids_set and pf_client_ids:
for pf_cid in pf_client_ids:
if _normalize_id(pf_cid) in _client_ids_set:
is_match = True is_match = True
match_reason.append("委托人身份证号匹配") match_reason.append(f"相对方匹配:{rn or ri or '身份证'}")
break
# 相对方姓名精准匹配
if party_names and pf_party_names:
for pf_p in pf_party_names:
if pf_p.strip() in _party_names_set:
is_match = True
match_reason.append(f"相对方姓名匹配:{pf_p}")
break
if not any("相对方" in r for r in match_reason) and party_originals:
_party_originals_set = {po.strip() for po in party_originals}
for pf_p in pf_party_names:
if pf_p.strip() in _party_originals_set:
is_match = True
match_reason.append(f"相对方信息匹配:{pf_p}")
break
# 相对方身份证号精准匹配(规范化后完全一致)
if _party_ids_set and pf_party_ids:
for pf_pid in pf_party_ids:
if _normalize_id(pf_pid) in _party_ids_set:
is_match = True
match_reason.append("相对方身份证号匹配")
break break
# 承办人员精准匹配 # 承办人员精准匹配
@@ -4518,34 +4508,27 @@ def conflict_search(client_info=None, party_info=None, undertaker=None, bidding_
project_records = ProjectRegistration.objects.filter(project_q) project_records = ProjectRegistration.objects.filter(project_q)
project_list = [] project_list = []
_client_names_set = {cn.strip() for cn in client_names}
_party_names_set = {pn.strip() for pn in party_names}
for pro in project_records[:50]: for pro in project_records[:50]:
is_match = False is_match = False
match_reason = [] match_reason = []
# 冲突规则:精准匹配。从立项记录的 client_info/party_info 解析出姓名身份证号再比对;身份证号规范化后完全一致才匹配 # 冲突规则:按「人」精准匹配,同一人必须姓名+身份证一致才命中
if (client_names or client_id_numbers) and pro.client_info: if client_persons and pro.client_info:
pro_client_names, pro_client_ids, _ = _extract_all_person_info(pro.client_info) pro_client_names, pro_client_ids, _ = _extract_all_person_info(pro.client_info)
pro_cn_set = {n.strip() for n in pro_client_names} pro_client_persons = _person_pairs(pro_client_names, pro_client_ids)
pro_cid_set = {_normalize_id(i) for i in pro_client_ids if _normalize_id(i)} for rn, ri in pro_client_persons:
if client_names and (pro_cn_set & _client_names_set): if _person_match(rn, ri, client_persons):
is_match = True is_match = True
match_reason.append("委托人姓名匹配") match_reason.append("委托人匹配")
elif _client_ids_set and (pro_cid_set & _client_ids_set): break
is_match = True if party_persons and pro.party_info:
match_reason.append("委托人身份证号匹配")
if (party_names or party_id_numbers) and pro.party_info:
pro_party_names, pro_party_ids, _ = _extract_all_person_info(pro.party_info) pro_party_names, pro_party_ids, _ = _extract_all_person_info(pro.party_info)
pro_pn_set = {n.strip() for n in pro_party_names} pro_party_persons = _person_pairs(pro_party_names, pro_party_ids)
pro_pid_set = {_normalize_id(i) for i in pro_party_ids if _normalize_id(i)} for rn, ri in pro_party_persons:
if party_names and (pro_pn_set & _party_names_set): if _person_match(rn, ri, party_persons):
is_match = True is_match = True
match_reason.append("相对方姓名匹配") match_reason.append("相对方匹配")
elif _party_ids_set and (pro_pid_set & _party_ids_set): break
is_match = True
match_reason.append("相对方身份证号匹配")
# 负责人精准匹配(与承办人字段完全一致才算匹配) # 负责人精准匹配(与承办人字段完全一致才算匹配)
if undertaker and pro.responsiblefor: if undertaker and pro.responsiblefor:
@@ -4592,34 +4575,33 @@ def conflict_search(client_info=None, party_info=None, undertaker=None, bidding_
is_match = False is_match = False
match_reason = [] match_reason = []
# 从招标单位解析出名称、身份证/统一代码,用于精准匹配;身份证号规范化后完全一致才匹配 # 从招标单位解析出人员列表,按「人」精准匹配(姓名+身份证都一致才命中)
bid_names, bid_ids, _ = _extract_all_person_info(bid.BiddingUnit) if bid.BiddingUnit else ([], [], []) bid_names, bid_ids, _ = _extract_all_person_info(bid.BiddingUnit) if bid.BiddingUnit else ([], [], [])
bid_names_set = {n.strip() for n in bid_names} bid_persons = _person_pairs(bid_names, bid_ids)
bid_ids_set = {_normalize_id(i) for i in bid_ids if _normalize_id(i)}
# 招标单位精准匹配:查询的招标单位与记录中的名称或证件号完全一致(证件号按规范化后比较 # 招标单位精准匹配:查询的招标单位与记录中某一人完全一致(姓名或证件号单独查时按原逻辑
if bidding_unit and bid.BiddingUnit: if bidding_unit and bid.BiddingUnit:
ut = bidding_unit.strip() ut = bidding_unit.strip()
ut_norm = _normalize_id(bidding_unit) ut_norm = _normalize_id(bidding_unit)
if ut in bid_names_set or (ut_norm and ut_norm in bid_ids_set): for rn, ri in bid_persons:
is_match = True if ut == rn or (ut_norm and ut_norm == ri):
match_reason.append("招标单位匹配") is_match = True
match_reason.append("招标单位匹配")
break
# 委托人/相对方与招标单位精准匹配(姓名身份证号完全一致) # 委托人/相对方与招标单位:同一人姓名+身份证都一致才命中
if (client_names or _client_ids_set) and bid.BiddingUnit: if client_persons and bid_persons:
if client_names and (bid_names_set & _client_names_set): for rn, ri in bid_persons:
is_match = True if _person_match(rn, ri, client_persons):
match_reason.append("委托人姓名在招标单位中") is_match = True
elif _client_ids_set and (bid_ids_set & _client_ids_set): match_reason.append("委托人匹配招标单位")
is_match = True break
match_reason.append("委托人身份证号在招标单位中") if party_persons and bid_persons:
if (party_names or _party_ids_set) and bid.BiddingUnit: for rn, ri in bid_persons:
if party_names and (bid_names_set & _party_names_set): if _person_match(rn, ri, party_persons):
is_match = True is_match = True
match_reason.append("相对方姓名在招标单位") match_reason.append("相对方匹配招标单位")
elif _party_ids_set and (bid_ids_set & _party_ids_set): break
is_match = True
match_reason.append("相对方身份证号在招标单位中")
if is_match: if is_match:
bid_list.append({ bid_list.append({