Files
wms-app/docs/reviewing/transaction-limits.md
T

5.8 KiB

Transaction Limits

Overview

Each company is assigned a package tier that defines how many documents they can create per day and per week. When a quota is hit, report endpoints return HTTP 402 — operations (create, edit, approve) are never blocked.


Package Tiers

Defined in app/config.php under $packages. Edit the array directly to adjust quotas or add tiers — no migration required.

Package Daily limit Weekly limit Locked on limit
free 10 30 dashboard, reports
starter 30 100 dashboard, reports
growth 150 500 dashboard, reports
pro unlimited unlimited nothing

lock_on_limit is an array of feature group keys. When either limit is hit, any endpoint that calls assertFeatureAccessible('<key>') returns 402 for that company until the quota resets.

A company's package is stored in wms.company_list.package (default 'starter'). Change it with:

UPDATE company_list SET package = 'growth' WHERE company_id = 1;

What Counts as a Transaction

One document created = one count. Updates to existing documents do not count.

Endpoint Document type
ics/api/engine/manage_stock_in.php Stock In
ics/api/engine/manage_stock_out.php Stock Out
ics/api/engine/manage_stock_transfer.php Stock Transfer
order/api/engine/manage_order.php WMS Sales Order
order/api/engine/confirm_order.php Auto-created WMS Invoice on confirm
order/api/engine/manage_invoice.php WMS Invoice / Credit Note
order/api/engine/proceed_to_invoice.php WMS Invoice from Sales Order
order/api/engine/manage_return.php Customer Return
order/api/engine/confirm_return.php Auto-created Credit Note on return confirm
order/api/engine/proceed_to_credit_note.php Credit Note from Customer Return
po/api/engine/manage_po.php Purchase Order
po/api/engine/manage_supplier_return.php Supplier Return
po/api/engine/confirm_supplier_return.php Auto-created Supplier Credit Note on supplier return confirm
po/api/engine/proceed_to_purchase_invoice.php Purchase Invoice from Purchase Order
po/api/engine/proceed_to_supplier_credit_note.php Supplier Credit Note from Supplier Return
revenue/api/engine/manage_order.php Revenue Sales Order
revenue/api/engine/proceed_to_invoice.php Revenue Invoice from Sales Order
revenue/api/engine/manage_credit_note.php Customer Credit Note
revenue/api/engine/manage_quotation.php Quotation
finance/api/engine/manage_receipt_billing.php Receipt Billing
finance/api/engine/manage_receipt.php Receipt
finance/api/engine/manage_payment_billing.php Payment Billing
finance/api/engine/manage_payment.php Payment
expense/api/engine/manage_purchase_request.php Purchase Request
expense/api/engine/manage_supplier_credit_note.php Supplier Credit Note

What Gets Locked

Two feature group keys are defined:

dashboard — gated on dashboard/report summary endpoints. The low-stock detail endpoint and accounting posting-window endpoint are not gated:

  • dashboard/api/engine_report/reports_stats.php (WMS dashboard)
  • ac_dashboard/api/engine/by_source.php
  • ac_dashboard/api/engine/journals.php
  • ac_dashboard/api/engine/pl.php
  • ac_dashboard/api/engine/recent.php
  • ac_dashboard/api/engine/trend.php

reports — gated on all report endpoints:

  • accounting/api/engine/get_trial_balance.php
  • accounting/api/engine/get_pl_statement.php
  • accounting/api/engine/get_balance_sheet.php
  • accounting/api/engine/get_gl_movement.php
  • accounting/api/engine/get_vat_report.php
  • reports/api/engine_report/stock_movement.php
  • reports/api/engine_report/stock_movement_sku.php
  • reports/api/engine_report/expired_stock.php
  • reports/api/engine_report/lot_stock_log.php
  • reports/api/engine_report/product_lot.php
  • reports/api/engine_report/rack_log.php
  • reports/api/engine_report/rack_occupancy.php

How Quotas Reset

  • Daily — resets at midnight each day. company_usage stores one row per company per day_date; a new day is a new row with count 0.
  • Weekly — resets at 00:00 Monday. The weekly count is the SUM of daily_count for all rows from Monday to today.

Database

wms.company_usage — one row per company per day:

CREATE TABLE company_usage (
    id          INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    company_id  INT(11) NOT NULL,
    day_date    DATE NOT NULL,
    daily_count INT(11) NOT NULL DEFAULT 0,
    PRIMARY KEY (id),
    UNIQUE KEY uq_company_day (company_id, day_date),
    KEY        idx_company_id (company_id)
);

Key Files

File Role
app/config.php $packages array — all tier definitions
app/assets/utils/classes/UsageGuard.php increment(), assertFeatureAccessible(), getStatus()
app/include_topbar.php Reads getStatus() on every page load; renders warning badge
app/assets/js/custom.js Global 402 handler in ajax_request — shows usage detail alert

Topbar Warning Badge

include_topbar.php calls UsageGuard::getStatus() on every page load and renders a badge in the nav bar:

  • ≥ 80% of either limit — amber badge showing percentage
  • ≥ 100% — red badge "Limit reached — reports locked"

Hovering the badge shows raw counts: Daily: 28/30 | Weekly: 87/100.


Adding a New Gated Feature

  1. Pick a key name (e.g. 'export').
  2. Add it to lock_on_limit arrays in the relevant package tiers in config.php.
  3. Add (new UsageGuard($pdo1, $company_id, $packages))->assertFeatureAccessible('export'); at the top of the target endpoint(s).