Домен: Документы / Заказ-наряды

Создание и чтение заказ-нарядов (document_out) и связанных цепочек записей.

Схема связей

document_out  (document_type_id=11, client_id, summa=0, flag=2, date_accept)
    │
    ├── service_work × N           ← строки услуг (см. два режима ниже)
    │
    ├── document_cargo             ← плательщик документа (payer_id = client_id)
    │
    └── document_registry          ← метазапись (аудит: кто создал, когда)
            │
            └── document_out_header  (номер, дата, prefix="АВТ", state=2)
                    │
                    └── document_service_detail  ← привязка авто (обязательно)

ORM-модели

DocumentOut

Таблица document_out — основная запись документа.

Поле

Тип

Описание

document_out_id

int PK

Первичный ключ; возвращается из create_service_order

document_type_id

int FK

Тип документа (11=Заказ-наряд)

client_id

int FK

Клиент

organization_id

int FK

Организация-исполнитель

summa

Decimal

Сумма товаров, не общая. NOT NULL, для заказ-наряда услуг (автомойка) = 0. UI считает итог как summa + document_service_detail.summa_work.

flag

int

Константа 2 у всех ручных заказ-нарядов АвтоМойки.

summa_bonus

Decimal

Бонусы к начислению (дефолт 0).

date_accept

datetime

Дата/время приёма / окончания работ

date_payment

datetime

Дата оплаты (обновляется при create_payment)

DocumentRegistry

Таблица document_registry — метазапись для каждого документа (аудит + связь с платежами).

Поле

Тип

Описание

document_registry_id

int PK

Первичный ключ

metatable_id

int

Тип сущности (12=document_out)

create_user_id

int FK

Кто создал

create_date

datetime

Когда создал

change_user_id

int FK

Кто изменил последним

change_date

datetime

Когда изменил

document_type_id_cache

int FK

Кэш типа документа

DocumentOutHeader

Таблица document_out_header — заголовок документа (номер, дата, исполнитель).

Поле

Тип

Описание

document_out_header_id

int PK

Первичный ключ

document_out_id

int FK

Ссылка на document_out

document_registry_id

int FK

Ссылка на document_registry

document_out_tree_id

int FK

Папка документов

user_id

int FK

Исполнитель

prefix

str(5)

Префикс номера ("АВТ")

number

int

Порядковый номер

suffix

str(5)

Суффикс номера (напр. "К")

fullnumber

str(21)

Вычисляемое поле: prefix + number + suffix (COMPUTED BY в Firebird)

date_create

datetime

Дата создания документа

state

int

Статус: 2=Черновик, 4=Оформлен, -1=Удалён

notes

text

Примечание

DocumentServiceDetail

Таблица document_service_detail — деталь услуги: привязка авто + сумма работ. Создаётся всегда; client_car у create_service_order()обязательный параметр.

Поле

Тип

Описание

document_service_detail_id

int PK

Первичный ключ

document_out_header_id

int FK

Заголовок документа

model_link_id

int FK

Привязка авто клиента (model_link.model_link_id)

summa_work

Decimal

Сумма услуг. UI прибавляет к document_out.summa для итога.

price_norm_id

int FK

Норма цены, у всех ручных = 5 (price_norm.price = 1).

discount_work

float

Скидка на работы (дефолт 0).

summa_bonus

Decimal

Бонусы за работу (дефолт 0).

doc_date_end_section_link

int

Константа 1 у всех ручных заказов АвтоМойки.

guarante

text

Текст гарантии (стандартный шаблон).

DocumentCargo

Таблица document_cargo — реквизиты плательщика документа (не про груз, несмотря на имя). У всех ручных заказ-нарядов АвтоМойки заполнена; create_service_order создаёт её автоматически.

Поле

Тип

Описание

document_cargo_id

int PK

Первичный ключ

document_out_id

int FK

Документ

payer_id

int FK

Плательщик (client.client_id; у заказов АвтоМойки равен document_out.client_id)

update_sender / update_receiver / update_payer

int

Флаги актуализации реквизитов (константно = 1)

use_main_payment

int

Использовать основной способ оплаты (константно = 0)

ServiceWork

Таблица service_work — строки услуг в заказ-наряде. Существует два режима записи: справочный (привязка к service_complex_work) и ручной. Выбор определяется наличием complex_work_id в ServiceOrderItem.

Поле

Тип

Описание

service_work_id

int PK

Первичный ключ

document_out_id

int FK

Заказ-наряд

name

str(255)

Справочный режим: каноническое имя ("Стандарт", "Комплекс"). Ручной режим: произвольное имя (напр. длинное из RW).

price

Decimal

Справочный режим: цена за единицу. Ручной режим: NULL — цена уходит в time_value.

time_value

Decimal

Справочный режим: NULL. Ручной режим: цена за единицу (UI считает time_value × price_norm как итог; при price_norm=NULL показывает 0, поэтому в любом режиме ставим price_norm=1).

price_norm

