teste storno eFactura: unitare (StornoEFacturaXML), e2e headless borderou->forma storno->trimitere pe mock, test4 ANAF TEST, fixturi anonimizate

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WsxyCHJYL6W9MZ6FPnH8ax
This commit is contained in:
2026-09-18 19:48:32 +03:00
parent 45aad0f07c
commit b851051c44
16 changed files with 1478 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
* extract_fixture_3795.prg
* Extrage xml-ul original al randului ANAF_EFACTURA.ID = 3795 (MARIUSM_AUTO) prin
* GetXmlOriginalEFactura, pentru anonimizare si salvare ca fixtura de test (storno diacritice reale).
* Rulare: vfp9.exe -A -T "D:\ROA\ROACONT\COMUN\utile\Teste\storno\extract_fixture_3795.prg"
* Iesire: D:\ROA\ROACONT\COMUN\utile\Teste\storno\_raw_3795.xml + _raw_3795_log.txt
SET SAFETY OFF
SET TALK OFF
CLOSE DATABASES
PUBLIC gcUILog
gcUILog = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\_raw_3795_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog)
ON ERROR DO PrErrLocal WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
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'
QUIT
ENDIF
LOCAL lcXml, lcMesaj, llSucces
llSucces = GetXmlOriginalEFactura(3795, @lcXml, @lcMesaj)
DO PrLogLocal WITH 'GetXmlOriginalEFactura(3795) = ' + TRANSFORM(llSucces) + ' mesaj=[' + m.lcMesaj + '] len=' + TRANSFORM(LEN(m.lcXml))
IF m.llSucces
STRTOFILE(m.lcXml, "D:\ROA\ROACONT\COMUN\utile\Teste\storno\_raw_3795.xml")
DO PrLogLocal WITH 'salvat _raw_3795.xml'
ENDIF
CATCH TO loEx
DO PrLogLocal WITH 'EXCEPTIE: ' + loEx.Message + ' (' + TRANSFORM(loEx.LineNo) + ') ' + loEx.Procedure
ENDTRY
QUIT
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

View File

@@ -0,0 +1,27 @@
* mock_amessagebox_storno.prg - mock AMESSAGEBOX specific testului E2E storno
* (test_storno_e2e.prg). Raspunde diferit dupa continutul mesajului: 1 (OK) la gate-ul
* initial "genereaza XML-ul de stornare", 6 (Da) la confirmarea "Trimiteti la ANAF",
* altfel gnMockRaspuns implicit. Logheaza TOATE apelurile in PUBLIC gaAmsgCalls/gnAmsgCalls,
* utile ca sa vedem daca un guard neasteptat (CIF/luna blocata) a oprit fluxul.
FUNCTION amessagebox
LPARAMETERS tcMessage, tnDialogBoxType, tcTitle, tcFont, tnTimeOut, tnTimeoutValue
LOCAL lnRaspuns
DO CASE
CASE 'genereaza XML-ul de stornare' $ tcMessage
lnRaspuns = 1
CASE 'Trimiteti la ANAF' $ tcMessage
lnRaspuns = 6
OTHERWISE
lnRaspuns = IIF(TYPE('gnMockRaspuns') = 'N', gnMockRaspuns, 6)
ENDCASE
IF TYPE('gnAmsgCalls') = 'N'
gnAmsgCalls = gnAmsgCalls + 1
DIMENSION gaAmsgCalls[gnAmsgCalls, 2]
gaAmsgCalls[gnAmsgCalls, 1] = TRANSFORM(tcMessage)
gaAmsgCalls[gnAmsgCalls, 2] = lnRaspuns
ENDIF
IF TYPE('gcUILog') = 'C'
DO PrLogLocal WITH 'MOCK amessagebox: [' + LEFT(TRANSFORM(tcMessage), 100) + '] -> ' + TRANSFORM(lnRaspuns)
ENDIF
RETURN lnRaspuns
ENDFUNC

View File

@@ -0,0 +1,55 @@
* mock_anaf_server_storno.prg - MOCK pentru AnafeFacturaServer, STRICT pentru testul E2E
* storno eFactura (test_storno_e2e.prg). ZERO apeluri reale la ANAF: RefreshTokenAuto /
* TrimiteFacturaXML / SaveFile / Xml2PdfAnaf doar logheaza apelul in PUBLIC gaMockApeluri /
* gnMockApeluri (declarate de test INAINTE de a instantia acest mock) si intorc raspunsuri
* canonice, fara retea si fara disc (in afara de SaveFile, care doar logheaza).
DEFINE CLASS MockAnafServerStorno AS Custom
cCodFiscal = ''
lTest = .T.
cToken = 'MOCK-TOKEN-STORNO'
cRefreshToken = 'MOCK-REFRESH-STORNO'
dTokenGendate = {}
dTokenExpdate = {}
PROCEDURE RegMock
LPARAMETERS tcMetoda, tcP2, tcP3
gnMockApeluri = gnMockApeluri + 1
DIMENSION gaMockApeluri[gnMockApeluri, 3]
gaMockApeluri[gnMockApeluri, 1] = tcMetoda
gaMockApeluri[gnMockApeluri, 2] = TRANSFORM(tcP2)
gaMockApeluri[gnMockApeluri, 3] = TRANSFORM(tcP3)
IF TYPE('gcUILog') = 'C'
DO PrLogLocal WITH 'MOCK ' + tcMetoda + ' p2=[' + TRANSFORM(tcP2) + '] p3=[' + TRANSFORM(tcP3) + ']'
ENDIF
ENDPROC
PROCEDURE RefreshTokenAuto
This.RegMock('RefreshTokenAuto', '', '')
ENDPROC
PROCEDURE TrimiteFacturaXML
LPARAMETERS tcFile, tlValidare, tlValidareOnline, tlNuTrimiteEFacturaANAF, tlExtern, tlB2C
LOCAL loReturn
This.RegMock('TrimiteFacturaXML', tcFile, TRANSFORM(tlB2C))
loReturn = CREATEOBJECT('Empty')
ADDPROPERTY(loReturn, 'lSucces', .T.)
ADDPROPERTY(loReturn, 'cIdIncarcare', 'MOCK-ID-STORNO-12345')
ADDPROPERTY(loReturn, 'cMesaj', '')
ADDPROPERTY(loReturn, 'cResponse', '<mock ok/>')
ADDPROPERTY(loReturn, 'nStatus', 200)
ADDPROPERTY(loReturn, 'cFile', TRANSFORM(tcFile))
RETURN loReturn
ENDPROC
PROCEDURE SaveFile
LPARAMETERS tcFile, tlVariable, tcDirectory, tcFileName
This.RegMock('SaveFile', tcFile, TRANSFORM(tcDirectory) + '|' + TRANSFORM(tcFileName))
RETURN .T.
ENDPROC
PROCEDURE Xml2PdfAnaf
LPARAMETERS tcXml, tcFile, tlVariable
This.RegMock('Xml2PdfAnaf', tcFile, '')
RETURN tcFile
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1 @@
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"><cbc:ID>TEST-B2C-01</cbc:ID><cbc:IssueDate>2026-05-08</cbc:IssueDate><cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode><cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode><cac:AccountingSupplierParty><cac:Party><cac:PartyTaxScheme><cbc:CompanyID>RO99999901</cbc:CompanyID><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:PartyTaxScheme><cac:PartyLegalEntity><cbc:RegistrationName>FURNIZOR TEST SA</cbc:RegistrationName><cbc:CompanyID>J40/9999/2020</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingSupplierParty><cac:AccountingCustomerParty><cac:Party><cac:PartyLegalEntity><cbc:RegistrationName>PERSOANA FIZICA TEST</cbc:RegistrationName><cbc:CompanyID>1990101123456</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingCustomerParty><cac:TaxTotal><cbc:TaxAmount currencyID="RON">19.00</cbc:TaxAmount><cac:TaxSubtotal><cbc:TaxableAmount currencyID="RON">100.00</cbc:TaxableAmount><cbc:TaxAmount currencyID="RON">19.00</cbc:TaxAmount><cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory></cac:TaxSubtotal></cac:TaxTotal><cac:LegalMonetaryTotal><cbc:LineExtensionAmount currencyID="RON">100.00</cbc:LineExtensionAmount><cbc:TaxExclusiveAmount currencyID="RON">100.00</cbc:TaxExclusiveAmount><cbc:TaxInclusiveAmount currencyID="RON">119.00</cbc:TaxInclusiveAmount><cbc:PayableAmount currencyID="RON">119.00</cbc:PayableAmount></cac:LegalMonetaryTotal><cac:InvoiceLine><cbc:ID>1</cbc:ID><cbc:InvoicedQuantity unitCode="EA">1.0</cbc:InvoicedQuantity><cbc:LineExtensionAmount currencyID="RON">100.00</cbc:LineExtensionAmount><cac:Item><cbc:Name>TEST-B2C</cbc:Name><cac:ClassifiedTaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:ClassifiedTaxCategory></cac:Item><cac:Price><cbc:PriceAmount currencyID="RON">100.00</cbc:PriceAmount></cac:Price></cac:InvoiceLine></Invoice>

View File

