Compare commits

..

4 Commits

Author SHA1 Message Date
胡尧
f6d8cb6267 编程单增加零件图号 2025-05-15 08:45:02 +08:00
胡尧
c898e02860 解决制造申请字段未复制到成品中 2025-05-14 17:02:04 +08:00
胡尧
5477582a69 修改中控日志接口授权为none 2025-05-14 16:09:06 +08:00
胡尧
9cb22d810e 增加接口日志 2025-05-12 15:14:04 +08:00
16 changed files with 99 additions and 108 deletions

View File

@@ -19,9 +19,8 @@ class MrpProduction(models.Model):
# item.pr_mp_count = len(pr_ids) # item.pr_mp_count = len(pr_ids)
# 由于采购申请合并了所有销售订单行的采购,所以不区分产品 # 由于采购申请合并了所有销售订单行的采购,所以不区分产品
first_mp = self.env['mrp.production'].search( first_mp = self.env['mrp.production'].search(
[('origin', '=', item.origin)], limit=1, order='id asc') [('origin', '=', item.origin)], limit=1, order='id asc')
pr_ids = self.env['purchase.request'].sudo().search( pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', first_mp.name)])
[('origin', 'like', first_mp.name), ('is_subcontract', '!=', 'True')])
item.pr_mp_count = len(pr_ids) item.pr_mp_count = len(pr_ids)
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name), ('is_subcontract', '!=', 'True')]) # pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', item.name), ('is_subcontract', '!=', 'True')])
@@ -30,10 +29,18 @@ class MrpProduction(models.Model):
采购请求 采购请求
""" """
self.ensure_one() self.ensure_one()
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name),('is_subcontract', '!=', True)])
# if self.product_id.product_tmpl_id.single_manufacturing == True and not self.is_remanufacture:
# first_order = self.env['mrp.production'].search(
# [('origin', '=', self.origin), ('product_id', '=', self.product_id.id)], limit=1, order='id asc')
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', first_order.name)])
# else:
# pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', self.name)])
# 由于采购申请合并了所有销售订单行的采购,所以不区分产品
first_mp = self.env['mrp.production'].search( first_mp = self.env['mrp.production'].search(
[('origin', '=', self.origin)], limit=1, order='id asc') [('origin', '=', self.origin)], limit=1, order='id asc')
pr_ids = self.env['purchase.request'].sudo().search( pr_ids = self.env['purchase.request'].sudo().search([('origin', 'like', first_mp.name)])
[('origin', 'like', first_mp.name), ('is_subcontract', '!=', 'True')])
action = { action = {
'res_model': 'purchase.request', 'res_model': 'purchase.request',
@@ -47,7 +54,7 @@ class MrpProduction(models.Model):
else: else:
action.update({ action.update({
'name': _("%s生成采购请求单", self.name), 'name': _("%s生成采购请求单", self.name),
'domain': [('id', 'in', pr_ids.ids)], 'domain': [('id', 'in', pr_ids)],
'view_mode': 'tree,form', 'view_mode': 'tree,form',
}) })
return action return action

View File

@@ -13,7 +13,11 @@ class ProductTemplate(models.Model):
template_id.purchase_request = product_id.purchase_request template_id.purchase_request = product_id.purchase_request
return template_id return template_id
class ProdcutProduct(models.Model):
_inherit = 'product.product'
def copy_template(self, product_template_id): def copy_template(self, product_template_id):
""" 复制成品模板时,复制采购申请 """ """ 复制成品模板时,复制采购申请 """
super(ProductTemplate, self).copy_template(product_template_id) super(ProdcutProduct, self).copy_template(product_template_id)
self.purchase_request = product_template_id.purchase_request self.purchase_request = product_template_id.purchase_request

View File

@@ -6,6 +6,10 @@ class ProductTemplate(models.Model):
is_manual_processing = fields.Boolean(string='人工线下加工') is_manual_processing = fields.Boolean(string='人工线下加工')
is_customer_provided = fields.Boolean(string='客供料') is_customer_provided = fields.Boolean(string='客供料')
class ProductProduct(models.Model):
_inherit = 'product.product'
def copy_template(self, product_template_id): def copy_template(self, product_template_id):
if not isinstance(product_template_id, ProductTemplate): if not isinstance(product_template_id, ProductTemplate):
raise ValueError('%s必须是ProductTemplate类型' % product_template_id) raise ValueError('%s必须是ProductTemplate类型' % product_template_id)

View File

@@ -4,6 +4,7 @@ import json
import logging import logging
from odoo.addons.sf_mrs_connect.controllers.controllers import Sf_Mrs_Connect from odoo.addons.sf_mrs_connect.controllers.controllers import Sf_Mrs_Connect
from odoo.addons.sf_manufacturing.controllers.controllers import Manufacturing_Connect from odoo.addons.sf_manufacturing.controllers.controllers import Manufacturing_Connect
from odoo.addons.sf_base.decorators.api_log import api_log
from datetime import datetime from datetime import datetime
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@@ -12,6 +13,7 @@ class WorkorderExceptionConroller(http.Controller):
@http.route('/AutoDeviceApi/BillError', type='json', auth='public', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/BillError', type='json', auth='public', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
@api_log('工单对接错误', requester='中控系统')
def workder_exception(self, **kw): def workder_exception(self, **kw):
""" """
记录工单异常 记录工单异常

View File

@@ -103,12 +103,19 @@ class PrintingUtils(models.AbstractModel):
self.send_to_printer(host, port, zpl_code) self.send_to_printer(host, port, zpl_code)
def add_qr_code_to_pdf(self, pdf_path:str, content:str, buttom_text:Optional[str]=False): def add_qr_code_to_pdf(
self,
pdf_path:str,
content:str,
qr_code_buttom_text:Optional[str]=False,
buttom_text:Optional[str]=False,
):
""" """
在PDF文件中添加二维码 在PDF文件中添加二维码
:param pdf_path: PDF文件路径 :param pdf_path: PDF文件路径
:param content: 二维码内容 :param content: 二维码内容
:param buttom_text: 二维码下方文字 :param qr_code_buttom_text: 二维码下方文字
:param buttom_text: 正文下方文字
:return: 是否成功 :return: 是否成功
""" """
if not os.path.exists(pdf_path): if not os.path.exists(pdf_path):
@@ -156,8 +163,9 @@ class PrintingUtils(models.AbstractModel):
existing_pdf = PdfFileReader(original_file) existing_pdf = PdfFileReader(original_file)
output = PdfFileWriter() output = PdfFileWriter()
# 处理一页 # 处理最后一页
page = existing_pdf.getPage(0) last_page = existing_pdf.getNumPages() - 1
page = existing_pdf.getPage(last_page)
# 获取页面尺寸 # 获取页面尺寸
page_width = float(page.mediaBox.getWidth()) page_width = float(page.mediaBox.getWidth())
page_height = float(page.mediaBox.getHeight()) page_height = float(page.mediaBox.getHeight())
@@ -179,13 +187,21 @@ class PrintingUtils(models.AbstractModel):
qr_y = margin + 20 # 将二维码向上移动一点,为文字留出空间 qr_y = margin + 20 # 将二维码向上移动一点,为文字留出空间
c.drawImage(qr_temp_path, page_width - qr_size - margin, qr_y, width=qr_size, height=qr_size) c.drawImage(qr_temp_path, page_width - qr_size - margin, qr_y, width=qr_size, height=qr_size)
if buttom_text: if qr_code_buttom_text:
# 在二维码下方绘制文字 # 在二维码下方绘制文字
text = buttom_text text = qr_code_buttom_text
text_width = c.stringWidth(text, "SimSun" if font_found else "Helvetica", 10) # 准确计算文字宽度 text_width = c.stringWidth(text, "SimSun" if font_found else "Helvetica", 10) # 准确计算文字宽度
text_x = page_width - qr_size - margin + (qr_size - text_width) / 2 # 文字居中对齐 text_x = page_width - qr_size - margin + (qr_size - text_width) / 2 # 文字居中对齐
text_y = margin + 20 # 文字位置靠近底部 text_y = margin + 20 # 文字位置靠近底部
c.drawString(text_x, text_y, text) c.drawString(text_x, text_y, text)
if buttom_text:
# 在下方中间添加文字
text = button_text
text_width = c.stringWidth(text, "SimSun" if font_found else "Helvetica", 10) # 准确计算文字宽度
text_x = (page_width - text_width) / 2 # 文字居中对齐
text_y = margin + 20 # 文字位置靠近底部
c.drawString(text_x, text_y, text)
c.save() c.save()
@@ -196,11 +212,12 @@ class PrintingUtils(models.AbstractModel):
# 合并原始页面和二维码页面 # 合并原始页面和二维码页面
page.mergePage(qr_page) page.mergePage(qr_page)
output.addPage(page)
# 添加剩余的页面 # 添加剩余的页面
for i in range(1, existing_pdf.getNumPages()): for i in range(0, last_page):
output.addPage(existing_pdf.getPage(i)) output.addPage(existing_pdf.getPage(i))
output.addPage(page)
# 保存最终的PDF到一个临时文件 # 保存最终的PDF到一个临时文件
final_temp_path = pdf_path + '.tmp' final_temp_path = pdf_path + '.tmp'

View File

@@ -24,8 +24,6 @@ class SfProductionProcessParameter(models.Model):
obj = super(SfProductionProcessParameter, self).create(vals) obj = super(SfProductionProcessParameter, self).create(vals)
return obj return obj
def create_service_product(self): def create_service_product(self):
if not self.active:
return
service_categ = self.env.ref( service_categ = self.env.ref(
'sf_dlm.product_category_surface_technics_sf').sudo() 'sf_dlm.product_category_surface_technics_sf').sudo()

View File

@@ -41,9 +41,7 @@
attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/> attrs="{'invisible': [('categ_type', 'not in', ['成品','坯料', '原材料'])],'readonly': [('id', '!=', False)]}"/>
<field name="server_product_process_parameters_id" string="工艺参数" <field name="server_product_process_parameters_id" string="工艺参数"
options="{'no_create': True}" options="{'no_create': True}"
attrs="{'invisible': ['|',('detailed_type', '!=', 'service'),('detailed_type', '=', False)]}" attrs="{'invisible': ['|',('detailed_type', '!=', 'service'),('detailed_type', '=', False)]}"/>
domain="[('active', '=', 'True'),('outsourced_service_products', '!=', 'True')]"
/>
<field name="cutting_tool_material_id" class="custom_required" <field name="cutting_tool_material_id" class="custom_required"
options="{'no_create': True}" options="{'no_create': True}"
attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}" attrs="{'invisible': [('categ_type', '!=', '刀具')],'required': [('categ_type', '=', '刀具')],'readonly': [('id', '!=', False)]}"

View File

@@ -56,6 +56,7 @@ class Manufacturing_Connect(http.Controller):
@http.route('/AutoDeviceApi/GetShiftPlan', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/GetShiftPlan', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
@api_log('获取日计划', requester='中控系统')
def get_ShiftPlan(self, **kw): def get_ShiftPlan(self, **kw):
""" """
自动化每天获取机台日计划 自动化每天获取机台日计划

View File

@@ -928,8 +928,6 @@ class MrpProduction(models.Model):
'sf_stock.stock_route_process_outsourcing').id)] 'sf_stock.stock_route_process_outsourcing').id)]
for product_id, request_line_list in grouped_purchase_request_line_sorted_list.items(): for product_id, request_line_list in grouped_purchase_request_line_sorted_list.items():
cur_request_line = request_line_list[0] cur_request_line = request_line_list[0]
if cur_request_line['product_qty'] == 1:
cur_request_line['product_qty'] = len(request_line_list)
# cur_request_line['product_qty'] = cur_request_line['product_qty'] # cur_request_line['product_qty'] = cur_request_line['product_qty']
cur_request_line['request_id'] = pr.id cur_request_line['request_id'] = pr.id
cur_request_line['origin'] = ", ".join({item['production_name'] for item in request_line_list if item.get('production_name')}) cur_request_line['origin'] = ", ".join({item['production_name'] for item in request_line_list if item.get('production_name')})

