Compare commits
48 Commits
master_sf_
...
release/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f005a29beb | ||
|
|
6a24776701 | ||
|
|
09d06980b5 | ||
|
|
8b492fc093 | ||
|
|
ba03790832 | ||
|
|
3148cd55b8 | ||
|
|
665ebaab9e | ||
|
|
40969adc2c | ||
|
|
95e89d8979 | ||
|
|
5b400b746e | ||
|
|
828b4b0f6b | ||
|
|
7d2c705c35 | ||
|
|
f3c2db7add | ||
|
|
0af6d7f4cd | ||
|
|
a82a54c464 | ||
|
|
d4253b21fe | ||
|
|
8356e898aa | ||
|
|
f67d08fc88 | ||
|
|
0a40409c6c | ||
|
|
927f74213e | ||
|
|
8b8570a901 | ||
|
|
ec30a07394 | ||
|
|
9110c81c73 | ||
|
|
5f4ecf8ff9 | ||
|
|
e453508f17 | ||
|
|
733b554942 | ||
|
|
eff2032762 | ||
|
|
16a00bdb10 | ||
|
|
de6014d1dd | ||
|
|
66b66a935f | ||
|
|
612906e01d | ||
|
|
21f94e5523 | ||
|
|
f8c1d75b63 | ||
|
|
fcba3b18b7 | ||
|
|
c6a509c6f4 | ||
|
|
67b48814f6 | ||
|
|
1f32aafc9b | ||
|
|
b390712308 | ||
|
|
c035ab8156 | ||
|
|
25dddb5b3b | ||
|
|
bc4dc82beb | ||
|
|
47305a2e61 | ||
|
|
9e58835082 | ||
|
|
63fa0e0c37 | ||
|
|
c6c9974326 | ||
|
|
d63c3b76bf | ||
|
|
3793d0a174 | ||
|
|
c1935e62b9 |
@@ -331,7 +331,7 @@ class ToolInventory(models.Model):
|
||||
work_material = fields.Selection([('钢', '钢'), ('铝', '铝')], string='加工材料')
|
||||
life_span = fields.Float('寿命(min)')
|
||||
|
||||
tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组')
|
||||
tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组', required=True)
|
||||
|
||||
active = fields.Boolean('已归档', default=True)
|
||||
|
||||
|
||||
@@ -555,9 +555,9 @@
|
||||
<field name="model">sf.tool.inventory</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="功能刀具清单" create="1" edit="1" delete="0" editable="bottom">
|
||||
<field name="name"/>
|
||||
<field name="name" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="functional_cutting_tool_model_id"/>
|
||||
<field name="tool_groups_id"/>
|
||||
<field name="tool_groups_id" required="1" attrs="{'readonly': [('id', '!=', False)]}"/>
|
||||
<field name="work_material"/>
|
||||
<field name="life_span"/>
|
||||
<field name="prefix" optional="hide"/>
|
||||
|
||||
@@ -14,7 +14,7 @@ _logger = logging.getLogger(__name__)
|
||||
class JdEclp(models.Model):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
senderNickName = fields.Char(string='寄件工厂简称', required=True, default='MW')
|
||||
senderNickName = fields.Char(string='寄件工厂简称', required=True, default='XT')
|
||||
|
||||
# receiverName = fields.Char(string='收件人姓名')
|
||||
# receiverMobile = fields.Char(string='收件人电话')
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//header" position="inside">
|
||||
<button string="程序下载" name="cnc_file_download" type="object" class="oe_highlight" attrs='{"invisible": ["|",
|
||||
("user_permissions","=",False),("routing_type","!=","CNC加工")]}'/>
|
||||
</xpath>
|
||||
<!-- <xpath expr="//header" position="inside">-->
|
||||
<!-- <button string="程序下载" name="cnc_file_download" type="object" class="oe_highlight" attrs='{"invisible": ["|",-->
|
||||
<!-- ("user_permissions","=",False),("routing_type","!=","CNC加工")]}'/>-->
|
||||
<!-- </xpath>-->
|
||||
<xpath expr="//page//field[@name='cnc_ids']" position="before">
|
||||
<group>
|
||||
<group>
|
||||
@@ -19,21 +19,28 @@
|
||||
<div>
|
||||
<field name="button_compensation_state" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿"
|
||||
class="btn-primary" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<span> </span>
|
||||
<button string="一键下发" name="up_all" type="object" style="text-align: right;" confirm="是否确认一键下发"
|
||||
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<span> </span>
|
||||
<button string="合并下发" id="action_up_select" name="%(sf_machine_connect.action_up_select)d"
|
||||
type="action" class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<span> </span>
|
||||
<button string="一键合并下发" name="up_merge_all" type="object" style="text-align: right;" confirm="是否确认一键合并下发"
|
||||
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
|
||||
("state","!=","progress"),("user_permissions","=",False)]}'/>
|
||||
<!-- <span> </span>-->
|
||||
<button name="button_send_program_again" type="object" string="重新下发NC程序"
|
||||
class="btn-primary"
|
||||
confirm="是否确认重新下发NC程序?"
|
||||
groups="sf_base.group_sf_order_user,sf_base.group_sf_equipment_user"
|
||||
attrs="{'invisible': ['|', '|', '|',('routing_type','!=','装夹预调'),('state','in',['done', 'cancel',
|
||||
'progress']),('processing_drawing','=',False),('is_send_program_again','=',True)]}"/>
|
||||
<!-- <button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿"-->
|
||||
<!-- class="btn-primary" attrs='{"invisible": ["|",-->
|
||||
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
|
||||
<!-- <span> </span>-->
|
||||
<!-- <button string="一键下发" name="up_all" type="object" style="text-align: right;" confirm="是否确认一键下发"-->
|
||||
<!-- class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
|
||||
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
|
||||
<!-- <span> </span>-->
|
||||
<!-- <button string="合并下发" id="action_up_select" name="%(sf_machine_connect.action_up_select)d"-->
|
||||
<!-- type="action" class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
|
||||
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
|
||||
<!-- <span> </span>-->
|
||||
<!-- <button string="一键合并下发" name="up_merge_all" type="object" style="text-align: right;" confirm="是否确认一键合并下发"-->
|
||||
<!-- class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
|
||||
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
|
||||
</div>
|
||||
</div>
|
||||
</group>
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
<tree>
|
||||
<field name="sequence_number"/>
|
||||
<field name="program_name"/>
|
||||
<field name="cnc_id" string="文件"/>
|
||||
<field name="functional_tool_type_id"/>
|
||||
<field name="cutting_tool_name"/>
|
||||
<field name="cutting_tool_no"/>
|
||||
|
||||
@@ -460,6 +460,7 @@ class Manufacturing_Connect(http.Controller):
|
||||
if f'RfidCode{i}' in ret:
|
||||
rfid_code = ret[f'RfidCode{i}']
|
||||
logging.info('RfidCode:%s' % rfid_code)
|
||||
if rfid_code is not None:
|
||||
domain = [
|
||||
('rfid_code', '=', rfid_code),
|
||||
('routing_type', '=', 'CNC加工')
|
||||
@@ -471,7 +472,8 @@ class Manufacturing_Connect(http.Controller):
|
||||
logging.info(
|
||||
'制造订单产线状态:%s' % order.production_id.production_line_state)
|
||||
order.production_id.write({'production_line_state': '已上产线'})
|
||||
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search([
|
||||
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
|
||||
[
|
||||
('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
|
||||
('production_id', '=', order.production_id.id)])
|
||||
if workpiece_delivery.status == '待下发':
|
||||
@@ -515,6 +517,7 @@ class Manufacturing_Connect(http.Controller):
|
||||
if f'RfidCode{i}' in ret:
|
||||
rfid_code = ret[f'RfidCode{i}']
|
||||
logging.info('RfidCode:%s' % rfid_code)
|
||||
if rfid_code is not None:
|
||||
domain = [
|
||||
('rfid_code', '=', rfid_code),
|
||||
('routing_type', '=', 'CNC加工')
|
||||
@@ -526,7 +529,8 @@ class Manufacturing_Connect(http.Controller):
|
||||
logging.info(
|
||||
'制造订单产线状态:%s' % order.production_id.production_line_state)
|
||||
order.production_id.write({'production_line_state': '已下产线'})
|
||||
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search([
|
||||
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
|
||||
[
|
||||
('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
|
||||
('production_id', '=', order.production_id.id)])
|
||||
delivery_Arr.append(workpiece_delivery.id)
|
||||
|
||||
@@ -292,7 +292,7 @@ class MrpProduction(models.Model):
|
||||
# 则根据设备找到工作中心;否则采用前面描述的工作中心分配机制;
|
||||
# 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心;
|
||||
|
||||
def _create_workorder3(self):
|
||||
def _create_workorder3(self, item):
|
||||
# 根据product_id对self进行分组
|
||||
grouped_product_ids = {k: list(g) for k, g in groupby(self, key=lambda x: x.product_id.id)}
|
||||
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
||||
@@ -328,19 +328,6 @@ class MrpProduction(models.Model):
|
||||
'state': 'pending',
|
||||
}]
|
||||
if production.product_id.categ_id.type == '成品':
|
||||
if production.product_id.id in product_id_to_production_names:
|
||||
# # 同一个产品多个制造订单对应一个编程单和模型库
|
||||
# # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||
if not production.programming_no:
|
||||
production_programming = self.search(
|
||||
[('product_id.id', '=', production.product_id.id), ('origin', '=', production.origin)],
|
||||
limit=1, order='id asc')
|
||||
if not production_programming.programming_no:
|
||||
production.fetchCNC(', '.join(product_id_to_production_names[production.product_id.id]))
|
||||
else:
|
||||
production.write({'programming_no': production_programming.programming_no,
|
||||
'programming_state': '编程中'})
|
||||
|
||||
# # 根据加工面板的面数及对应的工序模板生成工单
|
||||
i = 0
|
||||
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
|
||||
@@ -353,10 +340,10 @@ class MrpProduction(models.Model):
|
||||
for route in product_routing_workcenter:
|
||||
if route.is_repeat is True:
|
||||
workorders_values.append(
|
||||
self.env['mrp.workorder'].json_workorder_str(k, production, route))
|
||||
if i == processing_panel_len and route.routing_type == '解除装夹':
|
||||
workorders_values.append(
|
||||
self.env['mrp.workorder'].json_workorder_str(k, production, route))
|
||||
self.env['mrp.workorder'].json_workorder_str(k, production, route, item))
|
||||
# if i == processing_panel_len and route.routing_type == '解除装夹':
|
||||
# workorders_values.append(
|
||||
# self.env['mrp.workorder'].json_workorder_str(k, production, route))
|
||||
# 表面工艺工序
|
||||
# 获取表面工艺id
|
||||
if production.product_id.model_process_parameters_ids:
|
||||
@@ -404,6 +391,52 @@ class MrpProduction(models.Model):
|
||||
workorders_values.append(
|
||||
self.env['mrp.workorder'].json_workorder_str('', production, route))
|
||||
production.workorder_ids = workorders_values
|
||||
# for production_item in productions:
|
||||
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_item)
|
||||
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_item)
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production_item)
|
||||
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_item)
|
||||
if is_pick is False and m == 0:
|
||||
if len(sorted_workorders) == 1:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item)
|
||||
else:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production_item)
|
||||
for workorder in production.workorder_ids:
|
||||
workorder.duration_expected = workorder._get_duration_expected()
|
||||
|
||||
@@ -498,15 +531,23 @@ class MrpProduction(models.Model):
|
||||
def _reset_work_order_sequence(self):
|
||||
for rec in self:
|
||||
sequence_list = {}
|
||||
# 产品模型类型
|
||||
model_type_id = rec.product_id.product_model_type_id
|
||||
# 产品加工面板
|
||||
model_processing_panel = rec.product_id.model_processing_panel
|
||||
if model_type_id:
|
||||
if model_processing_panel:
|
||||
tmpl_num = 1
|
||||
panel_list = model_processing_panel.split(',')
|
||||
for panel in panel_list:
|
||||
panel_sequence_list = {}
|
||||
# 成品工序
|
||||
product_routing_tmpl_ids = model_type_id.product_routing_tmpl_ids
|
||||
if product_routing_tmpl_ids:
|
||||
for tmpl_id in product_routing_tmpl_ids:
|
||||
sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
|
||||
panel_sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
|
||||
tmpl_num += 1
|
||||
sequence_list.update({panel: panel_sequence_list})
|
||||
# 表面工艺工序
|
||||
# 模型类型的表面工艺工序模版
|
||||
surface_tmpl_ids = model_type_id.surface_technics_routing_tmpl_ids
|
||||
@@ -532,12 +573,21 @@ class MrpProduction(models.Model):
|
||||
for tmpl_id in embryo_routing_tmpl_ids:
|
||||
sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
|
||||
tmpl_num += 1
|
||||
else:
|
||||
raise ValidationError('该产品【加工面板】为空!')
|
||||
|
||||
else:
|
||||
raise ValidationError('该产品没有选择【模版类型】!')
|
||||
|
||||
for work in rec.workorder_ids:
|
||||
if sequence_list.get(work.name):
|
||||
work.sequence = sequence_list[work.name]
|
||||
elif sequence_list.get(work.processing_panel):
|
||||
processing_panel = sequence_list.get(work.processing_panel)
|
||||
if processing_panel.get(work.name):
|
||||
work.sequence = processing_panel[work.name]
|
||||
else:
|
||||
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
|
||||
else:
|
||||
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
|
||||
# if work.name == '获取CNC加工程序':
|
||||
@@ -546,8 +596,8 @@ class MrpProduction(models.Model):
|
||||
# work.button_finish()
|
||||
|
||||
# 创建工单并进行排序
|
||||
def _create_workorder(self):
|
||||
self._create_workorder3()
|
||||
def _create_workorder(self, item):
|
||||
self._create_workorder3(item)
|
||||
self._reset_work_order_sequence()
|
||||
return True
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import re
|
||||
|
||||
import json
|
||||
import logging
|
||||
import base64
|
||||
import urllib.parse
|
||||
@@ -207,6 +207,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
[("programming", "编程"), ("clamping", "返工"), ("cutter", "刀具"), ("operate computer", "操机"),
|
||||
("technology", "工艺"), ("customer redrawing", "客户改图"), ("other", "其他"), ], string="原因", tracking=True)
|
||||
detailed_reason = fields.Text('详细原因')
|
||||
is_send_program_again = fields.Boolean(string='是否重新下发NC程序', default=False)
|
||||
|
||||
@api.onchange('rfid_code')
|
||||
def _onchange(self):
|
||||
@@ -473,7 +474,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
raise UserError(_("该工单暂未完成,无法进行工件配送"))
|
||||
|
||||
# 拼接工单对象属性值
|
||||
def json_workorder_str(self, k, production, route):
|
||||
def json_workorder_str(self, k, production, route, item):
|
||||
# 计算预计时长duration_expected
|
||||
if route.routing_type == '切割':
|
||||
duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
|
||||
@@ -506,7 +507,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
'processing_panel': k,
|
||||
'quality_point_ids': route.route_workcenter_id.quality_point_ids,
|
||||
'routing_type': route.routing_type,
|
||||
'work_state': '待发起',
|
||||
# 'work_state': '待发起',
|
||||
'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids,
|
||||
route.routing_type,
|
||||
production.product_id),
|
||||
@@ -515,6 +516,10 @@ class ResMrpWorkOrder(models.Model):
|
||||
'date_planned_finished': datetime.now() + timedelta(days=1),
|
||||
'duration_expected': duration_expected,
|
||||
'duration': 0,
|
||||
'cnc_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cnc.processing']._json_cnc_processing(
|
||||
k, item),
|
||||
'cmm_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cmm.program']._json_cmm_program(k,
|
||||
item),
|
||||
'workpiece_delivery_ids': False if not route.routing_type == '装夹预调' else self._json_workpiece_delivery_list(
|
||||
production)
|
||||
}]
|
||||
@@ -1073,6 +1078,33 @@ class ResMrpWorkOrder(models.Model):
|
||||
workorder.detection_report = base64.b64encode(open(report_file_path, 'rb').read())
|
||||
return True
|
||||
|
||||
# 重新下发nc程序
|
||||
def button_send_program_again(self):
|
||||
try:
|
||||
res = {'programming_no': self.production_id.programming_no}
|
||||
configsettings = self.env['res.config.settings'].get_values()
|
||||
config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key'])
|
||||
url = '/api/intelligent_programming/reset_state_again'
|
||||
config_url = configsettings['sf_url'] + url
|
||||
r = requests.post(config_url, json=res, data=None, headers=config_header)
|
||||
r = r.json()
|
||||
result = json.loads(r['result'])
|
||||
if result['status'] == 1:
|
||||
productions = self.env['mrp.production'].search(
|
||||
[('programming_no', '=', self.production_id.programming_no), ('programming_state', '=', '已编程')])
|
||||
if productions:
|
||||
workorder = productions.workorder_ids.filtered(
|
||||
lambda ap: ap.routing_type in ['装夹预调', 'CNC加工'] and ap.state not in ['done', 'cancel',
|
||||
'progress'])
|
||||
if workorder:
|
||||
workorder.write({'is_send_program_again': True})
|
||||
productions.write({'work_state': '编程中', 'programming_state': '编程中'})
|
||||
else:
|
||||
raise UserError(result['message'])
|
||||
except Exception as e:
|
||||
logging.info('button_send_program_again error:%s' % e)
|
||||
raise UserError("重新下发nc程序失败,请联系管理员")
|
||||
|
||||
|
||||
class CNCprocessing(models.Model):
|
||||
_name = 'sf.cnc.processing'
|
||||
@@ -1098,6 +1130,7 @@ class CNCprocessing(models.Model):
|
||||
production_id = fields.Many2one('mrp.production', string="制造订单")
|
||||
button_state = fields.Boolean(string='是否已经下发')
|
||||
program_path = fields.Char('程序文件路径')
|
||||
program_create_date = fields.Datetime('程序创建日期')
|
||||
|
||||
# mrs下发编程单创建CNC加工
|
||||
def cnc_processing_create(self, cnc_workorder, ret, program_path, program_path_tmp):
|
||||
@@ -1130,24 +1163,27 @@ class CNCprocessing(models.Model):
|
||||
cnc_workorder.write({'programming_state': '已编程', 'work_state': '已编程'})
|
||||
return cnc_processing
|
||||
|
||||
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'],
|
||||
'program_path': obj['program_path'],
|
||||
'cnc_id': obj['cnc_id'].id,
|
||||
'remark': obj['remark']
|
||||
})
|
||||
return cnc_processing_str
|
||||
def _json_cnc_processing(self, panel, ret):
|
||||
cnc_processing = []
|
||||
for item in ret['programming_list']:
|
||||
if item['processing_panel'] == panel and item['ftp_path'].find('.dmi') == -1:
|
||||
cnc_processing.append((0, 0, {
|
||||
'sequence_number': item['sequence_number'],
|
||||
'program_name': item['program_name'],
|
||||
'cutting_tool_name': item['cutting_tool_name'],
|
||||
'cutting_tool_no': item['cutting_tool_no'],
|
||||
'processing_type': item['processing_type'],
|
||||
'margin_x_y': item['margin_x_y'],
|
||||
'margin_z': item['margin_z'],
|
||||
'depth_of_processing_z': item['depth_of_processing_z'],
|
||||
'cutting_tool_extension_length': item['cutting_tool_extension_length'],
|
||||
'cutting_tool_handle_type': item['cutting_tool_handle_type'],
|
||||
'estimated_processing_time': item['estimated_processing_time'],
|
||||
'program_path': item['ftp_path'],
|
||||
'program_create_date': datetime.strptime(item['program_create_date'], '%Y-%m-%d %H:%M:%S'),
|
||||
'remark': item['remark']
|
||||
}))
|
||||
return cnc_processing
|
||||
|
||||
# 根据程序名和加工面匹配到ftp里对应的Nc程序名,可优化为根据cnc_processing.program_path进行匹配
|
||||
def get_cnc_processing_file(self, serverdir, cnc_processing, program_path):
|
||||
@@ -1177,14 +1213,14 @@ class CNCprocessing(models.Model):
|
||||
})
|
||||
return attachment
|
||||
|
||||
# 将FTP的nc文件下载到临时目录
|
||||
# 将FTP的多面的程序单文件下载到临时目录
|
||||
def download_file_tmp(self, production_no, 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 = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']), ftp_resconfig['ftp_user'],
|
||||
ftp_resconfig['ftp_password'])
|
||||
download_state = ftp.download_file_tree(remotepath, serverdir)
|
||||
download_state = ftp.download_program_file(remotepath, serverdir)
|
||||
logging.info('download_state:%s' % download_state)
|
||||
return download_state
|
||||
|
||||
@@ -1589,80 +1625,22 @@ class CMMprogram(models.Model):
|
||||
_name = 'sf.cmm.program'
|
||||
_description = "CMM程序"
|
||||
|
||||
cmm_id = fields.Many2one('ir.attachment')
|
||||
sequence_number = fields.Integer('序号')
|
||||
program_name = fields.Char('程序名')
|
||||
cutting_tool_name = fields.Char('刀具名称')
|
||||
cutting_tool_no = fields.Char('刀号')
|
||||
processing_type = fields.Char('加工类型')
|
||||
margin_x_y = fields.Char('余量_X/Y')
|
||||
margin_z = fields.Char('余量_Z')
|
||||
depth_of_processing_z = fields.Char('加工深度(Z)')
|
||||
cutting_tool_extension_length = fields.Char('刀具伸出长度')
|
||||
cutting_tool_handle_type = fields.Char('刀柄型号')
|
||||
estimated_processing_time = fields.Char('预计加工时间')
|
||||
remark = fields.Text('备注')
|
||||
workorder_id = fields.Many2one('mrp.workorder', string="工单")
|
||||
production_id = fields.Many2one('mrp.production', string="制造订单")
|
||||
program_path = fields.Char('程序文件路径')
|
||||
program_create_date = fields.Datetime('程序创建日期')
|
||||
|
||||
def cmm_program_create(self, ret, program_path, program_path_tmp):
|
||||
cmm_program = None
|
||||
for obj in ret['programming_list']:
|
||||
workorder = self.env['mrp.workorder'].search(
|
||||
[('production_id.name', '=', ret['production_order_no'].split(',')[0]),
|
||||
('processing_panel', '=', obj['processing_panel']),
|
||||
('routing_type', '=', 'CNC加工')])
|
||||
if obj['program_name'] in program_path:
|
||||
logging.info('obj:%s' % obj['program_name'])
|
||||
cmm_program = self.sudo().create({
|
||||
'workorder_id': workorder.id,
|
||||
'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'],
|
||||
'program_path': program_path.replace('/tmp', '')
|
||||
})
|
||||
cmm_program.get_cmm_program_file(program_path_tmp, cmm_program, program_path)
|
||||
def _json_cmm_program(self, panel, ret):
|
||||
cmm_program = []
|
||||
for item in ret['programming_list']:
|
||||
if item['processing_panel'] == panel and item['ftp_path'].find('.dmi') != -1:
|
||||
cmm_program.append((0, 0, {
|
||||
'sequence_number': 1,
|
||||
'program_name': item['program_name'],
|
||||
'program_path': item['ftp_path'],
|
||||
'program_create_date': datetime.strptime(item['program_create_date'], '%Y-%m-%d %H:%M:%S'),
|
||||
}))
|
||||
return cmm_program
|
||||
|
||||
# 根据程序名和加工面匹配到ftp里对应的cmm程序名
|
||||
def get_cmm_program_file(self, serverdir, cmm_program, program_path):
|
||||
logging.info('cmm-serverdir:%s' % serverdir)
|
||||
for root, dirs, files in os.walk(serverdir):
|
||||
for f in files:
|
||||
if f in program_path:
|
||||
cmm_program_file_path = os.path.join(serverdir, root, f)
|
||||
self.write_file_cmm(cmm_program_file_path, cmm_program)
|
||||
|
||||
# 创建附件(nc文件)
|
||||
def attachment_create(self, name, data):
|
||||
attachment = self.env['ir.attachment'].create({
|
||||
'datas': base64.b64encode(data),
|
||||
'type': 'binary',
|
||||
'public': True,
|
||||
'description': '程序文件',
|
||||
'name': name
|
||||
})
|
||||
return attachment
|
||||
|
||||
# 将cmm文件存到attach的datas里
|
||||
def write_file_cmm(self, cmm_file_path, cnc):
|
||||
cmm_file_name = cmm_file_path.split('/')
|
||||
logging.info('cmm_file_name:%s' % cmm_file_name[-1])
|
||||
if os.path.exists(cmm_file_path):
|
||||
with open(cmm_file_path, 'rb') as file:
|
||||
data_bytes = file.read()
|
||||
attachment = self.attachment_create(cnc.program_name + cmm_file_name[-1], data_bytes)
|
||||
cnc.write({'cmm_id': attachment.id})
|
||||
file.close()
|
||||
else:
|
||||
return False
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import base64
|
||||
import qrcode
|
||||
from itertools import groupby
|
||||
from collections import defaultdict, namedtuple
|
||||
import logging
|
||||
import io
|
||||
@@ -205,61 +206,37 @@ class StockRule(models.Model):
|
||||
|
||||
# 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()
|
||||
'''
|
||||
创建工单
|
||||
'''
|
||||
# productions._create_workorder()
|
||||
#
|
||||
grouped_product_ids = {k: list(g) for k, g in groupby(productions, key=lambda x: x.product_id.id)}
|
||||
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
||||
product_id_to_production_names = {}
|
||||
# 对于每个product_id,获取其所有生产订单的名称
|
||||
for product_id, productions in grouped_product_ids.items():
|
||||
# 为同一个product_id创建一个生产订单名称列表
|
||||
product_id_to_production_names[product_id] = [production.name for production in productions]
|
||||
for production_item in productions:
|
||||
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_item.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
|
||||
if production_item.product_id.id in product_id_to_production_names:
|
||||
# # 同一个产品多个制造订单对应一个编程单和模型库
|
||||
# # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||
if not production_item.programming_no:
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('product_id.id', '=', production_item.product_id.id),
|
||||
('origin', '=', production_item.origin)],
|
||||
limit=1, order='id asc')
|
||||
if not production_programming.programming_no:
|
||||
production_item.fetchCNC(
|
||||
', '.join(product_id_to_production_names[production_item.product_id.id]))
|
||||
else:
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production_item)
|
||||
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_item)
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production_item)
|
||||
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_item)
|
||||
if is_pick is False and m == 0:
|
||||
if len(sorted_workorders) == 1:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item)
|
||||
else:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production_item)
|
||||
production_item.write({'programming_no': production_programming.programming_no,
|
||||
'programming_state': '编程中'})
|
||||
|
||||
for production in productions:
|
||||
'''
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sf_cnc_processing_group_sf_mrp_user,sf_cnc_processing,model_sf_cnc_processing,sf_base.group_sf_mrp_user,1,0,0,0
|
||||
access_sf_cnc_processing_manager,sf_cnc_processing,model_sf_cnc_processing,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||
access_sf_cmm_program_group_sf_mrp_user_group_sf_mrp_user,sf_cmm_program_group_sf_mrp_user,model_sf_cmm_program,sf_base.group_sf_mrp_user,1,0,0,0
|
||||
access_sf_cmm_program_group_sf_mrp_user,sf_cmm_program_group_sf_mrp_user,model_sf_cmm_program,sf_base.group_sf_mrp_user,1,0,0,0
|
||||
access_sf_cmm_program_group_sf_mrp_manager,sf_cmm_program_group_sf_mrp_manager,model_sf_cmm_program,sf_base.group_sf_mrp_manager,1,0,0,0
|
||||
access_sf_cmm_program_admin,sf_cmm_program_admin,model_sf_cmm_program,base.group_system,1,1,1,1
|
||||
access_sf_model_type_group_sf_mrp_user,sf_model_type,model_sf_model_type,sf_base.group_sf_mrp_user,1,0,0,0
|
||||
access_sf_model_type_admin,sf_model_type_admin,model_sf_model_type,base.group_system,1,1,1,0
|
||||
access_sf_model_type_manager,sf_model_type,model_sf_model_type,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||
|
||||
|
@@ -62,16 +62,17 @@
|
||||
<field name="inherit_id" ref="mrp.mrp_production_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='state']" position="attributes">
|
||||
<!-- <attribute name="statusbar_visible">draft,confirmed,progress,pending_processing,completed,done -->
|
||||
<!-- </attribute> -->
|
||||
<attribute name="statusbar_visible">progress,pending_cam,pending_processing,pending_era_cam,completed,done
|
||||
<!-- <attribute name="statusbar_visible">draft,confirmed,progress,pending_processing,completed,done -->
|
||||
<!-- </attribute> -->
|
||||
<attribute name="statusbar_visible">
|
||||
progress,pending_cam,pending_processing,pending_era_cam,completed,done
|
||||
</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//sheet//group//group[2]//label" position="before">
|
||||
<!-- <field name="process_state"/> -->
|
||||
<!-- <field name="process_state"/> -->
|
||||
<field name="state"/>
|
||||
<!-- <field name="process_state"/> -->
|
||||
<!-- <field name="process_state"/> -->
|
||||
|
||||
</xpath>
|
||||
<xpath expr="//sheet//group//group//div[3]" position="after">
|
||||
@@ -281,7 +282,7 @@
|
||||
<field name="routing_type" invisible="True"/>
|
||||
<button name="button_start" type="object" string="开始" class="btn-success"
|
||||
attrs="{'invisible': ['|', '|', '|','|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=', False), ('routing_type', '=', 'CNC加工')]}"
|
||||
groups="sf_base.group_sf_mrp_user"/>
|
||||
groups="sf_base.group_sf_mrp_user" confirm="是否确认开始?"/>
|
||||
</xpath>
|
||||
<xpath expr="//tree//button[@name='button_pending']" position="replace">
|
||||
<button name="button_pending" type="object" string="Pause" class="btn-warning"
|
||||
@@ -291,7 +292,8 @@
|
||||
<xpath expr="//tree//button[@name='button_finish']" position="replace">
|
||||
<button name="button_finish" type="object" string="Done" class="btn-success"
|
||||
attrs="{'invisible': ['|', '|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"
|
||||
groups="sf_base.group_sf_mrp_user"/>
|
||||
groups="sf_base.group_sf_mrp_user"
|
||||
confirm="是否确认完成?"/>
|
||||
</xpath>
|
||||
<xpath expr="//tree//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="replace">
|
||||
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="Block"
|
||||
@@ -309,10 +311,10 @@
|
||||
<button name="action_open_wizard" type="object" icon="fa-external-link" class="oe_edit_only"
|
||||
title="Open Work Order"
|
||||
context="{'default_workcenter_id': workcenter_id}" groups="sf_base.group_sf_mrp_user"/>
|
||||
<!-- ======= -->
|
||||
<!-- <button name="button_start" type="object" string="开始" class="btn-success" -->
|
||||
<!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=', False)]}" -->
|
||||
<!-- groups="sf_base.group_sf_mrp_user"/> -->
|
||||
<!-- ======= -->
|
||||
<!-- <button name="button_start" type="object" string="开始" class="btn-success" -->
|
||||
<!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=', False)]}" -->
|
||||
<!-- groups="sf_base.group_sf_mrp_user"/> -->
|
||||
</xpath>
|
||||
<xpath expr="//tree//button[@name='button_pending']" position="replace">
|
||||
<button name="button_pending" type="object" string="暂停" class="btn-warning"
|
||||
@@ -322,7 +324,7 @@
|
||||
<xpath expr="//tree//button[@name='button_finish']" position="replace">
|
||||
<button name="button_finish" type="object" string="完成" class="btn-success"
|
||||
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False), ('routing_type', '=', 'CNC加工')]}"
|
||||
groups="sf_base.group_sf_mrp_user"/>
|
||||
groups="sf_base.group_sf_mrp_user" confirm="是否确认完成?"/>
|
||||
</xpath>
|
||||
<xpath expr="//tree//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="replace">
|
||||
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="阻塞"
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<field name="name" decoration-success="is_subcontract" decoration-bf="is_subcontract"/>
|
||||
</field>
|
||||
<field name="name" position="before">
|
||||
<field name="sequence"/>
|
||||
<field name="sequence" optional="hide"/>
|
||||
<field name='user_permissions' invisible="1"/>
|
||||
</field>
|
||||
<field name="name" position="after">
|
||||
@@ -21,6 +21,12 @@
|
||||
<field name="work_state" optional="hide"/>
|
||||
<field name="product_tmpl_name" invisible="1"/>
|
||||
</field>
|
||||
<field name="duration" position="replace">
|
||||
<field name="duration" optional="hide"/>
|
||||
</field>
|
||||
<field name="workcenter_id" position="replace">
|
||||
<field name="workcenter_id" optional="hide"/>
|
||||
</field>
|
||||
<field name="product_id" position="after">
|
||||
<field name="equipment_id" optional="hide"/>
|
||||
</field>
|
||||
@@ -31,7 +37,7 @@
|
||||
<field name="date_planned_start" string="计划开始日期" optional="show"/>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='date_planned_finished']" position="replace">
|
||||
<field name="date_planned_finished" string="计划结束日期" optional="show"/>
|
||||
<field name="date_planned_finished" string="计划结束日期" optional="hide"/>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='button_start']" position="attributes">
|
||||
<attribute name="attrs">{'invisible': ['|', '|', '|','|','|', ('production_state','in', ('draft',
|
||||
@@ -118,6 +124,7 @@
|
||||
<field name='user_permissions' invisible="1"/>
|
||||
<field name='name' invisible="1"/>
|
||||
<field name='is_delivery' invisible="1"/>
|
||||
<field name='is_send_program_again' invisible="1"/>
|
||||
<!-- 工单form页面的开始停工按钮等 -->
|
||||
<!-- <button name="button_start" type="object" string="开始" class="btn-success" -->
|
||||
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'not in', ('pending_processing', 'pending_cam', 'pending_era_cam')), ('state','!=','ready'), ('routing_type', 'not in', ('装夹预调', 'CNC加工', '解除装夹'))]}" -->
|
||||
@@ -152,7 +159,12 @@
|
||||
<!-- groups="sf_base.group_sf_mrp_user" -->
|
||||
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'),('state','=','done')]}"/> -->
|
||||
<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),('state','!=','done')]}"/>
|
||||
<button name="button_send_program_again" type="object" string="重新下发NC程序" class="btn-primary"
|
||||
confirm="是否确认重新下发NC程序?"
|
||||
groups="sf_base.group_sf_order_user,sf_base.group_sf_equipment_user"
|
||||
attrs="{'invisible': ['|', '|', '|',('routing_type','!=','装夹预调'),('state','in',['done', 'cancel',
|
||||
'progress']),('cnc_worksheet','=',False),('is_send_program_again','=',True)]}"/>
|
||||
</xpath>
|
||||
<xpath expr="//page[1]" position="before">
|
||||
<page string="开料要求" attrs='{"invisible": [("routing_type","!=","切割")]}'>
|
||||
@@ -204,17 +216,17 @@
|
||||
<field name="processing_panel" readonly="1"
|
||||
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
|
||||
<field name="equipment_id"
|
||||
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
|
||||
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割","装夹预调"))]}'/>
|
||||
<field name="production_line_id"
|
||||
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
|
||||
<field name="production_line_state"
|
||||
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
|
||||
<field name="functional_fixture_id"
|
||||
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
|
||||
<field name="functional_fixture_code" force_save="1"
|
||||
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
|
||||
<field name="functional_fixture_type_id"
|
||||
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
|
||||
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割","装夹预调"))]}'/>
|
||||
<!-- <field name="functional_fixture_id" -->
|
||||
<!-- attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/> -->
|
||||
<!-- <field name="functional_fixture_code" force_save="1" -->
|
||||
<!-- attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/> -->
|
||||
<!-- <field name="functional_fixture_type_id" -->
|
||||
<!-- attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/> -->
|
||||
<field name="rfid_code" force_save="1" readonly="1" cache="True"
|
||||
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
|
||||
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
|
||||
@@ -282,20 +294,26 @@
|
||||
<!-- </group>-->
|
||||
<group string="托盘">
|
||||
<field name="tray_serial_number" readonly="1" string="序列号"/>
|
||||
</group>
|
||||
</group>
|
||||
<group>
|
||||
<group>
|
||||
<field name="tray_product_id" readonly="1" string="名称"/>
|
||||
<field name="tray_brand_id" readonly="1" string="品牌"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="tray_type_id" readonly="1" string="类型"/>
|
||||
<field name="tray_model_id" readonly="1" string="型号"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="加工图纸">
|
||||
<!-- 隐藏加工图纸字段名 -->
|
||||
<field name="processing_drawing" widget="pdf_viewer" string="" readonly="1"/>
|
||||
</group>
|
||||
<group string="预调程序信息">
|
||||
<field name="preset_program_information" colspan="2" nolabel="1"
|
||||
placeholder="如有预调程序信息请在此处输入....."/>
|
||||
</group>
|
||||
<group string="加工图纸">
|
||||
<!-- 隐藏加工图纸字段名 -->
|
||||
<field name="processing_drawing" widget="pdf_viewer" string=""/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="前置三元检测定位参数" attrs='{"invisible": [("routing_type","!=","装夹预调")]}'>
|
||||
|
||||
@@ -478,13 +496,13 @@
|
||||
<page string="后置三元检测" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
|
||||
<group>
|
||||
<field name="test_results" attrs='{"invisible":[("results","!=",False)]}'/>
|
||||
<!-- <field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>-->
|
||||
<!-- <field name="is_fetchcnc"-->
|
||||
<!-- attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>-->
|
||||
<!-- <field name="reason"-->
|
||||
<!-- attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/>-->
|
||||
<!-- <field name="detailed_reason" attrs='{"invisible":[("test_results","=","合格")]}'/>-->
|
||||
<!-- <field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>-->
|
||||
<!-- <field name="is_remanufacture" attrs='{"invisible":[("test_results","!=","报废")]}'/>-->
|
||||
<!-- <field name="is_fetchcnc"-->
|
||||
<!-- attrs='{"invisible":["|",("test_results","=","合格"),("is_remanufacture","=",False)]}'/>-->
|
||||
<!-- <field name="reason"-->
|
||||
<!-- attrs='{"required":[("test_results","!=","合格")],"invisible":[("test_results","=","合格")]}'/>-->
|
||||
<!-- <field name="detailed_reason" attrs='{"invisible":[("test_results","=","合格")]}'/>-->
|
||||
<!-- <field name="results" readonly="1" attrs='{"invisible":[("results","!=","合格")]}'/>-->
|
||||
<field name="detection_report" attrs='{"invisible":[("results","!=",False)]}'
|
||||
widget="pdf_viewer"/>
|
||||
</group>
|
||||
@@ -497,11 +515,11 @@
|
||||
</xpath>
|
||||
<xpath expr="//page[1]" position="before">
|
||||
<page string="CNC程序" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
|
||||
<field name="cnc_ids" widget="one2many" string="工作程序" default_order="sequence_number,id">
|
||||
<tree decoration-success="button_state" decoration-bf="button_state">
|
||||
<field name="cnc_ids" widget="one2many" string="工作程序" default_order="sequence_number,id"
|
||||
readonly="1">
|
||||
<tree>
|
||||
<field name="sequence_number"/>
|
||||
<field name="program_name"/>
|
||||
<field name="cnc_id" string="文件"/>
|
||||
<field name="cutting_tool_name"/>
|
||||
<field name="cutting_tool_no"/>
|
||||
<field name="processing_type"/>
|
||||
@@ -511,8 +529,10 @@
|
||||
<field name="cutting_tool_extension_length"/>
|
||||
<field name="cutting_tool_handle_type"/>
|
||||
<field name="estimated_processing_time"/>
|
||||
<field name="program_path"/>
|
||||
<field name="program_create_date"/>
|
||||
<field name="remark"/>
|
||||
<field name="button_state" invisible="1"/>
|
||||
<!-- <field name="button_state" invisible="1"/>-->
|
||||
</tree>
|
||||
</field>
|
||||
<group>
|
||||
@@ -520,20 +540,12 @@
|
||||
</group>
|
||||
</page>
|
||||
<page string="CMM程序" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
|
||||
<field name="cmm_ids" widget="one2many" string="CMM程序">
|
||||
<field name="cmm_ids" widget="one2many" string="CMM程序" readonly="1">
|
||||
<tree>
|
||||
<field name="sequence_number"/>
|
||||
<field name="program_name"/>
|
||||
<field name="cmm_id" string="文件"/>
|
||||
<field name="cutting_tool_name"/>
|
||||
<field name="cutting_tool_no"/>
|
||||
<field name="processing_type"/>
|
||||
<field name="margin_x_y"/>
|
||||
<field name="margin_z"/>
|
||||
<field name="depth_of_processing_z"/>
|
||||
<field name="cutting_tool_extension_length"/>
|
||||
<field name="cutting_tool_handle_type"/>
|
||||
<field name="estimated_processing_time"/>
|
||||
<field name="program_path"/>
|
||||
<field name="program_create_date"/>
|
||||
<field name="remark"/>
|
||||
</tree>
|
||||
</field>
|
||||
@@ -563,9 +575,9 @@
|
||||
</div>
|
||||
</xpath>
|
||||
<xpath expr="//form//sheet//group//group//div[3]" position="after">
|
||||
<field name="is_ok"/>
|
||||
<field name="processing_user_id"/>
|
||||
<field name="inspection_user_id"/>
|
||||
<field name="is_ok" attrs='{"invisible": [("routing_type","=","装夹预调")]}'/>
|
||||
<field name="processing_user_id" attrs='{"invisible": [("routing_type","=","装夹预调")]}'/>
|
||||
<field name="inspection_user_id" attrs='{"invisible": [("routing_type","=","装夹预调")]}'/>
|
||||
<field name="save_name" widget="CopyClipboardChar"
|
||||
attrs="{'invisible':[('routing_type','!=','装夹预调')]}"/>
|
||||
<label for="material_length" string="物料尺寸"/>
|
||||
@@ -580,10 +592,24 @@
|
||||
<field name="material_height" class="o_address_zip"/>
|
||||
</div>
|
||||
<field name="part_number" string="成品的零件图号"/>
|
||||
<field name="rfid_code" force_save="1" readonly="1" cache="True"
|
||||
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
|
||||
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="workcenter_form_workorder_search" model="ir.ui.view">
|
||||
<field name="name">custom.workorder.search</field>
|
||||
<field name="model">mrp.workorder</field>
|
||||
<field name="inherit_id" ref="mrp.view_mrp_production_work_order_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="product_id" position="after">
|
||||
<field name="part_number" string="成品零件图号"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_workorder_action_schedule" model="ir.actions.act_window">
|
||||
<field name="name">工单</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
|
||||
@@ -24,37 +24,18 @@ class Sf_Mrs_Connect(http.Controller):
|
||||
ret = json.loads(datas)
|
||||
ret = json.loads(ret['result'])
|
||||
logging.info('下发编程单:%s' % ret)
|
||||
is_delete_file = False
|
||||
# 查询状态为进行中且类型为获取CNC加工程序的工单
|
||||
cnc_production = request.env['mrp.production'].with_user(
|
||||
request.env.ref("base.user_admin")).search([('name', '=', ret['production_order_no'].split(',')[0])])
|
||||
cnc_program = request.env['mrp.production'].with_user(
|
||||
productions = request.env['mrp.production'].with_user(
|
||||
request.env.ref("base.user_admin")).search(
|
||||
[('programming_no', '=', cnc_production.programming_no), ('id', '!=', cnc_production.id)])
|
||||
if cnc_production.workorder_ids.filtered(lambda a: a.routing_type == 'CNC加工').cnc_ids:
|
||||
is_delete_file = True
|
||||
cnc_production.workorder_ids.filtered(
|
||||
lambda a1: a1.routing_type == 'CNC加工').cnc_ids.sudo().unlink()
|
||||
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(cnc_production)
|
||||
if cnc_program.workorder_ids.filtered(lambda c: c.routing_type == 'CNC加工').cnc_ids:
|
||||
cnc_program.workorder_ids.filtered(
|
||||
lambda c1: c1.routing_type == 'CNC加工').cnc_ids.sudo().unlink()
|
||||
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(cnc_program)
|
||||
# cnc_program = request.env['mrp.production'].with_user(
|
||||
# request.env.ref("base.user_admin")).search([('programming_no', '=', cnc_production.programming_no)])
|
||||
logging.info('制造订单号:%s' % cnc_production.name)
|
||||
if cnc_production:
|
||||
# if ret['glb_file']:
|
||||
# cnc_production.glb_file = base64.b64encode(ret['glb_file'])
|
||||
[('programming_no', '=', ret['programming_no'])])
|
||||
if productions:
|
||||
# 拉取所有加工面的程序文件
|
||||
if is_delete_file is True:
|
||||
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', 'R')
|
||||
for r in ret['processing_panel'].split(','):
|
||||
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r)
|
||||
files_r = os.listdir(program_path_tmp_r)
|
||||
if files_r:
|
||||
for file_name in files_r:
|
||||
file_path = os.path.join(program_path_tmp_r, file_name)
|
||||
os.remove(file_path)
|
||||
for r in ret['processing_panel']:
|
||||
download_state = request.env['sf.cnc.processing'].with_user(
|
||||
request.env.ref("base.user_admin")).download_file_tmp(
|
||||
ret['folder_name'], r)
|
||||
@@ -62,40 +43,48 @@ class Sf_Mrs_Connect(http.Controller):
|
||||
res['status'] = -2
|
||||
res['message'] = '制造订单号为%s的CNC程序文件从FTP拉取失败' % (cnc_production.name)
|
||||
return json.JSONEncoder().encode(res)
|
||||
logging.info('创建cnc工单')
|
||||
program_path_tmp = os.path.join('/tmp', ret['folder_name'], 'return', r)
|
||||
# program_path_tmp = "C://Users//43484//Desktop//机企猫工作文档//其他//model_analysis"
|
||||
files = os.listdir(program_path_tmp)
|
||||
cnc_processing_arr = []
|
||||
for f in files:
|
||||
program_path = os.path.join(program_path_tmp, f)
|
||||
logging.info('cnc程序路径 :%s' % program_path)
|
||||
if f.endswith(".doc"):
|
||||
# 插入cmm程序数据
|
||||
cmm_program = request.env['sf.cmm.program'].with_user(
|
||||
request.env.ref("base.user_admin")).cmm_program_create(ret, program_path, program_path_tmp)
|
||||
cnc_processing = request.env['sf.cnc.processing'].with_user(
|
||||
request.env.ref("base.user_admin")).cnc_processing_create(cnc_production, ret, program_path,
|
||||
program_path_tmp)
|
||||
logging.info('cnc_processing111:%s' % cnc_processing)
|
||||
if cnc_processing:
|
||||
cnc_processing_arr.append(cnc_processing._json_cnc_processing(cnc_processing))
|
||||
if (cnc_program and cnc_processing_arr) or (not cnc_program and cnc_processing_arr):
|
||||
cnc_production.workorder_ids.filtered(lambda g: g.routing_type == '装夹预调').write(
|
||||
{'processing_drawing': cnc_production.workorder_ids.filtered(
|
||||
lambda g1: g1.routing_type == 'CNC加工').cnc_worksheet})
|
||||
if cnc_program and cnc_processing_arr:
|
||||
cnc_program.write({'programming_state': '已编程', 'work_state': '已编程'})
|
||||
cnc_program.workorder_ids.filtered(lambda d: d.routing_type == '装夹预调').write(
|
||||
{'processing_drawing': cnc_production.workorder_ids.filtered(
|
||||
lambda d1: d1.routing_type == 'CNC加工').cnc_worksheet})
|
||||
cnc_program.workorder_ids.filtered(lambda b: b.routing_type == 'CNC加工').write(
|
||||
{'cnc_ids': cnc_processing_arr, 'cnc_worksheet': cnc_production.workorder_ids.filtered(
|
||||
lambda b1: b1.routing_type == 'CNC加工').cnc_worksheet})
|
||||
cnc_program |= cnc_production
|
||||
if not cnc_program and cnc_processing_arr:
|
||||
cnc_program = cnc_production
|
||||
cnc_program_ids = [item.id for item in cnc_program]
|
||||
for production in productions:
|
||||
if not production.workorder_ids:
|
||||
production.product_id.model_processing_panel = ret['processing_panel']
|
||||
production._create_workorder(ret)
|
||||
else:
|
||||
for panel in ret['processing_panel'].split(','):
|
||||
# 查询状态为进行中且工序类型为CNC加工的工单
|
||||
cnc_workorder = production.workorder_ids.filtered(
|
||||
lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done',
|
||||
'cancel'] and ac.processing_panel == panel)
|
||||
if cnc_workorder:
|
||||
if cnc_workorder.cnc_ids:
|
||||
cnc_workorder.cmm_ids.sudo().unlink()
|
||||
cnc_workorder.cnc_ids.sudo().unlink()
|
||||
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(
|
||||
production)
|
||||
# program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test',
|
||||
# panel)
|
||||
program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel)
|
||||
logging.info('program_path_tmp_panel:%s' % program_path_tmp_panel)
|
||||
files_panel = os.listdir(program_path_tmp_panel)
|
||||
if files_panel:
|
||||
for file in files_panel:
|
||||
file_extension = os.path.splitext(file)[1]
|
||||
logging.info('file_extension:%s' % file_extension)
|
||||
if file_extension.lower() == '.pdf':
|
||||
panel_file_path = os.path.join(program_path_tmp_panel, file)
|
||||
logging.info('panel_file_path:%s' % panel_file_path)
|
||||
cnc_workorder.write(
|
||||
{'is_send_program_again': False,
|
||||
'cnc_ids': cnc_workorder.cnc_ids.sudo()._json_cnc_processing(panel, ret),
|
||||
'cmm_ids': cnc_workorder.cmm_ids.sudo()._json_cmm_program(panel, ret),
|
||||
'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
|
||||
pre_workorder = production.workorder_ids.filtered(
|
||||
lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done',
|
||||
'cancel'] and ap.processing_panel == panel)
|
||||
if pre_workorder:
|
||||
pre_workorder.write(
|
||||
{'is_send_program_again': False,
|
||||
'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
|
||||
productions.write({'programming_state': '已编程', 'work_state': '已编程'})
|
||||
cnc_program_ids = [item.id for item in productions]
|
||||
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
|
||||
[('production_id', 'in', cnc_program_ids)])
|
||||
if workpiece_delivery:
|
||||
|
||||
@@ -19,7 +19,7 @@ class sf_production_plan(models.Model):
|
||||
('done', '已排程'),
|
||||
('processing', '加工中'),
|
||||
('finished', '已完成')
|
||||
], string='工单状态', tracking=True)
|
||||
], string='状态', tracking=True)
|
||||
|
||||
state_order = fields.Integer(compute='_compute_state_order', store=True)
|
||||
|
||||
@@ -36,7 +36,7 @@ class sf_production_plan(models.Model):
|
||||
|
||||
_order = 'state_order asc, write_date desc'
|
||||
|
||||
name = fields.Char(string='工单编号')
|
||||
name = fields.Char(string='制造订单')
|
||||
active = fields.Boolean(string='已归档', default=True)
|
||||
# selected = fields.Boolean(default=False)
|
||||
# order_number = fields.Char(string='订单号')
|
||||
@@ -52,7 +52,7 @@ class sf_production_plan(models.Model):
|
||||
schedule_setting = fields.Selection([
|
||||
('reverse', '倒排'), ('positive', '顺排')], string='排程设置', default='reverse')
|
||||
product_id = fields.Many2one('product.product', '关联产品')
|
||||
origin = fields.Char(string='订单号')
|
||||
origin = fields.Char(string='销售订单')
|
||||
# # 加工时长
|
||||
# process_time = fields.Float(string='加工时长', digits=(16, 2))
|
||||
# 实际加工时长、实际开始时间、实际结束时间
|
||||
@@ -200,6 +200,7 @@ class sf_production_plan(models.Model):
|
||||
raise ValidationError("未选择生产线")
|
||||
else:
|
||||
workorder_id_list = record.production_id.workorder_ids.ids
|
||||
if record.production_id:
|
||||
if record.production_id.workorder_ids:
|
||||
for item in record.production_id.workorder_ids:
|
||||
if item.name == 'CNC加工':
|
||||
@@ -231,12 +232,12 @@ class sf_production_plan(models.Model):
|
||||
# record.production_id.date_planned_start = record.date_planned_start
|
||||
# record.production_id.date_planned_finished = record.date_planned_finished
|
||||
record.sudo().production_id.production_line_id = record.production_line_id.id
|
||||
if record.production_id.workorder_ids:
|
||||
record.sudo().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:
|
||||
raise ValidationError("未找到工单")
|
||||
|
||||
# record.date_planned_finished = record.date_planned_start + timedelta(days=3)
|
||||
# record.state = 'done'
|
||||
return {
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
decoration-danger="state == 'finished'"/>
|
||||
<field name="name"/>
|
||||
<field name="origin"/>
|
||||
<field name="order_deadline"/>
|
||||
<field name="order_deadline" widget="date"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="production_line_id"/>
|
||||
<field name="date_planned_start"/>
|
||||
<field name="date_planned_finished"/>
|
||||
<field name="actual_start_time"/>
|
||||
<field name="actual_end_time"/>
|
||||
<field name="actual_process_time"/>
|
||||
<field name="schedule_setting"/>
|
||||
<button name="do_production_schedule" class="btn schedule_done" string="生产排程" type="object"
|
||||
attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('actual_start_time', '!=', False)]}"
|
||||
groups="sf_base.group_plan_dispatch"/>
|
||||
<field name="actual_start_time" optional='hide'/>
|
||||
<field name="actual_end_time" optional='hide'/>
|
||||
<field name="actual_process_time" optional='hide'/>
|
||||
<field name="schedule_setting" optional='hide'/>
|
||||
<!-- <button name="do_production_schedule" class="btn schedule_done" string="生产排程" type="object" -->
|
||||
<!-- attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('actual_start_time', '!=', False)]}" -->
|
||||
<!-- groups="sf_base.group_plan_dispatch"/> -->
|
||||
<button name="cancel_production_schedule" class="btn schedule_cancel" string="取消排程" type="object"
|
||||
attrs="{'invisible': ['|', ('state', '!=', 'done'), ('actual_start_time', '!=', False)]}"
|
||||
groups="sf_base.group_plan_dispatch"/>
|
||||
@@ -68,7 +68,7 @@
|
||||
<field name="product_id"/>
|
||||
<field name="origin"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="order_deadline"/>
|
||||
<field name="order_deadline" widget="date"/>
|
||||
<!-- <field name="process_time"/> -->
|
||||
<field name="schedule_setting"/>
|
||||
<field name="production_line_id" domain="[('name', 'ilike', 'CNC')]"/>
|
||||
@@ -152,16 +152,27 @@
|
||||
<field name="model">sf.production.plan</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="订单计划">
|
||||
|
||||
<!-- Your other filters go here -->
|
||||
<filter name="archived" string="已归档" domain="[('active','=',False)]"/>
|
||||
<filter name="not archived" string="未归档" domain="[('active','=',True)]"/>
|
||||
<!-- <filter name="archived" string="已归档" domain="[('active','=',False)]"/> -->
|
||||
<!-- <filter name="not archived" string="未归档" domain="[('active','=',True)]"/> -->
|
||||
<field name="name"/>
|
||||
<field name="product_qty"/>
|
||||
<field name="date_planned_start"/>
|
||||
<field name="date_planned_finished"/>
|
||||
<field name="state"/>
|
||||
<searchpanel class="account_root">
|
||||
<field name="state" icon="fa-filter"/>
|
||||
<filter string="待排程" name="draft" domain="[('state','=','draft')]"/>
|
||||
<filter string="已排程" name="done" domain="[('state','=','done')]"/>
|
||||
<filter string="加工中" name="processing" domain="[('state','=','processing')]"/>
|
||||
<filter string="已完成" name="finished" domain="[('state','=','finished')]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_by_state" string="状态" domain="[]" context="{'group_by': 'state'}"/>
|
||||
</group>
|
||||
<group expand="0" string="Group By">
|
||||
<filter name="group_by_production_line_id" string="生产线" domain="[]" context="{'group_by': 'production_line_id'}"/>
|
||||
</group>
|
||||
<searchpanel>
|
||||
<!-- <field name="state" icon="fa-filter"/> -->
|
||||
<field name="production_line_id" select="multi" string="生产线" icon="fa-building" enable_counters="1"/>
|
||||
<field name="state" select="multi" string="状态" icon="fa-building" enable_counters="1"/>
|
||||
</searchpanel>
|
||||
</search>
|
||||
</field>
|
||||
@@ -188,30 +199,41 @@
|
||||
<field name="date_planned_start"/>
|
||||
<field name="date_planned_finished"/>
|
||||
<field name="state"/>
|
||||
<field name="origin"/>
|
||||
<field name="order_deadline"/>
|
||||
<field name="product_id"/>
|
||||
<templates>
|
||||
<div t-name="gantt-popover" class="container-fluid">
|
||||
<div class="row g-0">
|
||||
<div class="col">
|
||||
<ul class="ps-1 mb-0 list-unstyled">
|
||||
<li>
|
||||
<strong>开始时间:</strong>
|
||||
<t t-out="userTimezoneStartDate.format('L LTS')"/>
|
||||
<strong>销售订单号:</strong>
|
||||
<t t-out="origin"/>
|
||||
</li>
|
||||
<li>
|
||||
<strong>结束时间:</strong>
|
||||
<t t-out="userTimezoneStopDate.format('L LTS')"/>
|
||||
</li>
|
||||
<li>
|
||||
<strong>名称:</strong>
|
||||
<strong>制造订单号:</strong>
|
||||
<t t-out="name"/>
|
||||
</li>
|
||||
<li>
|
||||
<strong>订单交期:</strong>
|
||||
<t t-out="order_deadline"/>
|
||||
</li>
|
||||
<li>
|
||||
<strong>产品名称:</strong>
|
||||
<t t-out="product_id"/>
|
||||
</li>
|
||||
<li>
|
||||
<strong>数量:</strong>
|
||||
<t t-out="product_qty"/>
|
||||
</li>
|
||||
<li>
|
||||
<strong>状态:</strong>
|
||||
<t t-out="state"/>
|
||||
<strong>计划开始时间:</strong>
|
||||
<t t-out="userTimezoneStartDate.format('L LTS')"/>
|
||||
</li>
|
||||
<li>
|
||||
<strong>计划结束时间:</strong>
|
||||
<t t-out="userTimezoneStopDate.format('L LTS')"/>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -246,6 +268,7 @@
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">sf.production.plan</field>
|
||||
<field name="view_mode">tree,gantt,form</field>
|
||||
<field name="context">{'search_default_group_by_state': 1, 'search_default_draft': 1, 'display_complete': True}</field>
|
||||
</record>
|
||||
|
||||
<menuitem
|
||||
|
||||
@@ -581,6 +581,15 @@ class FunctionalToolAssembly(models.Model):
|
||||
|
||||
active = fields.Boolean(string='已归档', default=True)
|
||||
|
||||
def action_open_reference1(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'res_model': self._name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'views': [[False, "form"]],
|
||||
'res_id': self.id,
|
||||
}
|
||||
|
||||
def put_start_preset(self):
|
||||
self.search([('start_preset_bool', '=', True)]).write({'start_preset_bool': False})
|
||||
self.write({
|
||||
@@ -750,7 +759,8 @@ class FunctionalToolDismantle(models.Model):
|
||||
return 'GNDJ-CJD-%s-%s' % (datetime, num)
|
||||
|
||||
functional_tool_id = fields.Many2one('sf.functional.cutting.tool.entity', '功能刀具', required=True,
|
||||
domain=[('functional_tool_status', '!=', '已拆除')])
|
||||
domain=[('functional_tool_status', '!=', '已拆除'),
|
||||
('current_location', '=', '刀具房')])
|
||||
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
|
||||
compute='_compute_functional_tool_num')
|
||||
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True)
|
||||
@@ -1028,7 +1038,7 @@ class ProductProduct(models.Model):
|
||||
'product_id': self.id,
|
||||
'lot_id': lot_id.id,
|
||||
'move_id': stock_move_id.id,
|
||||
'destination_location_id': shelf_location_id.id,
|
||||
'destination_location_id': shelf_location_id.id if shelf_location_id else False,
|
||||
'install_tool_time': fields.Datetime.now(),
|
||||
'qty_done': 1.0,
|
||||
'state': 'done',
|
||||
|
||||
@@ -387,6 +387,22 @@ class StockMoveLine(models.Model):
|
||||
names = categories._search([], order=order, access_rights_uid=SUPERUSER_ID)
|
||||
return categories.browse(names)
|
||||
|
||||
def action_open_reference1(self):
|
||||
self.ensure_one()
|
||||
if self.functional_tool_name_id:
|
||||
action = self.functional_tool_name_id.action_open_reference1()
|
||||
return action
|
||||
elif self.move_id:
|
||||
action = self.move_id.action_open_reference()
|
||||
if action['res_model'] != 'stock.move':
|
||||
return action
|
||||
return {
|
||||
'res_model': self._name,
|
||||
'type': 'ir.actions.act_window',
|
||||
'views': [[False, "form"]],
|
||||
'res_id': self.id,
|
||||
}
|
||||
|
||||
|
||||
class RealTimeDistributionOfFunctionalTools(models.Model):
|
||||
_name = 'sf.real.time.distribution.of.functional.tools'
|
||||
@@ -404,8 +420,8 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
|
||||
side_shelf_num = fields.Integer(string='线边刀库数量', compute='_compute_stock_num', store=True)
|
||||
on_tool_stock_num = fields.Integer(string='机内刀库数量', compute='_compute_stock_num', store=True)
|
||||
tool_stock_total = fields.Integer(string='当前库存量', compute='_compute_tool_stock_total', store=True)
|
||||
min_stock_num = fields.Integer('最低库存量')
|
||||
max_stock_num = fields.Integer('最高库存量')
|
||||
min_stock_num = fields.Integer('最低库存量', tracking=True)
|
||||
max_stock_num = fields.Integer('最高库存量', tracking=True)
|
||||
batch_replenishment_num = fields.Integer('批次补货量', readonly=True, compute='_compute_batch_replenishment_num',
|
||||
store=True)
|
||||
unit = fields.Char('单位', default="件")
|
||||
|
||||
@@ -477,7 +477,8 @@
|
||||
<field name="name">功能刀具出入库记录</field>
|
||||
<field name="model">stock.move.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="功能刀具出入库记录" create="0" edit="0" delete="0">
|
||||
<tree string="功能刀具出入库记录" create="0" edit="0" delete="0" default_order="id desc"
|
||||
action="action_open_reference1" type="object">
|
||||
<field name="reference" string="单据号"/>
|
||||
<field name="lot_id" invisible="1"/>
|
||||
<field name="rfid"/>
|
||||
@@ -531,7 +532,7 @@
|
||||
ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_tree"/>
|
||||
<field name="search_view_id"
|
||||
ref="sf_tool_management.sf_inbound_and_outbound_records_of_functional_tools_view_search"/>
|
||||
<field name="domain">[('functional_tool_name', '!=', False)]</field>
|
||||
<field name="domain">[('rfid', '!=', ''),('functional_tool_name', '!=', '')]</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
||||
Reference in New Issue
Block a user