# ACC6 Project Knowledge Base

> Purpose: This file is the persistent reference for the ACC6 accounting/ERP project.  
> Any AI assistant or developer must read this file before answering questions, generating code, debugging, or suggesting changes.

---

## 1. AI Usage Instructions

### 1.1 Required Reading Rule
Before working on ACC6, read this file first and treat it as the project source of truth unless newer source code, database output, or terminal output proves otherwise.

### 1.2 Response Rules
- Start with root-cause analysis before suggesting code changes.
- Do not apply quick patches unless explicitly requested.
- Preserve existing accounting logic unless the change is intentional and explained.
- Always return complete modified files, not snippets.
- Every returned PHP/JS/CSS/view file must start with a file path comment.
- For PHP files, use this style at the top:

```php
<?php
/* File Path: /20/acc6/path/to/file.php */
```

- For CSS/JS files, use:

```css
/* File Path: /20/acc6/path/to/file.css */
```

```js
/* File Path: /20/acc6/path/to/file.js */
```

### 1.3 AI Safety Rules
- Do not guess database columns; inspect schema or use dynamic column detection.
- Do not break F1 account picker behavior.
- Do not duplicate JavaScript listeners or create parallel search systems.
- Do not introduce Laravel, React, Vue, or framework migrations.
- Do not store real production passwords in a shared version of this file.
- If a fact is uncertain, say so and request the relevant file/output.

---

## 2. Project Identity

| Item | Value |
|---|---|
| Project | ACC6 ERP / Accounting System |
| Type | Native PHP ERP |
| UI | Arabic RTL desktop-style ERP |
| Backend | PHP Native + PDO MySQL |
| Frontend | jQuery / Vanilla JS / CSS |
| Server Path | `/var/www/vhosts/shneler.com/httpdocs/20/acc6` |
| URL | `https://www.shneler.com/20/acc6` |
| Database | `acc6` |
| Main DB User | `acc6` |
| Hosting | Plesk + Linux + Nginx/Apache |

> Security note: Keep real passwords only in a private local copy. In shared copies, replace passwords with placeholders.

---

## 3. Mandatory Terminal Rules

### 3.1 MySQL Command Style
Use `MYSQL_PWD` and never use `-p`.

```bash
DB_PASSWORD='REPLACE_WITH_PRIVATE_PASSWORD' MYSQL_PWD="$DB_PASSWORD" mysql --no-defaults -u acc6 acc6
```

### 3.2 Common Commands

```bash
cd /var/www/vhosts/shneler.com/httpdocs/20/acc6

php -l path/to/file.php

systemctl restart plesk-php83-fpm 2>/dev/null || systemctl restart plesk-php82-fpm 2>/dev/null
systemctl restart nginx 2>/dev/null
```

### 3.3 Backup Rule
Before modifying existing files:

```bash
cp -av path/to/file.php path/to/file.php.bak_before_CHANGE_NAME_$(date +%Y%m%d_%H%M%S)
```

---

## 4. Project Architecture

### 4.1 Important Folders

```text
app/
  Controllers/
  Services/
  Core/
resources/
  views/
public_assets/
  js/
  css/
database/
  patches/
  migrations/
tools/
storage/
  backups/
```

### 4.2 Important Core Files

```text
routes.php
index.php
app/Core/App.php
app/Core/Router.php
app/Core/Controller.php
app/Core/Database.php
app/Core/helpers.php
resources/views/layouts/app.php
public_assets/js/app.js
public_assets/css/app.css
```

---

## 5. Critical Existing Features

### 5.1 F1 Account Picker
The F1 account picker must be preserved completely.

Must preserve:
- F1 keyboard behavior.
- Account search popup.
- Account field filling.
- Opening account statement / ledger.
- ERP window behavior.
- Stable logic in `public_assets/js/app.js`.

Do not:
- Add duplicate F1 listeners.
- Add another account picker engine.
- Break existing account search behavior.

### 5.2 Smart Select/Search Rule
All select/search fields must be smart:
- Show results immediately when opened.
- Search from the first typed letter or number.
- Re-show all results when cleared or reopened.
- Work across all accountant screens.

