Branch kh-vendor-ai-coding → main · Generated 2026-06-18
Adds a new org-level Accounting Columns section to the Custom Columns settings
page. Practices can enable/disable a fixed, Nitra-managed catalog of standard accounting
dimensions (GL Account, Vendor, Class, Department, Location, Accounting Date). Some columns are
“Always On” per accounting platform and cannot be disabled. Disabling a column also
cascades into each member’s per-member display lists (customizedColumns) for
Card Transactions, Card Fees & Interest, and Expenses. As part of the same UI (one Save
button), the existing ruttercustomfieldconfig/update endpoint is converted to a
batch shape — a breaking change the frontend must adopt.
This PR at a glance ·
2 Added ·
1 Updated (breaking) ·
1 New table
Full navigation is in the sidebar on the left. On narrower screens, scroll the page or jump via the section anchors.
Added APIs
Added
GETPOST/v1/accountingcolumnconfig/query
Returns the fixed accounting column catalog merged with the org's enable config, for the settings page.
Auth: Must be logged in
Roles:member
Permissions: none
Request body
Field
Type
Required
Default
Description
organizationId
INTEGER
No
req.organization.id
The organization to read columns for
enabled
BOOLEAN
No
—
When set, only columns whose enabled flag matches are returned
Behavior: Only the columns available on the org's accounting platform
are returned, in catalog order — e.g. department is Sage-only and
location is Sage/NetSuite-only, so neither appears for a QuickBooks org. (When the
org has no platform, the full catalog is returned for display.) Columns with no stored config
default to enabled: true. required: true columns are platform-specific
(“Always On”, e.g. GL Account on NetSuite/QuickBooks) and are always returned
enabled: true — the FE should render their toggle as locked on.
Errors
Status
Code
400
BAD_REQUEST_INVALID_ARGUMENTS
401
UNAUTHORIZED
500
INTERNAL_SERVER_ERROR
GETPOST/v1/accountingcolumnconfig/update
Batch-update enabled status for accounting columns; cascades into member display lists. All-or-nothing.
Auth: Must be logged in
Roles:member
Permissions: none
Request body
Field
Type
Required
Default
Description
organizationId
INTEGER
No
req.organization.id
Must equal the caller's organization, else 403
accountingColumns
ARRAY
Yes
—
Min 1 item; no duplicate columnKeys
accountingColumns[].columnKey
STRING
Yes
—
One of the catalog keys (e.g. glaccount, vendor, class, department, location); must be available on the org's platform
All-or-nothing: the whole batch runs in one transaction. If any item disables a
platform-required column, the entire request is rejected with
ACCOUNTINGCOLUMNCONFIG_BAD_REQUEST_CANNOT_DISABLE_REQUIRED_COLUMN and nothing is
written. Duplicate columnKeys in accountingColumns are rejected as a 400.
Cascade side-effect: disabling a column removes it from every member's
per-member display list (MemberOrganizationPreference types
ACCOUNTING_ITEM_CUSTOMIZED_COLUMN, ACCOUNTING_CARD_FEES_INTEREST_CUSTOMIZED_COLUMN,
ACCOUNTING_EXPENSE_CUSTOMIZED_COLUMN); enabling re-adds it only where missing. The
FE should re-fetch member preferences after a successful save if it caches them.
Errors
Status
Code
400
BAD_REQUEST_INVALID_ARGUMENTS (invalid/missing fields, bad columnKey, duplicate keys)
FORBIDDEN (organizationId is not the caller's org)
500
INTERNAL_SERVER_ERROR
Updated APIs
Updated
GETPOST/v1/ruttercustomfieldconfig/updateBreaking
Update enabled status for NetSuite/Rutter custom fields — now batch / array-only.
Auth: Must be logged in
Roles:member
Permissions: none
What changed
change Request is now array-only: the per-toggle fields id / rutterCustomFieldDefinitionId / enabled move inside an customFields: [...] array. Sending the old top-level single-item shape will now fail validation.
change Processing is all-or-nothing in one transaction — if any item is invalid, nothing is written.
remove The success response no longer returns the updated rutterCustomFieldConfig object on the update-by-id path; it now always returns just { status, success }.
Request body (new shape)
Field
Type
Required
Default
Description
organizationId
INTEGER
No
req.organization.id
Must equal the caller's organization, else 403
customFields
ARRAY
Yes
—
Min 1 item
customFields[].id
INTEGER
Cond.
—
Existing config row id (update). Mutually exclusive with rutterCustomFieldDefinitionId (xor)
customFields[].rutterCustomFieldDefinitionId
INTEGER
Cond.
—
Definition id (create). Mutually exclusive with id (xor)
RUTTERCUSTOMFIELDCONFIG_BAD_REQUEST_RUTTER_CUSTOM_FIELD_CONFIG_DOES_NOT_EXIST (an id item references a missing row)
401
UNAUTHORIZED
403
FORBIDDEN (cross-org id, or definition not on the org's platform)
500
INTERNAL_SERVER_ERROR
Model / Payload Changes
Schema
AccountingColumnConfig New table
Backs the accounting column toggles. Not serialized to the FE raw — consumed only via /accountingcolumnconfig/query, which returns the derived catalog shape above.
addorganizationId — BIGINT, FK → Organizations.
addcolumnKey — STRING, one of the catalog keys.
addenabled — BOOLEAN, default true.
FE impact: none directly — interact with this table only through the two
/accountingcolumnconfig/* endpoints. No new fields are added to existing serialized payloads.