diff --git a/api/database-scripts/05_pack_import_parteneri.pck b/api/database-scripts/05_pack_import_parteneri.pck index 96776fa..ca5e6ac 100644 --- a/api/database-scripts/05_pack_import_parteneri.pck +++ b/api/database-scripts/05_pack_import_parteneri.pck @@ -18,6 +18,9 @@ CREATE OR REPLACE PACKAGE PACK_IMPORT_PARTENERI AS -- IN-set foloseste v_ro_cui (canonic) in loc de v_cod_fiscal_curat. Regula business platitor/ -- neplatitor pastrata. Bug anterior: input "RO 34963277" cadea pe branch neplatitor, rata partener -- existent "RO34963277" → duplicat FG COFFE #485065210. + -- 22.04.2026 - fix numar overflow: prima componenta ramane numar; "SAT X" → p_localitate (satul + -- = localitate, TIER L1/L2/L3 existent rezolva id_loc); landmark → strada; + -- COM/ORAS/MUN ignorate (deja in p_localitate din GoMag city) -- ==================================================================== -- CONSTANTS @@ -683,7 +686,32 @@ CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_PARTENERI AS END IF; -- Truncare de siguranta (limita coloanelor Oracle) - p_numar := SUBSTR(p_numar, 1, 10); + -- 22.04.2026 - numar overflow fix: + -- prima componenta ramane numar + -- "SAT X ..." → X ... devine p_localitate (satul = localitate, TIER L1/L2/L3 rezolva) + -- "COM X"/"ORAS X"/"MUN X" → ignorat (deja in p_localitate din GoMag) + -- altceva (landmark) → strada + IF LENGTH(p_numar) > 10 THEN + v_pozitie := INSTR(p_numar, ' '); + IF v_pozitie > 1 THEN + v_rest_parts := TRIM(SUBSTR(p_numar, v_pozitie + 1)); + p_numar := SUBSTR(p_numar, 1, v_pozitie - 1); + IF v_rest_parts IS NOT NULL THEN + IF UPPER(v_rest_parts) LIKE 'SAT %' THEN + -- Satul = localitate → overwrite p_localitate cu tot ce urmeaza dupa "SAT " + p_localitate := UPPER(TRIM(REGEXP_REPLACE(v_rest_parts, '^SAT\s+', '', 1, 1, 'i'))); + ELSIF UPPER(v_rest_parts) NOT LIKE 'COM %' + AND UPPER(v_rest_parts) NOT LIKE 'ORAS %' + AND UPPER(v_rest_parts) NOT LIKE 'MUN %' THEN + -- Landmark (ex: "LA NON STOP") → strada + p_strada := SUBSTR(TRIM(p_strada || ' ' || v_rest_parts), 1, 100); + END IF; + -- COM/ORAS/MUN aruncat (deja in p_localitate din GoMag) + END IF; + ELSE + p_numar := SUBSTR(p_numar, 1, 10); + END IF; + END IF; p_bloc := SUBSTR(p_bloc, 1, 30); p_scara := SUBSTR(p_scara, 1, 10); p_apart := SUBSTR(p_apart, 1, 10); diff --git a/api/tests/test_address_rules_oracle.py b/api/tests/test_address_rules_oracle.py index b8a5380..4196f18 100644 --- a/api/tests/test_address_rules_oracle.py +++ b/api/tests/test_address_rules_oracle.py @@ -370,6 +370,30 @@ class TestAddressComponentParsing: assert "MODARZAU BLOCURI" in (result.get("strada") or ""), f"strada should contain MODARZAU BLOCURI, got {result}" assert result.get("bloc") is None, f"bloc should be NULL for neighborhood name, got {result.get('bloc')}" + def test_numar_overflow_with_landmark(self, oracle_pool): + """'nr 5 la non stop' — numar=5, landmark overflow muta in strada.""" + addr = self._parse_address(oracle_pool, "Str zorilor nr 5 la non stop", "Brasov", "Brasov") + assert addr["numar"] == "5", f"numar={addr['numar']!r} (asteptat '5')" + assert "ZORILOR" in (addr["strada"] or ""), f"strada={addr['strada']!r}" + assert "NON" in (addr["strada"] or ""), f"landmark lipsa din strada: {addr['strada']!r}" + + def test_numar_overflow_with_sat_localitate(self, oracle_pool): + """'nr21 sat Grozavesti corbii mari' — numar=21, SAT overwrite p_localitate (satul = localitate).""" + addr = self._parse_address(oracle_pool, "Pe deal nr21 sat Grozavesti corbii mari", "Corbii Mari", "Dambovita") + assert addr["numar"] == "21", f"numar={addr['numar']!r} (asteptat '21')" + assert "DEAL" in (addr["strada"] or ""), f"strada={addr['strada']!r}" + assert "GROZAVESTI" not in (addr["strada"] or ""), f"SAT in strada: {addr['strada']!r}" + # SAT ... a fost mutat in p_localitate (override din GoMag "CORBII MARI") + assert "GROZAVESTI" in (addr["localitate"] or "").upper(), ( + f"localitate={addr['localitate']!r} (astept sa contina GROZAVESTI)" + ) + + def test_numar_normal_not_affected(self, oracle_pool): + """Numar normal (<= 10 chars) nu e atins de overflow fix.""" + addr = self._parse_address(oracle_pool, "Str Mihai Viteazu nr 10", "Cluj-Napoca", "Cluj") + assert addr["numar"] == "10", f"numar={addr['numar']!r}" + assert "VITEAZU" in (addr["strada"] or ""), f"strada={addr['strada']!r}" + # --------------------------------------------------------------------------- # Test regresie: comenzi existente în SQLite