# EIMS Beta — Full Todo List
> Last updated: 2026-05-31
> Project: D:\Dev\projects\isinternet\beta
> Current HEAD: c2e947c

---

## 🔴 CRITICAL BUGS (broken right now)

- [x] **Platform dashboard BROKEN** — view loops over `$tenantStats` (old variable) but controller now sends `$tenants` (paginated), `$profileStats`, `$revenueStats`. Fixed: view rewritten to use new variables with `{{ $tenants->links() }}` pagination.

---

## 🔐 SECURITY

- [x] Fix API login SQL operator precedence — inactive users could log in via email/username (`Api/V1/AuthController::login()`)
- [x] Remove duplicate `SESSION_DOMAIN=null` from `.env` — session cross-subdomain isolation was broken
- [x] Add `EnsurePlatformAdmin` middleware — `/platform/*` routes are now gated to `super-admin` role
- [x] Add `InitializeTenancyFromUser` middleware — API routes now correctly initialize tenancy from token owner's `tenant_id`; `HasTenant` global scope was returning all-tenant data on API calls
- [x] Add `can:` permission middleware to **all** tenant routes (customers, packages, villages, departments, users, bills, payments, tax/discount configs, reports, logs, settings)
- [x] **Deployment routes unprotected** — Fixed: `platform.admin` middleware added to `/settings/deployment/*` routes.
- [x] **`export-reports` permission not enforced** — Fixed: `$this->authorize('export-reports')` added to all three export blocks in `ReportsController`.

---

## 🐛 FIXED BUGS (for reference)

- [x] `LogsController::sessions()` was using wrong column names (`logged_in_at` → `login_at`, `logged_out_at` → `logout_at`, `ip_address` → `ip`)
- [x] `resources/views/tenant/logs/sessions.blade.php` was referencing wrong column names
- [x] `Api/V1/BillsController` had 5 bugs: invalid `max()` call, `label` → `description`, phantom `quantity` column
- [x] `LedgerEntry` was never created on payment — ledger view was always empty
- [x] `Platform/DashboardController` was doing O(n) `tenancy()->initialize()` loop for every tenant — replaced with aggregate SQL queries

---

## 🧩 MISSING UI (model + migration + permission exist — no controller/views/routes)

### Payment Method Configurations
- [x] **Controller** — `PaymentMethodConfigurationsController` created
  - Model: `App\Models\PaymentMethodConfiguration` ✅
  - Migration: `payment_method_configurations` table ✅
  - Permission: `manage-payment-methods` ✅
- [x] **Views** — `resources/views/tenant/settings/payment-methods.blade.php` created with toggle/configure UI
- [x] **Routes** — `GET/PATCH /settings/payment-methods` with `can:manage-payment-methods` added

### Installment Plans
- [ ] **Controller** — no `InstallmentPlansController` exists
  - Models: `App\Models\InstallmentPlan`, `App\Models\InstallmentSchedule` ✅
  - Migration: `installment_plans`, `installment_schedules` tables ✅
  - Permissions: `create-installment-plans`, `edit-installment-plans`, `cancel-installment-plans` ✅
  - `Bill` model has `installmentPlan()` relationship and `STATUS_INSTALLMENT` constant — never used
- [ ] **Views** — create plan form on bill detail, plan overview, schedule list with mark-paid actions
- [ ] **Routes** — `POST /bills/{bill}/installment-plan`, `GET/PATCH/DELETE /installment-plans/{plan}`

### Customer Bulk Import
- [ ] **Controller** — no import controller exists
  - Permission: `import-customer-profile` ✅ (defined in seeder, assigned to billing-staff+)
- [ ] **View** — CSV upload form with field mapping, validation summary, preview before commit
- [ ] **Route** — `GET/POST /customers/import` with `can:import-customer-profile`

### Send Bill (Email / WhatsApp)
- [ ] **Controller** — no send-bill feature in beta (only in legacy `sendA4BillController.php`)
  - Permission: `send-bills` ✅
- [ ] **Queue job** — send PDF attachment via Mail or Twilio/WhatsApp
- [ ] **Route** — `POST /bills/{bill}/send` with `can:send-bills`
- [ ] **View** — send confirmation modal on bill detail page

---

## 🗂️ SETTINGS — MISSING SECTIONS

The settings page at `/settings` currently only has Business Info.