Relevant files:
```text
public_assets/js/acc6-smart-selects.js
public_assets/css/acc6-smart-selects.css
```

---

## 6. Accounting Rules

### 6.1 Chart of Accounts Rules
- Parent accounts are summary only.
- Posting should happen on postable child accounts.
- Do not double-count parent balances.
- Totals must aggregate recursively from postable children.
- Trial balance, ledger, account statement, balance sheet, and income statement must reconcile.

### 6.2 Account Code Conventions
Common account groups:

```text
1 = Assets
2 = Liabilities
3 = Equity
4 = Revenue
5 = Operating Expenses
6 = Cost of Sales
7 = Other Income
8 = Other Expenses
9 = Statistical/System
```

### 6.3 Financial Report Rules
Trial balance:
```text
Total Debit = Total Credit
Difference = 0.000
```

Income statement:
```text
Revenue - Cost of Sales - Expenses + Other Income - Other Expenses = Net Income
```

Balance sheet:
```text
Assets = Liabilities + Equity
```

Inventory:
```text
Ending Quantity = Opening + In - Out
Ending Value must match inventory movements/costing logic.
```

---

## 7. Key Database Tables

```text
accounts
account_categories
journal_entries
journal_items
customers
suppliers
items
warehouses
sales_invoices
sales_invoice_items
purchase_invoices
purchase_invoice_items
receipts
payments
inventory_movements
treasury_accounts
fiscal_years
fiscal_periods
financial_closings
account_opening_balances
document_sequences
companies
branches
users
roles
permissions
user_roles
role_permissions
```

---

## 8. Known Schema Notes

ACC6 database columns may differ from assumptions. Always inspect or use dynamic detection.

Known examples:
- Some document number fields may be numeric and unique.
- `journal_no`, `invoice_no`, `receipt_no`, `payment_no`, `movement_no` may reject text values.
- Some reports must rely on account codes, not only `account_type`.
- Some invoice tables may use `total` or `subtotal` rather than `total_amount`.

---

## 9. Current Implemented Pro Features

### 9.1 Accounting Workspace
Purpose: Main accountant dashboard / workspace.

Typical URL:
```text
index.php?page=accounting_workspace
```

### 9.2 Account Statement Pro
Purpose: Professional account statement.

Typical URL:
```text
index.php?page=account_statement_pro
```

Relevant files:
```text
app/Controllers/AccountStatementProController.php
app/Services/AccountStatementProService.php
resources/views/reports/account_statement_pro.php
public_assets/css/acc6-accounting-statement-pro.css
```

### 9.3 Item Card Pro
Purpose: Professional inventory item card.

Typical URL:
```text
index.php?page=item_card_pro
```

Relevant files:
```text
app/Controllers/ItemCardProController.php
app/Services/ItemCardProService.php
resources/views/reports/item_card_pro.php
public_assets/css/acc6-item-card-pro.css
```

### 9.4 Balances Pro
Purpose: Unified balances page for customers, suppliers, treasury, and inventory.

Typical URL:
```text
index.php?page=balances_pro
```

Relevant files:
```text
app/Controllers/BalancesProController.php
app/Services/BalancesProService.php
resources/views/reports/balances_pro.php
public_assets/css/acc6-balances-pro.css
```

---

## 10. Current Debug Context

### 10.1 Demo Data
Demo data was generated to test all accountant screens.

Purpose:
- Validate dashboards.
- Validate trial balance.
- Validate income statement.
- Validate balance sheet.
- Validate account statements.
- Validate item card.
- Validate customers/suppliers balances.
- Validate receipts/payments and inventory cycle.

Demo data is temporary and must be deleted before real production use.

### 10.2 Operational Reset Feature
There is a system maintenance feature to reset demo/operational data before real use.

Requirements:
- Admin only.
- Strong typed confirmation.
- Automatic backup before reset.
- Delete operational data only.
- Preserve master data:
  - accounts
  - customers
  - suppliers
  - items
  - users
  - companies
  - branches
  - fiscal years and periods

