# Request for Design (RFD) - Technical Specification

## Almacen - Inventory Management System

**Project:** Almacen2  
**Version:** 1.0.0  
**Date:** 2026-03-18  
**Status:** Draft  

---

## 1. Architecture Overview

### 1.1 High-Level Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                      Presentation Layer                       │
│  ┌─────────────────────┐    ┌─────────────────────────────┐ │
│  │   Web (Blade+BS5)   │    │   API (JSON REST v1)       │ │
│  │   - Breeze Auth     │    │   - Sanctum Token Auth     │ │
│  │   - Server Render   │    │   - SPA/Mobile Ready      │ │
│  └─────────────────────┘    └─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      Service Layer                            │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐  │
│  │ ItemSvc  │ │ LoanSvc  │ │ ReportSvc│ │ ImportExport │  │
│  └──────────┘ └──────────┘ └──────────┘ └──────────────┘  │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                      Data Layer                              │
│  ┌──────────────────────────────────────────────────────┐   │
│  │              Eloquent ORM (Laravel)                   │   │
│  │  Items │ Categories │ Locations │ Transactions     │   │
│  └──────────────────────────────────────────────────────┘   │
│                              │                              │
│                              ▼                              │
│  ┌────────────────┐    ┌─────────────────────────────┐      │
│  │ SQLite (dev)  │    │ PostgreSQL 15+ (prod)      │      │
│  └────────────────┘    └─────────────────────────────┘      │
└─────────────────────────────────────────────────────────────┘
```

### 1.2 Directory Structure

```
almacen2/
├── app/
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── Api/V1/
│   │   │   │   ├── ApiController.php          # Base API controller
│   │   │   │   ├── AuthApiController.php      # API authentication
│   │   │   │   ├── ItemsApiController.php      # Items CRUD
│   │   │   │   ├── CategoriesApiController.php # Categories CRUD
│   │   │   │   ├── LocationsApiController.php  # Locations CRUD
│   │   │   │   ├── TransactionsApiController.php # All transaction types
│   │   │   │   ├── ReportsApiController.php     # Reports & exports
│   │   │   │   └── UsersApiController.php       # Users CRUD
│   │   │   └── Web/
│   │   │       ├── Auth/
│   │   │       ├── DashboardController.php
│   │   │       ├── ItemController.php
│   │   │       ├── LoanController.php
│   │   │       ├── ProvisionController.php
│   │   │       ├── TransferController.php
│   │   │       └── ReportController.php
│   │   ├── Middleware/
│   │   │   └── RoleMiddleware.php              # Role-based access
│   │   ├── Requests/Api/
│   │   │   ├── StoreItemRequest.php
│   │   │   ├── UpdateItemRequest.php
│   │   │   ├── StoreTransactionRequest.php
│   │   │   └── LoginRequest.php
│   │   └── Resources/
│   │       ├── ItemResource.php
│   │       ├── TransactionResource.php
│   │       └── UserResource.php
│   ├── Models/
│   │   ├── Item.php
│   │   ├── Category.php
│   │   ├── Location.php
│   │   ├── Transaction.php
│   │   ├── TransactionItem.php
│   │   ├── User.php (existing, enhanced)
│   │   └── UniformSize.php
│   ├── Services/
│   │   ├── ItemService.php
│   │   ├── TransactionService.php
│   │   ├── ReportService.php
│   │   ├── ExportService.php
│   │   ├── ImportService.php
│   │   └── BarcodeService.php
│   └── Policies/
│       ├── ItemPolicy.php
│       └── TransactionPolicy.php
├── database/
│   ├── migrations/
│   │   ├── 2026_03_18_000001_create_items_table.php
│   │   ├── 2026_03_18_000002_create_categories_table.php
│   │   ├── 2026_03_18_000003_create_locations_table.php
│   │   ├── 2026_03_18_000004_create_transactions_table.php
│   │   ├── 2026_03_18_000005_create_transaction_items_table.php
│   │   └── 2026_03_18_000006_create_uniform_sizes_table.php
│   ├── factories/
│   │   ├── ItemFactory.php
│   │   ├── CategoryFactory.php
│   │   ├── LocationFactory.php
│   │   └── TransactionFactory.php
│   └── seeders/
│       ├── CategorySeeder.php
│       ├── LocationSeeder.php
│       └── DatabaseSeeder.php
├── routes/
│   ├── web.php
│   └── api.php
└── tests/
    ├── Feature/
    │   ├── ItemsTest.php
    │   ├── LoansTest.php
    │   ├── ProvisionsTest.php
    │   └── TransfersTest.php
    └── Unit/
        ├── ItemServiceTest.php
        └── TransactionServiceTest.php