@@ -0,0 +1 @@
<CreditNote xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"><cbc:ID>TEST-CN-01</cbc:ID><cbc:IssueDate>2026-05-02</cbc:IssueDate><cbc:CreditNoteTypeCode>381</cbc:CreditNoteTypeCode><cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode><cac:AccountingSupplierParty><cac:Party><cac:PartyTaxScheme><cbc:CompanyID>RO99999901</cbc:CompanyID><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:PartyTaxScheme><cac:PartyLegalEntity><cbc:RegistrationName>FURNIZOR TEST SA</cbc:RegistrationName><cbc:CompanyID>J40/9999/2020</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingSupplierParty><cac:AccountingCustomerParty><cac:Party><cac:PartyLegalEntity><cbc:RegistrationName>CLIENT TEST SRL</cbc:RegistrationName><cbc:CompanyID>J40/8888/1999</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingCustomerParty><cac:TaxTotal><cbc:TaxAmount currencyID="RON">9.50</cbc:TaxAmount><cac:TaxSubtotal><cbc:TaxableAmount currencyID="RON">50.00</cbc:TaxableAmount><cbc:TaxAmount currencyID="RON">9.50</cbc:TaxAmount><cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory></cac:TaxSubtotal></cac:TaxTotal><cac:LegalMonetaryTotal><cbc:LineExtensionAmount currencyID="RON">50.00</cbc:LineExtensionAmount><cbc:TaxExclusiveAmount currencyID="RON">50.00</cbc:TaxExclusiveAmount><cbc:TaxInclusiveAmount currencyID="RON">59.50</cbc:TaxInclusiveAmount><cbc:PayableAmount currencyID="RON">59.50</cbc:PayableAmount></cac:LegalMonetaryTotal><cac:CreditNoteLine><cbc:ID>1</cbc:ID><cbc:CreditedQuantity unitCode="EA">1.0</cbc:CreditedQuantity><cbc:LineExtensionAmount currencyID="RON">50.00</cbc:LineExtensionAmount><cac:Item><cbc:Name>TEST-CN</cbc:Name><cac:ClassifiedTaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:ClassifiedTaxCategory></cac:Item><cac:Price><cbc:PriceAmount currencyID="RON">50.00</cbc:PriceAmount></cac:Price></cac:CreditNoteLine></CreditNote>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"><cbc:ID>TEST-NEG-01</cbc:ID><cbc:IssueDate>2026-05-05</cbc:IssueDate><cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode><cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode><cac:AccountingSupplierParty><cac:Party><cac:PartyTaxScheme><cbc:CompanyID>RO99999901</cbc:CompanyID><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:PartyTaxScheme><cac:PartyLegalEntity><cbc:RegistrationName>FURNIZOR TEST SA</cbc:RegistrationName><cbc:CompanyID>J40/9999/2020</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingSupplierParty><cac:AccountingCustomerParty><cac:Party><cac:PartyLegalEntity><cbc:RegistrationName>CLIENT TEST SRL</cbc:RegistrationName><cbc:CompanyID>J40/8888/1999</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingCustomerParty><cac:TaxTotal><cbc:TaxAmount currencyID="RON">-19.00</cbc:TaxAmount><cac:TaxSubtotal><cbc:TaxableAmount currencyID="RON">-100.00</cbc:TaxableAmount><cbc:TaxAmount currencyID="RON">-19.00</cbc:TaxAmount><cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory></cac:TaxSubtotal></cac:TaxTotal><cac:LegalMonetaryTotal><cbc:LineExtensionAmount currencyID="RON">-100.00</cbc:LineExtensionAmount><cbc:TaxExclusiveAmount currencyID="RON">-100.00</cbc:TaxExclusiveAmount><cbc:TaxInclusiveAmount currencyID="RON">-119.00</cbc:TaxInclusiveAmount><cbc:PayableAmount currencyID="RON">-119.00</cbc:PayableAmount></cac:LegalMonetaryTotal><cac:InvoiceLine><cbc:ID>1</cbc:ID><cbc:InvoicedQuantity unitCode="EA">-1.0</cbc:InvoicedQuantity><cbc:LineExtensionAmount currencyID="RON">-100.00</cbc:LineExtensionAmount><cac:Item><cbc:Name>TEST-NEG</cbc:Name><cac:ClassifiedTaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:ClassifiedTaxCategory></cac:Item><cac:Price><cbc:PriceAmount currencyID="RON">100.00</cbc:PriceAmount></cac:Price></cac:InvoiceLine></Invoice>

View File

@@ -0,0 +1 @@
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"><cbc:ID>TEST-NOPTS-01</cbc:ID><cbc:IssueDate>2026-05-09</cbc:IssueDate><cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode><cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode><cac:AccountingSupplierParty><cac:Party><cac:PartyLegalEntity><cbc:RegistrationName>FURNIZOR NEPLATITOR TVA SRL</cbc:RegistrationName><cbc:CompanyID>RO99999903</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingSupplierParty><cac:AccountingCustomerParty><cac:Party><cac:PartyLegalEntity><cbc:RegistrationName>CLIENT TEST SRL</cbc:RegistrationName><cbc:CompanyID>J40/8888/1999</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingCustomerParty><cac:TaxTotal><cbc:TaxAmount currencyID="RON">0.00</cbc:TaxAmount><cac:TaxSubtotal><cbc:TaxableAmount currencyID="RON">100.00</cbc:TaxableAmount><cbc:TaxAmount currencyID="RON">0.00</cbc:TaxAmount><cac:TaxCategory><cbc:ID>O</cbc:ID><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory></cac:TaxSubtotal></cac:TaxTotal><cac:LegalMonetaryTotal><cbc:LineExtensionAmount currencyID="RON">100.00</cbc:LineExtensionAmount><cbc:TaxExclusiveAmount currencyID="RON">100.00</cbc:TaxExclusiveAmount><cbc:TaxInclusiveAmount currencyID="RON">100.00</cbc:TaxInclusiveAmount><cbc:PayableAmount currencyID="RON">100.00</cbc:PayableAmount></cac:LegalMonetaryTotal><cac:InvoiceLine><cbc:ID>1</cbc:ID><cbc:InvoicedQuantity unitCode="EA">1.0</cbc:InvoicedQuantity><cbc:LineExtensionAmount currencyID="RON">100.00</cbc:LineExtensionAmount><cac:Item><cbc:Name>TEST-NOPTS</cbc:Name><cac:ClassifiedTaxCategory><cbc:ID>O</cbc:ID><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:ClassifiedTaxCategory></cac:Item><cac:Price><cbc:PriceAmount currencyID="RON">100.00</cbc:PriceAmount></cac:Price></cac:InvoiceLine></Invoice>

View File

@@ -0,0 +1 @@
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"><cbc:ID>TEST-PT-01</cbc:ID><cbc:IssueDate>2026-05-07</cbc:IssueDate><cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode><cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode><cac:AccountingSupplierParty><cac:Party><cac:PartyTaxScheme><cbc:CompanyID>RO99999901</cbc:CompanyID><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:PartyTaxScheme><cac:PartyLegalEntity><cbc:RegistrationName>FURNIZOR TEST SA</cbc:RegistrationName><cbc:CompanyID>J40/9999/2020</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingSupplierParty><cac:AccountingCustomerParty><cac:Party><cac:PartyLegalEntity><cbc:RegistrationName>CLIENT TEST SRL</cbc:RegistrationName><cbc:CompanyID>J40/8888/1999</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingCustomerParty><cac:PaymentTerms><cbc:Note>30 zile</cbc:Note><cbc:Amount currencyID="RON">119.00</cbc:Amount></cac:PaymentTerms><cac:TaxTotal><cbc:TaxAmount currencyID="RON">19.00</cbc:TaxAmount><cac:TaxSubtotal><cbc:TaxableAmount currencyID="RON">100.00</cbc:TaxableAmount><cbc:TaxAmount currencyID="RON">19.00</cbc:TaxAmount><cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory></cac:TaxSubtotal></cac:TaxTotal><cac:LegalMonetaryTotal><cbc:LineExtensionAmount currencyID="RON">100.00</cbc:LineExtensionAmount><cbc:TaxExclusiveAmount currencyID="RON">100.00</cbc:TaxExclusiveAmount><cbc:TaxInclusiveAmount currencyID="RON">119.00</cbc:TaxInclusiveAmount><cbc:PayableAmount currencyID="RON">119.00</cbc:PayableAmount></cac:LegalMonetaryTotal><cac:InvoiceLine><cbc:ID>1</cbc:ID><cbc:InvoicedQuantity unitCode="EA">1.0</cbc:InvoicedQuantity><cbc:LineExtensionAmount currencyID="RON">100.00</cbc:LineExtensionAmount><cac:Item><cbc:Name>TEST-PT</cbc:Name><cac:ClassifiedTaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:ClassifiedTaxCategory></cac:Item><cac:Price><cbc:PriceAmount currencyID="RON">100.00</cbc:PriceAmount></cac:Price></cac:InvoiceLine></Invoice>

View File

