Files

154 lines
4.1 KiB
PHP

<?php
namespace Modules\MaterialLogistics\Models;
use Modules\MasterData\Models\Material;
use Modules\MasterData\Models\MaterialGroup;
use App\Models\User;
use App\Traits\HasPublicIdentifier;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Modules\MaterialLogistics\Enums\MovementType;
use Modules\ProjectManagement\Models\Project;
use Modules\ProjectManagement\Models\Task;
class InventoryMovement extends Model
{
use HasPublicIdentifier;
protected $fillable = [
'material_id', 'warehouse_id', 'project_id', 'task_id', 'inventory_batch_id',
'movement_type', 'direction', 'quantity', 'balance_after',
'from_location_type', 'from_location_id',
'to_location_type', 'to_location_id',
'reference_type', 'reference_id',
'performed_by', 'notes',
'dispatched_by', 'received_by', 'returned_by', 'adjusted_by',
];
protected function casts(): array
{
return [
'movement_type' => MovementType::class,
'quantity' => 'decimal:2',
'balance_after' => 'decimal:2',
];
}
// --- Relationships ---
public function material(): BelongsTo
{
return $this->belongsTo(Material::class);
}
public function inventoryBatch(): BelongsTo
{
return $this->belongsTo(InventoryBatch::class);
}
public function warehouse(): BelongsTo
{
return $this->belongsTo(Warehouse::class);
}
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
public function task(): BelongsTo
{
return $this->belongsTo(Task::class);
}
public function performer(): BelongsTo
{
return $this->belongsTo(User::class, 'performed_by');
}
public function dispatcher(): BelongsTo
{
return $this->belongsTo(User::class, 'dispatched_by');
}
public function receiver(): BelongsTo
{
return $this->belongsTo(User::class, 'received_by');
}
public function returner(): BelongsTo
{
return $this->belongsTo(User::class, 'returned_by');
}
public function adjuster(): BelongsTo
{
return $this->belongsTo(User::class, 'adjusted_by');
}
public function reference(): MorphTo
{
return $this->morphTo();
}
// --- Scopes ---
public function scopeOfType($query, MovementType $type)
{
return $query->where('movement_type', $type);
}
public function scopeForMaterial($query, int $materialId)
{
return $query->where('material_id', $materialId);
}
public function scopeForWarehouse($query, int $warehouseId)
{
return $query->where('warehouse_id', $warehouseId);
}
public function scopeForProject($query, int $projectId)
{
return $query->where('project_id', $projectId);
}
public function scopeInDateRange($query, ?string $from, ?string $to)
{
if ($from) {
$query->where('created_at', '>=', $from);
}
if ($to) {
$query->where('created_at', '<=', $to . ' 23:59:59');
}
return $query;
}
// --- Helpers ---
public function getFromLabelAttribute(): string
{
return match ($this->from_location_type) {
'warehouse' => Warehouse::find($this->from_location_id)?->name ?? 'Warehouse',
'project' => Project::find($this->from_location_id)?->name ?? 'Project',
'task' => Task::find($this->from_location_id)?->name ?? 'Task',
'external' => 'External (Supplier)',
default => '-',
};
}
public function getToLabelAttribute(): string
{
return match ($this->to_location_type) {
'warehouse' => Warehouse::find($this->to_location_id)?->name ?? 'Warehouse',
'project' => Project::find($this->to_location_id)?->name ?? 'Project',
'task' => Task::find($this->to_location_id)?->name ?? 'Task',
'external' => 'External',
default => '-',
};
}
}