Orium Studios

PRJ-03Автоброкеридж

Autobroker: одно число и только одно место, откуда оно берётся.

Мультитенантная CRM для автоброкеров. Правило, по которому считается заработок со сделки, записано один раз в приложении и один раз в SQL, в одном и том же изменении, поэтому два экрана не могут тихо дать разные ответы.

Клиент · American Auto Group, Статен-Айленд, Нью-Йорк

aagleasing.com
Дет. 01 · живой продуктaagleasing.com
Система Autobroker в работе

PRJ-03-AОбъём работ

Чем занимается бизнес.

Брокер не продаёт машину с площадки. Он берёт то, что хочет покупатель, находит это в сети дилеров и добивается для покупателя финансирования. Работа, от которой зависит, заработает ли он хоть что-то, это кредитная заявка: длинная, скучная и юридически серьёзная форма, которую кредитор отклонит, если в ней не хватает одного раздела.

Несколько брокеров, несколько филиалов и компания, которая должна уметь сказать, сколько на самом деле принесла каждая сделка: брокеру, бухгалтеру и самой себе.

Публичный сайт и CRM это группы маршрутов в одном приложении на одном деплое. Между ними нечего интегрировать, потому что это одна и та же программа: форма, заполненная на сайте, через секунду становится строкой в воронке, ничего не перепечатано и ничего не лежит в чьей-то почте.

В чём сложность.

Прибыль по сделке считалась в четырёх разных местах, и в один и тот же день они давали три разных результата: плитка на дашборде, лидерборд двумя строками ниже, страница отчётов и собственная строка брокера.

Четыре места, которые считают одно число тремя способами, хуже, чем если бы одно из трёх было просто неверным: тогда нельзя доверять ни одному экрану. И конкретный сбой тихий. Расходы, записанные раньше, чем введена хоть какая-то комиссия, делают сделку похожей на убыток. Как вычитание это верно, как итог это неверно.

PRJ-03-BВыноски

Что построено.

У каждого пункта указан файл, который это доказывает. Пути даны относительно репозитория.

A

Одна денежная модель, записанная дважды намеренно

Каждый итог прибыли в продукте берётся из одного модуля, и то же правило записано в базе как SQL, чтобы триггер не мог считать по одной формуле, пока экран считает по другой. Они меняются одним коммитом, или не меняется ни один. Если выручка не записана, прибыль показывается как неизвестная, а не как убыток, а уже потраченные расходы показываются отдельно, а не отбрасываются: спрятать их значило бы завысить прибыль, а это ложь в обратную сторону.

Доказательство

lib/deal-money.ts, supabase/migrations/*_profit_has_one_writer.sql

B

Отчёты, которые читают то же самое правило

Страница отчётов, лидерборд и дашборд идут через денежную модель, а не суммируют сохранённую колонку каждый по-своему. Исправление попадает на все экраны сразу, и в этом весь смысл.

Доказательство

app/(app)/reports/, lib/broker-payouts.ts

C

Созаёмщику задают те же вопросы, а не часть из них

Большинство кредитных форм дают второму заявителю урезанную версию, и кредиторы такие заявки возвращают. Здесь созаёмщик рендерится тем же компонентом, что и основной заявитель, поэтому оба отвечают на те же 35 вопросов и оба загружают обе стороны водительских прав. Если по текущему адресу человек живёт меньше двух лет, ещё четыре поля становятся обязательными автоматически, потому что кредитор всё равно это спросит. Проверка полноты прогоняет тот же список на сервере для каждого человека, так что урезанный созаёмщик не может появиться случайно.

Доказательство

app/(site)/credit-application/, посчитано в компоненте формы

D

Номер социального страхования лежит шифротекстом, и каждый просмотр записан

AES-256-GCM, ключ хранится только в серверном окружении, никогда не уходит в браузер и никогда не хранится в базе. Запасного пути с открытым текстом нет: если ключа нет, заявка отклоняется, а не сохраняется в открытом виде. Показ полного номера сначала пишет запись в журнал доступа, и раскрытие зависит от того, удалась ли эта запись, поэтому номер нельзя прочитать без следа. Одновременно поддерживаются два ключа, чтобы при ротации не было окна, в которое заявка, поданная посреди смены ключа, становится нечитаемой. Это не гипотеза: настоящая заявка пришла днём, пока писалась ротация.

Доказательство

lib/crypto-ssn.ts, lib/pii-audit.ts

E

Хранение данных по расписанию

Задачи по расписанию берут на себя ту часть работы с персональными данными, которую никто не хочет держать в голове: срок хранения чувствительных полей и перешифровку при смене ключа.

Доказательство

app/api/cron/pii-retention/, app/api/cron/ssn-rekey/, lib/pii-retention.ts

F

Вехи лизинга, которые напоминают о себе сами

Ежедневная задача проходит по открытым сделкам, ставит напоминания на важных вехах лизинга, за 180, 120, 90 и 30 дней, и помечает сделки, которые не двигаются. Задачи пишутся идемпотентно по ключу дедупликации, поэтому задача, запущенная дважды, не создаст одно и то же напоминание дважды.

Доказательство

app/api/cron/automations/route.ts

G

Мультитенантность и собственный сайт клиента в той же системе

Разделение по компаниям и филиалам проходит через модель данных, а публичный сайт брокерской компании входит в тот же деплой: заявка с сайта приходит записью в воронку, а не письмом кому-то на телефон.

Доказательство

app/(site)/, supabase/migrations/20260804120000_website_leads.sql

PRJ-03-CСправка

Где это живёт.

Своя база, свой деплой. С двумя другими системами общего нет ничего, кроме кода, который сначала доказал себя в них.

Этот лист не называет ни выручку, ни рост конверсии. Сборка свежая, и любая такая цифра была бы догадкой, выданной за результат. Всё выше описывает, что делает софт, и всё это можно показать вживую.

Система
Autobroker
Репозиторий
autobroker-crm
Ремесло
Автоброкеридж

Файлы, названные на этом листе

  • autobroker-crm · lib/deal-money.ts, одна денежная модель
  • autobroker-crm · lib/crypto-ssn.ts, шифрование и ротация ключа
  • autobroker-crm · app/api/cron/automations/route.ts, вехи лизинга
  • autobroker-crm · lib/stripe.ts, байт в байт одинаковый во всех трёх системах

Три отдельных деплоя, три отдельные базы и никаких общих данных между клиентами. Общий у них только код, который сначала доказал себя в одной из них: lib/stripe.ts байт в байт одинаковый во всех трёх репозиториях.

Журнал сборки (по-английски): что нашли и каким коммитом исправилиКо всем работам

PRJ-03-DСтоимость

Сколько стоит такая система.

Своя CRM, собранная под то, как работает твоя компания, стоит от $2 500. Подгонка одной из уже работающих систем под твой процесс стоит от $1 500. Это нижние границы, а итог считается по объёму работы.

Своя CRM
от $2 500
Подгонка готовой системы
от $1 500