'integer', 'loyalty_discount_minor' => 'integer', 'loyalty_points_redeemed' => 'integer', 'loyalty_points_earned' => 'integer', 'tip_minor' => 'integer', 'total_minor' => 'integer', 'pay_order_id' => 'integer', 'crm_customer_id' => 'integer', 'covers' => 'integer', 'paid_at' => 'datetime', 'opened_at' => 'datetime', 'kitchen_sent_at' => 'datetime', 'closed_at' => 'datetime', ]; } public function location(): BelongsTo { return $this->belongsTo(PosLocation::class, 'location_id'); } public function table(): BelongsTo { return $this->belongsTo(PosTable::class, 'table_id'); } public function payments(): HasMany { return $this->hasMany(PosPayment::class); } public function paidMinor(): int { return (int) $this->payments()->where('status', PosPayment::STATUS_PAID)->sum('amount_minor'); } public function balanceMinor(): int { return max(0, (int) $this->total_minor - $this->paidMinor()); } public function isOpen(): bool { return $this->status === self::STATUS_PENDING; } public function isDineIn(): bool { return $this->order_type === self::ORDER_DINE_IN; } public function scopeOpenTickets(Builder $query): Builder { return $query->where('status', self::STATUS_PENDING); } public function lines(): HasMany { return $this->hasMany(PosSaleLine::class)->orderBy('position'); } public function isPaid(): bool { return $this->status === self::STATUS_PAID; } public function scopeOwned(Builder $query, string $ownerRef): Builder { return $query->where('owner_ref', $ownerRef); } }