up
This commit is contained in:
@@ -181,6 +181,10 @@ class OrdenProduccion extends Model
|
|||||||
{
|
{
|
||||||
if ($this->canBeFinalized()) {
|
if ($this->canBeFinalized()) {
|
||||||
$this->update(['estado' => 'finalizada']);
|
$this->update(['estado' => 'finalizada']);
|
||||||
|
|
||||||
|
// Crear inventario si corresponde
|
||||||
|
$this->crearInventarioPorFinalizacion();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -212,62 +216,67 @@ class OrdenProduccion extends Model
|
|||||||
|
|
||||||
// Si la orden llega a finalizada, crear entrada en inventario con lo que haya ingresado
|
// Si la orden llega a finalizada, crear entrada en inventario con lo que haya ingresado
|
||||||
if ($this->estado === 'finalizada') {
|
if ($this->estado === 'finalizada') {
|
||||||
// Sumar procesos de acabados recibidos para determinar cantidad terminada
|
$this->crearInventarioPorFinalizacion();
|
||||||
$cantidad = \App\Models\ProcesoAcabado::where('orden_produccion_id', $this->id)
|
|
||||||
->whereNotNull('fecha_recepcion')
|
|
||||||
->sum('cantidad_recibida');
|
|
||||||
|
|
||||||
// Crear inventario solo si hay traslados a bodega con cantidad
|
|
||||||
if ($cantidad > 0 && !\App\Models\InventarioPrenda::where('orden_produccion_id', $this->id)->exists()) {
|
|
||||||
// Determinar producto asociado: preferir producto_id en la OP, sino crear/buscar por prenda_modelo
|
|
||||||
$productoId = $this->producto_id;
|
|
||||||
|
|
||||||
if (! $productoId) {
|
|
||||||
$nombre = $this->prenda_modelo ?? $this->referencia ?? null;
|
|
||||||
if ($nombre) {
|
|
||||||
// Generar código de barras único por defecto para productos creados automáticamente
|
|
||||||
$codigo = 'AUTOP-' . $this->id . '-' . time();
|
|
||||||
$codigo = substr($codigo, 0, 50);
|
|
||||||
|
|
||||||
// Asegurar unicidad
|
|
||||||
while (\App\Models\Producto::where('codigo_barras', $codigo)->exists()) {
|
|
||||||
$codigo .= '-' . rand(0, 9);
|
|
||||||
$codigo = substr($codigo, 0, 50);
|
|
||||||
}
|
|
||||||
|
|
||||||
$producto = \App\Models\Producto::firstOrCreate(
|
|
||||||
['nombre' => $nombre],
|
|
||||||
[
|
|
||||||
'descripcion' => 'Creado automáticamente desde OrdenProduccion #' . $this->id,
|
|
||||||
'stock' => 0,
|
|
||||||
'estado' => true,
|
|
||||||
'precio_compra' => 0,
|
|
||||||
'precio_venta' => 0,
|
|
||||||
'unidad_medida' => 'unidad',
|
|
||||||
'codigo_barras' => $codigo,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
$productoId = $producto->id;
|
|
||||||
|
|
||||||
// Guardar vínculo en la OP para futuras referencias
|
|
||||||
$this->producto_id = $productoId;
|
|
||||||
$this->save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
\App\Models\InventarioPrenda::create([
|
|
||||||
'orden_produccion_id' => $this->id,
|
|
||||||
'cantidad_terminada' => $cantidad,
|
|
||||||
'cantidad_disponible' => $cantidad,
|
|
||||||
'fecha_ingreso' => now(),
|
|
||||||
'estado' => 'en_bodega',
|
|
||||||
'producto_id' => $productoId ?? null,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Si se creó inventario, también actualizar stock del producto asociado (handler en InventarioPrenda lo hará)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function crearInventarioPorFinalizacion(): void
|
||||||
|
{
|
||||||
|
// Sumar procesos de acabados recibidos para determinar cantidad terminada
|
||||||
|
$cantidad = \App\Models\ProcesoAcabado::where('orden_produccion_id', $this->id)
|
||||||
|
->whereNotNull('fecha_recepcion')
|
||||||
|
->sum('cantidad_recibida');
|
||||||
|
|
||||||
|
// Crear inventario solo si hay traslados a bodega con cantidad
|
||||||
|
if ($cantidad > 0 && !\App\Models\InventarioPrenda::where('orden_produccion_id', $this->id)->exists()) {
|
||||||
|
// Determinar producto asociado: preferir producto_id en la OP, sino crear/buscar por prenda_modelo
|
||||||
|
$productoId = $this->producto_id;
|
||||||
|
|
||||||
|
if (! $productoId) {
|
||||||
|
$nombre = $this->prenda_modelo ?? $this->referencia ?? null;
|
||||||
|
if ($nombre) {
|
||||||
|
// Generar código de barras único por defecto para productos creados automáticamente
|
||||||
|
$codigo = 'AUTOP-' . $this->id . '-' . time();
|
||||||
|
$codigo = substr($codigo, 0, 50);
|
||||||
|
|
||||||
|
// Asegurar unicidad
|
||||||
|
while (\App\Models\Producto::where('codigo_barras', $codigo)->exists()) {
|
||||||
|
$codigo .= '-' . rand(0, 9);
|
||||||
|
$codigo = substr($codigo, 0, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
$producto = \App\Models\Producto::firstOrCreate(
|
||||||
|
['nombre' => $nombre],
|
||||||
|
[
|
||||||
|
'descripcion' => 'Creado automáticamente desde OrdenProduccion #' . $this->id,
|
||||||
|
'stock' => 0,
|
||||||
|
'estado' => true,
|
||||||
|
'precio_compra' => 0,
|
||||||
|
'precio_venta' => 0,
|
||||||
|
'unidad_medida' => 'unidad',
|
||||||
|
'codigo_barras' => $codigo,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$productoId = $producto->id;
|
||||||
|
|
||||||
|
// Guardar vínculo en la OP para futuras referencias
|
||||||
|
$this->producto_id = $productoId;
|
||||||
|
$this->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\App\Models\InventarioPrenda::create([
|
||||||
|
'orden_produccion_id' => $this->id,
|
||||||
|
'cantidad_terminada' => $cantidad,
|
||||||
|
'cantidad_disponible' => $cantidad,
|
||||||
|
'fecha_ingreso' => now(),
|
||||||
|
'estado' => 'en_bodega',
|
||||||
|
'producto_id' => $productoId ?? null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Si se creó inventario, también actualizar stock del producto asociado (handler en InventarioPrenda lo hará)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,11 @@
|
|||||||
@foreach($ordersByState[$stateKey] as $op)
|
@foreach($ordersByState[$stateKey] as $op)
|
||||||
<div class="op-card bg-white rounded border p-2 shadow-sm" draggable="true" ondragstart="dragStart(event, {{ $op->id }})">
|
<div class="op-card bg-white rounded border p-2 shadow-sm" draggable="true" ondragstart="dragStart(event, {{ $op->id }})">
|
||||||
<div class="text-sm font-semibold">#{{ $op->numero_orden }} — {{ $op->prenda_modelo }}</div>
|
<div class="text-sm font-semibold">#{{ $op->numero_orden }} — {{ $op->prenda_modelo }}</div>
|
||||||
<div class="text-xs text-gray-500">Cant: {{ $op->cantidad_total }} · Metros: {{ $op->metros_requeridos }} · Entrega: {{ $op->fecha_entrega_estimada }}</div>
|
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
Cant: {{ $op->cantidad_total }} · Realizado: {{ $op->realizado }} · Faltan: {{ $op->faltantes }}<br>
|
||||||
|
Tela: {{ $op->tela?->codigo ?? '—' }} · Estado: <span class="inline-block px-2 py-0.5 rounded text-xs bg-gray-100">{{ \Illuminate\Support\Str::title(str_replace('_', ' ', $op->estado)) }}</span> · Entrega: {{ $op->fecha_entrega_estimada }}
|
||||||
|
</div>
|
||||||
<div class="mt-2 flex gap-2">
|
<div class="mt-2 flex gap-2">
|
||||||
<a href="{{ route('filament.admin.resources.orden-produccions.edit', ['record' => $op->id]) }}" class="text-blue-600 text-sm">Ver</a>
|
<a href="{{ route('filament.admin.resources.orden-produccions.edit', ['record' => $op->id]) }}" class="text-blue-600 text-sm">Ver</a>
|
||||||
<button class="text-sm px-2 py-1 bg-gray-100 rounded" onclick="quickAdvance({{ $op->id }})">Avanzar</button>
|
<button class="text-sm px-2 py-1 bg-gray-100 rounded" onclick="quickAdvance({{ $op->id }})">Avanzar</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user