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

144 lines
5.8 KiB
Markdown

# 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:
```sql
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:
```sql
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).