Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/修复编程单下发ftp路径

This commit is contained in:
jinling.yang
2024-06-26 10:17:14 +08:00
12 changed files with 196 additions and 111 deletions

View File

@@ -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)

View File

@@ -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"/>

View File

@@ -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>
@@ -23,6 +23,7 @@
<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="是否确认下发补偿"-->

View File

@@ -461,25 +461,27 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code)
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '待上产线':
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([
('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
('production_id', '=', order.production_id.id)])
if workpiece_delivery.status == '待下发':
workpiece_delivery.write({'is_manual_work': True})
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if rfid_code is not None:
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '待上产线':
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(
[
('rfid_code', '=', rfid_code), ('type', '=', '上产线'),
('production_id', '=', order.production_id.id)])
if workpiece_delivery.status == '待下发':
workpiece_delivery.write({'is_manual_work': True})
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
else:
res = {'Succeed': False, 'ErrorCode': 203, 'Error': '未传IsComplete字段'}
else:
@@ -516,24 +518,26 @@ class Manufacturing_Connect(http.Controller):
if f'RfidCode{i}' in ret:
rfid_code = ret[f'RfidCode{i}']
logging.info('RfidCode:%s' % rfid_code)
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '已上产线':
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([
('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
('production_id', '=', order.production_id.id)])
delivery_Arr.append(workpiece_delivery.id)
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if rfid_code is not None:
domain = [
('rfid_code', '=', rfid_code),
('routing_type', '=', 'CNC加工')
]
workorder = request.env['mrp.workorder'].sudo().search(domain, order='id asc')
if workorder:
for order in workorder:
if order.production_id.production_line_state == '已上产线':
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(
[
('rfid_code', '=', rfid_code), ('type', '=', '下产线'),
('production_id', '=', order.production_id.id)])
delivery_Arr.append(workpiece_delivery.id)
else:
res = {'Succeed': False, 'ErrorCode': 204,
'Error': 'DeviceId为%s没有对应的已配送工件数据' % ret['DeviceId']}
if delivery_Arr:
logging.info('delivery_Arr:%s' % delivery_Arr)
delivery_workpiece = request.env['sf.workpiece.delivery'].sudo().search(

View File

@@ -531,46 +531,63 @@ 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:
tmpl_num = 1
# 成品工序
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})
tmpl_num += 1
# 表面工艺工序
# 模型类型的表面工艺工序模版
surface_tmpl_ids = model_type_id.surface_technics_routing_tmpl_ids
# 产品选择的表面工艺
model_process_parameters_ids = rec.product_id.model_process_parameters_ids
process_dict = {}
if model_process_parameters_ids:
for process_parameters_id in model_process_parameters_ids:
process_id = process_parameters_id.process_id
for surface_tmpl_id in surface_tmpl_ids:
if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
process_dict.update({int(process_id.category_id.code): '%s-%s' % (
surface_tmpl_name, process_parameters_id.name)})
process_list = sorted(process_dict.keys())
for process_num in process_list:
sequence_list.update({process_dict.get(process_num): tmpl_num})
tmpl_num += 1
# 坯料工序
tmpl_num = 1
embryo_routing_tmpl_ids = model_type_id.embryo_routing_tmpl_ids
if embryo_routing_tmpl_ids:
for tmpl_id in embryo_routing_tmpl_ids:
sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
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:
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
# 产品选择的表面工艺
model_process_parameters_ids = rec.product_id.model_process_parameters_ids
process_dict = {}
if model_process_parameters_ids:
for process_parameters_id in model_process_parameters_ids:
process_id = process_parameters_id.process_id
for surface_tmpl_id in surface_tmpl_ids:
if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
process_dict.update({int(process_id.category_id.code): '%s-%s' % (
surface_tmpl_name, process_parameters_id.name)})
process_list = sorted(process_dict.keys())
for process_num in process_list:
sequence_list.update({process_dict.get(process_num): tmpl_num})
tmpl_num += 1
# 坯料工序
tmpl_num = 1
embryo_routing_tmpl_ids = model_type_id.embryo_routing_tmpl_ids
if embryo_routing_tmpl_ids:
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加工程序':

View File

@@ -162,6 +162,7 @@
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>
@@ -220,12 +221,12 @@
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","!=","装夹预调")]}'/> -->
<!-- <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)]}"/>

View File

@@ -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))
# 实际加工时长、实际开始时间、实际结束时间

View File

@@ -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,8 @@
<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> -->
<field name="context">{'search_default_draft': 1, 'display_complete': True}</field>
</record>
<menuitem

View File

@@ -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',

View File

@@ -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'

View File

@@ -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"/>

View File

@@ -622,6 +622,11 @@ class SfStockMoveLine(models.Model):
if not qr_code_data:
raise UserError("没有找到二维码数据。")
lot_name = self.lot_name
# 增加"当为坯料时,只打印序列号的前面部分"
if self.lot_name: # 确保 lot_name 存在
if self.product_id.categ_id.name == '坯料':
lot_name = lot_name.split('[', 1)[0]
# host = "192.168.50.110" # 可以根据实际情况修改
# port = 9100 # 可以根据实际情况修改
@@ -1184,6 +1189,12 @@ class CustomStockMove(models.Model):
# todo 待控制
if not lot_name:
raise ValidationError("请先分配序列号")
# 增加"当为坯料时,只打印序列号的前面部分"
if record.lot_name: # 确保 lot_name 存在
if record.product_id.categ_id.name == '坯料':
lot_name = lot_name.split('[', 1)[0]
# host = "192.168.50.110" # 可以根据实际情况修改
# port = 9100 # 可以根据实际情况修改