From 36fd17b6c78c320763b3ca788ef4984bc861eb5d Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 8 Aug 2024 17:03:36 +0800 Subject: [PATCH 01/12] =?UTF-8?q?1=E3=80=81=E5=A4=84=E7=90=86=20=E6=99=BA?= =?UTF-8?q?=E8=83=BD=E5=B7=A5=E5=8E=82=EF=BC=8C=E9=94=80=E5=94=AE=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E4=B8=8E=E9=87=87=E8=B4=AD=E8=A7=92=E8=89=B2=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=9B=B4=E6=96=B0=20=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_sale/__manifest__.py | 3 ++- sf_sale/models/sale_order.py | 5 +++++ sf_sale/security/ir.model.access.csv | 23 +++++++++++++++++++++++ sf_sale/views/purchase_menu.xml | 23 +++++++++++++++++++++++ sf_sale/views/sale_order_view.xml | 7 +++++++ 5 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 sf_sale/views/purchase_menu.xml diff --git a/sf_sale/__manifest__.py b/sf_sale/__manifest__.py index efe72de6..45c95030 100644 --- a/sf_sale/__manifest__.py +++ b/sf_sale/__manifest__.py @@ -20,7 +20,8 @@ 'views/sale_order_view.xml', 'views/res_partner_view.xml', 'views/purchase_order_view.xml', - 'views/quick_easy_order_view.xml' + 'views/quick_easy_order_view.xml', + 'views/purchase_menu.xml' ], 'assets': { 'web.assets_backend': [ diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 31a89c00..d0bd95a3 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -13,6 +13,11 @@ READONLY_FIELD_STATES = { class ReSaleOrder(models.Model): _inherit = 'sale.order' + mrp_production_count = fields.Integer( + "Count of MO generated", + compute='_compute_mrp_production_ids', + groups='mrp.group_mrp_user,sf_base.group_sale_salemanager,sf_base.group_sale_director') + logistics_way = fields.Selection([('自提', '自提'), ('到付', '到付'), ('在线支付', '在线支付')], string='物流方式') state = fields.Selection( selection=[ diff --git a/sf_sale/security/ir.model.access.csv b/sf_sale/security/ir.model.access.csv index 0e2f0684..0747340c 100644 --- a/sf_sale/security/ir.model.access.csv +++ b/sf_sale/security/ir.model.access.csv @@ -96,5 +96,28 @@ access_product_supplierinfo_group_plan_director,product.supplierinfo user,produc access_product_category_group_plan_director,product.category user,product.model_product_category,sf_base.group_plan_director,1,1,1,0 +access_purchase_report_sf_base_group_purchase,purchase_report_sf_base_group_purchase,purchase.model_purchase_report,sf_base.group_purchase,1,0,0,0 +access_purchase_report_sf_base_group_purchase_director,purchase_report_sf_base_group_purchase_director,purchase.model_purchase_report,sf_base.group_purchase_director,1,0,0,0 +access_sale_order_sf_base_group_purchase,sale_order_sf_base_group_purchase,model_sale_order,sf_base.group_purchase,1,0,0,0 +access_sale_order_sf_base_group_purchase_director,sale_order_sf_base_group_purchase_director,model_sale_order,sf_base.group_purchase_director,1,0,0,0 + + +access_quality_check_group_sale_salemanager,quality_check_group_sale_salemanager,quality.model_quality_check,sf_base.group_sale_salemanager,1,0,0,0 +access_quality_check_group_sale_director,quality_check_group_sale_director,quality.model_quality_check,sf_base.group_sale_director,1,0,0,0 +access_stock_picking_group_sale_salemanager,stock_picking_group_sale_salemanager,stock.model_stock_picking,sf_base.group_sale_salemanager,1,0,0,0 +access_stock_picking_group_sale_director,stock_picking_group_sale_director,stock.model_stock_picking,sf_base.group_sale_director,1,0,0,0 +access_mrp_workorder_group_sale_salemanager,mrp_workorder_group_sale_salemanager,mrp.model_mrp_workorder,sf_base.group_sale_salemanager,1,0,0,0 +access_mrp_workorder_group_sale_director,mrp_workorder_group_sale_director,mrp.model_mrp_workorder,sf_base.group_sale_director,1,0,0,0 +access_mrp_unbuild_group_sale_salemanager,mrp_unbuild_group_sale_salemanager,mrp.model_mrp_unbuild,sf_base.group_sale_salemanager,1,0,0,0 +access_mrp_unbuild_group_sale_director,mrp_unbuild_group_sale_director,mrp.model_mrp_unbuild,sf_base.group_sale_director,1,0,0,0 +access_mrp_workcenter_productivity_group_sale_salemanager,mrp_workcenter_productivity_group_sale_salemanager,mrp.model_mrp_workcenter_productivity,sf_base.group_sale_salemanager,1,0,0,0 +access_mrp_workcenter_productivity_group_sale_director,mrp_workcenter_productivity_group_sale_director,mrp.model_mrp_workcenter_productivity,sf_base.group_sale_director,1,0,0,0 +access_sf_detection_result_group_sale_salemanager,sf_detection_result_group_sale_salemanager,sf_manufacturing.model_sf_detection_result,sf_base.group_sale_salemanager,1,0,0,0 +access_sf_detection_result_group_sale_director,sf_detection_result_group_sale_director,sf_manufacturing.model_sf_detection_result,sf_base.group_sale_director,1,0,0,0 +access_stock_scrap_group_sale_salemanager,stock_scrap_group_sale_salemanager,stock.model_stock_scrap,sf_base.group_sale_salemanager,1,0,0,0 +access_stock_scrap_group_sale_director,stock_scrap_group_sale_director,stock.model_stock_scrap,sf_base.group_sale_director,1,0,0,0 + + + diff --git a/sf_sale/views/purchase_menu.xml b/sf_sale/views/purchase_menu.xml new file mode 100644 index 00000000..3b92ca4b --- /dev/null +++ b/sf_sale/views/purchase_menu.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf_sale/views/sale_order_view.xml b/sf_sale/views/sale_order_view.xml index 00cca206..75e2d0c1 100644 --- a/sf_sale/views/sale_order_view.xml +++ b/sf_sale/views/sale_order_view.xml @@ -6,6 +6,13 @@ sale.order + + sf_base.group_sale_salemanager,sf_base.group_sale_director + + + mrp.group_mrp_user,sf_base.group_sale_salemanager,sf_base.group_sale_director + + From e6ca4c27ac8998b42f7b6ccc9af6876fc274ef6f Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Fri, 9 Aug 2024 17:19:03 +0800 Subject: [PATCH 02/12] =?UTF-8?q?1=E3=80=81=E5=BA=93=E4=BD=8D=E5=8F=98?= =?UTF-8?q?=E6=9B=B4=E6=8E=A5=E5=8F=A3=E3=80=81=E5=BA=93=E4=BD=8D=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E6=8E=A5=E5=8F=A3=E4=BC=98=E5=8C=96=EF=BC=9B2?= =?UTF-8?q?=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E9=A2=84=E8=AD=A6?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E4=BC=98=E5=8C=96=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/controllers/controllers.py | 88 +++++++++++++------ sf_tool_management/models/base.py | 82 ++++++++--------- sf_tool_management/models/functional_tool.py | 63 ++++++++----- .../views/functional_tool_views.xml | 41 ++++----- sf_warehouse/models/model.py | 4 +- sf_warehouse/models/sync_common.py | 29 +++--- 6 files changed, 173 insertions(+), 134 deletions(-) diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index babda164..8075f126 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -396,34 +396,66 @@ class Manufacturing_Connect(http.Controller): OldDeciveStart = ret['OldDeciveStart'] OldDeciveEnd = ret['OldDeciveEnd'] - temp_val_sn_id = None - old_localtion = None - # if ChangeType == 'Part' or ChangeType == 'Tool': - stock_lot_obj = request.env['stock.lot'].sudo().search( - [('rfid', '=', RfidCode)], limit=1) - logging.info('stock_lot_obj===========:%s' % stock_lot_obj) - if not stock_lot_obj: - res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'} - return json.JSONEncoder().encode(res) - if OldPosition: - old_localtion = request.env['sf.shelf.location'].sudo().search( - [('barcode', '=', OldPosition)], limit=1) - logging.info('old_localtion===========:%s' % old_localtion) - new_localtion = request.env['sf.shelf.location'].sudo().search( - [('barcode', '=', NewPosition)], limit=1) - logging.info('new_localtion===========:%s' % new_localtion) - if not new_localtion: - res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'} - return json.JSONEncoder().encode(res) - if old_localtion: - temp_val_sn_id = old_localtion.product_sn_id - logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id) - old_localtion.product_sn_id = None - new_localtion.product_sn_id = temp_val_sn_id - logging.info('====1======') - else: - new_localtion.product_sn_id = stock_lot_obj.id - logging.info('=====2======') + if ChangeType == 'Part': + temp_val_sn_id = None + old_localtion = None + # if ChangeType == 'Part' or ChangeType == 'Tool': + stock_lot_obj = request.env['stock.lot'].sudo().search( + [('rfid', '=', RfidCode)], limit=1) + logging.info('stock_lot_obj===========:%s' % stock_lot_obj) + if not stock_lot_obj: + res = {'Succeed': False, 'ErrorCode': 202, 'Error': '未根据RfidCode找到该产品'} + return json.JSONEncoder().encode(res) + if OldPosition: + old_localtion = request.env['sf.shelf.location'].sudo().search( + [('barcode', '=', OldPosition)], limit=1) + logging.info('old_localtion===========:%s' % old_localtion) + new_localtion = request.env['sf.shelf.location'].sudo().search( + [('barcode', '=', NewPosition)], limit=1) + logging.info('new_localtion===========:%s' % new_localtion) + if not new_localtion: + res = {'Succeed': False, 'ErrorCode': 202, 'Error': '没有该目标位置'} + return json.JSONEncoder().encode(res) + if old_localtion: + temp_val_sn_id = old_localtion.product_sn_id + logging.info('temp_val_sn_id===========:%s' % temp_val_sn_id) + old_localtion.product_sn_id = None + new_localtion.product_sn_id = temp_val_sn_id + logging.info('====1======') + else: + new_localtion.product_sn_id = stock_lot_obj.id + logging.info('=====2======') + elif ChangeType == 'Tool': + # 对功能刀具库位变更信息进行更改 + def write_tool(DeciveId): + if 'Tool' in DeciveId: + shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info(DeciveId) + for item in shelfinfo: + shelf_barcode = self.env['sf.shelf.location.datasync'].find_our_code(item['Postion']) + location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], + limit=1) + if location_id: + # 如果是线边刀库信息,则对功能刀具移动生成记录 + if 'Tool' in item['Postion']: + tool = self.env['sf.functional.cutting.tool.entity'].sudo().search( + [('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')]) + tool.tool_in_out_stock_location(location_id) + if tool: + location_id.product_sn_id = tool.barcode_id.id + else: + location_id.product_sn_id = False + else: + equipment_id = self.env['maintenance.equipment'].search([('name', '=', DeciveId)]) + if equipment_id: + equipment_id.register_equipment_tool() + else: + res_1 = {'Succeed': False, 'ErrorCode': 202, 'Error': f'设备【{DeciveId}】不存在'} + return json.JSONEncoder().encode(res_1) + + if OldDeciveId: + write_tool(OldDeciveId) + elif NewDeciveId: + write_tool(NewDeciveId) except Exception as e: res = {'Succeed': False, 'ErrorCode': 202, 'Error': e} logging.info('LocationChange error:%s' % e) diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index 65475333..e756899b 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -94,47 +94,47 @@ class MachineTableToolChangingApply(models.Model): if len(records) > 1: raise ValidationError('该刀位号已存在,请重新选择!!!') - @api.constrains('functional_tool_status') - def automation_apply_for_tool_change(self): - """ - 自动申请换刀 - :return: - """ - # 更新数据到机台换刀申请界面 - if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id: - machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search( - [('maintenance_equipment_id', '=', self.maintenance_equipment_id.id), - ('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id) - ]) - - # 创建功能刀具预警记录 - self.env['sf.functional.tool.warning'].create_tool_warning_record({'tool_changing_apply_id': self}) - - # 新建组装任务 - sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({ - 'functional_tool_name': self.functional_tool_name, - 'functional_tool_type_id': self.functional_tool_type_id.id, - 'functional_tool_diameter': self.diameter, - 'knife_tip_r_angle': self.knife_tip_r_angle, - 'coarse_middle_thin': '3', - 'new_former': '0', - 'functional_tool_length': self.extension_length, - 'effective_length': self.effective_length, - 'loading_task_source': '1', - 'use_tool_time': fields.Datetime.now() + timedelta(hours=4), - 'production_line_name_id': self.production_line_id.id, - 'machine_tool_name_id': self.maintenance_equipment_id.id, - 'applicant': '系统自动', - 'apply_time': fields.Datetime.now(), - 'cutter_spacing_code_id': self.cutter_spacing_code_id.id, - 'whether_standard_knife': self.whether_standard_knife, - 'reason_for_applying': '机台报警自动换刀', - 'sf_machine_table_tool_changing_apply_id': self.id - }) - - machine_table_tool_changing_apply.write( - {'status': '1', - 'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id}) + # @api.constrains('functional_tool_status') + # def automation_apply_for_tool_change(self): + # """ + # 自动申请换刀 + # :return: + # """ + # # 更新数据到机台换刀申请界面 + # if self.functional_tool_status == '报警' and not self.sf_functional_tool_assembly_id: + # machine_table_tool_changing_apply = self.env['sf.machine.table.tool.changing.apply'].search( + # [('maintenance_equipment_id', '=', self.maintenance_equipment_id.id), + # ('cutter_spacing_code_id', '=', self.cutter_spacing_code_id.id) + # ]) + # + # # 创建功能刀具预警记录 + # self.env['sf.functional.tool.warning'].create_tool_warning_record({'tool_changing_apply_id': self}) + # + # # 新建组装任务 + # sf_functional_tool_assembly = self.env['sf.functional.tool.assembly'].create({ + # 'functional_tool_name': self.functional_tool_name, + # 'functional_tool_type_id': self.functional_tool_type_id.id, + # 'functional_tool_diameter': self.diameter, + # 'knife_tip_r_angle': self.knife_tip_r_angle, + # 'coarse_middle_thin': '3', + # 'new_former': '0', + # 'functional_tool_length': self.extension_length, + # 'effective_length': self.effective_length, + # 'loading_task_source': '1', + # 'use_tool_time': fields.Datetime.now() + timedelta(hours=4), + # 'production_line_name_id': self.production_line_id.id, + # 'machine_tool_name_id': self.maintenance_equipment_id.id, + # 'applicant': '系统自动', + # 'apply_time': fields.Datetime.now(), + # 'cutter_spacing_code_id': self.cutter_spacing_code_id.id, + # 'whether_standard_knife': self.whether_standard_knife, + # 'reason_for_applying': '机台报警自动换刀', + # 'sf_machine_table_tool_changing_apply_id': self.id + # }) + # + # machine_table_tool_changing_apply.write( + # {'status': '1', + # 'sf_functional_tool_assembly_id': sf_functional_tool_assembly.id}) def revocation_1(self): """ diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py index 0d9473ca..2c677e60 100644 --- a/sf_tool_management/models/functional_tool.py +++ b/sf_tool_management/models/functional_tool.py @@ -53,6 +53,21 @@ class FunctionalCuttingToolEntity(models.Model): safe_inventory_id = fields.Many2one('sf.real.time.distribution.of.functional.tools', string='功能刀具安全库存', readonly=True) + @api.onchange('functional_tool_status') + def _onchange_functional_tool_status(self): + for item in self: + if item: + if item.functional_tool_status == '报警': + # 创建报警刀具拆解单 + self.env['sf.functional.tool.dismantle'].sudo().create({ + 'functional_tool_id': item.id, + 'dismantle_cause': '寿命到期报废' + }) + # 创建刀具报警记录 + # self.env['sf.functional.tool.warning'].sudo().create({ + # '' + # }) + @api.depends('barcode_id.quant_ids', 'barcode_id.quant_ids.location_id', 'functional_tool_status', 'current_shelf_location_id') def _compute_current_location_id(self): @@ -324,7 +339,7 @@ class FunctionalToolWarning(models.Model): _description = '功能刀具预警' code = fields.Char('编码', related='functional_tool_name_id.code') - rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid') + rfid = fields.Char('Rfid') tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id') name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_name_id.name') # 机床信息 @@ -338,7 +353,7 @@ class FunctionalToolWarning(models.Model): domain="[('equipment_id', '=', maintenance_equipment_id)]") # 功能刀具信息 functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称') - barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id') + barcode_id = fields.Many2one('stock.lot', string='序列号', related='functional_tool_name_id.barcode_id') mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型') diameter = fields.Float(string='刀具直径(mm)') knife_tip_r_angle = fields.Float(string='刀尖R角(mm)') @@ -361,28 +376,28 @@ class FunctionalToolWarning(models.Model): machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID) return categories.browse(machine_table_name_ids) - def create_tool_warning_record(self, obj): - """ - 机台换刀申请报警状态时,创建功能刀具预警记录 - """ - if obj: - for tool in obj.get('tool_changing_apply_id'): - self.env['sf.functional.tool.warning'].create({ - 'production_line_id': tool.production_line_id.id, - 'maintenance_equipment_id': tool.maintenance_equipment_id.id, - 'machine_tool_code': tool.machine_tool_code, - 'machine_table_type_id': tool.machine_table_type_id.id, - 'cutter_spacing_code_id': tool.cutter_spacing_code_id.id, - 'functional_tool_name_id': tool.functional_tool_name_id.id, - 'barcode_id': tool.barcode_id.id, - 'diameter': tool.diameter, - 'knife_tip_r_angle': tool.knife_tip_r_angle, - 'max_lifetime_value': tool.max_lifetime_value, - 'alarm_value': tool.alarm_value, - 'used_value': tool.used_value, - 'functional_tool_status': tool.functional_tool_status, - 'alarm_time': fields.Datetime.now(), - }) + # def create_tool_warning_record(self, obj): + # """ + # 机台换刀申请报警状态时,创建功能刀具预警记录 + # """ + # if obj: + # for tool in obj.get('tool_changing_apply_id'): + # self.env['sf.functional.tool.warning'].create({ + # 'production_line_id': tool.production_line_id.id, + # 'maintenance_equipment_id': tool.maintenance_equipment_id.id, + # 'machine_tool_code': tool.machine_tool_code, + # 'machine_table_type_id': tool.machine_table_type_id.id, + # 'cutter_spacing_code_id': tool.cutter_spacing_code_id.id, + # 'functional_tool_name_id': tool.functional_tool_name_id.id, + # 'barcode_id': tool.barcode_id.id, + # 'diameter': tool.diameter, + # 'knife_tip_r_angle': tool.knife_tip_r_angle, + # 'max_lifetime_value': tool.max_lifetime_value, + # 'alarm_value': tool.alarm_value, + # 'used_value': tool.used_value, + # 'functional_tool_status': tool.functional_tool_status, + # 'alarm_time': fields.Datetime.now(), + # }) class StockMoveLine(models.Model): diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml index 103583c2..70edbafe 100644 --- a/sf_tool_management/views/functional_tool_views.xml +++ b/sf_tool_management/views/functional_tool_views.xml @@ -236,25 +236,26 @@ sf.functional.tool.warning - - - - - + + + + + + + - - + + + - - - + @@ -266,31 +267,19 @@ sf.functional.tool.warning - - - - - - - - - - - - - - - - + + + diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 5beeebc5..d3f9c585 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -507,13 +507,13 @@ class ShelfLocation(models.Model): print('eeeeeee空闲', e) # 调取获取货位信息接口 - def get_sf_shelf_location_info(self): + def get_sf_shelf_location_info(self, device_id='Cabinet-AL'): config = self.env['res.config.settings'].get_values() headers = {'Authorization': config['center_control_Authorization']} crea_url = config['center_control_url'] + "/AutoDeviceApi/GetLocationInfos" - params = {'DeviceId': 'Cabinet-AL'} + params = {'DeviceId': device_id} r = requests.get(crea_url, params=params, headers=headers) ret = r.json() diff --git a/sf_warehouse/models/sync_common.py b/sf_warehouse/models/sync_common.py index 3df97423..32632eac 100644 --- a/sf_warehouse/models/sync_common.py +++ b/sf_warehouse/models/sync_common.py @@ -13,13 +13,14 @@ class MrsShelfLocationDataSync(models.Model): _name = 'sf.shelf.location.datasync' _description = '同步库存信息' - def _cron_shelf_location_datasync(self): - try: - # 建立对应关系的函数 - def align_data(my_data, their_data): - paired_data = list(zip(my_data, their_data)) - return paired_data + def find_our_code(self, their_code): + # 建立对应关系的函数 + def align_data(my_data, their_data): + paired_data = list(zip(my_data, their_data)) + return paired_data + + def get_total_data(): shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1) tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id') @@ -82,19 +83,21 @@ class MrsShelfLocationDataSync(models.Model): total_data = aligned_data_1 + aligned_data_2 + aligned_data_3 + aligned_data_4 + aligned_data_5 print(total_data) logging.info(f"total_data: {total_data}") + return total_data + for code_pair in get_total_data(): + if code_pair[1] == their_code: + return code_pair[0] + return None # 如果没有找到对应的值,返回None或适当的默认值 + + def _cron_shelf_location_datasync(self): + try: def find_their_code(my_code, aligned_data): for code_pair in aligned_data: if code_pair[0] == my_code: return code_pair[1] return None # 如果没有找到对应的值,返回None或适当的默认值 - def find_our_code(their_code, aligned_data): - for code_pair in aligned_data: - if code_pair[1] == their_code: - return code_pair[0] - return None # 如果没有找到对应的值,返回None或适当的默认值 - # 定时更新所有设备机床刀库信息 equipment_ids = self.env['maintenance.equipment'].search( [('equipment_type', '=', '机床'), ('function_type', '!=', False)]) @@ -105,7 +108,7 @@ class MrsShelfLocationDataSync(models.Model): shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info() print('shelfinfo:', shelfinfo) for item in shelfinfo: - shelf_barcode = find_our_code(item['Postion'], total_data) + shelf_barcode = self.find_our_code(item['Postion']) location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1) if location_id: # 如果是线边刀库信息,则对功能刀具移动生成记录 From 894d3b9ea30777b8bba85f83a079eb3fc95c3d79 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Mon, 12 Aug 2024 17:25:56 +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=8B=86=E8=A7=A3=E5=8D=95=E6=B7=BB=E5=8A=A0=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=88=80=E5=85=B7=E5=94=AF=E4=B8=80=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=EF=BC=9B2=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8Btree=E8=A7=86=E5=9B=BE=E7=9A=84=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=AD=97=E6=AE=B5=E6=A0=B9=E6=8D=AE=E4=B8=8D=E5=90=8C?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E6=B7=BB=E5=8A=A0=E4=B8=8D=E5=90=8C=E9=A2=9C?= =?UTF-8?q?=E8=89=B2=EF=BC=9B=E5=BD=93=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E4=B8=BA=E6=8A=A5=E8=AD=A6=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=88=9B=E5=BB=BA=E6=8B=86=E8=A7=A3=E5=8D=95?= =?UTF-8?q?=E5=92=8C=E9=A2=84=E8=AD=A6=E8=AE=B0=E5=BD=95=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=8B=86=E8=A7=A3=E5=8D=95=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E6=8C=89=E9=92=AE=EF=BC=9B=E6=B7=BB=E5=8A=A0tree=E8=A7=86?= =?UTF-8?q?=E5=9B=BE=E6=8C=89=E7=8A=B6=E6=80=81=E6=8E=92=E5=BA=8F=EF=BC=8C?= =?UTF-8?q?=E5=B0=86=E6=8A=A5=E8=AD=A6=E7=8A=B6=E6=80=81=E5=88=80=E5=85=B7?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E6=98=BE=E7=A4=BA=E5=9C=A8=E6=9C=80=E5=89=8D?= =?UTF-8?q?=E9=9D=A2=EF=BC=9B3=E3=80=81=E4=BC=98=E5=8C=96=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=88=80=E5=85=B7=E9=A2=84=E8=AD=A6=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=8F=8A=E5=85=B3=E8=81=94=E5=85=B3=E7=B3=BB?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E9=A2=84=E8=AD=A6=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E5=88=B0=E5=AF=B9=E5=BA=94=E7=94=B1=E8=AF=A5?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=94=9F=E6=88=90=E7=9A=84?= =?UTF-8?q?=E6=8B=86=E8=A7=A3=E5=8D=95=E9=93=BE=E6=8E=A5=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/models/base.py | 19 +++- sf_tool_management/models/functional_tool.py | 91 ++++++++++++++----- .../views/functional_tool_views.xml | 21 ++++- sf_tool_management/views/tool_base_views.xml | 2 +- 4 files changed, 103 insertions(+), 30 deletions(-) diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index e756899b..fd9e6f29 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -760,6 +760,15 @@ class FunctionalToolDismantle(models.Model): functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True, tracking=True, domain=[('functional_tool_status', '!=', '已拆除'), ('current_location', '=', '刀具房')]) + + @api.onchange('functional_tool_id') + def _onchange_functional_tool_id(self): + for item in self: + if item: + dismantle_id = self.search([('functional_tool_id', '=', item.functional_tool_id.id)]) + if dismantle_id: + raise ValidationError(f'Rfid为【{item.rfid}】的功能刀具已经存在拆解单,单号是【{dismantle_id[0].code}】') + tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True, compute='_compute_functional_tool_num') tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True) @@ -942,11 +951,13 @@ class FunctionalToolDismantle(models.Model): logging.info('%s刀具确认开始拆解' % self.dismantle_cause) code = self.code if self.functional_tool_id.functional_tool_status == '已拆除': - raise ValidationError('Rfid为【%s】的功能刀具已经拆解,请勿重复操作!' % self.functional_tool_id.rfid_dismantle) + raise ValidationError('Rfid为【%s】名称为【%s】的功能刀具已经拆解,请勿重复操作!' % ( + self.functional_tool_id.rfid_dismantle, self.name)) # 对拆解的功能刀具进行校验,只有在刀具房的功能刀具才能拆解 - if self.functional_tool_id.tool_room_num == 0: - raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % ( - self.rfid, self.functional_tool_id.current_location)) + elif self.functional_tool_id.functional_tool_status != '报警': + if self.functional_tool_id.tool_room_num == 0: + raise ValidationError('Rfid为【%s】的功能刀具当前位置为【%s】,不能进行拆解!' % ( + self.rfid, self.functional_tool_id.current_location)) # 目标重复校验 self.location_duplicate_check() datas = {'scrap': [], 'picking': []} diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py index 2c677e60..c48cf2ac 100644 --- a/sf_tool_management/models/functional_tool.py +++ b/sf_tool_management/models/functional_tool.py @@ -11,6 +11,7 @@ from odoo.exceptions import ValidationError class FunctionalCuttingToolEntity(models.Model): _name = 'sf.functional.cutting.tool.entity' _description = '功能刀具列表' + _order = 'functional_tool_status' functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具组装单', readonly=True) @@ -40,7 +41,7 @@ class FunctionalCuttingToolEntity(models.Model): max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True) alarm_value = fields.Integer(string='报警值(min)', readonly=True) used_value = fields.Integer(string='已使用值(min)', readonly=True) - functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], + functional_tool_status = fields.Selection([('报警', '报警'), ('正常', '正常'), ('已拆除', '已拆除')], string='状态', store=True, default='正常') current_location_id = fields.Many2one('stock.location', string='当前位置', compute='_compute_current_location_id', store=True) @@ -60,13 +61,14 @@ class FunctionalCuttingToolEntity(models.Model): if item.functional_tool_status == '报警': # 创建报警刀具拆解单 self.env['sf.functional.tool.dismantle'].sudo().create({ - 'functional_tool_id': item.id, + 'functional_tool_id': item.ids[0], 'dismantle_cause': '寿命到期报废' }) # 创建刀具报警记录 - # self.env['sf.functional.tool.warning'].sudo().create({ - # '' - # }) + self.env['sf.functional.tool.warning'].sudo().create({ + 'rfid': item.rfid, + 'functional_tool_id': item.ids[0] + }) @api.depends('barcode_id.quant_ids', 'barcode_id.quant_ids.location_id', 'functional_tool_status', 'current_shelf_location_id') @@ -253,10 +255,30 @@ class FunctionalCuttingToolEntity(models.Model): functional_tool_model_ids.append(functional_tool_model.id) return [(6, 0, functional_tool_model_ids)] + def open_functional_tool_dismantle_form(self): + self.ensure_one() + dismantle_ids = self.env['sf.functional.tool.dismantle'].sudo().search([('functional_tool_id', '=', self.id)]) + action = { + 'res_model': 'sf.functional.tool.dismantle', + 'type': 'ir.actions.act_window', + 'name': '拆解单', + } + if len(dismantle_ids) == 1: + action.update({ + 'view_mode': 'form', + 'res_id': dismantle_ids[0].id, + }) + else: + action.update({ + 'domain': [('id', 'in', dismantle_ids.ids)], + 'view_mode': 'tree,form', + }) + return action + def open_functional_tool_warning(self): action = self.env.ref('sf_tool_management.action_sf_functional_tool_warning') result = action.read()[0] - result['domain'] = [('functional_tool_name_id', '=', self.functional_tool_name_id.id)] + result['domain'] = [('functional_tool_id', '=', self.id)] return result def open_stock_move_line(self): @@ -338,10 +360,10 @@ class FunctionalToolWarning(models.Model): _name = 'sf.functional.tool.warning' _description = '功能刀具预警' - code = fields.Char('编码', related='functional_tool_name_id.code') - rfid = fields.Char('Rfid') - tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_name_id.tool_groups_id') - name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_name_id.name') + code = fields.Char('编码', related='functional_tool_id.code') + rfid = fields.Char('Rfid', readonly=True) + tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', related='functional_tool_id.tool_groups_id') + name = fields.Char('名称', invisible=True, readonly=True, related='functional_tool_id.name') # 机床信息 production_line_id = fields.Many2one('sf.production.line', string='生产线', group_expand='_read_group_machine_table_name_ids') @@ -352,30 +374,55 @@ class FunctionalToolWarning(models.Model): cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', domain="[('equipment_id', '=', maintenance_equipment_id)]") # 功能刀具信息 - functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称') - barcode_id = fields.Many2one('stock.lot', string='序列号', related='functional_tool_name_id.barcode_id') - mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型') - diameter = fields.Float(string='刀具直径(mm)') - knife_tip_r_angle = fields.Float(string='刀尖R角(mm)') + functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', string='功能刀具', readonly=True) + barcode_id = fields.Many2one('stock.lot', string='序列号', related='functional_tool_id.barcode_id') + mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', + related='functional_tool_id.sf_cutting_tool_type_id') + diameter = fields.Float(string='刀具直径(mm)', related='functional_tool_id.functional_tool_diameter') + knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', related='functional_tool_id.knife_tip_r_angle') # 其他信息 install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time') on_board_time = fields.Datetime('上机装刀时间') - max_lifetime_value = fields.Integer(string='最大寿命值(min)') - alarm_value = fields.Integer(string='报警值(min)') - used_value = fields.Integer(string='已使用值(min)') + max_lifetime_value = fields.Integer(string='最大寿命值(min)', related='functional_tool_id.max_lifetime_value') + alarm_value = fields.Integer(string='报警值(min)', related='functional_tool_id.alarm_value') + used_value = fields.Integer(string='已使用值(min)', related='functional_tool_id.used_value') functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态') - alarm_time = fields.Datetime('报警时间') - dispose_user = fields.Char('处理人') - dispose_time = fields.Char('处理时间') - dispose_func = fields.Char('处理方法/措施', readonly=False) + alarm_time = fields.Datetime('报警时间', default=lambda self: fields.Datetime.now(), readonly=True) + dispose_user = fields.Char('处理人', readonly=True) + dispose_time = fields.Char('处理时间', readonly=True) + dispose_func = fields.Char('处理方法/措施', readonly=True) active = fields.Boolean(string='已归档', default=True) + functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称') + @api.model def _read_group_machine_table_name_ids(self, categories, domain, order): machine_table_name_ids = categories._search([], order=order, access_rights_uid=SUPERUSER_ID) return categories.browse(machine_table_name_ids) + def action_open_dismantle(self): + self.ensure_one() + dismantle_ids = self.env['sf.functional.tool.dismantle'].sudo().search( + [('functional_tool_id', '=', self.functional_tool_id.id)]) + action = { + 'res_model': 'sf.functional.tool.dismantle', + 'type': 'ir.actions.act_window', + 'name': '拆解单' + } + if len(dismantle_ids) == 1: + action.update({ + 'view_mode': 'form', + 'res_id': dismantle_ids.ids[0] + }) + elif dismantle_ids: + action.update({ + 'view_mode': 'tree,form', + 'res_id': dismantle_ids.ids + }) + else: + return False + return action # def create_tool_warning_record(self, obj): # """ # 机台换刀申请报警状态时,创建功能刀具预警记录 diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml index 70edbafe..b0c78117 100644 --- a/sf_tool_management/views/functional_tool_views.xml +++ b/sf_tool_management/views/functional_tool_views.xml @@ -25,7 +25,10 @@ - + @@ -48,6 +51,16 @@ + + + + 拆解单 + + + sf.functional.tool.warning.tree sf.functional.tool.warning - + + - + diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml index c180c917..3c19fede 100644 --- a/sf_tool_management/views/tool_base_views.xml +++ b/sf_tool_management/views/tool_base_views.xml @@ -911,7 +911,7 @@ - From bf34de58fc46be7ab97cfc2102cbe5b9175eef00 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Tue, 13 Aug 2024 17:30:19 +0800 Subject: [PATCH 04/12] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=E5=88=80=E5=85=B7=E9=A2=84=E8=AD=A6=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E8=B7=B3=E8=BD=AC=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E6=8B=86?= =?UTF-8?q?=E8=A7=A3=E5=8D=95=E9=93=BE=E6=8E=A5=E6=96=B9=E6=B3=95=EF=BC=9B?= =?UTF-8?q?2=E3=80=81=E4=BC=98=E5=8C=96=E5=8A=9F=E8=83=BD=E5=88=80?= =?UTF-8?q?=E5=85=B7=E9=A2=84=E8=AD=A6=E7=95=8C=E9=9D=A2=E5=8F=8A=E6=90=9C?= =?UTF-8?q?=E7=B4=A2=E7=AD=89=E6=96=B9=E6=B3=95=EF=BC=9B3=E3=80=81?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8B=86=E8=A7=A3=E5=8D=95=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=8F=8A=E7=95=8C=E9=9D=A2=EF=BC=9B4=E3=80=81=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=BB=84=E8=A3=85?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E5=88=80=E6=9F=84=E7=8A=B6=E6=80=81=E4=B8=8D?= =?UTF-8?q?=E5=AE=9E=E6=97=B6=E5=8F=98=E6=9B=B4=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/models/base.py | 14 ++++++++++ sf_tool_management/models/functional_tool.py | 2 +- sf_tool_management/views/tool_base_views.xml | 28 ++++++++++++++++---- sf_tool_management/wizard/wizard.py | 2 ++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index fd9e6f29..2876bc8f 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -947,6 +947,12 @@ class FunctionalToolDismantle(models.Model): if self.chuck_freight_id == self.pad_freight_id: raise ValidationError('【夹头】和【刀盘】的目标货位重复,请重新选择!') + def tool_scrap(self): + self.scrap_boolean = True + + def tool_no_scrap(self): + self.scrap_boolean = False + def confirmation_disassembly(self): logging.info('%s刀具确认开始拆解' % self.dismantle_cause) code = self.code @@ -1016,6 +1022,14 @@ class FunctionalToolDismantle(models.Model): 'rfid': '%s(已拆解)' % self.rfid, 'state': '已拆解' }) + # ==================修改刀具预警信息的值============ + warning_id = self.env['sf.functional.tool.warning'].sudo().search( + [('functional_tool_id', '=', self.functional_tool_id.id)]) + if warning_id: + warning_id.sudo().write({ + 'dispose_user': self.env.user.name, + 'dispose_time': fields.Datetime.now() + }) logging.info('【%s】刀具拆解成功!' % self.name) def create_tool_picking_scrap(self, datas): diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py index c48cf2ac..d398b87b 100644 --- a/sf_tool_management/models/functional_tool.py +++ b/sf_tool_management/models/functional_tool.py @@ -418,7 +418,7 @@ class FunctionalToolWarning(models.Model): elif dismantle_ids: action.update({ 'view_mode': 'tree,form', - 'res_id': dismantle_ids.ids + 'domain': [('id', 'in', dismantle_ids.ids)], }) else: return False diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml index 3c19fede..e8278fd9 100644 --- a/sf_tool_management/views/tool_base_views.xml +++ b/sf_tool_management/views/tool_base_views.xml @@ -803,7 +803,8 @@ + options="{'no_create': True}" + attrs="{'readonly': ['|',('state', '=', '已拆解'),('id', '!=', False)]}"/> @@ -833,10 +834,26 @@ - + + + + + + + + + + + + + + - @@ -952,8 +969,9 @@ sf.functional.tool.dismantle + - + diff --git a/sf_tool_management/wizard/wizard.py b/sf_tool_management/wizard/wizard.py index 7ae92d65..52dc8529 100644 --- a/sf_tool_management/wizard/wizard.py +++ b/sf_tool_management/wizard/wizard.py @@ -842,6 +842,8 @@ class StockPicking(models.Model): stock_move_id = self.env['stock.move'] datas = {'data': [], 'picking_id': picking_id} if obj.handle_code_id: + # 修改刀柄序列号状态为【在用】 + obj.handle_code_id.sudo().write({'tool_material_status': '在用'}) datas['data'].append( {'current_location_id': self.env['sf.shelf.location'], 'lot_id': obj.handle_code_id}) if obj.integral_product_id: From 366e81626809cc6d3f081ad4fba112db8fca8193 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 15 Aug 2024 16:45:39 +0800 Subject: [PATCH 05/12] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E8=B4=A7?= =?UTF-8?q?=E4=BD=8D=E5=8F=98=E6=9B=B4=E6=8E=A5=E5=8F=A3=E3=80=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=90=8C=E6=AD=A5=E5=BA=93=E5=AD=98=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=9B2=E3=80=81=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E5=B7=B2=E5=8F=96=E6=B6=88=E7=8A=B6=E6=80=81=E7=9A=84=E9=94=80?= =?UTF-8?q?=E5=94=AE=E8=AE=A2=E5=8D=95=E7=9A=84=E3=80=90=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E6=8E=A5=E5=8D=95=E3=80=91=E5=92=8C=E3=80=90=E5=8F=96=E6=B6=88?= =?UTF-8?q?=E3=80=91=E6=8C=89=E9=92=AE=EF=BC=9B3=E3=80=81=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E4=BB=8E=E7=BA=BF?= =?UTF-8?q?=E8=BE=B9=E5=88=80=E5=BA=93=E5=88=B0=E5=88=80=E5=85=B7=E6=88=BF?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E7=94=9F=E6=88=90=E7=A7=BB=E5=8A=A8=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E9=97=AE=E9=A2=98=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/controllers/controllers.py | 29 +++-- sf_sale/views/sale_order_view.xml | 6 +- sf_tool_management/models/functional_tool.py | 41 +++---- .../models/maintenance_equipment.py | 2 +- sf_warehouse/models/sync_common.py | 111 ++++++++++-------- 5 files changed, 104 insertions(+), 85 deletions(-) diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 8075f126..50ad39b1 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -386,7 +386,7 @@ class Manufacturing_Connect(http.Controller): ret = json.loads(datas) request.env['center_control.interface.log'].sudo().create( {'content': ret, 'name': 'AutoDeviceApi/LocationChange'}) - logging.info('LocationChange_ret===========:%s' % ret) + logging.info('库位变更LocationChange_ret:%s' % ret) RfidCode = ret['RfidCode'] ChangeType = ret['ChangeType'] OldDeciveId = ret['OldDeciveId'] @@ -429,25 +429,36 @@ class Manufacturing_Connect(http.Controller): # 对功能刀具库位变更信息进行更改 def write_tool(DeciveId): if 'Tool' in DeciveId: - shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info(DeciveId) + shelfinfo = list(filter(lambda x: x.get('DeviceId') == DeciveId, + request.env['sf.shelf.location'].sudo().get_sf_shelf_location_info( + DeciveId))) + total_data = request.env['sf.shelf.location.datasync'].sudo().get_total_data() for item in shelfinfo: - shelf_barcode = self.env['sf.shelf.location.datasync'].find_our_code(item['Postion']) - location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], - limit=1) + shelf_barcode = request.env['sf.shelf.location.datasync'].sudo().find_our_code( + total_data, item['Postion']) + location_id = request.env['sf.shelf.location'].sudo().search( + [('barcode', '=', shelf_barcode)], + limit=1) if location_id: # 如果是线边刀库信息,则对功能刀具移动生成记录 if 'Tool' in item['Postion']: - tool = self.env['sf.functional.cutting.tool.entity'].sudo().search( + tool = request.env['sf.functional.cutting.tool.entity'].sudo().search( [('rfid', '=', item['RfidCode']), ('functional_tool_status', '!=', '已拆除')]) - tool.tool_in_out_stock_location(location_id) + tool.sudo().tool_in_out_stock_location(location_id) if tool: location_id.product_sn_id = tool.barcode_id.id + # 修改功能刀具状态 + # tool_install_time = {'Nomal': '正常', 'Warning': '报警'} + # tool.write({ + # 'functional_tool_status': tool_install_time.get(item['State']) + # }) else: location_id.product_sn_id = False + logging.info('货架已获取信息:%s' % item) else: - equipment_id = self.env['maintenance.equipment'].search([('name', '=', DeciveId)]) + equipment_id = request.env['maintenance.equipment'].sudo().search([('name', '=', DeciveId)]) if equipment_id: - equipment_id.register_equipment_tool() + equipment_id.sudo().register_equipment_tool() else: res_1 = {'Succeed': False, 'ErrorCode': 202, 'Error': f'设备【{DeciveId}】不存在'} return json.JSONEncoder().encode(res_1) diff --git a/sf_sale/views/sale_order_view.xml b/sf_sale/views/sale_order_view.xml index 75e2d0c1..ce27a4df 100644 --- a/sf_sale/views/sale_order_view.xml +++ b/sf_sale/views/sale_order_view.xml @@ -42,12 +42,12 @@ + attrs="{'invisible': ['|','&','|',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&','&',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel']),('delivery_status', '!=', False),('state', 'in', ['cancel'])]}"/> - {'invisible': ['|','&',('check_status', '!=', 'approved'),('state', + {'invisible': ['|','&','|', ('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&','&',('check_status', '=', 'approved'),('state', 'in', - ['sale','cancel']),('delivery_status', '!=', False)]} + ['sale','cancel']),('delivery_status', '!=', False), ('state', 'in', ['cancel'])]} diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py index d398b87b..06078528 100644 --- a/sf_tool_management/models/functional_tool.py +++ b/sf_tool_management/models/functional_tool.py @@ -118,27 +118,28 @@ class FunctionalCuttingToolEntity(models.Model): def tool_in_out_stock_location(self, location_id): tool_room_id = self.env['stock.location'].search([('name', '=', '刀具房')]) pre_manufacturing_id = self.env['stock.location'].search([('name', '=', '制造前')]) - for item in self: - # 中控反馈该位置有刀 - if item: - # 系统该位置有刀 - if location_id.product_sn_id: - # 中控反馈和系统中,该位置是同一把刀 - if item.barcode_id == location_id.product_sn_id: - return True - # 中控反馈和系统中,该位置不是同一把刀 - else: - # 原刀从线边出库 - item.tool_in_out_stock_location_1(location_id, tool_room_id) - # 新刀入库到线边 - item.create_stock_move(pre_manufacturing_id, location_id) - item.current_shelf_location_id = location_id.id + if self: + for item in self: + # 中控反馈该位置有刀 + if item: + # 系统该位置有刀 + if location_id.product_sn_id: + # 中控反馈和系统中,该位置是同一把刀 + if item.barcode_id == location_id.product_sn_id: + return True + # 中控反馈和系统中,该位置不是同一把刀 + else: + # 原刀从线边出库 + item.tool_in_out_stock_location_1(location_id, tool_room_id) + # 新刀入库到线边 + item.create_stock_move(pre_manufacturing_id, location_id) + item.current_shelf_location_id = location_id.id - # 中控反馈该位置没有刀 - else: - # 系统该位置有刀 - if location_id.product_sn_id: - item.tool_in_out_stock_location_1(location_id, tool_room_id) + # 中控反馈该位置没有刀 + else: + # 系统该位置有刀 + if location_id.product_sn_id: + self.tool_in_out_stock_location_1(location_id, tool_room_id) def tool_in_out_stock_location_1(self, location_id, tool_room_id): tool = self.env['sf.functional.cutting.tool.entity'].search( diff --git a/sf_tool_management/models/maintenance_equipment.py b/sf_tool_management/models/maintenance_equipment.py index 48bc531f..18142e24 100644 --- a/sf_tool_management/models/maintenance_equipment.py +++ b/sf_tool_management/models/maintenance_equipment.py @@ -53,7 +53,7 @@ class SfMaintenanceEquipment(models.Model): params = {"DeviceId": self.name} r = requests.get(crea_url, params=params, headers=headers) ret = r.json() - logging.info('register_equipment_tool:%s' % ret) + logging.info('机床刀库register_equipment_tool():%s' % ret) datas = ret['Datas'] self.write_maintenance_equipment_tool(datas) if ret['Succeed']: diff --git a/sf_warehouse/models/sync_common.py b/sf_warehouse/models/sync_common.py index 32632eac..f0f2fc93 100644 --- a/sf_warehouse/models/sync_common.py +++ b/sf_warehouse/models/sync_common.py @@ -13,79 +13,80 @@ class MrsShelfLocationDataSync(models.Model): _name = 'sf.shelf.location.datasync' _description = '同步库存信息' - def find_our_code(self, their_code): + def get_total_data(self): # 建立对应关系的函数 def align_data(my_data, their_data): paired_data = list(zip(my_data, their_data)) return paired_data - def get_total_data(): - shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1) - tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id') + logging.info('============================get_total_data()======================') + shelf_1_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边刀架')], limit=1) + tool_location_objs_1 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_1_obj.id)], order='id') - location_codes_1 = [location.barcode for location in tool_location_objs_1] - print(location_codes_1) - # 对方的数据列表 - their_data_1 = [f"ToolCab1-{i:02}" for i in range(1, 73)] + location_codes_1 = [location.barcode for location in tool_location_objs_1] + print(location_codes_1) + # 对方的数据列表 + their_data_1 = [f"ToolCab1-{i:02}" for i in range(1, 73)] - # 执行对齐 - aligned_data_1 = align_data(location_codes_1, their_data_1) + # 执行对齐 + aligned_data_1 = align_data(location_codes_1, their_data_1) - # 2 - shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边刀架')], limit=1) - tool_location_objs_2 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_2_obj.id)], order='id') + # 2 + shelf_2_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边刀架')], limit=1) + tool_location_objs_2 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_2_obj.id)], order='id') - location_codes_2 = [location.barcode for location in tool_location_objs_2] - print(location_codes_2) - # 对方的数据列表 - their_data_2 = [f"ToolCab2-{i:02}" for i in range(1, 73)] + location_codes_2 = [location.barcode for location in tool_location_objs_2] + print(location_codes_2) + # 对方的数据列表 + their_data_2 = [f"ToolCab2-{i:02}" for i in range(1, 73)] - # 执行对齐 - aligned_data_2 = align_data(location_codes_2, their_data_2) + # 执行对齐 + aligned_data_2 = align_data(location_codes_2, their_data_2) - # 4 - shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边料架')], limit=1) - tool_location_objs_4 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_4_obj.id)], order='id') + # 4 + shelf_4_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-一号线边料架')], limit=1) + tool_location_objs_4 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_4_obj.id)], order='id') - location_codes_4 = [location.barcode for location in tool_location_objs_4] - print(location_codes_4) - # 对方的数据列表 - their_data_4 = [f"PartCab4-{i:02}" for i in range(1, 17)] + location_codes_4 = [location.barcode for location in tool_location_objs_4] + print(location_codes_4) + # 对方的数据列表 + their_data_4 = [f"PartCab4-{i:02}" for i in range(1, 17)] - # 执行对齐 - aligned_data_4 = align_data(location_codes_4, their_data_4) + # 执行对齐 + aligned_data_4 = align_data(location_codes_4, their_data_4) - # 3 - shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边料架')], limit=1) - tool_location_objs_3 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_3_obj.id)], order='id') + # 3 + shelf_3_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-二号线边料架')], limit=1) + tool_location_objs_3 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_3_obj.id)], order='id') - location_codes_3 = [location.barcode for location in tool_location_objs_3] - print(location_codes_3) - # 对方的数据列表 - their_data_3 = [f"PartCab3-{i:02}" for i in range(1, 13)] + location_codes_3 = [location.barcode for location in tool_location_objs_3] + print(location_codes_3) + # 对方的数据列表 + their_data_3 = [f"PartCab3-{i:02}" for i in range(1, 13)] - # 执行对齐 - aligned_data_3 = align_data(location_codes_3, their_data_3) + # 执行对齐 + aligned_data_3 = align_data(location_codes_3, their_data_3) - # 5 - shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-三号线边料架')], limit=1) - tool_location_objs_5 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_5_obj.id)], order='id') + # 5 + shelf_5_obj = self.env['sf.shelf'].search([('name', '=', '一号产线-三号线边料架')], limit=1) + tool_location_objs_5 = self.env['sf.shelf.location'].search([('shelf_id', '=', shelf_5_obj.id)], order='id') - location_codes_5 = [location.barcode for location in tool_location_objs_5] - print(location_codes_5) - # 对方的数据列表 - their_data_5 = [f"PartCab5-{i:02}" for i in range(1, 13)] + location_codes_5 = [location.barcode for location in tool_location_objs_5] + print(location_codes_5) + # 对方的数据列表 + their_data_5 = [f"PartCab5-{i:02}" for i in range(1, 13)] - # 执行对齐 - aligned_data_5 = align_data(location_codes_5, their_data_5) + # 执行对齐 + aligned_data_5 = align_data(location_codes_5, their_data_5) - total_data = aligned_data_1 + aligned_data_2 + aligned_data_3 + aligned_data_4 + aligned_data_5 - print(total_data) - logging.info(f"total_data: {total_data}") - return total_data + total_data = aligned_data_1 + aligned_data_2 + aligned_data_3 + aligned_data_4 + aligned_data_5 + print(total_data) + logging.info(f"total_data: {total_data}") + return total_data - for code_pair in get_total_data(): + def find_our_code(self, total_data, their_code): + for code_pair in total_data: if code_pair[1] == their_code: return code_pair[0] return None # 如果没有找到对应的值,返回None或适当的默认值 @@ -106,9 +107,10 @@ class MrsShelfLocationDataSync(models.Model): equipment_id.register_equipment_tool() shelfinfo = self.env['sf.shelf.location'].get_sf_shelf_location_info() + total_data = self.get_total_data() print('shelfinfo:', shelfinfo) for item in shelfinfo: - shelf_barcode = self.find_our_code(item['Postion']) + shelf_barcode = self.find_our_code(total_data, item['Postion']) location_id = self.env['sf.shelf.location'].search([('barcode', '=', shelf_barcode)], limit=1) if location_id: # 如果是线边刀库信息,则对功能刀具移动生成记录 @@ -118,6 +120,11 @@ class MrsShelfLocationDataSync(models.Model): tool.tool_in_out_stock_location(location_id) if tool: location_id.product_sn_id = tool.barcode_id.id + # 修改功能刀具状态 + # tool_install_time = {'Nomal': '正常', 'Warning': '报警'} + # tool.write({ + # 'functional_tool_status': tool_install_time.get(item['State']) + # }) else: location_id.product_sn_id = False else: From e78516f73c789528dbc3ff85d9177408b7b9f403 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Fri, 16 Aug 2024 15:59:24 +0800 Subject: [PATCH 06/12] =?UTF-8?q?1=E3=80=81=20=20=E5=AE=8C=E6=88=90=20=20?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=BB=84=E8=A3=85=E5=92=8C?= =?UTF-8?q?=E6=8B=86=E8=A7=A3=E9=A1=B5=E9=9D=A2=E6=89=AB=E6=8F=8F=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E4=BC=98=E5=8C=96=E9=9C=80=E6=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_tool_management/views/tool_base_views.xml | 11 ++++++++--- sf_tool_management/wizard/wizard_view.xml | 7 ++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sf_tool_management/views/tool_base_views.xml b/sf_tool_management/views/tool_base_views.xml index e8278fd9..2fc9d5ba 100644 --- a/sf_tool_management/views/tool_base_views.xml +++ b/sf_tool_management/views/tool_base_views.xml @@ -704,10 +704,10 @@ sf.functional.tool.assembly + - @@ -800,6 +800,11 @@ + - + - + diff --git a/sf_tool_management/wizard/wizard_view.xml b/sf_tool_management/wizard/wizard_view.xml index b6e15586..b5c2f82e 100644 --- a/sf_tool_management/wizard/wizard_view.xml +++ b/sf_tool_management/wizard/wizard_view.xml @@ -201,6 +201,11 @@ + @@ -368,7 +373,7 @@ From cc05e8423e77c5bedd7ef5fa3f0757a770351353 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Fri, 16 Aug 2024 16:01:24 +0800 Subject: [PATCH 07/12] =?UTF-8?q?1=E3=80=81=E6=B3=A8=E9=87=8A=E9=87=8D?= =?UTF-8?q?=E5=86=99=E7=9A=84=E9=94=80=E5=94=AE=E5=8D=95=E4=BA=A4=E8=B4=A7?= =?UTF-8?q?=E6=8C=89=E9=92=AE=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_sale/views/purchase_order_view.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sf_sale/views/purchase_order_view.xml b/sf_sale/views/purchase_order_view.xml index eda8e59d..a45d8049 100644 --- a/sf_sale/views/purchase_order_view.xml +++ b/sf_sale/views/purchase_order_view.xml @@ -86,6 +86,18 @@ + + + + + + {'readonly': [('state', 'in', ['purchase'])]} From 5ad35de76b920cb9dbacfa09f9e2a8438972427a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Mon, 19 Aug 2024 11:22:30 +0800 Subject: [PATCH 08/12] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dagv=E8=B0=83=E5=BA=A6bu?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/data/agv_scheduling_data.xml | 3 +++ sf_manufacturing/security/ir.model.access.csv | 5 +++++ .../views/agv_scheduling_views.xml | 20 +++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/sf_manufacturing/data/agv_scheduling_data.xml b/sf_manufacturing/data/agv_scheduling_data.xml index c5f6d6a1..f9dc6362 100644 --- a/sf_manufacturing/data/agv_scheduling_data.xml +++ b/sf_manufacturing/data/agv_scheduling_data.xml @@ -6,6 +6,9 @@ sf.agv.scheduling B%(year)s%(month)s%(day)s 4 + 1 + standard + True diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index f8affb19..fd3b0d21 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -151,6 +151,11 @@ access_sf_production_wizard_group_sf_order_user,sf_production_wizard_group_sf_or access_sf_processing_panel_group_plan_dispatch,sf_processing_panel_group_plan_dispatch,model_sf_processing_panel,sf_base.group_plan_dispatch,1,1,1,0 access_sf_agv_scheduling_admin,sf_agv_scheduling_admin,model_sf_agv_scheduling,base.group_system,1,1,1,1 +access_sf_agv_scheduling_group_sf_order_user,sf_agv_scheduling_group_sf_order_user,model_sf_agv_scheduling,sf_base.group_sf_order_user,1,1,1,0 +access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_manager,model_sf_agv_scheduling,sf_base.group_sf_mrp_manager,1,1,1,0 +access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0 + + diff --git a/sf_manufacturing/views/agv_scheduling_views.xml b/sf_manufacturing/views/agv_scheduling_views.xml index 642e65cd..684c32e8 100644 --- a/sf_manufacturing/views/agv_scheduling_views.xml +++ b/sf_manufacturing/views/agv_scheduling_views.xml @@ -37,10 +37,30 @@ + + sf.agv.scheduling.search + sf.agv.scheduling + + + + + + + + + + + AGV调度 sf.agv.scheduling tree + + { + "search_default_filter_to_be_issued": 1, + "search_default_filter_delivering": 1, + } + Date: Mon, 19 Aug 2024 14:37:55 +0800 Subject: [PATCH 09/12] =?UTF-8?q?=E4=BF=AE=E6=94=B9agv=E8=B0=83=E5=BA=A6?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/agv_scheduling.py | 15 +++++++++++++++ sf_manufacturing/views/agv_scheduling_views.xml | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/sf_manufacturing/models/agv_scheduling.py b/sf_manufacturing/models/agv_scheduling.py index 1a448146..c84f741d 100644 --- a/sf_manufacturing/models/agv_scheduling.py +++ b/sf_manufacturing/models/agv_scheduling.py @@ -50,6 +50,21 @@ class AgvScheduling(models.Model): delivery_workpieces = fields.Char('配送工件', compute=_compute_delivery_workpieces) + @api.model + def web_search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, count_limit=None): + domain = domain or [] + new_domain = [] + for index, item in enumerate(domain): + if isinstance(item, list): + if item[0] == 'delivery_workpieces': + new_domain.append('&') + new_domain.append(['workorder_ids.production_id.name', item[1], item[2]]) + new_domain.append(['agv_route_type', '!=', '运送空料架']) + continue + new_domain.append(item) + + return super(AgvScheduling, self).web_search_read(new_domain, fields, limit=limit, offset=offset) + @api.depends('task_completion_time', 'task_delivery_time') def _compute_task_duration(self): for rec in self: diff --git a/sf_manufacturing/views/agv_scheduling_views.xml b/sf_manufacturing/views/agv_scheduling_views.xml index 684c32e8..be7b35cf 100644 --- a/sf_manufacturing/views/agv_scheduling_views.xml +++ b/sf_manufacturing/views/agv_scheduling_views.xml @@ -43,6 +43,10 @@ + + + + From 062ca66328f80bb50fa27d739a771ae9f2709d7e Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Mon, 19 Aug 2024 17:29:09 +0800 Subject: [PATCH 10/12] =?UTF-8?q?1=E3=80=81=E5=BA=93=E4=BD=8D=E5=8F=98?= =?UTF-8?q?=E6=9B=B4=E6=8E=A5=E5=8F=A3=E3=80=81=E5=BA=93=E4=BD=8D=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E6=8E=A5=E5=8F=A3=E4=BC=98=E5=8C=96=EF=BC=9B2?= =?UTF-8?q?=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?from=E9=A1=B5=E9=9D=A2=E6=8C=89=E9=92=AE=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E5=8F=8A=E6=98=BE=E7=A4=BA=E4=BC=98=E5=8C=96=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/controllers/controllers.py | 10 ++++++---- sf_tool_management/models/functional_tool.py | 11 ++++++++++- sf_tool_management/views/functional_tool_views.xml | 12 +++++++----- sf_warehouse/models/sync_common.py | 10 ++++++---- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 86d919f3..6116ac12 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -450,10 +450,12 @@ class Manufacturing_Connect(http.Controller): if tool: location_id.product_sn_id = tool.barcode_id.id # 修改功能刀具状态 - # tool_install_time = {'Nomal': '正常', 'Warning': '报警'} - # tool.write({ - # 'functional_tool_status': tool_install_time.get(item['State']) - # }) + tool_state = {'Nomal': '正常', 'Warning': '报警'} + if tool_state.get(item.get('State')): + if tool_state.get(item.get('State')) != tool.functional_tool_status: + tool.write({ + 'functional_tool_status': tool_state.get(item['State']) + }) else: location_id.product_sn_id = False logging.info('货架已获取信息:%s' % item) diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py index 06078528..55a87339 100644 --- a/sf_tool_management/models/functional_tool.py +++ b/sf_tool_management/models/functional_tool.py @@ -41,7 +41,7 @@ class FunctionalCuttingToolEntity(models.Model): max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True) alarm_value = fields.Integer(string='报警值(min)', readonly=True) used_value = fields.Integer(string='已使用值(min)', readonly=True) - functional_tool_status = fields.Selection([('报警', '报警'), ('正常', '正常'), ('已拆除', '已拆除')], + functional_tool_status = fields.Selection([('正常', '正常'), ('报警', '报警'), ('已拆除', '已拆除')], string='状态', store=True, default='正常') current_location_id = fields.Many2one('stock.location', string='当前位置', compute='_compute_current_location_id', store=True) @@ -256,6 +256,15 @@ class FunctionalCuttingToolEntity(models.Model): functional_tool_model_ids.append(functional_tool_model.id) return [(6, 0, functional_tool_model_ids)] + dismantle_num = fields.Integer('拆解单数量', compute='_compute_dismantle_num', store=True) + dismantle_ids = fields.One2many('sf.functional.tool.dismantle', 'functional_tool_id', '拆解单') + + @api.depends('dismantle_ids') + def _compute_dismantle_num(self): + for item in self: + if item: + item.dismantle_num = len(item.dismantle_ids) + def open_functional_tool_dismantle_form(self): self.ensure_one() dismantle_ids = self.env['sf.functional.tool.dismantle'].sudo().search([('functional_tool_id', '=', self.id)]) diff --git a/sf_tool_management/views/functional_tool_views.xml b/sf_tool_management/views/functional_tool_views.xml index b0c78117..b2e71fb3 100644 --- a/sf_tool_management/views/functional_tool_views.xml +++ b/sf_tool_management/views/functional_tool_views.xml @@ -53,12 +53,14 @@ - - - 拆解单 + icon="fa-credit-card" + type="object" + attrs="{'invisible': [('dismantle_num', '=', 0)]}"> + + + + 拆解单 Date: Tue, 20 Aug 2024 10:45:31 +0800 Subject: [PATCH 11/12] =?UTF-8?q?=E7=94=9F=E4=BA=A7=E6=80=BB=E7=9B=91?= =?UTF-8?q?=E3=80=81=E6=9C=BA=E5=BA=8A=E6=93=8D=E4=BD=9C=E5=B2=97=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0agv=E8=B0=83=E5=BA=A6=E8=8F=9C=E5=8D=95=E6=9D=83?= =?UTF-8?q?=E9=99=90=EF=BC=8CAGV=E4=B8=8B=E5=8F=91=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E7=95=8C=E9=9D=A2=E9=9C=80=E4=BA=8C=E6=AC=A1=E7=A1=AE=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/__manifest__.py | 1 + sf_manufacturing/controllers/controllers.py | 4 +- sf_manufacturing/models/agv_scheduling.py | 1 + .../js/workpiece_delivery_wizard_confirm.js | 53 +++++++++++++++ .../views/agv_scheduling_views.xml | 1 + sf_manufacturing/views/mrp_workorder_view.xml | 6 ++ .../wizard/workpiece_delivery_views.xml | 4 +- .../wizard/workpiece_delivery_wizard.py | 68 ++++++++++++------- sf_plan/views/view.xml | 1 + 9 files changed, 112 insertions(+), 27 deletions(-) create mode 100644 sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index 9ea3bb60..e84b34cc 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -43,6 +43,7 @@ 'sf_manufacturing/static/src/js/kanban_change.js', 'sf_manufacturing/static/src/scss/kanban_change.scss', 'sf_manufacturing/static/src/xml/button_show_on_tree.xml', + 'sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js', ] }, diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 84ee9f46..4c5788ef 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -458,7 +458,7 @@ class Manufacturing_Connect(http.Controller): if f'RfidCode{i}' in ret: rfid_code = ret[f'RfidCode{i}'] logging.info('RfidCode:%s' % rfid_code) - if rfid_code is not None: + if rfid_code is not None and rfid_code != '': rfid_codes.append(rfid_code) domain = [ ('rfid_code', '=', rfid_code), @@ -531,7 +531,7 @@ class Manufacturing_Connect(http.Controller): if f'RfidCode{i}' in ret: rfid_code = ret[f'RfidCode{i}'] logging.info('RfidCode:%s' % rfid_code) - if rfid_code is not None: + if rfid_code is not None and rfid_code != '': domain = [ ('rfid_code', '=', rfid_code), ('routing_type', '=', 'CNC加工'), ('state', '!=', 'rework') diff --git a/sf_manufacturing/models/agv_scheduling.py b/sf_manufacturing/models/agv_scheduling.py index c84f741d..4fbfbf8d 100644 --- a/sf_manufacturing/models/agv_scheduling.py +++ b/sf_manufacturing/models/agv_scheduling.py @@ -88,6 +88,7 @@ class AgvScheduling(models.Model): agv_route_type: AGV任务类型 workorders: 工单 """ + _logger.info('创建AGV调度任务\r\n起点为【%s】,任务类型为【%s】,工单为【%s】' % (agv_start_site_name, agv_route_type, workorders)) if not workorders: raise UserError(_('工单不能为空')) agv_start_site = self.env['sf.agv.site'].sudo().search([('name', '=', agv_start_site_name)], limit=1) diff --git a/sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js b/sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js new file mode 100644 index 00000000..cb044955 --- /dev/null +++ b/sf_manufacturing/static/src/js/workpiece_delivery_wizard_confirm.js @@ -0,0 +1,53 @@ +odoo.define('sf_manufacturing.action_dispatch_confirm', function (require) { + const core = require('web.core'); + const ajax = require('web.ajax'); + const Dialog = require('web.Dialog'); + var rpc = require('web.rpc'); + var _t = core._t; + + async function dispatch_confirm(parent, {params}) { + console.log(params, 'params') + console.log("本次下发的工件数量为:" + params.workorder_count + ",是否确认?", 'content') + const dialog = new Dialog(parent, { + title: "确认", + $content: $('').append("请确认是否仅配送" + params.workorder_count + "个工件?"), + buttons: [ + { text: "确认", classes: 'btn-primary', close: true, click: () => dispatchConfirmed(parent, params) }, + { text: "取消", close: true }, + ], + }); + dialog.open(); + + + async function dispatchConfirmed(parent, params) { + console.log(parent, 'parent') + rpc.query({ + model: 'sf.workpiece.delivery.wizard', + method: 'confirm', + args: [params.active_id] + , + kwargs: { + context: params.context, + } + }).then(res => { + console.log(res, 'res') + console.log(res.name, 'res') + parent.services.action.doAction({ + 'type': 'ir.actions.client', + 'tag': 'display_notification', + 'target': 'new', + 'params': { + 'message': '任务下发成功!AGV任务调度编号为【' + res.name + '】', + 'type': 'success', + 'sticky': false, + 'next': {'type': 'ir.actions.act_window_close'}, + } + }); + }) + + } + } + + core.action_registry.add('dispatch_confirm', dispatch_confirm); + return dispatch_confirm; +}); diff --git a/sf_manufacturing/views/agv_scheduling_views.xml b/sf_manufacturing/views/agv_scheduling_views.xml index be7b35cf..ef932e54 100644 --- a/sf_manufacturing/views/agv_scheduling_views.xml +++ b/sf_manufacturing/views/agv_scheduling_views.xml @@ -73,6 +73,7 @@ sequence="28" action="action_agv_scheduling_tree" parent="mrp.menu_mrp_manufacturing" + groups="sf_base.group_sf_order_user,sf_base.group_sf_mrp_manager,sf_base.group_sf_equipment_user" /> \ No newline at end of file diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index b0815ed5..12b15968 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -835,5 +835,11 @@ tree [('type','in',['运送空料架']),('name','not ilike','WDO')] + + diff --git a/sf_manufacturing/wizard/workpiece_delivery_views.xml b/sf_manufacturing/wizard/workpiece_delivery_views.xml index cec33be9..a4723b6b 100644 --- a/sf_manufacturing/wizard/workpiece_delivery_views.xml +++ b/sf_manufacturing/wizard/workpiece_delivery_views.xml @@ -18,8 +18,8 @@