Files
pos_heidiver/app/Models/OrdenProduccion.php
T
2026-01-18 12:50:01 -05:00

161 lines
5.6 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class OrdenProduccion extends Model
{
use HasFactory;
protected $fillable = [
'numero_orden',
'prenda_modelo',
'referencia',
'cantidad_total',
'tela_id',
'fecha_inicio',
'fecha_entrega_estimada',
'estado',
'metros_requeridos',
'tela_reservada',
];
public function tela()
{
return $this->belongsTo(Tela::class);
}
public function traslados()
{
return $this->hasMany(\App\Models\TrasladoPrenda::class);
}
public function confeccions()
{
return $this->hasMany(\App\Models\Confeccion::class);
}
public function tintorerias()
{
return $this->hasMany(\App\Models\Tintoreria::class);
}
public function procesosAcabado()
{
return $this->hasMany(\App\Models\ProcesoAcabado::class);
}
public function inventarioPrenda()
{
return $this->hasMany(\App\Models\InventarioPrenda::class);
}
public function avanzarEstado(): void
{
$flujo = [
'en_corte',
'en_confeccion',
'en_tintoreria',
'en_acabados',
'finalizada',
];
$actual = array_search($this->estado, $flujo, true);
if ($actual !== false && isset($flujo[$actual + 1])) {
$this->update([
'estado' => $flujo[$actual + 1],
]);
// Si la orden llega a finalizada, crear entrada en inventario con lo que haya ingresado
if ($this->estado === 'finalizada') {
// Sumar traslados cuyo destino sea 'bodega'
$cantidad = \App\Models\TrasladoPrenda::where('orden_produccion_id', $this->id)
->where('destino', 'bodega')
->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()) {
\App\Models\InventarioPrenda::create([
'orden_produccion_id' => $this->id,
'cantidad_terminada' => $cantidad,
'cantidad_disponible' => $cantidad,
'fecha_ingreso' => now(),
'estado' => 'en_bodega',
]);
}
}
}
}
protected static function booted()
{
static::creating(function ($orden) {
if (!$orden->numero_orden) {
$ultimoId = self::max('id') + 1;
$orden->numero_orden = 'OP-' . str_pad($ultimoId, 6, '0', STR_PAD_LEFT);
}
});
// Validar y reservar tela al cambiar de estado a 'en_corte'
static::updating(function ($orden) {
// Validación: si se especifica tela y metros_requeridos, verificar disponibilidad
if ($orden->tela_id && $orden->metros_requeridos !== null) {
$tela = \App\Models\Tela::find($orden->tela_id);
$originalMetros = $orden->getOriginal('metros_requeridos') ?? 0;
$reservedAlready = $orden->tela_reservada ? $originalMetros : 0;
$available = $tela ? ($tela->metros_disponibles + $reservedAlready) : null;
if ($available !== null && $orden->metros_requeridos > $available) {
throw \Illuminate\Validation\ValidationException::withMessages([
'metros_requeridos' => 'No hay suficientes metros de tela disponibles. Disponibles: ' . ($available),
]);
}
}
$originalEstado = $orden->getOriginal('estado');
$nuevoEstado = $orden->estado;
// Reservar cuando pasamos a en_corte y no estaba reservado
if ($originalEstado !== 'en_corte' && $nuevoEstado === 'en_corte' && ! $orden->tela_reservada) {
if ($orden->tela_id && $orden->metros_requeridos > 0) {
$tela = \App\Models\Tela::find($orden->tela_id);
if (! $tela) {
throw \Illuminate\Validation\ValidationException::withMessages([
'tela_id' => 'No se encontró la tela asociada.',
]);
}
if ($tela->metros_disponibles < $orden->metros_requeridos) {
throw \Illuminate\Validation\ValidationException::withMessages([
'metros_requeridos' => 'No hay suficientes metros disponibles para reservar (' . $tela->metros_disponibles . ').',
]);
}
// Reservar: restar metros y marcar orden
$tela->metros_disponibles = $tela->metros_disponibles - $orden->metros_requeridos;
$tela->save();
$orden->tela_reservada = true;
}
}
// Si retrocede desde en_corte y ya estaba reservado, devolver la tela
if ($originalEstado === 'en_corte' && $nuevoEstado !== 'en_corte' && $orden->tela_reservada) {
if ($orden->tela_id && $orden->metros_requeridos > 0) {
$tela = \App\Models\Tela::find($orden->tela_id);
if ($tela) {
$tela->metros_disponibles = $tela->metros_disponibles + $orden->metros_requeridos;
$tela->save();
}
}
$orden->tela_reservada = false;
}
});
}
}