# Installation and deployment

## 1. Prepare MySQL 8

Create a UTF-8 database and a dedicated user. Do not run the application with the MySQL root account.

```sql
CREATE DATABASE mutlaq_erp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'mutlaq_erp'@'localhost' IDENTIFIED BY 'replace-with-a-long-random-password';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX, DROP, REFERENCES ON mutlaq_erp.* TO 'mutlaq_erp'@'localhost';
FLUSH PRIVILEGES;
```

## 2. Configure the application

Copy `.env.example` to `.env` and set `APP_URL`, database credentials, and SMTP credentials. Keep `APP_DEBUG=false` outside development. Run:

```powershell
composer install
php artisan key:generate
php artisan migrate --seed --force
php artisan storage:link
php artisan optimize:clear
php artisan test
php artisan optimize
```

Run the test suite before caching configuration so `phpunit.xml` can select its isolated in-memory SQLite database. After tests pass, a production deployment may run `composer install --no-dev --optimize-autoloader` and rebuild the Laravel caches.

For a development refresh only, `php artisan migrate:fresh --seed` recreates all data and must never be used on a live database.

## 3. Web server

Point the virtual host document root to `C:\xampp\htdocs\saudi\public` on XAMPP, or `/var/www/saudi/public` on Linux. Enable URL rewriting. Never expose the project root, `.env`, `storage`, database backups, or Composer files through the web server.

Apache example:

```apache
<VirtualHost *:443>
    ServerName erp.example.sa
    DocumentRoot "C:/xampp/htdocs/saudi/public"
    <Directory "C:/xampp/htdocs/saudi/public">
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>
```

Use a trusted TLS certificate and redirect HTTP to HTTPS.

## 4. Writable folders

The web-server identity must be able to write to `storage/` and `bootstrap/cache/`, but should not own or modify application source. Backups are stored under `storage/app/private/backups` and are downloadable only through an authenticated, permission-protected route.

## 5. Scheduler and queue

Run the scheduler once per minute and use a supervised queue worker when database queues are enabled:

```bash
* * * * * cd /var/www/saudi && php artisan schedule:run >> /dev/null 2>&1
php artisan queue:work --sleep=2 --tries=3 --max-time=3600
```

Restart queue workers after each deployment with `php artisan queue:restart`.

## 6. First login

Sign in with `admin` / `Password123!`, immediately change the credentials, review the company/branch addresses, upload the official logo and stamp, verify invoice numbering, configure SMTP, and validate the first invoice QR using an independent TLV decoder.

## 7. Upgrade procedure

Create and verify a database backup, run the test suite in CI or staging with configuration caches cleared, place the application in maintenance mode, deploy code, run `composer install --no-dev --optimize-autoloader`, run `php artisan migrate --force`, rebuild caches, restart workers, then restore service.