```

---

## 2. Database Schema

### 2.1 Modern Tables (Target)

#### `items`
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | BIGINT UNSIGNED | PK, AUTO_INCREMENT | Primary key |
| sap_code | VARCHAR(50) | UNIQUE, NULLABLE | SAP system code |
| barcode | VARCHAR(100) | UNIQUE, NULLABLE | Auto-generated barcode |
| description | VARCHAR(255) | NOT NULL | Item description |
| short_description | VARCHAR(100) | NULLABLE | Short name |
| category_id | BIGINT UNSIGNED | FK → categories | Category reference |
| location_id | BIGINT UNSIGNED | FK → locations | Current location |
| stock | INT | DEFAULT 0 | Current stock quantity |
| min_stock | INT | DEFAULT 0 | Minimum stock threshold |
| max_stock | INT | DEFAULT 0 | Maximum stock threshold |
| unit | VARCHAR(20) | NULLABLE | Base unit (PZA, KG, etc.) |
| pack_unit | VARCHAR(20) | NULLABLE | Pack unit for bulk |
| pack_quantity | INT | NULLABLE | Qty per pack |
| distribution_unit | VARCHAR(20) | NULLABLE | Distribution unit |
| cost | DECIMAL(12,2) | DEFAULT 0 | Unit cost |
| weight | DECIMAL(10,3) | DEFAULT 0 | Weight in kg |
| brand | VARCHAR(100) | NULLABLE | Brand name |
| model | VARCHAR(100) | NULLABLE | Model number |
| serial_number | VARCHAR(100) | UNIQUE, NULLABLE | Serial number |
| image_path | VARCHAR(255) | NULLABLE | Image file path |
| status | ENUM | DEFAULT 'active' | active/inactive/maintenance/disposed |
| notes | TEXT | NULLABLE | Additional notes |
| created_at | TIMESTAMP | | Creation timestamp |
| updated_at | TIMESTAMP | | Update timestamp |
| deleted_at | TIMESTAMP | NULLABLE | Soft delete |

#### `categories`
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | BIGINT UNSIGNED | PK, AUTO_INCREMENT | Primary key |
| name | VARCHAR(100) | NOT NULL | Category name |
| code | VARCHAR(20) | UNIQUE, NULLABLE | Category code |
| is_epp | BOOLEAN | DEFAULT FALSE | Is PPE category |
| description | TEXT | NULLABLE | Category description |
| created_at | TIMESTAMP | | Creation timestamp |
| updated_at | TIMESTAMP | | Update timestamp |

#### `locations`
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | BIGINT UNSIGNED | PK, AUTO_INCREMENT | Primary key |
| name | VARCHAR(100) | NOT NULL | Location name |
| code | VARCHAR(20) | UNIQUE, NULLABLE | Location code |
| location_type | ENUM | NOT NULL | warehouse/area/site/boat/vehicle/container |
| parent_id | BIGINT UNSIGNED | FK → locations, NULLABLE | Parent location |
| address | VARCHAR(255) | NULLABLE | Physical address |
| is_active | BOOLEAN | DEFAULT TRUE | Active status |
| created_at | TIMESTAMP | | Creation timestamp |
| updated_at | TIMESTAMP | | Update timestamp |

#### `transactions`
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | BIGINT UNSIGNED | PK, AUTO_INCREMENT | Primary key |
| type | ENUM | NOT NULL | loan/provision/transfer |
| status | ENUM | NOT NULL | pending/approved/rejected/dispatched/completed/cancelled |
| operation_number | VARCHAR(20) | UNIQUE | Auto-generated operation # |
| requester_id | BIGINT UNSIGNED | FK → users | User who requested |
| authorizer_id | BIGINT UNSIGNED | FK → users, NULLABLE | User who approved |
| dispatcher_id | BIGINT UNSIGNED | FK → users, NULLABLE | User who dispatched |
| source_location_id | BIGINT UNSIGNED | FK → locations, NULLABLE | Source for transfers |
| destination_location_id | BIGINT UNSIGNED | FK → locations, NULLABLE | Destination for transfers |
| notes | TEXT | NULLABLE | General notes |
| requested_at | TIMESTAMP | | Request timestamp |
| approved_at | TIMESTAMP | NULLABLE | Approval timestamp |
| dispatched_at | TIMESTAMP | NULLABLE | Dispatch timestamp |
| completed_at | TIMESTAMP | NULLABLE | Completion timestamp |
| created_at | TIMESTAMP | | Creation timestamp |
| updated_at | TIMESTAMP | | Update timestamp |

#### `transaction_items`
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | BIGINT UNSIGNED | PK, AUTO_INCREMENT | Primary key |
| transaction_id | BIGINT UNSIGNED | FK → transactions | Parent transaction |
| item_id | BIGINT UNSIGNED | FK → items | Item reference |
| quantity | INT | NOT NULL | Quantity |
| notes | TEXT | NULLABLE | Item-specific notes |
| created_at | TIMESTAMP | | Creation timestamp |
| updated_at | TIMESTAMP | | Update timestamp |

#### `uniform_sizes`
| Column | Type | Constraints | Description |
|--------|------|-------------|-------------|
| id | BIGINT UNSIGNED | PK, AUTO_INCREMENT | Primary key |
| user_id | BIGINT UNSIGNED | FK → users, UNIQUE | User reference |
| shirt_size | VARCHAR(10) | NULLABLE | Shirt size |
| jacket_size | VARCHAR(10) | NULLABLE | Jacket size |
| pants_size | VARCHAR(10) | NULLABLE | Pants size |
| boots_size | VARCHAR(10) | NULLABLE | Boots size |
| shoes_size | VARCHAR(10) | NULLABLE | Shoes size |
| created_at | TIMESTAMP | | Creation timestamp |
| updated_at | TIMESTAMP | | Update timestamp |

### 2.2 Indexes

```sql
-- Items indexes
CREATE INDEX idx_items_sap_code ON items(sap_code);
CREATE INDEX idx_items_barcode ON items(barcode);
CREATE INDEX idx_items_category ON items(category_id);
CREATE INDEX idx_items_location ON items(location_id);
CREATE INDEX idx_items_status ON items(status);
CREATE INDEX idx_items_low_stock ON items(stock, min_stock) WHERE stock <= min_stock;

