# Tarnova cPanel Deployment Guide

This guide prepares Tarnova for a cPanel shared-hosting test deployment. It assumes a typical Afrihost/cPanel PHP hosting account using MySQL or MariaDB.

## What cPanel Needs

- PHP 8.3 or newer with `pdo_mysql`, `mbstring`, `openssl`, `fileinfo`, `zip`, `curl`, `gd`, `intl`, `bcmath`, and `exif` enabled.
- MySQL or MariaDB database created in cPanel.
- Composer access through SSH, or a local production `vendor/` folder uploaded with the app.
- Node/Vite assets built before upload if cPanel does not support Node.
- A real SMTP mailbox/provider for invoices, quotations, statements, reminders, password reset, and credit note emails.
- Cron access for Laravel scheduler if reminders, recurring invoices, quote expiry, overdue refresh, and backups should run automatically.

## Recommended cPanel `.env`

Use your real cPanel database name, user, and password. cPanel often prefixes names with your hosting username, for example `cpaneluser_tarnova`.

```env
APP_NAME="Tarnova"
APP_ENV=production
APP_KEY=base64:GENERATE_A_REAL_KEY
APP_DEBUG=false
APP_URL=https://your-domain.co.za
APP_TIMEZONE=Africa/Johannesburg

DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=cpaneluser_tarnova
DB_USERNAME=cpaneluser_tarnova
DB_PASSWORD=your_database_password
DB_SOCKET=

SESSION_DRIVER=database
SESSION_SECURE_COOKIE=true
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=lax

CACHE_STORE=database
QUEUE_CONNECTION=sync
QUEUE_FAILED_DRIVER=database-uuids

MAIL_MAILER=smtp
MAIL_SCHEME=smtps
MAIL_HOST=mail.your-domain.co.za
MAIL_PORT=465
MAIL_USERNAME=no-reply@your-domain.co.za
MAIL_PASSWORD=your_mailbox_password
MAIL_ENCRYPTION=ssl
MAIL_TIMEOUT=15
MAIL_EHLO_DOMAIN=your-domain.co.za
MAIL_FROM_ADDRESS=no-reply@your-domain.co.za
MAIL_FROM_NAME="${APP_NAME}"
MAIL_QUEUE_WHEN_AVAILABLE=false

FILESYSTEM_DISK=local
FILESYSTEM_THROW=false
FILESYSTEM_REPORT=false

PAYMENT_GATEWAY=stub
PAYMENT_CURRENCY=ZAR

BACKUP_NAME="${APP_NAME}"
BACKUP_DISKS=local
BACKUP_ARCHIVE_PASSWORD=use-a-long-random-secret
BACKUP_VERIFY=true
BACKUP_NOTIFICATION_MAIL_TO=admin@your-domain.co.za
```

## Before Upload

Run these locally if cPanel does not support Composer or Node:

```bash
composer install --no-dev --optimize-autoloader
npm ci
npm run build
```

Upload the app files after the build is complete. Do not upload your local `.env` if it contains local database or mail credentials.

## Document Root

Best option: point the domain or subdomain document root to:

```text
/home/YOUR_CPANEL_USER/invoice-app/public
```

If your host does not allow changing the document root, ask the host to point it to the Laravel `public` folder. Avoid moving Laravel core files into `public_html` unless there is no other option.

## First Server Commands

Run these from the project root over SSH:

```bash
php artisan key:generate --force
php artisan migrate --force
php artisan storage:link
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan app:deployment-readiness
```

If you generated `APP_KEY` locally, paste that same value into cPanel and skip `key:generate`.

## Scheduler Cron

Add this cron entry in cPanel Cron Jobs:

```cron
* * * * * cd /home/YOUR_CPANEL_USER/invoice-app && /usr/local/bin/php artisan schedule:run >> /dev/null 2>&1
```

If `/usr/local/bin/php` is not correct, use the PHP path shown by cPanel or ask the host.

## Queues on Shared Hosting

For shared cPanel testing, use:

```env
QUEUE_CONNECTION=sync
MAIL_QUEUE_WHEN_AVAILABLE=false
```

This makes email sending happen during the request, which is simpler and safer on shared hosting. If the host supports a persistent process manager, you can later switch to:

```env
QUEUE_CONNECTION=database
MAIL_QUEUE_WHEN_AVAILABLE=true
```

Then run a supervised worker:

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

Do not enable queued mail unless something is actually processing the queue.

## Storage and Uploads

Tarnova uses Laravel storage for logos, EFT proofs, and generated public files. After `storage:link`, confirm this exists:

```text
public/storage -> storage/app/public
```

Keep private files out of public web folders. If `storage:link` is blocked, ask the host to enable symlinks or create the link for you.

## Backups

For testing, also use cPanel backups or phpMyAdmin exports. Application backups are helpful, but a backup only counts when you have tested restore.

Minimum backup routine:

- Export the MySQL database from cPanel/phpMyAdmin.
- Download `storage/app/public` and any uploaded document/proof files.
- Store `.env` securely outside public hosting.
- Test restoring database and uploads into a separate test folder before trusting the backup.

## Post-Deployment Checks

- Visit `/login`.
- Log in with the seeded/admin user.
- Create a client, quotation, invoice, payment, and credit note.
- Send a quotation email and invoice email to a real inbox.
- Test password reset email.
- Download invoice, quotation, statement, and credit note PDFs.
- Test public invoice/quotation/statement links on mobile.
- Run `php artisan app:deployment-readiness` and review any warnings.

## Common cPanel Problems

- `500 Server Error`: check `storage/logs/laravel.log`, `.env`, `APP_KEY`, and database credentials.
- Assets look broken: run `npm run build` locally and upload `public/build`.
- Login fails after upload: run migrations and seed/admin setup on the cPanel database.
- Emails do not arrive: verify SMTP host, port, username, password, SPF, DKIM, and DMARC.
- Reminders do not send automatically: cron is missing or not using the correct PHP binary.
- Uploads do not show: `storage:link` is missing or symlinks are disabled.

## Render/Docker Note

This cPanel path does not use Docker, Render, or `DATABASE_URL`. Use explicit MySQL environment variables instead.