View File

@@ -443,11 +443,21 @@ class ResMrpWorkOrder(models.Model):
@api.depends('state', 'production_id.name') @api.depends('state', 'production_id.name')
def _compute_surface_technics_purchase_ids(self): def _compute_surface_technics_purchase_ids(self):
for order in self: for order in self:
pr_ids = self.env['purchase.request'].sudo().search( if order.routing_type == '表面工艺' and order.state not in ['cancel']:
[('origin', 'like', self.production_id.name), ('is_subcontract', '=', 'True'), # domain = [('group_id', '=', self.production_id.procurement_group_id.id),
('state', '!=', 'rejected')]) # ('purchase_type', '=', 'consignment'), ('state', '!=', 'cancel')]
if pr_ids.purchase_count: domain = [('purchase_type', '=', 'consignment'),
order.surface_technics_purchase_count = pr_ids.purchase_count ('origin', 'like', '%' + self.production_id.name + '%'),
('state', '!=', 'cancel')]
purchase = self.env['purchase.order'].search(domain)
order.surface_technics_purchase_count = 0
if not purchase:
order.surface_technics_purchase_count = 0
for po in purchase:
if any(
line.product_id and line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id
for line in po.order_line):
order.surface_technics_purchase_count = 1
else: else:
order.surface_technics_purchase_count = 0 order.surface_technics_purchase_count = 0
@@ -492,19 +502,16 @@ class ResMrpWorkOrder(models.Model):
# if technology_design.is_auto is False: # if technology_design.is_auto is False:
# domain = [('origin', '=', self.production_id.name)] # domain = [('origin', '=', self.production_id.name)]
# else: # else:
pr_ids = self.env['purchase.request'].sudo().search( purchase_orders_id = self._get_surface_technics_purchase_ids()
[('origin', 'like', self.production_id.name), ('is_subcontract', '=', 'True'), result = {
('state', '!=', 'rejected')]) "type": "ir.actions.act_window",
# purchase_orders_id = self._get_surface_technics_purchase_ids() "res_model": "purchase.order",
# result = { "res_id": purchase_orders_id.id,
# "type": "ir.actions.act_window", # "domain": [['id', 'in', self.purchase_id]],
# "res_model": "purchase.order", "name": _("Purchase Orders"),
# "res_id": purchase_orders_id.id, 'view_mode': 'form',
# # "domain": [['id', 'in', self.purchase_id]], }
# "name": _("Purchase Orders"), return result
# 'view_mode': 'form',
# }
return pr_ids.action_view_purchase_order()
def _get_surface_technics_purchase_ids(self): def _get_surface_technics_purchase_ids(self):
domain = [('origin', 'like', '%' + self.production_id.name + '%'), ('purchase_type', '=', 'consignment'), domain = [('origin', 'like', '%' + self.production_id.name + '%'), ('purchase_type', '=', 'consignment'),
@@ -1276,27 +1283,20 @@ class ResMrpWorkOrder(models.Model):
# for move_line in move.move_line_ids # for move_line in move.move_line_ids
# ) # )
if (workorder.production_id.production_type == '人工线下加工' if (workorder.production_id.production_type == '人工线下加工'
and workorder.production_id.programming_state == '编程'): and workorder.production_id.schedule_state == ''):
# and workorder.production_id.programming_state == '已编程' # and workorder.production_id.programming_state == '已编程'
if workorder.is_subcontract is True: if workorder.is_subcontract is True:
if workorder.production_id.state == 'rework': if workorder.production_id.state == 'rework':
workorder.state = 'waiting' workorder.state = 'waiting'
continue continue
purchase_orders_id = self._get_surface_technics_purchase_ids() purchase_orders_id = self._get_surface_technics_purchase_ids()
purchase_count = 0 if purchase_orders_id.state == 'purchase':
for purchase_order in purchase_orders_id:
for purchase_order_line in purchase_order.order_line:
if purchase_order_line.product_id.server_product_process_parameters_id.id == workorder.surface_technics_parameters_id.id:
purchase_count = purchase_order_line.product_qty
if purchase_orders_id.state == 'purchase' and purchase_count>=workorder.production_id.product_qty:
workorder.state = 'ready' workorder.state = 'ready'
picking_id = workorder.production_id.picking_ids.filtered( picking_id = workorder.production_id.picking_ids.filtered(
lambda wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区') lambda wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区')
move_out = picking_id.move_ids move_out = picking_id.move_ids
# move_out = workorder.move_subcontract_workorder_ids[1] # move_out = workorder.move_subcontract_workorder_ids[1]
for mo in move_out: for mo in move_out:
if workorder.production_id.bom_id.bom_line_ids.product_id.id != mo.product_id.id:
continue
if mo.state != 'done': if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False}) mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids: if not mo.move_line_ids:
@@ -1312,7 +1312,6 @@ class ResMrpWorkOrder(models.Model):
else: else:
workorder.state = 'ready' workorder.state = 'ready'
continue continue
continue
# ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]========================== # ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]==========================
if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework' if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework'
or workorder.production_id.schedule_state != '已排' or workorder.production_id.schedule_state != '已排'
@@ -1328,7 +1327,9 @@ class ResMrpWorkOrder(models.Model):
if workorder.is_subcontract is False: if workorder.is_subcontract is False:
workorder.state = 'ready' workorder.state = 'ready'
else: else:
if workorder.production_id.programming_state == '已编程': if len(workorder.production_id.picking_ids.filtered(
lambda w: w.state not in ['done',
'cancel'])) == 0 and workorder.production_id.programming_state == '已编程':
purchase_orders_id = self._get_surface_technics_purchase_ids() purchase_orders_id = self._get_surface_technics_purchase_ids()
if purchase_orders_id: if purchase_orders_id:
if purchase_orders_id.state == 'purchase': if purchase_orders_id.state == 'purchase':
@@ -1338,8 +1339,6 @@ class ResMrpWorkOrder(models.Model):
wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区') wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区')
move_out = picking_id.move_ids move_out = picking_id.move_ids
for mo in move_out: for mo in move_out:
if workorder.production_id.bom_id.bom_line_ids.product_id.id != mo.product_id.id:
continue
if mo.state != 'done': if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False}) mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids: if not mo.move_line_ids:
@@ -1388,16 +1387,7 @@ class ResMrpWorkOrder(models.Model):
boolean = True boolean = True
if not boolean: if not boolean:
raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name) raise UserError('制造订单【%s】缺少组件的序列号信息!' % self.production_id.name)
self.pro_code = False # 默认值 self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name
if (
self.production_id
and self.production_id.move_raw_ids
and len(self.production_id.move_raw_ids) > 0
and self.production_id.move_raw_ids[0].move_line_ids
and len(self.production_id.move_raw_ids[0].move_line_ids) > 0
and self.production_id.move_raw_ids[0].move_line_ids[0].lot_id
):
self.pro_code = self.production_id.move_raw_ids[0].move_line_ids[0].lot_id.name
# cnc校验 # cnc校验
if self.production_id.production_type == '自动化产线加工': if self.production_id.production_type == '自动化产线加工':
cnc_workorder = self.search( cnc_workorder = self.search(
@@ -1432,8 +1422,6 @@ class ResMrpWorkOrder(models.Model):
# [('barcode', 'ilike', 'VL-SPOC')]).id), # [('barcode', 'ilike', 'VL-SPOC')]).id),
# ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])]) # ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])])
for mo in move_out: for mo in move_out:
if self.production_id.bom_id.bom_line_ids.product_id.id != mo.product_id.id:
continue
if mo.state != 'done': if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False}) mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids: if not mo.move_line_ids:
@@ -1566,8 +1554,7 @@ class ResMrpWorkOrder(models.Model):
lambda wo: wo.is_subcontract == True and wo.state != 'cancel').sorted('sequence') lambda wo: wo.is_subcontract == True and wo.state != 'cancel').sorted('sequence')
if self == subcontract_workorders[-1]: if self == subcontract_workorders[-1]:
# 给下一个库存移动就绪 # 给下一个库存移动就绪
if self.move_subcontract_workorder_ids: self.move_subcontract_workorder_ids[0].move_dest_ids._action_done()
self.move_subcontract_workorder_ids[0].move_dest_ids._action_done()
# self.production_id.button_mark_done() # self.production_id.button_mark_done()
tem_date_planned_finished = record.date_planned_finished tem_date_planned_finished = record.date_planned_finished
tem_date_finished = record.date_finished tem_date_finished = record.date_finished