Decimal

Множитель для UI-расчёта итога. Всегда 1.

rt_work_id

int

FK в справочник работ. При work_source=3service_complex_work.service_complex_work_id, при work_source=2service_common_work.service_common_work_id, при NULL — ручной ввод.

work_source

int

Тип справочника: 3 — комплексные работы, 2 — общий каталог, NULL — ручной ввод.

quantity

int

Количество (по умолчанию 1)

position_number

int

Порядок строки

external_id

str(512)

Внешний ID (напр. из RocketWash — services.id)

DocumentOutTree

Таблица document_out_tree — иерархия папок для документов реализации.

from autodealer.domain.document_out_tree import DocumentOutTree

folders = DocumentOutTree.objects.filter(hidden=0).all()
# document_out_tree_id=3 → «АвтоМойка»

Высокоуровневые функции (services)

create_service_order

autodealer.services.create_service_order(*, client_id, items, document_out_tree_id, organization_id, client_car, date_start, date_finish, created_by_user_id=1, notes=None, service_order_suffix=None)

Создать заказ-наряд. Все записи — в одной транзакции.

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

  • items (list[ServiceOrderItem]) – Строки услуг. Не может быть пустым.

  • document_out_tree_id (int) – Папка документов.

  • organization_id (int) – Организация-исполнитель.

  • client_car (int) – model_link_idобязателен. При None функция выбрасывает ValueError.

  • date_start (datetime) – Дата начала.

  • date_finish (datetime) – Дата окончания / приёма.

  • created_by_user_id (int) – Исполнитель (по умолчанию 1).

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

  • service_order_suffix (str) – Суффикс номера (напр. "К").

Результат:

document_out_id.

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

int

Исключение:

ValueError – Если items пустой или client_car не передан.

from datetime import datetime, timedelta
from autodealer.services import create_service_order, ServiceOrderItem

now = datetime.now()
doc_id = create_service_order(
    client_id=920,
    organization_id=1,
    document_out_tree_id=3,
    date_start=now,
    date_finish=now + timedelta(hours=1),
    client_car=959,
    notes="Комплексная мойка",
    service_order_suffix="К",
    items=[
        ServiceOrderItem("Комплекс",    price=2300.0, time_value=90, external_id="821460"),
        ServiceOrderItem("Вторая Фаза", price=800.0,  time_value=20, external_id="821462"),
    ],
)

delete_service_order / restore_service_order

autodealer.services.delete_service_order(document_out_id, *, hard=False)

Удалить заказ-наряд.

  • Soft (hard=False, по умолчанию): ставит document_out_header.state = -1 («Удалён»). Документ скрывается в UI АвтоДилера, но данные сохраняются.

  • Hard (hard=True): физически удаляет всю цепочку записей в одной транзакции — document_cargoservice_workdocument_service_detaildocument_out_headerdocument_registrydocument_out. Перед этим авто-удаляются «ботовые» платежи (с маркером BOT_NOTE_MARKER в payment.notes). Если на документе есть ручные платежи — функция выбрасывает ValueError.

Исключение:

ValueError – Документ не найден; при hard=True — привязаны ручные платежи.

autodealer.services.restore_service_order(document_out_id, *, state=2)

Парная операция к soft-delete. Переводит document_out_header.state из -1 обратно в рабочее (по умолчанию 2 — «Черновик»). Отказывает, если текущий state ≠ -1, чтобы не понизить/повысить state живого документа.

get_service_order

autodealer.services.get_service_order(document_out_id)

Прочитать заказ-наряд со строками услуг.

Результат:

ServiceOrder или None.

order = get_service_order(42)
print(order.summa, order.date_accept)
for item in order.items:
    print(item.name, item.price)
class autodealer.services.ServiceOrderItem

Одна строка услуги в заказ-наряде. Два режима записи в service_work (см. ServiceWork выше):

name: str

Имя работы. В справочном режиме — каноническое из service_complex_work.name ("Стандарт", "Комплекс").

price: float

Цена за единицу. Попадает в service_work.price (справочный режим) или service_work.time_value (ручной режим).

time_value: float

Длительность (минуты). Справочная информация, в БД не сохраняется — в service_work нет отдельного поля под длительность.

quantity: int = 1
external_id: str | None

Напр. "821459"services.id из RocketWash.

complex_work_id: int | None = None

PK в service_complex_work. Если задан — включает «справочный» режим записи: rt_work_id = complex_work_id, work_source = 3. Ищется через autodealer.integration.rocketwash.resolve_complex_work().

class autodealer.services.ServiceOrder
document_out_id: int
client_id: int | None
summa: float
date_accept: datetime | None
date_payment: datetime | None
document_number: int | None
client_car: int | None
items: list[ServiceOrderItem]

Константы

Константа

Значение

Описание

document_type_id

11

Заказ-наряд

prefix

"АВТ"

Префикс номера

state (Черновик)

2

Статус при создании

metatable_id

12

document_registry.metatable_id