# 🐾 IMPLEMENTACIÓN LITTERS MODULE

## **📋 OBJETIVO ESPECÍFICO**

Implementar la gestión de **Litters (Camadas)**, que depende de **Animals**, incluyendo validaciones de integridad referencial y lógica de negocio específica para camadas.

---

## **🎯 ANÁLISIS LITTERS MODULE**

### **🔹 ENTIDAD A IMPLEMENTAR:**

**Litters (Camadas)**
- **Depende de Animals** - Validación de integridad referencial.
- **Atributos clave**: Fecha de nacimiento, padre, madre, número de crías.
- **CRUD con validaciones**: Crear, listar, editar y eliminar camadas.

### **🔹 RELACIÓN DEFINIDA:**
```
Animals (1) -----> (N) Litters
```

### **🔹 CARACTERÍSTICAS CLAVE:**
- ✅ **Dependiente de Animals**: Cada camada debe tener padre y madre válidos.
- ✅ **Validación referencial**: Los padres deben ser de la misma especie.
- ✅ **Atributos únicos**: Identificador único por camada.

### **🔹 REGLAS DE NEGOCIO:**
- ✅ El father_id y mother_id son obligatorios y deben existir.
- ✅ Validar que los padres sean de la misma especie.
- ✅ Las camadas pueden estar activas o inactivas.

---

## **🏗️ PLAN DE IMPLEMENTACIÓN PASO A PASO**

### **FASE 1: PREPARACIÓN Y ESTRUCTURA BASE**

#### **PASO 1.1: Crear Estructura de Directorios para Litters**

**🔧 COMANDOS PHP ARTISAN:**

```powershell
# Crear controlador de Litters
php artisan make:controller Animal/Catalog/LitterController --api

# Crear Form Requests para Litters
php artisan make:request Animal/Catalog/StoreLitterRequest
php artisan make:request Animal/Catalog/UpdateLitterRequest

# Crear excepciones personalizadas para Litters
php artisan make:exception Animal/Catalog/LitterNotFoundException
php artisan make:exception Animal/Catalog/LitterValidationException

# Crear tests para Litters
php artisan make:test Animal/LitterRepositoryTest --unit
php artisan make:test Animal/LitterServiceTest --unit
php artisan make:test Animal/LitterValidatorTest --unit
php artisan make:test Animal/LitterManagementTest
```

**📁 Estructura resultante para Litters:**
```
app/
├── Interfaces/
│   └── Animal/
│       └── Catalog/
│           ├── LitterRepositoryInterface.php
│           └── LitterServiceInterface.php
├── Repositories/
│   └── Animal/
│       └── Catalog/
│           └── LitterRepository.php
├── Services/
│   └── Animal/
│       └── Catalog/
│           └── LitterService.php
├── Http/
│   ├── Controllers/
│   │   └── Animal/
│   │       └── Catalog/
│   │           └── LitterController.php
│   └── Requests/
│       └── Animal/
│           └── Catalog/
│               ├── StoreLitterRequest.php
│               └── UpdateLitterRequest.php
├── Exceptions/
│   └── Animal/
│       └── Catalog/
│           ├── LitterNotFoundException.php
│           └── LitterValidationException.php
└── Validators/
    └── Animal/
        └── Catalog/
            └── LitterValidator.php
```

---

### **FASE 2: IMPLEMENTACIÓN COMPLETA DE LITTERS**

#### **PASO 2.1: Interfaces de Litters**

**LitterRepositoryInterface.php:**
```php
<?php

namespace App\Interfaces\Animal\Catalog;

interface LitterRepositoryInterface
{
    public function findAll();
    public function findById(int $id);
    public function create(array $data);
    public function update(int $id, array $data);
    public function delete(int $id);
    public function restore(int $id);
    public function exists(int $id): bool;
}
```

