# -*- coding: utf-8 -*- # Part of SmartGo. See LICENSE file for full copyright and licensing details. import base64 import logging import math from io import BytesIO from odoo import api, fields, models, SUPERUSER_ID from pystrich.code128 import Code128Encoder from odoo.exceptions import ValidationError _logger = logging.getLogger(__name__) class CNCprocessing(models.Model): _inherit = 'cnc.processing' _description = "CNC加工" workorder_id = fields.Many2one('mrp.workorder', string="工单") class Tray(models.Model): _inherit = 'sf.tray' _description = '托盘' qr_image = fields.Binary(string="托盘二维码", compute='compute_qr_image') production_id = fields.Many2one('mrp.production', string='制造订单', related='workorder_id.production_id' ) workorder_id = fields.Many2one('mrp.workorder', string="工单" ) @api.onchange('production_id') def updateTrayState(self): if self.workorder_id != False: self.state = '占用' else: self.state = '空闲' def unclamp(self): self.workorder_id = False self.production_id = False self.state = '空闲' @api.depends('code') def compute_qr_image(self): for item in self: if not item.code: item.qr_image = False continue # 根据code动态生成二维码图片 # qr = qrcode.QRCode( # version=1, # error_correction=qrcode.constants.ERROR_CORRECT_L, # box_size=10, # border=4, # ) # qr.add_data(item.code) # qr.make(fit=True) # img = qr.make_image() # 生成条形码文件 # bar = barcode.get("ean13", "123456789102", writer=ImageWriter()) # a = bar.get_fullcode() # b = bar.save('occ') # 生成条形码图片 partner_encoder = Code128Encoder(item.code) # 转换bytes流 temp = BytesIO() partner_encoder.save(temp) # img.save(temp, format='PNG') qr_image = base64.b64encode(temp.getvalue()) item.qr_image = qr_image ''' 工单绑定托盘信息 ''' class MrpWorkOrder(models.Model): _inherit = 'mrp.workorder' _description = '工单' tray_ids = fields.One2many('sf.tray', 'workorder_id', string='托盘') # def get_tray_info(self): # @api.onchange('X_axis', 'Y_axis', 'Z_axis') # def get_center_point(self): # return 'X:%s,Y:%s,Z:%s' % (self.X_axis, self.Y_axis, self.Z_axis) # 加工面 # surface = fields.Selection([("前面", "前面"), ("后面", "后面"), ("左面", "左面"), ("右面", "右面"), # ("上面", "上面")], string="加工面1") material_center_point = fields.Char(string='配料中心点') X1_axis = fields.Float(string='Lx1', default=0) Y1_axis = fields.Float(string='Ly1', default=0) Z1_axis = fields.Float(string='Lz1', default=0) X2_axis = fields.Float(string='Lx2', default=0) Y2_axis = fields.Float(string='Ly2', default=0) Z2_axis = fields.Float(string='Lz2', default=0) X3_axis = fields.Float(string='Fx3', default=0) Y3_axis = fields.Float(string='Fy3', default=0) Z3_axis = fields.Float(string='Fz3', default=0) X4_axis = fields.Float(string='Fx4', default=0) Y4_axis = fields.Float(string='Fy4', default=0) Z4_axis = fields.Float(string='Fz4', default=0) X5_axis = fields.Float(string='Rx5', default=0) Y5_axis = fields.Float(string='Ry5', default=0) Z5_axis = fields.Float(string='Rz5', default=0) X6_axis = fields.Float(string='Rx6', default=0) Y6_axis = fields.Float(string='Ry6', default=0) Z6_axis = fields.Float(string='Rz6', default=0) X7_axis = fields.Float(string='Bx7', default=0) Y7_axis = fields.Float(string='By7', default=0) Z7_axis = fields.Float(string='Bz7', default=0) X8_axis = fields.Float(string='Bx8', default=0) Y8_axis = fields.Float(string='By8', default=0) Z8_axis = fields.Float(string='Bz8', default=0) X9_axis = fields.Float(string='Uz9', default=0) Y9_axis = fields.Float(string='Uz9', default=0) Z9_axis = fields.Float(string='Uz9', default=0) X10_axis = fields.Float(string='Uz10', default=0) Y10_axis = fields.Float(string='Uz10', default=0) Z10_axis = fields.Float(string='Uz10', default=0) # 计算配料中心点和与x轴倾斜度方法 def getcenter(self): x1 = self.X1_axis x2 = self.X2_axis x3 = self.X3_axis x4 = self.X4_axis x5 = self.X5_axis x6 = self.X6_axis x7 = self.X7_axis x8 = self.X8_axis y1 = self.Y1_axis y2 = self.Y2_axis y3 = self.Y3_axis y4 = self.Y4_axis y5 = self.Y5_axis y6 = self.Y6_axis y7 = self.Y7_axis y8 = self.Y8_axis z1 = self.Z9_axis x0 = ((x3 - x4) * (x2 * y1 - x1 * y2) - (x1 - x2) * (x4 * y3 - x3 * y4)) / ( (x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)) y0 = ((y3 - y4) * (y2 * x1 - y1 * x2) - (y1 - y2) * (y4 * x3 - y3 * x4)) / ( (y3 - y4) * (x1 - x2) - (y1 - y2) * (x3 - x4)) x1 = ((x7 - x8) * (x6 * y5 - x5 * y7) - (x5 - x6) * (x8 * y7 - x7 * y8)) / ( (x7 - x8) * (y5 - y6) - (x5 - x6) * (y7 - y8)); y1 = ((y7 - y8) * (y6 * x5 - y5 * x7) - (y5 - y6) * (y8 * x7 - y7 * x8)) / ( (y7 - y8) * (x5 - x6) - (y5 - y6) * (x7 - x8)) x = (x0 + x1) / 2 y = (y0 + y1) / 2 z = z1 / 2 jd = math.atan2((x7 - x8), (y7 - y8)) jdz = jd * 180 / math.pi print("(%s,%s)" % (x, y)) self.material_center_point = ("(%s,%s,%s)" % (x, y, z)) self.X_deviation_angle = jdz X_deviation_angle = fields.Integer(string="X轴偏差度", default=0) test_results = fields.Selection([("合格", "合格"), ("返工", "返工"), ("报废", "报废")], string="检测结果") cnc_ids = fields.One2many("cnc.processing", 'workorder_id', string="CNC加工") tray_code = fields.Char(string="托盘") # 扫码绑定托盘方法 def gettray(self): if self.tray_code != False: values = self.env['sf.tray'].search([("code", "=", self.tray_code)]) if values: if values.state == "占用": raise ValidationError('该托盘已占用') if values.state == "报损": raise ValidationError('该托盘已损坏') else: values.update({ 'workorder_id': self, 'production_id': self.production_id, 'state': '占用', }) else: raise ValidationError('该托盘编码已失效') else:return "" # 解除托盘绑定 def unbindtray(self): tray = self.env['sf.tray'].search([("production_id", "=", self.production_id.id)]) if tray: tray.unclamp() return "" def recreateManufacturing(self): """ 重新生成制造订单 """ values = self.env['mrp.production'].create_production1_values(self.production_id) productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company( self.production_id.company_id).create( values) self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) productions._create_workorder() productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \ ( p.move_dest_ids.procure_method != 'make_to_order' and not p.move_raw_ids and not p.workorder_ids)).action_confirm() for production in productions: origin_production = production.move_dest_ids and production.move_dest_ids[ 0].raw_material_production_id or False orderpoint = production.orderpoint_id if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual': production.message_post( body=_('This production order has been created from Replenishment Report.'), message_type='comment', subtype_xmlid='mail.mt_note') elif orderpoint: production.message_post_with_view( 'mail.message_origin_link', values={'self': production, 'origin': orderpoint}, subtype_id=self.env.ref('mail.mt_note').id) elif origin_production: production.message_post_with_view( 'mail.message_origin_link', values={'self': production, 'origin': origin_production}, subtype_id=self.env.ref('mail.mt_note').id) # print(productions) return "" def recreateWorkerOrder(self): """ 返工重新生成工单 """ productions = self.production_id self.env['stock.move'].sudo().create(productions._get_moves_raw_values()) self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) productions.create_workorder1(self.processing_panel) return "" def fetchCNC(self): return "" ''' 制造订单绑定托盘信息 ''' class MrpProduction(models.Model): _inherit = 'mrp.production' _description = "制造订单" tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘") def create_production1_values(self, production): production_values_str = {'origin': production.origin, 'product_id': production.product_id.id, 'product_description_variants': production.product_description_variants, 'product_qty': production.product_qty, 'product_uom_id': production.product_uom_id.id, 'location_src_id': production.location_src_id.id, 'location_dest_id': production.location_dest_id.id, 'bom_id': production.bom_id.id, 'date_deadline': production.date_deadline, 'date_planned_start': production.date_planned_start, 'date_planned_finished': production.date_planned_finished, 'procurement_group_id': False, 'propagate_cancel': production.propagate_cancel, 'orderpoint_id': production.orderpoint_id.id, 'picking_type_id': production.picking_type_id.id, 'company_id': production.company_id.id, 'move_dest_ids': production.move_dest_ids.ids, 'user_id': production.user_id.id} return production_values_str def create_workorder1(self, k): for production in self: if not production.bom_id or not production.product_id: continue workorders_values = [] product_qty = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id) exploded_boms, dummy = production.bom_id.explode(production.product_id, product_qty / production.bom_id.product_qty, picking_type=production.bom_id.picking_type_id) for bom, bom_data in exploded_boms: # If the operations of the parent BoM and phantom BoM are the same, don't recreate work orders. if not (bom.operation_ids and (not bom_data['parent_line'] or bom_data[ 'parent_line'].bom_id.operation_ids != bom.operation_ids)): continue for operation in bom.operation_ids: if operation._skip_operation_line(bom_data['product']): continue workorders_values += [{ 'name': operation.name, 'production_id': production.id, 'workcenter_id': operation.workcenter_id.id, 'product_uom_id': production.product_uom_id.id, 'operation_id': operation.id, 'state': 'pending', }] # 根据加工面板的面数及对应的工序模板生成工单 i = 0 production.product_id.model_processing_panel = k processing_panel_len = len(k) for k in (production.product_id.model_processing_panel.split(',')): routingworkcenter = self.env['sf.model.type.routing.sort'].search( [('model_type_id', '=', production.product_id.model_type_id.id)], order='sequence asc' ) i += 1 for route in routingworkcenter: if route.routing_type == 'CNC加工': workorders_values.append( self.env['mrp.workorder'].json_workorder_str(k, production, route)) if route.routing_type == '后置三元质量检测': workorders_values.append( self.env['mrp.workorder'].json_workorder_str(k, production, route)) production.workorder_ids = workorders_values for workorder in production.workorder_ids: workorder.duration_expected = workorder._get_duration_expected() class Attachment(models.Model): _inherit = 'ir.attachment' cnc_model = fields.Binary('cnc文件', attachment=False) model_name = fields.Char('模型名称')