-- Transactions indexes
CREATE INDEX idx_transactions_type ON transactions(type);
CREATE INDEX idx_transactions_status ON transactions(status);
CREATE INDEX idx_transactions_requester ON transactions(requester_id);
CREATE INDEX idx_transactions_operation ON transactions(operation_number);

-- Locations indexes
CREATE INDEX idx_locations_parent ON locations(parent_id);
CREATE INDEX idx_locations_type ON locations(location_type);
```

---

## 3. API Design

### 3.1 API Version 1 Structure

**Base URL:** `/api/v1`

**Authentication:** Bearer Token (Laravel Sanctum)

### 3.2 Endpoints

#### Authentication
| Method | Endpoint | Description |
|--------|----------|-------------|
| POST | /auth/login | Login with credentials |
| POST | /auth/logout | Logout (revoke token) |
| GET | /auth/me | Get current user |

#### Items
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /items | List items (paginated, filterable) |
| POST | /items | Create item |
| GET | /items/{id} | Get item details |
| PUT | /items/{id} | Update item |
| DELETE | /items/{id} | Delete item (soft) |
| GET | /items/low-stock | List low stock items |
| POST | /items/bulk-import | Bulk import from CSV |
| GET | /items/bulk-template | Download CSV template |

#### Categories
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /categories | List categories |
| POST | /categories | Create category |
| GET | /categories/{id} | Get category |
| PUT | /categories/{id} | Update category |
| DELETE | /categories/{id} | Delete category |

#### Locations
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /locations | List locations (tree) |
| POST | /locations | Create location |
| GET | /locations/{id} | Get location |
| PUT | /locations/{id} | Update location |
| DELETE | /locations/{id} | Delete location |
| GET | /locations/{id}/items | Items at location |

#### Transactions (Loans)
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /transactions/loans | List loans |
| POST | /transactions/loans | Create loan request |
| GET | /transactions/loans/{id} | Get loan details |
| POST | /transactions/{id}/approve | Approve transaction |
| POST | /transactions/{id}/reject | Reject transaction |
| POST | /transactions/{id}/dispatch | Dispatch transaction |
| POST | /transactions/{id}/return | Return items (loans) |
| POST | /transactions/{id}/complete | Complete (provisions) |

#### Transactions (Provisions)
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /transactions/provisions | List provisions |
| POST | /transactions/provisions | Create provision request |

#### Transactions (Transfers)
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /transactions/transfers | List transfers |
| POST | /transactions/transfers | Create transfer request |

#### Reports
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /reports/inventory | Inventory report |
| GET | /reports/inventory/export | Export inventory CSV |
| GET | /reports/loans | Loans report |
| GET | /reports/loans/export | Export loans CSV |
| GET | /reports/provisions | Provisions report |
| GET | /reports/transfers | Transfers report |
| GET | /reports/low-stock | Low stock report |
| GET | /reports/tracking/{item_id} | Item history |

#### Users
| Method | Endpoint | Description |
|--------|----------|-------------|
| GET | /users | List users |
| POST | /users | Create user |
| GET | /users/{id} | Get user |
| PUT | /users/{id} | Update user |
| DELETE | /users/{id} | Delete user |
| GET | /users/{id}/transactions | User's transactions |

### 3.3 Response Format

**Success Response:**
```json
{
  "success": true,
  "message": "Operation completed successfully",
  "data": { ... }
}
```

**Paginated Response:**
```json
{
  "success": true,
  "message": "Data retrieved successfully",
  "data": {
    "items": [...],
    "pagination": {
      "current_page": 1,
      "per_page": 15,
      "total": 100,
      "last_page": 7,
      "from": 1,
      "to": 15
    }
  }
}
```

**Error Response:**
```json
{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "description": ["La descripción es requerida."],
    "stock": ["El stock debe ser un número positivo."]
  }
}
```

---

## 4. Web Interface Design

### 4.1 Route Structure

```
/                           → Dashboard
/login                      → Login (guest)
/logout                     → Logout (POST)

