a907fea031
Schema delta (4 правки в db/schema.sql):
- tenants + delivered_in_month INT NOT NULL DEFAULT 0 CHECK (>=0) — month
counter для PricingTierResolver O(1) lookup на горячем пути.
- lead_charges + charge_source VARCHAR(8) DEFAULT 'rub' CHECK IN ('prepaid','rub')
+ ALTER ADD CONSTRAINT chk_lead_charges_prepaid_zero_price (prepaid → price=0).
- supplier_leads + recovered_from_csv_at TIMESTAMPTZ + partial index
WHERE recovered_from_csv_at IS NOT NULL.
- Новая таблица supplier_csv_reconcile_log (SaaS-level, без RLS) + 2 индекса
(started_at DESC, partial status WHERE status IN ('drift_alert','failed')).
Метрики: 61 → 62 базовых таблиц / 114 → 117 индексов / 39 RLS (без изменений).
Сопутствующие правки:
- db/CHANGELOG_schema.md — v8.19 entry (18 записей).
- db/02_grants.sql — GRANT SELECT,INSERT,UPDATE on supplier_csv_reconcile_log
+ GRANT USAGE,SELECT on sequence для crm_supplier_worker.
- app/Models/Tenant — fillable+casts: delivered_in_month integer.
- app/Models/LeadCharge — fillable+casts: charge_source string.
- app/Models/SupplierLead — fillable+casts: recovered_from_csv_at datetime.
- LeadChargeFactory — defaults charge_source='rub' + prepaid() state.
- PricingTierSeeder (новый) — 7 ступеней дефолтного тарифа (placeholder,
Plan 4 Открытый вопрос #1: 100/200/400/800/1500/3000/∞ leads at
50000/45000/40000/35000/30000/27000/25000 копеек).
- DatabaseSeeder — call PricingTierSeeder; убран broken Laravel scaffold
User::factory(['name' => ...]) (наша схема first_name/last_name).
Tests (Plan 4 surface):
- SchemaDeltaTest.php — 5 it() блоков: delivered_in_month CHECK, charge_source
CHECK на prepaid+zero-price, recovered_from_csv_at колонка, reconcile_log
таблица+status CHECK, migrate:fresh idempotency (skip in parallel).
- pest --filter=SchemaDeltaTest: 5/5 PASS (9 assertions, 2076 ms).
- pest --filter='Tenant|LeadCharge|SupplierLead|Plan4': 111/111 PASS.
CI gates:
- composer pint: passed.
- composer stan: passed (0 errors above baseline — @phpstan-ignore-next-line
на $this->markTestSkipped в Pest closure rebound context).
Verify:
- migrate:fresh --seed на DB_DATABASE=liderra_testing: 0 errors, 754 ms.
- PricingTier::count() = 7.
Концерны (НЕ блокируют Task 1):
- pest --parallel: 617/622 PASS + 4 skipped + 1 flaky FAIL — flaky test
колеблется между ProjectExtensionsTest::supplierB1_B2_B3_relations
(SupplierProjectFactory race: closure пикает signal_type=sms до override
platform=B1 → CHECK chk_supplier_projects_b1_not_for_sms violation)
и NewLeadNotificationTest::webhook_дубль_Биз_19 (известный microsecond
precision quirk в anti-spam exclusion, memory feedback_environment.md).
Оба теста существуют на main (HEAD 0802f7c = plan4-billing branch HEAD
до этого commit'а), Plan 4 их не трогает. Фиксы — вне Task 1 scope.
Spec: docs/superpowers/specs/2026-05-11-plan4-billing-csv-admin-design.md §2.
Plan: docs/superpowers/plans/2026-05-11-plan4-billing-csv-admin-plan.md Task 1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
1.3 KiB
PHP
36 lines
1.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Database\Seeders;
|
|
|
|
use App\Models\PricingTier;
|
|
use Illuminate\Database\Seeder;
|
|
|
|
class PricingTierSeeder extends Seeder
|
|
{
|
|
/**
|
|
* 7 ступеней дефолтного тарифа (Plan 4 spec §2.3 — placeholder, ожидает
|
|
* подтверждения заказчика. Открытый вопрос #1).
|
|
*/
|
|
public function run(): void
|
|
{
|
|
$tiers = [
|
|
['tier_no' => 1, 'leads_in_tier' => 100, 'price_per_lead_kopecks' => 50000],
|
|
['tier_no' => 2, 'leads_in_tier' => 200, 'price_per_lead_kopecks' => 45000],
|
|
['tier_no' => 3, 'leads_in_tier' => 400, 'price_per_lead_kopecks' => 40000],
|
|
['tier_no' => 4, 'leads_in_tier' => 800, 'price_per_lead_kopecks' => 35000],
|
|
['tier_no' => 5, 'leads_in_tier' => 1500, 'price_per_lead_kopecks' => 30000],
|
|
['tier_no' => 6, 'leads_in_tier' => 3000, 'price_per_lead_kopecks' => 27000],
|
|
['tier_no' => 7, 'leads_in_tier' => null, 'price_per_lead_kopecks' => 25000],
|
|
];
|
|
|
|
foreach ($tiers as $tier) {
|
|
PricingTier::updateOrCreate(
|
|
['tier_no' => $tier['tier_no'], 'effective_from' => '1970-01-01'],
|
|
array_merge($tier, ['is_active' => true, 'effective_from' => '1970-01-01']),
|
|
);
|
|
}
|
|
}
|
|
}
|