62aa55f033
- app/Models/SupplierProject.php — fillable + casts (jsonb arrays + datetime) + scopes: active() (inactive_since IS NULL), staleSince(N days), forSignal(signal_type, unique_key) - database/factories/SupplierProjectFactory.php — корректно учитывает chk_supplier_projects_b1_not_for_sms (B1 не порождает SMS-проекты) - tests/Feature/Models/SupplierProjectTest.php — 6 тестов: factory, array casts (workdays + regions), scopeActive, scopeStaleSince, scopeForSignal (3 платформы на один домен — UNIQUE (platform,unique_key)) ide-helper:models -W -M -N перегенерил docblocks для 4 существующих моделей (SaasAdminAuditLog, SystemSetting, UserRecoveryCode, ImpersonationToken) — синхронизировал @property после schema v8.16. Pest: 451 / 449 passed / 2 skipped (было 443+6 новых от Task 6 = 449). Larastan: 0 errors. Pint: passed. Spec: §2.2 Plan: Task 6 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
89 lines
2.5 KiB
PHP
89 lines
2.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Models;
|
|
|
|
use Database\Factories\SupplierProjectFactory;
|
|
use Illuminate\Database\Eloquent\Builder;
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
|
|
/**
|
|
* Supplier-уровневый агрегат проекта у поставщика crm.bp-gr.ru.
|
|
*
|
|
* Sharing-model: один supplier_project разделяется между несколькими Лидерра-tenant'ами
|
|
* (см. spec §2.2). НЕ tenant-scoped — RLS НЕ применяется.
|
|
*
|
|
* Уникальность: (platform, unique_key). Для site/call: unique_key = домен/номер.
|
|
* Для sms: B2 ключ — sender+keyword (конкатенация), B3 — только sender.
|
|
*
|
|
* Spec: docs/superpowers/specs/2026-05-10-supplier-integration-design.md §2.2
|
|
*
|
|
* @mixin IdeHelperSupplierProject
|
|
*/
|
|
class SupplierProject extends Model
|
|
{
|
|
/** @use HasFactory<SupplierProjectFactory> */
|
|
use HasFactory;
|
|
|
|
protected $table = 'supplier_projects';
|
|
|
|
protected $fillable = [
|
|
'platform',
|
|
'signal_type',
|
|
'unique_key',
|
|
'supplier_external_id',
|
|
'current_limit',
|
|
'current_workdays',
|
|
'current_regions',
|
|
'sync_status',
|
|
'last_synced_at',
|
|
'inactive_since',
|
|
];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'current_workdays' => 'array',
|
|
'current_regions' => 'array',
|
|
'current_limit' => 'integer',
|
|
'last_synced_at' => 'datetime',
|
|
'inactive_since' => 'datetime',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param Builder<SupplierProject> $query
|
|
* @return Builder<SupplierProject>
|
|
*/
|
|
public function scopeActive(Builder $query): Builder
|
|
{
|
|
return $query->whereNull('inactive_since');
|
|
}
|
|
|
|
/**
|
|
* @param Builder<SupplierProject> $query
|
|
* @return Builder<SupplierProject>
|
|
*/
|
|
public function scopeStaleSince(Builder $query, int $days): Builder
|
|
{
|
|
return $query->whereNotNull('inactive_since')
|
|
->where('inactive_since', '<=', now()->subDays($days));
|
|
}
|
|
|
|
/**
|
|
* @param Builder<SupplierProject> $query
|
|
* @return Builder<SupplierProject>
|
|
*/
|
|
public function scopeForSignal(Builder $query, string $signalType, string $uniqueKey): Builder
|
|
{
|
|
return $query->where('signal_type', $signalType)->where('unique_key', $uniqueKey);
|
|
}
|
|
|
|
protected static function newFactory(): SupplierProjectFactory
|
|
{
|
|
return SupplierProjectFactory::new();
|
|
}
|
|
}
|