Skip to content

Finance Module Backend

Related documentation: Backend Modules · Finance API · Data ownership · Access Matrix · Error Contract

Backend-Kisum-Finance is the Finance domain backend for Kisum.

It owns finance-domain workflows such as:

  • bills / expenses
  • income / revenue
  • vendor portal flows
  • Xero accounting integration
  • finance-linked files, notifications, and exchange-rate helpers
  • Kisum compatibility reads for event-linked finance data

It does not own:

  • user identity
  • sessions / JWT issuance
  • company memberships
  • business-unit memberships
  • company master data
  • business-unit master data
  • package / add-on / entitlement truth

Those ownership boundaries now matter in runtime, not only in architecture diagrams.

  • users
  • sessions
  • company memberships
  • business-unit memberships
  • permission / scope resolution for the acting user

Finance consumes Auth context. It is not allowed to become the source of truth for those relations again.

  • company master data
  • business-unit master data
  • packages
  • add-ons
  • company subscriptions
  • entitlements

Finance now depends on Core for:

  • company / business-unit master reads
  • company commercial entitlement checks
  • business-unit master writes
  • Kisum company id as part of canonical company resolution

Finance owns (financial domain source of truth)

Section titled “Finance owns (financial domain source of truth)”

Finance is the source of truth for financial workflow data stored in the Finance database: bills/invoices, income, vendor portal and vendor-finance links, Xero connection and sync state, finance-related files/notifications, and related audit rows. It is not the source of truth for company or business-unit master data (that is Core) or for users/memberships (that is Auth).

Concretely, Finance owns:

  • bills / invoices in the finance sense
  • income rows and income payments
  • venue-deposit invoices once Venue submits them through the Finance income flow
  • vendor finance workflows
  • Xero sync state
  • audit / notification behavior related to finance workflows
  • scalar companyId / businessUnitId (and other FKs) on finance tables that point at Core-owned ids — without re-defining company/BU master records in Finance

Finance access requires both Auth and Core

Section titled “Finance access requires both Auth and Core”

A company-scoped Finance request is allowed only when:

  1. the caller is authenticated
  2. Auth confirms the caller can act for the selected company
  3. Core confirms the selected company has the finance add-on / enabled module

If membership exists but the company is not entitled to Finance, Finance returns:

  • 403
  • code: finance_addon_required

For company-scoped internal routes, the active tenant is selected through x-org.

Accepted forms:

  • canonical Company.id UUID
  • kisumCompanyId when the company is linked to Kisum

Finance resolves that value to the canonical Core company, then hydrates the local compatibility row if needed.

Current cross-service detail:

  • Backend-Kisum-Venues now reuses Finance POST|PATCH /api/income in machine source=venue_deposit mode for deposit invoices
  • Finance still runs the normal income/Xero flow and remains the source of truth for payment state

How company and business unit appear in Finance (no local org-master tables)

Section titled “How company and business unit appear in Finance (no local org-master tables)”

The Finance Prisma schema does not include Company or BusinessUnit models. Finance tables store Core canonical UUIDs in scalar columns (e.g. companyId, businessUnitId on Invoice, Income, XeroConnection, vendor links, etc.).

Master truth for company and business unit name, code, status, and lifecycle remains in Core. Finance resolves display and validation by calling Core (and related helpers) and, where needed, enriches API responses in memory (enrichRowsWithCoreOrg, Core company maps, etc.) — not via Prisma relations to local org tables.

Practical rule: never treat Finance as the system of record for creating or editing tenant companies or BUs; use Core (or Admin’s Core proxies) for that. Use Finance for AP/AR, vendors, Xero, and other finance-domain persistence keyed by those Core ids.

Finance company lifecycle is removed.

These company master write endpoints should not be used anymore:

  • POST /api/admin/companies
  • PUT /api/admin/companies
  • PATCH /api/admin/companies
  • DELETE /api/admin/companies
  • POST /api/admin/companies/{id}/request-deletion

Current behavior:

  • they return 405
  • code: company_master_write_removed

Business units are still finance-relevant, but BU master truth is now in Core.

Finance admin BU CRUD writes through Core, then syncs the local compatibility row.

Main route groups in the current implementation:

  • admin/*
  • bills/*
  • income/*
  • income-categories/*
  • vendor/*
  • xero/*
  • kisum/*
  • files/*
  • upload/*
  • notifications
  • exchange-rates/*
  • dashboard/*
  • auth/vendor/*

These are documented in more detail here:

Finance relies on Auth for:

  • GET /auth/me style user context resolution
  • company and BU membership truth
  • platform / company / BU access checks

Finance docs should never describe local Finance membership tables as the active runtime model.

Finance relies on Core for:

  • company reads
  • business-unit reads
  • business-unit writes
  • entitlements
  • company lookup by canonical id and Kisum-linked id

kisum/* routes remain supported compatibility routes for event-linked finance reads.

Important current rule:

  • remaining Kisum company resolution is now Core-first
  • Finance local company rows are no longer the first resolver for those routes

Xero remains a first-class Finance integration area.

The Finance backend still owns:

  • connect / callback
  • sync
  • account / tax / currency reads
  • finance-domain Xero behavior

Important Finance runtime dependencies now include:

  • Auth internal/user context integration
  • Core internal integration
  • Redis where configured
  • PostgreSQL / Prisma
  • Kisum API
  • Xero API
  • S3-compatible file storage

For the Core integration, Finance must have working values for:

  • CORE_INTERNAL_BASE_URL
  • CORE_INTERNAL_API_KEY

Without those, commercial entitlement verification and Core org-master synchronization will fail.

What is already implemented:

  • Finance entitlement enforcement through Core
  • Auth as the source of truth for users and memberships
  • Core as the source of truth for company / business-unit master data
  • company master writes removed from Finance
  • business-unit admin CRUD routed through Core (where applicable)
  • remaining kisum/* company resolution moved to Core-first behavior
  • removal of Finance-local Company / BusinessUnit Prisma models; finance rows use scalar Core ids with runtime enrichment for responses

What still remains true:

  • Finance remains the persistence and workflow owner for invoices, income, vendors, and Xero integration — keyed by Core companyId / businessUnitId where those columns exist
  • Any older docs or code comments referring to “local company rows” in Finance should be read as historical; the current model is FK scalars + Core enrichment, not Finance-owned org master tables

When working in Backend-Kisum-Finance:

  • do not add new company master ownership here
  • do not add new business-unit master ownership here
  • prefer Auth for user / membership truth
  • prefer Core for company / BU / entitlement truth
  • persist finance-domain data in Finance; store only Core ids for tenant scope — enrich names and org fields from Core at read/API boundaries, not from Finance-local org tables
  • if code and older repo docs disagree, the implemented Auth / Core / Finance split above is the current platform rule