fix(import): insert kit discount lines per-kit under components instead of deferred cross-kit

Discount lines now appear immediately after each kit's components on the order,
making it clear which package each discount belongs to.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-25 21:39:14 +00:00
parent 21e26806f7
commit 580ca595a5

View File

@@ -32,7 +32,7 @@
-- distributed: discountul fata de suma componentelor se distribuie
-- proportional in pretul fiecarei componente
-- separate_line: componentele se insereaza la pret plin +
-- linii discount separate grupate pe cota TVA
-- linii discount separate per-kit sub componente, grupate pe cota TVA
-- p_id_pol_productie — politica de pret pentru articole de productie
-- (cont in 341/345); NULL = nu se foloseste
-- p_kit_discount_codmat — CODMAT-ul articolului discount (Mode separate_line)
@@ -67,6 +67,7 @@
-- 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)
-- ====================================================================
CREATE OR REPLACE PACKAGE PACK_IMPORT_COMENZI AS
@@ -274,17 +275,6 @@ CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS
v_pret_ajustat NUMBER;
v_discount_allocated NUMBER;
-- Acumulare discount-uri kit cross-kit (separate_line, deferred insertion)
TYPE t_kit_disc_entry IS RECORD (
ptva NUMBER,
pret NUMBER, -- pret unitar (disc_amt / cantitate_web)
qty NUMBER -- cantitate negativa acumulata
);
TYPE t_kit_disc_list IS TABLE OF t_kit_disc_entry INDEX BY PLS_INTEGER;
v_kit_disc_list t_kit_disc_list;
v_kit_disc_count PLS_INTEGER := 0;
v_kit_disc_found BOOLEAN;
-- Zecimale pret vanzare (din optiuni firma, default 2)
v_nzec_pretv PLS_INTEGER := NVL(TO_NUMBER(pack_sesiune.getoptiunefirma(USER, 'PPRETV')), 2);
@@ -523,14 +513,13 @@ CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS
END LOOP;
ELSIF p_kit_mode = 'separate_line' THEN
-- Mode B: componente la pret plin, discount deferred cross-kit
-- 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;
v_unit_pret NUMBER;
BEGIN
-- Inserare componente la pret plin + acumulare discount pe cota TVA (per kit)
FOR i_comp IN 1 .. v_kit_comps.COUNT LOOP
@@ -572,42 +561,50 @@ CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS
END IF;
END LOOP;
-- Merge per-kit discounts into cross-kit list (v_kit_disc_list)
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;
-- 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
v_unit_pret := ROUND(v_disc_amt, v_nzec_pretv);
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;
-- Search for existing entry with same (ptva, pret) to merge qty
v_kit_disc_found := FALSE;
FOR j IN 1 .. v_kit_disc_count LOOP
IF v_kit_disc_list(j).ptva = v_vat_key
AND v_kit_disc_list(j).pret = v_unit_pret THEN
v_kit_disc_list(j).qty := v_kit_disc_list(j).qty + (-1 * v_cantitate_web);
v_kit_disc_found := TRUE;
EXIT;
END IF;
END LOOP;
IF NOT v_kit_disc_found THEN
v_kit_disc_count := v_kit_disc_count + 1;
v_kit_disc_list(v_kit_disc_count).ptva := v_vat_key;
v_kit_disc_list(v_kit_disc_count).pret := v_unit_pret;
v_kit_disc_list(v_kit_disc_count).qty := -1 * v_cantitate_web;
v_vat_key := v_vat_disc.NEXT(v_vat_key);
END LOOP;
END IF;
END IF;
v_vat_key := v_vat_disc.NEXT(v_vat_key);
END LOOP;
END;
END IF;
END; -- end mode B per-kit block
END IF; -- end kit mode branching
@@ -692,43 +689,6 @@ CREATE OR REPLACE PACKAGE BODY PACK_IMPORT_COMENZI AS
END LOOP;
-- ============================================================
-- INSERARE DISCOUNT-URI KIT DEFERRED (separate_line)
-- Linii cu preturi diferite raman separate, coliziuni merged pe qty
-- ============================================================
IF p_kit_mode = 'separate_line' AND v_kit_disc_count > 0 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
FOR j IN 1 .. v_kit_disc_count LOOP
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 => v_kit_disc_list(j).qty,
V_PRET => v_kit_disc_list(j).pret,
V_ID_UTIL => c_id_util,
V_ID_SECTIE => p_id_sectie,
V_PTVA => v_kit_disc_list(j).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 linie discount kit TVA=' || v_kit_disc_list(j).ptva ||
'% id_pol=' || NVL(p_kit_discount_id_pol, p_id_pol) ||
' id_art=' || v_disc_artid ||
' codmat=' || p_kit_discount_codmat || ': ' || SQLERRM;
END;
END LOOP;
END IF;
END;
END IF;
-- Verifica daca s-au procesat articole cu succes
IF v_articole_procesate = 0 THEN
g_last_error := g_last_error || CHR(10) || 'IMPORTA_COMANDA ' ||