**LitterServiceInterface.php:**
```php
<?php

namespace App\Interfaces\Animal\Catalog;

interface LitterServiceInterface
{
    public function getAllLitters();
    public function getLitterById(int $id);
    public function createLitter(array $data);
    public function updateLitter(int $id, array $data);
    public function deleteLitter(int $id);
    public function restoreLitter(int $id);
    public function validateLitterExists(int $id): bool;
}
```

#### **PASO 2.2: Repositorio de Litters**

**LitterRepository.php:**
```php
<?php

namespace App\Repositories\Animal\Catalog;

use App\Interfaces\Animal\Catalog\LitterRepositoryInterface;
use App\Models\Litter;
use App\Exceptions\Animal\Catalog\LitterNotFoundException;

class LitterRepository implements LitterRepositoryInterface
{
    public function findAll()
    {
        return Litter::all();
    }

    public function findById(int $id)
    {
        $litter = Litter::find($id);
        if (!$litter) {
            throw new LitterNotFoundException("Litter with ID {$id} not found");
        }
        return $litter;
    }

    public function create(array $data)
    {
        return Litter::create($data);
    }

    public function update(int $id, array $data)
    {
        $litter = $this->findById($id);
        $litter->update($data);
        return $litter;
    }

    public function delete(int $id)
    {
        $litter = $this->findById($id);
        return $litter->delete();
    }

    public function restore(int $id)
    {
        $litter = Litter::withTrashed()->find($id);
        if (!$litter) {
            throw new LitterNotFoundException("Litter with ID {$id} not found");
        }
        return $litter->restore();
    }

    public function exists(int $id): bool
    {
        return Litter::where('id', $id)->exists();
    }
}
```

#### **PASO 2.3: Servicio de Litters**

**LitterService.php:**
```php
<?php

namespace App\Services\Animal\Catalog;

use App\Interfaces\Animal\Catalog\LitterServiceInterface;
use App\Interfaces\Animal\Catalog\LitterRepositoryInterface;
use App\Validators\Animal\Catalog\LitterValidator;
use Illuminate\Support\Facades\DB;

class LitterService implements LitterServiceInterface
{
    protected $litterRepository;
    protected $validator;

    public function __construct(
        LitterRepositoryInterface $litterRepository,
        LitterValidator $validator
    ) {
        $this->litterRepository = $litterRepository;
        $this->validator = $validator;
    }

    public function getAllLitters()
    {
        return $this->litterRepository->findAll();
    }

    public function getLitterById(int $id)
    {
        return $this->litterRepository->findById($id);
    }

    public function createLitter(array $data)
    {
        $this->validator->validateForCreation($data);
        DB::beginTransaction();
        try {
            $litter = $this->litterRepository->create($data);
            DB::commit();
            return $litter;
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    public function updateLitter(int $id, array $data)
    {
        $this->validator->validateForUpdate($id, $data);
        DB::beginTransaction();
        try {
            $litter = $this->litterRepository->update($id, $data);
            DB::commit();
            return $litter;
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    public function deleteLitter(int $id)
    {
        $this->validator->validateForDeletion($id);
        DB::beginTransaction();
        try {
            $result = $this->litterRepository->delete($id);
            DB::commit();
            return $result;
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    public function restoreLitter(int $id)
    {
        $this->validator->validateForRestore($id);
        DB::beginTransaction();
        try {
            $result = $this->litterRepository->restore($id);
            DB::commit();
            return $result;
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }
    }

    public function validateLitterExists(int $id): bool
    {
        return $this->litterRepository->exists($id);
    }
}
```

#### **PASO 2.4: Validador de Litters**

