Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC
This commit is contained in:
7
directive_common/models/__init__.py
Normal file
7
directive_common/models/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from . import project_task
|
||||
from . import sale_order
|
||||
from . import directive_directive
|
||||
from . import account_move
|
||||
from . import account_payment
|
||||
from . import mrp_workorder
|
||||
from . import stock_picking
|
||||
16
directive_common/models/account_move.py
Normal file
16
directive_common/models/account_move.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_name = "account.move"
|
||||
_inherit = ["account.move", "directive.mixin"]
|
||||
|
||||
def action_audit_response(self, payload: dict):
|
||||
"""
|
||||
Вызывается агентом-аудитором.
|
||||
"""
|
||||
for move in self:
|
||||
move.message_post(
|
||||
body=f"Audit Bot: Обнаружен риск, 30/100.<br/>"
|
||||
f"Директива #{payload.get('directive_id')} завершена с предупреждением."
|
||||
)
|
||||
17
directive_common/models/account_payment.py
Normal file
17
directive_common/models/account_payment.py
Normal file
@@ -0,0 +1,17 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class AccountPayment(models.Model):
|
||||
_name = 'account.payment'
|
||||
_inherit = ["account.payment", "directive.mixin"]
|
||||
|
||||
def action_bank_gateway_response(self, payload: dict):
|
||||
for pay in self:
|
||||
bank_ref = f"REF-{pay.id}-X99"
|
||||
|
||||
pay.message_post(
|
||||
body=f"Bank Gateway: Платеж отправлен в банк.<br/>"
|
||||
f"Bank Reference: {bank_ref}<br/>"
|
||||
f"Комиссия агента: 0.00 у.е."
|
||||
)
|
||||
return True
|
||||
37
directive_common/models/directive_directive.py
Normal file
37
directive_common/models/directive_directive.py
Normal file
@@ -0,0 +1,37 @@
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from odoo.addons.directive_layer.models.directive_constants import (
|
||||
STAGE_DRAFT,
|
||||
STAGE_PLANNED,
|
||||
STAGE_IN_PROGRESS,
|
||||
STAGE_DONE,
|
||||
)
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Directive(models.Model):
|
||||
_inherit = "directive.directive"
|
||||
|
||||
@api.model
|
||||
def _cron_simulate_system_agents(self):
|
||||
"""
|
||||
Этот метод имитирует работу внешних систем (WMS, Банк, AI).
|
||||
Запускается раз в минуту.
|
||||
"""
|
||||
system_directives = self.search([
|
||||
('executor_type', 'in', ['software', 'machine']),
|
||||
('stage_code', 'in', [STAGE_DRAFT, STAGE_PLANNED, STAGE_IN_PROGRESS]),
|
||||
('stage_code', '!=', STAGE_DONE)
|
||||
], limit=50)
|
||||
|
||||
for d in system_directives:
|
||||
|
||||
if d.stage_code == STAGE_PLANNED:
|
||||
d._set_stage(STAGE_IN_PROGRESS)
|
||||
_logger.info("Agent started directive %s", d.id)
|
||||
|
||||
elif d.stage_code == STAGE_IN_PROGRESS:
|
||||
d.action_done()
|
||||
_logger.info("Agent finished directive %s", d.id)
|
||||
68
directive_common/models/mrp_workorder.py
Normal file
68
directive_common/models/mrp_workorder.py
Normal file
@@ -0,0 +1,68 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class MrpWorkorder(models.Model):
|
||||
_name = "mrp.workorder"
|
||||
_inherit = ["mrp.workorder", "directive.mixin"]
|
||||
|
||||
def action_iot_signal(self, payload: dict):
|
||||
"""
|
||||
Метод-обработчик завершения директивы оборудованием.
|
||||
Записывает телеметрию в саму операцию и в головной заказ (MO).
|
||||
"""
|
||||
for wo in self:
|
||||
telemetry = payload.get('telemetry', {})
|
||||
temp = telemetry.get('temperature', 59)
|
||||
vibro = telemetry.get('vibration', 'Норма')
|
||||
|
||||
message = (
|
||||
f"IoT CNC [{wo.name}]: Операция завершена.<br/>"
|
||||
f"Температура шпинделя: {temp}°C<br/>"
|
||||
f"Вибрация: {vibro}."
|
||||
)
|
||||
|
||||
if wo.production_id:
|
||||
wo.production_id.message_post(
|
||||
body=f"Отчет по операции {wo.name}: {message}"
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
class MrpProduction(models.Model):
|
||||
_inherit = 'mrp.production'
|
||||
|
||||
def action_choose_directive_group(self):
|
||||
"""Открывает визард выбора группы директив для первой операции заказа.
|
||||
|
||||
У `mrp.production` нет собственного directive.origin, поэтому визард
|
||||
открывается для первой операции (workorder_ids[:1]) — в типовом
|
||||
сценарии MO имеет одну ключевую операцию. Внешний контракт (кнопка на
|
||||
форме mrp.production открывает визард выбора группы) сохраняется.
|
||||
"""
|
||||
self.ensure_one()
|
||||
|
||||
workorder = self.workorder_ids[:1]
|
||||
|
||||
if not workorder:
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'display_notification',
|
||||
'params': {
|
||||
'title': 'Внимание',
|
||||
'message': 'Сначала подтвердите заказ, чтобы появились операции (Work Orders)',
|
||||
'type': 'warning',
|
||||
'sticky': False,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"name": f"Назначить директивы для: {workorder.name}",
|
||||
"res_model": "directive.choose.group.wizard",
|
||||
"view_mode": "form",
|
||||
"target": "new",
|
||||
"context": {
|
||||
"active_model": "mrp.workorder",
|
||||
"active_id": workorder.id,
|
||||
},
|
||||
}
|
||||
19
directive_common/models/project_task.py
Normal file
19
directive_common/models/project_task.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class ProjectTask(models.Model):
|
||||
_name = 'project.task'
|
||||
_inherit = ["project.task", "directive.mixin"]
|
||||
|
||||
def directive_on_done_post_message(self, payload: dict):
|
||||
for task in self:
|
||||
task.message_post(
|
||||
body=f"Директива выполнена: {payload.get('directive_name')})"
|
||||
)
|
||||
return True
|
||||
|
||||
def action_demo_directive_callback(self):
|
||||
for task in self:
|
||||
task.message_post(body="Demo callback executed")
|
||||
self._directive_run_callback_policies("action_demo_directive_callback")
|
||||
return True
|
||||
18
directive_common/models/sale_order.py
Normal file
18
directive_common/models/sale_order.py
Normal file
@@ -0,0 +1,18 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class SaleOrder(models.Model):
|
||||
_name = 'sale.order'
|
||||
_inherit = ["sale.order", "directive.mixin"]
|
||||
|
||||
def action_wms_response(self, payload: dict):
|
||||
for order in self:
|
||||
bin_location = "ZONE-A-ROW-5"
|
||||
|
||||
order.message_post(
|
||||
body=f"WMS Агент: Товар зарезервирован.<br/>"
|
||||
f"Ячейка: {bin_location}<br/>"
|
||||
f"Директива #{payload.get('directive_id')} закрыта успешно."
|
||||
)
|
||||
|
||||
return True
|
||||
24
directive_common/models/stock_picking.py
Normal file
24
directive_common/models/stock_picking.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from odoo import models
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_name = 'stock.picking'
|
||||
_inherit = ["stock.picking", "directive.mixin"]
|
||||
|
||||
def button_validate(self):
|
||||
res = super().button_validate()
|
||||
# Сохраняем семантику старого monkey-patch wrapper: политика срабатывала
|
||||
# ТОЛЬКО если метод не вернул False, и НЕ должна срабатывать на промежуточном
|
||||
# возврате экшена-визарда (backorder / immediate transfer), т.к. в этот момент
|
||||
# перемещение ещё не проведено.
|
||||
if res is not False and not (isinstance(res, dict) and res.get("type") == "ir.actions.act_window"):
|
||||
self._directive_run_callback_policies("button_validate")
|
||||
return res
|
||||
|
||||
def action_agv_callback(self, payload: dict):
|
||||
for picking in self:
|
||||
picking.message_post(
|
||||
body="AGV Unit 01: Доставка в зону производства выполнена.<br/>"
|
||||
"Батарея: 84%."
|
||||
)
|
||||
return True
|
||||
Reference in New Issue
Block a user