优化工件配送

This commit is contained in:
jinling.yang
2024-04-30 17:05:09 +08:00
parent b45ffcc0d2
commit 68d8c36755
6 changed files with 163 additions and 35 deletions

View File

@@ -42,7 +42,9 @@ class AgvTaskRoute(models.Model):
name = fields.Char('名称') name = fields.Char('名称')
type = fields.Selection([ type = fields.Selection([
('F01', '搬运'), ], string='类型', default="F01") ('F01', '搬运'), ], string='任务类型', default="F01")
route_type = fields.Selection([
('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
start_site_id = fields.Many2one('sf.agv.site', '起点接驳站位置编号') start_site_id = fields.Many2one('sf.agv.site', '起点接驳站位置编号')
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站位置编号') end_site_id = fields.Many2one('sf.agv.site', '终点接驳站位置编号')
destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线') destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线')

View File

@@ -427,19 +427,22 @@ class ResMrpWorkOrder(models.Model):
if not item.route_id: if not item.route_id:
raise UserError('【工件配送】明细中请选择【任务路线】') raise UserError('【工件配送】明细中请选择【任务路线】')
else: else:
if item.is_cnc_program_down is True: if self.state == 'done':
if item.status == '待下发': if item.is_cnc_program_down is True:
return { if item.status == '待下发':
'name': _('确认'), return {
'type': 'ir.actions.act_window', 'name': _('确认'),
'view_mode': 'form', 'type': 'ir.actions.act_window',
'res_model': 'sf.workpiece.delivery.wizard', 'view_mode': 'form',
'target': 'new', 'res_model': 'sf.workpiece.delivery.wizard',
'context': { 'target': 'new',
'default_workorder_id': self.id, 'context': {
}} 'default_workorder_id': self.id,
}}
else:
raise UserError(_("该制造订单还未下发CNC程序单无法进行工件配送"))
else: else:
raise UserError(_("制造订单还未下发CNC程序单,无法进行工件配送")) raise UserError(_("工单暂未完成,无法进行工件配送"))
# 拼接工单对象属性值 # 拼接工单对象属性值
def json_workorder_str(self, k, production, route): def json_workorder_str(self, k, production, route):
@@ -636,6 +639,33 @@ class ResMrpWorkOrder(models.Model):
# 'domain': [('production_id', '=', self.id)], # 'domain': [('production_id', '=', self.id)],
# 'target':'new' # 'target':'new'
# } # }
@api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state')
def _compute_state(self):
for workorder in self:
if workorder.routing_type == '装夹预调':
if not workorder.cnc_ids:
workorder.state = 'waiting'
else:
for item in workorder.cnc_ids:
functional_cutting_tool = self.env['sf.functional.cutting.tool.entity'].search(
[('tool_name_id.name', '=', item.cutting_tool_name)])
if not functional_cutting_tool:
workorder.state = 'waiting'
if workorder.state == 'pending':
if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]):
workorder.state = 'ready' if workorder.production_id.reservation_state == 'assigned' else 'waiting'
continue
if workorder.state not in ('waiting', 'ready'):
continue
if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]):
workorder.state = 'pending'
continue
if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'):
continue
if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting':
workorder.state = 'ready'
elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready':
workorder.state = 'waiting'
def recreateManufacturingOrWorkerOrder(self): def recreateManufacturingOrWorkerOrder(self):
""" """
@@ -822,6 +852,8 @@ class ResMrpWorkOrder(models.Model):
self.process_state = '已完工' self.process_state = '已完工'
self.production_id.button_mark_done1() self.production_id.button_mark_done1()
# self.production_id.state = 'done' # self.production_id.state = 'done'
# if self.routing_type == '装夹预调':
# self.workpiece_delivery_ids.write({''})
# 将FTP的检测报告文件下载到临时目录 # 将FTP的检测报告文件下载到临时目录
def download_reportfile_tmp(self, workorder, reportpath): def download_reportfile_tmp(self, workorder, reportpath):
@@ -1096,6 +1128,7 @@ class WorkPieceDelivery(models.Model):
name = fields.Char('单据编号') name = fields.Char('单据编号')
workorder_id = fields.Many2one('mrp.workorder', string='工单', readonly=True) workorder_id = fields.Many2one('mrp.workorder', string='工单', readonly=True)
workorder_state = fields.Selection(related='workorder_id.state', string='工单状态')
production_id = fields.Many2one('mrp.production', string='制造订单号', readonly=True) production_id = fields.Many2one('mrp.production', string='制造订单号', readonly=True)
production_line_id = fields.Many2one('sf.production.line', string='目的生产线') production_line_id = fields.Many2one('sf.production.line', string='目的生产线')
plan_start_processing_time = fields.Datetime('计划开始加工时间', readonly=True) plan_start_processing_time = fields.Datetime('计划开始加工时间', readonly=True)
@@ -1140,6 +1173,7 @@ class WorkPieceDelivery(models.Model):
# 工件配送 # 工件配送
def button_delivery(self): def button_delivery(self):
delivery_ids = [] delivery_ids = []
production_ids = []
is_cnc_down = 0 is_cnc_down = 0
is_not_production_line = 0 is_not_production_line = 0
is_not_route = 0 is_not_route = 0
@@ -1172,7 +1206,13 @@ class WorkPieceDelivery(models.Model):
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:
raise UserError('请选择状态为【待下发】的制造订单进行配送') up_workpiece = self.search([('type', '=', '上产线'), ('production_id', '=', item.production_id),
('status', '=', '待下发')])
if up_workpiece:
raise UserError('您所选择的制造订单暂未上产线,请在上产线后再进行配送')
else:
raise UserError('请选择状态为【待下发】的制造订单进行配送')
if same_production_line_id is None: if same_production_line_id is None:
same_production_line_id = item.production_line_id.id same_production_line_id = item.production_line_id.id
if item.production_line_id.id != same_production_line_id: if item.production_line_id.id != same_production_line_id:
@@ -1181,13 +1221,15 @@ class WorkPieceDelivery(models.Model):
is_cnc_down += 1 is_cnc_down += 1
if is_cnc_down == 0 and is_not_production_line == 0 and is_not_route == 0: if is_cnc_down == 0 and is_not_production_line == 0 and is_not_route == 0:
delivery_ids.append(item.id) delivery_ids.append(item.id)
production_ids.append(item.production_id.id)
if is_cnc_down >= 1: if is_cnc_down >= 1:
raise UserError('您所选择制造订单的【CNC程序】暂未下发请在程序下发后再进行配送') raise UserError('您所选择制造订单的【CNC程序】暂未下发请在程序下发后再进行配送')
if is_not_production_line >= 1: if is_not_production_line >= 1:
raise UserError('您所选择制造订单的【目的生产线】不一致,请重新确认') raise UserError('您所选择制造订单的【目的生产线】不一致,请重新确认')
if is_not_route >= 1: if is_not_route >= 1:
raise UserError('您所选择制造订单的【任务路线】不一致,请重新确认') raise UserError('您所选择制造订单的【任务路线】不一致,请重新确认')
is_free = self._check_avgsite_state() # is_free = self._check_avgsite_state()
is_free = True
if is_free is True: if is_free is True:
if delivery_ids: if delivery_ids:
return { return {
@@ -1198,6 +1240,9 @@ class WorkPieceDelivery(models.Model):
'target': 'new', 'target': 'new',
'context': { 'context': {
'default_delivery_ids': [(6, 0, delivery_ids)], 'default_delivery_ids': [(6, 0, delivery_ids)],
'default_production_ids': [(6, 0, production_ids)],
'default_destination_production_line_id': same_production_line_id,
'default_route_id': same_route_id,
}} }}
else: else:
if self.type == '运送空料架': if self.type == '运送空料架':
@@ -1231,21 +1276,27 @@ class WorkPieceDelivery(models.Model):
# 配送至avg小车 # 配送至avg小车
def _delivery_avg(self): def _delivery_avg(self):
config = self.env['res.config.settings'].get_values() config = self.env['res.config.settings'].get_values()
if self.type == '运送空料架':
self = self.create(
{'name': self.env['ir.sequence'].next_by_code('sf.workpiece.delivery'), 'route_id': self.route_id.id,
'feeder_station_start_id': self.feeder_station_start_id.id,
'feeder_station_destination_id': self.feeder_station_destination_id.id})
positionCode_Arr = [] positionCode_Arr = []
delivery_Arr = [] delivery_Arr = []
feeder_station_start = None feeder_station_start = None
feeder_station_destination = None feeder_station_destination = None
route_id = None
for item in self: for item in self:
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
delivery_Arr.append(item.name) delivery_Arr.append(item.name)
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
else:
self = self.create(
{'name': self.env['ir.sequence'].next_by_code('sf.workpiece.delivery'),
'route_id': self.route_id.id,
'feeder_station_start_id': self.feeder_station_start_id.id,
'feeder_station_destination_id': self.feeder_station_destination_id.id})
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({

View File

@@ -34,7 +34,8 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree editable="bottom"> <tree editable="bottom">
<field name="name" required="1"/> <field name="name" required="1"/>
<field name="type" readonly="1"/> <field name="type" readonly="1" string="任务类型"/>
<field name="route_type" string="类型"/>
<field name="start_site_id" required="1" options="{'no_create': True}" string="起点接驳站"/> <field name="start_site_id" required="1" options="{'no_create': True}" string="起点接驳站"/>
<field name="end_site_id" required="1" options="{'no_create': True}" string="终点接驳站"/> <field name="end_site_id" required="1" options="{'no_create': True}" string="终点接驳站"/>
<field name="destination_production_line_id" required="1" options="{'no_create': True}"/> <field name="destination_production_line_id" required="1" options="{'no_create': True}"/>

View File

@@ -626,7 +626,7 @@
<search string="工件配送"> <search string="工件配送">
<filter string="上产线" name="up" domain="[('type', '=', '上产线')]"/> <filter string="上产线" name="up" domain="[('type', '=', '上产线')]"/>
<filter string="下产线" name="down" domain="[('type', '=', '下产线' )]"/> <filter string="下产线" name="down" domain="[('type', '=', '下产线' )]"/>
<field name="rfid_code" invisible="1"/> <field name="rfid_code"/>
<field name="production_id"/> <field name="production_id"/>
<field name="feeder_station_start_id"/> <field name="feeder_station_start_id"/>
<field name="production_line_id"/> <field name="production_line_id"/>
@@ -649,7 +649,7 @@
<field name="search_view_id" ref="sf_workpiece_delivery_search"/> <field name="search_view_id" ref="sf_workpiece_delivery_search"/>
<!-- <field name="context">{'search_default_on_up':1}</field>--> <!-- <field name="context">{'search_default_on_up':1}</field>-->
<field name="view_mode">tree,search</field> <field name="view_mode">tree,search</field>
<field name="domain">[('type','in',['上产线','下产线'])]</field> <field name="domain">[('type','in',['上产线','下产线']),('workorder_state','=','done')]</field>
</record> </record>

View File

@@ -5,13 +5,32 @@
<field name="model">sf.workpiece.delivery.wizard</field> <field name="model">sf.workpiece.delivery.wizard</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form>
<sheet>
<field name="delivery_ids" invisible="True"/> <field name="delivery_ids" invisible="True"/>
<field name="workorder_id" invisible="True"/> <field name="workorder_id" invisible="True"/>
<div>是否确定配送?</div> <field name="type" invisible="True"/>
<footer> <group>
<button string="确认" name="confirm" type="object" class="oe_highlight"/> <field name="production_ids" readonly="1" widget="many2many_tags" string="制造订单号"/>
<button string="取消" class="btn btn-secondary" special="cancel"/> <div class="o_address_format">
</footer> <lable for="rfid_code"></lable>
<field name="rfid_code" class="o_address_zip"/>
<button name="recognize_production" string="识别" type="object" class="oe_highlight"/>
</div>
<field name="destination_production_line_id" readonly="1"/>
<field name="route_id" required="1"/>
</group>
<group>
<field name="feeder_station_start_id" focesave="1" readonly="1"/>
<field name="feeder_station_destination_id" focesave="1" readonly="1"/>
</group>
<div attrs="{'invisible': [('type', 'in', ['上产线','下产线'])]}">
是否确定配送
</div>
<footer>
<button string="配送" name="confirm" type="object" class="oe_highlight"/>
<button string="取消" class="btn btn-secondary" special="cancel"/>
</footer>
</sheet>
</form> </form>
</field> </field>
</record> </record>

View File

@@ -2,7 +2,7 @@
# Part of YiZuo. See LICENSE file for full copyright and licensing details. # Part of YiZuo. See LICENSE file for full copyright and licensing details.
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, _
class WorkpieceDeliveryWizard(models.TransientModel): class WorkpieceDeliveryWizard(models.TransientModel):
@@ -10,15 +10,70 @@ class WorkpieceDeliveryWizard(models.TransientModel):
_description = '工件配送' _description = '工件配送'
delivery_ids = fields.Many2many('sf.workpiece.delivery', string='配送') delivery_ids = fields.Many2many('sf.workpiece.delivery', string='配送')
rfid_code = fields.Char('rfid码')
workorder_id = fields.Many2one('mrp.workorder', string='工单') workorder_id = fields.Many2one('mrp.workorder', string='工单')
production_ids = fields.Many2many('mrp.production', string='制造订单号') production_ids = fields.Many2many('mrp.production', string='制造订单号')
destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线') destination_production_line_id = fields.Many2one('sf.production.line', '目的生产线')
route_id = fields.Many2one('sf.agv.task.route', '任务路线', domain=[('route_type', 'in', ['上产线', '下产线'])])
feeder_station_start_id = fields.Many2one('sf.agv.site', '起点接驳站') feeder_station_start_id = fields.Many2one('sf.agv.site', '起点接驳站')
feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站') feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站')
type = fields.Selection(
[('上产线', '上产线'), ('下产线', '下产线'), ('运送空料架', '运送空料架')], string='类型')
def confirm(self): def confirm(self):
if self.workorder_id: if self.workorder_id:
self.workorder_id.workpiece_delivery_ids[0]._delivery_avg() self.workorder_id.workpiece_delivery_ids[0]._delivery_avg()
else: else:
self.delivery_ids._delivery_avg() is_not_production_line = 0
same_production_line_id = None
notsame_production_line_arr = []
for item in self.production_ids:
if same_production_line_id is None:
same_production_line_id = item.production_line_id.id
if item.production_line_id.id != same_production_line_id:
notsame_production_line_arr.append(item.name)
notsame_production_line_str = ','.join(map(str, notsame_production_line_arr))
if is_not_production_line >= 1:
raise UserError('制造订单号为%s的目的生产线不一致' % notsame_production_line_str)
else:
self.delivery_ids._delivery_avg()
def recognize_production(self):
# production_ids = []
# delivery_ids = []
if len(self.production_ids) > 4:
raise UserError('只能配送四个制造订单')
else:
if self.rfid_code:
wd = self.env['sf.workpiece.delivery'].search(
[('type', '=', self.delivery_ids[0].type), ('rfid_code', '=', self.rfid_code),
('status', '=', self.delivery_ids[0].status)])
if wd:
if wd.production_line_id.id == self.delivery_ids[0].production_line_id.id:
# production_ids.append(wd.production_id)
# delivery_ids.append(wd.id)
# 将对象添加到对应的同模型且是多对多类型里
self.production_ids |= wd.production_id
self.delivery_ids |= wd
self.rfid_code = False
# self.production_ids = [(6, 0, production_ids)]
# self.delivery_ids = [(6, 0, delivery_ids)]
else:
raise UserError('该rfid对应的制造订单号为%s的目的生产线不一致' % wd.production_id.name)
return {
'name': _('确认'),
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'sf.workpiece.delivery.wizard',
'target': 'new',
'context': {
'default_delivery_ids': [(6, 0, self.delivery_ids.ids)],
'default_production_ids': [(6, 0, self.production_ids.ids)],
'default_route_id': self.delivery_ids[0].route_id.id
}}
@api.onchange('route_id')
def onchange_route(self):
if self.route_id:
self.feeder_station_start_id = self.route_id.start_site_id.id
self.feeder_station_destination_id = self.route_id.end_site_id.id