Files
comun/utile/Teste/storno/test_storno_efactura.prg

450 lines
20 KiB
Plaintext

* 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('<Invoice><nchis', '', '', gcOutDir + 'blocaj_malformat.xml', @laMod, @lcMsg)
DO Assert WITH !llRet AND 'pars' $ LOWER(lcMsg), '3b: XML malformat -> eroare de parsare', '[' + lcMsg + ']'
llRet = StornoEFacturaXML('<Altceva xmlns="x"><y>1</y></Altceva>', '', '', 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('<Invoice xmlns:cbc="u1" xmlns:cac="u2"><cbc:DueDate>2026-01-01</cbc:DueDate></Invoice>', '', '', 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'), '<cbc:TaxAmount currencyID="RON">18.18</cbc:TaxAmount>', '<cbc:TaxAmount currencyID="RON">ABC</cbc:TaxAmount>', 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, '<cac:AccountingCustomerParty>', '</cac:AccountingCustomerParty>', 1, 1)
lcPartyLegal = STREXTRACT(lcCustomer, '<cac:PartyLegalEntity>', '</cac:PartyLegalEntity>', 1, 1)
lcCodFiscalClient = ALLTRIM(STREXTRACT(lcPartyLegal, '<cbc:CompanyID>', '</cbc:CompanyID>', 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