---

## 11. Current Issues / Watch List

Update this section after every debugging session.

### 11.1 Balances Pro
Status:
```text
Needs verification in browser after service fixes.
```

Expected:
```text
Customer balances should show from sales invoices minus receipts.
Supplier balances should show from purchase invoices minus payments.
```

### 11.2 Income Statement
Status:
```text
Needs verification after ReportsController fix.
```

Expected:
```text
Account code 4 = revenue
Account code 5 = operating expenses
Account code 6 = cost of sales
Account code 7 = other income
Account code 8 = other expenses
```

### 11.3 Operating Cycle Review
Status:
```text
May show false warning if source_type names differ.
```

Expected:
```text
Accept source_type variations such as:
sales_invoice
sales_invoices
purchase_invoice
purchase_invoices
receipt
receipts
payment
payments
```

---

## 12. Validation Checklist

After any accounting/reporting change, test:

```text
/dashboard
/accounting_workspace
/balances_pro
/account_statement_pro
/item_card_pro
/trial_balance
/income_statement
/balance_sheet
/operating_cycle_review
/receipts
/payments
/sales_invoices
/purchase_invoices
```

### 12.1 Must Pass
```text
No HTTP 500.
No SQL unknown column errors.
Trial balance balanced.
Income statement shows real data.
Balance sheet balanced.
Account statement shows running balance.
Item card shows in/out/running balance.
Smart selects work from first character.
Print/PDF opens cleanly.
```

---

## 13. Standard Debug Commands

### 13.1 Route and File Search

```bash
grep -R "balances_pro\|BalancesProController\|balances_pro.php" -n routes.php app/Controllers resources/views 2>/dev/null
```

### 13.2 PHP Syntax

```bash
php -l app/Services/BalancesProService.php
php -l app/Controllers/ReportsController.php
```

### 13.3 Restart Services

```bash
systemctl restart plesk-php83-fpm 2>/dev/null || systemctl restart plesk-php82-fpm 2>/dev/null
systemctl restart nginx 2>/dev/null
```

### 13.4 Browser Cache
Use:
```text
Ctrl + F5
nocache parameter
private browser window
```

### 13.5 Opcache Reset
Use only when needed:

```bash
cat > public_assets/opcache_reset.php <<'PHP'
<?php
if (function_exists('opcache_reset')) {
    var_dump(opcache_reset());
} else {
    echo 'no opcache';
}
PHP

curl -k "https://www.shneler.com/20/acc6/public_assets/opcache_reset.php"
rm -f public_assets/opcache_reset.php
```

---

## 14. Development Decision Log

| Date | Decision | Reason |
|---|---|---|
| 2026-05 | Use ACC6 database, not ACC5 | Current production target is ACC6 |
| 2026-05 | Preserve F1 picker | Core ERP navigation feature |
| 2026-05 | Use dynamic column detection | Database columns differ across screens |
| 2026-05 | Add smart selects globally | Better accountant UX |
| 2026-05 | Use demo data for testing | Needed to validate final UI and reports |
| 2026-05 | Keep reset feature | Remove demo data before real launch |

---

## 15. Future Tasks

### 15.1 Short Term
- Verify Balances Pro in browser.
- Fix Income Statement if still zero.
- Fix Operating Cycle Review false warnings.
- Improve sales invoices Pro UI.
- Improve receipts/payments print consistency.
- Validate all print screens.

### 15.2 Medium Term
- Create unified accountant design system.
- Create unified report print layout.
- Create audit dashboard.
- Add report export options.
- Add better fiscal lock indicators.

### 15.3 Before Real Launch
- Reset all demo operational data.
- Confirm backup exists.
- Verify master data.
- Enter real opening balances.
- Validate first real invoice cycle.
- Lock old/demo periods if needed.

---

## 16. AI Update Strategy

After each meaningful change, update:
1. `Current Issues / Watch List`
2. `Implemented Pro Features`
3. `Development Decision Log`
4. `Future Tasks`
5. Any new file paths or database findings