@@ -0,0 +1 @@
<n3:Invoice xmlns:n3="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:n1="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:n2="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"><n1:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:efactura.mfinante.ro:CIUS-RO:1.0.1</n1:CustomizationID><n1:ID>TEST-N3-01</n1:ID><n1:IssueDate>2026-04-10</n1:IssueDate><n1:InvoiceTypeCode>380</n1:InvoiceTypeCode><n1:DocumentCurrencyCode>RON</n1:DocumentCurrencyCode><n2:AccountingSupplierParty><n2:Party><n2:PartyTaxScheme><n1:CompanyID>RO99999901</n1:CompanyID><n2:TaxScheme><n1:ID>VAT</n1:ID></n2:TaxScheme></n2:PartyTaxScheme><n2:PartyLegalEntity><n1:RegistrationName>FURNIZOR TEST SA</n1:RegistrationName><n1:CompanyID>J40/9999/2020</n1:CompanyID></n2:PartyLegalEntity></n2:Party></n2:AccountingSupplierParty><n2:AccountingCustomerParty><n2:Party><n2:PartyLegalEntity><n1:RegistrationName>CLIENT TEST SRL</n1:RegistrationName><n1:CompanyID>J40/8888/1999</n1:CompanyID></n2:PartyLegalEntity></n2:Party></n2:AccountingCustomerParty><n2:TaxTotal><n1:TaxAmount currencyID="RON">19.00</n1:TaxAmount><n2:TaxSubtotal><n1:TaxableAmount currencyID="RON">100.00</n1:TaxableAmount><n1:TaxAmount currencyID="RON">19.00</n1:TaxAmount><n2:TaxCategory><n1:ID>S</n1:ID><n1:Percent>19.0</n1:Percent><n2:TaxScheme><n1:ID>VAT</n1:ID></n2:TaxScheme></n2:TaxCategory></n2:TaxSubtotal></n2:TaxTotal><n2:LegalMonetaryTotal><n1:LineExtensionAmount currencyID="RON">100.00</n1:LineExtensionAmount><n1:TaxExclusiveAmount currencyID="RON">100.00</n1:TaxExclusiveAmount><n1:TaxInclusiveAmount currencyID="RON">119.00</n1:TaxInclusiveAmount><n1:PayableAmount currencyID="RON">119.00</n1:PayableAmount></n2:LegalMonetaryTotal><n2:InvoiceLine><n1:ID>1</n1:ID><n1:InvoicedQuantity unitCode="EA">1.0</n1:InvoicedQuantity><n1:LineExtensionAmount currencyID="RON">100.00</n1:LineExtensionAmount><n2:Item><n1:Name>TEST-N3</n1:Name><n2:ClassifiedTaxCategory><n1:ID>S</n1:ID><n1:Percent>19.0</n1:Percent><n2:TaxScheme><n1:ID>VAT</n1:ID></n2:TaxScheme></n2:ClassifiedTaxCategory></n2:Item><n2:Price><n1:PriceAmount currencyID="RON">100.00</n1:PriceAmount></n2:Price></n2:InvoiceLine></n3:Invoice>

View File

@@ -0,0 +1 @@
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"><cbc:ID>TEST-ZERO-01</cbc:ID><cbc:IssueDate>2026-05-06</cbc:IssueDate><cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode><cbc:DocumentCurrencyCode>RON</cbc:DocumentCurrencyCode><cac:AccountingSupplierParty><cac:Party><cac:PartyTaxScheme><cbc:CompanyID>RO99999901</cbc:CompanyID><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:PartyTaxScheme><cac:PartyLegalEntity><cbc:RegistrationName>FURNIZOR TEST SA</cbc:RegistrationName><cbc:CompanyID>J40/9999/2020</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingSupplierParty><cac:AccountingCustomerParty><cac:Party><cac:PartyLegalEntity><cbc:RegistrationName>CLIENT TEST SRL</cbc:RegistrationName><cbc:CompanyID>J40/8888/1999</cbc:CompanyID></cac:PartyLegalEntity></cac:Party></cac:AccountingCustomerParty><cac:AllowanceCharge><cbc:ChargeIndicator>false</cbc:ChargeIndicator><cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode><cbc:Amount currencyID="RON">-0.00</cbc:Amount><cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>19.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory></cac:AllowanceCharge><cac:TaxTotal><cbc:TaxAmount currencyID="RON">0.00</cbc:TaxAmount><cac:TaxSubtotal><cbc:TaxableAmount currencyID="RON">0.00</cbc:TaxableAmount><cbc:TaxAmount currencyID="RON">0.00</cbc:TaxAmount><cac:TaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>0.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:TaxCategory></cac:TaxSubtotal></cac:TaxTotal><cac:LegalMonetaryTotal><cbc:LineExtensionAmount currencyID="RON">0.00</cbc:LineExtensionAmount><cbc:TaxExclusiveAmount currencyID="RON">0.00</cbc:TaxExclusiveAmount><cbc:TaxInclusiveAmount currencyID="RON">0.00</cbc:TaxInclusiveAmount><cbc:AllowanceTotalAmount currencyID="RON">-0.00</cbc:AllowanceTotalAmount><cbc:PayableAmount currencyID="RON">0.00</cbc:PayableAmount></cac:LegalMonetaryTotal><cac:InvoiceLine><cbc:ID>1</cbc:ID><cbc:InvoicedQuantity unitCode="EA">0.0</cbc:InvoicedQuantity><cbc:LineExtensionAmount currencyID="RON">0.00</cbc:LineExtensionAmount><cac:Item><cbc:Name>TEST-ZERO</cbc:Name><cac:ClassifiedTaxCategory><cbc:ID>S</cbc:ID><cbc:Percent>0.0</cbc:Percent><cac:TaxScheme><cbc:ID>VAT</cbc:ID></cac:TaxScheme></cac:ClassifiedTaxCategory></cac:Item><cac:Price><cbc:PriceAmount currencyID="RON">0.00</cbc:PriceAmount></cac:Price></cac:InvoiceLine></Invoice>

View File

