Accept Merge Request #1004: (feature/优化制造订单和编程 -> develop)
Merge Request: 优化制造订单和工件配送 Created By: @杨金灵 Reviewed By: @马广威 Approved By: @马广威 Accepted By: @杨金灵 URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1004
This commit is contained in:
@@ -111,11 +111,12 @@ class Sf_Bf_Connect(http.Controller):
|
|||||||
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
|
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
|
||||||
request.cr.rollback()
|
request.cr.rollback()
|
||||||
return json.JSONEncoder().encode(res)
|
return json.JSONEncoder().encode(res)
|
||||||
# 产品配置bom
|
else:
|
||||||
product_bom_purchase = request.env['mrp.bom'].with_user(
|
# 产品配置bom
|
||||||
request.env.ref("base.user_admin")).bom_create(product, 'normal', False)
|
product_bom_purchase = request.env['mrp.bom'].with_user(
|
||||||
product_bom_purchase.with_user(request.env.ref("base.user_admin")).bom_create_line_has(
|
request.env.ref("base.user_admin")).bom_create(product, 'normal', False)
|
||||||
purchase_embryo)
|
product_bom_purchase.with_user(request.env.ref("base.user_admin")).bom_create_line_has(
|
||||||
|
purchase_embryo)
|
||||||
order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item)
|
order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item)
|
||||||
i += 1
|
i += 1
|
||||||
res['factory_order_no'] = order_id.name
|
res['factory_order_no'] = order_id.name
|
||||||
|
|||||||
@@ -511,7 +511,6 @@ class Manufacturing_Connect(http.Controller):
|
|||||||
rfid_code = ret[f'RfidCode{i}']
|
rfid_code = ret[f'RfidCode{i}']
|
||||||
logging.info('RfidCode:%s' % rfid_code)
|
logging.info('RfidCode:%s' % rfid_code)
|
||||||
domain = [
|
domain = [
|
||||||
('feeder_station_start_id.name', '=', ret['DeviceId']),
|
|
||||||
('workorder_id.rfid_code', '=', rfid_code),
|
('workorder_id.rfid_code', '=', rfid_code),
|
||||||
('status', '=', '待下发'),
|
('status', '=', '待下发'),
|
||||||
('type', '=', '下产线')
|
('type', '=', '下产线')
|
||||||
|
|||||||
@@ -166,26 +166,30 @@ class MrpProduction(models.Model):
|
|||||||
if quick_order:
|
if quick_order:
|
||||||
programme_way = 'manual operation'
|
programme_way = 'manual operation'
|
||||||
try:
|
try:
|
||||||
res = {'model_code': '' if not cnc.product_id.model_code else cnc.product_id.model_code,
|
res = {
|
||||||
'production_no': cnc.name,
|
'production_no': cnc.name,
|
||||||
'machine_tool_code': "",
|
'machine_tool_code': '',
|
||||||
'material_code': self.env['sf.production.materials'].search(
|
'model_code': cnc.product_id.model_code,
|
||||||
[('id', '=', cnc.product_id.materials_id.id)]).materials_no,
|
'material_code': self.env['sf.production.materials'].search(
|
||||||
'material_type_code': self.env['sf.materials.model'].search(
|
[('id', '=', cnc.product_id.materials_id.id)]).materials_no,
|
||||||
[('id', '=', cnc.product_id.materials_type_id.id)]).materials_no,
|
'material_type_code': self.env['sf.materials.model'].search(
|
||||||
'machining_processing_panel': cnc.product_id.model_processing_panel,
|
[('id', '=', cnc.product_id.materials_type_id.id)]).materials_no,
|
||||||
'machining_precision': cnc.product_id.model_machining_precision,
|
'machining_processing_panel': cnc.product_id.model_processing_panel,
|
||||||
'embryo_long': cnc.product_id.bom_ids.bom_line_ids.product_id.length,
|
'machining_precision': cnc.product_id.model_machining_precision,
|
||||||
'embryo_height': cnc.product_id.bom_ids.bom_line_ids.product_id.height,
|
'embryo_long': cnc.product_id.bom_ids.bom_line_ids.product_id.length,
|
||||||
'embryo_width': cnc.product_id.bom_ids.bom_line_ids.product_id.width,
|
'embryo_height': cnc.product_id.bom_ids.bom_line_ids.product_id.height,
|
||||||
'order_no': cnc.origin,
|
'embryo_width': cnc.product_id.bom_ids.bom_line_ids.product_id.width,
|
||||||
'model_order_no': cnc.product_id.default_code,
|
'order_no': cnc.origin,
|
||||||
'user': cnc.env.user.name,
|
'model_order_no': cnc.product_id.default_code,
|
||||||
'programme_way': programme_way,
|
'user': cnc.env.user.name,
|
||||||
'model_file': '' if not cnc.product_id.model_file else base64.b64encode(
|
'programme_way': programme_way,
|
||||||
cnc.product_id.model_file).decode('utf-8')
|
'model_file': '' if not cnc.product_id.model_file else base64.b64encode(
|
||||||
}
|
cnc.product_id.model_file).decode('utf-8')
|
||||||
logging.info('res:%s' % res)
|
}
|
||||||
|
# 打印出除了 model_file 之外的所有键值对
|
||||||
|
for key, value in res.items():
|
||||||
|
if key != 'model_file':
|
||||||
|
logging.info('%s: %s' % (key, value))
|
||||||
configsettings = self.env['res.config.settings'].get_values()
|
configsettings = self.env['res.config.settings'].get_values()
|
||||||
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
|
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
|
||||||
url = '/api/intelligent_programming/create'
|
url = '/api/intelligent_programming/create'
|
||||||
@@ -263,14 +267,15 @@ class MrpProduction(models.Model):
|
|||||||
# 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心;
|
# 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心;
|
||||||
|
|
||||||
def _create_workorder3(self):
|
def _create_workorder3(self):
|
||||||
programming_no = None
|
# production_names = [production.name for production in self if production.product_id.categ_id.type == '成品']
|
||||||
product_id_new = None
|
# programming_no = None
|
||||||
|
# product_first = None
|
||||||
for production in self:
|
for production in self:
|
||||||
if not production.bom_id or not production.product_id:
|
if not production.bom_id or not production.product_id:
|
||||||
continue
|
continue
|
||||||
workorders_values = []
|
workorders_values = []
|
||||||
if product_id_new is None:
|
# if product_first is None:
|
||||||
product_id_new = production.product_id
|
# product_first = production.product_id
|
||||||
|
|
||||||
product_qty = production.product_uom_id._compute_quantity(production.product_qty,
|
product_qty = production.product_uom_id._compute_quantity(production.product_qty,
|
||||||
production.bom_id.product_uom_id)
|
production.bom_id.product_uom_id)
|
||||||
@@ -295,14 +300,15 @@ class MrpProduction(models.Model):
|
|||||||
'state': 'pending',
|
'state': 'pending',
|
||||||
}]
|
}]
|
||||||
if production.product_id.categ_id.type == '成品':
|
if production.product_id.categ_id.type == '成品':
|
||||||
if programming_no is None:
|
production.fetchCNC()
|
||||||
production.fetchCNC()
|
# 第二期同一个产品多个制造订单对应一个编程单和模型库
|
||||||
programming_no = production.programming_no
|
# if programming_no is None:
|
||||||
else:
|
# production.fetchCNC(production_names)
|
||||||
if production.product_id == product_id_new:
|
# programming_no = production.programming_no
|
||||||
if not production.programming_no:
|
# else:
|
||||||
production.write({'programming_no': programming_no, 'programming_state': '编程中'})
|
# if production.product_id == product_first:
|
||||||
|
# if not production.programming_no:
|
||||||
|
# production.write({'programming_no': programming_no, 'programming_state': '编程中'})
|
||||||
# 根据加工面板的面数及对应的工序模板生成工单
|
# 根据加工面板的面数及对应的工序模板生成工单
|
||||||
i = 0
|
i = 0
|
||||||
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
|
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
|
||||||
|
|||||||
@@ -493,9 +493,15 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
return workorders_values_str
|
return workorders_values_str
|
||||||
|
|
||||||
def _json_workpiece_delivery_list(self, production):
|
def _json_workpiece_delivery_list(self, production):
|
||||||
|
up_route = self.env['sf.agv.task.route'].search([('route_type', '=', '上产线')], limit=1, order='id asc')
|
||||||
|
down_route = self.env['sf.agv.task.route'].search([('route_type', '=', '下产线')], limit=1, order='id asc')
|
||||||
return [
|
return [
|
||||||
[0, '', {'production_id': production.id, 'type': '上产线'}],
|
[0, '', {'production_id': production.id, 'type': '上产线', 'route_id': up_route.id,
|
||||||
[0, '', {'production_id': production.id, 'type': '下产线'}]]
|
'feeder_station_start_id': up_route.start_site_id.id,
|
||||||
|
'feeder_station_destination_id': up_route.end_site_id.id}],
|
||||||
|
[0, '', {'production_id': production.id, 'type': '下产线', 'route_id': down_route.id,
|
||||||
|
'feeder_station_start_id': down_route.start_site_id.id,
|
||||||
|
'feeder_station_destination_id': down_route.end_site_id.id}]]
|
||||||
|
|
||||||
# 拼接工单对象属性值(表面工艺)
|
# 拼接工单对象属性值(表面工艺)
|
||||||
def _json_workorder_surface_process_str(self, production, route, process_parameter, supplier_id):
|
def _json_workorder_surface_process_str(self, production, route, process_parameter, supplier_id):
|
||||||
@@ -827,16 +833,13 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
raise UserError("请对前置三元检测定位参数进行计算定位")
|
raise UserError("请对前置三元检测定位参数进行计算定位")
|
||||||
if not record.rfid_code:
|
if not record.rfid_code:
|
||||||
raise UserError("请扫RFID码进行绑定")
|
raise UserError("请扫RFID码进行绑定")
|
||||||
record.workpiece_delivery_ids[0].write({'status': '待下发'})
|
|
||||||
record.process_state = '待加工'
|
record.process_state = '待加工'
|
||||||
# record.write({'process_state': '待加工'})
|
# record.write({'process_state': '待加工'})
|
||||||
record.production_id.process_state = '待加工'
|
record.production_id.process_state = '待加工'
|
||||||
|
|
||||||
if record.routing_type == 'CNC加工':
|
if record.routing_type == 'CNC加工':
|
||||||
record.process_state = '待解除装夹'
|
record.process_state = '待解除装夹'
|
||||||
# record.write({'process_state': '待加工'})
|
# record.write({'process_state': '待加工'})
|
||||||
record.production_id.process_state = '待解除装夹'
|
record.production_id.process_state = '待解除装夹'
|
||||||
|
|
||||||
if record.routing_type == '解除装夹':
|
if record.routing_type == '解除装夹':
|
||||||
'''
|
'''
|
||||||
记录结束时间
|
记录结束时间
|
||||||
@@ -904,13 +907,17 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
|
|
||||||
# 根据中控系统提供的检测文件地址去ftp里对应的制造订单里获取
|
# 根据中控系统提供的检测文件地址去ftp里对应的制造订单里获取
|
||||||
def get_detection_file(self, workorder, reportPath):
|
def get_detection_file(self, workorder, reportPath):
|
||||||
if reportPath.startswith('/'):
|
# if reportPath.startswith('/'):
|
||||||
reportPath = reportPath[4:]
|
# reportPath = reportPath[4:]
|
||||||
serverdir = os.path.join('/tmp', reportPath)
|
# serverdir = os.path.join('/tmp', reportPath)
|
||||||
|
serverdir = '/tmp' + reportPath
|
||||||
logging.info('get_detection_file-serverdir:%s' % serverdir)
|
logging.info('get_detection_file-serverdir:%s' % serverdir)
|
||||||
serverdir_prefix = os.path.dirname(serverdir)
|
serverdir_prefix = os.path.dirname(serverdir)
|
||||||
|
logging.info('serverdir_prefix-serverdir:%s' % serverdir_prefix)
|
||||||
for root, dirs, files in os.walk(serverdir_prefix):
|
for root, dirs, files in os.walk(serverdir_prefix):
|
||||||
for filename in files:
|
for filename in files:
|
||||||
|
logging.info('filename:%s' % filename)
|
||||||
|
logging.info('reportPath:%s' % os.path.basename(reportPath))
|
||||||
if filename == os.path.basename(reportPath):
|
if filename == os.path.basename(reportPath):
|
||||||
report_file_path = os.path.join(root, filename)
|
report_file_path = os.path.join(root, filename)
|
||||||
logging.info('get_detection_file-report_file_path:%s' % report_file_path)
|
logging.info('get_detection_file-report_file_path:%s' % report_file_path)
|
||||||
@@ -945,6 +952,8 @@ class CNCprocessing(models.Model):
|
|||||||
|
|
||||||
# mrs下发编程单创建CNC加工
|
# mrs下发编程单创建CNC加工
|
||||||
def cnc_processing_create(self, cnc_workorder, ret, program_path, program_path_tmp):
|
def cnc_processing_create(self, cnc_workorder, ret, program_path, program_path_tmp):
|
||||||
|
# 注释代码为第二期同一产品多个编程单需求
|
||||||
|
# cnc_processing = None
|
||||||
for obj in ret['programming_list']:
|
for obj in ret['programming_list']:
|
||||||
workorder = self.env['mrp.workorder'].search([('production_id.name', '=', ret['production_order_no']),
|
workorder = self.env['mrp.workorder'].search([('production_id.name', '=', ret['production_order_no']),
|
||||||
('processing_panel', '=', obj['processing_panel']),
|
('processing_panel', '=', obj['processing_panel']),
|
||||||
@@ -979,10 +988,28 @@ class CNCprocessing(models.Model):
|
|||||||
item.is_cnc_program_down = True
|
item.is_cnc_program_down = True
|
||||||
if item.workorder_id.state == 'waiting':
|
if item.workorder_id.state == 'waiting':
|
||||||
item.workorder_id.state = 'ready'
|
item.workorder_id.state = 'ready'
|
||||||
|
# return cnc_processing
|
||||||
|
|
||||||
# cnc_workorder.time_ids.date_end = datetime.now()
|
# cnc_workorder.time_ids.date_end = datetime.now()
|
||||||
# cnc_workorder.button_finish()
|
# cnc_workorder.button_finish()
|
||||||
|
|
||||||
|
def _json_cnc_processing(self, obj):
|
||||||
|
cnc_processing_str = [0, 0, {
|
||||||
|
'sequence_number': obj['sequence_number'],
|
||||||
|
'program_name': obj['program_name'],
|
||||||
|
'cutting_tool_name': obj['cutting_tool_name'],
|
||||||
|
'cutting_tool_no': obj['cutting_tool_no'],
|
||||||
|
'processing_type': obj['processing_type'],
|
||||||
|
'margin_x_y': obj['margin_x_y'],
|
||||||
|
'margin_z': obj['margin_z'],
|
||||||
|
'depth_of_processing_z': obj['depth_of_processing_z'],
|
||||||
|
'cutting_tool_extension_length': obj['cutting_tool_extension_length'],
|
||||||
|
'cutting_tool_handle_type': obj['cutting_tool_handle_type'],
|
||||||
|
'estimated_processing_time': obj['estimated_processing_time'],
|
||||||
|
'remark': obj['remark']
|
||||||
|
}]
|
||||||
|
return cnc_processing_str
|
||||||
|
|
||||||
# 根据程序名和加工面匹配到ftp里对应的Nc程序名,可优化为根据cnc_processing.program_path进行匹配
|
# 根据程序名和加工面匹配到ftp里对应的Nc程序名,可优化为根据cnc_processing.program_path进行匹配
|
||||||
def get_cnc_processing_file(self, serverdir, cnc_processing, program_path):
|
def get_cnc_processing_file(self, serverdir, cnc_processing, program_path):
|
||||||
logging.info('serverdir:%s' % serverdir)
|
logging.info('serverdir:%s' % serverdir)
|
||||||
@@ -1014,7 +1041,6 @@ class CNCprocessing(models.Model):
|
|||||||
# 将FTP的nc文件下载到临时目录
|
# 将FTP的nc文件下载到临时目录
|
||||||
def download_file_tmp(self, production_no, processing_panel):
|
def download_file_tmp(self, production_no, processing_panel):
|
||||||
remotepath = os.path.join('/NC', production_no, 'return', processing_panel)
|
remotepath = os.path.join('/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_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 = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']), ftp_resconfig['ftp_user'],
|
||||||
ftp_resconfig['ftp_password'])
|
ftp_resconfig['ftp_password'])
|
||||||
@@ -1236,8 +1262,8 @@ class WorkPieceDelivery(models.Model):
|
|||||||
same_route_id = item.route_id.id
|
same_route_id = item.route_id.id
|
||||||
if item.route_id.id != same_route_id:
|
if item.route_id.id != same_route_id:
|
||||||
is_not_route += 1
|
is_not_route += 1
|
||||||
else:
|
# else:
|
||||||
raise UserError('请选择【任务路线】再进行配送')
|
# raise UserError('请选择【任务路线】再进行配送')
|
||||||
if production_type != item.type:
|
if production_type != item.type:
|
||||||
raise UserError('请选择类型为%s的制造订单进行配送' % production_type)
|
raise UserError('请选择类型为%s的制造订单进行配送' % production_type)
|
||||||
if down_status != item.status:
|
if down_status != item.status:
|
||||||
@@ -1280,7 +1306,7 @@ class WorkPieceDelivery(models.Model):
|
|||||||
'default_type': production_type,
|
'default_type': production_type,
|
||||||
}}
|
}}
|
||||||
else:
|
else:
|
||||||
if self.type == '运送空料架':
|
if production_type == '运送空料架':
|
||||||
raise UserError("您所选择的【任务路线】的【终点接驳站】已占用,请在该接驳站空闲时进行配送")
|
raise UserError("您所选择的【任务路线】的【终点接驳站】已占用,请在该接驳站空闲时进行配送")
|
||||||
else:
|
else:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
@@ -1317,30 +1343,33 @@ class WorkPieceDelivery(models.Model):
|
|||||||
feeder_station_destination = None
|
feeder_station_destination = None
|
||||||
route_id = None
|
route_id = None
|
||||||
for item in self:
|
for item in self:
|
||||||
delivery_Arr.append(item.name)
|
if route_id is None:
|
||||||
|
route_id = item.route_id.id
|
||||||
|
if feeder_station_start is None:
|
||||||
|
feeder_station_start = item.feeder_station_start_id
|
||||||
|
if feeder_station_destination is None:
|
||||||
|
feeder_station_destination = item.feeder_station_destination_id
|
||||||
if item.type in ['上产线', '下产线']:
|
if item.type in ['上产线', '下产线']:
|
||||||
if route_id is None:
|
|
||||||
route_id = item.route_id.id
|
|
||||||
if feeder_station_start is None:
|
|
||||||
feeder_station_start = item.feeder_station_start_id.name
|
|
||||||
if feeder_station_destination is None:
|
|
||||||
feeder_station_destination = item.feeder_station_destination_id.name
|
|
||||||
item.route_id = route_id
|
item.route_id = route_id
|
||||||
|
item.feeder_station_start_id = feeder_station_start.id
|
||||||
|
item.feeder_station_destination_id = feeder_station_destination.id
|
||||||
|
delivery_Arr.append(item.name)
|
||||||
else:
|
else:
|
||||||
self = self.create(
|
self = self.create(
|
||||||
{'name': self.env['ir.sequence'].next_by_code('sf.workpiece.delivery'),
|
{'name': self.env['ir.sequence'].next_by_code('sf.workpiece.delivery'),
|
||||||
'route_id': self.route_id.id,
|
'route_id': self.route_id.id,
|
||||||
'feeder_station_start_id': self.feeder_station_start_id.id,
|
'feeder_station_start_id': self.feeder_station_start_id.id,
|
||||||
'feeder_station_destination_id': self.feeder_station_destination_id.id})
|
'feeder_station_destination_id': self.feeder_station_destination_id.id})
|
||||||
|
delivery_Arr.append(self.name)
|
||||||
delivery_str = ','.join(map(str, delivery_Arr))
|
delivery_str = ','.join(map(str, delivery_Arr))
|
||||||
if feeder_station_start is not None:
|
if feeder_station_start is not None:
|
||||||
positionCode_Arr.append({
|
positionCode_Arr.append({
|
||||||
'positionCode': feeder_station_start,
|
'positionCode': feeder_station_start.name,
|
||||||
'code': '00'
|
'code': '00'
|
||||||
})
|
})
|
||||||
if feeder_station_destination is not None:
|
if feeder_station_destination is not None:
|
||||||
positionCode_Arr.append({
|
positionCode_Arr.append({
|
||||||
'positionCode': feeder_station_destination,
|
'positionCode': feeder_station_destination.name,
|
||||||
'code': '00'
|
'code': '00'
|
||||||
})
|
})
|
||||||
res = {'reqCode': delivery_str, 'reqTime': '', 'clientCode': '', 'tokenCode': '',
|
res = {'reqCode': delivery_str, 'reqTime': '', 'clientCode': '', 'tokenCode': '',
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import os
|
|||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from odoo.modules import get_resource_path
|
from odoo.modules import get_resource_path
|
||||||
|
|
||||||
|
|
||||||
from OCC.Extend.DataExchange import read_step_file
|
from OCC.Extend.DataExchange import read_step_file
|
||||||
from OCC.Extend.DataExchange import write_stl_file
|
from OCC.Extend.DataExchange import write_stl_file
|
||||||
|
|
||||||
@@ -179,6 +181,12 @@ class ResProductMo(models.Model):
|
|||||||
# ('standard_library_id', '=', self.cutting_tool_model_id.id)],
|
# ('standard_library_id', '=', self.cutting_tool_model_id.id)],
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
# def name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
|
||||||
|
# # if self._context.get('is_sale_order_line'):
|
||||||
|
# # domain = [('sale_ok', '=', True), ('categ_type', '=', '成品')]
|
||||||
|
# # return self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid)
|
||||||
|
# return super(product.template, self)._name_search(name, args, operator, limit, name_get_uid)
|
||||||
|
|
||||||
@api.onchange('specification_id')
|
@api.onchange('specification_id')
|
||||||
def _onchange_specification(self):
|
def _onchange_specification(self):
|
||||||
if self.specification_id:
|
if self.specification_id:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ access_mrp_workcenter_group_sf_mrp_user,mrp_workcenter,model_mrp_workcenter,sf_b
|
|||||||
access_mrp_workcenter_manager,mrp_workcenter,model_mrp_workcenter,sf_base.group_sf_mrp_manager,1,1,1,0
|
access_mrp_workcenter_manager,mrp_workcenter,model_mrp_workcenter,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
access_mrp_workcenter_productivity_group_sf_mrp_user,mrp_workcenter_productivity,model_mrp_workcenter_productivity,sf_base.group_sf_mrp_user,1,0,0,0
|
access_mrp_workcenter_productivity_group_sf_mrp_user,mrp_workcenter_productivity,model_mrp_workcenter_productivity,sf_base.group_sf_mrp_user,1,0,0,0
|
||||||
access_mrp_workcenter_productivity_manager,mrp_workcenter_productivity,model_mrp_workcenter_productivity,sf_base.group_sf_mrp_manager,1,1,1,0
|
access_mrp_workcenter_productivity_manager,mrp_workcenter_productivity,model_mrp_workcenter_productivity,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
access_sf_workpiece_delivery_group_sf_order_user,sf_workpiece_delivery_group_sf_order_user,model_sf_workpiece_delivery,sf_base.group_sf_order_user,1,1,0,0
|
access_sf_workpiece_delivery_group_sf_order_user,sf_workpiece_delivery_group_sf_order_user,model_sf_workpiece_delivery,sf_base.group_sf_order_user,1,1,1,0
|
||||||
access_sf_workpiece_delivery_group_sf_equipment_user,sf_workpiece_delivery_group_sf_equipment_user,model_sf_workpiece_delivery,sf_base.group_sf_equipment_user,1,1,0,0
|
access_sf_workpiece_delivery_group_sf_equipment_user,sf_workpiece_delivery_group_sf_equipment_user,model_sf_workpiece_delivery,sf_base.group_sf_equipment_user,1,1,0,0
|
||||||
|
|
||||||
access_sf_workpiece_delivery_manager,sf_workpiece_delivery,model_sf_workpiece_delivery,sf_base.group_sf_mrp_manager,1,1,0,0
|
access_sf_workpiece_delivery_manager,sf_workpiece_delivery,model_sf_workpiece_delivery,sf_base.group_sf_mrp_manager,1,1,0,0
|
||||||
|
|||||||
|
@@ -145,7 +145,6 @@
|
|||||||
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'),('state','=','done')]}"/> -->
|
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'),('state','=','done')]}"/> -->
|
||||||
<button name="button_workpiece_delivery" type="object" string="工件配送" class="btn-primary"
|
<button name="button_workpiece_delivery" type="object" string="工件配送" class="btn-primary"
|
||||||
attrs="{'invisible': ['|',('routing_type','!=','装夹预调'),('is_delivery','=',True)]}"/>
|
attrs="{'invisible': ['|',('routing_type','!=','装夹预调'),('is_delivery','=',True)]}"/>
|
||||||
|
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//page[1]" position="before">
|
<xpath expr="//page[1]" position="before">
|
||||||
<page string="开料要求" attrs='{"invisible": [("routing_type","!=","切割")]}'>
|
<page string="开料要求" attrs='{"invisible": [("routing_type","!=","切割")]}'>
|
||||||
@@ -266,13 +265,13 @@
|
|||||||
<page string="工件装夹" attrs='{"invisible": [("routing_type","!=","装夹预调")]}'>
|
<page string="工件装夹" attrs='{"invisible": [("routing_type","!=","装夹预调")]}'>
|
||||||
<group>
|
<group>
|
||||||
<field name="_barcode_scanned" widget="barcode_handler"/>
|
<field name="_barcode_scanned" widget="barcode_handler"/>
|
||||||
<group string="卡盘">
|
<!-- <group string="卡盘">-->
|
||||||
<field name="chuck_serial_number"/>
|
<!-- <field name="chuck_serial_number"/>-->
|
||||||
<field name="chuck_name"/>
|
<!-- <field name="chuck_name"/>-->
|
||||||
<field name="chuck_brand_id"/>
|
<!-- <field name="chuck_brand_id"/>-->
|
||||||
<field name="chuck_type_id"/>
|
<!-- <field name="chuck_type_id"/>-->
|
||||||
<field name="chuck_model_id"/>
|
<!-- <field name="chuck_model_id"/>-->
|
||||||
</group>
|
<!-- </group>-->
|
||||||
<group string="托盘">
|
<group string="托盘">
|
||||||
<field name="tray_serial_number" readonly="1" string="序列号"/>
|
<field name="tray_serial_number" readonly="1" string="序列号"/>
|
||||||
<field name="tray_product_id" readonly="1" string="名称"/>
|
<field name="tray_product_id" readonly="1" string="名称"/>
|
||||||
@@ -446,7 +445,8 @@
|
|||||||
<field name='X_deviation_angle' readonly="1"/>
|
<field name='X_deviation_angle' readonly="1"/>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
<page string="工件配送" attrs='{"invisible": [("routing_type","!=","装夹预调")]}'>
|
<page string="工件配送"
|
||||||
|
attrs="{'invisible': [('routing_type','!=','装夹预调')]}">
|
||||||
<field name="workpiece_delivery_ids">
|
<field name="workpiece_delivery_ids">
|
||||||
<tree editable="bottom">
|
<tree editable="bottom">
|
||||||
<field name="production_id" invisible="1"/>
|
<field name="production_id" invisible="1"/>
|
||||||
@@ -457,7 +457,7 @@
|
|||||||
<field name="production_line_id"/>
|
<field name="production_line_id"/>
|
||||||
<field name="task_delivery_time" readonly="1"/>
|
<field name="task_delivery_time" readonly="1"/>
|
||||||
<field name="task_completion_time" readonly="1"/>
|
<field name="task_completion_time" readonly="1"/>
|
||||||
<field name="status"/>
|
<field name="status" readonly="1"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</page>
|
</page>
|
||||||
@@ -607,12 +607,14 @@
|
|||||||
decoration-danger="status == '待配送'"/>
|
decoration-danger="status == '待配送'"/>
|
||||||
<field name="production_id"/>
|
<field name="production_id"/>
|
||||||
<field name="type" readonly="1"/>
|
<field name="type" readonly="1"/>
|
||||||
<field name="production_line_id" options="{'no_create': True}"/>
|
<field name="production_line_id" options="{'no_create': True}" readonly="1"/>
|
||||||
<field name="route_id" options="{'no_create': True}"/>
|
<field name="route_id" options="{'no_create': True}"
|
||||||
|
domain="[('route_type','in',['上产线','下产线'])]"/>
|
||||||
|
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
|
||||||
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
|
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
|
||||||
<field name="feeder_station_destination_id" readonly="1" force_save="1"/>
|
<field name="feeder_station_destination_id" readonly="1" force_save="1"/>
|
||||||
<field name="is_cnc_program_down" readonly="1"/>
|
<field name="is_cnc_program_down" readonly="1"/>
|
||||||
<!-- <field name="rfid_code"/>-->
|
<!-- <field name="rfid_code"/>-->
|
||||||
<field name="task_delivery_time" readonly="1"/>
|
<field name="task_delivery_time" readonly="1"/>
|
||||||
<field name="task_completion_time" readonly="1"/>
|
<field name="task_completion_time" readonly="1"/>
|
||||||
<field name="delivery_duration" widget="float_time"/>
|
<field name="delivery_duration" widget="float_time"/>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Part of YiZuo. See LICENSE file for full copyright and licensing details.
|
# Part of YiZuo. See LICENSE file for full copyright and licensing details.
|
||||||
|
import logging
|
||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import UserError, ValidationError
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from odoo import models, api, fields, _
|
from odoo import models, api, fields, _
|
||||||
@@ -44,7 +45,11 @@ class WorkpieceDeliveryWizard(models.TransientModel):
|
|||||||
def recognize_production(self):
|
def recognize_production(self):
|
||||||
# production_ids = []
|
# production_ids = []
|
||||||
# delivery_ids = []
|
# delivery_ids = []
|
||||||
if len(self.production_ids) > 4:
|
# aa = self.production_ids.workorder_ids.filtered(
|
||||||
|
# lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.filtered(
|
||||||
|
# lambda c: c.rfid_code == self.rfid_code)
|
||||||
|
# logging.info('aa:%s' % aa)
|
||||||
|
if len(self.production_ids) == 4:
|
||||||
raise UserError('只能配送四个制造订单')
|
raise UserError('只能配送四个制造订单')
|
||||||
else:
|
else:
|
||||||
if self.rfid_code:
|
if self.rfid_code:
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class FtpController():
|
|||||||
def file_exists(self, path):
|
def file_exists(self, path):
|
||||||
# 检查文件是否存在于FTP服务器上
|
# 检查文件是否存在于FTP服务器上
|
||||||
try:
|
try:
|
||||||
|
logging.info("dirname:%s" % os.path.dirname(path))
|
||||||
self.ftp.cwd(os.path.dirname(path))
|
self.ftp.cwd(os.path.dirname(path))
|
||||||
files = self.ftp.nlst()
|
files = self.ftp.nlst()
|
||||||
return os.path.basename(path) in files
|
return os.path.basename(path) in files
|
||||||
@@ -31,6 +32,11 @@ class FtpController():
|
|||||||
logging.error(f"Error checking file: {e}")
|
logging.error(f"Error checking file: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# # 检测字符串的编码
|
||||||
|
# def detect_encoding(self, s):
|
||||||
|
# result = chardet.detect(s)
|
||||||
|
# return result['encoding']
|
||||||
|
|
||||||
# 下载目录下的文件
|
# 下载目录下的文件
|
||||||
def download_file_tree(self, target_dir, serverdir):
|
def download_file_tree(self, target_dir, serverdir):
|
||||||
if not os.path.exists(serverdir):
|
if not os.path.exists(serverdir):
|
||||||
@@ -84,6 +90,9 @@ class FtpController():
|
|||||||
return 1
|
return 1
|
||||||
except Exception:
|
except Exception:
|
||||||
return 0
|
return 0
|
||||||
|
finally:
|
||||||
|
self.ftp.quit()
|
||||||
|
logging.info("ftp已关闭")
|
||||||
|
|
||||||
# 下载指定目录下的指定文件
|
# 下载指定目录下的指定文件
|
||||||
def download_file(self, serverfile, remotefile):
|
def download_file(self, serverfile, remotefile):
|
||||||
|
|||||||
@@ -229,6 +229,11 @@ class sf_production_plan(models.Model):
|
|||||||
record.env['mrp.production'].sudo().browse(i).schedule_state = '已排'
|
record.env['mrp.production'].sudo().browse(i).schedule_state = '已排'
|
||||||
# record.production_id.date_planned_start = record.date_planned_start
|
# record.production_id.date_planned_start = record.date_planned_start
|
||||||
# record.production_id.date_planned_finished = record.date_planned_finished
|
# record.production_id.date_planned_finished = record.date_planned_finished
|
||||||
|
record.production_id.production_line_id = record.production_line_id.id
|
||||||
|
record.production_id.workorder_ids.filtered(
|
||||||
|
lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.write(
|
||||||
|
{'production_line_id': record.production_line_id.id,
|
||||||
|
'plan_start_processing_time': record.date_planned_start})
|
||||||
else:
|
else:
|
||||||
raise ValidationError("未找到工单")
|
raise ValidationError("未找到工单")
|
||||||
# record.date_planned_finished = record.date_planned_start + timedelta(days=3)
|
# record.date_planned_finished = record.date_planned_start + timedelta(days=3)
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ class ReSaleOrder(models.Model):
|
|||||||
self.check_status = 'pending'
|
self.check_status = 'pending'
|
||||||
|
|
||||||
def get_customer(self):
|
def get_customer(self):
|
||||||
partner_tag = self.env['res.partner.category'].sudo().search([('name', '=', '业务平台')], limit=1, order='id asc')
|
partner_tag = self.env['res.partner.category'].sudo().search([('name', '=', '业务平台')], limit=1,
|
||||||
|
order='id asc')
|
||||||
if not partner_tag:
|
if not partner_tag:
|
||||||
partner_tag = self.env['res.partner.category'].sudo().create({'name': '平台客户'})
|
partner_tag = self.env['res.partner.category'].sudo().create({'name': '平台客户'})
|
||||||
customer = self.env['res.partner'].search([('name', '=', '业务平台')], limit=1, order='id asc')
|
customer = self.env['res.partner'].search([('name', '=', '业务平台')], limit=1, order='id asc')
|
||||||
@@ -139,9 +140,19 @@ class ResaleOrderLine(models.Model):
|
|||||||
_inherit = 'sale.order.line'
|
_inherit = 'sale.order.line'
|
||||||
|
|
||||||
model_glb_file = fields.Binary('模型的glb文件')
|
model_glb_file = fields.Binary('模型的glb文件')
|
||||||
|
# product_template_id = fields.Many2one(
|
||||||
|
# string="产品",
|
||||||
|
# comodel_name='product.template',
|
||||||
|
# compute='_compute_product_template_id',
|
||||||
|
# readonly=False,
|
||||||
|
# search='_search_product_template_id',
|
||||||
|
# # previously related='product_id.product_tmpl_id'
|
||||||
|
# # not anymore since the field must be considered editable for product configurator logic
|
||||||
|
# # without modifying the related product_id when updated.
|
||||||
|
# domain=[('sale_ok', '=', True), ('categ_type', '=', '成品')])
|
||||||
check_status = fields.Selection(related='order_id.check_status')
|
check_status = fields.Selection(related='order_id.check_status')
|
||||||
|
|
||||||
@api.onchange('product_id')
|
@api.onchange('product_template_id')
|
||||||
def _compute_model_glb_file(self):
|
def _compute_model_glb_file(self):
|
||||||
for line in self:
|
for line in self:
|
||||||
if line.product_template_id:
|
if line.product_template_id:
|
||||||
|
|||||||
@@ -117,6 +117,10 @@
|
|||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='name']" position="before">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='name']" position="before">
|
||||||
<field name="model_glb_file" widget="Viewer3D" optional="show"
|
<field name="model_glb_file" widget="Viewer3D" optional="show"
|
||||||
string="模型文件" attrs="{'readonly': [('state', 'in', ['draft'])]}"/>
|
string="模型文件" attrs="{'readonly': [('state', 'in', ['draft'])]}"/>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_template_id']" position="attributes">
|
||||||
|
<attribute name="options">{'no_create': True}</attribute>
|
||||||
|
<attribute name="context">{'is_sale_order_line': True }</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='order_line']" position="attributes">
|
<xpath expr="//field[@name='order_line']" position="attributes">
|
||||||
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
|
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
|
||||||
|
|||||||
Reference in New Issue
Block a user