diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 719ac481..48144622 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -668,7 +668,7 @@ class Manufacturing_Connect(http.Controller): logging.info('AGVDownProduct error:%s' % e) return json.JSONEncoder().encode(res) - @http.route('/AutoDeviceApi/AgvStationState', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, + @http.route('/AutoDeviceApi/AgvStationState', type='json', auth='public', methods=['GET', 'POST'], csrf=False, cors="*") def AGVStationState(self, **kw): """ diff --git a/sf_manufacturing/models/agv_scheduling.py b/sf_manufacturing/models/agv_scheduling.py index 488fa0a0..f758abd9 100644 --- a/sf_manufacturing/models/agv_scheduling.py +++ b/sf_manufacturing/models/agv_scheduling.py @@ -270,6 +270,7 @@ class ResMrpWorkOrder(models.Model): """ 获取关联的制造订单下产线的agv任务 """ + self.ensure_one() workorder_ids = self.production_id.workorder_ids cnc_workorder = workorder_ids.filtered( lambda w: w.routing_type == 'CNC加工' and w.state == 'done' and w.processing_panel == self.processing_panel diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 2e77bcdd..997e2ba3 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1361,23 +1361,23 @@ class ResMrpWorkOrder(models.Model): return res def button_delivery(self): - production_ids = [] - workorder_ids = [] + # production_ids = [] + # workorder_ids = [] delivery_type = '运送空料架' - max_num = 4 # 最大配送数量 - feeder_station_start_id = False - if len(self) > max_num: - raise UserError('仅限于拆卸1-4个制造订单,请重新选择') - for item in self: - if item.state != 'ready': - raise UserError('请选择状态为【就绪】的工单进行解除装夹') - - production_ids.append(item.production_id.id) - workorder_ids.append(item.id) - if not feeder_station_start_id: - down_product_agv_scheduling = self.get_down_product_agv_scheduling() - if down_product_agv_scheduling: - feeder_station_start_id = down_product_agv_scheduling.end_site_id.id + # max_num = 4 # 最大配送数量 + # feeder_station_start_id = False + # if len(self) > max_num: + # raise UserError('仅限于拆卸1-4个制造订单,请重新选择') + # for item in self: + # if item.state != 'ready': + # raise UserError('请选择状态为【就绪】的工单进行解除装夹') + # + # production_ids.append(item.production_id.id) + # workorder_ids.append(item.id) + # if not feeder_station_start_id: + # down_product_agv_scheduling = item.get_down_product_agv_scheduling() + # if down_product_agv_scheduling: + # feeder_station_start_id = down_product_agv_scheduling.end_site_id.id return { 'name': _('确认'), 'type': 'ir.actions.act_window', @@ -1386,12 +1386,12 @@ class ResMrpWorkOrder(models.Model): 'target': 'new', 'context': { # 'default_delivery_ids': [(6, 0, delivery_ids)], - 'default_production_ids': [(6, 0, production_ids)], + # 'default_production_ids': [(6, 0, production_ids)], 'default_delivery_type': delivery_type, - 'default_workorder_ids': [(6, 0, workorder_ids)], + # 'default_workorder_ids': [(6, 0, workorder_ids)], 'default_workcenter_id': self.env.context.get('default_workcenter_id'), 'default_confirm_button': '确认解除', - 'default_feeder_station_start_id': feeder_station_start_id, + # 'default_feeder_station_start_id': feeder_station_start_id, }} diff --git a/sf_manufacturing/wizard/workpiece_delivery_views.xml b/sf_manufacturing/wizard/workpiece_delivery_views.xml index 699fff53..e895d39e 100644 --- a/sf_manufacturing/wizard/workpiece_delivery_views.xml +++ b/sf_manufacturing/wizard/workpiece_delivery_views.xml @@ -18,8 +18,8 @@ diff --git a/sf_manufacturing/wizard/workpiece_delivery_wizard.py b/sf_manufacturing/wizard/workpiece_delivery_wizard.py index f00ac499..4ee0928c 100644 --- a/sf_manufacturing/wizard/workpiece_delivery_wizard.py +++ b/sf_manufacturing/wizard/workpiece_delivery_wizard.py @@ -1,9 +1,8 @@ # -*- coding: utf-8 -*- # Part of YiZuo. See LICENSE file for full copyright and licensing details. -import json import logging -from odoo.exceptions import UserError, ValidationError from datetime import datetime, date +from odoo.exceptions import UserError from odoo import models, api, fields @@ -79,29 +78,18 @@ class WorkpieceDeliveryWizard(models.TransientModel): 'tag': 'display_notification', 'target': 'new', 'params': { - 'message': '任务下发成功!AGV任务调度编号为【%s】' % scheduling['name'], + 'message': f'任务下发成功!AGV任务调度编号为【{scheduling["name"]}】', 'type': 'success', 'sticky': False, 'next': {'type': 'ir.actions.act_window_close'}, } } + def confirm(self): try: - # if self.workorder_id: - # self.workorder_id.workpiece_delivery_ids[0].agv_scheduling_id() - # else: - # is_not_production_line = 0 - # same_production_line_id = None - # notsame_production_line_arr = [] - # for item in self.production_ids: - # if same_production_line_id is None: - # same_production_line_id = item.production_line_id.id - # if item.production_line_id.id != same_production_line_id: - # notsame_production_line_arr.append(item.name) - # notsame_production_line_str = ','.join(map(str, notsame_production_line_arr)) - # if is_not_production_line >= 1: - # raise UserError('制造订单号为%s的目的生产线不一致' % notsame_production_line_str) - # else: + if not self.workorder_ids: + raise UserError('制造订单不能为空') + scheduling = self.env['sf.agv.scheduling'].add_scheduling( agv_start_site_name=self.feeder_station_start_id.name, agv_route_type=self.delivery_type, @@ -129,10 +117,21 @@ class WorkpieceDeliveryWizard(models.TransientModel): item.button_start() item.button_finish() - return scheduling.read()[0] + # return scheduling.read()[0] + return { + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'target': 'new', + 'params': { + 'message': f'任务下发成功!AGV任务调度编号为【{scheduling.name}】', + 'type': 'success', + 'sticky': False, + 'next': {'type': 'ir.actions.act_window_close'}, + } + } except Exception as e: - logging.info('%s任务下发失败:%s' % (self.delivery_type, e)) - raise UserError('%s任务下发失败:%s' % (self.delivery_type, e)) + logging.info('%s任务下发失败:%s', self.delivery_type, e) + raise UserError(f'{self.delivery_type}任务下发失败:{e}') from e # def recognize_production(self): # # production_ids = [] @@ -185,7 +184,11 @@ class WorkpieceDeliveryWizard(models.TransientModel): # 判断是否是AGV接驳站名称 agv_site = self.env['sf.agv.site'].search([('name', '=', barcode)]) if agv_site: - self.feeder_station_start_id = agv_site.id + if not self.feeder_station_start_id: + self.feeder_station_start_id = agv_site.id + else: + if self.feeder_station_start_id.id != agv_site.id: + raise UserError('起点接驳站不匹配!') return delivery_type = self.env.context.get('default_delivery_type') if delivery_type == '上产线': @@ -205,16 +208,20 @@ class WorkpieceDeliveryWizard(models.TransientModel): if workorder: if (len(self.production_ids) > 0 and workorder.production_line_id.id != self.production_ids[0].production_line_id.id): - raise UserError('该rfid对应的制造订单号为%s的目的生产线不一致' % workorder.production_id.name) + raise UserError(f'该rfid对应的制造订单号为{workorder.production_id.name}的目的生产线不一致') # 将对象添加到对应的同模型且是多对多类型里 self.production_ids |= workorder.production_id self.workorder_ids |= workorder - if not self.feeder_station_start_id: - down_product_agv_scheduling = self.get_down_product_agv_scheduling() - if down_product_agv_scheduling: + down_product_agv_scheduling = self.get_down_product_agv_scheduling() + if down_product_agv_scheduling: + if not self.feeder_station_start_id: self.feeder_station_start_id = down_product_agv_scheduling.end_site_id.id + else: + if self.feeder_station_start_id.id != down_product_agv_scheduling.end_site_id.id: + raise UserError(f'该rfid不在{self.feeder_station_start_id.name}接驳站内') + else: raise UserError('该rfid码对应的工单不存在') return diff --git a/sf_tool_management/models/__init__.py b/sf_tool_management/models/__init__.py index e4f2a622..c39b6763 100644 --- a/sf_tool_management/models/__init__.py +++ b/sf_tool_management/models/__init__.py @@ -10,4 +10,5 @@ from . import temporary_data_processing_methods from . import stock from . import jikimo_bom from . import tool_inventory -from . import functional_cutting_tool_model \ No newline at end of file +from . import functional_cutting_tool_model +# from . import product_product \ No newline at end of file diff --git a/sf_tool_management/models/functional_cutting_tool_model.py b/sf_tool_management/models/functional_cutting_tool_model.py index db04b762..fe2c68c5 100644 --- a/sf_tool_management/models/functional_cutting_tool_model.py +++ b/sf_tool_management/models/functional_cutting_tool_model.py @@ -3,4 +3,4 @@ from odoo import models, fields class SyncFunctionalCuttingToolModel(models.Model): _inherit = 'sf.functional.cutting.tool.model' - cutting_tool_type_ids = fields.Many2many('sf.cutting.tool.type', string='刀具物料类型') \ No newline at end of file + cutting_tool_type_ids = fields.Many2many('sf.cutting.tool.type', string='适用刀具物料类型', required=True) \ No newline at end of file diff --git a/sf_tool_management/models/jikimo_bom.py b/sf_tool_management/models/jikimo_bom.py index 627a8892..29ef1605 100644 --- a/sf_tool_management/models/jikimo_bom.py +++ b/sf_tool_management/models/jikimo_bom.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- +from collections import Counter from xml import etree from odoo import models, fields, api, Command -from odoo.exceptions import UserError +from odoo.exceptions import UserError, AccessError from odoo.http import request @@ -28,6 +29,26 @@ class jikimo_bom(models.Model): result.append((bom.id, '功能刀具物料清单')) return result + def check_types_in_list(self): + # 统计每个元素的类型 + type_counts = Counter(item.cutting_tool_material_id.name for item in self.product_ids) + return all(count > 0 for count in type_counts.values()) and len(type_counts) == self.options.split('+') + + def write(self, vals): + # 在更新模型时记录旧的 Many2many ID 列表 + if 'product_ids' in vals: + old_product_counter = Counter(self.product_ids.ids) + super(jikimo_bom, self).write(vals) + new_product_counter = Counter(self.product_ids.ids) + delete_product_counter = old_product_counter - new_product_counter + if delete_product_counter: + # 删除操作 + if self.check_types_in_list(): + return True + else: + raise UserError('每种物料最少要有一个') + return super(jikimo_bom, self).write(vals) + def bom_product_domains(self, assembly_options): self.options = assembly_options cutting_tool_materials = self.env['sf.cutting.tool.material'].search( @@ -65,6 +86,7 @@ class jikimo_bom(models.Model): # product = self.env['product.product'].search(domain) # if product: # products = products + product + domains = domains + [('stock_move_count', '>', 0)] return domains def generate_bill_materials(self, assembly_options): @@ -88,6 +110,16 @@ class jikimo_bom_line(models.Model): class ProductProduct(models.Model): _inherit = 'product.product' + _order = 'cutting_tool_material_id, cutting_tool_type_id' + stock_move_count = fields.Integer(string='stock_move count', compute='_compute_stock_move_count', store=True) + + @api.depends('stock_move_ids') + def _compute_stock_move_count(self): + for record in self: + if record.stock_move_ids: + record.stock_move_count = len(record.stock_move_ids) + else: + record.stock_move_count = 0 def search(self, args, offset=0, limit=None, order=None, count=False): # 你可以在这里修改 `args` 以调整搜索条件 diff --git a/sf_tool_management/models/tool_inventory.py b/sf_tool_management/models/tool_inventory.py index db15834a..5b27c9aa 100644 --- a/sf_tool_management/models/tool_inventory.py +++ b/sf_tool_management/models/tool_inventory.py @@ -5,10 +5,10 @@ from odoo.http import request class ToolInventory(models.Model): _inherit = 'sf.tool.inventory' _description = '功能刀具清单' - knife_handle_model = fields.Selection([('BT30', 'BT30'), ('BT40', 'BT40'), ('BT50', 'BT50'), ('GSK30', 'GSK30'), ('GSK40', 'GSK40'), ('GSK50', 'GSK50')], string='使用刀柄型号') + knife_handle_model = fields.Selection([('BT30', 'BT30'), ('BT40', 'BT40'), ('BT50', 'BT50'), ('GSK30', 'GSK30'), ('GSK40', 'GSK40'), ('GSK50', 'GSK50')], string='使用刀柄型号', required=True) jikimo_bom_ids = fields.One2many('jikimo.bom','tool_inventory_id', 'bom单') + blade_length = fields.Float('刃长(mm)') def bom_mainfest(self): - jikimo_bom_ids = self.mapped('jikimo_bom_ids') if not jikimo_bom_ids: self._bom_mainfest() diff --git a/sf_tool_management/views/jikimo_bom.xml b/sf_tool_management/views/jikimo_bom.xml index 90e3232e..c42af591 100644 --- a/sf_tool_management/views/jikimo_bom.xml +++ b/sf_tool_management/views/jikimo_bom.xml @@ -35,11 +35,12 @@ + + - diff --git a/sf_tool_management/views/tool_inventory.xml b/sf_tool_management/views/tool_inventory.xml index f7fbc6b5..68efbca3 100644 --- a/sf_tool_management/views/tool_inventory.xml +++ b/sf_tool_management/views/tool_inventory.xml @@ -5,7 +5,7 @@ sf.tool.inventory - +