/items                      → Items list
/items/create               → Create item
/items/{id}                 → View item
/items/{id}/edit            → Edit item

/transactions               → All transactions
/transactions/loans        → Loans
/transactions/provisions    → Provisions
/transactions/transfers     → Transfers
/transactions/create       → Create transaction
/transactions/{id}         → View transaction

/reports                    → Reports menu
/reports/inventory          → Inventory report
/reports/low-stock          → Low stock report
/reports/loans             → Loans report
/reports/provisions         → Provisions report
/reports/transfers          → Transfers report

/import                     → Bulk import
/settings                   → System settings
```

### 4.2 Blade Components

```
resources/views/
├── layouts/
│   ├── app.blade.php           # Main layout
│   └── auth.blade.php          # Auth layout
├── components/
│   ├── dropdown.blade.php
│   ├── modal.blade.php
│   ├── table.blade.php
│   ├── pagination.blade.php
│   └── alert.blade.php
├── items/
│   ├── index.blade.php
│   ├── create.blade.php
│   ├── edit.blade.php
│   └── show.blade.php
├── transactions/
│   ├── index.blade.php
│   ├── create.blade.php
│   ├── show.blade.php
│   └── partials/
│       ├── loan-form.blade.php
│       ├── provision-form.blade.php
│       └── transfer-form.blade.php
├── reports/
│   ├── index.blade.php
│   └── partials/
│       └── export-button.blade.php
└── auth/
    ├── login.blade.php
    └── logout.blade.php