View File

@@ -126,13 +126,11 @@ class PurchaseOrder(models.Model):
if not work_ids: if not work_ids:
continue continue
min_sequence_wk = min(work_ids, key=lambda wk: wk.sequence) min_sequence_wk = min(work_ids, key=lambda wk: wk.sequence)
if min_sequence_wk.is_subcontract and min_sequence_wk.state == 'ready': if min_sequence_wk.is_subcontract:
picking_id = production_id.picking_ids.filtered( picking_id = production_id.picking_ids.filtered(
lambda wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区') lambda wk: wk.location_id.name == '制造前' and wk.location_dest_id.name == '外协加工区')
move_out = picking_id.move_ids move_out = picking_id.move_ids
for mo in move_out: for mo in move_out:
if production_id.bom_id.bom_line_ids.product_id.id != mo.product_id.id:
continue
if mo.state != 'done': if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False}) mo.write({'state': 'assigned', 'production_id': False})
if not mo.move_line_ids: if not mo.move_line_ids:
@@ -154,8 +152,6 @@ class PurchaseOrder(models.Model):
for line in self.order_line: for line in self.order_line:
# 将产品不追踪序列号的行项目设置qty_done # 将产品不追踪序列号的行项目设置qty_done
if not line.move_ids:
continue
if line.move_ids and line.move_ids[0].product_id.tracking == 'none': if line.move_ids and line.move_ids[0].product_id.tracking == 'none':
line.move_ids[0].quantity_done = line.move_ids[0].product_qty line.move_ids[0].quantity_done = line.move_ids[0].product_qty
return res return res
@@ -228,24 +224,6 @@ class PurchaseOrderLine(models.Model):
) )
record.part_number = filtered_order_line.product_id.part_number record.part_number = filtered_order_line.product_id.part_number
record.part_name = filtered_order_line.product_id.part_name record.part_name = filtered_order_line.product_id.part_name
elif record.order_id.purchase_type == 'consignment':
product_name = ''
match = re.search(r'(S\d{5}-\d)', record.related_product.name)
# 如果匹配成功,提取结果
if match:
product_name = match.group(0)
sale_order_name = ''
match_sale = re.search(r'S(\d+)', record.related_product.name)
if match_sale:
sale_order_name = match_sale.group(0)
sale_order = self.env['sale.order'].sudo().search(
[('name', '=', sale_order_name)])
if sale_order:
filtered_order_line = sale_order.order_line.filtered(
lambda order_line: re.search(f'{product_name}$', order_line.product_id.name)
)
record.part_number = filtered_order_line.product_id.part_number
record.part_name = filtered_order_line.product_id.part_name
else: else:
record.part_number = record.product_id.part_number record.part_number = record.product_id.part_number
record.part_name = record.product_id.part_name record.part_name = record.product_id.part_name

