# DAMAC App & System — Update Plan: Technical Implementation Spec

> Source: *Damac App & System — Update & Enhancement Plan* (NCIT Solutions, June 2026, v1.0)
> Covers both repos: **Dashboard** (`d:\Damac-Dashboard`, Laravel 10 + Eloquent + Sanctum) and **Mobile** (`D:\Damac-Mobile`, React Native 0.76 + TS).
> Pillar 1 (Relationship Management / foundation) is specified to migration + endpoint + screen level. Later pillars are specified at design level and will be expanded to that depth before each is built.

---

## 0. Conventions & shared infrastructure (build once, used everywhere)

These cross-cutting pieces are prerequisites for Pillar 1 and beyond. Build them first.

### 0.1 Parameter / settings store  *(satisfies [HS3], [HS8], and the "parameter file" comments)*
Several comments ask for values "kept in the parameter files in the backend" — maintenance request types, utility-bill types, unread-reminder period, OTP TTL, etc. Implement a single configurable settings store rather than scattering them.

- **Migration** `create_settings_table`: `id`, `group` (e.g. `maintenance`, `billing`, `messaging`, `auth`), `key`, `value` (json/text), `type` (`string|int|bool|json`), `is_editable` (bool), timestamps.
- **Model** `App\Models\Setting` with `Setting::get('messaging.unread_reminder_days', 3)` / `Setting::set(...)` helpers and a request-cached read.
- **Admin UI**: `Admin/SettingsController` + a "System Parameters" screen grouped by `group`.
- **Seeder** `SettingsSeeder` with defaults for every parameter referenced below.

### 0.2 OTP service (reuse for 1.2, 1.5/[HS4], 5.2)
The current OTP logic lives inline on `User::sendOTP/verifyOTP` (login only). Extract into `App\Services\OtpService` with a **purpose** discriminator so the same mechanism gates different actions:
- `OtpService::issue(User $user, string $purpose)` → cache key `otp_{purpose}_{user_id}`, TTL from `Setting::get('auth.otp_ttl_minutes', 10)`.
- `OtpService::verify(User $user, string $purpose, string $code): bool`.
- Purposes: `login`, `contact_change` (1.2), `agent_grant` (1.5/[HS4]), `meeting_join` (5.2).

### 0.3 Approvals log  *(satisfies [HS11] + cross-cutting Traceability)*
A single polymorphic approval/audit log used by profile changes, payment plans, work/maintenance, and guest/worker access.
- **Migration** `create_approvals_table`: `id`, `type` (`profile_change|payment_plan|maintenance|access`), `approvable_type`, `approvable_id` (morphs), `requested_by` (user), `approved_by` (nullable user), `status` (`pending|approved|rejected`), `payload` (json snapshot), `decided_at`, `notes`, timestamps.
- **Model** `App\Models\Approval` (morphTo `approvable`).
- Admin "Approvals" inbox with filters by `type`/`status`; approve/reject actions write `decided_at` + notification.
- Every approval-gated flow below creates an `Approval` row.

### 0.4 Activity / audit trail (cross-cutting Traceability)
Add `spatie/laravel-activitylog` (or a minimal `activity_log` table) and log create/update/delete + key actions (payments, authorizations, votes) with actor + timestamp. Lower priority than 0.1–0.3 but wire the trait into models as they are touched.

### 0.5 Role matrix (cross-cutting Role-based access)
Current roles: admin (id 1) + default (id 2). Introduce explicit roles and a helper layer:
- Roles: `admin`, `employee`, `owner`, `agent`, `security`.
- Seeder to create them + map permissions.
- `User::hasRole()` already exists; add convenience accessors `isOwner()`, `isAgent()`, `isSecurity()`.
- API middleware `role:owner` / `role:security` etc. for endpoint gating (see 1.5).

### 0.6 Bilingual (EN/AR) (cross-cutting)
- Dashboard: `resources/lang/en` + `resources/lang/ar`, `__()` keys for new UI; mPDF already ships Arabic fonts.
- Mobile: add `i18n` (e.g. `i18next` + `react-native-localize`) with `en`/`ar` resource files and RTL handling. Net-new for mobile — scoped as its own task, applied to new screens first.