```

---

## 5. Services

### 5.1 ItemService

```php
class ItemService
{
    public function create(array $data): Item;
    public function update(Item $item, array $data): Item;
    public function delete(Item $item): bool;
    public function getAvailableStock(Item $item): int;
    public function adjustStock(Item $item, int $quantity, string $reason): Transaction;
    public function generateBarcode(): string;
    public function bulkImport(UploadedFile $file): BulkImportResult;
    public function calculatePackDistribution(Item $item, int $packs): float;
}
```

### 5.2 TransactionService

```php
class TransactionService
{
    public function createLoan(array $data): Transaction;
    public function createProvision(array $data): Transaction;
    public function createTransfer(array $data): Transaction;
    public function approve(Transaction $transaction, User $user): Transaction;
    public function reject(Transaction $transaction, User $user, string $reason): Transaction;
    public function dispatch(Transaction $transaction, User $user): Transaction;
    public function return(Transaction $transaction, User $user, array $items): Transaction;
    public function complete(Transaction $transaction, User $user): Transaction;
    public function cancel(Transaction $transaction, User $user): Transaction;
}
```

### 5.3 ReportService

```php
class ReportService
{
    public function inventoryReport(array $filters): Collection;
    public function loansReport(array $filters): Collection;
    public function provisionsReport(array $filters): Collection;
    public function transfersReport(array $filters): Collection;
    public function lowStockReport(): Collection;
    public function itemTracking(int $itemId): Collection;
    public function exportToCsv(string $reportType, array $filters): StreamedResponse;
}
```

### 5.4 ExportService

```php
class ExportService
{
    public function exportInventoryCsv(array $filters): StreamedResponse;
    public function exportLoansCsv(array $filters): StreamedResponse;
    public function exportProvisionsCsv(array $filters): StreamedResponse;
    public function exportTransfersCsv(array $filters): StreamedResponse;
    public function generateTemplate(string $type): StreamedResponse;
}
```

### 5.5 ImportService

```php
class ImportService
{
    public function importItems(UploadedFile $file): ImportResult;
    protected function validateRow(array $row): ?array;
    protected function findOrCreateCategory(string $name): Category;
    protected function findOrCreateLocation(string $name): Location;
}
```

---

## 6. Security Implementation

### 6.1 Authentication

**Web (Breeze):**
- Session-based authentication
- CSRF protection on all forms
- Password hashing with BCrypt

**API (Sanctum):**
- Token-based authentication
- Rate limiting: 60 requests/minute
- Token revocation on logout

### 6.2 Authorization

**Role Middleware:**
```php
Route::middleware(['auth', 'role:admin'])->group(function () {
    // Admin-only routes
});

Route::middleware(['auth', 'role:supervisor|admin'])->group(function () {
    // Supervisor and Admin routes
});
```

**Policies:**
- `ItemPolicy` - who can CRUD items
- `TransactionPolicy` - who can approve/reject/dispatch

### 6.3 File Upload Security

```php
// Image validation in StoreItemRequest
'logo' => [
    'image',
    'mimes:jpeg,png,jpg,gif,webp',
    'max:2048', // 2MB max
    'dimensions:min_width=100,min_height=100,max_width=2000,max_height=2000',
],
```

---

## 7. Configuration

### 7.1 Environment Variables

```env
# Application
APP_NAME="Almacen2"
APP_ENV=local
APP_DEBUG=true

