Files
comun/utile/Teste/editare_factura/creeaza_documente_s8.prg
Marius Mutu 93a2718e6d #6 editare factura emisa: harnessul S8 de creare documente intra in versionare
Cele trei fisiere erau pe disc, netrackuite, iar ce se stia despre ele traia
intr-un handoff intre sesiuni. Handoff-ul a fost desfiintat: ce era durabil a
intrat in antetul harnessului - plaja de serii care chiar prinde (FACTURA cere
gnIdUtil=8 cu gnIdSucursala=167, AVIZ merge si cu -3), faptul ca alocarea
consuma numere ireversibil chiar cand documentul nu se scrie, ordinea gresita
de incarcare a lui mock_amessagebox care e suspectul principal pentru agatari,
si riscul de curs EUR ramas neconfirmat pe cursor_contract.

Harnessul nu a scris inca niciun document cu succes - antetul spune asta
explicit, ca sa nu fie luat drept unealta functionala.

test_init_env_auto_roafacturare.prg e generic si folosit deja de alte suite:
seteaza gcNumeProgram=[ROAFACTURARE], fara de care garzile proprii fluxului de
facturare nu se declanseaza.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SN8snvkk94KuhWwoXUUey3
2026-08-11 22:19:05 +03:00

698 lines
30 KiB
Plaintext

