'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); } }