# Système de Permissions et Rôles
## Gestion des Stocks - Hôpital Psychiatrique de Bingerville

Ce document décrit le système de permissions et rôles implémenté avec **Spatie Laravel Permission**.

---

## 📋 Rôles Disponibles

### 1. **Super Administrateur**
- **Accès complet** : Peut effectuer toutes les actions sur toutes les ressources
- **Permissions** : Toutes les permissions sont accordées
- **Utilisation** : Gestion complète du système

### 2. **Administrateur**
- **Peut** :
  - ✅ Voir toutes les informations enregistrées par les magasiniers
  - ✅ Supprimer n'importe quel enregistrement
  - ✅ Approuver les demandes
  - ✅ Rejeter les demandes
- **Ne peut pas** :
  - ❌ Ajouter de nouveaux enregistrements
  - ❌ Modifier des enregistrements existants
- **Utilisation** : Supervision et validation des opérations

### 3. **Magasinier**
- **Peut** :
  - ✅ Voir toutes les demandes
  - ✅ Ajouter de nouveaux enregistrements
  - ✅ Modifier **uniquement** ses propres enregistrements (créés par lui)
  <!-- - Supprimer **uniquement** ses propres enregistrements -->
- **Ne peut pas** :
  - ❌ Approuver les demandes
  - ❌ Rejeter les demandes
  - ❌ Modifier les enregistrements créés par d'autres utilisateurs
- **Utilisation** : Saisie et gestion quotidienne des stocks

### 4. **Responsable du département**
- **Peut** :
  - ✅ **Demandes** :
    - Voir toutes les demandes de son département (tous statuts)
    - Créer de nouvelles demandes de stock
    - Modifier/Supprimer ses propres demandes **uniquement si statut = "en_attente"**
  - ✅ **Consultation** (lecture seule) :
    - Voir le catalogue des produits
    - Voir l'état des stocks disponibles
    - Voir l'historique des mouvements de son département
    - Voir les équipements de son département
    - Voir les catégories, fournisseurs, unités
  - ✅ **Notifications** :
    - Recevoir des notifications quand ses demandes sont approuvées/rejetées
- **Ne peut pas** :
  - ❌ Approuver ou rejeter des demandes (même les siennes)
  - ❌ Modifier les demandes créées par d'autres utilisateurs
  - ❌ Modifier ses demandes après validation/rejet
  - ❌ Créer/modifier des produits, catégories, fournisseurs
  - ❌ Gérer les stocks directement (entrées/sorties)
  - ❌ Accéder aux demandes des autres départements
- **Utilisation** : Créer et gérer les demandes de stock pour son département en fonction des besoins quotidiens

---

## 🔐 Permissions Disponibles

### Départements (`departments`)
- `departments.view` - Voir les départements
- `departments.create` - Créer un département
- `departments.update` - Modifier un département
- `departments.delete` - Supprimer un département

### Fournisseurs (`suppliers`)
- `suppliers.view` - Voir les fournisseurs
- `suppliers.create` - Créer un fournisseur
- `suppliers.update` - Modifier un fournisseur
- `suppliers.delete` - Supprimer un fournisseur

### Catégories (`categories`)
- `categories.view` - Voir les catégories
- `categories.create` - Créer une catégorie
- `categories.update` - Modifier une catégorie
- `categories.delete` - Supprimer une catégorie

### Produits (`products`)
- `products.view` - Voir les produits
- `products.create` - Créer un produit
- `products.update` - Modifier un produit
- `products.delete` - Supprimer un produit

### Stocks (`stocks`)
- `stocks.view` - Voir les stocks
- `stocks.create` - Créer un stock
- `stocks.update` - Modifier un stock
- `stocks.delete` - Supprimer un stock

### Mouvements de Stock (`movement_stocks`)
- `movement_stocks.view` - Voir les mouvements
- `movement_stocks.create` - Créer un mouvement
- `movement_stocks.update` - Modifier un mouvement
- `movement_stocks.delete` - Supprimer un mouvement

### Demandes (`requests`)
- `requests.view` - Voir les demandes
- `requests.create` - Créer une demande
- `requests.update` - Modifier une demande
- `requests.delete` - Supprimer une demande
- `requests.approve` - Approuver une demande
- `requests.reject` - Rejeter une demande