**LitterValidator.php:**
```php
<?php

namespace App\Validators\Animal\Catalog;

use App\Interfaces\Animal\Catalog\LitterRepositoryInterface;
use App\Exceptions\Animal\Catalog\LitterValidationException;

class LitterValidator
{
    protected $litterRepository;

    public function __construct(LitterRepositoryInterface $litterRepository)
    {
        $this->litterRepository = $litterRepository;
    }

    public function validateForCreation(array $data)
    {
        $this->validateRequired($data);
    }

    public function validateForUpdate(int $id, array $data)
    {
        $this->validateExists($id);
    }

    public function validateForDeletion(int $id)
    {
        $this->validateExists($id);
    }

    public function validateForRestore(int $id)
    {
        $litter = \App\Models\Litter::withTrashed()->find($id);
        if (!$litter || !$litter->trashed()) {
            throw new LitterValidationException("Litter with ID {$id} is not deleted");
        }
    }

    private function validateRequired(array $data)
    {
        if (empty($data['father_id']) || empty($data['mother_id']) || empty($data['birth_date'])) {
            throw new LitterValidationException('Father, mother, and birth date are required');
        }
    }

    private function validateExists(int $id)
    {
        if (!$this->litterRepository->exists($id)) {
            throw new LitterValidationException("Litter with ID {$id} does not exist");
        }
    }
}
```

#### **PASO 2.5: Excepciones de Litters**

**LitterNotFoundException.php:**
```php
<?php

namespace App\Exceptions\Animal\Catalog;

use Exception;

class LitterNotFoundException extends Exception
{
    protected $message = 'Litter not found';

    public function __construct($message = null, $code = 404, Exception $previous = null)
    {
        $message = $message ?: $this->message;
        parent::__construct($message, $code, $previous);
    }

    public function render($request)
    {
        return response()->json([
            'success' => false,
            'error' => 'Litter Not Found',
            'message' => $this->getMessage(),
            'code' => $this->getCode()
        ], $this->getCode());
    }
}
```

**LitterValidationException.php:**
```php
<?php

namespace App\Exceptions\Animal\Catalog;

use Exception;

class LitterValidationException extends Exception
{
    protected $message = 'Litter validation failed';

    public function __construct($message = null, $code = 422, Exception $previous = null)
    {
        $message = $message ?: $this->message;
        parent::__construct($message, $code, $previous);
    }

    public function render($request)
    {
        return response()->json([
            'success' => false,
            'error' => 'Validation Error',
            'message' => $this->getMessage(),
            'code' => $this->getCode()
        ], $this->getCode());
    }
}
```

#### **PASO 2.6: Form Requests de Litters**

**StoreLitterRequest.php:**
```php
<?php

namespace App\Http\Requests\Animal\Catalog;

use Illuminate\Foundation\Http\FormRequest;

class StoreLitterRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'father_id' => 'required|integer|exists:animals,id',
            'mother_id' => 'required|integer|exists:animals,id',
            'birth_date' => 'required|date',
            'number_of_offspring' => 'required|integer|min:1'
        ];
    }

    public function messages()
    {
        return [
            'father_id.required' => 'El padre es obligatorio',
            'mother_id.required' => 'La madre es obligatoria',
            'birth_date.required' => 'La fecha de nacimiento es obligatoria',
            'number_of_offspring.required' => 'El número de crías es obligatorio'
        ];
    }
}
```

**UpdateLitterRequest.php:**
```php
<?php

namespace App\Http\Requests\Animal\Catalog;

use Illuminate\Foundation\Http\FormRequest;

class UpdateLitterRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'father_id' => 'sometimes|required|integer|exists:animals,id',
            'mother_id' => 'sometimes|required|integer|exists:animals,id',
            'birth_date' => 'sometimes|required|date',
            'number_of_offspring' => 'sometimes|required|integer|min:1'
        ];
    }

    public function messages()
    {
        return [
            'father_id.required' => 'El padre es obligatorio',
            'mother_id.required' => 'La madre es obligatoria',
            'birth_date.required' => 'La fecha de nacimiento es obligatoria',
            'number_of_offspring.required' => 'El número de crías es obligatorio'
        ];
    }
}
```

#### **PASO 2.7: Controlador de Litters**

