# Local Integration Setup: e-prescription ↔ viviane-inventory

This guide covers how to run both systems locally so the prescription dispensing integration works end-to-end.

## Overview

| App | Port | Database |
|-----|------|----------|
| viviane-inventory | 3000 | viviane_inventory |
| e-prescription | 9100 | viviane_e |

The e-prescription system calls viviane-inventory's API to check stock availability when a prescription is edited, and to deduct stock when a prescription is completed.

---

## Prerequisites

- PHP 8.2+
- MySQL
- Composer
- Node.js + npm

---

## 1. viviane-inventory Setup

```bash
git clone <repo-url> viviane-inventory
cd viviane-inventory
composer install
npm install
cp .env.example .env
php artisan key:generate
```

### Configure `.env`

```env
APP_URL=http://localhost:3000

DB_DATABASE=viviane_inventory
DB_USERNAME=root
DB_PASSWORD=

# Shared API token — must match INVENTORY_API_TOKEN in e-prescription
INVENTORY_API_TOKEN=<generate with: openssl rand -hex 32>
```

### Database setup

```bash
php artisan migrate
php artisan db:seed
```

The seeder must create at minimum:
- One `Institution` with an `external_id` matching the one in e-prescription
- One `Branch` and `Store` under that institution
- One `Program` with `code = 'PHARMACY'`
- At least one `Item` with stock in a `StockCard`
- One `User` with an `external_id` matching the pharmacist's external_id in e-prescription

### Run

```bash
php artisan serve --port=3000
```

---

## 2. e-prescription Setup

```bash
git clone <repo-url> e-prescription
cd e-prescription
composer install
npm install
cp .env.example .env
php artisan key:generate
```

### Configure `.env`

```env
APP_URL=http://localhost:9100

DB_DATABASE=viviane_e
DB_USERNAME=root
DB_PASSWORD=

# OAuth2 (Account Manager)
PASSPORT_CLIENT_ID=<from account manager>
PASSPORT_CLIENT_SECRET=<from account manager>
PASSPORT_REDIRECT_URI=http://localhost:9100/auth/callback
PASSPORT_BASE_URL=http://localhost:8000

# Inventory integration
INVENTORY_BASE_URL=http://localhost:3000
INVENTORY_API_TOKEN=<same token as viviane-inventory>
```

### Database setup

```bash
php artisan migrate
php artisan db:seed
```

The institution record must have `external_id` set to the same value as the institution's `external_id` in viviane-inventory.

### Run

```bash
php artisan serve --port=9100
```

---

## 3. How the Integration Works

### Stock Check (on prescription edit/save)

When a prescription is saved, e-prescription calls:

```
POST http://localhost:3000/api/v1/stock/check-availability
Authorization: Bearer <INVENTORY_API_TOKEN>

{
  "institution_external_id": "1",
  "branch_external_id": null,
  "items": [
    { "item_code": "Ibuprofen 400mg", "quantity": 97 }
  ]
}
```

The response updates `stock_status` and `available_quantity` on each `prescription_item`. The UI shows green/yellow/red badges accordingly.

### Stock Dispense (on prescription completion)

When "Complete Order" is clicked, e-prescription calls:

```
POST http://localhost:3000/api/v1/stock/dispense
Authorization: Bearer <INVENTORY_API_TOKEN>

{
  "institution_external_id": "1",
  "branch_external_id": null,
  "prescription_number": "PRP-015",
  "dispensed_by_user_external_id": "4",
  "items": [
    { "item_code": "Ibuprofen 400mg", "quantity": 97, "lot_id": null }
  ]
}
```

viviane-inventory finds the store with sufficient stock, creates a `StockEvent` (ISSUE), and decrements the `StockCard` balance. If any item has insufficient stock, the entire dispense is rejected and the prescription stays in `processing` status.

---

## 4. Required Data Alignment

For the integration to work, these records must exist and match across both databases:

| Field | e-prescription | viviane-inventory |
|-------|---------------|-------------------|
| Institution | `institutions.external_id` | `institutions.external_id` |
| Branch | `branches.external_id` | `branches.external_id` |
| User (pharmacist) | `users.external_id` | `users.external_id` |
| Item | `prescription_items.medication + strength` | `items.name` (e.g. "Ibuprofen 400mg") |

The `external_id` fields are populated automatically when users log in via OAuth2 (Account Manager). For local testing without OAuth2, set them manually in the database.

---

## 5. Troubleshooting

**401 Unauthorized on API calls**
- Confirm `INVENTORY_API_TOKEN` is set and identical in both `.env` files
- Run `php artisan config:clear` in e-prescription after changing `.env`

**"Item not found or inactive"**
- The medication name + strength sent from e-prescription doesn't match any `items.name` or `items.code` in viviane-inventory
- Add the item to viviane-inventory's catalog

**"Insufficient stock"**
- The item exists but has 0 balance in all stores for that institution
- Add stock via viviane-inventory's Stock Management UI

**"User does not have external_id"**
- The logged-in pharmacist was created locally, not via OAuth2
- Set `external_id` manually on the user record, matching their `id` in viviane-inventory's `users` table

**cURL timeout**
- viviane-inventory is not running or not reachable at `INVENTORY_BASE_URL`
- Stock check failures are non-blocking — the prescription save still succeeds
- Stock dispense failures are blocking — prescription completion will fail
