- Star (is_starred) and colored tags for services, customers, orders, invoices:
Markable trait, tags/taggables tables, PATCH administrator/marks/{type}/{key},
tag CRUD, list filters starred / tag_ids[]
- GET administrator/services accepts product_type (falls back to product type
for legacy rows without services.type)
- Mail campaigns: bulk cancel / retry failed / delete; cancelled campaigns are
skipped by SendMailCampaignRecipient
- POST administrator/settings/test-smtp sends a test email through the saved
mail transport
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
32 lines
976 B
PHP
32 lines
976 B
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Support;
|
|
|
|
use App\Models\Customer;
|
|
use App\Models\Invoice;
|
|
use App\Models\Order;
|
|
use App\Models\Service;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
final class Markables
|
|
{
|
|
/**
|
|
* @var array<string, array{model: class-string<Model>, key: string, permission: string}>
|
|
*/
|
|
public const TYPES = [
|
|
'services' => ['model' => Service::class, 'key' => 'id', 'permission' => 'customer.edit'],
|
|
'customers' => ['model' => Customer::class, 'key' => 'uuid', 'permission' => 'customer.edit'],
|
|
'orders' => ['model' => Order::class, 'key' => 'id', 'permission' => 'order.edit'],
|
|
'invoices' => ['model' => Invoice::class, 'key' => 'id', 'permission' => 'invoice.edit'],
|
|
];
|
|
|
|
public static function find(string $type, string $key): Model
|
|
{
|
|
$definition = self::TYPES[$type];
|
|
|
|
return $definition['model']::query()->where($definition['key'], $key)->firstOrFail();
|
|
}
|
|
}
|