up
This commit is contained in:
@@ -138,6 +138,10 @@ class ConfeccionResource extends Resource
|
|||||||
|
|
||||||
TextColumn::make('cantidad_recibida'),
|
TextColumn::make('cantidad_recibida'),
|
||||||
|
|
||||||
|
TextColumn::make('faltantes')
|
||||||
|
->label('Faltan')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
BadgeColumn::make('estado')
|
BadgeColumn::make('estado')
|
||||||
->colors([
|
->colors([
|
||||||
'warning' => 'pendiente',
|
'warning' => 'pendiente',
|
||||||
@@ -165,7 +169,7 @@ class ConfeccionResource extends Resource
|
|||||||
public static function getRelations(): array
|
public static function getRelations(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
//
|
RelationManagers\RecepcionesRelationManager::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\ConfeccionResource\RelationManagers;
|
||||||
|
|
||||||
|
use Filament\Forms;
|
||||||
|
use Filament\Forms\Form;
|
||||||
|
use Filament\Resources\RelationManagers\RelationManager;
|
||||||
|
use Filament\Tables;
|
||||||
|
use Filament\Tables\Table;
|
||||||
|
use Filament\Tables\Columns\TextColumn;
|
||||||
|
use Filament\Forms\Components\DateTimePicker;
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Forms\Components\Textarea;
|
||||||
|
use Filament\Tables\Actions\DeleteAction;
|
||||||
|
use Filament\Tables\Actions\EditAction;
|
||||||
|
|
||||||
|
class RecepcionesRelationManager extends RelationManager
|
||||||
|
{
|
||||||
|
protected static string $relationship = 'recepciones';
|
||||||
|
protected static ?string $recordTitleAttribute = 'id';
|
||||||
|
|
||||||
|
public function form(Forms\Form $form): Forms\Form
|
||||||
|
{
|
||||||
|
return $form->schema([
|
||||||
|
DateTimePicker::make('fecha_recepcion')->required(),
|
||||||
|
TextInput::make('cantidad')->numeric()->required()->minValue(1),
|
||||||
|
Textarea::make('notas'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function table(Tables\Table $table): Tables\Table
|
||||||
|
{
|
||||||
|
return $table
|
||||||
|
->columns([
|
||||||
|
TextColumn::make('id')->label('#'),
|
||||||
|
TextColumn::make('fecha_recepcion')->dateTime()->label('Fecha'),
|
||||||
|
TextColumn::make('cantidad')->label('Cantidad'),
|
||||||
|
TextColumn::make('usuario.name')->label('Usuario'),
|
||||||
|
TextColumn::make('notas')->limit(50)->wrap(),
|
||||||
|
TextColumn::make('created_at')->dateTime()->label('Creado'),
|
||||||
|
])
|
||||||
|
->headerActions([])
|
||||||
|
->actions([
|
||||||
|
EditAction::make(),
|
||||||
|
DeleteAction::make(),
|
||||||
|
])
|
||||||
|
->bulkActions([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -124,6 +124,10 @@ class TintoreriaResource extends Resource
|
|||||||
|
|
||||||
TextColumn::make('cantidad_recibida'),
|
TextColumn::make('cantidad_recibida'),
|
||||||
|
|
||||||
|
TextColumn::make('faltantes')
|
||||||
|
->label('Faltan')
|
||||||
|
->sortable(),
|
||||||
|
|
||||||
TextColumn::make('perdidas')
|
TextColumn::make('perdidas')
|
||||||
->label('Pérdidas'),
|
->label('Pérdidas'),
|
||||||
|
|
||||||
@@ -146,7 +150,7 @@ class TintoreriaResource extends Resource
|
|||||||
public static function getRelations(): array
|
public static function getRelations(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
//
|
RelationManagers\RecepcionesRelationManager::class,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\TintoreriaResource\RelationManagers;
|
||||||
|
|
||||||
|
use Filament\Forms;
|
||||||
|
use Filament\Forms\Form;
|
||||||
|
use Filament\Resources\RelationManagers\RelationManager;
|
||||||
|
use Filament\Tables;
|
||||||
|
use Filament\Tables\Table;
|
||||||
|
use Filament\Tables\Columns\TextColumn;
|
||||||
|
use Filament\Forms\Components\DateTimePicker;
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Forms\Components\Textarea;
|
||||||
|
use Filament\Tables\Actions\DeleteAction;
|
||||||
|
use Filament\Tables\Actions\EditAction;
|
||||||
|
|
||||||
|
class RecepcionesRelationManager extends RelationManager
|
||||||
|
{
|
||||||
|
protected static string $relationship = 'recepciones';
|
||||||
|
protected static ?string $recordTitleAttribute = 'id';
|
||||||
|
|
||||||
|
public function form(Forms\Form $form): Forms\Form
|
||||||
|
{
|
||||||
|
return $form->schema([
|
||||||
|
DateTimePicker::make('fecha_recepcion')->required(),
|
||||||
|
TextInput::make('cantidad')->numeric()->required()->minValue(1),
|
||||||
|
Textarea::make('notas'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function table(Tables\Table $table): Tables\Table
|
||||||
|
{
|
||||||
|
return $table
|
||||||
|
->columns([
|
||||||
|
TextColumn::make('id')->label('#'),
|
||||||
|
TextColumn::make('fecha_recepcion')->dateTime()->label('Fecha'),
|
||||||
|
TextColumn::make('cantidad')->label('Cantidad'),
|
||||||
|
TextColumn::make('usuario.name')->label('Usuario'),
|
||||||
|
TextColumn::make('notas')->limit(50)->wrap(),
|
||||||
|
TextColumn::make('created_at')->dateTime()->label('Creado'),
|
||||||
|
])
|
||||||
|
->headerActions([])
|
||||||
|
->actions([
|
||||||
|
EditAction::make(),
|
||||||
|
DeleteAction::make(),
|
||||||
|
])
|
||||||
|
->bulkActions([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
+13
-25
@@ -64,35 +64,23 @@ class Confeccion extends Model
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Crear traslado cuando la confección tenga recepción (en creación y en actualización)
|
/* Recepciones polimórficas */
|
||||||
$createTrasladoFn = function ($confeccion) {
|
public function recepciones()
|
||||||
if ($confeccion->cantidad_recibida !== null) {
|
{
|
||||||
// Evitar duplicados
|
return $this->morphMany(\App\Models\Recepcion::class, 'referencia');
|
||||||
$exists = \App\Models\TrasladoPrenda::where('referencia_type', self::class)
|
|
||||||
->where('referencia_id', $confeccion->id)
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if (! $exists) {
|
|
||||||
$destino = 'tintoreria';
|
|
||||||
|
|
||||||
\App\Models\TrasladoPrenda::crearDesdeReferencia(
|
|
||||||
$confeccion,
|
|
||||||
'confeccion',
|
|
||||||
$destino
|
|
||||||
);
|
|
||||||
|
|
||||||
// Marcar el paso como terminado y avanzar la OP incluso si fue parcial
|
|
||||||
$confeccion->ordenProduccion?->avanzarEstado();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mantener el comportamiento anterior: si está completo, también avanzamos (por seguridad)
|
// 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') {
|
if ($confeccion->estado === 'completo') {
|
||||||
$confeccion->ordenProduccion?->avanzarEstado();
|
$confeccion->ordenProduccion?->avanzarEstado();
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
static::updated($createTrasladoFn);
|
|
||||||
static::saved($createTrasladoFn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
|
class Recepcion extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'referencia_type',
|
||||||
|
'referencia_id',
|
||||||
|
'user_id',
|
||||||
|
'cantidad',
|
||||||
|
'fecha_recepcion',
|
||||||
|
'notas',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'fecha_recepcion' => 'datetime',
|
||||||
|
'cantidad' => 'integer',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function referencia()
|
||||||
|
{
|
||||||
|
return $this->morphTo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function usuario()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'user_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function booted()
|
||||||
|
{
|
||||||
|
static::creating(function ($rec) {
|
||||||
|
// Cantidad debe ser entero >= 1
|
||||||
|
$rec->cantidad = (int) $rec->cantidad;
|
||||||
|
if ($rec->cantidad <= 0) {
|
||||||
|
throw ValidationException::withMessages(['cantidad' => 'La cantidad debe ser un entero mayor que 0.']);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fecha por defecto
|
||||||
|
if (! $rec->fecha_recepcion) {
|
||||||
|
$rec->fecha_recepcion = now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validación: no permitir sobrepasar la cantidad enviada en la referencia
|
||||||
|
if ($rec->referencia) {
|
||||||
|
$referencia = $rec->referencia;
|
||||||
|
$enviada = (int) ($referencia->cantidad_enviada ?? 0);
|
||||||
|
$yaRecibido = (int) \\App\\Models\\Recepcion::where('referencia_type', get_class($referencia))
|
||||||
|
->where('referencia_id', $referencia->id)
|
||||||
|
->sum('cantidad');
|
||||||
|
|
||||||
|
if (($yaRecibido + $rec->cantidad) > $enviada) {
|
||||||
|
throw ValidationException::withMessages(['cantidad' => "La recepción excede la cantidad pendiente (faltan: " . max(0, $enviada - $yaRecibido) . ")."]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set user if available
|
||||||
|
if (! $rec->user_id && auth()->check()) {
|
||||||
|
$rec->user_id = auth()->id();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static::created(function ($rec) {
|
||||||
|
$rec->syncParentAggregates();
|
||||||
|
|
||||||
|
// Crear un traslado parcial desde la referencia usando esta recepción
|
||||||
|
if ($rec->referencia) {
|
||||||
|
$referencia = $rec->referencia;
|
||||||
|
$payload = [
|
||||||
|
'cantidad_enviada' => $rec->cantidad,
|
||||||
|
'cantidad_recibida' => $rec->cantidad,
|
||||||
|
'fecha_recepcion' => $rec->fecha_recepcion,
|
||||||
|
'notas' => 'Creado desde recepción #' . $rec->id . ($rec->notas ? (" - " . $rec->notas) : ''),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Map destino según tipo de referencia
|
||||||
|
if ($referencia instanceof Confeccion) {
|
||||||
|
$origen = 'confeccion';
|
||||||
|
$destino = 'tintoreria';
|
||||||
|
} elseif ($referencia instanceof Tintoreria) {
|
||||||
|
$origen = 'tintoreria';
|
||||||
|
$destino = 'acabados';
|
||||||
|
} else {
|
||||||
|
$origen = 'referencia';
|
||||||
|
$destino = 'bodega';
|
||||||
|
}
|
||||||
|
|
||||||
|
\App\Models\TrasladoPrenda::crearDesdeReferencia($referencia, $origen, $destino, $payload);
|
||||||
|
|
||||||
|
// Avanzar OP por seguridad
|
||||||
|
$referencia->ordenProduccion?->avanzarEstado();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
static::updated(function ($rec) {
|
||||||
|
$rec->syncParentAggregates();
|
||||||
|
});
|
||||||
|
|
||||||
|
static::deleted(function ($rec) {
|
||||||
|
$rec->syncParentAggregates();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function syncParentAggregates()
|
||||||
|
{
|
||||||
|
if (! $this->referencia) return;
|
||||||
|
$referencia = $this->referencia;
|
||||||
|
$sum = (int) static::where('referencia_type', get_class($referencia))
|
||||||
|
->where('referencia_id', $referencia->id)
|
||||||
|
->sum('cantidad');
|
||||||
|
|
||||||
|
$referencia->cantidad_recibida = $sum;
|
||||||
|
$referencia->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
+14
-33
@@ -55,42 +55,23 @@ class Tintoreria extends Model
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$createTrasladoFn = function ($tintoreria) {
|
/* Recepciones polimórficas */
|
||||||
if ($tintoreria->cantidad_recibida !== null) {
|
public function recepciones()
|
||||||
// Evitar duplicados
|
{
|
||||||
$exists = \App\Models\TrasladoPrenda::where('referencia_type', self::class)
|
return $this->morphMany(\App\Models\Recepcion::class, 'referencia');
|
||||||
->where('referencia_id', $tintoreria->id)
|
}
|
||||||
->exists();
|
|
||||||
|
|
||||||
if (! $exists) {
|
// Cuantas faltan por recibir
|
||||||
// Mapear "perdidas" a prendas_defectuosas en el traslado
|
public function getFaltantesAttribute()
|
||||||
$payload = [
|
{
|
||||||
'prendas_defectuosas' => $tintoreria->perdidas ?? 0,
|
return max(0, (int)($this->cantidad_enviada ?? 0) - (int)($this->cantidad_recibida ?? 0));
|
||||||
];
|
}
|
||||||
|
|
||||||
$destino = 'acabados';
|
// Avanzar OP al cerrar el paso o cuando se complete
|
||||||
|
static::saved(function ($tintoreria) {
|
||||||
\App\Models\TrasladoPrenda::crearDesdeReferencia(
|
if ($tintoreria->fecha_recepcion && $tintoreria->cantidad_recibida !== null) {
|
||||||
$tintoreria,
|
|
||||||
'tintoreria',
|
|
||||||
$destino,
|
|
||||||
$payload
|
|
||||||
);
|
|
||||||
|
|
||||||
// Avanzar la OP al cerrar el paso
|
|
||||||
$tintoreria->ordenProduccion?->avanzarEstado();
|
$tintoreria->ordenProduccion?->avanzarEstado();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
if (
|
|
||||||
$tintoreria->fecha_recepcion &&
|
|
||||||
$tintoreria->cantidad_recibida !== null
|
|
||||||
) {
|
|
||||||
$tintoreria->ordenProduccion?->avanzarEstado();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static::updated($createTrasladoFn);
|
|
||||||
static::saved($createTrasladoFn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('recepciones', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('referencia_type');
|
||||||
|
$table->unsignedBigInteger('referencia_id');
|
||||||
|
$table->unsignedBigInteger('user_id')->nullable();
|
||||||
|
$table->integer('cantidad')->unsigned();
|
||||||
|
$table->dateTime('fecha_recepcion')->nullable();
|
||||||
|
$table->text('notas')->nullable();
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(['referencia_type', 'referencia_id']);
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onDelete('set null');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('recepciones');
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -4,26 +4,51 @@ $op = \App\Models\OrdenProduccion::find($opId);
|
|||||||
$events = [];
|
$events = [];
|
||||||
|
|
||||||
if ($op) {
|
if ($op) {
|
||||||
$confecciones = $op->confeccions()->orderBy('fecha_recepcion')->get();
|
$confecciones = $op->confeccions()->get();
|
||||||
foreach ($confecciones as $c) {
|
foreach ($confecciones as $c) {
|
||||||
|
// Evento principal de la confección (creación/envío)
|
||||||
$events[] = [
|
$events[] = [
|
||||||
'tipo' => 'Confección',
|
'tipo' => 'Confección',
|
||||||
'id' => $c->id,
|
'id' => $c->id,
|
||||||
'fecha' => $c->fecha_recepcion ?? $c->created_at,
|
'fecha' => $c->fecha_envio ?? $c->created_at,
|
||||||
'detalle' => "Enviado: {$c->cantidad_enviada} - Recibido: {$c->cantidad_recibida} - Defectos: {$c->prendas_defectuosas}",
|
'detalle' => "Enviado: {$c->cantidad_enviada} - Recibido total: {$c->cantidad_recibida} - Defectos: {$c->prendas_defectuosas}",
|
||||||
|
'link' => route('filament.admin.resources.confeccions.edit', ['record' => $c->id]),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Eventos por cada recepción
|
||||||
|
$recepciones = $c->recepciones()->orderBy('fecha_recepcion')->get();
|
||||||
|
foreach ($recepciones as $r) {
|
||||||
|
$events[] = [
|
||||||
|
'tipo' => 'Recepción (Confección)',
|
||||||
|
'id' => $r->id,
|
||||||
|
'fecha' => $r->fecha_recepcion ?? $r->created_at,
|
||||||
|
'detalle' => "Recibido: {$r->cantidad} - Notas: " . ($r->notas ?? '—'),
|
||||||
'link' => route('filament.admin.resources.confeccions.edit', ['record' => $c->id]),
|
'link' => route('filament.admin.resources.confeccions.edit', ['record' => $c->id]),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$tints = $op->tintorerias()->orderBy('fecha_recepcion')->get();
|
$tints = $op->tintorerias()->get();
|
||||||
foreach ($tints as $t) {
|
foreach ($tints as $t) {
|
||||||
$events[] = [
|
$events[] = [
|
||||||
'tipo' => 'Tintorería',
|
'tipo' => 'Tintorería',
|
||||||
'id' => $t->id,
|
'id' => $t->id,
|
||||||
'fecha' => $t->fecha_recepcion ?? $t->created_at,
|
'fecha' => $t->fecha_envio ?? $t->created_at,
|
||||||
'detalle' => "Enviado: {$t->cantidad_enviada} - Recibido: {$t->cantidad_recibida} - Perdidas: {$t->perdidas}",
|
'detalle' => "Enviado: {$t->cantidad_enviada} - Recibido total: {$t->cantidad_recibida} - Perdidas: {$t->perdidas}",
|
||||||
'link' => route('filament.admin.resources.tintorerias.edit', ['record' => $t->id]),
|
'link' => route('filament.admin.resources.tintorerias.edit', ['record' => $t->id]),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Eventos por cada recepción
|
||||||
|
$recepciones = $t->recepciones()->orderBy('fecha_recepcion')->get();
|
||||||
|
foreach ($recepciones as $r) {
|
||||||
|
$events[] = [
|
||||||
|
'tipo' => 'Recepción (Tintorería)',
|
||||||
|
'id' => $r->id,
|
||||||
|
'fecha' => $r->fecha_recepcion ?? $r->created_at,
|
||||||
|
'detalle' => "Recibido: {$r->cantidad} - Notas: " . ($r->notas ?? '—'),
|
||||||
|
'link' => route('filament.admin.resources.tintorerias.edit', ['record' => $t->id]),
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$acabados = $op->procesosAcabado()->orderBy('fecha_recepcion')->get();
|
$acabados = $op->procesosAcabado()->orderBy('fecha_recepcion')->get();
|
||||||
@@ -89,6 +114,11 @@ if ($op) {
|
|||||||
<p class="mb-4 text-base font-normal text-gray-500 dark:text-gray-300">{{ $e['detalle'] }}</p>
|
<p class="mb-4 text-base font-normal text-gray-500 dark:text-gray-300">{{ $e['detalle'] }}</p>
|
||||||
|
|
||||||
{{-- Acciones rápidas --}}
|
{{-- Acciones rápidas --}}
|
||||||
|
@if(in_array($e['tipo'], ['Confección','Tintorería']))
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<a href="{{ $e['link'] }}#recepciones" class="inline-flex items-center px-2 py-1 bg-blue-600 text-white rounded text-sm">Agregar recepción</a>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
@if($e['tipo'] === 'Traslado')
|
@if($e['tipo'] === 'Traslado')
|
||||||
@php $tr = \App\Models\TrasladoPrenda::find($e['id']); @endphp
|
@php $tr = \App\Models\TrasladoPrenda::find($e['id']); @endphp
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature;
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use App\Models\Confeccion;
|
||||||
|
use App\Models\OrdenProduccion;
|
||||||
|
use App\Models\Proveedor;
|
||||||
|
use App\Models\Recepcion;
|
||||||
|
use App\Models\TrasladoPrenda;
|
||||||
|
|
||||||
|
class RecepcionFlowTest extends TestCase
|
||||||
|
{
|
||||||
|
use RefreshDatabase;
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function it_allows_multiple_recepciones_and_updates_confeccion_and_traslados()
|
||||||
|
{
|
||||||
|
$proveedor = Proveedor::factory()->create(['categoria' => 'talleres']);
|
||||||
|
$op = OrdenProduccion::factory()->create(['cantidad_total' => 100]);
|
||||||
|
|
||||||
|
$conf = Confeccion::create([
|
||||||
|
'proveedor_id' => $proveedor->id,
|
||||||
|
'orden_produccion_id' => $op->id,
|
||||||
|
'cantidad_enviada' => 100,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Primera recepción 60
|
||||||
|
Recepcion::create([
|
||||||
|
'referencia_type' => Confeccion::class,
|
||||||
|
'referencia_id' => $conf->id,
|
||||||
|
'cantidad' => 60,
|
||||||
|
'fecha_recepcion' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$conf->refresh();
|
||||||
|
$this->assertEquals(60, $conf->cantidad_recibida);
|
||||||
|
$this->assertEquals('parcial', $conf->estado);
|
||||||
|
|
||||||
|
// Segunda recepción 40
|
||||||
|
Recepcion::create([
|
||||||
|
'referencia_type' => Confeccion::class,
|
||||||
|
'referencia_id' => $conf->id,
|
||||||
|
'cantidad' => 40,
|
||||||
|
'fecha_recepcion' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$conf->refresh();
|
||||||
|
$this->assertEquals(100, $conf->cantidad_recibida);
|
||||||
|
$this->assertEquals('completo', $conf->estado);
|
||||||
|
|
||||||
|
// Debería haber 2 traslados creados (uno por cada recepción)
|
||||||
|
$count = TrasladoPrenda::where('referencia_type', Confeccion::class)
|
||||||
|
->where('referencia_id', $conf->id)
|
||||||
|
->count();
|
||||||
|
|
||||||
|
$this->assertEquals(2, $count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @test */
|
||||||
|
public function it_prevents_recepcion_exceeding_cantidad_enviada()
|
||||||
|
{
|
||||||
|
$this->expectException(\Illuminate\Validation\ValidationException::class);
|
||||||
|
|
||||||
|
$proveedor = Proveedor::factory()->create(['categoria' => 'talleres']);
|
||||||
|
$op = OrdenProduccion::factory()->create(['cantidad_total' => 100]);
|
||||||
|
|
||||||
|
$conf = Confeccion::create([
|
||||||
|
'proveedor_id' => $proveedor->id,
|
||||||
|
'orden_produccion_id' => $op->id,
|
||||||
|
'cantidad_enviada' => 100,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Recepción primera 100
|
||||||
|
Recepcion::create([
|
||||||
|
'referencia_type' => Confeccion::class,
|
||||||
|
'referencia_id' => $conf->id,
|
||||||
|
'cantidad' => 100,
|
||||||
|
'fecha_recepcion' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Esta segunda debería fallar
|
||||||
|
Recepcion::create([
|
||||||
|
'referencia_type' => Confeccion::class,
|
||||||
|
'referencia_id' => $conf->id,
|
||||||
|
'cantidad' => 1,
|
||||||
|
'fecha_recepcion' => now(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user