Car-Repairs-Shop/app/Models/StockMovement.php
sackey e839d40a99
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Initial commit
2025-07-30 17:15:50 +00:00

130 lines
3.9 KiB
PHP

<?php
namespace App\Models;
use App\Models\PartHistory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class StockMovement extends Model
{
use HasFactory;
protected $fillable = [
'part_id',
'supplier_id',
'purchase_order_id',
'service_order_id',
'movement_type',
'quantity',
'type', // Add this for compatibility
'reference_type',
'reference_id',
'unit_cost',
'total_cost',
'notes',
'created_by',
'user_id', // Add this for compatibility
];
protected $casts = [
'quantity' => 'integer',
'unit_cost' => 'decimal:2',
'total_cost' => 'decimal:2',
];
protected static function boot()
{
parent::boot();
static::created(function ($stockMovement) {
$part = $stockMovement->part;
// Get the quantity before this movement
$quantityBefore = $part->quantity_on_hand;
// Calculate quantity after based on movement type
$quantityChange = $stockMovement->movement_type === 'in' ?
$stockMovement->quantity : -$stockMovement->quantity;
$quantityAfter = $quantityBefore + $quantityChange;
// Log the stock movement in part history
PartHistory::logEvent(
$stockMovement->part_id,
$stockMovement->movement_type === 'in' ? PartHistory::EVENT_STOCK_IN :
($stockMovement->movement_type === 'out' ? PartHistory::EVENT_STOCK_OUT : PartHistory::EVENT_ADJUSTMENT),
[
'quantity_change' => $quantityChange,
'quantity_before' => $quantityBefore,
'quantity_after' => $quantityAfter,
'reference_type' => $stockMovement->reference_type,
'reference_id' => $stockMovement->reference_id,
'notes' => $stockMovement->notes ?? "Stock {$stockMovement->movement_type}",
]
);
});
}
// Handle both user_id and created_by for compatibility
public function setUserIdAttribute($value)
{
$this->attributes['created_by'] = $value;
}
const TYPE_IN = 'in';
const TYPE_OUT = 'out';
const TYPE_ADJUSTMENT = 'adjustment';
const TYPE_TRANSFER = 'transfer';
const TYPE_RETURN = 'return';
const REFERENCE_PURCHASE = 'purchase';
const REFERENCE_SALE = 'sale';
const REFERENCE_ADJUSTMENT = 'adjustment';
const REFERENCE_TRANSFER = 'transfer';
const REFERENCE_RETURN = 'return';
public function part(): BelongsTo
{
return $this->belongsTo(Part::class);
}
public function supplier(): BelongsTo
{
return $this->belongsTo(Supplier::class);
}
public function purchaseOrder(): BelongsTo
{
return $this->belongsTo(PurchaseOrder::class);
}
public function serviceOrder(): BelongsTo
{
return $this->belongsTo(ServiceOrder::class);
}
public function createdBy(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
public function getMovementTypeColorAttribute(): string
{
return match($this->movement_type) {
self::TYPE_IN => 'text-green-600 dark:text-green-400',
self::TYPE_OUT => 'text-red-600 dark:text-red-400',
self::TYPE_ADJUSTMENT => 'text-blue-600 dark:text-blue-400',
self::TYPE_TRANSFER => 'text-purple-600 dark:text-purple-400',
self::TYPE_RETURN => 'text-orange-600 dark:text-orange-400',
default => 'text-gray-600 dark:text-gray-400',
};
}
public function getFormattedQuantityAttribute(): string
{
$prefix = $this->movement_type === self::TYPE_IN ? '+' : '-';
return $prefix . number_format($this->quantity);
}
}