Recommended rule:
```text
Every session ends by updating this file.
```

---

## 17. How an AI Should Use This File

When asked to help with ACC6:

1. Read this file first.
2. Identify the relevant module.
3. Ask for or inspect the current file if needed.
4. Diagnose root cause.
5. Avoid assumptions about DB columns.
6. Preserve existing behavior.
7. Return complete files with file path comment.
8. Provide terminal commands.
9. Provide validation steps.
10. Update this file with new decisions or findings.

---

## 18. Private Notes

> Keep this section only in a private copy.

```text
Do not put real passwords, tokens, SSH keys, private customer data, or production financial secrets in a shared AI context file.
```

---

## 19. Debug Finding - Balances Pro HTTP / Cache

Date: 2026-05-30

Finding:
- Testing protected ACC6 pages with plain `curl` may return login/empty output because the request has no authenticated browser session.
- `opcache_reset()` was executed and returned `bool(true)`.
- PHP-FPM and Nginx were restarted.
- If browser still shows zeros after cache reset, the issue is not only browser/opcache cache.
- Next debugging rule: compare the same service through CLI versus the browser route.

Current suspect:
- `BalancesProService` may return correct data in CLI but the browser page may still display old/zero data due to route/controller/service mismatch, duplicated class/file, or current service logic not being reached.

Required next test:
- Run `BalancesProService` directly from CLI using the same dates and compare with browser output.


---

## 19. Debug Finding - Balances Pro HTTP / Cache

Date: 2026-05-30

Finding:
- Testing protected ACC6 pages with plain `curl` may return login/empty output because the request has no authenticated browser session.
- `opcache_reset()` was executed and returned `bool(true)`.
- PHP-FPM and Nginx were restarted.
- If browser still shows zeros after cache reset, the issue is not only browser/opcache cache.
- Next debugging rule: compare the same service through CLI versus the browser route.

Current suspect:
- `BalancesProService` may return correct data in CLI but the browser page may still display old/zero data due to route/controller/service mismatch, duplicated class/file, or current service logic not being reached.

Required next test:
- Run `BalancesProService` directly from CLI using the same dates and compare with browser output.


---

## 20. Debug Finding - BalancesProService CLI Confirmed Correct

Date: 2026-05-30

Finding:
- `BalancesProService` was tested directly from CLI using:
  - section: customers
  - section: suppliers
  - date_from: 2026-01-01
  - date_to: 2026-05-30
  - show_zeros: true
- CLI result is correct.

Confirmed values:
- Customers:
  - debit: 920
  - credit: 700
  - closing_debit: 220
  - rows: 1
- Suppliers:
  - debit: 700
  - credit: 1580
  - closing_credit: 880
  - rows: 1

Conclusion:
- Demo data is valid.
- `BalancesProService` is calculating correctly.
- Remaining issue is in browser rendering, route/session execution, cache, or the displayed page state.
- Next rule: add a temporary debug output in the `balances_pro` view or controller to compare the actual `$data` reaching the browser.


---

## 21. Debug Finding - balances_pro Debug Injection Failed

Date: 2026-05-30

Finding:
- Attempted to inject temporary debug output into `resources/views/reports/balances_pro.php` using a long `perl -0pi` command.
- The command failed with:
  - `Unknown regexp modifier`
  - `Execution of -e aborted due to compilation errors`
- Therefore no debug block was inserted into the view.
- Browser did not show debug output because the file was unchanged.

Rule:
- Avoid very long inline `perl` replacements for PHP/HTML mixed files.
- Use a small PHP patch script or manual file replacement for safe modifications.


---

## 22. Debug Finding - Balances Pro Browser vs CLI Difference

Date: 2026-05-30

Finding:
- Temporary debug block was successfully added to `resources/views/reports/balances_pro.php`.
- Browser debug shows:
  - section: customers/suppliers
  - dateFrom: 2026-01-01
  - dateTo: 2026-05-30
  - showZeros: true
  - rows: 0
  - summary: empty/zero
- CLI test of `BalancesProService` with the same dates returns correct rows and totals.

