Location Budget Management


Budget Model Used by the App

Budgets in the current build are attached to a location.

Each budget record stores:

  • one year
  • one yearly amount
  • optional monthly amounts from January through December

The application prevents duplicate budget years for the same location.

Where Budgets Are Managed

Budgets are managed from the Budgets relation manager inside a location record.

The table currently shows:

  • Year
  • Yearly Amount

Available actions can include:

  • Create Budget
  • New Budget
  • Edit
  • Delete
  • Force Delete
  • Restore

The budget section is embedded inside the location record rather than exposed as its own top-level resource.

Creating a Budget

The budget form currently has two sections.

Budget Year

  • Year
  • Yearly Amount

Monthly Amounts

  • January through December

The yearly amount is required and must be zero or greater.

Monthly Allocation Rules

The current rules are:

  • monthly amounts are optional
  • if a month is left empty, the app can fall back to the yearly amount for budget checks and explanations
  • the total of all entered monthly amounts cannot exceed the yearly amount

This validation is enforced in the relation manager form.

How Budget Checks Work

Budget checks are performed on draft orders against the location budget for the order year.

Yearly budget check

The app:

  • loads the location budget for the order year
  • subtracts recorded budget transactions from the yearly amount
  • compares the order subtotal to the remaining yearly budget

Monthly budget check

The app:

  • looks up the budget field for the order month
  • subtracts recorded budget transactions for that month
  • compares the order subtotal to the remaining monthly budget

Important implementation detail

Budget checks rely on budget transactions, not on every draft order in every state.

That means the remaining budget calculation is based on recorded spending transactions rather than every pending order in the list.

Budget Transactions

A budget transaction is created when an order is sent successfully to Shopify and completed.

The transaction stores:

  • the budget
  • the draft order
  • the amount
  • a description
  • the transaction date

This is why completed purchasing activity affects future budget availability calculations.

Policy-Based Permissions

The current code uses more than one policy check around location budgets.

Location-level budget access

LocationPolicy::manageLocationBudgets() allows the budget relation manager to become writable for:

  • CompanyAdmin
  • BudgetAdmin when the user is attached to that location

Budget-action authorization

The create, edit, delete, restore, and force-delete actions also call updateLocationBudget.

That means practical button visibility depends on both:

  • the location-level budget permission check
  • the dedicated budget policy method used by the actions

For documentation purposes, the safest user-facing description is:

  • CompanyAdmin is the primary budget-management role
  • BudgetAdmin is intended to manage budgets for assigned locations
  • other roles should be treated as read-only for budget management