6de9c615f7
'PS' was baked in — wrong for multi-tenant. Now:
1. Honor $tenant->settings['protocol_prefix'] if set
2. Else use uppercase first 2 chars of tenant slug
('psauto' → 'PS', 'autoplus' → 'AP', 'plusrepair' → 'PL')
3. Fallback 'PR' if no tenant resolvable
Format changed from 'PS-{companyId}-{year}-{seq}' to '{PREFIX}-{year}-{seq}'
— dropped the redundant companyId since prefix already identifies the
tenant contextually.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
131 lines
4.0 KiB
PHP
131 lines
4.0 KiB
PHP
<?php
|
||
|
||
namespace App\Models\Tenant;
|
||
|
||
use App\Models\Concerns\BelongsToTenant;
|
||
use App\Tenancy\TenantManager;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||
|
||
class InjectorProtocol extends Model
|
||
{
|
||
use BelongsToTenant;
|
||
|
||
public const SOURCE_TYPES = [
|
||
'client' => 'Клиент',
|
||
'service_partner' => 'Автосервис',
|
||
];
|
||
|
||
protected $fillable = [
|
||
'company_id', 'protocol_number',
|
||
'client_id', 'vehicle_id', 'work_order_id',
|
||
'source_type', 'source_name', 'phone',
|
||
'car_model', 'plate_number', 'vin', 'mileage', 'year',
|
||
'injector_brand', 'injector_count',
|
||
'reason_new_injectors', 'reason_engine_overhaul', 'reason_check',
|
||
'conclusion_ok', 'conclusion_needs_cleaning', 'conclusion_needs_replacement',
|
||
'master_comment', 'master_id', 'master_name_signed',
|
||
'issue_date', 'client_acknowledged',
|
||
];
|
||
|
||
protected $casts = [
|
||
'reason_new_injectors' => 'boolean',
|
||
'reason_engine_overhaul' => 'boolean',
|
||
'reason_check' => 'boolean',
|
||
'conclusion_ok' => 'boolean',
|
||
'conclusion_needs_cleaning' => 'boolean',
|
||
'conclusion_needs_replacement' => 'boolean',
|
||
'client_acknowledged' => 'boolean',
|
||
'issue_date' => 'date',
|
||
'mileage' => 'integer',
|
||
'year' => 'integer',
|
||
'injector_count' => 'integer',
|
||
];
|
||
|
||
public function client(): BelongsTo
|
||
{
|
||
return $this->belongsTo(Client::class);
|
||
}
|
||
|
||
public function vehicle(): BelongsTo
|
||
{
|
||
return $this->belongsTo(Vehicle::class);
|
||
}
|
||
|
||
public function workOrder(): BelongsTo
|
||
{
|
||
return $this->belongsTo(WorkOrder::class);
|
||
}
|
||
|
||
public function master(): BelongsTo
|
||
{
|
||
return $this->belongsTo(User::class, 'master_id');
|
||
}
|
||
|
||
public function rows(): HasMany
|
||
{
|
||
return $this->hasMany(InjectorProtocolRow::class)->orderBy('position');
|
||
}
|
||
|
||
protected static function booted(): void
|
||
{
|
||
static::creating(function (InjectorProtocol $p) {
|
||
$p->protocol_number ??= static::generateNumber();
|
||
});
|
||
|
||
static::created(function (InjectorProtocol $p) {
|
||
// Auto-seed empty rows for each injector position (1..N)
|
||
$count = max(1, min(8, (int) $p->injector_count));
|
||
for ($i = 1; $i <= $count; $i++) {
|
||
$p->rows()->create([
|
||
'company_id' => $p->company_id,
|
||
'position' => $i,
|
||
]);
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* {PREFIX}-{YYYY}-{seq6} — per-tenant, per-year sequence.
|
||
*
|
||
* PREFIX is derived from the tenant (settings.protocol_prefix override,
|
||
* else uppercase of the first 2–3 letters of the tenant slug —
|
||
* 'psauto' → 'PS', 'autoplus' → 'AP', etc.). Falls back to 'PR' when
|
||
* no tenant is resolvable.
|
||
*/
|
||
public static function generateNumber(): string
|
||
{
|
||
$tenant = app(TenantManager::class)->current();
|
||
$companyId = $tenant?->id
|
||
?? auth()->user()?->company_id
|
||
?? 0;
|
||
$year = now()->year;
|
||
$seq = static::withoutGlobalScopes()
|
||
->where('company_id', $companyId)
|
||
->whereYear('created_at', $year)
|
||
->count() + 1;
|
||
|
||
$prefix = self::resolvePrefix($tenant);
|
||
|
||
return sprintf('%s-%d-%06d', $prefix, $year, $seq);
|
||
}
|
||
|
||
/** Explicit tenant setting → slug initials → 'PR' fallback. */
|
||
protected static function resolvePrefix($tenant): string
|
||
{
|
||
if ($tenant) {
|
||
$explicit = trim((string) data_get($tenant->settings ?? [], 'protocol_prefix'));
|
||
if ($explicit !== '') {
|
||
return mb_strtoupper($explicit);
|
||
}
|
||
$slug = (string) ($tenant->slug ?? '');
|
||
if ($slug !== '') {
|
||
// Take first 2 characters of the slug — 'psauto' → 'PS'
|
||
return mb_strtoupper(mb_substr($slug, 0, 2));
|
||
}
|
||
}
|
||
return 'PR';
|
||
}
|
||
}
|