fix(partners): prevent duplicate PF partners on firstname/lastname swap

Customers often swap firstname/lastname in GoMag forms, causing duplicate
partner creation in Oracle. Fix with two layers:

- Python: sort PF name words alphabetically before Oracle lookup
- PL/SQL: add Step 2b permutation search (2-3 word names, PF only)
- Normalize name order to lastname+firstname across all Python files
- Add diagnostic SQL for finding existing reversed-name duplicates
- Add Oracle integration test for reverse-name matching

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-04-06 12:06:55 +00:00
parent 0992744490
commit fc1013bff6
6 changed files with 213 additions and 10 deletions

View File

@@ -901,6 +901,93 @@ def test_duplicate_codmat_different_prices():
return False
def test_pf_reverse_name_dedup():
"""Test that PF partner with reversed name order is found, not duplicated.
Creates partner 'POPESCU ION', then searches for 'ION POPESCU' — should return same id_part.
"""
print("\n🔄 TEST: PF Reverse Name Deduplication")
print("=" * 50)
try:
conn = oracledb.connect(user=user, password=password, dsn=dsn)
with conn.cursor() as cur:
timestamp = datetime.now().strftime('%H%M%S')
unique_suffix = random.randint(1000, 9999)
# Step 1: Create partner with name "TESTPF_{unique} POPESCU ION"
# Using unique prefix to avoid collision with real data
name_original = f'ZZTEST{unique_suffix} POPESCU ION'
id_partener_var = cur.var(oracledb.NUMBER)
cur.callproc("PACK_IMPORT_PARTENERI.cauta_sau_creeaza_partener", [
None, # p_cod_fiscal
name_original, # p_denumire
None, # p_registru
0, # p_is_persoana_juridica = 0 (PF)
None, # p_strict_search
id_partener_var # p_id_partener OUT
])
conn.commit()
id_original = id_partener_var.getvalue()
if not id_original or id_original <= 0:
print(f" ❌ Failed to create original partner: {name_original}")
return False
print(f" ✅ Created partner '{name_original}' → ID_PART={int(id_original)}")
# Step 2: Search with reversed name "ZZTEST{unique} ION POPESCU"
name_reversed = f'ZZTEST{unique_suffix} ION POPESCU'
id_reversed_var = cur.var(oracledb.NUMBER)
cur.callproc("PACK_IMPORT_PARTENERI.cauta_sau_creeaza_partener", [
None, # p_cod_fiscal
name_reversed, # p_denumire (reversed)
None, # p_registru
0, # p_is_persoana_juridica = 0 (PF)
None, # p_strict_search
id_reversed_var # p_id_partener OUT
])
id_reversed = id_reversed_var.getvalue()
print(f" Searched for '{name_reversed}' → ID_PART={int(id_reversed) if id_reversed else 'NULL'}")
if id_reversed == id_original:
print(f" ✅ PASS: Same partner found (no duplicate created)")
success = True
else:
print(f" ❌ FAIL: Different partner returned! Original={int(id_original)}, Reversed={int(id_reversed)}")
print(f" Duplicate was created instead of matching existing partner")
success = False
# Cleanup the duplicate too
if id_reversed and id_reversed > 0:
try:
cur.execute("DELETE FROM nom_parteneri WHERE id_part = :1", [int(id_reversed)])
except Exception:
pass
# Cleanup: delete the test partner
try:
cur.execute("DELETE FROM nom_parteneri WHERE id_part = :1", [int(id_original)])
conn.commit()
print(f" 🧹 Cleaned up test partner ID_PART={int(id_original)}")
except Exception as e:
print(f" ⚠️ Cleanup warning: {e}")
conn.rollback()
return success
except Exception as e:
print(f" ❌ Test error: {e}")
import traceback
traceback.print_exc()
return False
finally:
try:
conn.close() # noqa: F821
except Exception:
pass
if __name__ == "__main__":
print("Starting complete order import test...")
print(f"Timestamp: {datetime.now()}")
@@ -937,4 +1024,12 @@ if __name__ == "__main__":
biz_passed += 1
print(f"\nBusiness rule tests: {biz_passed}/{len(biz_tests)} passed")
# Run PF reverse name dedup test
print("\n")
dedup_success = test_pf_reverse_name_dedup()
if dedup_success:
print("PF REVERSE NAME DEDUP: SUCCESSFUL")
else:
print("PF REVERSE NAME DEDUP: NEEDS ATTENTION")
exit(0 if success else 1)