From 0a4c86f6013a34591db07bbb8539d242d3698118 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 9 Apr 2024 13:38:13 +0800 Subject: [PATCH 01/12] =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7?= =?UTF-8?q?=E6=B8=85=E5=8D=95=E6=B7=BB=E5=8A=A0=E5=88=80=E5=85=B7=E7=BB=84?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/models/tool_base_new.py | 2 ++ sf_base/views/tool_views.xml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py index e3b737f0..d442639b 100644 --- a/sf_base/models/tool_base_new.py +++ b/sf_base/models/tool_base_new.py @@ -327,4 +327,6 @@ class ToolInventory(models.Model): blade_number = fields.Integer('刃数(个)') extension = fields.Float('伸出长度(mm)') + tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组') + active = fields.Boolean('已归档', default=True) diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml index 25d1824f..13f3da8d 100644 --- a/sf_base/views/tool_views.xml +++ b/sf_base/views/tool_views.xml @@ -557,6 +557,7 @@ + @@ -580,6 +581,7 @@ + From 961b4f8e2df39afe8a9b795689eb2a99a0db3c87 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Tue, 9 Apr 2024 15:21:47 +0800 Subject: [PATCH 02/12] =?UTF-8?q?=E5=BA=93=E5=AD=98=E9=9C=80=E6=B1=82?= =?UTF-8?q?=E4=BF=AE=E6=94=B91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_warehouse/models/model.py | 57 +++++++++++++------ .../views/change_stock_move_views.xml | 16 ++++-- sf_warehouse/views/shelf_location.xml | 1 + 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 347fd658..63a02e0d 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -310,7 +310,7 @@ class SfShelf(models.Model): class ShelfLocation(models.Model): _name = 'sf.shelf.location' _description = '货位' - _order = 'create_date desc' + _order = 'id asc, create_date asc' # current_location_id = fields.Many2one('sf.shelf.location', string='当前位置') # # 目的位置 @@ -363,8 +363,10 @@ class ShelfLocation(models.Model): ('禁用', '禁用') ], string='货位状态', default='空闲', readonly=True) # product_id = fields.Many2one('product.template', string='产品') - product_id = fields.Many2one('product.product', string='产品', readonly=True) + product_id = fields.Many2one('product.product', string='产品', compute='_compute_product_id', store=True) product_sn_id = fields.Many2one('stock.lot', string='产品序列号') + # 产品数量 + product_num = fields.Integer('数量') # 修改货位状态为禁用 def action_location_status_disable(self): @@ -381,12 +383,20 @@ class ShelfLocation(models.Model): """ for record in self: if record.product_sn_id: - record.sudo().product_id = record.product_sn_id.product_id - record.sudo().location_status = '占用' + try: + record.sudo().product_id = record.product_sn_id.product_id + record.sudo().location_status = '占用' + record.sudo().product_num = 1 + except Exception as e: + print('eeeeeee占用', e) else: - record.product_id = False - # record.location_status = '空闲' + try: + record.sudo().product_id = False + record.sudo().location_status = '空闲' + record.sudo().product_num = 0 + except Exception as e: + print('eeeeeee空闲', e) # 调取获取货位信息接口 def get_sf_shelf_location_info(self): @@ -423,6 +433,8 @@ class Sf_stock_move_line(models.Model): location_dest_id_value = fields.Integer(compute='_compute_location_dest_id_value', store=True) # lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True) lot_qr_code = fields.Binary(string='二维码', compute='_compute_lot_qr_code', store=True) + current_product_id = fields.Integer(compute='_compute_location_dest_id_value', store=True) + there_is_no_sn = fields.Boolean('是否有序列号', default=False) def action_revert_inventory(self): # 检查用户是否有执行操作的权限 @@ -692,6 +704,7 @@ class Sf_stock_move_line(models.Model): def _compute_location_dest_id_value(self): for record in self: record.location_dest_id_value = record.location_dest_id.id if record.location_dest_id else False + record.current_product_id = record.product_id.id if record.product_id else False destination_location_id = fields.Many2one( 'sf.shelf.location', string='目标货位') @@ -699,23 +712,31 @@ class Sf_stock_move_line(models.Model): @api.onchange('destination_location_id') def _compute_destination_location_id(self): for record in self: - shelf_location_obj = self.env['sf.shelf.location'].search( - [('product_sn_id', '=', record.lot_id.id)]) - if shelf_location_obj: - shelf_location_obj.product_sn_id = False - # obj = self.env['sf.shelf.location'].search([('location_id', '=', - # self.destination_location_id.id)]) - obj = self.env['sf.shelf.location'].search([('name', '=', - self.destination_location_id.name)]) - if obj: - obj.product_sn_id = record.lot_id.id + if record.lot_id: + shelf_location_obj = self.env['sf.shelf.location'].search( + [('product_sn_id', '=', record.lot_id.id)]) + if shelf_location_obj: + shelf_location_obj.product_sn_id = False + # obj = self.env['sf.shelf.location'].search([('location_id', '=', + # self.destination_location_id.id)]) + obj = self.env['sf.shelf.location'].search([('name', '=', + self.destination_location_id.name)]) + if obj: + obj.product_sn_id = record.lot_id.id + else: + pass else: - pass + obj = self.env['sf.shelf.location'].search([('name', '=', + self.destination_location_id.name)]) + if obj: + obj.product_sn_id = record.lot_id.id else: obj = self.env['sf.shelf.location'].search([('name', '=', self.destination_location_id.name)]) if obj: - obj.product_sn_id = record.lot_id.id + obj.product_id = record.product_id.id + obj.location_status = '占用' + obj.product_num = record.reserved_uom_qty class SfStockPicking(models.Model): diff --git a/sf_warehouse/views/change_stock_move_views.xml b/sf_warehouse/views/change_stock_move_views.xml index cc4213c6..c9db5059 100644 --- a/sf_warehouse/views/change_stock_move_views.xml +++ b/sf_warehouse/views/change_stock_move_views.xml @@ -10,10 +10,18 @@ - + + + + + + + + + + diff --git a/sf_warehouse/views/shelf_location.xml b/sf_warehouse/views/shelf_location.xml index 49fdf42e..9cd4446a 100644 --- a/sf_warehouse/views/shelf_location.xml +++ b/sf_warehouse/views/shelf_location.xml @@ -149,6 +149,7 @@ + From 85649daef666fa783d154201ab76114784c6616c Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 9 Apr 2024 16:53:15 +0800 Subject: [PATCH 03/12] =?UTF-8?q?1=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80?= =?UTF-8?q?=E5=85=B7=E6=B8=85=E5=8D=95=E6=A8=A1=E5=9E=8B=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=B1=BB=E5=9E=8B=E3=80=81?= =?UTF-8?q?=E5=8A=A0=E5=B7=A5=E6=9D=90=E6=96=99=E3=80=81=E5=AF=BF=E5=91=BD?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=9B2=E3=80=81=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E4=BE=9B=E5=BA=94=E5=95=86=E7=9A=84=E5=9C=B0=E5=9D=80=E5=92=8C?= =?UTF-8?q?email=E5=BF=85=E5=A1=AB=EF=BC=9B3=E3=80=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=BB=84=E8=A3=85=E5=8D=95?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=EF=BC=8C=E6=96=B0=E5=A2=9E=E4=BA=94=E7=A7=8D?= =?UTF-8?q?=E7=89=A9=E6=96=99=E7=9A=84=E8=B4=A7=E4=BD=8D=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E7=BB=A7=E6=89=BF=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=A0=B9=E6=8D=AE=E8=B4=A7=E4=BD=8D?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=8A=9F=E8=83=BD=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/models/tool_base_new.py | 3 + sf_base/views/tool_views.xml | 15 ++-- sf_mrs_connect/models/sync_common.py | 2 - sf_sale/views/res_partner_view.xml | 10 +-- sf_tool_management/wizard/wizard.py | 90 +++++++++++++++-------- sf_tool_management/wizard/wizard_view.xml | 40 ++++------ 6 files changed, 94 insertions(+), 66 deletions(-) diff --git a/sf_base/models/tool_base_new.py b/sf_base/models/tool_base_new.py index d442639b..f2010b4a 100644 --- a/sf_base/models/tool_base_new.py +++ b/sf_base/models/tool_base_new.py @@ -316,6 +316,7 @@ class ToolInventory(models.Model): name = fields.Char('功能刀具名称', required=True) type = fields.Char('类型') + functional_cutting_tool_model_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型') prefix = fields.Char('前缀') postfix = fields.Char('后缀') diameter = fields.Float('直径(mm)') @@ -326,6 +327,8 @@ class ToolInventory(models.Model): cutter_number = fields.Char('刀号') blade_number = fields.Integer('刃数(个)') extension = fields.Float('伸出长度(mm)') + work_material = fields.Selection([('钢', '钢'), ('铝', '铝')], string='加工材料') + life_span = fields.Float('寿命(h)') tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组') diff --git a/sf_base/views/tool_views.xml b/sf_base/views/tool_views.xml index 13f3da8d..e52a6222 100644 --- a/sf_base/views/tool_views.xml +++ b/sf_base/views/tool_views.xml @@ -556,20 +556,23 @@ - + - - + + + + - + + @@ -580,8 +583,10 @@ - + + + diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py index 3ee916e7..81cd05de 100644 --- a/sf_mrs_connect/models/sync_common.py +++ b/sf_mrs_connect/models/sync_common.py @@ -52,8 +52,6 @@ class MrStaticResourceDataSync(models.Model): logging.info("夹具型号已每日同步成功") self.env['sf.fixture.materials.basic.parameters'].sync_fixture_materials_basic_parameters_yesterday() logging.info("夹具型号基本参数已每日同步成功") - self.env['sf.functional.fixture.type'].sync_fixture_materials_basic_parameters_yesterday() - logging.info("夹具型号基本参数已每日同步成功") self.env['sf.functional.fixture.type'].sync_functional_fixture_type_yesterday() logging.info("功能夹具类型已每日同步成功") self.env['sf.cutting.tool.material'].sync_cutting_tool_material_yesterday() diff --git a/sf_sale/views/res_partner_view.xml b/sf_sale/views/res_partner_view.xml index 4b2d55d6..cc8f49fb 100644 --- a/sf_sale/views/res_partner_view.xml +++ b/sf_sale/views/res_partner_view.xml @@ -26,7 +26,7 @@ + attrs="{'readonly': [('id','!=', False)]}"/> {'required': [('phone', '=', False)],'readonly': [('id','!=', False)]} @@ -37,19 +37,19 @@ - {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]} + {'readonly': [('id','!=', False)]} - {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]} + {'readonly': [('id','!=', False)]} - {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]} + {'readonly': [('id','!=', False)]} - {'required': [('supplier_rank','>', 0)],'readonly': [('id','!=', False)]} + {'readonly': [('id','!=', False)]} diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index 36bb310d..d736ad53 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -222,72 +222,104 @@ class FunctionalToolAssemblyOrder(models.TransientModel): image = fields.Binary('图片') # 功能刀具组装信息 - # 整体式刀具型号 + # ===============整体式刀具型号================= + integral_freight_barcode = fields.Char('整体式刀具货位') integral_code_id = fields.Many2one('stock.lot', string='整体式刀具序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '整体式刀具'), ('tool_material_status', '=', '可用')]) + integral_product_id = fields.Many2one('product.product', string='整体式刀具名称', + compute='_compute_integral_product_id', store=True) cutting_tool_integral_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='整体式刀具型号', - related='integral_code_id.product_id.cutting_tool_model_id') - integral_name = fields.Char('整体式刀具名称', related='integral_code_id.product_id.name') + related='integral_product_id.cutting_tool_model_id') integral_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='整体式刀具规格', - related='integral_code_id.product_id.specification_id') + related='integral_product_id.specification_id') sf_tool_brand_id_1 = fields.Many2one('sf.machine.brand', string='整体式刀具品牌', - related='integral_code_id.product_id.brand_id') + related='integral_product_id.brand_id') - # 刀片型号 + @api.depends('integral_freight_barcode') + def _compute_integral_product_id(self): + pass + + # ===============刀片型号==================== + blade_freight_barcode = fields.Char('刀片货位') blade_code_id = fields.Many2one('stock.lot', '刀片序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '刀片'), ('tool_material_status', '=', '可用')]) + blade_product_id = fields.Many2one('product.product', string='刀片名称', compute='_compute_blade_product_id', + store=True) cutting_tool_blade_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀片型号', - related='blade_code_id.product_id.cutting_tool_model_id') - blade_name = fields.Char('刀片名称', related='blade_code_id.product_id.name') + related='blade_product_id.cutting_tool_model_id') blade_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀片规格', - related='blade_code_id.product_id.specification_id') - sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', related='blade_code_id.product_id.brand_id') + related='blade_product_id.specification_id') + sf_tool_brand_id_2 = fields.Many2one('sf.machine.brand', '刀片品牌', related='blade_product_id.brand_id') - # 刀杆型号 + @api.depends('blade_freight_barcode') + def _compute_blade_product_id(self): + pass + + # ====================刀杆型号================== + bar_freight_barcode = fields.Char('刀杆货位') bar_code_id = fields.Many2one('stock.lot', '刀杆序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '刀杆'), ('tool_material_status', '=', '可用')]) + bar_product_id = fields.Many2one('product.product', string='刀杆名称', compute='_compute_bar_product_id', + store=True) cutting_tool_cutterbar_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀杆型号', - related='bar_code_id.product_id.cutting_tool_model_id') - bar_name = fields.Char('刀杆名称', related='bar_code_id.product_id.name') + related='bar_product_id.cutting_tool_model_id') bar_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀杆规格', - related='bar_code_id.product_id.specification_id') - sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', related='bar_code_id.product_id.brand_id') + related='bar_product_id.specification_id') + sf_tool_brand_id_3 = fields.Many2one('sf.machine.brand', '刀杆品牌', related='bar_product_id.brand_id') - # 刀盘型号 + @api.depends('bar_freight_barcode') + def _compute_bar_product_id(self): + pass + + # ===============刀盘型号=================== + pad_freight_barcode = fields.Char('刀盘货位') pad_code_id = fields.Many2one('stock.lot', '刀盘序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '刀盘'), ('tool_material_status', '=', '可用')]) + pad_product_id = fields.Many2one('product.product', string='刀盘名称', compute='_compute_pad_product_id', + store=True) cutting_tool_cutterpad_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀盘型号', - related='pad_code_id.product_id.cutting_tool_model_id') - pad_name = fields.Char('刀盘名称', related='pad_code_id.product_id.name') + related='pad_product_id.cutting_tool_model_id') pad_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀盘规格', - related='pad_code_id.product_id.specification_id') - sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', related='pad_code_id.product_id.brand_id') + related='pad_product_id.specification_id') + sf_tool_brand_id_4 = fields.Many2one('sf.machine.brand', '刀盘品牌', related='pad_product_id.brand_id') - # 刀柄型号 + @api.depends('pad_freight_barcode') + def _compute_pad_product_id(self): + pass + + # ================刀柄型号=============== handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', required=True, domain=[('product_id.cutting_tool_material_id.name', '=', '刀柄'), ('tool_material_status', '=', '可用')]) + handle_product_id = fields.Many2one('product.product', string='刀柄名称', related='handle_code_id.product_id') cutting_tool_cutterhandle_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='刀柄型号', related='handle_code_id.product_id.cutting_tool_model_id') - handle_name = fields.Char('刀柄名称', related='handle_code_id.product_id.name') handle_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='刀柄规格', related='handle_code_id.product_id.specification_id') sf_tool_brand_id_5 = fields.Many2one('sf.machine.brand', '刀柄品牌', related='handle_code_id.product_id.brand_id') - # 夹头型号 - chuck_code_id = fields.Many2one('stock.lot', '夹头序列号', required=True, + # =================夹头型号============== + chuck_freight_barcode = fields.Char('夹头货位', required=True) + chuck_code_id = fields.Many2one('stock.lot', '夹头序列号', domain=[('product_id.cutting_tool_material_id.name', '=', '夹头'), ('tool_material_status', '=', '可用')]) + chuck_product_id = fields.Many2one('product.product', string='夹头名称', compute='_compute_chuck_product_id', + store=True) cutting_tool_cutterhead_model_id = fields.Many2one('sf.cutting_tool.standard.library', string='夹头型号', - related='chuck_code_id.product_id.cutting_tool_model_id') - chuck_name = fields.Char('夹头名称', related='chuck_code_id.product_id.name') + related='chuck_product_id.cutting_tool_model_id') chuck_specification_id = fields.Many2one('sf.tool.materials.basic.parameters', string='夹头规格', - related='chuck_code_id.product_id.specification_id') - sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', related='chuck_code_id.product_id.brand_id') + related='chuck_product_id.specification_id') + sf_tool_brand_id_6 = fields.Many2one('sf.machine.brand', '夹头品牌', related='chuck_product_id.brand_id') + + @api.depends('chuck_freight_barcode') + def _compute_chuck_product_id(self): + pass + + # ======================================== def on_barcode_scanned(self, barcode): """ @@ -437,7 +469,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel): else: obj.after_assembly_functional_tool_name = '' - @api.onchange('integral_code_id') + @api.onchange('integral_freight_barcode') def _onchange_after_assembly_functional_tool_diameter(self): for obj in self: if obj.integral_code_id: diff --git a/sf_tool_management/wizard/wizard_view.xml b/sf_tool_management/wizard/wizard_view.xml index a1b35664..912f7dcf 100644 --- a/sf_tool_management/wizard/wizard_view.xml +++ b/sf_tool_management/wizard/wizard_view.xml @@ -201,20 +201,18 @@ + attrs="{'invisible': ['|','|',('blade_freight_barcode', '!=', False),('bar_freight_barcode', '!=', False),('pad_freight_barcode', '!=', False)]}">
- + - + @@ -223,20 +221,18 @@
- +
- + - + @@ -246,20 +242,18 @@ + attrs="{'invisible': ['|',('integral_freight_barcode', '!=', False),('pad_freight_barcode', '!=', False)]}">
- + - + @@ -269,20 +263,18 @@ + attrs="{'invisible': ['|',('bar_freight_barcode', '!=', False),('bar_freight_barcode', '!=', False)]}">
- + - + @@ -304,7 +296,7 @@ - + @@ -319,14 +311,12 @@ - + - + From f19a1a282a0bca6bc893fa6e117e7beae3450dac Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 9 Apr 2024 17:27:37 +0800 Subject: [PATCH 04/12] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E5=BD=95=E5=85=A5=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/wizard/wizard.py | 111 ++++++++++++---------------- 1 file changed, 47 insertions(+), 64 deletions(-) diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index d736ad53..303c87d5 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -238,7 +238,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('integral_freight_barcode') def _compute_integral_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.integral_freight_barcode)]) + if location: + self.integral_product_id = location.product_id.id # ===============刀片型号==================== blade_freight_barcode = fields.Char('刀片货位') @@ -255,7 +257,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('blade_freight_barcode') def _compute_blade_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.blade_freight_barcode)]) + if location: + self.blade_product_id = location.product_id.id # ====================刀杆型号================== bar_freight_barcode = fields.Char('刀杆货位') @@ -272,7 +276,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('bar_freight_barcode') def _compute_bar_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.bar_freight_barcode)]) + if location: + self.bar_product_id = location.product_id.id # ===============刀盘型号=================== pad_freight_barcode = fields.Char('刀盘货位') @@ -289,7 +295,9 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('pad_freight_barcode') def _compute_pad_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.pad_freight_barcode)]) + if location: + self.pad_product_id = location.product_id.id # ================刀柄型号=============== handle_code_id = fields.Many2one('stock.lot', '刀柄序列号', required=True, @@ -317,69 +325,44 @@ class FunctionalToolAssemblyOrder(models.TransientModel): @api.depends('chuck_freight_barcode') def _compute_chuck_product_id(self): - pass + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.chuck_freight_barcode)]) + if location: + self.chuck_product_id = location.product_id.id # ======================================== def on_barcode_scanned(self, barcode): """ - 智能工厂组装单处扫码绑定刀具物料') + 智能工厂组装单处扫码绑定刀具物料 """ for record in self: - if 'DJWL' in barcode: - lot_ids = record.env['stock.lot'].sudo().search([('name', '=', barcode)]) - if not lot_ids: - raise ValidationError('扫描的条形码数据不存在,请重新扫描!') - for lot_id in lot_ids: - if lot_id.quant_ids[-1].location_id.name == '刀具组装位置': - raise ValidationError('该刀具物料已使用,请重新扫描!!!') - elif lot_id.quant_ids[-1].location_id.name not in '刀具房': - raise ValidationError('该刀具物料未入库,请重新扫描!!!') - tool_material_name = lot_id.product_id.cutting_tool_material_id.name - if tool_material_name == '整体式刀具': - record.integral_code_id = lot_id.id - elif tool_material_name == '刀片': - record.blade_code_id = lot_id.id - elif tool_material_name == '刀杆': - record.bar_code_id = lot_id.id - elif tool_material_name == '刀盘': - record.pad_code_id = lot_id.id - elif tool_material_name == '刀柄': - record.handle_code_id = lot_id.id - record.chuck_code_id = record.get_chuck_code_id(lot_id).id or False - elif tool_material_name == '夹头': - record.chuck_code_id = lot_id.id - else: - raise ValidationError('扫描的刀具物料不存在,请重新扫描!') - else: - lot_ids = self.env['stock.lot'].sudo().search([('rfid', '=', barcode)]) - if not lot_ids: - raise ValidationError('扫描的刀具物料不存在,请重新扫描!') + lot_ids = self.env['stock.lot'].sudo().search([('rfid', '=', barcode)]) + if lot_ids: for lot_id in lot_ids: if lot_id.quant_ids[-1].location_id.name in '刀具房': record.handle_code_id = lot_id.id - record.chuck_code_id = record.get_chuck_code_id(lot_id).id or False elif lot_id.quant_ids[-1].location_id.name == '刀具组装位置': raise ValidationError('该刀柄已使用,请重新扫描!!!') else: raise ValidationError('该刀柄未入库,请重新扫描!!!') - - def get_chuck_code_id(self, lot_id): - # 适用夹头型号 - cutting_tool_chuck_id = lot_id.product_id.cutting_tool_chuck_id - # 适用夹头尺寸 - fit_chuck_size = lot_id.product_id.cutting_tool_fit_chuck_size - # 适用夹头产品 - chuck_product_id = self.env['product.product'].sudo().search( - [('cutting_tool_model_id', '=', cutting_tool_chuck_id.id), - ('cutting_tool_er_size_model', '=', fit_chuck_size)]) - # 适用夹头产品序列号 - chuck_product_lot_ids = self.env['stock.lot'].sudo().search( - [('product_id', '=', chuck_product_id.id), ('tool_material_status', '=', '可用')]) - for chuck_product_lot_id in chuck_product_lot_ids: - if chuck_product_lot_id.quant_ids[-1].location_id.name in '刀具房': - return chuck_product_lot_id - return False + else: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', barcode)]) + if location: + material_name = location.product_id.cutting_tool_material_id.name + if material_name == '整体式刀具': + record.integral_freight_barcode = barcode + elif material_name == '刀片': + record.blade_freight_barcode = barcode + elif material_name == '刀杆': + record.bar_freight_barcode = barcode + elif material_name == '刀盘': + record.pad_freight_barcode = barcode + elif material_name == '夹头': + record.chuck_freight_barcode = barcode + else: + raise ValidationError('扫描的刀具物料不存在,请重新扫描!') + else: + raise ValidationError('扫描的刀具物料不存在,请重新扫描!') @api.depends('handle_code_id') def _compute_rfid(self): @@ -605,12 +588,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): 'name': self.after_assembly_functional_tool_name, 'rfid': self.rfid, 'tool_groups_id': self.tool_groups_id.id, - 'integral_code_id': self.integral_code_id.id, - 'blade_code_id': self.blade_code_id.id, - 'bar_code_id': self.bar_code_id.id, - 'pad_code_id': self.pad_code_id.id, + 'integral_product_id': self.integral_product_id.id, + 'blade_product_id': self.blade_product_id.id, + 'bar_product_id': self.bar_product_id.id, + 'pad_product_id': self.pad_product_id.id, 'handle_code_id': self.handle_code_id.id, - 'chuck_code_id': self.chuck_code_id.id, + 'chuck_product_id': self.chuck_product_id.id, 'after_assembly_functional_tool_name': self.after_assembly_functional_tool_name, 'after_assembly_functional_tool_type_id': self.after_assembly_functional_tool_type_id.id, @@ -645,12 +628,12 @@ class FunctionalToolAssemblyOrder(models.TransientModel): 'tool_groups_id': self.tool_groups_id.id, 'functional_tool_name_id': functional_tool_assembly_id.id, 'sf_cutting_tool_type_id': self.after_assembly_functional_tool_type_id.id, - 'cutting_tool_integral_model_id': self.integral_code_id.product_id.id, - 'cutting_tool_blade_model_id': self.blade_code_id.product_id.id, - 'cutting_tool_cutterbar_model_id': self.bar_code_id.product_id.id, - 'cutting_tool_cutterpad_model_id': self.pad_code_id.product_id.id, - 'cutting_tool_cutterhandle_model_id': self.handle_code_id.product_id.id, - 'cutting_tool_cutterhead_model_id': self.chuck_code_id.product_id.id, + 'cutting_tool_integral_model_id': self.integral_product_id.id, + 'cutting_tool_blade_model_id': self.blade_product_id.id, + 'cutting_tool_cutterbar_model_id': self.bar_product_id.id, + 'cutting_tool_cutterpad_model_id': self.pad_product_id.id, + 'cutting_tool_cutterhandle_model_id': self.handle_product_id.id, + 'cutting_tool_cutterhead_model_id': self.chuck_product_id.id, 'functional_tool_diameter': self.after_assembly_functional_tool_diameter, 'knife_tip_r_angle': self.after_assembly_knife_tip_r_angle, From 310a2de34f5e8a8fb2abfca022c0aa27be6b2c01 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Tue, 9 Apr 2024 20:14:44 +0800 Subject: [PATCH 05/12] =?UTF-8?q?=E5=BC=80=E5=AE=8C=E5=BA=93=E5=AD=98?= =?UTF-8?q?=E5=A4=84=E6=96=B0=E5=A2=9E=E9=9C=80=E6=B1=82=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_warehouse/models/model.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 63a02e0d..1e1d8328 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -132,7 +132,7 @@ class SfLocation(models.Model): for record in self: if record.product_sn_id: record.product_id = record.product_sn_id.product_id - record.location_status = '占用' + # record.location_status = '占用' else: record.product_id = False # record.location_status = '空闲' @@ -361,13 +361,21 @@ class ShelfLocation(models.Model): ('空闲', '空闲'), ('占用', '占用'), ('禁用', '禁用') - ], string='货位状态', default='空闲', readonly=True) + ], string='货位状态', default='空闲', compute='_compute_product_num', store=True) # product_id = fields.Many2one('product.template', string='产品') product_id = fields.Many2one('product.product', string='产品', compute='_compute_product_id', store=True) product_sn_id = fields.Many2one('stock.lot', string='产品序列号') # 产品数量 product_num = fields.Integer('数量') + @api.depends('product_num') + def _compute_product_num(self): + for record in self: + if record.product_num > 0: + record.location_status = '占用' + elif record.product_num == 0: + record.location_status = '空闲' + # 修改货位状态为禁用 def action_location_status_disable(self): self.location_status = '禁用' @@ -385,7 +393,7 @@ class ShelfLocation(models.Model): if record.product_sn_id: try: record.sudo().product_id = record.product_sn_id.product_id - record.sudo().location_status = '占用' + # record.sudo().location_status = '占用' record.sudo().product_num = 1 except Exception as e: print('eeeeeee占用', e) @@ -393,7 +401,7 @@ class ShelfLocation(models.Model): else: try: record.sudo().product_id = False - record.sudo().location_status = '空闲' + # record.sudo().location_status = '空闲' record.sudo().product_num = 0 except Exception as e: print('eeeeeee空闲', e) @@ -735,8 +743,8 @@ class Sf_stock_move_line(models.Model): self.destination_location_id.name)]) if obj: obj.product_id = record.product_id.id - obj.location_status = '占用' - obj.product_num = record.reserved_uom_qty + # obj.location_status = '占用' + obj.product_num += record.reserved_uom_qty class SfStockPicking(models.Model): @@ -761,8 +769,11 @@ class SfStockPicking(models.Model): for line in self.move_line_ids: if line: if line.current_location_id: - line.current_location_id.product_sn_id = False - line.current_location_id.location_status = '空闲' + if line.current_location_id.product_sn_id: + line.current_location_id.product_sn_id = False + # line.current_location_id.location_status = '空闲' + line.current_location_id.product_num = 0 + return res # def print_all_barcode(self): From eb2db1dfdd8bc2cbb7084eb375b22f035b23120e Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Fri, 12 Apr 2024 17:30:59 +0800 Subject: [PATCH 06/12] =?UTF-8?q?1=E3=80=81=E6=B7=BB=E5=8A=A0=E5=AE=9A?= =?UTF-8?q?=E6=97=B6=E5=90=8C=E6=AD=A5=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99?= =?UTF-8?q?=E5=92=8C=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=9A=84=E4=BF=A1=E6=81=AF=E5=88=B0cloud=E7=9A=84=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=EF=BC=9B2=E3=80=81=E6=B7=BB=E5=8A=A0=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E6=89=80=E4=BB=A5=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99?= =?UTF-8?q?=E5=92=8C=E6=89=80=E4=BB=A5=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E8=AE=B0=E5=BD=95=E5=90=8C=E6=AD=A5=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/__manifest__.py | 1 + sf_tool_management/data/tool_data.xml | 14 ++- .../models/functional_tool_enroll.py | 99 ++++++++++++++++++- 3 files changed, 108 insertions(+), 6 deletions(-) diff --git a/sf_tool_management/__manifest__.py b/sf_tool_management/__manifest__.py index a7750f69..fe65c05e 100644 --- a/sf_tool_management/__manifest__.py +++ b/sf_tool_management/__manifest__.py @@ -21,6 +21,7 @@ 'views/menu_view.xml', 'views/tool_material_search.xml', 'views/fixture_material_search_views.xml', + 'data/tool_data.xml', ], 'demo': [ ], diff --git a/sf_tool_management/data/tool_data.xml b/sf_tool_management/data/tool_data.xml index 714d03ee..282f8c2a 100644 --- a/sf_tool_management/data/tool_data.xml +++ b/sf_tool_management/data/tool_data.xml @@ -1,8 +1,12 @@ - - - - - + + 定时同步刀具物料、功能刀具信息到cloud + + code + model._cron_tool_datasync_all() + 1 + days + -1 + \ No newline at end of file diff --git a/sf_tool_management/models/functional_tool_enroll.py b/sf_tool_management/models/functional_tool_enroll.py index 8fb781f8..6f49af02 100644 --- a/sf_tool_management/models/functional_tool_enroll.py +++ b/sf_tool_management/models/functional_tool_enroll.py @@ -1,9 +1,10 @@ import json import base64 import requests +import logging from odoo import models, api from odoo.addons.sf_base.commons.common import Common -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError def get_suitable_machining_method_names(item): @@ -30,6 +31,30 @@ def get_suitable_coolant_names(item): return suitable_coolant_names +class ToolDatasync(models.Model): + _name = 'sf.tool.datasync' + _description = '定时同步所有刀具' + + def _cron_tool_datasync_all(self): + try: + self.env['stock.lot'].sudo().sync_enroll_tool_material_stock_all() + logging.info("刀具物料序列号每日同步成功") + self.env['sf.tool.material.search'].sudo().sync_enroll_tool_material_all() + logging.info("刀具物料每日同步成功") + self.env['sf.functional.cutting.tool.entity'].sudo().esync_enroll_functional_tool_entity_all() + logging.info("功能刀具列表每日同步成功") + self.env['sf.functional.tool.warning'].sudo().sync_enroll_functional_tool_warning_all() + logging.info("功能刀具列表每日同步成功") + self.env['stock.move.line'].sudo().sync_enroll_functional_tool_move_all() + logging.info("功能刀具出入库记录每日同步成功") + self.env[ + 'sf.real.time.distribution.of.functional.tools'].sudo().sync_enroll_functional_tool_real_time_distribution_all() + logging.info("功能刀具安全库存每日同步成功") + except Exception as e: + logging.info("捕获错误信息:%s" % e) + raise ValidationError("数据错误导致同步失败,请联系管理员") + + class StockLot(models.Model): _inherit = 'stock.lot' _description = '刀具物料序列号注册' @@ -41,6 +66,18 @@ class StockLot(models.Model): headers = Common.get_headers(self, token, sf_secret_key) str_url = sf_sync_config['sf_url'] + "/api/tool_material_stock/create" objs_all = self.env['stock.lot'].search([('id', '=', self.id), ('active', 'in', [True, False])]) + self._get_sync_stock_lot(objs_all, str_url, token, headers) + + def sync_enroll_tool_material_stock_all(self): + sf_sync_config = self.env['res.config.settings'].get_values() + token = sf_sync_config['token'] + sf_secret_key = sf_sync_config['sf_secret_key'] + headers = Common.get_headers(self, token, sf_secret_key) + str_url = sf_sync_config['sf_url'] + "/api/tool_material_stock/create" + objs_all = self.env['stock.lot'].search([('rfid', '!=', False)]) + self._get_sync_stock_lot(objs_all, str_url, token, headers) + + def _get_sync_stock_lot(self, objs_all, str_url, token, headers): tool_material_stock_list = [] if objs_all: for item in objs_all: @@ -73,6 +110,18 @@ class ToolMaterial(models.Model): headers = Common.get_headers(self, token, sf_secret_key) str_url = sf_sync_config['sf_url'] + self.crea_url objs_all = self.search([('id', '=', self.id)]) + self._get_sync_tool_material_search(objs_all, str_url, token, headers) + + def sync_enroll_tool_material_all(self): + sf_sync_config = self.env['res.config.settings'].get_values() + token = sf_sync_config['token'] + sf_secret_key = sf_sync_config['sf_secret_key'] + headers = Common.get_headers(self, token, sf_secret_key) + str_url = sf_sync_config['sf_url'] + self.crea_url + objs_all = self.search([]) + self._get_sync_tool_material_search(objs_all, str_url, token, headers) + + def _get_sync_tool_material_search(self, objs_all, str_url, token, headers): tool_material_list = [] if objs_all: for item in objs_all: @@ -120,6 +169,18 @@ class FunctionalCuttingToolEntity(models.Model): headers = Common.get_headers(self, token, sf_secret_key) str_url = sf_sync_config['sf_url'] + self.crea_url objs_all = self.env['sf.functional.cutting.tool.entity'].search([('id', '=', self.id)]) + self._get_sync_functional_cutting_tool_entity(objs_all, str_url, token, headers) + + def esync_enroll_functional_tool_entity_all(self): + sf_sync_config = self.env['res.config.settings'].get_values() + token = sf_sync_config['token'] + sf_secret_key = sf_sync_config['sf_secret_key'] + headers = Common.get_headers(self, token, sf_secret_key) + str_url = sf_sync_config['sf_url'] + self.crea_url + objs_all = self.env['sf.functional.cutting.tool.entity'].search([]) + self._get_sync_functional_cutting_tool_entity(objs_all, str_url, token, headers) + + def _get_sync_functional_cutting_tool_entity(self, objs_all, str_url, token, headers): functional_tool_list = [] if objs_all: for item in objs_all: @@ -201,6 +262,18 @@ class FunctionalToolWarning(models.Model): headers = Common.get_headers(self, token, sf_secret_key) str_url = sf_sync_config['sf_url'] + self.crea_url objs_all = self.env['sf.functional.tool.warning'].search([('id', '=', self.id)]) + self.get_sync_functional_tool_warning(objs_all, str_url, token, headers) + + def sync_enroll_functional_tool_warning_all(self): + sf_sync_config = self.env['res.config.settings'].get_values() + token = sf_sync_config['token'] + sf_secret_key = sf_sync_config['sf_secret_key'] + headers = Common.get_headers(self, token, sf_secret_key) + str_url = sf_sync_config['sf_url'] + self.crea_url + objs_all = self.env['sf.functional.tool.warning'].search([]) + self.get_sync_functional_tool_warning(objs_all, str_url, token, headers) + + def get_sync_functional_tool_warning(self, objs_all, str_url, token, headers): tool_warning_list = [] if objs_all: for item in objs_all: @@ -262,6 +335,18 @@ class StockMoveLine(models.Model): headers = Common.get_headers(self, token, sf_secret_key) str_url = sf_sync_config['sf_url'] + self.crea_url objs_all = self.env['stock.move.line'].search([('id', '=', self.id), ('functional_tool_name_id', '!=', False)]) + self.get_sync_stock_move_line(objs_all, str_url, token, headers) + + def sync_enroll_functional_tool_move_all(self): + sf_sync_config = self.env['res.config.settings'].get_values() + token = sf_sync_config['token'] + sf_secret_key = sf_sync_config['sf_secret_key'] + headers = Common.get_headers(self, token, sf_secret_key) + str_url = sf_sync_config['sf_url'] + self.crea_url + objs_all = self.env['stock.move.line'].search([('functional_tool_name_id', '!=', False)]) + self.get_sync_stock_move_line(objs_all, str_url, token, headers) + + def get_sync_stock_move_line(self, objs_all, str_url, token, headers): tool_stock_list = [] if objs_all: for item in objs_all: @@ -314,6 +399,18 @@ class RealTimeDistributionFunctionalTools(models.Model): headers = Common.get_headers(self, token, sf_secret_key) str_url = sf_sync_config['sf_url'] + self.crea_url objs_all = self.env['sf.real.time.distribution.of.functional.tools'].search([('id', '=', self.id)]) + self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers) + + def sync_enroll_functional_tool_real_time_distribution_all(self): + sf_sync_config = self.env['res.config.settings'].get_values() + token = sf_sync_config['token'] + sf_secret_key = sf_sync_config['sf_secret_key'] + headers = Common.get_headers(self, token, sf_secret_key) + str_url = sf_sync_config['sf_url'] + self.crea_url + objs_all = self.env['sf.real.time.distribution.of.functional.tools'].search([]) + self.get_sync_real_time_distribution_functional_tools(objs_all, str_url, token, headers) + + def get_sync_real_time_distribution_functional_tools(self, objs_all, str_url, token, headers): tool_distribution_list = [] if objs_all: for item in objs_all: From ef0e09ba4bc0a747515a037d30b7cef3cf2146cc Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Mon, 15 Apr 2024 10:22:19 +0800 Subject: [PATCH 07/12] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E5=88=80=E5=85=B7=E4=BF=A1=E6=81=AF=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=97=B6=E5=90=8C=E6=AD=A5=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../models/functional_tool_enroll.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sf_tool_management/models/functional_tool_enroll.py b/sf_tool_management/models/functional_tool_enroll.py index 6f49af02..61ca4731 100644 --- a/sf_tool_management/models/functional_tool_enroll.py +++ b/sf_tool_management/models/functional_tool_enroll.py @@ -44,7 +44,7 @@ class ToolDatasync(models.Model): self.env['sf.functional.cutting.tool.entity'].sudo().esync_enroll_functional_tool_entity_all() logging.info("功能刀具列表每日同步成功") self.env['sf.functional.tool.warning'].sudo().sync_enroll_functional_tool_warning_all() - logging.info("功能刀具列表每日同步成功") + logging.info("功能刀具预警每日同步成功") self.env['stock.move.line'].sudo().sync_enroll_functional_tool_move_all() logging.info("功能刀具出入库记录每日同步成功") self.env[ @@ -94,7 +94,7 @@ class StockLot(models.Model): if ret.get('code') == 200: return '刀具物料序列号注册成功' else: - raise UserError("没有注册刀具物料序列号信息") + logging.info("没有注册刀具物料序列号信息") class ToolMaterial(models.Model): @@ -144,7 +144,7 @@ class ToolMaterial(models.Model): if ret.get('code') == 200: return '刀具物料注册成功' else: - raise UserError("没有注册刀具物料信息") + logging.info('没有注册刀具物料信息') @api.model_create_multi def create(self, vals_list): @@ -231,7 +231,7 @@ class FunctionalCuttingToolEntity(models.Model): if ret.get('code') == 200: return "功能刀具注册成功" else: - raise UserError("没有注册功能刀具信息") + logging.info('没有注册功能刀具信息') @api.model_create_multi def create(self, vals_list): @@ -310,7 +310,7 @@ class FunctionalToolWarning(models.Model): if ret.get('code') == 200: return "功能刀具预警注册成功" else: - raise UserError("没有注册功能刀具预警信息") + logging.info('没有注册功能刀具预警信息') @api.model_create_multi def create(self, vals_list): @@ -374,7 +374,7 @@ class StockMoveLine(models.Model): if ret.get('code') == 200: return "功能刀具出入库记录注册成功" else: - raise UserError("没有注册功能刀具出入库记录信息") + logging.info('没有注册功能刀具出入库记录信息') @api.model_create_multi def create(self, vals_list): @@ -450,7 +450,7 @@ class RealTimeDistributionFunctionalTools(models.Model): if ret.get('code') == 200: return "功能刀具出入库记录注册成功" else: - raise UserError("没有注册功能刀具出入库记录信息") + logging.info('没有注册功能刀具出入库记录信息') @api.model_create_multi def create(self, vals_list): From 9ac3ef7c934c23c12c2b904d1962b854ff6ce8ae Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Mon, 15 Apr 2024 11:16:33 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E5=89=8D=E7=BD=AE=E4=B8=89=E6=AC=A1?= =?UTF-8?q?=E5=85=83=E6=A3=80=E6=B5=8B=E6=95=B0=E6=8D=AE=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 149 ++++++++++++++++++ sf_manufacturing/views/mrp_workorder_view.xml | 5 + 2 files changed, 154 insertions(+) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 89510ae0..c76d3028 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -8,6 +8,7 @@ from datetime import datetime, timedelta import requests import os import math +from lxml import etree from dateutil.relativedelta import relativedelta # import subprocess from odoo import api, fields, models, SUPERUSER_ID, _ @@ -115,6 +116,17 @@ class ResMrpWorkOrder(models.Model): processing_user_id = fields.Many2one('res.users', string='加工人') # 检测人 inspection_user_id = fields.Many2one('res.users', string='检测人') + # 保存名称 + save_name = fields.Char(string='检测文件保存名称', compute='_compute_save_name') + + @api.depends('production_id') + def _compute_save_name(self): + """ + 保存名称 + """ + for record in self: + record.save_name = record.production_id.name.replace('/', '_') + schedule_state = fields.Selection(related='production_id.schedule_state', store=True) # 工件装夹信息 functional_fixture_code = fields.Char(string="功能夹具编码", readonly=True) @@ -187,6 +199,143 @@ class ResMrpWorkOrder(models.Model): [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_id)]) return process_parameter_workorder + # 获取三次元检测点数据 + def get_three_check_datas(self): + factory_nick_name = 'XT' + ftp_resconfig = self.env['res.config.settings'].get_values() + ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']), + ftp_resconfig['ftp_user'], + ftp_resconfig['ftp_password']) + # ftp.connect() + + local_dir_path = '/ftp/before' + os.makedirs(local_dir_path, exist_ok=True) + local_filename = 'WH_MO_00099.xls' + local_file_path = os.path.join(local_dir_path, local_filename) + logging.info('local_file_path:%s' % local_file_path) + remote_path = '/home/ftp/ftp_root/ThreeTest/XT/Before/WH_MO_00099.xls' + + with open(local_file_path, 'wb') as local_file: + ftp.ftp.retrbinary('RETR ' + remote_path, local_file.write) + logging.info('下载文件成功') + # 解析本地文件 + # file_path = 'WH_MO_00099.xls' # 使用下载的实际文件路径 + parser = etree.XMLParser(recover=True) # Using recover to handle errors + tree = etree.parse(local_file_path, parser) + logging.info('tree:%s' % tree) + root = tree.getroot() + logging.info('root:%s' % root) + + # 准备一个外部字典来存储以PT为键的坐标字典 + pt_coordinates = {} + # 遍历每个工作表和行 + for worksheet in root.iterfind('.//{urn:schemas-microsoft-com:office:spreadsheet}Worksheet'): + sheet_name = worksheet.attrib.get('{urn:schemas-microsoft-com:office:spreadsheet}Name') + logging.info('sheet_name:%s' % sheet_name) + if sheet_name == "Sheet1": # 确保我们只查看包含数据的工作表 + current_pt = None + for row in worksheet.iterfind('.//{urn:schemas-microsoft-com:office:spreadsheet}Row'): + cells = list(row.iterfind('.//{urn:schemas-microsoft-com:office:spreadsheet}Cell')) + for i, cell in enumerate(cells): + data_cell = cell.find('.//{urn:schemas-microsoft-com:office:spreadsheet}Data') + if data_cell is not None and data_cell.text is not None: # 添加检查以确保data_cell.text不为空 + # 检查是否是PT标识 + logging.info(f"Data in cell: {data_cell.text}") # 输出单元格数据 + if "PT" in data_cell.text: + current_pt = data_cell.text + pt_coordinates[current_pt] = [] + elif data_cell.text in ["X", "Y", "Z"] and current_pt is not None: + # 确保当前单元格后面还有单元格存在,以获取理论值 + if i + 1 < len(cells): + next_cell = cells[i + 1] + theory_value = next_cell.find( + './/{urn:schemas-microsoft-com:office:spreadsheet}Data') + if theory_value is not None: + # 为当前PT键添加坐标数据 + pt_coordinates[current_pt].append({ + data_cell.text: float(theory_value.text) + }) + logging.info(f"PT: {current_pt} - {data_cell.text}: {theory_value.text}") + logging.info('pt_coordinates=====%s' % pt_coordinates) + # pt_coordinates:{'PT1': [{'X': 38.9221}, {'Y': -18.7304}, {'Z': 128.0783}], + # 'PT2': [{'X': 39.2456}, {'Y': -76.9169}, {'Z': 123.7541}]} + + # 检查是否存在PT1等键 + if 'PT1' in pt_coordinates and pt_coordinates['PT1']: + self.X1_axis = pt_coordinates['PT1'][0]['X'] + self.Y1_axis = pt_coordinates['PT1'][1]['Y'] + self.Z1_axis = pt_coordinates['PT1'][2]['Z'] + else: + raise UserError('PT1点未测或数据错误') + if 'PT2' in pt_coordinates and pt_coordinates['PT2']: + self.X2_axis = pt_coordinates['PT2'][0]['X'] + self.Y2_axis = pt_coordinates['PT2'][1]['Y'] + self.Z2_axis = pt_coordinates['PT2'][2]['Z'] + else: + raise UserError('PT2点未测或数据错误') + if 'PT3' in pt_coordinates and pt_coordinates['PT3']: + self.X3_axis = pt_coordinates['PT3'][0]['X'] + self.Y3_axis = pt_coordinates['PT3'][1]['Y'] + self.Z3_axis = pt_coordinates['PT3'][2]['Z'] + else: + raise UserError('PT3点未测或数据错误') + if 'PT4' in pt_coordinates and pt_coordinates['PT4']: + self.X4_axis = pt_coordinates['PT4'][0]['X'] + self.Y4_axis = pt_coordinates['PT4'][1]['Y'] + self.Z4_axis = pt_coordinates['PT4'][2]['Z'] + else: + raise UserError('PT4点未测或数据错误') + if 'PT5' in pt_coordinates and pt_coordinates['PT5']: + self.X5_axis = pt_coordinates['PT5'][0]['X'] + self.Y5_axis = pt_coordinates['PT5'][1]['Y'] + self.Z5_axis = pt_coordinates['PT5'][2]['Z'] + else: + raise UserError('PT5点未测或数据错误') + if 'PT6' in pt_coordinates and pt_coordinates['PT6']: + self.X6_axis = pt_coordinates['PT6'][0]['X'] + self.Y6_axis = pt_coordinates['PT6'][1]['Y'] + self.Z6_axis = pt_coordinates['PT6'][2]['Z'] + else: + raise UserError('PT6点未测或数据错误') + if 'PT7' in pt_coordinates and pt_coordinates['PT7']: + self.X7_axis = pt_coordinates['PT7'][0]['X'] + self.Y7_axis = pt_coordinates['PT7'][1]['Y'] + self.Z7_axis = pt_coordinates['PT7'][2]['Z'] + else: + raise UserError('PT7点未测或数据错误') + if 'PT8' in pt_coordinates and pt_coordinates['PT8']: + self.X8_axis = pt_coordinates['PT8'][0]['X'] + self.Y8_axis = pt_coordinates['PT8'][1]['Y'] + self.Z8_axis = pt_coordinates['PT8'][2]['Z'] + else: + raise UserError('PT8点未测或数据错误') + if 'PT9' in pt_coordinates and pt_coordinates['PT9']: + self.X9_axis = pt_coordinates['PT9'][0]['X'] + self.Y9_axis = pt_coordinates['PT9'][1]['Y'] + self.Z9_axis = pt_coordinates['PT9'][2]['Z'] + else: + raise UserError('PT9点未测或数据错误') + if 'PT10' in pt_coordinates and pt_coordinates['PT10']: + self.X10_axis = pt_coordinates['PT10'][0]['X'] + self.Y10_axis = pt_coordinates['PT10'][1]['Y'] + self.Z10_axis = pt_coordinates['PT10'][2]['Z'] + else: + raise UserError('PT10点未测或数据错误') + + return True + + # ftp.download_file('three_check_datas.xls', '/home/ftpuser/three_check_datas.xls') + # ftp.close() + # data = xlrd.open_workbook('/home/ftpuser/three_check_datas.xls') + # table = data.sheets()[0] + # nrows = table.nrows + # # 点坐标列表 + # point_list = [] + # datas = [] + # for i in range(1, nrows): + # datas.append(table.row_values(i)) + # return datas + # 计算配料中心点和与x轴倾斜度方法 def getcenter(self): try: diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 9a747791..4c3955e5 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -403,6 +403,10 @@
+
+
@@ -517,6 +521,7 @@ +
From 19156f5944426fd9147d54ba4f7ed6f834c61c23 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Mon, 15 Apr 2024 11:39:10 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E5=81=A5=E5=A3=AE=E6=80=A7=EF=BC=8C=E8=A7=A3=E5=86=B3=E9=83=A8?= =?UTF-8?q?=E5=88=86=E7=A1=AC=E7=BC=96=E7=A0=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 8 ++++++-- sf_mrs_connect/models/ftp_operate.py | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index c76d3028..c4396d38 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -210,10 +210,14 @@ class ResMrpWorkOrder(models.Model): local_dir_path = '/ftp/before' os.makedirs(local_dir_path, exist_ok=True) - local_filename = 'WH_MO_00099.xls' + local_filename = self.save_name + '.xls' local_file_path = os.path.join(local_dir_path, local_filename) logging.info('local_file_path:%s' % local_file_path) - remote_path = '/home/ftp/ftp_root/ThreeTest/XT/Before/WH_MO_00099.xls' + remote_path = '/home/ftp/ftp_root/ThreeTest/XT/Before/' + local_filename + logging.info('remote_path:%s' % remote_path) + + if not ftp.file_exists(remote_path): + raise UserError(f"文件不存在: {remote_path}") with open(local_file_path, 'wb') as local_file: ftp.ftp.retrbinary('RETR ' + remote_path, local_file.write) diff --git a/sf_mrs_connect/models/ftp_operate.py b/sf_mrs_connect/models/ftp_operate.py index c8d0abb6..724f56b4 100644 --- a/sf_mrs_connect/models/ftp_operate.py +++ b/sf_mrs_connect/models/ftp_operate.py @@ -21,6 +21,16 @@ class FtpController(): except Exception: logging.info("ftp连接失败") + def file_exists(self, path): + # 检查文件是否存在于FTP服务器上 + try: + self.ftp.cwd(os.path.dirname(path)) + files = self.ftp.nlst() + return os.path.basename(path) in files + except Exception as e: + logging.error(f"Error checking file: {e}") + return False + # 下载目录下的文件 def download_file_tree(self, target_dir, serverdir): if not os.path.exists(serverdir): From 9df62129b76b83cced57791d502ab32f60491d86 Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Mon, 15 Apr 2024 13:39:58 +0800 Subject: [PATCH 10/12] =?UTF-8?q?=E6=8E=A7=E5=88=B6=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E6=98=BE=E9=9A=90=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 4 ++++ sf_manufacturing/views/mrp_workorder_view.xml | 7 +++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index c4396d38..631b9823 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -118,6 +118,8 @@ class ResMrpWorkOrder(models.Model): inspection_user_id = fields.Many2one('res.users', string='检测人') # 保存名称 save_name = fields.Char(string='检测文件保存名称', compute='_compute_save_name') + # 获取数据状态 + data_state = fields.Boolean(string='获取数据状态', default=False) @api.depends('production_id') def _compute_save_name(self): @@ -326,6 +328,8 @@ class ResMrpWorkOrder(models.Model): else: raise UserError('PT10点未测或数据错误') + self.data_state = True + return True # ftp.download_file('three_check_datas.xls', '/home/ftpuser/three_check_datas.xls') diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 4c3955e5..8a76fe71 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -403,12 +403,11 @@
+
-
+ attrs='{"invisible": ["|", "|", "|", ("material_center_point","!=",False),("state","!=","progress"),("user_permissions","=",False), ("data_state", "=", True)]}'/>
From 48cba4274b2fd7c1b29933de41542d27f025e152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E7=84=B1?= Date: Mon, 15 Apr 2024 17:04:43 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=9B=A0=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=A1=A8=E6=A0=BC=E5=BF=85=E5=A1=AB=E8=80=8C=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../static/src/js/custom_form_status_indicator.js | 3 +-- jikimo_frontend/static/src/scss/custom_style.scss | 12 +++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/jikimo_frontend/static/src/js/custom_form_status_indicator.js b/jikimo_frontend/static/src/js/custom_form_status_indicator.js index 100542b8..de50eddc 100644 --- a/jikimo_frontend/static/src/js/custom_form_status_indicator.js +++ b/jikimo_frontend/static/src/js/custom_form_status_indicator.js @@ -128,8 +128,7 @@ patch(ListRenderer.prototype, 'jikimo_frontend.ListRenderer', { this.allColumns.forEach(_ => { if( tableRequiredList.indexOf(_.name) >= 0 ) { const dom = $(`th[data-name=${_.name}]`) - let t = dom.html() - dom.html('*' + t) + dom.addClass('addRequired') } }) } diff --git a/jikimo_frontend/static/src/scss/custom_style.scss b/jikimo_frontend/static/src/scss/custom_style.scss index f7195534..3c106665 100644 --- a/jikimo_frontend/static/src/scss/custom_style.scss +++ b/jikimo_frontend/static/src/scss/custom_style.scss @@ -478,4 +478,14 @@ div:has(.o_required_modifier) > label::before { width: auto !important; flex: unset; } - +.addRequired { + padding-left: calc(0.3rem + 2px)!important; +} +.addRequired:before { + content: '*'; + color: red; + position: absolute; + left: 0; + top: 50%; + transform: translateY(-50%); +} \ No newline at end of file From 028eb18dd8edccd0527075d3e451328c9d59533e Mon Sep 17 00:00:00 2001 From: mgw <1392924357@qq.com> Date: Mon, 15 Apr 2024 21:14:12 +0800 Subject: [PATCH 12/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=B5=8B=E7=82=B9?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E5=8C=B9=E9=85=8D=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=94=99=E8=AF=AF=E6=8A=9B=E5=87=BA=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 65 ++++++++++++------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 631b9823..99061895 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -268,63 +268,63 @@ class ResMrpWorkOrder(models.Model): # 检查是否存在PT1等键 if 'PT1' in pt_coordinates and pt_coordinates['PT1']: - self.X1_axis = pt_coordinates['PT1'][0]['X'] - self.Y1_axis = pt_coordinates['PT1'][1]['Y'] - self.Z1_axis = pt_coordinates['PT1'][2]['Z'] + self.X1_axis = pt_coordinates['PT3'][0]['X'] + self.Y1_axis = pt_coordinates['PT3'][1]['Y'] + self.Z1_axis = pt_coordinates['PT3'][2]['Z'] else: raise UserError('PT1点未测或数据错误') if 'PT2' in pt_coordinates and pt_coordinates['PT2']: - self.X2_axis = pt_coordinates['PT2'][0]['X'] - self.Y2_axis = pt_coordinates['PT2'][1]['Y'] - self.Z2_axis = pt_coordinates['PT2'][2]['Z'] + self.X2_axis = pt_coordinates['PT4'][0]['X'] + self.Y2_axis = pt_coordinates['PT4'][1]['Y'] + self.Z2_axis = pt_coordinates['PT4'][2]['Z'] else: raise UserError('PT2点未测或数据错误') if 'PT3' in pt_coordinates and pt_coordinates['PT3']: - self.X3_axis = pt_coordinates['PT3'][0]['X'] - self.Y3_axis = pt_coordinates['PT3'][1]['Y'] - self.Z3_axis = pt_coordinates['PT3'][2]['Z'] + self.X3_axis = pt_coordinates['PT5'][0]['X'] + self.Y3_axis = pt_coordinates['PT5'][1]['Y'] + self.Z3_axis = pt_coordinates['PT5'][2]['Z'] else: raise UserError('PT3点未测或数据错误') if 'PT4' in pt_coordinates and pt_coordinates['PT4']: - self.X4_axis = pt_coordinates['PT4'][0]['X'] - self.Y4_axis = pt_coordinates['PT4'][1]['Y'] - self.Z4_axis = pt_coordinates['PT4'][2]['Z'] + self.X4_axis = pt_coordinates['PT6'][0]['X'] + self.Y4_axis = pt_coordinates['PT6'][1]['Y'] + self.Z4_axis = pt_coordinates['PT6'][2]['Z'] else: raise UserError('PT4点未测或数据错误') if 'PT5' in pt_coordinates and pt_coordinates['PT5']: - self.X5_axis = pt_coordinates['PT5'][0]['X'] - self.Y5_axis = pt_coordinates['PT5'][1]['Y'] - self.Z5_axis = pt_coordinates['PT5'][2]['Z'] + self.X5_axis = pt_coordinates['PT7'][0]['X'] + self.Y5_axis = pt_coordinates['PT7'][1]['Y'] + self.Z5_axis = pt_coordinates['PT7'][2]['Z'] else: raise UserError('PT5点未测或数据错误') if 'PT6' in pt_coordinates and pt_coordinates['PT6']: - self.X6_axis = pt_coordinates['PT6'][0]['X'] - self.Y6_axis = pt_coordinates['PT6'][1]['Y'] - self.Z6_axis = pt_coordinates['PT6'][2]['Z'] + self.X6_axis = pt_coordinates['PT8'][0]['X'] + self.Y6_axis = pt_coordinates['PT8'][1]['Y'] + self.Z6_axis = pt_coordinates['PT8'][2]['Z'] else: raise UserError('PT6点未测或数据错误') if 'PT7' in pt_coordinates and pt_coordinates['PT7']: - self.X7_axis = pt_coordinates['PT7'][0]['X'] - self.Y7_axis = pt_coordinates['PT7'][1]['Y'] - self.Z7_axis = pt_coordinates['PT7'][2]['Z'] + self.X7_axis = pt_coordinates['PT9'][0]['X'] + self.Y7_axis = pt_coordinates['PT9'][1]['Y'] + self.Z7_axis = pt_coordinates['PT9'][2]['Z'] else: raise UserError('PT7点未测或数据错误') if 'PT8' in pt_coordinates and pt_coordinates['PT8']: - self.X8_axis = pt_coordinates['PT8'][0]['X'] - self.Y8_axis = pt_coordinates['PT8'][1]['Y'] - self.Z8_axis = pt_coordinates['PT8'][2]['Z'] + self.X8_axis = pt_coordinates['PT10'][0]['X'] + self.Y8_axis = pt_coordinates['PT10'][1]['Y'] + self.Z8_axis = pt_coordinates['PT10'][2]['Z'] else: raise UserError('PT8点未测或数据错误') if 'PT9' in pt_coordinates and pt_coordinates['PT9']: - self.X9_axis = pt_coordinates['PT9'][0]['X'] - self.Y9_axis = pt_coordinates['PT9'][1]['Y'] - self.Z9_axis = pt_coordinates['PT9'][2]['Z'] + self.X9_axis = pt_coordinates['PT1'][0]['X'] + self.Y9_axis = pt_coordinates['PT1'][1]['Y'] + self.Z9_axis = pt_coordinates['PT1'][2]['Z'] else: raise UserError('PT9点未测或数据错误') if 'PT10' in pt_coordinates and pt_coordinates['PT10']: - self.X10_axis = pt_coordinates['PT10'][0]['X'] - self.Y10_axis = pt_coordinates['PT10'][1]['Y'] - self.Z10_axis = pt_coordinates['PT10'][2]['Z'] + self.X10_axis = pt_coordinates['PT2'][0]['X'] + self.Y10_axis = pt_coordinates['PT2'][1]['Y'] + self.Z10_axis = pt_coordinates['PT2'][2]['Z'] else: raise UserError('PT10点未测或数据错误') @@ -387,8 +387,9 @@ class ResMrpWorkOrder(models.Model): work.compensation_value_x = eval(self.material_center_point)[0] work.compensation_value_y = eval(self.material_center_point)[1] workorder.button_finish() - except: - raise UserError("参数计算有误") + except Exception as e: + # 重新抛出捕获到的异常信息 + raise UserError(str(e)) def button_workpiece_delivery(self): if self.routing_type == '装夹预调':