# Installation Guide — cPanel Shared Hosting

## 1. Requirements

- PHP 8.0 or higher (PHP 8.1–8.3 recommended)
- MySQL 5.7+ or MariaDB 10.3+
- PHP extensions: `pdo_mysql`, `mbstring`, `fileinfo`, `curl`, `openssl`,
  `json` (all enabled by default on virtually every cPanel host)
- No Composer, no Node.js, no shell access required (though cron jobs need
  cPanel's built-in "Cron Jobs" UI, which every host provides)

## 2. Upload the files

1. Zip the contents of this project (already done if you're reading this
   from the delivered zip).
2. In cPanel → File Manager (or via FTP), upload and extract into
   `public_html/` (or a subfolder like `public_html/school-erp/` if you want
   it at a sub-path — the app auto-detects its depth, no code changes
   needed).

## 3. Import the database schema

Your database (`mytoolsh_schooldata`) and user (`mytoolsh_schooluser`) are
already created. Just import the schema:

1. cPanel → **phpMyAdmin** → select `mytoolsh_schooldata` → **Import** →
   choose `database/schema.sql` → Go.
   - This creates all 37 tables and seeds: 3 default subscription plans
     (Trial/Basic/Pro), one super admin login, and default global settings.

## 4. Configure the application

**This is already done for this deployment** — `config/constants.php` is
pre-configured with:
```php
define('DB_NAME', 'mytoolsh_schooldata');
define('DB_USER', 'mytoolsh_schooluser');
define('DB_PASS', 'Samir@154198');
define('JWT_SECRET', '35c026d27b40707f95610a9d9fc80cf390cdaede64b59714a2a0aafc8302a89c');
define('APP_DEBUG', false);
```
No editing needed unless you're redeploying this same codebase to a
**different** database/hosting account — in that case, update the four `DB_*`
values to match the new database.

## 5. Set folder permissions

Via File Manager, right-click → Permissions:

- `uploads/` and all its subfolders → `755` (writable by PHP)
- `backups/` → `755`
- Everything else → default (`644` for files, `755` for folders) is fine.

## 6. First login & first school

1. Visit `https://yourdomain.com/admin/super-admin/login.php`
2. Log in with the seeded super admin:
   - Email: `superadmin@schoolerp.com`
   - Password: `Admin@123`
3. **Immediately** go to your profile / change password (or update the
   `erp_super_admins` row directly via phpMyAdmin using
   `password_hash()` — there's no self-service "change password" screen for
   super admin in v1, use **Forgot Password** flow or update the DB row
   directly with a bcrypt hash).
4. Go to **Add School** — this creates the school AND its first Admin
   login in one step. Note the Admin email/password you set; hand these to
   the school.
5. Log into `https://yourdomain.com/admin/school-admin/login.php` with
   those credentials to start configuring the school (classes, sections,
   subjects, then students/teachers).

## 7. Set up cron jobs (recommended, not required for basic operation)

cPanel → **Cron Jobs** → Add New Cron Job for each of the following. Use the
full path to PHP CLI on your host (commonly `/usr/local/bin/php` or
`/usr/bin/php` — check cPanel → "Select PHP Version" page for the exact
path, or ask your host).

| Job | Schedule | Command |
|---|---|---|
| Fee reminders | Daily, e.g. 8:00 AM | `/usr/local/bin/php /home/USER/public_html/cron/fee-reminders.php` |
| Push notification delivery | Every 5 minutes | `/usr/local/bin/php /home/USER/public_html/cron/send-push-notifications.php` |
| Nightly database backup | Daily, e.g. 2:00 AM | `/usr/local/bin/php /home/USER/public_html/cron/nightly-backup.php` |
| Subscription expiry check | Daily, e.g. 1:00 AM | `/usr/local/bin/php /home/USER/public_html/cron/subscription-check.php` |

Replace `/home/USER/public_html/` with your actual absolute path (visible
in cPanel's File Manager path bar).

## 8. Set up Firebase Cloud Messaging (for push notifications)

Push notifications are queued into the database regardless of whether FCM
is configured (so nothing breaks without it), but to actually deliver them
to phones:

1. Create a Firebase project at https://console.firebase.google.com (free).
2. Add your Flutter app to it (Android/iOS) and follow Firebase's
   `google-services.json` / `GoogleService-Info.plist` setup in the Flutter
   project.
3. Firebase Console → Project Settings → **Service Accounts** → **Generate
   new private key** → downloads a JSON file.
4. In this app: Super Admin → **Settings → Firebase (Push)** → enter your
   Project ID and upload that JSON file → **Save Settings**. That's it —
   no manual file editing or SSH access needed; the file is stored at
   `config/firebase/service-account.json`, which is blocked from direct
   web access by `.htaccess`.
5. The Flutter app calls `POST /api/notifications/register-token.php` after
   login (and whenever FCM issues a refreshed token) to register each
   device — this is required for delivery to work.

## 9. SMS/Email for password resets

**Email is already built in** (both admin panels have a Settings > Email
page for configuring SMTP — School Admin per-school, Super Admin for the
platform level). If you don't configure it right away, **nothing breaks**:
Forgot Password automatically falls back to showing the reset link
directly on screen instead of emailing it, so nobody gets locked out while
you're still setting things up. Once you fill in SMTP settings and save,
emails start going out automatically — no code changes needed.

To configure: log in → **Settings** → **Email (SMTP)** tab → fill in your
mail server details → **Send Test Email** to confirm it works. Common
values:
- Your own hosting's mail server: host `mail.yourdomain.com`, port 587
  (TLS) or 465 (SSL) — check cPanel → Email Accounts → Connect Devices for
  exact values.
- Gmail: host `smtp.gmail.com`, port 587, TLS — you must use an
  [App Password](https://myaccount.google.com/apppasswords), not your
  normal Gmail password.

SMS for parent (phone-based) password reset is **also built in** — School
Admin → **Settings → SMS** → choose MSG91 or Fast2SMS, enter your API key
and sender ID → **Send Test SMS** to confirm. Same graceful fallback as
email: until it's configured, the reset code just isn't delivered via SMS
(the app-facing API response includes the code directly in that case so
your Flutter app can still show it — see `API_DOCUMENTATION.md`).

## 10. Set up the App Connection (dynamic domain for the Flutter app)

This lets you move/rename this admin panel's domain later **without**
publishing a new version of the Flutter app — the app discovers the
current domain at runtime instead of having it hardcoded.

1. Deploy the small resolver service in `mytoolshub-resolver/` to a
   **separate, stable domain you control** (the delivered version is
   pre-configured to go on `mytoolshub.co.in` — see
   `mytoolshub-resolver/README.md` for its own setup steps).
2. Back in **this** app: Super Admin → **App Connection Settings**:
   - **App Key**: a unique ID for this deployment, e.g.
     `school-erp-yourschool` — pick once, this value gets built into the
     Flutter app, so don't change it later.
   - **Current Live Domain**: this admin panel's current URL.
   - **Resolver Update URL**: `https://mytoolshub.co.in/resolver/update.php`
     (wherever you deployed the resolver in step 1).
   - **Resolver Secret Key**: any strong random string, 12+ characters —
     the first save registers it, every future save must reuse the same
     one.
3. Click **Save & Sync Now**. If it says "Synced", your Flutter app can
   now discover this domain at
   `https://mytoolshub.co.in/resolver/resolve.php?app_key=school-erp-yourschool`.
4. If you ever move this admin panel to a new domain: come back to this
   same page, update **Current Live Domain**, save — every installed copy
   of the app picks up the change automatically (see
   `mytoolshub-resolver/README.md` for the Flutter-side integration code).

## 11. New settings to know about

All of these live under each panel's **Settings** menu and are entirely
optional — the app works without them, just with reduced functionality
until configured:

- **SMS** (School Admin > Settings > SMS): MSG91 or Fast2SMS, needed for
  parent (phone-login) password resets to actually deliver an SMS instead
  of showing the code on-screen as a fallback.
- **Payment** (School Admin > Settings > Payment): Razorpay Key ID/Secret,
  needed for the Flutter app's "Pay Online" fee option. Without it, parents
  still see their fee status, just not an online-pay button.
- **Permissions** (School Admin > Settings > Permissions): per-teacher
  module access — see the in-app notice on that page about current
  enforcement scope.
- **Firebase** (Super Admin > Settings > Firebase): see step 8 above.
- **App Connection** (Super Admin > Settings > App Connection): see step
  10 above.

## 12. Verify everything works

- [ ] Super admin can log in and see the dashboard
- [ ] Creating a school works and the admin login is issued
- [ ] School admin can log in and add a class/section/subject
- [ ] Adding a student auto-creates a parent login (check **Parents** page)
- [ ] `POST /api/auth/login.php` with `role: parent` and the student's
      mobile number returns a token (test with curl or Postman — see
      `API_DOCUMENTATION.md`)
- [ ] Marking attendance as Absent queues a notification (check
      `erp_notification_log` table — it will sit as `pending` until the
      push cron + Firebase are configured)
- [ ] File uploads (student photo, homework attachment) work and the
      resulting URL is reachable in a browser

## Troubleshooting

**"Authorization token missing" on every API call, even with a valid
token** — Your host is stripping the `Authorization` header. The root
`.htaccess` already includes a `mod_rewrite` fix for this; if it still
fails, ask your host to enable `CGIPassAuth On` for your account, or add
this to `.htaccess`:
```apache
CGIPassAuth On
```

**"DB connection failed"** — Double-check `DB_HOST`/`DB_NAME`/`DB_USER`/
`DB_PASS` in `config/constants.php`. On most cPanel hosts, `DB_HOST` is
`localhost` and the DB name/user are prefixed with your cPanel username
(e.g. `youruser_schoolerp`).

**Uploaded images/PDFs 404** — Check that `UPLOAD_URL_BASE` in
`config/constants.php` matches where you deployed the app (e.g. if you
deployed to a subfolder `school-erp/`, set it to `/school-erp/uploads`).
