p
This commit is contained in:
@@ -131,6 +131,14 @@ class OrdenProduccionResource extends Resource
|
|||||||
TextColumn::make('cantidad_total')
|
TextColumn::make('cantidad_total')
|
||||||
->label('Cantidad'),
|
->label('Cantidad'),
|
||||||
|
|
||||||
|
TextColumn::make('realizado')
|
||||||
|
->label('Realizado')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
|
TextColumn::make('faltantes')
|
||||||
|
->label('Faltan')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
TextColumn::make('tela.codigo')
|
TextColumn::make('tela.codigo')
|
||||||
->label('Tela')
|
->label('Tela')
|
||||||
->toggleable(),
|
->toggleable(),
|
||||||
|
|||||||
@@ -58,6 +58,18 @@ class OrdenProduccion extends Model
|
|||||||
return $this->belongsTo(\App\Models\Producto::class, 'producto_id');
|
return $this->belongsTo(\App\Models\Producto::class, 'producto_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Total realizado: suma de cantidad_terminada en inventarios asociados
|
||||||
|
public function getRealizadoAttribute()
|
||||||
|
{
|
||||||
|
return (int) $this->inventarioPrenda()->sum('cantidad_terminada');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Faltantes = cantidad_total - realizado
|
||||||
|
public function getFaltantesAttribute()
|
||||||
|
{
|
||||||
|
return max(0, (int)$this->cantidad_total - $this->realizado);
|
||||||
|
}
|
||||||
|
|
||||||
public function avanzarEstado(): void
|
public function avanzarEstado(): void
|
||||||
{
|
{
|
||||||
$flujo = [
|
$flujo = [
|
||||||
|
|||||||
@@ -80,9 +80,15 @@ class ProcesoAcabado extends Model
|
|||||||
->exists();
|
->exists();
|
||||||
|
|
||||||
if (!$pendientes) {
|
if (!$pendientes) {
|
||||||
$acabado->ordenProduccion?->update([
|
$op = $acabado->ordenProduccion;
|
||||||
'estado' => 'finalizada',
|
if ($op) {
|
||||||
]);
|
$realizado = (int) $op->inventarioPrenda()->sum('cantidad_terminada');
|
||||||
|
if ($realizado >= (int) ($op->cantidad_total ?? 0)) {
|
||||||
|
$op->update([
|
||||||
|
'estado' => 'finalizada',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,19 @@ return new class extends Migration
|
|||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
// Backfill producto_id in inventario_prendas from la OP relacionada cuando sea NULL
|
// Backfill producto_id in inventario_prendas from la OP relacionada cuando sea NULL
|
||||||
DB::statement("UPDATE inventario_prendas ip SET producto_id = op.producto_id FROM orden_produccions op WHERE ip.orden_produccion_id = op.id AND ip.producto_id IS NULL AND op.producto_id IS NOT NULL");
|
// Use a compatible update for both MySQL/Postgres and SQLite
|
||||||
|
$driver = Schema::getConnection()->getDriverName();
|
||||||
|
if ($driver === 'sqlite') {
|
||||||
|
DB::statement(
|
||||||
|
"UPDATE inventario_prendas SET producto_id = (
|
||||||
|
SELECT op.producto_id FROM orden_produccions op WHERE op.id = inventario_prendas.orden_produccion_id
|
||||||
|
) WHERE producto_id IS NULL AND orden_produccion_id IS NOT NULL AND (
|
||||||
|
SELECT op.producto_id FROM orden_produccions op WHERE op.id = inventario_prendas.orden_produccion_id
|
||||||
|
) IS NOT NULL"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
DB::statement("UPDATE inventario_prendas ip SET producto_id = op.producto_id FROM orden_produccions op WHERE ip.orden_produccion_id = op.id AND ip.producto_id IS NULL AND op.producto_id IS NOT NULL");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(): void
|
public function down(): void
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use App\Models\OrdenProduccion;
|
||||||
|
use App\Models\InventarioPrenda;
|
||||||
|
use App\Models\ProcesoAcabado;
|
||||||
|
|
||||||
|
class OrdenProduccionFaltantesTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
public function test_faltantes_and_realizado_calculation()
|
||||||
|
{
|
||||||
|
$op = OrdenProduccion::create(['numero_orden' => 'OP-900', 'prenda_modelo' => 'ModeloX', 'cantidad_total' => 50, 'metros_requeridos' => 0, 'fecha_inicio' => now(), 'fecha_entrega_estimada' => now()->addDays(7)]);
|
||||||
|
|
||||||
|
// Initially nothing done
|
||||||
|
$this->assertEquals(0, $op->realizado);
|
||||||
|
$this->assertEquals(50, $op->faltantes);
|
||||||
|
|
||||||
|
// Create an inventario with 20 finished
|
||||||
|
InventarioPrenda::create(['orden_produccion_id' => $op->id, 'cantidad_terminada' => 20, 'cantidad_disponible' => 20, 'fecha_ingreso' => now(), 'estado' => 'en_bodega']);
|
||||||
|
|
||||||
|
$op->refresh();
|
||||||
|
|
||||||
|
$this->assertEquals(20, $op->realizado);
|
||||||
|
$this->assertEquals(30, $op->faltantes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_do_not_set_finalizada_until_completed()
|
||||||
|
{
|
||||||
|
$op = OrdenProduccion::create(['numero_orden' => 'OP-901', 'prenda_modelo' => 'ModeloY', 'cantidad_total' => 10, 'metros_requeridos' => 0, 'fecha_inicio' => now(), 'fecha_entrega_estimada' => now()->addDays(7)]);
|
||||||
|
|
||||||
|
// Create process finished but no inventario yet
|
||||||
|
ProcesoAcabado::create(['orden_produccion_id' => $op->id, 'tipo_proceso' => 'PA', 'proveedor_id' => \App\Models\Proveedor::factory()->create(['categoria' => 'proveedor'])->id, 'cantidad_enviada' => 0, 'cantidad_recibida' => 8, 'fecha_envio' => now(), 'fecha_recepcion' => now()]);
|
||||||
|
|
||||||
|
$op->refresh();
|
||||||
|
|
||||||
|
// Since only 8 are received into processus, but no inventory recorded, still not finalizada
|
||||||
|
$this->assertNotEquals('finalizada', $op->estado);
|
||||||
|
|
||||||
|
// Create inventory for the 8 (not enough to finalize)
|
||||||
|
InventarioPrenda::create(['orden_produccion_id' => $op->id, 'cantidad_terminada' => 8, 'cantidad_disponible' => 8, 'fecha_ingreso' => now(), 'estado' => 'en_bodega']);
|
||||||
|
|
||||||
|
$op->refresh();
|
||||||
|
$this->assertEquals(2, $op->faltantes);
|
||||||
|
|
||||||
|
// Now add remaining inventory
|
||||||
|
InventarioPrenda::create(['orden_produccion_id' => $op->id, 'cantidad_terminada' => 2, 'cantidad_disponible' => 2, 'fecha_ingreso' => now(), 'estado' => 'en_bodega']);
|
||||||
|
|
||||||
|
$op->refresh();
|
||||||
|
$this->assertEquals(0, $op->faltantes);
|
||||||
|
|
||||||
|
// Simulate no pending procesosAcabado and trigger the check
|
||||||
|
ProcesoAcabado::where('orden_produccion_id', $op->id)->update(['fecha_recepcion' => now()]);
|
||||||
|
$op->refresh();
|
||||||
|
|
||||||
|
// Now the orden should be finalizada when all completed
|
||||||
|
$this->assertEquals('finalizada', $op->estado);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user