---

## PILLAR 1 — Relationship Management  *(PRIORITY)*

### 1.1 Building Information — registry extensions + [HS1] shops

**Goal:** Units carry type/area/building/number + allocated parking; community has shared facilities, amenities, and shops with map location/direction.

**Dashboard — migrations**
1. `add_fields_to_units_table`: add
   - `unit_type` (string, nullable) — e.g. apartment, studio, penthouse, shop, office.
   - `area_sqm` (decimal, nullable) — distinct from existing `title_deed_area`.
   - `building` (string, nullable), `unit_number` (string, nullable).
   - `parking_spot` (string, nullable) — allocated spot label (links to `parking_spots` in 3.2 when present).
   - `floor` (string, nullable).
2. `add_fields_to_properties_table`: `latitude`, `longitude` (decimal, nullable), `description` (text, nullable).
3. `create_facilities_table` (shared facilities & amenities): `id`, `property_id` (nullable = community-wide), `name`, `type` (`pool|gym|parking|lobby|amenity|other`), `description`, `latitude`, `longitude`, timestamps + soft deletes.
4. `create_shops_table` *([HS1])*: `id`, `property_id` (nullable), `name`, `category`, `description`, `unit_id` (nullable link), `floor`, `latitude`, `longitude`, `directions` (text), `phone`, `logo_path`, `is_active`, timestamps + soft deletes.

**Dashboard — models / controllers / views**
- Update `Unit::$fillable` with the new columns; add `parkingSpot()` relation later.
- New `Facility`, `Shop` models.
- `Admin/FacilityController`, `Admin/ShopController` (resource CRUD + DataTables), nav entries.
- Extend Unit create/edit Blade forms with the new fields.

**Dashboard — API**
- `GET /api/v1/mobile/facilities` (+ `?property_id=`).
- `GET /api/v1/mobile/shops` (+ filters); each shop returns lat/lng + `directions`.
- Extend existing `GET /units` payload with the new unit fields.

**Mobile**
- New `FacilitiesScreen` and `ShopsScreen` (list + detail). Shop detail shows map pin + "Get directions" (deep-link to Google/Apple Maps via `Linking`).
- `UnitDetailsScreen` (currently a stub) → render type, area, building/number, floor, parking spot.
- Add nav entries (likely under the Units tab or Menu).

### 1.2 Owner Information + [HS2] OTP-gated contact change

**Dashboard**
- Owner profile already covered by `User`. Add endpoint `PUT /api/v1/mobile/user/contact` that:
  1. requires an OTP issued via `OtpService::issue(user,'contact_change')`,
  2. on verify, updates email/phone,
  3. writes an `Approval` row of type `profile_change` (per [HS11]).
- New endpoint `POST /api/v1/mobile/user/contact/request-otp`.
- Admin: surface profile-change approvals in the Approvals inbox (0.3).

**Mobile**
- `ProfileScreen`: editing email/phone now triggers an OTP step (reuse `EmailOTPScreen` UI in `purpose=contact_change` mode) before saving.

### 1.3 Messaging & Announcements + [HS3] unread-reminder scheduler

Push/news/QA already exist. Add the unread-reminder loop.
- **Migration**: `messages`/`announcements` read tracking — add `read_at` to the per-user notification/announcement pivot (create `announcement_user` pivot if announcements are broadcast: `announcement_id`, `user_id`, `read_at`, `last_reminded_at`).
- **Command** `app:send-unread-reminders` (scheduled in `Console/Kernel`): for announcements/messages unread for ≥ `Setting::get('messaging.unread_reminder_days')`, resend push (reuse `PushNotificationService`) and stamp `last_reminded_at`; stop once `read_at` set.
- **Mobile**: mark-as-read call when an announcement/thread is opened (`POST /messages/{id}/read`).

### 1.4 Owner's Agent — agent↔owner linkage  *(net new)*