# Database
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=almacen2
DB_USERNAME=postgres
DB_PASSWORD=

# API
API_PREFIX=api
API_VERSION=v1
API_RATE_LIMIT=60

# Export
CSV_DELIMITER=;
CSV_BOM=\xEF\xBB\xBF
```

### 7.2 Config Files

```php
// config/almacen.php
return [
    'barcode_prefix' => 'AV',
    'operation_prefix' => 'OP',
    'low_stock_threshold' => 10,
    'csv_delimiter' => ';',
    'image_max_size' => 2048, // KB
    'allowed_image_types' => ['jpeg', 'png', 'jpg', 'gif', 'webp'],
];
```

---

## 8. Testing Strategy

### 8.1 Test Coverage Target: >85%

### 8.2 Unit Tests
- ItemService::getAvailableStock()
- ItemService::calculatePackDistribution()
- TransactionService::approve()
- TransactionService::dispatch()
- ExportService::formatCsv()

### 8.3 Feature Tests
- Authentication flow
- Item CRUD operations
- Loan workflow (full lifecycle)
- Provision workflow
- Transfer workflow
- Report generation
- Bulk import

### 8.4 Test Data (Factories)

```php
// ItemFactory
$factory->define(Item::class, function (Faker $faker) {
    return [
        'sap_code' => 'SAP-' . $faker->unique()->numberBetween(1000, 9999),
        'description' => $faker->sentence(3),
        'category_id' => factory(Category::class),
        'location_id' => factory(Location::class),
        'stock' => $faker->numberBetween(0, 100),
        'min_stock' => $faker->numberBetween(5, 20),
        'cost' => $faker->randomFloat(2, 1, 1000),
    ];
});
```

---

## 9. Implementation Phases

### Phase 1: Foundation (M1)
1. Create modern migrations
2. Create Eloquent models with relationships
3. Create seeders for reference data
4. Set up API controller base class

### Phase 2: Items Module (M2)
1. Implement ItemService
2. Create Item CRUD controllers (web + API)
3. Create category and location management
4. Add barcode generation
5. Add image handling
6. Add unit conversion helpers

### Phase 3: Transactions (M3-M5)
1. Implement TransactionService
2. Create loan workflow
3. Create provision workflow
4. Create transfer workflow
5. Add stock adjustment logic

### Phase 4: Reports & Import (M6)
1. Implement ReportService
2. Create report views
3. Add CSV export
4. Implement bulk import

### Phase 5: Testing (M7)
1. Write unit tests
2. Write feature tests
3. Fix bugs
4. Coverage verification

---

## 10. Dependencies

### Composer Packages (to add)
| Package | Version | Purpose |
|---------|---------|---------|
| barryvdh/laravel-dompdf | ^3.0 | PDF generation (optional) |
| league/csv | ^9.0 | CSV handling |
|干预 laravel-analytics | - | Not needed (custom implementation) |

### Dev Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| laravel/pint | ^1.0 | Code formatting |
| pestphp/pest | ^4.0 | Testing |
| mockery/mockery | ^1.6 | Mocking |

---

## 11. Migration Strategy

### Legacy Data Migration
1. Export legacy data to JSON
2. Create migration command: `php artisan migrate:legacy`
3. Map legacy tables to new schema:
   - `bienes` → `items`
   - `prestamos` → `transactions` (type='loan')
   - `dotacion` → `transactions` (type='provision')
   - `transferencias` → `transactions` (type='transfer')
   - `usuarios` → `users`

### Data Integrity
- Generate new barcodes for all items
- Generate new operation numbers
- Preserve all historical transaction data

---

*Document Version: 1.0.0*  
*Last Updated: 2026-03-18*
