Files
portal/app/app/Models/SupplierSyncLog.php
T
Дмитрий 084a952bfa feat(models): add SupplierSyncLog model + factory (audit trail для AJAX-sync)
- app/Models/SupplierSyncLog.php — fillable + casts (jsonb arrays + datetime)
  + supplierProject() BelongsTo relation (nullable, ON DELETE SET NULL —
    лог переживает удаление supplier-проекта для audit-trail).
  $timestamps = false (только created_at, без updated_at — append-only)
- database/factories/SupplierSyncLogFactory.php — реалистичные действия из enum
- tests/Feature/Models/SupplierSyncLogTest.php — 4 теста: factory,
  supplier_project relation, jsonb array casts, nullable FK lifecycle

Pest: 463 / 461 passed / 2 skipped (457 + 4 новых = 461).
Larastan: 0 errors. Pint passed.

Spec: §4.3
Plan: Task 9

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 16:53:55 +03:00

67 lines
1.8 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Models;
use Database\Factories\SupplierSyncLogFactory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* SaaS-level append-only audit log AJAX-синхронизаций с поставщиком crm.bp-gr.ru.
*
* Используется для retry-логики, отладки rt-project-* AJAX-запросов и алертов
* менеджеру при failed sync. НЕ tenant-scoped — события агрегатные на уровне SaaS.
*
* supplier_project_id nullable: лог переживает удаление supplier-проекта
* (ON DELETE SET NULL) для аудит-trail.
*
* Spec: docs/superpowers/specs/2026-05-10-supplier-integration-design.md §4.3
*
* @mixin IdeHelperSupplierSyncLog
*/
class SupplierSyncLog extends Model
{
/** @use HasFactory<SupplierSyncLogFactory> */
use HasFactory;
public $timestamps = false;
protected $table = 'supplier_sync_log';
protected $fillable = [
'supplier_project_id',
'action',
'request_payload',
'response_body',
'http_status',
'error_message',
'duration_ms',
'created_at',
];
protected function casts(): array
{
return [
'request_payload' => 'array',
'response_body' => 'array',
'http_status' => 'integer',
'duration_ms' => 'integer',
'created_at' => 'datetime',
];
}
/** @return BelongsTo<SupplierProject, $this> */
public function supplierProject(): BelongsTo
{
return $this->belongsTo(SupplierProject::class);
}
protected static function newFactory(): SupplierSyncLogFactory
{
return SupplierSyncLogFactory::new();
}
}