Conclusion:
- `BalancesProService` can calculate correctly in CLI.
- Browser/controller execution returns empty data.
- Suspect difference between web DB connection, controller environment, loaded class path, session/company filters, or service invocation context.
- Next debugging step: add controller-level debug showing DATABASE(), DB user, service file path, table counts, and raw document totals from the same `$this->db` used by the controller.



---

## 24. Debug Finding - Short Debug Patch for Balances Pro

Date: 2026-05-30

Finding:
- Long terminal commands were difficult to paste safely in Plesk SSH terminal.
- A short patch workflow was introduced using `tools/add_balances_pro_full_debug.php`.
- This script patches both:
  - `app/Controllers/BalancesProController.php`
  - `resources/views/reports/balances_pro.php`
- The debug output should show:
  - database
  - db_user
  - controller_file
  - service_file
  - table counts
  - raw totals
  - service result summary
  - service result row count

Rule:
- Prefer short install scripts over long inline terminal patches.

---

## 26. Fix - Balances Pro reportData safe fix

Date: 2026-05-30

Finding:
- Browser controller debug proved service data was correct, but the view-level `` variable was empty.
- Root cause is a variable-name conflict with the base view renderer.

Fix:
- `BalancesProController` now passes ``.
- `balances_pro.php` maps `` to `` before rendering.

Rule:
- Avoid using generic `` as the main payload variable in complex views; use `` or a named view model.


---

## 27. Fix Confirmed - Balances Pro final fix confirmed

Date: 2026-05-30

Finding:
- Browser debug confirmed `BalancesProService` returned correct data.
- View was displaying zero because of `` variable conflict.

Fix:
- `BalancesProController` passes ``.
- `balances_pro.php` reads report payload from ``.
- Customer balances now display correctly in browser.

Confirmed customer values:
- Debit movement: 920.000
- Credit movement: 700.000
- Debit balance: 220.000

Next check:
- Verify suppliers section displays credit balance 880.000.
- Then continue fixing Income Statement if still zero.

---

## 30. Current Issue - Trial Balance HTTP 500

Date: 2026-05-30

Issue:
- `index.php?page=trial_balance` returns HTTP 500.
- This happened after recent report-related patches.
- Trial balance was previously working and balanced.

Most likely area:
- `app/Controllers/ReportsController.php`
- Report views under `resources/views/reports/`

Rule:
- Do not guess the fix.
- First inspect:
  - `php -l app/Controllers/ReportsController.php`
  - Plesk/site error logs
  - PHP-FPM logs

Required next step:
- Capture exact fatal error from server logs before patching.


---

## 33. Stabilization Confirmed - Core Reports Restored

Date: 2026-05-31

Status:
- System stabilized after restoring `app/Controllers/ReportsController.php` from stable backup:
  `ReportsController.php.bak_balances_income_20260530_105946`

Confirmed working pages:
- `index.php?page=dashboard`
- `index.php?page=trial_balance`
- `index.php?page=income_statement`
- `index.php?page=balance_sheet`
- `index.php?page=operating_cycle_review`

Root Cause:
- Recent experimental report patches caused `ReportsController.php` conflicts:
  - missing helper method
  - duplicated helper method
  - HTTP 500 in reporting pages

Decision:
- Stop experimental report patches.
- Keep stable restored controller.
- Continue development only with small, isolated, verified patches.

Current Rule:
- Before modifying `ReportsController.php`, make backup and test syntax immediately.
- Avoid adding helper methods unless confirming they do not already exist.
- Do not use long inline `php -r` or `perl` patches for major controller changes.

Next Priorities:
1. Clean temporary debug from `balances_pro` if still visible.
2. Verify customers/suppliers balances after stabilization.
3. Fix Operating Cycle Review warning logic carefully, without touching stable report controller.
4. Continue accountant UI improvements screen by screen.


---

## 34. Demo Seed Finding - journal_items requires line_no

Date: 2026-05-31

Issue:
- Minimal accounting cycle seed failed with:
  `Duplicate entry '1-0' for key 'uq_ji_line'`

