# AHS VirtualStock Integration Module

VirtualStock API integration for Yii2 / NGauge applications.

Handles order polling, order management (acknowledge, dispatch, cancel), product/stock
retrieval, inbound webhooks, rate limiting, response caching, and structured logging.

## Requirements

- PHP 8.4+
- Yii2 Framework 2.0+
- `yiisoft/yii2-httpclient` ^2.0

## Installation

```bash
composer require portalpeople/ahs-virtualstock
```

Register the module in your application config:

```php
// backend/config/main.php
'modules' => [
    'virtualstock' => [
        'class' => \PortalPeople\virtualstock\Module::class,
    ],
],
'bootstrap' => ['virtualstock'],
```

Add credentials to `backend/config/params-local.php`:

```php
'plugins' => [
    'virtualstock' => [
        'enabled'           => true,
        'apiEndpoint'       => '', // leave blank to use environment default
        'environment'       => 'sandbox', // 'sandbox' or 'production'
        'apiKey'            => 'your-api-key',
        'apiSecret'         => 'your-api-secret',
        'requestTimeout'    => 30,
        'pollLimit'         => 100,
        'orderNumberPrefix' => 'VS-',
        'debug'             => false,
        'webhookSecret'     => '', // leave blank to disable signature verification
    ],
],
```

Credentials are encrypted at rest using `backend\components\Security`.

## Configuration UI

Navigate to `/virtualstock/config` in the backend to manage settings, test the
connection, view module status, and trigger on-demand imports.

## Order Import (Polling)

Run the console command to pull new/updated orders from VirtualStock:

```bash
./yii virtualstock/order-import/run
```

Options:

```bash
./yii virtualstock/order-import/run --limit=200
./yii virtualstock/order-import/run --cursor="2026-03-06T00:00:00Z"
./yii virtualstock/order-import/run --dry-run=1
```

Suggested cron (every 5 minutes):

```cron
*/5 * * * * cd /var/www/vhosts/.../NGauge_Base && ./yii virtualstock/order-import/run
```

## Order Management (REST)

```php
$module  = Yii::$app->getModule('virtualstock');
$service = new \PortalPeople\virtualstock\services\OrderService();
$service->client = $module->createClient();

// Fetch a single order
$order = $service->getOrder('VS-12345678901234');

// Acknowledge
$service->acknowledgeOrder('VS-12345678901234');

// Dispatch with tracking
$service->dispatchOrder('VS-12345678901234', [
    'tracking_number' => 'TRK-001',
    'courier'         => 'DPD',
    'dispatch_date'   => '2026-05-03',
]);

// Cancel
$service->cancelOrder('VS-12345678901234', 'Out of stock');
```

## Product & Stock

```php
$service = new \PortalPeople\virtualstock\services\ProductService();
$service->client = $module->createClient();

$products   = $service->listProducts(['supplier_code' => 'TSL']);
$product    = $service->getProduct('SKU-001');
$stockLevel = $service->getStockLevel('SKU-001');

if ($stockLevel->isAvailable()) {
    // product is in stock
}
```

## Webhooks

Register the endpoint in your URL rules:

```php
'virtualstock/webhook/receive' => 'virtualstock/webhook/receive',
```

Set `webhookSecret` in params-local.php. VirtualStock will POST signed JSON to
`/virtualstock/webhook/receive`. The module verifies the HMAC-SHA256 signature and
fires a Yii2 application event:

```php
Yii::$app->on('virtualstock.order.updated', function (\yii\base\Event $event) {
    $payload = $event->data; // full webhook payload array
    // handle order update ...
});
```

## Rate Limiting

The `RateLimiter` component enforces the 60 req/min VirtualStock limit using a
sliding-window counter stored in Yii cache. Attach it to the client:

```php
$client = $module->createClient();
$client->rateLimiter = Yii::createObject(\PortalPeople\virtualstock\components\RateLimiter::class);
```

## Response Caching

```php
$cache  = Yii::createObject(\PortalPeople\virtualstock\components\ApiCache::class);
$cached = $cache->get('orders', ['limit' => 10]);
if ($cached === null) {
    $cached = $client->getOrdersUpdatedSince(null, 10);
    $cache->set('orders', ['limit' => 10], $cached);
}
```

## Logging

```php
$client = $module->createClient();
$client->logger = Yii::createObject([
    'class'     => \PortalPeople\virtualstock\components\ApiLogger::class,
    'logBodies' => false, // set true for debugging only
    'debug'     => $module->debug,
]);
```

All log entries are tagged `virtualstock` so they can be routed to a dedicated
log target in `components.log`.

## Database Migrations

Run the bundled migrations to create the local tracking tables:

```bash
./yii migrate --migrationPath=@vendor/portalpeople/ahs-virtualstock/src/migrations
```

Tables created:
- `virtualstock_orders` — local order import tracking
- `virtualstock_api_log` — API request/response audit log
- `virtualstock_webhook_events` — inbound webhook event log

## Testing

```bash
cd NGauge_modules/ahs-virtualstock
composer install
./vendor/bin/phpunit
```

## License

MIT