**Dashboard — migration** `create_owner_agent_table`:
`id`, `owner_id` (user), `agent_id` (user), `relationship`/`title` (string), `phone`, `email`, `can_view_financials` (bool, default false — toggled in 1.5/[HS4]), `can_pay` (bool, default false), `status` (`active|revoked`), `granted_at`, `revoked_at`, timestamps.
- **Model** `OwnerAgent` + `User::agents()` / `User::ownersRepresented()` (belongsToMany through this table).
- **Admin** `Admin/OwnerAgentController` to view/manage linkages; owners manage their own via app.

**Mobile**
- Owner: "My Agents" screen — invite/link an agent, see status, grant/revoke (grant/revoke financial access uses OTP, see 1.5).
- Agent: sees which owners they represent.

### 1.5 Owner vs Agent Visibility — enforcement + [HS4] OTP financial grant + agent pay

**Rule:** owners = full; agents = reporting/viewing only; agents see financial data **only** when the owner granted it (OTP), and may pay when `can_pay` is set.

**Dashboard**
- Middleware `EnsureOwner` (blocks agents from owner-only endpoints: voting, full financial unless granted).
- A resolver `ActingContext` so an agent can act "on behalf of owner X" — endpoints accept `?on_behalf_of=owner_id` and verify an active `OwnerAgent` link.
- Financial endpoints check `OwnerAgent.can_view_financials`; payment endpoints check `can_pay`.
- Grant/revoke flow: `POST /api/v1/mobile/agents/{agent}/financial-access` requires OTP (`purpose=agent_grant`), writes `Approval` + toggles flags + logs activity.

**Mobile**
- Conditional rendering by role: agent build hides Financial (unless granted) and Elections; shows Maintenance reporting.
- Owner sees everything.

### 1.6 Maintenance Request Types + [HS5] "Other" free-text

**Dashboard — migration** `create_maintenance_types_table`: `id`, `name_en`, `name_ar`, `default_priority`, `route_to` (team/vendor spec), `is_active`, `sort`, timestamps. Seed: water leak, electrical, general repair, common-area, + "Other".
- Add `maintenance_type_id` (nullable FK) and keep existing `specify` as the [HS5] free-text "short description" used when type = Other.
- Admin CRUD for types (also editable as parameters). 
- This table feeds routing/priority in Pillar 5.

**Mobile**
- `NewMaintenanceRequestScreen`: replace/augment free text with a **type picker** (from API) + show free-text "describe" box when "Other" chosen.
- New endpoint `GET /api/v1/mobile/maintenance-types`.

### Pillar 1 build order
1. Shared infra 0.1 (settings), 0.2 (OTP service), 0.3 (approvals), 0.5 (roles).
2. 1.1 registry migrations + admin CRUD + API.
3. 1.6 request types (small, unblocks Pillar 5).
4. 1.4 owner/agent model.
5. 1.5 visibility enforcement + [HS4].
6. 1.2 OTP contact change.
7. 1.3 unread-reminder scheduler.
8. Mobile screens for each, then EN/AR (0.6) on the new screens.

---

## PILLAR 5 — Maintenance Reporting (build 2nd; extends existing)

- **Status lifecycle**: replace 2-state with `Submitted → Acknowledged → In Progress → On Hold → Resolved → Closed`. Migration: change `maintenances.status` to enum/string + `create_maintenance_status_history` (status, changed_by, note, timestamp) for the audit trail.
- **Categorization & routing**: use `maintenance_type_id` (1.6) `default_priority` + `route_to` to auto-assign team/vendor; add `priority` column.
- **Assignment & accountability**: extend `Workorder` with labor/parts log table, internal notes, completion record.
- **Notifications**: push/email on each status change (reuse 1.3 backbone); on `Resolved`, prompt requester to confirm (`confirmed_at`).
- **Agent reporting**: agents submit/view on behalf (1.5 ActingContext).
- **Analytics**: `Admin/MaintenanceReportController` — by building, unit, type, response time, cost; export PDF/Excel. Feeds budget (2.2).
- **History/audit**: per-unit maintenance history endpoint + screen.
- **[HS10] deposit cheque details** (noted under access cards 3.5 but build the field set here/with 3.5): cheque no, bank, amount, date, status.
- **Mobile**: status timeline on `ViewMaintenanceRequestScreen`, confirm-resolution action, history view.