Root Cause:
- `journal_items` has a unique key that likely includes:
  - `journal_entry_id`
  - `line_no`
- The seed script inserted multiple journal lines without explicit `line_no`.
- Database defaulted `line_no` to `0`, causing duplicate key errors.

Fix:
- Seed script must insert sequential line numbers into journal item rows:
  - `line_no`
  - `line_number`
  - `sort_order`
- Invoice item rows should also include line numbers to avoid similar unique-key issues.

Result:
- Failed seed attempt rolled back fully.
- No data was committed from the failed attempt.


---

## 36. Debug Finding - inventory_movements column mismatch

Date: 2026-05-31

Finding:
- Sales invoices are posted and exist:
  - 3 sales invoices
  - each total = 600
- Querying `inventory_movements.qty_in` and `inventory_movements.qty_out` failed with:
  `ERROR 1054 (42S22): Unknown column 'qty_in' in 'field list'`

Conclusion:
- ACC6 actual `inventory_movements` schema does not contain `qty_in / qty_out`.
- Any report or screen that checks sales invoice inventory matching using `qty_in / qty_out` will fail or show false mismatch.
- This likely explains:
  - Sales invoices page showing `غير مطابقة`
  - Sales invoices page showing inventory movements = 0
  - Operating Cycle Review warning about sales invoices vs inventory/cost

Next Step:
- Inspect actual columns using:
  `SHOW COLUMNS FROM inventory_movements`
- Then update sales invoice matching and operating cycle review logic to use dynamic column detection instead of fixed `qty_in / qty_out`.

Rule:
- Never assume inventory movement quantity column names.
- Use dynamic detection for:
  - quantity column
  - direction/type column
  - source_type/source_id columns
  - cost/value columns


---

## 37. Final Finding - Sales Inventory Matching Column Mismatch

Date: 2026-05-31

Finding:
- `inventory_movements` actual schema does not contain `qty_in` or `qty_out`.
- Actual columns are:
  - `movement_type`
  - `quantity`
  - `unit_cost`
  - `total_cost`
  - `source_type`
  - `source_id`
- Purchase movements are stored as:
  - `movement_type = in`
  - `source_type = purchase_invoice`
- Sales movements are stored as:
  - `movement_type = out`
  - `source_type = sales_invoice`

Confirmed:
- Sales invoices are posted and exist.
- Inventory outbound movements exist for sales invoices.
- Inventory balances are correct.
- Income Statement is correct.
- Trial Balance is balanced.

Root Cause:
- Sales invoices page and Operating Cycle Review likely use old/fixed inventory columns such as `qty_in` / `qty_out`, or incorrect source type matching.
- Therefore they show false mismatch: `غير مطابقة` and `حركات مخزون = 0`.

Correct Matching Rule:
- For sales invoices:
  - Join/check `inventory_movements.source_type = 'sales_invoice'`
  - `inventory_movements.source_id = sales_invoices.id`
  - `inventory_movements.movement_type = 'out'`
  - Quantity column = `quantity`
  - Value column = `total_cost`

Rule:
- Never assume `qty_in` / `qty_out`.
- Use dynamic inventory movement detection:
  - quantity: `quantity`
  - direction: `movement_type`
  - value: `total_cost`
  - source: `source_type`, `source_id`



---

## 38. Fix - Sales inventory matching accepts sales_invoice and sales_invoice_cogs

Date: 2026-05-31

Context:
- After clean reset and one minimal accounting cycle seed, dashboard and financial reports matched expected results.
- Sales invoice page still showed inventory movements = 0 and cost mismatch.

Root Cause:
- Sales invoice matching logic expected `inventory_movements.source_type = sales_invoice_cogs`.
- Actual inventory movements from the current cycle use `source_type = sales_invoice` with `movement_type = out`.

Fix:
- Matching now accepts both:
  - `sales_invoice`
  - `sales_invoice_cogs`

Affected files:
- `app/Controllers/SalesInvoicesController.php`
- `app/Controllers/ReportsController.php`

