diff --git a/sf_base/__manifest__.py b/sf_base/__manifest__.py index 11931f4c..2daf3ec0 100644 --- a/sf_base/__manifest__.py +++ b/sf_base/__manifest__.py @@ -23,6 +23,7 @@ ], 'qweb': [ ], + 'license': 'LGPL-3', 'installable': True, 'application': False, 'auto_install': False, diff --git a/sf_base/models/common.py b/sf_base/models/common.py index 987444e5..419caf17 100644 --- a/sf_base/models/common.py +++ b/sf_base/models/common.py @@ -75,6 +75,18 @@ class MrsMaterialModel(models.Model): active = fields.Boolean('有效', default=True) +class MrsProductionProcessCategory(models.Model): + _name = 'sf.production.process.category' + _description = '表面工艺类别' + order = 'id desc' + + name = fields.Char('名称') + code = fields.Char("编码") + sequence = fields.Integer('排序') + production_process_ids = fields.One2many('sf.production.process', 'category_id', string="表面工艺") + active = fields.Boolean('有效', default=True) + + # 工艺 编码,名称,备注 class MrsProductionProcess(models.Model): _name = 'sf.production.process' @@ -87,6 +99,8 @@ class MrsProductionProcess(models.Model): partner_process_ids = fields.Many2many('res.partner', 'process_ids', '加工工厂') active = fields.Boolean('有效', default=True) parameter_ids = fields.One2many('sf.production.process.parameter', 'process_id', string='可选参数') + category_id = fields.Many2one('sf.production.process.category') + # workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_process', required=True) class MrsProcessingTechnology(models.Model): @@ -134,12 +148,30 @@ class SupplierSort(models.Model): ('supplier_sort_uniq', 'unique (partner_id,materials_model_id)', '排序不能重复!') ] + class MrsProductionProcessParameter(models.Model): _name = 'sf.production.process.parameter' _description = '可选参数' - name = fields.Char('参数名') - active = fields.Boolean('有效', default=True) - price = fields.Float('单价') + # _display_name = 'name' + + code = fields.Char("编码") + name = fields.Char('名称') + gain_way = fields.Selection([("自加工", "自加工"), ("外协", "外协")], default="", string="获取方式") + is_check = fields.Boolean(default=False) + # price = fields.Float('单价') process_id = fields.Many2one('sf.production.process', string='表面工艺') materials_model_ids = fields.Many2many('sf.materials.model', 'applicable_material', string='适用材料') - code = fields.Char("编码") \ No newline at end of file + active = fields.Boolean('有效', default=True) + + def name_get(self): + result = [] + for parameter in self: + if parameter.process_id: + name = parameter.process_id.name + '-' + parameter.name + result.append((parameter.id, name)) + return result + + # 获取表面工艺的获取方式 + def get_gain_way(self, item): + process_parameter = self.env['sf.production.process.parameter'].search([('id', '=', item.id)]) + return process_parameter diff --git a/sf_base/security/ir.model.access.csv b/sf_base/security/ir.model.access.csv index c9e93e5b..7c13d58d 100644 --- a/sf_base/security/ir.model.access.csv +++ b/sf_base/security/ir.model.access.csv @@ -13,8 +13,8 @@ access_sf_materials_model,sf_materials_model,model_sf_materials_model,base.group access_sf_processing_technology,sf_processing_technology,model_sf_processing_technology,base.group_user,1,1,1,1 access_sf_tray,sf_tray,model_sf_tray,base.group_user,1,1,1,1 access_sf_supplier_sort,sf_supplier_sort,model_sf_supplier_sort,base.group_user,1,1,1,1 - access_sf_production_process_parameter,sf_production_process_parameter,model_sf_production_process_parameter,base.group_user,1,1,1,1 +access_sf_production_process_category,sf_production_process_category,model_sf_production_process_category,base.group_user,1,1,1,1 diff --git a/sf_base/views/common_view.xml b/sf_base/views/common_view.xml index be899852..82e1e918 100644 --- a/sf_base/views/common_view.xml +++ b/sf_base/views/common_view.xml @@ -39,6 +39,61 @@ + + + + sf.production.process.category + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + sf.production.process.category + + + + + + + + + + + search.sf.production.process.category + sf.production.process.category + + + + + + + + sf.production.process @@ -55,55 +110,65 @@ sf.production.process
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - + + + + + + + + + + + + - - - - - - - - - - - -
-
-
- - - + + + +
+ + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+ + +
+
+
+ + + + + + + +
@@ -229,26 +294,6 @@ - - - - - - - - - - - - - - - - - - - - 材料 ir.actions.act_window @@ -288,13 +333,24 @@ sf.processing.technology tree,form -

加工工艺!

+ + 表面工艺类别 + ir.actions.act_window + sf.production.process.category + tree,form + +

+ 表面工艺类别! +

