* test_storno_efactura.prg * Teste StornoEFacturaXML/GetXmlOriginalEFactura (COMUN\programe\anaf_efactura.prg) si * rutarea CN/FCN + B2C din SendEfactura/ValidareEFacturaANAF (verificare fara retea). * Fixturi in COMUN\utile\Teste\storno\ (anonimizate, cu diacritice reale la fixtura din id 3795). * * Rulare: vfp9.exe -A -T "D:\ROA\ROACONT\COMUN\utile\Teste\storno\test_storno_efactura.prg" * Iesire in D:\ROA\ROACONT\COMUN\utile\Teste\storno\test_storno_efactura_log.txt SET SAFETY OFF SET TALK OFF SET DELETED ON SET EXACT ON SET CENTURY ON SET DATE DMY SET NULLDISPLAY TO '' CLOSE DATABASES PUBLIC gcUILog, gcFixDir, gcOutDir gcFixDir = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\" gcOutDir = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\out\" IF !DIRECTORY(gcOutDir) MD (gcOutDir) ENDIF gcUILog = gcFixDir + "test_storno_efactura_log.txt" STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog) ON ERROR DO PrErrLocal WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() ON SHUTDOWN QUIT PUBLIC lnPass, lnFail lnPass = 0 lnFail = 0 TRY DO "D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg" WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT' IF gnHandle <= 0 DO PrLogLocal WITH 'FAIL: conectare Oracle esuata (gnHandle=' + TRANSFORM(gnHandle) + ')' QUIT ENDIF DO PrLogLocal WITH 'mediu initializat, gnHandle=' + TRANSFORM(gnHandle) + ' gnAn=' + TRANSFORM(gnAn) + ' gnLuna=' + TRANSFORM(gnLuna) *========================================================================= DO PrLogLocal WITH '=== TEST 0: functiile noi sunt incarcate (SET PROCEDURE anaf_efactura.prg din init) ===' LOCAL lcMsg0, llRet0 LOCAL laMod0[1,4] llRet0 = StornoEFacturaXML('', '', '', gcOutDir + 't0.xml', @laMod0, @lcMsg0) DO Assert WITH !llRet0 AND 'gol' $ LOWER(lcMsg0), 'StornoEFacturaXML e apelabila si valideaza XML gol', 'retur=' + TRANSFORM(llRet0) + ' mesaj=[' + lcMsg0 + ']' *========================================================================= DO PrLogLocal WITH '=== TEST 1 + 1b + 2: round-trip dubla negare + diacritice + noduri neatinse (fixtura reala id 3795) ===' DO TestRoundTrip WITH 'storno_fixture_diacritice_reale.xml', 'diacritice_reale', .T. DO PrLogLocal WITH '=== TEST 1 + 2: round-trip (fixtura simpla cu reduceri/majorari pe document) ===' DO TestRoundTrip WITH 'storno_fixture_diacritice_reale.xml', 'diacritice_reale_bis', .F. DO PrLogLocal WITH '=== TEST 1 + 1c: round-trip + namespace corect pe prefixe custom n1/n2/n3 ===' DO TestRoundTrip WITH 'storno_fixture_prefix_n3.xml', 'prefix_n3', .F. DO TestNamespaceN3 DO PrLogLocal WITH '=== TEST 1: round-trip pe CreditNote minimal ===' DO TestRoundTrip WITH 'storno_fixture_creditnote_minimal.xml', 'creditnote_minimal', .F. DO PrLogLocal WITH '=== TEST 1: round-trip pe factura deja negativa (D13: permisa) ===' DO TestRoundTrip WITH 'storno_fixture_factura_negativa.xml', 'factura_negativa', .F. DO PrLogLocal WITH '=== TEST 1: sume zero / -0.00 raman neschimbate (nu apar in taModificari) ===' DO TestSumeZero DO PrLogLocal WITH '=== TEST 1: cbc:Amount in PaymentTerms NU se neaga (doar Amount/BaseAmount sub AllowanceCharge) ===' DO TestPaymentTermsNeatins DO PrLogLocal WITH '=== TEST: motiv cu caractere speciale (& si <) scris corect prin DOM, nu concatenare ===' DO TestMotivSpecial DO PrLogLocal WITH '=== TEST: numar nou cu slash pastrat exact (scris prin DOM) ===' DO TestNumarCuSlash DO PrLogLocal WITH '=== TEST 3b: blocaje fara retea (in interiorul StornoEFacturaXML) ===' DO TestBlocaje DO PrLogLocal WITH '=== TEST: fixtura B2C (CNP 13 cifre) si furnizor fara PartyTaxScheme - parsare OK, pregatite pentru Lane 2/C ===' DO TestRoundTrip WITH 'storno_fixture_b2c_cnp.xml', 'b2c_cnp', .F. DO TestRoundTrip WITH 'storno_fixture_fara_partytaxscheme.xml', 'fara_partytaxscheme', .F. DO PrLogLocal WITH '=== TEST: rutare CN/FCN si B2C (logica SendEfactura/ValidareEFacturaANAF, fara apel retea) ===' DO TestRutareCNSiB2C DO PrLogLocal WITH '=== TEST 3: validare online ANAF TEST - neexecutat (fara token de test verificat; risc cunoscut SET STEP ON anaf_efactura.prg:717 cu token expirat) ===' DO PrLogLocal WITH '=== TEST 4: upload real ANAF - INTERZIS pentru Lane 1, neexecutat ===' DO PrLogLocal WITH 'TOTAL: PASS=' + TRANSFORM(lnPass) + ' FAIL=' + TRANSFORM(lnFail) DO PrLogLocal WITH 'TOTAL: test terminat fara exceptie' CATCH TO loEx DO PrLogLocal WITH 'EXCEPTIE: ' + loEx.Message + ' (' + TRANSFORM(loEx.LineNo) + ') ' + loEx.Procedure ENDTRY QUIT ********************************************************** * neaga de doua ori (storno al storno-ului) si verifica identitatea: valorile noi din a doua * trecere trebuie sa fie exact valorile originale din prima trecere (textual, fara rotunjire). * Foloseste taModificari (nu re-parseaza XML-ul), deci verifica direct contractul functiei. PROCEDURE TestRoundTrip LPARAMETERS tcFixtura, tcLabel, tlVerificaDiacritice LOCAL lcXml, lcFile1, lcFile2, lcMsg1, lcMsg2, llRet1, llRet2 LOCAL laMod1[1,4], laMod2[1,4] IF !FILE(gcFixDir + tcFixtura) DO Assert WITH .F., '[' + tcLabel + '] fixtura exista', gcFixDir + tcFixtura RETURN ENDIF lcXml = FILETOSTR(gcFixDir + tcFixtura) lcFile1 = gcOutDir + tcLabel + '_storno1.xml' lcFile2 = gcOutDir + tcLabel + '_storno2.xml' llRet1 = StornoEFacturaXML(m.lcXml, '', 'Stornare factura test ' + m.tcLabel, m.lcFile1, @laMod1, @lcMsg1) DO Assert WITH llRet1, '[' + tcLabel + '] StornoEFacturaXML (prima trecere) reuseste', 'mesaj=[' + lcMsg1 + ']' IF !llRet1 RETURN ENDIF DO Assert WITH FILE(m.lcFile1), '[' + tcLabel + '] fisierul storno1 exista pe disc', m.lcFile1 IF m.tlVerificaDiacritice LOCAL lcBrutOriginal, lcBrutStorno lcBrutOriginal = FILETOSTR(gcFixDir + tcFixtura) lcBrutStorno = FILETOSTR(m.lcFile1) *-- Constan[C5 A3]a (U+0163, "t cu virgula") pastrat identic pe octeti in storno DO Assert WITH ('Constan' + CHR(0xC5) + CHR(0xA3) + 'a') $ m.lcBrutStorno, '[' + tcLabel + '] 1b: diacritice C5 A3 (U+0163) pastrate pe octeti in storno1', 'len=' + TRANSFORM(LEN(m.lcBrutStorno)) ENDIF llRet2 = StornoEFacturaXML(FILETOSTR(m.lcFile1), 'ORIG-TEST-' + tcLabel, '', m.lcFile2, @laMod2, @lcMsg2) DO Assert WITH llRet2, '[' + tcLabel + '] StornoEFacturaXML (a doua trecere, pe storno1) reuseste', 'mesaj=[' + lcMsg2 + ']' IF !llRet2 RETURN ENDIF *-- filtreaza doar randurile de sume/cantitati (tip 2 total, tip 3 linie), fara antet (tip 1) LOCAL lnI, lnJ1, lnJ2 DIMENSION laF1[1], laF2[1] lnJ1 = 0 FOR lnI = 1 TO ALEN(laMod1, 1) IF laMod1[lnI, 4] = 2 OR laMod1[lnI, 4] = 3 lnJ1 = lnJ1 + 1 DIMENSION laF1[lnJ1, 2] laF1[lnJ1, 1] = laMod1[lnI, 2] laF1[lnJ1, 2] = laMod1[lnI, 3] ENDIF ENDFOR lnJ2 = 0 FOR lnI = 1 TO ALEN(laMod2, 1) IF laMod2[lnI, 4] = 2 OR laMod2[lnI, 4] = 3 lnJ2 = lnJ2 + 1 DIMENSION laF2[lnJ2, 2] laF2[lnJ2, 1] = laMod2[lnI, 2] laF2[lnJ2, 2] = laMod2[lnI, 3] ENDIF ENDFOR DO Assert WITH lnJ1 = lnJ2 AND lnJ1 > 0, '[' + tcLabel + '] 1: numarul de noduri numerice negate e acelasi la dus si intors', 'trecere1=' + TRANSFORM(lnJ1) + ' trecere2=' + TRANSFORM(lnJ2) IF lnJ1 = lnJ2 AND lnJ1 > 0 LOCAL llToateOk llToateOk = .T. FOR lnI = 1 TO lnJ1 *-- valoarea noua din trecerea 1 (negata) trebuie sa fie valoarea originala din trecerea 2 IF ALLTRIM(laF1[lnI, 2]) <> ALLTRIM(laF2[lnI, 1]) llToateOk = .F. ENDIF *-- valoarea noua din trecerea 2 (negata a doua oara) trebuie sa fie exact valoarea originala din trecerea 1 IF ALLTRIM(laF1[lnI, 1]) <> ALLTRIM(laF2[lnI, 2]) llToateOk = .F. ENDIF ENDFOR DO Assert WITH llToateOk, '[' + tcLabel + '] 1: dubla negare da exact valorile originale (textual)', '' ENDIF *-- 2: un nod static, neatins de negare, ramane identic intre original si storno1 LOCAL loDOMOrig, loDOMStorno, loNodOrig, loNodStorno loDOMOrig = CREATEOBJECT('MSXML2.DOMDocument.6.0') loDOMOrig.Async = .F. loDOMOrig.setProperty('SelectionLanguage', 'XPath') loDOMOrig.LoadXML(m.lcXml) loDOMStorno = CREATEOBJECT('MSXML2.DOMDocument.6.0') loDOMStorno.Async = .F. loDOMStorno.setProperty('SelectionLanguage', 'XPath') loDOMStorno.Load(m.lcFile1) loNodOrig = loDOMOrig.documentElement.selectSingleNode("//*[local-name()='RegistrationName']") loNodStorno = loDOMStorno.documentElement.selectSingleNode("//*[local-name()='RegistrationName']") IF !ISNULL(m.loNodOrig) AND !ISNULL(m.loNodStorno) DO Assert WITH loNodOrig.Text == loNodStorno.Text, '[' + tcLabel + '] 2: RegistrationName (nod neatins) identic in storno', '[' + loNodOrig.Text + '] vs [' + loNodStorno.Text + ']' ENDIF *-- ID radacinii trebuie sa fie exact numarul cerut (implicit + '-S') LOCAL loIdOrig, loIdStorno loIdOrig = loDOMOrig.documentElement.selectSingleNode("*[local-name()='ID']") loIdStorno = loDOMStorno.documentElement.selectSingleNode("*[local-name()='ID']") IF !ISNULL(m.loIdOrig) AND !ISNULL(m.loIdStorno) DO Assert WITH ALLTRIM(loIdStorno.Text) == ALLTRIM(loIdOrig.Text) + '-S', '[' + tcLabel + '] numar storno implicit = numar original + -S', '[' + loIdStorno.Text + ']' ENDIF *-- BillingReference catre originalul (numarul VECHI, dinainte de schimbare) LOCAL loRef loRef = loDOMStorno.documentElement.selectSingleNode("//*[local-name()='BillingReference']/*[local-name()='InvoiceDocumentReference']/*[local-name()='ID']") IF !ISNULL(m.loRef) AND !ISNULL(m.loIdOrig) DO Assert WITH ALLTRIM(loRef.Text) == ALLTRIM(loIdOrig.Text), '[' + tcLabel + '] BillingReference contine numarul original', '[' + loRef.Text + ']' ELSE DO Assert WITH .F., '[' + tcLabel + '] BillingReference/InvoiceDocumentReference/ID gasit', '' ENDIF *-- Nota scrisa (a fost trimisa nevida la trecerea 1) LOCAL loNote loNote = loDOMStorno.documentElement.selectSingleNode("*[local-name()='Note']") IF !ISNULL(m.loNote) DO Assert WITH 'Stornare factura test' $ loNote.Text, '[' + tcLabel + '] Nota scrisa pe document', '[' + loNote.Text + ']' ELSE DO Assert WITH .F., '[' + tcLabel + '] Nota (cbc:Note) gasita dupa storno', '' ENDIF ENDPROC ********************************************************** * namespace-ul nodurilor NOI (BillingReference/ID, Note) trebuie sa fie cel din radacina * originalului (n1/CommonBasicComponents-2, n2/CommonAggregateComponents-2), nu prefix implicit PROCEDURE TestNamespaceN3 LOCAL lcFile1, loDOM, loRef, loNote LOCAL lcUriCbc, lcUriCac lcUriCbc = 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2' lcUriCac = 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2' lcFile1 = gcOutDir + 'prefix_n3_storno1.xml' IF !FILE(m.lcFile1) DO Assert WITH .F., '[prefix_n3] 1c: fisierul storno1 exista (rulat de TestRoundTrip)', m.lcFile1 RETURN ENDIF loDOM = CREATEOBJECT('MSXML2.DOMDocument.6.0') loDOM.Async = .F. loDOM.setProperty('SelectionLanguage', 'XPath') loDOM.Load(m.lcFile1) loRef = loDOM.documentElement.selectSingleNode("//*[local-name()='BillingReference']") IF !ISNULL(m.loRef) DO Assert WITH loRef.namespaceURI == lcUriCac, '[prefix_n3] 1c: BillingReference in namespace cac corect', loRef.namespaceURI ELSE DO Assert WITH .F., '[prefix_n3] 1c: BillingReference gasit', '' ENDIF LOCAL loRefId loRefId = loDOM.documentElement.selectSingleNode("//*[local-name()='BillingReference']/*[local-name()='InvoiceDocumentReference']/*[local-name()='ID']") IF !ISNULL(m.loRefId) DO Assert WITH loRefId.namespaceURI == lcUriCbc, '[prefix_n3] 1c: ID din InvoiceDocumentReference in namespace cbc corect', loRefId.namespaceURI ELSE DO Assert WITH .F., '[prefix_n3] 1c: BillingReference/InvoiceDocumentReference/ID gasit', '' ENDIF loNote = loDOM.documentElement.selectSingleNode("*[local-name()='Note']") IF !ISNULL(m.loNote) DO Assert WITH loNote.namespaceURI == lcUriCbc, '[prefix_n3] 1c: Note in namespace cbc corect', loNote.namespaceURI ELSE DO Assert WITH .F., '[prefix_n3] 1c: Note gasita', '' ENDIF ENDPROC ********************************************************** * -0.00 si 0.00 nu trebuie sa apara deloc in taModificari (raman neschimbate, cf. spec) PROCEDURE TestSumeZero LOCAL lcXml, lcFile, lcMsg, llRet LOCAL laMod[1,4] lcXml = FILETOSTR(gcFixDir + 'storno_fixture_sume_zero.xml') lcFile = gcOutDir + 'sume_zero_storno1.xml' llRet = StornoEFacturaXML(m.lcXml, '', '', m.lcFile, @laMod, @lcMsg) DO Assert WITH llRet, '[sume_zero] StornoEFacturaXML reuseste', 'mesaj=[' + lcMsg + ']' IF !llRet RETURN ENDIF LOCAL lnI, llGasitZero llGasitZero = .F. FOR lnI = 1 TO ALEN(laMod, 1) IF (laMod[lnI, 4] = 2 OR laMod[lnI, 4] = 3) AND ('0.00' $ laMod[lnI, 2] OR '0,00' $ laMod[lnI, 2]) IF VAL(STRTRAN(ALLTRIM(laMod[lnI, 2]), '-', '')) = 0 llGasitZero = .T. ENDIF ENDIF ENDFOR DO Assert WITH !llGasitZero, '[sume_zero] nicio valoare zero (inclusiv -0.00) nu apare in taModificari', 'randuri=' + TRANSFORM(ALEN(laMod,1)) *-- verificare directa pe fisier: -0.00 din AllowanceCharge/Amount ramane neschimbat LOCAL lcOut lcOut = FILETOSTR(m.lcFile) DO Assert WITH '-0.00' $ m.lcOut, '[sume_zero] -0.00 (AllowanceCharge/Amount) prezent neschimbat in storno', '' ENDPROC ********************************************************** * cbc:Amount din cac:PaymentTerms nu are parintele AllowanceCharge -> nu se neaga PROCEDURE TestPaymentTermsNeatins LOCAL lcXml, lcFile, lcMsg, llRet LOCAL laMod[1,4] lcXml = FILETOSTR(gcFixDir + 'storno_fixture_paymentterms.xml') lcFile = gcOutDir + 'paymentterms_storno1.xml' llRet = StornoEFacturaXML(m.lcXml, '', '', m.lcFile, @laMod, @lcMsg) DO Assert WITH llRet, '[paymentterms] StornoEFacturaXML reuseste', 'mesaj=[' + lcMsg + ']' IF !llRet RETURN ENDIF LOCAL loDOM, loPT loDOM = CREATEOBJECT('MSXML2.DOMDocument.6.0') loDOM.Async = .F. loDOM.setProperty('SelectionLanguage', 'XPath') loDOM.Load(m.lcFile) loPT = loDOM.documentElement.selectSingleNode("//*[local-name()='PaymentTerms']/*[local-name()='Amount']") IF !ISNULL(m.loPT) DO Assert WITH ALLTRIM(loPT.Text) == '119.00', '[paymentterms] cbc:Amount din PaymentTerms ramane neatins (119.00)', '[' + loPT.Text + ']' ELSE DO Assert WITH .F., '[paymentterms] nodul PaymentTerms/Amount gasit', '' ENDIF ENDPROC ********************************************************** * Nota cu '&' si '<' scrisa prin .Text (DOM face escape automat) - XML-ul ramane valid PROCEDURE TestMotivSpecial LOCAL lcXml, lcFile, lcMsg, llRet, lcNota LOCAL laMod[1,4] lcXml = FILETOSTR(gcFixDir + 'storno_fixture_diacritice_reale.xml') lcFile = gcOutDir + 'motiv_special_storno1.xml' lcNota = 'Marfa < prag & retur client' llRet = StornoEFacturaXML(m.lcXml, '', m.lcNota, m.lcFile, @laMod, @lcMsg) DO Assert WITH llRet, '[motiv_special] StornoEFacturaXML reuseste cu motiv & si <', 'mesaj=[' + lcMsg + ']' IF !llRet RETURN ENDIF LOCAL loDOM, loNote loDOM = CREATEOBJECT('MSXML2.DOMDocument.6.0') loDOM.Async = .F. loDOM.setProperty('SelectionLanguage', 'XPath') loDOM.Load(m.lcFile) DO Assert WITH loDOM.parseError.errorcode = 0, '[motiv_special] xml-ul rezultat e valid (parseError=0)', TRANSFORM(loDOM.parseError.errorcode) loNote = loDOM.documentElement.selectSingleNode("*[local-name()='Note']") IF !ISNULL(m.loNote) DO Assert WITH loNote.Text == m.lcNota, '[motiv_special] textul notei intact dupa reincarcare (& si < pastrate ca text)', '[' + loNote.Text + ']' ELSE DO Assert WITH .F., '[motiv_special] Note gasita', '' ENDIF ENDPROC ********************************************************** * numar cu '/' (documente cu numerotare pe serie/numar) scris prin .Text, fara conflict XML PROCEDURE TestNumarCuSlash LOCAL lcXml, lcFile, lcMsg, llRet, lcNumar LOCAL laMod[1,4] lcXml = FILETOSTR(gcFixDir + 'storno_fixture_diacritice_reale.xml') lcFile = gcOutDir + 'numar_slash_storno1.xml' lcNumar = 'FF/2026/S' llRet = StornoEFacturaXML(m.lcXml, m.lcNumar, '', m.lcFile, @laMod, @lcMsg) DO Assert WITH llRet, '[numar_slash] StornoEFacturaXML reuseste cu numar continand /', 'mesaj=[' + lcMsg + ']' IF !llRet RETURN ENDIF LOCAL loDOM, loId loDOM = CREATEOBJECT('MSXML2.DOMDocument.6.0') loDOM.Async = .F. loDOM.setProperty('SelectionLanguage', 'XPath') loDOM.Load(m.lcFile) loId = loDOM.documentElement.selectSingleNode("*[local-name()='ID']") IF !ISNULL(m.loId) DO Assert WITH loId.Text == m.lcNumar, '[numar_slash] ID radacinii = numarul cu / exact', '[' + loId.Text + ']' ELSE DO Assert WITH .F., '[numar_slash] ID gasit', '' ENDIF ENDPROC ********************************************************** * blocaje interne StornoEFacturaXML, fara nicio conexiune de retea PROCEDURE TestBlocaje LOCAL lcMsg, llRet LOCAL laMod[1,4] llRet = StornoEFacturaXML('', '', '', gcOutDir + 'blocaj_gol.xml', @laMod, @lcMsg) DO Assert WITH !llRet AND 'gol' $ LOWER(lcMsg), '3b: XML gol -> blocare cu mesaj clar', '[' + lcMsg + ']' llRet = StornoEFacturaXML(' eroare de parsare', '[' + lcMsg + ']' llRet = StornoEFacturaXML('1', '', '', gcOutDir + 'blocaj_radacina.xml', @laMod, @lcMsg) DO Assert WITH !llRet AND 'Invoice/CreditNote' $ lcMsg, '3b: radacina ne-Invoice/CreditNote -> blocare cu mesaj clar', '[' + lcMsg + ']' llRet = StornoEFacturaXML('2026-01-01', '', '', gcOutDir + 'blocaj_lipsa.xml', @laMod, @lcMsg) DO Assert WITH !llRet AND 'Lipseste' $ lcMsg, '3b: lipseste ID/IssueDate/Supplier -> blocare cu mesaj clar', '[' + lcMsg + ']' LOCAL lcXmlBadNum lcXmlBadNum = STRTRAN(FILETOSTR(gcFixDir + 'storno_fixture_diacritice_reale.xml'), '18.18', 'ABC', 1, 1) DO Assert WITH 'ABC' $ lcXmlBadNum, '3b: pregatire fixtura cu valoare nenumerica (substitutie reusita)', '' llRet = StornoEFacturaXML(m.lcXmlBadNum, '', '', gcOutDir + 'blocaj_nenumeric.xml', @laMod, @lcMsg) DO Assert WITH !llRet AND 'nenumeric' $ LOWER(lcMsg) AND 'TaxAmount' $ lcMsg, '3b: valoare nenumerica -> blocare, mesajul numeste nodul', '[' + lcMsg + ']' DO PrLogLocal WITH ' (CIF strain / luna blocata: verificari la pasul 2 in frm_storno_efactura, Lane 2/C - nu exista inca cod de testat)' ENDPROC ********************************************************** * rutarea CN/FCN (standard=CN la upload, FCN la validare) si detectia B2C (CNP 13 cifre) - * aceeasi expresie ca in SendEfactura/ValidareEFacturaANAF, verificata fara HTTP PROCEDURE TestRutareCNSiB2C LOCAL lcInv, lcCn, lcB2c lcInv = FILETOSTR(gcFixDir + 'storno_fixture_diacritice_reale.xml') lcCn = FILETOSTR(gcFixDir + 'storno_fixture_creditnote_minimal.xml') lcB2c = FILETOSTR(gcFixDir + 'storno_fixture_b2c_cnp.xml') DO Assert WITH IIF('CreditNote' $ lcInv, 'CN', 'UBL') == 'UBL', 'rutare: Invoice -> standard=UBL / validare FACT1', '' DO Assert WITH IIF('CreditNote' $ lcCn, 'CN', 'UBL') == 'CN', 'rutare: CreditNote -> standard=CN', '' DO Assert WITH IIF('CreditNote' $ lcCn, 'FCN', 'FACT1') == 'FCN', 'rutare: CreditNote -> validare FCN', '' DO Assert WITH IIF('CreditNote' $ lcInv, 'FCN', 'FACT1') == 'FACT1', 'rutare: Invoice -> validare FACT1', '' LOCAL lcCustomer, lcPartyLegal, lcCodFiscalClient lcCustomer = STREXTRACT(lcB2c, '', '', 1, 1) lcPartyLegal = STREXTRACT(lcCustomer, '', '', 1, 1) lcCodFiscalClient = ALLTRIM(STREXTRACT(lcPartyLegal, '', '', 1, 1)) DO Assert WITH LEN(lcCodFiscalClient) = 13, 'B2C: CNP de 13 cifre detectat din fixtura (llB2C ar deveni .T.)', 'cnp=[' + lcCodFiscalClient + '] len=' + TRANSFORM(LEN(lcCodFiscalClient)) ENDPROC ********************************************************** PROCEDURE Assert LPARAMETERS tlCond, tcTitlu, tcDetaliu IF tlCond lnPass = lnPass + 1 DO PrLogLocal WITH ' OK ' + tcTitlu + IIF(EMPTY(tcDetaliu), '', ' (' + tcDetaliu + ')') ELSE lnFail = lnFail + 1 DO PrLogLocal WITH ' FAIL ' + tcTitlu + IIF(EMPTY(tcDetaliu), '', ' (' + tcDetaliu + ')') ENDIF ENDPROC ********************************************************** PROCEDURE PrLogLocal LPARAMETERS tcMsg LOCAL lcL SET SAFETY OFF lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '') STRTOFILE(lcL + TRANSFORM(tcMsg) + CHR(13) + CHR(10), gcUILog) ENDPROC ********************************************************** PROCEDURE PrErrLocal LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo DO PrLogLocal WITH 'EROARE ' + TRANSFORM(tnError) + ' ' + TRANSFORM(tcMessage) + ' in ' + TRANSFORM(tcProgram) + ' linia ' + TRANSFORM(tnLineNo) ENDPROC