@@ -0,0 +1,227 @@
* test4_storno_efactura_anaf_test.prg
* Test 4 (docs\plan_storno_efactura.md): upload real pe ANAF TEST al unui storno + reincarcarea
* facturii corecte cu acelasi numar ca originalul. Sursa: MARIUSM_AUTO.anaf_efactura (test=1).
* Maxim 4 incarcari (aprobat); interzisa orice trimitere spre /prod/.
* Validarea online (ValidareEFacturaANAF) e SARITA intentionat: xmlefactura.prg:1275,1278
* construieste URL-ul hardcodat pe /prod/, indiferent de context (fara proprietate lTest pe
* ExportEFactura) - decizie aprobata, ANAF valideaza oricum la upload.
*
* Rulare: vfp9.exe -A -T "D:\ROA\ROACONT\COMUN\utile\Teste\storno\test4_storno_efactura_anaf_test.prg"
* Iesire: test4_storno_efactura_anaf_test_log.txt (acelasi folder)
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, gcOutDir
gcOutDir = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\out\"
IF !DIRECTORY(gcOutDir)
MD (gcOutDir)
ENDIF
gcUILog = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\test4_storno_efactura_anaf_test_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog)
ON ERROR DO PrErrLocal WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
PUBLIC lnUploads
lnUploads = 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)
IF !('nfjsonread' $ LOWER(SET("Procedure")))
SET PROCEDURE TO 'D:\ROA\ROACONT\COMUN\utile\nfjson\nfjsonread.prg' ADDITIVE
ENDIF
*=========================================================================
DO PrLogLocal WITH '=== PAS 1: selectie sursa (MARIUSM_AUTO.anaf_efactura, test=1, factura_emisa=1, FACTURA TRIMISA) ==='
LOCAL lcSql, lnIdSursa, lcIdIncarcareSursa
lnIdSursa = 0
lcSql = "select id, id_incarcare from anaf_efactura"
lcSql = lcSql + " where factura_emisa=1 and test=1 and tip_mesaj_raspuns='FACTURA TRIMISA'"
lcSql = lcSql + " and detalii_zip is not null order by id desc"
IF !goExecutor.oExecuta(lcSql, "cSursa")
DO PrLogLocal WITH 'FAIL: select sursa: ' + ALLTRIM(NVL(goExecutor.cEroare,''))
QUIT
ENDIF
IF RECCOUNT('cSursa') = 0
DO PrLogLocal WITH 'FAIL: nicio sursa disponibila in MARIUSM_AUTO (factura_emisa=1, test=1, FACTURA TRIMISA, cu detalii_zip)'
QUIT
ENDIF
SELECT cSursa
GO TOP
lnIdSursa = id
lcIdIncarcareSursa = ALLTRIM(NVL(id_incarcare, ''))
USE IN (SELECT('cSursa'))
DO PrLogLocal WITH 'sursa aleasa: id=' + TRANSFORM(lnIdSursa) + ' id_incarcare_original=' + lcIdIncarcareSursa
*=========================================================================
DO PrLogLocal WITH '=== PAS 2: GetXmlOriginalEFactura + StornoEFacturaXML ==='
LOCAL lcXmlOriginal, lcMsgGet, llRetGet
llRetGet = GetXmlOriginalEFactura(lnIdSursa, @lcXmlOriginal, @lcMsgGet)
IF !llRetGet
DO PrLogLocal WITH 'FAIL: GetXmlOriginalEFactura: ' + lcMsgGet
QUIT
ENDIF
DO PrLogLocal WITH 'GetXmlOriginalEFactura OK, len=' + TRANSFORM(LEN(lcXmlOriginal))
LOCAL lcFileOriginal, lcFileStorno, lcMsgStorno, llRetStorno
LOCAL laMod[1,4]
lcFileOriginal = gcOutDir + 'test4_original_' + TRANSFORM(lnIdSursa) + '.xml'
lcFileStorno = gcOutDir + 'test4_storno_' + TRANSFORM(lnIdSursa) + '.xml'
STRTOFILE(lcXmlOriginal, lcFileOriginal)
llRetStorno = StornoEFacturaXML(lcXmlOriginal, '', 'Stornare factura test 4 ANAF TEST', lcFileStorno, @laMod, @lcMsgStorno)
IF !llRetStorno
DO PrLogLocal WITH 'FAIL: StornoEFacturaXML: ' + lcMsgStorno
QUIT
ENDIF
DO PrLogLocal WITH 'StornoEFacturaXML OK, fisier=' + lcFileStorno
*=========================================================================
DO PrLogLocal WITH '=== PAS 3: pregatire AnafeFacturaServer pe TEST (token + CIF), garda /test/ ==='
LOCAL loAnaf As 'AnafeFacturaServer'
loAnaf = CREATEOBJECT('AnafeFacturaServer', .F., '', gcS, '')
loAnaf.lTest = .T.
loAnaf.RefreshTokenAuto()
DO PrLogLocal WITH 'CIF=' + loAnaf.cCodFiscal + ' lTest=' + TRANSFORM(loAnaf.lTest) + ' tokenExp=' + DTOC(loAnaf.dTokenExpdate) + ' tokenGol=' + TRANSFORM(EMPTY(loAnaf.cToken))
* garda: nicio trimitere daca lTest nu e .T., tokenul e gol sau expirat - fara presupuneri
IF !loAnaf.lTest
DO PrLogLocal WITH 'BLOCAT: lTest nu e .T. - opresc, fara nicio trimitere'
QUIT
ENDIF
IF EMPTY(loAnaf.cToken)
DO PrLogLocal WITH 'BLOCAT: token gol - opresc, fara nicio trimitere'
QUIT
ENDIF
IF loAnaf.dTokenExpdate <= DATE()
DO PrLogLocal WITH 'BLOCAT: token expirat (' + DTOC(loAnaf.dTokenExpdate) + ') - opresc, fara nicio trimitere'
QUIT
ENDIF
*=========================================================================
DO PrLogLocal WITH '=== PAS 4: upload 1/2 - storno pe TEST ==='
LOCAL loRetStorno
IF !loAnaf.lTest
DO PrLogLocal WITH 'BLOCAT (garda finala): lTest nu mai e .T. inainte de upload storno'
QUIT
ENDIF
loRetStorno = loAnaf.TrimiteFacturaXML(lcFileStorno, .F., .F., .F., .F., .F.)
lnUploads = lnUploads + 1
DO PrLogLocal WITH 'upload storno: lSucces=' + TRANSFORM(loRetStorno.lSucces) + ' status=' + TRANSFORM(loRetStorno.nStatus) + ' idIncarcare=' + ALLTRIM(NVL(loRetStorno.cIdIncarcare,'')) + ' mesaj=[' + ALLTRIM(NVL(loRetStorno.cMesaj,'')) + ']'
DO PrLogLocal WITH 'raspuns brut storno: ' + ALLTRIM(NVL(loRetStorno.cResponse,''))
*=========================================================================
DO PrLogLocal WITH '=== PAS 5: upload 2/2 - reincarcare XML original (acelasi numar) pe TEST ==='
LOCAL loRetReincarcare
IF !loAnaf.lTest
DO PrLogLocal WITH 'BLOCAT (garda finala): lTest nu mai e .T. inainte de reincarcare'
QUIT
ENDIF
loRetReincarcare = loAnaf.TrimiteFacturaXML(lcFileOriginal, .F., .F., .F., .F., .F.)
lnUploads = lnUploads + 1
DO PrLogLocal WITH 'upload reincarcare: lSucces=' + TRANSFORM(loRetReincarcare.lSucces) + ' status=' + TRANSFORM(loRetReincarcare.nStatus) + ' idIncarcare=' + ALLTRIM(NVL(loRetReincarcare.cIdIncarcare,'')) + ' mesaj=[' + ALLTRIM(NVL(loRetReincarcare.cMesaj,'')) + ']'
DO PrLogLocal WITH 'raspuns brut reincarcare: ' + ALLTRIM(NVL(loRetReincarcare.cResponse,''))
DO PrLogLocal WITH '=== PAS 6: storno CreditNote - NEEXECUTAT: nicio sursa CreditNote emisa in MARIUSM_AUTO.anaf_efactura (test=1) ==='
DO PrLogLocal WITH '=== PAS 7: storno B2C - NEEXECUTAT: nicio sursa cu CNP 13 cifre in MARIUSM_AUTO.anaf_efactura (test=1) ==='
*=========================================================================
DO PrLogLocal WITH '=== PAS 8: verificare stare incarcari (stareMesaj, /test/) ==='
IF !EMPTY(ALLTRIM(NVL(loRetStorno.cIdIncarcare,'')))
DO VerificaStare WITH loAnaf, ALLTRIM(loRetStorno.cIdIncarcare), 'storno'
ELSE
DO PrLogLocal WITH 'storno: fara id_incarcare, nu se poate verifica starea (vezi mesajul de upload de mai sus)'
ENDIF
IF !EMPTY(ALLTRIM(NVL(loRetReincarcare.cIdIncarcare,'')))
DO VerificaStare WITH loAnaf, ALLTRIM(loRetReincarcare.cIdIncarcare), 'reincarcare'
ELSE
DO PrLogLocal WITH 'reincarcare: fara id_incarcare, nu se poate verifica starea (vezi mesajul de upload de mai sus)'
ENDIF
DO PrLogLocal WITH 'TOTAL incarcari efectuate: ' + TRANSFORM(lnUploads) + ' (limita aprobata: 4)'
DO PrLogLocal WITH 'TOTAL: test terminat fara exceptie'
CATCH TO loEx
DO PrLogLocal WITH 'EXCEPTIE: ' + loEx.Message + ' (' + TRANSFORM(loEx.LineNo) + ') ' + loEx.Procedure
ENDTRY
QUIT
**********************************************************
* interogheaza stareMesaj pe /test/ pentru un id_incarcare, cu reincercari, fara sa scrie nimic
PROCEDURE VerificaStare
LPARAMETERS toAnaf, tcIdIncarcare, tcLabel
LOCAL loHTTP, lcServer, lnStatus, lcResponse, lnIncercare, llGata, loJson, lcStare
LOCAL loEx As Exception
llGata = .F.
FOR lnIncercare = 1 TO 5
lcServer = 'https://api.anaf.ro/test/FCTEL/rest/stareMesaj?id_incarcare=' + tcIdIncarcare
TRY
loHTTP = CREATEOBJECT('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('GET', lcServer, .F.)
loHTTP.setRequestHeader('Authorization', 'Bearer ' + toAnaf.cToken)
loHTTP.Send()
lnStatus = loHTTP.Status
lcResponse = loHTTP.ResponseText
CATCH TO loEx
lnStatus = 0
lcResponse = '<errorMessage="' + loEx.Message + '">'
ENDTRY
DO PrLogLocal WITH '[' + tcLabel + '] stareMesaj incercare ' + TRANSFORM(lnIncercare) + '/5 id_incarcare=' + tcIdIncarcare + ' status=' + TRANSFORM(lnStatus) + ' raspuns=' + lcResponse
lcStare = ''
TRY
loJson = nfjsonread(lcResponse)
IF TYPE('loJson.stare') = 'C'
lcStare = LOWER(ALLTRIM(loJson.stare))
ENDIF
CATCH
lcStare = ''
ENDTRY
IF INLIST(lcStare, 'ok', 'nok')
llGata = .T.
DO PrLogLocal WITH '[' + tcLabel + '] stare finala ANAF: ' + lcStare
EXIT
ENDIF
IF lnIncercare < 5
INKEY(20, 'H')
ENDIF
ENDFOR
IF !llGata
DO PrLogLocal WITH '[' + tcLabel + '] stare neconcludenta dupa 5 incercari (posibil inca in prelucrare la ANAF) - vezi ultimul raspuns de mai sus'
ENDIF
ENDPROC
**********************************************************
PROCEDURE PrLogLocal
LPARAMETERS tcMsg
LOCAL lcL
SET SAFETY OFF
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + TTOC(DATETIME()) + ' ' + 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

View File

@@ -0,0 +1,143 @@
* test4b_retry_storno_si_poll.prg
* Continuare test4 (docs\plan_storno_efactura.md): PAS 4 (upload storno) a esuat cu eroare
* tehnica ANAF (Cod: 1814, fara id_incarcare) la prima incercare - reincercare (upload 3/4
* aprobate) + continuare poll stareMesaj pe /test/ pentru storno (nou) si reincarcare
* (id_incarcare=5036305973, "in prelucrare" la ultima verificare).
* Refoloseste fisierul deja generat: out\test4_storno_1127.xml (nu regenereaza StornoEFacturaXML).
*
* Rulare: vfp9.exe -A -T "D:\ROA\ROACONT\COMUN\utile\Teste\storno\test4b_retry_storno_si_poll.prg"
* Iesire: test4b_retry_storno_si_poll_log.txt (acelasi folder)
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, gcOutDir
gcOutDir = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\out\"
gcUILog = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\test4b_retry_storno_si_poll_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog)
ON ERROR DO PrErrLocal WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
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)
IF !('nfjsonread' $ LOWER(SET("Procedure")))
SET PROCEDURE TO 'D:\ROA\ROACONT\COMUN\utile\nfjson\nfjsonread.prg' ADDITIVE
ENDIF
LOCAL lcFileStorno
lcFileStorno = gcOutDir + 'test4_storno_1127.xml'
IF !FILE(lcFileStorno)
DO PrLogLocal WITH 'FAIL: nu exista fisierul storno de la rularea anterioara: ' + lcFileStorno
QUIT
ENDIF
LOCAL loAnaf As 'AnafeFacturaServer'
loAnaf = CREATEOBJECT('AnafeFacturaServer', .F., '', gcS, '')
loAnaf.lTest = .T.
loAnaf.RefreshTokenAuto()
DO PrLogLocal WITH 'CIF=' + loAnaf.cCodFiscal + ' lTest=' + TRANSFORM(loAnaf.lTest) + ' tokenExp=' + DTOC(loAnaf.dTokenExpdate) + ' tokenGol=' + TRANSFORM(EMPTY(loAnaf.cToken))
IF !loAnaf.lTest OR EMPTY(loAnaf.cToken) OR loAnaf.dTokenExpdate <= DATE()
DO PrLogLocal WITH 'BLOCAT: garda lTest/token nu trece - opresc, fara nicio trimitere'
QUIT
ENDIF
DO PrLogLocal WITH '=== PAS 4 (reincercare, upload 3/4 aprobate): storno pe TEST ==='
LOCAL loRetStorno
loRetStorno = loAnaf.TrimiteFacturaXML(lcFileStorno, .F., .F., .F., .F., .F.)
DO PrLogLocal WITH 'upload storno (reincercare): lSucces=' + TRANSFORM(loRetStorno.lSucces) + ' status=' + TRANSFORM(loRetStorno.nStatus) + ' idIncarcare=' + ALLTRIM(NVL(loRetStorno.cIdIncarcare,'')) + ' mesaj=[' + ALLTRIM(NVL(loRetStorno.cMesaj,'')) + ']'
DO PrLogLocal WITH 'raspuns brut storno (reincercare): ' + ALLTRIM(NVL(loRetStorno.cResponse,''))
IF !EMPTY(ALLTRIM(NVL(loRetStorno.cIdIncarcare,'')))
DO VerificaStare WITH loAnaf, ALLTRIM(loRetStorno.cIdIncarcare), 'storno-reincercare'
ELSE
DO PrLogLocal WITH 'storno-reincercare: fara id_incarcare, nu se poate verifica starea'
ENDIF
DO PrLogLocal WITH '=== continuare poll reincarcare (id_incarcare=5036305973, era "in prelucrare") ==='
DO VerificaStare WITH loAnaf, '5036305973', 'reincarcare'
DO PrLogLocal WITH 'TOTAL: test terminat fara exceptie'
CATCH TO loEx
DO PrLogLocal WITH 'EXCEPTIE: ' + loEx.Message + ' (' + TRANSFORM(loEx.LineNo) + ') ' + loEx.Procedure
ENDTRY
QUIT
**********************************************************
PROCEDURE VerificaStare
LPARAMETERS toAnaf, tcIdIncarcare, tcLabel
LOCAL loHTTP, lcServer, lnStatus, lcResponse, lnIncercare, llGata, loJson, lcStare
LOCAL loEx As Exception
llGata = .F.
FOR lnIncercare = 1 TO 6
lcServer = 'https://api.anaf.ro/test/FCTEL/rest/stareMesaj?id_incarcare=' + tcIdIncarcare
TRY
loHTTP = CREATEOBJECT('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('GET', lcServer, .F.)
loHTTP.setRequestHeader('Authorization', 'Bearer ' + toAnaf.cToken)
loHTTP.Send()
lnStatus = loHTTP.Status
lcResponse = loHTTP.ResponseText
CATCH TO loEx
lnStatus = 0
lcResponse = '<errorMessage="' + loEx.Message + '">'
ENDTRY
DO PrLogLocal WITH '[' + tcLabel + '] stareMesaj incercare ' + TRANSFORM(lnIncercare) + '/6 id_incarcare=' + tcIdIncarcare + ' status=' + TRANSFORM(lnStatus) + ' raspuns=' + lcResponse
lcStare = ''
TRY
loJson = nfjsonread(lcResponse)
IF TYPE('loJson.stare') = 'C'
lcStare = LOWER(ALLTRIM(loJson.stare))
ENDIF
CATCH
lcStare = ''
ENDTRY
IF INLIST(lcStare, 'ok', 'nok')
llGata = .T.
DO PrLogLocal WITH '[' + tcLabel + '] stare finala ANAF: ' + lcStare
EXIT
ENDIF
IF lnIncercare < 6
INKEY(25, 'H')
ENDIF
ENDFOR
IF !llGata
DO PrLogLocal WITH '[' + tcLabel + '] stare neconcludenta dupa 6 incercari (posibil inca in prelucrare la ANAF) - vezi ultimul raspuns de mai sus'
ENDIF
ENDPROC
**********************************************************
PROCEDURE PrLogLocal
LPARAMETERS tcMsg
LOCAL lcL
SET SAFETY OFF
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + TTOC(DATETIME()) + ' ' + 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

View File

@@ -0,0 +1,109 @@
* test4c_descarcare_raspuns.prg
* Continuare test4: descarca raspunsul ANAF (nok) pentru reincarcarea originalului cu acelasi
* numar (id_descarcare=3059138503), ca sa se vada mesajul exact de respingere. Doar GET/descarcare
* si dezarhivare locala - nu scrie nimic in Oracle, nu conteaza ca incarcare.
*
* Rulare: vfp9.exe -A -T "D:\ROA\ROACONT\COMUN\utile\Teste\storno\test4c_descarcare_raspuns.prg"
SET SAFETY OFF
SET TALK OFF
CLOSE DATABASES
PUBLIC gcUILog, gcOutDir
gcOutDir = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\out\"
gcUILog = "D:\ROA\ROACONT\COMUN\utile\Teste\storno\test4c_descarcare_raspuns_log.txt"
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog)
ON ERROR DO PrErrLocal WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
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'
QUIT
ENDIF
LOCAL loAnaf As 'AnafeFacturaServer'
loAnaf = CREATEOBJECT('AnafeFacturaServer', .F., '', gcS, '')
loAnaf.lTest = .T.
loAnaf.RefreshTokenAuto()
IF !loAnaf.lTest OR EMPTY(loAnaf.cToken)
DO PrLogLocal WITH 'BLOCAT: garda lTest/token nu trece'
QUIT
ENDIF
DO DescarcaSiLogheaza WITH loAnaf, '3059138503', 'reincarcare-nok'
DO DescarcaSiLogheaza WITH loAnaf, '3059138527', 'storno-reincercare-ok'
DO PrLogLocal WITH 'TOTAL: test terminat fara exceptie'
CATCH TO loEx
DO PrLogLocal WITH 'EXCEPTIE: ' + loEx.Message + ' (' + TRANSFORM(loEx.LineNo) + ') ' + loEx.Procedure
ENDTRY
QUIT
**********************************************************
PROCEDURE DescarcaSiLogheaza
LPARAMETERS toAnaf, tcIdDescarcare, tcLabel
LOCAL loHTTP, lcServer, lnStatus, lcZip, lcDir, lcMesaj, llSucces
LOCAL loEx As Exception
lcServer = 'https://api.anaf.ro/test/FCTEL/rest/descarcare?id=' + tcIdDescarcare
TRY
loHTTP = CREATEOBJECT('winHTTP.winHTTPrequest.5.1')
loHTTP.Open('GET', lcServer, .F.)
loHTTP.setRequestHeader('Authorization', 'Bearer ' + toAnaf.cToken)
loHTTP.Send()
lnStatus = loHTTP.Status
CATCH TO loEx
DO PrLogLocal WITH '[' + tcLabel + '] descarcare eroare: ' + loEx.Message
RETURN
ENDTRY
DO PrLogLocal WITH '[' + tcLabel + '] descarcare id=' + tcIdDescarcare + ' status=' + TRANSFORM(lnStatus) + ' content-type=' + loHTTP.getResponseHeader('Content-Type')
IF lnStatus <> 200
DO PrLogLocal WITH '[' + tcLabel + '] raspuns brut (non-200): ' + loHTTP.ResponseText
RETURN
ENDIF
lcZip = gcOutDir + 'test4_descarcare_' + tcIdDescarcare + '.zip'
STRTOFILE(loHTTP.ResponseBody, lcZip)
lcDir = ''
lcMesaj = ''
llSucces = MyUnzip(lcZip, @lcDir, @lcMesaj, .T.)
IF !llSucces
DO PrLogLocal WITH '[' + tcLabel + '] MyUnzip esuat: ' + lcMesaj + ' (zip pastrat: ' + lcZip + ')'
RETURN
ENDIF
DO PrLogLocal WITH '[' + tcLabel + '] dezarhivat in ' + lcDir
LOCAL lcFisier, laFisiere[1], lnI, lnFisiere
lnFisiere = ADIR(laFisiere, ADDBS(lcDir) + '*.*')
FOR lnI = 1 TO lnFisiere
lcFisier = ADDBS(lcDir) + laFisiere[lnI, 1]
DO PrLogLocal WITH '[' + tcLabel + '] fisier: ' + laFisiere[lnI,1] + ' (' + TRANSFORM(laFisiere[lnI,2]) + ' octeti)'
IF LOWER(JUSTEXT(lcFisier)) = 'xml'
DO PrLogLocal WITH '[' + tcLabel + '] continut: ' + FILETOSTR(lcFisier)
ENDIF
ENDFOR
ENDPROC
**********************************************************
PROCEDURE PrLogLocal
LPARAMETERS tcMsg
LOCAL lcL
SET SAFETY OFF
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + TTOC(DATETIME()) + ' ' + 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

