Skip to content

Local CRM system for auto repair workshops — FastAPI, SQLModel, SQLite, Jinja2, TailwindCSS.

Notifications You must be signed in to change notification settings

TeodorArg/galpon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Auto CRM (FastAPI + Alembic + SQLite/PostgreSQL)

Локальная CRM-система для автосервиса. Хранит клиентов, авто, заказы, вложения.
Работает через HTML-интерфейс и Swagger API на localhost.
Поддерживает Alembic для миграций БД и легко переводится на PostgreSQL.


👤 Демо-учётные записи

🔧 Служебные пользователи

Роль Логин Пароль Email
superadmin superadmin admin [email protected]
admin maria.admin admin123 [email protected]
admin sergio.admin admin456 [email protected]
master lucas.master lucaspass [email protected]
master natalia.master natamaster [email protected]
master diego.master diegomaster [email protected]
master marcela.master marcela22 [email protected]

👥 Клиенты

Логин Пароль Email
juan.rivas client1 [email protected]
laura.mendez client2 [email protected]
pablo.flores client3 [email protected]
carla.sosa client4 [email protected]
matias.lopez client5 [email protected]
veronica.diaz client6 [email protected]
federico.gomez client7 [email protected]
sofia.rios client8 [email protected]
tomas.acosta client9 [email protected]
julieta.bianchi client10 [email protected]

🔐 HTML-интерфейс

  • Вход: http://localhost:8000/admin/login
  • Клиенты: http://localhost:8000/admin/clients
  • Добавить клиента: http://localhost:8000/admin/clients/add
  • Добавить авто: http://localhost:8000/admin/vehicles/add
  • Создать заказ: http://localhost:8000/admin/orders/add
  • Выход: http://localhost:8000/admin/logout

📦 Backup DB

Для резервного копирования SQLite используется встроенный тул:

Создать бэкап (по умолчанию в backups/db/):

python -m tools.db_backup

Создать бэкап с тегом и архивом:

python -m tools.db_backup --compress --tag pre-seed

Хранить только 7 последних бэкапов:

python -m tools.db_backup --keep 7

Каждый бэкап:

  • Создаётся консистентно через sqlite3.Connection.backup();
  • Проверяется PRAGMA integrity_check (результат пишется в .ok/.fail);
  • Хранится как backups/db/auto_crm_YYYYMMDD-HHMMSS[_tag].sqlite (+ .zip если --compress).

⚠️ В .gitignore уже прописано исключение всех .sqlite, .zip, .ok, .fail внутри backups/.


🥮 Swagger API

  • Swagger UI: http://localhost:8000/docs
  • ReDoc: http://localhost:8000/redoc

🚀 Установка и запуск

1. Клонирование проекта

git clone https://github.com/your-user/auto-crm.git
cd auto-crm

2. Установка зависимостей

Теперь зависимости разделены на основные (requirements.txt) и dev (requirements-dev.txt)
В dev-версии закреплены стабильные версии ruff, djlint, eslint и prettier, чтобы авто-форматирование было воспроизводимым.

✅ macOS / Linux

python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install -r requirements-dev.txt
pnpm install

✅ Windows

python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
pip install -r requirements-dev.txt
pnpm install

3. Настройка и инициализация базы данных

Создайте .env в корне:

PYTHONPATH=.
DATABASE_URL=sqlite:///./auto_crm.db
SECRET_KEY=your_super_secret_key

Примените миграции Alembic:

make migrate

Добавьте демо-данные:

make init

4. Запуск в режиме разработки

make dev

Доступные варианты:

make run
make dev-css
make build-css

🛠 Makefile — основные команды

Команда Описание
make dev API + CSS-watcher параллельно
make run Только API
make dev-css Только CSS-watcher
make build-css Сборка минифицированных стилей
make lint Проверка кода
make lint-fix Авто-фиксы
make clean Очистка кешей
make makemigration Генерация миграции
make migrate Применение миграций
make init Загрузка демо-данных
make reset Полный сброс БД

