HubfiscalCreateDocument
Description
Section titled “Description”Registers a fiscal document in the Hub Fiscal, an external SQL Server database that acts as a central hub for all fiscal operations. The node consolidates orders from Shopify (or other sources) along with the results from fiscal providers (Bill.pt, Fiskaly, Sage) into a single unified database.
Key features:
- MERGE (upsert): If the order already exists it updates, otherwise creates. Prevents duplicates.
- Auto-detection: Extracts country from
billing_address, detects fiscal provider by country (PT=billpt, ES=fiskaly). - Atomic transaction: Inserts into
documents,fiscal_statusandlogstables in one transaction. - Ticket storage: Stores the HTML ticket and/or PDF binary returned by the fiscal provider.
Configuration
Section titled “Configuration”| Field | Type | Required | Description |
|---|---|---|---|
| credentials_id | credentials | Yes | Hub Fiscal SQL Server (MSSQL) credential |
| entity_id | text | No | Order ID (Shopify). If empty, uses data.id |
| entity_source | select | No | Origin: shopify, prestashop, woocommerce, manual, api. Default: shopify |
| order_number | text | No | Visible order number (e.g. PT14684). If empty, uses data.name |
| country_iso | text | No | ISO country code (PT, ES, AO, MZ). If empty, extracts from billing_address |
| doc_type | select | No | Document type: FT, FR, NC, ORC. Default: FT |
| fiscal_provider | select | No | Fiscal provider: billpt, fiskaly, sage. Auto-detected by country if empty |
| fiscal_doc_id | text | No | Document ID returned by fiscal provider |
| fiscal_doc_number | text | No | Invoice number from fiscal provider |
| contact_name | text | No | Contact name. If empty, extracts from billing_address |
| contact_nif | text | No | Contact tax number (NIF) |
| contact_email | text | No | Contact email |
| total_net | text | No | Net total (tax base). If empty, uses data.subtotal_price |
| total_tax | text | No | Tax total. If empty, uses data.current_total_tax |
| total_gross | text | No | Gross total. If empty, calculated as net + tax |
| currency | text | No | ISO currency (default: EUR) |
| issued_at | text | No | Issue date ISO. If empty, uses current date |
| ticket_html | textarea | No | Ticket HTML from Bill.pt or other provider |
| ticket_pdf | textarea | No | Ticket PDF in base64. Stored as binary in SQL Server |
| assign_numbering | select | No | No (default): only stores portal and zone. Yes: also assigns the series number and sets completed (portals without a fiscal third party) |
| save_payload | select | No | Save full order JSON in payload_json (max 50KB). Default: Yes |
| timeout | text | No | Timeout in milliseconds (default: 30000) |
Credentials
Section titled “Credentials”This module requires a hubfiscalCreateDocument type credential (SQL Server) with:
- host: SQL Server hostname or IP
- user: Database username
- password: Database password
- database: Hub Fiscal database name
- port: Port (default: 1433)
The credential test verifies the connection and checks that all Hub Fiscal tables exist (documents, fiscal_status, logs, countries, reports_cache).
Database Schema
Section titled “Database Schema”The Hub Fiscal database requires 5 tables. The SQL schema is included in the module at modules/hubfiscalCreateDocument/schema.sql.
| Table | Purpose |
|---|---|
| documents | Central fiscal document (order + status + totals + tickets) |
| fiscal_status | Each fiscalization attempt (request/response per provider) |
| logs | System events and errors |
| countries | Enabled countries for fiscalization |
| reports_cache | Pre-calculated report cache for dashboard KPIs |
Output
Section titled “Output”{ "success": true, "hub_document_id": 42, "entity_id": "6702987051221", "order_number": "PT14684", "country_iso": "PT", "type": "FT", "status": "completed", "fiscal_provider": "billpt", "fiscal_doc_id": "789", "fiscal_doc_number": "FT 2026/1", "total_gross": 19.90, "currency": "EUR", "message": "Documento registrado en Hub Fiscal (ID: 42)"}Usage Example
Section titled “Usage Example”Typical flow: Shopify Webhook → Decision (country) → Bill.pt (create invoice) → HubfiscalCreateDocument
{ "credentials_id": "10", "entity_id": "{{id}}", "order_number": "{{name}}", "country_iso": "{{billing_address.country_code}}", "doc_type": "FT", "contact_name": "{{billing_address.name}}", "contact_email": "{{email}}", "total_net": "{{subtotal_price}}", "total_tax": "{{current_total_tax}}", "total_gross": "{{total_price}}"}Most fields are auto-detected from the previous node’s data, so a minimal configuration works:
{ "credentials_id": "10", "save_payload": "true"}- The
documentstable has a unique constraint on(entity_id, entity_source, type)to prevent duplicates - If the previous node returned
error, the document is saved withstatus: "failed"and the error message is stored - If the previous node returned
success: true, the document is saved withstatus: "completed" - The
ticket_htmlfield stores HTML content asNVARCHAR(MAX)(up to 2GB, queryable) - The
ticket_pdffield stores binary PDF asVARBINARY(MAX)(accepts base64 input, converted to Buffer) - The original order payload is truncated to 50KB to avoid excessive storage
- Provider auto-detection: PT → billpt, ES → fiskaly, AO → billpt, MZ → billpt
Portal and numbering (daily aggregation to Sage X3)
Section titled “Portal and numbering (daily aggregation to Sage X3)”Besides storing the document, the node determines the sales portal (equivalenza.com, .it, .fr or .pt) from the order and the zone (Canary Islands, if the shipping postal code starts with 35 or 38), and stores them on the document. HubfiscalAggregateSales uses this to group the day’s sales.
With the Number and complete option set to Yes, on portals without a fiscal third party (equivalenza.com, .it and .fr) the node also:
- assigns the next sequential number of the series, with no leading zeros and no yearly reset (
FESH1,FESH2…), and - sets the document to
completed.
| Portal | Invoice | Credit note |
|---|---|---|
| equivalenza.com | FESH | AESH |
| equivalenza.com (Canary Islands) | FCAH | ACAH |
| equivalenza.it | FITH | AITH |
| equivalenza.fr | FFRH | AFRH |
- No gaps or duplicates, even when orders arrive at the same time: each series counter is locked while assigning, and an error does not consume the number.
- Idempotent: resending the same order does not renumber it.
- equivalenza.pt is not numbered here: Bill.pt does it (
FHPT/AHPT). - A type other than invoice or credit note (for example
ORC) or a portal with no rule is not numbered. - It is off by default (
No): only portal and zone are stored. Turn it on when you decide from which day numbering starts, because numbering consumes real series numbers.
It requires applying to the Hub Fiscal database the portal and zone columns and the document_sequences and portal_providers tables. If they are not applied, the node keeps working as before and does not number.
Extra node output with this data: portal, zone, fiscal_doc_number and numbering (the result: numerado, ya_numerado, numeracion_desactivada, delegado_en_billpt, esquema_no_aplicado…).
Related Nodes
Section titled “Related Nodes”- HubfiscalAggregateSales - Groups the day’s sales by portal and prepares them for Sage X3
- HubfiscalUpdateDocument - Update existing document
- HubfiscalExportPdf - Export PDF/HTML tickets
- HubfiscalGetDocuments - Query and filter documents
- BillptCreateDocument - Create document in Bill.pt
- SageCreateDocument - Create document in Sage X3
- FiskalyCreateInvoice - Create invoice in Fiskaly