## 馃敡 Mejoras T茅cnicas Recomendadas
### Optimizaci贸n de Rendimiento
#### 1. Implementar Cach茅 Estrat茅gico
```php
// ProductosController.php
public function index(Request $request)
{
$cacheKey = 'products.' . md5(serialize($request->all()));
$products = Cache::remember($cacheKey, 300, function () use ($request) {
return Product::query()
->when($request->search, fn($q, $term) =>
$q->where('name', 'like', "%{$term}%")
)
->paginate(10);
});
}
// Limpiar cach茅 al modificar productos
Cache::forget('products.*');
```
#### 2. Eager Loading para Relaciones
```php
// Evitar N+1 queries
$sales = Sale::with(['client', 'details.product'])
->latest()
->paginate(15);
// En lugar de:
$sales = Sale::all(); // Genera queries adicionales
```
#### 3. 脥ndices de Base de Datos
```php
// En migraciones
Schema::table('products', function (Blueprint $table) {
$table->index('sku');
$table->index('type');
$table->index(['stock_quantity', 'min_stock_alert']);
});
Schema::table('sales', function (Blueprint $table) {
$table->index('created_at');
$table->index(['client_id', 'created_at']);
});
```
#### 4. Paginaci贸n con Cursor
```php
// Para datasets grandes
$products = Product::latest()->cursorPaginate(20);
```
### Refactorizaci贸n de C贸digo
#### 1. Services para L贸gica de Negocio
```php
// app/Services/SaleService.php
class SaleService
{
public function processSale(array $data): Sale
{
return DB::transaction(function () use ($data) {
$sale = Sale::create([...]);
foreach ($data['items'] as $item) {
$this->addItem($sale, $item);
}
return $sale;
});
}
private function addItem(Sale $sale, array $item): void
{
$product = Product::findOrFail($item['product_id']);
if ($product->stock_quantity < $item['quantity']) {
throw new InsufficientStockException();
}
SaleDetail::create([...]);
$product->decrement('stock_quantity', $item['quantity']);
}
}
```
#### 2. Form Request Validation
```php
// app/Http/Requests/StoreSaleRequest.php
class StoreSaleRequest extends FormRequest
{
public function rules(): array
{
return [
'client_id' => 'nullable|exists:clients,id',
'payment_method' => 'required|string',
'items' => 'required|array|min:1',
'items.*.product_id' => 'required|exists:products,id',
'items.*.quantity' => 'required|integer|min:1',
];
}
public function messages(): array
{
return [
'items.required' => 'Debe agregar al menos un producto.',
'items.*.quantity.min' => 'La cantidad debe ser mayor a 0.',
];
}
}
// En el controlador
public function store(StoreSaleRequest $request)
{
// $request ya est谩 validado
}
```
#### 3. Repository Pattern
```php
// app/Repositories/ProductRepository.php
interface ProductRepositoryInterface
{
public function search(string $term): Collection;
public function lowStock(): Collection;
public function byType(string $type): Collection;
}
class ProductRepository implements ProductRepositoryInterface
{
public function search(string $term): Collection
{
return Product::where('name', 'like', "%{$term}%")
->orWhere('sku', 'like', "%{$term}%")
->get();
}
}
// Registrar en AppServiceProvider
$this->app->bind(
ProductRepositoryInterface::class,
ProductRepository::class
);
```
#### 4. Policies para Autorizaci贸n
```php
// app/Policies/ProductPolicy.php
class ProductPolicy
{
public function viewAny(User $user): bool
{
return in_array($user->role, ['admin', 'employee']);
}
public function create(User $user): bool
{
return $user->role === 'admin';
}
public function update(User $user, Product $product): bool
{
return $user->role === 'admin';
}
public function delete(User $user, Product $product): bool
{
return $user->role === 'admin';
}
}
// En controlador
$this->authorize('create', Product::class);
```
### Mejoras de Seguridad
#### 1. Rate Limiting Espec铆fico
```php
// routes/web.php
Route::post('/sales', [SaleController::class, 'store'])
->middleware(['auth', 'throttle:sales']);
// app/Providers/RouteServiceProvider.php
RateLimiter::for('sales', function (Request $request) {
return Limit::perMinute(10)->by($request->user()?->id);
});
```
#### 2. Sanitizaci贸n de Inputs
```php
// En Form Request
protected function prepareForValidation()
{
$this->merge([
'name' => strip_tags($this->name),
'description' => Purifier::clean($this->description),
]);
}
```
#### 3. Protecci贸n CSRF Expl铆cita
```php
// Verificar en AJAX
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
```
#### 4. Validaci贸n de Im谩genes
```php
'image' => [
'nullable',
'image',
'mimes:jpeg,png,jpg,webp',
'max:2048', // 2MB
'dimensions:min_width=100,min_height=100,max_width=2000,max_height=2000'
]
```
### Mejoras de UI/UX
#### 1. Loading States
```blade
```
#### 2. Confirmaciones Elegantes
```javascript
// Usar SweetAlert2
Swal.fire({
title: '驴Eliminar producto?',
text: "Esta acci贸n no se puede revertir",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#ccff00',
cancelButtonColor: '#d33',
confirmButtonText: 'S铆, eliminar',
cancelButtonText: 'Cancelar'
}).then((result) => {
if (result.isConfirmed) {
// Ejecutar eliminaci贸n
}
});
```
#### 3. Toast Notifications
```javascript
// Mensajes no intrusivos
const Toast = Swal.mixin({
toast: true,
position: 'top-end',
showConfirmButton: false,
timer: 3000
});
Toast.fire({
icon: 'success',
title: 'Producto guardado'
});
```
#### 4. Validaci贸n en Tiempo Real
```javascript
$('input[name="sku"]').on('blur', function() {
const sku = $(this).val();
$.get(`/api/products/check-sku/${sku}`, function(data) {
if (data.exists) {
// Mostrar error
$(this).addClass('border-red-500');
}
});
});
```
### Testing
#### 1. Tests de Feature
```php
// tests/Feature/ProductTest.php
public function test_admin_can_create_product()
{
$admin = User::factory()->create(['role' => 'admin']);
$this->actingAs($admin)
->post('/productos', [
'name' => 'Test Product',
'price' => 100,
'stock_quantity' => 10,
'min_stock_alert' => 5,
'type' => 'accessory'
])
->assertRedirect('/productos')
->assertSessionHas('success');
$this->assertDatabaseHas('products', [
'name' => 'Test Product'
]);
}
public function test_guest_cannot_create_product()
{
$response = $this->post('/productos', []);
$response->assertRedirect('/login');
}
```
#### 2. Tests Unitarios
```php
// tests/Unit/ProductTest.php
public function test_product_has_low_stock()
{
$product = Product::factory()->create([
'stock_quantity' => 3,
'min_stock_alert' => 5
]);
$this->assertTrue($product->hasLowStock());
}
```
#### 3. Browser Tests (Dusk)
```php
// tests/Browser/PosTest.php
public function test_can_complete_sale()
{
$this->browse(function (Browser $browser) {
$browser->loginAs(User::find(1))
->visit('/sales/create')
->select('items[0][product_id]', 1)
->type('items[0][quantity]', 2)
->press('Confirmar Venta')
->assertPathIs('/sales/1');
});
}
```