From d777970a9b8b3f9244c0f8a06095e8c9414a4de2 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Tue, 16 Apr 2024 16:22:26 +0800 Subject: [PATCH 01/20] =?UTF-8?q?1.ftp=E6=96=87=E4=BB=B6=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=BA:/NC/=E4=BB=A5=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/controllers/controllers.py | 16 +++++ sf_manufacturing/models/mrp_production.py | 2 +- sf_manufacturing/models/mrp_workorder.py | 70 ++++++++++++------- sf_manufacturing/models/product_template.py | 4 +- sf_manufacturing/views/mrp_workorder_view.xml | 5 ++ sf_mrs_connect/models/ftp_operate.py | 17 ++++- sf_mrs_connect/models/res_config_setting.py | 15 ++++ sf_mrs_connect/models/sync_common.py | 1 + .../views/res_config_settings_views.xml | 2 + sf_sale/models/quick_easy_order_old.py | 4 +- 10 files changed, 103 insertions(+), 33 deletions(-) diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 63fd4f57..d530b227 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import logging import json +from datetime import datetime from odoo import http from odoo.http import request @@ -438,6 +439,7 @@ class Manufacturing_Connect(http.Controller): logging.info('wd.production_id:%s' % wd.production_id.name) logging.info('wd.production_line_state:%s' % wd.production_id.production_line_state) wd.production_id.write({'production_line_state': '已上产线'}) + wd.write({'production_line_state': '已上产线'}) else: res = {'Succeed': False, 'ErrorCode': 203, 'Error': '该DeviceId没有对应的工件配送数据'} else: @@ -471,7 +473,21 @@ class Manufacturing_Connect(http.Controller): if wd.workorder_id.state == 'done' and wd.production_id.production_line_state == '已上产线': logging.info('wd.production_id:%s' % wd.production_id.name) logging.info('wd.production_line_state:%s' % wd.production_id.production_line_state) + workpiece_delivery_off=request.env['sf.workpiece.delivery'].create({ + 'production_id': wd.production_id.id, + 'feeder_station_start': ret['DeviceId'], + 'feeder_station_destination': '', + 'workorder_id': workpiece_delivery.workorder_id, + 'workpiece_code': workpiece_delivery.workpiece_code, + 'production_line_id': workpiece_delivery.production_line_id, + 'task_delivery_time': datetime.now(), + 'production_line_state': '已下产线' + }) wd.production_id.write({'production_line_state': '已下产线'}) + logging.info('开始向agv下发下产线任务') + workpiece_delivery_off._delivery_avg() + logging.info('agv下发下产线任务已配送') + else: res = {'Succeed': False, 'ErrorCode': 203, 'Error': '该DeviceId没有对应的工件配送数据'} else: diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index dff2763b..7c389c2d 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -146,7 +146,7 @@ class MrpProduction(models.Model): 'embryo_height': cnc.product_id.bom_ids.bom_line_ids.product_id.height, 'embryo_width': cnc.product_id.bom_ids.bom_line_ids.product_id.width, 'order_no': cnc.origin, - 'model_order_no': cnc.product_id.default_code.rsplit(' -', 1)[0], + 'model_order_no': '-'.join(cnc.product_id.default_code.split('-')[:4]), 'user': cnc.env.user.name, 'model_file': '' if not cnc.product_id.model_file else base64.b64encode( cnc.product_id.model_file).decode('utf-8') diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 89510ae0..6053222e 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -241,16 +241,19 @@ class ResMrpWorkOrder(models.Model): # if not item.workpiece_code: # raise UserError('请对【同运工件】进行扫描') else: - if item.status == '待下发': - return { - 'name': _('确认'), - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'sf.workpiece.delivery.wizard', - 'target': 'new', - 'context': { - 'default_workorder_id': self.id, - }} + if self.cnc_program_down_state == '已下发': + if item.status == '待下发': + return { + 'name': _('确认'), + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'sf.workpiece.delivery.wizard', + 'target': 'new', + 'context': { + 'default_workorder_id': self.id, + }} + else: + raise UserError(_("该制造订单还未下发CNC程序单,无法进行工件配送")) # 拼接工单对象属性值 def json_workorder_str(self, k, production, route): @@ -654,7 +657,7 @@ class ResMrpWorkOrder(models.Model): production_no_ftp = reportpath.split('/') production_no = workorder.production_id.name.replace('/', '_') # ftp地址 - remotepath = os.path.join('/', production_no_ftp[1], 'detection') + remotepath = os.path.join('/NC/', production_no_ftp[1], 'detection') logging.info('ftp地址:%s' % remotepath) if reportpath.find(production_no) != -1: # 服务器内临时地址 @@ -772,8 +775,8 @@ class CNCprocessing(models.Model): # 将FTP的nc文件下载到临时目录 def download_file_tmp(self, production_no, processing_panel): - remotepath = os.path.join('/', production_no, 'return', processing_panel) - serverdir = os.path.join('/tmp', production_no, 'return', processing_panel) + remotepath = os.path.join('/NC/', production_no, 'return', processing_panel) + serverdir = os.pat.join('/tmp', production_no, 'return', processing_panel) 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']) @@ -956,26 +959,39 @@ class WorkPieceDelivery(models.Model): status = fields.Selection( [('待下发', '待下发'), ('待配送', '待配送'), ('已配送', '已配送')], string='状态', default='待下发') + production_line_state = fields.Selection( + [('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], + string='上/下产线', default='待上产线') + cnc_program_down_state = fields.Selection([('待下发', '待下发'), ('已下发', '已下发')], + string='CNC程序下发状态', default='待下发') # 工件配送 def button_delivery(self): - if self.status == '待下发': - return { - 'name': _('确认'), - 'type': 'ir.actions.act_window', - 'view_mode': 'form', - 'res_model': 'sf.workpiece.delivery.wizard', - 'target': 'new', - 'context': { - 'default_delivery_id': self.id, - }} + if self.cnc_program_down_state == '待下发': + if self.status == '待下发': + return { + 'name': _('确认'), + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'res_model': 'sf.workpiece.delivery.wizard', + 'target': 'new', + 'context': { + 'default_delivery_id': self.id, + }} + else: + raise UserError('状态为【待下发】的工件记录可进行配送') else: - raise UserError('状态为【待下发】的工件记录可进行配送') + raise UserError(_("该制造订单还未下发CNC程序单,无法进行工件配送")) # 配送至avg小车 def _delivery_avg(self): config = self.env['res.config.settings'].get_values() - agv_site = self.env['res.agv.site'].search([]) + site_production_line = False + if self.production_line_state == '待上产线': + site_production_line = [('production_line_status', '=', '已上产线')] + elif self.production_line_state == '已下产线': + site_production_line = [('production_line_status', '=', '已下产线')] + agv_site = self.env['res.agv.site'].search(site_production_line, order="number asc") positionCode_Arr = [] if agv_site: for item in agv_site: @@ -984,14 +1000,16 @@ class WorkPieceDelivery(models.Model): 'code': item.type }) res = {'reqCode': self.production_id.name, 'reqTime': '', 'clientCode': '', 'tokenCode': '', - 'taskTyp': config['task_type_no'], 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': config['wbcode'], + 'taskTyp': 'F01', 'ctnrTyp': '', 'ctnrCode': '', 'wbCode': config['wbcode'], 'positionCodePath': positionCode_Arr, 'podCode': '', 'podDir': '', 'materialLot': '', 'priority': '', 'taskCode': '', 'agvCode': '', 'materialLot': '', 'data': ''} try: + config['agv_rcs_url'] = 'http://172.16.10.114:8182/rcms/services/rest/hikRpcService/genAgvSchedulingTask' logging.info('AGV请求路径:%s' % config['agv_rcs_url']) logging.info('AGV-json:%s' % res) + headers = {'Content-Type': 'application/json'} ret = requests.post((config['agv_rcs_url']), json=res, headers=headers) ret = ret.json() diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index f3cba150..d81b41b9 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -6,8 +6,8 @@ import os from odoo import models, fields, api, _ from odoo.exceptions import ValidationError from odoo.modules import get_resource_path -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 9a747791..e9d27ca5 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -419,6 +419,7 @@ + @@ -560,6 +561,7 @@ + @@ -584,6 +586,9 @@ + + + diff --git a/sf_mrs_connect/models/ftp_operate.py b/sf_mrs_connect/models/ftp_operate.py index c8d0abb6..0600ce49 100644 --- a/sf_mrs_connect/models/ftp_operate.py +++ b/sf_mrs_connect/models/ftp_operate.py @@ -27,8 +27,16 @@ class FtpController(): os.makedirs(serverdir) try: logging.info("进入FTP目录 ") - self.ftp.cwd(target_dir) # 切换工作路径 - logging.info('FTP目录:%s' % target_dir) + logging.info('目录:%s' % target_dir) + target_dir1 = target_dir.split('/') + logging.info('目录1:%s' % target_dir1[1]) + self.ftp.cwd(target_dir1[1]) # 切换工作路径 + logging.info('目录2:%s' % target_dir1[2]) + self.ftp.cwd(target_dir1[2]) # 切换工作路径 + logging.info('目录3:%s' % target_dir1[3]) + self.ftp.cwd(target_dir1[3]) # 切换工作路径 + logging.info('目录4:%s' % target_dir1[4]) + self.ftp.cwd(target_dir1[4]) # 切换工作路径 remotenames = self.ftp.nlst() logging.info('FTP目录文件:%s' % remotenames) for file in remotenames: @@ -38,6 +46,9 @@ class FtpController(): return 1 except Exception: return 0 + finally: + self.ftp.quit() + logging.info("ftp已关闭") # 下载目录下的检测文件 def download_reportfile_tree(self, target_dir, serverdir, reportpath): @@ -51,6 +62,8 @@ class FtpController(): self.ftp.cwd(target_dir1[1]) # 切换工作路径 logging.info('目录2:%s' % target_dir1[2]) self.ftp.cwd(target_dir1[2]) # 切换工作路径 + logging.info('目录2:%s' % target_dir1[3]) + self.ftp.cwd(target_dir1[3]) # 切换工作路径 remotenames = self.ftp.nlst() logging.info('FTP目录检测报告文件:%s' % remotenames) for filename in remotenames: diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index 7aa46639..3f109cbe 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -140,5 +140,20 @@ class ResAgvSite(models.Model): _name = 'res.agv.site' _description = 'agv站点' + number = fields.Integer('编号') type = fields.Selection([('00', '位置编号'), ('01', '库区编号'), ('02', '货架编号')], '类型') content = fields.Char('内容') + site_prop = fields.Selection([('上产线', '上产线'), ('下产线', '下产线')], '属性') + state_status = fields.Selection([('占用', '占用'), ('空闲', '空闲')], '状态') + # remark = fields.Char + active = fields.Boolean('有效', default=True) + + # @api.model + # def create(self, vals): + # if vals.get('number', 'new') == 'new': + # vals['number'] = self.env['ir.sequence'].next_by_code('res.agv.site') or '/' + # return super(ResAgvSite, self).create(vals) + + def unlink(self): + for item in self: + item.active == True diff --git a/sf_mrs_connect/models/sync_common.py b/sf_mrs_connect/models/sync_common.py index 0a44f130..b6a3c937 100644 --- a/sf_mrs_connect/models/sync_common.py +++ b/sf_mrs_connect/models/sync_common.py @@ -2375,6 +2375,7 @@ class CuttingToolBasicParameters(models.Model): r = requests.post(strUrl, json={}, data=None, headers=headers) r = r.json() result = json.loads(r['result']) + logging.info(result) if result['status'] == 1: if 'basic_parameters_integral_tool' in result['cutting_tool_basic_parameters_all_list']: if result['cutting_tool_basic_parameters_all_list']['basic_parameters_integral_tool']: diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml index e297f0eb..0a60df0a 100644 --- a/sf_mrs_connect/views/res_config_settings_views.xml +++ b/sf_mrs_connect/views/res_config_settings_views.xml @@ -6,8 +6,10 @@ res.agv.site + + diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py index 28618488..651e1ea8 100644 --- a/sf_sale/models/quick_easy_order_old.py +++ b/sf_sale/models/quick_easy_order_old.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError From 8dfef16b519ff2a4f94f98df7479d8d62831eb6c Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 18 Apr 2024 15:38:16 +0800 Subject: [PATCH 02/20] =?UTF-8?q?1=E3=80=81=E4=BA=A7=E5=93=81=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E3=80=81=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E3=80=81=E5=B7=A5=E5=8D=95=E6=A8=A1=E5=9E=8B=EF=BC=8C?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=BA=E5=B7=A5=E7=BC=96=E7=A8=8B=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=EF=BC=9B2=E3=80=81=E6=94=BE=E5=BC=80=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E6=89=AB=E6=8F=8F=E7=BB=91=E5=AE=9ARfid=E7=9A=84?= =?UTF-8?q?=E6=A3=80=E9=AA=8C=E5=8A=9F=E8=83=BD=EF=BC=9B3=E3=80=81bfm?= =?UTF-8?q?=E4=B8=8B=E5=8D=95=E5=88=9B=E5=BB=BA=E4=BA=A7=E5=93=81=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E4=BA=BA=E5=B7=A5=E6=8A=A5=E4=BB=B7=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=86=85=E5=AE=B9=EF=BC=9B4=E3=80=81=E4=BC=98=E5=8C=96CNC?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E7=94=A8=E5=88=80=E6=A3=80=E9=AA=8C=E5=BA=93?= =?UTF-8?q?=E5=8C=BA=E6=98=AF=E5=90=A6=E6=9C=89=E5=88=80=E7=9A=84=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 2 + sf_manufacturing/models/mrp_workorder.py | 10 ++-- sf_manufacturing/models/product_template.py | 2 +- sf_sale/models/sale_order.py | 6 +++ sf_tool_management/models/base.py | 53 +++++++++++++-------- sf_tool_management/models/mrp_workorder.py | 1 + sf_warehouse/models/model.py | 2 +- 7 files changed, 50 insertions(+), 26 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index dff2763b..24ac58b2 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -57,6 +57,8 @@ class MrpProduction(models.Model): production_line_state = fields.Selection([('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], string='上/下产线', default='待上产线') + manual_quotation = fields.Boolean('人工编程', default=False) + @api.depends( 'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'workorder_ids.state', 'product_qty', 'qty_producing', 'schedule_state') diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 134922d1..c9d72b79 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -46,6 +46,8 @@ class ResMrpWorkOrder(models.Model): ], string="工序类型") results = fields.Char('结果') + manual_quotation = fields.Boolean('人工编程', default=False) + @api.onchange('users_ids') def get_user_permissions(self): uid = self.env.uid @@ -984,9 +986,9 @@ class SfWorkOrderBarcodes(models.Model): workorder = self.env['mrp.workorder'].browse(self.ids) # workorder = self.env['mrp.workorder'].search( # [('routing_type', '=', '装夹预调'), ('production_id', '=', self.production_id.id)]) - # workorder_old = self.env['mrp.workorder'].search([('rfid_code', '=', barcode)]) - # if workorder_old: - # raise UserError('该托盘已绑定工件,请先解除绑定!!!') + workorder_old = self.env['mrp.workorder'].search([('rfid_code', '=', barcode)]) + if workorder_old: + raise UserError('该托盘已绑定工件,请先解除绑定!!!') if workorder: if workorder.routing_type == '装夹预调': if workorder.state in ['done']: @@ -1046,7 +1048,7 @@ class SfWorkOrderBarcodes(models.Model): for item in workorder_rfid: if item.state == "progress": item.write({'rfid_code': barcode}) - # raise UserError('该托盘信息不存在!!!') + raise UserError('该托盘信息不存在!!!') # stock_move_line = self.env['stock.move.line'].search([('lot_name', '=', barcode)]) # if stock_move_line.product_id.categ_type == '夹具': # workorder.write({ diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index f3cba150..57ad0eaa 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -10,7 +10,6 @@ from OCC.Extend.DataExchange import read_step_file from OCC.Extend.DataExchange import write_stl_file - class ResProductMo(models.Model): _inherit = 'product.template' @@ -616,6 +615,7 @@ class ResProductMo(models.Model): 'process_parameters_code') else self.get_process_parameters_id(item['process_parameters_code']), 'model_remark': item['remark'], 'default_code': '%s-%s' % (order_number, i), + 'manual_quotation': item['manual_quotation'] or False, 'active': True, } copy_product_id.sudo().write(vals) diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 05523194..379ff199 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -142,6 +142,12 @@ class ResaleOrderLine(models.Model): check_status = fields.Selection(related='order_id.check_status') +class ProductTemplate(models.Model): + _inherit = 'product.template' + + manual_quotation = fields.Boolean('人工编程', default=False) + + class RePurchaseOrder(models.Model): _inherit = 'purchase.order' diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index 56391077..01c3de46 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +import logging + from datetime import timedelta from odoo import SUPERUSER_ID from odoo import fields, models, api @@ -191,7 +193,7 @@ class CAMWorkOrderProgramKnifePlan(models.Model): machine_table_name_id = fields.Many2one('maintenance.equipment', string='机床名称', domain="[('production_line_id', '=', production_line_id)]") machine_table_name = fields.Char(string='机台号', readonly=True, related='machine_table_name_id.name') - cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', required=True, + cutter_spacing_code_id = fields.Many2one('maintenance.equipment.tool', string='刀位号', domain="[('equipment_id', '=', machine_table_name_id)]") whether_standard_knife = fields.Boolean(string='是否标准刀', default=True) need_knife_time = fields.Datetime(string='用刀时间', readonly=False) @@ -201,19 +203,20 @@ class CAMWorkOrderProgramKnifePlan(models.Model): barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', domain=[('product_id.name', '=', '功能刀具')]) - functional_tool_name = fields.Char(string='功能刀具名称', compute='_compute_functional_tool_name') - functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False) - tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组') - diameter = fields.Integer(string='刀具直径(mm)', readonly=False) - tool_included_angle = fields.Float(string='刀尖R角(mm)', readonly=False) - tool_loading_length = fields.Float(string='总长度(mm)', readonly=False) + functional_tool_name = fields.Char(string='功能刀具名称', readonly=True) + functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', + compute='_compute_tool_number', store=True) + tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_tool_number', store=True) + diameter = fields.Integer(string='刀具直径(mm)', compute='_compute_tool_number', store=True) + tool_included_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_tool_number', store=True) + tool_loading_length = fields.Float(string='总长度(mm)', compute='_compute_tool_number', store=True) extension_length = fields.Float(string='伸出长(mm)') effective_length = fields.Float(string='有效长(mm)') new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=False, default='0') coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], default='3', string='粗/中/精', readonly=False) L_D = fields.Float(string='L/D值', readonly=False) - clearance_length = fields.Float(string='避空长(mm)', readonly=False) + clearance_length = fields.Float(string='避空长(mm)', compute='_compute_tool_number', store=True) required_cutting_time = fields.Integer(string='需切削时长', readonly=False) process_type = fields.Char('加工类型') margin_x_y = fields.Float('余量_X/Y') @@ -229,15 +232,24 @@ class CAMWorkOrderProgramKnifePlan(models.Model): active = fields.Boolean(string='已归档', default=True) - @api.depends('diameter', 'tool_included_angle', 'tool_groups_id') - def _compute_functional_tool_name(self): - for obj in self: - if obj.tool_groups_id: - obj.functional_tool_name = '%s-D%sR%s' % ( - obj.tool_groups_id.name, obj.diameter, - obj.tool_included_angle) + @api.depends('functional_tool_name') + def _compute_tool_number(self): + for item in self: + inventory = self.env['sf.tool.inventory'].sudo().search([('name', '=', item.functional_tool_name)]) + if inventory: + item.functional_tool_type_id = inventory.functional_cutting_tool_model_id.id + item.tool_groups_id = inventory.tool_groups_id.id + item.diameter = int(inventory.diameter) + item.tool_included_angle = inventory.angle + item.tool_loading_length = inventory.tool_length + item.clearance_length = inventory.blade_length else: - obj.functional_tool_name = None + item.functional_tool_type_id = False + item.tool_groups_id = False + item.diameter = 0 + item.tool_included_angle = 0 + item.tool_loading_length = 0 + item.clearance_length = 0 @api.model def _read_group_names(self, categories, domain, order): @@ -311,10 +323,9 @@ class CAMWorkOrderProgramKnifePlan(models.Model): 根据传入的工单信息,查询是否有需要的功能刀具,如果没有则生成CAM工单程序用刀计划 """ status = False - if cnc_processing.functional_tool_type_id and cnc_processing.cutting_tool_name: + if cnc_processing.cutting_tool_name: functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search( - [('sf_cutting_tool_type_id', '=', cnc_processing.functional_tool_type_id.id), - ('name', '=', cnc_processing.cutting_tool_name)]) + [('name', '=', cnc_processing.cutting_tool_name)]) if functional_tools: for functional_tool in functional_tools: if functional_tool.on_tool_stock_num == 0: @@ -327,7 +338,6 @@ class CAMWorkOrderProgramKnifePlan(models.Model): 'name': cnc_processing.workorder_id.production_id.name, 'cam_procedure_code': cnc_processing.program_name, 'filename': cnc_processing.cnc_id.name, - 'functional_tool_type_id': cnc_processing.functional_tool_type_id.id, 'functional_tool_name': cnc_processing.cutting_tool_name, 'cam_cutter_spacing_code': cnc_processing.cutting_tool_no, 'process_type': cnc_processing.processing_type, @@ -338,8 +348,11 @@ class CAMWorkOrderProgramKnifePlan(models.Model): 'shank_model': cnc_processing.cutting_tool_handle_type, 'estimated_processing_time': cnc_processing.estimated_processing_time, }) + logging.info('CAM工单程序用刀计划创建成功!!!') # 创建装刀请求 knife_plan.apply_for_tooling() + else: + logging.info('功能刀具【%s】满足CNC用刀需求!!!') class FunctionalToolAssembly(models.Model): diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py index df9a341e..8098c5a1 100644 --- a/sf_tool_management/models/mrp_workorder.py +++ b/sf_tool_management/models/mrp_workorder.py @@ -36,6 +36,7 @@ class CNCprocessing(models.Model): obj = super(CNCprocessing, self).create(vals) # 调用CAM工单程序用刀计划创建方法 self.env['sf.cam.work.order.program.knife.plan'].create_cam_work_plan(obj) + logging.info('成功调用CAM工单程序用刀计划创建方法!!!') return obj diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index b4bec292..9ff18ebe 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -531,7 +531,7 @@ class Sf_stock_move_line(models.Model): current_product_id = fields.Integer(compute='_compute_location_dest_id_value', store=True) there_is_no_sn = fields.Boolean('是否有序列号', default=False) - rfid = fields.Char('Rfid', readonly=True) + rfid = fields.Char('Rfid') rfid_barcode = fields.Char('Rfid', compute='_compute_rfid') @api.depends('lot_id') From 59670fb3d74817fe783d4222a88ed06fbd8761d9 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Thu, 18 Apr 2024 18:40:05 +0800 Subject: [PATCH 03/20] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=8E=B7=E5=8F=96CNC?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=EF=BC=9A=E6=B7=BB=E5=8A=A0=E7=BC=96=E7=A8=8B?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=EF=BC=88=E4=BA=BA=E5=B7=A5/=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=EF=BC=89=EF=BC=8C=E5=A6=82=E6=98=AF=E5=BF=AB=E9=80=9F?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=EF=BC=8C=E7=BC=96=E7=A8=8B=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E4=B8=BA=E4=BA=BA=E5=B7=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/controllers/controllers.py | 6 +++--- sf_manufacturing/models/mrp_production.py | 11 +++++++++++ sf_manufacturing/models/mrp_workorder.py | 10 ++++++---- sf_sale/models/sale_order.py | 6 ++++++ 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/sf_manufacturing/controllers/controllers.py b/sf_manufacturing/controllers/controllers.py index 63fd4f57..a519d9b0 100644 --- a/sf_manufacturing/controllers/controllers.py +++ b/sf_manufacturing/controllers/controllers.py @@ -114,7 +114,7 @@ class Manufacturing_Connect(http.Controller): logging.info('RfidCode:%s' % ret['RfidCode']) if 'RfidCode' in ret: workorder = request.env['mrp.workorder'].sudo().search( - [('routing_type', '=', '装夹预调'), ('rfid_code', '=', ret['RfidCode'])]) + [('routing_type', '=', '装夹预调'), ('rfid_code', '=', ret['RfidCode'])], limit=1, order='id asc') if workorder: for item in workorder: if item.material_center_point: @@ -122,8 +122,8 @@ class Manufacturing_Connect(http.Controller): res['Datas'].append({ 'XOffset': 0 if not item.material_center_point else offset[0], 'YOffset': 0 if not item.material_center_point else offset[1], - 'ZOffet': 0 if not item.material_center_point else offset[2], - 'COffset': 0 if not item.X_deviation_angle else item.X_deviation_angle, + 'ZOffset': 0 if not item.material_center_point else offset[2], + 'COffset': 0, 'Coordinate': 'G54' }) else: diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index dff2763b..e45a2960 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -57,6 +57,8 @@ class MrpProduction(models.Model): production_line_state = fields.Selection([('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], string='上/下产线', default='待上产线') + manual_quotation = fields.Boolean('人工编程', default=False) + @api.depends( 'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', 'workorder_ids.state', 'product_qty', 'qty_producing', 'schedule_state') @@ -132,6 +134,14 @@ class MrpProduction(models.Model): # cnc程序获取 def fetchCNC(self): cnc = self.env['mrp.production'].search([('id', '=', self.id)]) + quick_order = self.env['quick.easy.order'].search([('id', '=', cnc.product_id.id)]) + programme_way = False + if cnc.manual_quotation is True: + programme_way = 'manual operation' + else: + programme_way = 'auto' + if quick_order: + programme_way = 'manual operation' try: res = {'model_code': '' if not cnc.product_id.model_code else cnc.product_id.model_code, 'production_no': cnc.name, @@ -148,6 +158,7 @@ class MrpProduction(models.Model): 'order_no': cnc.origin, 'model_order_no': cnc.product_id.default_code.rsplit(' -', 1)[0], 'user': cnc.env.user.name, + 'programme_way': programme_way, 'model_file': '' if not cnc.product_id.model_file else base64.b64encode( cnc.product_id.model_file).decode('utf-8') } diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 134922d1..c9d72b79 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -46,6 +46,8 @@ class ResMrpWorkOrder(models.Model): ], string="工序类型") results = fields.Char('结果') + manual_quotation = fields.Boolean('人工编程', default=False) + @api.onchange('users_ids') def get_user_permissions(self): uid = self.env.uid @@ -984,9 +986,9 @@ class SfWorkOrderBarcodes(models.Model): workorder = self.env['mrp.workorder'].browse(self.ids) # workorder = self.env['mrp.workorder'].search( # [('routing_type', '=', '装夹预调'), ('production_id', '=', self.production_id.id)]) - # workorder_old = self.env['mrp.workorder'].search([('rfid_code', '=', barcode)]) - # if workorder_old: - # raise UserError('该托盘已绑定工件,请先解除绑定!!!') + workorder_old = self.env['mrp.workorder'].search([('rfid_code', '=', barcode)]) + if workorder_old: + raise UserError('该托盘已绑定工件,请先解除绑定!!!') if workorder: if workorder.routing_type == '装夹预调': if workorder.state in ['done']: @@ -1046,7 +1048,7 @@ class SfWorkOrderBarcodes(models.Model): for item in workorder_rfid: if item.state == "progress": item.write({'rfid_code': barcode}) - # raise UserError('该托盘信息不存在!!!') + raise UserError('该托盘信息不存在!!!') # stock_move_line = self.env['stock.move.line'].search([('lot_name', '=', barcode)]) # if stock_move_line.product_id.categ_type == '夹具': # workorder.write({ diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 05523194..379ff199 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -142,6 +142,12 @@ class ResaleOrderLine(models.Model): check_status = fields.Selection(related='order_id.check_status') +class ProductTemplate(models.Model): + _inherit = 'product.template' + + manual_quotation = fields.Boolean('人工编程', default=False) + + class RePurchaseOrder(models.Model): _inherit = 'purchase.order' From 053fa3feb33800e09a62a424f728f7bfaa535d59 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Thu, 18 Apr 2024 19:09:48 +0800 Subject: [PATCH 04/20] =?UTF-8?q?=E4=BC=98=E5=8C=96ftp=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_workorder.py | 6 +++--- sf_mrs_connect/models/ftp_operate.py | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index c9d72b79..e9648062 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -815,7 +815,7 @@ class ResMrpWorkOrder(models.Model): production_no_ftp = reportpath.split('/') production_no = workorder.production_id.name.replace('/', '_') # ftp地址 - remotepath = os.path.join('/', production_no_ftp[1], 'detection') + remotepath = os.path.join('/home/ftp/ftp_root/NC', production_no_ftp[1], 'detection') logging.info('ftp地址:%s' % remotepath) if reportpath.find(production_no) != -1: # 服务器内临时地址 @@ -894,7 +894,7 @@ class CNCprocessing(models.Model): 'cutting_tool_handle_type': obj['cutting_tool_handle_type'], 'estimated_processing_time': obj['estimated_processing_time'], 'remark': obj['remark'], - 'program_path': program_path.replace('/tmp', '') + 'program_path': program_path.replace('/tmp', '/home/ftp/ftp_root/NC') }) cnc_processing.get_cnc_processing_file(program_path_tmp, cnc_processing, program_path) # cnc_workorder.state = 'done' @@ -933,7 +933,7 @@ class CNCprocessing(models.Model): # 将FTP的nc文件下载到临时目录 def download_file_tmp(self, production_no, processing_panel): - remotepath = os.path.join('/', production_no, 'return', processing_panel) + remotepath = os.path.join('/home/ftp/ftp_root/NC', production_no, 'return', processing_panel) serverdir = os.path.join('/tmp', production_no, 'return', processing_panel) 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'], diff --git a/sf_mrs_connect/models/ftp_operate.py b/sf_mrs_connect/models/ftp_operate.py index 724f56b4..7dfeabcd 100644 --- a/sf_mrs_connect/models/ftp_operate.py +++ b/sf_mrs_connect/models/ftp_operate.py @@ -37,8 +37,22 @@ class FtpController(): os.makedirs(serverdir) try: logging.info("进入FTP目录 ") - self.ftp.cwd(target_dir) # 切换工作路径 - logging.info('FTP目录:%s' % target_dir) + logging.info('目录:%s' % target_dir) + target_dir1 = target_dir.split('/') + logging.info('目录1:%s' % target_dir1[1]) + self.ftp.cwd(target_dir1[1]) + logging.info('目录2:%s' % target_dir1[2]) + self.ftp.cwd(target_dir1[2]) + logging.info('目录3:%s' % target_dir1[3]) + self.ftp.cwd(target_dir1[3]) + logging.info('目录4:%s' % target_dir1[4]) + self.ftp.cwd(target_dir1[4]) + logging.info('目录5:%s' % target_dir1[5]) + self.ftp.cwd(target_dir1[5]) + logging.info('目录6:%s' % target_dir1[6]) + self.ftp.cwd(target_dir1[6]) + logging.info('目录7:%s' % target_dir1[7]) + self.ftp.cwd(target_dir1[7]) remotenames = self.ftp.nlst() logging.info('FTP目录文件:%s' % remotenames) for file in remotenames: @@ -48,6 +62,9 @@ class FtpController(): return 1 except Exception: return 0 + finally: + self.ftp.quit() + logging.info("ftp已关闭") # 下载目录下的检测文件 def download_reportfile_tree(self, target_dir, serverdir, reportpath): @@ -61,6 +78,8 @@ class FtpController(): self.ftp.cwd(target_dir1[1]) # 切换工作路径 logging.info('目录2:%s' % target_dir1[2]) self.ftp.cwd(target_dir1[2]) # 切换工作路径 + logging.info('目录2:%s' % target_dir1[3]) + self.ftp.cwd(target_dir1[3]) # 切换工作路径 remotenames = self.ftp.nlst() logging.info('FTP目录检测报告文件:%s' % remotenames) for filename in remotenames: From f26b4510cf86901712fdbcdac56826bb63436ce2 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 18 Apr 2024 19:10:41 +0800 Subject: [PATCH 05/20] =?UTF-8?q?1=E3=80=81=E9=87=87=E8=B4=AD=E5=85=A5?= =?UTF-8?q?=E5=BA=93=E4=BD=9C=E4=B8=9A=E8=AF=A6=E6=83=85=E7=9A=84=E7=9B=AE?= =?UTF-8?q?=E6=A0=87=E4=BD=8D=E7=BD=AE=E5=AD=97=E6=AE=B5=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E8=B4=A7=E4=BD=8D=E7=9A=84=E5=88=9B=E5=BB=BA=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=9B2=E3=80=81=E4=BC=98=E5=8C=96=E5=85=A5=E5=BA=93?= =?UTF-8?q?=E5=88=B0=E8=B4=A7=E4=BD=8D=E6=B5=81=E7=A8=8B=EF=BC=88=E8=BF=9B?= =?UTF-8?q?=E8=A1=8C=E4=B8=AD=EF=BC=89=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product_template_management_view.xml | 1 + sf_manufacturing/models/mrp_production.py | 2 +- sf_manufacturing/models/mrp_workorder.py | 2 +- sf_manufacturing/models/product_template.py | 3 ++ sf_sale/models/sale_order.py | 6 --- sf_warehouse/models/model.py | 49 ++++++++++++++----- .../views/change_stock_move_views.xml | 2 +- sf_warehouse/views/shelf_location.xml | 4 +- 8 files changed, 45 insertions(+), 24 deletions(-) diff --git a/sf_dlm_management/views/product_template_management_view.xml b/sf_dlm_management/views/product_template_management_view.xml index 453de6a3..94fc6b45 100644 --- a/sf_dlm_management/views/product_template_management_view.xml +++ b/sf_dlm_management/views/product_template_management_view.xml @@ -10,6 +10,7 @@ + diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 24ac58b2..9deba53d 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -57,7 +57,7 @@ class MrpProduction(models.Model): production_line_state = fields.Selection([('待上产线', '待上产线'), ('已上产线', '已上产线'), ('已下产线', '已下产线')], string='上/下产线', default='待上产线') - manual_quotation = fields.Boolean('人工编程', default=False) + manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) @api.depends( 'move_raw_ids.state', 'move_raw_ids.quantity_done', 'move_finished_ids.state', diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index c9d72b79..a2da9d7c 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -46,7 +46,7 @@ class ResMrpWorkOrder(models.Model): ], string="工序类型") results = fields.Char('结果') - manual_quotation = fields.Boolean('人工编程', default=False) + manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) @api.onchange('users_ids') def get_user_permissions(self): diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 57ad0eaa..52f1fc9d 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -521,6 +521,9 @@ class ResProductMo(models.Model): string='注册状态', default='未注册') industry_code = fields.Char('行业编码', readonly=True) + # bfm下单 + manual_quotation = fields.Boolean('人工编程', default=False, readonly=True) + @api.constrains('tool_length') def _check_tool_length_size(self): if self.tool_length > 1000000: diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 379ff199..05523194 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -142,12 +142,6 @@ class ResaleOrderLine(models.Model): check_status = fields.Selection(related='order_id.check_status') -class ProductTemplate(models.Model): - _inherit = 'product.template' - - manual_quotation = fields.Boolean('人工编程', default=False) - - class RePurchaseOrder(models.Model): _inherit = 'purchase.order' diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 9ff18ebe..718a5877 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -191,6 +191,7 @@ class SfLocation(models.Model): # return res # 生成货位 + def create_location(self): """ 当仓库类型为货架时,自动生成其下面的货位,数量为货架层数*层数容量 @@ -429,7 +430,6 @@ class ShelfLocation(models.Model): } return action - # # 仓库类别(selection:库区、库位、货位) # location_type = fields.Selection([ # ('货架', '货架'), @@ -516,6 +516,19 @@ class ShelfLocation(models.Model): else: raise UserError("该库位无产品") + @api.model_create_multi + def create(self, vals_list): + # 编码重复校验 + barcode_list = [] + for val in vals_list: + location = self.search([('barcode', '=', val['barcode'])]) + if location: + barcode_list.append(val['name']) + if barcode_list: + raise UserError("货位编码【%s】存在重复" % barcode_list) + records = super(ShelfLocation, self).create(vals_list) + return records + class Sf_stock_move_line(models.Model): _name = 'stock.move.line' @@ -812,35 +825,42 @@ class Sf_stock_move_line(models.Model): destination_location_id = fields.Many2one( 'sf.shelf.location', string='目标货位') - @api.onchange('destination_location_id') - def _compute_destination_location_id(self): + def compute_destination_location_id(self): for record in self: + obj = self.env['sf.shelf.location'].search([('name', '=', + self.destination_location_id.name)]) + # if obj.product_id and obj.product_id != record.product_id: + # # 判断货位产品和将入到该货位的产品是否是同一种 + # raise ValidationError( + # '【%s】产品和【%s】货位的【%s】产品不同,请重新选择【%s】产品的货位!!!' % + # (record.product_id, obj.name, obj.product_id, record.product_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: - 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_id = record.product_id.id # obj.location_status = '占用' obj.product_num += record.reserved_uom_qty + @api.onchange('destination_location_id') + def _check_destination_location_id(self): + for item in self: + if item: + line_destination_location_ids = [] + for obj in item.picking_id.move_line_ids: + if obj.destination_location_id: + line_destination_location_ids.append(obj.destination_location_id.barcode) + if item.destination_location_id.barcode in line_destination_location_ids: + raise ValidationError('【%s】货位已经被占用,请重新选择!!!' % item.destination_location_id.barcode) + class SfStockPicking(models.Model): _inherit = 'stock.picking' @@ -863,12 +883,15 @@ class SfStockPicking(models.Model): res = super(SfStockPicking, self).button_validate() for line in self.move_line_ids: if line: + # 调用入库方法进行入库 + line.compute_destination_location_id() if line.current_location_id: 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 + # 对入库作业的刀柄和托盘进行Rfid绑定校验 for move in self.move_ids: if move and move.product_id.cutting_tool_material_id.name == '刀柄' or '托盘' in ( move.product_id.fixture_material_id.name or ''): diff --git a/sf_warehouse/views/change_stock_move_views.xml b/sf_warehouse/views/change_stock_move_views.xml index 7af154b7..519eca85 100644 --- a/sf_warehouse/views/change_stock_move_views.xml +++ b/sf_warehouse/views/change_stock_move_views.xml @@ -19,7 +19,7 @@ + '=', there_is_no_sn)]" options="{'no_create': True,'no_create_edit':True}"/> diff --git a/sf_warehouse/views/shelf_location.xml b/sf_warehouse/views/shelf_location.xml index d736f89c..ff8f54b2 100644 --- a/sf_warehouse/views/shelf_location.xml +++ b/sf_warehouse/views/shelf_location.xml @@ -126,7 +126,7 @@ Shelf Location form sf.shelf.location -
+
@@ -175,7 +175,7 @@ shelf.location.kanban sf.shelf.location - +
Date: Fri, 19 Apr 2024 08:33:04 +0800 Subject: [PATCH 07/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E6=9D=A1=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index e45a2960..d9839ae4 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -156,7 +156,7 @@ class MrpProduction(models.Model): 'embryo_height': cnc.product_id.bom_ids.bom_line_ids.product_id.height, 'embryo_width': cnc.product_id.bom_ids.bom_line_ids.product_id.width, 'order_no': cnc.origin, - 'model_order_no': cnc.product_id.default_code.rsplit(' -', 1)[0], + 'model_order_no': cnc.product_id.default_code, 'user': cnc.env.user.name, 'programme_way': programme_way, 'model_file': '' if not cnc.product_id.model_file else base64.b64encode( From 5f2600c96f4f074864acbbb310fbdda2865fb837 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Fri, 19 Apr 2024 08:34:41 +0800 Subject: [PATCH 08/20] =?UTF-8?q?=E9=87=8A=E6=94=BE=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_sale/models/quick_easy_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py index ed52d9de..1ece6b86 100644 --- a/sf_sale/models/quick_easy_order.py +++ b/sf_sale/models/quick_easy_order.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -# from OCC.Extend.DataExchange import read_step_file -# from OCC.Extend.DataExchange import write_stl_file +from OCC.Extend.DataExchange import read_step_file +from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError From b43c3496a1d70e2b19e0f8258871c6facd6d295f Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Fri, 19 Apr 2024 10:49:48 +0800 Subject: [PATCH 09/20] =?UTF-8?q?1=E3=80=81=E8=B4=A7=E4=BD=8D=E7=9C=8B?= =?UTF-8?q?=E6=9D=BF=E6=A8=A1=E5=9E=8B=E6=B7=BB=E5=8A=A0=E8=B4=A7=E4=BD=8D?= =?UTF-8?q?=E5=8F=98=E6=9B=B4=E5=BC=B9=E7=AA=97=E6=A8=A1=E5=9D=97=E5=8F=8A?= =?UTF-8?q?=E5=85=B6=E5=8A=9F=E8=83=BD=E6=8C=89=E9=92=AE=EF=BC=8C=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E4=BA=A7=E5=93=81=E5=9C=A8=E5=90=8C=E5=BA=93=E5=8C=BA?= =?UTF-8?q?=E7=9A=84=E5=86=85=E9=83=A8=E8=B4=A7=E4=BD=8D=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_warehouse/__init__.py | 1 + sf_warehouse/__manifest__.py | 1 + sf_warehouse/models/model.py | 5 -- sf_warehouse/security/ir.model.access.csv | 3 ++ sf_warehouse/views/shelf_location.xml | 22 +++++--- sf_warehouse/wizard/__init__.py | 1 + sf_warehouse/wizard/wizard.py | 64 +++++++++++++++++++++++ sf_warehouse/wizard/wizard_view.xml | 49 +++++++++++++++++ 8 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 sf_warehouse/wizard/__init__.py create mode 100644 sf_warehouse/wizard/wizard.py create mode 100644 sf_warehouse/wizard/wizard_view.xml diff --git a/sf_warehouse/__init__.py b/sf_warehouse/__init__.py index c081ee06..c9ba0265 100644 --- a/sf_warehouse/__init__.py +++ b/sf_warehouse/__init__.py @@ -1,2 +1,3 @@ # -*-coding:utf-8-*- from . import models +from . import wizard diff --git a/sf_warehouse/__manifest__.py b/sf_warehouse/__manifest__.py index 04051b06..b409c7ce 100644 --- a/sf_warehouse/__manifest__.py +++ b/sf_warehouse/__manifest__.py @@ -15,6 +15,7 @@ 'data/ir_cron_data.xml', 'security/sf_stock_security.xml', 'security/ir.model.access.csv', + 'wizard/wizard_view.xml', 'views/view.xml', 'views/shelf_location.xml', 'views/change_stock_move_views.xml', diff --git a/sf_warehouse/models/model.py b/sf_warehouse/models/model.py index 98a4b513..50469284 100644 --- a/sf_warehouse/models/model.py +++ b/sf_warehouse/models/model.py @@ -829,11 +829,6 @@ class Sf_stock_move_line(models.Model): for record in self: obj = self.env['sf.shelf.location'].search([('name', '=', self.destination_location_id.name)]) - # if obj.product_id and obj.product_id != record.product_id: - # # 判断货位产品和将入到该货位的产品是否是同一种 - # raise ValidationError( - # '【%s】产品和【%s】货位的【%s】产品不同,请重新选择【%s】产品的货位!!!' % - # (record.product_id, obj.name, obj.product_id, record.product_id)) if record.lot_id: shelf_location_obj = self.env['sf.shelf.location'].search( [('product_sn_id', '=', record.lot_id.id)]) diff --git a/sf_warehouse/security/ir.model.access.csv b/sf_warehouse/security/ir.model.access.csv index db246adc..a5b3b2fa 100644 --- a/sf_warehouse/security/ir.model.access.csv +++ b/sf_warehouse/security/ir.model.access.csv @@ -132,6 +132,9 @@ access_sf_cutting_tool_material_group_sf_stock_manager,sf_cutting_tool_material_ access_sf_cutting_tool_standard_library_group_sf_stock_manager,sf_cutting_tool_standard_library_group_sf_stock_manager,sf_base.model_sf_cutting_tool_standard_library,sf_warehouse.group_sf_stock_manager,1,0,1,0 access_sf_tool_materials_basic_parameters_group_sf_stock_manager,sf_tool_materials_basic_parameters_group_sf_stock_manager,sf_base.model_sf_tool_materials_basic_parameters,sf_warehouse.group_sf_stock_manager,1,0,1,0 +access_sf_shelf_location_wizard_group_plan_dispatch,sf_shelf_location_wizard_group_plan_dispatch,model_sf_shelf_location_wizard,sf_base.group_plan_dispatch,1,0,0,0 +access_sf_shelf_location_wizard_group_sf_stock_user_group_sf_stock_user,sf_shelf_location_wizard_group_sf_stock_user_group_sf_stock_user,model_sf_shelf_location_wizard,sf_warehouse.group_sf_stock_user,1,0,0,0 +access_sf_shelf_location_wizard_group_sf_stock_manager,sf_shelf_location_wizard_group_sf_stock_manager,model_sf_shelf_location_wizard,sf_warehouse.group_sf_stock_manager,1,1,1,0 diff --git a/sf_warehouse/views/shelf_location.xml b/sf_warehouse/views/shelf_location.xml index ff8f54b2..a0e1a5c1 100644 --- a/sf_warehouse/views/shelf_location.xml +++ b/sf_warehouse/views/shelf_location.xml @@ -128,7 +128,17 @@
- +
- - - - - + + + + + diff --git a/sf_warehouse/wizard/__init__.py b/sf_warehouse/wizard/__init__.py new file mode 100644 index 00000000..20a7f5c4 --- /dev/null +++ b/sf_warehouse/wizard/__init__.py @@ -0,0 +1 @@ +from . import wizard \ No newline at end of file diff --git a/sf_warehouse/wizard/wizard.py b/sf_warehouse/wizard/wizard.py new file mode 100644 index 00000000..7961819b --- /dev/null +++ b/sf_warehouse/wizard/wizard.py @@ -0,0 +1,64 @@ +from odoo import fields, models, api +from odoo.exceptions import UserError, ValidationError + + +class ShelfLocationWizard(models.TransientModel): + _name = 'sf.shelf.location.wizard' + _description = '货位变更' + + name = fields.Char('') + + current_location_id = fields.Many2one('stock.location', string='所属库区', readonly=True) + + current_shelf_id = fields.Many2one('sf.shelf', string='当前货架', readonly=True) + current_barcode = fields.Char('当前货位编码', readonly=True) + current_name = fields.Char('当前货位名称', readonly=True) + current_product_id = fields.Many2one('product.product', string='产品', readonly=True) + + destination_shelf_id = fields.Many2one('sf.shelf', string='目标货架', compute='_compute_destination_name') + destination_barcode_id = fields.Many2one('sf.shelf.location', string='目标货位编码', required=True, + domain="") + destination_name = fields.Char('目标货位名称', compute='_compute_destination_name') + + def return_domain(self): + val = [('location_status', '=', '空闲')] + if self.current_product_id: + val = ['|', ('location_status', '=', '空闲'), ('product_id', '=', self.current_product_id)] + if self.destination_shelf_id: + val.append(('shelf_id', '=', self.destination_shelf_id)) + return "%s" % val + + @api.depends('destination_barcode_id') + def _compute_destination_name(self): + if self.destination_barcode_id: + self.destination_name = self.destination_barcode_id.name + self.destination_shelf_id = self.destination_barcode_id.shelf_id.id + else: + self.destination_name = '' + self.destination_shelf_id = False + + # + # @api.onchange('destination_barcode_id') + # def _onchange_destination_shelf_id(self): + # if self.destination_barcode_id: + # self.destination_shelf_id = self.destination_barcode_id.shelf_id.id + + def confirm_the_change(self): + shelf_location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', self.current_barcode)]) + # 变更货位 + if self.destination_barcode_id and shelf_location: + if self.destination_barcode_id.product_id and self.destination_barcode_id.product_id == shelf_location.current_product_id and not self.destination_barcode_id.product_sn_id: + self.destination_barcode_id.product_num += shelf_location.product_num + else: + self.destination_barcode_id.product_sn_id = shelf_location.product_sn_id.id + self.destination_barcode_id.product_id = shelf_location.product_id.id + self.destination_barcode_id.product_num = shelf_location.product_num + + shelf_location.product_sn_id = False + shelf_location.product_id = False + shelf_location.product_num = 0 + else: + raise ValidationError('目标货位出错,请联系管理员!') + + # 关闭弹出窗口 + return {'type': 'ir.actions.act_window_close'} diff --git a/sf_warehouse/wizard/wizard_view.xml b/sf_warehouse/wizard/wizard_view.xml new file mode 100644 index 00000000..1bb95e15 --- /dev/null +++ b/sf_warehouse/wizard/wizard_view.xml @@ -0,0 +1,49 @@ + + + + 货位变更 + sf.shelf.location.wizard + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+ + + 货位变更 + ir.actions.act_window + sf.shelf.location.wizard + form + + new + +
\ No newline at end of file From 80f0284c3c48b4739fdd3ed5aaad7905a2451fd1 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Fri, 19 Apr 2024 13:39:17 +0800 Subject: [PATCH 10/20] =?UTF-8?q?1=E3=80=81=E4=BC=98=E5=8C=96=E8=B4=A7?= =?UTF-8?q?=E4=BD=8D=E7=9C=8B=E6=9D=BF=E7=9A=84=E6=9B=B4=E6=8D=A2=E8=B4=A7?= =?UTF-8?q?=E4=BD=8D=E5=8A=9F=E8=83=BD=E3=80=81=E6=B7=BB=E5=8A=A0=E6=8C=89?= =?UTF-8?q?=E7=BC=96=E7=A0=81=E6=90=9C=E7=B4=A2=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_tool_management/models/base.py | 55 +++++++++++++++------------ sf_warehouse/views/shelf_location.xml | 9 +++-- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py index 01c3de46..83b4b550 100644 --- a/sf_tool_management/models/base.py +++ b/sf_tool_management/models/base.py @@ -422,11 +422,12 @@ class FunctionalToolAssembly(models.Model): @api.depends('integral_freight_barcode') def _compute_integral_product_id(self): for item in self: - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.integral_freight_barcode)]) - if location: - item.integral_product_id = location.product_id.id - else: - item.integral_product_id = False + if item.integral_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.integral_freight_barcode)]) + if location: + item.integral_product_id = location.product_id.id + else: + item.integral_product_id = False # =================刀片型号============= blade_freight_barcode = fields.Char('刀片货位') @@ -441,11 +442,12 @@ class FunctionalToolAssembly(models.Model): @api.depends('blade_freight_barcode') def _compute_blade_product_id(self): for item in self: - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.blade_freight_barcode)]) - if location: - item.blade_product_id = location.product_id.id - else: - item.blade_product_id = False + if item.integral_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.blade_freight_barcode)]) + if location: + item.blade_product_id = location.product_id.id + else: + item.blade_product_id = False # ==============刀杆型号================ bar_freight_barcode = fields.Char('刀杆货位') @@ -460,11 +462,12 @@ class FunctionalToolAssembly(models.Model): @api.depends('bar_freight_barcode') def _compute_bar_product_id(self): for item in self: - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.bar_freight_barcode)]) - if location: - item.bar_product_id = location.product_id.id - else: - item.bar_product_id = False + if item.integral_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.bar_freight_barcode)]) + if location: + item.bar_product_id = location.product_id.id + else: + item.bar_product_id = False # =============刀盘型号================ pad_freight_barcode = fields.Char('刀盘货位') @@ -479,11 +482,12 @@ class FunctionalToolAssembly(models.Model): @api.depends('pad_freight_barcode') def _compute_pad_product_id(self): for item in self: - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.pad_freight_barcode)]) - if location: - item.pad_product_id = location.product_id.id - else: - item.pad_product_id = False + if item.integral_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.pad_freight_barcode)]) + if location: + item.pad_product_id = location.product_id.id + else: + item.pad_product_id = False # ==============刀柄型号============== handle_freight_rfid = fields.Char('刀柄Rfid', compute='_compute_handle_product_id', store=True) @@ -519,11 +523,12 @@ class FunctionalToolAssembly(models.Model): @api.depends('chuck_freight_barcode') def _compute_chuck_product_id(self): for item in self: - location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.chuck_freight_barcode)]) - if location: - item.chuck_product_id = location.product_id.id - else: - item.chuck_product_id = False + if item.integral_freight_barcode: + location = self.env['sf.shelf.location'].sudo().search([('barcode', '=', item.chuck_freight_barcode)]) + if location: + item.chuck_product_id = location.product_id.id + else: + item.chuck_product_id = False # ==================待删除字段================== blade_name = fields.Char('') diff --git a/sf_warehouse/views/shelf_location.xml b/sf_warehouse/views/shelf_location.xml index a0e1a5c1..90783fca 100644 --- a/sf_warehouse/views/shelf_location.xml +++ b/sf_warehouse/views/shelf_location.xml @@ -129,16 +129,16 @@
@@ -567,12 +569,13 @@ decoration-danger="status == '待配送'"/> - - - - - - + + + + + + + @@ -585,10 +588,10 @@ - + - + diff --git a/sf_manufacturing/wizard/workpiece_delivery_views.xml b/sf_manufacturing/wizard/workpiece_delivery_views.xml index 49e80d52..34625878 100644 --- a/sf_manufacturing/wizard/workpiece_delivery_views.xml +++ b/sf_manufacturing/wizard/workpiece_delivery_views.xml @@ -5,14 +5,18 @@ sf.workpiece.delivery.wizard - - - + + + + +
- 是否确定配送? + + 确认上述信息正确无误.
-
diff --git a/sf_manufacturing/wizard/workpiece_delivery_wizard.py b/sf_manufacturing/wizard/workpiece_delivery_wizard.py index 7101410d..1de3e84c 100644 --- a/sf_manufacturing/wizard/workpiece_delivery_wizard.py +++ b/sf_manufacturing/wizard/workpiece_delivery_wizard.py @@ -11,10 +11,11 @@ class WorkpieceDeliveryWizard(models.TransientModel): delivery_id = fields.Many2one('sf.workpiece.delivery', string='配送') workorder_id = fields.Many2one('mrp.workorder', string='工单') + route_id = fields.Many2one('sf.agv.task.route', '任务路线') + is_ok = fields.Boolean('确认上述信息正确无误.') def confirm(self): if self.workorder_id: self.workorder_id.workpiece_delivery_ids._delivery_avg() else: self.delivery_id._delivery_avg() - diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index 3f109cbe..ef2d93d8 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -15,6 +15,8 @@ class ResConfigSettings(models.TransientModel): sf_url = fields.Char(string='访问地址', default='https://sf.cs.jikimo.com') agv_rcs_url = fields.Char(string='avg_rcs访问地址', default='http://172.16.10.114:8182/rcms/services/rest/hikRpcService/genAgvSchedulingTask') + center_control_url = fields.Char(string='中控访问地址', + default='http://172.16.21.50:8001') wbcode = fields.Char('地码') agv_code = fields.Char(string='agv编号') task_type_no = fields.Char('任务单类型编号') @@ -99,7 +101,7 @@ class ResConfigSettings(models.TransientModel): agv_rcs_url = config.get_param('agv_rcs_url', default='') wbcode = config.get_param('wbcode', default='') agv_code = config.get_param('agv_code', default='') - task_type_no = config.get_param('task_type_no', default='') + center_control_url = config.get_param('center_control_url', default='') ftp_host = config.get_param('ftp_host', default='') ftp_port = config.get_param('ftp_port', default='') ftp_user = config.get_param('ftp_user', default='') @@ -112,7 +114,7 @@ class ResConfigSettings(models.TransientModel): agv_rcs_url=agv_rcs_url, wbcode=wbcode, agv_code=agv_code, - task_type_no=task_type_no, + center_control_url=center_control_url, ftp_host=ftp_host, ftp_port=ftp_port, ftp_user=ftp_user, @@ -129,31 +131,8 @@ class ResConfigSettings(models.TransientModel): ir_config.set_param("agv_rcs_url", self.agv_rcs_url or "") ir_config.set_param("wbcode", self.wbcode or "") ir_config.set_param("agv_code", self.agv_code or "") - ir_config.set_param("task_type_no", self.task_type_no or "") + ir_config.set_param("center_control_url", self.center_control_url or "") ir_config.set_param("ftp_host", self.ftp_host or "") ir_config.set_param("ftp_port", self.ftp_port or "") ir_config.set_param("ftp_user", self.ftp_user or "") ir_config.set_param("ftp_password", self.ftp_password or "") - - -class ResAgvSite(models.Model): - _name = 'res.agv.site' - _description = 'agv站点' - - number = fields.Integer('编号') - type = fields.Selection([('00', '位置编号'), ('01', '库区编号'), ('02', '货架编号')], '类型') - content = fields.Char('内容') - site_prop = fields.Selection([('上产线', '上产线'), ('下产线', '下产线')], '属性') - state_status = fields.Selection([('占用', '占用'), ('空闲', '空闲')], '状态') - # remark = fields.Char - active = fields.Boolean('有效', default=True) - - # @api.model - # def create(self, vals): - # if vals.get('number', 'new') == 'new': - # vals['number'] = self.env['ir.sequence'].next_by_code('res.agv.site') or '/' - # return super(ResAgvSite, self).create(vals) - - def unlink(self): - for item in self: - item.active == True diff --git a/sf_mrs_connect/security/ir.model.access.csv b/sf_mrs_connect/security/ir.model.access.csv index f512ec84..0ed43a62 100644 --- a/sf_mrs_connect/security/ir.model.access.csv +++ b/sf_mrs_connect/security/ir.model.access.csv @@ -1,6 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_sf_static_resource_datasync,sf_static_resource_datasync,model_sf_static_resource_datasync,base.group_user,1,1,1,1 -access_res_agv_site,access_res_agv_site,model_res_agv_site,base.group_system,1,1,1,1 diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml index 0a60df0a..0d1ccc3e 100644 --- a/sf_mrs_connect/views/res_config_settings_views.xml +++ b/sf_mrs_connect/views/res_config_settings_views.xml @@ -1,28 +1,6 @@ - - agv站点集合 - res.agv.site - - - - - - - - - - - - 站点集合 - res.agv.site - tree - - - - res.config.settings.view.form.inherit.sf_sync res.config.settings @@ -106,10 +84,6 @@