Skip to content

Commit fc01479

Browse files
authored
Merge pull request #68 from chechojgb/buttonsLovers
refactor: cambios tabla bl_movimientos
2 parents 037fd31 + b36e7af commit fc01479

File tree

9 files changed

+133
-63
lines changed

9 files changed

+133
-63
lines changed

app/Http/Controllers/BLMarcacionController.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,18 @@ public function destroy($id)
8888

8989
public function actualizarEstado(BLPedidoItem $item, Request $request)
9090
{
91+
$user = Auth::id();
9192
$request->validate([
9293
'estado' => 'required|in:pendiente,en proceso,completado'
9394
]);
9495
$item->estado = $request->estado;
9596
$item->save();
97+
$item->movimientos()->create([
98+
'tipo' => 'pedido', // identificamos que el movimiento es de un pedido
99+
'cantidad' => $item->cantidad_empaques, // opcional: cantidad afectada
100+
'motivo' => "Cambio de estado a {$request->estado}", // motivo descriptivo
101+
'usuario_id' => $user, // usuario que hizo el cambio
102+
]);
96103
return redirect()->back()->with([
97104
'toast' => [
98105
'type' => 'success',

app/Http/Controllers/DashboardController.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ public function index()
6363

6464
$pedidosEspera = BLPedido::get()
6565
->where('estado', 'pendiente');
66-
$movimientos = BlMovimiento::with(['empaque.producto'])->get()
67-
->take(6);
66+
$movimientos = BlMovimiento::with(['empaque.producto'])->orderByDesc('created_at')->take(6)->get();
6867
// dd($movimientos);
6968
$produccion = $this->produccionSemanal();
7069

app/Models/BLCliente.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Database\Eloquent\Model;
66
use Illuminate\Database\Eloquent\Relations\HasMany;
7+
use Illuminate\Database\Eloquent\Relations\MorphMany;
78
use App\Models\BLPedido;
89

910
class BLCliente extends Model
@@ -25,4 +26,8 @@ public function pedidos(): HasMany
2526
{
2627
return $this->hasMany(BLPedido::class, 'cliente_id');
2728
}
29+
public function movimientos(): MorphMany
30+
{
31+
return $this->morphMany(BlMovimiento::class, 'movible');
32+
}
2833
}

app/Models/BLPedidoItem.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace App\Models;
44

55
use Illuminate\Database\Eloquent\Model;
6+
use Illuminate\Database\Eloquent\Relations\HasMany;
7+
use Illuminate\Database\Eloquent\Relations\MorphMany;
68

79
class BLPedidoItem extends Model
810
{
@@ -32,4 +34,9 @@ public function marcaciones()
3234
{
3335
return $this->hasMany(BLMarcacion::class, 'pedido_item_id');
3436
}
37+
38+
public function movimientos(): MorphMany
39+
{
40+
return $this->morphMany(BlMovimiento::class, 'movible');
41+
}
3542
}

app/Models/BlEmpaque.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,13 @@ public function movimientos(): HasMany
2626
// Accesor: Total de unidades en stock para este empaque
2727
public function getStockUnidadesAttribute(): int
2828
{
29-
return $this->movimientos->sum('cantidad') * $this->cantidad_por_empaque;
29+
$entradas = $this->movimientos()->where('tipo', 'entrada')->sum('cantidad');
30+
$salidas = $this->movimientos()->where('tipo', 'salida')->sum('cantidad');
31+
$ajustes = $this->movimientos()->where('tipo', 'ajuste')->sum('cantidad');
32+
33+
$totalEmpaques = $entradas - $salidas + $ajustes;
34+
35+
return $totalEmpaques * $this->cantidad_por_empaque;
3036
}
3137
public function pedidoItems(): HasMany
3238
{

app/Models/BlMovimiento.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,32 @@
99
class BlMovimiento extends Model
1010
{
1111
protected $table = 'bl_movimientos';
12-
protected $fillable = ['empaque_id', 'tipo', 'cantidad', 'motivo', 'lote', 'usuario_id'];
12+
protected $fillable = [
13+
'empaque_id',
14+
'tipo',
15+
'cantidad',
16+
'motivo',
17+
'lote',
18+
'usuario_id',
19+
'movible_id',
20+
'movible_type',
21+
];
1322

1423
// Tipos de movimiento permitidos
15-
public const TIPOS = ['entrada', 'salida', 'ajuste'];
24+
25+
const TIPOS = [
26+
'entrada',
27+
'salida',
28+
'ajuste',
29+
'pedido',
30+
'marcacion',
31+
'cliente',
32+
];
33+
34+
public function movible()
35+
{
36+
return $this->morphTo();
37+
}
1638

1739
// Relación: Un movimiento pertenece a un empaque
1840
public function empaque(): BelongsTo
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('bl_movimientos', function (Blueprint $table) {
15+
// Agregar la columna movible_id si no existe
16+
if (!Schema::hasColumn('bl_movimientos', 'movible_id')) {
17+
$table->unsignedBigInteger('movible_id')->nullable()->after('id');
18+
}
19+
20+
// Agregar la columna movible_type si no existe
21+
if (!Schema::hasColumn('bl_movimientos', 'movible_type')) {
22+
$table->string('movible_type')->nullable()->after('movible_id');
23+
}
24+
});
25+
}
26+
27+
/**
28+
* Reverse the migrations.
29+
*/
30+
public function down(): void
31+
{
32+
Schema::table('bl_movimientos', function (Blueprint $table) {
33+
// Eliminar la columna movible_id si existe
34+
if (Schema::hasColumn('bl_movimientos', 'movible_id')) {
35+
$table->dropColumn('movible_id');
36+
}
37+
38+
// Eliminar la columna movible_type si existe
39+
if (Schema::hasColumn('bl_movimientos', 'movible_type')) {
40+
$table->dropColumn('movible_type');
41+
}
42+
});
43+
}
44+
};

resources/js/components/BL/MovimientosRecientes.jsx

Lines changed: 37 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,6 @@
1-
import { ArrowDownCircle, ArrowUpCircle } from 'lucide-react';
1+
import { ArrowDownCircle, ArrowUpCircle, Users, Package, ClipboardList } from 'lucide-react';
22

3-
// const movimientos = [
4-
// {
5-
// tipo: 'Entrada',
6-
// producto: 'Botón Z6',
7-
// cantidad: 500,
8-
// fecha: '2025-08-02',
9-
// icono: <ArrowDownCircle className="text-green-600 w-5 h-5" />,
10-
// },
11-
// {
12-
// tipo: 'Salida',
13-
// producto: 'Botón R4',
14-
// cantidad: 300,
15-
// fecha: '2025-08-02',
16-
// icono: <ArrowUpCircle className="text-red-600 w-5 h-5" />,
17-
// },
18-
// {
19-
// tipo: 'Entrada',
20-
// producto: 'Botón L2',
21-
// cantidad: 200,
22-
// fecha: '2025-08-01',
23-
// icono: <ArrowDownCircle className="text-green-600 w-5 h-5" />,
24-
// },
25-
// {
26-
// tipo: 'Salida',
27-
// producto: 'Botón M1',
28-
// cantidad: 100,
29-
// fecha: '2025-07-31',
30-
// icono: <ArrowUpCircle className="text-red-600 w-5 h-5" />,
31-
// },
32-
// {
33-
// tipo: 'Entrada',
34-
// producto: 'Botón Z1',
35-
// cantidad: 200,
36-
// fecha: '2025-08-01',
37-
// icono: <ArrowDownCircle className="text-green-600 w-5 h-5" />,
38-
// },
39-
// {
40-
// tipo: 'Entrada',
41-
// producto: 'Botón Z1',
42-
// cantidad: 1000,
43-
// fecha: '2025-08-02',
44-
// icono: <ArrowDownCircle className="text-green-600 w-5 h-5" />,
45-
// },
46-
// // Puedes duplicar más para probar el scroll
47-
// ];
48-
49-
export default function MovimientosRecientesBL({movimientos}) {
50-
console.log('movimientos',movimientos);
3+
export default function MovimientosRecientesBL({ movimientos }) {
514
return (
525
<div className="relative flex flex-col h-full p-5">
536
{/* Header */}
@@ -58,12 +11,41 @@ export default function MovimientosRecientesBL({movimientos}) {
5811
{/* Lista scrollable */}
5912
<div className="flex-1 overflow-y-auto pr-1">
6013
<ul className="space-y-4 text-sm text-gray-800 dark:text-gray-300">
61-
{Object.values(movimientos).map((mov, i) => {
14+
{movimientos.map((mov, i) => {
15+
// Icono según tipo de movimiento
6216
let icono;
63-
if (mov.tipo === "entrada") {
64-
icono = <ArrowUpCircle className="text-green-600 w-5 h-5" />;
17+
switch (mov.tipo) {
18+
case "entrada":
19+
icono = <ArrowDownCircle className="text-green-600 w-5 h-5" />;
20+
break;
21+
case "salida":
22+
icono = <ArrowUpCircle className="text-red-600 w-5 h-5" />;
23+
break;
24+
case "pedido":
25+
icono = <ClipboardList className="text-blue-600 w-5 h-5" />;
26+
break;
27+
case "marcacion":
28+
icono = <Package className="text-yellow-600 w-5 h-5" />;
29+
break;
30+
case "cliente":
31+
icono = <Users className="text-purple-600 w-5 h-5" />;
32+
break;
33+
default:
34+
icono = <Package className="text-gray-400 w-5 h-5" />;
35+
}
36+
37+
// Nombre dinámico según tipo de movible
38+
let nombre;
39+
if (mov.empaque?.producto?.descripcion) {
40+
nombre = mov.empaque.producto.descripcion;
41+
} else if (mov.movible?.nombre) {
42+
nombre = mov.movible.nombre;
43+
} else if (mov.movible?.descripcion) {
44+
nombre = mov.movible.descripcion;
45+
}else if (mov?.motivo){
46+
nombre = mov.motivo;
6547
} else {
66-
icono = <ArrowDownCircle className="text-red-600 w-5 h-5" />;
48+
nombre = "Sin información";
6749
}
6850

6951
return (
@@ -74,19 +56,17 @@ export default function MovimientosRecientesBL({movimientos}) {
7456
</div>
7557
<div>
7658
<p className="font-medium">
77-
{mov.tipo}: {mov?.empaque?.producto?.descripcion}
59+
{mov.tipo.toUpperCase()}: {nombre}
7860
</p>
7961
<p className="text-xs text-gray-500 dark:text-gray-400">
80-
Fecha: {mov.created_at.slice(0, 10)}
62+
Fecha: {new Date(mov.created_at).toLocaleDateString()}
8163
</p>
8264
</div>
8365
</div>
84-
<div className="text-xs text-gray-500 dark:text-gray-400">{mov.fecha}</div>
8566
</li>
8667
);
8768
})}
8869
</ul>
89-
9070
</div>
9171
</div>
9272
);

resources/js/components/BL/tablaMarcacionBL.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export default function TablaMarcacionBL({itemsPedidos, search}) {
125125

126126
return (
127127
<>
128-
<table className="min-w-full text-sm text-left text-gray-500 dark:text-gray-400">
128+
<table className="min-w-full text-sm text-left text-gray-500 dark:text-gray-400 mb-8">
129129
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-800 dark:text-gray-400">
130130
{table.getHeaderGroups().map(headerGroup => (
131131
<tr key={headerGroup.id}>

0 commit comments

Comments
 (0)