**LitterController.php:**
```php
<?php

namespace App\Http\Controllers\Animal\Catalog;

use App\Http\Controllers\Controller;
use App\Interfaces\Animal\Catalog\LitterServiceInterface;
use App\Http\Requests\Animal\Catalog\StoreLitterRequest;
use App\Http\Requests\Animal\Catalog\UpdateLitterRequest;
use App\Exceptions\Animal\Catalog\LitterNotFoundException;
use App\Exceptions\Animal\Catalog\LitterValidationException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class LitterController extends Controller
{
    protected $litterService;

    public function __construct(LitterServiceInterface $litterService)
    {
        $this->litterService = $litterService;
    }

    public function index(Request $request): JsonResponse
    {
        try {
            $litters = $this->litterService->getAllLitters();
            return response()->json([
                'success' => true,
                'data' => $litters,
                'message' => 'Litters retrieved successfully'
            ], 200);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving litters',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function store(StoreLitterRequest $request): JsonResponse
    {
        try {
            $litter = $this->litterService->createLitter($request->validated());
            return response()->json([
                'success' => true,
                'data' => $litter,
                'message' => 'Litter created successfully'
            ], 201);
        } catch (LitterValidationException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
                'error_type' => 'validation'
            ], 422);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error creating litter',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function show(int $id): JsonResponse
    {
        try {
            $litter = $this->litterService->getLitterById($id);
            return response()->json([
                'success' => true,
                'data' => $litter,
                'message' => 'Litter retrieved successfully'
            ], 200);
        } catch (LitterNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
                'error_type' => 'not_found'
            ], 404);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error retrieving litter',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function update(UpdateLitterRequest $request, int $id): JsonResponse
    {
        try {
            $litter = $this->litterService->updateLitter($id, $request->validated());
            return response()->json([
                'success' => true,
                'data' => $litter,
                'message' => 'Litter updated successfully'
            ], 200);
        } catch (LitterNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
                'error_type' => 'not_found'
            ], 404);
        } catch (LitterValidationException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
                'error_type' => 'validation'
            ], 422);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error updating litter',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function destroy(int $id): JsonResponse
    {
        try {
            $this->litterService->deleteLitter($id);
            return response()->json([
                'success' => true,
                'message' => 'Litter deleted successfully'
            ], 200);
        } catch (LitterNotFoundException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
                'error_type' => 'not_found'
            ], 404);
        } catch (LitterValidationException $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
                'error_type' => 'validation'
            ], 422);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Error deleting litter',
                'error' => $e->getMessage()
            ], 500);
        }
    }
}
```

---

### **FASE 3: CONFIGURACIÓN E INTEGRACIÓN**

#### **PASO 3.1: Actualizar Inyección de Dependencias**

**AppServiceProvider.php (agregar a lo existente):**
```php
public function register()
{
    // Animal Module Bindings (ya existentes)
    $this->app->bind(
        \App\Interfaces\Animal\Catalog\AnimalRepositoryInterface::class,
        \App\Repositories\Animal\Catalog\AnimalRepository::class
    );
    
    $this->app->bind(
        \App\Interfaces\Animal\Catalog\AnimalServiceInterface::class,
        \App\Services\Animal\Catalog\AnimalService::class
    );

    // Litter Module Bindings (nuevos)
    $this->app->bind(
        \App\Interfaces\Animal\Catalog\LitterRepositoryInterface::class,
        \App\Repositories\Animal\Catalog\LitterRepository::class
    );
    
    $this->app->bind(
        \App\Interfaces\Animal\Catalog\LitterServiceInterface::class,
        \App\Services\Animal\Catalog\LitterService::class
    );
}
```

#### **PASO 3.2: Actualizar Definición de Rutas**

**routes/bully.php (agregar a las existentes):**
```php
<?php

use App\Http\Controllers\Animal\Catalog\LitterController;
use Illuminate\Support\Facades\Route;

Route::prefix('animal')->group(function () {
    Route::prefix('catalog')->group(function () {
        
        // Litter Routes (nuevos)
        Route::apiResource('litters', LitterController::class);
        Route::get('litters/search', [LitterController::class, 'search']);
        Route::post('litters/{id}/restore', [LitterController::class, 'restore']);
        Route::get('litters/stats', [LitterController::class, 'stats']);
    });
});
```

---
