mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-09-05 23:01:07 +00:00
113 lines
3.1 KiB
PHP
113 lines
3.1 KiB
PHP
<?php
|
|
|
|
namespace App\Domains\Catalog\Models;
|
|
|
|
use App\Domains\Accounts\Models\Company;
|
|
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
/**
|
|
* A measure a company sells by: "hour", "kg", "licence".
|
|
*
|
|
* Units are a small per-company lookup list -- a name, and nothing else of
|
|
* substance. The name is unique inside the company, and a unit stays
|
|
* un-deletable for as long as an item points at it.
|
|
*/
|
|
class Unit extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $table = 'units';
|
|
|
|
/**
|
|
* The company is mass-assignable because callers stamp it from the
|
|
* request context; it is never read off the submitted payload.
|
|
*/
|
|
protected $fillable = [
|
|
'name',
|
|
'company_id',
|
|
];
|
|
|
|
public function company(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Company::class, 'company_id', 'id');
|
|
}
|
|
|
|
/**
|
|
* Items measured in this unit. A non-empty set pins the unit: deletion is
|
|
* refused while any of them remain.
|
|
*/
|
|
public function items(): HasMany
|
|
{
|
|
return $this->hasMany(Item::class, 'unit_id', 'id');
|
|
}
|
|
|
|
/**
|
|
* Turn the listing's query string into query conditions.
|
|
*
|
|
* A `company_id` entry merely switches the company scope on -- the value
|
|
* submitted with it is discarded, because the scope reads the company
|
|
* from the request header instead.
|
|
*/
|
|
public function scopeApplyFilters(Builder $query, array $filters): Builder
|
|
{
|
|
$filters = collect($filters);
|
|
|
|
if ($search = $filters->get('search')) {
|
|
$query->whereSearch($search);
|
|
}
|
|
|
|
if ($unitId = $filters->get('unit_id')) {
|
|
$query->whereUnit($unitId);
|
|
}
|
|
|
|
if ($filters->get('company_id')) {
|
|
$query->whereCompany();
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
/**
|
|
* Restrict to the company the request is acting in; callers get no say in
|
|
* which company that is.
|
|
*/
|
|
public function scopeWhereCompany(Builder $query): void
|
|
{
|
|
$company = request()->header('company');
|
|
|
|
$query->where('company_id', $company);
|
|
}
|
|
|
|
/**
|
|
* Pull one specific unit into the result set. It is an OR clause, so it
|
|
* adds to whatever the query already matched rather than narrowing it.
|
|
*/
|
|
public function scopeWhereUnit(Builder $query, int $unit_id): void
|
|
{
|
|
$query->orWhere('id', '=', $unit_id);
|
|
}
|
|
|
|
public function scopeWhereSearch(Builder $query, string $search): Builder
|
|
{
|
|
$pattern = '%'.$search.'%';
|
|
|
|
return $query->where('name', 'LIKE', $pattern);
|
|
}
|
|
|
|
/**
|
|
* `limit=all` opts out of pagination and hands back the collection.
|
|
*
|
|
* @return LengthAwarePaginator|Collection
|
|
*/
|
|
public function scopePaginateData(Builder $query, string $limit)
|
|
{
|
|
return $limit === 'all' ? $query->get() : $query->paginate($limit);
|
|
}
|
|
}
|