feat(sales): artisan sales:prospects-demo — демо-карточки воронки

Этап 1 Task 8. По 2 карточки на каждую из 8 стадий у указанного менеджера
(для показа досок). Baseline под artisan() Pest-паттерн.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-07-15 16:35:52 +03:00
parent 9d8fd8d48c
commit d6cddf73a6
4 changed files with 81 additions and 3 deletions
@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace App\Console\Commands;
use App\Models\SalesProspect;
use App\Models\SalesUser;
use Illuminate\Console\Command;
/**
* Демо-наполнение воронки «Потенциальные клиенты» для показа Этапа 1.
* Создаёт по 2 карточки на каждую из 8 стадий у указанного менеджера.
*
* Использование: php artisan sales:prospects-demo {salesUserId}
*/
class SalesProspectsDemoSeed extends Command
{
protected $signature = 'sales:prospects-demo {salesUserId : ID менеджера (sales_users.id)}';
protected $description = 'Наполнить воронку демо-карточками для показа';
public function handle(): int
{
$id = (int) $this->argument('salesUserId');
$user = SalesUser::find($id);
if ($user === null) {
$this->error("sales_user #{$id} не найден");
return self::FAILURE;
}
$stages = ['new', 'negotiation', 'registered', 'testing', 'topped_up', 'user', 'rejected', 'no_answer'];
foreach ($stages as $stage) {
for ($i = 1; $i <= 2; $i++) {
SalesProspect::factory()->for($user, 'salesUser')->create([
'stage' => $stage,
'assigned_by' => $user->id,
'next_call_at' => $stage === 'negotiation' ? now()->addDay() : null,
'reason' => in_array($stage, ['rejected', 'no_answer'], true) ? 'демо-причина' : null,
'registered_email' => in_array($stage, ['registered', 'testing', 'topped_up', 'user'], true)
? 'demo'.$i.'@example.com' : null,
]);
}
}
$this->info("Готово: 16 демо-карточек для {$user->name}");
return self::SUCCESS;
}
}
+6
View File
@@ -3996,6 +3996,12 @@ parameters:
count: 2
path: tests/Feature/Sales/SalesProspectApiTest.php
-
message: '#^Call to an undefined method Pest\\PendingCalls\\TestCall\:\:artisan\(\)\.$#'
identifier: method.notFound
count: 1
path: tests/Feature/Sales/SalesProspectsDemoSeedTest.php
-
message: '#^Call to an undefined method Pest\\PendingCalls\\TestCall\:\:artisan\(\)\.$#'
identifier: method.notFound
@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
use App\Models\SalesProspect;
use App\Models\SalesUser;
use Illuminate\Foundation\Testing\DatabaseTransactions;
uses(DatabaseTransactions::class);
test('sales:prospects-demo наполняет карточки для менеджера по всем стадиям', function () {
$mgr = SalesUser::create([
'name' => 'Демо '.uniqid(), 'email' => 'demo'.uniqid().'@s.local',
'password' => bcrypt('x'), 'role' => 'manager', 'is_active' => true,
]);
$this->artisan('sales:prospects-demo', ['salesUserId' => $mgr->id])->assertExitCode(0);
$stages = SalesProspect::where('sales_user_id', $mgr->id)->pluck('stage')->unique();
expect($stages)->toContain('new')->toContain('negotiation')->toContain('testing')->toContain('user');
});
+3 -3
View File
@@ -1,6 +1,6 @@
# Brain Status (auto-generated)
Last updated: 2026-07-15T13:25:11.930Z
Last updated: 2026-07-15T13:33:42.226Z
| Контролёр | Состояние | Детали |
|---|---|---|
@@ -112,8 +112,8 @@ Episodes since last run: 542 / threshold: 10
| PID | Имя | CPU-время | Возраст |
|---|---|---|---|
| 3488 | MsMpEng | 6.88ч | 0.0ч |
| 9756 | Code | 3.16ч | NaNч |
| 3488 | MsMpEng | 6.90ч | 0.0ч |
| 9756 | Code | 3.17ч | NaNч |
| 1320 | svchost | 1.33ч | 0.0ч |
⚠️ Проверь, не «осиротевшие» ли это процессы от завершённых Claude-сессий.