pdv.backend/app/Http/Controllers/App/InventoryController.php

207 lines
6.5 KiB
PHP

<?php namespace App\Http\Controllers\App;
use App\Models\Inventory;
use App\Http\Controllers\Controller;
use App\Http\Requests\App\InventoryStoreRequest;
use App\Http\Requests\App\InventoryUpdateRequest;
use App\Http\Requests\App\InventoryImportRequest;
use App\Services\ProductService;
use App\Imports\ProductsImport;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Notsoweb\ApiResponse\Enums\ApiResponse;
use Maatwebsite\Excel\Facades\Excel;
use Maatwebsite\Excel\Validators\ValidationException;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\Exportable;
class InventoryController extends Controller
{
public function __construct(
protected ProductService $productService
) {}
public function index(Request $request)
{
$products = Inventory::with(['category', 'price'])->withCount('serials')
->where('is_active', true);
// Filtro por búsqueda de texto (nombre, SKU, código de barras)
if ($request->has('q') && $request->q) {
$products->where(function($query) use ($request) {
$query->where('name', 'like', "%{$request->q}%")
->orWhere('sku', 'like', "%{$request->q}%")
->orWhere('barcode', $request->q);
});
}
// Filtro por categoría (independiente de la búsqueda de texto)
if ($request->has('category_id') && $request->category_id) {
$products->where('category_id', $request->category_id);
}
// Calcular el valor total del inventario
$totalInventoryValue = Inventory::join('prices', 'inventories.id', '=', 'prices.inventory_id')
->where('inventories.is_active', true)
->sum(DB::raw('inventories.stock * prices.cost'));
$products = $products->orderBy('name')
->paginate(config('app.pagination'));
return ApiResponse::OK->response([
'products' => $products,
'total_inventory_value' => round($totalInventoryValue, 2)
]);
}
public function show(Inventory $inventario)
{
return ApiResponse::OK->response([
'model' => $inventario->load(['category', 'price'])->loadCount('serials')
]);
}
public function store(InventoryStoreRequest $request)
{
$product = $this->productService->createProduct($request->validated());
return ApiResponse::OK->response([
'model' => $product
]);
}
public function update(InventoryUpdateRequest $request, Inventory $inventario)
{
$product = $this->productService->updateProduct($inventario, $request->validated());
return ApiResponse::OK->response([
'model' => $product
]);
}
public function destroy(Inventory $inventario)
{
$inventario->delete();
return ApiResponse::OK->response();
}
/**
* Importar productos desde Excel
*/
public function import(InventoryImportRequest $request)
{
try {
$import = new ProductsImport();
Excel::import($import, $request->file('file'));
$stats = $import->getStats();
return ApiResponse::OK->response([
'message' => 'Importación completada exitosamente.',
'imported' => $stats['imported'],
'updated' => $stats['updated'],
'skipped' => $stats['skipped'],
'errors' => $stats['errors'],
]);
} catch (ValidationException $e) {
$failures = $e->failures();
$errors = [];
foreach ($failures as $failure) {
$errors[] = [
'row' => $failure->row(),
'attribute' => $failure->attribute(),
'errors' => $failure->errors(),
'values' => $failure->values(),
];
}
return ApiResponse::BAD_REQUEST->response([
'message' => 'Error de validación en el archivo.',
'errors' => $errors,
]);
} catch (\Exception $e) {
return ApiResponse::INTERNAL_ERROR->response([
'message' => 'Error al importar productos: ' . $e->getMessage(),
]);
}
}
/**
* Descargar plantilla de Excel para importación
*/
public function downloadTemplate()
{
$headers = [
'nombre',
'sku',
'codigo_barras',
'categoria',
'stock',
'costo',
'precio_venta',
'impuesto',
'numeros_serie'
];
$exampleData = [
[
'nombre' => 'Samsung Galaxy A55',
'sku' => 'SAM-A55-BLK',
'codigo_barras' => '7502276853456',
'categoria' => 'Electrónica',
'stock' => 15,
'costo' => 5000.00,
'precio_venta' => 7500.00,
'impuesto' => 16
],
[
'nombre' => 'Coca Cola 600ml',
'sku' => 'COCA-600',
'codigo_barras' => '750227686666',
'categoria' => 'Bebidas',
'stock' => 5,
'costo' => 12.50,
'precio_venta' => 18.00,
'impuesto' => 8,
'numeros_serie' => '' // Dejar vacío si el producto no maneja seriales individuales
],
[
'nombre' => 'Laptop HP Pavilion 15',
'sku' => 'HP-LAP-15',
'codigo_barras' => '7502276854443',
'categoria' => 'Computadoras',
'stock' => 5,
'costo' => 8500.00,
'precio_venta' => 12000.00,
'impuesto' => 16,
'numeros_serie' => 'HP-LAP-15-01,HP-LAP-15-02,HP-LAP-15-03,HP-LAP-15-04,HP-LAP-15-05'
],
];
return Excel::download(
new class($headers, $exampleData) implements FromArray, WithHeadings {
use Exportable;
public function __construct(private array $headers, private array $data) {}
public function array(): array
{
return $this->data;
}
public function headings(): array
{
return $this->headers;
}
},
'plantilla_productos.xlsx'
);
}
}