belongsTo(Proveedor::class); } public function ordenProduccion() { return $this->belongsTo(OrdenProduccion::class); } /* Lógica de negocio */ protected static function booted() { static::saving(function ($confeccion) { // Establecer fecha de envío por defecto si no se proporcionó if (! $confeccion->fecha_envio) { $confeccion->fecha_envio = now(); } // Validación: cantidad_enviada no puede exceder la cantidad total de la OP if ($confeccion->cantidad_enviada !== null && $confeccion->orden_produccion_id) { $orden = \App\Models\OrdenProduccion::find($confeccion->orden_produccion_id); if ($orden && $confeccion->cantidad_enviada > $orden->cantidad_total) { throw \Illuminate\Validation\ValidationException::withMessages([ 'cantidad_enviada' => 'La cantidad enviada no puede exceder la cantidad total de la Orden de Producción (' . $orden->cantidad_total . ').', ]); } } // Total a pagar: usa cantidad_recibida si existe, sino cantidad_enviada $cantidadBase = $confeccion->cantidad_recibida ?? $confeccion->cantidad_enviada ?? 0; $valorUnitario = $confeccion->valor_por_prenda ?? 0; $confeccion->total_pagar = $cantidadBase * $valorUnitario; // Estado automático if (! $confeccion->cantidad_recibida) { $confeccion->estado = 'pendiente'; } elseif ($confeccion->cantidad_recibida < $confeccion->cantidad_enviada) { $confeccion->estado = 'parcial'; } else { $confeccion->estado = 'completo'; } }); /* Recepciones polimórficas */ public function recepciones() { return $this->morphMany(\App\Models\Recepcion::class, 'referencia'); } // Cuantas faltan por recibir public function getFaltantesAttribute() { return max(0, (int)($this->cantidad_enviada ?? 0) - (int)($this->cantidad_recibida ?? 0)); } // Mantener avance de OP cuando la confección se completa static::saved(function ($confeccion) { if ($confeccion->estado === 'completo') { $confeccion->ordenProduccion?->avanzarEstado(); } }); } }