# TemseeEdu School Edition Install Notes

## Fresh install

1. Point the web server to `public/`.
2. Set writable permissions for `storage/` and `bootstrap/cache/`.
3. Visit `/install`.
4. Enter the central database credentials, school domain, first admin account, and license key.
5. Submit the installer.

The installer runs central migrations, applies default AI plan quotas, creates one tenant, runs tenant migrations and seeders, creates the School Edition subscription record, writes school profile settings, syncs default school integration blueprints, creates storage links, writes the local license settings, and creates `storage/app/temseeedu-installed.json`.

After installation, verify:

```bash
/opt/lampp/bin/php artisan install:status
/opt/lampp/bin/php artisan tenants:migrate --force
/opt/lampp/bin/php artisan temsee:sync-school-integrations
```

The last two commands are safe to run again after updates. They keep tenant schema and integration blueprints current.

For shared cPanel hosts, prefer the cPanel-safe command flow in [cpanel-school-edition-deployment.md](cpanel-school-edition-deployment.md). That mode assumes databases are created manually and skips automatic tenant database creation.

After any shared cPanel upload or update, run:

```bash
php artisan temsee:cpanel-check --fix
php artisan temsee:cpanel-check
```

This verifies the cPanel-safe `.env` values, writable folders, Laravel exception renderer assets, Livewire vendor assets, and published Livewire public assets. A healthy Livewire asset endpoint should return JavaScript:

```bash
curl -I 'https://schooldomain.com/livewire/livewire.min.js?id=dev'
```

Expected:

```text
HTTP/1.1 200 OK
Content-Type: application/javascript
```

## Build package

Demo QA build without SourceGuardian:

```bash
SKIP_ENCODING=1 ./scripts/build-school-edition.sh demo
```

Production build with SourceGuardian:

```bash
./scripts/build-school-edition.sh 1.0.0
```

Production license keys and provider credentials should be injected during deployment or entered in the installer. Do not hard-code live credentials in the build script.

## Failed install recovery

Check installer state:

```bash
/opt/lampp/bin/php artisan install:status
```

Unlock the installer after a failed setup:

```bash
/opt/lampp/bin/php artisan install:unlock --force
```

Unlocking only clears the installer lock and sets `TEMSEEEDU_INSTALLED=false`. It does not delete databases, tenants, uploaded files, or demo data.

## Plugin packages

Install plugin zips from Admin -> Plugins -> Install Plugin Zip, or with:

```bash
/opt/lampp/bin/php artisan plugin:install /path/to/plugin.zip
```

Plugin migrations are run explicitly in tenant context. Core central migrations should not run plugin migrations.

## Plugin access rules

The V1 plugin catalog currently maps:

- `results` -> `Results`
- `attendance` -> `Attendance`
- `fees` -> `Payments`

Cloud/demo schools use central `school_plugins` records to activate plugins. The demo tenant is seeded with `results`, `attendance`, and `fees` active for local testing.

School Edition uses local plugin keys in `.env`:

```env
TEMSEEEDU_PLUGIN_RESULTS_KEY=TSPLUGIN-RESULTS-demo
TEMSEEEDU_PLUGIN_ATTENDANCE_KEY=TSPLUGIN-ATTENDANCE-demo
TEMSEEEDU_PLUGIN_FEES_KEY=TSPLUGIN-FEES-demo
```

When a plugin is inactive:

- its Filament resources are hidden;
- parent/student plugin pages are hidden;
- direct plugin routes return `403`;
- database tables and data are preserved.

Cloud schools request plugins from Admin -> Plugins. First-time access uses **Buy Plugin** (Paystack) or **Request Approval** (`pending` in central `school_plugins`; Temsee staff approve at `/temsee/plugin-licenses`). **Deactivate** sets the license to `inactive` and disables the module but keeps data and payment history. Schools with an existing license use **Reactivate**—no second payment. Temsee approval or reactivation also enables the module and runs tenant migrations.

Plugin names, modules, prices, plan requirements, and marketplace availability are managed from `/temsee/plugin-catalog-items`. Use **Sync Defaults** to copy the default catalog from `config/temseeedu.php` into editable central records.

Run subscription warning checks from the scheduler or manually:

```bash
php artisan subscriptions:notify-expiring --days=14
```

The command notifies platform users about active/trialing subscriptions ending within the selected window. Configure real mail credentials in production; local/dev can keep demo mail settings.

Production servers should run Laravel's scheduler every minute:

```cron
* * * * * cd /path/to/temseeedu && php artisan schedule:run >> /dev/null 2>&1
```

The scheduler currently publishes due announcements every minute and sends subscription expiry warnings daily. Run a queue worker for queued mail and notifications:

```bash
php artisan queue:work --tries=3
```

Paystack keys belong in `.env`:

```env
PAYSTACK_SECRET_KEY=
PAYSTACK_PUBLIC_KEY=
```

Schools can send direct SMS from Admin -> Communication -> SMS Broadcast. Announcement SMS still works from Admin -> Communication -> Announcements when `Send SMS Notification` is enabled.

## Single-school production shape

For a dedicated school install, use one licensed School Edition instance with one tenant and one school domain:

```text
schoolname.edu.gh        -> public website
schoolname.edu.gh/admin  -> school admin panel
```

In School Edition, `/temsee` is hidden. The school should not use the SaaS signup flow. Provisioning is handled by the installer or:

```bash
php artisan temsee:provision-school \
  --tenant-id=schoolname \
  --domain=schoolname.edu.gh \
  --name="School Name" \
  --email="admin@schoolname.edu.gh" \
  --plan=school_edition \
  --years=1
```

The provisioning command now finalizes the subscription record, writes basic school profile settings, and syncs school integration blueprints.

## Notice board

Create notices from Admin -> Communication -> Announcements.

- Use `Target Audience` for portal delivery.
- Enable `Show on Public Notice Board` only for notices that should appear on the public website.
- Enable `Pin on Notice Board` for priority notices.
- Set `Public Expiry` when the notice should automatically disappear from the website.

Public website routes:

- `/notices`
- `/notice-board`
- `/notices/{id}`
