Высокоуровневые действия (autodealer.actions)

Пакет autodealer.actions содержит высокоуровневые функции для работы с клиентами, автомобилями и платежами. В отличие от ORM-моделей, каждая функция выполняет атомарную бизнес-операцию и скрывает детали directory_registry / транзакций от вызывающего кода.

Клиенты и автомобили (actions.client)

Создание клиента

autodealer.actions.client.create_client(fullname, *, phone=None, email=None, birth=None, sex=None, discount=0.0, discount_work=0.0, client_tree_id=1, created_by_user_id=1)

Создать клиента в Firebird.

Атомарно создаёт цепочку: DirectoryRegistry (metatable=3)ClientContact (если есть phone/email).

Параметры:
  • fullname (str) – Полное имя (обязательно).

  • phone (str) – Мобильный телефон.

  • email (str) – Email.

  • birth (date) – Дата рождения.

  • sex (int) – 1=муж, 2=жен, ``None``=не указан.

  • discount (float) – Скидка на товары %.

  • discount_work (float) – Скидка на работы %.

  • client_tree_id (int) – Папка клиентов (1=Физлица, 2=Юрлица, 3=VIP).

  • created_by_user_id (int) – Пользователь-создатель.

Результат:

client_id созданного клиента.

Тип результата:

int

from datetime import date
from autodealer.actions.client import create_client

client_id = create_client(
    "Иванов Иван Иванович",
    phone="79991234567",
    email="ivan@example.com",
    birth=date(1990, 5, 15),
    sex=1,
    discount=5.0,
)

Автомобили клиента

autodealer.actions.client.add_vehicle_to_client(client_id, make, model_name, *, regno=None, vin=None, year=None, color=None, default_car=False, created_by_user_id=1)

Добавить автомобиль клиенту по имени марки и модели.

Автоматически находит или создаёт записи в mark, model, color, затем создаёт model_detail и model_link.

Идемпотентность: если машина с таким regno уже существует — возвращает существующий model_detail_id без дубликата.

Параметры:
  • client_id (int) – PK клиента.

  • make (str) – Марка («Toyota», «BMW»).

  • model_name (str) – Модель («Camry», «X5»).

  • regno (str) – Госномер.

  • vin (str) – VIN-номер.

  • year (int) – Год выпуска.

  • color (str) – Цвет строкой («Белый», «Чёрный»).

  • default_car (bool) – Пометить как основное авто.

Результат:

model_detail_id созданного или существующего автомобиля.

Тип результата:

int

from autodealer.actions.client import add_vehicle_to_client

md_id = add_vehicle_to_client(
    client_id=42,
    make="Toyota",
    model_name="Camry",
    regno="А001ВС77",
    year=2020,
    color="Белый",
    default_car=True,
)
autodealer.actions.client.get_client_vehicles(client_id)

Вернуть все автомобили клиента в виде объектов ModelLink.

Параметры:

client_id (int) – PK клиента.

Результат:

Список ModelLink. Пустой список если у клиента нет машин.

from autodealer.actions.client import get_client_vehicles

cars = get_client_vehicles(42)
for car in cars:
    print(car.model_link_id, car.model_detail_id, car.default_car)
autodealer.actions.client.create_vehicle_for_client(*, client_id, model_id, vin=None, regno=None, year_of_production=None, color_id=None, ...)

Создать автомобиль и привязать к клиенту напрямую через model_id.

Результат:

Экземпляр ModelLink.

Вспомогательные функции

autodealer.actions.client.get_or_create_mark(name)

Найти марку по имени или создать новую. Возвращает mark_id.

autodealer.actions.client.get_or_create_model(mark_id, model_name)

Найти модель по марке и имени или создать новую. Возвращает model_id.

autodealer.actions.client.get_or_create_color(name)

Найти цвет или создать новый. Возвращает color_id или None если name пустой.

autodealer.actions.client.find_vehicle_by_regno(regno)

Найти автомобиль по госномеру. Возвращает model_detail_id или None.

autodealer.actions.client.find_vehicle_by_vin(vin)

Найти автомобиль по VIN. Возвращает model_detail_id или None.