🎯 Форматирование и линтинг

  • ruff — Python
  • eslint — JS
  • prettier — JSON, CSS, Markdown
  • djlint — Jinja

🖼 Скрипты для работы с медиа

python -m app.scripts.audit_media_exists
python -m app.scripts.repair_missing_variants
python -m app.scripts.purge_broken_media --dry-run

Работа с переводами

python tools/i18n_scan.py scan --phrase app/templates/shared/ui/_confirm_modal.html
python tools/i18n_scan.py interactive app/templates/shared/ui/page_header.html

# 1) Генерация .pot:
make i18n-extract

# 2) Разовая инициализация языков:
make i18n-init

# 3) После добавления/обновления строк в шаблонах:
make i18n-all

# 4) Быстрый цикл после обёртки:
make i18n-extract     # обновит messages.pot (если нужно)
make i18n-update      # подтянет новые msgid в .po
make i18n-compile     # соберёт .mo

🛡 CSRF Protection Checklist

В проекте используется централизованная защита от CSRF (Cross-Site Request Forgery).

1. Middleware (автоматическая выдача токена)

Файл: app/middleware/csrf.py

  • На всех GET/HEAD/OPTIONS запросах:
    • гарантируем наличие CSRF-токена в cookie;
    • кладём токен в request.state.csrf_token для шаблонов;
    • возвращаем тот же токен в cookie через issue_csrf_with.

2. Dependency для POST-запросов

Файл: app/deps/csrf.py

  • require_csrf проверяет:
    • скрытое поле формы csrf_token ИЛИ заголовок X-CSRF-Token;
    • сверяет его с токеном в cookie csrf_token;
    • если несовпадение → 403 Forbidden.

3. Макрос для скрытого input

Файл: app/templates/partials/form/_csrf.html

  • Используется в формах для вставки:
    <input type="hidden" name="csrf_token" value="{{ токен }}">
  • Источники: request.state.csrf_token → cookie → контекст csrf_token.

4. Где применяется

  • FormKit-формы (clients, vehicles, electrical):
    • GET: ensure_csrf выдаёт токен в hidden и cookie;
    • POST: require_csrf проверяет hidden+cookie.
  • Upload/replace/delete вложений (vehicles, electrical):
    • POST: требуют require_csrf, hidden-input добавлен в upload_panel.html.
  • Confirm-модалка удаления: всегда передаёт csrf_token в скрытом input.

5. Best Practices

  • Никогда не использовать токен напрямую через JS (meta[name=csrf-token] было удалено).
  • Всегда использовать {% from "partials/form/_csrf.html" import csrf_input with context %} внутри форм.
  • Для API-запросов использовать заголовок X-CSRF-Token.

✅ Conventional Commits

  • feat: добавление новой функциональности
  • fix: исправление ошибки
  • refactor: изменение логики без изменения функционала
  • chore: служебные задачи (зависимости, настройки)
  • style: стилистические изменения
  • docs: изменение документации
  • test: добавление/изменение тестов

Готово ✅ — открой http://localhost:8000/admin/login и начинай работать 🚗


Как использовать в шаблонах i18n (пример)

