From 05bb0b1b01a470698907b9d11cb5a082678e5c3d Mon Sep 17 00:00:00 2001 From: Marius Mutu Date: Wed, 19 Nov 2025 22:32:41 +0200 Subject: [PATCH] Reorganize Oracle packages into database-scripts for unified git tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move Oracle package files from docs/ to api/database-scripts/ with sequential numbering: - PACK_COMENZI.pck → 04_pack_comenzi.pck (renamed with git) - PACK_IMPORT_PARTENERI.pck → 05_pack_import_parteneri.pck - PACK_IMPORT_COMENZI.pck → 06_pack_import_comenzi.pck Remove 04_import_comenzi.sql (replaced by 06_pack_import_comenzi.pck actual version) Update VFP integration files and project structure. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .gitignore | 1 + api/database-scripts/04_import_comenzi.sql | 416 ------- .../database-scripts/04_pack_comenzi.pck | 407 ++++--- .../05_pack_import_parteneri.pck | 824 +++++++++++++ .../06_pack_import_comenzi.pck | 397 ++++++ docs/completeaza-parteneri-roa.prg | 3 +- vfp/gomag-adapter.prg | 241 +--- vfp/gomag-comenzi.sql | 7 + vfp/roawebcomenzi.PJT | Bin 4257 -> 4257 bytes vfp/roawebcomenzi.pjx | Bin 2493 -> 2493 bytes vfp/sync-comenzi-web.prg | 1060 ++++++++++------- 11 files changed, 2101 insertions(+), 1255 deletions(-) delete mode 100644 api/database-scripts/04_import_comenzi.sql rename docs/PACK_COMENZI.pck => api/database-scripts/04_pack_comenzi.pck (97%) create mode 100644 api/database-scripts/05_pack_import_parteneri.pck create mode 100644 api/database-scripts/06_pack_import_comenzi.pck create mode 100644 vfp/gomag-comenzi.sql diff --git a/.gitignore b/.gitignore index 11c0b27..ccdcb32 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ __pycache__/ settings.ini vfp/settings.ini vfp/output/ +vfp/*.json diff --git a/api/database-scripts/04_import_comenzi.sql b/api/database-scripts/04_import_comenzi.sql deleted file mode 100644 index bdd0342..0000000 --- a/api/database-scripts/04_import_comenzi.sql +++ /dev/null @@ -1,416 +0,0 @@ --- ==================================================================== --- P1-003: Package IMPORT_COMENZI pentru import comenzi web -> ROA --- Sistem Import Comenzi Web -> ROA --- ==================================================================== - --- Package pentru importul comenzilor web cu mapari complexe SKU -> CODMAT -CREATE OR REPLACE PACKAGE PACK_IMPORT_COMENZI AS - - -- Tipuri pentru returnarea rezultatelor - TYPE t_articol_result IS RECORD ( - id_articol NUMBER, - codmat VARCHAR2(50), - cantitate_roa NUMBER, - pret_unitar NUMBER, - success NUMBER, - error_message VARCHAR2(4000) - ); - - TYPE t_articol_table IS TABLE OF t_articol_result; - - -- Variabila package pentru ultima eroare (pentru orchestrator VFP) - g_last_error VARCHAR2(4000); - - -- Functie pentru gasirea/maparea articolelor ROA - FUNCTION gaseste_articol_roa( - p_sku IN VARCHAR2, - p_pret_web IN NUMBER DEFAULT NULL, - p_cantitate_web IN NUMBER DEFAULT 1 - ) RETURN t_articol_table PIPELINED; - - -- Functie pentru importul complet al unei comenzi - FUNCTION importa_comanda( - p_nr_comanda_ext IN VARCHAR2, - p_data_comanda IN DATE, - p_id_partener IN NUMBER, - p_json_articole IN CLOB, -- JSON array cu articolele - p_id_adresa_livrare IN NUMBER DEFAULT NULL, - p_id_adresa_facturare IN NUMBER DEFAULT NULL, - p_observatii IN VARCHAR2 DEFAULT NULL - ) RETURN NUMBER; -- Returneaza ID_COMANDA sau -1 pentru eroare - - -- Functii pentru managementul erorilor (similar cu PACK_JSON) - FUNCTION get_last_error RETURN VARCHAR2; - PROCEDURE clear_error; - -END PACK_IMPORT_COMENZI; -/ - --- ==================================================================== --- Package Body - Implementarea functiilor --- ==================================================================== -CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS - - -- Constante pentru configurare - c_id_gestiune CONSTANT NUMBER := NULL; -- NULL pentru INTERNA=2 (comenzi client) - c_id_sectie CONSTANT NUMBER := 2; -- Prima sectie disponibilă - c_id_pol CONSTANT NUMBER := NULL; - c_id_util CONSTANT NUMBER := -3; -- Sistem - c_interna CONSTANT NUMBER := 2; -- Comenzi de la client (web) - - -- ================================================================ - -- Functii helper pentru managementul erorilor - -- ================================================================ - FUNCTION get_last_error RETURN VARCHAR2 IS - BEGIN - RETURN g_last_error; - END get_last_error; - - PROCEDURE clear_error IS - BEGIN - g_last_error := NULL; - END clear_error; - - -- ================================================================ - -- Functii interne - -- ================================================================ - - -- Procedura interna pentru validarea seturilor - FUNCTION valideaza_set(p_sku IN VARCHAR2) RETURN BOOLEAN IS - v_suma_procent NUMBER := 0; - v_count_articole NUMBER := 0; - BEGIN - SELECT NVL(SUM(procent_pret), 0), COUNT(*) - INTO v_suma_procent, v_count_articole - FROM articole_terti - WHERE sku = p_sku - AND activ = 1; - - -- Validari logice pentru seturi - IF v_count_articole > 1 THEN - -- Set compus - suma procentelor trebuie sa fie intre 95-105% (toleranta) - IF v_suma_procent < 95 OR v_suma_procent > 105 THEN - -- pINFO('WARN VALIDEAZA_SET ' || p_sku || ': Suma procente nelogica: ' || v_suma_procent || '%', 'IMPORT_COMENZI'); - RETURN FALSE; - END IF; - ELSIF v_count_articole = 1 THEN - -- Reimpachetare - procentul trebuie sa fie 100% - IF v_suma_procent != 100 THEN - -- pINFO('WARN VALIDEAZA_SET ' || p_sku || ': Reimpachetare cu procent != 100%: ' || v_suma_procent || '%', 'IMPORT_COMENZI'); - RETURN FALSE; - END IF; - END IF; - - RETURN TRUE; - END valideaza_set; - - -- ================================================================ - -- Functia principala pentru gasirea articolelor ROA - -- ================================================================ - FUNCTION gaseste_articol_roa( - p_sku IN VARCHAR2, - p_pret_web IN NUMBER DEFAULT NULL, - p_cantitate_web IN NUMBER DEFAULT 1 - ) RETURN t_articol_table PIPELINED IS - - v_result t_articol_result; - v_found_mapping BOOLEAN := FALSE; - v_id_articol NUMBER; - - -- Cursor pentru maparile din ARTICOLE_TERTI - CURSOR c_mapari IS - SELECT at.codmat, at.cantitate_roa, at.procent_pret, - na.id_articol - FROM articole_terti at - JOIN nom_articole na ON na.codmat = at.codmat - WHERE at.sku = p_sku - AND at.activ = 1 - ORDER BY at.procent_pret DESC; -- Articolele principale primul - - BEGIN - -- pINFO('GASESTE_ARTICOL ' || p_sku || ': Cautare articol pentru SKU: ' || p_sku, 'IMPORT_COMENZI'); - - -- Initializare rezultat - v_result.success := 0; - v_result.error_message := NULL; - - -- STEP 1: Verifica maparile speciale din ARTICOLE_TERTI - FOR rec IN c_mapari LOOP - v_found_mapping := TRUE; - - v_result.id_articol := rec.id_articol; - v_result.codmat := rec.codmat; - v_result.cantitate_roa := rec.cantitate_roa * p_cantitate_web; - - -- Calculeaza pretul unitar pe baza procentului alocat - IF p_pret_web IS NOT NULL THEN - v_result.pret_unitar := (p_pret_web * rec.procent_pret / 100) / rec.cantitate_roa; - ELSE - -- Fara pret web, setam 0 (va fi necesar sa fie furnizat) - v_result.pret_unitar := 0; - END IF; - - v_result.success := 1; - - -- pINFO('GASESTE_ARTICOL ' || p_sku || ': Mapare gasita: ' || rec.codmat || - -- ', Cant: ' || v_result.cantitate_roa || - -- ', Pret: ' || v_result.pret_unitar, 'IMPORT_COMENZI'); - - PIPE ROW(v_result); - END LOOP; - - -- STEP 2: Daca nu s-au gasit mapari speciale, cauta direct in nom_articole - IF NOT v_found_mapping THEN - BEGIN - SELECT id_articol, codmat - INTO v_result.id_articol, v_result.codmat - FROM nom_articole - WHERE codmat = p_sku; - - v_result.cantitate_roa := p_cantitate_web; - - -- Pentru cautare directa, foloseste pretul din web daca este furnizat - IF p_pret_web IS NOT NULL THEN - v_result.pret_unitar := p_pret_web; - END IF; - - v_result.success := 1; - - -- pINFO('GASESTE_ARTICOL ' || p_sku || ': Gasit direct in nomenclator: ' || v_result.codmat, 'IMPORT_COMENZI'); - - PIPE ROW(v_result); - - EXCEPTION - WHEN NO_DATA_FOUND THEN - v_result.success := 0; - v_result.error_message := 'SKU nu a fost gasit nici in ARTICOLE_TERTI, nici in nom_articole: ' || p_sku; - - -- pINFO('ERROR GASESTE_ARTICOL ' || p_sku || ': ' || v_result.error_message, 'IMPORT_COMENZI'); - PIPE ROW(v_result); - - WHEN TOO_MANY_ROWS THEN - v_result.success := 0; - v_result.error_message := 'Multiple articole gasite pentru SKU: ' || p_sku; - - -- pINFO('ERROR GASESTE_ARTICOL ' || p_sku || ': ' || v_result.error_message, 'IMPORT_COMENZI'); - PIPE ROW(v_result); - END; - ELSE - -- Valideaza seturile dupa ce au fost returnate toate maparile - IF NOT valideaza_set(p_sku) THEN - null; - -- pINFO('WARN GASESTE_ARTICOL ' || p_sku || ': Set cu configuratie suspecta - verifica procentele', 'IMPORT_COMENZI'); - END IF; - END IF; - - EXCEPTION - WHEN OTHERS THEN - v_result.success := 0; - v_result.error_message := 'Eroare neasteptata: ' || SQLERRM; - - -- pINFO('ERROR GASESTE_ARTICOL ' || p_sku || ': Eroare neasteptata: ' || SQLERRM, 'IMPORT_COMENZI'); - PIPE ROW(v_result); - END gaseste_articol_roa; - - -- ================================================================ - -- Functia pentru importul complet al unei comenzi - -- ================================================================ - FUNCTION importa_comanda( - p_nr_comanda_ext IN VARCHAR2, - p_data_comanda IN DATE, - p_id_partener IN NUMBER, - p_json_articole IN CLOB, - p_id_adresa_livrare IN NUMBER DEFAULT NULL, - p_id_adresa_facturare IN NUMBER DEFAULT NULL, - p_observatii IN VARCHAR2 DEFAULT NULL - ) RETURN NUMBER IS - - v_id_comanda NUMBER; - v_data_livrare DATE; - v_sku VARCHAR2(100); - v_cantitate_web NUMBER; - v_pret_web NUMBER; - v_articole_procesate NUMBER := 0; - v_articole_eroare NUMBER := 0; - v_start_time DATE; - v_json_pos NUMBER := 1; - v_json_end NUMBER; - v_json_item CLOB; - - BEGIN - v_start_time := SYSDATE; - - -- Resetare eroare la inceputul procesarii - clear_error; - - -- Validari de baza - IF p_nr_comanda_ext IS NULL OR p_id_partener IS NULL THEN - g_last_error := 'IMPORTA_COMANDA ' || NVL(p_nr_comanda_ext, 'NULL') || ': Parametri obligatorii lipsa'; - RETURN -1; - END IF; - - -- Verifica daca comanda nu exista deja - BEGIN - SELECT id_comanda INTO v_id_comanda - FROM comenzi - WHERE comanda_externa = p_nr_comanda_ext - AND sters = 0; - - -- pINFO('WARN IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Comanda exista deja cu ID: ' || v_id_comanda, 'IMPORT_COMENZI'); - RETURN v_id_comanda; -- Returneaza ID-ul comenzii existente - - EXCEPTION - WHEN NO_DATA_FOUND THEN - NULL; -- Normal, comanda nu exista - END; - - -- Calculeaza data de livrare (comanda + 1 zi) - v_data_livrare := p_data_comanda + 1; - - -- STEP 1: Creeaza comanda folosind versiunea overloaded cu OUT parameter - BEGIN - -- Apeleaza procedura adauga_comanda care returneaza ID_COMANDA prin OUT - PACK_COMENZI.adauga_comanda( - V_NR_COMANDA => p_nr_comanda_ext, - V_DATA_COMANDA => p_data_comanda, - V_ID => p_id_partener, -- ID_PART - V_DATA_LIVRARE => v_data_livrare, - V_PROC_DISCOUNT => 0, -- Fara discount implicit - V_INTERNA => c_interna, - V_ID_UTIL => c_id_util, - V_ID_SECTIE => c_id_sectie, - V_ID_ADRESA_FACTURARE => p_id_adresa_facturare, - V_ID_ADRESA_LIVRARE => p_id_adresa_livrare, - V_ID_CODCLIENT => NULL, -- Nu folosim cod client - V_COMANDA_EXTERNA => p_nr_comanda_ext, - V_ID_CTR => NULL, -- Nu avem contract - V_ID_COMANDA => v_id_comanda -- OUT parameter cu ID_COMANDA - ); - - IF v_id_comanda IS NULL OR v_id_comanda <= 0 THEN - g_last_error := 'IMPORTA_COMANDA ' || p_nr_comanda_ext || ': PACK_COMENZI.adauga_comanda a returnat ID invalid'; - RETURN -1; - END IF; - - -- pINFO('IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Comanda creata cu ID: ' || v_id_comanda, 'IMPORT_COMENZI'); - - EXCEPTION - WHEN OTHERS THEN - g_last_error := 'IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Eroare la crearea comenzii: ' || SQLERRM; - RETURN -1; - END; - - -- STEP 2: Proceseaza articolele din JSON folosind PACK_JSON - -- Asteapta format JSON: [{"sku":"ABC","cantitate":1,"pret":10.5},{"sku":"DEF","cantitate":2,"pret":20.0}] - DECLARE - v_articol_json VARCHAR2(4000); - v_articol_count NUMBER := 0; - BEGIN - -- Parse JSON array folosind package-ul generic - FOR json_obj IN ( - SELECT * FROM TABLE(PACK_JSON.parse_array(p_json_articole)) - ) LOOP - v_articol_count := v_articol_count + 1; - v_articol_json := json_obj.COLUMN_VALUE; - - BEGIN - -- Extrage datele folosind functiile PACK_JSON - v_sku := PACK_JSON.get_string(v_articol_json, 'sku'); - v_cantitate_web := PACK_JSON.get_number(v_articol_json, 'cantitate'); - v_pret_web := PACK_JSON.get_number(v_articol_json, 'pret'); - - -- pINFO('IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Procesez articol ' || v_articol_count || ': ' || v_sku || ', cant: ' || v_cantitate_web || ', pret: ' || v_pret_web, 'IMPORT_COMENZI'); - - -- STEP 3: Gaseste maparile pentru acest SKU - DECLARE - v_articole_table t_articol_table; - v_articol_idx NUMBER; - BEGIN - -- Apeleaza functia si stocheaza rezultatele - SELECT * BULK COLLECT INTO v_articole_table - FROM TABLE(gaseste_articol_roa(v_sku, v_pret_web, v_cantitate_web)); - - -- Itereaza prin rezultate - IF v_articole_table.COUNT > 0 THEN - FOR v_articol_idx IN 1..v_articole_table.COUNT LOOP - DECLARE - art_rec t_articol_result := v_articole_table(v_articol_idx); - BEGIN - IF art_rec.success = 1 THEN - -- Adauga articolul la comanda - BEGIN - PACK_COMENZI.adauga_articol_comanda( - V_ID_COMANDA => v_id_comanda, - V_ID_ARTICOL => art_rec.id_articol, - V_ID_POL => c_id_pol, - V_CANTITATE => art_rec.cantitate_roa, - V_PRET => art_rec.pret_unitar, - V_ID_UTIL => c_id_util, - V_ID_SECTIE => c_id_sectie - ); - - v_articole_procesate := v_articole_procesate + 1; - - -- pINFO('IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Articol adaugat: ' || art_rec.codmat || - -- ', cant: ' || art_rec.cantitate_roa || - -- ', pret: ' || art_rec.pret_unitar, 'IMPORT_COMENZI'); - - EXCEPTION - WHEN OTHERS THEN - v_articole_eroare := v_articole_eroare + 1; - -- pINFO('ERROR IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Eroare la adaugare articol ' || art_rec.codmat || ': ' || SQLERRM, 'IMPORT_COMENZI'); - END; - ELSE - v_articole_eroare := v_articole_eroare + 1; - -- pINFO('ERROR IMPORTA_COMANDA ' || p_nr_comanda_ext || ': SKU nu a putut fi mapat: ' || v_sku || ' - ' || art_rec.error_message, 'IMPORT_COMENZI'); - END IF; - END; -- End art_rec DECLARE block - END LOOP; -- End v_articol_idx loop - ELSE - v_articole_eroare := v_articole_eroare + 1; - -- pINFO('WARN IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Niciun articol gasit pentru SKU: ' || v_sku, 'IMPORT_COMENZI'); - END IF; - END; -- End DECLARE block pentru v_articole_table - - EXCEPTION - WHEN OTHERS THEN - v_articole_eroare := v_articole_eroare + 1; - -- pINFO('ERROR IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Eroare la procesarea articolului ' || v_articol_count || ': ' || SQLERRM, 'IMPORT_COMENZI'); - END; - - END LOOP; - - EXCEPTION - WHEN OTHERS THEN - g_last_error := 'IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Eroare la parsarea JSON: ' || SQLERRM; - RETURN -1; - END; - - -- Verifica daca s-au procesat articole cu succes - IF v_articole_procesate = 0 THEN - g_last_error := 'IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Niciun articol nu a fost procesat cu succes'; - RETURN -1; - END IF; - - -- Log sumar final - -- pINFO('IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Import finalizat - ID comanda: ' || v_id_comanda || - -- ', Articole procesate: ' || v_articole_procesate || - -- ', Articole cu erori: ' || v_articole_eroare || - -- ', Timp procesare: ' || ROUND((SYSDATE - v_start_time) * 24 * 60 * 60, 2) || 's', 'IMPORT_COMENZI'); - - RETURN v_id_comanda; - - EXCEPTION - WHEN OTHERS THEN - g_last_error := 'IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Eroare neasteptata in importa_comanda: ' || SQLERRM; - RETURN -1; - END importa_comanda; - -END PACK_IMPORT_COMENZI; -/ - --- ==================================================================== --- Grant-uri pentru utilizarea package-ului --- ==================================================================== --- GRANT EXECUTE ON PACK_IMPORT_COMENZI TO PUBLIC; - diff --git a/docs/PACK_COMENZI.pck b/api/database-scripts/04_pack_comenzi.pck similarity index 97% rename from docs/PACK_COMENZI.pck rename to api/database-scripts/04_pack_comenzi.pck index 68bbc24..7cae75d 100644 --- a/docs/PACK_COMENZI.pck +++ b/api/database-scripts/04_pack_comenzi.pck @@ -84,7 +84,8 @@ create or replace package PACK_COMENZI is V_CANTITATE IN NUMBER, V_PRET IN NUMBER, V_ID_UTIL IN NUMBER, - V_ID_SECTIE IN NUMBER); + V_ID_SECTIE IN NUMBER, + V_PTVA IN NUMBER DEFAULT NULL); procedure modifica_articol_comanda(V_ID_COMANDA_ELEMENT IN NUMBER, V_CANTITATE IN NUMBER, @@ -95,6 +96,12 @@ create or replace package PACK_COMENZI is V_PRET IN NUMBER, V_ID_UTIL IN NUMBER); + procedure modifica_articol_comanda(V_ID_COMANDA_ELEMENT IN NUMBER, + V_CANTITATE IN NUMBER, + V_PRET IN NUMBER, + V_PTVA IN NUMBER, + V_ID_UTIL IN NUMBER); + /* procedure sterge_articol_comanda(V_ID_COMANDA IN NUMBER, V_ID_ARTICOL IN NUMBER, V_ID_POL IN NUMBER, @@ -298,6 +305,11 @@ create or replace package body PACK_COMENZI is -- 26.03.2021 -- marius.mutu -- adauga_articol_comanda, modifica_articol_comanda - se poate modifica si pretul, in loc sa il ia din politica de preturi + + -- 11.09.2025 + -- marius.mutu + -- adauga_articol_comanda, modifica_articol_comanda + se poate completa ptva (21,11) in loc sa il ia din politica de preturi + ---------------------------------------------------------------------------------- procedure adauga_masina(V_ID_MODEL_MASINA IN NUMBER, V_NRINMAT IN VARCHAR2, @@ -310,7 +322,7 @@ create or replace package body PACK_COMENZI is FROM NOM_MASINI WHERE NRINMAT = V_NRINMAT AND STERS = 0; - + IF V_EXISTA > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Mai exista o masina cu acest numar de inmatriculare!'); @@ -335,7 +347,7 @@ create or replace package body PACK_COMENZI is WHERE NRINMAT = V_NRINMAT AND STERS = 0 AND ID_MASINA <> V_ID_MASINA; - + IF V_EXISTA > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Mai exista o masina cu acest numar de inmatriculare!'); @@ -370,9 +382,19 @@ create or replace package body PACK_COMENZI is V_ID_COMANDA NUMBER; begin -- Wrapper pentru compatibilitate - apeleaza versiunea cu OUT parameter - adauga_comanda(V_NR_COMANDA, V_DATA_COMANDA, V_ID, V_DATA_LIVRARE, V_PROC_DISCOUNT, - V_INTERNA, V_ID_UTIL, V_ID_SECTIE, V_ID_ADRESA_FACTURARE, - V_ID_ADRESA_LIVRARE, V_ID_CODCLIENT, V_COMANDA_EXTERNA, V_ID_CTR, + adauga_comanda(V_NR_COMANDA, + V_DATA_COMANDA, + V_ID, + V_DATA_LIVRARE, + V_PROC_DISCOUNT, + V_INTERNA, + V_ID_UTIL, + V_ID_SECTIE, + V_ID_ADRESA_FACTURARE, + V_ID_ADRESA_LIVRARE, + V_ID_CODCLIENT, + V_COMANDA_EXTERNA, + V_ID_CTR, V_ID_COMANDA); end adauga_comanda; @@ -408,12 +430,12 @@ create or replace package body PACK_COMENZI is FROM COMENZI WHERE STERS = V_NESTERS AND NR_COMANDA = V_NR_COMANDA; - + IF V_NR_INREGISTRARI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Mai exista o comanda cu acest numar!'); END IF; - + IF V_ID_CTR IS NOT NULL THEN SELECT COUNT(*) INTO V_NR_INREGISTRARI @@ -426,13 +448,13 @@ create or replace package body PACK_COMENZI is (SELECT NVL(ID_SUCURSALA, -99) FROM NOM_SECTII WHERE ID_SECTIE = V_ID_SECTIE); - + IF V_NR_INREGISTRARI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Contractul ales nu este activ la data comenzii!'); END IF; END IF; - + CASE WHEN V_INTERNA = 1 THEN V_ID_GESTIUNE := NULL; @@ -471,9 +493,12 @@ create or replace package body PACK_COMENZI is V_ID_CODCLIENT1 := NULL; V_COMANDA_EXTERNA1 := ''; END CASE; - - SELECT MAX(ID_SUCURSALA) INTO V_ID_SUCURSALA FROM NOM_SECTII WHERE ID_SECTIE = V_ID_SECTIE; - + + SELECT MAX(ID_SUCURSALA) + INTO V_ID_SUCURSALA + FROM NOM_SECTII + WHERE ID_SECTIE = V_ID_SECTIE; + INSERT INTO COMENZI (NR_COMANDA, DATA_COMANDA, @@ -491,22 +516,23 @@ create or replace package body PACK_COMENZI is COMANDA_EXTERNA, ID_SUCURSALA, ID_CTR) - VALUES( V_NR_COMANDA, - V_DATA_COMANDA, - V_ID_GESTIUNE, - V_ID_PART, - V_DATA_LIVRARE2, - V_INTERNA, - V_ID_UTIL, - V_ID_SECTIE, - V_ID_SECTIE2, - V_ID_ADRESA_FACTURARE1, - V_ID_ADRESA_LIVRARE1, - V_ID_CODCLIENT1, - V_PROC_DISCOUNT, - V_COMANDA_EXTERNA1, - V_ID_SUCURSALA, - V_ID_CTR) + VALUES + (V_NR_COMANDA, + V_DATA_COMANDA, + V_ID_GESTIUNE, + V_ID_PART, + V_DATA_LIVRARE2, + V_INTERNA, + V_ID_UTIL, + V_ID_SECTIE, + V_ID_SECTIE2, + V_ID_ADRESA_FACTURARE1, + V_ID_ADRESA_LIVRARE1, + V_ID_CODCLIENT1, + V_PROC_DISCOUNT, + V_COMANDA_EXTERNA1, + V_ID_SUCURSALA, + V_ID_CTR) RETURNING ID_COMANDA INTO V_ID_COMANDA; end adauga_comanda; ---------------------------------------------------------------------------------- @@ -543,12 +569,12 @@ create or replace package body PACK_COMENZI is WHERE STERS = V_NESTERS AND NR_COMANDA = V_NR_COMANDA AND ID_COMANDA <> V_ID_COMANDA; - + IF V_NR_INREGISTRARI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Mai exista o comanda cu acest numar!'); END IF; - + IF V_ID_CTR IS NOT NULL THEN SELECT COUNT(*) INTO V_NR_INREGISTRARI @@ -561,19 +587,19 @@ create or replace package body PACK_COMENZI is (SELECT NVL(ID_SUCURSALA, -99) FROM NOM_SECTII WHERE ID_SECTIE = V_ID_SECTIE); - + IF V_NR_INREGISTRARI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Contractul ales nu este activ la data comenzii!'); END IF; END IF; - + SELECT ID_SECTIE INTO V_ID_SECTIE FROM COMENZI WHERE STERS = V_NESTERS AND ID_COMANDA = V_ID_COMANDA; - + SELECT ID_FACTURARE, ID_LIVRARE, ID_CODCLIENT, COMANDA_EXTERNA INTO V_ADRESA_FACTURAREold, V_ADRESA_LIVRAREold, @@ -582,7 +608,7 @@ create or replace package body PACK_COMENZI is FROM COMENZI WHERE STERS = V_NESTERS AND ID_COMANDA = V_ID_COMANDA; - + CASE WHEN V_INTERNA = 1 THEN V_ID_GESTIUNE := NULL; @@ -600,7 +626,7 @@ create or replace package body PACK_COMENZI is V_ADRESA_LIVRARE1 := V_ADRESA_LIVRARE; V_ID_CODCLIENT1 := V_ID_CODCLIENT; V_COMANDA_EXTERNA1 := V_COMANDA_EXTERNA; - + WHEN V_INTERNA = 3 THEN V_ID_GESTIUNE := V_ID; V_ID_PART := NULL; @@ -616,7 +642,7 @@ create or replace package body PACK_COMENZI is V_ADRESA_FACTURARE1 := V_ADRESA_FACTURAREold; V_ADRESA_LIVRARE1 := V_ADRESA_LIVRAREold; END CASE; - + UPDATE COMENZI SET NR_COMANDA = V_NR_COMANDA, DATA_COMANDA = V_DATA_COMANDA, @@ -634,12 +660,12 @@ create or replace package body PACK_COMENZI is ID_UTIL_UM = V_ID_UTIL, DATAORA_UM = SYSDATE WHERE ID_COMANDA = V_ID_COMANDA; - + UPDATE COMENZI_ELEMENTE SET DISCOUNT_UNITAR = ROUND(PRET * (V_PROC_DISCOUNT / 100), pack_sesiune.getoptiunefirma('PPRETV')) WHERE ID_COMANDA = V_ID_COMANDA; - + pack_comenzi.actualizeaza_lucrare(V_ID_COMANDA, V_ID_UTIL, V_ID_SECTIE); end modifica_comanda; ---------------------------------------------------------------------------------- @@ -653,18 +679,18 @@ create or replace package body PACK_COMENZI is SET STERS = V_STERS, ID_UTILS = V_ID_UTIL, DATAORAS = V_DATAORAS WHERE ID_COMANDA = V_ID_COMANDA AND STERS = V_NESTERS; - + SELECT ID_SECTIE INTO V_ID_SECTIE FROM COMENZI WHERE STERS = V_NESTERS AND ID_COMANDA = V_ID_COMANDA; - + UPDATE COMENZI SET STERS = V_STERS, ID_UTILS = V_ID_UTIL, DATAORAS = V_DATAORAS WHERE ID_COMANDA = V_ID_COMANDA AND STERS = V_NESTERS; - + pack_comenzi.actualizeaza_lucrare(V_ID_COMANDA, V_ID_UTIL, V_ID_SECTIE); end sterge_comanda; ---------------------------------------------------------------------------------- @@ -694,7 +720,7 @@ create or replace package body PACK_COMENZI is V_NUMAR_CTR := NULL; V_ID_CTR := NULL; end; - + end cauta_contract_comanda; ---------------------------------------------------------------------------------- procedure adauga_articol_comanda(V_ID_COMANDA IN NUMBER, @@ -704,6 +730,7 @@ create or replace package body PACK_COMENZI is V_ID_UTIL IN NUMBER, V_ID_SECTIE IN NUMBER) is V_PRET CRM_POLITICI_PRET_ART.PRET%TYPE; + V_PTVA COMENZI_ELEMENTE.PTVA%TYPE; begin adauga_articol_comanda(V_ID_COMANDA, V_ID_ARTICOL, @@ -711,7 +738,8 @@ create or replace package body PACK_COMENZI is V_CANTITATE, V_PRET, V_ID_UTIL, - V_ID_SECTIE); + V_ID_SECTIE, + V_PTVA); end adauga_articol_comanda; procedure adauga_articol_comanda(V_ID_COMANDA IN NUMBER, @@ -720,12 +748,13 @@ create or replace package body PACK_COMENZI is V_CANTITATE IN NUMBER, V_PRET IN NUMBER, V_ID_UTIL IN NUMBER, - V_ID_SECTIE IN NUMBER) is + V_ID_SECTIE IN NUMBER, + V_PTVA IN NUMBER DEFAULT NULL) is V_PRET2 CRM_POLITICI_PRET_ART.PRET%TYPE; V_ID_VALUTA NOM_VALUTE.ID_VALUTA%TYPE; V_PRET_CU_TVA CRM_POLITICI_PRETURI.PRETURI_CU_TVA%TYPE; V_DISCOUNT_UNITAR COMENZI_ELEMENTE.DISCOUNT_UNITAR%TYPE := 0; - + V_NR_INREG NUMBER(2); V_DENUMIRE NOM_ARTICOLE.DENUMIRE%TYPE; begin @@ -742,29 +771,29 @@ create or replace package body PACK_COMENZI is RAISE_APPLICATION_ERROR(-20000, 'Pretul pentru acest articol nu a fost gasit in lista de preturi! (COM-001)'); end; - + IF V_PRET IS NOT NULL THEN V_PRET2 := V_PRET; END IF; - + SELECT COUNT(*) INTO V_NR_INREG FROM COMENZI_ELEMENTE WHERE ID_COMANDA = V_ID_COMANDA AND ID_ARTICOL = V_ID_ARTICOL AND STERS = 0; - + IF V_NR_INREG > 0 THEN SELECT DENUMIRE INTO V_DENUMIRE FROM NOM_ARTICOLE WHERE ID_ARTICOL = V_ID_ARTICOL; - + RAISE_APPLICATION_ERROR(-20000, 'Articolul ' || V_DENUMIRE || ' a fost deja introdus pe aceasta comanda! Deschideti o alta instanta a programului de comenzi si verificati inainte sa reincercati salvarea datelor actuale!'); END IF; - + INSERT INTO COMENZI_ELEMENTE (ID_COMANDA, ID_ARTICOL, @@ -774,7 +803,8 @@ create or replace package body PACK_COMENZI is CANTITATE, ID_VALUTA, PRET_CU_TVA, - ID_SECTIE) + ID_SECTIE, + PTVA) VALUES (V_ID_COMANDA, V_ID_ARTICOL, @@ -784,8 +814,9 @@ create or replace package body PACK_COMENZI is V_CANTITATE, V_ID_VALUTA, V_PRET_CU_TVA, - V_ID_SECTIE); - + V_ID_SECTIE, + V_PTVA); + end adauga_articol_comanda; ---------------------------------------------------------------------------------- procedure modifica_articol_comanda(V_ID_COMANDA_ELEMENT IN NUMBER, @@ -806,6 +837,18 @@ create or replace package body PACK_COMENZI is SET CANTITATE = V_CANTITATE, PRET = V_PRET WHERE ID_COMANDA_ELEMENT = V_ID_COMANDA_ELEMENT; end modifica_articol_comanda; + + procedure modifica_articol_comanda(V_ID_COMANDA_ELEMENT IN NUMBER, + V_CANTITATE IN NUMBER, + V_PRET IN NUMBER, + V_PTVA IN NUMBER, + V_ID_UTIL IN NUMBER) is + begin + UPDATE COMENZI_ELEMENTE + SET CANTITATE = V_CANTITATE, PRET = V_PRET, PTVA = V_PTVA + WHERE ID_COMANDA_ELEMENT = V_ID_COMANDA_ELEMENT; + end modifica_articol_comanda; + ---------------------------------------------------------------------------------- /* procedure sterge_articol_comanda(V_ID_COMANDA IN NUMBER, @@ -843,11 +886,11 @@ create or replace package body PACK_COMENZI is INTO V_ID_LUCRARE_VECHE FROM COMENZI WHERE ID_COMANDA = V_ID_COMANDA; - + UPDATE COMENZI SET ID_LUCRARE = V_ID_LUCRARE WHERE ID_COMANDA = V_ID_COMANDA; - + IF V_ID_LUCRARE_VECHE IS NOT NULL THEN pack_comenzi.actualizeaza_articole_lucrare(V_ID_LUCRARE_VECHE, V_ID_UTIL, @@ -863,7 +906,7 @@ create or replace package body PACK_COMENZI is V_LUNGIME_SIR NUMBER(10); begin V_LUNGIME_SIR := SIR_IN_SIR(V_SIR_COMENZI, ';'); - + FOR i IN 1 .. V_LUNGIME_SIR LOOP V_ID_COMANDA := TO_NUMBER(ELEMENT_DIN_SIR(V_SIR_COMENZI, ';', i)); pack_comenzi.adauga_lucrare_pe_comanda(V_ID_COMANDA, @@ -871,7 +914,7 @@ create or replace package body PACK_COMENZI is V_ID_UTIL, V_ID_SECTIE); END LOOP; - + pack_comenzi.actualizeaza_articole_lucrare(V_ID_LUCRARE, V_ID_UTIL, V_ID_SECTIE); @@ -895,7 +938,7 @@ create or replace package body PACK_COMENZI is NR_LIVRARE = V_NR_LIVRARE WHERE ID_COMANDA = V_ID_COMANDA RETURNING ID_PART INTO V_ID_PART; - + IF V_ID_PART IS NOT NULL THEN MERGE INTO CORESP_DELEGATI_PART A USING dual @@ -915,7 +958,7 @@ create or replace package body PACK_COMENZI is begin pack_sesiune.set_id_sectie_comenzi(V_ID_SECTIE); V_DATAORA := sysdate; - + begin select a.csectie || to_char(NVL(V_DATA_LUCRARE, V_DATAORA), 'DDMMYY') || '-' || (select count(*) + 1 as nr @@ -937,13 +980,13 @@ create or replace package body PACK_COMENZI is to_char(NVL(V_DATA_LUCRARE, V_DATAORA), 'DDMMYY') || '%' and sters = 0; end; - + INSERT INTO NOM_LUCRARI (NRORD) VALUES (V_NRORD) RETURNING ID_LUCRARE INTO V_ID_LUCRARE; - + INSERT INTO LUCRARI_DETALII (ID_LUCRARE, DATA_LUCRARE, TERMEN_EXECUTIE, ID_UTIL, ID_SECTIE) VALUES @@ -955,7 +998,7 @@ create or replace package body PACK_COMENZI is 1), V_ID_UTIL, V_ID_SECTIE); - + end genereaza_lucrare; ---------------------------------------------------------------------------------- procedure adauga_lucrare(V_NRORD IN VARCHAR2, @@ -964,28 +1007,28 @@ create or replace package body PACK_COMENZI is V_TERMEN_EXECUTIE IN DATE, V_ID_UTIL IN NUMBER, V_ID_SECTIE IN NUMBER) is - + V_NR_LUCRARI NUMBER(10); V_NESTERS NUMBER := 0; V_ID_LUCRARE NOM_LUCRARI.ID_LUCRARE%TYPE; V_DATA_LUCRARE_INCHISA DATE; begin pack_sesiune.set_id_sectie_comenzi(V_ID_SECTIE); - + SELECT COUNT(*) INTO V_NR_LUCRARI FROM NOM_LUCRARI WHERE STERS = V_NESTERS AND NRORD = V_NRORD; - + IF V_NR_LUCRARI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Mai exista o lucrare cu acest numar!'); END IF; - + V_DATA_LUCRARE_INCHISA := sysdate + (pack_comenzi.citeste_ore_inchidere(V_ID_SECTIE) / 24); - + IF V_TERMEN_EXECUTIE <= V_DATA_LUCRARE_INCHISA THEN RAISE_APPLICATION_ERROR(-20000, 'Termenul de executie trebuie sa fie mai mare de ' || @@ -993,13 +1036,13 @@ create or replace package body PACK_COMENZI is 'DD/MM/YYYY HH24:MI') || ' pentru ca sa puteti adauga comenzi pe aceasta lucrare!'); END IF; - + INSERT INTO NOM_LUCRARI (NRORD) VALUES (V_NRORD) RETURNING ID_LUCRARE INTO V_ID_LUCRARE; - + INSERT INTO LUCRARI_DETALII (ID_LUCRARE, DATA_LUCRARE, @@ -1032,27 +1075,27 @@ create or replace package body PACK_COMENZI is WHERE STERS = V_NESTERS AND NRORD = V_NRORD AND ID_LUCRARE <> V_ID_LUCRARE; - + IF V_NR_LUCRARI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Mai exista o lucrare cu acest numar!'); END IF; - + SELECT COUNT(*) INTO V_NR_COMENZI FROM COMENZI WHERE STERS = V_NESTERS AND ID_LUCRARE = V_ID_LUCRARE AND DATA_COMANDA > V_TERMEN_EXECUTIE; - + IF V_NR_COMENZI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Exista ' || V_NR_COMENZI || ' comenzi cu data mai mare decat termenul de executie al lucrarii!'); END IF; - + UPDATE NOM_LUCRARI SET NRORD = V_NRORD WHERE ID_LUCRARE = V_ID_LUCRARE; - + UPDATE LUCRARI_DETALII SET DATA_LUCRARE = V_DATA_LUCRARE, EXPLICATIE = V_EXPLICATIE, @@ -1069,9 +1112,9 @@ create or replace package body PACK_COMENZI is V_NR_INREGISTRARI NUMBER(5); begin /* V_LOOKUP := 'COMENZI.ID_LUCRARE;RUL.ID_LUCRARE;'; - + nomdelprocn(USER, 'NOM_LUCRARI', 'ID_LUCRARE', V_ID_LUCRARE, V_LOOKUP);*/ - + SELECT SUM(NR) INTO V_NR_INREGISTRARI FROM (SELECT COUNT(*) AS NR @@ -1089,12 +1132,12 @@ create or replace package body PACK_COMENZI is WHERE ID_LUCRARE = V_ID_LUCRARE AND STERS = 0*/ ); - + IF V_NR_INREGISTRARI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Nu se pot sterge detaliile, deoarece mai exista comenzi pe lucrare!'); END IF; - + UPDATE LUCRARI_DETALII SET STERS = V_STERS WHERE ID_LUCRARE = V_ID_LUCRARE; @@ -1103,13 +1146,13 @@ create or replace package body PACK_COMENZI is FROM COMENZI WHERE STERS = V_NESTERS AND ID_LUCRARE = V_ID_LUCRARE; - + IF V_NR_COMENZI > 0 THEN RAISE_APPLICATION_ERROR(-20000, 'Pe aceasta lucrare exista comenzi!'); END IF; - + UPDATE NOM_LUCRARI SET STERS = V_STERS WHERE ID_LUCRARE = V_ID_LUCRARE; - + UPDATE LUCRARI_DETALII SET STERS = V_STERS WHERE ID_LUCRARE = V_ID_LUCRARE;*/ @@ -1125,13 +1168,13 @@ create or replace package body PACK_COMENZI is INTO V_ID_LUCRARE FROM COMENZI WHERE ID_COMANDA = V_ID_COMANDA; - + IF V_ID_LUCRARE IS NOT NULL THEN pack_comenzi.actualizeaza_articole_lucrare(V_ID_LUCRARE, V_ID_UTIL, V_ID_SECTIE); END IF; - + end actualizeaza_lucrare; ---------------------------------------------------------------------------------- procedure actualizeaza_articole_lucrare(V_ID_LUCRARE IN NUMBER, @@ -1145,14 +1188,14 @@ create or replace package body PACK_COMENZI is V_OPTIUNE VARCHAR2(100); begin V_OPTIUNE := 'ID_LISTA_PRETURI_PV'; - + pack_preturi.optiune_polpret_utilizator_sec(V_ID_UTIL, V_ID_SECTIE, V_OPTIUNE, V_ID_POL); - + DELETE FROM LUCRARI_ELEMENTE WHERE ID_LUCRARE = V_ID_LUCRARE; - + INSERT INTO LUCRARI_ELEMENTE (ID_LUCRARE, ID_ARTICOL, @@ -1198,7 +1241,7 @@ create or replace package body PACK_COMENZI is LEFT JOIN NOM_ARTICOLE B ON A.ID_ARTICOL = B.ID_ARTICOL WHERE A.ID_LUCRARE = V_ID_LUCRARE; - + crs_linie crs%rowtype; V_ID_LOT NOM_LUCRARI.ID_LUCRARE%TYPE; begin @@ -1206,13 +1249,13 @@ create or replace package body PACK_COMENZI is SET CANTITATE = 0 WHERE ID_LUCRARE IN (SELECT ID_LUCRARE FROM NOM_LUCRARI WHERE ID_TATA = V_ID_LUCRARE); - + open crs; loop fetch crs into crs_linie; exit when crs%notfound; - + begin SELECT ID_LUCRARE INTO V_ID_LOT @@ -1228,7 +1271,7 @@ create or replace package body PACK_COMENZI is (crs_linie.codmat, V_ID_LUCRARE) RETURNING ID_LUCRARE INTO V_ID_LOT; end; - + MERGE INTO LUCRARI_ELEMENTE A USING DUAL B ON (A.ID_LUCRARE = V_ID_LOT AND A.ID_ARTICOL = crs_linie.id_articol AND A.ID_POL = crs_linie.id_pol AND A.PRET = crs_linie.pret AND NVL(A.ID_SECTIE, -100) = NVL(crs_linie.id_sectie, -100)) @@ -1251,9 +1294,9 @@ create or replace package body PACK_COMENZI is crs_linie.pret, crs_linie.discount_unitar, crs_linie.id_sectie); - + end loop; - + close crs; end adauga_loturi; ---------------------------------------------------------------------------------- @@ -1262,7 +1305,7 @@ create or replace package body PACK_COMENZI is DELETE FROM LUCRARI_ELEMENTE WHERE ID_LUCRARE IN (SELECT ID_LUCRARE FROM NOM_LUCRARI WHERE ID_TATA = V_ID_LUCRARE); - + UPDATE NOM_LUCRARI SET STERS = 1 WHERE ID_TATA = V_ID_LUCRARE; end sterge_loturi; ---------------------------------------------------------------------------------- @@ -1298,19 +1341,19 @@ create or replace package body PACK_COMENZI is V_VALIDAT := 1; LOOP SELECT TO_CHAR(SEQ_NR_LUCRARE.NEXTVAL) INTO V_NRORD FROM DUAL; - + SELECT COUNT(*) INTO V_NR_LUCRARI FROM NOM_LUCRARI WHERE STERS = V_NESTERS AND NRORD = V_NRORD; - + IF V_NR_LUCRARI > 0 THEN V_VALIDAT := 0; ELSE V_VALIDAT := 1; END IF; - + EXIT WHEN V_VALIDAT = 1; END LOOP; return V_NRORD; @@ -1327,7 +1370,7 @@ create or replace package body PACK_COMENZI is V_OPTIUNE_CANT IN NUMBER, V_ID_UTIL IN NUMBER, V_ID_COMANDA_NOU OUT NUMBER) is - + V_NR_COMANDA varchar2(100); V_DATA_COMANDA date; V_ID_PART NOM_PARTENERI.ID_PART%TYPE; @@ -1367,13 +1410,13 @@ create or replace package body PACK_COMENZI is V_PROC_DISCOUNT FROM COMENZI WHERE ID_COMANDA = V_ID_COMANDA; - + V_NR_COMANDA := pack_comenzi.genereaza_nr_comanda(); V_DATA_COMANDA := SYSDATE; V_DATA_LIVRARE := V_DATA_COMANDA + NVL(to_number(pack_comenzi.extrage_optiuni(pack_sesiune.getoptiunefirma('ORE_LIVRARE'), V_ID_SECTIE)), 0) / 24; - + IF V_OPTIUNE_CANT IS NULL THEN BEGIN SELECT NVL(to_number(pack_comenzi.extrage_optiuni(pack_sesiune.getoptiunefirma('COPIERECANTITATE'), @@ -1390,7 +1433,7 @@ create or replace package body PACK_COMENZI is ELSE V_COPIERECANTITATE := V_OPTIUNE_CANT; END IF; - + CASE WHEN V_INTERNA = 1 THEN V_OPTIUNE := 'ID_LISTA_PRETURI_PV'; @@ -1399,12 +1442,12 @@ create or replace package body PACK_COMENZI is WHEN V_INTERNA = 3 THEN V_OPTIUNE := 'IDPOLITICAPRET'; END CASE; - + pack_preturi.optiune_polpret_utilizator_sec(V_ID_UTIL, V_ID_SECTIE, V_OPTIUNE, V_ID_POL); - + INSERT INTO COMENZI (NR_COMANDA, DATA_COMANDA, @@ -1438,7 +1481,7 @@ create or replace package body PACK_COMENZI is V_ID_SUCURSALA, V_PROC_DISCOUNT) RETURNING id_comanda INTO V_ID_COMANDA_NOU; - + IF V_COPIERECANTITATE = 1 THEN INSERT INTO comenzi_elemente (id_comanda, @@ -1514,17 +1557,17 @@ create or replace package body PACK_COMENZI is procedure copiaza_comenzi(V_SIR_ID_COMANDA IN VARCHAR2, V_SEPARATOR_PARAM IN VARCHAR2, V_ID_UTIL IN NUMBER) is - + TYPE num_rec IS RECORD( id_comanda dbms_sql.Number_Table); numtab num_rec; - + V_ID_COMANDA_NOU COMENZI.ID_COMANDA%TYPE; V_SEPARATOR VARCHAR2(5); V_COPIERECANTITATE NUMBER(1); begin V_SEPARATOR := NVL(V_SEPARATOR_PARAM, ','); - + BEGIN SELECT TO_NUMBER(VARVALUE) INTO V_COPIERECANTITATE @@ -1535,7 +1578,7 @@ create or replace package body PACK_COMENZI is RAISE_APPLICATION_ERROR(-20000, 'Nu ati setat optiunea pentru copierea cantitatilor pe comenzi!'); END; - + SELECT TO_NUMBER(substr(V_SIR_ID_COMANDA, decode(rownum, 1, @@ -1557,23 +1600,23 @@ create or replace package body PACK_COMENZI is FROM dual CONNECT BY level <= length(V_SIR_ID_COMANDA) - length(REPLACE(V_SIR_ID_COMANDA, V_SEPARATOR)); - + FOR i IN 1 .. numtab.id_comanda.count LOOP pack_comenzi.copiaza_comanda(numtab.id_comanda(i), V_COPIERECANTITATE, V_ID_UTIL, V_ID_COMANDA_NOU); END LOOP; - + end copiaza_comenzi; ---------------------------------------------------------------------------------- procedure sectii_utilizator(V_ID_UTIL IN NUMBER, V_ID_SUCURSALA IN NUMBER, p_cursor OUT pack_types.tip_cursor) IS -- sectiile la care este asociat partenerul legat de utilizator - + begin - + open p_cursor for select ps.id_sectie, s.sectie from asociere_parteneri_sectii ps @@ -1585,19 +1628,19 @@ create or replace package body PACK_COMENZI is and NVL2(V_ID_SUCURSALA, s.id_sucursala, -99) = NVL(V_ID_SUCURSALA, -99) order by s.sectie; - + end sectii_utilizator; ---------------------------------------------------------------------------------- function extrage_optiuni(tcLista varchar2, tnId number) return varchar2 is - + lcLista varchar2(1000); lnNrOptiuni number(3) := 0; lcExtragOptId varchar2(500); lcId_extras varchar2(10); lcReturn varchar2(100); - + begin - + lcLista := trim(tcLista); lnNrOptiuni := Getwordcount(lcLista, ';'); for i in 1 .. lnNrOptiuni loop @@ -1607,7 +1650,7 @@ create or replace package body PACK_COMENZI is lcReturn := GETWORDNUM(lcExtragOptId, 2, '::'); end if; end loop; - + RETURN lcReturn; end extrage_optiuni; ---------------------------------------------------------------------------------- @@ -1616,7 +1659,7 @@ create or replace package body PACK_COMENZI is lcLista varchar2(1000); lnId number(5) := 0; begin - + lnId := tnId; begin SELECT VARVALUE @@ -1628,14 +1671,14 @@ create or replace package body PACK_COMENZI is raise_application_error(-20000, 'Nu este setata perioada de dinaintea termenului de executie pentru care o lucrare este considerata inchisa!'); end; - + V_NR_ORE := to_number(pack_comenzi.extrage_optiuni(lcLista, lnId)); - + return V_NR_ORE; end; ---------------------------------------------------------------------------------- procedure raport_proc_vanzari_sterge(V_ID_COMRAPVANZ IN NUMBER) is - + begin delete from comrapvanzelem where ID_COMRAPVANZ = V_ID_COMRAPVANZ; delete from comrapvanz where ID_COMRAPVANZ = V_ID_COMRAPVANZ; @@ -1657,7 +1700,7 @@ create or replace package body PACK_COMENZI is V_PROCENT_BD NUMBER(10, 4); V_TOATE_GRUPELE NUMBER(1); V_ID_GRUPA_ART GEST_ART_GR.ID_GRUPA%TYPE; - + V_ID_COMRAPVANZ COMRAPVANZ.ID_COMRAPVANZ%TYPE; V_LISTA_GESTIUNI_DEPOZIT VARCHAR2(1000); V_DATAORA_I0 DATE := TRUNC(V_DATAORA_I, 'MONTH'); -- 1 ale lunii de inceput; @@ -1665,7 +1708,7 @@ create or replace package body PACK_COMENZI is begin V_AN_I := EXTRACT(YEAR FROM V_DATAORA_I); V_LUNA_I := EXTRACT(MONTH FROM V_DATAORA_I); - + V_AN_F := EXTRACT(YEAR FROM V_DATAORA_S); V_LUNA_F := EXTRACT(MONTH FROM V_DATAORA_S); V_PROCENT_BD := to_number(nvl(pack_sesiune.getoptiunefirma('PROCVANZPER'), @@ -1678,20 +1721,20 @@ create or replace package body PACK_COMENZI is ELSE V_ID_GRUPA_ART := 0; END IF; - + V_LISTA_GESTIUNI_DEPOZIT := pack_comenzi.extrage_optiuni(pack_sesiune.getoptiunefirma('LISTA_GESTIUNI_DEPOZIT'), V_ID_SECTIE); - + IF V_PROCENT_BD <> V_PROCENT THEN UPDATE OPTIUNI SET VARVALUE = TO_CHAR(V_PROCENT) WHERE VARNAME = 'PROCVANZPER'; - + V_PROCENT_BD := V_PROCENT; END IF; - + V_PROCENT_BD := V_PROCENT_BD / 100; - + INSERT INTO COMRAPVANZ (DATAI, DATAS, ID_GRUPE, PROCENT, ID_SECTIE, ID_UTIL, ID_SUCURSALA) VALUES @@ -1703,7 +1746,7 @@ create or replace package body PACK_COMENZI is V_ID_UTIL, V_ID_SUCURSALA) RETURNING ID_COMRAPVANZ INTO V_ID_COMRAPVANZ; - + INSERT INTO COMRAPVANZELEM (ID_COMRAPVANZ, ID_GESTIUNE, @@ -1821,7 +1864,7 @@ create or replace package body PACK_COMENZI is and id_articol in (select id_articol from crsarticole) group by id_articol) c1 on a1.id_articol = c1.id_articol; - + -- aceleasi coloane ca si cursorul din completeaza_raport OPEN V_CURSOR FOR SELECT A.ID_COMRAPVANZ, @@ -1850,7 +1893,7 @@ create or replace package body PACK_COMENZI is ON C.ID_SUBGRUPA = D.ID_SUBGRUPA WHERE A.ID_COMRAPVANZ = V_ID_COMRAPVANZ ORDER BY B.NUME_GESTIUNE, D.SUBGRUPA, C.DENUMIRE; - + end raport_proc_vanzari; ---------------------------------------------------------------------------------- procedure completeaza_raport(V_ID_COMRAPVANZ IN NUMBER, @@ -1874,12 +1917,12 @@ create or replace package body PACK_COMENZI is WHERE ID_COMRAPVANZ = V_ID_COMRAPVANZ) A LEFT JOIN COMRAPVANZ B ON A.ID_COMRAPVANZ = B.ID_COMRAPVANZ; - + V_AN_I := EXTRACT(YEAR FROM V_DATAORA_I); V_LUNA_I := EXTRACT(MONTH FROM V_DATAORA_I); V_AN_F := EXTRACT(YEAR FROM V_DATAORA_S); V_LUNA_F := EXTRACT(MONTH FROM V_DATAORA_S); - + MERGE INTO COMRAPVANZELEM A USING ( WITH CRS_GESTIUNI AS @@ -1959,7 +2002,7 @@ create or replace package body PACK_COMENZI is B.STOCI, B.VANZARI, B.STOCF); - + -- aceleasi coloane ca si cursorul din raport_proc_vanzari OPEN V_CURSOR FOR SELECT A.ID_COMRAPVANZ, @@ -1989,7 +2032,7 @@ create or replace package body PACK_COMENZI is WHERE A.ID_COMRAPVANZ = V_ID_COMRAPVANZ AND A.ID_COMRAPVANZELEM > V_ID_MAX ORDER BY B.NUME_GESTIUNE, D.SUBGRUPA, C.DENUMIRE; - + end completeaza_raport; ------------------------------------------------------------- @@ -2026,7 +2069,7 @@ create or replace package body PACK_COMENZI is ON C.ID_SUBGRUPA = D.ID_SUBGRUPA WHERE A.ID_COMRAPVANZ = V_ID_COMRAPVANZ ORDER BY B.NUME_GESTIUNE, D.SUBGRUPA, C.DENUMIRE; - + end raport_proc_vanzari_viz; ---------------------------------------------------------------------------------- procedure actualizeaza_raport(V_ID_COMRAPVANZ IN NUMBER, @@ -2055,16 +2098,16 @@ create or replace package body PACK_COMENZI is V_LISTA_ERORI VARCHAR2(32000); begin V_NR_COMENZI_GENERATE := 0; - + -- generare comenzi SELECT ID_SECTIE, ID_UTIL, ID_SUCURSALA, DATAORA INTO V_ID_SECTIE, V_ID_UTIL, V_ID_SUCURSALA, V_DATA_COMANDA FROM COMRAPVANZ WHERE ID_COMRAPVANZ = V_ID_COMRAPVANZ; - + V_ID_POL := to_number(pack_comenzi.extrage_optiuni(pack_sesiune.getoptiunefirma('IDPOLITICAPRET'), V_ID_SECTIE)); - + IF V_ID_POL IS NULL THEN RAISE_APPLICATION_ERROR(-20000, 'Nu este setata politica de preturi implicita pentru comenzile de la subunitati!'); @@ -2078,7 +2121,7 @@ create or replace package body PACK_COMENZI is 'Politica de preturi implicita nu mai este valabila!'); END IF; END IF; - + SELECT STRINGAGG(ID_ARTICOL) INTO V_LISTA_ERORI FROM (SELECT DISTINCT ID_ARTICOL @@ -2092,7 +2135,7 @@ create or replace package body PACK_COMENZI is FROM CRM_POLITICI_PRET_ART WHERE ID_POL = V_ID_POL AND PRET <> 0); - + IF V_LISTA_ERORI IS NOT NULL THEN OPEN V_CURSOR FOR SELECT DENUMIRE, CODMAT @@ -2101,12 +2144,12 @@ create or replace package body PACK_COMENZI is (SELECT TO_NUMBER(X) AS ID FROM table(charc2collection(V_LISTA_ERORI, ','))) ORDER BY DENUMIRE; - + ELSE UPDATE COMRAPVANZ SET COMPLETAT = 1 WHERE ID_COMRAPVANZ = V_ID_COMRAPVANZ; - + MERGE INTO COMRAPVANZELEM A USING (select to_number(extractvalue(column_value, '/crsraportvanzari/id')) as ID, @@ -2119,17 +2162,17 @@ create or replace package body PACK_COMENZI is ON (A.ID_COMRAPVANZELEM = B.ID) WHEN MATCHED THEN UPDATE SET CANTITATE = B.CANTITATE, VALIDAT = 1; - + V_DATA_LIVRARE := V_DATA_COMANDA + NVL(to_number(pack_comenzi.extrage_optiuni(pack_sesiune.getoptiunefirma('ORE_LIVRARE'), V_ID_SECTIE)), 0) / 24; - + OPEN CRS; LOOP FETCH CRS INTO CRS_LINIE; EXIT WHEN CRS%NOTFOUND; - + INSERT INTO COMENZI (NR_COMANDA, DATA_COMANDA, @@ -2149,9 +2192,9 @@ create or replace package body PACK_COMENZI is V_ID_SECTIE, V_ID_SUCURSALA) RETURNING ID_COMANDA INTO V_ID_COMANDA; - + V_NR_COMENZI_GENERATE := V_NR_COMENZI_GENERATE + 1; - + INSERT INTO COMENZI_ELEMENTE (ID_COMANDA, ID_ARTICOL, @@ -2189,10 +2232,10 @@ create or replace package body PACK_COMENZI is ON B.ID_POL = C.ID_POL AND A.ID_ARTICOL = C.ID_ARTICOL ORDER BY A.SUBGRUPA, A.DENUMIRE; - + END LOOP; CLOSE CRS; - + OPEN V_CURSOR FOR SELECT DENUMIRE FROM NOM_ARTICOLE WHERE 1 = 2; END IF; @@ -2222,7 +2265,7 @@ create or replace package body PACK_COMENZI is TO_DATE(V_AN || V_LUNA, 'YYYYMM') AND NVL(A.ID_SECTIE, -99) = NVL(V_ID_SECTIE, -99) ORDER BY A.DATAORA DESC; - + end centralizator_rapoarte; ---------------------------------------------------------------------------------- procedure listeaza_raport(V_ID_COMRAPVANZ IN NUMBER, @@ -2233,7 +2276,7 @@ create or replace package body PACK_COMENZI is INTO V_DATA FROM COMRAPVANZ WHERE ID_COMRAPVANZ = V_ID_COMRAPVANZ; - + OPEN V_CURSOR FOR SELECT A.ID_COMRAPVANZ, A.ID_COMRAPVANZELEM, @@ -2269,7 +2312,7 @@ create or replace package body PACK_COMENZI is INTO V_DATA, V_DATAI, V_DATAS FROM COMRAPVANZ WHERE ID_COMRAPVANZ = V_ID_COMRAPVANZ; - + OPEN V_CURSOR FOR SELECT E.GRUPA, D.SUBGRUPA, @@ -2303,7 +2346,7 @@ create or replace package body PACK_COMENZI is C.CODMAT, C.UM ORDER BY E.GRUPA, D.SUBGRUPA, B.DENUMIRE, C.DENUMIRE, C.CODMAT; - + end listeaza_raport_vz_fz; ---------------------------------------------------------------------------------- @@ -2323,7 +2366,7 @@ create or replace package body PACK_COMENZI is JOIN COMRAPVANZ V ON VE.ID_COMRAPVANZ = V.ID_COMRAPVANZ WHERE ID_COMRAPVANZELEM = V_ID_COMRAPVANZELEM; - + OPEN V_CURSOR FOR SELECT R.ID_ARTICOL, G.GRUPA, @@ -2353,7 +2396,7 @@ create or replace package body PACK_COMENZI is EXTRACT(YEAR FROM V_DATAS) AND R.ID_TIP_RULAJ = 0 ORDER BY R.DATAORA; - + end rap_vanz_per_detaliu; ---------------------------------------------------------------------------------- @@ -2364,7 +2407,7 @@ create or replace package body PACK_COMENZI is INTO V_ID_SECTIE FROM COMENZI WHERE ID_COMANDA = V_ID_COMANDA; - + return pack_sesiune.verifica_acces('COMENZI_ELEMENTE', V_ID_COMANDA, pack_comenzi.extrage_optiuni(pack_sesiune.getoptiunefirma('MINSESCOMANDA'), @@ -2397,17 +2440,17 @@ create or replace package body PACK_COMENZI is tnIdUtil IN vanzari.id_util%type DEFAULT -3, tcMesaj OUT VARCHAR2, tnIdVanzare OUT VANZARI.ID_VANZARE%TYPE) IS - + -- tdDataAct - provizoriu pentru inregistrarea unor bonuri care nu s-au inregistrat in baza de date -- tnIncasat: 0 = neincasat; 1 = incasat total; 2 = incasat partial (avans) -- tcTipIncasare: BONFISCAL/CARD/TICHETE/CHITANTA lnTipIncasare number(2); - + nTipIncasareBonFiscal NUMBER := 2; nTipIncasareCardBancar NUMBER := 3; nTipIncasareTichete NUMBER := 5; nTipIncasareChitanta NUMBER := 11; - + lnAn calendar.anul%type := tnAn; lnLuna calendar.luna%type := tnLuna; lnTvaIncasare calendar.tva_incasare%type; @@ -2415,7 +2458,7 @@ create or replace package body PACK_COMENZI is ldDataIreg act.dataireg%type; ldDataScad act.datascad%type; ldDataCurs act.dataact%type; - + lcSerieFactura vanzari.serie_act%type; lnNrAct vanzari.numar_act%type := tnNrAct; lnIdResponsabil act.id_responsabil%type; @@ -2423,15 +2466,15 @@ create or replace package body PACK_COMENZI is lcDescriere varchar2(100); lnTip vanzari.tip%type := 3; -- factura din comanda lnIdFdoc act.id_fdoc%type; - + lnIdValuta act.id_valuta%type; lnInValuta number(1) := 0; lnIdUtil vanzari.id_util%type := nvl(tnIdUtil, -3); - + lnTotftva act.suma%type; lnTotTva act.suma%type; lnTotcTva act.suma%type; - + ldDataExp vanzari.dataora_exp%type; lnDiscountFactura vanzari.discount%type := 0; lnIdDelegat vanzari.id_delegat%type := tnIdDelegat; @@ -2440,10 +2483,10 @@ create or replace package body PACK_COMENZI is lcTextAditional varchar2(100) := tcTextAditional; lnDiscountEvidentiat vanzari.discount_evidentiat%type := 0; lnParametruAditional number(1); - + lcListaIncasare varchar2(1000); -- V_LISTA_INCASARE : tip1|valoare1|id_bancasa1;tip2|valoare2|id_bancasa2 (pentru incasari cu mai multe tipuri ex: NUMERAR + CARD + TICHETE) V_CURSOR_VERIFICARE pack_facturare.cursor_facturare; - + lnIdSucursala act.id_sucursala%type; lnIdSectie act.id_sectie%type; lnIdVenChelt act.id_venchelt%type; @@ -2451,7 +2494,7 @@ create or replace package body PACK_COMENZI is lnIdPartCasa act.id_partd%type; lnIdSet act.Id_set%type := 25002; lnIdLucrare act.id_lucrare%type; - + lnIdGestiune stoc.id_gestiune%type; lnSumaIncasat act.suma%type; lnIdTipDocFactura number(2) := pack_facturare.nid_tipfactura; @@ -2469,10 +2512,10 @@ create or replace package body PACK_COMENZI is ldDataIreg := ldDataAct; ldDataScad := ldDataAct; ldDataCurs := ldDataAct; - + pack_sesiune.setAn(lnAn); pack_sesiune.setLuna(lnLuna); - + begin SELECT TVA_INCASARE INTO lnTvaIncasare @@ -2485,7 +2528,7 @@ create or replace package body PACK_COMENZI is 'Nu s-a deschis luna ' || lpad(lnLuna, 2, '0') || '/' || lnAn || '!'); end; - + lnTipIncasare := case when tcTipIncasare = 'BONFISCAL' then pack_facturare.nTipIncasareBonFiscal @@ -2498,19 +2541,19 @@ create or replace package body PACK_COMENZI is else pack_facturare.nTipIncasareChitanta end; - + lnIdFdoc := TO_NUMBER(pack_sesiune.getoptiunefirma('ID_FDOC_FACT')); -- FEL DOCUMENT DIN OPTIUNI if lnIdFdoc is null then tcMesaj := 'Nu s-a configurat Tip Document Factura (ID_FDOC_FACT) in Optiuni!'; RAISE_APPLICATION_ERROR(-20001, tcMesaj); end if; - + lnIdSerieFactura := to_number(pack_sesiune.getoptiunefirma('COM_ID_SERIE_FACT')); if lnIdSerieFactura is null then tcMesaj := 'Nu s-a configurat Serie Factura (COM_ID_SERIE_FACT) in Optiuni!'; RAISE_APPLICATION_ERROR(-20001, tcMesaj); end if; - + -- obtin lcSerieFactura, lnNrAct lcSerieFactura := pack_serii_numere.citeste_serie(lnIdSerieFactura); if NVL(lnNrAct, 0) = 0 then @@ -2531,7 +2574,7 @@ create or replace package body PACK_COMENZI is join crm_politici_preturi p on e.id_pol = p.id_pol where c.id_comanda = tnIdComanda; - + pack_facturare.initializeaza_date_factura(ldDataIreg, lnIdFdoc, ldDataAct, @@ -2555,7 +2598,7 @@ create or replace package body PACK_COMENZI is lnTvaIncasare, lnIdSucursala, lnIdUtil); - + insert into vanzari_detalii_temp (id_pol, id_articol, @@ -2613,9 +2656,9 @@ create or replace package body PACK_COMENZI is on e.id_pol = ppa.id_pol and e.id_articol = ppa.id_articol where c.id_comanda = tnIdComanda; - + select count(*) into lnRec from vanzari_detalii_temp; - + -- totaluri pentru inregistrarea facturii si incasarii select sum(pack_sesiune.calculeaza_total_fara_tva(e.pret, null, @@ -2655,7 +2698,7 @@ create or replace package body PACK_COMENZI is on e.id_pol = ppa.id_pol and e.id_articol = ppa.id_articol WHERE e.id_comanda = tnIdComanda; - + if tnIncasat <> 0 then lnSumaIncasat := case when tnIncasat = 1 then @@ -2665,11 +2708,11 @@ create or replace package body PACK_COMENZI is end; -- tip|valoare|id_bancasa|ascc|scd|ascd lnIdPartCasa := to_number(pack_sesiune.getoptiunefirma('ID_PART_CASA')); - + lcListaIncasare := lnTipIncasare || '|' || lnSumaIncasat || '|' || lnIdPartCasa || '|' || 'xxxx|5311|xxxx'; end if; - + ldDataExp := SYSDATE; pack_facturare.scrie_factura2(lnTOTFTVA, lnTOTTVA, @@ -2688,7 +2731,7 @@ create or replace package body PACK_COMENZI is lnParametruAditional, tnIdVanzare, V_CURSOR_VERIFICARE); - + -- SCRIU VANZAREA CHIAR DACA NU SUNT COMPLETATE ANALITICELE/PARTENERII, SI INTORC MESAJ DE ATENTIONARE if tnIdVanzare is null then pack_facturare.finalizeaza_factura(NULL, @@ -2706,7 +2749,7 @@ create or replace package body PACK_COMENZI is /* RAISE_APPLICATION_ERROR(-20000, 'Nu s-au configurat partenerii si/sau conturile analitice!');*/ end if; - + <> null; end factureaza_comanda; diff --git a/api/database-scripts/05_pack_import_parteneri.pck b/api/database-scripts/05_pack_import_parteneri.pck new file mode 100644 index 0000000..ca5d802 --- /dev/null +++ b/api/database-scripts/05_pack_import_parteneri.pck @@ -0,0 +1,824 @@ +CREATE OR REPLACE PACKAGE PACK_IMPORT_PARTENERI AS + + -- ==================================================================== + -- CONSTANTS + -- ==================================================================== + + -- ID utilizator sistem pentru toate operatiile + C_ID_UTIL_SISTEM CONSTANT NUMBER := -3; + + -- Valori default pentru adrese incomplete + C_JUD_DEFAULT CONSTANT VARCHAR2(50) := 'BUCURESTI'; + N_ID_JUD_DEFAULT CONSTANT NUMBER(10) := 10; + C_LOCALITATE_DEFAULT CONSTANT VARCHAR2(50) := 'BUCURESTI SECTORUL 1'; + N_ID_LOCALITATE_DEFAULT CONSTANT NUMBER(10) := 1797; + C_SECTOR_DEFAULT CONSTANT VARCHAR2(50) := 'SECTOR 1'; + C_TARA_DEFAULT CONSTANT VARCHAR2(50) := 'ROMANIA'; + N_ID_TARA_DEFAULT CONSTANT NUMBER(10) := 1; + + -- Lungimi maxime pentru validari + C_MIN_COD_FISCAL CONSTANT NUMBER := 3; + C_CUI_PERS_FIZICA CONSTANT NUMBER := 13; -- CNP are 13 cifre + + -- Variabila package pentru ultima eroare (pentru orchestrator VFP) + g_last_error VARCHAR2(4000); + + -- ==================================================================== + -- 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 + -- ==================================================================== + + /** + * Procedura principala pentru cautarea sau crearea unui partener + * SCHIMBAT din FUNCTION in PROCEDURE pentru compatibilitate cu DML operations + * + * Algoritm: + * 1. Cauta dupa cod_fiscal (daca > 3 caractere) + * 2. Cauta dupa denumire exacta + * 3. Creeaza partener nou cu pack_def.adauga_partener() + * 4. Adauga 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 in format: "JUD:Bucuresti;BUCURESTI;Str.Victoriei;10" + * @param p_telefon Numar de telefon + * @param p_email Adresa de email + * @param p_is_persoana_juridica 1=persoana juridica, 0=persoana fizica, NULL=auto-detect prin CNP + * @param p_id_partener OUT ID_PART al partenerului gasit sau creat + */ + PROCEDURE cauta_sau_creeaza_partener(p_cod_fiscal IN VARCHAR2, + p_denumire IN VARCHAR2, + p_registru IN VARCHAR2, + p_is_persoana_juridica IN NUMBER DEFAULT NULL, + p_id_partener OUT NUMBER); + + procedure cauta_sau_creeaza_adresa(p_id_part IN NUMBER, + p_adresa IN VARCHAR2, + p_phone IN VARCHAR2, + p_email IN VARCHAR2, + p_id_adresa OUT NUMBER); + /** + * Parseaza o adresa din format semicolon in componentele individuale + * + * Format input: "JUD:Bucuresti;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 Judetul extras (default: Bucuresti) + * @param p_localitate OUT Localitatea extrasa (default: BUCURESTI) + * @param p_strada OUT Strada si numarul + * @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_numar OUT VARCHAR2, + p_sector OUT VARCHAR2); + + -- ==================================================================== + -- UTILITY FUNCTIONS (PUBLIC pentru testare) + -- ==================================================================== + + /** + * Cauta partener dupa cod fiscal + * @param p_cod_fiscal Codul fiscal de cautat + * @return ID_PART sau NULL daca nu gaseste + */ + FUNCTION cauta_partener_dupa_cod_fiscal(p_cod_fiscal IN VARCHAR2) + RETURN NUMBER; + + /** + * Cauta partener dupa denumire exacta + * @param p_denumire Denumirea de cautat + * @return ID_PART sau NULL daca nu gaseste + */ + FUNCTION cauta_partener_dupa_denumire(p_denumire IN VARCHAR2) RETURN NUMBER; + + /** + * Verifica daca un cod fiscal apartine unei persoane fizice (CNP) + * @param p_cod_fiscal Codul fiscal de verificat + * @return 1 daca este persoana fizica, 0 daca este companie + */ + FUNCTION este_persoana_fizica(p_cod_fiscal IN VARCHAR2) RETURN NUMBER; + + /** + * Separa numele complet in nume si 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); + + -- ==================================================================== + -- ERROR MANAGEMENT FUNCTIONS (similar cu PACK_JSON) + -- ==================================================================== + + /** + * Returneaza ultima eroare pentru orchestrator VFP + */ + FUNCTION get_last_error RETURN VARCHAR2; + + /** + * Reseteaza eroarea + */ + PROCEDURE clear_error; + +END PACK_IMPORT_PARTENERI; +/ +CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_PARTENERI AS + + -- ================================================================ + -- ERROR MANAGEMENT FUNCTIONS IMPLEMENTATION + -- ================================================================ + FUNCTION get_last_error RETURN VARCHAR2 IS + BEGIN + RETURN g_last_error; + END get_last_error; + + PROCEDURE clear_error IS + BEGIN + g_last_error := NULL; + END clear_error; + + -- ==================================================================== + -- PRIVATE FUNCTIONS + -- ==================================================================== + + /** + * Valideaza datele unui partener inainte de creare + */ + FUNCTION valideaza_date_partener(p_cod_fiscal IN VARCHAR2, + p_denumire IN VARCHAR2) RETURN BOOLEAN IS + BEGIN + -- Verificari obligatorii + IF p_denumire IS NULL THEN + g_last_error := 'Denumirea partenerului nu poate fi goala'; + RETURN FALSE; + END IF; + + -- Cod fiscal optional, dar daca exista trebuie sa aiba 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 + g_last_error := 'Codul fiscal trebuie sa aiba minim ' || + C_MIN_COD_FISCAL || ' caractere'; + RETURN FALSE; + END IF; + END IF; + + RETURN TRUE; + + EXCEPTION + WHEN OTHERS THEN + g_last_error := 'ERROR in valideaza_date_partener: ' || SQLERRM; + RETURN FALSE; + END valideaza_date_partener; + + /** + * Curata si standardizeaza textul pentru cautare + */ + 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); + + -- pINFO('Cautare partener dupa cod_fiscal: ' || v_cod_fiscal_curat, 'IMPORT_PARTENERI'); + + -- Cautare in 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; -- In caz de duplicate, luam primul + + -- pINFO('Gasit partener cu cod_fiscal ' || v_cod_fiscal_curat || ': ID_PART=' || v_id_part, 'IMPORT_PARTENERI'); + RETURN v_id_part; + + EXCEPTION + WHEN NO_DATA_FOUND THEN + -- pINFO('Nu s-a gasit partener cu cod_fiscal: ' || v_cod_fiscal_curat, 'IMPORT_PARTENERI'); + RETURN NULL; + + WHEN TOO_MANY_ROWS THEN + -- Luam primul gasit + 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; + + pINFO('WARNING: Multiple parteneri cu acelasi cod_fiscal ' || + v_cod_fiscal_curat || '. Selectat ID_PART=' || v_id_part, + 'IMPORT_PARTENERI'); + RETURN v_id_part; + END; + + EXCEPTION + WHEN OTHERS THEN + pINFO('ERROR in cauta_partener_dupa_cod_fiscal: ' || SQLERRM, + 'IMPORT_PARTENERI'); + 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 THEN + RETURN NULL; + END IF; + + v_denumire_curata := curata_text_cautare(p_denumire); + + -- pINFO('Cautare partener dupa denumire: ' || v_denumire_curata, 'IMPORT_PARTENERI'); + + -- Cautare in NOM_PARTENERI + BEGIN + SELECT id_part + INTO v_id_part + FROM nom_parteneri + WHERE UPPER(TRIM(denumire)) = v_denumire_curata + AND ROWNUM = 1; -- In caz de duplicate, luam primul + + -- pINFO('Gasit partener cu denumirea ' || v_denumire_curata || ': ID_PART=' || v_id_part, 'IMPORT_PARTENERI'); + RETURN v_id_part; + + EXCEPTION + WHEN NO_DATA_FOUND THEN + -- pINFO('Nu s-a gasit partener cu denumirea: ' || v_denumire_curata, 'IMPORT_PARTENERI'); + RETURN NULL; + + WHEN TOO_MANY_ROWS THEN + -- Luam primul gasit + 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; + + pINFO('WARNING: Multiple parteneri cu aceeasi denumire ' || + v_denumire_curata || '. Selectat ID_PART=' || v_id_part, + 'IMPORT_PARTENERI'); + RETURN v_id_part; + END; + + EXCEPTION + WHEN OTHERS THEN + pINFO('ERROR in cauta_partener_dupa_denumire: ' || SQLERRM, + 'IMPORT_PARTENERI'); + 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 + -- pINFO('ERROR in este_persoana_fizica: ' || SQLERRM, 'IMPORT_PARTENERI'); + 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 THEN + p_nume := NULL; + p_prenume := NULL; + RETURN; + END IF; + + v_denumire_curata := TRIM(p_denumire_completa); + + -- Cauta primul spatiu + 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 exista spatiu, totul este nume + p_nume := v_denumire_curata; + p_prenume := NULL; + END IF; + + -- Validare lungimi maxime (sa nu depaseasca 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 + -- pINFO('ERROR in separa_nume_prenume: ' || SQLERRM, 'IMPORT_PARTENERI'); + 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_numar 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); + v_pozitie NUMBER; + v_strada VARCHAR2(100); + BEGIN + -- p_adresa_text: JUD: JUDET;LOCALITATE;STRADA, NR + -- Initializare 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 THEN + -- pINFO('Adresa goala, se folosesc valorile default', 'IMPORT_PARTENERI'); + RETURN; + END IF; + + v_adresa_curata := TRIM(p_adresa_text); + + -- pINFO('Parsare adresa: ' || v_adresa_curata, 'IMPORT_PARTENERI'); + + -- Split dupa 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 + -- pINFO('Nu s-au gasit componente in adresa', 'IMPORT_PARTENERI'); + RETURN; + END IF; + + -- Parsare in functie de numarul 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, 100); + p_strada := SUBSTR(v_componente(2), 1, 100); + + ELSIF v_count >= 3 THEN + -- Verifica daca prima componenta contine "JUD:" + v_temp_judet := v_componente(1); + + IF UPPER(v_temp_judet) LIKE 'JUD:%' THEN + -- Format: JUD:Bucuresti;BUCURESTI;Strada,Numar + p_judet := SUBSTR(REPLACE(v_temp_judet, 'JUD:', ''), 1, 100); + p_localitate := SUBSTR(v_componente(2), 1, 100); + p_strada := SUBSTR(v_componente(3), 1, 100); + v_strada := p_strada; + + -- Combina strada si numarul + v_pozitie := INSTR(v_strada, ','); + IF v_pozitie > 0 THEN + p_strada := TRIM(SUBSTR(v_strada, 1, v_pozitie - 1)); + p_numar := TRIM(SUBSTR(v_strada, v_pozitie + 1)); + + -- Elimina prefixele din numele strazii (STR., STRADA, BD., BDUL., etc.) + /* v_nume_strada := TRIM(REGEXP_REPLACE(v_nume_strada, + '^(STR\.|STRADA|BD\.|BDUL\.|CALEA|PIATA|PTA\.|AL\.|ALEEA|SOS\.|SOSEA|INTR\.|INTRAREA)\s*', + '', 1, 1, 'i')); */ + + -- Elimina prefixele din numarul strazii (NR., NUMARUL, etc.) + p_numar := TRIM(REGEXP_REPLACE(p_numar, + '^(NR\.|NUMARUL|NUMAR)\s*', + '', + 1, + 1, + 'i')); + END IF; + + ELSE + -- Format: Localitate;Strada;Altceva + p_localitate := SUBSTR(v_componente(1), 1, 100); + p_strada := SUBSTR(v_componente(2) || ' ' || v_componente(3), + 1, + 100); + END IF; + END IF; + + -- Curatare finala + p_judet := UPPER(TRIM(p_judet)); + p_localitate := UPPER(TRIM(p_localitate)); + p_strada := UPPER(TRIM(p_strada)); + p_numar := UPPER(TRIM(p_numar)); + p_sector := UPPER(TRIM(p_sector)); + + -- Fallback pentru campuri goale + IF p_judet IS NULL THEN + p_judet := C_JUD_DEFAULT; + END IF; + + IF p_localitate IS NULL THEN + p_localitate := C_LOCALITATE_DEFAULT; + END IF; + + IF p_sector IS NULL THEN + p_sector := C_SECTOR_DEFAULT; + END IF; + + -- pINFO('Adresa parsata: JUD=' || p_judet || ', LOC=' || p_localitate || + -- ', STRADA=' || NVL(p_strada, 'NULL') || ', SECTOR=' || p_sector, 'IMPORT_PARTENERI'); + + EXCEPTION + WHEN OTHERS THEN + g_last_error := 'ERROR in parseaza_adresa_semicolon: ' || SQLERRM; + -- pINFO('ERROR in parseaza_adresa_semicolon: ' || SQLERRM, 'IMPORT_PARTENERI'); + + -- Pastram valorile default in caz de eroare + p_judet := C_JUD_DEFAULT; + p_localitate := C_LOCALITATE_DEFAULT; + p_sector := C_SECTOR_DEFAULT; + END parseaza_adresa_semicolon; + + PROCEDURE cauta_sau_creeaza_partener(p_cod_fiscal IN VARCHAR2, + p_denumire IN VARCHAR2, + p_registru IN VARCHAR2, + p_is_persoana_juridica IN NUMBER DEFAULT NULL, + p_id_partener OUT NUMBER) IS + + v_id_part NUMBER; + 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); + + BEGIN + -- Resetare eroare la inceputul procesarii + clear_error; + + -- pINFO('=== INCEPUT cauta_sau_creeaza_partener ===', 'IMPORT_PARTENERI'); + -- pINFO('Input: cod_fiscal=' || NVL(p_cod_fiscal, 'NULL') || + -- ', denumire=' || NVL(p_denumire, 'NULL') || + -- ', adresa=' || NVL(p_adresa, 'NULL'), 'IMPORT_PARTENERI'); + + -- Validare date input + IF NOT valideaza_date_partener(p_cod_fiscal, p_denumire) THEN + g_last_error := 'Date partener invalide - validare esuata'; + p_id_partener := -1; + RETURN; + END IF; + + v_cod_fiscal_curat := TRIM(p_cod_fiscal); + v_denumire_curata := TRIM(p_denumire); + + -- STEP 1: Cautare dupa 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 + -- pINFO('Partener gasit dupa cod_fiscal. ID_PART=' || v_id_part, 'IMPORT_PARTENERI'); + -- pINFO('=== SFARSIT cauta_sau_creeaza_partener ===', 'IMPORT_PARTENERI'); + p_id_partener := v_id_part; + RETURN; + END IF; + END IF; + + -- STEP 2: Cautare dupa denumire exacta (prioritate 2) + v_id_part := cauta_partener_dupa_denumire(v_denumire_curata); + + IF v_id_part IS NOT NULL THEN + -- pINFO('Partener gasit dupa denumire. ID_PART=' || v_id_part, 'IMPORT_PARTENERI'); + -- pINFO('=== SFARSIT cauta_sau_creeaza_partener ===', 'IMPORT_PARTENERI'); + p_id_partener := v_id_part; + RETURN; + END IF; + + -- STEP 3: Creare partener nou + -- pINFO('Nu s-a gasit partener existent. Se creeaza unul nou...', 'IMPORT_PARTENERI'); + + -- Verifica tipul partenerului + -- Prioritate: parametru explicit > detectie prin CNP + IF p_is_persoana_juridica IS NOT NULL THEN + -- Foloseste informatia explicita din GoMag orders + v_este_persoana_fizica := CASE + WHEN p_is_persoana_juridica = 1 THEN + 0 + ELSE + 1 + END; + ELSE + -- Auto-detect prin CNP (comportament original) + v_este_persoana_fizica := este_persoana_fizica(v_cod_fiscal_curat); + END IF; + + IF v_este_persoana_fizica = 1 THEN + -- pINFO('Detectata persoana fizica (CUI 13 cifre)', 'IMPORT_PARTENERI'); + separa_nume_prenume(v_denumire_curata, v_nume, v_prenume); + -- pINFO('Nume separat: NUME=' || NVL(v_nume, 'NULL') || ', PRENUME=' || NVL(v_prenume, 'NULL'), 'IMPORT_PARTENERI'); + END IF; + + -- Creare partener prin pack_def + BEGIN + IF v_este_persoana_fizica = 1 THEN + -- Pentru persoane fizice + pack_def.adauga_partener(tcDenumire => v_nume, -- nume de familie pentru persoane fizice + tcNume => v_nume, + tcPrenume => v_prenume, + tcCod_fiscal => v_cod_fiscal_curat, + tcReg_comert => p_registru, + tnId_loc => NULL, + tnId_categorie_entitate => NULL, + tcPrefix => '', + tcSufix => '', + tnTip_persoana => 2, -- persoana fizica + tcBanca => '', -- nu avem info bancara + tcCont_banca => '', -- nu avem info bancara + tnInactiv => 0, + tcMotiv_inactiv => '', + tnId_util => C_ID_UTIL_SISTEM, + tcSir_id_tipPart => '16;17', + tcSir_id_part_del => '', + tnId_Part => v_id_part); + ELSE + -- Pentru companii + pack_def.adauga_partener(tcDenumire => v_denumire_curata, + tcNume => v_denumire_curata, + tcPrenume => '', + tcCod_fiscal => v_cod_fiscal_curat, + tcReg_comert => p_registru, + tnId_loc => NULL, + tnId_categorie_entitate => NULL, + tcPrefix => '', + tcSufix => '', + tnTip_persoana => 1, -- persoana juridica + tcBanca => '', -- nu avem info bancara + tcCont_banca => '', -- nu avem info bancara + tnInactiv => 0, + tcMotiv_inactiv => '', + tnId_util => C_ID_UTIL_SISTEM, + tcSir_id_tipPart => '16;17', + tcSir_id_part_del => '', + tnId_Part => v_id_part); + END IF; + + IF v_id_part IS NULL OR v_id_part <= 0 THEN + g_last_error := 'pack_def.adauga_partener a returnat ID invalid'; + p_id_partener := -1; + RETURN; + END IF; + + -- pINFO('Partener creat cu succes. ID_PART=' || v_id_part, 'IMPORT_PARTENERI'); + + EXCEPTION + WHEN OTHERS THEN + g_last_error := 'ERROR la crearea partenerului prin pack_def: ' || + SQLERRM; + p_id_partener := -1; + RETURN; + END; + + -- pINFO('Partener creat complet. ID_PART=' || v_id_part, 'IMPORT_PARTENERI'); + -- pINFO('=== SFARSIT cauta_sau_creeaza_partener ===', 'IMPORT_PARTENERI'); + + p_id_partener := v_id_part; + + EXCEPTION + WHEN OTHERS THEN + g_last_error := 'ERROR NEASTEPTAT in cauta_sau_creeaza_partener: ' || + SQLERRM; + p_id_partener := -1; + + END cauta_sau_creeaza_partener; + + procedure cauta_sau_creeaza_adresa(p_id_part IN NUMBER, + p_adresa IN VARCHAR2, + p_phone IN VARCHAR2, + p_email IN VARCHAR2, + p_id_adresa OUT NUMBER) is + v_judet VARCHAR2(200); + v_id_judet NUMBER(10); + v_localitate VARCHAR2(200); + v_id_localitate NUMBER(10); + v_strada VARCHAR2(1000); + v_numar VARCHAR2(1000); + v_sector VARCHAR2(100); + v_id_tara NUMBER(10); + v_principala NUMBER(1); + begin + -- Resetare eroare la inceputul procesarii + clear_error; + + IF p_id_part is null OR p_adresa IS NULL THEN + GOTO sfarsit; + END IF; + -- pINFO('Se adauga adresa pentru partenerul nou creat...', 'IMPORT_PARTENERI'); + + -- Verific daca exista o adresa principala + SELECT DECODE(nr, 0, 1, 0) + INTO v_principala + FROM (SELECT count(id_adresa) nr + from vadrese_parteneri + where id_part = p_id_part + and principala = 1); + + -- Parseaza adresa + parseaza_adresa_semicolon(p_adresa, + v_judet, + v_localitate, + v_strada, + v_numar, + v_sector); + + -- caut prima adresa dupa judet si localitate, ordonate dupa principala = 1 + begin + select max(id_adresa) over(order by principala desc) + into p_id_adresa + from vadrese_parteneri + where id_part = p_id_part + and judet = v_judet + and localitate = v_localitate; + exception + WHEN NO_DATA_FOUND THEN + p_id_adresa := null; + end; + + -- caut prima adresa dupa judet, ordonate dupa principala = 1 + if p_id_adresa is null then + begin + select max(id_adresa) over(order by principala desc) + into p_id_adresa + from vadrese_parteneri + where id_part = p_id_part + and judet = v_judet; + exception + WHEN NO_DATA_FOUND THEN + p_id_adresa := null; + end; + end if; + + -- Adaug o adresa + if p_id_adresa is null then + -- caut judetul + begin + select id_judet + into v_id_judet + from syn_nom_judete + where judet = v_judet + and sters = 0; + exception + when NO_DATA_FOUND then + v_id_judet := N_ID_JUD_DEFAULT; + end; + + -- caut localitatea + begin + select id_loc, id_judet, id_tara + into v_id_localitate, v_id_judet, v_id_tara + from (select id_loc, id_judet, id_tara, rownum rn + from syn_nom_localitati l + where id_judet = v_id_judet + and localitate = v_localitate + and inactiv = 0 + and sters = 0 + order by localitate) + where rn = 1; + exception + when NO_DATA_FOUND then + begin + select id_loc, id_judet, id_tara + into v_id_localitate, v_id_judet, v_id_tara + from (select id_loc, id_judet, id_tara, rownum rn + from syn_nom_localitati l + where id_judet = v_id_judet + and inactiv = 0 + and sters = 0 + order by localitate) + where rn = 1; + exception + when NO_DATA_FOUND then + v_id_localitate := N_ID_LOCALITATE_DEFAULT; + v_id_judet := N_ID_JUD_DEFAULT; + v_id_tara := N_ID_TARA_DEFAULT; + end; + end; + + BEGIN + pack_def.adauga_adresa_partener2(tnId_part => p_id_part, + tcDenumire_adresa => NULL, + tnDA_apare => 0, + tcStrada => v_strada, + tcNumar => v_numar, + tcBloc => NULL, + tcScara => NULL, + tcApart => NULL, + tnEtaj => NULL, + tnId_loc => v_id_localitate, + tcLocalitate => v_localitate, + tnId_judet => v_id_judet, + tnCodpostal => NULL, + tnId_tara => v_id_tara, + tcTelefon1 => p_phone, + tcTelefon2 => NULL, + tcFax => NULL, + tcEmail => p_email, + tcWeb => NULL, + tnPrincipala => to_char(v_principala), + tnInactiv => 0, + tnId_util => C_ID_UTIL_SISTEM, + tnIdAdresa => p_id_adresa); + + IF p_id_adresa IS NOT NULL AND p_id_adresa > 0 THEN + -- pINFO('Adresa adaugata cu succes. ID_ADRESA=' || p_id_adresa, 'IMPORT_PARTENERI'); + NULL; + ELSE + g_last_error := 'WARNING: pack_def.adauga_adresa_partener2 a returnat ID invalid: ' || + NVL(TO_CHAR(p_id_adresa), 'NULL'); + -- pINFO('WARNING: pack_def.adauga_adresa_partener2 a returnat ID invalid: ' || NVL(TO_CHAR(p_id_adresa), 'NULL'), 'IMPORT_PARTENERI'); + END IF; + + EXCEPTION + WHEN OTHERS THEN + g_last_error := 'ERROR la adaugarea adresei prin pack_def: ' || + SQLERRM; + -- pINFO('ERROR la adaugarea adresei prin pack_def: ' || SQLERRM, 'IMPORT_PARTENERI'); + -- Nu raisam exceptia pentru adresa, partenerii pot exista fara adresa + -- pINFO('Partenerul a fost creat, dar adresa nu a putut fi adaugata', 'IMPORT_PARTENERI'); + END; + END IF; + + <> + null; + end; + +END PACK_IMPORT_PARTENERI; +/ diff --git a/api/database-scripts/06_pack_import_comenzi.pck b/api/database-scripts/06_pack_import_comenzi.pck new file mode 100644 index 0000000..9f66827 --- /dev/null +++ b/api/database-scripts/06_pack_import_comenzi.pck @@ -0,0 +1,397 @@ +CREATE OR REPLACE PACKAGE PACK_IMPORT_COMENZI AS + + -- Tipuri pentru returnarea rezultatelor + TYPE t_articol_result IS RECORD( + id_articol NUMBER, + codmat VARCHAR2(50), + cantitate_roa NUMBER, + pret_unitar NUMBER, + ptva NUMBER, + success NUMBER, + error_message VARCHAR2(4000)); + + TYPE t_articol_table IS TABLE OF t_articol_result; + + -- Variabila package pentru ultima eroare (pentru orchestrator VFP) + g_last_error VARCHAR2(4000); + + -- Functie pentru gasirea/maparea articolelor ROA + FUNCTION gaseste_articol_roa(p_sku IN VARCHAR2, + p_pret_web IN NUMBER DEFAULT NULL, + p_cantitate_web IN NUMBER DEFAULT 1, + p_ptva IN NUMBER) + RETURN t_articol_table + PIPELINED; + + -- Procedura pentru importul complet al unei comenzi + PROCEDURE importa_comanda(p_nr_comanda_ext IN VARCHAR2, + p_data_comanda IN DATE, + p_id_partener IN NUMBER, + p_json_articole IN CLOB, + p_id_adresa_livrare IN NUMBER DEFAULT NULL, + p_id_adresa_facturare IN NUMBER DEFAULT NULL, + v_id_comanda OUT NUMBER); + + -- Functii pentru managementul erorilor (similar cu PACK_JSON) + FUNCTION get_last_error RETURN VARCHAR2; + PROCEDURE clear_error; + +END PACK_IMPORT_COMENZI; +/ +CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS + + -- Constante pentru configurare + -- c_id_gestiune CONSTANT NUMBER := NULL; -- NULL pentru INTERNA=2 (comenzi client) + c_id_sectie CONSTANT NUMBER := NULL; -- Prima sectie disponibila + c_id_pol CONSTANT NUMBER := NULL; + c_id_util CONSTANT NUMBER := -3; -- Sistem + c_interna CONSTANT NUMBER := 2; -- Comenzi de la client (web) + + -- ================================================================ + -- Functii helper pentru managementul erorilor + -- ================================================================ + FUNCTION get_last_error RETURN VARCHAR2 IS + BEGIN + RETURN g_last_error; + END get_last_error; + + PROCEDURE clear_error IS + BEGIN + g_last_error := NULL; + END clear_error; + + -- ================================================================ + -- Functii interne + -- ================================================================ + + -- Procedura interna pentru validarea seturilor + FUNCTION valideaza_set(p_sku IN VARCHAR2) RETURN BOOLEAN IS + v_suma_procent NUMBER := 0; + v_count_articole NUMBER := 0; + BEGIN + SELECT NVL(SUM(procent_pret), 0), COUNT(*) + INTO v_suma_procent, v_count_articole + FROM articole_terti + WHERE sku = p_sku + AND activ = 1; + + -- Validari logice pentru seturi + IF v_count_articole > 1 THEN + -- Set compus - suma procentelor trebuie sa fie intre 95-105% (toleranta) + IF v_suma_procent < 95 OR v_suma_procent > 105 THEN + -- pINFO('WARN VALIDEAZA_SET ' || p_sku || ': Suma procente nelogica: ' || v_suma_procent || '%', 'IMPORT_COMENZI'); + RETURN FALSE; + END IF; + ELSIF v_count_articole = 1 THEN + -- Reimpachetare - procentul trebuie sa fie 100% + IF v_suma_procent != 100 THEN + -- pINFO('WARN VALIDEAZA_SET ' || p_sku || ': Reimpachetare cu procent != 100%: ' || v_suma_procent || '%', 'IMPORT_COMENZI'); + RETURN FALSE; + END IF; + END IF; + + RETURN TRUE; + END valideaza_set; + + -- ================================================================ + -- Functia principala pentru gasirea articolelor ROA + -- ================================================================ + FUNCTION gaseste_articol_roa(p_sku IN VARCHAR2, + p_pret_web IN NUMBER DEFAULT NULL, + p_cantitate_web IN NUMBER DEFAULT 1, + p_ptva IN NUMBER) + RETURN t_articol_table + PIPELINED IS + + v_result t_articol_result; + v_found_mapping BOOLEAN := FALSE; + + -- Cursor pentru maparile din ARTICOLE_TERTI + CURSOR c_mapari IS + SELECT at.codmat, at.cantitate_roa, at.procent_pret, na.id_articol + FROM articole_terti at + JOIN nom_articole na + ON na.codmat = at.codmat + WHERE at.sku = p_sku + AND at.activ = 1 + ORDER BY at.procent_pret DESC; -- Articolele principale primul + + BEGIN + -- pINFO('GASESTE_ARTICOL ' || p_sku || ': Cautare articol pentru SKU: ' || p_sku, 'IMPORT_COMENZI'); + + -- Initializare rezultat + v_result.success := 0; + v_result.error_message := NULL; + + -- STEP 1: Verifica maparile speciale din ARTICOLE_TERTI + FOR rec IN c_mapari LOOP + v_found_mapping := TRUE; + + v_result.id_articol := rec.id_articol; + v_result.codmat := rec.codmat; + v_result.cantitate_roa := rec.cantitate_roa * p_cantitate_web; + + -- Calculeaza pretul unitar pe baza procentului alocat + IF p_pret_web IS NOT NULL THEN + v_result.pret_unitar := (p_pret_web * rec.procent_pret / 100) / + rec.cantitate_roa; + ELSE + -- Fara pret web, setam 0 (va fi necesar sa fie furnizat) + v_result.pret_unitar := 0; + END IF; + + v_result.ptva := p_ptva; + + v_result.success := 1; + + -- pINFO('GASESTE_ARTICOL ' || p_sku || ': Mapare gasita: ' || rec.codmat || + -- ', Cant: ' || v_result.cantitate_roa || + -- ', Pret: ' || v_result.pret_unitar, 'IMPORT_COMENZI'); + + PIPE ROW(v_result); + END LOOP; + + -- STEP 2: Daca nu s-au gasit mapari speciale, cauta direct in nom_articole + IF NOT v_found_mapping THEN + BEGIN + SELECT id_articol, codmat + INTO v_result.id_articol, v_result.codmat + FROM nom_articole + WHERE codmat = p_sku; + + v_result.cantitate_roa := p_cantitate_web; + + -- Pentru cautare directa, foloseste pretul din web daca este furnizat + IF p_pret_web IS NOT NULL THEN + v_result.pret_unitar := p_pret_web; + END IF; + + v_result.ptva := p_ptva; + + v_result.success := 1; + + -- pINFO('GASESTE_ARTICOL ' || p_sku || ': Gasit direct in nomenclator: ' || v_result.codmat, 'IMPORT_COMENZI'); + + PIPE ROW(v_result); + + EXCEPTION + WHEN NO_DATA_FOUND THEN + v_result.success := 0; + v_result.error_message := 'SKU nu a fost gasit nici in ARTICOLE_TERTI, nici in nom_articole: ' || + p_sku; + + -- pINFO('ERROR GASESTE_ARTICOL ' || p_sku || ': ' || v_result.error_message, 'IMPORT_COMENZI'); + PIPE ROW(v_result); + + WHEN TOO_MANY_ROWS THEN + v_result.success := 0; + v_result.error_message := 'Multiple articole gasite pentru SKU: ' || + p_sku; + + -- pINFO('ERROR GASESTE_ARTICOL ' || p_sku || ': ' || v_result.error_message, 'IMPORT_COMENZI'); + PIPE ROW(v_result); + END; + ELSE + -- Valideaza seturile dupa ce au fost returnate toate maparile + IF NOT valideaza_set(p_sku) THEN + null; + -- pINFO('WARN GASESTE_ARTICOL ' || p_sku || ': Set cu configuratie suspecta - verifica procentele', 'IMPORT_COMENZI'); + END IF; + END IF; + + EXCEPTION + WHEN OTHERS THEN + v_result.success := 0; + v_result.error_message := 'Eroare neasteptata: ' || SQLERRM; + + -- pINFO('ERROR GASESTE_ARTICOL ' || p_sku || ': Eroare neasteptata: ' || SQLERRM, 'IMPORT_COMENZI'); + PIPE ROW(v_result); + END gaseste_articol_roa; + + -- ================================================================ + -- Functia pentru importul complet al unei comenzi + -- ================================================================ + PROCEDURE importa_comanda(p_nr_comanda_ext IN VARCHAR2, + p_data_comanda IN DATE, + p_id_partener IN NUMBER, + p_json_articole IN CLOB, + p_id_adresa_livrare IN NUMBER DEFAULT NULL, + p_id_adresa_facturare IN NUMBER DEFAULT NULL, + v_id_comanda OUT NUMBER) IS + v_data_livrare DATE; + v_sku VARCHAR2(100); + v_cantitate_web NUMBER; + v_pret_web NUMBER; + v_articole_procesate NUMBER := 0; + v_articole_eroare NUMBER := 0; + v_start_time DATE; + v_vat NUMBER; + + v_articol_json VARCHAR2(4000); + v_articol_count NUMBER := 0; + + v_articole_table t_articol_table; + v_articol_idx NUMBER; + art_rec t_articol_result; + + l_json_articole CLOB := p_json_articole; + BEGIN + v_start_time := SYSDATE; + + -- Resetare eroare la inceputul procesarii + clear_error; + + -- Validari de baza + IF p_nr_comanda_ext IS NULL OR p_id_partener IS NULL THEN + g_last_error := 'IMPORTA_COMANDA ' || NVL(p_nr_comanda_ext, 'NULL') || + ': Parametri obligatorii lipsa'; + GOTO SFARSIT; + END IF; + + -- Verifica daca comanda nu exista deja + BEGIN + SELECT id_comanda + INTO v_id_comanda + FROM comenzi + WHERE comanda_externa = p_nr_comanda_ext + AND sters = 0; + + -- pINFO('WARN IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Comanda exista deja cu ID: ' || v_id_comanda, 'IMPORT_COMENZI'); + if v_id_comanda is not null then + GOTO sfarsit; + end if; + EXCEPTION + WHEN NO_DATA_FOUND THEN + NULL; -- Normal, comanda nu exista + END; + + -- Calculeaza data de livrare (comanda + 1 zi) + v_data_livrare := p_data_comanda + 1; + + -- STEP 1: Creeaza comanda folosind versiunea overloaded cu OUT parameter + -- Apeleaza procedura adauga_comanda care returneaza ID_COMANDA prin OUT + PACK_COMENZI.adauga_comanda(V_NR_COMANDA => p_nr_comanda_ext, + V_DATA_COMANDA => p_data_comanda, + V_ID => p_id_partener, -- ID_PART + V_DATA_LIVRARE => v_data_livrare, + V_PROC_DISCOUNT => 0, -- Fara discount implicit + V_INTERNA => c_interna, + V_ID_UTIL => c_id_util, + V_ID_SECTIE => c_id_sectie, + V_ID_ADRESA_FACTURARE => p_id_adresa_facturare, + V_ID_ADRESA_LIVRARE => p_id_adresa_livrare, + V_ID_CODCLIENT => NULL, -- Nu folosim cod client + V_COMANDA_EXTERNA => p_nr_comanda_ext, + V_ID_CTR => NULL, -- Nu avem contract + V_ID_COMANDA => v_id_comanda -- OUT parameter cu ID_COMANDA + ); + + IF v_id_comanda IS NULL OR v_id_comanda <= 0 THEN + g_last_error := 'IMPORTA_COMANDA ' || p_nr_comanda_ext || + ': PACK_COMENZI.adauga_comanda a returnat ID invalid'; + GOTO sfarsit; + END IF; + + -- pINFO('IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Comanda creata cu ID: ' || v_id_comanda, 'IMPORT_COMENZI'); + + -- STEP 2: Proceseaza articolele din JSON folosind PACK_JSON + -- Asteapta format JSON: [{"sku":"ABC","cantitate":1,"pret":10.5},{"sku":"DEF","cantitate":2,"pret":20.0}] + + -- Parse JSON array folosind package-ul generic + FOR json_obj IN (SELECT * + FROM TABLE(PACK_JSON.parse_array(l_json_articole))) LOOP + v_articol_count := v_articol_count + 1; + v_articol_json := json_obj.COLUMN_VALUE; + + BEGIN + -- Extrage datele folosind functiile PACK_JSON + v_sku := PACK_JSON.get_string(v_articol_json, 'sku'); + v_cantitate_web := PACK_JSON.get_number(v_articol_json, 'quantity'); + v_pret_web := PACK_JSON.get_number(v_articol_json, 'price'); + v_vat := PACK_JSON.get_number(v_articol_json, 'vat'); + + -- pINFO('IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Procesez articol ' || v_articol_count || ': ' || v_sku || ', cant: ' || v_cantitate_web || ', pret: ' || v_pret_web, 'IMPORT_COMENZI'); + + -- STEP 3: Gaseste maparile pentru acest SKU + -- Apeleaza functia si stocheaza rezultatele + SELECT * + BULK COLLECT + INTO v_articole_table + FROM TABLE(gaseste_articol_roa(v_sku, + v_pret_web, + v_cantitate_web, + v_vat)); + + -- Itereaza prin rezultate + IF v_articole_table.COUNT > 0 THEN + FOR v_articol_idx IN 1 .. v_articole_table.COUNT LOOP + + art_rec := v_articole_table(v_articol_idx); + + IF art_rec.success = 1 THEN + -- Adauga articolul la comanda + BEGIN + PACK_COMENZI.adauga_articol_comanda(V_ID_COMANDA => v_id_comanda, + V_ID_ARTICOL => art_rec.id_articol, + V_ID_POL => c_id_pol, + V_CANTITATE => art_rec.cantitate_roa, + V_PRET => art_rec.pret_unitar, + V_ID_UTIL => c_id_util, + V_ID_SECTIE => c_id_sectie, + V_PTVA => art_rec.ptva); + + v_articole_procesate := v_articole_procesate + 1; + + -- pINFO('IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Articol adaugat: ' || art_rec.codmat || + -- ', cant: ' || art_rec.cantitate_roa || + -- ', pret: ' || art_rec.pret_unitar, 'IMPORT_COMENZI'); + + EXCEPTION + WHEN OTHERS THEN + v_articole_eroare := v_articole_eroare + 1; + g_last_error := g_last_error || CHR(10) || + 'ERROR IMPORTA_COMANDA ' || + p_nr_comanda_ext || + ': Eroare la adaugare articol ' || + art_rec.codmat || ': ' || SQLERRM; + -- pINFO('ERROR IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Eroare la adaugare articol ' || art_rec.codmat || ': ' || SQLERRM, 'IMPORT_COMENZI'); + END; + ELSE + v_articole_eroare := v_articole_eroare + 1; + g_last_error := g_last_error || CHR(10) || + 'ERROR IMPORTA_COMANDA ' || + p_nr_comanda_ext || + ': SKU nu a putut fi mapat: ' || v_sku || + ' - ' || art_rec.error_message; + -- pINFO('ERROR IMPORTA_COMANDA ' || p_nr_comanda_ext || ': SKU nu a putut fi mapat: ' || v_sku || ' - ' || art_rec.error_message, 'IMPORT_COMENZI'); + END IF; + + END LOOP; -- End v_articol_idx loop + ELSE + v_articole_eroare := v_articole_eroare + 1; + g_last_error := g_last_error || CHR(10) || + 'WARN IMPORTA_COMANDA ' || p_nr_comanda_ext || + ': Niciun articol gasit pentru SKU: ' || + v_sku; + -- pINFO('WARN IMPORTA_COMANDA ' || p_nr_comanda_ext || ': Niciun articol gasit pentru SKU: ' || v_sku, 'IMPORT_COMENZI'); + END IF; + END; -- End DECLARE block pentru v_articole_table + + END LOOP; + + -- Verifica daca s-au procesat articole cu succes + IF v_articole_procesate = 0 THEN + g_last_error := g_last_error || CHR(10) || 'IMPORTA_COMANDA ' || + p_nr_comanda_ext || + ': Niciun articol nu a fost procesat cu succes'; + END IF; + + <> + IF g_last_error IS NOT NULL THEN + RAISE_APPLICATION_ERROR(-20001, g_last_error); + END IF; + + END importa_comanda; + +END PACK_IMPORT_COMENZI; +/ diff --git a/docs/completeaza-parteneri-roa.prg b/docs/completeaza-parteneri-roa.prg index 633a399..ef0f0c7 100644 --- a/docs/completeaza-parteneri-roa.prg +++ b/docs/completeaza-parteneri-roa.prg @@ -66,6 +66,7 @@ Procedure completeaza_parteneri_roa Select cJudete Append From Dbf('cJudeteTemp') Index On id_judet Tag id_judet + Index On judet Tag judet Use In (Select('cJudeteTemp')) Create Cursor cLocalitati (id_loc I, id_judet I Null, id_tara I Null, localitate C(100) Null) @@ -250,7 +251,7 @@ Procedure completeaza_parteneri_roa lnIdJudet = m.lnIdJudetBucuresti Select cJudete - If Seek(m.lcJudet, 'cJudete', 'id_judet') + If Seek(m.lcJudet, 'cJudete', 'judet') lnIdJudet = cJudete.id_judet Endif diff --git a/vfp/gomag-adapter.prg b/vfp/gomag-adapter.prg index 5f84b80..cd3da5d 100644 --- a/vfp/gomag-adapter.prg +++ b/vfp/gomag-adapter.prg @@ -23,9 +23,6 @@ LOCAL llGetProducts, llGetOrders PRIVATE loJsonData, gcLogFile, gnStartTime, gnProductsProcessed, gnOrdersProcessed -*-- Include utilitare necesare -SET PROCEDURE TO regex.prg ADDITIVE - *-- Initializare logging si statistici gnStartTime = SECONDS() gnProductsProcessed = 0 @@ -229,9 +226,8 @@ IF llGetProducts llHasMorePages = .F. ENDTRY - *-- Pauza scurta intre cereri pentru a evita rate limiting IF llHasMorePages - INKEY(1) && Pauza de 1 secunda + INKEY(1) && Pauza de 10 secunde pentru a evita "Limitele API depasite" ENDIF ENDDO @@ -301,80 +297,59 @@ DO WHILE llHasMorePages *-- Success - preluare raspuns lcResponse = loHttp.ResponseText - *-- Parsare JSON cu nfjson - SET PATH TO nfjson ADDITIVE - loJsonData = nfJsonRead(lcResponse) + *-- SALVARE DIRECTA: Salveaza raspunsul RAW exact cum vine din API, pe pagini + lcOrderJsonFileName = lcOutputDir + "\gomag_orders_page" + TRANSFORM(lnCurrentPage) + "_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json" + STRTOFILE(lcResponse, lcOrderJsonFileName) + LogMessage("[ORDERS] JSON RAW salvat: " + lcOrderJsonFileName, "INFO", gcLogFile) - IF !ISNULL(loJsonData) - *-- Debug: Afisam structura JSON pentru prima pagina + *-- Parsare JSON pentru obtinerea numarului de pagini + SET PATH TO nfjson ADDITIVE + loOrdersJsonData = nfJsonRead(lcResponse) + + IF !ISNULL(loOrdersJsonData) + *-- Extragere informatii paginare din JSON procesat IF lnCurrentPage = 1 - LogMessage("[ORDERS] Analyzing JSON structure...", "INFO", gcLogFile) - LOCAL ARRAY laJsonProps[1] - lnPropCount = AMEMBERS(laJsonProps, loJsonData, 0) - FOR lnDebugIndex = 1 TO MIN(lnPropCount, 10) && Primele 10 proprietati - lcPropName = laJsonProps(lnDebugIndex) - lcPropType = TYPE('loJsonData.' + lcPropName) - LogMessage("[ORDERS] Property: " + lcPropName + " (Type: " + lcPropType + ")", "DEBUG", gcLogFile) - ENDFOR - ENDIF - - *-- Prima pagina - setam informatiile generale din metadata - IF lnCurrentPage = 1 - IF TYPE('loJsonData.total') = 'C' OR TYPE('loJsonData.total') = 'N' - loAllOrderData.total = VAL(TRANSFORM(loJsonData.total)) - ENDIF - IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N' - loAllOrderData.pages = VAL(TRANSFORM(loJsonData.pages)) - ENDIF - LogMessage("[ORDERS] Total orders: " + TRANSFORM(loAllOrderData.total), "INFO", gcLogFile) - LogMessage("[ORDERS] Total pages: " + TRANSFORM(loAllOrderData.pages), "INFO", gcLogFile) - ENDIF - - *-- Adaugare comenzi din pagina curenta - *-- API-ul GoMag returneaza obiect cu metadata si orders - LOCAL llHasOrders, lnOrdersFound - llHasOrders = .F. - lnOrdersFound = 0 - - *-- Verificam daca avem obiectul orders - IF TYPE('loJsonData.orders') = 'O' - *-- Numaram comenzile din obiectul orders - lnOrdersFound = AMEMBERS(laOrdersPage, loJsonData.orders, 0) - IF lnOrdersFound > 0 - *-- Mergem comenzile din pagina curenta - DO MergeOrdersArray WITH loAllOrderData, loJsonData - llHasOrders = .T. - LogMessage("[ORDERS] Found: " + TRANSFORM(lnOrdersFound) + " orders in page " + TRANSFORM(lnCurrentPage), "INFO", gcLogFile) - gnOrdersProcessed = gnOrdersProcessed + lnOrdersFound + IF TYPE('loOrdersJsonData.total') = 'C' OR TYPE('loOrdersJsonData.total') = 'N' + LOCAL lnTotalOrders + lnTotalOrders = VAL(TRANSFORM(loOrdersJsonData.total)) + LogMessage("[ORDERS] Total orders: " + TRANSFORM(lnTotalOrders), "INFO", gcLogFile) ENDIF ENDIF - IF !llHasOrders - LogMessage("[ORDERS] WARNING: No orders found in JSON response for page " + TRANSFORM(lnCurrentPage), "WARN", gcLogFile) - ENDIF - - *-- Verificare daca mai sunt pagini folosind metadata - IF TYPE('loJsonData.pages') = 'C' OR TYPE('loJsonData.pages') = 'N' - lnTotalPages = VAL(TRANSFORM(loJsonData.pages)) + IF TYPE('loOrdersJsonData.pages') = 'C' OR TYPE('loOrdersJsonData.pages') = 'N' + lnTotalPages = VAL(TRANSFORM(loOrdersJsonData.pages)) + IF lnCurrentPage = 1 + LogMessage("[ORDERS] Total pages: " + TRANSFORM(lnTotalPages), "INFO", gcLogFile) + ENDIF + IF lnCurrentPage >= lnTotalPages llHasMorePages = .F. + LogMessage("[ORDERS] Reached last page (" + TRANSFORM(lnCurrentPage) + "/" + TRANSFORM(lnTotalPages) + ")", "INFO", gcLogFile) ENDIF ELSE - *-- Fallback: verifica daca am primit mai putin decat limita - IF !llHasOrders OR lnOrdersFound < lnLimit + *-- Fallback: verificare daca mai sunt comenzi in pagina + IF TYPE('loOrdersJsonData.orders') != 'O' llHasMorePages = .F. + LogMessage("[ORDERS] No orders found in response, stopping pagination", "INFO", gcLogFile) ENDIF ENDIF - lnCurrentPage = lnCurrentPage + 1 + *-- Numarare comenzi din pagina curenta + IF TYPE('loOrdersJsonData.orders') = 'O' + LOCAL lnOrdersInPage + lnOrdersInPage = AMEMBERS(laOrdersPage, loOrdersJsonData.orders, 0) + gnOrdersProcessed = gnOrdersProcessed + lnOrdersInPage + LogMessage("[ORDERS] Found " + TRANSFORM(lnOrdersInPage) + " orders in page " + TRANSFORM(lnCurrentPage), "INFO", gcLogFile) + ENDIF ELSE - *-- Salvare raspuns JSON raw in caz de eroare de parsare - lcFileName = "gomag_order_error_page" + TRANSFORM(lnCurrentPage) + "_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json" - STRTOFILE(lcResponse, lcFileName) + *-- Eroare la parsarea JSON + LogMessage("[ORDERS] ERROR: Could not parse JSON response for page " + TRANSFORM(lnCurrentPage), "ERROR", gcLogFile) llHasMorePages = .F. ENDIF + lnCurrentPage = lnCurrentPage + 1 + ELSE *-- Eroare HTTP - salvare in fisier de log lcLogFileName = "gomag_order_error_page" + TRANSFORM(lnCurrentPage) + "_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".log" @@ -405,19 +380,14 @@ DO WHILE llHasMorePages llHasMorePages = .F. ENDTRY - *-- Pauza scurta intre cereri pentru a evita rate limiting IF llHasMorePages - INKEY(1) && Pauza de 1 secunda + INKEY(1) && Pauza de 10 secunde pentru a evita "Limitele API depasite" ENDIF ENDDO - *-- Salvare array JSON cu toate comenzile - IF !ISNULL(loAllOrderData) AND TYPE('loAllOrderData.orders') = 'O' - lcOrderJsonFileName = lcOutputDir + "\gomag_orders_last7days_" + DTOS(DATE()) + "_" + STRTRAN(TIME(), ":", "") + ".json" - DO SaveOrdersArray WITH loAllOrderData, lcOrderJsonFileName - LogMessage("[ORDERS] JSON file created: " + lcOrderJsonFileName, "INFO", gcLogFile) - ENDIF + LogMessage("[ORDERS] JSON files salvate pe pagini separate in directorul output/", "INFO", gcLogFile) + LogMessage("[ORDERS] Total orders processed: " + TRANSFORM(gnOrdersProcessed), "INFO", gcLogFile) ELSE LogMessage("[ORDERS] Skipped order retrieval (llGetOrders = .F.)", "INFO", gcLogFile) @@ -430,139 +400,6 @@ loHttp = NULL CloseLog(gnStartTime, gnProductsProcessed, gnOrdersProcessed, gcLogFile) -*-- Functie pentru salvarea array-ului de produse in format JSON -PROCEDURE SaveProductsArray -PARAMETERS tloAllData, tcFileName - -LOCAL lcJsonContent, lnPropCount, lnIndex, lcPropName, loProduct, lcProductJson - -*-- Incepe array-ul JSON -lcJsonContent = "[" + CHR(13) + CHR(10) - -*-- Verifica daca avem produse -IF TYPE('tloAllData.products') = 'O' - lnPropCount = AMEMBERS(laProducts, tloAllData.products, 0) - - FOR lnIndex = 1 TO lnPropCount - lcPropName = laProducts(lnIndex) - loProduct = EVALUATE('tloAllData.products.' + lcPropName) - - IF TYPE('loProduct') = 'O' - *-- Adauga virgula pentru elementele anterioare - IF lnIndex > 1 - lcJsonContent = lcJsonContent + "," + CHR(13) + CHR(10) - ENDIF - - *-- Serializeaza produsul cu nfjsoncreate standard - lcProductJson = nfJsonCreate(loProduct, .F.) - lcJsonContent = lcJsonContent + " " + lcProductJson - ENDIF - ENDFOR -ENDIF - -*-- Inchide array-ul JSON -lcJsonContent = lcJsonContent + CHR(13) + CHR(10) + "]" - -*-- Salveaza fisierul -STRTOFILE(lcJsonContent, tcFileName) - -ENDPROC - -*-- Functie pentru salvarea array-ului de comenzi in format JSON -PROCEDURE SaveOrdersArray -PARAMETERS tloAllData, tcFileName - -LOCAL lcJsonContent, lnPropCount, lnIndex, lcPropName, loOrder, lcOrderJson - -*-- Incepe array-ul JSON -lcJsonContent = "[" + CHR(13) + CHR(10) - -*-- Verifica daca avem comenzi -IF TYPE('tloAllData.orders') = 'O' - lnPropCount = AMEMBERS(laOrders, tloAllData.orders, 0) - - FOR lnIndex = 1 TO lnPropCount - lcPropName = laOrders(lnIndex) - loOrder = EVALUATE('tloAllData.orders.' + lcPropName) - - IF TYPE('loOrder') = 'O' - *-- Adauga virgula pentru elementele anterioare - IF lnIndex > 1 - lcJsonContent = lcJsonContent + "," + CHR(13) + CHR(10) - ENDIF - - *-- Serializeaza comanda cu nfjsoncreate standard - lcOrderJson = nfJsonCreate(loOrder, .F.) - lcJsonContent = lcJsonContent + " " + lcOrderJson - ENDIF - ENDFOR -ENDIF - -*-- Inchide array-ul JSON -lcJsonContent = lcJsonContent + CHR(13) + CHR(10) + "]" - -*-- Salveaza fisierul -STRTOFILE(lcJsonContent, tcFileName) - -ENDPROC - - -*-- Functie pentru unirea produselor din toate paginile (versiune simpla) -PROCEDURE MergeProducts -PARAMETERS tloAllData, tloPageData - -LOCAL lnPropCount, lnIndex, lcPropName, loProduct - -*-- Verifica daca avem produse in pagina curenta -IF TYPE('tloPageData.products') = 'O' - *-- Itereaza prin toate produsele din pagina - lnPropCount = AMEMBERS(laPageProducts, tloPageData.products, 0) - - FOR lnIndex = 1 TO lnPropCount - lcPropName = laPageProducts(lnIndex) - loProduct = EVALUATE('tloPageData.products.' + lcPropName) - - IF TYPE('loProduct') = 'O' - *-- Adauga produsul la colectia principala - ADDPROPERTY(tloAllData.products, lcPropName, loProduct) - ENDIF - ENDFOR -ENDIF - -ENDPROC - -*-- Functie pentru unirea comenzilor din array direct (structura GoMag) -PROCEDURE MergeOrdersArray -PARAMETERS tloAllData, tloPageData - -LOCAL lnPropCount, lnIndex, lcPropName, loOrder - -*-- Verifica daca avem comenzi in pagina curenta -IF TYPE('tloPageData.orders') = 'O' - *-- Itereaza prin toate comenzile din pagina (array direct) - lnPropCount = AMEMBERS(laPageOrders, tloPageData.orders, 0) - - FOR lnIndex = 1 TO lnPropCount - lcPropName = laPageOrders(lnIndex) - loOrder = EVALUATE('tloPageData.orders.' + lcPropName) - - IF TYPE('loOrder') = 'O' - *-- Folosim ID-ul comenzii ca nume proprietate, sau un index secvential - LOCAL lcOrderId - lcOrderId = "" - IF TYPE('loOrder.id') = 'C' - lcOrderId = "order_" + loOrder.id - ELSE - lcOrderId = "order_" + TRANSFORM(lnIndex) - ENDIF - - *-- Adauga comanda la colectia principala - ADDPROPERTY(tloAllData.orders, lcOrderId, loOrder) - ENDIF - ENDFOR -ENDIF - -ENDPROC *-- Functiile utilitare au fost mutate in utils.prg diff --git a/vfp/gomag-comenzi.sql b/vfp/gomag-comenzi.sql new file mode 100644 index 0000000..9001a99 --- /dev/null +++ b/vfp/gomag-comenzi.sql @@ -0,0 +1,7 @@ +alter table COMENZI_ELEMENTE add ptva number(5,2); +comment on column COMENZI_ELEMENTE.ptva is 'PROCENT TVA (11,21)'; + +-- ARTICOLE_TERTI +-- PACK_COMENZI +-- PACK_IMPORT_PARTENERI +-- PACK_IMPORT_COMENZI \ No newline at end of file diff --git a/vfp/roawebcomenzi.PJT b/vfp/roawebcomenzi.PJT index 8193f762d397bdead1d60c3d10de3d01c4af1fd2..b7357136aac96c40609093bb78cb7389e48a67df 100644 GIT binary patch delta 173 zcmZ3exKMF}I8(iWt5r-ukiVy^bBJq9n5&txiva`}ftV=e ilP580F{(}e&m_sJTb7!aGFg^ciHQM8V6!Z93oih+Ya(9& diff --git a/vfp/roawebcomenzi.pjx b/vfp/roawebcomenzi.pjx index 796822b383cc4adf9f344de8386831e74a397231..3bd90bc0a1b90e979e1cda130d25184594ef7dba 100644 GIT binary patch delta 13 UcmdlhyjPgTK$4SZBg;-s02+4#dH?_b delta 13 UcmdlhyjPgTK$4StBg;-s02*=wc>n+a diff --git a/vfp/sync-comenzi-web.prg b/vfp/sync-comenzi-web.prg index 90f9471..046aa21 100644 --- a/vfp/sync-comenzi-web.prg +++ b/vfp/sync-comenzi-web.prg @@ -1,39 +1,39 @@ *-- sync-comenzi-web.prg - Orchestrator pentru sincronizarea comenzilor web cu Oracle ROA -*-- Autor: Claude AI +*-- Autor: Claude AI *-- Data: 10 septembrie 2025 *-- Dependency: gomag-vending.prg trebuie rulat mai intai pentru generarea JSON-urilor -SET SAFETY OFF -SET CENTURY ON -SET DATE DMY -SET EXACT ON -SET ANSI ON -SET DELETED ON +Set Safety Off +Set Century On +Set Date Dmy +Set Exact On +Set Ansi On +Set Deleted On *-- Variabile globale -PRIVATE gcAppPath, gcLogFile, gnStartTime, gnOrdersProcessed, gnOrdersSuccess, gnOrdersErrors -PRIVATE goConnectie, goSettings, goAppSetup -LOCAL lcJsonPattern, laJsonFiles[1], lnJsonFiles, lnIndex, lcJsonFile -LOCAL loJsonData, lcJsonContent, lnOrderCount, lnOrderIndex -LOCAL loOrder, lcResult, llProcessSuccess, lcPath +Private gcAppPath, gcLogFile, gnStartTime, gnOrdersProcessed, gnOrdersSuccess, gnOrdersErrors +Private goConnectie, goSettings, goAppSetup +Local lcJsonPattern, laJsonFiles[1], lnJsonFiles, lnIndex, lcJsonFile +Local loJsonData, lcJsonContent, lnOrderCount, lnOrderIndex +Local loOrder, lcResult, llProcessSuccess, lcPath -goConnectie = NULL +goConnectie = Null *-- Initializare -gcAppPath = ADDBS(JUSTPATH(SYS(16,0))) -SET DEFAULT TO (m.gcAppPath) +gcAppPath = Addbs(Justpath(Sys(16,0))) +Set Default To (m.gcAppPath) lcPath = gcAppPath + 'nfjson;' -SET PATH TO &lcPath ADDITIVE +Set Path To &lcPath Additive -SET PROCEDURE TO utils.prg ADDITIVE -SET PROCEDURE TO ApplicationSetup.prg ADDITIVE -SET PROCEDURE TO nfjsonread.prg ADDITIVE -SET PROCEDURE TO nfjsoncreate.prg ADDITIVE -SET PROCEDURE TO regex.prg ADDITIVE +Set Procedure To utils.prg Additive +Set Procedure To ApplicationSetup.prg Additive +Set Procedure To nfjsonread.prg Additive +Set Procedure To nfjsoncreate.prg Additive +Set Procedure To regex.prg Additive *-- Statistici -gnStartTime = SECONDS() +gnStartTime = Seconds() gnOrdersProcessed = 0 gnOrdersSuccess = 0 gnOrdersErrors = 0 @@ -43,537 +43,689 @@ gcLogFile = InitLog("sync_comenzi") LogMessage("=== SYNC COMENZI WEB > ORACLE ROA ===", "INFO", gcLogFile) *-- Creare si initializare clasa setup aplicatie -goAppSetup = CREATEOBJECT("ApplicationSetup", gcAppPath) +goAppSetup = Createobject("ApplicationSetup", gcAppPath) *-- Setup complet cu validare si afisare configuratie -IF !goAppSetup.Initialize() - LogMessage("EROARE: Setup-ul aplicatiei a esuat sau necesita configurare!", "ERROR", gcLogFile) - RETURN .F. -ENDIF +If !goAppSetup.Initialize() + LogMessage("EROARE: Setup-ul aplicatiei a esuat sau necesita configurare!", "ERROR", gcLogFile) + Return .F. +Endif *-- Obtinere setari din clasa goSettings = goAppSetup.GetSettings() *-- Verificare directoare necesare -IF !DIRECTORY(gcAppPath + "output") - LogMessage("EROARE: Directorul output/ nu exista! Ruleaza mai intai adapter-ul web", "ERROR", gcLogFile) - RETURN .F. -ENDIF +If !Directory(gcAppPath + "output") + LogMessage("EROARE: Directorul output/ nu exista! Ruleaza mai intai adapter-ul web", "ERROR", gcLogFile) + Return .F. +Endif *-- Rulare automata adapter pentru obtinere comenzi (daca este configurat) -IF goSettings.AutoRunAdapter - LogMessage("Rulez adapter pentru obtinere comenzi: " + goSettings.AdapterProgram, "INFO", gcLogFile) - IF !ExecuteAdapter() - LogMessage("EROARE la rularea adapter-ului, continuez cu fisierele JSON existente", "WARN", gcLogFile) - ENDIF -ELSE - LogMessage("AutoRunAdapter este dezactivat, folosesc doar fisierele JSON existente", "INFO", gcLogFile) -ENDIF -SET STEP ON +If goSettings.AutoRunAdapter + LogMessage("Rulez adapter pentru obtinere comenzi: " + goSettings.AdapterProgram, "INFO", gcLogFile) + If !ExecuteAdapter() + LogMessage("EROARE la rularea adapter-ului, continuez cu fisierele JSON existente", "WARN", gcLogFile) + Endif +Else + LogMessage("AutoRunAdapter este dezactivat, folosesc doar fisierele JSON existente", "INFO", gcLogFile) +Endif + *-- Gasire fisiere JSON comenzi din pattern configurat lcJsonPattern = gcAppPath + "output\" + goSettings.JsonFilePattern -lnJsonFiles = ADIR(laJsonFiles, lcJsonPattern) +lnJsonFiles = Adir(laJsonFiles, lcJsonPattern) -IF lnJsonFiles = 0 - LogMessage("AVERTISMENT: Nu au fost gasite fisiere JSON cu comenzi web", "WARN", gcLogFile) - LogMessage("Ruleaza mai intai adapter-ul web cu GetOrders=1 in settings.ini", "INFO", gcLogFile) - RETURN .T. -ENDIF +If lnJsonFiles = 0 + LogMessage("AVERTISMENT: Nu au fost gasite fisiere JSON cu comenzi web", "WARN", gcLogFile) + LogMessage("Ruleaza mai intai adapter-ul web cu GetOrders=1 in settings.ini", "INFO", gcLogFile) + Return .T. +Endif -LogMessage("Gasite " + TRANSFORM(lnJsonFiles) + " fisiere JSON cu comenzi web", "INFO", gcLogFile) +LogMessage("Gasite " + Transform(lnJsonFiles) + " fisiere JSON cu comenzi web", "INFO", gcLogFile) *-- Incercare conectare Oracle (folosind conexiunea existenta din sistem) -IF !ConnectToOracle() - LogMessage("EROARE: Nu s-a putut conecta la Oracle ROA", "ERROR", gcLogFile) - RETURN .F. -ENDIF - +If !ConnectToOracle() + LogMessage("EROARE: Nu s-a putut conecta la Oracle ROA", "ERROR", gcLogFile) + Return .F. +Endif +SET STEP ON *-- Procesare fiecare fisier JSON gasit -FOR lnIndex = 1 TO lnJsonFiles - lcJsonFile = gcAppPath + "output\" + laJsonFiles[lnIndex, 1] - LogMessage("Procesez fisierul: " + laJsonFiles[lnIndex, 1], "INFO", gcLogFile) - - *-- Citire si parsare JSON - TRY - lcJsonContent = FILETOSTR(lcJsonFile) - IF EMPTY(lcJsonContent) - LogMessage("AVERTISMENT: Fisier JSON gol - " + laJsonFiles[lnIndex, 1], "WARN", gcLogFile) - LOOP - ENDIF - - *-- Parsare JSON array cu comenzi - loJsonData = nfJsonRead(lcJsonContent) - IF ISNULL(loJsonData) - LogMessage("EROARE: Nu s-a putut parsa JSON-ul din " + laJsonFiles[lnIndex, 1], "ERROR", gcLogFile) - LOOP - ENDIF - - *-- Verificare daca este array - IF TYPE('loJsonData') != 'O' - LogMessage("EROARE: JSON-ul nu este un array valid - " + laJsonFiles[lnIndex, 1], "ERROR", gcLogFile) - LOOP - ENDIF - SET STEP ON - *-- Obtinere numar comenzi din array - lnOrderCount = 0 - IF TYPE('loJsonData.array') = 'U' - lnOrderCount = ALEN(loJsonData.array) - ENDIF - LogMessage("Gasite " + TRANSFORM(lnOrderCount) + " comenzi in " + laJsonFiles[lnIndex, 1], "INFO", gcLogFile) - - *-- Procesare fiecare comanda din JSON - FOR EACH loOrder IN loJsonData.array - IF TYPE('loOrder') = 'O' - gnOrdersProcessed = gnOrdersProcessed + 1 - llProcessSuccess = ProcessWebOrder(loOrder) - - IF llProcessSuccess - gnOrdersSuccess = gnOrdersSuccess + 1 - ELSE - gnOrdersErrors = gnOrdersErrors + 1 - ENDIF - ENDIF - ENDFOR - - CATCH TO loError - LogMessage("EROARE la procesarea fisierului " + laJsonFiles[lnIndex, 1] + ": " + loError.Message, "ERROR", gcLogFile) - gnOrdersErrors = gnOrdersErrors + 1 - ENDTRY -ENDFOR +For lnIndex = 1 To lnJsonFiles + lcJsonFile = gcAppPath + "output\" + laJsonFiles[lnIndex, 1] + LogMessage("Procesez fisierul: " + laJsonFiles[lnIndex, 1], "INFO", gcLogFile) + + *-- Citire si parsare JSON + Try + lcJsonContent = Filetostr(lcJsonFile) + If Empty(lcJsonContent) + LogMessage("AVERTISMENT: Fisier JSON gol - " + laJsonFiles[lnIndex, 1], "WARN", gcLogFile) + Loop + Endif + + *-- Parsare JSON array cu comenzi + loJsonData = nfjsonread(lcJsonContent) + If Isnull(loJsonData) + LogMessage("EROARE: Nu s-a putut parsa JSON-ul din " + laJsonFiles[lnIndex, 1], "ERROR", gcLogFile) + Loop + Endif + + *-- Verificare daca este obiect JSON valid + If Type('loJsonData') != 'O' + LogMessage("EROARE: JSON-ul nu este un obiect valid - " + laJsonFiles[lnIndex, 1], "ERROR", gcLogFile) + Loop + Endif + + *-- Verificare structura GoMag (cu proprietatea "orders") + If Type('loJsonData.orders') != 'O' + LogMessage("EROARE: JSON-ul nu contine proprietatea 'orders' - " + laJsonFiles[lnIndex, 1], "ERROR", gcLogFile) + Loop + Endif + + *-- Obtinere numar comenzi din obiectul orders + Local Array laOrderProps[1] + lnOrderCount = Amembers(laOrderProps, loJsonData.orders, 0) + LogMessage("Gasite " + Transform(lnOrderCount) + " comenzi in " + laJsonFiles[lnIndex, 1], "INFO", gcLogFile) + + *-- Log informatii pagina daca sunt disponibile + If Type('loJsonData.page') = 'C' Or Type('loJsonData.page') = 'N' + LogMessage("Pagina: " + Transform(loJsonData.Page) + " din " + Transform(loJsonData.Pages), "DEBUG", gcLogFile) + Endif + + *-- Procesare fiecare comanda din obiectul orders + For lnOrderIndex = 1 To lnOrderCount + Local lcOrderId, loOrder + lcOrderId = laOrderProps[lnOrderIndex] + loOrder = Evaluate('loJsonData.orders.' + lcOrderId) + + If Type('loOrder') = 'O' + gnOrdersProcessed = gnOrdersProcessed + 1 + LogMessage("Procesez comanda ID: " + lcOrderId + " (Nr: " + Iif(Type('loOrder.number') = 'C', loOrder.Number, "NECUNOSCUT") + ")", "DEBUG", gcLogFile) + + llProcessSuccess = ProcessWebOrder(loOrder) + + If llProcessSuccess + gnOrdersSuccess = gnOrdersSuccess + 1 + Else + gnOrdersErrors = gnOrdersErrors + 1 + Endif + Else + LogMessage("AVERTISMENT: Comanda cu ID " + lcOrderId + " nu este un obiect valid", "WARN", gcLogFile) + Endif + + * Daca sunt peste 10 erori, ies din import fara sa mai import alte comenzi + * Probabil ca sunt erori in cod / baza de date + If m.gnOrdersErrors > 10 + Exit + Endif + Endfor + + Catch To loError + LogMessage("EROARE la procesarea fisierului " + laJsonFiles[lnIndex, 1] + ": " + loError.Message, "ERROR", gcLogFile) + gnOrdersErrors = gnOrdersErrors + 1 + Endtry + + * Daca sunt peste 10 erori, ies din import fara sa mai import alte comenzi + * Probabil ca sunt erori in cod / baza de date + If m.gnOrdersErrors > 10 + LogMessage("Peste 10 comenzi au dat eroare la import. Nu se mai importa restul de comenzi.", "ERROR", gcLogFile) + Exit + Endif +Endfor *-- Inchidere conexiune Oracle DisconnectFromOracle() *-- Logging final cu statistici LogMessage("=== PROCESARE COMPLETA ===", "INFO", gcLogFile) -LogMessage("Total comenzi procesate: " + TRANSFORM(gnOrdersProcessed), "INFO", gcLogFile) -LogMessage("Comenzi importate cu succes: " + TRANSFORM(gnOrdersSuccess), "INFO", gcLogFile) -LogMessage("Comenzi cu erori: " + TRANSFORM(gnOrdersErrors), "INFO", gcLogFile) +LogMessage("Total comenzi procesate: " + Transform(gnOrdersProcessed), "INFO", gcLogFile) +LogMessage("Comenzi importate cu succes: " + Transform(gnOrdersSuccess), "INFO", gcLogFile) +LogMessage("Comenzi cu erori: " + Transform(gnOrdersErrors), "INFO", gcLogFile) CloseLog(gnStartTime, 0, gnOrdersProcessed, gcLogFile) -RETURN .T. +Return .T. *-- =================================================================== *-- HELPER FUNCTIONS *-- =================================================================== *-- Functie pentru conectarea la Oracle folosind setarile din settings.ini -FUNCTION ConnectToOracle -LOCAL llSuccess, lcConnectionString, lnHandle +Function ConnectToOracle + Local llSuccess, lcConnectionString, lnHandle -llSuccess = .F. + llSuccess = .F. -TRY - *-- Conectare Oracle folosind datele din settings.ini - lnHandle = SQLCONNECT(goSettings.OracleDSN, goSettings.OracleUser, goSettings.OraclePassword) - - IF lnHandle > 0 - goConnectie = lnHandle - llSuccess = .T. - LogMessage("Conectare Oracle reusita - Handle: " + TRANSFORM(lnHandle), "INFO", gcLogFile) - LogMessage("DSN: " + goSettings.OracleDSN + " | User: " + goSettings.OracleUser, "DEBUG", gcLogFile) - ELSE - LogMessage("EROARE: Conectare Oracle esuata - Handle: " + TRANSFORM(lnHandle), "ERROR", gcLogFile) - LogMessage("DSN: " + goSettings.OracleDSN + " | User: " + goSettings.OracleUser, "ERROR", gcLogFile) - ENDIF - -CATCH TO loError - LogMessage("EROARE la conectarea Oracle: " + loError.Message, "ERROR", gcLogFile) -ENDTRY + Try + *-- Conectare Oracle folosind datele din settings.ini + lnHandle = SQLConnect(goSettings.OracleDSN, goSettings.OracleUser, goSettings.OraclePassword) -RETURN llSuccess -ENDFUNC + If lnHandle > 0 + goConnectie = lnHandle + llSuccess = .T. + LogMessage("Conectare Oracle reusita - Handle: " + Transform(lnHandle), "INFO", gcLogFile) + LogMessage("DSN: " + goSettings.OracleDSN + " | User: " + goSettings.OracleUser, "DEBUG", gcLogFile) + Else + LogMessage("EROARE: Conectare Oracle esuata - Handle: " + Transform(lnHandle), "ERROR", gcLogFile) + LogMessage("DSN: " + goSettings.OracleDSN + " | User: " + goSettings.OracleUser, "ERROR", gcLogFile) + Endif + + Catch To loError + LogMessage("EROARE la conectarea Oracle: " + loError.Message, "ERROR", gcLogFile) + Endtry + + Return llSuccess +Endfunc *-- Functie pentru deconectarea de la Oracle -FUNCTION DisconnectFromOracle -IF TYPE('goConnectie') = 'N' AND goConnectie > 0 - SQLDISCONNECT(goConnectie) - LogMessage("Deconectare Oracle reusita", "INFO", gcLogFile) -ENDIF -RETURN .T. -ENDFUNC +Function DisconnectFromOracle + If Type('goConnectie') = 'N' And goConnectie > 0 + SQLDisconnect(goConnectie) + LogMessage("Deconectare Oracle reusita", "INFO", gcLogFile) + Endif + Return .T. +Endfunc *-- Functie principala de procesare comanda web -FUNCTION ProcessWebOrder -PARAMETERS loOrder -LOCAL llSuccess, lcOrderNumber, lcOrderDate, lnPartnerID, lcArticlesJSON -LOCAL lcObservatii, lcSQL, lnResult, lcErrorDetails +Function ProcessWebOrder + Parameters loOrder + Local llSuccess, lcOrderNumber, lcOrderDate, lnPartnerID, lcArticlesJSON + Local lcObservatii, lcSQL, lnResult, lcErrorDetails, lnIdComanda, llSucces + Local ldOrderDate, loError + Local lnIdAdresaFacturare, lnIdAdresaLivrare, lcErrorMessage -llSuccess = .F. + lnIdAdresaLivrare = NULL + lnIdAdresaFacturare = NULL + lnIdComanda = 0 + llSucces = .T. -TRY - *-- Validare comanda - IF !ValidateWebOrder(loOrder) - LogMessage("EROARE: Comanda web invalida - lipsesc date obligatorii", "ERROR", gcLogFile) - RETURN .F. - ENDIF - - *-- Extragere date comanda - lcOrderNumber = CleanWebText(TRANSFORM(loOrder.number)) - lcOrderDate = ConvertWebDate(loOrder.date) - - LogMessage("Procesez comanda: " + lcOrderNumber + " din " + lcOrderDate, "INFO", gcLogFile) - - *-- Procesare partener (billing address) - lnPartnerID = ProcessPartnerFromBilling(loOrder.billing) - IF lnPartnerID <= 0 - LogMessage("EROARE: Nu s-a putut procesa partenerul pentru comanda " + lcOrderNumber, "ERROR", gcLogFile) - RETURN .F. - ENDIF - - LogMessage("Partener identificat/creat: ID=" + TRANSFORM(lnPartnerID), "INFO", gcLogFile) - - *-- Construire JSON articole - lcArticlesJSON = BuildArticlesJSON(loOrder.items) - IF EMPTY(lcArticlesJSON) - LogMessage("EROARE: Nu s-au gasit articole valide in comanda " + lcOrderNumber, "ERROR", gcLogFile) - RETURN .F. - ENDIF - - *-- Construire observatii cu detalii suplimentare - lcObservatii = BuildOrderObservations(loOrder) - - *-- Apel package Oracle pentru import comanda - lcSQL = "SELECT PACK_IMPORT_COMENZI.importa_comanda_web(?, TO_DATE(?, 'YYYY-MM-DD'), ?, ?, NULL, ?) AS ID_COMANDA FROM dual" - - lnResult = SQLEXEC(goConnectie, lcSQL, ; - lcOrderNumber, ; && p_nr_comanda_ext - lcOrderDate, ; && p_data_comanda - lnPartnerID, ; && p_id_partener - lcArticlesJSON, ; && p_json_articole - lcObservatii, ; && p_observatii - "cursor_comanda") - - IF lnResult > 0 AND RECCOUNT("cursor_comanda") > 0 AND cursor_comanda.ID_COMANDA > 0 - LogMessage("SUCCES: Comanda importata - ID Oracle: " + TRANSFORM(cursor_comanda.ID_COMANDA), "INFO", gcLogFile) - USE IN cursor_comanda - llSuccess = .T. - ELSE - *-- Obtinere detalii eroare Oracle - lcErrorDetails = GetOracleErrorDetails() - LogMessage("EROARE: Import comanda esuat pentru " + lcOrderNumber + " - " + lcErrorDetails, "ERROR", gcLogFile) - IF USED("cursor_comanda") - USE IN cursor_comanda - ENDIF - ENDIF - -CATCH TO loError - LogMessage("EXCEPTIE la procesarea comenzii " + lcOrderNumber + ": " + loError.Message, "ERROR", gcLogFile) -ENDTRY + Try + *-- Validare comanda + If !ValidateWebOrder(loOrder) + LogMessage("EROARE: Comanda web invalida - lipsesc date obligatorii", "ERROR", gcLogFile) + llSucces = .F. + Endif -RETURN llSuccess -ENDFUNC + *-- Extragere date comanda + If m.llSucces + lcOrderNumber = CleanWebText(Transform(loOrder.Number)) + lcOrderDate = ConvertWebDate(loOrder.Date) && yyyymmdd + ldOrderDate = String2Date(m.lcOrderDate, 'yyyymmdd') + + LogMessage("Procesez comanda: " + lcOrderNumber + " din " + lcOrderDate, "INFO", gcLogFile) + + *-- Procesare partener (billing address) + lnPartnerID = ProcessPartner(loOrder.billing) + If lnPartnerID <= 0 + LogMessage("EROARE: Nu s-a putut procesa partenerul pentru comanda " + lcOrderNumber, "ERROR", gcLogFile) + llSucces = .F. + Else + LogMessage("Partener identificat/creat: ID=" + Transform(lnPartnerID), "INFO", gcLogFile) + + *-- Adresa facturare + lnIdAdresaFacturare = ProcessAddress(m.lnPartnerID, loOrder.billing) + + IF TYPE('loOrder.shipping') = 'O' + *-- Adresa livrares + lnIdAdresaLivrare = ProcessAddress(m.lnPartnerID, loOrder.shipping) + ENDIF + Endif + Endif + + *-- Construire JSON articole + If m.llSucces + lcArticlesJSON = BuildArticlesJSON(loOrder.items) + If Empty(m.lcArticlesJSON) + LogMessage("EROARE: Nu s-au gasit articole valide in comanda " + lcOrderNumber, "ERROR", gcLogFile) + llSucces = .F. + Endif + Endif + + *-- Construire observatii cu detalii suplimentare + *!* lcObservatii = BuildOrderObservations(loOrder) + + *-- Apel package Oracle pentru import comanda + If m.llSucces + lcSQL = "BEGIN PACK_IMPORT_COMENZI.importa_comanda(?lcOrderNumber, ?ldOrderDate, ?lnPartnerID, ?lcArticlesJSON, ?lnIdAdresaLivrare, ?lnIdAdresaFacturare, ?@lnIdComanda); END;" + lnResult = SQLExec(goConnectie, lcSQL) + + If lnResult > 0 And Nvl(m.lnIdComanda,0) > 0 + LogMessage("SUCCES: Comanda importata - ID Oracle: " + Transform(m.lnIdComanda), "INFO", gcLogFile) + llSuccess = .T. + Else + llSuccess = .F. + *-- Obtinere detalii eroare Oracle + lcErrorDetails = GetOracleErrorDetails(m.lcSQL) + LogMessage("EROARE: Import comanda esuat pentru " + lcOrderNumber + CHR(10) + lcErrorDetails, "ERROR", gcLogFile) + Endif + Endif + + Catch To loError + llSucces = .F. + LogMessage("EXCEPTIE la procesarea comenzii " + lcOrderNumber + ": " + loError.Message, "ERROR", gcLogFile) + Endtry + + Return llSuccess +Endfunc *-- Functie pentru validarea comenzii web -FUNCTION ValidateWebOrder -PARAMETERS loOrder -LOCAL llValid +Function ValidateWebOrder + Parameters loOrder + Local llValid -llValid = .T. + llValid = .T. -*-- Verificari obligatorii -IF TYPE('loOrder.number') != 'C' OR EMPTY(loOrder.number) - llValid = .F. -ENDIF + *-- Verificari obligatorii + If Type('loOrder.number') != 'C' Or Empty(loOrder.Number) + llValid = .F. + Endif -IF TYPE('loOrder.date') != 'C' OR EMPTY(loOrder.date) - llValid = .F. -ENDIF + If Type('loOrder.date') != 'C' Or Empty(loOrder.Date) + llValid = .F. + Endif -IF TYPE('loOrder.billing') != 'O' - llValid = .F. -ENDIF + If Type('loOrder.billing') != 'O' + llValid = .F. + Endif -IF TYPE('loOrder.items') != 'O' - llValid = .F. -ENDIF + If Type('loOrder.items') != 'O' + llValid = .F. + Endif -RETURN llValid -ENDFUNC + Return llValid +Endfunc -*-- Functie pentru procesarea partenerului din billing GoMag -FUNCTION ProcessPartnerFromBilling -PARAMETERS loBilling -LOCAL lnPartnerID, lcDenumire, lcCodFiscal, lcAdresa, lcTelefon, lcEmail -LOCAL lcSQL, lnResult +*-- Functie pentru procesarea partenerului din billing.company GoMag +Function ProcessPartner + Lparameters toBilling + Local lcDenumire, lcCodFiscal, lcRegistru, lcAdresa, lcTelefon, lcEmail, lcRegistru + Local lcSQL, lnResult + Local lnIdPart, lnIdAdresa, lnIsPersoanaJuridica + lnIdPart = 0 + lnIdAdresa = 0 + lcDenumire = '' + lcCodFiscal = '' + lcRegistru = '' + lnIsPersoanaJuridica = 0 + lcCodFiscal = Null && Persoanele fizice nu au CUI in platformele web -lnPartnerID = 0 + If .F. + TEXT TO lcExampleJsonAdresa NOSHOW + "billing": { + "address": "STR. CAMPUL LINISTII, NR. 1", + "city": "Arad", + "company": { + "bank": "", + "code": "RO30071208", + "iban": "", + "name": "BASSANO BUILDINGS SRL", + "registrationNo": "" + }, + "country": "Romania", + "customerId": "13422", + "email": "office@bassano.ro", + "firstname": "Ionela", + "lastname": "Letcan", + "phone": "0728141899", + "region": "Arad" + }, + ENDTEXT + ENDIF -TRY - *-- Extragere date partener din datele billing - LOCAL lnIsPersoanaJuridica - - IF TYPE('loBilling.company') = 'O' AND !EMPTY(loBilling.company.name) - *-- Companie - persoana juridica - lcDenumire = CleanWebText(loBilling.company.name) - lcCodFiscal = IIF(TYPE('loBilling.company.code') = 'C', loBilling.company.code, NULL) - lnIsPersoanaJuridica = 1 && Persoana juridica - ELSE - *-- Persoana fizica - lcDenumire = CleanWebText(ALLTRIM(loBilling.firstname) + " " + ALLTRIM(loBilling.lastname)) - lcCodFiscal = NULL && Persoanele fizice nu au CUI in platformele web - lnIsPersoanaJuridica = 0 && Persoana fizica - ENDIF - - *-- Formatare adresa pentru Oracle (format semicolon cu prefix JUD:) - lcAdresa = FormatAddressForOracle(loBilling) - - *-- Date contact - lcTelefon = IIF(TYPE('loBilling.phone') = 'C', loBilling.phone, "") - lcEmail = IIF(TYPE('loBilling.email') = 'C', loBilling.email, "") - - LogMessage("Partener: " + lcDenumire + " | CUI: " + IIF(ISNULL(lcCodFiscal), "NULL", lcCodFiscal) + " | Tip: " + IIF(lnIsPersoanaJuridica = 1, "JURIDICA", "FIZICA"), "DEBUG", gcLogFile) - - *-- Apel package Oracle IMPORT_PARTENERI (PROCEDURA cu parametru OUT) - *-- Folosind sintaxa corecta pentru parametrii OUT in VFP - LOCAL lnPartnerResult - lnPartnerResult = 0 - - lcSQL = "BEGIN PACK_IMPORT_PARTENERI.cauta_sau_creeaza_partener(?lcCodFiscal, ?lcDenumire, ?lcAdresa, ?lcTelefon, ?lcEmail, ?lnIsPersoanaJuridica, ?@lnPartnerResult); END;" - - lnResult = SQLEXEC(goConnectie, lcSQL) - - IF lnResult > 0 - lnPartnerID = lnPartnerResult - LogMessage("Partener procesat cu succes: ID=" + TRANSFORM(lnPartnerID), "DEBUG", gcLogFile) - ELSE - *-- Obtinere detalii eroare Oracle - lcErrorDetails = GetOracleErrorDetails() - LogMessage("EROARE la apelul procedurii PACK_IMPORT_PARTENERI pentru: " + lcDenumire + " - " + lcErrorDetails, "ERROR", gcLogFile) - lnPartnerID = 0 - ENDIF - -CATCH TO loError - LogMessage("EXCEPTIE la procesarea partenerului: " + loError.Message, "ERROR", gcLogFile) -ENDTRY + Try + *-- Extragere date partener din datele billing + If Type('toBilling.company') = 'O' And !Empty(toBilling.company.Name) + loCompany = toBilling.company + *-- Companie - persoana juridica + lcDenumire = CleanWebText(loCompany.Name) + lcCodFiscal = Iif(Type('loCompany.code') = 'C', loCompany.Code, Null) + lcCodFiscal = CleanWebText(m.lcCodFiscal) + lcRegistru = Iif(Type('loCompany.registrationNo') = 'C', loCompany.registrationNo, Null) + lcRegistru = CleanWebText(m.lcRegistru) + lnIsPersoanaJuridica = 1 && Persoana juridica + Else + *-- Persoana fizica + IF TYPE('toBilling.firstname') = 'C' + lcDenumire = CleanWebText(Alltrim(toBilling.firstname) + " " + Alltrim(toBilling.lastname)) + lnIsPersoanaJuridica = 0 && Persoana fizica + ENDIF + Endif + + LogMessage("Partener: " + lcDenumire + " | CUI: " + Iif(Isnull(lcCodFiscal), "NULL", lcCodFiscal) + " | Tip: " + Iif(lnIsPersoanaJuridica = 1, "JURIDICA", "FIZICA"), "DEBUG", gcLogFile) + + * Cautare/creare client + lcSQL = "BEGIN PACK_IMPORT_PARTENERI.cauta_sau_creeaza_partener(?lcCodFiscal, ?lcDenumire, ?lcRegistru, ?lnIsPersoanaJuridica, ?@lnIdPart); END;" + + lnResult = SQLExec(goConnectie, lcSQL) + + If lnResult > 0 + LogMessage("Partener procesat cu succes: ID=" + Transform(m.lnIdPart), "DEBUG", gcLogFile) + Else + *-- Obtinere detalii eroare Oracle + lcErrorDetails = GetOracleErrorDetails(m.lcSQL) + LogMessage("EROARE la apelul procedurii PACK_IMPORT_PARTENERI.cauta_sau_creeaza_partener pentru: " + lcDenumire + CHR(10) + lcErrorDetails, "ERROR", gcLogFile) + Endif + + Catch To loError + LogMessage("EXCEPTIE la procesarea partenerului: " + loError.Message, "ERROR", gcLogFile) + Endtry + + Return m.lnIdPart +ENDFUNC && ProcessPartner + +*-- Functie pentru procesarea adresei din billing/shipping +Function ProcessAddress + Lparameters tnIdPart, toAdresa + + Local lcAdresa, lcTelefon, lcEmail, lcSQL, lnResult, lnIdAdresa + lnIdAdresa = 0 + + If .F. + TEXT TO lcExampleJsonAdresa NOSHOW + "billing": { + "address": "STR. CAMPUL LINISTII, NR. 1", + "city": "Arad", + "company": { + "bank": "", + "code": "RO30071208", + "iban": "", + "name": "BASSANO BUILDINGS SRL", + "registrationNo": "" + }, + "country": "Romania", + "customerId": "13422", + "email": "office@bassano.ro", + "firstname": "Ionela", + "lastname": "Letcan", + "phone": "0728141899", + "region": "Arad" + }, + "shipping": { + "address": "Strada Molnar Janos nr 23 bloc 37 sc B etj e ap. 16", + "city": "Bra?ov", + "company": "", + "country": "Romania", + "email": "ancamirela74@gmail.com", + "firstname": "Anca", + "lastname": "Stanciu", + "phone": "0758261492", + "region": "Brasov", + "zipcode": "" + } + ENDTEXT + Endif + + Try + * Cautare/creare adresa + If !Empty(Nvl(m.tnIdPart,0)) + *-- Formatare adresa pentru Oracle (format semicolon cu prefix JUD:) + lcAdresa = FormatAddressForOracle(toAdresa) + + *-- Date contact + lcTelefon = Iif(Type('toAdresa.phone') = 'C', toAdresa.phone, "") + lcEmail = Iif(Type('toAdresa.email') = 'C', toAdresa.email, "") + + lcSQL = "BEGIN PACK_IMPORT_PARTENERI.cauta_sau_creeaza_adresa(?tnIdPart, ?lcAdresa, ?lcTelefon, ?lcEmail, ?@lnIdAdresa); END;" + + lnResult = SQLExec(goConnectie, lcSQL) + + If lnResult > 0 + LogMessage("Adresa procesata cu succes: ID=" + Transform(m.lnIdAdresa), "DEBUG", gcLogFile) + Else + *-- Obtinere detalii eroare Oracle + lcErrorDetails = GetOracleErrorDetails(m.lcSQL) + LogMessage("EROARE la apelul procedurii PACK_IMPORT_PARTENERI.cauta_sau_creeaza_adresa pentru PartnerId: " + ALLTRIM(TRANSFORM(m.tnIdPart)) + CHR(10) + lcErrorDetails, "ERROR", gcLogFile) + Endif + + Endif + + Catch To loError + LogMessage("EXCEPTIE la procesarea adresei: " + loError.Message, "ERROR", gcLogFile) + Endtry + + Return m.lnIdAdresa +Endfunc && ProcessAddress -RETURN lnPartnerID -ENDFUNC *-- Functie pentru construirea JSON-ului cu articole conform package Oracle -FUNCTION BuildArticlesJSON -PARAMETERS loItems -LOCAL lcJSON, lnItemCount, lnIndex, lcItemProp, loItem -LOCAL lcSku, lcQuantity, lcPrice +Function BuildArticlesJSON + Lparameters loItems -lcJSON = "" + Local lcJSON, loError -TRY - IF TYPE('loItems') != 'O' - RETURN "" - ENDIF - - lnItemCount = AMEMBERS(laItems, loItems, 0) - IF lnItemCount = 0 - RETURN "" - ENDIF - - lcJSON = "[" - - FOR lnIndex = 1 TO lnItemCount - lcItemProp = laItems[lnIndex] - loItem = EVALUATE('loItems.' + lcItemProp) - - IF TYPE('loItem') = 'O' - *-- Extragere date articol - lcSku = IIF(TYPE('loItem.sku') = 'C', CleanWebText(loItem.sku), "") - lcQuantity = IIF(TYPE('loItem.quantity') = 'C' OR TYPE('loItem.quantity') = 'N', TRANSFORM(VAL(TRANSFORM(loItem.quantity))), "1") - lcPrice = IIF(TYPE('loItem.price') = 'C' OR TYPE('loItem.price') = 'N', TRANSFORM(VAL(TRANSFORM(loItem.price))), "0") - - IF !EMPTY(lcSku) - *-- Adaugare virgula pentru elementele urmatoare - IF lnIndex > 1 - lcJSON = lcJSON + "," - ENDIF - - *-- Format JSON conform package Oracle: {"sku":"...", "cantitate":..., "pret":...} - lcJSON = lcJSON + '{"sku":"' + lcSku + '","cantitate":' + lcQuantity + ',"pret":' + lcPrice + '}' - ENDIF - ENDIF - ENDFOR - - lcJSON = lcJSON + "]" - -CATCH TO loError - LogMessage("EROARE la construirea JSON articole: " + loError.Message, "ERROR", gcLogFile) - lcJSON = "" -ENDTRY + lcJSON = "" + Try + lcJSON = nfjsoncreate(loItems) + Catch To loError + LogMessage("EROARE la construirea JSON articole: " + loError.Message, "ERROR", gcLogFile) + lcJSON = "" + Endtry -RETURN lcJSON -ENDFUNC + Return lcJSON +Endfunc *-- Functie pentru curatarea textului web (HTML entities → ASCII simplu) -FUNCTION CleanWebText -PARAMETERS tcText -LOCAL lcResult +Function CleanWebText + Parameters tcText + Local lcResult -IF EMPTY(tcText) OR TYPE('tcText') != 'C' - RETURN "" -ENDIF + If Empty(tcText) Or Type('tcText') != 'C' + Return "" + Endif -lcResult = tcText + lcResult = tcText -*-- Conversie HTML entities in caractere simple (fara diacritice) -lcResult = STRTRAN(lcResult, 'ă', 'a') && ă → a -lcResult = STRTRAN(lcResult, 'ș', 's') && È™ → s -lcResult = STRTRAN(lcResult, 'ț', 't') && È› → t -lcResult = STRTRAN(lcResult, 'î', 'i') && î → i -lcResult = STRTRAN(lcResult, 'â', 'a') && â → a -lcResult = STRTRAN(lcResult, '&', '&') -lcResult = STRTRAN(lcResult, '<', '<') -lcResult = STRTRAN(lcResult, '>', '>') -lcResult = STRTRAN(lcResult, '"', '"') + *-- Conversie HTML entities in caractere simple (fara diacritice) + lcResult = Strtran(lcResult, 'ă', 'a') && ă → a + lcResult = Strtran(lcResult, 'ș', 's') && È™ → s + lcResult = Strtran(lcResult, 'ț', 't') && È› → t + lcResult = Strtran(lcResult, 'î', 'i') && î → i + lcResult = Strtran(lcResult, 'â', 'a') && â → a + lcResult = Strtran(lcResult, '&', '&') + lcResult = Strtran(lcResult, '<', '<') + lcResult = Strtran(lcResult, '>', '>') + lcResult = Strtran(lcResult, '"', '"') -*-- Eliminare tag-uri HTML simple -lcResult = STRTRAN(lcResult, '
', ' ') -lcResult = STRTRAN(lcResult, '
', ' ') -lcResult = STRTRAN(lcResult, '
', ' ') + *-- Eliminare tag-uri HTML simple + lcResult = Strtran(lcResult, '
', ' ') + lcResult = Strtran(lcResult, '
', ' ') + lcResult = Strtran(lcResult, '
', ' ') -RETURN ALLTRIM(lcResult) -ENDFUNC + *-- Eliminare Esc character + lcResult = Strtran(lcResult, '\/', '/') + + Return Alltrim(lcResult) +Endfunc *-- Functie pentru conversia datei web in format Oracle -FUNCTION ConvertWebDate -PARAMETERS tcWebDate -LOCAL lcResult +Function ConvertWebDate + Parameters tcWebDate + Local lcResult -IF EMPTY(tcWebDate) OR TYPE('tcWebDate') != 'C' - RETURN DTOS(DATE()) -ENDIF + If Empty(tcWebDate) Or Type('tcWebDate') != 'C' + Return Dtos(Date()) && yyyymmdd + Endif -*-- Web date format: "2025-08-27 16:32:43" → "2025-08-27" -lcResult = LEFT(tcWebDate, 10) + *-- Web date format: "2025-08-27 16:32:43" → "20250827" + lcResult = Strtran(Left(tcWebDate, 10), "-", "",1,10,1) -*-- Validare format YYYY-MM-DD -IF LEN(lcResult) = 10 AND SUBSTR(lcResult, 5, 1) = '-' AND SUBSTR(lcResult, 8, 1) = '-' - RETURN lcResult -ELSE - RETURN DTOS(DATE()) -ENDIF -ENDFUNC + *-- Validare format YYYYMMDD + If Len(lcResult) = 8 + Return lcResult + Else + Return Dtos(Date()) + Endif +Endfunc + +*-- Functie pentru conversia datei string in Date +* ldData = String2Date('20250912', ['yyyymmdd']) +Function String2Date + Lparameters tcDate, tcFormat + * tcDate: 20250911 + * tcFormat: yyyymmdd (default) + + Local lcAn, lcDate, lcFormat, lcLuna, lcZi, ldData, lnAn, lnLuna, lnZi, loEx + ldData = {} + + lcDate = m.tcDate + lcFormat = Iif(!Empty(m.tcFormat), Alltrim(Lower(m.tcFormat)), 'yyyymmdd') + + lcDate = Chrtran(m.lcDate, '-/\','...') && inlocuiesc .-/\ cu . ca sa am doar variante yyyy.mm.dd, dd.mm.yyyy + lcDate = Strtran(m.lcDate, '.', '', 1, 2, 1) + lcFormat = Chrtran(m.lcFormat, '.-/\','...') + lcFormat = Strtran(m.lcFormat, '.', '', 1, 2, 1) + + + Do Case + Case m.lcFormat = 'ddmmyyyy' + lcAn = Substr(m.tcDate, 5, 4) + lcLuna = Substr(m.tcDate, 3, 2) + lcZi = Substr(m.tcDate, 1, 2) + Otherwise + * yyyymmdd + lcAn = Substr(m.tcDate, 1, 4) + lcLuna = Substr(m.tcDate, 5, 2) + lcZi = Substr(m.tcDate, 7, 2) + Endcase + lnAn = Int(Val(m.lcAn)) + lnLuna = Int(Val(m.lcLuna)) + lnZi = Int(Val(m.lcZi)) + + Try + ldData = Date(m.lnAn, m.lnLuna, m.lnZi) + Catch To loEx + ldData = {} + Endtry + + Return m.ldData +Endfunc *-- Functie pentru formatarea adresei in format semicolon pentru Oracle -FUNCTION FormatAddressForOracle -PARAMETERS loBilling -LOCAL lcAdresa, lcJudet, lcOras, lcStrada +Function FormatAddressForOracle + Parameters loBilling + Local lcAdresa, lcJudet, lcOras, lcStrada -*-- Extragere componente adresa -lcJudet = IIF(TYPE('loBilling.region') = 'C', CleanWebText(loBilling.region), "Bucuresti") -lcOras = IIF(TYPE('loBilling.city') = 'C', CleanWebText(loBilling.city), "BUCURESTI") -lcStrada = IIF(TYPE('loBilling.address') = 'C', CleanWebText(loBilling.address), "Adresa necunoscuta") + *-- Extragere componente adresa + lcJudet = Iif(Type('loBilling.region') = 'C', CleanWebText(loBilling.Region), "") + lcOras = Iif(Type('loBilling.city') = 'C', CleanWebText(loBilling.city), "") + lcStrada = Iif(Type('loBilling.address') = 'C', CleanWebText(loBilling.address), "") -*-- Format semicolon cu prefix JUD: conform specificatiilor Oracle -lcAdresa = "JUD:" + lcJudet + ";" + lcOras + ";" + lcStrada + *-- Format semicolon cu prefix JUD: conform specificatiilor Oracle + lcAdresa = "JUD:" + lcJudet + ";" + lcOras + ";" + lcStrada -RETURN lcAdresa -ENDFUNC + Return lcAdresa +Endfunc *-- Functie pentru construirea observatiilor comenzii -FUNCTION BuildOrderObservations -PARAMETERS loOrder -LOCAL lcObservatii +Function BuildOrderObservations + Parameters loOrder + Local lcObservatii -lcObservatii = "" + lcObservatii = "" -*-- Informatii plata si livrare -IF TYPE('loOrder.payment') = 'O' AND TYPE('loOrder.payment.name') = 'C' - lcObservatii = lcObservatii + "Payment: " + CleanWebText(loOrder.payment.name) + "; " -ENDIF + *-- Informatii plata si livrare + If Type('loOrder.payment') = 'O' And Type('loOrder.payment.name') = 'C' + lcObservatii = lcObservatii + "Payment: " + CleanWebText(loOrder.Payment.Name) + "; " + Endif -IF TYPE('loOrder.delivery') = 'O' AND TYPE('loOrder.delivery.name') = 'C' - lcObservatii = lcObservatii + "Delivery: " + CleanWebText(loOrder.delivery.name) + "; " -ENDIF + If Type('loOrder.delivery') = 'O' And Type('loOrder.delivery.name') = 'C' + lcObservatii = lcObservatii + "Delivery: " + CleanWebText(loOrder.delivery.Name) + "; " + Endif -*-- Status si sursa -IF TYPE('loOrder.status') = 'C' - lcObservatii = lcObservatii + "Status: " + CleanWebText(loOrder.status) + "; " -ENDIF + *-- Status si sursa + If Type('loOrder.status') = 'C' + lcObservatii = lcObservatii + "Status: " + CleanWebText(loOrder.Status) + "; " + Endif -IF TYPE('loOrder.source') = 'C' - lcObservatii = lcObservatii + "Source: " + CleanWebText(loOrder.source) - - IF TYPE('loOrder.sales_channel') = 'C' - lcObservatii = lcObservatii + " " + CleanWebText(loOrder.sales_channel) - ENDIF - lcObservatii = lcObservatii + "; " -ENDIF + If Type('loOrder.source') = 'C' + lcObservatii = lcObservatii + "Source: " + CleanWebText(loOrder.Source) -*-- Verificare adrese diferite shipping vs billing -IF TYPE('loOrder.shipping') = 'O' AND TYPE('loOrder.billing') = 'O' - IF TYPE('loOrder.shipping.address') = 'C' AND TYPE('loOrder.billing.address') = 'C' - IF !ALLTRIM(loOrder.shipping.address) == ALLTRIM(loOrder.billing.address) - lcObservatii = lcObservatii + "Shipping: " + CleanWebText(loOrder.shipping.address) - - IF TYPE('loOrder.shipping.city') = 'C' - lcObservatii = lcObservatii + ", " + CleanWebText(loOrder.shipping.city) - ENDIF - lcObservatii = lcObservatii + "; " - ENDIF - ENDIF -ENDIF + If Type('loOrder.sales_channel') = 'C' + lcObservatii = lcObservatii + " " + CleanWebText(loOrder.sales_channel) + Endif + lcObservatii = lcObservatii + "; " + Endif -*-- Limitare lungime observatii pentru Oracle -IF LEN(lcObservatii) > 500 - lcObservatii = LEFT(lcObservatii, 497) + "..." -ENDIF + *-- Verificare adrese diferite shipping vs billing + If Type('loOrder.shipping') = 'O' And Type('loOrder.billing') = 'O' + If Type('loOrder.shipping.address') = 'C' And Type('loOrder.billing.address') = 'C' + If !Alltrim(loOrder.shipping.address) == Alltrim(loOrder.billing.address) + lcObservatii = lcObservatii + "Shipping: " + CleanWebText(loOrder.shipping.address) -RETURN lcObservatii -ENDFUNC + If Type('loOrder.shipping.city') = 'C' + lcObservatii = lcObservatii + ", " + CleanWebText(loOrder.shipping.city) + Endif + lcObservatii = lcObservatii + "; " + Endif + Endif + Endif + + *-- Limitare lungime observatii pentru Oracle + If Len(lcObservatii) > 500 + lcObservatii = Left(lcObservatii, 497) + "..." + Endif + + Return lcObservatii +Endfunc *-- Functie pentru obtinerea detaliilor erorii Oracle -FUNCTION GetOracleErrorDetails -LOCAL lcError, laError[1], lnErrorLines, lnIndex +Function GetOracleErrorDetails + Lparameters tcSql + * tcSql (optional) : SQL executat -lcError = "" + Local lcError, laError[1], lnErrorLines, lnIndex -*-- Obtinere eroare Oracle -lnErrorLines = AERROR(laError) -IF lnErrorLines > 0 - FOR lnIndex = 1 TO lnErrorLines - IF lnIndex > 1 - lcError = lcError + " | " - ENDIF - lcError = lcError + ALLTRIM(STR(laError[lnIndex, 1])) + ": " + laError[lnIndex, 2] - ENDFOR -ENDIF + lcError = "" -IF EMPTY(lcError) - lcError = "Eroare Oracle nedefinita" -ENDIF + *-- Obtinere eroare Oracle + lnErrorLines = Aerror(laError) + If lnErrorLines > 0 + For lnIndex = 1 To lnErrorLines + If lnIndex > 1 + lcError = lcError + " | " + Endif + lcError = lcError + Alltrim(Str(laError[lnIndex, 1])) + ": " + laError[lnIndex, 2] + Endfor + Endif -RETURN lcError -ENDFUNC + If Empty(lcError) + lcError = "Eroare Oracle nedefinita" + Endif + + lcError = Iif(Pcount() = 1 And !Empty(m.tcSql) And Type('tcSql') = 'C', m.tcSql + Chr(13) + Chr(10), '') + m.lcError + + Return lcError +Endfunc *-- Functie pentru executia adapter-ului configurat -FUNCTION ExecuteAdapter -LOCAL llSuccess, lcAdapterPath +Function ExecuteAdapter + Local llSuccess, lcAdapterPath -llSuccess = .F. + llSuccess = .F. -TRY - lcAdapterPath = gcAppPath + goSettings.AdapterProgram - - IF FILE(lcAdapterPath) - LogMessage("Executie adapter: " + lcAdapterPath, "INFO", gcLogFile) - DO (lcAdapterPath) - llSuccess = .T. - LogMessage("Adapter executat cu succes", "INFO", gcLogFile) - ELSE - LogMessage("EROARE: Adapter-ul nu a fost gasit la: " + lcAdapterPath, "ERROR", gcLogFile) - ENDIF - -CATCH TO loError - LogMessage("EXCEPTIE la executia adapter-ului " + goSettings.AdapterProgram + ": " + loError.Message, "ERROR", gcLogFile) -ENDTRY + Try + lcAdapterPath = gcAppPath + goSettings.AdapterProgram -RETURN llSuccess -ENDFUNC + If File(lcAdapterPath) + LogMessage("Executie adapter: " + lcAdapterPath, "INFO", gcLogFile) + Do (lcAdapterPath) + llSuccess = .T. + LogMessage("Adapter executat cu succes", "INFO", gcLogFile) + Else + LogMessage("EROARE: Adapter-ul nu a fost gasit la: " + lcAdapterPath, "ERROR", gcLogFile) + Endif + + Catch To loError + LogMessage("EXCEPTIE la executia adapter-ului " + goSettings.AdapterProgram + ": " + loError.Message, "ERROR", gcLogFile) + Endtry + + Return llSuccess +Endfunc *-- Orchestrator complet pentru sincronizarea comenzilor web cu Oracle ROA *-- Caracteristici: *-- - Citeste JSON-urile generate de gomag-vending.prg -*-- - Proceseaza comenzile cu toate helper functions necesare +*-- - Proceseaza comenzile cu toate helper functions necesare *-- - Integreaza cu package-urile Oracle validate in Phase 1 *-- - Logging complet cu statistici de procesare *-- - Error handling pentru toate situatiile -*-- - Support pentru toate formatele GoMag (billing/shipping, companii/persoane fizice) \ No newline at end of file +*-- - Support pentru toate formatele GoMag (billing/shipping, companii/persoane fizice) + + \ No newline at end of file