Rule:
- Sales inventory matching must not assume only `sales_invoice_cogs`.
- Accept current and older source types to keep compatibility.


---

## 40. UI Cleanup - Removed outdated sales duplicate warning

Date: 2026-05-31

Context:
- After clean reset and running the minimal accounting cycle seed once, sales invoices page had only one valid posted invoice.
- The page still displayed an old orange warning about duplicate invoices and drafts.

Finding:
- The warning text was static in `resources/views/sales/invoices.php` and not based on a real current duplicate check.

Fix:
- Removed the outdated orange warning block from the sales invoices page.

Confirmed before cleanup:
- Sales invoice count: 1
- Inventory movement count shown: 1
- Cost status shown: posted/matched
- Operating Cycle Review: green

Rule:
- Warnings should be data-driven only.
- Do not show old diagnostic messages after the underlying issue is fixed.

---

## 43. Sales Invoice UI Simplified and Confirmed

Date: 2026-05-31

Status:
- Sales invoices page works through:
  `/index.php?page=sales_invoices`
- Do not open internal view files directly, such as:
  `/resources/views/sales/invoices.php`
- Directly opening view files may return HTTP 500 because views require controller-provided variables.

Confirmed UI improvement:
- Fiscal year and fiscal period are no longer manual accountant selections in the sales invoice form.
- The accountant selects only the invoice date.
- The system displays the fiscal period automatically based on invoice date.
- If the invoice date is outside an open fiscal period, the form should prevent saving.

Confirmed current sales test:
- One posted sales invoice.
- Inventory movement count = 1.
- Cost status = posted/matched.
- Invoice status = posted.

Rule:
- All ERP pages must be opened through `index.php?page=...`.
- Internal files under `resources/views` are not browser entry points.



---

## 45. UI Fix - Purchase item picker button visibility

Date: 2026-05-31

Context:
- The purchase invoice item picker button was still not clear enough inside the invoice line table.
- The original select/dropdown was visually clipped by the table cell and scroll container.

Fix:
- Added stronger CSS/JS override for the purchase invoice item column.
- The original select remains in the form for backend compatibility but is visually hidden.
- A large modern button is shown instead.
- The selected item name is displayed clearly on the button.
- The button state changes when no item is selected.

Rule:
- Item selection inside invoice rows must be visibly clear and accountant-friendly.


---

## 46. UI Fix - Purchase invoice item card layout

Date: 2026-05-31

Context:
- The purchase item selector was still unclear inside the invoice table.
- User approved converting the item column into a wide card above other row fields.

Fix:
- Removed previous item picker experimental blocks.
- Converted purchase invoice rows visually into accountant-friendly cards.
- The item selector appears as a wide field at the top of each row card.
- Description, quantity, price, and account appear below in a clear grid.
- Original field names remain unchanged for backend compatibility.

Rule:
- If table dropdowns are visually clipped, prefer card-based row layout rather than forcing dropdowns inside narrow table cells.


---

## 47. UI Fix - Purchase line autofill and recalculation delegated fix

Date: 2026-05-31

Context:
- After converting purchase invoice lines to card layout, changing the item did not reliably update description or price.
- Increasing quantity did not always recalculate totals automatically.

Fix:
- Added delegated JavaScript listeners on `#purchaseInvoiceForm`.
- Item change now updates description, quantity when empty/zero, purchase price, line total, and invoice total.
- Quantity and price input/change/blur now refresh totals reliably.

Rule:
- Invoice row JS must use delegated events because rows and smart-select elements may be cloned or enhanced dynamically.


---

## 48. Routing Fix - Journal route alias fix

Date: 2026-06-01

Finding:
- `routes.php` had active routes for `journal_entries` but no route for `journal`.
- Opening `/index.php?page=journal` returned the dashboard/fallback instead of the new JournalController screen.

Fix:
- Added safe route alias: `journal` → `JournalController@index`.
- Existing `journal_entries` routes remain unchanged and still use `JournalEntriesController` for operational journal entry workflows.

Rule:
- UI menu/page aliases must match actual `routes.php` page keys. Do not rely on fallback routing.