### Détails de Demandes (`request_details`)
- `request_details.view` - Voir les détails
- `request_details.create` - Créer un détail
- `request_details.update` - Modifier un détail
- `request_details.delete` - Supprimer un détail

### Équipements (`equipment`)
- `equipment.view` - Voir les équipements
- `equipment.create` - Créer un équipement
- `equipment.update` - Modifier un équipement
- `equipment.delete` - Supprimer un équipement

### Unités de Mesure (`units`)
- `units.view` - Voir les unités
- `units.create` - Créer une unité
- `units.update` - Modifier une unité
- `units.delete` - Supprimer une unité

### Utilisateurs (`users`) - Super Admin uniquement
- `users.view` - Voir les utilisateurs
- `users.create` - Créer un utilisateur
- `users.update` - Modifier un utilisateur
- `users.delete` - Supprimer un utilisateur

---

## 🛡️ Policies (Autorisations Granulaires)

Des **Policies** ont été créées pour gérer les autorisations spécifiques :

### BasePolicy
Classe de base contenant les méthodes communes :
- `isSuperAdmin()` - Vérifie si l'utilisateur est Super Admin
- `isAdmin()` - Vérifie si l'utilisateur est Admin
- `isMagasinier()` - Vérifie si l'utilisateur est Magasinier
- `isOwner()` - Vérifie si l'utilisateur est propriétaire de l'enregistrement
- `canModify()` - Vérifie si l'utilisateur peut modifier
- `canDelete()` - Vérifie si l'utilisateur peut supprimer

### Policies Créées
- `DepartmentPolicy`
- `ProductPolicy`
- `RequestPolicy` (avec méthodes `approve()` et `reject()`)
- `StockPolicy`
- `MovementStockPolicy`

### Logique des Policies

#### Pour la Modification (Update)
```php
- Super Admin : ✅ Peut modifier tout
- Admin : ❌ Ne peut pas modifier
- Magasinier : ✅ Peut modifier uniquement ses propres enregistrements (user_id)
```

#### Pour la Suppression (Delete)
```php
- Super Admin : ✅ Peut supprimer tout
- Admin : ✅ Peut supprimer tout
- Magasinier : ✅ Peut supprimer uniquement ses propres enregistrements
```

#### Pour l'Approbation/Rejet des Demandes
```php
- Super Admin : ✅ Peut approuver/rejeter
- Admin : ✅ Peut approuver/rejeter
- Magasinier : ❌ Ne peut pas approuver/rejeter
```

---

## 🚀 Installation et Utilisation

### 1. Exécuter le Seeder

```bash
php artisan db:seed --class=RolePermissionSeeder
```

Ou dans le `DatabaseSeeder` :

```php
$this->call([
    RolePermissionSeeder::class,
]);
```

### 2. Assigner un Rôle à un Utilisateur

```php
$user = User::find(1);
$user->assignRole('Super Administrateur');
// ou
$user->assignRole('Administrateur');
// ou
$user->assignRole('Magasinier');
```

### 3. Vérifier les Permissions dans les Controllers

```php
// Vérifier une permission
if ($user->hasPermissionTo('products.create')) {
    // L'utilisateur peut créer un produit
}

// Vérifier un rôle
if ($user->hasRole('Super Administrateur')) {
    // L'utilisateur est Super Admin
}

// Utiliser les gates
Gate::authorize('create', Product::class);
```

### 4. Utiliser les Policies dans les Controllers

```php
use Illuminate\Support\Facades\Gate;

public function update(Request $request, Product $product)
{
    // Vérifier l'autorisation
    Gate::authorize('update', $product);
    
    // Ou utiliser la méthode authorize() du controller
    $this->authorize('update', $product);
    
    // Continuer avec la logique...
}
```

### 5. Utiliser dans les Vues (Blade)

```blade
@can('create', App\Models\Product::class)
    <a href="{{ route('products.create') }}">Créer un produit</a>
@endcan

@can('approve', $request)
    <button>Approuver</button>
@endcan

@role('Super Administrateur')
    <p>Vous êtes Super Admin</p>
@endrole
```

