actualizare

This commit is contained in:
2026-03-10 15:23:12 +02:00
parent 6f988db1f9
commit 8e94c05901
3 changed files with 164 additions and 102 deletions

1
.gitignore vendored
View File

@@ -24,3 +24,4 @@ settings.ini
vfp/settings.ini vfp/settings.ini
vfp/output/ vfp/output/
vfp/*.json vfp/*.json
*.~pck

75
SPECIFICATIE_CONTRACT.txt Normal file
View File

@@ -0,0 +1,75 @@
SPECIFICATIE PROIECT - IMPORT COMENZI WEB IN ROA ORACLE
Data: 5 martie 2026
================================================================================
DESCRIERE SCOP
================================================================================
Implementarea unui sistem automat de import a comenzilor de pe platforme web
(GoMag si altele) in sistemul ERP ROA Oracle. Sistemul va prelua comenzi,
va realiza mapari de articole, va converte unitati de masura si va crea
comenzi in ROA automat.
================================================================================
DELIVERABLES
================================================================================
1. Logica de import completa in baza de date ROA Oracle
2. Orchestrator automat (cron job) pentru sincronizare comenzi
3. Interfata web de configurare mapari SKU-uri
4. Suport pentru articole compuse (mapari complexe)
5. Conversii unitati de masura intre platforme
6. Documentatie tehnica si handover
7. Support 3 luni pentru bug fixes
================================================================================
EFORTURI SI COSTURI
================================================================================
Lucrat deja: 20h 1,200 EUR
De lucrat: 60h 3,600 EUR
Support 3 luni: 24h 1,440 EUR
TOTAL IMPLEMENTARE: 80h 4,800 EUR
TOTAL CU SUPPORT: 104h 6,240 EUR
Tarif orar: 60 EUR/h
================================================================================
INCLUS IN PRET
================================================================================
- Analiza si integrare cu baza de date client
- Testare completa cu date reale
- Integrare in sistemul ROA Oracle
- Validari si controale de integritate
- Documentation si training
- Support de 3 luni pentru probleme critice
================================================================================
CONDITII GENERALE
================================================================================
Duratie proiect: 2-4 saptamani
Payment terms: 50% avans, 50% la finalizare
Garantie: 3 luni (bug fixes gratuit)
Suport suplimentar: 60 EUR/h (dupa perioada garantie)
Buffer estimare: 50% (pentru integrare ROA + incertitudini)
================================================================================
RESPONSABILITATI CLIENT
================================================================================
- Acces la baza de date client si ROA Oracle
- Accesul la comenzile din platforma web
- Clarificarea logicii maparii articole compuse
- Testing si validare in mediu pilot
================================================================================

View File

@@ -1,40 +1,35 @@
-- ====================================================================
-- P1-004: Package PACK_JSON pentru parsing JSON generic
-- Sistem Import Comenzi Web → ROA
-- ====================================================================
CREATE OR REPLACE PACKAGE PACK_JSON AS CREATE OR REPLACE PACKAGE PACK_JSON AS
-- Tipuri pentru lucrul cu JSON -- Tipuri pentru lucrul cu JSON
TYPE t_json_array IS TABLE OF VARCHAR2(4000); TYPE t_json_array IS TABLE OF VARCHAR2(4000);
TYPE t_json_key_value IS RECORD ( TYPE t_json_key_value IS RECORD (
key_name VARCHAR2(100), key_name VARCHAR2(100),
key_value VARCHAR2(4000), key_value VARCHAR2(4000),
key_type VARCHAR2(20) -- 'STRING', 'NUMBER', 'BOOLEAN', 'NULL' key_type VARCHAR2(20) -- 'STRING', 'NUMBER', 'BOOLEAN', 'NULL'
); );
TYPE t_json_object IS TABLE OF t_json_key_value; TYPE t_json_object IS TABLE OF t_json_key_value;
-- Proprietate pentru tracking erori -- Proprietate pentru tracking erori
g_last_error VARCHAR2(4000); g_last_error VARCHAR2(4000);
-- Functie pentru accesarea ultimei erori -- Functie pentru accesarea ultimei erori
FUNCTION get_last_error RETURN VARCHAR2; FUNCTION get_last_error RETURN VARCHAR2;
-- Functie pentru resetarea erorii -- Functie pentru resetarea erorii
PROCEDURE clear_error; PROCEDURE clear_error;
-- Main parsing functions -- Main parsing functions
FUNCTION parse_array(p_json_array IN CLOB) RETURN t_json_array PIPELINED; -- Parse [{"a":1},{"b":2}] FUNCTION parse_array(p_json_array IN CLOB) RETURN t_json_array PIPELINED; -- Parse [{"a":1},{"b":2}]
FUNCTION get_string(p_json_object IN VARCHAR2, p_key_name IN VARCHAR2) RETURN VARCHAR2; -- Get "value" FUNCTION get_string(p_json_object IN VARCHAR2, p_key_name IN VARCHAR2) RETURN VARCHAR2; -- Get "value"
FUNCTION get_number(p_json_object IN VARCHAR2, p_key_name IN VARCHAR2) RETURN NUMBER; -- Get 123.45 FUNCTION get_number(p_json_object IN VARCHAR2, p_key_name IN VARCHAR2) RETURN NUMBER; -- Get 123.45
FUNCTION get_boolean(p_json_object IN VARCHAR2, p_key_name IN VARCHAR2) RETURN BOOLEAN; -- Get true/false FUNCTION get_boolean(p_json_object IN VARCHAR2, p_key_name IN VARCHAR2) RETURN BOOLEAN; -- Get true/false
-- Advanced functions -- Advanced functions
FUNCTION parse_object(p_json_object IN VARCHAR2) RETURN t_json_object PIPELINED; -- Parse to key-value pairs FUNCTION parse_object(p_json_object IN VARCHAR2) RETURN t_json_object PIPELINED; -- Parse to key-value pairs
FUNCTION clean(p_json IN CLOB) RETURN CLOB; -- Remove whitespace/formatting FUNCTION clean(p_json IN CLOB) RETURN CLOB; -- Remove whitespace/formatting
-- Test functions -- Test functions
PROCEDURE run_tests; -- Run all built-in tests PROCEDURE run_tests; -- Run all built-in tests
FUNCTION test_basic_parsing RETURN VARCHAR2; -- Test basic JSON parsing FUNCTION test_basic_parsing RETURN VARCHAR2; -- Test basic JSON parsing
@@ -44,10 +39,6 @@ CREATE OR REPLACE PACKAGE PACK_JSON AS
END PACK_JSON; END PACK_JSON;
/ /
-- ====================================================================
-- Package Body - Implementarea functiilor
-- ====================================================================
CREATE OR REPLACE PACKAGE BODY PACK_JSON AS CREATE OR REPLACE PACKAGE BODY PACK_JSON AS
/* /*
PACK_JSON - Generic JSON Parser (Oracle 10g/11g/12c compatible) PACK_JSON - Generic JSON Parser (Oracle 10g/11g/12c compatible)
@@ -57,12 +48,12 @@ USAGE:
FOR obj IN (SELECT * FROM TABLE(PACK_JSON.parse_array(json_clob))) LOOP FOR obj IN (SELECT * FROM TABLE(PACK_JSON.parse_array(json_clob))) LOOP
v_val := PACK_JSON.get_string(obj.COLUMN_VALUE, 'key'); v_val := PACK_JSON.get_string(obj.COLUMN_VALUE, 'key');
END LOOP; END LOOP;
-- Get values from object: {"name":"John","age":25,"active":true} -- Get values from object: {"name":"John","age":25,"active":true}
v_name := PACK_JSON.get_string(json_obj, 'name'); -- Returns: John v_name := PACK_JSON.get_string(json_obj, 'name'); -- Returns: John
v_age := PACK_JSON.get_number(json_obj, 'age'); -- Returns: 25 v_age := PACK_JSON.get_number(json_obj, 'age'); -- Returns: 25
v_active := PACK_JSON.get_boolean(json_obj, 'active'); -- Returns: TRUE v_active := PACK_JSON.get_boolean(json_obj, 'active'); -- Returns: TRUE
-- Error handling: -- Error handling:
IF PACK_JSON.get_last_error() IS NOT NULL THEN IF PACK_JSON.get_last_error() IS NOT NULL THEN
-- Handle error: PACK_JSON.get_last_error() -- Handle error: PACK_JSON.get_last_error()
@@ -72,7 +63,7 @@ USAGE:
FUNCTIONS: FUNCTIONS:
parse_array(clob) - Parse JSON array, returns table of objects parse_array(clob) - Parse JSON array, returns table of objects
get_string(obj,key) - Extract string value from JSON object get_string(obj,key) - Extract string value from JSON object
get_number(obj,key) - Extract number value from JSON object get_number(obj,key) - Extract number value from JSON object
get_boolean(obj,key) - Extract boolean value from JSON object get_boolean(obj,key) - Extract boolean value from JSON object
get_last_error() - Get last parsing error (NULL if no error) get_last_error() - Get last parsing error (NULL if no error)
clear_error() - Clear error state clear_error() - Clear error state
@@ -85,7 +76,7 @@ FUNCTIONS:
BEGIN BEGIN
RETURN g_last_error; RETURN g_last_error;
END get_last_error; END get_last_error;
PROCEDURE clear_error IS PROCEDURE clear_error IS
BEGIN BEGIN
g_last_error := NULL; g_last_error := NULL;
@@ -100,9 +91,9 @@ FUNCTIONS:
v_clean CLOB; v_clean CLOB;
BEGIN BEGIN
-- Elimina spatii, tab-uri, newline-uri pentru parsing mai usor -- Elimina spatii, tab-uri, newline-uri pentru parsing mai usor
v_clean := REPLACE(REPLACE(REPLACE(REPLACE(p_json, v_clean := REPLACE(REPLACE(REPLACE(REPLACE(p_json,
CHR(10), ''), CHR(13), ''), CHR(9), ''), ' ', ''); CHR(10), ''), CHR(13), ''), CHR(9), ''), ' ', '');
RETURN v_clean; RETURN v_clean;
END clean; END clean;
@@ -112,50 +103,50 @@ FUNCTIONS:
FUNCTION parse_array( FUNCTION parse_array(
p_json_array IN CLOB p_json_array IN CLOB
) RETURN t_json_array PIPELINED IS ) RETURN t_json_array PIPELINED IS
v_json_clean CLOB; v_json_clean CLOB;
v_articol_json VARCHAR2(4000); v_articol_json VARCHAR2(4000);
v_start_pos NUMBER := 1; v_start_pos NUMBER := 1;
v_end_pos NUMBER; v_end_pos NUMBER;
v_bracket_count NUMBER; v_bracket_count NUMBER;
BEGIN BEGIN
-- Reset error -- Reset error
g_last_error := NULL; g_last_error := NULL;
-- Curata JSON-ul -- Curata JSON-ul
v_json_clean := clean(p_json_array); v_json_clean := clean(p_json_array);
-- Elimina bracket-urile exterioare [ ] -- Elimina bracket-urile exterioare [ ]
v_json_clean := TRIM(BOTH '[]' FROM v_json_clean); v_json_clean := TRIM(BOTH '[]' FROM v_json_clean);
-- Parse fiecare obiect JSON din array -- Parse fiecare obiect JSON din array
LOOP LOOP
-- Gaseste inceputul obiectului JSON { -- Gaseste inceputul obiectului JSON {
v_start_pos := INSTR(v_json_clean, '{', v_start_pos); v_start_pos := INSTR(v_json_clean, '{', v_start_pos);
EXIT WHEN v_start_pos = 0; EXIT WHEN v_start_pos = 0;
-- Gaseste sfarsitul obiectului JSON } - ia in considerare nested objects -- Gaseste sfarsitul obiectului JSON } - ia in considerare nested objects
v_bracket_count := 1; v_bracket_count := 1;
v_end_pos := v_start_pos; v_end_pos := v_start_pos;
WHILE v_bracket_count > 0 AND v_end_pos < LENGTH(v_json_clean) LOOP WHILE v_bracket_count > 0 AND v_end_pos < LENGTH(v_json_clean) LOOP
v_end_pos := v_end_pos + 1; v_end_pos := v_end_pos + 1;
IF SUBSTR(v_json_clean, v_end_pos, 1) = '{' THEN IF SUBSTR(v_json_clean, v_end_pos, 1) = '{' THEN
v_bracket_count := v_bracket_count + 1; v_bracket_count := v_bracket_count + 1;
ELSIF SUBSTR(v_json_clean, v_end_pos, 1) = '}' THEN ELSIF SUBSTR(v_json_clean, v_end_pos, 1) = '}' THEN
v_bracket_count := v_bracket_count - 1; v_bracket_count := v_bracket_count - 1;
END IF; END IF;
END LOOP; END LOOP;
-- Extrage obiectul JSON curent -- Extrage obiectul JSON curent
IF v_bracket_count = 0 THEN IF v_bracket_count = 0 THEN
v_articol_json := SUBSTR(v_json_clean, v_start_pos, v_end_pos - v_start_pos + 1); v_articol_json := SUBSTR(v_json_clean, v_start_pos, v_end_pos - v_start_pos + 1);
PIPE ROW(v_articol_json); PIPE ROW(v_articol_json);
-- Trece la urmatorul articol -- Trece la urmatorul articol
v_start_pos := v_end_pos + 1; v_start_pos := v_end_pos + 1;
ELSE ELSE
@@ -164,8 +155,8 @@ FUNCTIONS:
EXIT; EXIT;
END IF; END IF;
END LOOP; END LOOP;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
g_last_error := 'Eroare la parsing array: ' || SQLERRM; g_last_error := 'Eroare la parsing array: ' || SQLERRM;
@@ -181,16 +172,16 @@ FUNCTIONS:
v_result VARCHAR2(4000); v_result VARCHAR2(4000);
BEGIN BEGIN
-- Oracle 10g compatible: Extract string values -- Oracle 10g compatible: Extract string values
v_result := REGEXP_SUBSTR(p_json_object, v_result := REGEXP_SUBSTR(p_json_object,
'"' || p_key_name || '":"[^"]*"'); '"' || p_key_name || '":"[^"]*"');
IF v_result IS NOT NULL THEN IF v_result IS NOT NULL THEN
-- Remove key part and quotes manually -- Remove key part and quotes manually
v_result := REGEXP_REPLACE(v_result, '^"' || p_key_name || '":"', ''); v_result := REGEXP_REPLACE(v_result, '^"' || p_key_name || '":"', '');
v_result := REGEXP_REPLACE(v_result, '"$', ''); v_result := REGEXP_REPLACE(v_result, '"$', '');
END IF; END IF;
RETURN v_result; RETURN v_result;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
g_last_error := 'Eroare la extragere string pentru ' || p_key_name || ': ' || SQLERRM; g_last_error := 'Eroare la extragere string pentru ' || p_key_name || ': ' || SQLERRM;
@@ -209,23 +200,23 @@ FUNCTIONS:
BEGIN BEGIN
-- Oracle 10g compatible: Extract number values without subexpressions -- Oracle 10g compatible: Extract number values without subexpressions
-- Pattern: "key_name":123.45 (numeric value direct) -- Pattern: "key_name":123.45 (numeric value direct)
v_result_str := REGEXP_SUBSTR(p_json_object, v_result_str := REGEXP_SUBSTR(p_json_object,
'"' || p_key_name || '":[0-9]+\.?[0-9]*'); '"' || p_key_name || '":[0-9]+\.?[0-9]*');
IF v_result_str IS NOT NULL THEN IF v_result_str IS NOT NULL THEN
-- Extract just the number part after the colon -- Extract just the number part after the colon
v_result_str := REGEXP_SUBSTR(v_result_str, '[0-9]+\.?[0-9]*'); v_result_str := REGEXP_SUBSTR(v_result_str, '[0-9]+\.?[0-9]*');
END IF; END IF;
-- Daca nu gaseste, incearca cu quotes: "key_name":"123.45" -- Daca nu gaseste, incearca cu quotes: "key_name":"123.45"
IF v_result_str IS NULL OR LENGTH(TRIM(v_result_str)) = 0 THEN IF v_result_str IS NULL OR LENGTH(TRIM(v_result_str)) = 0 THEN
v_result_str := REGEXP_SUBSTR(p_json_object, v_result_str := REGEXP_SUBSTR(p_json_object,
'"' || p_key_name || '":"[0-9]+\.?[0-9]*"'); '"' || p_key_name || '":"[0-9]+\.?[0-9]*"');
IF v_result_str IS NOT NULL THEN IF v_result_str IS NOT NULL THEN
-- Extract number between quotes -- Extract number between quotes
v_result_str := REGEXP_SUBSTR(v_result_str, '[0-9]+\.?[0-9]*'); v_result_str := REGEXP_SUBSTR(v_result_str, '[0-9]+\.?[0-9]*');
END IF; END IF;
END IF; END IF;
IF v_result_str IS NOT NULL AND LENGTH(TRIM(v_result_str)) > 0 THEN IF v_result_str IS NOT NULL AND LENGTH(TRIM(v_result_str)) > 0 THEN
BEGIN BEGIN
v_result_str := TRIM(v_result_str); v_result_str := TRIM(v_result_str);
@@ -243,9 +234,9 @@ FUNCTIONS:
END; END;
END; END;
END IF; END IF;
RETURN v_result; RETURN v_result;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
g_last_error := 'Eroare la extragere number pentru ' || p_key_name || ': ' || SQLERRM; g_last_error := 'Eroare la extragere number pentru ' || p_key_name || ': ' || SQLERRM;
@@ -262,13 +253,13 @@ FUNCTIONS:
v_result_str VARCHAR2(100); v_result_str VARCHAR2(100);
BEGIN BEGIN
-- Oracle 10g compatible: Extract boolean values -- Oracle 10g compatible: Extract boolean values
v_result_str := REGEXP_SUBSTR(p_json_object, v_result_str := REGEXP_SUBSTR(p_json_object,
'"' || p_key_name || '":(true|false)'); '"' || p_key_name || '":(true|false)');
IF v_result_str IS NOT NULL THEN IF v_result_str IS NOT NULL THEN
-- Extract just the boolean value -- Extract just the boolean value
v_result_str := REGEXP_REPLACE(v_result_str, '^"' || p_key_name || '":', ''); v_result_str := REGEXP_REPLACE(v_result_str, '^"' || p_key_name || '":', '');
END IF; END IF;
IF v_result_str = 'true' THEN IF v_result_str = 'true' THEN
RETURN TRUE; RETURN TRUE;
ELSIF v_result_str = 'false' THEN ELSIF v_result_str = 'false' THEN
@@ -276,7 +267,7 @@ FUNCTIONS:
ELSE ELSE
RETURN NULL; RETURN NULL;
END IF; END IF;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
g_last_error := 'Eroare la extragere boolean pentru ' || p_key_name || ': ' || SQLERRM; g_last_error := 'Eroare la extragere boolean pentru ' || p_key_name || ': ' || SQLERRM;
@@ -289,7 +280,7 @@ FUNCTIONS:
FUNCTION parse_object( FUNCTION parse_object(
p_json_object IN VARCHAR2 p_json_object IN VARCHAR2
) RETURN t_json_object PIPELINED IS ) RETURN t_json_object PIPELINED IS
v_clean_json VARCHAR2(4000); v_clean_json VARCHAR2(4000);
v_key VARCHAR2(100); v_key VARCHAR2(100);
v_value VARCHAR2(4000); v_value VARCHAR2(4000);
@@ -299,27 +290,27 @@ FUNCTIONS:
v_key_end NUMBER; v_key_end NUMBER;
v_value_start NUMBER; v_value_start NUMBER;
v_value_end NUMBER; v_value_end NUMBER;
BEGIN BEGIN
-- Curata JSON-ul si elimina { } -- Curata JSON-ul si elimina { }
v_clean_json := TRIM(BOTH '{}' FROM REPLACE(p_json_object, ' ', '')); v_clean_json := TRIM(BOTH '{}' FROM REPLACE(p_json_object, ' ', ''));
-- Parse fiecare pereche key:value -- Parse fiecare pereche key:value
WHILE v_pos < LENGTH(v_clean_json) LOOP WHILE v_pos < LENGTH(v_clean_json) LOOP
-- Gaseste cheia -- Gaseste cheia
v_key_start := INSTR(v_clean_json, '"', v_pos); v_key_start := INSTR(v_clean_json, '"', v_pos);
EXIT WHEN v_key_start = 0; EXIT WHEN v_key_start = 0;
v_key_end := INSTR(v_clean_json, '"', v_key_start + 1); v_key_end := INSTR(v_clean_json, '"', v_key_start + 1);
EXIT WHEN v_key_end = 0; EXIT WHEN v_key_end = 0;
v_key := SUBSTR(v_clean_json, v_key_start + 1, v_key_end - v_key_start - 1); v_key := SUBSTR(v_clean_json, v_key_start + 1, v_key_end - v_key_start - 1);
-- Gaseste valoarea -- Gaseste valoarea
v_value_start := INSTR(v_clean_json, ':', v_key_end); v_value_start := INSTR(v_clean_json, ':', v_key_end);
EXIT WHEN v_value_start = 0; EXIT WHEN v_value_start = 0;
v_value_start := v_value_start + 1; v_value_start := v_value_start + 1;
-- Determina tipul si extrage valoarea -- Determina tipul si extrage valoarea
IF SUBSTR(v_clean_json, v_value_start, 1) = '"' THEN IF SUBSTR(v_clean_json, v_value_start, 1) = '"' THEN
-- String value -- String value
@@ -331,7 +322,7 @@ FUNCTIONS:
-- Number, boolean sau null -- Number, boolean sau null
v_value_end := NVL(INSTR(v_clean_json, ',', v_value_start), LENGTH(v_clean_json) + 1); v_value_end := NVL(INSTR(v_clean_json, ',', v_value_start), LENGTH(v_clean_json) + 1);
v_value := SUBSTR(v_clean_json, v_value_start, v_value_end - v_value_start); v_value := SUBSTR(v_clean_json, v_value_start, v_value_end - v_value_start);
IF v_value IN ('true', 'false') THEN IF v_value IN ('true', 'false') THEN
v_result.key_type := 'BOOLEAN'; v_result.key_type := 'BOOLEAN';
ELSIF v_value = 'null' THEN ELSIF v_value = 'null' THEN
@@ -341,16 +332,16 @@ FUNCTIONS:
ELSE ELSE
v_result.key_type := 'UNKNOWN'; v_result.key_type := 'UNKNOWN';
END IF; END IF;
v_pos := v_value_end + 1; v_pos := v_value_end + 1;
END IF; END IF;
v_result.key_name := v_key; v_result.key_name := v_key;
v_result.key_value := v_value; v_result.key_value := v_value;
PIPE ROW(v_result); PIPE ROW(v_result);
END LOOP; END LOOP;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
g_last_error := 'Eroare la parsing obiect: ' || SQLERRM; g_last_error := 'Eroare la parsing obiect: ' || SQLERRM;
@@ -359,7 +350,7 @@ FUNCTIONS:
-- ================================================================ -- ================================================================
-- Functii de testare -- Functii de testare
-- ================================================================ -- ================================================================
FUNCTION test_basic_parsing RETURN VARCHAR2 IS FUNCTION test_basic_parsing RETURN VARCHAR2 IS
v_test_json VARCHAR2(1000) := '{"name":"John","age":25,"active":true,"score":98.5}'; v_test_json VARCHAR2(1000) := '{"name":"John","age":25,"active":true,"score":98.5}';
v_name VARCHAR2(100); v_name VARCHAR2(100);
@@ -369,29 +360,29 @@ FUNCTIONS:
v_result VARCHAR2(4000) := 'BASIC_PARSING: '; v_result VARCHAR2(4000) := 'BASIC_PARSING: ';
BEGIN BEGIN
clear_error(); clear_error();
v_name := get_string(v_test_json, 'name'); v_name := get_string(v_test_json, 'name');
v_age := get_number(v_test_json, 'age'); v_age := get_number(v_test_json, 'age');
v_active := get_boolean(v_test_json, 'active'); v_active := get_boolean(v_test_json, 'active');
v_score := get_number(v_test_json, 'score'); v_score := get_number(v_test_json, 'score');
-- Validate results -- Validate results
IF v_name = 'John' AND v_age = 25 AND v_active = TRUE AND v_score = 98.5 THEN IF v_name = 'John' AND v_age = 25 AND v_active = TRUE AND v_score = 98.5 THEN
v_result := v_result || 'PASS - All values extracted correctly'; v_result := v_result || 'PASS - All values extracted correctly';
ELSE ELSE
v_result := v_result || 'FAIL - Values: name=' || v_name || ', age=' || v_age || ', score=' || v_score; v_result := v_result || 'FAIL - Values: name=' || v_name || ', age=' || v_age || ', score=' || v_score;
END IF; END IF;
IF get_last_error() IS NOT NULL THEN IF get_last_error() IS NOT NULL THEN
v_result := v_result || ' ERROR: ' || get_last_error(); v_result := v_result || ' ERROR: ' || get_last_error();
END IF; END IF;
RETURN v_result; RETURN v_result;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
RETURN 'BASIC_PARSING: EXCEPTION - ' || SQLERRM; RETURN 'BASIC_PARSING: EXCEPTION - ' || SQLERRM;
END test_basic_parsing; END test_basic_parsing;
FUNCTION test_array_parsing RETURN VARCHAR2 IS FUNCTION test_array_parsing RETURN VARCHAR2 IS
v_test_array CLOB := '[{"sku":"PROD1","price":10.5},{"sku":"PROD2","price":25.0}]'; v_test_array CLOB := '[{"sku":"PROD1","price":10.5},{"sku":"PROD2","price":25.0}]';
v_count NUMBER := 0; v_count NUMBER := 0;
@@ -400,12 +391,12 @@ FUNCTIONS:
v_result VARCHAR2(4000) := 'ARRAY_PARSING: '; v_result VARCHAR2(4000) := 'ARRAY_PARSING: ';
BEGIN BEGIN
clear_error(); clear_error();
FOR obj IN (SELECT * FROM TABLE(parse_array(v_test_array))) LOOP FOR obj IN (SELECT * FROM TABLE(parse_array(v_test_array))) LOOP
v_count := v_count + 1; v_count := v_count + 1;
v_sku := get_string(obj.COLUMN_VALUE, 'sku'); v_sku := get_string(obj.COLUMN_VALUE, 'sku');
v_price := get_number(obj.COLUMN_VALUE, 'price'); v_price := get_number(obj.COLUMN_VALUE, 'price');
IF v_count = 1 THEN IF v_count = 1 THEN
IF v_sku != 'PROD1' OR v_price != 10.5 THEN IF v_sku != 'PROD1' OR v_price != 10.5 THEN
RETURN v_result || 'FAIL - First object: sku=' || v_sku || ', price=' || v_price; RETURN v_result || 'FAIL - First object: sku=' || v_sku || ', price=' || v_price;
@@ -416,23 +407,23 @@ FUNCTIONS:
END IF; END IF;
END IF; END IF;
END LOOP; END LOOP;
IF v_count = 2 THEN IF v_count = 2 THEN
v_result := v_result || 'PASS - Parsed ' || v_count || ' objects correctly'; v_result := v_result || 'PASS - Parsed ' || v_count || ' objects correctly';
ELSE ELSE
v_result := v_result || 'FAIL - Expected 2 objects, got ' || v_count; v_result := v_result || 'FAIL - Expected 2 objects, got ' || v_count;
END IF; END IF;
IF get_last_error() IS NOT NULL THEN IF get_last_error() IS NOT NULL THEN
v_result := v_result || ' ERROR: ' || get_last_error(); v_result := v_result || ' ERROR: ' || get_last_error();
END IF; END IF;
RETURN v_result; RETURN v_result;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
RETURN 'ARRAY_PARSING: EXCEPTION - ' || SQLERRM; RETURN 'ARRAY_PARSING: EXCEPTION - ' || SQLERRM;
END test_array_parsing; END test_array_parsing;
FUNCTION test_nested_objects RETURN VARCHAR2 IS FUNCTION test_nested_objects RETURN VARCHAR2 IS
v_test_nested CLOB := '[{"order":{"id":123,"items":[{"sku":"A1","qty":2}],"total":25.50}},{"order":{"id":124,"items":[{"sku":"B1","qty":1},{"sku":"C1","qty":3}],"total":45.00}}]'; v_test_nested CLOB := '[{"order":{"id":123,"items":[{"sku":"A1","qty":2}],"total":25.50}},{"order":{"id":124,"items":[{"sku":"B1","qty":1},{"sku":"C1","qty":3}],"total":45.00}}]';
v_count NUMBER := 0; v_count NUMBER := 0;
@@ -443,16 +434,16 @@ FUNCTIONS:
v_order_json VARCHAR2(2000); v_order_json VARCHAR2(2000);
BEGIN BEGIN
clear_error(); clear_error();
-- Test parsing array cu nested objects -- Test parsing array cu nested objects
FOR obj IN (SELECT * FROM TABLE(parse_array(v_test_nested))) LOOP FOR obj IN (SELECT * FROM TABLE(parse_array(v_test_nested))) LOOP
v_count := v_count + 1; v_count := v_count + 1;
v_object := obj.COLUMN_VALUE; v_object := obj.COLUMN_VALUE;
-- Extrage nested object "order" (Oracle 10g compatible) -- Extrage nested object "order" (Oracle 10g compatible)
v_order_json := REGEXP_SUBSTR(v_object, '"order":\{[^}]+\}'); v_order_json := REGEXP_SUBSTR(v_object, '"order":\{[^}]+\}');
IF v_order_json IS NOT NULL THEN IF v_order_json IS NOT NULL THEN
-- Extract just the object part -- Extract just the object part
v_order_json := REGEXP_REPLACE(v_order_json, '^"order":', ''); v_order_json := REGEXP_REPLACE(v_order_json, '^"order":', '');
END IF; END IF;
IF v_order_json IS NULL THEN IF v_order_json IS NULL THEN
@@ -461,11 +452,11 @@ FUNCTIONS:
-- Elimina "order": din fata -- Elimina "order": din fata
v_order_json := REGEXP_REPLACE(v_order_json, '^"order":', ''); v_order_json := REGEXP_REPLACE(v_order_json, '^"order":', '');
END IF; END IF;
IF v_order_json IS NOT NULL THEN IF v_order_json IS NOT NULL THEN
v_order_id := get_number(v_order_json, 'id'); v_order_id := get_number(v_order_json, 'id');
v_total := get_number(v_order_json, 'total'); v_total := get_number(v_order_json, 'total');
IF v_count = 1 THEN IF v_count = 1 THEN
IF v_order_id != 123 OR v_total != 25.50 THEN IF v_order_id != 123 OR v_total != 25.50 THEN
RETURN v_result || 'FAIL - First nested: id=' || v_order_id || ', total=' || v_total; RETURN v_result || 'FAIL - First nested: id=' || v_order_id || ', total=' || v_total;
@@ -479,30 +470,30 @@ FUNCTIONS:
RETURN v_result || 'FAIL - Could not extract nested order object from: ' || SUBSTR(v_object, 1, 100); RETURN v_result || 'FAIL - Could not extract nested order object from: ' || SUBSTR(v_object, 1, 100);
END IF; END IF;
END LOOP; END LOOP;
IF v_count = 2 THEN IF v_count = 2 THEN
v_result := v_result || 'PASS - Parsed ' || v_count || ' nested objects correctly'; v_result := v_result || 'PASS - Parsed ' || v_count || ' nested objects correctly';
ELSE ELSE
v_result := v_result || 'FAIL - Expected 2 nested objects, got ' || v_count; v_result := v_result || 'FAIL - Expected 2 nested objects, got ' || v_count;
END IF; END IF;
IF get_last_error() IS NOT NULL THEN IF get_last_error() IS NOT NULL THEN
v_result := v_result || ' ERROR: ' || get_last_error(); v_result := v_result || ' ERROR: ' || get_last_error();
END IF; END IF;
RETURN v_result; RETURN v_result;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
RETURN 'NESTED_OBJECTS: EXCEPTION - ' || SQLERRM; RETURN 'NESTED_OBJECTS: EXCEPTION - ' || SQLERRM;
END test_nested_objects; END test_nested_objects;
FUNCTION test_error_handling RETURN VARCHAR2 IS FUNCTION test_error_handling RETURN VARCHAR2 IS
v_result VARCHAR2(4000) := 'ERROR_HANDLING: '; v_result VARCHAR2(4000) := 'ERROR_HANDLING: ';
v_invalid_json VARCHAR2(1000) := '{"broken":}'; v_invalid_json VARCHAR2(1000) := '{"broken":}';
v_value VARCHAR2(100); v_value VARCHAR2(100);
BEGIN BEGIN
clear_error(); clear_error();
-- Force an error by trying to parse malformed array -- Force an error by trying to parse malformed array
BEGIN BEGIN
FOR obj IN (SELECT * FROM TABLE(parse_array('[{"incomplete":"object"'))) LOOP FOR obj IN (SELECT * FROM TABLE(parse_array('[{"incomplete":"object"'))) LOOP
@@ -513,52 +504,52 @@ FUNCTIONS:
-- This should trigger parse_array to set g_last_error -- This should trigger parse_array to set g_last_error
NULL; NULL;
END; END;
-- Alternative: try to get a string from NULL object -- Alternative: try to get a string from NULL object
v_value := get_string(NULL, 'test'); v_value := get_string(NULL, 'test');
IF get_last_error() IS NOT NULL THEN IF get_last_error() IS NOT NULL THEN
v_result := v_result || 'PASS - Error properly captured: ' || SUBSTR(get_last_error(), 1, 100); v_result := v_result || 'PASS - Error properly captured: ' || SUBSTR(get_last_error(), 1, 100);
clear_error(); clear_error();
ELSE ELSE
v_result := v_result || 'FAIL - No error captured for invalid operations'; v_result := v_result || 'FAIL - No error captured for invalid operations';
END IF; END IF;
-- Test error clearing -- Test error clearing
IF get_last_error() IS NULL THEN IF get_last_error() IS NULL THEN
v_result := v_result || ' - Error cleared successfully'; v_result := v_result || ' - Error cleared successfully';
ELSE ELSE
v_result := v_result || ' - Error not cleared properly'; v_result := v_result || ' - Error not cleared properly';
END IF; END IF;
RETURN v_result; RETURN v_result;
EXCEPTION EXCEPTION
WHEN OTHERS THEN WHEN OTHERS THEN
RETURN 'ERROR_HANDLING: EXCEPTION - ' || SQLERRM; RETURN 'ERROR_HANDLING: EXCEPTION - ' || SQLERRM;
END test_error_handling; END test_error_handling;
PROCEDURE run_tests IS PROCEDURE run_tests IS
v_test_result VARCHAR2(4000); v_test_result VARCHAR2(4000);
BEGIN BEGIN
DBMS_OUTPUT.PUT_LINE('=== PACK_JSON Test Suite ==='); DBMS_OUTPUT.PUT_LINE('=== PACK_JSON Test Suite ===');
DBMS_OUTPUT.PUT_LINE(''); DBMS_OUTPUT.PUT_LINE('');
-- Test 1: Basic parsing -- Test 1: Basic parsing
v_test_result := test_basic_parsing(); v_test_result := test_basic_parsing();
DBMS_OUTPUT.PUT_LINE(v_test_result); DBMS_OUTPUT.PUT_LINE(v_test_result);
-- Test 2: Array parsing -- Test 2: Array parsing
v_test_result := test_array_parsing(); v_test_result := test_array_parsing();
DBMS_OUTPUT.PUT_LINE(v_test_result); DBMS_OUTPUT.PUT_LINE(v_test_result);
-- Test 3: Nested objects -- Test 3: Nested objects
v_test_result := test_nested_objects(); v_test_result := test_nested_objects();
DBMS_OUTPUT.PUT_LINE(v_test_result); DBMS_OUTPUT.PUT_LINE(v_test_result);
-- Test 4: Error handling -- Test 4: Error handling
v_test_result := test_error_handling(); v_test_result := test_error_handling();
DBMS_OUTPUT.PUT_LINE(v_test_result); DBMS_OUTPUT.PUT_LINE(v_test_result);
DBMS_OUTPUT.PUT_LINE(''); DBMS_OUTPUT.PUT_LINE('');
DBMS_OUTPUT.PUT_LINE('=== Test Suite Complete ==='); DBMS_OUTPUT.PUT_LINE('=== Test Suite Complete ===');
EXCEPTION EXCEPTION
@@ -568,8 +559,3 @@ FUNCTIONS:
END PACK_JSON; END PACK_JSON;
/ /
-- ====================================================================
-- Grant-uri pentru utilizarea package-ului
-- ====================================================================
-- GRANT EXECUTE ON PACK_JSON TO PUBLIC;