Схема БД fuel_prod1

Снято живьём 2026-07-24 через devopsmcp db_schema. 187 таблиц в public (включая легаси-мусор от Metabase/Quartz в той же БД) — ниже только таблицы, участвующие в антифрод-детекторах.

Связи ключевых таблиц

CardId GasStationId CompanyId CardOwnerId RegionId CardOwnerId CardId CompanyId CompanyId FinanceTransaction 4.87M строк · хаб Cards 113 493 строк GasStations 389 262 строк CardOwners 31 604 строк Region TimzeZone (sic) Companies 3 683 строк Limits 650 736 строк

Стрелка = внешний ключ, подпись — колонка-источник. Limits хранит владельца в одном из трёх полей (CardId / CardGroupId / CompanyId) — на диаграмме показаны связи с Cards и Companies.

FinanceTransaction

4 865 144 строк, 2.3 GB. Ядро схемы: одна строка = одна заправка/операция.

КолонкаТипПримечание
Idint PK
CardIdint FK→Cardsиндекс есть
CompanyIdint FK→Companiesклиент; индекс есть
CardOwnerIdint FK→CardOwnersводитель; индекс есть
GasStationIdint FK→GasStationsиндекс есть
FuelTypeIdint FK→FuelTypesnullable
FuelVinkTypeIdint FK→FuelTypeVinkтип топлива в кодах ВИНК
CreateTimetimestamp (naive, локальное)индекса нет (только композитные CompanyUserId+CreateTime, SecondCompanyUserId+CreateTime)
CreateTimeUtctimestamp (naive UTC)default '0001-01-01' — заполнено не всегда
LitersSumnumeric NOT NULLлитры
PriceBasenumeric NOT NULLцена за литр
FullSumnumeric NOT NULLсумма ₽
TransactionNumbertextномер транзакции ВИНК
UniqVINKCodetextуникальный код ВИНК, индекс есть
VinkTypeint NOT NULL0=Роснефть 1=Газпромнефть 2=Татнефть 3=Лукойл 4=СТС 5=Вездеход(Газпром) 6=Инфорком 7=ГПН-ГТЛ 8=АСМАП 9=ТаифНК 10=НатКар 11=Трасса
OperationType, From, RequestTypeintтип операции/источник
IsOfflineboolофлайн-транзакция (пришла постфактум)
AutoInputboolавтоввод
ReceiveWithNegativeBalanceboolпроведена при минусе
CompanyUserId, SecondCompanyUserIdint FK→Companiesцепочка перепродажи
NoFuelGoodIdint FK→NoFuelGoodsнетопливные товары
VinkInDiscountPerLiternumericвходящая скидка
GasStationBrandId / ManualFuelTypeId / ManualGasStationBrandIdint FKручные справочники

Остальные ключевые таблицы

Cards — 113 493 строк

Колонка(и)Примечание
CompanyIdклиент
CompanyUserId, SecondCompanyUserIdперепродажа
CardOwnerIdводитель
CardType= VinkType карты, индекс
Number / CardNumber
IsActivebool
BlockStatusint
IsAdminBlocked / IsManagerBlocked / IsSuperUserBlocked / IsHidden / IsVirtualbool
BrokenStatus / BrokenTime
Validityсрок действия
DirectContractId / DirectContractWithVendorId / BookedDirectContractId
ActivationData
PIN / PinCode

CardOwners (водители) — 31 604 строк

Колонка(и)Примечание
Title
CompanyId
InDay / InWeek / InMonthлимиты, int
MaxInDayCurrent / MaxInWeekCurrent / MaxInMonthCurrentостатки
IsBlocked
DateForUnblock
IsHidden

Limits — 650 736 строк (лимиты карт/групп/компаний)

Колонка(и)Примечание
CardId | CardGroupId | CompanyIdодно из — владелец лимита
FuelCategoryId, FuelTypeId
InDay / InWeek / InMonthint
MaxInDayCurrent / MaxInWeekCurrent / MaxInMonthCurrentтекущие остатки
LimitTypeint (0=обычный, Custom и т.д.)
IsCloseAccessnumeric
IsReadyToEdit

CardOwnerLimits — 287 989 строк (лимиты водителей)

Колонка(и)Примечание
CardOwnerIdFK
FuelCategoryId, FuelTypeId
LimitType
InDay / InWeek / InMonth
IsCloseAccess

