## Vilogi Integration — Next Steps

Codebase as of May 2026. The accounting abstraction layer is complete and migrations have run.

**Current architecture:**
- `AccountingConfig` / `AccountingJournalEntry` / `AccountingContrepartie` models
- `AccountingSyncInterface` → `VilogiAccountingService` → `VilogiService`
- `AccountingSyncFactory` registered in `AppServiceProvider` with `vilogi` driver
- `SyncToAccountingJob` dispatches via queue `accounting`
- `JournalEntryService` builds `AccountingPayload`; all translation to Vilogi format is isolated in `VilogiAccountingService::toVilogiPayload()`

---

### Blocking before production

**1. CRUD for contrepartie accounts**

Add endpoints to manage `accounting_contreparties`. Each service provider needs one account per service type (e.g. Water → `60100000`, Electricity → `60200000`).

Suggested routes (superadmin block in `routes/api.php`):
```
GET    /api/v1/superadmin/vilogi-config/{serviceProviderId}/contreparties
POST   /api/v1/superadmin/vilogi-config/{serviceProviderId}/contreparties
DELETE /api/v1/superadmin/vilogi-config/{serviceProviderId}/contreparties/{serviceTypeId}
```

Request body for POST: `{ "service_type_id": 1, "account": "60100000" }`.
Update `VilogiConfigController::show()` to include the contreparties array in its response.

**2. Expose `accounting_external_id` on the Site update endpoint**

The Vilogi `copropriété` identifier (e.g. `69509`) must be settable per site from the UI.
Add `accounting_external_id` to whatever Site PUT/PATCH endpoint the superadmin uses.
To look up the value for a site: `GET https://copro.vilogi.com/rest/coproLot?token={token}&copro={copro_id}`.

**3. Decouple sync from email send (make it manual)**

Currently `MailingRepo::processLotAndSendEmail()` automatically queues a sync job after each successful email. This couples two independent operations and makes it hard to re-trigger or skip.

Replace the automatic trigger with a deliberate admin action:
- Remove `createAccountingJournalEntry()` call from `MailingRepo`
- Add `POST /api/v1/admin/accounting-journal-entries/sync/{archivedSessionId}` — creates the `AccountingJournalEntry` and dispatches `SyncToAccountingJob`
- The PDF must already exist at the time this endpoint is called (either generated on demand or reused from a prior email send)

**4. Encrypt the API key at rest**

`AccountingConfig.settings` stores the Vilogi API key as plaintext JSON. Add a cast to encrypt it:

```php
// AccountingConfig model
protected $casts = [
    'settings' => 'encrypted:array',
];
```

Laravel handles encryption/decryption transparently. Existing rows will need re-saving after the cast is added.

---

### Minor gaps

**5. PDF cleanup in `SyncToAccountingJob::failed()`**

The `failed()` callback (called by Laravel's queue infrastructure when all attempts are exhausted) currently only logs. If Laravel kills the job before the in-job retry logic runs, the PDF is orphaned.
Add `app(JournalEntryService::class)->cleanupPdfFile($entry)` to `failed()`, same pattern as `handleException()`.

**6. Retry backoff off-by-one**

In `SyncToAccountingJob::handleException()`, `markAsFailed()` increments `retry_count` before the backoff index is read:
```php
$delay = $this->backoff[$journalEntry->retry_count - 1] ?? 300;
```
Verify this is correct after `markAsFailed()` runs — the index may need to be `$journalEntry->retry_count - 2` depending on whether you read the count before or after the update.

**7. Rename the feature flag column**

`service_providers.allow_vilogi_webhook` controls whether the accounting sync is enabled. The column name is misleading now that the abstraction is generic. A future migration should rename it to `accounting_sync_enabled` and update all references (`MailingRepo::isAccountingEnabled`, `ServiceProvider::$casts`, `ServiceProvider::$fillable`).

---

### Cleanup (safe to defer)

**8. Delete old Vilogi-specific files**

These files are superseded and should be removed once the new flow is smoke-tested in production:
- `app/Jobs/SyncToVilogiJob.php`
- `app/Models/VilogiConfig.php`
- `app/Models/VilogiJournalEntry.php`
- `app/Models/VilogiContrepartie.php` (if it still exists)
- Any remaining migrations that reference the old tables (already run — safe to delete)

**9. Queue worker**

The `accounting` queue must be running in production for `SyncToAccountingJob` to process:
```
php artisan queue:work --queue=accounting --tries=3
```
Add this to the server's process manager (Supervisor, systemd, etc.).

---

### Feature test (required before considering complete)

Write a test that:
1. Seeds an `AccountingConfig` (provider_type=vilogi, settings with a fake api_key)
2. Seeds an `AccountingContrepartie` for the session's service_type
3. Sets `accounting_external_id` on the site
4. Mocks the Vilogi HTTP endpoint
5. Dispatches `SyncToAccountingJob` synchronously
6. Asserts the exact request shape sent to the mock:
   - Query params: `token`, `idAdh`, `idCopro`
   - Body: `saisie` (DD/MM/YYYY), `compte`, `contrepartie`, `copropriete`, `debit`, `libelle`, `piece`, `file.{file, nameFile}`
7. Asserts the `AccountingJournalEntry` is marked `synced` with the returned external ID
