'array', 'use_test_env' => 'boolean', ]; } /** * Store the gateway settings as JSON. * * Writing the column by hand takes precedence over the array cast, so an * empty value is encoded and stored rather than skipped. * * @param mixed $value */ public function setSettingsAttribute($value) { $encoded = json_encode($value); $this->attributes['settings'] = $encoded; } /* |-------------------------------------------------------------------------- | Relationships |-------------------------------------------------------------------------- */ /** * Receipts taken this way. */ public function payments(): HasMany { return $this->hasMany(Payment::class, 'payment_method_id'); } /** * Expenses settled this way. */ public function expenses(): HasMany { return $this->hasMany(Expense::class, 'payment_method_id'); } /** * Company the method was created under. */ public function company(): BelongsTo { return $this->belongsTo(Company::class, 'company_id'); } /* |-------------------------------------------------------------------------- | Query scopes |-------------------------------------------------------------------------- */ /** * Run every listed filter that carries a value. * * Order is load-bearing: the method-id filter contributes an OR, which * makes anything queued before it part of that alternative. Note that the * company filter ignores the id it is handed and narrows to the company on * the current request instead. */ public function scopeApplyFilters($query, array $filters) { $clauses = [ 'method_id' => fn ($wanted) => $query->wherePaymentMethod($wanted), 'company_id' => fn ($wanted) => $query->whereCompany($wanted), 'search' => fn ($wanted) => $query->whereSearch($wanted), ]; foreach ($clauses as $filter => $clause) { $wanted = $filters[$filter] ?? null; if ($wanted) { $clause($wanted); } } } /** * Narrow to one company. */ public function scopeWhereCompanyId($query, $id) { $query->where('company_id', '=', $id); } /** * Narrow to the company the current request is acting on. */ public function scopeWhereCompany($query) { $company = request()->header('company'); $query->where('company_id', '=', $company); } /** * Widen a listing to also take in one specific method. */ public function scopeWherePaymentMethod($query, $payment_id) { $query->orWhere('id', $payment_id); } /** * Partial match on the method's name. */ public function scopeWhereSearch($query, $search) { $needle = '%'.$search.'%'; $query->where('name', 'LIKE', $needle); } /** * Return the whole result set for the sentinel limit "all", otherwise a * page of the requested size. */ public function scopePaginateData($query, $limit) { return $limit == 'all' ? $query->get() : $query->paginate($limit); } /** * Retrieve the settings array for a payment method by its ID. */ public static function getSettings(int $id): mixed { $method = self::find($id); return $method->settings; } }