---

## PILLAR 3 — Financial Relation & Position (build 3rd; owner-only)

- **2.1 Owner-only + Gov data + [HS9] HOA accounting API**: enforce owner-only (1.5). Add `App\Services\HoaAccountingService` (realtime API client — needs endpoint/credentials from client) and `App\Services\GovDataService` for official records. *Blocked on external API specs — flag for client.*
- **2.2 Annual Budget & Schedules (EN/AR) + [HS7] payment-plan scheduling**:
  - `create_budgets_table` (year, property_id, planned vs actual lines, EN/AR labels) + `budget_lines`.
  - `create_payment_plans_table` (preset templates: name, installments, schedule) — admin-defined; owner **selects a plan only**.
  - `create_owner_payment_schedules_table` (owner_id, plan_id, status `pending_approval|approved`, due dates) → admin approval (0.3) → reminders on each due date (scheduled command).
- **2.3 Account Statements**: `Admin`+`mobile` statement view = running ledger per unit/owner from invoices+payments (+Abivia ledger). `GET /api/v1/mobile/statement`.
- **2.4 Utility Bills + [HS8] bill types param**: `create_utility_bills_table` (unit_id, type_id, amount, period, due) + `utility_bill_types` (parameterized via 0.1). Admin adds; reflected in owner account/invoices.
- **2.5 Emailed receipts/invoices**: ✅ already done — verify covers utility bills + payment-plan installments.
- **Mobile**: Budget screen (EN/AR), Statement screen, Utility bills in invoices list, Payment-plan selection screen.

---

## PILLAR 4 — Authorizations (build 4th; mostly net-new)

- **New role `security`** (0.5) + security build/view in mobile.
- **3.1 Paper Authorization → Email**: `create_authorizations_table` (type `guest|tenant|worker|parking`, requested_by, unit_id, approver, status, valid_from/to, document); on approval, email PDF (mPDF) to requester + `Approval`/activity log.
- **3.2 Parking Reservation (visitors)**: `create_parking_spots_table` (label, property_id, status `free|reserved|assigned`) + `parking_reservations_table` (spot_id, requested_by, visitor info, from/to). Prevent double-booking (unique active reservation per spot/time).
- **3.3 Security Staff App**: mobile screens for security role — live list of issued/valid authorizations, gate verify (search by plate/guest/QR), mark entry. `GET /api/v1/mobile/security/authorizations` (role:security), realtime via push.
- **3.4 Guest Authorization**: owner/tenant issues guest auth (creates `authorizations` row type=guest) → security validates. QR or code for gate.
- **3.5 Rental Access Cards + [HS10] deposit cheque**: `create_access_cards_table` (card_number, tenant/unit, status `active|lost|deactivated|reissued`, deposit cheque fields). Report-lost/reissue actions + audit; revoke on tenancy end.
- **Mobile**: Guest auth issue screen (owner/tenant), Parking reservation screen, Access cards screen, Security app screens.

---

## PILLAR 6 — Elections & Board Meetings (build last; most complex, governance-critical)

Rules must be enforced **exactly** per bylaws.

- **Data model**:
  - `meetings` (type `election|board`, scheduled_at, meeting_round 1..3, quorum_threshold, status, board_term_type).
  - `meeting_invitations` (meeting_id, user_id, acknowledged_at, last_reminded_at) — drives 5.3.
  - `meeting_attendance` (meeting_id, owner_id, agent_id nullable, joined_at, otp_verified) — for quorum.
  - `elections`, `candidates`, `votes` (voter_id, candidate_id, weight).
  - `boards`, `board_members` (term_start, term_end, term_type `full_3y|temporary_6m`).