{# Кнопки/формы/фильтры/сайдбар/страницы — всё домен ui, но контекст разный #}
<button class="btn">{{ pgettext('ui.buttons', 'Save') }}</button>
<label>{{ pgettext('ui.filters', 'Status') }}</label>
<nav>{{ pgettext('ui.sidebar', 'Vehicles') }}</nav>
<h1>{{ pgettext('ui.pages.reports', 'Print') }}</h1>

{# ENUM-лейбл (в БД хранится код): #}
<span class="chip">{{ pgettext('enums.report.status', report.status) }}</span>

{# Форматирование дат/валюты/чисел: #}
<time>{{ i18n.dt(report.created_at, 'medium') }}</time>
<div>{{ i18n.money(1234.5, 'USD') }}</div>
<div>{{ i18n.num(12345.678) }}</div>

Команды для мультиязыка (с пояснениями)

make i18n-scan — просканировать app/templates и вывести все куски «видимого» русского текста. Ничего не меняет.

make i18n-wrap [PATHS="..."] [I18N_CTX=ui.forms] [I18N_WORDS=1] [I18N_USE_KEYS=1] [I18N_NO_INFER=1] Обернуть найденные фразы в {{ pgettext('', "…") }} прямо в файлах, делая .bak-резервные копии.

PATHS — что оборачивать (по умолчанию app/templates).

I18N_CTX — жёсткий контекст (например, ui.forms).

I18N_WORDS=1 — оборачивать по словам (иначе фразами).

I18N_USE_KEYS=1 — вместо оригинальной фразы использовать ключ . как msgid.

I18N_NO_INFER=1 — отключить авто-инференс контекста по пути/атрибуту.

make i18n-interactive [PATHS="..."] — интерактивный режим: показ → выбор индексов → обёртка (всегда с .bak).

make i18n-extract — создать отдельный .pot по каждому домену в .i18n/pot/. Да, содержимое .pot совпадает — это нормально: разделение смысла у нас идёт через pgettext('ui.*', ...) и разные .po.

make i18n-init

— разово создать .po для всех локалей и всех доменов (существующие не трогаем).

make i18n-update

— обновить все .po из свежих .pot (нужно после изменений в коде/шаблонах).

make i18n-compile

— собрать .mo из .po (нужно для рантайма).

make i18n-all

— весь цикл (extract → update → compile).

make i18n-clean

— удалить только .mo (удобно для чистой пересборки).

make i18n-status

— сверка POT↔PO по (msgctxt,msgid). Возвращает exit 2, если что-то missing/obsolete.

🔧 i18n_translate_scan.py — Улучшенный i18n-сканер с переводом

Утилита для сканирования шаблонов на русский текст, автоматического перевода в английский, проверки ключей в app/locales/en/LC_MESSAGES/ui.po и оборачивания в pgettext с использованием существующих или новых msgid (EN). Основана на i18n_scan.py + i18n_autofill.py.

Процесс:

  • Сканирует RU-текст в шаблонах.
  • Переводит в EN (с кэшем RU → EN в JSON).
  • Проверяет ключи по ctx/msgid в en/ui.po.
  • Оборачивает в pgettext('<ctx>', 'msgid').
  • Опционально добавляет новые ключи в PO-файлы.

Зависимости: polib (установите: pip install polib). Python 3.9+.

Использование:

python tools/i18n_translate_scan.py [PATHS] [options]

Основные опции (на основе логики скрипта):

  • --add-to-po: Добавляет новые ключи в соответствующие .po-файлы (en/ui.po и другие локали).
  • --cache: Использует/обновляет JSON-кэш переводов RU → EN (по умолчанию в ./.i18n_cache.json).
  • --domain ui: Указывает домен (по умолчанию 'ui' для шаблонов).
  • --paths "app/templates": Пути для сканирования (по умолчанию app/templates).
  • --dry-run: Только сканирование и вывод, без изменений файлов.
  • --verbose: Подробный вывод (логи переводов и найденных ключей).
  • --help: Полный список опций.

Пример:

# Сканирование и оборачивание с переводом, добавлением в PO
python tools/i18n_translate_scan.py app/templates --add-to-po --verbose

# Только сканирование с кэшем
python tools/i18n_translate_scan.py --dry-run --cache

После запуска:

  • Файлы шаблонов обновляются (.bak-копии создаются автоматически).
  • Новые msgid добавляются в .po (если --add-to-po).
  • Запустите make i18n-compile для сборки .mo.

⚠️ Предупреждение: Тестируйте на копии проекта. Переводы автоматические — проверяйте msgid на точность. Для интерактивного режима используйте существующие инструменты вроде make i18n-interactive.

Интеграция с Makefile: Добавьте make i18n-translate-scan для удобства (аналогично другим i18n-командам).

Полный вывод: VERBOSE=1 make i18n-status.

About

Local CRM system for auto repair workshops — FastAPI, SQLModel, SQLite, Jinja2, TailwindCSS.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published