| Section | Gate Permission | Status |
|---|---|---|
| Business Info (name, phone, email, address, logo, proprietors) | `manage-tenant-settings` | ✅ Done |
| **Payment Methods** (enable/disable methods, account nos., surcharge %) | `manage-payment-methods` | ❌ Not started |
| **Bill Settings** (default due days, late fee type/amount, bill # prefix, auto-generate day) | `manage-tenant-settings` | ❌ Not started |
| **Notification Settings** (SMS/email on bill gen, X-day reminder, overdue alert) | `manage-tenant-settings` | ❌ Not started |
| **Roles & Permissions UI** (list roles, assign permissions per role, assign role to user) | `manage-roles` + `assign-permissions` | ❌ Not started |

> Tax & Discount configurations already exist at `/configurations/taxes` — can link from settings page as a shortcut.

---

## 🖥️ UI / UX GAPS (feature works but no access point)

- [x] **Settings link missing from tenant navigation** — Fixed: added to More dropdown and responsive nav under `@can('manage-tenant-settings')`.
- [x] **Payment proof not shown** — Fixed: `payments/show.blade.php` now shows a download link; `PaymentsController::proof()` serves the file via `Storage::disk('local')->response()`; route `GET /payments/{payment}/proof` added.
- [x] **Bill generation form misleads user** — Fixed: amber info banner added explaining async processing; submit button disables on click with "Queuing bills…" text.
- [x] **Platform dashboard pagination** — Fixed: `{{ $tenants->links() }}` added to view.

---

## 📊 REPORTS

- [x] Monthly income report (Excel export)
- [x] Outstanding dues report (Excel export)
- [x] Package-wise revenue report (Excel export)
- [x] Ledger view (income/expense entries — now populated via auto LedgerEntry on payment)
- [x] **`export-reports` permission not enforced** — Fixed (see Security section)
- [x] **Expense entries UI** — `add-expenses` permission now enforced; modal form on ledger page to add manual expense `LedgerEntry` (POST `/reports/ledger/expenses`).
- [ ] **Ledger balance summary** — ledger view shows entries list but no running balance or income vs expense totals at the top

---

## 🌐 PLATFORM / SUPER-ADMIN

- [x] **Platform dashboard view update** — Fixed (see Critical Bugs)
- [x] `EnsurePlatformAdmin` middleware on all `/platform/*` routes
- [x] **Deployment routes need super-admin gate** — Fixed: `platform.admin` added
- [ ] **Platform tenant edit page** — `TenantsController::update()` exists but there's no edit view (`resources/views/platform/tenants/edit.blade.php`). Only `show.blade.php` exists.
- [ ] **Tenant suspension enforcement** — `isSubscriptionActive()` exists on Tenant model but no middleware checks it. Expired/suspended tenants can still log in and use the system.

---

## 📱 API (Mobile)

- [x] API login SQL operator precedence bug fixed
- [x] API tenant context fixed (InitializeTenancyFromUser middleware)
- [x] Rate limiting on auth endpoints (throttle:10,1)
- [x] **API: Permission enforcement on API controllers** — Fixed: `abort_if(! $request->user()->can(...), 403)` added to `index`, `show`, `store` on `BillsController`, `PaymentsController`, `CustomersController`.

---

## 🔧 TECHNICAL DEBT / IMPROVEMENTS

- [ ] **Queue worker not auto-started** — `GenerateTenantBillsJob` is dispatched to the queue but if `QUEUE_CONNECTION=sync` (default for local), it still runs inline. Production needs `QUEUE_CONNECTION=database` (or Redis) and a running `php artisan queue:work` process. Add this to deployment docs.
- [ ] **Failed job handling** — no `php artisan queue:failed` monitoring. If bill generation fails mid-loop, partial bills are committed (no rollback at job level). The job uses a single DB transaction which helps, but failure alerting is needed.
- [ ] **`manage-departments` permission not in all role assignments** — only added to `manager` role. Consider whether `admin` role (which gets `*`) still needs it explicitly, and whether `billing-staff` needs it.
- [ ] **Seeder re-run safety** — `RolesAndPermissionsSeeder` uses `firstOrCreate` for permissions but if a tenant has old permission data and seeder is re-run after adding `manage-departments`, the manager role in existing tenants won't auto-get the new permission.
- [ ] **`payment_proof` storage** — files are stored in `local` disk (`storage/app/payments/proofs`). Not publicly accessible. Need a signed URL or a controller endpoint `GET /payments/{payment}/proof` to serve the file securely.
- [ ] **Tenant logo storage** — settings page stores logo to `public` disk. But `php artisan storage:link` must have been run. If not, logos won't display.

---

## ✅ COMPLETED SUMMARY

| Area | Done |
|---|---|
| Security: SQL login bug | ✅ |
| Security: SESSION_DOMAIN | ✅ |
| Security: Platform admin gate | ✅ |
| Security: API tenant context | ✅ |
| Security: Route-level authorization | ✅ |
| Bugs: LogsController columns | ✅ |
| Bugs: Sessions view columns | ✅ |
| Bugs: API BillsController 5 bugs | ✅ |
| Bugs: LedgerEntry never created | ✅ |
| Bugs: Platform dashboard O(n) loop | ✅ |
| Feature: Queue bill generation | ✅ |
| Feature: Tenant settings page | ✅ |
| Feature: Payment proof upload | ✅ |
| Feature: manage-departments seeder | ✅ |

---

*This file lives at `TEMP/TODO.md` — not committed to git.*