- **5.1 Three-meeting flow + terms**: state machine — 1st needs 51% (per owner/agent weighted base), else 2nd needs 25%, else 3rd needs ≥5 board members. Record which path → set term `full` (3y) or `temporary` (6m); schedule next cycle automatically.
- **5.2 OTP meeting login**: `OtpService` purpose `meeting_join`; only eligible owners/authorized agents admitted; attendance counts trustworthy.
- **5.3 Persistent invite reminders**: scheduled command re-sends until `acknowledged_at` set (reuse 1.3 backbone + settings interval).
- **5.4 Weighted voting & quorum**: vote weight = units owned; quorum counted per owner (or representing agent). Compute against eligible owner base.
- **Board of Directors brief**: a board roster/overview screen (owners can view current board, terms).
- **Mobile**: Meetings list + invite ack, OTP join, voting screen (weighted), board roster. Owner-only (agents per 1.5 / quorum rules).

---

## External dependencies / open questions for client
1. **[HS9]** HOA accounting system — API base URL, auth, and realtime mechanism (webhook vs poll).
2. **2.1** Government data source — which records, API access.
3. **3.x** Gate hardware — QR vs plate recognition vs manual for security verification.
4. **Payments** — confirm HyperPay covers utility bills + payment-plan installments.
5. **Bylaws** — confirm exact quorum base (all owners vs eligible), tie-break rules, candidate eligibility for elections.
6. **Mobile i18n** — confirm AR is required across all screens or new screens only.

## BUILD STATUS — Pillar 1 + shared infra (implemented 2026-06-27)

**Shared infra (§0):** ✅ Settings store (`settings` table, `Setting` model, admin "System Parameters" screen, `SettingsSeeder`) · ✅ `OtpService` (purpose-keyed; login key shape preserved) · ✅ Approvals log (`approvals` table, `Approval` model, admin inbox) · ✅ Role matrix (`RolesMatrixSeeder` → Owner/Agent/Security/Employee; `User::isOwner/isAgent/isSecurity/isEmployee`; `role:` + `owner` middleware) · ✅ **Activity log (§0.4)** — `activity_logs` table + `ActivityLog` model + `App\Models\Traits\LogsActivity` trait (auto-logs create/update/delete) wired into Payment/Authorization/Vote/AccessCard/OwnerPaymentSchedule; admin "Activity Log" viewer (`activity_log_access`) · ⏳ mobile full-app i18n (0.6) deferred (new screens bilingual-ready).

**Pillar 1:** ✅ 1.1 unit fields + Facilities + Shops (admin CRUD + mobile screens w/ map directions) · ✅ 1.2 OTP-gated contact change · ✅ 1.3 unread-reminder command (`app:send-unread-reminders`, scheduled daily) · ✅ 1.4 owner↔agent (`owner_agent` table, `OwnerAgent`, admin CRUD, mobile "My Agents") · ✅ 1.5 `EnsureOwner` + `ActingOwnerResolver` + OTP financial grant (HS4) · ✅ 1.6 maintenance types (`maintenance_types`, admin CRUD, mobile type picker + Other free-text).

**Permissions:** new gates added via idempotent `Pillar1PermissionsSeeder` (safe on live DB).

**To run after pulling:** `composer install` → `php artisan migrate` → `php artisan db:seed --class=SettingsSeeder` + `--class=Pillar1PermissionsSeeder` + `--class=RolesMatrixSeeder` + `--class=MaintenanceTypesSeeder` (or full `db:seed`). For HS3 reminders, ensure the scheduler cron runs `php artisan schedule:run`. Could not boot artisan here (vendor/ not installed); all PHP files pass `php -l`, mobile TS adds no new `tsc` errors.

**New mobile API endpoints:** `GET /facilities`, `GET /shops`, `GET /maintenance-types`, `GET /agents`, `POST /agents`, `POST /agents/{agent}/financial-access[/request-otp]`, `GET /represented-owners`, `POST /user/contact/request-otp`, `PUT /user/contact`.

## BUILD STATUS — Pillar 5 Maintenance lifecycle (implemented 2026-06-27)