Внимание: CardId в этой таблице нет — лимиты водителей привязаны через CardOwnerId; дневные/недельные/месячные значения хранятся в полях InDay/InWeek/InMonth (детекторы: каталог).

GasStations — 389 262 строк

Колонка(и)Примечание
Title
RegionIdFK→Region, NOT NULL — текстового поля Region нет
CoordsX / CoordsYtext
VinkName
CardType
GasStationBrandIdFK→GasStationBrands — поля Brand нет
ProviderCompanyId
Status
Adress

Region

Колонка(и)Примечание
Title
TimzeZoneint (sic — опечатка в самой схеме)
Code
PartRegionTitle

Companies — 3 683 строк

Колонка(и)Примечание
Title, JurudicalTitle, Inn
IsBlocked
VinkType
CardTypestext
IsBrandCompany
AccessToDirectContracts / Resale / FuelUsing
CompanySettingsId

Договорная модель

Таблицы Contracts нет — договор оформлен как DirectContracts + ContractTerms(+Templates).

DirectContracts
4 328 строк — CompanySellerId, CompanyBuyerId, CurrentContractBalanceId FK, ContractStatus, ContractNumber, SumOverDraft, TempOverdraftSum/Until, OverdraftIsBanned, AverageDailyPumpingRUB, PaymentLimit, DepositAmount, SubmittedToCourt, DebtorEntryDate
ContractTerms
6 107 строк — DirectContractId FK, ContractTermTemplateId FK, CardType, IsActive, TechLimit numeric, TotalLimit numeric (общий суточный лимит договора — VESTAFUEL-1970)
ContractTermTemplates
297 строк — Title, CompanyId, CardType, SizeExtraChange (наценка), TemplateType, ConditionType, DateFrom, DirectContractWithVendorId. MaxTransactionLimit нет, FuelTypeId нет.

Балансы и деньги

CurrentContractBalances
4 444 — текущий баланс договора
BalanceActions
4.43M — CurrentContractBalanceId, BalanceActionType, Sum, BalanceSum (баланс после), Comment, LastModifed
SummaryContractBalances
7.47M
ContractPayInfos
410K
MinusBalanceTransactionToDirectContracts
1.14M
CurrentTemporaryOverdrafts
23.7K

Зеркало ВИНК и история

ApiLimitInfo
835K — лимиты как их видит кабинет ВИНК (для сверки mirror-divergence)
ApiCardInfos
171K — карты по данным ВИНК
LimitVinkHistory
480K — история изменений лимитов в ВИНК
RestrictionLimitStates
378K — состояния ограничений
CardLogs
7.75M
CardChangeLogs
271K — только Id, CompanyOwnerId, CompanyUserId, CardId, LastModifed; тип и значения изменения не сохраняются
FinanceTransactionParts
11.2M — части транзакций (12 колонок)
FinanceTransactionDiscountHistories
2.1M
DeletedFinanceTransactionForReports
67

Критичные факты для антифрода

  1. Нет индекса по FinanceTransaction.CreateTime — любой «за последние N дней» = seq scan 2.3 GB. Сервису нужен либо индекс (btree CreateTime или BRIN), либо инкрементальная выгрузка по Id.
  2. CreateTime naive-локальное, CreateTimeUtc частично '0001-01-01' — все временные проверки обязаны фиксировать таймзону; NOW() на сервере БД ≠ время транзакции. Регион АЗС имеет TimzeZone — ночь надо считать в локальном времени АЗС.
  3. Координаты АЗС — text (CoordsX/CoordsY), нужен CAST + фильтр мусора; PostGIS не предполагается — haversine на float.
  4. Таблицы Contracts нет — договорная модель: DirectContracts + ContractTerms(+Templates).
  5. Полная история изменений лимитов внутри БД не сохраняется — детекторы опираются на LimitVinkHistory/ApiLimitInfo (зеркало ВИНК) и на LastModifed текущих записей.
  6. Прод пережил реальные инциденты класса «порча лимитов»: zero-limit flood 2026-07-01 (ГПН+Татнефть, ~18K тасков), Лайт Скай limit-wipe 2026-06-23, фантом категории-0 Роснефть (A-1353). Детекторы массовых изменений лимитов (D-14) — не теория.

Снято живьём через devopsmcp db_schema 2026-07-24, 187 таблиц в public. Детекторы, использующие эти таблицы — на странице «Детекторы».