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