✅ **Lifecycle** — `maintenances.status` is now canonical: Submitted → Acknowledged → In Progress → On Hold → Resolved → Closed, with `priority`, `acknowledged_at/resolved_at/closed_at/confirmed_at`, `reported_by` (agent). `MaintenanceWorkflow` service drives transitions.
✅ **Audit trail** — `maintenance_status_histories` (every transition logged, actor + note); admin show page renders the timeline.
✅ **Routing/priority** — priority auto-derived from `maintenance_type.default_priority` on submit (admin can override).
✅ **Accountability** — workorders gained `internal_notes/labor_cost/parts_cost/completed_at`; `maintenance_work_logs` (note/labor/parts) editable on admin show.
✅ **Notifications** — push + email on each status change (reuses `PushNotificationService`); Resolved prompts requester to confirm.
✅ **Agent reporting** — mobile submit honours `on_behalf_of` (owner = subject, agent = `reported_by`) via `ActingOwnerResolver`.
✅ **Analytics** — `Admin/MaintenanceReportController` + screen: counts by status/type/building/unit, avg response & resolution hours, total cost; date-range filter. Permission `maintenance_report_access` (via `Pillar5PermissionsSeeder`).
✅ **History** — per-request `GET /maintenances/{id}/history`, per-unit `GET /units/{id}/maintenance-history`.
✅ **Mobile** — `ViewMaintenanceRequestScreen` shows type/priority/status timeline + "Confirm work completed"; `NewMaintenanceRequest` already had the type picker (1.6).
⏳ Deferred: HS10 deposit-cheque belongs to Access Cards (Pillar 4); itemised vendor portal beyond admin work-logs.

**New maintenance API endpoints:** `POST /maintenances/{id}/confirm`, `GET /maintenances/{id}/history`, `GET /units/{id}/maintenance-history`. **New admin routes:** `maintenances/{id}/status`, `maintenances/{id}/work-log`, `maintenance-reports`.

## BUILD STATUS — Pillar 3 Financial (implemented 2026-06-27)

