Spec (docs/reviewing/master-data.md): - M1: Remove margin from stored product fields (it's a derived frontend value) - M2: Clarify posting window only restricts transaction dates, not master data - M5: Document AccountFormulaManager::delete() as archive, not physical delete Code: - C1: Fix CompanySettingManager property typo (company_id → companyId) — prevented PHP 8.4 dynamic property fatal on all posting window operations - C2: Fix WarehouseManager::deleteWarehouse() guard — was comparing warehouse_name (string) against warehouse id column (no-op); now correctly blocks on storage rows and active stock rows - M3: Remove hard-delete of td_rack_log in deleteStorage() — retain rack history consistent with soft-delete philosophy elsewhere - M4: Add reference guards to ChartOfAccounts::delete() (blocks on GL items, formula items, product account mappings) and DepartmentManager::delete() (blocks on GL items) - M6: Fix CompanySettingManager::handle() partial update — only upsert keys present in the request, not all allowed keys defaulted Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.0 KiB
Master Data Features
Products
Routes:
app/inventory/product.phpapp/inventory/manage_product.phpapp/inventory/manage_category.phpapp/inventory/api/engine/product.phpapp/inventory/api/engine/manage_product.phpapp/inventory/api/engine/product_category.php
Products store SKU, product name, barcode, UOM, price, cost price, min stock, reorder point, category, image, status, and GL mapping fields. Margin is a derived display value (price − cost price) computed on the frontend and is not stored.
Product accounting fields:
sales_account_codepurchase_account_code
These fields support Product Account Mapping for GL posting.
Accounting users can maintain only these two GL mapping fields from app/accounting/account_formulas.php without opening the full product edit page.
Backend support:
ProductManager::getProductList()ProductManager::saveProduct()ProductManager::deleteProduct()ProductManager::updateAccountMapping()
Product Categories
Routes:
app/inventory/manage_category.phpapp/inventory/api/engine/manage_category.phpapp/inventory/api/engine/product_category.php
Product categories organize products and are protected from deletion when active products or stock depend on them.
Backend support:
ProductManager::getCategoryList()ProductManager::saveCategory()ProductManager::deleteCategory()
Warehouse Locations
Routes:
app/inventory/warehouse.phpapp/inventory/manage_warehouse.phpapp/inventory/manage_storage.phpapp/inventory/api/engine/warehouse.phpapp/inventory/api/engine/manage_warehouse.phpapp/inventory/api/engine/storage.phpapp/inventory/api/engine/manage_storage.php
Warehouse setup manages warehouses and storage hierarchy. WMS forms use warehouse, zone, aisle, and rack data for stock movement, barcode labels, validation, and capacity reporting.
Backend support:
WarehouseManagerReportManagercapacity and occupancy methods
Contacts
Routes:
app/contact/contact.phpapp/contact/manage_contact.phpapp/contact/manage_contact_type.phpapp/contact/api/engine/contact.phpapp/contact/api/engine/manage_contact.phpapp/contact/api/engine/contact_type.php
Contacts represent customers, suppliers, or other counterparties. Contact records support type/category, image upload, status, search, and transaction references from sales, purchase, receipts, and payments.
Backend support:
ContactManager::getContactList()ContactManager::searchContact()ContactManager::saveContact()ContactManager::deleteContact()ContactManager::saveContactType()
Chart Of Accounts
Routes:
app/accounting/chart_of_accounts.phpapp/accounting/manage_account.php
Chart of Accounts is master data for accounting. Each account has code, name, type, category, parent, posting flag, and status.
Important account categories:
sales_taxpurchase_tax
These categories feed VAT reporting.
Backend support:
ChartOfAccounts
Departments
Routes:
app/accounting/departments.phpapp/accounting/manage_department.php
Departments are accounting dimensions used by formulas, journals, and reports. They can be active or inactive.
Backend support:
DepartmentManager
Account Formulas
Routes:
app/accounting/account_formulas.php
Account Formulas are master setup for automated GL posting. They are maintained separately from actual journal entries.
AccountFormulaManager::delete() is an archive operation, not a physical delete. It sets status = 0 and clears the is_default flag on md_account_formula. The formula row and its line items remain in the database. Historical GL entries in td_gl that reference the formula via formula_id continue to point to the archived row — this is intentional, as the snapshot is preserved for audit and re-post replay. An archived formula can no longer be selected for new postings (isPostingAccount() requires status = 1) but existing GL history is unaffected.
Formula setup includes:
- Document type.
- Formula name.
- Default flag.
- Status.
- Debit/credit formula lines.
- Amount key per line.
- Posting account per line.
Backend support:
AccountFormulaManager
Posting Window
Routes:
app/accounting/posting_window.php
Posting Window is master configuration for accounting/inventory date control. It can define no restriction, a lower date, an upper date, or a bounded posting period.
The posting window restricts transaction document dates only — GL postings, stock movements, receipts, payments, and invoice issuance. It does not restrict saves or deletes of master data records (products, contacts, warehouses, chart of accounts, departments). Master data edits are always permitted regardless of the posting window.
Backend support:
CompanySettingManager— stores and retrieves the window bounds as company settings (posting_open_from,posting_open_to)PostingWindowGuard— enforces the window; called byGlManagerandWarehouseManagerstock-movement paths, not by master-data managers