Платежи (actions.payment)

Связь таблиц

document_out
    │
    └── payment_out.document_out_id ──► payment
                                            │
                                            ├── payment_document.payment_id
                                            │       └── document_registry
                                            │
                                            └── money_document_payment.payment_id
                                                    └── money_document_detail
                                                            (accounting_item_id=3
                                                             «Поступление от клиента»)

Справочники

autodealer.actions.payment.get_wallets(organization_id)

Вернуть кошельки (кассы/счета) организации.

Параметры:

organization_id (int) – PK организации.

Результат:

Список WalletInfo.

from autodealer.actions.payment import get_wallets

for w in get_wallets(1):
    print(w.wallet_id, w.name)
autodealer.actions.payment.get_payment_types()

Вернуть активные способы оплаты из payment_type.

Результат:

Список PaymentTypeInfo.

from autodealer.actions.payment import get_payment_types

for pt in get_payment_types():
    print(pt.payment_type_id, pt.name)

Чтение платежей

autodealer.actions.payment.get_payments(document_out_id)

Вернуть все платежи по заказ-наряду.

Параметры:

document_out_id (int) – PK заказ-наряда.

Результат:

Список PaymentRecord. Пустой если платежей нет.

from autodealer.actions.payment import get_payments

for p in get_payments(42):
    print(p.payment_id, p.summa, p.payment_type_name, p.wallet_name)

Создание платежа

autodealer.actions.payment.create_payment(*, document_out_id, summa, wallet_id, payment_type_id, payment_date=None, notes=None)

Создать документ оплаты для заказ-наряда.

Атомарно создаёт цепочку:

  1. payment — запись платежа.

  2. payment_out — привязка к document_out.

  3. payment_document — привязка к document_registry.

  4. money_document_detail — бухгалтерская проводка (accounting_item_id=3).

  5. money_document_payment — связь проводки с платежом.

  6. UPDATE document_out.date_payment.

Параметры:
  • document_out_id (int) – PK заказ-наряда.

  • summa (float) – Сумма платежа.

  • wallet_id (int) – FK в wallet — касса/счёт.

  • payment_type_id (int) – FK в payment_type — способ оплаты.

  • payment_date (datetime) – Дата платежа. По умолчанию — текущее время.

  • notes (str) – Примечание.

Результат:

payment_id созданного платежа.

Тип результата:

int

Исключение:

ValueError – Если заказ-наряд не найден.

from autodealer.actions.payment import create_payment

payment_id = create_payment(
    document_out_id=42,
    summa=2300.0,
    wallet_id=1,        # Наличный расчёт
    payment_type_id=1,  # Наличный
)

Разбивка оплаты

autodealer.actions.payment.create_payment_split(*, document_out_id, parts, payment_date=None)

Создать несколько платежей за один заказ-наряд (разбивка по способам оплаты). Каждая часть создаётся через create_payment() независимо.

Параметры:
  • document_out_id (int) – PK заказ-наряда.

  • parts (list) – Список PaymentSplitItem.

  • payment_date (datetime) – Единая дата для всех частей.

Результат:

Список payment_id в том же порядке, что и parts.

Тип результата:

list[int]

Исключение:

ValueError – Если parts пустой или суммы <= 0.

from autodealer.actions.payment import create_payment_split, PaymentSplitItem

ids = create_payment_split(
    document_out_id=42,
    parts=[
        PaymentSplitItem(wallet_id=1, payment_type_id=1, summa=1000.0),  # наличные
        PaymentSplitItem(wallet_id=4, payment_type_id=7, summa=1300.0),  # карта
    ],
)

Типы данных

class autodealer.actions.payment.WalletInfo
wallet_id: int
name: str
organization_id: int
class autodealer.actions.payment.PaymentTypeInfo
payment_type_id: int
name: str
class autodealer.actions.payment.PaymentRecord
payment_id: int
summa: Decimal
payment_date: datetime
payment_type_id: int
payment_type_name: str | None
wallet_id: int | None
wallet_name: str | None
notes: str | None
class autodealer.actions.payment.PaymentSplitItem
wallet_id: int
payment_type_id: int
summa: float
notes: str | None