View File

@@ -0,0 +1,411 @@
* test_storno_e2e.prg
* Test E2E HEADLESS pentru "Generare XML storno si trimitere la ANAF" din borderoul eFactura:
* exerseaza codul REAL din anaf_efactura.vcx (metoda do_storno_efactura + clasa
* frm_storno_efactura), nu copii ale lui. Vezi docs\handoff_storno_efactura.md.
*
* Ruleaza direct pe binarul real din proiect (COMUN\CLASE\anaf_efactura.vcx, cu write-back):
* vfp9.exe -A -T "...\test_storno_e2e.prg"
*
* ZERO trimiteri ANAF: Thisform.oAnaf.AnafeFacturaServer e inlocuit cu MockAnafServerStorno
* (mock_anaf_server_storno.prg) imediat dupa ce forma reala citeste cCodFiscal/lTest de la
* serverul real. cmdValideaza (ValidareEFacturaANAF, apel HTTP real, hardcodat /prod/ -
* xmlefactura.prg:1275,1278) NU e apelat; se ocoleste cu SetStare(1) direct.
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, gcTestDir, gcTesteDir
PUBLIC gnPass, gnFail, gnMockRaspuns, gnAmsgCalls, gnMockApeluri
PUBLIC loAnaf, loForm, loMockSrv, loStornoForm, lnLastErrorNo, lcLastErrorMsg
DECLARE gaAmsgCalls[1,2]
DECLARE gaMockApeluri[1,3]
gnPass = 0
gnFail = 0
gnAmsgCalls = 0
gnMockApeluri = 0
gnMockRaspuns = 6
lnLastErrorNo = 0
lcLastErrorMsg = ''
gcTestDir = ADDBS(JUSTPATH(SYS(16)))
gcTesteDir = ADDBS(JUSTPATH(JUSTPATH(SYS(16))))
gcUILog = gcTestDir + 'test_storno_e2e_log_real.txt'
STRTOFILE('START ' + TTOC(DATETIME()) + CHR(13) + CHR(10), gcUILog)
ON ERROR DO PrErrLocal WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
ON SHUTDOWN QUIT
* mock-urile INAINTEA test_init_env_auto: la nume duplicat de procedura castiga fisierul
* cautat PRIMUL (vezi mock_amessagebox.prg / capcana testare-ui-vfp.md)
SET PROCEDURE TO (gcTestDir + 'mock_amessagebox_storno.prg') ADDITIVE
SET PROCEDURE TO (gcTestDir + 'mock_anaf_server_storno.prg') ADDITIVE
TRY
DO (gcTesteDir + '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) + ' gcS=' + gcS
* gnId_Prg_Owner: setat de roacont.prg la pornirea reala a aplicatiei (=0). test_init_env_auto.prg
* NU il seteaza pentru ROACONT - do_storno_efactura il foloseste direct (is_luna_blocata),
* fara TYPE()-check => "variable not found" daca lipseste (capcana de mediu, nu bug de aplicatie).
PUBLIC gnId_Prg_Owner
gnId_Prg_Owner = 0
* gnEFACTURA_*/gcEFACTURA_*: memvari globale create dinamic de optiuni_firma() (oinit_optiuni.prg,
* apelata din ocomenzi.vc2:6675 la login real) din tabela de optiuni (v_optiuni, macro-substitutie
* PUBLIC gn&lcvarname.). test_init_env_auto.prg:290 apeleaza ACELASI loader - nu setez manual,
* doar diagnostichez ce a produs, pentru cele 11 legate de controale in pgfeFactura.Page4
* (vc2:4952-5201).
LOCAL i, laEFVars[11], lcEFDiag
laEFVars[1] = 'gnEFACTURA_ZIP_DATABASE'
laEFVars[2] = 'gnEFACTURA_SAVE'
laEFVars[3] = 'gnEFACTURA_SAVE_ANAF_PDF'
laEFVars[4] = 'gnEFACTURA_VALIDARE_ONLINE'
laEFVars[5] = 'gcEFACTURA_NETWORK_PATH'
laEFVars[6] = 'gcEFACTURA_RESPONSESPATH'
laEFVars[7] = 'gcEFACTURA_SAVE_CLIENTI_FILE'
laEFVars[8] = 'gcEFACTURA_SAVE_CLIENTI_PATH'
laEFVars[9] = 'gcEFACTURA_SAVE_FURNIZORI_FILE'
laEFVars[10] = 'gcEFACTURA_SAVE_FURNIZORI_PATH'
laEFVars[11] = 'gcEFACTURA_SERVER_PATH'
FOR i = 1 TO 11
lcEFDiag = laEFVars[i] + '=TYPE[' + TYPE(laEFVars[i]) + ']'
IF TYPE(laEFVars[i]) != 'U'
lcEFDiag = lcEFDiag + ' val=[' + TRANSFORM(EVALUATE(laEFVars[i])) + ']'
ENDIF
DO PrLogLocal WITH lcEFDiag
ENDFOR
*=========================================================================
DO PrLogLocal WITH '=== PAS 0: sursa reala MARIUSM_AUTO.anaf_vefactura_trimis id=1127 (FACTURA TRIMISA) ==='
LOCAL lnIdSursa, lnTestSursa, ldDataSursa, llLunaBlocataDiag
lnIdSursa = 0
* numar_act/data_act nu exista pe tabela anaf_efactura (are xnumar_act/xdata_act) - doar pe
* view-ul anaf_vefactura_trimis (verificat cu DESC pe MARIUSM_AUTO@ROA_CENTRAL).
IF !goExecutor.oExecuta("select id, numar_act, data_act, test, tip_mesaj_raspuns from anaf_vefactura_trimis where id = 1127", "cSursa")
DO PrLogLocal WITH 'FAIL: select sursa id=1127: ' + ALLTRIM(NVL(goExecutor.cEroare,''))
QUIT
ENDIF
IF RECCOUNT('cSursa') = 0
DO PrLogLocal WITH 'FAIL: id=1127 nu exista in MARIUSM_AUTO.anaf_vefactura_trimis'
QUIT
ENDIF
SELECT cSursa
lnIdSursa = id
lnTestSursa = NVL(test, 0)
ldDataSursa = data_act
DO PrLogLocal WITH 'sursa: id=' + TRANSFORM(lnIdSursa) + ' numar=[' + ALLTRIM(NVL(numar_act, '')) + '] data=' + DTOC(ldDataSursa) + ' test=' + TRANSFORM(lnTestSursa) + ' tip_mesaj=' + ALLTRIM(NVL(tip_mesaj_raspuns, ''))
USE IN (SELECT('cSursa'))
llLunaBlocataDiag = IS_LUNA_BLOCATA(gcS, gnId_Prg_Owner, YEAR(ldDataSursa), MONTH(ldDataSursa))
DO PrLogLocal WITH 'diagnostic is_luna_blocata(' + TRANSFORM(YEAR(ldDataSursa)) + '/' + TRANSFORM(MONTH(ldDataSursa)) + ')=' + TRANSFORM(llLunaBlocataDiag) + ' (informativ - daca e .T., formularul de storno nu va aparea deloc)'
*=========================================================================
DO PrLogLocal WITH '=== PAS 1: cursoarele borderoului (copie fluxul real ANAFeFactura.vizeFactura, anaf_efactura.prg:2867+) ==='
PUBLIC poFacturiEmise, poFacturiPrimite, poFacturiTrimise, poFacturiDetalii
LOCAL lcData1, lcSchema, lcSelect, lcFiltru, lcFiltruOriginal, lcOrder, lcgroup, llModParam, llAfiseaza
lcData1 = '01' + PADL(INT(gnLuna), 2, '0') + ALLTRIM(STR(gnAn))
* FACTURI PRIMITE (goale - nu sunt necesare pentru storno, dar cursorul trebuie sa existe:
* lipsa lui a lasat formularul cu controale incomplete intr-o sesiune anterioara - vezi
* testare-ui-vfp.md, capcana j)
TEXT TO lcSchema NOSHOW
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), id_incarcare C(36), id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
ENDTEXT
TEXT TO lcSelect NOSHOW
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-NVL(jtotctva, 0.00) as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_primit
ENDTEXT
lcOrder = [data_act,numar_act,data_raspuns]
lcgroup = []
lcFiltru = [1=2]
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poFacturiPrimite', 'crsFacturiPrimite', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiPrimite.ca_baza1.afisare()
SELECT crsFacturiPrimite
GO TOP
* FACTURI TRIMISE - filtru tintit pe sursa reala (id=1127), nu pe luna curenta
TEXT TO lcSchema NOSHOW
ales N(1), id N(20), id_fact N(20), data_act D, data_scad D, numar_act C(30), xfurnizor C(200), xclient C(200), id_incarcare C(36), id_descarcare c(36) null, mesaj_trimis C(250) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, trimis N(1) null, data_trimis T null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, total_fara_tva N(16,4), total_tva N(16,4), total_tva_ron N(16,4), total_cu_tva N(16,4), discount_fara_tva N(16,4), taxe_fara_tva N(16,4), valoare_fara_tva N(16,4), total_de_plata N(16,4), nume_valuta C(5), test N(1) null, jtotctva N(16,4), descriere M null, detalii_plata M null, diferenta N(16,4), procesat N(1), tip_persoana N(1) null, descarcat N(1) null, filepath c(250) null, procesat_server N(1) null, creditnote N(1)
ENDTEXT
TEXT TO lcSelect NOSHOW
SELECT 0 as ales, id, id_fact, data_act, data_scad, numar_act, xfurnizor, xclient, id_incarcare, id_descarcare, mesaj_trimis, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, NVL(trimis,0) as trimis, data_trimis, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, total_fara_tva, total_tva, total_tva_ron, total_cu_tva, discount_fara_tva, taxe_fara_tva, valoare_fara_tva, total_de_plata, nume_valuta, test, jtotctva, descriere, detalii_plata, decode(creditnote,0,1,-1) * NVL(total_cu_tva, 0.00)-NVL(jtotctva, 0.00) as diferenta, procesat, tip_persoana, descarcat, filepath, procesat_server, creditnote FROM anaf_vefactura_trimis
ENDTEXT
lcOrder = [data_act,numar_act,data_trimis,data_raspuns]
lcgroup = []
lcFiltru = [id = 1127]
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poFacturiTrimise', 'crsFacturiTrimise', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiTrimise.ca_baza1.afisare()
SELECT crsFacturiTrimise
GO TOP
DO TVerdict WITH RECCOUNT('crsFacturiTrimise') = 1 AND NVL(crsFacturiTrimise.Id, 0) = lnIdSursa, 'PRECONDITIE crsFacturiTrimise populat cu id=1127 (flux real gencursor)', 'reccount=' + TRANSFORM(RECCOUNT('crsFacturiTrimise')) + ' id curent=' + TRANSFORM(NVL(crsFacturiTrimise.Id, 0))
* FACTURI EMISE (goale)
TEXT TO lcSchema NOSHOW
ales N(1), id N(20), id_fact N(20), id_vanzare N(10), data_act D, numar_act N(14), in_valuta N(1) null, curs N(10,4) null, valval N(16,2), tvaval N(16,2),totval N(16,2), total_fara_tva N(16,2), total_tva N(16,2), total_cu_tva N(16,2), nume_valuta C(5) null, client C(100), id_client N(10), cod_fiscal C(30), tip_persoana N(1) null, trimis N(1) null, data_trimis T null, stare C(100) null, id_incarcare C(36) null, mesaj_trimis C(250) null, id_descarcare c(36) null, tip_mesaj_raspuns C(50) null,mesaj_raspuns C(250) null, data_raspuns D null, cod_fiscal_emitent C(30) null, cod_fiscal_beneficiar C(30) null, detalii M null, xfurnizor C(200), xclient C(200), xdata_act D, xnumar_act C(30), xtotal_fara_tva N(16,4), xtotal_tva N(16,4), xtotal_tva_ron N(16,4), xtotal_cu_tva N(16,4), xdiscount_fara_tva N(16,4), xtaxe_fara_tva N(16,4), xvaloare_fara_tva N(16,4), xtotal_de_plata N(16,4), xnume_valuta C(5), test N(1) null, id_util N(10), utilizator C(100), jtotctva N(16,4), diferenta N(16,4), procesat N(1), procesat_server N(1), creditnote N(1)
ENDTEXT
TEXT TO lcSelect NOSHOW
SELECT 0 as ales, id, id_fact, id_vanzare, data_act, numar_act, in_valuta, curs, valval, tvaval, totval, total_fara_tva, total_tva,total_cu_tva, nume_valuta, client, id_client, cod_fiscal, NVL(tip_persoana,1) as tip_persoana, NVL(trimis,0) as trimis, data_trimis, stare, id_incarcare, mesaj_trimis, id_descarcare, tip_mesaj_raspuns, mesaj_raspuns, data_raspuns, cod_fiscal_emitent, cod_fiscal_beneficiar, '' as detalii, xfurnizor, xclient, xdata_act, xnumar_act, xtotal_fara_tva, xtotal_tva, xtotal_tva_ron, xtotal_cu_tva, xdiscount_fara_tva, xtaxe_fara_tva, xvaloare_fara_tva, xtotal_de_plata, xnume_valuta, test, id_util, utilizator, jtotctva, decode(creditnote,0,1,-1) * ROUND(NVL(xtotal_cu_tva , 0.00) * decode(in_valuta,1,curs,1), 2)-NVL(jtotctva, 0.00) as diferenta, procesat, procesat_server,creditnote FROM anaf_vefactura_emis
ENDTEXT
lcOrder = [data_act,numar_act]
lcgroup = []
lcFiltru = [1=2]
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poFacturiEmise', 'crsFacturiEmise', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiEmise.ca_baza1.afisare()
* DETALII (goale)
TEXT TO lcSchema NOSHOW
id N(20), id_efactura N(20), nr N(5), articol V(250), descriere V(250), detalii M, cantitate N(18,6), um V(20), pret N(20,6), proctva N(7,2), valoarefaratva N(20,6), discountfaratva N(20,6)
ENDTEXT
TEXT TO lcSelect NOSHOW
select id, id_efactura, nr, articol, descriere, detalii, cantitate, um, pret, proctva, valoarefaratva, discountfaratva from anaf_vefactura_detalii
ENDTEXT
lcOrder = [nr]
lcgroup = []
lcFiltru = [1=2]
lcFiltruOriginal = []
llModParam = .T.
llAfiseaza = .F.
gencursor('poFacturiDetalii', 'crsDetaliiFacturi', lcSelect, lcFiltru, lcSchema, lcOrder, llAfiseaza, lcgroup, llModParam, lcFiltruOriginal)
poFacturiDetalii.ca_baza1.afisare()
*=========================================================================
DO PrLogLocal WITH '=== PAS 2: forma REALA anaf_efactura (modeless) + mock pe AnafeFacturaServer ==='
LOCAL lcCifReal
loAnaf = CREATEOBJECT('ANAFeFactura')
lcCifReal = ALLTRIM(loAnaf.AnafeFacturaServer.cCodFiscal)
DO PrLogLocal WITH 'AnafeFacturaServer real (INAINTE de inlocuire): cCodFiscal=[' + lcCifReal + '] lTest=' + TRANSFORM(loAnaf.AnafeFacturaServer.lTest)
loMockSrv = NEWOBJECT('MockAnafServerStorno', gcTestDir + 'mock_anaf_server_storno.prg')
loMockSrv.cCodFiscal = lcCifReal
loMockSrv.lTest = (lnTestSursa = 1)
loAnaf.AnafeFacturaServer = loMockSrv
DO PrLogLocal WITH 'AnafeFacturaServer INLOCUIT cu MockAnafServerStorno (ZERO retea): cCodFiscal=[' + loAnaf.AnafeFacturaServer.cCodFiscal + '] lTest=' + TRANSFORM(loAnaf.AnafeFacturaServer.lTest) + ' Class=' + loAnaf.AnafeFacturaServer.Class
CATCH TO loExOuter
DO PrLogLocal WITH 'EXCEPTIE NEPRINSA: ' + loExOuter.Message + ' (' + TRANSFORM(loExOuter.LineNo) + ') ' + loExOuter.Procedure
gnFail = gnFail + 1
DO PrLogLocal WITH 'REZULTAT FINAL: PASS=' + TRANSFORM(gnPass) + ' FAIL=' + TRANSFORM(gnFail)
QUIT
ENDTRY
* ABATERE: instantiat prin frmtest_anaf.scx (subclasa goala peste anaf_efactura.vcx, stub de test,
* vezi frmtest_anaf.sc2 in acest folder) in loc de CREATEOBJECT direct pe clasa din .vcx - sfatul
* lui Marius: instantierea prin forma .scx arata calea COMPLETA a controlului in mesajul de eroare,
* nu doar numele de baza "_checkbox1". Afara din orice TRY, ca eroarea sa treaca prin ON ERROR
* (logata cu AERROR, executia continua) in loc sa opreasca testul.
* CREATEOBJECT('form1', <scx>) a dat "Class definition FORM1 is not found" - .scx foloseste alt
* mecanism de incarcare decat .vcx; DO FORM e calea nativa pentru clase de forma.
DO FORM (gcTestDir + 'frmtest_anaf.scx') NAME loForm NOSHOW WITH loAnaf
IF VARTYPE(loForm) != 'O'
DO PrLogLocal WITH 'FAIL: DO FORM frmtest_anaf nu a returnat obiect, VARTYPE=' + VARTYPE(loForm)
QUIT
ENDIF
DO PrLogLocal WITH 'loForm creat dupa eroarea 177 (abatere de mediu, consemnata): VARTYPE=O, Class=' + loForm.Class
TRY
DO PrLogLocal WITH 'ClassLibrary anaf_efactura = implicit, via SET CLASSLIB (COMUN\CLASE\anaf_efactura.vcx, binar real cu write-back)'
* ABATERE: loForm.Show() NU se apeleaza (nu e necesar - do_storno_efactura foloseste doar
* Thisform.oAnaf si crsFacturiTrimise).
loForm.WindowType = 0
DO PrLogLocal WITH 'BORDEROU creat (nu afisat - vezi abaterea de mai sus): Class=' + loForm.Class
*=========================================================================
DO PrLogLocal WITH '=== PAS 3: driver Timer pe _SCREEN (Show(1) in do_storno_efactura e modal si pompeaza mesaje Windows) ==='
IF TYPE('_SCREEN.tmrDrvStorno') = 'U'
_SCREEN.ADDOBJECT('tmrDrvStorno', 'Timer')
ENDIF
_SCREEN.tmrDrvStorno.Interval = 200
PUBLIC loDriverStorno
loDriverStorno = CREATEOBJECT('DriverStorno')
BINDEVENT(_SCREEN.tmrDrvStorno, 'Timer', loDriverStorno, 'Executa')
_SCREEN.tmrDrvStorno.Enabled = .T.
DO PrLogLocal WITH '=== PAS 4: This.do_storno_efactura() - exact ce apeleaza optiunea de meniu 10 (anaf_efactura.vc2:5829) ==='
DO PrLogLocal WITH 'ON(ERROR) inainte de do_storno_efactura: [' + ON('ERROR') + ']'
loForm.do_storno_efactura()
_SCREEN.tmrDrvStorno.Enabled = .F.
TRY
UNBINDEVENTS(_SCREEN.tmrDrvStorno)
CATCH
ENDTRY
DO TVerdict WITH loDriverStorno.lDone, 'driverul a ajuns la final (a tratat forma de storno pana la capat)', 'nState final=' + TRANSFORM(loDriverStorno.nState) + ' tick-uri=' + TRANSFORM(loDriverStorno.nTicks)
LOCAL i
IF !loDriverStorno.lDone OR loDriverStorno.nState < 4
FOR i = 1 TO gnAmsgCalls
DO PrLogLocal WITH 'AMESSAGEBOX vazut: [' + gaAmsgCalls[i, 1] + '] -> ' + TRANSFORM(gaAmsgCalls[i, 2])
ENDFOR
ENDIF
DO PrLogLocal WITH 'TOTAL apeluri mock server: ' + TRANSFORM(gnMockApeluri)
FOR i = 1 TO gnMockApeluri
DO PrLogLocal WITH ' mock[' + TRANSFORM(i) + '] ' + gaMockApeluri[i, 1] + ' | ' + gaMockApeluri[i, 2] + ' | ' + gaMockApeluri[i, 3]
ENDFOR
TRY
loForm.Release()
CATCH
ENDTRY
DO PrLogLocal WITH 'REZULTAT FINAL: PASS=' + TRANSFORM(gnPass) + ' FAIL=' + TRANSFORM(gnFail)
CATCH TO loExOuter
DO PrLogLocal WITH 'EXCEPTIE NEPRINSA: ' + loExOuter.Message + ' (' + TRANSFORM(loExOuter.LineNo) + ') ' + loExOuter.Procedure
gnFail = gnFail + 1
DO PrLogLocal WITH 'REZULTAT FINAL: PASS=' + TRANSFORM(gnPass) + ' FAIL=' + TRANSFORM(gnFail)
ENDTRY
QUIT
**********************************************************
PROCEDURE TVerdict
LPARAMETERS tlCond, tcLabel, tcDetaliu
IF tlCond
gnPass = gnPass + 1
DO PrLogLocal WITH 'PASS ' + tcLabel + ' | ' + TRANSFORM(tcDetaliu)
ELSE
gnFail = gnFail + 1
DO PrLogLocal WITH 'FAIL ' + tcLabel + ' | ' + TRANSFORM(tcDetaliu)
ENDIF
ENDPROC
**********************************************************
PROCEDURE PrLogLocal
LPARAMETERS tcMsg
LOCAL lcL
SET SAFETY OFF
lcL = IIF(FILE(gcUILog), FILETOSTR(gcUILog), '')
STRTOFILE(lcL + TTOC(DATETIME()) + ' ' + TRANSFORM(tcMsg) + CHR(13) + CHR(10), gcUILog)
ENDPROC
**********************************************************
PROCEDURE PrErrLocal
LPARAMETERS tnError, tcMessage, tcProgram, tnLineNo
LOCAL laErrDetail[1], i, lcDetail
lnLastErrorNo = tnError
lcLastErrorMsg = TRANSFORM(tcMessage)
DO PrLogLocal WITH 'EROARE ' + TRANSFORM(tnError) + ' ' + TRANSFORM(tcMessage) + ' in ' + TRANSFORM(tcProgram) + ' linia ' + TRANSFORM(tnLineNo)
AERROR(laErrDetail)
lcDetail = ''
FOR i = 1 TO ALEN(laErrDetail, 1)
lcDetail = lcDetail + TRANSFORM(i) + '=[' + TRANSFORM(NVL(laErrDetail[i], '')) + '] '
ENDFOR
DO PrLogLocal WITH 'AERROR: ' + lcDetail
ENDPROC
**********************************************************
FUNCTION ExistaApelMock
LPARAMETERS tcMetoda
LOCAL i
FOR i = 1 TO gnMockApeluri
IF gaMockApeluri[i, 1] == tcMetoda
RETURN .T.
ENDIF
ENDFOR
RETURN .F.
ENDFUNC
**********************************************************
* Driver pentru dialogul modal Show(1) al frm_storno_efactura (deschis din interiorul
* do_storno_efactura). Vezi COMUN\docs\testare-ui-vfp.md, sectiunea "Dialoguri modale (Show(1))",
* varianta B: Timer pe _SCREEN, detectie prin _SCREEN.Forms (nu _SCREEN.ActiveForm - nu merge
* headless).
DEFINE CLASS DriverStorno AS Custom
nState = 0
nTicks = 0
lDone = .F.
PROCEDURE Executa
LOCAL loStorno, i, llRet
LOCAL loExD
This.nTicks = This.nTicks + 1
IF This.nTicks = 1
DO PrLogLocal WITH 'ON(ERROR) in interiorul DriverStorno.Executa (primul tick): [' + ON('ERROR') + ']'
ENDIF
TRY
DO CASE
CASE This.nState = 0
loStorno = .NULL.
FOR i = 1 TO _SCREEN.FormCount
IF UPPER(_SCREEN.Forms(i).Class) == 'FRM_STORNO_EFACTURA'
loStorno = _SCREEN.Forms(i)
EXIT
ENDIF
ENDFOR
IF ISNULL(loStorno)
IF This.nTicks > 150
DO PrLogLocal WITH 'DRIVER FAIL: frm_storno_efactura nu a aparut in ~30s (nState=0)'
gnFail = gnFail + 1
This.lDone = .T.
_SCREEN.tmrDrvStorno.Enabled = .F.
ENDIF
RETURN
ENDIF
loStornoForm = loStorno
DO PrLogLocal WITH 'DRIVER: frm_storno_efactura gasita dupa ' + TRANSFORM(This.nTicks) + ' tick-uri, Class=' + loStorno.Class
DO TVerdict WITH lnLastErrorNo = 0, 'fara eroare pana la afisarea formei stornului', 'lnLastErrorNo=' + TRANSFORM(lnLastErrorNo) + ' [' + lcLastErrorMsg + ']'
DO TVerdict WITH RECCOUNT('crsStornoDetalii') > 0, 'grid crsStornoDetalii populat', 'reccount=' + TRANSFORM(RECCOUNT('crsStornoDetalii'))
DO TVerdict WITH 'TEST' $ UPPER(loStorno.Caption), 'Caption contine TEST', 'caption=[' + loStorno.Caption + ']'
DO TVerdict WITH UPPER(ALLTRIM(loStorno.lblStare.Caption)) == 'NEVALIDAT', 'stare initiala Nevalidat', 'stare=[' + loStorno.lblStare.Caption + ']'
DO TVerdict WITH FILE(loStorno.pcFisierStorno), 'fisier storno exista pe disc', 'fisier=[' + loStorno.pcFisierStorno + ']'
This.nState = 1
CASE This.nState = 1
loStorno = loStornoForm
loStorno.pcNumarNou = ALLTRIM(loStorno.pcNumarNou) + 'X'
loStorno.pcMotiv = 'Motiv test E2E'
llRet = loStorno.RegenereazaXml()
DO TVerdict WITH llRet, 'RegenereazaXml dupa schimbare numar/motiv', 'numarnou=[' + loStorno.pcNumarNou + '] return=' + TRANSFORM(llRet)
DO TVerdict WITH RECCOUNT('crsStornoDetalii') > 0, 'grid populat dupa regenerare', 'reccount=' + TRANSFORM(RECCOUNT('crsStornoDetalii'))
This.nState = 2
CASE This.nState = 2
loStorno = loStornoForm
loStorno.SetStare(1)
DO TVerdict WITH UPPER(ALLTRIM(loStorno.lblStare.Caption)) == 'VALID', 'SetStare(1) -> Valid (ocolire ValidareEFacturaANAF, retea reala, cf. instructiuni)', 'stare=[' + loStorno.lblStare.Caption + ']'
loStorno.cmdTrimite.Click()
DO TVerdict WITH UPPER(ALLTRIM(loStorno.lblStare.Caption)) == 'TRIMIS', 'dupa cmdTrimite.Click -> Trimis', 'stare=[' + loStorno.lblStare.Caption + ']'
DO TVerdict WITH ExistaApelMock('TrimiteFacturaXML'), 'mock a primit TrimiteFacturaXML', ''
This.nState = 3
CASE This.nState = 3
loStorno = loStornoForm
TRY
loStorno.Release()
CATCH TO loExD
DO PrLogLocal WITH 'DRIVER: eroare la Release: ' + loExD.Message
ENDTRY
This.lDone = .T.
This.nState = 4
_SCREEN.tmrDrvStorno.Enabled = .F.
ENDCASE
CATCH TO loExD
DO PrLogLocal WITH 'DRIVER EXCEPTIE nState=' + TRANSFORM(This.nState) + ': ' + loExD.Message + ' linia ' + TRANSFORM(loExD.LineNo)
gnFail = gnFail + 1
This.lDone = .T.
_SCREEN.tmrDrvStorno.Enabled = .F.
TRY
loStornoForm.Release()
CATCH
ENDTRY
ENDTRY
ENDPROC
ENDDEFINE

View File

@@ -0,0 +1,449 @@
* 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