# Directives Projet kView INVESTOR - Phase 1

## Objectif

Creer une nouvelle application **kView INVESTOR** pour suivre des investissements en :

- Private Equity
- Private Debt

Application **API-only**, sans interface utilisateur.

## Emplacement du projet

```text
C:\dev.cloud\kview_investor
```

## Stack technique

- Laravel 11
- PHP 8.4, cible Composer fixee a PHP `8.4.22`
- PostgreSQL
- Laravel Passport pour l'authentification API
- Utilisation du package partage :

```text
lncshared/ (dans le depot kview_investor)
```

## Bases PostgreSQL

Creer deux bases :

```text
kview_investor
kview_investor_uat
```

Utilisateur applicatif :

```text
kview_investor_user
```

## PHP

PHP 8.4.22 utilise explicitement :

```text
C:\Program Files\php\PHP 8.4.22\php.exe
```

Variable PowerShell souhaitee :

```powershell
$env:PHP84 = 'C:\Program Files\php\PHP 8.4.22\php.exe'
```

Composer doit cibler :

```json
"platform": {
  "php": "8.4.22"
}
```

## Qualite Code

Installer et configurer :

- Laravel Pint
- PHPStan / Larastan

Creer une documentation dans :

```text
C:\dev.cloud\kview_investor\dev_guide\
```

Fichier demande :

```text
pint_larastan.md
```

## Modeles Principaux

Creer les modeles :

- `Fund`
- `CallDistrib`
- `CapitalAccount`

Ces modeles doivent :

- etendre `DynamicModel`
- utiliser les UUID
- stocker une partie des champs en `dynamic_fields`

Le modele `Fund` doit aussi utiliser :

- `NameFullName`

## Modele ExchangeRate

Creer aussi :

- `ExchangeRate`

Reprendre la specification depuis Tikeasy :

```text
C:\dev.cloud\tikeasy
```

Champs :

```text
id uuid
cur1 string(3)
cur2 string(3)
rate decimal(20,10)
rate_date date
source string default ECB
timestamps
```

Contrainte :

```text
unique(cur1, cur2, rate_date, source)
```

Ajouter un service de synchronisation ECB.

## Dynamic Fields

Creer un seeder pour alimenter la table `dynamic_fields`.

### Dynamic Fields Fund

```text
strategy enum/private_equity,private_debt,real_assets,venture,other
asset_class enum/private_equity,private_debt
vintage_year integer nullable
currency char(3)
commitment decimal(20,2)
manager_name string nullable
jurisdiction string nullable
status enum/due_diligence,active,harvesting,liquidated,closed
inception_date date nullable
final_close_date date nullable
notes text nullable
```

### Dynamic Fields CallDistrib

```text
notice_date date nullable
event_date date
currency char(3)
amount decimal(20,2)
amount_base decimal(20,2) nullable
base_currency char(3) nullable
fx_rate decimal(20,10) nullable
category string nullable
reference string nullable
description text nullable
status enum/draft,confirmed,cancelled
```

### Dynamic Fields CapitalAccount

```text
commitment decimal(20,2)
called_amount decimal(20,2)
distributed_amount decimal(20,2)
nav decimal(20,2)
unfunded_commitment decimal(20,2)
dpi decimal(20,8) nullable
rvpi decimal(20,8) nullable
tvpi decimal(20,8) nullable
irr decimal(20,8) nullable
source string nullable
```

## Cles Metier

Creer les contraintes metier suivantes :

```text
call_distribs: fund_id + due_date
capital_accounts: fund_id + as_of_date
```

Remarque d'implementation retenue :

- garder un `id` UUID technique
- ajouter une contrainte unique metier sur les champs ci-dessus

## Dates CallDistrib

Clarification fonctionnelle :

```text
notice_date = date de notification officielle
event_date  = date economique de l'operation
due_date    = date limite de paiement ou reglement
```

## API

Creer une API versionnee :

```text
/api/v1
```

Endpoints principaux :

```text
/funds
/funds/{fund}/call-distribs
/funds/{fund}/capital-accounts
/call-distribs
/capital-accounts
/exchange-rates
/exchange-rates/latest
/exchange-rates/convert
/exchange-rates/sync-ecb
/status
/db-status
```

Toutes les routes API doivent etre protegees par Passport, sauf endpoints explicitement publics si necessaire.

## Authentification

Utiliser Laravel Passport.

Activer le password grant :

```php
Passport::enablePasswordGrant();
```

Creer un client Passport password grant.

Endpoint token :

```text
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
```

Corps attendu :

```text
grant_type=password
client_id=<uuid client>
client_secret=<secret>
username=<email>
password=<password>
scope=*
```

## Commandes Artisan

Creer une commande similaire a Tikeasy pour creer un utilisateur.

Commandes :

```text
lnc:create-user
kview_investor:create-user
```

Exemple :

```powershell
php artisan lnc:create-user test@example.com --name="Test User" --password="Secret123!"
```

Options :

```text
--name
--password
--force
```

## Nginx Local

Modifier :

```text
C:\dev.local\myPath\Ngnix.local.cmd
```

Ajouter un serveur PHP-CGI dedie kView INVESTOR :

```text
PHP 8.4.22
127.0.0.1:8005
```

Ajouter la conf Nginx :

```text
C:\dev.cloud\nginx\nginx-1.16.1\sites-enabled\kview_investor.conf
```

Configuration retenue :

```text
server_name kview-investor.local
listen 84
root C:/dev.cloud/kview_investor/public
fastcgi_pass 127.0.0.1:8005
```

URL locale :

```text
http://kview-investor.local:84
```

Mettre aussi :

```text
APP_URL=http://kview-investor.local:84
```

## Hosts Windows

Verifier que :

```text
kview-investor.local -> 127.0.0.1
```

## Tests

Creer des tests API pour :

- routes protegees par Passport
- creation / lecture / mise a jour `Fund`
- creation `CallDistrib`
- creation `CapitalAccount`
- presence des `dynamic_fields`
- workflow token Passport

Commandes de validation :

```powershell
php artisan migrate --seed
php artisan migrate:status
php vendor\bin\pint --test
php -d memory_limit=512M vendor\bin\phpstan analyse --no-progress
php vendor\bin\phpunit
```

## Documentation API

Creer une collection ou documentation API exploitable avec Postman/Bruno.

Inclure notamment :

- obtention token `/oauth/token`
- appel `/api/v1/status`
- CRUD `funds`
- creation `call-distribs`
- creation `capital-accounts`
- endpoints `exchange-rates`
