Skip to main content
An order moves through several stages from the moment a cashier submits a sale to the moment revenue is reconciled. Some stages are triggered by HTTP calls; others fire automatically as Firestore triggers.

OrderData structure

The following fields are written to the orders collection by order_created and mirrored to the orders PostgreSQL table.
FieldTypeDescription
amountnumberTotal order value in base currency
date.createdTimestampServer timestamp set at creation
date.updatedTimestampUpdated each time the order is modified
event_idstringFirestore ID of the parent event
event_namestringDisplay name of the event
office_idstringID of the box office that processed the sale
office_namestringDisplay name of the box office
client_idstringID of the event organizer (client)
client_namestringDisplay name of the event organizer
box_office_idstringID of the physical point of sale
box_office_namestringDisplay name of the physical point of sale
statusstringOrder status string passed by the caller
status_type.idstringAlways "completed" on creation
status_type.namestringAlways "Completada" on creation
exchange_ratenumberExchange rate applied to foreign-currency payments
ticketsarrayList of ticket objects included in the order
transactionsarrayList of transaction objects (one per payment method)
purchaser_infoobject|nullPurchaser details if provided
recipient_infoobject|nullRecipient details if provided
is_courtesybooleantrue if this is a complimentary order
is_corporatebooleantrue for corporate purchases
is_giftbooleantrue if tickets are being gifted
distributionarrayPayout distribution records (written by order_process)
billing_infoobjectBilling result added by process_order_billing

Ticket item structure

Each entry in the tickets array represents one seat in the order:
{
  "amount": 25.00,
  "id": "zone-seat-ref",
  "metadata": {
    "customer_email": "[email protected]",
    "customer_id": "12345678",
    "customer_id_type": "V",
    "customer_name": "Ana Gomez",
    "customer_phone": "+58-412-0000000",
    "customer_address": "Caracas",
    "customer_country": { "code": "ve", "name": "Venezuela", "key": 0 }
  },
  "ticket_id": "{event_id}-{ticket_doc_id}",
  "status": false
}
ticket_id is a composite key in the format {event_id}-{firestore_doc_id}. order_process splits this value on the - character to locate the ticket document at events/{event_id}/tickets/{ticket_doc_id}.

Lifecycle flow

1

order_created — write the order

An HTTP POST from the point-of-sale client submits the full order payload. The function:
  1. Builds the OrderData object with server-side timestamps.
  2. Writes it to the orders Firestore collection.
  3. Inserts a matching row into the orders PostgreSQL table.
  4. Returns the new Firestore document ID.
This write immediately triggers order_process via the onDocumentCreated Firestore trigger.
2

order_process — process tickets, payouts, and transactions

Fired automatically when a new document appears in the orders collection. The function:
  1. Iterates the tickets array and updates customer metadata on each events/{id}/tickets/{id} document via a batched Firestore write, and updates the tickets PostgreSQL table.
  2. Calls order_user to register the order under the buyer’s user profile (creating a u_users account if none exists).
  3. Reads the event’s setup/financial document to calculate the fixed-cost and variable-cost split.
  4. Writes orders_payout records to Firestore and PostgreSQL for both TMT (platform) and Client (organizer) shares.
  5. Updates the order document with the distribution array.
  6. Calls transactions_generate to create orders_transactions records and mark tickets as sold.
3

order_user — register the order on the buyer's profile

Called internally by order_process. Looks up the buyer by customer_email in u_users.
  • If a user record exists, the order is written to u_users/{uid}/orders/{order_id}.
  • If no user record exists, a Firebase Auth account and u_users document are created automatically using the buyer’s details from ticket.metadata. A random temporary password is stored in u_users/{uid}/security.
4

order_payout — handle non-manual payout references

A Firestore trigger on orders_payout/{id}. When a new payout record has payout_type != "Manual", the function writes a payment_reference object back to the payout document containing the amount, timestamp, and a placeholder reference string.Manual payouts (the default) are not touched by this trigger — they are settled through invoice_payout_status.
5

invoice_payout_status — mark payouts as settled

An HTTP function used by finance staff to confirm that a batch of payout obligations has been paid. Filters orders_payout records by event_id, date range, and currency (vef / usd flags), then sets payout_status = true and records a reference_number on all matching rows in PostgreSQL.
6

process_order_billing — generate the invoice

An independent HTTP function called after order creation to trigger invoice generation without blocking the main order flow. It:
  1. Enriches purchaser_info from the u_users collection.
  2. Fetches client (tercero) data from u_clients.
  3. Calls getNextInvoiceNumber() for a sequential invoice number.
  4. Builds billing data via generateBillingDataFromOrder() and emits the invoice via emitirFacturaCore().
  5. On success, writes a billing_info object back to the order document.

Function reference

order_created

Creates a new order in Firestore and PostgreSQL. Trigger: POST /order_created

Request

