feat(projects): Plan 5 Task 3 — store + StoreProjectRequest + ProjectService::create

- StoreProjectRequest: 3-way conditional validation (site domain regex, call 7\d{10}, sms senders required)
- ProjectService::create(): max_projects limit check via Tenant.limits JSONB + dispatch SyncSupplierProjectJob
- ProjectController: constructor DI + store() method returning 201
- SyncSupplierProjectJob: stub (Task 4 полная реализация)
- POST /api/projects route inside auth:sanctum+tenant group (name projects.store)
- Migration add_limits_to_tenants: JSONB DEFAULT '{}' per-tenant limits column
- Tenant model: limits added to fillable + casts as array
- schema.sql/CHANGELOG: tenants.limits documented in v8.20
- phpstan-baseline: +8 actingAs entries for new test file
- Quirk: region_mode in request uses 'include'/'exclude' (schema CHECK) not 'all'/'whitelist' (plan spec typo)
- Quirk: Project::first() → Project::where('signal_identifier','x.ru')->latest()->first() (no RefreshDatabase, persistent test DB)
- 8/8 ProjectsStoreTest passed; 699/706 total (4 pre-existing failures unchanged)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-05-11 18:29:54 +03:00
parent e242e7d7fc
commit 9d2e7270de
11 changed files with 290 additions and 5 deletions
@@ -5,8 +5,10 @@ declare(strict_types=1);
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Requests\StoreProjectRequest;
use App\Http\Resources\ProjectResource;
use App\Models\Project;
use App\Services\Project\ProjectService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@@ -21,6 +23,8 @@ use Illuminate\Http\Request;
*/
class ProjectController extends Controller
{
public function __construct(private readonly ProjectService $projects) {}
/** GET /api/projects */
public function index(Request $request): JsonResponse
{
@@ -78,6 +82,14 @@ class ProjectController extends Controller
]);
}
/** POST /api/projects */
public function store(StoreProjectRequest $request): JsonResponse
{
$project = $this->projects->create($request->user()->tenant, $request->validated());
return response()->json(['data' => new ProjectResource($project)], 201);
}
/** GET /api/projects/{id} */
public function show(Request $request, int $id): JsonResponse
{