View File

@@ -56,10 +56,10 @@ class SaleOrder(models.Model):
'jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo() 'jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo()
# 复制成品模板上的属性 # 复制成品模板上的属性
line.product_id.product_tmpl_id.copy_template(product_template_id) line.product_id.copy_template(product_template_id)
# 将模板上的single_manufacturing属性复制到成品上 # 将模板上的single_manufacturing属性复制到成品上
line.product_id.single_manufacturing = product_template_id.single_manufacturing # line.product_id.single_manufacturing = product_template_id.single_manufacturing
line.product_id.tracking = product_template_id.tracking # line.product_id.tracking = product_template_id.tracking
order_id = self order_id = self
product = line.product_id product = line.product_id
@@ -76,7 +76,7 @@ class SaleOrder(models.Model):
'embryo_redundancy_id': line.embryo_redundancy_id, 'embryo_redundancy_id': line.embryo_redundancy_id,
} }
product_name = '' product_name = ''
match = re.search(r'(S\d{5}-\d)', product.name) match = re.search(r'(S\d{5}-\d*)', product.name)
# 如果匹配成功,提取结果 # 如果匹配成功,提取结果
if match: if match:
product_name = match.group(0) product_name = match.group(0)

View File

@@ -20,6 +20,13 @@ class SfProductionProcessParameter(models.Model):
is_product_button = fields.Boolean(compute='_compute_is_product_button',default=False) is_product_button = fields.Boolean(compute='_compute_is_product_button',default=False)
is_delete_button = fields.Boolean(compute='_compute_is_delete_button', default=False) is_delete_button = fields.Boolean(compute='_compute_is_delete_button', default=False)
routing_id = fields.Many2one('mrp.routing.workcenter', string="工序") routing_id = fields.Many2one('mrp.routing.workcenter', string="工序")
@api.depends('outsourced_service_products')
def _compute_service_products(self):
for record in self:
# 假设取第一条作为主明细
record.service_products = record.outsourced_service_products.ids if record.outsourced_service_products else False
def _inverse_service_products(self): def _inverse_service_products(self):
for record in self: for record in self:
if record.service_products: if record.service_products:
@@ -27,12 +34,6 @@ class SfProductionProcessParameter(models.Model):
record.outsourced_service_products = record.service_products.ids if record.service_products else False record.outsourced_service_products = record.service_products.ids if record.service_products else False
else: else:
record.outsourced_service_products = False record.outsourced_service_products = False
@api.depends('outsourced_service_products')
def _compute_service_products(self):
for record in self:
# 假设取第一条作为主明细
record.service_products = record.outsourced_service_products[0].id if record.outsourced_service_products else False
def name_get(self): def name_get(self):
result = [] result = []
for record in self: for record in self:

View File

@@ -930,8 +930,6 @@ class ReStockMove(models.Model):
} }
def get_move_line(self, production_id, sorted_workorders): def get_move_line(self, production_id, sorted_workorders):
# if not self.move_ids[0].product_id.single_manufacturing and self.move_ids[0].product_id.tracking == 'none':
qty = production_id.product_qty
return { return {
'move_id': self.id, 'move_id': self.id,
'product_id': self.product_id.id, 'product_id': self.product_id.id,
@@ -939,7 +937,7 @@ class ReStockMove(models.Model):
'location_id': self.picking_id.location_id.id, 'location_id': self.picking_id.location_id.id,
'location_dest_id': self.picking_id.location_dest_id.id, 'location_dest_id': self.picking_id.location_dest_id.id,
'picking_id': self.picking_id.id, 'picking_id': self.picking_id.id,
'reserved_uom_qty': qty, 'reserved_uom_qty': 1.0,
'lot_id': production_id.move_line_raw_ids.lot_id.id, 'lot_id': production_id.move_line_raw_ids.lot_id.id,
'company_id': self.env.company.id, 'company_id': self.env.company.id,
# 'workorder_id': '' if not sorted_workorders else sorted_workorders.id, # 'workorder_id': '' if not sorted_workorders else sorted_workorders.id,

View File

@@ -3,9 +3,6 @@ import logging
import os import os
import json import json
import base64 import base64
import traceback
from odoo import http, fields, models from odoo import http, fields, models
from odoo.http import request from odoo.http import request
from odoo.addons.sf_base.controllers.controllers import MultiInheritController from odoo.addons.sf_base.controllers.controllers import MultiInheritController
@@ -276,8 +273,7 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
except Exception as e: except Exception as e:
res = {'status': -1, 'message': '系统解析失败'} res = {'status': -1, 'message': '系统解析失败'}
request.cr.rollback() request.cr.rollback()
traceback_error = traceback.format_exc() logging.info('get_cnc_processing_create error:%s' % e)
logging.error("get_cnc_processing_create error:%s" % traceback_error)
return json.JSONEncoder().encode(res) return json.JSONEncoder().encode(res)

View File

@@ -41,6 +41,7 @@ class Manufacturing_Connect(http.Controller):
@http.route('/AutoDeviceApi/ToolInventory', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/ToolInventory', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
@api_log('功能刀具清单', requester='中控系统')
def get_functional_tool_inventory_Info(self, **kw): def get_functional_tool_inventory_Info(self, **kw):
""" """
功能刀具清单接口 功能刀具清单接口
@@ -70,6 +71,7 @@ class Manufacturing_Connect(http.Controller):
@http.route('/AutoDeviceApi/ToolEntity', type='json', auth='none', methods=['GET', 'POST'], csrf=False, @http.route('/AutoDeviceApi/ToolEntity', type='json', auth='none', methods=['GET', 'POST'], csrf=False,
cors="*") cors="*")
@api_log('功能刀具', requester='中控系统')
def get_functional_tool_entity_Info(self, **kw): def get_functional_tool_entity_Info(self, **kw):
""" """
功能刀具列表接口 功能刀具列表接口