up
This commit is contained in:
@@ -30,12 +30,8 @@ class EditConfeccion extends EditRecord
|
||||
->helperText(fn () => 'Máximo: ' . ($this->getRecord()->faltantes ?? 0))
|
||||
->default(fn () => $this->getRecord()->faltantes ?? 0),
|
||||
|
||||
Forms\Components\TextInput::make('prendas_defectuosas')
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->maxValue(fn ($get) => (int) ($get('cantidad') ?? 0))
|
||||
->helperText('Opcional. Se restará del total recibido.'),
|
||||
Forms\Components\Textarea::make('notas'),
|
||||
Forms\Components\Textarea::make('notas')
|
||||
->helperText('Si hay prendas defectuosas, regístralas después en "Arreglos".'),
|
||||
])
|
||||
->action(function (array $data): void {
|
||||
$record = $this->getRecord();
|
||||
@@ -46,7 +42,7 @@ class EditConfeccion extends EditRecord
|
||||
'referencia_id' => $record->id,
|
||||
'cantidad' => (int) $data['cantidad'],
|
||||
'fecha_recepcion' => $data['fecha_recepcion'],
|
||||
'prendas_defectuosas' => isset($data['prendas_defectuosas']) ? (int) $data['prendas_defectuosas'] : 0,
|
||||
'prendas_defectuosas' => 0,
|
||||
'notas' => $data['notas'] ?? null,
|
||||
]);
|
||||
|
||||
|
||||
+2
-9
@@ -30,14 +30,8 @@ class RecepcionesRelationManager extends RelationManager
|
||||
->maxValue(fn () => $this->getOwnerRecord()?->faltantes ?? 0)
|
||||
->helperText(fn () => 'Máximo: ' . ($this->getOwnerRecord()?->faltantes ?? 0)),
|
||||
|
||||
TextInput::make('prendas_defectuosas')
|
||||
->label('Faltantes')
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->maxValue(fn ($get) => (int) ($get('cantidad') ?? 0))
|
||||
->helperText('Opcional. Se restará del total recibido.'),
|
||||
|
||||
Textarea::make('notas'),
|
||||
Textarea::make('notas')
|
||||
->helperText('Si hay prendas defectuosas, regístralas en "Arreglos" después de crear la recepción.'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -48,7 +42,6 @@ class RecepcionesRelationManager extends RelationManager
|
||||
TextColumn::make('id')->label('#'),
|
||||
TextColumn::make('fecha_recepcion')->dateTime()->label('Fecha'),
|
||||
TextColumn::make('cantidad')->label('Cantidad'),
|
||||
TextColumn::make('prendas_defectuosas')->label('Faltantes'),
|
||||
TextColumn::make('usuario.name')->label('Usuario'),
|
||||
TextColumn::make('notas')->limit(50)->wrap(),
|
||||
TextColumn::make('created_at')->dateTime()->label('Creado'),
|
||||
|
||||
+46
-58
@@ -118,7 +118,8 @@ class Confeccion extends Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Registrar un arreglo como ajuste histórico y crear traslado de reparaciones
|
||||
* Registrar un arreglo: prendas que llegaron mal y salen a reparación
|
||||
* Permiten re-recepción cuando regresen arregladas
|
||||
*/
|
||||
public function registerArreglo(int $cantidad, ?string $notas = null, ?int $userId = null)
|
||||
{
|
||||
@@ -126,9 +127,25 @@ class Confeccion extends Model
|
||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad' => 'La cantidad debe ser mayor que 0.']);
|
||||
}
|
||||
|
||||
$recibido = $this->recibido_total;
|
||||
if ($cantidad > $recibido) {
|
||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad' => 'La cantidad supera lo recibido.']);
|
||||
// Validar que no exceda las recepciones efectivas (solo puedes marcar como arreglo lo que YA recibiste)
|
||||
$recepcionesEfectivas = (int) $this->recepciones()->sum(\DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
|
||||
$arreglosActuales = (int) $this->ajustes()->where('tipo', 'arreglo')->sum('cantidad');
|
||||
|
||||
$disponibleParaArreglos = $recepcionesEfectivas - $arreglosActuales;
|
||||
|
||||
if ($cantidad > $disponibleParaArreglos) {
|
||||
throw \Illuminate\Validation\ValidationException::withMessages([
|
||||
'cantidad' => "No puedes registrar {$cantidad} prendas como arreglo.
|
||||
|
||||
📊 Resumen:
|
||||
• Recepciones efectivas: {$recepcionesEfectivas}
|
||||
• Arreglos ya registrados: {$arreglosActuales}
|
||||
• Disponible para marcar como arreglo: {$disponibleParaArreglos}
|
||||
|
||||
➡️ Solo puedes registrar máximo {$disponibleParaArreglos} prendas como arreglo.
|
||||
|
||||
💡 Los arreglos deben ser de prendas YA recibidas que necesitan reparación."
|
||||
]);
|
||||
}
|
||||
|
||||
// Crear ajuste
|
||||
@@ -141,31 +158,12 @@ class Confeccion extends Model
|
||||
'notas' => $notas,
|
||||
]);
|
||||
|
||||
// Crear traslado de reparaciones para reflejar la salida
|
||||
\App\Models\TrasladoPrenda::create([
|
||||
'orden_produccion_id' => $this->orden_produccion_id,
|
||||
'referencia_type' => self::class,
|
||||
'referencia_id' => $this->id,
|
||||
'origen' => 'confeccion',
|
||||
'destino' => 'reparaciones',
|
||||
'cantidad_enviada' => $cantidad,
|
||||
'cantidad_recibida' => 0,
|
||||
'prendas_defectuosas' => 0,
|
||||
'reparaciones' => $cantidad,
|
||||
'fecha_envio' => now(),
|
||||
'fecha_recepcion' => now(),
|
||||
'estado' => 'recibido',
|
||||
]);
|
||||
|
||||
// Recalcular cantidad_recibida almacenada para compatibilidad con UI
|
||||
$this->cantidad_recibida = $this->recibido_total;
|
||||
$this->save();
|
||||
|
||||
return $aj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registrar un cobro: descontar inventario y crear registro de cobro
|
||||
* Registrar un cobro: solo registra el cobro sin descontar inventario
|
||||
* Los cobros son prendas que NO llegaron - se cobran al confeccionista
|
||||
*/
|
||||
public function registerCobro(int $cantidad, float $valor, ?string $notas = null, ?int $userId = null)
|
||||
{
|
||||
@@ -173,46 +171,36 @@ class Confeccion extends Model
|
||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad' => 'La cantidad debe ser mayor que 0.']);
|
||||
}
|
||||
|
||||
if (!$this->orden_produccion_id) {
|
||||
throw \Illuminate\Validation\ValidationException::withMessages(['orden_produccion_id' => 'La confección debe tener una orden de producción asociada.']);
|
||||
// Validar que no se exceda lo enviado
|
||||
$enviada = (int) ($this->cantidad_enviada ?? 0);
|
||||
if ($enviada <= 0) {
|
||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad' => 'La confección no tiene cantidad_enviada registrada.']);
|
||||
}
|
||||
|
||||
// Buscar inventarios disponibles de esta orden de producción
|
||||
$inventarios = \App\Models\InventarioPrenda::where('orden_produccion_id', $this->orden_produccion_id)
|
||||
->where('cantidad_disponible', '>', 0)
|
||||
->orderBy('cantidad_disponible', 'desc')
|
||||
->get();
|
||||
// Calcular lo que ya se ha contabilizado
|
||||
$recepcionesEfectivas = (int) $this->recepciones()->sum(\DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
|
||||
$arreglos = (int) $this->ajustes()->where('tipo', 'arreglo')->sum('cantidad');
|
||||
$recibidoNeto = $recepcionesEfectivas - $arreglos; // Los arreglos permiten re-recepción
|
||||
|
||||
if ($inventarios->isEmpty()) {
|
||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad' => 'No hay inventario disponible para la orden de producción #' . $this->orden_produccion_id . '. Asegúrate de que exista inventario con cantidad_disponible > 0.']);
|
||||
}
|
||||
$cobrosActuales = (int) $this->cobros()->sum('cantidad');
|
||||
|
||||
$totalDisponible = $inventarios->sum('cantidad_disponible');
|
||||
$totalContabilizado = $recibidoNeto + $cobrosActuales;
|
||||
$disponible = $enviada - $totalContabilizado;
|
||||
|
||||
if ($totalDisponible < $cantidad) {
|
||||
throw \Illuminate\Validation\ValidationException::withMessages(['cantidad' => "Solo hay {$totalDisponible} unidades disponibles en inventario. No se puede descontar {$cantidad}."]);
|
||||
}
|
||||
if ($cantidad > $disponible) {
|
||||
throw \Illuminate\Validation\ValidationException::withMessages([
|
||||
'cantidad' => "No puedes registrar {$cantidad} prendas como cobro.
|
||||
|
||||
// Descontar del inventario de forma distribuida si es necesario
|
||||
$cantidadRestante = $cantidad;
|
||||
foreach ($inventarios as $inventario) {
|
||||
if ($cantidadRestante <= 0) {
|
||||
break;
|
||||
}
|
||||
📊 Resumen:
|
||||
• Enviadas: {$enviada}
|
||||
• Recepciones efectivas: {$recepcionesEfectivas}
|
||||
• Arreglos (permiten re-recepción): {$arreglos}
|
||||
• Recibido neto: {$recibidoNeto}
|
||||
• Cobros registrados: {$cobrosActuales}
|
||||
• Disponible para cobros: {$disponible}
|
||||
|
||||
$aDescontar = min($cantidadRestante, $inventario->cantidad_disponible);
|
||||
$inventario->cantidad_disponible -= $aDescontar;
|
||||
$inventario->save();
|
||||
|
||||
// Si está asociado a producto, decrementar stock
|
||||
if ($inventario->producto_id) {
|
||||
$producto = \App\Models\Producto::find($inventario->producto_id);
|
||||
if ($producto) {
|
||||
$producto->decrement('stock', $aDescontar);
|
||||
}
|
||||
}
|
||||
|
||||
$cantidadRestante -= $aDescontar;
|
||||
➡️ Solo puedes registrar máximo {$disponible} prendas más como cobros."
|
||||
]);
|
||||
}
|
||||
|
||||
// Crear registro de cobro
|
||||
|
||||
@@ -60,20 +60,46 @@ class Recepcion extends Model
|
||||
$rec->fecha_recepcion = now();
|
||||
}
|
||||
|
||||
// Validación: no permitir sobrepasar la cantidad enviada en la referencia (considerando defectuosos)
|
||||
// Validación: no permitir sobrepasar la cantidad enviada en la referencia (considerando cobros)
|
||||
if ($rec->referencia) {
|
||||
$referencia = $rec->referencia;
|
||||
$enviada = (int) ($referencia->cantidad_enviada ?? 0);
|
||||
|
||||
// ya recibido efectivo (cantidad - defectuosos)
|
||||
// Ya recibido efectivo (cantidad - defectuosos) - arreglos permiten re-recepción
|
||||
$yaRecibido = (int) \App\Models\Recepcion::where('referencia_type', get_class($referencia))
|
||||
->where('referencia_id', $referencia->id)
|
||||
->sum(\DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
|
||||
|
||||
$efectivo = $rec->cantidad - $rec->prendas_defectuosas;
|
||||
// Los arreglos se restan porque permiten re-recepción cuando regresen
|
||||
$arreglos = 0;
|
||||
if (method_exists($referencia, 'ajustes')) {
|
||||
$arreglos = (int) $referencia->ajustes()->where('tipo', 'arreglo')->sum('cantidad');
|
||||
}
|
||||
|
||||
if (($yaRecibido + $efectivo) > $enviada) {
|
||||
throw ValidationException::withMessages(['cantidad' => "La recepción excede la cantidad pendiente (faltan: " . max(0, $enviada - $yaRecibido) . ")."]);
|
||||
// Los cobros NO permiten más recepciones (son prendas que no llegaron)
|
||||
$cobros = 0;
|
||||
if (method_exists($referencia, 'cobros')) {
|
||||
$cobros = (int) $referencia->cobros()->sum('cantidad');
|
||||
}
|
||||
|
||||
$efectivo = $rec->cantidad - $rec->prendas_defectuosas;
|
||||
$yaRecibidoNeto = $yaRecibido - $arreglos;
|
||||
$maxPermitido = $enviada - $cobros;
|
||||
|
||||
if (($yaRecibidoNeto + $efectivo) > $maxPermitido) {
|
||||
$disponible = max(0, $maxPermitido - $yaRecibidoNeto);
|
||||
throw ValidationException::withMessages([
|
||||
'cantidad' => "La recepción excede lo permitido.
|
||||
|
||||
📊 Resumen:
|
||||
• Enviadas: {$enviada}
|
||||
• Ya recibidas (neto): {$yaRecibidoNeto}
|
||||
• Cobros registrados: {$cobros}
|
||||
• Arreglos (permiten re-recepción): {$arreglos}
|
||||
• Disponible para recibir: {$disponible}
|
||||
|
||||
➡️ Solo puedes recibir {$disponible} prendas más."
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = require_once __DIR__ . '/../bootstrap/app.php';
|
||||
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
|
||||
echo "=== Diagnóstico de Confección #9 ===\n\n";
|
||||
|
||||
$confeccion = \App\Models\Confeccion::find(9);
|
||||
|
||||
if (!$confeccion) {
|
||||
echo "❌ No se encontró la confección con ID 9\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "✅ Confección encontrada:\n";
|
||||
echo " ID: {$confeccion->id}\n";
|
||||
echo " Orden Producción ID: {$confeccion->orden_produccion_id}\n";
|
||||
echo " Cliente: {$confeccion->cliente->nombre}\n\n";
|
||||
|
||||
if (!$confeccion->orden_produccion_id) {
|
||||
echo "❌ La confección NO tiene orden_produccion_id asociada\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "=== Buscando inventarios para orden_produccion_id = {$confeccion->orden_produccion_id} ===\n\n";
|
||||
|
||||
$inventarios = \App\Models\InventarioPrenda::where('orden_produccion_id', $confeccion->orden_produccion_id)->get();
|
||||
|
||||
echo "Total inventarios encontrados: {$inventarios->count()}\n\n";
|
||||
|
||||
if ($inventarios->isEmpty()) {
|
||||
echo "❌ NO HAY INVENTARIOS para esta orden de producción\n";
|
||||
echo " Esto explica el error\n\n";
|
||||
|
||||
// Verificar si existe la orden de producción
|
||||
$op = \App\Models\OrdenProduccion::find($confeccion->orden_produccion_id);
|
||||
if ($op) {
|
||||
echo "✅ La orden de producción #{$op->id} existe:\n";
|
||||
echo " Producto: " . ($op->producto->nombre ?? 'N/A') . "\n";
|
||||
echo " Cantidad: {$op->cantidad}\n";
|
||||
echo " Estado: {$op->estado}\n\n";
|
||||
echo "⚠️ Necesitas crear registros de inventario para esta orden\n";
|
||||
} else {
|
||||
echo "❌ La orden de producción no existe\n";
|
||||
}
|
||||
} else {
|
||||
echo "Detalles de inventarios:\n";
|
||||
foreach ($inventarios as $inv) {
|
||||
echo "---\n";
|
||||
echo "ID: {$inv->id}\n";
|
||||
echo "Cantidad terminada: {$inv->cantidad_terminada}\n";
|
||||
echo "Cantidad disponible: {$inv->cantidad_disponible}\n";
|
||||
echo "Estado: {$inv->estado}\n";
|
||||
echo "Producto ID: {$inv->producto_id}\n";
|
||||
}
|
||||
|
||||
$totalDisponible = $inventarios->sum('cantidad_disponible');
|
||||
echo "\n✅ Total disponible: {$totalDisponible} unidades\n";
|
||||
|
||||
if ($totalDisponible > 0) {
|
||||
echo "✅ Hay inventario suficiente para registrar cobros\n";
|
||||
} else {
|
||||
echo "❌ No hay inventario con cantidad_disponible > 0\n";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = require_once __DIR__ . '/../bootstrap/app.php';
|
||||
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
|
||||
echo "=== Diagnóstico de Orden de Producción #9 ===\n\n";
|
||||
|
||||
$op = \App\Models\OrdenProduccion::find(9);
|
||||
|
||||
if (!$op) {
|
||||
echo "❌ No se encontró la orden de producción con ID 9\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "✅ Orden de Producción encontrada:\n";
|
||||
echo " ID: {$op->id}\n";
|
||||
echo " Producto: " . ($op->producto->nombre ?? 'N/A') . " (ID: {$op->producto_id})\n";
|
||||
echo " Cantidad: {$op->cantidad}\n";
|
||||
echo " Estado: {$op->estado}\n\n";
|
||||
|
||||
// Buscar confecciones asociadas
|
||||
$confecciones = \App\Models\Confeccion::where('orden_produccion_id', 9)->get();
|
||||
echo "Confecciones asociadas a esta OP: {$confecciones->count()}\n";
|
||||
foreach ($confecciones as $conf) {
|
||||
$clienteNombre = $conf->cliente ? $conf->cliente->nombre : 'Sin cliente';
|
||||
echo " - Confección #{$conf->id} - Cliente: {$clienteNombre}\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "=== Buscando inventarios para orden_produccion_id = 9 ===\n\n";
|
||||
|
||||
$inventarios = \App\Models\InventarioPrenda::where('orden_produccion_id', 9)->get();
|
||||
|
||||
echo "Total inventarios encontrados: {$inventarios->count()}\n\n";
|
||||
|
||||
if ($inventarios->isEmpty()) {
|
||||
echo "❌ NO HAY INVENTARIOS para esta orden de producción\n";
|
||||
echo " Esto explica el error al intentar registrar cobros\n\n";
|
||||
echo "⚠️ Necesitas crear registros de InventarioPrenda para esta orden\n";
|
||||
echo " Deberías ir a la sección de recepciones/inventario y registrar\n";
|
||||
echo " las {$op->cantidad} prendas producidas\n";
|
||||
} else {
|
||||
echo "Detalles de inventarios:\n";
|
||||
$totalTerminada = 0;
|
||||
$totalDisponible = 0;
|
||||
|
||||
foreach ($inventarios as $inv) {
|
||||
echo "---\n";
|
||||
echo "ID: {$inv->id}\n";
|
||||
echo "Cantidad terminada: {$inv->cantidad_terminada}\n";
|
||||
echo "Cantidad disponible: {$inv->cantidad_disponible}\n";
|
||||
echo "Estado: {$inv->estado}\n";
|
||||
echo "Producto ID: {$inv->producto_id}\n";
|
||||
echo "Fecha ingreso: {$inv->fecha_ingreso}\n";
|
||||
|
||||
$totalTerminada += $inv->cantidad_terminada;
|
||||
$totalDisponible += $inv->cantidad_disponible;
|
||||
}
|
||||
|
||||
echo "\n📊 Resumen:\n";
|
||||
echo " Total terminada: {$totalTerminada} unidades\n";
|
||||
echo " Total disponible: {$totalDisponible} unidades\n";
|
||||
|
||||
if ($totalDisponible > 0) {
|
||||
echo "\n✅ Hay inventario suficiente para registrar cobros\n";
|
||||
} else {
|
||||
echo "\n❌ No hay inventario con cantidad_disponible > 0\n";
|
||||
echo " Todas las prendas ya han sido cobradas/distribuidas\n";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
$app = require_once __DIR__ . '/../bootstrap/app.php';
|
||||
$app->make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
|
||||
echo "=== Sincronización de Inventarios desde Recepciones ===\n\n";
|
||||
|
||||
// Buscar todas las confecciones que tienen recepciones pero cuya OP no tiene inventario
|
||||
$confecciones = \App\Models\Confeccion::whereNotNull('orden_produccion_id')
|
||||
->whereHas('recepciones')
|
||||
->with(['ordenProduccion', 'recepciones'])
|
||||
->get();
|
||||
|
||||
echo "Total confecciones con recepciones: {$confecciones->count()}\n\n";
|
||||
|
||||
$creados = 0;
|
||||
$actualizados = 0;
|
||||
$sinCambios = 0;
|
||||
|
||||
foreach ($confecciones as $confeccion) {
|
||||
$op_id = $confeccion->orden_produccion_id;
|
||||
$op = $confeccion->ordenProduccion;
|
||||
|
||||
if (!$op) {
|
||||
echo "⚠️ Confección #{$confeccion->id} tiene orden_produccion_id={$op_id} pero la OP no existe\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sumar recepciones efectivas (cantidad - defectuosas)
|
||||
$totalRecibido = $confeccion->recepciones->sum(function($rec) {
|
||||
return $rec->cantidad - ($rec->prendas_defectuosas ?? 0);
|
||||
});
|
||||
|
||||
if ($totalRecibido <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Buscar o crear inventario
|
||||
$inventario = \App\Models\InventarioPrenda::where('orden_produccion_id', $op_id)->first();
|
||||
|
||||
if (!$inventario) {
|
||||
// Crear inventario nuevo
|
||||
$inventario = \App\Models\InventarioPrenda::create([
|
||||
'orden_produccion_id' => $op_id,
|
||||
'cantidad_terminada' => $totalRecibido,
|
||||
'cantidad_disponible' => $totalRecibido,
|
||||
'fecha_ingreso' => $confeccion->recepciones->first()->fecha_recepcion ?? now(),
|
||||
'estado' => 'en_bodega',
|
||||
]);
|
||||
|
||||
echo "✅ Creado inventario para OP #{$op_id} con {$totalRecibido} prendas\n";
|
||||
echo " → Confección #{$confeccion->id}\n";
|
||||
$creados++;
|
||||
} else {
|
||||
// Verificar si necesita actualización
|
||||
if ($inventario->cantidad_terminada < $totalRecibido) {
|
||||
$diferencia = $totalRecibido - $inventario->cantidad_terminada;
|
||||
$inventario->cantidad_terminada = $totalRecibido;
|
||||
$inventario->cantidad_disponible += $diferencia;
|
||||
$inventario->save();
|
||||
|
||||
echo "✅ Actualizado inventario para OP #{$op_id}: +{$diferencia} prendas (total: {$totalRecibido})\n";
|
||||
$actualizados++;
|
||||
} else {
|
||||
$sinCambios++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo "\n📊 Resumen:\n";
|
||||
echo " Inventarios creados: {$creados}\n";
|
||||
echo " Inventarios actualizados: {$actualizados}\n";
|
||||
echo " Sin cambios: {$sinCambios}\n";
|
||||
Reference in New Issue
Block a user