FinBaze for Platforms

Concepts

Record types#

mutation { definePlatformRecordType(input: {
  key: "shipment", name: "Shipment",
  schema: { type: "object", required: ["reference"], properties: { reference: { type: "string" } } },
  states: ["booked", "delivered", "cancelled"], initialState: "booked",
  displayTemplate: "Shipment {{data.reference}}"
}) { version } }

Changing the schema, states or transitions creates a new version; an identical call returns the current one. transitions ({ "booked": ["delivered"] }) restricts which moves are allowed.

Records#

upsertCustomRecord creates or updates a record by (company, type, externalId). data is validated against the type. A change of status or data bumps revision; the record keeps its history, the bookings it caused (effects) and its runs. deleteCustomRecord only works for a record without bookings.

Flow templates#

A template is YAML or JSON:

apiVersion: finbaze.com/flows/v1
kind: FlowTemplate
metadata: { key: shipment-invoicing, version: 1, recordType: shipment }
chart: rgs
ledgers: { carrier_costs: "<ledger code>", accrued_costs: "<ledger code>" }
on:
  - transition: { to: delivered }
    onDataChange: rebook          # ignore (default) | rebook | fail
    steps:
      - id: invoice
        create_sales_invoice:
          relation: "= steps.customer.id"
          date: "= $date(record.data.deliveredAt, 'Europe/Amsterdam')"
          currency: "= record.data.currency"
          finalise: true
          lines:
            - forEach: "= record.data.lanes"
              as: lane
              name: "Transport {{ lane.from }} - {{ lane.to }}"
              priceMinor: "= lane.revenueMinor"
              taxCode: NL_2012_HIGH
  • "{{ path }}" interpolates text. A string starting with = is a JSONata expression with typed results. Functions you can define yourself and $eval are not available.
  • Helpers: $lookup(table, ctx), $net(grossMinor, taxCode), $vatRate(taxCode), $date(timestamp, zone), $euCountry(code).
  • Steps: upsert_relation, upsert_project, create_sales_invoice, create_purchase_invoice, create_journal_entry, reverse and fail. Objects get the id flow:<template>:<record>:<step>, so running a trigger again changes nothing.
  • A reverse step credits the invoices and mirrors the journal entries that a step of an earlier run created. It uses what that run recorded, never the current template.

testFlowTemplate plans what a template would do for sample records without writing anything. activateFlowTemplate checks that the ledgers named in ledgers exist in your companies' charts.

Runs#

A run is one transaction: if a step fails, nothing of the run is kept and the run is failed with the step, code and path. Runs of one record go in order, so a failed run holds the later ones back until you retryFlowRun. Events: flow_run.succeeded and flow_run.failed.