Введение
В Odoo всё бизнес‑данные организованы в моделях — это ярлыки для таблиц базы: куда и как сохранять заказы, счета и остатки. Модель определяет структуру записей, типы полей и связи между объектами, поэтому правильный дизайн моделей критичен для стабильной работы системы.
Понимание моделей важно и для консультантов, и для разработчиков: именно на уровне моделей прописывается логика, проверки, вычисляемые суммы и связи между документами. Чем лучше вы понимаете модель, тем быстрее настроите бизнес‑правила, отчёты и интеграции.
В этой заметке мы разберём одну из ключевых моделей Odoo — purchase.order. Она лежит в основе закупочных процессов: настройка согласований, интеграция с поставщиками, автоматизация приёма товаров и связка с бухгалтерией часто опираются именно на неё.
Что такое модель purchase.order
Модель purchase.order отвечает за заявки на закупку и запросы котировок (RFQ). В ней аккумулируются все позиции, суммы и статусы до тех пор, пока заказ не превратится в приёмку или счёт поставщика.
Модель используется модулем «Закупки»: когда покупатель создаёт RFQ, он получает запись purchase.order. При подтверждении от поставщика (или ручном подтверждении) статус меняется с черновика на подтверждённый. В одном и том же объекте хранятся как черновые RFQ, так и окончательные заказы — поле состояния управляет жизненным циклом.
Другие модули дополняют purchase.order через наследование: склад добавляет приёмки и перемещения, бухгалтерия — поля для счёта‑фактуры, производство — создание заявок под BOM. Каждый модуль расширяет модель, не дублируя базовую структуру.
Ключевые поля модели
Ниже — список ключевых полей purchase.order, которые важно знать. Это поможет правильно настраивать процессы и писать кастомную логику.
1. name
Тип: Char. Номер заказа (например PO00042). Обычно генерируется автоматически и служит основным идентификатором в списках и печатных бланках.
2. state
Тип: Selection. Отражает этап: draft (черновик/RFQ), sent (отправлен поставщику), to approve (ожидает одобрения), purchase (подтверждён), done (полностью обработан), cancel (отменён). От состояния зависят доступные действия.
3. partner_id
Тип: Many2one (res.partner). Поставщик. Обязательное поле — основной контакт или компания по заказу; применяется во всех отчётах и правилах учёта поставщиков.
4. partner_ref
Тип: Char. Номер заказа поставщика — его внутренняя ссылка. Полезно для сверки приходов и счётов и для отображения в документах.
5. date_order
Тип: Datetime. Дата заказа: в черновиках — дата создания, в подтверждённых — дата подтверждения. Используется в отчётности и планировании сроков по позициям.
6. date_approve
Тип: Datetime. Дата подтверждения/одобрения заказа. Устанавливается при переходе в состояние purchase; обычно только для чтения и важна для аудита.
7. order_line
Тип: One2many (purchase.order.line). Строки заказа: товар, количество, цена, налоги. Это детальная часть заказа, от которой считаются суммы и создаются приходные операции.
8. amount_untaxed
Тип: Float. Сумма без налогов. Вычисляется по строкам заказа; нужна для отображения и отчётов.
9. amount_tax
Тип: Float. Сумма налогов. Рассчитывается по налоговым настройкам строк; показывается в заказе и на счёте поставщика.
10. amount_total
Тип: Float. Общая сумма с налогами. Ключевая величина для выставления счётов и аналитики.
11. currency_id
Тип: Many2one (res.currency). Валюта заказа; обычно наследуется от компании или поставщика. Все денежные поля привязаны к этой валюте.
12. origin
Тип: Char. Источник документа: номер продажной заявки, производственного ордера и т.д. Нужен для прослеживаемости операций между модулями.
13. dest_address_id
Тип: Many2one (res.partner). Адрес доставки. Если не указан — адрес компании по умолчанию. В дропшиппинге указывает адрес конечного клиента.
14. priority
Тип: Selection. Приоритет заказа — Normal или Urgent. Помогает сортировать и выделять заказы, которым требуется ускоренная обработка.
15. invoice_status
Тип: Selection. Статус выставления счёта: no (нет), to invoice (к выставлению), invoiced (выполнено). Определяет доступность действий «Создать счёт».
16. invoice_count
Тип: Integer. Число связанных счетов поставщика. Вычисляемое поле для быстрого перехода к документам в учёте.
17. invoice_ids
Тип: One2many (account.move). Связанные бухгалтерские документы поставщика. Нужны для трёхстороннего сопоставления и контроля оплат.
18. picking_ids
Тип: One2many (stock.picking). Связанные приёмки/отгрузки. Появляются при установке модуля Склад и привязаны к закупке.
19. picking_count
Тип: Integer. Количество связанных приёмок. Вычисляется автоматически и служит для перехода к списку приходов.
20. create_date
Тип: Datetime. Время создания записи. Устанавливается системой и полезно для аудита и отчётности.
21. write_date
Тип: Datetime. Время последнего изменения записи. Тоже ведётся автоматически и помогает отслеживать обновления.
22. notes
Тип: Text. Коммерческие условия или внутренние заметки. Могут попадать в печатные формы и служат инструкциями для поставщика.
23. company_id
Тип: Many2one (res.company). В многофирменной конфигурации указывает, к какой компании принадлежит заказ. Влияет на права доступа и видимость записей.
24. user_id
Тип: Many2one (res.users). Отвественный пользователь или закупщик. Используется в процессах согласования и при назначении задач.
25. fiscal_position_id
Тип: Many2one (account.fiscal.position). Фискальная позиция для перекартирования налогов (например, при международных поставках).
26. payment_term_id
Тип: Many2one (account.payment.term). Условия оплаты — аванс, NET30 и т.д. Переносится в счёт при выставлении.
27. display_name
Тип: Char. Вычисляемое отображаемое имя: обычно сочетание номера заказа и данных поставщика. Используется в выпадающих списках и поиске.
28. active
Тип: Boolean. Флаг «активности» — при False запись архивируется и скрывается от обычных представлений. Историю заказов обычно не удаляют физически.
Как модель используется в бизнес‑процессах
1. От RFQ к подтверждённому заказу
Покупатель создаёт RFQ в статусе черновика, добавляет строки и отправляет поставщику. После подтверждения поставщиком (или ручного подтверждения) статус меняется на purchase, и можно создавать приходные операции и счета.
2. Приёмка товара
При поступлении товаров по заказу создаётся приходная операция, связанная с purchase.order через picking_ids. Полученные количества обновляют запасы, и на основе цены закупки пересчитывается себестоимость товара.
3. Счёт поставщика
Из подтверждённого заказа создаётся счёт поставщика: строки счёта подтягиваются из строк заказа, условия оплаты и фискальная позиция наследуются, а поле invoice_status показывает прогресс выставления счёта.
4. Дропшиппинг
Когда продажа инициирует закупку, поле origin хранит номер исходной продажи, а dest_address_id указывает адрес клиента — тогда поставщик отгружает товар напрямую конечному покупателю. purchase.order связывает продажи и закупки в этой цепочке.
5. Производство и MRP
Если производственный ордер требует закупки компонентов, он может создавать purchase.order для сырья, а origin ссылается на номер производственного документа. Модель — центральный узел в цепочке procure‑to‑pay.
Как разработчики расширяют эту модель
Разработчики расширяют purchase.order разными способами, но основным инструментом остаётся наследование моделей Odoo.
Наследование модели
В коде используют _inherit = 'purchase.order' чтобы дописать поля, изменить методы или добавить проверки. Такое расширение удобно поддерживать отдельно — оно проще переносится при обновлениях ядра.
Добавление полей
В собственном модуле объявляйте новые поля нужного типа: Char, Many2one, Boolean, Integer, Text, Selection. Для мультикомпаний учитывайте зависимости и делайте поля company‑dependent, если нужно.
Расширения на Python
Переопределяйте методы вроде button_confirm, create или write чтобы добавить бизнес‑логику, при этом всегда вызывайте super(), чтобы не ломать поведение других модулей. Особое внимание — вычисляемым полям и их зависимостям.
Odoo Studio
Studio позволяет быстро добавить поля через интерфейс без кода — удобно для прототипов. Но для серьёзной логики и безопасных обновлений лучше писать модули. API модели доступен через XML‑RPC и JSON‑RPC для интеграций.
Рекомендуемые практики
- Используйте корректные статусы для каждого шага и не пропускайте обязательные переходы — это сохраняет консистентность данных.
- Фиксируйте partner_ref, когда поставщик даёт свой номер — это облегчает сверку приходов и оплат.
- Заполняйте origin для простого трассирования источника заказа — особенно важно при дропшиппинге и производственных сценариях.
- Для интеграций используйте XML‑RPC или JSON‑RPC и аккуратно сопоставляйте внешние идентификаторы, чтобы избежать дублирования записей.
- Для пользовательских полей применяйте префиксы типа x_ или префикс модуля, чтобы минимизировать конфликты при обновлениях Odoo.
Распространённые ошибки
- Изменение уже подтверждённого заказа без проверки состояния. У подтверждённых заказов ряд полей ограничен — при необходимости создавайте новый заказ или следуйте корректному workflow.
- Путаница partner_id и dest_address_id: partner_id — это поставщик, dest_address_id — адрес доставки (например, клиент при дропшиппинге).
- Переопределение button_confirm без вызова super() — такой код ломает логику других модулей и затрудняет апгрейды.
- Добавление обязательных пользовательских полей без значений по умолчанию — старые записи могут не пройти валидацию при обновлении системы.
- Забывание указать currency_id при работе с мультивалютными поставщиками — ведёт к неверным расчётам стоимости и ошибкам в учёте.
Заключение
Модель purchase.order является ядром модуля Закупок в Odoo: в ней хранятся и RFQ, и подтверждённые заказы. Знание её полей и того, как она расширяется модулями, помогает правильно настраивать процессы и интеграции.
Независимо от вашей роли — консультант или разработчик — глубокое понимание purchase.order экономит время, уменьшает количество ошибок и упрощает сопровождение решений.
Нужна помощь с внедрением Odoo?
Dasolo помогает компаниям внедрять и дорабатывать Odoo: мы выполняем интеграции по API, разрабатываем модули и оптимизируем архитектуру данных, включая работу с моделями вроде purchase.order.
Если нужна помощь с внедрением Odoo, разработкой модулей или интеграцией — мы готовы подключиться и проконсультировать. Запланировать демо чтобы обсудить ваш проект.