* creeaza_documente_s8.prg
* S8 (punct #6, editare factura emisa) - creeaza in MARIUSM_AUTO cele 3 documente lipsa (aviz,
* factura din aviz, factura din contract) prin fluxul REAL de emitere (Procedure factureaza,
* COMUN\programe\ofacturare.prg:81-560), ca sa poata fi editate ulterior de matricea S8.
*
* Tehnica: reproduce fidel corpul lui factureaza() pentru fiecare tnTip, cu DOUA inlocuiri, ambele
* DOAR de conducere UI (nu de scriere):
* 1) dialogul modal de antet (frm_date_aviz / frm_date_factura) - inlocuit cu setare DIRECTA a
* proprietatilor poDate (efect identic cu ce ar face operatorul in dialog), ca in precedentul
* acceptat test_s5_al_doilea_intrare.prg / test_pret_cu_tva_nivel2.prg. Numarul documentului
* (poDate.nract) vine din poGeneratorNumere.creeaza_cursor_serii()+aloca_numar() REAL - acelasi
* apel pe care l-ar face controlul clb_serie_act din dialog (serii_numere.vc2:114-136) - nu e
* inventat.
* 2) al doilea modal inevitabil, frm_alte_date (ofacturare.vc2:14921-14935) - condus cu driverul
* validat in test_pret_cu_tva_nivel2.prg (Timer pe _SCREEN + _SCREEN.Forms), care ii apeleaza
* direct .do_termin() dupa ce poDate.id_delegat a fost presetat (evita dependenta de
* cauta_date_ultima_factura din Init-ul formularului).
* Al treilea modal, "Do Form verificare" (ofacturare.vc2:14404, in do_scrie_factura), e evitat prin
* SET PATH cu stub_verificare INAINTEA COMUN\FERESTRE (COMUN\utile\Teste\achizitie_import\
* stub_verificare\verificare.sc2 - stub existent, versionat, folosit deja de suitele
* achizitie_import\*; Init lui seteaza gnButon=1 si RETURN .F., deci formularul nu se arata deloc).
*
* Scrierea efectiva ramane 100% in codul de productie: do_adauga_tot() -> do_calculeaza_totaluri()
* -> do_termin() -> inainte_de_do_termin() -> do_scrie_factura() -> PACK_FACTURARE (neatins).
*
* gnScadereStoc = 0 (ca in precedente): do_adauga_articol sare peste dialogul per-linie
* frm_articol_factura, nu mai e nevoie de driver pentru el.
*
* STARE: niciun document nu a fost inca scris cu succes. Rularile s-au oprit in do_termin(), fara
* linie de rezultat in log. Capcanele de mediu deja platite, de citit inainte de o reluare:
*
* 1) Plaja de serii. poGeneratorNumere.creeaza_cursor_serii(nIdTipDoc) + aloca_numar() sunt apeluri
* REALE (pack_serii_numere), deci utilizatorul si sucursala din harness trebuie sa se potriveasca
* unei plaje active. In MARIUSM_AUTO, pentru FACTURA (nIdTipDoc=5) exista o singura plaja activa
* si doar gnIdUtil=8 cu gnIdSucursala=167 o prinde; cu -3 iese ORA-20000 "Nu exista plaje de
* serii facturi". Pentru AVIZ (nIdTipDoc=6) merge si gnIdUtil=-3, plajele fiind pe
* id_tipentitate=2, care ocoleste verificarea de entitate. Verificabil fara sa consumi numere:
* pack_serii_numere.verifica_cursor_serii(5, 8, 167, :prez, :rc) e SELECT pur.
*
* 2) Alocarea consuma numere ireversibil, chiar daca documentul final nu se scrie: seria SSS/AVIZ a
* sarit deja cel putin numerele 11 si 12 in incercari esuate. Nu le socoti pierdute de o rulare noua.
*
* 3) mock_amessagebox.prg trebuie incarcat ULTIMUL, nu primul (la nume duplicat castiga fisierul
* deschis cel mai recent, cum scrie chiar in antetul lui). Aici e incarcat inaintea lui
* OPROCEDURI_COMUNE.PRG, deci amessagebox-ul REAL castiga, iar ramura Otherwise a handler-ului de
* erori Oracle (oproceduri_comune.prg, ~421-424) deschide un MessageBox nativ care agata procesul
* fara sa scrie nimic in log - simptomul observat. Ipoteza netestata inca.
*
* 4) Cursul EUR lipseste in acest mediu pentru 08-10.08.2026 (ultimul rand CURS pentru id_valuta=2 e
* 07.08.2026, fiecare rand valabil o singura zi). Pe calea AVIZ nu s-a declansat - cursor_preturi
* a reusit cu Reccount=1. Ramane risc NECONFIRMAT pentru cursor_contract pe id_ctr=235, care are
* expunere reala EUR; de verificat prin apel direct, nu prin deductie din alt cod.
SET SAFETY OFF
SET TALK OFF
SET DELETED ON
SET EXACT ON
SET CENTURY ON
SET DATE DMY
SET DECIMALS TO 4
SET NULLDISPLAY TO ''
CLOSE DATABASES
PUBLIC gcLog
gcLog = "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\editare_factura\creeaza_documente_s8_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13)+CHR(10), gcLog)
ON ERROR DO S8Err WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
TRY
LOCAL gcAppPath, lcPath
gcAppPath = "D:\ROA\ROAFACTURARE\"
SET DEFAULT TO (gcAppPath)
*-- stub_verificare PRIMUL, ca sa castige rezolutia "Do Form verificare" fata de COMUN\FERESTRE
lcPath = gcAppPath + 'COMUN\utile\Teste\achizitie_import\stub_verificare;' + ;
gcAppPath + 'Date;' + gcAppPath + 'Include;' + gcAppPath + 'FERESTRE;' + ;
gcAppPath + 'GRAFICE;' + gcAppPath + 'CLASE;' + gcAppPath + 'MENIURI;' + ;
gcAppPath + 'PROGRAME;' + gcAppPath + 'RAPOARTE;' + gcAppPath + 'COMUN;' + ;
gcAppPath + 'COMUN\CLASE;' + gcAppPath + 'COMUN\FERESTRE;' + gcAppPath + 'COMUN\PROGRAME;' + ;
gcAppPath + 'COMUN\GRAFICE;' + gcAppPath + 'COMUN\RAPOARTE;' + ;
gcAppPath + 'COMUN\UTILE\CALENDAR;' + gcAppPath + 'COMUN\UTILE\CTL32;' + ;
gcAppPath + 'COMUN\UTILE\HPDF;' + gcAppPath + 'COMUN\UTILE\HPDF\REPORTOUTPUT;' + ;
gcAppPath + 'COMUN\UTILE\WEB;' + gcAppPath + 'COMUN\UTILE\EMAIL;' + ;
gcAppPath + 'COMUN\UTILE\NFJSON;' + gcAppPath + 'COMUN\UTILE\NFXML;' + ;
ADDBS(SUBSTR(gcAppPath,1,RAT([\],gcAppPath,2)))+[COMUNROA\]
SET PATH TO &lcPath ADDITIVE
DO S8Log WITH 'SET PATH OK'
*----- CLASE (lista identica cu test_pret_cu_tva_nivel2.prg, deja dovedita) -----
SET CLASSLIB TO (gcAppPath + "comun\clase\appwiz") ADDITIVE
SET CLASSLIB TO registry ADDITIVE
SET CLASSLIB TO cauta_alfa_forms ADDITIVE
SET CLASSLIB TO ofacturare.vcx ADDITIVE
SET CLASSLIB TO ofacturare_comun.vcx ADDITIVE
SET CLASSLIB TO accessibility.vcx ADDITIVE
SET CLASSLIB TO ocriterii.vcx ADDITIVE
SET CLASSLIB TO ctl32_statusbar.vcx ADDITIVE
SET CLASSLIB TO ctl32_common.vcx ADDITIVE
SET CLASSLIB TO ctl32_structs.vcx ADDITIVE
SET CLASSLIB TO ctl32_progressbar.vcx ADDITIVE
SET CLASSLIB TO DECABAZA ADDITIVE
SET CLASSLIB TO onomenclatoare ADDITIVE
SET CLASSLIB TO onomenclatoare2 ADDITIVE
SET CLASSLIB TO ofacturare_rapoarte ADDITIVE
SET CLASSLIB TO orapoarte ADDITIVE
SET CLASSLIB TO ferestre_oracle ADDITIVE
SET CLASSLIB TO messagebox ADDITIVE
SET CLASSLIB TO otoolbar ADDITIVE
SET CLASSLIB TO onom_curs ADDITIVE
SET CLASSLIB TO comun ADDITIVE
SET CLASSLIB TO ferestre_cere_date ADDITIVE
SET CLASSLIB TO baza ADDITIVE
SET CLASSLIB TO caut ADDITIVE
SET CLASSLIB TO ointroduceri ADDITIVE
SET CLASSLIB TO serii_numere ADDITIVE
SET CLASSLIB TO caut_ora ADDITIVE
SET CLASSLIB TO wwdialogs.vcx ADDITIVE
SET CLASSLIB TO _calendar.vcx ADDITIVE
SET CLASSLIB TO locale ADDITIVE
SET CLASSLIB TO overificari ADDITIVE
SET CLASSLIB TO ocomenzi ADDITIVE
DO S8Log WITH 'SET CLASSLIB OK'
*----- PROCEDURI (mock amessagebox PRIMUL) -----
SET PROCEDURE TO "D:\ROA\ROAFACTURARE\COMUN\utile\Teste\mock_amessagebox.prg"
SET PROCEDURE TO proceduri_comune ADDITIVE
SET PROCEDURE TO quitapp ADDITIVE
SET PROCEDURE TO init_program ADDITIVE
SET PROCEDURE TO onomenclatoare.prg ADDITIVE
SET PROCEDURE TO onomenclatoare2.prg ADDITIVE
SET PROCEDURE TO oproceduri_rapoarte_fact.prg ADDITIVE
SET PROCEDURE TO email.prg ADDITIVE
SET PROCEDURE TO GENCURSOR.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_COMUNE.PRG ADDITIVE
SET PROCEDURE TO OINIT_OPTIUNI.PRG ADDITIVE
SET PROCEDURE TO updateserver.PRG ADDITIVE
SET PROCEDURE TO OPROCEDURI_aMS.PRG ADDITIVE
SET PROCEDURE TO ocautare ADDITIVE
SET PROCEDURE TO odocumente ADDITIVE
SET PROCEDURE TO osecurity ADDITIVE
SET PROCEDURE TO acces_meniu ADDITIVE
SET PROCEDURE TO wwxmlhttp.prg ADDITIVE
SET PROCEDURE TO wwcodeupdate.prg ADDITIVE
SET PROCEDURE TO ini.prg ADDITIVE
SET PROCEDURE TO cauta_alfa.prg ADDITIVE
SET PROCEDURE TO oHeader.prg ADDITIVE
SET PROCEDURE TO oproceduri_curs.prg ADDITIVE
SET PROCEDURE TO proceduri.prg ADDITIVE
SET PROCEDURE TO oproceduri_facturare.prg ADDITIVE
SET PROCEDURE TO proceduri_rapoarte.prg ADDITIVE
SET PROCEDURE TO ofacturare.prg ADDITIVE
SET PROCEDURE TO oserii_numere.prg ADDITIVE
SET PROCEDURE TO wwutils.prg ADDITIVE
SET PROCEDURE TO wwConfig.prg ADDITIVE
SET PROCEDURE TO wwApi.prg ADDITIVE
SET PROCEDURE TO oexport.prg ADDITIVE
SET PROCEDURE TO validare.prg ADDITIVE
SET PROCEDURE TO ofacturare_comun.prg ADDITIVE
SET PROCEDURE TO ofacturare_stoc.prg ADDITIVE
SET PROCEDURE TO pmenu.prg ADDITIVE
SET PROCEDURE TO ointroduceri.prg ADDITIVE
SET PROCEDURE TO ovariabile_globale.prg ADDITIVE
SET PROCEDURE TO ooperatii_comune.prg ADDITIVE
SET PROCEDURE TO oproceduri_util.prg ADDITIVE
SET PROCEDURE TO filebringer.prg ADDITIVE
SET PROCEDURE TO iniacces.prg ADDITIVE
SET PROCEDURE TO oupdate.prg ADDITIVE
SET PROCEDURE TO procese.prg ADDITIVE
SET PROCEDURE TO version.prg ADDITIVE
SET PROCEDURE TO wwhttp.prg ADDITIVE
SET PROCEDURE TO xmlaccess.prg ADDITIVE
SET PROCEDURE TO xmlparser.prg ADDITIVE
SET PROCEDURE TO xdate.prg ADDITIVE
SET PROCEDURE TO suma_in_vorbe.prg ADDITIVE
SET PROCEDURE TO controllerecr ADDITIVE
SET PROCEDURE TO regex.prg ADDITIVE
DO S8Log WITH 'SET PROCEDURE OK'
*----- Globale aplicatie -----
PUBLIC gnPc, gnPVal, gnPcant, gnPPretV, gnScadereStoc, gnMemProcDisc, gl406, gcAcces
PUBLIC gnModTotFact, gnRF_FACTURARE_FARA_STOC, gnPPret, gnPPretVal
PUBLIC gnFactSeturi, gnCoefKFact, gnListareAvizBonFiscal, gnid_part_casa
gnPc = 2
gnPVal = 2
gnPcant = 3
gnPPretV = 4
gnPPret = 4
gnPPretVal = 4
gnScadereStoc = 0 && bypass complet dialogul per-linie (do_adauga_articol)
gnMemProcDisc = 0
gl406 = .F.
gcAcces = "1;2;3;4;5;6;7;8;"
gnModTotFact = 0
gnRF_FACTURARE_FARA_STOC = 0
gnFactSeturi = 0 && nu se factureaza in seturi (nu e cazul S8)
gnCoefKFact = 2 && poDate.tip<>48, ramura inactiva - valoare neutra
gnListareAvizBonFiscal = 0
gnid_part_casa = 0 && frm_alte_date.Init (ferestre_cere_date.vc2:3165) - fara partener CASA LEI implicit in headless
PUBLIC nror(65000)
PUBLIC buton, gnButon, pnButon
buton = 1
gnButon = 1
pnButon = 1
*----- Conectare Oracle REALA, context ROAFACTURARE (nu ROACONT) -----
PUBLIC gnHandle, goExecutor, goConn, gcS, gcFirma, gcUserName, gnAn, gnLuna, gnIdUtil, ;
gnIdFirma, gnIdSucursala, gcNumeProgram, gcAppName, glLunaInchisa, glEMama, goCalendar, goFirma
gcNumeProgram = [ROAFACTURARE]
gcAppName = [ROAFACTURARE]
*-- gnIdUtil=-3 e conventia din restul harnesselor de test (marcaj sintetic in id_util/id_utils),
*-- dar SERII_TIPDOC.ID_TIPDOC=5 (FACTURA) are PLAJE_NUMERE scoping per UTILIZATOR
*-- (ID_TIPENTITATE=3), fara nicio plaja activa pentru user -3 - verificat prin sqlplus pe
*-- MARIUSM_AUTO: PLAJE_NUMERE unde id_tipdoc=5 si id_tipentitate=3 are doar id_entitate in
*-- (8,3779,75852,75904,75921); userul 8 are 2 plaje active (id_plaja=10 si 48), fara restrictie
*-- de sucursala (id_sucursala NULL) - singurul care acopera atat FACTURA DIN AVIZ cat si FACTURA
*-- DIN CONTRACT. AVIZ (tnTip=22) nu e afectat, plaja lui e globala (id_tipentitate=2,
*-- id_entitate=0), nu per-utilizator. Insa acelasi gnIdUtil e folosit si de cursor_avize/
*-- cursor_contract/cursor_preturi (vizibilitate documente sursa) - user 8 nu vede AVIZ 1051 nici
*-- CONTRACT 235 (create/asociate userului -3), deci gnIdUtil ramane -3 aici (convenția din restul
*-- harnesselor, marcaj sintetic in id_util/id_utils) si e comutat LOCAL, doar in jurul apelurilor
*-- de alocare numar/serie, in CreeazaDocument (vezi comutarea gnIdUtil=8/-3 mai jos).
gnIdUtil = -3
gnIdFirma = 110
gnAn = YEAR(DATE())
gnLuna = MONTH(DATE())
glLunaInchisa = .F.
glEMama = .F.
gcS = 'MARIUSM_AUTO'
gcFirma = gcS
gcUserName = gcS
goExecutor = CREATEOBJECT('oExecutor')
goConn = CREATEOBJECT('oConn')
gnHandle = 0
goConn.Connect('CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT')
IF gnHandle <= 0
DO S8Log WITH 'EROARE: conectare Oracle esuata'
QUIT
ENDIF
DO S8Log WITH 'Oracle conectat, gnHandle=' + TRANSFORM(gnHandle)
LOCAL llSucces
goFirma = NULL
llSucces = goExecutor.oExecuta("select * from syn_v_nom_firme where schema = ?gcS", "cFirma")
IF llSucces
SELECT cFirma
gnIdFirma = id_firma
gnIdSucursala = NULL
SCATTER NAME goFirma
ENDIF
IF USED('cFirma')
USE IN cFirma
ENDIF
goCalendar = NULL
llSucces = goExecutor.oExecuta('SELECT anul, luna, tva_incasare FROM calendar WHERE an*12+luna = (select MAX(an*12+luna) FROM calendar)', 'cCalendar')
IF llSucces
SELECT cCalendar
GO TOP
gnAn = anul
gnLuna = luna
SCATTER NAME goCalendar
ENDIF
IF USED('cCalendar')
USE IN cCalendar
ENDIF
DO S8Log WITH 'gnAn/gnLuna=' + TRANSFORM(gnAn) + '/' + TRANSFORM(gnLuna)
CREATE CURSOR dual (dummy c(10))
INSERT INTO dual (dummy) VALUES ("")
*-- gcSettingsFile/goApi: cerute de get_ora() (oproceduri_comune.prg) - reproduse din
*-- test_init_env_auto.prg:209-230, altfel oDateFactura.Init -> get_ora() cade cu variabila lipsa
PUBLIC gcAppPath2, DIRGEN, gcBasePath, gcTempPath, gcGeneralIniFile, gcSettingsFile
DIRGEN = [D:\ROA\]
gcBasePath = DIRGEN
gcGeneralIniFile = DIRGEN + "settings.ini"
gcSettingsFile = gcGeneralIniFile
IF TYPE('goApi') = 'U'
PUBLIC goApi
goApi = NEWOBJECT("wwAPI", "wwAPI.prg")
ENDIF
gcTempPath = ADDBS(SHORTPATH(goApi.GetTempPath())) + gcS + [\]
IF !DIRECTORY(gcTempPath)
MD (gcTempPath)
ENDIF
LOCAL lcSql
lcSql = [begin pack_sesiune.set_Id_Util(?gnIdUtil); end;]
goExecutor.oExecuta(lcSql)
lcSql = [begin pack_sesiune.setluna(?gnLuna); pack_sesiune.setan(?gnAn); end;]
goExecutor.oExecuta(lcSql)
lcSql = [begin pack_sesiune.setlunabal(?gnLuna); pack_sesiune.setanbal(?gnAn); end;]
goExecutor.oExecuta(lcSql)
lcSql = [begin pack_contafin.SET_DATA_RON(?gcS); end;]
goExecutor.oExecuta(lcSql)
lcSql = [begin pack_sesiune.set_data_ron(?gcS); end;]
goExecutor.oExecuta(lcSql)
lcSql = [begin pack_contafin.set_id_sucursala(?gnIdSucursala); end;]
goExecutor.oExecuta(lcSql)
lcSql = [begin pack_contafin.set_id_firma(?gnIdFirma); end;]
goExecutor.oExecuta(lcSql)
DO S8Log WITH 'sesiune Oracle initializata'
PUBLIC goApp, goExport
goApp = CREATEOBJECT('dummyapp')
goExport = CREATEOBJECT('dummyexport')
*----- driver: conduce frm_alte_date (singurul modal ramas dupa stub_verificare) -----
PUBLIC goDriver8, glDlgTratat8
glDlgTratat8 = .F.
goDriver8 = CREATEOBJECT('driverAlteDate8')
_SCREEN.AddObject('tmrDrv8', 'Timer')
_SCREEN.tmrDrv8.Interval = 200
BINDEVENT(_SCREEN.tmrDrv8, 'Timer', goDriver8, 'Executa')
_SCREEN.tmrDrv8.Enabled = .T.
_SCREEN.Visible = .T.
_SCREEN.WindowState = 2
_SCREEN.Caption = 'S8 - creare documente (AVIZ / FACTURA DIN AVIZ / FACTURA DIN CONTRACT)'
DO S8Log WITH 'driver+timer pregatiti'
*======================================================================
* PASUL 1: AVIZ (tnTip=22) din lista de preturi, client RAJA (id_part=463)
*======================================================================
LOCAL lnIdVanzareAviz, lnIdVanzareFactAviz, lnIdVanzareFactContract
lnIdVanzareAviz = 0
lnIdVanzareFactAviz = 0
lnIdVanzareFactContract = 0
*-- AVIZ id_vanzare=1051 creat cu succes intr-o rulare anterioara (log 10/08/2026 12:01:58,
*-- verificat in Oracle: tip=22, id_part=463, numar_act=13, serie_act=SSS, sters=0, id_fact=8009676,
*-- 1 rand in VANZARI_DETALII, nefolosit inca de nicio factura) - reutilizat ca sa nu se creeze
*-- un AVIZ orfan suplimentar la fiecare rerulare a PAS 2/3.
LOCAL llReutilizeazaAviz1051
*-- 1051 are cantitate=0 pe unicul rand (VANZARI_DETALII, articol negestionabil - do_adauga_tot nu
*-- a filtrat cantitate=0) - inutil ca sursa pentru FACTURA DIN AVIZ (cursor_avize il exclude).
*-- Creeaza un AVIZ NOU, cu fix-ul de cantitate=1 aplicat mai jos (REPLACE ALL cantitate WITH 1).
llReutilizeazaAviz1051 = .F.
IF llReutilizeazaAviz1051
lnIdVanzareAviz = 1051
DO S8Log WITH CHR(13)+CHR(10) + '===== PAS 1: AVIZ SARIT, reutilizat id_vanzare=1051 (creat intr-o rulare anterioara) ====='
ELSE
DO S8Log WITH CHR(13)+CHR(10) + '===== PAS 1: AVIZ (tip=22) ====='
lnIdVanzareAviz = CreeazaDocument(22, 463, '', 256)
DO S8Log WITH 'PAS 1 rezultat: id_vanzare=' + TRANSFORM(lnIdVanzareAviz)
ENDIF
IF lnIdVanzareAviz > 0
DO S8Log WITH CHR(13)+CHR(10) + '===== PAS 2: FACTURA DIN AVIZ (tip=4), sursa id_vanzare=' + TRANSFORM(lnIdVanzareAviz) + ' ====='
lnIdVanzareFactAviz = CreeazaDocument(4, 463, TRANSFORM(lnIdVanzareAviz), 256)
DO S8Log WITH 'PAS 2 rezultat: id_vanzare=' + TRANSFORM(lnIdVanzareFactAviz)
ELSE
DO S8Log WITH 'PAS 2 SARIT: avizul de la pasul 1 nu s-a creat'
ENDIF
*-- FACTURA DIN CONTRACT id_vanzare=1057 creata cu succes intr-o rulare anterioara (log
*-- 10/08/2026 12:28:34) - verificat in Oracle: tip=2, id_part=598, numar_act=14, serie_act=SSS,
*-- sters=0, id_fact=8009682, 1 rand in VANZARI_DETALII - reutilizata ca sa nu se creeze un
*-- duplicat la fiecare rerulare de debug pt. PAS 2.
LOCAL llReutilizeazaFactContract1057
llReutilizeazaFactContract1057 = .T.
IF llReutilizeazaFactContract1057
lnIdVanzareFactContract = 1057
DO S8Log WITH CHR(13)+CHR(10) + '===== PAS 3: SARIT, reutilizat id_vanzare=1057 (creat intr-o rulare anterioara) ====='
ELSE
DO S8Log WITH CHR(13)+CHR(10) + '===== PAS 3: FACTURA DIN CONTRACT (tip=2), id_ctr=235 ====='
lnIdVanzareFactContract = CreeazaDocument(2, 598, '235', 256)
DO S8Log WITH 'PAS 3 rezultat: id_vanzare=' + TRANSFORM(lnIdVanzareFactContract)
ENDIF
DO S8Log WITH CHR(13)+CHR(10) + '========== REZUMAT =========='
DO S8Log WITH 'AVIZ (tip=22): id_vanzare=' + TRANSFORM(lnIdVanzareAviz)
DO S8Log WITH 'FACTURA DIN AVIZ (tip=4): id_vanzare=' + TRANSFORM(lnIdVanzareFactAviz)
DO S8Log WITH 'FACTURA DIN CONTRACT (tip=2): id_vanzare=' + TRANSFORM(lnIdVanzareFactContract)
_SCREEN.tmrDrv8.Enabled = .F.
DO S8Log WITH 'done ' + TTOC(DATETIME())
CATCH TO loExc
DO S8Log WITH 'CATCH TOP-LEVEL ErrorNo=' + TRANSFORM(loExc.ErrorNo) + ' Message=' + loExc.Message + ' Proc=' + loExc.Procedure + ' Line=' + TRANSFORM(loExc.LineNo) + ' [' + loExc.LineContents + ']'
ENDTRY
QUIT
*==================================================================================
PROCEDURE S8Log
LPARAMETERS tcMsg
LOCAL lcL
lcL = IIF(FILE(gcLog), FILETOSTR(gcLog), '')
STRTOFILE(lcL + tcMsg + CHR(13)+CHR(10), gcLog)
ENDPROC
PROCEDURE S8Err
LPARAMETERS tnErr, tcMsg, tcProg, tnLine
DO S8Log WITH 'ON ERROR ' + TRANSFORM(tnErr) + ' [' + tcProg + ':' + TRANSFORM(tnLine) + '] ' + tcMsg
ENDPROC
*==================================================================================
* CreeazaDocument: reproduce corpul lui Procedure factureaza (ofacturare.prg:81-560) pentru UN
* singur tnTip, o singura trecere (fara bucla "continuati?" si fara listare). Intoarce
* poDate.nid_vanzare (>0 succes) sau 0 (esec, detaliat in log).
FUNCTION CreeazaDocument
LPARAMETERS tnTip, tnIdClient, tcListaId, tnIdDelegat
PRIVATE poDate, poGeneratorNumere, poDateGestiuneDest, pnTotalDiscountAvize
LOCAL lnIdSet, lcSqlCursor, lcCursor, lnSucces, lnIdVanzareRezultat
lnIdVanzareRezultat = 0
pnTotalDiscountAvize = 0
update_jtva_coloane([JV], [jtva_coloane_temp])
update_saft_taxtable()
lnIdSet = 25000 + tnTip - 1 + gnScadereStoc * 10
poDate = CREATEOBJECT("oDateFactura", lnIdSet, tnTip)
poGeneratorNumere = CREATEOBJECT("oGeneratorNumere")
poDateGestiuneDest = CREATEOBJECT("oDateGestiune")
DO CASE
CASE tnTip < 21 OR INLIST(tnTip, 45, 48, 49, 51, 52)
poDate.nIdTipDoc = 5 && FACTURA
OTHERWISE
poDate.nIdTipDoc = 6 && AVIZ
ENDCASE
*-- comutare LOCALA gnIdUtil=8 (user cu plaja FACTURA activa) doar pt. alocarea numar/serie -
*-- cursor_avize/cursor_contract/cursor_preturi de mai jos au nevoie de gnIdUtil=-3 (vizibilitate
*-- AVIZ 1051 / CONTRACT 235, create/asociate userului -3) - vezi comentariul de la initializare.
gnIdUtil = 8
poGeneratorNumere.ResetNumere()
poDate.rezultat_serii = poGeneratorNumere.creeaza_cursor_serii(poDate.nIdTipDoc)
DO S8Log WITH ' poDate.nIdTipDoc=' + TRANSFORM(poDate.nIdTipDoc) + ' rezultat_serii=' + TRANSFORM(poDate.rezultat_serii) + ' id_fdoc=' + TRANSFORM(NVL(poDate.id_fdoc,-1)) + ' dataact=' + TRANSFORM(poDate.dataact) + ' datascad=' + TRANSFORM(NVL(poDate.datascad,{}))
*-- INLOCUIRE 1: setare directa poDate (echivalent cu ce ar completa operatorul in
*-- frm_date_aviz/frm_date_factura), NU prin INSERT. Numarul vine din generatorul real.
poDate.id_client = tnIdClient
IF !EMPTY(tcListaId)
poDate.listaid = tcListaId
ENDIF
poDate.id_delegat = tnIdDelegat
*-- zi_curs: Init() il seteaza = dataact (azi, 10.08.2026), dar in MARIUSM_AUTO nu exista inca
*-- curs EUR pentru azi (verificat prin sqlplus) - cursor_preturi/cursor_contract cad pe orice
*-- articol/rata in EUR din lista/contract cu eroarea Oracle 20005 "Nu este setat cursul...".
*-- Productia trateaza asta cu un dialog editabil (vizualizeaza_curs); headless, folosim ultima
*-- zi cu curs EUR real existent in schema (07.08.2026, tot in luna curenta) - camp distinct de
*-- dataact/dataireg, nu schimba data documentului.
poDate.zi_curs = {^2026-08-07}
*-- do_initializeaza din clb_serie_act (serii_numere.vc2:90-109) cheama getSerieCursor() DOAR pe
*-- ramura OTHERWISE (rezultat_serii=3, cu serie SI plaja) - pe rezultat_serii=1 (cu serie, fara
*-- plaja) serie_act ramane necompletat, de tastat manual de operator (text_simplu1 legat direct
*-- pe pcobj.cvariabila). getSerieCursor() nu are garda IsNull() ca aloca_numar() - apelat cand
*-- paPlaje(tip,2) e NULL (cazul rezultat=1 din ramura de esec verifica_cursor_serii/verifica_tipdoc)
*-- da eroare Oracle reala "Table number is invalid" (Reccount(NULL)).
IF poDate.rezultat_serii = 3
poDate.serie_act = poGeneratorNumere.getSerieCursor(poDate.nIdTipDoc)
ENDIF
poDate.nract = poGeneratorNumere.aloca_numar(poDate.nIdTipDoc, NULL)
poGeneratorNumere.verifica_numar(poDate.nIdTipDoc, poDate.nract)
gnIdUtil = -3
DO S8Log WITH ' numar alocat: serie_act=[' + TRANSFORM(NVL(poDate.serie_act,[])) + '] nract=' + TRANSFORM(poDate.nract)
IF poDate.tva_incasare = 0
SELECT * FROM jtva_coloane_temp WHERE ISNULL(id_jtva_ex) AND !'RORTC'$UPPER(coloana_jv) INTO CURSOR jtva_coloane
ELSE
SELECT * FROM jtva_coloane_temp WHERE ISNULL(id_jtva_neex) AND !'RORTC'$UPPER(coloana_jv) INTO CURSOR jtva_coloane
ENDIF
*-- cursorul sursa de articole, dupa tnTip (identic cu Do Case din factureaza())
DO CASE
CASE tnTip = 2
poDate.id_agent = 0
lcSqlCursor = [{call ] + gcS + [.pack_facturare.cursor_contract(?poDate.zi_curs,?poDate.tip,?poDate.id_valuta,] + ;
[?poDate.listaid,?poDate.id_gestiune_init,?gnLuna,?gnAn,?gnIdUtil,?gnIdSucursala,?@poDate.id_agent,?@poDate.nume_agent)}]
CASE tnTip = 4
lcSqlCursor = [{call ] + gcS + [.pack_facturare.cursor_avize(?poDate.listaid,?gnIdUtil,?@pnTotalDiscountAvize)}]
OTHERWISE && tnTip = 22 (lista de preturi)
lcSqlCursor = [{call ] + gcS + [.pack_facturare.cursor_preturi(?poDate.zi_curs,?poDate.tip,?poDate.id_valuta,] + ;
[?poDate.id_gestiune_init,?gnLuna,?gnAn,?gnIdUtil,?gnIdSucursala)}]
ENDCASE
lcCursor = [crsarticole]
lnSucces = goExecutor.oExecute(lcSqlCursor, lcCursor)
IF lnSucces < 0
DO S8Log WITH ' EROARE cursor articole: ' + goExecutor.oPrelucrareEroare()
poGeneratorNumere.dezaloca_numar(poDate.nIdTipDoc)
DO S8CurataJtva
RELEASE poDate, poGeneratorNumere, poDateGestiuneDest
RETURN 0
ENDIF
IF RECCOUNT(lcCursor) = 0 AND (!USED(lcCursor+'1') OR (USED(lcCursor+'1') AND RECCOUNT(lcCursor+'1') = 0))
DO S8Log WITH ' Nu exista articole pentru optiunile alese (Reccount=0) - abandon document'
poGeneratorNumere.dezaloca_numar(poDate.nIdTipDoc)
IF USED('crsCtrTemp')
USE IN crsCtrTemp
ENDIF
DO S8CurataJtva
RELEASE poDate, poGeneratorNumere, poDateGestiuneDest
RETURN 0
ENDIF
DO S8Log WITH ' crsarticole Reccount=' + TRANSFORM(RECCOUNT(lcCursor))
*-- cursor_preturi (lista de preturi, tnTip=22) nu are cantitate implicita - in dialogul real
*-- operatorul o tasteaza in grid inainte de "adauga tot". do_adauga_tot (ofacturare.vc2:13181)
*-- sare peste articolele gestionabile cu cantitate=0, dar articolul nostru nu e gestionabil, deci
*-- s-a adaugat cu cantitate=0 (verificat in Oracle: VANZARI_DETALII.CANTITATE=0 pt. AVIZ 1051) -
*-- inutil ca sursa pentru FACTURA DIN AVIZ (cursor_avize exclude liniile cu cantitate ramasa 0).
IF tnTip = 22
*-- crsarticole vine cu Buffering optimistic pe rand (3) - REPLACE fara TABLEUPDATE() ramane
*-- in bufferul local si e pierdut la urmatoarea citire/mutare de recno (verificat empiric:
*-- REPLACE arata cantitate=1 imediat, dar orice citire ulterioara arata iar 0).
SELECT (lcCursor)
REPLACE ALL cantitate WITH 1
=TABLEUPDATE(.T., .T., lcCursor)
GO TOP
DO S8Log WITH ' dupa fix cantitate: ' + lcCursor + '.cantitate=' + TRANSFORM(cantitate)
ENDIF
creeaza_facturacrs([crsfactura])
IF poDate.in_valuta = 1
SELECT DISTINCT Curs, nume_val, id_valuta, multiplicator FROM (lcCursor) WITH (Buffering = .T.) WHERE tip_valuta = 1 ORDER BY nume_val INTO CURSOR crscursuri
SELECT crscursuri
poDate.Curs = Curs
poDate.multiplicator = multiplicator
ELSE
citeste_cursuri_zi(poDate.zi_curs)
IF RECCOUNT('crscursuri') = 0
USE IN crscursuri
ENDIF
ENDIF
IF TYPE(lcCursor + '.nume_lista_preturi') <> 'U'
CREATE CURSOR crspolitici (id_pol N(20), nume_lista_preturi c(100))
SELECT crspolitici
INSERT INTO crspolitici(id_pol, nume_lista_preturi) VALUES (-9999, '<TOATE>')
INSERT INTO crspolitici(id_pol, nume_lista_preturi) ;
SELECT DISTINCT id_pol, nume_lista_preturi FROM (lcCursor) ORDER BY nume_lista_preturi
ENDIF
IF INLIST(tnTip, 2, 6, 26)
CREATE CURSOR crscontracte(id_ctr N(20), numar_contract c(100), Data d NULL, numar c(50) NULL)
SELECT crscontracte
APPEND BLANK
REPLACE id_ctr WITH -9999, numar_contract WITH '<TOATE>'
IF USED(lcCursor + '1')
INSERT INTO crscontracte(id_ctr, numar_contract, Data, numar) ;
SELECT DISTINCT id_ctr, numar_contract, Data, numar FROM (lcCursor + [1]) ORDER BY Data, numar
ENDIF
ENDIF
*-- INLOCUIRE 2: frm_facturare_articole modeless (apel direct de metode, ca in
*-- test_pret_cu_tva_nivel2.prg:266-272), NU .Show() modal
PUBLIC goFrm8
goFrm8 = CREATEOBJECT('frm_facturare_articole')
goFrm8.WindowType = 0
goFrm8.Show()
DOEVENTS FORCE
DO S8Log WITH ' frm_facturare_articole afisat modeless'
goFrm8.do_adauga_tot()
DOEVENTS FORCE
DO S8Log WITH ' do_adauga_tot() -> Reccount(crsfactura)=' + TRANSFORM(RECCOUNT('crsfactura'))
goFrm8.do_calculeaza_totaluri()
DOEVENTS FORCE
glDlgTratat8 = .F.
LOCAL lnScris
lnScris = goFrm8.do_termin()
LOCAL lnWait
lnWait = 0
DO WHILE !glDlgTratat8 AND lnWait < 10
DOEVENTS FORCE
lnWait = lnWait + 1
ENDDO
DO S8Log WITH ' do_termin() -> ' + TRANSFORM(lnScris) + ' (frm_alte_date tratat=' + TRANSFORM(glDlgTratat8) + ') poDate.nid_vanzare=' + TRANSFORM(NVL(poDate.nid_vanzare,0))
IF lnScris
lnIdVanzareRezultat = NVL(poDate.nid_vanzare, 0)
ELSE
lnIdVanzareRezultat = 0
ENDIF
IF TYPE('goFrm8') = 'O' AND !ISNULL(goFrm8)
goFrm8.Release()
ENDIF
goFrm8 = NULL
IF USED('crspolitici')
USE IN crspolitici
ENDIF
IF USED('crscursuri')
USE IN crscursuri
ENDIF
IF USED('crscontracte')
USE IN crscontracte
ENDIF
IF USED('crsCtrTemp')
USE IN crsCtrTemp
ENDIF
IF USED('crsfactura')
USE IN crsfactura
ENDIF
IF USED('crsfacturaset')
USE IN crsfacturaset
ENDIF
IF USED('crsfacturafinala')
USE IN crsfacturafinala
ENDIF
IF USED('crsarticole')
USE IN crsarticole
ENDIF
IF USED('crsarticole1')
USE IN crsarticole1
ENDIF
IF USED('jtva_coloane')
USE IN jtva_coloane
ENDIF
IF USED('jtva_coloane_temp')
USE IN jtva_coloane_temp
ENDIF
RELEASE poDate, poGeneratorNumere, poDateGestiuneDest
RETURN lnIdVanzareRezultat
ENDFUNC
PROCEDURE S8CurataJtva
IF USED('jtva_coloane')
USE IN jtva_coloane
ENDIF
IF USED('jtva_coloane_temp')
USE IN jtva_coloane_temp
ENDIF
ENDPROC
*==================================================================================
DEFINE CLASS dummyapp AS Custom
PROCEDURE ReadIni
LPARAMETERS tcSection, tcKey
RETURN ''
ENDPROC
PROCEDURE WriteIni
LPARAMETERS tcSection, tcKey, tcValue
RETURN .T.
ENDPROC
ENDDEFINE
DEFINE CLASS dummyexport AS Custom
PROCEDURE citesteSetareRegistru
LPARAMETERS tcCheie
RETURN ''
ENDPROC
ENDDEFINE
*-- driverAlteDate8: cauta FRM_ALTE_DATE prin _SCREEN.Forms (mecanism validat, driverdeblocare3 din
*-- test_pret_cu_tva_nivel2.prg) si ii apeleaza .do_termin() direct - poDate.id_delegat si
*-- poDate.dataora_exp sunt deja setate inainte sa ajunga aici (id_delegat de CreeazaDocument,
*-- dataora_exp de frm_facturare_articole.inainte_de_do_termin, ofacturare.vc2:14921, cod neatins)
DEFINE CLASS driverAlteDate8 AS Custom
PROCEDURE Executa
LOCAL lnI, loForm, llGasit
llGasit = .F.
FOR lnI = 1 TO _SCREEN.FormCount
IF UPPER(_SCREEN.Forms(lnI).Class) == 'FRM_ALTE_DATE'
loForm = _SCREEN.Forms(lnI)
llGasit = .T.
ENDIF
ENDFOR
IF glDlgTratat8 OR !llGasit
RETURN
ENDIF
DO S8Log WITH ' driverAlteDate8: FRM_ALTE_DATE detectat, apas do_termin()'
*-- FIX crash dur: citirea lui loForm.ActiveControl AICI, separat, inainte de do_termin(),
*-- evita access-violation-ul din inainte_de_do_termin (ferestre_cere_date.vc2:3058,
*-- Upper(This.ActiveControl.BaseClass) necondiționat) - confirmat empiric ca elimina crash-ul
*-- (fara aceasta atingere prealabila, do_termin() nu mai revine deloc, fara nicio linie de
*-- CATCH ulterioara in log). ActiveControl a iesit valid (TEXTBOX/Text_simplu1) chiar si fara
*-- SetFocus explicit - simpla accesare a proprietatii inainte de apelul real pare sa
*-- sincronizeze starea COM/OLE a formularului aflat inca in Show(1) modal, apelat din Timer.
LOCAL loAC
loAC = loForm.ActiveControl
DO S8Log WITH ' driverAlteDate8: ActiveControl VARTYPE=' + VARTYPE(loAC) + ;
IIF(VARTYPE(loAC)='O', ' BaseClass=' + UPPER(loAC.BaseClass) + ' Name=' + loAC.Name, '')
TRY
loForm.do_termin()
glDlgTratat8 = .T.
CATCH TO loExcDrv
DO S8Log WITH ' driverAlteDate8: CATCH ErrorNo=' + TRANSFORM(loExcDrv.ErrorNo) + ' Message=' + loExcDrv.Message + ' Procedure=' + loExcDrv.Procedure + ' LineNo=' + TRANSFORM(loExcDrv.LineNo)
glDlgTratat8 = .T.
ENDTRY
ENDPROC
ENDDEFINE