{
  "data": {
    "amount": 75.00,
    "event_id": "evt_abc123",
    "event_name": "Festival de Jazz 2024",
    "office_id": "off_001",
    "office_name": "Taquilla Central",
    "client_id": "cli_xyz",
    "client_name": "Producciones XYZ",
    "box_office_id": "bo_001",
    "box_office_name": "Caja 1",
    "status": "completed",
    "exchange_rate": 36.5,
    "is_courtesy": false,
    "is_corporate": false,
    "is_gift": false,
    "purchaser_info": null,
    "recipient_info": null,
    "tickets": [
      {
        "amount": 25.00,
        "id": "zone1-1",
        "metadata": {
          "customer_email": "[email protected]",
          "customer_id": "12345678",
          "customer_id_type": "V",
          "customer_name": "Ana Gomez",
          "customer_phone": "+58-412-0000000",
          "customer_address": "Caracas",
          "customer_country": { "code": "ve", "name": "Venezuela", "key": 0 }
        },
        "ticket_id": "evt_abc123-tk001"
      }
    ],
    "transactions": [
      {
        "amount": 75.00,
        "custody_account": {
          "id": "cust_001",
          "name": "Caja Principal",
          "account_number": "0102-0000-00"
        },
        "payment_data": {
          "bank": "Banco de Venezuela",
          "phone": "+58-412-0000000",
          "reference_number": "123456"
        },
        "payment_id": "pm_transfer",
        "payment_name": "Transferencia",
        "status": true,
        "amount_currency": "USD",
        "amount_exchange": 2737.50,
        "amount_exchange_rate": 36.5,
        "point_sale_tmt": false
      }
    ]
  }
}

Response

{
  "message": "Orden Creada ",
  "status": 200,
  "data": {
    "valido": true,
    "order": "<firestore_document_id>"
  }
}
data.valido
boolean
true when the order was created successfully.
data.order
string
The Firestore document ID of the newly created order.

split_queries

Returns a summary of payout distribution for an event across a date range. Queries the orders_payout PostgreSQL table grouped by entity and description. Trigger: POST /split_queries

Request

data.event_id
string
required
The event to query.
data.from
string
Start of the date range (ISO 8601). Filters on date_created >= from.
data.to
string
End of the date range (ISO 8601). Filters on date_created <= to.

Response

{
  "message": "Datos Split Enviados ",
  "status": 200,
  "data": {
    "total_cost_fijo": 150.00,
    "total_cost_variable_tmt": 45.00,
    "total_cost_variable_cliente": 30.00,
    "costs_fixed": [
      {
        "name": "Alquiler de sala",
        "amaount": 150.00,
        "entity": "TMT",
        "percentage": 100
      }
    ],
    "costs_variables": [
      {
        "name": "Comisión plataforma",
        "amaount": 45.00,
        "entity": "TMT",
        "percentage": 5
      },
      {
        "name": "Comisión organizador",
        "amaount": 30.00,
        "entity": "Cliente",
        "percentage": 3
      }
    ]
  }
}

split_payout

Returns a detailed payout breakdown for an event, split by currency (USD/VEF) and payment status (payout_status = true/false). Used by finance to reconcile what has been paid versus what is outstanding. Trigger: POST /split_payout

Request

data.event_id
string
required
The event to query.
data.from
string
Start of the date range (ISO 8601).
data.to
string
End of the date range (ISO 8601).
The response includes totals for total_cost_fijo, total_cost_variable_tmt, and total_cost_variable_cliente, each with _pagado (paid), _nopagado (unpaid), and _VEF (bolivar-denominated) variants.

invoice_payout_status

Marks a batch of orders_payout records as settled in PostgreSQL. Trigger: POST /invoice_payout_status

Request

data.event_id
string
required
The event whose payouts are being settled.
data.from
string
Start date filter (ISO 8601).
data.to
string
End date filter (ISO 8601).
data.vef
boolean
If true, marks VEF-denominated payout records as paid.
data.usd
boolean
If true, marks USD-denominated payout records as paid.
data.reference_number
string
required
The payment reference to record on settled rows.

process_order_billing

Triggers invoice generation for a completed order. Run separately from order_process to avoid Cloud Function timeouts. Trigger: POST /process_order_billing

Request

data.order_id
string
required
The Firestore document ID of the order to invoice.
data.order_data
object
required
The full order data object (same shape as the orders document).
data.event_id
string
required
The event ID.
data.event_name
string
required
The event display name.
data.office_id
string
required
The office ID.
data.office_name
string
required
The office display name.
data.exchange_rate
number
required
The exchange rate used for currency conversion on the invoice.

Response (success)

{
  "message": "Facturación completada exitosamente",
  "status": 200,
  "data": {
    "success": true,
    "order_id": "<order_id>",
    "billing_result": {}
  }
}

Response (failure)

{
  "message": "Error en facturación",
  "status": 400,
  "data": {
    "success": false,
    "order_id": "<order_id>",
    "error": "<error detail>"
  }
}
If billing fails, the order itself is not rolled back. The order remains in Firestore and PostgreSQL. Retry process_order_billing with the same order_id once the underlying billing issue is resolved.

Build docs developers (and LLMs) love