+
+
+ #------------------托盘------------------ 托盘 diff --git a/sf_base/views/menu_view.xml b/sf_base/views/menu_view.xml index 3b329ccb..620712ac 100644 --- a/sf_base/views/menu_view.xml +++ b/sf_base/views/menu_view.xml @@ -63,6 +63,13 @@ action="sf_production_process" /> + ', 0), - ('location_id', 'in', wh_location_ids), - ('move_orig_ids', '=', False), - ('picking_id', 'not in', self.ids), - ('product_id', 'in', lines.product_id.ids)], limit=1): + ('state', 'in', ['confirmed', 'partially_available', 'waiting', 'assigned']), + ('product_qty', '>', 0), + ('location_id', 'in', wh_location_ids), + ('move_orig_ids', '=', False), + ('picking_id', 'not in', self.ids), + ('product_id', 'in', lines.product_id.ids)], limit=1): action = self.action_view_reception_report() action['context'] = {'default_picking_ids': self.ids} return action diff --git a/sf_dlm/__manifest__.py b/sf_dlm/__manifest__.py index af65279b..ba5e706b 100644 --- a/sf_dlm/__manifest__.py +++ b/sf_dlm/__manifest__.py @@ -10,8 +10,10 @@ """, 'category': 'sf', 'website': 'https://www.sf.jikimo.com', - 'depends': ['mrp', 'base', 'sf_manufacturing','web_widget_model_viewer','mrp_subcontracting'], + 'depends': ['mrp', 'base', 'sf_manufacturing', 'web_widget_model_viewer', 'mrp_subcontracting', 'purchase_stock', + 'uom'], 'data': [ + 'data/product_data.xml', 'data/uom_data.xml', 'views/product_template_view.xml', 'views/product_workorder.xml' @@ -20,6 +22,7 @@ ], 'qweb': [ ], + 'license': 'LGPL-3', 'installable': True, 'application': False, 'auto_install': False, diff --git a/sf_dlm/data/product_data.xml b/sf_dlm/data/product_data.xml index f4b9b717..54a468ad 100644 --- a/sf_dlm/data/product_data.xml +++ b/sf_dlm/data/product_data.xml @@ -2,8 +2,8 @@ - 胚料 - 胚料 + 坯料 + 坯料 成品 @@ -15,6 +15,11 @@ 原材料 + + 表面工艺 + 表面工艺 + + CNC加工产品模板 @@ -29,10 +34,10 @@ true serial - + false - 胚料自加工模板 + 坯料自加工模板 true serial + false - 胚料外协加工模板 + 坯料外协加工模板 serial + false - 胚料采购模板 + 坯料采购模板 serial + false \ No newline at end of file diff --git a/sf_dlm/models/product_template.py b/sf_dlm/models/product_template.py index 43f24ba9..a673c912 100644 --- a/sf_dlm/models/product_template.py +++ b/sf_dlm/models/product_template.py @@ -15,7 +15,8 @@ class ResProductTemplate(models.Model): # 模型的长,宽,高,体积,精度,材料 model_name = fields.Char('模型名称') categ_type = fields.Selection( - [("成品", "成品"), ("胚料", "胚料"), ("原材料", "原材料")], string='产品的类别', related='categ_id.type', + [("成品", "成品"), ("坯料", "坯料"), ("原材料", "原材料"), ("表面工艺", "表面工艺")], + string='产品的类别', related='categ_id.type', store=True) model_long = fields.Float('模型长[mm]', digits=(16, 3)) model_width = fields.Float('模型宽[mm]', digits=(16, 3)) @@ -28,10 +29,14 @@ class ResProductTemplate(models.Model): ('0.02', '±0.02mm'), ('0.01', '±0.01mm')], string='加工精度') product_model_type_id = fields.Many2one('sf.model.type', string='产品模型类型') - embryo_model_type_id = fields.Many2one('sf.model.type', string='胚料模型类型') + embryo_model_type_id = fields.Many2one('sf.model.type', string='坯料模型类型') model_processing_panel = fields.Char('模型加工面板') - model_surface_process_id = fields.Many2one('sf.production.process', string='表面工艺') - model_process_parameters_id = fields.Many2one('sf.processing.technology', string='工艺参数') + # model_surface_process_category_id = fields.Many2one('sf.production.process.category', string='表面工艺类别') + # model_surface_process_ids = fields.Many2many('sf.production.process', 'rel_product_process', string='表面工艺') + server_product_process_parameters_id = fields.Many2one('sf.production.process.parameter', + string='表面工艺参数(服务产品)') + model_process_parameters_ids = fields.Many2many('sf.production.process.parameter', 'process_parameter_rel', + string='表面工艺参数') # model_price = fields.Float('模型单价', digits=(16, 3)) model_remark = fields.Char('模型备注说明') length = fields.Float('长[mm]', digits=(16, 3)) @@ -53,7 +58,7 @@ class ResProductTemplate(models.Model): # model_file = fields.Binary('模型文件') - # 胚料的库存路线设置 + # 坯料的库存路线设置 # def _get_routes(self, route_type): # route_manufacture = self.env.ref('mrp.route_warehouse0_manufacture', raise_if_not_found=False).sudo() # route_mto = self.env.ref('stock.route_warehouse0_mto', raise_if_not_found=False).sudo() @@ -98,6 +103,7 @@ class ResProductTemplate(models.Model): 'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']), 'model_name': attachment.name, 'upload_model_file': [(6, 0, [attachment.id])], + # 'tag_ids': [(6, 0, [t.id for t in account_template.tag_ids])], # 'single_manufacturing': True, # 'tracking': 'serial', 'list_price': item['price'], @@ -106,10 +112,8 @@ class ResProductTemplate(models.Model): [('materials_no', '=', item['texture_code'])]).id, 'materials_type_id': self.env['sf.materials.model'].search( [('materials_no', '=', item['texture_type_code'])]).id, - 'model_surface_process_id': self.env['sf.production.process'].search( - [('process_encode', '=', item['surface_process_code'])]).id, - # 'model_process_parameters_id': self.env['sf.processing.technology'].search( - # [('process_encode', '=', item['process_parameters_code'])]).id, + # 'model_surface_process_ids': self.get_production_process_id(item['surface_process_code']), + 'model_process_parameters_ids': self.get_process_parameters_id(item['process_parameters_code']), 'model_remark': item['remark'], 'default_code': '%s-%s' % (order_number, i), # 'barcode': item['barcode'], @@ -120,6 +124,20 @@ class ResProductTemplate(models.Model): # product_id.product_tmpl_id.active = False return copy_product_id + # def get_production_process_id(self, surface_process_code): + # production_process_ids = [] + # for item in surface_process_code: + # production_process = self.env['sf.production.process'].search([('process_encode', '=', item)]) + # production_process_ids.append(production_process.id) + # return [(6, 0, production_process_ids)] + + def get_process_parameters_id(self, process_parameters_code): + process_parameters_ids = [] + for item in process_parameters_code: + process_parameters = self.env['sf.production.process.parameter'].search([('code', '=', item)]) + process_parameters_ids.append(process_parameters.id) + return [(6, 0, process_parameters_ids)] + def attachment_create(self, name, data): attachment = self.env['ir.attachment'].create({ 'datas': base64.b64decode(data), @@ -130,7 +148,7 @@ class ResProductTemplate(models.Model): }) return attachment - # 创建胚料 + # 创建坯料 def no_bom_product_create(self, product_id, item, order_id, route_type, i): no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy() no_bom_copy_product_id.product_tmpl_id.active = True @@ -166,7 +184,7 @@ class ResProductTemplate(models.Model): # [('process_encode', '=', item['process_parameters_code'])]).id, 'active': True } - # 外协和采购生成的胚料需要根据材料型号绑定供应商 + # 外协和采购生成的坯料需要根据材料型号绑定供应商 if route_type == 'subcontract' or route_type == 'purchase': no_bom_copy_product_id.purchase_ok = True no_bom_copy_product_id.seller_ids = [ @@ -179,32 +197,33 @@ class ResProductTemplate(models.Model): # product_id.product_tmpl_id.active = False return no_bom_copy_product_id - # @api.model_create_multi - # def create(self, vals_list): - # for vals in vals_list: - # if vals['upload_model_file']: - # for item in vals['upload_model_file']: - # attachment = self.env['ir.attachment'].sudo().search([('id', '=', int(item[2][0]))]) - # base64_data = base64.b64encode(attachment.datas) - # base64_datas = base64_data.decode('utf-8') - # model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest() - # report_path = attachment._full_path(attachment.store_fname) - # vals['model_file'] = self.transition_glb_file(report_path, model_code) - # self._sanitize_vals(vals) - # templates = super(ResProductTemplate, self).create(vals_list) - # if "create_product_product" not in self._context: - # templates._create_variant_ids() - # - # # This is needed to set given values to first variant after creation - # for template, vals in zip(templates, vals_list): - # related_vals = {} - # for field_name in self._get_related_fields_variant_template(): - # if vals.get(field_name): - # related_vals[field_name] = vals[field_name] - # if related_vals: - # template.write(related_vals) - # - # return templates + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if vals.get('upload_model_file'): + if vals.get('is_bfm') is False and vals.get('categ_type') == '成品': + for item in vals['upload_model_file']: + attachment = self.env['ir.attachment'].sudo().search([('id', '=', int(item[2][0]))]) + base64_data = base64.b64encode(attachment.datas) + base64_datas = base64_data.decode('utf-8') + model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest() + report_path = attachment._full_path(attachment.store_fname) + vals['model_file'] = self.transition_glb_file(report_path, model_code) + self._sanitize_vals(vals) + templates = super(ResProductTemplate, self).create(vals_list) + if "create_product_product" not in self._context: + templates._create_variant_ids() + + # This is needed to set given values to first variant after creation + for template, vals in zip(templates, vals_list): + related_vals = {} + for field_name in self._get_related_fields_variant_template(): + if vals.get(field_name): + related_vals[field_name] = vals[field_name] + if related_vals: + template.write(related_vals) + + return templates @api.onchange('upload_model_file') def onchange_model_file(self): @@ -224,7 +243,7 @@ class ResProductTemplate(models.Model): item.model_file = self.transition_glb_file(report_path, model_code) # 将attach的datas内容转为glb文件 - def transition_glb_file(self,report_path, code): + def transition_glb_file(self, report_path, code): shapes = read_step_file(report_path) output_file = os.path.join('/tmp', str(code) + '.stl') write_stl_file(shapes, output_file, 'binary', 0.03, 0.5) @@ -269,11 +288,11 @@ class ResMrpBom(models.Model): bom_id.subcontractor_id = subcontract.partner_id.id return bom_id - # 胚料BOM组件:选取当前胚料原材料, - # 然后根据当前的胚料的体积得出需要的原材料重量(立方米m³) *材料密度 * 1000 = 所需原材料重量KG(公斤) - # 胚料所需原材料公式:当前的胚料的体积(立方米m³) *材料密度 * 1000 = 所需原材料重量KG(公斤) + # 坯料BOM组件:选取当前坯料原材料, + # 然后根据当前的坯料的体积得出需要的原材料重量(立方米m³) *材料密度 * 1000 = 所需原材料重量KG(公斤) + # 坯料所需原材料公式:当前的坯料的体积(立方米m³) *材料密度 * 1000 = 所需原材料重量KG(公斤) def bom_create_line(self, embryo): - # 选取当前胚料原材料 + # 选取当前坯料原材料 raw_bom_line = self.get_raw_bom(embryo) if raw_bom_line: bom_line = self.env['mrp.bom.line'].create({ @@ -298,7 +317,7 @@ class ResMrpBom(models.Model): # 匹配bom def get_bom(self, product): embryo_has = self.env['product.product'].search( - [('categ_id.type', '=', '胚料'), ('materials_type_id', '=', product.materials_type_id.id), + [('categ_id.type', '=', '坯料'), ('materials_type_id', '=', product.materials_type_id.id), ('length', '>', product.length), ('width', '>', product.width), ('height', '>', product.height), ('is_bfm', '=', False) ], @@ -324,7 +343,7 @@ class ResProductCategory(models.Model): _inherit = "product.category" type = fields.Selection( - [("成品", "成品"), ("胚料", "胚料"), ("原材料", "原材料")], + [("成品", "成品"), ("坯料", "坯料"), ("原材料", "原材料"), ("表面工艺", "表面工艺")], default="", string="类型") # @api.constrains('type') diff --git a/sf_dlm/models/product_workorder.py b/sf_dlm/models/product_workorder.py index 2f825d4e..bcdc5d86 100644 --- a/sf_dlm/models/product_workorder.py +++ b/sf_dlm/models/product_workorder.py @@ -5,8 +5,8 @@ class ResMrpWorkOrder(models.Model): _inherit = 'mrp.workorder' _order = 'sequence' - product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True, check_company=True, string="胚料长度(mm)") - product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True, check_company=True, string="胚料宽度(mm)") - product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True, check_company=True, string="胚料高度(mm)") + product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True, check_company=True, string="坯料长度(mm)") + product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True, check_company=True, string="坯料宽度(mm)") + product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True, check_company=True, string="坯料高度(mm)") product_tmpl_id_materials_id = fields.Many2one(related='production_id.product_tmpl_id.materials_id', readonly=True, store=True, check_company=True, string="材料") product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id', readonly=True, store=True, check_company=True, string="型号") diff --git a/sf_dlm/views/product_template_view.xml b/sf_dlm/views/product_template_view.xml index 7eb5f625..efcab98d 100644 --- a/sf_dlm/views/product_template_view.xml +++ b/sf_dlm/views/product_template_view.xml @@ -14,16 +14,21 @@ + widget="many2many_binary" + attrs="{'invisible': ['|', ('categ_type', '!=', '成品'),('categ_type', '=', False)]}"/> - + attrs="{'invisible': ['|',('categ_type', '!=', '坯料'),('categ_type', '=', False)]}"/> + + domain="[('materials_id', '=', materials_id)]" + attrs="{'invisible': [('categ_type', '=', '表面工艺')]}"/> + @@ -64,9 +69,9 @@ - - + + @@ -140,7 +145,7 @@ - + diff --git a/sf_machine_connect/__manifest__.py b/sf_machine_connect/__manifest__.py index 8d46d66f..f63a1fd5 100644 --- a/sf_machine_connect/__manifest__.py +++ b/sf_machine_connect/__manifest__.py @@ -37,7 +37,7 @@ 'sf_machine_connect/static/src/js/*' ], }, - + 'license': 'LGPL-3', 'installable': True, 'application': True, # 'auto_install': False, diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index 70277dca..2f181b42 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -10,8 +10,9 @@ """, 'category': 'sf', 'website': 'https://www.sf.jikimo.com', - 'depends': ['mrp', 'sf_base', 'maintenance', 'web_widget_model_viewer'], + 'depends': ['mrp', 'sf_base', 'maintenance', 'web_widget_model_viewer', 'stock'], 'data': [ + 'data/stock_data.xml', 'security/group_security.xml', 'security/ir.model.access.csv', 'report/tray_report.xml', @@ -27,6 +28,7 @@ ], 'qweb': [ ], + 'license': 'LGPL-3', 'installable': True, 'application': False, 'auto_install': False, diff --git a/sf_manufacturing/data/stock_data.xml b/sf_manufacturing/data/stock_data.xml new file mode 100644 index 00000000..a50a948d --- /dev/null +++ b/sf_manufacturing/data/stock_data.xml @@ -0,0 +1,52 @@ + + + + + + YourCompany Sequence ocin + WH/OCIN/ + 5 + + + + YourCompany Sequence ocout + WH/OCOUT/ + 5 + + + + 外协 + + internal + VL-OC + true + + + + + 外协入库 + internal + true + + + OCIN + + + + + + 外协出库 + internal + + true + + OCOUT + + + + + + + diff --git a/sf_manufacturing/models/model_type.py b/sf_manufacturing/models/model_type.py index 5428534d..14315148 100644 --- a/sf_manufacturing/models/model_type.py +++ b/sf_manufacturing/models/model_type.py @@ -6,11 +6,14 @@ class ModelType(models.Model): _description = '模型类型' name = fields.Char('名称') - embryo_tolerance = fields.Integer('胚料容余') + embryo_tolerance = fields.Integer('坯料容余') product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id', '成品工序模板') embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id', - '胚料工序模板') + '坯料工序模板') + surface_technics_routing_tmpl_ids = fields.One2many('sf.surface_technics.model.type.routing.sort', + 'surface_technics_model_type_id', + '表面工艺工序模板') class ProductModelTypeRoutingSort(models.Model): @@ -26,7 +29,7 @@ class ProductModelTypeRoutingSort(models.Model): ('前置三元定位检测', '前置三元定位检测'), ('CNC加工', 'CNC加工'), ('后置三元质量检测', '后置三元质量检测'), - ('解除装夹', '解除装夹'), ('切割', '切割') + ('解除装夹', '解除装夹'), ('切割', '切割'), ('表面工艺', '表面工艺') ], string="工序类型", related='route_workcenter_id.routing_type') workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids') product_model_type_id = fields.Many2one('sf.model.type') @@ -38,7 +41,7 @@ class ProductModelTypeRoutingSort(models.Model): class EmbryoModelTypeRoutingSort(models.Model): _name = 'sf.embryo.model.type.routing.sort' - _description = '胚料工序排序' + _description = '坯料工序排序' sequence = fields.Integer('Sequence') route_workcenter_id = fields.Many2one('mrp.routing.workcenter') @@ -49,11 +52,35 @@ class EmbryoModelTypeRoutingSort(models.Model): ('前置三元定位检测', '前置三元定位检测'), ('CNC加工', 'CNC加工'), ('后置三元质量检测', '后置三元质量检测'), - ('解除装夹', '解除装夹'), ('切割', '切割') + ('解除装夹', '解除装夹'), ('切割', '切割'), ('表面工艺', '表面工艺') ], string="工序类型", related='route_workcenter_id.routing_type') workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids') embryo_model_type_id = fields.Many2one('sf.model.type') _sql_constraints = [ - ('route_model_type_uniq', 'unique (route_workcenter_id,embryo_model_type_id)', '胚料工序不能重复!') + ('route_model_type_uniq', 'unique (route_workcenter_id,embryo_model_type_id)', '坯料工序不能重复!') + ] + + +class SurfaceTechnicsModelTypeRoutingSort(models.Model): + _name = 'sf.surface_technics.model.type.routing.sort' + _description = '表面工艺工序排序' + + sequence = fields.Integer('Sequence') + route_workcenter_id = fields.Many2one('mrp.routing.workcenter') + is_repeat = fields.Boolean('重复', related='route_workcenter_id.is_repeat') + routing_type = fields.Selection([ + ('获取CNC加工程序', '获取CNC加工程序'), + ('装夹', '装夹'), + ('前置三元定位检测', '前置三元定位检测'), + ('CNC加工', 'CNC加工'), + ('后置三元质量检测', '后置三元质量检测'), + ('解除装夹', '解除装夹'), ('切割', '切割'), ('表面工艺', '表面工艺') + ], string="工序类型", related='route_workcenter_id.routing_type') + workcenter_ids = fields.Many2many('mrp.workcenter', required=False, related='route_workcenter_id.workcenter_ids') + surface_technics_model_type_id = fields.Many2one('sf.model.type') + + _sql_constraints = [ + ( + 'route_model_type_uniq', 'unique (route_workcenter_id,surface_technics_model_type_id)', '表面工艺工序不能重复!') ] diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 361d6c01..2cd692f3 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -23,7 +23,7 @@ class MrpProduction(models.Model): for production in self: production.maintenance_count = len(production.request_ids) - #维修模块按钮 + # 维修模块按钮 def button_maintenance_req(self): self.ensure_one() return { @@ -37,7 +37,8 @@ class MrpProduction(models.Model): }, 'domain': [('production_id', '=', self.id)], } - #打开维修模块请求 + + # 打开维修模块请求 def open_maintenance_request_mo(self): self.ensure_one() action = { @@ -59,7 +60,8 @@ class MrpProduction(models.Model): def action_generate_serial(self): self.ensure_one() - iot_code = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env['ir.sequence'].next_by_code('stock.lot.serial') + iot_code = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[ + 'ir.sequence'].next_by_code('stock.lot.serial') iot_code_name = re.sub('[\u4e00-\u9fa5]', "", iot_code) self.lot_producing_id = self.env['stock.lot'].create({ 'product_id': self.product_id.id, @@ -127,7 +129,44 @@ class MrpProduction(models.Model): if i == processing_panel_len and route.routing_type == '解除装夹': workorders_values.append( self.env['mrp.workorder'].json_workorder_str(k, production, route)) - elif production.product_id.categ_id.type == '胚料': + # 表面工艺工序 + # 获取表面工艺id + surface_technics_arr = [] + # 工序id + route_workcenter_arr = [] + for item in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids: + surface_technics_arr.append(item.route_workcenter_id.surface_technics_id.id) + route_workcenter_arr.append(item.route_workcenter_id.id) + if surface_technics_arr: + production_process_category = self.env['sf.production.process.category'].search( + [('production_process_ids.id', 'in', surface_technics_arr)], + order='sequence asc' + ) + # 用filter刷选表面工艺id'是否存在工艺类别对象里 + if production_process_category: + for p in production_process_category: + production_process = p.production_process_ids.filtered( + lambda pp: pp.id in surface_technics_arr) + if production_process: + process_parameter = production.product_id.model_process_parameters_ids.filtered( + lambda pm: pm.process_id.id == production_process.id) + if process_parameter: + # 产品为表面工艺服务的供应商 + product_production_process = self.env['product.template'].search( + [('server_product_process_parameters_id', '=', process_parameter.id)]) + if product_production_process: + route_production_process = self.env[ + 'mrp.routing.workcenter'].search( + [('surface_technics_id', '=', production_process.id), + ('id', 'in', route_workcenter_arr)]) + if route_production_process: + workorders_values.append( + self.env[ + 'mrp.workorder']._json_workorder_surface_process_str( + production, route_production_process, + process_parameter, + product_production_process.seller_ids[0].partner_id.id)) + elif production.product_id.categ_id.type == '坯料': embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search( [('embryo_model_type_id', '=', production.product_id.embryo_model_type_id.id)], order='sequence asc' @@ -135,12 +174,50 @@ class MrpProduction(models.Model): for route in embryo_routing_workcenter: workorders_values.append( self.env['mrp.workorder'].json_workorder_str('', production, route)) - production.workorder_ids= workorders_values + production.workorder_ids = workorders_values + process_parameter_workorder = self.env['mrp.workorder'].search( + [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id), + ('is_subcontract', '=', True)]) + if process_parameter_workorder: + is_pick = False + consecutive_workorders = [] + m = 0 + sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id) + for i in range(len(sorted_workorders) - 1): + if m == 0: + is_pick = False + if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \ + sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \ + sorted_workorders[i].id == sorted_workorders[i + 1].id - 1: + if sorted_workorders[i] not in consecutive_workorders: + consecutive_workorders.append(sorted_workorders[i]) + consecutive_workorders.append(sorted_workorders[i + 1]) + m += 1 + continue + else: + if m == len(consecutive_workorders) - 1 and m != 0: + self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) + if sorted_workorders[i] in consecutive_workorders: + is_pick = True + consecutive_workorders = [] + m = 0 + # 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单 + if is_pick is False: + self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production) + if m == len(consecutive_workorders) - 1 and m != 0: + self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) + if sorted_workorders[i] in consecutive_workorders: + is_pick = True + consecutive_workorders = [] + m = 0 + if m == len(consecutive_workorders) - 1 and m != 0: + self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) + if is_pick is False and m == 0: + self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production) for workorder in production.workorder_ids: workorder.duration_expected = workorder._get_duration_expected() - - #在之前的销售单上重新生成制造订单 + # 在之前的销售单上重新生成制造订单 def create_production1_values(self, production): production_values_str = {'origin': production.origin, 'product_id': production.product_id.id, @@ -162,7 +239,21 @@ class MrpProduction(models.Model): 'user_id': production.user_id.id} return production_values_str - #工单排序 + def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, picking_type_id): + move_values = { + 'name': item.name if item.name else '/', + 'company_id': item.company_id.id, + 'product_id': item.bom_id.bom_line_ids.product_id.id, + 'product_uom': item.bom_id.bom_line_ids.product_uom_id.id, + 'product_uom_qty': 1.0, + 'location_id': location_src_id, + 'location_dest_id': location_dest_id, + 'origin': item.origin, + 'picking_type_id': picking_type_id, + } + return move_values + + # 工单排序 def _reset_work_order_sequence1(self, k): sequen = 0 for rec in self: @@ -179,7 +270,7 @@ class MrpProduction(models.Model): if work.name == 'CNC加工(返工)' and work.processing_panel == k: work.sequence = sequen + 1 - #在制造订单上新增工单 + # 在制造订单上新增工单 def _create_workorder1(self, k): for production in self: if not production.bom_id or not production.product_id: @@ -213,9 +304,9 @@ class MrpProduction(models.Model): production.product_id.model_processing_panel = k for k in (production.product_id.model_processing_panel.split(',')): routingworkcenter = self.env['sf.product.model.type.routing.sort'].search( - [('product_model_type_id', '=', production.product_id.product_model_type_id.id)], - order='sequence asc' - ) + [('product_model_type_id', '=', production.product_id.product_model_type_id.id)], + order='sequence asc' + ) i += 1 for route in routingworkcenter: @@ -248,9 +339,9 @@ class MrpProduction(models.Model): if work.name == '获取CNC加工程序': work.button_start() work.button_finish() - #work.fetchCNC() + work.fetchCNC() - #创建工单并进行排序 + # 创建工单并进行排序 def _create_workorder(self): res = self._create_workorder3() self._reset_work_order_sequence() diff --git a/sf_manufacturing/models/mrp_routing_workcenter.py b/sf_manufacturing/models/mrp_routing_workcenter.py index 5bb08aa2..27324e40 100644 --- a/sf_manufacturing/models/mrp_routing_workcenter.py +++ b/sf_manufacturing/models/mrp_routing_workcenter.py @@ -1,4 +1,5 @@ from odoo import fields, models +import logging class ResMrpRoutingWorkcenter(models.Model): @@ -11,12 +12,14 @@ class ResMrpRoutingWorkcenter(models.Model): ('CNC加工', 'CNC加工'), ('后置三元质量检测', '后置三元质量检测'), ('解除装夹', '解除装夹'), - ('切割', '切割') + ('切割', '切割'), + ('表面工艺', '表面工艺') ], string="工序类型") is_repeat = fields.Boolean('重复', default=False) workcenter_id = fields.Many2one('mrp.workcenter', required=False) workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_route', required=True) bom_id = fields.Many2one('mrp.bom', required=False) + surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺") # 获得当前登陆者公司 def get_company_id(self): @@ -24,7 +27,8 @@ class ResMrpRoutingWorkcenter(models.Model): company_id = fields.Many2one('res.company', compute="get_company_id", related=False) - # 排产的时候, 根据胚料的长宽高比对一下机床的最大加工尺寸.不符合就不要分配给这个加工中心(机床). + + # 排产的时候, 根据坯料的长宽高比对一下机床的最大加工尺寸.不符合就不要分配给这个加工中心(机床). # 工单对应的工作中心,根据工序中的工作中心去匹配, # 如果只配置了一个工作中心,则默认采用该工作中心; # 如果有多个工作中心, @@ -39,11 +43,13 @@ class ResMrpRoutingWorkcenter(models.Model): workcenter = self.env['mrp.workcenter'].search([('id', 'in', workcenter_ids)]) workcenter_ids = [] for item in workcenter: - print(item.name) + logging.info('get_workcenter-vals:%s' % item.machine_tool_id.name) if item.machine_tool_id: machine_tool = self.env['sf.machine_tool'].search( - [('x_axis', '>', product.bom_ids.bom_line_ids.product_id.length), ('y_axis', '>', product.bom_ids.bom_line_ids.product_id.width), - ('z_axis', '>', product.bom_ids.bom_line_ids.product_id.height), ('id', '=', item.machine_tool_id.id)]) + [('x_axis', '>', product.bom_ids.bom_line_ids.product_id.length), + ('y_axis', '>', product.bom_ids.bom_line_ids.product_id.width), + ('z_axis', '>', product.bom_ids.bom_line_ids.product_id.height), + ('id', '=', item.machine_tool_id.id)]) if machine_tool: workcenter_ids.append(item.id) if len(workcenter_ids) == 1: @@ -52,5 +58,9 @@ class ResMrpRoutingWorkcenter(models.Model): SELECT workcenter_id FROM mrp_workorder where workcenter_id in %s group by workcenter_id order by count(*),workcenter_id asc limit 1 """, [tuple(workcenter_ids)]) - workcenter_id = self.env.cr.dictfetchall()[0].get('workcenter_id') + res = self.env.cr.fetchone() + if res: + workcenter_id = res[0] + else: + workcenter_id = workcenter_ids[0] return workcenter_id diff --git a/sf_manufacturing/models/mrp_workcenter.py b/sf_manufacturing/models/mrp_workcenter.py index 5b266a20..fcfe04ce 100644 --- a/sf_manufacturing/models/mrp_workcenter.py +++ b/sf_manufacturing/models/mrp_workcenter.py @@ -7,13 +7,18 @@ from odoo.addons.resource.models.resource import Intervals class ResWorkcenter(models.Model): _inherit = "mrp.workcenter" machine_tool_id = fields.Many2one('sf.machine_tool', '机床') - + is_process_outsourcing = fields.Boolean('工艺外协') users_ids = fields.Many2many("res.users", 'users_workcenter') equipment_ids = fields.One2many( 'maintenance.equipment', 'workcenter_id', string="Maintenance Equipment", check_company=True) + # 查询工艺外协加工中心 + def get_process_outsourcing_workcenter(self): + outsourcing_workcenter = self.env['mrp.workcenter'].search([('is_process_outsourcing', '=', True)]) + return outsourcing_workcenter.id + @api.onchange('machine_tool_id') def update_machine_tool_is_binding(self): machine_tool = self.env["sf.machine_tool"].search([('is_binding', '=', True)]) diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 54c5d39d..94a9d217 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -29,7 +29,7 @@ class ResMrpWorkOrder(models.Model): ('CNC加工', 'CNC加工'), ('后置三元质量检测', '后置三元质量检测'), ('解除装夹', '解除装夹'), - ('切割', '切割') + ('切割', '切割'), ('表面工艺', '表面工艺') ], string="工序类型") results = fields.Char('检测结果') @@ -54,7 +54,7 @@ class ResMrpWorkOrder(models.Model): programming_state = fields.Char('编程状态') cnc_worksheet = fields.Binary( '工作指令', readonly=True) - material_center_point = fields.Char(string='胚料中心点') + material_center_point = fields.Char(string='坯料中心点') X1_axis = fields.Float(default=0) Y1_axis = fields.Float(default=0) Z1_axis = fields.Float(default=0) @@ -91,6 +91,16 @@ class ResMrpWorkOrder(models.Model): cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工") tray_code = fields.Char(string="托盘") glb_file = fields.Binary("glb模型文件") + is_subcontract = fields.Boolean(string='是否外协') + surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数") + picking_in_id = fields.Many2one('stock.picking', string='外协入库单') + picking_out_id = fields.Many2one('stock.picking', string='外协出库单') + supplier_id = fields.Many2one('res.partner', string='外协供应商') + + def get_no_data(self, production_id): + process_parameter_workorder = self.search( + [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_id)]) + return process_parameter_workorder # 计算配料中心点和与x轴倾斜度方法 def getcenter(self): @@ -137,7 +147,7 @@ class ResMrpWorkOrder(models.Model): except: raise UserError("参数计算有误") - #拼接工单对象属性值 + # 拼接工单对象属性值 def json_workorder_str(self, k, production, route): workorders_values_str = [0, '', { 'product_uom_id': production.product_uom_id.id, @@ -159,6 +169,31 @@ class ResMrpWorkOrder(models.Model): }] return workorders_values_str + # 拼接工单对象属性值(表面工艺) + def _json_workorder_surface_process_str(self, production, route, process_parameter, supplier_id): + workorders_values_str = [0, '', { + 'product_uom_id': production.product_uom_id.id, + 'qty_producing': 0, + 'operation_id': False, + 'name': '%s-%s' % (route.name, process_parameter.name), + 'processing_panel': '', + 'routing_type': '表面工艺', + 'surface_technics_parameters_id': process_parameter.id, + 'work_state': '', + 'supplier_id': supplier_id, + 'is_subcontract': True if process_parameter.gain_way == '外协' else False, + 'workcenter_id': self.env[ + 'mrp.workcenter'].get_process_outsourcing_workcenter() if process_parameter.gain_way == '外协' else + self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids, + route.routing_type, + production.product_id), + 'date_planned_start': False, + 'date_planned_finished': False, + 'duration_expected': 60, + 'duration': 0 + }] + return workorders_values_str + # 维修模块按钮 def button_maintenance_req(self): self.ensure_one() @@ -205,9 +240,9 @@ class ResMrpWorkOrder(models.Model): else: raise UserError('托盘码不能为空') - #验证坯料序列号是否正确 - def pro_code_is_ok(self,barcode): - if barcode!=False: + # 验证坯料序列号是否正确 + def pro_code_is_ok(self, barcode): + if barcode != False: if barcode != self.pro_code: raise UserError('坯料序列号错误') return False @@ -218,7 +253,7 @@ class ResMrpWorkOrder(models.Model): pro_code_ok = fields.Boolean(default=False) - #托盘扫码绑定 + # 托盘扫码绑定 def gettray_auto(self, barcode): if barcode != False: values = self.env['sf.tray'].search([("code", "=", barcode)]) @@ -257,7 +292,6 @@ class ResMrpWorkOrder(models.Model): else: raise UserError('托盘码不能为空') - # 解除托盘绑定 def unbindtray(self): tray = self.env['sf.tray'].search([("production_id", "=", self.production_id.id)]) @@ -396,7 +430,6 @@ class ResMrpWorkOrder(models.Model): }] return workorders_values_str - # 重写工单开始按钮方法 def button_start(self): if self.routing_type == '装夹': @@ -449,6 +482,51 @@ class ResMrpWorkOrder(models.Model): else: raise UserError(_('请先完成上一步工单')) + def button_finish(self): + end_date = datetime.now() + for workorder in self: + if workorder.state in ('done', 'cancel'): + continue + workorder.end_all() + vals = { + 'qty_produced': workorder.qty_produced or workorder.qty_producing or workorder.qty_production, + 'state': 'done', + 'date_finished': end_date, + 'date_planned_finished': end_date, + 'costs_hour': workorder.workcenter_id.costs_hour + } + if not workorder.date_start: + vals['date_start'] = end_date + if not workorder.date_planned_start or end_date < workorder.date_planned_start: + vals['date_planned_start'] = end_date + workorder.with_context(bypass_duration_calculation=True).write(vals) + self.env.cr.commit() + finish_workorder_count = self.env['mrp.workorder'].search_count( + [('production_id', '=', workorder.production_id.id), + ('is_subcontract', '=', True)]) + subcontract_workorder_count = self.env['mrp.workorder'].search_count( + [('production_id', '=', workorder.production_id.id), ('is_subcontract', '=', True), + ('state', '=', 'done')]) + if finish_workorder_count > 0 and subcontract_workorder_count > 0: + subcontract_workorder = self.env['mrp.workorder'].search( + [('production_id', '=', workorder.production_id.id), ('is_subcontract', '=', True), + ('state', '=', 'done')]) + for item in subcontract_workorder: + order_line_ids = [] + server_product = self.env['product.template'].search( + [('server_product_process_parameters_id', '=', item.surface_technics_parameters_id.id), + ('categ_type', '=', '服务'), ('detailed_type', '=', 'service')]) + order_line_ids.append((0, 0, { + 'product_id': server_product.product_variant_id.id, + 'product_qty': 1, + 'product_uom': server_product.uom_id.id + })) + self.env['purchase.order'].create({ + 'partner_id': server_product.seller_ids.partner_id.id, + 'state': 'draft', + 'order_line': order_line_ids, + }) + class CNCprocessing(models.Model): _name = 'sf.cnc.processing' @@ -471,7 +549,6 @@ class CNCprocessing(models.Model): workorder_id = fields.Many2one('mrp.workorder', string="工单") button_state = fields.Boolean(string='是否已经下发') - # mrs下发编程单创建CNC加工 def cnc_processing_create(self, cnc_workorder, ret): logging.info('ret:%s' % ret) @@ -554,6 +631,25 @@ class CNCprocessing(models.Model): else: return False + # end_date = datetime.now() + # for workorder in self: + # if workorder.state in ('done', 'cancel'): + # continue + # workorder.end_all() + # vals = { + # 'qty_produced': workorder.qty_produced or workorder.qty_producing or workorder.qty_production, + # 'state': 'done', + # 'date_finished': end_date, + # 'date_planned_finished': end_date, + # 'costs_hour': workorder.workcenter_id.costs_hour + # } + # if not workorder.date_start: + # vals['date_start'] = end_date + # if not workorder.date_planned_start or end_date < workorder.date_planned_start: + # vals['date_planned_start'] = end_date + # workorder.with_context(bypass_duration_calculation=True).write(vals) + return True + class SfWorkOrderBarcodes(models.Model): """ @@ -571,8 +667,6 @@ class SfWorkOrderBarcodes(models.Model): else: self.pro_code_ok = workorder.pro_code_is_ok(barcode) - - # return { # 'type': 'ir.actions.act_window', # 'name': '工单', @@ -581,5 +675,3 @@ class SfWorkOrderBarcodes(models.Model): # 'context': {'active_id': self.id}, # # 'target': 'current', # } - - diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 03095ad4..dcfcf754 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -3,9 +3,11 @@ from collections import defaultdict, namedtuple from odoo.addons.stock.models.stock_rule import ProcurementException from re import findall as regex_findall from re import split as regex_split -from odoo import SUPERUSER_ID, _, api, models +from odoo import SUPERUSER_ID, _, api, fields, models from odoo.tools import float_compare +from odoo.exceptions import UserError + class StockRule(models.Model): _inherit = 'stock.rule' @@ -226,3 +228,72 @@ class ProductionLot(models.Model): return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name, 2)[ 1] return "%s-%03d" % (product.name, 1) + + +class StockPicking(models.Model): + _inherit = 'stock.picking' + + workorder_in_id = fields.One2many('mrp.workorder', 'picking_in_id') + workorder_out_id = fields.One2many('mrp.workorder', 'picking_out_id') + + # 设置外协出入单的名称 + def _get_name_Res(self, rescode): + count = self.env['ir.sequence'].search_count([('prefix', 'like', rescode)]) + if not count: + num = "%04d" % 1 + else: + m = int(count) + 1 + num = "%04d" % m + return '%s%s' % (rescode, num) + + # 创建 外协出库入单 + def create_outcontract_picking(self, sorted_workorders_arr, item): + m = 0 + for sorted_workorders in sorted_workorders_arr: + if m == 0: + outcontract_stock_move = self.env['stock.move'].search( + [('workorder_id', '=', sorted_workorders.id), ('production_id', '=', item.id)]) + if not outcontract_stock_move: + location_id = self.env.ref( + 'sf_manufacturing.stock_location_locations_virtual_outcontract').id, + location_dest_id = self.env['stock.location'].search( + [('barcode', '=', 'WH-PREPRODUCTION')]).id, + outcontract_picking_type_in = self.env.ref( + 'sf_manufacturing.outcontract_picking_in').id, + outcontract_picking_type_out = self.env.ref( + 'sf_manufacturing.outcontract_picking_out').id, + moves_in = self.env['stock.move'].sudo().create( + item._get_stock_move_values_Res(item, location_id, location_dest_id, + outcontract_picking_type_in)) + moves_out = self.env['stock.move'].sudo().create( + item._get_stock_move_values_Res(item, location_dest_id, location_id, + outcontract_picking_type_out)) + new_picking = True + picking_in = self.env['stock.picking'].create( + moves_in._get_new_picking_values_Res(item, sorted_workorders,'WH/OCIN/')) + picking_out = self.env['stock.picking'].create( + moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/')) + moves_in.write({'picking_id': picking_in.id}) + moves_out.write({'picking_id': picking_out.id}) + moves_in._assign_picking_post_process(new=new_picking) + moves_out._assign_picking_post_process(new=new_picking) + m += 1 + sorted_workorders.write({'picking_in_id': picking_in.id, 'picking_out_id': picking_out.id}) + + +class ReStockMove(models.Model): + _inherit = 'stock.move' + + def _get_new_picking_values_Res(self, item, sorted_workorders, rescode): + return { + 'name': self.env['stock.picking']._get_name_Res(rescode), + 'origin': item.name, + 'company_id': self.mapped('company_id').id, + 'user_id': False, + 'move_type': self.mapped('group_id').move_type or 'direct', + 'partner_id': sorted_workorders.supplier_id.id, + 'picking_type_id': self.mapped('picking_type_id').id, + 'location_id': self.mapped('location_id').id, + 'location_dest_id': self.mapped('location_dest_id').id, + 'state': 'draft', + } diff --git a/sf_manufacturing/models/tray.py b/sf_manufacturing/models/tray.py index 4a691c50..1ba0bea7 100644 --- a/sf_manufacturing/models/tray.py +++ b/sf_manufacturing/models/tray.py @@ -3,7 +3,7 @@ import base64 from io import BytesIO from odoo import api, fields, models -from pystrich.code128 import Code128Encoder +#from pystrich.code128 import Code128Encoder class Tray(models.Model): diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index f2bf5270..bc24436c 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -3,6 +3,8 @@ access_sf_cnc_processing,sf_cnc_processing,model_sf_cnc_processing,base.group_us access_sf_model_type,sf_model_type,model_sf_model_type,base.group_user,1,1,1,1 access_sf_product_model_type_routing_sort,sf_product_model_type_routing_sort,model_sf_product_model_type_routing_sort,base.group_user,1,1,1,1 access_sf_embryo_model_type_routing_sort,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,base.group_user,1,1,1,1 +access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,base.group_user,1,1,1,1 + diff --git a/sf_manufacturing/views/model_type_view.xml b/sf_manufacturing/views/model_type_view.xml index e44f7311..7c3f18de 100644 --- a/sf_manufacturing/views/model_type_view.xml +++ b/sf_manufacturing/views/model_type_view.xml @@ -31,7 +31,7 @@
- + @@ -55,6 +55,17 @@ + + + + + + + + + + +
diff --git a/sf_manufacturing/views/mrp_routing_workcenter_view.xml b/sf_manufacturing/views/mrp_routing_workcenter_view.xml index b854160a..d0db3a7b 100644 --- a/sf_manufacturing/views/mrp_routing_workcenter_view.xml +++ b/sf_manufacturing/views/mrp_routing_workcenter_view.xml @@ -8,6 +8,8 @@ + diff --git a/sf_manufacturing/views/mrp_workcenter_views.xml b/sf_manufacturing/views/mrp_workcenter_views.xml index cc6f1ba9..8c16f783 100644 --- a/sf_manufacturing/views/mrp_workcenter_views.xml +++ b/sf_manufacturing/views/mrp_workcenter_views.xml @@ -109,6 +109,9 @@ + + + diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 82a78866..295a8399 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -5,6 +5,10 @@ mrp.workorder + + + + @@ -113,8 +117,7 @@ ('is_user_working', '!=', False),('user_permissions','=',False),('name','=','获取CNC加工程序')]}"/>