Skip to content

HubfiscalStoreBillpt

Stores the output of BillptCreateInvoiceFromShopify (or any Bill.pt document node) in the Hub Fiscal centralized MySQL/MariaDB database. Designed to be placed immediately after the Bill.pt creation step, whether the invoice succeeded or failed.

Key features:

  • Upsert: If the order already has a record it updates it, otherwise inserts. Prevents duplicates on retries.
  • Full traceability: Stores atcud, fiscal_doc_number, totals, contact data, and the raw JSON payload.
  • Atomic transaction: Inserts into documents, fiscal_status and logs in one transaction — rolls back fully on error.
  • Failure recording: Stores failed attempts with status: failed and the error message, incrementing retry_count.
FieldTypeRequiredDescription
credentials_idcredentialsYesHub Fiscal MySQL/MariaDB credential (sqlQuery type)
country_isotextNoCountry ISO code (PT, ES, AO…). Defaults to the Bill.pt contact country. Default: PT
entity_sourcetextNoOrder source: shopify, manual, api. Default: shopify
document_typeselectNoFallback document type if not present in the Bill.pt response: FT, FR, ORC, NC. Default: FT
save_payloadselectNoSave full JSON payload (up to 50KB) in payload_json. Default: Yes

Requires a sqlQuery credential (MySQL/MariaDB) with:

  • host: Database host (e.g. 127.0.0.1)
  • user: Database user (e.g. user_hubfiscal)
  • password: User password
  • database: Hub Fiscal database name (e.g. hubfiscal)
  • port: Port (default: 3306 or 3307 for dev)

The Hub Fiscal database requires 5 tables. The SQL schema is at modules/hubfiscalStoreBillpt/schema.sql.

TablePurpose
documentsOne record per fiscal document — status, ATCUD, totals, payload
fiscal_statusEach fiscalization attempt with full request/response
logsSystem events and errors
countriesCountries enabled for fiscalization
reports_cachePre-calculated report cache

The documents table has a unique constraint on (entity_id, entity_source, type) to prevent duplicates.

Expected input: the output of BillptCreateInvoiceFromShopify or any Bill.pt document node:

{
"success": true,
"document_id": 789,
"document_number": "FT FHPT/3",
"shopify_order_id": 6684429451477,
"shopify_order_number": 14522,
"document": {
"id": 789,
"tipificacao": "FT",
"invoice_number": "FT FHPT/3",
"atcud": "J6X8WR2G-3",
"net_total": 63.56,
"tax_total": 14.62,
"gross_total": 78.18,
"moeda": "EUR_€",
"invoice_date": "2026-04-20",
"contato": {
"nome": "John Doe",
"nif": "999999990",
"email": "customer@example.com",
"pais": "PT"
}
}
}
{
"success": true,
"hub_document_id": 15,
"entity_id": "6684429451477",
"order_number": "14522",
"country_iso": "PT",
"type": "FT",
"status": "completed",
"fiscal_provider": "billpt",
"fiscal_doc_id": "789",
"fiscal_doc_number": "FT FHPT/3",
"atcud": "J6X8WR2G-3",
"total_gross": 78.18,
"currency": "EUR",
"message": "Documento registrado en Hub Fiscal (ID: 15, ATCUD: J6X8WR2G-3)"
}

The node auto-maps fields from the Bill.pt response:

Hub Fiscal fieldSource
entity_iddata.shopify_order_id → data.entity_id → document.id
order_numberdata.shopify_order_number → data.order_number
country_isoconfig → document.contato.pais → PT
typedocument.tipificacao → config document_type → FT
fiscal_doc_iddata.document_id → document.id
fiscal_doc_numberdocument.invoice_number → data.document_number
atcuddocument.atcud
currencydocument.moeda (strips _€ suffix)
issued_atdocument.invoice_date → document.system_entry_date → today
contact_namedocument.contato.nome
contact_nifdocument.contato.nif
contact_emaildocument.contato.email → data.email

When the upstream Bill.pt node returns success: false, the document is still stored with status: failed. On each retry, retry_count is incremented. This allows monitoring pending or failed fiscalizations from the Hub Fiscal database.

-- Find failed documents
SELECT entity_id, order_number, error_message, retry_count
FROM documents
WHERE status = 'failed' AND fiscal_provider = 'billpt'
ORDER BY updated_at DESC;
  • The ATCUD (atcud) field is required by Portuguese law (AT regulation) and stored as a dedicated column for easy querying and audit.
  • currency is normalized from Bill.pt’s EUR_€ format to standard ISO EUR.
  • payload_json stores the full input up to 50KB. Set save_payload: false to store only fiscal data.
  • The action field in fiscal_status is set to void for NC (Credit Note) documents and create for all others.
  • MariaDB users: the credential test (sqlQuery type) includes a GSSAPI auth workaround. Use mysql_native_password for the database user to avoid authentication errors.