-- ==================================================================== -- P1-002: Package IMPORT_PARTENERI pentru căutare și creare parteneri -- Sistem Import Comenzi Web → ROA -- ==================================================================== -- -- Implementare completă package pentru gestionarea partenerilor din comenzi web -- Integrare cu pack_def existent pentru creare parteneri și adrese -- -- Funcționalități: -- - Căutare parteneri după cod_fiscal și denumire -- - Creare parteneri noi cu validări -- - Parsare adrese format semicolon -- - Separare nume/prenume pentru persoane fizice -- - Error handling și logging complet -- -- Author: Generated with Claude Code -- Date: 09 septembrie 2025 -- ==================================================================== -- Creare package specification CREATE OR REPLACE PACKAGE IMPORT_PARTENERI AS -- ==================================================================== -- CONSTANTS -- ==================================================================== -- ID utilizator sistem pentru toate operațiile C_ID_UTIL_SISTEM CONSTANT NUMBER := -3; -- Valori default pentru adrese incomplete C_JUD_DEFAULT CONSTANT VARCHAR2(50) := 'București'; C_LOCALITATE_DEFAULT CONSTANT VARCHAR2(50) := 'BUCURESTI'; C_SECTOR_DEFAULT CONSTANT VARCHAR2(50) := 'Sectorul 1'; -- Lungimi maxime pentru validări C_MIN_COD_FISCAL CONSTANT NUMBER := 3; C_CUI_PERS_FIZICA CONSTANT NUMBER := 13; -- CNP are 13 cifre -- ==================================================================== -- CUSTOM EXCEPTIONS -- ==================================================================== partener_invalid_exception EXCEPTION; PRAGMA EXCEPTION_INIT(partener_invalid_exception, -20001); adresa_invalid_exception EXCEPTION; PRAGMA EXCEPTION_INIT(adresa_invalid_exception, -20002); integrare_pack_def_exception EXCEPTION; PRAGMA EXCEPTION_INIT(integrare_pack_def_exception, -20003); -- ==================================================================== -- PUBLIC FUNCTIONS -- ==================================================================== /** * Funcția principală pentru căutarea sau crearea unui partener * * Algoritm: * 1. Caută după cod_fiscal (dacă > 3 caractere) * 2. Caută după denumire exactă * 3. Creează partener nou cu pack_def.adauga_partener() * 4. Adaugă adresa cu pack_def.adauga_adresa_partener2() * * @param p_cod_fiscal Cod fiscal/CUI/CNP partener * @param p_denumire Denumirea partenerului (companie sau nume complet) * @param p_adresa Adresa în format: "JUD:București;BUCURESTI;Str.Victoriei;10" * @param p_telefon Număr de telefon * @param p_email Adresa de email * @return ID_PART al partenerului găsit sau creat */ FUNCTION cauta_sau_creeaza_partener( p_cod_fiscal IN VARCHAR2, p_denumire IN VARCHAR2, p_adresa IN VARCHAR2 DEFAULT NULL, p_telefon IN VARCHAR2 DEFAULT NULL, p_email IN VARCHAR2 DEFAULT NULL ) RETURN NUMBER; /** * Parsează o adresă din format semicolon în componentele individuale * * Format input: "JUD:București;BUCURESTI;Str.Victoriei;10" * sau: "BUCURESTI;Str.Victoriei;10" * sau: "Str.Victoriei;10" * * @param p_adresa_text Textul adresei de parseat * @param p_judet OUT Județul extras (default: București) * @param p_localitate OUT Localitatea extrasă (default: BUCURESTI) * @param p_strada OUT Strada și numărul * @param p_sector OUT Sectorul (default: Sectorul 1) */ PROCEDURE parseaza_adresa_semicolon( p_adresa_text IN VARCHAR2, p_judet OUT VARCHAR2, p_localitate OUT VARCHAR2, p_strada OUT VARCHAR2, p_sector OUT VARCHAR2 ); -- ==================================================================== -- UTILITY FUNCTIONS (PUBLIC pentru testare) -- ==================================================================== /** * Caută partener după cod fiscal * @param p_cod_fiscal Codul fiscal de căutat * @return ID_PART sau NULL dacă nu găsește */ FUNCTION cauta_partener_dupa_cod_fiscal(p_cod_fiscal IN VARCHAR2) RETURN NUMBER; /** * Caută partener după denumire exactă * @param p_denumire Denumirea de căutat * @return ID_PART sau NULL dacă nu găsește */ FUNCTION cauta_partener_dupa_denumire(p_denumire IN VARCHAR2) RETURN NUMBER; /** * Verifică dacă un cod fiscal aparține unei persoane fizice (CNP) * @param p_cod_fiscal Codul fiscal de verificat * @return 1 dacă este persoană fizică, 0 dacă este companie */ FUNCTION este_persoana_fizica(p_cod_fiscal IN VARCHAR2) RETURN NUMBER; /** * Separă numele complet în nume și prenume pentru persoane fizice * @param p_denumire_completa Numele complet * @param p_nume OUT Numele de familie * @param p_prenume OUT Prenumele */ PROCEDURE separa_nume_prenume( p_denumire_completa IN VARCHAR2, p_nume OUT VARCHAR2, p_prenume OUT VARCHAR2 ); /** * Scrie în log operațiile executate * @param p_mesaj Mesajul de logat * @param p_nivel Nivelul: INFO, WARN, ERROR */ PROCEDURE log_operatie( p_mesaj IN VARCHAR2, p_nivel IN VARCHAR2 DEFAULT 'INFO' ); END IMPORT_PARTENERI; / -- ==================================================================== -- PACKAGE BODY IMPLEMENTATION -- ==================================================================== CREATE OR REPLACE PACKAGE BODY IMPORT_PARTENERI AS -- ==================================================================== -- PRIVATE FUNCTIONS -- ==================================================================== /** * Validează datele unui partener înainte de creare */ FUNCTION valideaza_date_partener( p_cod_fiscal IN VARCHAR2, p_denumire IN VARCHAR2 ) RETURN BOOLEAN IS BEGIN -- Verificări obligatorii IF p_denumire IS NULL OR TRIM(p_denumire) = '' THEN RAISE_APPLICATION_ERROR(-20001, 'Denumirea partenerului nu poate fi goală'); END IF; -- Cod fiscal opțional, dar dacă există trebuie să aibă minim 3 caractere IF p_cod_fiscal IS NOT NULL AND LENGTH(TRIM(p_cod_fiscal)) > 0 THEN IF LENGTH(TRIM(p_cod_fiscal)) < C_MIN_COD_FISCAL THEN RAISE_APPLICATION_ERROR(-20001, 'Codul fiscal trebuie să aibă minim ' || C_MIN_COD_FISCAL || ' caractere'); END IF; END IF; RETURN TRUE; EXCEPTION WHEN OTHERS THEN log_operatie('ERROR în valideaza_date_partener: ' || SQLERRM, 'ERROR'); RAISE; END valideaza_date_partener; /** * Curăță și standardizează textul pentru căutare */ FUNCTION curata_text_cautare(p_text IN VARCHAR2) RETURN VARCHAR2 IS BEGIN IF p_text IS NULL THEN RETURN NULL; END IF; RETURN UPPER(TRIM(p_text)); END curata_text_cautare; -- ==================================================================== -- PUBLIC FUNCTIONS IMPLEMENTATION -- ==================================================================== FUNCTION cauta_partener_dupa_cod_fiscal(p_cod_fiscal IN VARCHAR2) RETURN NUMBER IS v_id_part NUMBER; v_cod_fiscal_curat VARCHAR2(50); BEGIN -- Validare input IF p_cod_fiscal IS NULL OR LENGTH(TRIM(p_cod_fiscal)) < C_MIN_COD_FISCAL THEN RETURN NULL; END IF; v_cod_fiscal_curat := curata_text_cautare(p_cod_fiscal); log_operatie('Căutare partener după cod_fiscal: ' || v_cod_fiscal_curat); -- Căutare în NOM_PARTENERI BEGIN SELECT id_part INTO v_id_part FROM nom_parteneri WHERE UPPER(TRIM(cod_fiscal)) = v_cod_fiscal_curat AND ROWNUM = 1; -- În caz de duplicate, luăm primul log_operatie('Găsit partener cu cod_fiscal ' || v_cod_fiscal_curat || ': ID_PART=' || v_id_part); RETURN v_id_part; EXCEPTION WHEN NO_DATA_FOUND THEN log_operatie('Nu s-a găsit partener cu cod_fiscal: ' || v_cod_fiscal_curat); RETURN NULL; WHEN TOO_MANY_ROWS THEN -- Luăm primul găsit SELECT id_part INTO v_id_part FROM ( SELECT id_part FROM nom_parteneri WHERE UPPER(TRIM(cod_fiscal)) = v_cod_fiscal_curat ORDER BY id_part ) WHERE ROWNUM = 1; log_operatie('WARNING: Multiple parteneri cu același cod_fiscal ' || v_cod_fiscal_curat || '. Selectat ID_PART=' || v_id_part, 'WARN'); RETURN v_id_part; END; EXCEPTION WHEN OTHERS THEN log_operatie('ERROR în cauta_partener_dupa_cod_fiscal: ' || SQLERRM, 'ERROR'); RAISE; END cauta_partener_dupa_cod_fiscal; FUNCTION cauta_partener_dupa_denumire(p_denumire IN VARCHAR2) RETURN NUMBER IS v_id_part NUMBER; v_denumire_curata VARCHAR2(200); BEGIN -- Validare input IF p_denumire IS NULL OR TRIM(p_denumire) = '' THEN RETURN NULL; END IF; v_denumire_curata := curata_text_cautare(p_denumire); log_operatie('Căutare partener după denumire: ' || v_denumire_curata); -- Căutare în NOM_PARTENERI BEGIN SELECT id_part INTO v_id_part FROM nom_parteneri WHERE UPPER(TRIM(denumire)) = v_denumire_curata AND ROWNUM = 1; -- În caz de duplicate, luăm primul log_operatie('Găsit partener cu denumirea ' || v_denumire_curata || ': ID_PART=' || v_id_part); RETURN v_id_part; EXCEPTION WHEN NO_DATA_FOUND THEN log_operatie('Nu s-a găsit partener cu denumirea: ' || v_denumire_curata); RETURN NULL; WHEN TOO_MANY_ROWS THEN -- Luăm primul găsit SELECT id_part INTO v_id_part FROM ( SELECT id_part FROM nom_parteneri WHERE UPPER(TRIM(denumire)) = v_denumire_curata ORDER BY id_part ) WHERE ROWNUM = 1; log_operatie('WARNING: Multiple parteneri cu aceeași denumire ' || v_denumire_curata || '. Selectat ID_PART=' || v_id_part, 'WARN'); RETURN v_id_part; END; EXCEPTION WHEN OTHERS THEN log_operatie('ERROR în cauta_partener_dupa_denumire: ' || SQLERRM, 'ERROR'); RAISE; END cauta_partener_dupa_denumire; FUNCTION este_persoana_fizica(p_cod_fiscal IN VARCHAR2) RETURN NUMBER IS v_cod_curat VARCHAR2(50); BEGIN IF p_cod_fiscal IS NULL THEN RETURN 0; END IF; v_cod_curat := TRIM(p_cod_fiscal); -- CNP-ul are exact 13 cifre IF LENGTH(v_cod_curat) = C_CUI_PERS_FIZICA AND REGEXP_LIKE(v_cod_curat, '^[0-9]{13}$') THEN RETURN 1; END IF; RETURN 0; EXCEPTION WHEN OTHERS THEN log_operatie('ERROR în este_persoana_fizica: ' || SQLERRM, 'ERROR'); RETURN 0; END este_persoana_fizica; PROCEDURE separa_nume_prenume( p_denumire_completa IN VARCHAR2, p_nume OUT VARCHAR2, p_prenume OUT VARCHAR2 ) IS v_pozitie_spatiu NUMBER; v_denumire_curata VARCHAR2(200); BEGIN IF p_denumire_completa IS NULL OR TRIM(p_denumire_completa) = '' THEN p_nume := NULL; p_prenume := NULL; RETURN; END IF; v_denumire_curata := TRIM(p_denumire_completa); -- Caută primul spațiu v_pozitie_spatiu := INSTR(v_denumire_curata, ' '); IF v_pozitie_spatiu > 0 THEN -- Numele = prima parte p_nume := TRIM(SUBSTR(v_denumire_curata, 1, v_pozitie_spatiu - 1)); -- Prenumele = restul p_prenume := TRIM(SUBSTR(v_denumire_curata, v_pozitie_spatiu + 1)); ELSE -- Nu există spațiu, totul este nume p_nume := v_denumire_curata; p_prenume := NULL; END IF; -- Validare lungimi maxime (să nu depășească limitele tabelei) IF LENGTH(p_nume) > 50 THEN p_nume := SUBSTR(p_nume, 1, 50); END IF; IF LENGTH(p_prenume) > 50 THEN p_prenume := SUBSTR(p_prenume, 1, 50); END IF; EXCEPTION WHEN OTHERS THEN log_operatie('ERROR în separa_nume_prenume: ' || SQLERRM, 'ERROR'); p_nume := SUBSTR(p_denumire_completa, 1, 50); -- fallback p_prenume := NULL; END separa_nume_prenume; PROCEDURE parseaza_adresa_semicolon( p_adresa_text IN VARCHAR2, p_judet OUT VARCHAR2, p_localitate OUT VARCHAR2, p_strada OUT VARCHAR2, p_sector OUT VARCHAR2 ) IS v_adresa_curata VARCHAR2(500); v_componente SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST(); v_count NUMBER; v_temp_judet VARCHAR2(100); BEGIN -- Inițializare cu valori default p_judet := C_JUD_DEFAULT; p_localitate := C_LOCALITATE_DEFAULT; p_strada := NULL; p_sector := C_SECTOR_DEFAULT; -- Validare input IF p_adresa_text IS NULL OR TRIM(p_adresa_text) = '' THEN log_operatie('Adresă goală, se folosesc valorile default', 'WARN'); RETURN; END IF; v_adresa_curata := TRIM(p_adresa_text); log_operatie('Parsare adresă: ' || v_adresa_curata); -- Split după semicolon SELECT TRIM(REGEXP_SUBSTR(v_adresa_curata, '[^;]+', 1, LEVEL)) BULK COLLECT INTO v_componente FROM DUAL CONNECT BY REGEXP_SUBSTR(v_adresa_curata, '[^;]+', 1, LEVEL) IS NOT NULL; v_count := v_componente.COUNT; IF v_count = 0 THEN log_operatie('Nu s-au găsit componente în adresă', 'WARN'); RETURN; END IF; -- Parsare în funcție de numărul de componente IF v_count = 1 THEN -- Doar strada p_strada := SUBSTR(v_componente(1), 1, 100); ELSIF v_count = 2 THEN -- Localitate;Strada p_localitate := SUBSTR(v_componente(1), 1, 50); p_strada := SUBSTR(v_componente(2), 1, 100); ELSIF v_count = 3 THEN -- Localitate;Strada;Număr (combinate în strada) p_localitate := SUBSTR(v_componente(1), 1, 50); p_strada := SUBSTR(v_componente(2) || ' ' || v_componente(3), 1, 100); ELSIF v_count >= 4 THEN -- Verifică dacă prima componentă conține "JUD:" v_temp_judet := v_componente(1); IF UPPER(v_temp_judet) LIKE 'JUD:%' THEN -- Format: JUD:București;BUCURESTI;Strada;Număr p_judet := SUBSTR(REPLACE(v_temp_judet, 'JUD:', ''), 1, 50); p_localitate := SUBSTR(v_componente(2), 1, 50); -- Combină strada și numărul IF v_count >= 4 THEN p_strada := SUBSTR(v_componente(3) || CASE WHEN v_count >= 4 THEN ' ' || v_componente(4) END, 1, 100); ELSE p_strada := SUBSTR(v_componente(3), 1, 100); END IF; ELSE -- Format: Localitate;Strada;Număr;AlteCeva p_localitate := SUBSTR(v_componente(1), 1, 50); p_strada := SUBSTR(v_componente(2) || ' ' || v_componente(3), 1, 100); END IF; END IF; -- Curățare finală p_judet := TRIM(p_judet); p_localitate := TRIM(p_localitate); p_strada := TRIM(p_strada); p_sector := TRIM(p_sector); -- Fallback pentru câmpuri goale IF p_judet IS NULL OR p_judet = '' THEN p_judet := C_JUD_DEFAULT; END IF; IF p_localitate IS NULL OR p_localitate = '' THEN p_localitate := C_LOCALITATE_DEFAULT; END IF; IF p_sector IS NULL OR p_sector = '' THEN p_sector := C_SECTOR_DEFAULT; END IF; log_operatie('Adresă parsată: JUD=' || p_judet || ', LOC=' || p_localitate || ', STRADA=' || NVL(p_strada, 'NULL') || ', SECTOR=' || p_sector); EXCEPTION WHEN OTHERS THEN log_operatie('ERROR în parseaza_adresa_semicolon: ' || SQLERRM, 'ERROR'); -- Păstrăm valorile default în caz de eroare p_judet := C_JUD_DEFAULT; p_localitate := C_LOCALITATE_DEFAULT; p_sector := C_SECTOR_DEFAULT; END parseaza_adresa_semicolon; FUNCTION cauta_sau_creeaza_partener( p_cod_fiscal IN VARCHAR2, p_denumire IN VARCHAR2, p_adresa IN VARCHAR2 DEFAULT NULL, p_telefon IN VARCHAR2 DEFAULT NULL, p_email IN VARCHAR2 DEFAULT NULL ) RETURN NUMBER IS v_id_part NUMBER; v_id_adresa NUMBER; v_este_persoana_fizica NUMBER; v_nume VARCHAR2(50); v_prenume VARCHAR2(50); -- Componente adresă v_judet VARCHAR2(50); v_localitate VARCHAR2(50); v_strada VARCHAR2(100); v_sector VARCHAR2(50); -- Date pentru pack_def v_cod_fiscal_curat VARCHAR2(50); v_denumire_curata VARCHAR2(200); BEGIN log_operatie('=== ÎNCEPUT cauta_sau_creeaza_partener ==='); log_operatie('Input: cod_fiscal=' || NVL(p_cod_fiscal, 'NULL') || ', denumire=' || NVL(p_denumire, 'NULL') || ', adresa=' || NVL(p_adresa, 'NULL')); -- Validare date input IF NOT valideaza_date_partener(p_cod_fiscal, p_denumire) THEN RAISE partener_invalid_exception; END IF; v_cod_fiscal_curat := TRIM(p_cod_fiscal); v_denumire_curata := TRIM(p_denumire); -- STEP 1: Căutare după cod fiscal (prioritate 1) IF v_cod_fiscal_curat IS NOT NULL AND LENGTH(v_cod_fiscal_curat) >= C_MIN_COD_FISCAL THEN v_id_part := cauta_partener_dupa_cod_fiscal(v_cod_fiscal_curat); IF v_id_part IS NOT NULL THEN log_operatie('Partener găsit după cod_fiscal. ID_PART=' || v_id_part); log_operatie('=== SFÂRȘIT cauta_sau_creeaza_partener ==='); RETURN v_id_part; END IF; END IF; -- STEP 2: Căutare după denumire exactă (prioritate 2) v_id_part := cauta_partener_dupa_denumire(v_denumire_curata); IF v_id_part IS NOT NULL THEN log_operatie('Partener găsit după denumire. ID_PART=' || v_id_part); log_operatie('=== SFÂRȘIT cauta_sau_creeaza_partener ==='); RETURN v_id_part; END IF; -- STEP 3: Creare partener nou log_operatie('Nu s-a găsit partener existent. Se creează unul nou...'); -- Verifică tipul partenerului v_este_persoana_fizica := este_persoana_fizica(v_cod_fiscal_curat); IF v_este_persoana_fizica = 1 THEN log_operatie('Detectată persoană fizică (CUI 13 cifre)'); separa_nume_prenume(v_denumire_curata, v_nume, v_prenume); log_operatie('Nume separat: NUME=' || NVL(v_nume, 'NULL') || ', PRENUME=' || NVL(v_prenume, 'NULL')); END IF; -- Creare partener prin pack_def BEGIN IF v_este_persoana_fizica = 1 THEN -- Pentru persoane fizice v_id_part := pack_def.adauga_partener( p_denumire => v_nume, -- nume de familie p_prenume => v_prenume, p_cod_fiscal => v_cod_fiscal_curat, p_telefon => p_telefon, p_email => p_email, p_id_util => C_ID_UTIL_SISTEM ); ELSE -- Pentru companii v_id_part := pack_def.adauga_partener( p_denumire => v_denumire_curata, p_cod_fiscal => v_cod_fiscal_curat, p_telefon => p_telefon, p_email => p_email, p_id_util => C_ID_UTIL_SISTEM ); END IF; IF v_id_part IS NULL OR v_id_part <= 0 THEN RAISE_APPLICATION_ERROR(-20003, 'pack_def.adauga_partener a returnat ID invalid'); END IF; log_operatie('Partener creat cu succes. ID_PART=' || v_id_part); EXCEPTION WHEN OTHERS THEN log_operatie('ERROR la crearea partenerului prin pack_def: ' || SQLERRM, 'ERROR'); RAISE integrare_pack_def_exception; END; -- STEP 4: Adăugare adresă (dacă există) IF p_adresa IS NOT NULL AND TRIM(p_adresa) != '' THEN log_operatie('Se adaugă adresa pentru partenerul nou creat...'); -- Parsează adresa parseaza_adresa_semicolon(p_adresa, v_judet, v_localitate, v_strada, v_sector); -- Adaugă adresa prin pack_def BEGIN v_id_adresa := pack_def.adauga_adresa_partener2( p_id_part => v_id_part, p_judet => v_judet, p_localitate => v_localitate, p_strada => v_strada, p_sector => v_sector, p_id_util => C_ID_UTIL_SISTEM ); IF v_id_adresa IS NOT NULL AND v_id_adresa > 0 THEN log_operatie('Adresă adăugată cu succes. ID_ADRESA=' || v_id_adresa); ELSE log_operatie('WARNING: pack_def.adauga_adresa_partener2 a returnat ID invalid: ' || NVL(TO_CHAR(v_id_adresa), 'NULL'), 'WARN'); END IF; EXCEPTION WHEN OTHERS THEN log_operatie('ERROR la adăugarea adresei prin pack_def: ' || SQLERRM, 'ERROR'); -- Nu raisăm excepția pentru adresă, partenerii pot exista fără adresă log_operatie('Partenerul a fost creat, dar adresa nu a putut fi adăugată', 'WARN'); END; ELSE log_operatie('Nu s-a furnizat adresă pentru partenerul nou'); END IF; log_operatie('Partener creat complet. ID_PART=' || v_id_part); log_operatie('=== SFÂRȘIT cauta_sau_creeaza_partener ==='); RETURN v_id_part; EXCEPTION WHEN partener_invalid_exception THEN log_operatie('ERROR: Date partener invalide', 'ERROR'); RAISE_APPLICATION_ERROR(-20001, 'Date partener invalide: ' || SQLERRM); WHEN integrare_pack_def_exception THEN log_operatie('ERROR: Problemă la integrarea cu pack_def', 'ERROR'); RAISE_APPLICATION_ERROR(-20003, 'Eroare la integrarea cu pack_def: ' || SQLERRM); WHEN OTHERS THEN log_operatie('ERROR NEAȘTEPTAT în cauta_sau_creeaza_partener: ' || SQLERRM, 'ERROR'); RAISE_APPLICATION_ERROR(-20099, 'Eroare neașteptată la crearea partenerului: ' || SQLERRM); END cauta_sau_creeaza_partener; PROCEDURE log_operatie( p_mesaj IN VARCHAR2, p_nivel IN VARCHAR2 DEFAULT 'INFO' ) IS PRAGMA AUTONOMOUS_TRANSACTION; v_timestamp VARCHAR2(50); v_mesaj_complet VARCHAR2(4000); BEGIN v_timestamp := TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'); v_mesaj_complet := v_timestamp || ' | ' || RPAD(p_nivel, 5) || ' | IMPORT_PARTENERI | ' || p_mesaj; -- Output în server log (DBMS_OUTPUT pentru sesiuni interactive) DBMS_OUTPUT.PUT_LINE(v_mesaj_complet); -- Încearcă să scrie în audit_trail sau altă tabelă de logging dacă există BEGIN -- Această instrucțiune va reuși doar dacă există o tabelă de logging EXECUTE IMMEDIATE ' INSERT INTO system_log (timestamp, nivel, modul, mesaj, id_util) VALUES (:1, :2, :3, :4, :5)' USING SYSDATE, p_nivel, 'IMPORT_PARTENERI', p_mesaj, C_ID_UTIL_SISTEM; COMMIT; EXCEPTION WHEN OTHERS THEN -- Ignoră erorile de logging - nu vrem să întrerupă procesul principal NULL; END; EXCEPTION WHEN OTHERS THEN -- Nu lăsăm logging-ul să întrerupă procesul principal NULL; END log_operatie; END IMPORT_PARTENERI; / -- ==================================================================== -- VALIDARE COMPILARE -- ==================================================================== -- Verifică dacă package-ul s-a compilat corect SELECT object_name, object_type, status FROM user_objects WHERE object_name = 'IMPORT_PARTENERI' AND object_type IN ('PACKAGE', 'PACKAGE BODY'); -- ==================================================================== -- TESTE RAPIDE (opțional) -- ==================================================================== -- Exemplu de utilizare: -- SELECT IMPORT_PARTENERI.cauta_sau_creeaza_partener('1234567890123', 'Ion Popescu', 'BUCURESTI;Calea Victoriei;10') FROM dual; -- Exemplu de parsare adresă: -- DECLARE -- v_jud VARCHAR2(50); -- v_loc VARCHAR2(50); -- v_str VARCHAR2(100); -- v_sec VARCHAR2(50); -- BEGIN -- IMPORT_PARTENERI.parseaza_adresa_semicolon('JUD:București;BUCURESTI;Str.Victoriei;10', v_jud, v_loc, v_str, v_sec); -- DBMS_OUTPUT.PUT_LINE('JUD: ' || v_jud || ', LOC: ' || v_loc || ', STR: ' || v_str || ', SEC: ' || v_sec); -- END; -- / -- ==================================================================== -- SFÂRȘIT FIȘIER -- ==================================================================== -- Package implementat complet cu: -- ✓ Căutare parteneri după cod_fiscal (prioritate 1) -- ✓ Căutare parteneri după denumire exactă (prioritate 2) -- ✓ Creare partener nou cu pack_def.adauga_partener() -- ✓ Adăugare adresă cu pack_def.adauga_adresa_partener2() -- ✓ Separare nume/prenume pentru persoane fizice (CUI 13 cifre) -- ✓ Default București Sectorul 1 pentru adrese incomplete -- ✓ Error handling complet cu custom exceptions -- ✓ Logging comprehensive cu AUTONOMOUS_TRANSACTION -- ✓ Toate partenerele create cu ID_UTIL = -3 (sistem) -- ✓ Parsare adresă format semicolon flexibilă -- ✓ Validări complete pentru toate inputurile -- ✓ Integrare cu pack_def existent -- -- Implementare production-ready cu documentație completă.