### 6. Middleware dans les Routes

```php
Route::middleware(['auth', 'role:Super Administrateur'])->group(function () {
    // Routes pour Super Admin
});

Route::middleware(['auth', 'permission:requests.approve'])->group(function () {
    // Routes nécessitant la permission d'approbation
});
```

---

## 📝 Exemples d'Utilisation

### Exemple 1 : Créer un Produit (Magasinier)

```php
public function store(Request $request)
{
    // Vérifier la permission
    Gate::authorize('create', Product::class);
    
    // Créer le produit avec l'utilisateur actuel
    $product = Product::create([
        ...$request->validated(),
        'user_id' => auth()->id(), // Important pour les policies
    ]);
    
    return redirect()->route('products.index');
}
```

### Exemple 2 : Modifier un Produit (Magasinier - seulement ses propres)

```php
public function update(Request $request, Product $product)
{
    // La policy vérifie automatiquement si c'est le propriétaire
    Gate::authorize('update', $product);
    
    $product->update($request->validated());
    
    return redirect()->route('products.index');
}
```

### Exemple 3 : Approuver une Demande (Admin)

```php
public function approve(Request $requestModel)
{
    // Vérifier la permission et le statut
    Gate::authorize('approve', $requestModel);
    
    $requestModel->update([
        'status' => 'validée',
        'approved_by' => auth()->id(),
    ]);
    
    return redirect()->back();
}
```

---

## 🔄 Matrice des Permissions

| Action | Super Admin | Admin | Magasinier | Responsable Dept. |
|--------|-------------|-------|------------|-------------------|
| **Voir** | ✅ Tout | ✅ Tout | ✅ Tout | ✅ Tout (lecture seule) |
| **Créer** | ✅ Tout | ❌ | ✅ Tout | ✅ Demandes uniquement |
| **Modifier** | ✅ Tout | ❌ | ✅ Ses propres | ✅ Ses demandes (en attente) |
| **Supprimer** | ✅ Tout | ✅ Tout | ✅ Ses propres | ✅ Ses demandes (en attente) |
| **Approuver Demandes** | ✅ | ✅ | ❌ | ❌ |
| **Rejeter Demandes** | ✅ | ✅ | ❌ | ❌ |
| **Notifications** | ✅ | ✅ | ✅ | ✅ Sur ses demandes |

---

## 📦 Produits & Stocks (Vue unifiée)

La page **Produits & Stocks** combine le catalogue produits et les niveaux de stock. Les permissions sont gérées ainsi :

| Action | Permission requise | Rôle |
|--------|-------------------|------|
| **Accéder à la page** | `products.view` **OU** `stocks.view` | Tous ceux qui peuvent voir produits ou stocks |
| **Bouton Nouveau produit** | `products.create` | Super Admin, Magasinier |
| **Stock initial (à la création)** | `stocks.create` | Si quantité initiale > 0 |
| **Bouton Voir (mouvements)** | `products.view` **OU** `stocks.view` | Tous |
| **Bouton Modifier** | `products.update` + ProductPolicy (propriétaire si Magasinier) | Super Admin, Magasinier (ses propres) |
| **Bouton Supprimer** | `products.delete` + ProductPolicy | Super Admin, Admin (tout), Magasinier (ses propres) |

---

## ⚠️ Notes Importantes

1. **Propriété des Enregistrements** : Les enregistrements doivent avoir un champ `user_id` pour que les policies fonctionnent correctement
2. **Cache des Permissions** : Spatie met en cache les permissions. Utilisez `php artisan permission:cache-reset` si nécessaire
3. **Soft Deletes** : Les policies prennent en compte les soft deletes
4. **Demandes** : Seules les demandes avec le statut `en_attente` peuvent être approuvées/rejetées

---

## 🎯 Prochaines Étapes

1. ✅ Exécuter le seeder : `php artisan db:seed --class=RolePermissionSeeder`
2. ✅ Assigner les rôles aux utilisateurs existants
3. ✅ Implémenter les vérifications dans les controllers
4. ✅ Ajouter les middlewares dans les routes
5. ✅ Tester les permissions avec différents rôles

---

**Système de permissions configuré et prêt à l'emploi !** 🎉

