Files
gomag-vending/api/database-scripts/06_pack_import_comenzi.pck
Claude Agent 9f2fd24d93 docs(design): add design system with typography, colors, and mobile specs
Industrial/utilitarian aesthetic with amber accent, Space Grotesk + DM Sans +
JetBrains Mono stack, full dark mode, and dedicated mobile design including
bottom nav and card-based order views. Updates CLAUDE.md to enforce DESIGN.md
compliance on all visual work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:29:13 +00:00

662 lines
29 KiB
Plaintext

CREATE OR REPLACE PACKAGE PACK_IMPORT_COMENZI AS
-- Variabila package pentru ultima eroare (pentru orchestrator VFP)
g_last_error VARCHAR2(4000);
-- 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,
p_id_pol IN NUMBER DEFAULT NULL,
p_id_sectie IN NUMBER DEFAULT NULL,
p_id_gestiune IN VARCHAR2 DEFAULT NULL,
p_kit_mode IN VARCHAR2 DEFAULT NULL,
p_id_pol_productie IN NUMBER DEFAULT NULL,
p_kit_discount_codmat IN VARCHAR2 DEFAULT NULL,
p_kit_discount_id_pol IN NUMBER DEFAULT NULL,
v_id_comanda OUT NUMBER);
-- Functii pentru managementul erorilor (pentru orchestrator VFP)
FUNCTION get_last_error RETURN VARCHAR2;
PROCEDURE clear_error;
END PACK_IMPORT_COMENZI;
/
CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS
-- ====================================================================
-- PACK_IMPORT_COMENZI
-- Package pentru importul comenzilor din platforme web (GoMag, etc.)
-- in sistemul ROA Oracle.
--
-- Dependinte:
-- Packages: PACK_COMENZI (adauga_comanda, adauga_articol_comanda)
-- pljson (pljson_list, pljson) - instalat in CONTAFIN_ORACLE,
-- accesat prin PUBLIC SYNONYM
-- Tabele: ARTICOLE_TERTI (mapari SKU -> CODMAT)
-- NOM_ARTICOLE (nomenclator articole ROA)
-- COMENZI (verificare duplicat comanda_externa)
-- CRM_POLITICI_PRETURI (flag PRETURI_CU_TVA per politica)
-- CRM_POLITICI_PRET_ART (preturi componente kituri)
-- 20.03.2026 - dual policy vanzare/productie, kit pricing distributed/separate_line, SKU→CODMAT via ARTICOLE_TERTI
-- 20.03.2026 - kit discount deferred cross-kit (separate_line, merge-on-collision)
-- 20.03.2026 - merge_or_insert_articol: merge cantitati cand kit+individual au acelasi articol/pret
-- 20.03.2026 - kit pricing extins pt reambalari single-component (cantitate_roa > 1)
-- 21.03.2026 - diagnostic detaliat discount kit (id_pol, id_art, codmat in eroare)
-- 21.03.2026 - fix discount amount: v_disc_amt e per-kit, nu se imparte la v_cantitate_web
-- 25.03.2026 - skip negative kit discount (markup), ROUND prices to nzecimale_pretv
-- 25.03.2026 - kit discount inserat per-kit sub componente (nu deferred cross-kit)
-- ====================================================================
-- Constante pentru configurare
c_id_util CONSTANT NUMBER := -3; -- Sistem
c_interna CONSTANT NUMBER := 2; -- Comenzi de la client (web)
-- Tipuri pentru kit pricing (accesibile in toate procedurile din body)
TYPE t_kit_component IS RECORD (
codmat VARCHAR2(50),
id_articol NUMBER,
cantitate_roa NUMBER,
pret_cu_tva NUMBER,
ptva NUMBER,
id_pol_comp NUMBER,
value_total NUMBER
);
TYPE t_kit_components IS TABLE OF t_kit_component INDEX BY PLS_INTEGER;
-- ================================================================
-- 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;
-- ================================================================
-- Functie helper: selecteaza id_articol corect pentru un CODMAT
-- Prioritate: sters=0 AND inactiv=0, preferinta stoc, MAX(id_articol) fallback
-- ================================================================
FUNCTION resolve_id_articol(p_codmat IN VARCHAR2, p_id_gest IN VARCHAR2) RETURN NUMBER IS
v_result NUMBER;
BEGIN
IF p_id_gest IS NOT NULL THEN
-- Cu gestiuni specifice (CSV: "1,3") — split in subquery pentru IN clause
BEGIN
SELECT id_articol INTO v_result FROM (
SELECT na.id_articol
FROM nom_articole na
WHERE na.codmat = p_codmat AND na.sters = 0 AND na.inactiv = 0
ORDER BY
CASE WHEN EXISTS (
SELECT 1 FROM stoc s
WHERE s.id_articol = na.id_articol
AND s.id_gestiune IN (
SELECT TO_NUMBER(REGEXP_SUBSTR(p_id_gest, '[^,]+', 1, LEVEL))
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT(p_id_gest, ',') + 1
)
AND s.an = EXTRACT(YEAR FROM SYSDATE)
AND s.luna = EXTRACT(MONTH FROM SYSDATE)
AND s.cants + s.cant - s.cante > 0
) THEN 0 ELSE 1 END,
na.id_articol DESC
) WHERE ROWNUM = 1;
EXCEPTION WHEN NO_DATA_FOUND THEN v_result := NULL;
END;
ELSE
-- Fara gestiune — cauta stoc in orice gestiune
BEGIN
SELECT id_articol INTO v_result FROM (
SELECT na.id_articol
FROM nom_articole na
WHERE na.codmat = p_codmat AND na.sters = 0 AND na.inactiv = 0
ORDER BY
CASE WHEN EXISTS (
SELECT 1 FROM stoc s
WHERE s.id_articol = na.id_articol
AND s.an = EXTRACT(YEAR FROM SYSDATE)
AND s.luna = EXTRACT(MONTH FROM SYSDATE)
AND s.cants + s.cant - s.cante > 0
) THEN 0 ELSE 1 END,
na.id_articol DESC
) WHERE ROWNUM = 1;
EXCEPTION WHEN NO_DATA_FOUND THEN v_result := NULL;
END;
END IF;
RETURN v_result;
END resolve_id_articol;
-- ================================================================
-- Helper: merge-or-insert articol pe comanda
-- Daca aceeasi combinatie (ID_COMANDA, ID_ARTICOL, PTVA, PRET, SIGN(CANTITATE))
-- exista deja, aduna cantitatea; altfel insereaza linie noua.
-- Previne crash la duplicate cand acelasi articol apare din kit + individual.
-- ================================================================
PROCEDURE merge_or_insert_articol(
p_id_comanda IN NUMBER,
p_id_articol IN NUMBER,
p_id_pol IN NUMBER,
p_cantitate IN NUMBER,
p_pret IN NUMBER,
p_id_util IN NUMBER,
p_id_sectie IN NUMBER,
p_ptva IN NUMBER
) IS
v_cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO v_cnt
FROM COMENZI_ELEMENTE
WHERE ID_COMANDA = p_id_comanda
AND ID_ARTICOL = p_id_articol
AND NVL(PTVA, 0) = NVL(p_ptva, 0)
AND PRET = p_pret
AND SIGN(CANTITATE) = SIGN(p_cantitate)
AND STERS = 0;
IF v_cnt > 0 THEN
UPDATE COMENZI_ELEMENTE
SET CANTITATE = CANTITATE + p_cantitate
WHERE ID_COMANDA = p_id_comanda
AND ID_ARTICOL = p_id_articol
AND NVL(PTVA, 0) = NVL(p_ptva, 0)
AND PRET = p_pret
AND SIGN(CANTITATE) = SIGN(p_cantitate)
AND STERS = 0
AND ROWNUM = 1;
ELSE
PACK_COMENZI.adauga_articol_comanda(
V_ID_COMANDA => p_id_comanda,
V_ID_ARTICOL => p_id_articol,
V_ID_POL => p_id_pol,
V_CANTITATE => p_cantitate,
V_PRET => p_pret,
V_ID_UTIL => p_id_util,
V_ID_SECTIE => p_id_sectie,
V_PTVA => p_ptva);
END IF;
END merge_or_insert_articol;
-- ================================================================
-- Procedura principala pentru importul 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,
p_id_pol IN NUMBER DEFAULT NULL,
p_id_sectie IN NUMBER DEFAULT NULL,
p_id_gestiune IN VARCHAR2 DEFAULT NULL,
p_kit_mode IN VARCHAR2 DEFAULT NULL,
p_id_pol_productie IN NUMBER DEFAULT NULL,
p_kit_discount_codmat IN VARCHAR2 DEFAULT NULL,
p_kit_discount_id_pol 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_vat NUMBER;
v_articole_procesate NUMBER := 0;
v_articole_eroare NUMBER := 0;
v_articol_count NUMBER := 0;
-- Variabile pentru cautare articol
v_found_mapping BOOLEAN;
v_id_articol NUMBER;
v_codmat VARCHAR2(50);
v_cantitate_roa NUMBER;
v_pret_unitar NUMBER;
v_id_pol_articol NUMBER; -- id_pol per articol (din JSON), prioritar fata de p_id_pol
-- Variabile kit pricing
v_kit_count NUMBER := 0;
v_max_cant_roa NUMBER := 1;
v_kit_comps t_kit_components;
v_sum_list_prices NUMBER;
v_discount_total NUMBER;
v_discount_share NUMBER;
v_pret_ajustat NUMBER;
v_discount_allocated NUMBER;
-- Zecimale pret vanzare (din optiuni firma, default 2)
v_nzec_pretv PLS_INTEGER := NVL(TO_NUMBER(pack_sesiune.getoptiunefirma(USER, 'PPRETV')), 2);
-- pljson
l_json_articole CLOB := p_json_articole;
v_json_arr pljson_list;
v_json_obj pljson;
BEGIN
-- 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;
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
PACK_COMENZI.adauga_comanda(V_NR_COMANDA => p_nr_comanda_ext,
V_DATA_COMANDA => p_data_comanda,
V_ID => p_id_partener,
V_DATA_LIVRARE => v_data_livrare,
V_PROC_DISCOUNT => 0,
V_INTERNA => c_interna,
V_ID_UTIL => c_id_util,
V_ID_SECTIE => p_id_sectie,
V_ID_ADRESA_FACTURARE => p_id_adresa_facturare,
V_ID_ADRESA_LIVRARE => p_id_adresa_livrare,
V_ID_CODCLIENT => NULL,
V_COMANDA_EXTERNA => p_nr_comanda_ext,
V_ID_CTR => NULL,
V_ID_COMANDA => v_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;
-- STEP 2: Proceseaza articolele din JSON folosind pljson
-- Suporta atat array "[{...},{...}]" cat si obiect singular "{...}"
IF LTRIM(l_json_articole) LIKE '[%' THEN
v_json_arr := pljson_list(l_json_articole);
ELSE
v_json_arr := pljson_list('[' || l_json_articole || ']');
END IF;
FOR i IN 1 .. v_json_arr.count LOOP
v_articol_count := v_articol_count + 1;
v_json_obj := pljson(v_json_arr.get(i));
BEGIN
-- Extrage datele folosind pljson (valorile vin ca string din json magazin web)
v_sku := v_json_obj.get_string('sku');
v_cantitate_web := TO_NUMBER(v_json_obj.get_string('quantity'));
v_pret_web := TO_NUMBER(v_json_obj.get_string('price'));
v_vat := TO_NUMBER(v_json_obj.get_string('vat'));
-- id_pol per articol (optional, pentru transport/discount cu politica separata)
BEGIN
v_id_pol_articol := TO_NUMBER(v_json_obj.get_string('id_pol'));
EXCEPTION
WHEN OTHERS THEN v_id_pol_articol := NULL;
END;
-- STEP 3: Gaseste articolele ROA pentru acest SKU
v_found_mapping := FALSE;
-- Numara randurile ARTICOLE_TERTI pentru a detecta kituri (>1 rand = set compus)
SELECT COUNT(*), NVL(MAX(at.cantitate_roa), 1)
INTO v_kit_count, v_max_cant_roa
FROM articole_terti at
WHERE at.sku = v_sku
AND at.activ = 1
AND at.sters = 0;
IF ((v_kit_count > 1) OR (v_kit_count = 1 AND v_max_cant_roa > 1))
AND p_kit_mode IS NOT NULL THEN
-- ============================================================
-- KIT PRICING: set compus (>1 componente) sau reambalare (cantitate_roa>1), mod activ
-- Prima trecere: colecteaza componente + preturi din politici
-- ============================================================
v_found_mapping := TRUE;
v_kit_comps.DELETE;
v_sum_list_prices := 0;
DECLARE
v_comp_idx PLS_INTEGER := 0;
v_cont_vanz VARCHAR2(20);
v_preturi_fl NUMBER;
v_pret_val NUMBER;
v_proc_tva NUMBER;
BEGIN
FOR rec IN (SELECT at.codmat, at.cantitate_roa
FROM articole_terti at
WHERE at.sku = v_sku
AND at.activ = 1
AND at.sters = 0
ORDER BY at.codmat) LOOP
v_comp_idx := v_comp_idx + 1;
v_kit_comps(v_comp_idx).codmat := rec.codmat;
v_kit_comps(v_comp_idx).cantitate_roa := rec.cantitate_roa;
v_kit_comps(v_comp_idx).id_articol :=
resolve_id_articol(rec.codmat, p_id_gestiune);
IF v_kit_comps(v_comp_idx).id_articol IS NULL THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'Articol activ negasit pentru CODMAT: ' || rec.codmat;
v_kit_comps(v_comp_idx).pret_cu_tva := 0;
v_kit_comps(v_comp_idx).ptva := ROUND(v_vat);
v_kit_comps(v_comp_idx).id_pol_comp := NVL(v_id_pol_articol, p_id_pol);
v_kit_comps(v_comp_idx).value_total := 0;
CONTINUE;
END IF;
-- Determina id_pol_comp: cont 341/345 → politica productie, altfel vanzare
BEGIN
SELECT NVL(na.cont, '') INTO v_cont_vanz
FROM nom_articole na
WHERE na.id_articol = v_kit_comps(v_comp_idx).id_articol
AND ROWNUM = 1;
EXCEPTION WHEN OTHERS THEN v_cont_vanz := '';
END;
IF v_cont_vanz IN ('341', '345') AND p_id_pol_productie IS NOT NULL THEN
v_kit_comps(v_comp_idx).id_pol_comp := p_id_pol_productie;
ELSE
v_kit_comps(v_comp_idx).id_pol_comp := NVL(v_id_pol_articol, p_id_pol);
END IF;
-- Query flag PRETURI_CU_TVA pentru aceasta politica
BEGIN
SELECT NVL(pp.preturi_cu_tva, 0) INTO v_preturi_fl
FROM crm_politici_preturi pp
WHERE pp.id_pol = v_kit_comps(v_comp_idx).id_pol_comp;
EXCEPTION WHEN OTHERS THEN v_preturi_fl := 0;
END;
-- Citeste PRET si PROC_TVAV din crm_politici_pret_art
BEGIN
SELECT ppa.pret, NVL(ppa.proc_tvav, 1)
INTO v_pret_val, v_proc_tva
FROM crm_politici_pret_art ppa
WHERE ppa.id_pol = v_kit_comps(v_comp_idx).id_pol_comp
AND ppa.id_articol = v_kit_comps(v_comp_idx).id_articol
AND ROWNUM = 1;
-- V_PRET always WITH TVA
IF v_preturi_fl = 1 THEN
v_kit_comps(v_comp_idx).pret_cu_tva := v_pret_val;
ELSE
v_kit_comps(v_comp_idx).pret_cu_tva := v_pret_val * v_proc_tva;
END IF;
v_kit_comps(v_comp_idx).ptva := ROUND((v_proc_tva - 1) * 100);
EXCEPTION WHEN OTHERS THEN
v_kit_comps(v_comp_idx).pret_cu_tva := 0;
v_kit_comps(v_comp_idx).ptva := ROUND(v_vat);
END;
v_kit_comps(v_comp_idx).value_total :=
v_kit_comps(v_comp_idx).pret_cu_tva * v_kit_comps(v_comp_idx).cantitate_roa;
v_sum_list_prices := v_sum_list_prices + v_kit_comps(v_comp_idx).value_total;
END LOOP;
END; -- end prima trecere
-- Discount = suma liste - pret web (poate fi negativ = markup)
v_discount_total := v_sum_list_prices - v_pret_web;
-- ============================================================
-- A doua trecere: inserare in functie de mod
-- ============================================================
IF p_kit_mode = 'distributed' THEN
-- Mode A: distribui discountul proportional in pretul fiecarei componente
v_discount_allocated := 0;
FOR i_comp IN 1 .. v_kit_comps.COUNT LOOP
IF v_kit_comps(i_comp).id_articol IS NOT NULL THEN
-- Ultimul articol valid primeste remainder pentru precizie exacta
IF i_comp = v_kit_comps.LAST THEN
v_discount_share := v_discount_total - v_discount_allocated;
ELSE
IF v_sum_list_prices != 0 THEN
v_discount_share := v_discount_total *
(v_kit_comps(i_comp).value_total / v_sum_list_prices);
ELSE
v_discount_share := 0;
END IF;
v_discount_allocated := v_discount_allocated + v_discount_share;
END IF;
-- pret_ajustat = pret_cu_tva - discount_share / cantitate_roa
v_pret_ajustat := ROUND(
v_kit_comps(i_comp).pret_cu_tva -
(v_discount_share / v_kit_comps(i_comp).cantitate_roa),
v_nzec_pretv);
BEGIN
merge_or_insert_articol(
p_id_comanda => v_id_comanda,
p_id_articol => v_kit_comps(i_comp).id_articol,
p_id_pol => v_kit_comps(i_comp).id_pol_comp,
p_cantitate => v_kit_comps(i_comp).cantitate_roa * v_cantitate_web,
p_pret => v_pret_ajustat,
p_id_util => c_id_util,
p_id_sectie => p_id_sectie,
p_ptva => v_kit_comps(i_comp).ptva);
v_articole_procesate := v_articole_procesate + 1;
EXCEPTION
WHEN OTHERS THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'Eroare adaugare kit component (A) ' ||
v_kit_comps(i_comp).codmat || ': ' || SQLERRM;
END;
END IF;
END LOOP;
ELSIF p_kit_mode = 'separate_line' THEN
-- Mode B: componente la pret plin, discount per-kit imediat sub componente
DECLARE
TYPE t_vat_discount IS TABLE OF NUMBER INDEX BY PLS_INTEGER;
v_vat_disc t_vat_discount;
v_vat_key PLS_INTEGER;
v_vat_disc_alloc NUMBER;
v_disc_amt NUMBER;
BEGIN
-- Inserare componente la pret plin + acumulare discount pe cota TVA (per kit)
FOR i_comp IN 1 .. v_kit_comps.COUNT LOOP
IF v_kit_comps(i_comp).id_articol IS NOT NULL THEN
BEGIN
merge_or_insert_articol(
p_id_comanda => v_id_comanda,
p_id_articol => v_kit_comps(i_comp).id_articol,
p_id_pol => v_kit_comps(i_comp).id_pol_comp,
p_cantitate => v_kit_comps(i_comp).cantitate_roa * v_cantitate_web,
p_pret => v_kit_comps(i_comp).pret_cu_tva,
p_id_util => c_id_util,
p_id_sectie => p_id_sectie,
p_ptva => v_kit_comps(i_comp).ptva);
v_articole_procesate := v_articole_procesate + 1;
EXCEPTION
WHEN OTHERS THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'Eroare adaugare kit component (B) ' ||
v_kit_comps(i_comp).codmat || ': ' || SQLERRM;
END;
-- Acumuleaza discountul pe cota TVA (per kit, local)
v_vat_key := v_kit_comps(i_comp).ptva;
IF v_sum_list_prices != 0 THEN
IF v_vat_disc.EXISTS(v_vat_key) THEN
v_vat_disc(v_vat_key) := v_vat_disc(v_vat_key) +
v_discount_total * (v_kit_comps(i_comp).value_total / v_sum_list_prices);
ELSE
v_vat_disc(v_vat_key) :=
v_discount_total * (v_kit_comps(i_comp).value_total / v_sum_list_prices);
END IF;
ELSE
IF NOT v_vat_disc.EXISTS(v_vat_key) THEN
v_vat_disc(v_vat_key) := 0;
END IF;
END IF;
END IF;
END LOOP;
-- Inserare imediata discount per kit (sub componentele kitului)
IF v_discount_total > 0 AND p_kit_discount_codmat IS NOT NULL THEN
DECLARE
v_disc_artid NUMBER;
BEGIN
v_disc_artid := resolve_id_articol(p_kit_discount_codmat, p_id_gestiune);
IF v_disc_artid IS NOT NULL THEN
v_vat_disc_alloc := 0;
v_vat_key := v_vat_disc.FIRST;
WHILE v_vat_key IS NOT NULL LOOP
-- Remainder trick per kit
IF v_vat_key = v_vat_disc.LAST THEN
v_disc_amt := v_discount_total - v_vat_disc_alloc;
ELSE
v_disc_amt := v_vat_disc(v_vat_key);
v_vat_disc_alloc := v_vat_disc_alloc + v_disc_amt;
END IF;
IF v_disc_amt > 0 THEN
BEGIN
PACK_COMENZI.adauga_articol_comanda(
V_ID_COMANDA => v_id_comanda,
V_ID_ARTICOL => v_disc_artid,
V_ID_POL => NVL(p_kit_discount_id_pol, p_id_pol),
V_CANTITATE => -1 * v_cantitate_web,
V_PRET => ROUND(v_disc_amt, v_nzec_pretv),
V_ID_UTIL => c_id_util,
V_ID_SECTIE => p_id_sectie,
V_PTVA => v_vat_key);
v_articole_procesate := v_articole_procesate + 1;
EXCEPTION
WHEN OTHERS THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'Eroare linie discount kit TVA=' || v_vat_key ||
'% codmat=' || p_kit_discount_codmat || ': ' || SQLERRM;
END;
END IF;
v_vat_key := v_vat_disc.NEXT(v_vat_key);
END LOOP;
END IF;
END;
END IF;
END; -- end mode B per-kit block
END IF; -- end kit mode branching
ELSE
-- ============================================================
-- MAPARE SIMPLA: 1 CODMAT, sau kit fara kit_mode activ
-- Pret = pret web / cantitate_roa (fara procent_pret)
-- ============================================================
FOR rec IN (SELECT at.codmat, at.cantitate_roa
FROM articole_terti at
WHERE at.sku = v_sku
AND at.activ = 1
AND at.sters = 0
ORDER BY at.codmat) LOOP
v_found_mapping := TRUE;
v_id_articol := resolve_id_articol(rec.codmat, p_id_gestiune);
IF v_id_articol IS NULL THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'Articol activ negasit pentru CODMAT: ' || rec.codmat;
CONTINUE;
END IF;
v_cantitate_roa := rec.cantitate_roa * v_cantitate_web;
v_pret_unitar := CASE WHEN v_pret_web IS NOT NULL
THEN v_pret_web / rec.cantitate_roa
ELSE 0
END;
BEGIN
merge_or_insert_articol(p_id_comanda => v_id_comanda,
p_id_articol => v_id_articol,
p_id_pol => NVL(v_id_pol_articol, p_id_pol),
p_cantitate => v_cantitate_roa,
p_pret => v_pret_unitar,
p_id_util => c_id_util,
p_id_sectie => p_id_sectie,
p_ptva => v_vat);
v_articole_procesate := v_articole_procesate + 1;
EXCEPTION
WHEN OTHERS THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'Eroare adaugare articol ' || rec.codmat || ': ' || SQLERRM;
END;
END LOOP;
-- Daca nu s-a gasit mapare in ARTICOLE_TERTI, cauta direct in NOM_ARTICOLE
IF NOT v_found_mapping THEN
v_id_articol := resolve_id_articol(v_sku, p_id_gestiune);
IF v_id_articol IS NULL THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'SKU negasit in ARTICOLE_TERTI si NOM_ARTICOLE (activ): ' || v_sku;
ELSE
v_codmat := v_sku;
v_pret_unitar := NVL(v_pret_web, 0);
BEGIN
PACK_COMENZI.adauga_articol_comanda(V_ID_COMANDA => v_id_comanda,
V_ID_ARTICOL => v_id_articol,
V_ID_POL => NVL(v_id_pol_articol, p_id_pol),
V_CANTITATE => v_cantitate_web,
V_PRET => v_pret_unitar,
V_ID_UTIL => c_id_util,
V_ID_SECTIE => p_id_sectie,
V_PTVA => v_vat);
v_articole_procesate := v_articole_procesate + 1;
EXCEPTION
WHEN OTHERS THEN
v_articole_eroare := v_articole_eroare + 1;
g_last_error := g_last_error || CHR(10) ||
'Eroare adaugare articol ' || v_sku ||
' (CODMAT: ' || v_codmat || '): ' || SQLERRM;
END;
END IF;
END IF;
END IF; -- end kit vs simplu
END; -- End BEGIN block pentru articol individual
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;
<<SFARSIT>>
IF g_last_error IS NOT NULL THEN
RAISE_APPLICATION_ERROR(-20001, g_last_error);
END IF;
END importa_comanda;
END PACK_IMPORT_COMENZI;
/