'integer', 'supply_id' => 'integer', 'quantity' => 'integer', 'received_qty' => 'integer', 'unit_cost' => 'decimal:2', // adjust scale to match DB (e.g., decimal:4) 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; public function getFillable(): array { return $this->fillable; } /* ============================================================ * Relationships (optional but recommended) * ============================================================ */ public function purchaseOrder(): BelongsTo { return $this->belongsTo(PurchaseOrder::class, 'purchase_order_id'); } public function supply(): BelongsTo { return $this->belongsTo(Supply::class, 'supply_id'); } /* ============================================================ * Accessors (handy for totals / UI) * ============================================================ */ // total ordered cost public function getLineTotalAttribute(): float { $qty = (int) ($this->quantity ?? 0); $cost = (float) ($this->unit_cost ?? 0); return $qty * $cost; } // total received cost public function getReceivedLineTotalAttribute(): float { $qty = (int) ($this->received_qty ?? 0); $cost = (float) ($this->unit_cost ?? 0); return $qty * $cost; } /* ============================================================ * Validation rules (use in FormRequest or controller) * ============================================================ */ public static function rules(bool $updating = false): array { // if updating, you might allow partial updates (sometimes) // keep strict by default to match legacy behavior return [ 'purchase_order_id' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1', 'exists:purchase_orders,id'], 'supply_id' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1', 'exists:supplies,id'], 'description' => ['nullable', 'string', 'max:1000'], 'quantity' => [$updating ? 'sometimes' : 'required', 'integer', 'min:1'], 'received_qty' => ['nullable', 'integer', 'min:0', 'lte:quantity'], 'unit_cost' => [$updating ? 'sometimes' : 'required', 'numeric', 'min:0'], ]; } }