Skip to content

Commit 8401343

Browse files
authored
Merge pull request #73 from chechojgb/buttonsLovers
refactor: cambios guardado de movimientos
2 parents a775f4c + c9ca7c5 commit 8401343

File tree

7 files changed

+255
-176
lines changed

7 files changed

+255
-176
lines changed

app/Http/Controllers/BlCuentaCobroController.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,26 @@
44

55
use App\Models\BlCuentaCobro;
66
use App\Models\BlCuentaCobroItem;
7+
use App\Models\BLCliente;
78
use App\Models\BLMarcacion;
9+
use App\Models\BLPedido;
10+
use App\Models\BLPedidoItem;
11+
use App\Models\User;
812
use Illuminate\Http\Request;
9-
13+
use Inertia\Inertia;
14+
use Illuminate\Support\Facades\Auth;
1015
use Illuminate\Support\Facades\DB;
1116

1217
class BlCuentaCobroController extends Controller
1318
{
19+
public function index()
20+
{
21+
$user = Auth::user();
22+
return Inertia::render('BLCuentaCobro', [
23+
'user' => $user,
24+
]);
25+
}
26+
1427
public function pasarPagados(Request $request)
1528
{
1629
$items = $request->input('items', []);

app/Http/Controllers/BlProductoController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,11 +154,12 @@ public function store(Request $request)
154154

155155

156156
BlMovimiento::create([
157-
'empaque_id' => $empaque->id, // aqui debe ir el id del empaque creado mas no del producto
157+
'movible_id' => $empaque->id,
158+
'movible_type' => \App\Models\BLEmpaque::class,
158159
'tipo' => 'entrada',
159160
'cantidad' => 1,
160161
'motivo' => 'compra',
161-
'usuario_id' => $request->user()->id, // Asegúrate de que el usuario esté autenticado
162+
'usuario_id' => $request->user()->id,
162163
]);
163164

164165
return redirect()->back()->with([

resources/js/components/BL/tablaMarcacionBL.jsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,8 @@ import { HiOutlineExclamationCircle } from "react-icons/hi";
1818

1919
export default function TablaMarcacionBL({itemsPedidos, search}) {
2020
const [openModal, setOpenModal] = useState(false);
21-
console.log(itemsPedidos);
22-
2321
const { props } = usePage();
2422
const [selectedItems, setSelectedItems] = useState([]);
25-
console.log(selectedItems.map(item => item.nombre_trabajador));
26-
2723
const proyecto = props?.auth?.user?.proyecto || 'AZZU';
2824
const theme = themeByProject[proyecto];
2925
const [toast, setToast] = useState({
@@ -54,7 +50,10 @@ export default function TablaMarcacionBL({itemsPedidos, search}) {
5450
'Nota': item.nota || '',
5551
'Estado': item.estado,
5652
'Completado por': item.marcaciones?.[0]?.trabajador?.name || 'Sin asignar',
57-
'Fecha': item.fecha ? new Date(item.fecha).toLocaleDateString() : ''
53+
'Fecha de creacion': item.created_at ? new Date(item.created_at).toLocaleDateString() : '',
54+
'Fecha de ultima actualizacion': item.updated_at ? new Date(item.updated_at).toLocaleDateString() : '',
55+
'estado': item.marcaciones?.[0]?.pagado === 1 ? 'pagado' : 'pendiente',
56+
'costo': item.marcaciones?.[0]?.costo_total || 'Sin costo',
5857
}));
5958

6059
const wb = XLSX.utils.book_new();
@@ -81,6 +80,14 @@ export default function TablaMarcacionBL({itemsPedidos, search}) {
8180
const value = row.getValue("estado"); // estado actual
8281
const itemId = row.original.id; // ID del item
8382
const handleChange = (nuevoEstado) => {
83+
if (value === "completado") {
84+
setToast({
85+
show: true,
86+
success: false,
87+
message: "Este item ya está completado y no se puede modificar."
88+
});
89+
return; // salir sin ejecutar el patch
90+
}
8491
router.patch(route('bl-historicos.actualizar-estado', itemId), { estado: nuevoEstado }, {
8592
preserveState: true,
8693
onSuccess: () => {

resources/js/components/app-sidebar.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,15 @@ const staticNavItems = [
113113
icon: BadgeCheck,
114114
proyectosPermitidos: ['Button Lovers', 'AZZU', 'Button LoversM'],
115115
},
116-
{
117-
title: 'Inventario de Desempaque',
118-
href: '/BLproductosInventario/BLMarcacion',
119-
icon: PcCase,
120-
proyectosPermitidos: ['Button Lovers', 'AZZU', 'Button LoversM'],
121-
},
116+
// {
117+
// title: 'Inventario de Desempaque',
118+
// href: '/BLproductosInventario/BLMarcacion',
119+
// icon: PcCase,
120+
// proyectosPermitidos: ['Button Lovers', 'AZZU', 'Button LoversM'],
121+
// },
122122
{
123123
title: 'Cuentas de cobro',
124-
href: '/BLproductosInventario/BLMarcacion',
124+
href: '/BLproductosInventario/BLCuentaCobro',
125125
icon: BadgeDollarSign,
126126
proyectosPermitidos: ['Button Lovers', 'AZZU', 'Button LoversM'],
127127
}
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
import AppLayout from '@/layouts/app-layout';
2+
import { Head } from '@inertiajs/react';
3+
import { useState } from 'react';
4+
5+
const breadcrumbs = [
6+
{
7+
title: 'Cuentas de cobro',
8+
href: '/BLCuentaCobro',
9+
},
10+
];
11+
12+
// Datos de prueba (en producción vendrían del backend)
13+
const datosPrueba = [
14+
{
15+
id: 1,
16+
numero: "CC-001-2023",
17+
cliente: "Empresa ABC S.A.S.",
18+
fecha_emision: "2023-10-15",
19+
fecha_vencimiento: "2023-11-15",
20+
monto: 2500000,
21+
estado: "pendiente"
22+
},
23+
{
24+
id: 2,
25+
numero: "CC-002-2023",
26+
cliente: "Comercial XYZ Ltda",
27+
fecha_emision: "2023-10-10",
28+
fecha_vencimiento: "2023-10-25",
29+
monto: 1800000,
30+
estado: "pagado"
31+
},
32+
{
33+
id: 3,
34+
numero: "CC-003-2023",
35+
cliente: "Distribuidora Norte",
36+
fecha_emision: "2023-09-20",
37+
fecha_vencimiento: "2023-10-20",
38+
monto: 3200000,
39+
estado: "vencido"
40+
}
41+
];
42+
43+
export default function CuentasCobro({ user, cuentas = datosPrueba }) {
44+
const [filtroEstado, setFiltroEstado] = useState('todos');
45+
const [busqueda, setBusqueda] = useState('');
46+
47+
// Asegurarse de que cuentas siempre sea un array
48+
const cuentasSeguras = cuentas || datosPrueba;
49+
50+
// Filtrar cuentas según estado y búsqueda
51+
const cuentasFiltradas = cuentasSeguras.filter(cuenta => {
52+
const coincideEstado = filtroEstado === 'todos' || cuenta.estado === filtroEstado;
53+
const coincideBusqueda = cuenta.cliente.toLowerCase().includes(busqueda.toLowerCase()) ||
54+
cuenta.numero.toString().includes(busqueda);
55+
return coincideEstado && coincideBusqueda;
56+
});
57+
58+
// Calcular totales
59+
const totalPendiente = cuentasSeguras.filter(c => c.estado === 'pendiente')
60+
.reduce((sum, c) => sum + c.monto, 0);
61+
const totalPagado = cuentasSeguras.filter(c => c.estado === 'pagado')
62+
.reduce((sum, c) => sum + c.monto, 0);
63+
64+
return (
65+
<AppLayout breadcrumbs={breadcrumbs}>
66+
<Head title="Cuentas de Cobro" />
67+
68+
<div className="container mx-auto px-4 py-6">
69+
{/* Header con estadísticas */}
70+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
71+
<div className="bg-white rounded-lg shadow p-6">
72+
<h3 className="text-lg font-semibold text-gray-600">Total Pendiente</h3>
73+
<p className="text-3xl font-bold text-red-500">${totalPendiente.toLocaleString()}</p>
74+
</div>
75+
<div className="bg-white rounded-lg shadow p-6">
76+
<h3 className="text-lg font-semibold text-gray-600">Total Pagado</h3>
77+
<p className="text-3xl font-bold text-green-500">${totalPagado.toLocaleString()}</p>
78+
</div>
79+
<div className="bg-white rounded-lg shadow p-6">
80+
<h3 className="text-lg font-semibold text-gray-600">Cuentas Totales</h3>
81+
<p className="text-3xl font-bold text-blue-500">{cuentasSeguras.length}</p>
82+
</div>
83+
</div>
84+
85+
{/* Controles de filtrado y búsqueda */}
86+
<div className="bg-white rounded-lg shadow p-6 mb-6">
87+
<div className="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
88+
<div className="flex flex-col md:flex-row gap-4">
89+
<div>
90+
<label htmlFor="filtro" className="block text-sm font-medium text-gray-700 mb-1">
91+
Filtrar por estado
92+
</label>
93+
<select
94+
id="filtro"
95+
className="rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
96+
value={filtroEstado}
97+
onChange={(e) => setFiltroEstado(e.target.value)}
98+
>
99+
<option value="todos">Todos</option>
100+
<option value="pendiente">Pendiente</option>
101+
<option value="pagado">Pagado</option>
102+
<option value="vencido">Vencido</option>
103+
</select>
104+
</div>
105+
106+
<div>
107+
<label htmlFor="busqueda" className="block text-sm font-medium text-gray-700 mb-1">
108+
Buscar
109+
</label>
110+
<input
111+
type="text"
112+
id="busqueda"
113+
placeholder="Cliente o número de cuenta"
114+
className="rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
115+
value={busqueda}
116+
onChange={(e) => setBusqueda(e.target.value)}
117+
/>
118+
</div>
119+
</div>
120+
121+
<button className="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-4 rounded-md">
122+
Nueva Cuenta de Cobro
123+
</button>
124+
</div>
125+
</div>
126+
127+
{/* Tabla de cuentas de cobro */}
128+
<div className="bg-white rounded-lg shadow overflow-hidden">
129+
<div className="overflow-x-auto">
130+
<table className="min-w-full divide-y divide-gray-200">
131+
<thead className="bg-gray-50">
132+
<tr>
133+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
134+
Número
135+
</th>
136+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
137+
Cliente
138+
</th>
139+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
140+
Fecha Emisión
141+
</th>
142+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
143+
Fecha Vencimiento
144+
</th>
145+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
146+
Monto
147+
</th>
148+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
149+
Estado
150+
</th>
151+
<th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
152+
Acciones
153+
</th>
154+
</tr>
155+
</thead>
156+
<tbody className="bg-white divide-y divide-gray-200">
157+
{cuentasFiltradas.length > 0 ? (
158+
cuentasFiltradas.map((cuenta) => (
159+
<tr key={cuenta.id} className="hover:bg-gray-50">
160+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
161+
#{cuenta.numero}
162+
</td>
163+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
164+
{cuenta.cliente}
165+
</td>
166+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
167+
{new Date(cuenta.fecha_emision).toLocaleDateString()}
168+
</td>
169+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
170+
{new Date(cuenta.fecha_vencimiento).toLocaleDateString()}
171+
</td>
172+
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-900">
173+
${cuenta.monto.toLocaleString()}
174+
</td>
175+
<td className="px-6 py-4 whitespace-nowrap">
176+
<span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full
177+
${cuenta.estado === 'pagado' ? 'bg-green-100 text-green-800' :
178+
cuenta.estado === 'pendiente' ? 'bg-yellow-100 text-yellow-800' :
179+
'bg-red-100 text-red-800'}`}>
180+
{cuenta.estado}
181+
</span>
182+
</td>
183+
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
184+
<button className="text-indigo-600 hover:text-indigo-900 mr-3">
185+
Ver
186+
</button>
187+
<button className="text-blue-600 hover:text-blue-900 mr-3">
188+
Editar
189+
</button>
190+
<button className="text-red-600 hover:text-red-900">
191+
Eliminar
192+
</button>
193+
</td>
194+
</tr>
195+
))
196+
) : (
197+
<tr>
198+
<td colSpan="7" className="px-6 py-4 text-center text-sm text-gray-500">
199+
No se encontraron cuentas de cobro
200+
</td>
201+
</tr>
202+
)}
203+
</tbody>
204+
</table>
205+
</div>
206+
</div>
207+
</div>
208+
</AppLayout>
209+
);
210+
}

0 commit comments

Comments
 (0)