Deploy Ladill POS / deploy (push) Successful in 31s
Send real receipt emails from the customer display and sale page, store branch promo content for the idle screen, and fold selected tips into totals.
142 lines
3.4 KiB
PHP
142 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
class PosSale extends Model
|
|
{
|
|
public const STATUS_PENDING = 'pending';
|
|
|
|
public const STATUS_PAID = 'paid';
|
|
|
|
public const STATUS_FAILED = 'failed';
|
|
|
|
public const STATUS_CANCELLED = 'cancelled';
|
|
|
|
public const METHOD_PAY = 'pay';
|
|
|
|
public const METHOD_CASH = 'cash';
|
|
|
|
public const ORDER_COUNTER = 'counter';
|
|
|
|
public const ORDER_DINE_IN = 'dine_in';
|
|
|
|
public const ORDER_TAKEAWAY = 'takeaway';
|
|
|
|
public const KITCHEN_NONE = 'none';
|
|
|
|
public const KITCHEN_ACTIVE = 'active';
|
|
|
|
public const KITCHEN_SERVED = 'served';
|
|
|
|
protected $fillable = [
|
|
'owner_ref',
|
|
'location_id',
|
|
'table_id',
|
|
'reference',
|
|
'external_ref',
|
|
'status',
|
|
'payment_method',
|
|
'order_type',
|
|
'kitchen_status',
|
|
'covers',
|
|
'notes',
|
|
'pay_order_id',
|
|
'payment_reference',
|
|
'customer_name',
|
|
'customer_email',
|
|
'customer_phone',
|
|
'crm_customer_id',
|
|
'subtotal_minor',
|
|
'loyalty_discount_minor',
|
|
'loyalty_points_redeemed',
|
|
'loyalty_points_earned',
|
|
'loyalty_external_ref',
|
|
'tip_minor',
|
|
'total_minor',
|
|
'currency',
|
|
'paid_at',
|
|
'opened_at',
|
|
'kitchen_sent_at',
|
|
'closed_at',
|
|
];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'subtotal_minor' => '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);
|
|
}
|
|
}
|