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

@@ -5,6 +5,7 @@ CREATE OR REPLACE PACKAGE PACK_IMPORT_PARTENERI AS
-- 01.04.2026 - ANAF dedup: cautare duala CUI, adrese pe strada+diacritics, strip diacritics la stocare
-- 02.04.2026 - cautare CUI strict (p_strict_search=1) sau dual anti-dedup (NULL)
-- 02.04.2026 - parser adrese: extrage APARTAMENT/SCARA/ETAJ embedded in strada (fix "Nr17 apartament 8")
-- 02.04.2026 - fallback cautare PF cu permutari nume (evita duplicate la swap firstname/lastname)
-- ====================================================================
-- CONSTANTS
@@ -677,10 +678,17 @@ CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_PARTENERI AS
v_este_persoana_fizica NUMBER;
v_nume VARCHAR2(50);
v_prenume VARCHAR2(50);
-- Date pentru pack_def
v_cod_fiscal_curat VARCHAR2(50);
v_denumire_curata VARCHAR2(200);
-- Permutari nume PF (Step 2b)
v_word1 VARCHAR2(100);
v_word2 VARCHAR2(100);
v_word3 VARCHAR2(100);
v_pos1 NUMBER;
v_pos2 NUMBER;
BEGIN
-- Resetare eroare la inceputul procesarii
@@ -726,7 +734,54 @@ CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_PARTENERI AS
RETURN;
END IF;
END IF;
-- STEP 2b: Cautare cu permutari nume (doar persoane fizice, 2-3 cuvinte)
-- Rezolva cazul cand clientul inverseaza firstname/lastname in GoMag
IF p_strict_search IS NULL AND
(p_is_persoana_juridica IS NOT NULL AND p_is_persoana_juridica = 0) THEN
v_pos1 := INSTR(v_denumire_curata, ' ');
IF v_pos1 > 0 THEN
v_word1 := TRIM(SUBSTR(v_denumire_curata, 1, v_pos1 - 1));
v_pos2 := INSTR(v_denumire_curata, ' ', v_pos1 + 1);
IF v_pos2 = 0 THEN
-- 2 cuvinte: incearca inversarea "WORD2 WORD1"
v_word2 := TRIM(SUBSTR(v_denumire_curata, v_pos1 + 1));
v_id_part := cauta_partener_dupa_denumire(v_word2 || ' ' || v_word1);
IF v_id_part IS NOT NULL THEN
pINFO('Partener PF gasit prin inversare nume: ' || v_denumire_curata ||
' -> ID_PART=' || v_id_part, 'IMPORT_PARTENERI');
p_id_partener := v_id_part;
RETURN;
END IF;
ELSE
-- 3 cuvinte: incearca toate permutatiile (5 ramase, originala deja incercata)
v_word2 := TRIM(SUBSTR(v_denumire_curata, v_pos1 + 1, v_pos2 - v_pos1 - 1));
v_word3 := TRIM(SUBSTR(v_denumire_curata, v_pos2 + 1));
-- Permutari: W1 W3 W2, W2 W1 W3, W2 W3 W1, W3 W1 W2, W3 W2 W1
FOR i IN 1..5 LOOP
v_id_part := cauta_partener_dupa_denumire(
CASE i
WHEN 1 THEN v_word1 || ' ' || v_word3 || ' ' || v_word2
WHEN 2 THEN v_word2 || ' ' || v_word1 || ' ' || v_word3
WHEN 3 THEN v_word2 || ' ' || v_word3 || ' ' || v_word1
WHEN 4 THEN v_word3 || ' ' || v_word1 || ' ' || v_word2
WHEN 5 THEN v_word3 || ' ' || v_word2 || ' ' || v_word1
END
);
IF v_id_part IS NOT NULL THEN
pINFO('Partener PF gasit prin permutare nume: ' || v_denumire_curata ||
' -> ID_PART=' || v_id_part, 'IMPORT_PARTENERI');
p_id_partener := v_id_part;
RETURN;
END IF;
END LOOP;
END IF;
END IF;
END IF;
-- STEP 3: Creare partener nou
-- pINFO('Nu s-a gasit partener existent. Se creeaza unul nou...', 'IMPORT_PARTENERI');