# A&B Hub — Backend

Backend for **A&B Homecare Services Inc.** and
**A&B Cleaner Janitorial Services**, sharing one CRM.

**Phase 1** built the architecture. **Phase 2** built authentication
and administration. **Phase 3** built the complete CRM. **Phase 4**
built the complete marketing system. **Phase 5** built every AI module
and external integration. **Phase 6** (this state) made it
production-ready: a 9-report analytics suite (CSV/Excel/PDF/Print
export, all hand-built with zero third-party dependencies — see
`docs/DEVELOPER_GUIDE.md`), a real caching layer and confirmed
(`EXPLAIN`-verified) database indexes, a scripted full-route audit
that found and fixed real bugs, a working external API with scoped
API keys, bulk actions, tested deployment tooling (Apache config,
least-privilege DB grants, a backup script verified with a full
restore round-trip), and four documentation guides. See
`docs/PHASE_6_SUMMARY.md` for the full rundown of what was built,
tested, and found along the way.

This is the full six-phase build: architecture, auth/admin, CRM,
marketing, AI/integrations, and production readiness, all on one
consistent foundation with no phase redesigning what an earlier one
built. See `docs/INSTALLATION.md` to deploy it for real.

## Requirements

- PHP 8.3+ (with `pdo_mysql`, `fileinfo`, `mbstring`, `json` extensions)
- MySQL 8.0+
- Apache with `mod_rewrite` and `mod_headers`
- Composer

## Setup

```bash
# 1. Install dependencies (PHPMailer, dev tooling)
composer install

# 2. Configure environment
cp .env.example .env
php bin/generate_key.php   # paste the output into APP_KEY in .env
# then edit .env: DB_DATABASE, DB_USERNAME, DB_PASSWORD, MAIL_*, APP_URL

# 3. Create the database (matching whatever you set DB_DATABASE to)
mysql -u root -p -e "CREATE DATABASE ab_hub CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# 4. Create a dedicated, least-privilege application DB user — never
#    point the running app at a root/admin MySQL account.
mysql -u root -p -e "
  CREATE USER 'ab_hub_app'@'localhost' IDENTIFIED BY 'choose-a-real-password';
  GRANT SELECT, INSERT, UPDATE, DELETE ON ab_hub.* TO 'ab_hub_app'@'localhost';
  FLUSH PRIVILEGES;
"
# (Run migrations as root or another account with CREATE TABLE rights —
# the app's own runtime user intentionally cannot alter schema.)

# 5. Run migrations, then seed reference data + demo accounts
php bin/migrate.php
php bin/seed.php
# ^ seed.php prints one-time generated passwords for the demo users —
#   copy them immediately, they are never written to disk.

# 6. Point Apache's DocumentRoot at /public (not the project root —
#    see docs/ARCHITECTURE.md §6 for why this matters), or for local
#    development:
php -S localhost:8000 -t public
```

Visit `http://localhost:8000/health` — you should see
`{"status":"ok","database":true,...}`. Then visit `/login` and sign in
with one of the four seeded accounts (`jordan@abhomecare.com`,
`rita@abhomecare.com`, `tomas@abcleaner.com`, `elena@abhomecare.com`) —
the password for each was printed once by `bin/seed.php` above.

## Background workers (Phase 4)

Four scripts are meant to run on a schedule (cron), not on every
request — see each file's docblock for details:

```cron
* * * * *     php bin/process_email_queue.php        # bulk + personal email sends
*/15 * * * *  php bin/process_automations.php         # resumes paused automation runs
0 6 * * *     php bin/process_automations.php --daily # birthday / inactivity triggers
*/15 * * * *  php bin/send_appointment_reminders.php  # appointment reminders (Phase 3)
0 3 * * *     php bin/process_recurring_campaigns.php # generates the next Newsletter occurrence
0 2 * * *     deploy/backup-database.sh               # nightly database backup (Phase 6)
```

## Where to go next

| Question | Answer |
|---|---|
| What's the folder structure and why? | `docs/ARCHITECTURE.md` |
| What tables exist and how do they relate? | `docs/DATABASE.md` |
| What did Phase 2 build, and what's next for Phase 3? | `docs/PHASE_2_SUMMARY.md` |
| What did Phase 3 build, and what's next for Phase 4 (Marketing)? | `docs/PHASE_3_SUMMARY.md` |
| What did Phase 4 build, and what's next for Phase 5 (AI)? | `docs/PHASE_4_SUMMARY.md` |
| What did Phase 5 build, and what's next? | `docs/PHASE_5_SUMMARY.md` |
| What did Phase 6 build, and what's the current state? | `docs/PHASE_6_SUMMARY.md` |
| How do I deploy this for real? | `docs/INSTALLATION.md` |
| How do I administer the app day-to-day? | `docs/ADMIN_GUIDE.md` |
| How do I extend the codebase? | `docs/DEVELOPER_GUIDE.md` |
| What API endpoints exist? | `docs/API.md` |
| What was reviewed on the frontend and what gaps did it surface? | `docs/GAP_ANALYSIS.md` |
| What are the coding/security rules for anything added later? | `docs/CODING_STANDARDS.md` |
| How do I add a new feature module (Leads, Customers, ...)? | `docs/ARCHITECTURE.md` §9, plus the README.md inside `app/controllers/` and `app/models/` |

## Project structure

```
/app          MVC application code (controllers, models, core, services, helpers, middleware, views)
/config       Environment-driven configuration, one file per concern
/routes       web.php (pages) + api.php (JSON endpoints)
/database     schema.sql (source of truth), migrations/, seeders/
/storage      Logs, cache, sessions — never web-accessible
/uploads      User-uploaded files — never web-accessible, never executable
/public       Web server document root — the ONLY web-accessible directory
/bin          CLI tools (migrate, seed, generate_key)
/docs         Architecture, database, coding standards, gap analysis
```

## A note on what "done" means here

Every core mechanism in this repository — routing and middleware,
session handling, the PDO connection, `BaseModel` CRUD, the validator
(including its database-backed `unique`/`exists` rules), the
authenticaton flow, RBAC permission resolution, login rate limiting,
and the full migration + seeding pipeline — was run against a live
MySQL 8 database during development and confirmed working, not just
written and assumed correct. Several real bugs were caught and fixed
this way (a `PDO::FETCH_KEY_PAIR` column-order mistake that silently
broke role-permission seeding, a namespace typo that broke pagination,
a MySQL constraint conflict between a `CHECK` and a cascading foreign
key). That's the standard the rest of this project should be held to
as new modules are built on top of it.