✅ **2.4 / HS8 Utility bills** — `utility_bill_types` (parameterized, EN/AR, seeded) + `utility_bills` (attributed to the unit's owner); admin CRUD for both.
✅ **2.2 Annual budget (EN/AR)** — `budgets` + `budget_lines` (planned vs actual, EN/AR categories); admin CRUD with dynamic line repeater; `is_published` gates owner visibility.
✅ **HS7 Payment-plan scheduling** — `payment_plans` (preset templates, admin CRUD) → owner selects a plan (`owner_payment_schedules`, status `pending_approval`) → admin approves (sets total + start date) → `PaymentScheduleService` generates `owner_payment_schedule_installments` → `app:send-payment-reminders` (scheduled daily, lead-days from settings).
✅ **2.3 Account statement** — `AccountStatementService` assembles a running ledger (invoices + utility bills − payments); admin viewer + mobile screen.
✅ **2.1 owner-only + HS9 scaffolds** — financial mobile endpoints resolve the owner via `ActingOwnerResolver` with the `financials` capability (agents need granted access); `HoaAccountingClient` + `GovDataClient` contracts bound to safe Null implementations in `AppServiceProvider` — swap the binding to go live, no caller changes.
✅ **2.5** already done (emailed receipts/invoices) — utility bills surface in the statement.
✅ **Mobile** — Budget (EN/AR), Statement, Utility Bills, Payment Plans screens; Menu entries added.

**Permissions:** `Pillar3PermissionsSeeder` (utility_bill_type/utility_bill/budget/payment_plan CRUD + owner_payment_schedule_access/approve + account_statement_access).
**New mobile API:** `GET /budgets`, `GET /statement`, `GET /utility-bills`, `GET /payment-plans`, `GET|POST /payment-schedules`.
**Still external-blocked:** real HOA accounting API (HS9) + government-data source (2.1) — scaffolds ready, awaiting client specs.

## BUILD STATUS — Pillar 4 Authorizations (implemented 2026-06-27)

Gate verification implemented as **code/QR + manual lookup**; `vehicle_plate` is captured on every authorization so license-plate recognition can be added later without schema changes.

✅ **3.1 Paper auth → email** — `AuthorizationService::approve` generates a unique gate code, renders `admin/authorizations/pdf` (DomPDF), stores it, emails it as an attachment, and logs an `Approval` (TYPE_ACCESS, HS11).
✅ **3.4 Guest authorization** — owner/tenant issues via mobile (`POST /authorizations`), auto-approved (owner is authority) → instant gate code + emailed PDF. Admin CRUD + approve/reject for worker/tenant/parking types.
✅ **3.2 Parking reservation** — `parking_spots` (admin CRUD) + `parking_reservations`; mobile lists available visitor spots, reserves with **overlap/double-booking prevention**, cancels.
✅ **3.3 Security staff app** — new endpoints behind `role:Security`: `GET /security/authorizations` (currently-valid list) + `POST /security/verify` (by code or plate → marks entry, status→used). Mobile `SecurityScreen`.
✅ **3.5 Rental access cards + HS10** — `access_cards` with deposit-cheque fields (no/bank/amount/date); admin CRUD + **report-lost** (deactivate) + **reissue** (new card linked via `replaced_card_id`, carries deposit details). Tenant mobile view + report-lost.

**Models:** `Authorization`, `ParkingSpot`, `ParkingReservation`, `AccessCard`. **Permissions:** `Pillar4PermissionsSeeder` (authorization/parking_spot/access_card CRUD). **Security role** (`role:Security`) gates the gate app (role created in `RolesMatrixSeeder`).
**New mobile API:** `GET|POST /authorizations`, `GET /authorizations/{id}`, `GET /parking/available`, `GET|POST /parking/reservations`, `POST /parking/reservations/{id}/cancel`, `GET /access-cards`, `POST /access-cards/{id}/report-lost`, `GET /security/authorizations`, `POST /security/verify`.
**Mobile screens:** GuestAuthorization, Parking, AccessCards, Security.
**Deferred:** license-plate auto-recognition (plate captured, manual today) — confirm gate hardware with client.

## BUILD STATUS — Pillar 6 Elections & Board Meetings (implemented 2026-06-27)

Quorum rule implemented as **counted once per owner** (the owner OR their representing agent), **weighted votes by units owned**, against the **total eligible owner base** (per property when the election is property-scoped). Confirm against final bylaws.

✅ **5.1 Three-meeting flow + terms** — `ElectionService` round thresholds (1: 51%, 2: 25%, 3: ≥5 members). `evaluateMeeting` carries the election when quorum is met (→ **full 3-year** term) or fails the meeting and opens the next round; reaching round 3 yields a **temporary 6-month** term; exhausting round 3 marks the election failed. Board + members created on completion with term dates.
✅ **5.2 OTP meeting login** — `OtpService` purpose `meeting_join`; `POST /meetings/{id}/request-otp` + `/join` records OTP-verified attendance (one row per owner, weight snapshot).
✅ **5.3 Persistent invite reminders** — `app:send-meeting-invite-reminders` (scheduled every 4h) re-notifies until `acknowledged_at` is set; interval from `meetings.invite_reminder_hours`.
✅ **5.4 Weighted voting & quorum** — vote weight = units owned; one vote per owner (`votes.unique[election,voter]`); quorum % computed from distinct OTP-verified owners present / total eligible.
✅ **Board of Directors brief** — `boards`/`board_members`; `GET /board` roster + mobile screen; admin election show page renders meetings/quorum/candidates/results.

**Data model:** `elections`, `meetings`, `meeting_invitations`, `meeting_attendances`, `candidates`, `votes`, `boards`, `board_members`.
**Permissions:** `Pillar6PermissionsSeeder` (election_access/create/edit/delete + board_access).
**New mobile API:** `GET /meetings`, `POST /meetings/{id}/acknowledge|request-otp|join`, `GET /elections/{id}/candidates`, `POST /elections/{id}/vote`, `GET /board`.
**Admin:** Elections menu → create election, start (round 1 + auto-invite all owners), add candidates, evaluate each meeting's quorum (auto-advances rounds + re-invites), view board result.
**Mobile screens:** Meetings (ack + OTP join), Voting (weighted), Board.

---

## POST-BUILD CORRECTNESS REVIEW (2026-06-27) — all findings fixed
A full review of the unexecuted dashboard PHP was run. Fixed:
- **CRITICAL** Pillar-6 mobile routes used `{id}` while `MeetingsController` args were `$meetingId`/`$electionId` → params injected null (all 5 meeting/election endpoints broken). Aligned placeholders to `{meetingId}`/`{electionId}`.
- **CRITICAL** `MaintenanceReportController` date filter caused ambiguous `created_at` across joins → qualified to `maintenances.created_at`.
- **MODERATE** `SendUnreadReminders` sent one push per unread message → grouped per thread (one push, stamp all rows).
- **MODERATE** `AuthorizationService::verifyAndMarkEntry` could return a stale plate row → exact-code first, then approved-only plate fallback.
- **MODERATE** report `COALESCE(...,"...")` double-quoted literals → single-quoted (ANSI_QUOTES-safe).
- **MINOR** OtpService length floor (≥4); parking `cancel` only frees a spot with no remaining active reservations.
- **CAVEAT** `users.phone` had no migration of record (used by pre-existing code) → added a guarded `add_phone_to_users_table` for fresh-DB/CI safety.
- Reviewed-and-intended: `vote()` is owner-exclusive (agents excluded per §1.5) — documented, not changed.

## FINAL GAP-CLOSURE PASS (2026-06-27) — document fully covered except external API
- **HS4 agent payment** — `OwnerAgent::agentCanPay()`; `InvoicesController::pay`/`generateCheckoutId` and `PaymentsController::store` now allow an authorised agent to pay on behalf (and bill the owner's details). Previously only the flag existed.
- **HS11 work/maintenance approval** — `MaintenanceWorkflow::initialise` now writes a `TYPE_MAINTENANCE` approval-log entry on submit (all 4 HS11 categories now logged).
- **3.3 realtime security push** — `AuthorizationService::approve` pushes the new authorization to all `Security`-role staff via FCM.
- **Bilingual EN/AR (cross-cutting)** — Mobile i18n built: `src/i18n/translations.ts` (en/ar), `LanguageContext` provider + `useT()` hook + AsyncStorage persistence + `I18nManager` RTL; **language switcher** in the Menu. Translated: Menu + Profile + all new owner-facing screens (Budget, Statement, UtilityBills, PaymentPlans, GuestAuthorization, Parking, AccessCards, Security, Meetings, Voting, Board). Dashboard: `ar` enabled in `panel.available_languages`; data already bilingual (budget/utility/maintenance-type AR fields).
  - *Not translated (English, infra-ready):* Shops/Facilities/Agents screens and legacy screens (login, invoices, etc.) — they use the same `useT()` and can be converted incrementally.

**Only remaining document item: the external HOA accounting API + government-data integration (2.1/HS9)** — scaffolded behind Null clients, awaiting client API specs.

## ✅ ALL FIVE PILLARS IMPLEMENTED (2026-06-27)
Pillars 1–6 (the plan numbers pillars 1,2/financial,3/auth,4/maintenance,5/elections; built in order 1 → maintenance → financial → auth → elections) plus shared infra §0 are complete on both repos. Every margin comment HS1–HS11 addressed. Remaining work is **external-integration wiring only**: HOA accounting API (HS9) + government data (2.1) behind ready Null scaffolds, optional license-plate recognition, mobile full-app Arabic (new screens already bilingual-ready), and the activity-log trait (0.4). Run order after pulling: `composer install` → `php artisan migrate` → `php artisan db:seed` → ensure `php artisan schedule:run` is on cron.

## Suggested phasing (recap)
1. Shared infra (0.1–0.3, 0.5) + **Pillar 1** ← priority, starting now
2. Pillar 5 (Maintenance lifecycle)
3. Pillar 3 (Financial)
4. Pillar 4 (Authorizations)
5. Pillar 6 (Elections)
6. Bilingual (0.6) + activity log (0.4) woven through each phase.
