Merge branch 'develop' into feature/commercially_launched
This commit is contained in:
@@ -10,7 +10,6 @@
|
|||||||
</t>
|
</t>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 暂存,同一份文件中有问题,拆分后正常工作 -->
|
<!-- 暂存,同一份文件中有问题,拆分后正常工作 -->
|
||||||
|
|
||||||
<!-- <t t-name="og.web.ListRenderer.Rows" t-inherit="web.ListRenderer.Rows" t-inherit-mode="extension"> -->
|
<!-- <t t-name="og.web.ListRenderer.Rows" t-inherit="web.ListRenderer.Rows" t-inherit-mode="extension"> -->
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ class CuttingToolModel(models.Model):
|
|||||||
def _get_ids(self, cutting_tool_type_code, factory_short_name):
|
def _get_ids(self, cutting_tool_type_code, factory_short_name):
|
||||||
cutting_tool_type_ids = []
|
cutting_tool_type_ids = []
|
||||||
for item in cutting_tool_type_code:
|
for item in cutting_tool_type_code:
|
||||||
cutting_tool_type = self.search([('code', '=', item.replace("JKM", factory_short_name))])
|
cutting_tool_type = self.search([('code', '=', item)])
|
||||||
if cutting_tool_type:
|
if cutting_tool_type:
|
||||||
cutting_tool_type_ids.append(cutting_tool_type.id)
|
cutting_tool_type_ids.append(cutting_tool_type.id)
|
||||||
return [(6, 0, cutting_tool_type_ids)]
|
return [(6, 0, cutting_tool_type_ids)]
|
||||||
|
|||||||
@@ -112,6 +112,8 @@
|
|||||||
<field name="cutting_tool_material_id"/>
|
<field name="cutting_tool_material_id"/>
|
||||||
<field name="cutting_tool_type_id"/>
|
<field name="cutting_tool_type_id"/>
|
||||||
<field name="brand_id"/>
|
<field name="brand_id"/>
|
||||||
|
<field name="create_date" optional="hide"/>
|
||||||
|
<field name="write_date" string="修改时间" optional="hide"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
@@ -317,28 +319,28 @@
|
|||||||
|
|
||||||
<field name="knife_handle_basic_parameters_ids"
|
<field name="knife_handle_basic_parameters_ids"
|
||||||
attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')]}">
|
attrs="{'invisible': [('cutting_tool_type', '!=', '刀柄')]}">
|
||||||
<tree editable="bottom" class="center" delete="1">
|
<tree editable="bottom" delete="1">
|
||||||
<field name="cutting_tool_type" invisible="1"/>
|
<field name="cutting_tool_type" invisible="1"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="taper_shank_model"/>
|
<field name="taper_shank_model"/>
|
||||||
<field name="total_length"/>
|
<field name="total_length"/>
|
||||||
<field name="shank_length"/>
|
<field name="shank_length"/>
|
||||||
<field name="shank_diameter" class="diameter"/>
|
<field name="shank_diameter" class="diameter"/>
|
||||||
<field name="flange_shank_length"/>
|
<field name="flange_shank_length" optional="hide"/>
|
||||||
<field name="flange_diameter"/>
|
<field name="flange_diameter" optional="hide"/>
|
||||||
<field name="diameter_slip_accuracy"/>
|
<field name="diameter_slip_accuracy" optional="hide"/>
|
||||||
<field name="dynamic_balance_class"/>
|
<field name="dynamic_balance_class" optional="hide"/>
|
||||||
<field name="min_clamping_diameter" class="diameter"/>
|
<field name="min_clamping_diameter" class="diameter"/>
|
||||||
<field name="max_clamping_diameter" class="diameter"/>
|
<field name="max_clamping_diameter" class="diameter"/>
|
||||||
<field name="max_rotate_speed"/>
|
<field name="max_rotate_speed" optional="hide"/>
|
||||||
<field name="fit_chuck_size"/>
|
<field name="fit_chuck_size"/>
|
||||||
<field name="nut"/>
|
<field name="nut" optional="hide"/>
|
||||||
<field name="spanner" string="适配锁紧扳手型号"/>
|
<field name="spanner" string="适配锁紧扳手型号" optional="hide"/>
|
||||||
<field name="clamping_mode"/>
|
<field name="clamping_mode" optional="hide"/>
|
||||||
<field name="tool_changing_time"/>
|
<field name="tool_changing_time" optional="hide"/>
|
||||||
<field name="cooling_model"/>
|
<field name="cooling_model" optional="hide"/>
|
||||||
<field name="is_quick_cutting"/>
|
<field name="is_quick_cutting" optional="hide"/>
|
||||||
<field name="is_safe_lock"/>
|
<field name="is_safe_lock" optional="hide"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
<field name="chuck_basic_parameters_ids"
|
<field name="chuck_basic_parameters_ids"
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ class AgvScheduling(models.Model):
|
|||||||
|
|
||||||
name = fields.Char('任务单号', index=True, copy=False)
|
name = fields.Char('任务单号', index=True, copy=False)
|
||||||
agv_route_id = fields.Many2one('sf.agv.task.route', '任务路线')
|
agv_route_id = fields.Many2one('sf.agv.task.route', '任务路线')
|
||||||
agv_route_type = fields.Selection(related='agv_route_id.route_type', string='任务类型', required=True)
|
def _get_agv_route_type_selection(self):
|
||||||
|
return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection']
|
||||||
|
agv_route_type = fields.Selection(selection=_get_agv_route_type_selection, string='任务类型', required=True)
|
||||||
start_site_id = fields.Many2one('sf.agv.site', '起点接驳站', required=True)
|
start_site_id = fields.Many2one('sf.agv.site', '起点接驳站', required=True)
|
||||||
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站', tracking=True)
|
end_site_id = fields.Many2one('sf.agv.site', '终点接驳站', tracking=True)
|
||||||
site_state = fields.Selection([
|
site_state = fields.Selection([
|
||||||
|
|||||||
@@ -265,6 +265,23 @@ class MrpProduction(models.Model):
|
|||||||
|
|
||||||
part_name = fields.Char(string='零件名称', related='product_id.part_name', readonly=True)
|
part_name = fields.Char(string='零件名称', related='product_id.part_name', readonly=True)
|
||||||
|
|
||||||
|
# 判断制造的产品类型
|
||||||
|
production_product_type = fields.Selection([
|
||||||
|
('成品', '成品'),
|
||||||
|
('坯料', '坯料'),
|
||||||
|
('其他', '其他')
|
||||||
|
], string='产品类型', compute='_compute_production_product_type')
|
||||||
|
|
||||||
|
@api.depends('product_id')
|
||||||
|
def _compute_production_product_type(self):
|
||||||
|
for record in self:
|
||||||
|
if record.product_id.categ_id.name == '成品':
|
||||||
|
record.production_product_type = '成品'
|
||||||
|
elif record.product_id.categ_id.name == '坯料':
|
||||||
|
record.production_product_type = '坯料'
|
||||||
|
else:
|
||||||
|
record.production_product_type = '其他'
|
||||||
|
|
||||||
@api.depends('product_id.manual_quotation')
|
@api.depends('product_id.manual_quotation')
|
||||||
def _compute_manual_quotation(self):
|
def _compute_manual_quotation(self):
|
||||||
for item in self:
|
for item in self:
|
||||||
@@ -776,11 +793,11 @@ class MrpProduction(models.Model):
|
|||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
iot_code = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[
|
iot_code = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id) or self.env[
|
||||||
'ir.sequence'].next_by_code('stock.lot.serial')
|
'ir.sequence'].next_by_code('stock.lot.serial')
|
||||||
iot_code_name = re.sub('[\u4e00-\u9fa5]', "", iot_code)
|
# iot_code_name = re.sub('[\u4e00-\u9fa5]', "", iot_code)
|
||||||
self.lot_producing_id = self.env['stock.lot'].create({
|
self.lot_producing_id = self.env['stock.lot'].create({
|
||||||
'product_id': self.product_id.id,
|
'product_id': self.product_id.id,
|
||||||
'company_id': self.company_id.id,
|
'company_id': self.company_id.id,
|
||||||
'name': iot_code_name,
|
'name': iot_code,
|
||||||
})
|
})
|
||||||
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
|
if self.move_finished_ids.filtered(lambda m: m.product_id == self.product_id).move_line_ids:
|
||||||
self.move_finished_ids.filtered(
|
self.move_finished_ids.filtered(
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ from odoo.exceptions import UserError, ValidationError
|
|||||||
from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController
|
from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ResMrpWorkOrder(models.Model):
|
class ResMrpWorkOrder(models.Model):
|
||||||
_inherit = 'mrp.workorder'
|
_inherit = 'mrp.workorder'
|
||||||
_order = 'sequence asc'
|
_order = 'sequence asc'
|
||||||
|
_description = '工单'
|
||||||
|
|
||||||
product_tmpl_name = fields.Char('坯料产品名称', related='production_bom_id.bom_line_ids.product_id.name')
|
product_tmpl_name = fields.Char('坯料产品名称', related='production_bom_id.bom_line_ids.product_id.name')
|
||||||
|
|
||||||
@@ -69,6 +69,67 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
|
|
||||||
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效',
|
delivery_warning = fields.Selection([('normal', '正常'), ('warning', '告警'), ('overdue', '逾期')], string='时效',
|
||||||
tracking=True)
|
tracking=True)
|
||||||
|
back_button_display = fields.Boolean(default=False, compute='_compute_back_button_display', store=True)
|
||||||
|
|
||||||
|
@api.depends('state')
|
||||||
|
def _compute_back_button_display(self):
|
||||||
|
for record in self:
|
||||||
|
sorted_workorders = record.production_id.workorder_ids.filtered(lambda w: w.state != 'cancel').sorted(
|
||||||
|
key=lambda w: w.sequence)
|
||||||
|
if not sorted_workorders:
|
||||||
|
continue
|
||||||
|
position = next((idx for idx, workorder in enumerate(sorted_workorders) if workorder.id == record.id), -1)
|
||||||
|
cur_workorder = sorted_workorders[position]
|
||||||
|
if position == len(sorted_workorders) - 1:
|
||||||
|
picking_ids = cur_workorder.production_id.sale_order_id.picking_ids
|
||||||
|
finished_product_area = picking_ids.filtered(
|
||||||
|
lambda picking: picking.location_dest_id.name == '成品存货区' and picking.state == 'done'
|
||||||
|
)
|
||||||
|
if finished_product_area:
|
||||||
|
moves = self.env['stock.move'].search([
|
||||||
|
('name', '=', cur_workorder.production_id.name),
|
||||||
|
('state', '!=', 'cancel')
|
||||||
|
])
|
||||||
|
finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None)
|
||||||
|
if not finish_move and not cur_workorder.is_subcontract and not cur_workorder.routing_type == '解除装夹':
|
||||||
|
record.back_button_display = True
|
||||||
|
else:
|
||||||
|
record.back_button_display = any(
|
||||||
|
finish_move.move_dest_ids.ids not in move.ids and record.state == 'done'
|
||||||
|
for picking in finished_product_area
|
||||||
|
for move in picking.move_ids
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if record.state == 'done':
|
||||||
|
record.back_button_display = True
|
||||||
|
else:
|
||||||
|
record.back_button_display = False
|
||||||
|
# tag_type
|
||||||
|
if cur_workorder.is_subcontract or cur_workorder.routing_type == '解除装夹' or cur_workorder.routing_type == '切割' or any(
|
||||||
|
detection_result.processing_panel == cur_workorder.processing_panel and
|
||||||
|
detection_result.routing_type == cur_workorder.routing_type and
|
||||||
|
cur_workorder.tag_type !='重新加工' and
|
||||||
|
detection_result.test_results != '合格'
|
||||||
|
for detection_result in cur_workorder.production_id.detection_result_ids
|
||||||
|
):
|
||||||
|
record.back_button_display = False
|
||||||
|
else:
|
||||||
|
next_workorder = sorted_workorders[position + 1]
|
||||||
|
next_state = next_workorder.state
|
||||||
|
if (next_state == 'ready' or (
|
||||||
|
next_workorder.state == 'waiting' and next_workorder.is_subcontract)) and cur_workorder.state == 'done':
|
||||||
|
record.back_button_display = True
|
||||||
|
else:
|
||||||
|
record.back_button_display = False
|
||||||
|
if cur_workorder.is_subcontract or cur_workorder.routing_type == '解除装夹' or cur_workorder.routing_type == '切割' or any(
|
||||||
|
detection_result.processing_panel == cur_workorder.processing_panel and
|
||||||
|
detection_result.routing_type == cur_workorder.routing_type and
|
||||||
|
cur_workorder.tag_type !='重新加工' and
|
||||||
|
detection_result.test_results != '合格'
|
||||||
|
for detection_result in cur_workorder.production_id.detection_result_ids
|
||||||
|
):
|
||||||
|
record.back_button_display = False
|
||||||
|
|
||||||
date_planned_start = fields.Datetime(tracking=True)
|
date_planned_start = fields.Datetime(tracking=True)
|
||||||
|
|
||||||
@api.depends('processing_panel')
|
@api.depends('processing_panel')
|
||||||
@@ -86,6 +147,82 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
|
|
||||||
manual_quotation = fields.Boolean('人工编程', default=False, compute=_compute_manual_quotation, store=True)
|
manual_quotation = fields.Boolean('人工编程', default=False, compute=_compute_manual_quotation, store=True)
|
||||||
|
|
||||||
|
def button_back(self):
|
||||||
|
if self.production_id.state == 'rework':
|
||||||
|
raise UserError('制造订单为返工时不能进行工单回退')
|
||||||
|
sorted_workorders = self.production_id.workorder_ids.filtered(lambda w: w.state != 'cancel').sorted(
|
||||||
|
key=lambda w: w.sequence)
|
||||||
|
position = next((idx for idx, workorder in enumerate(sorted_workorders) if workorder.id == self.id), -1)
|
||||||
|
cur_workorder = sorted_workorders[position]
|
||||||
|
if position == len(sorted_workorders) - 1:
|
||||||
|
# 末工序
|
||||||
|
picking_ids = cur_workorder.production_id.sale_order_id.picking_ids
|
||||||
|
finished_product_area = picking_ids.filtered(
|
||||||
|
lambda picking: picking.location_dest_id.name == '成品存货区' and picking.state == 'done'
|
||||||
|
)
|
||||||
|
moves = self.env['stock.move'].search([
|
||||||
|
('name', '=', cur_workorder.production_id.name),
|
||||||
|
('state', '!=', 'cancel')
|
||||||
|
])
|
||||||
|
finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None) or []
|
||||||
|
if any(
|
||||||
|
finish_move.move_dest_ids.ids in move.ids
|
||||||
|
for picking in finished_product_area
|
||||||
|
for move in picking.move_ids
|
||||||
|
):
|
||||||
|
raise UserError('已入库,无法回退')
|
||||||
|
else:
|
||||||
|
moves = self.env['stock.move'].search([
|
||||||
|
('name', '=', cur_workorder.production_id.name),
|
||||||
|
('state', '!=', 'cancel')
|
||||||
|
])
|
||||||
|
move_lines = self.env['stock.move.line'].search([
|
||||||
|
('reference', '=', cur_workorder.production_id.name),
|
||||||
|
('state', '!=', 'cancel')
|
||||||
|
])
|
||||||
|
moves.state = 'assigned'
|
||||||
|
external_assistance = move_lines.filtered(
|
||||||
|
lambda picking: picking.location_id.name != '外协线边仓'
|
||||||
|
)
|
||||||
|
external_assistance.state = 'assigned'
|
||||||
|
# move_lines.state = 'assigned'
|
||||||
|
self.time_ids.date_end = None
|
||||||
|
cur_workorder.state = 'progress'
|
||||||
|
cur_workorder.production_id.state = 'progress'
|
||||||
|
quality_check = self.env['quality.check'].search(
|
||||||
|
[('workorder_id', '=', self.id)])
|
||||||
|
for check_order in quality_check:
|
||||||
|
if check_order.point_id.is_inspect:
|
||||||
|
check_order.quality_state = 'waiting'
|
||||||
|
else:
|
||||||
|
check_order.quality_state = 'none'
|
||||||
|
# move_dest_ids
|
||||||
|
finished_quants = moves.mapped('move_line_ids.lot_id.quant_ids')
|
||||||
|
finished_quants.quantity = 0
|
||||||
|
finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None)
|
||||||
|
finish_move.move_dest_ids.reserved_availability = 0
|
||||||
|
finish_move.move_dest_ids.move_line_ids.state = 'draft'
|
||||||
|
finish_move.move_dest_ids.move_line_ids.unlink()
|
||||||
|
# finish_move.move_dest_ids.move_line_ids.reserved_uom_qty = 0
|
||||||
|
else:
|
||||||
|
next_workorder = sorted_workorders[position + 1]
|
||||||
|
next_state = next_workorder.state
|
||||||
|
if next_state not in ['pending', 'waiting', 'ready']:
|
||||||
|
raise UserError('下工序已经开始,无法回退')
|
||||||
|
if next_workorder.is_subcontract:
|
||||||
|
next_workorder.picking_ids.write({'state': 'waiting'})
|
||||||
|
next_workorder.state = 'pending'
|
||||||
|
self.time_ids.date_end = None
|
||||||
|
cur_workorder.state = 'progress'
|
||||||
|
cur_workorder.production_id.state = 'progress'
|
||||||
|
quality_check = self.env['quality.check'].search(
|
||||||
|
[('workorder_id', '=', self.id)])
|
||||||
|
for check_order in quality_check:
|
||||||
|
if check_order.point_id.is_inspect:
|
||||||
|
check_order.quality_state = 'waiting'
|
||||||
|
else:
|
||||||
|
check_order.quality_state = 'none'
|
||||||
|
|
||||||
def _compute_working_users(self):
|
def _compute_working_users(self):
|
||||||
super()._compute_working_users()
|
super()._compute_working_users()
|
||||||
for item in self:
|
for item in self:
|
||||||
@@ -156,7 +293,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
|
surface_technics_parameters_id = fields.Many2one('sf.production.process.parameter', string="表面工艺可选参数")
|
||||||
|
|
||||||
picking_ids = fields.Many2many('stock.picking', string='外协出入库单',
|
picking_ids = fields.Many2many('stock.picking', string='外协出入库单',
|
||||||
compute='_compute_surface_technics_picking_ids')
|
compute='_compute_surface_technics_picking_ids', store=True)
|
||||||
|
|
||||||
purchase_id = fields.Many2many('purchase.order', string='外协采购单')
|
purchase_id = fields.Many2many('purchase.order', string='外协采购单')
|
||||||
surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids')
|
surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids')
|
||||||
@@ -456,6 +593,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因", tracking=True)
|
("technology", "工艺"), ("customer redrawing", "客户改图")], string="原因", tracking=True)
|
||||||
detailed_reason = fields.Text('详细原因')
|
detailed_reason = fields.Text('详细原因')
|
||||||
is_rework = fields.Boolean(string='是否返工', default=False)
|
is_rework = fields.Boolean(string='是否返工', default=False)
|
||||||
|
|
||||||
# rework_flag = fields.Boolean(string='返工标志', compute='_compute_rework_flag')
|
# rework_flag = fields.Boolean(string='返工标志', compute='_compute_rework_flag')
|
||||||
#
|
#
|
||||||
# @api.depends('state', 'production_line_state')
|
# @api.depends('state', 'production_line_state')
|
||||||
@@ -1087,9 +1225,12 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
if (workorder.production_id.production_type == '人工线下加工'
|
if (workorder.production_id.production_type == '人工线下加工'
|
||||||
and workorder.production_id.schedule_state == '已排'
|
and workorder.production_id.schedule_state == '已排'
|
||||||
and len(workorder.production_id.picking_ids.filtered(
|
and len(workorder.production_id.picking_ids.filtered(
|
||||||
lambda w: w.state not in ['done', 'cancel'])) == 0
|
lambda w: w.state not in ['done', 'cancel'])) == 0):
|
||||||
and workorder.production_id.programming_state == '已编程'):
|
# and workorder.production_id.programming_state == '已编程'
|
||||||
if workorder.is_subcontract is True:
|
if workorder.is_subcontract is True:
|
||||||
|
if workorder.production_id.state == 'rework':
|
||||||
|
workorder.state = 'waiting'
|
||||||
|
continue
|
||||||
purchase_orders_id = self._get_surface_technics_purchase_ids()
|
purchase_orders_id = self._get_surface_technics_purchase_ids()
|
||||||
if purchase_orders_id.state == 'purchase':
|
if purchase_orders_id.state == 'purchase':
|
||||||
workorder.state = 'ready'
|
workorder.state = 'ready'
|
||||||
@@ -1104,6 +1245,9 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
else:
|
else:
|
||||||
workorder.state = 'waiting'
|
workorder.state = 'waiting'
|
||||||
continue
|
continue
|
||||||
|
elif workorder.routing_type == '人工线下加工':
|
||||||
|
if workorder.production_id.programming_state == '已编程':
|
||||||
|
workorder.state = 'ready'
|
||||||
else:
|
else:
|
||||||
workorder.state = 'ready'
|
workorder.state = 'ready'
|
||||||
continue
|
continue
|
||||||
@@ -1145,6 +1289,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
mo.get_move_line(workorder.production_id, workorder))
|
mo.get_move_line(workorder.production_id, workorder))
|
||||||
else:
|
else:
|
||||||
workorder.state = 'waiting'
|
workorder.state = 'waiting'
|
||||||
|
|
||||||
# 重写工单开始按钮方法
|
# 重写工单开始按钮方法
|
||||||
def button_start(self):
|
def button_start(self):
|
||||||
# 判断工单状态是否为等待组件
|
# 判断工单状态是否为等待组件
|
||||||
@@ -1311,7 +1456,8 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
'detailed_reason': record.detailed_reason,
|
'detailed_reason': record.detailed_reason,
|
||||||
'processing_panel': record.processing_panel,
|
'processing_panel': record.processing_panel,
|
||||||
'routing_type': record.routing_type,
|
'routing_type': record.routing_type,
|
||||||
'handle_result': '待处理' if record.test_results in ['返工', '报废'] or record.is_rework is True else '',
|
'handle_result': '待处理' if record.test_results in ['返工',
|
||||||
|
'报废'] or record.is_rework is True else '',
|
||||||
'test_results': record.test_results,
|
'test_results': record.test_results,
|
||||||
'test_report': record.detection_report})],
|
'test_report': record.detection_report})],
|
||||||
'is_scrap': True if record.test_results == '报废' else False
|
'is_scrap': True if record.test_results == '报废' else False
|
||||||
@@ -1328,7 +1474,8 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
raise UserError('请先完成该工单的工艺外协再进行操作')
|
raise UserError('请先完成该工单的工艺外协再进行操作')
|
||||||
# 表面工艺外协,最后一张工单
|
# 表面工艺外协,最后一张工单
|
||||||
workorders = self.production_id.workorder_ids
|
workorders = self.production_id.workorder_ids
|
||||||
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True and wo.state != 'cancel').sorted('sequence')
|
subcontract_workorders = workorders.filtered(
|
||||||
|
lambda wo: wo.is_subcontract == True and wo.state != 'cancel').sorted('sequence')
|
||||||
if self == subcontract_workorders[-1]:
|
if self == subcontract_workorders[-1]:
|
||||||
# 给下一个库存移动就绪
|
# 给下一个库存移动就绪
|
||||||
self.move_subcontract_workorder_ids[0].move_dest_ids._action_done()
|
self.move_subcontract_workorder_ids[0].move_dest_ids._action_done()
|
||||||
@@ -1385,6 +1532,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# ('state', '!=', 'done')])
|
# ('state', '!=', 'done')])
|
||||||
# if raw_move:
|
# if raw_move:
|
||||||
# raw_move.write({'state': 'done'})
|
# raw_move.write({'state': 'done'})
|
||||||
|
if record.production_id.state != 'rework':
|
||||||
record.production_id.button_mark_done1()
|
record.production_id.button_mark_done1()
|
||||||
# record.production_id.state = 'done'
|
# record.production_id.state = 'done'
|
||||||
|
|
||||||
@@ -1551,6 +1699,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# 根据工单对应的【作业_个性化记录】配置页签
|
# 根据工单对应的【作业_个性化记录】配置页签
|
||||||
if any(item.code == 'PTD' for item in mw.routing_workcenter_id.individuation_page_ids):
|
if any(item.code == 'PTD' for item in mw.routing_workcenter_id.individuation_page_ids):
|
||||||
mw.individuation_page_PTD = True
|
mw.individuation_page_PTD = True
|
||||||
|
|
||||||
# =============================================================================================
|
# =============================================================================================
|
||||||
|
|
||||||
is_inspect = fields.Boolean('需送检', compute='_compute_is_inspect', store=True, default=False)
|
is_inspect = fields.Boolean('需送检', compute='_compute_is_inspect', store=True, default=False)
|
||||||
@@ -1860,7 +2009,10 @@ class WorkPieceDelivery(models.Model):
|
|||||||
feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站')
|
feeder_station_destination_id = fields.Many2one('sf.agv.site', '目的接驳站')
|
||||||
task_delivery_time = fields.Datetime('任务下发时间')
|
task_delivery_time = fields.Datetime('任务下发时间')
|
||||||
task_completion_time = fields.Datetime('任务完成时间')
|
task_completion_time = fields.Datetime('任务完成时间')
|
||||||
type = fields.Selection(related='route_id.route_type', string='类型')
|
|
||||||
|
def _get_agv_route_type_selection(self):
|
||||||
|
return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection']
|
||||||
|
type = fields.Selection(selection=_get_agv_route_type_selection, string='类型')
|
||||||
delivery_duration = fields.Float('配送时长', compute='_compute_delivery_duration')
|
delivery_duration = fields.Float('配送时长', compute='_compute_delivery_duration')
|
||||||
status = fields.Selection(
|
status = fields.Selection(
|
||||||
[('待下发', '待下发'), ('已下发', '待配送'), ('已配送', '已配送'), ('已取消', '已取消')], string='状态',
|
[('待下发', '待下发'), ('已下发', '待配送'), ('已配送', '已配送'), ('已取消', '已取消')], string='状态',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
|
import re
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from odoo import api, fields, models, _
|
from odoo import api, fields, models, _
|
||||||
@@ -109,13 +109,35 @@ class PurchaseOrder(models.Model):
|
|||||||
class PurchaseOrderLine(models.Model):
|
class PurchaseOrderLine(models.Model):
|
||||||
_inherit = 'purchase.order.line'
|
_inherit = 'purchase.order.line'
|
||||||
|
|
||||||
part_number = fields.Char('零件图号', related='product_id.part_number', readonly=True)
|
part_number = fields.Char('零件图号', store=True, compute='_compute_related_product')
|
||||||
|
part_name = fields.Char('零件名称', store=True,
|
||||||
|
compute='_compute_related_product')
|
||||||
related_product = fields.Many2one('product.product', string='关联产品',
|
related_product = fields.Many2one('product.product', string='关联产品',
|
||||||
help='经此产品工艺加工成的成品')
|
help='经此产品工艺加工成的成品')
|
||||||
|
@api.depends('product_id')
|
||||||
# @api.depends('order_id.origin')
|
def _compute_related_product(self):
|
||||||
# def _compute_related_product(self):
|
for record in self:
|
||||||
# for record in self:
|
if record.product_id.categ_id.name == '坯料':
|
||||||
|
product_name = ''
|
||||||
|
match = re.search(r'(S\d{5}-\d)', record.product_id.name)
|
||||||
|
# 如果匹配成功,提取结果
|
||||||
|
if match:
|
||||||
|
product_name = match.group(0)
|
||||||
|
sale_order_name = ''
|
||||||
|
match_sale = re.search(r'S(\d+)', record.product_id.name)
|
||||||
|
if match_sale:
|
||||||
|
sale_order_name = match_sale.group(0)
|
||||||
|
sale_order = self.env['sale.order'].sudo().search(
|
||||||
|
[('name', '=', sale_order_name)])
|
||||||
|
if sale_order:
|
||||||
|
filtered_order_line = sale_order.order_line.filtered(
|
||||||
|
lambda order_line: re.search(f'{product_name}$', order_line.product_id.name)
|
||||||
|
)
|
||||||
|
record.part_number = filtered_order_line.product_id.part_number if filtered_order_line else None
|
||||||
|
record.part_name = filtered_order_line.product_id.part_name if filtered_order_line else None
|
||||||
|
else:
|
||||||
|
record.part_number = record.product_id.part_number
|
||||||
|
record.part_name = record.product_id.part_name
|
||||||
# if record.product_id.detailed_type:
|
# if record.product_id.detailed_type:
|
||||||
# production_id = self.env['mrp.production'].search([('name', '=', record.order_id.origin)])
|
# production_id = self.env['mrp.production'].search([('name', '=', record.order_id.origin)])
|
||||||
# record.related_product = production_id.product_id if production_id else False
|
# record.related_product = production_id.product_id if production_id else False
|
||||||
|
|||||||
@@ -3,5 +3,6 @@ from odoo import fields, models, api
|
|||||||
|
|
||||||
class QualityCheck(models.Model):
|
class QualityCheck(models.Model):
|
||||||
_inherit = "quality.check"
|
_inherit = "quality.check"
|
||||||
|
_description = "质量检查"
|
||||||
|
|
||||||
is_inspect = fields.Boolean('需送检')
|
is_inspect = fields.Boolean('需送检')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
from odoo import models, fields, api
|
from odoo import models, fields, api, _
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
_logger = logging.getLogger(__name__)
|
_logger = logging.getLogger(__name__)
|
||||||
@@ -24,6 +24,8 @@ class SaleOrder(models.Model):
|
|||||||
self.state = 'supply method'
|
self.state = 'supply method'
|
||||||
|
|
||||||
def action_confirm(self):
|
def action_confirm(self):
|
||||||
|
if self._get_forbidden_state_confirm() & set(self.mapped('state')):
|
||||||
|
raise UserError(_('订单状态已发生变化,请刷新当前页面'))
|
||||||
# 判断是否所有产品都选择了供货方式
|
# 判断是否所有产品都选择了供货方式
|
||||||
filter_line = self.order_line.filtered(lambda line: not line.supply_method)
|
filter_line = self.order_line.filtered(lambda line: not line.supply_method)
|
||||||
if filter_line:
|
if filter_line:
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import base64
|
import base64
|
||||||
|
import random
|
||||||
|
import re
|
||||||
|
|
||||||
import qrcode
|
import qrcode
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
@@ -449,25 +452,15 @@ class ProductionLot(models.Model):
|
|||||||
"""Return the next serial number to be attributed to the product."""
|
"""Return the next serial number to be attributed to the product."""
|
||||||
if product.tracking == "serial":
|
if product.tracking == "serial":
|
||||||
last_serial = self.env['stock.lot'].search(
|
last_serial = self.env['stock.lot'].search(
|
||||||
[('company_id', '=', company.id), ('product_id', '=', product.id)],
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('name', 'ilike', product.name)],
|
||||||
limit=1, order='name desc')
|
limit=1, order='name desc')
|
||||||
if last_serial:
|
move_line_id = self.env['stock.move.line'].sudo().search(
|
||||||
if product.categ_id.name == '刀具':
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('lot_name', 'ilike', product.name)],
|
||||||
return self.env['stock.lot'].get_tool_generate_lot_names1(company, product)
|
limit=1, order='lot_name desc')
|
||||||
else:
|
if last_serial or move_line_id:
|
||||||
# 对last_serial的name进行检测,如果不是以产品名称+数字的形式的就重新搜索
|
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name if (
|
||||||
if product.name.split('[')[0] not in last_serial.name:
|
not move_line_id or
|
||||||
last_serial = self.env['stock.lot'].search(
|
(last_serial and last_serial.name > move_line_id.lot_name)) else move_line_id.lot_name, 2)[1]
|
||||||
[('company_id', '=', company.id), ('product_id', '=', product.id),
|
|
||||||
('name', 'ilike', product.name.split('[')[0])],
|
|
||||||
limit=1, order='name desc')
|
|
||||||
if not last_serial:
|
|
||||||
return "%s-%03d" % (product.name, 1)
|
|
||||||
return self.env['stock.lot'].generate_lot_names1(product.name, last_serial.name, 2)[1]
|
|
||||||
now = datetime.now().strftime("%Y%m%d")
|
|
||||||
if product.cutting_tool_model_id:
|
|
||||||
split_codes = product.cutting_tool_model_id.code.split('-')
|
|
||||||
return "%s-T-%s-%s-%03d" % (split_codes[0], now, product.specification_id.name, 1)
|
|
||||||
return "%s-%03d" % (product.name, 1)
|
return "%s-%03d" % (product.name, 1)
|
||||||
|
|
||||||
qr_code_image = fields.Binary(string='二维码', compute='_generate_qr_code')
|
qr_code_image = fields.Binary(string='二维码', compute='_generate_qr_code')
|
||||||
@@ -632,12 +625,12 @@ class StockPicking(models.Model):
|
|||||||
workorder = move_in.subcontract_workorder_id
|
workorder = move_in.subcontract_workorder_id
|
||||||
workorders = workorder.production_id.workorder_ids
|
workorders = workorder.production_id.workorder_ids
|
||||||
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True and wo.state!='cancel').sorted('sequence')
|
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True and wo.state!='cancel').sorted('sequence')
|
||||||
if workorder == subcontract_workorders[-1]:
|
# if workorder == subcontract_workorders[-1]:
|
||||||
self.env['stock.quant']._update_reserved_quantity(
|
# self.env['stock.quant']._update_reserved_quantity(
|
||||||
move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty,
|
# move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty,
|
||||||
lot_id=move_in.move_line_ids.lot_id,
|
# lot_id=move_in.move_line_ids.lot_id,
|
||||||
package_id=False, owner_id=False, strict=False
|
# package_id=False, owner_id=False, strict=False
|
||||||
)
|
# )
|
||||||
workorder.button_finish()
|
workorder.button_finish()
|
||||||
picking_type_out = self.env.ref('sf_manufacturing.outcontract_picking_out').id
|
picking_type_out = self.env.ref('sf_manufacturing.outcontract_picking_out').id
|
||||||
if res and self.picking_type_id.id == picking_type_out:
|
if res and self.picking_type_id.id == picking_type_out:
|
||||||
@@ -653,6 +646,16 @@ class StockPicking(models.Model):
|
|||||||
stock_picking = stock_picking_list.filtered(lambda p: p.state not in ("done", "cancel"))
|
stock_picking = stock_picking_list.filtered(lambda p: p.state not in ("done", "cancel"))
|
||||||
if sale_id and not stock_picking:
|
if sale_id and not stock_picking:
|
||||||
sale_id.write({'state': 'delivered'})
|
sale_id.write({'state': 'delivered'})
|
||||||
|
if self.location_dest_id.name == '成品存货区' and self.state == 'done':
|
||||||
|
for move in self.move_ids:
|
||||||
|
for production in self.sale_order_id.mrp_production_ids:
|
||||||
|
moves = self.env['stock.move'].search([
|
||||||
|
('name', '=', production.name),
|
||||||
|
('state', '!=', 'cancel')
|
||||||
|
])
|
||||||
|
finish_move = next((move for move in moves if move.location_dest_id.name == '制造后'), None)
|
||||||
|
if finish_move.id in move.move_orig_ids.ids and finish_move.state == 'done':
|
||||||
|
production.workorder_ids.write({'back_button_display': False})
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# 创建 外协出库入单
|
# 创建 外协出库入单
|
||||||
@@ -691,8 +694,8 @@ class StockPicking(models.Model):
|
|||||||
picking_in = self.create(
|
picking_in = self.create(
|
||||||
moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
|
moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
|
||||||
# pick_ids.append(picking_in.id)
|
# pick_ids.append(picking_in.id)
|
||||||
moves_in.write(
|
moves_in.write({'picking_id': picking_in.id})
|
||||||
{'picking_id': picking_in.id, 'state': 'waiting'})
|
moves_in._action_confirm()
|
||||||
moves_in._assign_picking_post_process(new=new_picking)
|
moves_in._assign_picking_post_process(new=new_picking)
|
||||||
# self.env.context.get('default_production_id')
|
# self.env.context.get('default_production_id')
|
||||||
moves_out = self.env['stock.move'].sudo().with_context(context).create(
|
moves_out = self.env['stock.move'].sudo().with_context(context).create(
|
||||||
@@ -702,8 +705,8 @@ class StockPicking(models.Model):
|
|||||||
picking_out = self.create(
|
picking_out = self.create(
|
||||||
moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/'))
|
moves_out._get_new_picking_values_Res(item, workorder, 'WH/OCOUT/'))
|
||||||
# pick_ids.append(picking_out.id)
|
# pick_ids.append(picking_out.id)
|
||||||
moves_out.write(
|
moves_out.write({'picking_id': picking_out.id})
|
||||||
{'picking_id': picking_out.id, 'state': 'waiting'})
|
moves_out._action_confirm()
|
||||||
moves_out._assign_picking_post_process(new=new_picking)
|
moves_out._assign_picking_post_process(new=new_picking)
|
||||||
|
|
||||||
@api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id')
|
@api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id')
|
||||||
@@ -721,6 +724,20 @@ class StockPicking(models.Model):
|
|||||||
'draft', 'sent']:
|
'draft', 'sent']:
|
||||||
picking.state = 'waiting'
|
picking.state = 'waiting'
|
||||||
|
|
||||||
|
@api.constrains('state', 'move_ids_without_package')
|
||||||
|
def _check_move_ids_without_package(self):
|
||||||
|
"""
|
||||||
|
凡库存调拨单的【作业类型】=“收料入库、客供料入库”,且其产品行的【产品_库存_追溯】="按唯一序列号/按批次”的,当调拨单的【状态】=就绪时
|
||||||
|
自动生成预分配序列号
|
||||||
|
"""
|
||||||
|
for sp in self:
|
||||||
|
if (sp.picking_type_id.use_existing_lots is False and sp.picking_type_id.use_create_lots is True
|
||||||
|
and sp.state == 'assigned'):
|
||||||
|
if sp.move_ids_without_package:
|
||||||
|
for move_id in sp.move_ids_without_package:
|
||||||
|
if move_id.product_id.tracking in ['serial', 'lot'] and not move_id.move_line_nosuggest_ids:
|
||||||
|
move_id.action_show_details()
|
||||||
|
|
||||||
|
|
||||||
class ReStockMove(models.Model):
|
class ReStockMove(models.Model):
|
||||||
_inherit = 'stock.move'
|
_inherit = 'stock.move'
|
||||||
@@ -738,25 +755,27 @@ class ReStockMove(models.Model):
|
|||||||
move.part_number = move.product_id.part_number
|
move.part_number = move.product_id.part_number
|
||||||
move.part_name = move.product_id.part_name
|
move.part_name = move.product_id.part_name
|
||||||
elif move.product_id.categ_id.type == '坯料':
|
elif move.product_id.categ_id.type == '坯料':
|
||||||
if move.origin:
|
product_name = ''
|
||||||
origin = move.origin.split(',')[0] if ',' in move.origin else move.origin
|
match = re.search(r'(S\d{5}-\d)', move.product_id.name)
|
||||||
mrp_productio_info = self.env['mrp.production'].sudo().search(
|
# 如果匹配成功,提取结果
|
||||||
[('name', '=', origin)])
|
if match:
|
||||||
if mrp_productio_info:
|
product_name = match.group(0)
|
||||||
move.part_number = mrp_productio_info.part_number
|
if move.picking_id.sale_order_id:
|
||||||
move.part_name = mrp_productio_info.part_name
|
sale_order = move.picking_id.sale_order_id
|
||||||
else:
|
else:
|
||||||
purchase_order_info = self.env['purchase.order'].sudo().search(
|
sale_order_name = ''
|
||||||
[('name', '=', origin)])
|
match = re.search(r'(S\d+)', move.product_id.name)
|
||||||
if purchase_order_info:
|
if match:
|
||||||
mrp_production_ids = purchase_order_info._get_mrp_productions().ids
|
sale_order_name = match.group(0)
|
||||||
if mrp_production_ids:
|
sale_order = self.env['sale.order'].sudo().search(
|
||||||
mrp_productio_info = self.env['mrp.production'].sudo().search(
|
[('name', '=', sale_order_name)])
|
||||||
[('id', '=', mrp_production_ids[0])])
|
filtered_order_line = sale_order.order_line.filtered(
|
||||||
if mrp_productio_info:
|
lambda production: re.search(f'{product_name}$', production.product_id.name)
|
||||||
move.part_number = mrp_productio_info.part_number
|
)
|
||||||
move.part_name = mrp_productio_info.part_name
|
|
||||||
|
|
||||||
|
if filtered_order_line:
|
||||||
|
move.part_number = filtered_order_line.part_number
|
||||||
|
move.part_name = filtered_order_line.part_name
|
||||||
def _get_stock_move_values_Res(self, item, picking_type_id, group_id, move_dest_ids=False):
|
def _get_stock_move_values_Res(self, item, picking_type_id, group_id, move_dest_ids=False):
|
||||||
route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
|
route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
|
||||||
stock_rule = self.env['stock.rule'].sudo().search(
|
stock_rule = self.env['stock.rule'].sudo().search(
|
||||||
@@ -860,6 +879,7 @@ class ReStockMove(models.Model):
|
|||||||
and self.picking_type_id.use_create_lots is True and not self.move_line_nosuggest_ids):
|
and self.picking_type_id.use_create_lots is True and not self.move_line_nosuggest_ids):
|
||||||
self.action_assign_serial_show_details()
|
self.action_assign_serial_show_details()
|
||||||
elif self.product_id.tracking == "lot":
|
elif self.product_id.tracking == "lot":
|
||||||
|
if self.product_id.categ_id.name == '刀具':
|
||||||
self._put_tool_lot(self.company_id, self.product_id, self.origin)
|
self._put_tool_lot(self.company_id, self.product_id, self.origin)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -885,37 +905,22 @@ class ReStockMove(models.Model):
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
def put_move_line(self):
|
|
||||||
"""
|
|
||||||
确认订单时,自动分配序列号
|
|
||||||
"""
|
|
||||||
if self.product_id.tracking == "serial":
|
|
||||||
if self.product_id.categ_id.name == '刀具':
|
|
||||||
self.next_serial = self._get_tool_next_serial(self.company_id, self.product_id, self.origin)
|
|
||||||
else:
|
|
||||||
self.next_serial = self.env['stock.lot']._get_next_serial(self.company_id, self.product_id)
|
|
||||||
self._generate_serial_numbers()
|
|
||||||
for item in self.move_line_nosuggest_ids:
|
|
||||||
if item.lot_name:
|
|
||||||
lot_name = item.lot_name
|
|
||||||
if item.product_id.categ_id.name == '坯料':
|
|
||||||
lot_name = lot_name.split('[', 1)[0]
|
|
||||||
item.lot_qr_code = self.compute_lot_qr_code(lot_name)
|
|
||||||
|
|
||||||
def _put_tool_lot(self, company, product, origin):
|
def _put_tool_lot(self, company, product, origin):
|
||||||
if product.tracking == "lot" and self.product_id.categ_id.name == '刀具':
|
if product.tracking == "lot" and self.product_id.categ_id.name == '刀具':
|
||||||
if not self.move_line_nosuggest_ids:
|
if not self.move_line_nosuggest_ids:
|
||||||
lot_code = '%s-%s-%s' % ('%s-T-DJWL-%s' % (
|
lot_code = '%s-%s-%s' % ('%s-T-DJWL-%s' % (
|
||||||
product.cutting_tool_model_id.code.split('-')[0], product.cutting_tool_material_id.code),
|
product.cutting_tool_model_id.code.split('-')[0], product.cutting_tool_material_id.code),
|
||||||
datetime.now().strftime("%Y%m%d"), origin)
|
datetime.now().strftime("%Y%m%d"), origin)
|
||||||
move_line_ids = self.env['stock.move.line'].sudo().search([('lot_name', 'like', lot_code)], limit=1,
|
move_line_ids = self.env['stock.move.line'].sudo().search(
|
||||||
order='id desc')
|
[('company_id', '=', company.id), ('lot_name', 'like', lot_code)], limit=1, order='id desc')
|
||||||
if not move_line_ids:
|
if not move_line_ids:
|
||||||
lot_code = '%s-001' % lot_code
|
lot_code = '%s-001' % lot_code
|
||||||
else:
|
else:
|
||||||
lot_code = '%s-%03d' % (lot_code, int(move_line_ids.lot_name[-3:]) + 1)
|
lot_code = '%s-%03d' % (lot_code, int(move_line_ids.lot_name[-3:]) + 1)
|
||||||
lot_names = self.env['stock.lot'].generate_lot_names(lot_code, 1)
|
lot_names = self.env['stock.lot'].generate_lot_names(lot_code, 1)
|
||||||
move_lines_commands = self._generate_serial_move_line_commands_tool_lot(lot_names)
|
move_lines_commands = self._generate_serial_move_line_commands_tool_lot(lot_names)
|
||||||
|
for move_lines_command in move_lines_commands:
|
||||||
|
move_lines_command[2]['qty_done'] = self.product_uom_qty
|
||||||
self.write({'move_line_nosuggest_ids': move_lines_commands})
|
self.write({'move_line_nosuggest_ids': move_lines_commands})
|
||||||
for item in self.move_line_nosuggest_ids:
|
for item in self.move_line_nosuggest_ids:
|
||||||
if item.lot_name:
|
if item.lot_name:
|
||||||
@@ -943,10 +948,16 @@ class ReStockMove(models.Model):
|
|||||||
last_serial = self.env['stock.lot'].search(
|
last_serial = self.env['stock.lot'].search(
|
||||||
[('company_id', '=', company.id), ('product_id', '=', product.id), ('name', 'ilike', origin)],
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('name', 'ilike', origin)],
|
||||||
limit=1, order='id DESC')
|
limit=1, order='id DESC')
|
||||||
|
move_line_id = self.env['stock.move.line'].sudo().search(
|
||||||
|
[('company_id', '=', company.id), ('product_id', '=', product.id), ('lot_name', 'ilike', origin)],
|
||||||
|
limit=1, order='lot_name desc')
|
||||||
split_codes = product.cutting_tool_model_id.code.split('-')
|
split_codes = product.cutting_tool_model_id.code.split('-')
|
||||||
if last_serial:
|
if last_serial or move_line_id:
|
||||||
return "%s-T-%s-%s-%03d" % (
|
return "%s-T-%s-%s-%03d" % (
|
||||||
split_codes[0], origin, product.specification_id.name, int(last_serial.name[-3:]) + 1)
|
split_codes[0], origin, product.specification_id.name,
|
||||||
|
int(last_serial.name[-3:] if (not move_line_id or
|
||||||
|
(last_serial and last_serial.name > move_line_id.lot_name))
|
||||||
|
else move_line_id.lot_name[-3:]) + 1)
|
||||||
else:
|
else:
|
||||||
return "%s-T-%s-%s-%03d" % (split_codes[0], origin, product.specification_id.name, 1)
|
return "%s-T-%s-%s-%03d" % (split_codes[0], origin, product.specification_id.name, 1)
|
||||||
|
|
||||||
@@ -1042,6 +1053,15 @@ class ReStockMove(models.Model):
|
|||||||
subcontract_workorder_id = fields.Many2one('mrp.workorder', '外协工单组件', check_company=True,
|
subcontract_workorder_id = fields.Many2one('mrp.workorder', '外协工单组件', check_company=True,
|
||||||
index='btree_not_null')
|
index='btree_not_null')
|
||||||
|
|
||||||
|
def button_update_the_sequence_number(self):
|
||||||
|
"""
|
||||||
|
更新序列号 功能按钮
|
||||||
|
"""
|
||||||
|
self.move_line_nosuggest_ids.unlink()
|
||||||
|
if self.state != 'assigned':
|
||||||
|
self.state = 'assigned'
|
||||||
|
return self.action_show_details()
|
||||||
|
|
||||||
|
|
||||||
class ReStockQuant(models.Model):
|
class ReStockQuant(models.Model):
|
||||||
_inherit = 'stock.quant'
|
_inherit = 'stock.quant'
|
||||||
|
|||||||
@@ -193,4 +193,4 @@ access_sf_programming_record,sf_programming_record,model_sf_programming_record,b
|
|||||||
access_sf_work_individuation_page,sf_work_individuation_page,model_sf_work_individuation_page,sf_base.group_sf_mrp_user,1,1,1,0
|
access_sf_work_individuation_page,sf_work_individuation_page,model_sf_work_individuation_page,sf_base.group_sf_mrp_user,1,1,1,0
|
||||||
access_sf_work_individuation_page_group_plan_dispatch,sf_work_individuation_page_group_plan_dispatch,model_sf_work_individuation_page,sf_base.group_plan_dispatch,1,1,0,0
|
access_sf_work_individuation_page_group_plan_dispatch,sf_work_individuation_page_group_plan_dispatch,model_sf_work_individuation_page,sf_base.group_plan_dispatch,1,1,0,0
|
||||||
access_sf_sale_order_cancel_wizard,sf_sale_order_cancel_wizard,model_sf_sale_order_cancel_wizard,sf_base.group_sf_order_user,1,1,1,0
|
access_sf_sale_order_cancel_wizard,sf_sale_order_cancel_wizard,model_sf_sale_order_cancel_wizard,sf_base.group_sf_order_user,1,1,1,0
|
||||||
access_sf_sale_order_cancel_line,sf_sale_order_cancel_line,model_sf_sale_order_cancel_line,sf_base.group_sf_order_user,1,1,1,0
|
access_sf_sale_order_cancel_line,sf_sale_order_cancel_line,model_sf_sale_order_cancel_line,sf_base.group_sf_order_user,1,0,1,1
|
||||||
|
@@ -116,12 +116,13 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//sheet//group//group//div[3]" position="after">
|
<xpath expr="//sheet//group//group//div[3]" position="after">
|
||||||
<field name="production_type" readonly="1"/>
|
<field name="production_type" readonly="1"/>
|
||||||
|
<field name="production_product_type" invisible="1"/>
|
||||||
<field name="manual_quotation" readonly="1"
|
<field name="manual_quotation" readonly="1"
|
||||||
attrs="{'invisible': [('production_type', 'not in', ['自动化产线加工', '人工线下加工'])]}"/>
|
attrs="{'invisible': ['|', ('production_type', 'not in', ['自动化产线加工', '人工线下加工']), ('production_product_type', '!=', '成品')]}"/>
|
||||||
<field name="programming_no" readonly="1"
|
<field name="programming_no" readonly="1"
|
||||||
attrs="{'invisible': [('production_type', 'not in', ['自动化产线加工', '人工线下加工'])]}"/>
|
attrs="{'invisible': ['|', ('production_type', 'not in', ['自动化产线加工', '人工线下加工']), ('production_product_type', '!=', '成品')]}"/>
|
||||||
<field name="programming_state" readonly="1"
|
<field name="programming_state" readonly="1"
|
||||||
attrs="{'invisible': [('production_type', 'not in', ['自动化产线加工', '人工线下加工'])]}"
|
attrs="{'invisible': ['|', ('production_type', 'not in', ['自动化产线加工', '人工线下加工']), ('production_product_type', '!=', '成品')]}"
|
||||||
decoration-success="programming_state == '已编程'"
|
decoration-success="programming_state == '已编程'"
|
||||||
decoration-warning="programming_state =='编程中'"
|
decoration-warning="programming_state =='编程中'"
|
||||||
decoration-danger="programming_state =='已编程未下发'"/>
|
decoration-danger="programming_state =='已编程未下发'"/>
|
||||||
@@ -416,7 +417,9 @@
|
|||||||
<span class="o_stat_text">子MO</span>
|
<span class="o_stat_text">子MO</span>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//sheet//notebook//page[last()]" position="after">
|
<xpath expr="//sheet//notebook//page[last()]" position="after">
|
||||||
<page string="编程记录">
|
<page string="编程记录" attrs="{'invisible': ['|', ('production_type', 'not in', ['自动化产线加工', '人工线下加工']), ('production_product_type', '!=', '成品')]}">
|
||||||
|
<field name="production_type" invisible="1"/>
|
||||||
|
<field name="production_product_type" invisible="1"/>
|
||||||
<field name="programming_record_ids" widget="one2many" attrs="{'readonly': [('id', '!=', False)]}">
|
<field name="programming_record_ids" widget="one2many" attrs="{'readonly': [('id', '!=', False)]}">
|
||||||
<tree>
|
<tree>
|
||||||
<field name="number"/>
|
<field name="number"/>
|
||||||
@@ -795,7 +798,7 @@
|
|||||||
groups="sf_base.group_plan_dispatch,sf_base.group_sf_mrp_manager"
|
groups="sf_base.group_plan_dispatch,sf_base.group_sf_mrp_manager"
|
||||||
sequence="1"/>
|
sequence="1"/>
|
||||||
|
|
||||||
<menuitem id="stock_picking_type_menu"
|
<menuitem id="stock.stock_picking_type_menu"
|
||||||
name="驾驶舱"
|
name="驾驶舱"
|
||||||
parent="stock.menu_stock_root"
|
parent="stock.menu_stock_root"
|
||||||
action="stock.stock_picking_type_action"
|
action="stock.stock_picking_type_action"
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='date_planned_finished']" position="replace">
|
<xpath expr="//field[@name='date_planned_finished']" position="replace">
|
||||||
<field name="date_planned_finished" string="计划结束日期" optional="hide"/>
|
<field name="date_planned_finished" string="计划结束日期" optional="hide"/>
|
||||||
|
<field name="back_button_display" invisible="1"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//button[@name='button_start']" position="attributes">
|
<xpath expr="//button[@name='button_start']" position="attributes">
|
||||||
<!-- <attribute name="attrs">{'invisible': ['|', '|', '|','|','|', ('production_state','in', ('draft',-->
|
<!-- <attribute name="attrs">{'invisible': ['|', '|', '|','|','|', ('production_state','in', ('draft',-->
|
||||||
@@ -58,6 +59,11 @@
|
|||||||
<attribute name="attrs">{'invisible': [('state', '!=', 'ready')]}
|
<attribute name="attrs">{'invisible': [('state', '!=', 'ready')]}
|
||||||
</attribute>
|
</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|
||||||
|
<xpath expr="//button[@name='button_start']" position="after">
|
||||||
|
<button name="button_back" string="回退" type="object" class="btn-primary"
|
||||||
|
attrs="{'invisible': [('back_button_display', '=', False)]}" confirm="是否确认回退"/>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="attributes">
|
<xpath expr="//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="attributes">
|
||||||
<attribute name="attrs">{'invisible':
|
<attribute name="attrs">{'invisible':
|
||||||
['|',("user_permissions","=",False),("name","=","获取CNC加工程序")]}
|
['|',("user_permissions","=",False),("name","=","获取CNC加工程序")]}
|
||||||
@@ -163,6 +169,7 @@
|
|||||||
<field name='is_delivery' invisible="1"/>
|
<field name='is_delivery' invisible="1"/>
|
||||||
<field name="is_trayed" invisible="1"/>
|
<field name="is_trayed" invisible="1"/>
|
||||||
<field name="is_inspect" invisible="1"/>
|
<field name="is_inspect" invisible="1"/>
|
||||||
|
<field name="back_button_display" invisible="1"/>
|
||||||
<!-- <field name="rework_flag" invisible="1"/>-->
|
<!-- <field name="rework_flag" invisible="1"/>-->
|
||||||
<!-- <field name='is_send_program_again' invisible="1"/>-->
|
<!-- <field name='is_send_program_again' invisible="1"/>-->
|
||||||
<!-- 工单form页面的开始停工按钮等 -->
|
<!-- 工单form页面的开始停工按钮等 -->
|
||||||
@@ -178,6 +185,8 @@
|
|||||||
|
|
||||||
<!-- <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始"-->
|
<!-- <button name="button_start" type="object" string="开始" class="btn-success" confirm="是否确认开始"-->
|
||||||
<!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>-->
|
<!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel','to be detected')), ('is_user_working', '!=', False)]}"/>-->
|
||||||
|
<button name="button_back" string="回退" type="object" class="btn-primary"
|
||||||
|
attrs="{'invisible': [('back_button_display', '=', False)]}" confirm="是否确认回退"/>
|
||||||
<button name="button_start" type="object" string="开始" class="btn-success"
|
<button name="button_start" type="object" string="开始" class="btn-success"
|
||||||
attrs="{'invisible': [('state', '!=', 'ready')]}"/>
|
attrs="{'invisible': [('state', '!=', 'ready')]}"/>
|
||||||
<button name="button_pending" type="object" string="暂停" class="btn-warning"
|
<button name="button_pending" type="object" string="暂停" class="btn-warning"
|
||||||
@@ -193,7 +202,8 @@
|
|||||||
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}"/>
|
attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}"/>
|
||||||
<button name="do_inspect" type="object" string="送检" class="btn-success" confirm="是否确认送检"
|
<button name="do_inspect" type="object" string="送检" class="btn-success" confirm="是否确认送检"
|
||||||
attrs="{'invisible': ['|', '|', ('state', 'not in', ('progress')), ('is_inspect', '=', False), ('routing_type','=','CNC加工')]}"/>
|
attrs="{'invisible': ['|', '|', ('state', 'not in', ('progress')), ('is_inspect', '=', False), ('routing_type','=','CNC加工')]}"/>
|
||||||
|
<button name="do_inspect" type="object" string="送检" class="btn-success" confirm="是否确认送检"
|
||||||
|
attrs="{'invisible': ['|', '|', ('state', 'not in', ('progress')), ('is_inspect', '=', False), ('production_line_state','!=','已下产线')]}"/>
|
||||||
<!-- <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工" -->
|
<!-- <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工" -->
|
||||||
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
|
<!-- context="{'default_workcenter_id': workcenter_id}" class="btn-danger" -->
|
||||||
<!-- groups="sf_base.group_sf_mrp_user" -->
|
<!-- groups="sf_base.group_sf_mrp_user" -->
|
||||||
@@ -217,7 +227,8 @@
|
|||||||
<!-- attrs='{"invisible": [("rework_flag","=",True)]}' confirm="是否返工"/>-->
|
<!-- attrs='{"invisible": [("rework_flag","=",True)]}' confirm="是否返工"/>-->
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//page[1]" position="before">
|
<xpath expr="//page[1]" position="before">
|
||||||
<page string="开料要求" attrs='{"invisible": [("routing_type","not in",("切割", "线切割", "人工线下加工"))]}'>
|
<page string="开料要求"
|
||||||
|
attrs='{"invisible": [("routing_type","not in",("切割", "线切割", "人工线下加工"))]}'>
|
||||||
<group>
|
<group>
|
||||||
<group>
|
<group>
|
||||||
<field name="product_tmpl_id_materials_id" widget="many2one"/>
|
<field name="product_tmpl_id_materials_id" widget="many2one"/>
|
||||||
@@ -493,7 +504,8 @@
|
|||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
<page string="2D加工图纸" attrs='{"invisible": [("routing_type","not in",["装夹预调", "人工线下加工"])]}'>
|
<page string="2D加工图纸"
|
||||||
|
attrs='{"invisible": [("routing_type","not in",["装夹预调", "人工线下加工"])]}'>
|
||||||
<field name="machining_drawings" widget="adaptive_viewer"/>
|
<field name="machining_drawings" widget="adaptive_viewer"/>
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
@@ -642,7 +654,8 @@
|
|||||||
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
|
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//form//sheet//group//group[2]" position="replace">
|
<xpath expr="//form//sheet//group//group[2]" position="replace">
|
||||||
<group string="装夹图纸" attrs="{'invisible': [('routing_type', 'not in', ['装夹预调', '人工线下加工'])]}">
|
<group string="装夹图纸"
|
||||||
|
attrs="{'invisible': [('routing_type', 'not in', ['装夹预调', '人工线下加工'])]}">
|
||||||
<!-- 隐藏加工图纸字段名 -->
|
<!-- 隐藏加工图纸字段名 -->
|
||||||
<field name="processing_drawing" widget="pdf_viewer" string="" readonly="1"/>
|
<field name="processing_drawing" widget="pdf_viewer" string="" readonly="1"/>
|
||||||
<!-- <field name="production_id" invisible="0"/>-->
|
<!-- <field name="production_id" invisible="0"/>-->
|
||||||
|
|||||||
@@ -74,5 +74,30 @@
|
|||||||
<field name="view_ids" eval="[(5, 0, 0),
|
<field name="view_ids" eval="[(5, 0, 0),
|
||||||
(0, 0, {'view_mode': 'tree', 'view_id': ref('stock.vpicktree')})]"/>
|
(0, 0, {'view_mode': 'tree', 'view_id': ref('stock.vpicktree')})]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="sf_view_stock_move_operations" model="ir.ui.view">
|
||||||
|
<field name="name">sf.stock.move.operations.form</field>
|
||||||
|
<field name="model">stock.move</field>
|
||||||
|
<field name="inherit_id" ref="stock.view_stock_move_operations"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//form//field[@name='next_serial']" position="attributes">
|
||||||
|
<attribute name="invisible">True</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//form//field[@name='next_serial_count']" position="attributes">
|
||||||
|
<attribute name="invisible">True</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//form//button[@name='action_assign_serial_show_details']" position="after">
|
||||||
|
<button name="button_update_the_sequence_number" type="object" class="btn-link" data-hotkey="k" title="Assign Serial Numbers">
|
||||||
|
<span>更新序列号</span>
|
||||||
|
</button>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//form//button[@name='action_assign_serial_show_details']" position="attributes">
|
||||||
|
<attribute name="invisible">True</attribute>
|
||||||
|
</xpath>
|
||||||
|
<xpath expr="//form//button[@name='action_clear_lines_show_details']" position="attributes">
|
||||||
|
<attribute name="invisible">True</attribute>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
import logging
|
import logging
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
from odoo import models, api, fields, _
|
from odoo import models, api, fields, _
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
class ProductionTechnologyWizard(models.TransientModel):
|
class ProductionTechnologyWizard(models.TransientModel):
|
||||||
@@ -88,7 +89,10 @@ class ProductionTechnologyWizard(models.TransientModel):
|
|||||||
for item in productions:
|
for item in productions:
|
||||||
workorder = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted(
|
workorder = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted(
|
||||||
key=lambda a: a.sequence)
|
key=lambda a: a.sequence)
|
||||||
if workorder[0].state in ['pending']:
|
first_element = workorder[0] if workorder else None
|
||||||
if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
if not first_element:
|
||||||
workorder[0].state = 'waiting'
|
raise UserError('工艺确认后,工单未生成,请检查配置')
|
||||||
|
if first_element.state in ['pending']:
|
||||||
|
if first_element.production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
||||||
|
first_element.state = 'waiting'
|
||||||
return productions
|
return productions
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from odoo import models, fields, api
|
from odoo import models, fields, api
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
class SFSaleOrderCancelWizard(models.TransientModel):
|
class SFSaleOrderCancelWizard(models.TransientModel):
|
||||||
@@ -47,6 +48,23 @@ class SFSaleOrderCancelWizard(models.TransientModel):
|
|||||||
def action_confirm_cancel(self):
|
def action_confirm_cancel(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
|
|
||||||
|
# 删除现有关联单据行
|
||||||
|
self.related_docs.unlink()
|
||||||
|
|
||||||
|
# 重新生成最新关联单据行
|
||||||
|
self.env['sf.sale.order.cancel.line'].create_from_order(self.id, self.order_id)
|
||||||
|
|
||||||
|
# 强制重新计算校验字段
|
||||||
|
self._compute_has_movement()
|
||||||
|
self._compute_display_message()
|
||||||
|
|
||||||
|
# 检查是否存在异动
|
||||||
|
if self.has_movement:
|
||||||
|
raise UserError(
|
||||||
|
"存在下游单据异动,无法取消订单!\n"
|
||||||
|
"请关闭向导重新进入,以查看最新状态!"
|
||||||
|
)
|
||||||
|
|
||||||
# 取消销售订单关联的采购单
|
# 取消销售订单关联的采购单
|
||||||
purchase_orders = self.env['purchase.order'].search([
|
purchase_orders = self.env['purchase.order'].search([
|
||||||
('origin', '=', self.order_id.name)
|
('origin', '=', self.order_id.name)
|
||||||
@@ -76,6 +94,23 @@ class SFSaleOrderCancelWizard(models.TransientModel):
|
|||||||
if mo_quality_checks:
|
if mo_quality_checks:
|
||||||
mo_quality_checks.write({'quality_state': 'cancel'})
|
mo_quality_checks.write({'quality_state': 'cancel'})
|
||||||
|
|
||||||
|
# 取消制造订单的子制造订单
|
||||||
|
child_mo_ids = self.env['mrp.production'].search([
|
||||||
|
('origin', '=', mo.name)
|
||||||
|
])
|
||||||
|
|
||||||
|
if child_mo_ids:
|
||||||
|
# child_mo_ids |= mo.child_ids
|
||||||
|
# for child_mo in child_mo_ids:
|
||||||
|
for child_mo in child_mo_ids:
|
||||||
|
child_mo.action_cancel()
|
||||||
|
|
||||||
|
# 取消工单的外协单
|
||||||
|
for workorder in mo.workorder_ids:
|
||||||
|
if workorder.picking_ids:
|
||||||
|
for pkd in workorder.picking_ids:
|
||||||
|
pkd.write({'state': 'cancel'})
|
||||||
|
|
||||||
# 取消制造订单
|
# 取消制造订单
|
||||||
mo.action_cancel()
|
mo.action_cancel()
|
||||||
|
|
||||||
@@ -111,6 +146,18 @@ class SFSaleOrderCancelLine(models.TransientModel):
|
|||||||
doc_state = fields.Char('单据状态')
|
doc_state = fields.Char('单据状态')
|
||||||
cancel_reason = fields.Char('禁止取消原因')
|
cancel_reason = fields.Char('禁止取消原因')
|
||||||
|
|
||||||
|
quantity_str = fields.Char(
|
||||||
|
string="数量(字符串)",
|
||||||
|
compute="_compute_quantity_str",
|
||||||
|
store=False, # 默认不存储,除非需要搜索/排序
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.depends("quantity")
|
||||||
|
def _compute_quantity_str(self):
|
||||||
|
for record in self:
|
||||||
|
# 处理所有可能的 False/0 情况
|
||||||
|
record.quantity_str = str(int(record.quantity)) if record.quantity not in [False, 0] else ""
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def create_from_order(self, wizard_id, order):
|
def create_from_order(self, wizard_id, order):
|
||||||
sequence = 1
|
sequence = 1
|
||||||
@@ -136,6 +183,20 @@ class SFSaleOrderCancelLine(models.TransientModel):
|
|||||||
'assigned': '就绪'
|
'assigned': '就绪'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_name_dict = {
|
||||||
|
'purchase': '采购',
|
||||||
|
'quality': '质量',
|
||||||
|
'mrp': '制造',
|
||||||
|
'stock': '库存',
|
||||||
|
'account': '会计',
|
||||||
|
'hr': '员工',
|
||||||
|
'project': '项目',
|
||||||
|
'crm': '销售',
|
||||||
|
'point_of_sale': '销售',
|
||||||
|
'website': '网站',
|
||||||
|
'sf_plan': '计划',
|
||||||
|
}
|
||||||
|
|
||||||
# 检查销售订单
|
# 检查销售订单
|
||||||
if order.invoice_ids:
|
if order.invoice_ids:
|
||||||
a = 0
|
a = 0
|
||||||
@@ -159,67 +220,213 @@ class SFSaleOrderCancelLine(models.TransientModel):
|
|||||||
|
|
||||||
# 检查交货单
|
# 检查交货单
|
||||||
if order.picking_ids:
|
if order.picking_ids:
|
||||||
b = 0
|
|
||||||
for picking in order.picking_ids:
|
for picking in order.picking_ids:
|
||||||
|
b = 0
|
||||||
|
for move in picking.move_ids:
|
||||||
b += 1
|
b += 1
|
||||||
vals = {
|
vals = {
|
||||||
'wizard_id': wizard_id,
|
'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
'sequence': sequence,
|
||||||
'category': '库存',
|
# 'category': '库存',
|
||||||
'doc_name': '交货单',
|
'category': module_name_dict[picking._original_module],
|
||||||
'operation_type': '调拨',
|
# 'doc_name': '交货单',
|
||||||
|
'doc_name': picking._description,
|
||||||
|
'operation_type': picking.picking_type_id.name,
|
||||||
'doc_number': picking.name,
|
'doc_number': picking.name,
|
||||||
'line_number': b,
|
'line_number': b,
|
||||||
'product_name': picking.product_id.name if picking.product_id else '',
|
'product_name': f'[{move.product_id.default_code}] {move.product_id.name}' if move else '',
|
||||||
# 'quantity': picking.product_qty if hasattr(picking, 'product_qty') else 0,
|
# 'quantity': picking.product_qty if hasattr(picking, 'product_qty') else 0,
|
||||||
'quantity': sum(picking.move_ids.mapped('product_uom_qty') or [0]),
|
'quantity': move.product_uom_qty,
|
||||||
'doc_state': map_dict.get(picking.state, picking.state),
|
'doc_state': map_dict.get(picking.state, picking.state),
|
||||||
'cancel_reason': '已有异动' if picking.state not in ['draft', 'cancel', 'waiting'] else ''
|
'cancel_reason': '已有异动' if picking.state not in ['draft', 'cancel', 'waiting'] else ''
|
||||||
}
|
}
|
||||||
lines.append(self.create(vals))
|
lines.append(self.create(vals))
|
||||||
sequence += 1
|
sequence += 1
|
||||||
|
|
||||||
|
# # 成品质检单
|
||||||
|
# fin_quality_checks = self.env['quality.check'].search([
|
||||||
|
# ('picking_id', '=', picking.id)
|
||||||
|
# ])
|
||||||
|
# if fin_quality_checks:
|
||||||
|
# b1 = 0
|
||||||
|
# for fin_qc in fin_quality_checks:
|
||||||
|
# b1 += 1
|
||||||
|
# vals = {
|
||||||
|
# 'wizard_id': wizard_id,
|
||||||
|
# 'sequence': sequence,
|
||||||
|
# 'category': '制造',
|
||||||
|
# 'doc_name': '质检单',
|
||||||
|
# 'operation_type': '',
|
||||||
|
# 'doc_number': fin_qc.name,
|
||||||
|
# 'line_number': b1,
|
||||||
|
# 'product_name': f'[{fin_qc.product_id.default_code}] {fin_qc.product_id.name}',
|
||||||
|
# 'quantity': 1,
|
||||||
|
# 'doc_state': map_dict.get(fin_qc.quality_state, fin_qc.quality_state),
|
||||||
|
# 'cancel_reason': '已有异动' if fin_qc.quality_state not in ['none', 'cancel', 'waiting'] else ''
|
||||||
|
# }
|
||||||
|
# lines.append(self.create(vals))
|
||||||
|
|
||||||
|
# 检查所有的质检单
|
||||||
|
quality_checks = self.env['quality.check'].search([
|
||||||
|
('product_id.name', 'like', f'%{order.name}%')])
|
||||||
|
if quality_checks:
|
||||||
|
b1 = 0
|
||||||
|
for quality_check in quality_checks:
|
||||||
|
b1 += 1
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[quality_check._original_module],
|
||||||
|
'doc_name': quality_check._description,
|
||||||
|
'operation_type': '',
|
||||||
|
'doc_number': f'{quality_check.name}-{quality_check.title}',
|
||||||
|
'line_number': 1,
|
||||||
|
'product_name': f'[{quality_check.product_id.default_code}] {quality_check.product_id.name}' if quality_check.product_id.default_code else quality_check.product_id.name,
|
||||||
|
'quantity': 1,
|
||||||
|
'doc_state': map_dict.get(quality_check.quality_state, quality_check.quality_state),
|
||||||
|
'cancel_reason': '已有异动' if quality_check.quality_state not in ['none', 'cancel', 'waiting'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
|
||||||
|
# 检查组件的制造单
|
||||||
|
# component_mos = self.env['mrp.production'].search([
|
||||||
|
# ('origin', '=', mo.name)])
|
||||||
|
component_mos = self.env['mrp.production'].search([
|
||||||
|
('product_id.name', 'like', f'%R-{order.name}%')])
|
||||||
|
h = 0
|
||||||
|
if component_mos:
|
||||||
|
for comp_mo in component_mos:
|
||||||
|
h += 1
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[comp_mo._original_module],
|
||||||
|
'doc_name': comp_mo._description,
|
||||||
|
'operation_type': '',
|
||||||
|
'doc_number': comp_mo.name,
|
||||||
|
'line_number': h,
|
||||||
|
'product_name': f'{comp_mo.product_id.name}',
|
||||||
|
'quantity': comp_mo.product_qty,
|
||||||
|
'doc_state': map_dict.get(comp_mo.state, comp_mo.state),
|
||||||
|
'cancel_reason': '已有异动' if comp_mo.state not in ['technology_to_confirmed',
|
||||||
|
'cancel'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
sequence += 1
|
||||||
|
|
||||||
|
for pinking_id in comp_mo.picking_ids:
|
||||||
|
y = 0
|
||||||
|
for move in pinking_id.move_ids:
|
||||||
|
y += 1
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[pinking_id._original_module],
|
||||||
|
'doc_name': pinking_id._description,
|
||||||
|
'doc_number': f'{comp_mo.name}-{pinking_id.name}',
|
||||||
|
'line_number': y,
|
||||||
|
'operation_type': pinking_id.picking_type_id.name,
|
||||||
|
'product_name': move.product_id.name if move.product_id else '',
|
||||||
|
'quantity': move.product_uom_qty,
|
||||||
|
'doc_state': map_dict.get(pinking_id.state, pinking_id.state),
|
||||||
|
'cancel_reason': '已有异动' if pinking_id.state not in ['cancel', 'waiting',
|
||||||
|
'assigned'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
|
||||||
# 检查销售订单直接关联的采购单
|
# 检查销售订单直接关联的采购单
|
||||||
purchase_orders = self.env['purchase.order'].search([
|
purchase_orders = self.env['purchase.order'].search([
|
||||||
('origin', '=', order.name)
|
('origin', 'like', f'%{order.name}%')
|
||||||
])
|
])
|
||||||
if purchase_orders:
|
if purchase_orders:
|
||||||
c = 0
|
c = 0
|
||||||
for po in purchase_orders:
|
for po in purchase_orders:
|
||||||
|
for order_line in po.order_line:
|
||||||
c += 1
|
c += 1
|
||||||
vals = {
|
vals = {
|
||||||
'wizard_id': wizard_id,
|
'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
'sequence': sequence,
|
||||||
'category': '采购',
|
'category': module_name_dict[po._original_module],
|
||||||
'doc_name': '询价单',
|
'doc_name': po._description,
|
||||||
'operation_type': po.picking_type_id.name,
|
'operation_type': '',
|
||||||
'doc_number': po.name,
|
'doc_number': po.name,
|
||||||
'line_number': c,
|
'line_number': c,
|
||||||
'product_name': po.order_line[0].product_id.name if po.order_line else '',
|
'product_name': f'[{order_line.product_id.default_code}] {order_line.product_id.name}',
|
||||||
'quantity': po.order_line[0].product_qty if po.order_line else 0,
|
'quantity': order_line.product_qty if order_line else 0,
|
||||||
'doc_state': map_dict.get(po.state, po.state),
|
'doc_state': map_dict.get(po.state, po.state),
|
||||||
'cancel_reason': '已有异动' if po.state not in ['draft', 'cancel'] else ''
|
'cancel_reason': '已有异动' if po.state not in ['draft', 'cancel'] else ''
|
||||||
}
|
}
|
||||||
lines.append(self.create(vals))
|
lines.append(self.create(vals))
|
||||||
sequence += 1
|
sequence += 1
|
||||||
|
|
||||||
|
# 客供料的入库单
|
||||||
|
for pod in purchase_orders:
|
||||||
|
pkds = self.env['stock.picking'].search([
|
||||||
|
('origin', '=', pod.name)
|
||||||
|
])
|
||||||
|
if pkds:
|
||||||
|
for pkd in pkds:
|
||||||
|
x3 = 0
|
||||||
|
for move in pkd.move_ids:
|
||||||
|
x3 += 1
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[pkd._original_module],
|
||||||
|
'doc_name': pkd._description,
|
||||||
|
'doc_number': pkd.name,
|
||||||
|
'line_number': x3,
|
||||||
|
'operation_type': pkd.picking_type_id.name,
|
||||||
|
'product_name': f'[{move.product_id.default_code}] {move.product_id.name}',
|
||||||
|
'quantity': move.product_uom_qty,
|
||||||
|
'doc_state': map_dict.get(pkd.state, pkd.state),
|
||||||
|
'cancel_reason': '已有异动' if pkd.state not in ['waiting', 'cancel', 'confirmed'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
|
||||||
|
#
|
||||||
|
for child_pkd in self.env['stock.picking'].search([
|
||||||
|
('origin', '=', pkd.name)
|
||||||
|
]):
|
||||||
|
x4 = 0
|
||||||
|
for child_move in child_pkd.move_ids:
|
||||||
|
x4 += 1
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[child_pkd._original_module],
|
||||||
|
'doc_name': child_pkd._description,
|
||||||
|
'doc_number': child_pkd.name,
|
||||||
|
'line_number': x4,
|
||||||
|
'operation_type': child_pkd.picking_type_id.name,
|
||||||
|
'product_name': child_move.product_id.name if child_move.product_id else '',
|
||||||
|
'quantity': child_move.product_uom_qty,
|
||||||
|
'doc_state': map_dict.get(child_pkd.state, child_pkd.state),
|
||||||
|
'cancel_reason': '已有异动' if child_pkd.state not in ['waiting',
|
||||||
|
'cancel', 'confirmed'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
|
||||||
# 检查制造订单
|
# 检查制造订单
|
||||||
manufacturing_orders = self.env['mrp.production'].search([
|
manufacturing_orders = self.env['mrp.production'].search([
|
||||||
('origin', '=', order.name)
|
('origin', '=', order.name)
|
||||||
])
|
])
|
||||||
d = 0
|
d = 0
|
||||||
|
# 在领料单处只进行一次
|
||||||
|
flag = True
|
||||||
|
program_list = []
|
||||||
for mo in manufacturing_orders:
|
for mo in manufacturing_orders:
|
||||||
# 添加制造订单本身
|
# 添加制造订单本身
|
||||||
d += 1
|
d += 1
|
||||||
vals = {
|
vals = {
|
||||||
'wizard_id': wizard_id,
|
'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
'sequence': sequence,
|
||||||
'category': '制造',
|
'category': module_name_dict[mo._original_module],
|
||||||
'doc_name': '制造订单',
|
'doc_name': mo._description,
|
||||||
'doc_number': mo.name,
|
'doc_number': mo.name,
|
||||||
'operation_type': '',
|
'operation_type': '',
|
||||||
'line_number': d,
|
'line_number': d,
|
||||||
'product_name': mo.product_id.name,
|
'product_name': f'[{mo.product_id.default_code}] {mo.product_id.name}',
|
||||||
'quantity': mo.product_qty,
|
'quantity': mo.product_qty,
|
||||||
'doc_state': map_dict.get(mo.state, mo.state),
|
'doc_state': map_dict.get(mo.state, mo.state),
|
||||||
'cancel_reason': '已有异动' if mo.state not in ['technology_to_confirmed', 'cancel'] else ''
|
'cancel_reason': '已有异动' if mo.state not in ['technology_to_confirmed', 'cancel'] else ''
|
||||||
@@ -229,48 +436,104 @@ class SFSaleOrderCancelLine(models.TransientModel):
|
|||||||
|
|
||||||
# 检查制造订单关联的采购单
|
# 检查制造订单关联的采购单
|
||||||
purchase_orders = self.env['purchase.order'].search([
|
purchase_orders = self.env['purchase.order'].search([
|
||||||
('origin', '=', mo.name)
|
('origin', 'like', f'%{mo.name}%')
|
||||||
])
|
])
|
||||||
if purchase_orders:
|
if purchase_orders:
|
||||||
e = 0
|
e = 0
|
||||||
for po in purchase_orders:
|
for po in purchase_orders:
|
||||||
|
for order_line in po.order_line:
|
||||||
e += 1
|
e += 1
|
||||||
vals = {
|
vals = {
|
||||||
'wizard_id': wizard_id,
|
'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
'sequence': sequence,
|
||||||
'category': '制造',
|
'category': module_name_dict[po._original_module],
|
||||||
'doc_name': '询价单',
|
'doc_name': po._description,
|
||||||
'doc_number': po.name,
|
'doc_number': po.name,
|
||||||
'line_number': e,
|
'line_number': e,
|
||||||
'operation_type': po.picking_type_id.name,
|
'operation_type': '',
|
||||||
'product_name': po.order_line[0].product_id.name if po.order_line else '',
|
'product_name': order_line.product_id.name if order_line else '',
|
||||||
'quantity': po.order_line[0].product_qty if po.order_line else 0,
|
'quantity': order_line.product_qty if order_line else 0,
|
||||||
'doc_state': map_dict.get(po.state, po.state),
|
'doc_state': map_dict.get(po.state, po.state),
|
||||||
'cancel_reason': '已有异动' if po.state not in ['draft', 'cancel'] else ''
|
'cancel_reason': '已有异动' if po.state not in ['draft', 'cancel'] else ''
|
||||||
}
|
}
|
||||||
lines.append(self.create(vals))
|
lines.append(self.create(vals))
|
||||||
sequence += 1
|
sequence += 1
|
||||||
|
|
||||||
# 检查制造订单的领料单
|
# 制造询价单的入库单
|
||||||
if mo.picking_ids:
|
for pod in purchase_orders:
|
||||||
f = 0
|
pkds = self.env['stock.picking'].search([
|
||||||
for picking in mo.picking_ids:
|
('origin', '=', pod.name)
|
||||||
f += 1
|
])
|
||||||
|
if pkds:
|
||||||
|
for pkd in pkds:
|
||||||
|
x1 = 0
|
||||||
|
for move in pkd.move_ids:
|
||||||
|
x1 += 1
|
||||||
vals = {
|
vals = {
|
||||||
'wizard_id': wizard_id,
|
'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
'sequence': sequence,
|
||||||
'category': '制造',
|
'category': module_name_dict[pkd._original_module],
|
||||||
'doc_name': '库存移动',
|
'doc_name': pkd._description,
|
||||||
|
'doc_number': pkd.name,
|
||||||
|
'line_number': x1,
|
||||||
|
'operation_type': pkd.picking_type_id.name,
|
||||||
|
'product_name': move.product_id.name if move.product_id else '',
|
||||||
|
'quantity': move.product_uom_qty,
|
||||||
|
'doc_state': map_dict.get(pkd.state, pkd.state),
|
||||||
|
'cancel_reason': '已有异动' if pkd.state not in ['draft', 'cancel'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
|
||||||
|
#
|
||||||
|
for child_pkd in self.env['stock.picking'].search([
|
||||||
|
('origin', '=', pkd.name)
|
||||||
|
]):
|
||||||
|
x2 = 0
|
||||||
|
for child_move in child_pkd.move_ids:
|
||||||
|
x2 += 1
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[child_pkd._original_module],
|
||||||
|
'doc_name': child_pkd._description,
|
||||||
|
'doc_number': child_pkd.name,
|
||||||
|
'line_number': x2,
|
||||||
|
'operation_type': child_pkd.picking_type_id.name,
|
||||||
|
'product_name': child_move.product_id.name if child_move.product_id else '',
|
||||||
|
'quantity': child_move.product_uom_qty,
|
||||||
|
'doc_state': map_dict.get(child_pkd.state, child_pkd.state),
|
||||||
|
'cancel_reason': '已有异动' if child_pkd.state not in ['draft', 'cancel'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
|
||||||
|
# 检查制造订单的领料单
|
||||||
|
|
||||||
|
if mo.picking_ids and flag:
|
||||||
|
for picking in mo.picking_ids:
|
||||||
|
f = 0
|
||||||
|
for move in picking.move_ids:
|
||||||
|
f += 1
|
||||||
|
is_changed = False
|
||||||
|
if picking.state not in ['draft', 'cancel', 'waiting']:
|
||||||
|
is_changed = True
|
||||||
|
if picking.picking_type_id.name == '客供料入库' and picking.state in ['cancel', 'assigned']:
|
||||||
|
is_changed = False
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[picking._original_module],
|
||||||
|
'doc_name': picking._description,
|
||||||
'doc_number': picking.name,
|
'doc_number': picking.name,
|
||||||
'line_number': f,
|
'line_number': f,
|
||||||
'operation_type': picking.picking_type_id.name,
|
'operation_type': picking.picking_type_id.name,
|
||||||
'product_name': picking.product_id.name if picking.product_id else '',
|
'product_name': move.product_id.name if move.product_id else '',
|
||||||
'quantity': sum(picking.move_ids.mapped('product_uom_qty') or [0]),
|
'quantity': move.product_uom_qty,
|
||||||
'doc_state': map_dict.get(picking.state, picking.state),
|
'doc_state': map_dict.get(picking.state, picking.state),
|
||||||
'cancel_reason': '已有异动' if picking.state not in ['draft', 'cancel', 'waiting'] else ''
|
'cancel_reason': '已有异动' if is_changed else ''
|
||||||
}
|
}
|
||||||
lines.append(self.create(vals))
|
lines.append(self.create(vals))
|
||||||
sequence += 1
|
sequence += 1
|
||||||
|
flag = False
|
||||||
|
|
||||||
# 检查制造订单的工单
|
# 检查制造订单的工单
|
||||||
if mo.workorder_ids:
|
if mo.workorder_ids:
|
||||||
@@ -280,12 +543,12 @@ class SFSaleOrderCancelLine(models.TransientModel):
|
|||||||
vals = {
|
vals = {
|
||||||
'wizard_id': wizard_id,
|
'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
'sequence': sequence,
|
||||||
'category': '制造',
|
'category': module_name_dict[workorder._original_module],
|
||||||
'doc_name': '工单',
|
'doc_name': workorder._description,
|
||||||
'doc_number': workorder.name,
|
'doc_number': f'{mo.name}-{workorder.processing_panel}-{workorder.name}' if workorder.processing_panel else f'{mo.name}-{workorder.name}',
|
||||||
'line_number': g,
|
'line_number': g,
|
||||||
'operation_type': workorder.workcenter_id.name,
|
'operation_type': '',
|
||||||
'product_name': mo.product_id.name,
|
'product_name': f'[{mo.product_id.default_code}] {mo.product_id.name}',
|
||||||
'quantity': workorder.qty_production,
|
'quantity': workorder.qty_production,
|
||||||
'doc_state': map_dict.get(workorder.state, workorder.state),
|
'doc_state': map_dict.get(workorder.state, workorder.state),
|
||||||
'cancel_reason': '已有异动' if workorder.state not in ['draft', 'cancel', 'pending',
|
'cancel_reason': '已有异动' if workorder.state not in ['draft', 'cancel', 'pending',
|
||||||
@@ -294,8 +557,29 @@ class SFSaleOrderCancelLine(models.TransientModel):
|
|||||||
lines.append(self.create(vals))
|
lines.append(self.create(vals))
|
||||||
sequence += 1
|
sequence += 1
|
||||||
|
|
||||||
# 检查制造订单组件的采购单和制造单
|
# 工艺外协处理
|
||||||
for move in mo.move_raw_ids:
|
if workorder.picking_ids:
|
||||||
|
for pkd in workorder.picking_ids:
|
||||||
|
z = 0
|
||||||
|
for move in pkd.move_ids:
|
||||||
|
z += 1
|
||||||
|
vals = {
|
||||||
|
'wizard_id': wizard_id,
|
||||||
|
'sequence': sequence,
|
||||||
|
'category': module_name_dict[pkd._original_module],
|
||||||
|
'doc_name': pkd._description,
|
||||||
|
'doc_number': f'{mo.name}-{workorder.name}-{pkd.name}',
|
||||||
|
'line_number': z,
|
||||||
|
'operation_type': pkd.picking_type_id.name,
|
||||||
|
'product_name': move.product_id.name if move.product_id else '',
|
||||||
|
'quantity': move.product_uom_qty,
|
||||||
|
'doc_state': map_dict.get(pkd.state, pkd.state),
|
||||||
|
'cancel_reason': '已有异动' if pkd.state not in ['cancel', 'waiting'] else ''
|
||||||
|
}
|
||||||
|
lines.append(self.create(vals))
|
||||||
|
|
||||||
|
# # 检查制造订单组件的采购单和制造单
|
||||||
|
# for move in mo.move_raw_ids:
|
||||||
# # 检查组件的采购单
|
# # 检查组件的采购单
|
||||||
# component_pos = self.env['purchase.order'].search([
|
# component_pos = self.env['purchase.order'].search([
|
||||||
# ('origin', '=', mo.name),
|
# ('origin', '=', mo.name),
|
||||||
@@ -317,78 +601,59 @@ class SFSaleOrderCancelLine(models.TransientModel):
|
|||||||
# lines.append(self.create(vals))
|
# lines.append(self.create(vals))
|
||||||
# sequence += 1
|
# sequence += 1
|
||||||
|
|
||||||
# 检查组件的制造单
|
# # 检查制造订单的质检单
|
||||||
component_mos = self.env['mrp.production'].search([
|
# quality_checks = self.env['quality.check'].search([
|
||||||
('origin', '=', mo.name),
|
# ('production_id', '=', mo.id)
|
||||||
('product_id', '=', move.product_id.id)
|
# ])
|
||||||
])
|
# if quality_checks:
|
||||||
h = 0
|
# i = 0
|
||||||
for comp_mo in component_mos:
|
# for check in quality_checks:
|
||||||
h += 1
|
# i += 1
|
||||||
vals = {
|
# vals = {
|
||||||
'wizard_id': wizard_id,
|
# 'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
# 'sequence': sequence,
|
||||||
'category': '制造',
|
# 'category': '制造',
|
||||||
'doc_name': '组件制造单',
|
# 'doc_name': '质检单',
|
||||||
'operation_type': '',
|
# 'operation_type': '',
|
||||||
'doc_number': comp_mo.name,
|
# 'doc_number': check.name,
|
||||||
'line_number': h,
|
# 'line_number': i,
|
||||||
'product_name': move.product_id.name,
|
# 'product_name': f'[{check.product_id.default_code}] {check.product_id.name}',
|
||||||
'quantity': comp_mo.product_qty,
|
# 'quantity': 1,
|
||||||
'doc_state': map_dict.get(comp_mo.state, comp_mo.state),
|
# 'doc_state': map_dict.get(check.quality_state, check.quality_state),
|
||||||
'cancel_reason': '已有异动' if comp_mo.state not in ['technology_to_confirmed'] else ''
|
# 'cancel_reason': '已有异动' if check.quality_state not in ['none', 'cancel', 'waiting'] else ''
|
||||||
}
|
# }
|
||||||
lines.append(self.create(vals))
|
# lines.append(self.create(vals))
|
||||||
sequence += 1
|
# sequence += 1
|
||||||
|
|
||||||
# 检查制造订单的质检单
|
|
||||||
quality_checks = self.env['quality.check'].search([
|
|
||||||
('production_id', '=', mo.id)
|
|
||||||
])
|
|
||||||
if quality_checks:
|
|
||||||
i = 0
|
|
||||||
for check in quality_checks:
|
|
||||||
i += 1
|
|
||||||
vals = {
|
|
||||||
'wizard_id': wizard_id,
|
|
||||||
'sequence': sequence,
|
|
||||||
'category': '制造',
|
|
||||||
'doc_name': '质检单',
|
|
||||||
'operation_type': '',
|
|
||||||
'doc_number': check.name,
|
|
||||||
'line_number': i,
|
|
||||||
'product_name': check.product_id.name,
|
|
||||||
'quantity': 1,
|
|
||||||
'doc_state': map_dict.get(check.quality_state, check.quality_state),
|
|
||||||
'cancel_reason': '已有异动' if check.quality_state not in ['none', 'cancel'] else ''
|
|
||||||
}
|
|
||||||
lines.append(self.create(vals))
|
|
||||||
sequence += 1
|
|
||||||
|
|
||||||
# 检查制造订单的编程单
|
# 检查制造订单的编程单
|
||||||
cloud_programming = mo._cron_get_programming_state()
|
cloud_programming = mo._cron_get_programming_state()
|
||||||
if cloud_programming:
|
if cloud_programming:
|
||||||
|
programming_no = cloud_programming['programming_no']
|
||||||
|
|
||||||
|
# 检查当前lines中是否已存在相同doc_number的记录
|
||||||
|
if not any(line.doc_number == programming_no for line in lines):
|
||||||
vals = {
|
vals = {
|
||||||
'wizard_id': wizard_id,
|
'wizard_id': wizard_id,
|
||||||
'sequence': sequence,
|
'sequence': sequence,
|
||||||
'category': '编程',
|
'category': '编程',
|
||||||
'doc_name': '编程单',
|
'doc_name': '编程单',
|
||||||
'operation_type': '',
|
'operation_type': '',
|
||||||
'doc_number': cloud_programming['programming_no'],
|
'doc_number': programming_no, # 直接使用变量
|
||||||
'line_number': 1,
|
'line_number': 1,
|
||||||
'product_name': cloud_programming['production_order_no'],
|
'product_name': '',
|
||||||
'quantity': 1,
|
'quantity': 0,
|
||||||
'doc_state': cloud_programming['programming_state'],
|
'doc_state': cloud_programming['programming_state'],
|
||||||
'cancel_reason': ''
|
'cancel_reason': ''
|
||||||
}
|
}
|
||||||
lines.append(self.create(vals))
|
lines.append(self.create(vals))
|
||||||
sequence += 1
|
|
||||||
|
|
||||||
unique_lines = {}
|
return lines
|
||||||
for line in lines:
|
|
||||||
doc_number = line.doc_number
|
|
||||||
if doc_number not in unique_lines:
|
|
||||||
unique_lines[doc_number] = line
|
|
||||||
|
|
||||||
# 返回去重后的记录列表
|
# unique_lines = {}
|
||||||
return list(unique_lines.values())
|
# for line in lines:
|
||||||
|
# doc_number = line.doc_number
|
||||||
|
# if doc_number not in unique_lines:
|
||||||
|
# unique_lines[doc_number] = line
|
||||||
|
#
|
||||||
|
# # 返回去重后的记录列表
|
||||||
|
# return list(unique_lines.values())
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<field name="doc_number" string="单据编号"/>
|
<field name="doc_number" string="单据编号"/>
|
||||||
<field name="line_number" string="行号"/>
|
<field name="line_number" string="行号"/>
|
||||||
<field name="product_name" string="产品名称"/>
|
<field name="product_name" string="产品名称"/>
|
||||||
<field name="quantity" string="数量"/>
|
<field name="quantity_str" string="数量"/>
|
||||||
<field name="doc_state" string="单据状态"/>
|
<field name="doc_state" string="单据状态"/>
|
||||||
<field name="cancel_reason" string="禁止取消原因"/>
|
<field name="cancel_reason" string="禁止取消原因"/>
|
||||||
</tree>
|
</tree>
|
||||||
@@ -39,4 +39,31 @@
|
|||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="view_sf_sale_order_cancel_line" model="ir.ui.view">
|
||||||
|
<field name="name">sf.sale.order.cancel.line.form</field>
|
||||||
|
<field name="model">sf.sale.order.cancel.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="下游单据明细">
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="category"/>
|
||||||
|
<field name="doc_name"/>
|
||||||
|
<field name="operation_type"/>
|
||||||
|
<field name="quantity_str"/>
|
||||||
|
<field name="cancel_reason"/>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="line_number"/>
|
||||||
|
<field name="doc_number"/>
|
||||||
|
<field name="product_name"/>
|
||||||
|
<field name="doc_state"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -54,7 +54,9 @@ class WorkpieceDeliveryWizard(models.TransientModel):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delivery_type = fields.Selection(related='route_id.route_type', string='类型')
|
def _get_agv_route_type_selection(self):
|
||||||
|
return self.env['sf.agv.task.route'].fields_get(['route_type'])['route_type']['selection']
|
||||||
|
delivery_type = fields.Selection(selection=_get_agv_route_type_selection, string='类型')
|
||||||
|
|
||||||
def dispatch_confirm(self):
|
def dispatch_confirm(self):
|
||||||
if len(self.workorder_ids) < 4:
|
if len(self.workorder_ids) < 4:
|
||||||
|
|||||||
@@ -262,7 +262,7 @@
|
|||||||
<field name="msgtype">markdown</field>
|
<field name="msgtype">markdown</field>
|
||||||
<field name="urgency">normal</field>
|
<field name="urgency">normal</field>
|
||||||
<field name="content">### {{picking_type_name}}待处理提醒:
|
<field name="content">### {{picking_type_name}}待处理提醒:
|
||||||
单号:{{name}}
|
单号:[{{name}}]({{request_url}})
|
||||||
事项:质量检查已完成</field>
|
事项:质量检查已完成</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ class SFMessageStockPicking(models.Model):
|
|||||||
for record in self:
|
for record in self:
|
||||||
if (record.state == 'assigned' and record.picking_type_id.sequence_code == 'PC'
|
if (record.state == 'assigned' and record.picking_type_id.sequence_code == 'PC'
|
||||||
and record.product_id.categ_id.type == '坯料'):
|
and record.product_id.categ_id.type == '坯料'):
|
||||||
|
jikimo_message_queue = record.get_message_queue(record.id)
|
||||||
|
if not jikimo_message_queue:
|
||||||
record.add_queue('坯料发料提醒')
|
record.add_queue('坯料发料提醒')
|
||||||
|
|
||||||
if record.picking_type_id.sequence_code == 'SFP' and record.state == 'done':
|
if record.picking_type_id.sequence_code == 'SFP' and record.state == 'done':
|
||||||
@@ -51,7 +53,13 @@ class SFMessageStockPicking(models.Model):
|
|||||||
all_ready_or_done = all(picking.state in ['assigned', 'done'] for picking in stock_picking_list)
|
all_ready_or_done = all(picking.state in ['assigned', 'done'] for picking in stock_picking_list)
|
||||||
if all_ready_or_done:
|
if all_ready_or_done:
|
||||||
mrp_production.add_queue('工序外协发料通知')
|
mrp_production.add_queue('工序外协发料通知')
|
||||||
if all(qc.quality_state in ['pass', 'fail'] for qc in record.quality_check_ids):
|
if record.quality_check_ids and all(
|
||||||
|
qc.quality_state in ['pass', 'fail'] for qc in record.quality_check_ids):
|
||||||
|
message_template_id = self.env["jikimo.message.template"].sudo().search(
|
||||||
|
[('name', '=', '调拨单质检完成提醒')])
|
||||||
|
stock_picking_send = self.env["jikimo.message.queue"].sudo().search(
|
||||||
|
[('res_id', '=', record.id), ('message_template_id', '=', message_template_id.id)])
|
||||||
|
if not stock_picking_send:
|
||||||
record.add_queue('调拨单质检完成提醒')
|
record.add_queue('调拨单质检完成提醒')
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info('add_queue_compute_state error:%s' % e)
|
logging.info('add_queue_compute_state error:%s' % e)
|
||||||
@@ -90,8 +98,14 @@ class SFMessageStockPicking(models.Model):
|
|||||||
contents.append(content)
|
contents.append(content)
|
||||||
elif message_queue_id.message_template_id.name == '调拨单质检完成提醒':
|
elif message_queue_id.message_template_id.name == '调拨单质检完成提醒':
|
||||||
content = message_queue_id.message_template_id.content
|
content = message_queue_id.message_template_id.content
|
||||||
content = content.replace('{{picking_type_name}}', self.picking_type_id.name).replace(
|
stock_picking_line = self.env['stock.picking'].sudo().search(
|
||||||
'{{name}}', self.name)
|
[('id', '=', int(message_queue_id.res_id))])
|
||||||
|
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
|
||||||
|
action_id = self.env.ref('stock.action_picking_tree_ready').id
|
||||||
|
menu_id = self.env.ref('stock.menu_stock_root').id
|
||||||
|
url_with_id = f"{url}/web#view_type=form&action={action_id}&menu_id={menu_id}&id={stock_picking_line.id}"
|
||||||
|
content = content.replace('{{picking_type_name}}', stock_picking_line.picking_type_id.name).replace(
|
||||||
|
'{{name}}', stock_picking_line.name).replace('{{request_url}}', url_with_id)
|
||||||
contents.append(content)
|
contents.append(content)
|
||||||
return contents, message_queue_ids
|
return contents, message_queue_ids
|
||||||
|
|
||||||
@@ -117,3 +131,14 @@ class SFMessageStockPicking(models.Model):
|
|||||||
# 拼接URL
|
# 拼接URL
|
||||||
full_url = url + "/web#" + query_string
|
full_url = url + "/web#" + query_string
|
||||||
return full_url
|
return full_url
|
||||||
|
|
||||||
|
def get_message_queue(self, res_id):
|
||||||
|
business_node_id = self.env.ref('sf_message.bussiness_material_picking_remind').id
|
||||||
|
message_template = self.env["jikimo.message.template"].sudo().search([
|
||||||
|
("model", "=", self._name),
|
||||||
|
("bussiness_node_id", "=", business_node_id)
|
||||||
|
], limit=1)
|
||||||
|
jikimo_message_queue = self.env['jikimo.message.queue'].sudo().search(
|
||||||
|
[('res_id', '=', res_id), ("message_status", "in", ("pending", "sent")),
|
||||||
|
('message_template_id', '=', message_template.id)])
|
||||||
|
return jikimo_message_queue
|
||||||
|
|||||||
@@ -1968,8 +1968,7 @@ class CuttingSpeed(models.Model):
|
|||||||
self.create({
|
self.create({
|
||||||
'name': item['name'],
|
'name': item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'execution_standard_id': self.env['sf.international.standards'].search(
|
'execution_standard_id': self.env['sf.international.standards'].search(
|
||||||
[('code', '=', item['execution_standard_code'])]).id,
|
[('code', '=', item['execution_standard_code'])]).id,
|
||||||
'material_name_id': self.env['sf.materials.model'].search(
|
'material_name_id': self.env['sf.materials.model'].search(
|
||||||
@@ -1989,8 +1988,7 @@ class CuttingSpeed(models.Model):
|
|||||||
else:
|
else:
|
||||||
cutting_speed.write({
|
cutting_speed.write({
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'execution_standard_id': self.env['sf.international.standards'].search(
|
'execution_standard_id': self.env['sf.international.standards'].search(
|
||||||
[('code', '=', item['execution_standard_code'])]).id,
|
[('code', '=', item['execution_standard_code'])]).id,
|
||||||
'material_name_id': self.env['sf.materials.model'].search(
|
'material_name_id': self.env['sf.materials.model'].search(
|
||||||
@@ -2023,8 +2021,7 @@ class CuttingSpeed(models.Model):
|
|||||||
self.create({
|
self.create({
|
||||||
'name': item['name'],
|
'name': item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'execution_standard_id': self.env['sf.international.standards'].search(
|
'execution_standard_id': self.env['sf.international.standards'].search(
|
||||||
[('code', '=', item['execution_standard_code'])]).id,
|
[('code', '=', item['execution_standard_code'])]).id,
|
||||||
'material_name_id': self.env['sf.materials.model'].search(
|
'material_name_id': self.env['sf.materials.model'].search(
|
||||||
@@ -2044,8 +2041,7 @@ class CuttingSpeed(models.Model):
|
|||||||
else:
|
else:
|
||||||
cutting_speed.write({
|
cutting_speed.write({
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'execution_standard_id': self.env['sf.international.standards'].search(
|
'execution_standard_id': self.env['sf.international.standards'].search(
|
||||||
[('code', '=', item['execution_standard_code'])]).id,
|
[('code', '=', item['execution_standard_code'])]).id,
|
||||||
'material_name_id': self.env['sf.materials.model'].search(
|
'material_name_id': self.env['sf.materials.model'].search(
|
||||||
@@ -2124,8 +2120,7 @@ class CuttingSpeed(models.Model):
|
|||||||
self.create({
|
self.create({
|
||||||
'name': item['name'],
|
'name': item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'materials_type_id': self.env['sf.materials.model'].search(
|
'materials_type_id': self.env['sf.materials.model'].search(
|
||||||
[('materials_no', '=', item['materials_type_code'])]).id,
|
[('materials_no', '=', item['materials_type_code'])]).id,
|
||||||
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
||||||
@@ -2137,8 +2132,7 @@ class CuttingSpeed(models.Model):
|
|||||||
else:
|
else:
|
||||||
feed_per_tooth.write({
|
feed_per_tooth.write({
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'materials_type_id': self.env['sf.materials.model'].search(
|
'materials_type_id': self.env['sf.materials.model'].search(
|
||||||
[('materials_no', '=', item['materials_type_code'])]).id,
|
[('materials_no', '=', item['materials_type_code'])]).id,
|
||||||
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
||||||
@@ -2165,8 +2159,7 @@ class CuttingSpeed(models.Model):
|
|||||||
self.create({
|
self.create({
|
||||||
'name': item['name'],
|
'name': item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'materials_type_id': self.env['sf.materials.model'].search(
|
'materials_type_id': self.env['sf.materials.model'].search(
|
||||||
[('materials_no', '=', item['materials_type_code'])]).id,
|
[('materials_no', '=', item['materials_type_code'])]).id,
|
||||||
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
||||||
@@ -2178,8 +2171,7 @@ class CuttingSpeed(models.Model):
|
|||||||
else:
|
else:
|
||||||
feed_per_tooth.write({
|
feed_per_tooth.write({
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', item['standard_library_code'].replace("JKM", result[
|
[('code', '=', item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'materials_type_id': self.env['sf.materials.model'].search(
|
'materials_type_id': self.env['sf.materials.model'].search(
|
||||||
[('materials_no', '=', item['materials_type_code'])]).id,
|
[('materials_no', '=', item['materials_type_code'])]).id,
|
||||||
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
'cutting_width_depth_id': self.env['sf.cutting.width.depth'].search(
|
||||||
@@ -2207,7 +2199,7 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
if result['status'] == 1:
|
if result['status'] == 1:
|
||||||
for item in result['cutting_tool_standard_library_yesterday_list']:
|
for item in result['cutting_tool_standard_library_yesterday_list']:
|
||||||
cutting_tool_standard_library = self.search(
|
cutting_tool_standard_library = self.search(
|
||||||
[("code", '=', item['code'].replace("JKM", result['factory_short_name'])),
|
[("code", '=', item['code']),
|
||||||
('active', 'in', [True, False])])
|
('active', 'in', [True, False])])
|
||||||
cutting_tool_type = self.env['sf.cutting.tool.type'].search(
|
cutting_tool_type = self.env['sf.cutting.tool.type'].search(
|
||||||
[("code", '=', item['cutting_tool_type_code'])])
|
[("code", '=', item['cutting_tool_type_code'])])
|
||||||
@@ -2218,7 +2210,7 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
brand = self.env['sf.machine.brand'].search([("code", '=', item['brand_code'])])
|
brand = self.env['sf.machine.brand'].search([("code", '=', item['brand_code'])])
|
||||||
if not cutting_tool_standard_library:
|
if not cutting_tool_standard_library:
|
||||||
self.create({
|
self.create({
|
||||||
"code": item['code'].replace("JKM", result['factory_short_name']),
|
"code": item['code'],
|
||||||
"name": item['name'],
|
"name": item['name'],
|
||||||
"cutting_tool_material_id": cutting_tool_material.id,
|
"cutting_tool_material_id": cutting_tool_material.id,
|
||||||
"cutting_tool_type_id": cutting_tool_type.id,
|
"cutting_tool_type_id": cutting_tool_type.id,
|
||||||
@@ -2240,9 +2232,9 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
'maintenance.equipment.image'].search(
|
'maintenance.equipment.image'].search(
|
||||||
[('name', '=', item['fit_blade_shape'])]).id,
|
[('name', '=', item['fit_blade_shape'])]).id,
|
||||||
"chuck_id": False if not item['chuck_code'] else self.search(
|
"chuck_id": False if not item['chuck_code'] else self.search(
|
||||||
[('code', '=', item['chuck_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['chuck_code'])]).id,
|
||||||
"handle_id": False if not item['handle_code'] else self.search(
|
"handle_id": False if not item['handle_code'] else self.search(
|
||||||
[('code', '=', item['handle_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['handle_code'])]).id,
|
||||||
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
||||||
'suitable_machining_methods') else self.env['maintenance.equipment.image']._get_ids(
|
'suitable_machining_methods') else self.env['maintenance.equipment.image']._get_ids(
|
||||||
item['suitable_machining_methods']),
|
item['suitable_machining_methods']),
|
||||||
@@ -2282,9 +2274,9 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
'maintenance.equipment.image'].search(
|
'maintenance.equipment.image'].search(
|
||||||
[('name', '=', item['fit_blade_shape'])]).id,
|
[('name', '=', item['fit_blade_shape'])]).id,
|
||||||
"chuck_id": False if not item['chuck_code'] else self.search(
|
"chuck_id": False if not item['chuck_code'] else self.search(
|
||||||
[('code', '=', item['chuck_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['chuck_code'])]).id,
|
||||||
"handle_id": False if not item['handle_code'] else self.search(
|
"handle_id": False if not item['handle_code'] else self.search(
|
||||||
[('code', '=', item['handle_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['handle_code'])]).id,
|
||||||
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
||||||
'suitable_machining_methods') else self.env['maintenance.equipment.image']._get_ids(
|
'suitable_machining_methods') else self.env['maintenance.equipment.image']._get_ids(
|
||||||
item['suitable_machining_methods']),
|
item['suitable_machining_methods']),
|
||||||
@@ -2314,7 +2306,7 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
if result['status'] == 1:
|
if result['status'] == 1:
|
||||||
for item in result['cutting_tool_standard_library_all_list']:
|
for item in result['cutting_tool_standard_library_all_list']:
|
||||||
cutting_tool_standard_library = self.search(
|
cutting_tool_standard_library = self.search(
|
||||||
[("code", '=', item['code'].replace("JKM", result['factory_short_name'])),
|
[("code", '=', item['code']),
|
||||||
("active", 'in', [True, False])])
|
("active", 'in', [True, False])])
|
||||||
cutting_tool_type = self.env['sf.cutting.tool.type'].search(
|
cutting_tool_type = self.env['sf.cutting.tool.type'].search(
|
||||||
[("code", '=', item['cutting_tool_type_code'])])
|
[("code", '=', item['cutting_tool_type_code'])])
|
||||||
@@ -2325,7 +2317,7 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
brand = self.env['sf.machine.brand'].search([("code", '=', item['brand_code'])])
|
brand = self.env['sf.machine.brand'].search([("code", '=', item['brand_code'])])
|
||||||
if not cutting_tool_standard_library:
|
if not cutting_tool_standard_library:
|
||||||
self.create({
|
self.create({
|
||||||
"code": item['code'].replace("JKM", result['factory_short_name']),
|
"code": item['code'],
|
||||||
"name": item['name'],
|
"name": item['name'],
|
||||||
"cutting_tool_material_id": cutting_tool_material.id,
|
"cutting_tool_material_id": cutting_tool_material.id,
|
||||||
"cutting_tool_type_id": cutting_tool_type.id,
|
"cutting_tool_type_id": cutting_tool_type.id,
|
||||||
@@ -2347,9 +2339,9 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
'maintenance.equipment.image'].search(
|
'maintenance.equipment.image'].search(
|
||||||
[('name', '=', item['fit_blade_shape'])]).id,
|
[('name', '=', item['fit_blade_shape'])]).id,
|
||||||
"chuck_id": False if not item['chuck_code'] else self.search(
|
"chuck_id": False if not item['chuck_code'] else self.search(
|
||||||
[('code', '=', item['chuck_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['chuck_code'])]).id,
|
||||||
"handle_id": False if not item['handle_code'] else self.search(
|
"handle_id": False if not item['handle_code'] else self.search(
|
||||||
[('code', '=', item['handle_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['handle_code'])]).id,
|
||||||
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
||||||
'suitable_machining_method') else self.env['maintenance.equipment.image']._get_ids(
|
'suitable_machining_method') else self.env['maintenance.equipment.image']._get_ids(
|
||||||
item['suitable_machining_method']),
|
item['suitable_machining_method']),
|
||||||
@@ -2389,12 +2381,12 @@ class Cutting_tool_standard_library(models.Model):
|
|||||||
'maintenance.equipment.image'].search(
|
'maintenance.equipment.image'].search(
|
||||||
[('name', '=', item['fit_blade_shape'])]).id,
|
[('name', '=', item['fit_blade_shape'])]).id,
|
||||||
"chuck_id": False if not item['chuck_code'] else self.search(
|
"chuck_id": False if not item['chuck_code'] else self.search(
|
||||||
[('code', '=', item['chuck_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['chuck_code'])]).id,
|
||||||
"handle_id": False if not item['handle_code'] else self.search(
|
"handle_id": False if not item['handle_code'] else self.search(
|
||||||
[('code', '=', item['handle_code'].replace("JKM", result['factory_short_name']))]).id,
|
[('code', '=', item['handle_code'])]).id,
|
||||||
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
"suitable_machining_method_ids": [(6, 0, [])] if not item.get(
|
||||||
'suitable_machining_methods') else self.env['maintenance.equipment.image']._get_ids(
|
'suitable_machining_method') else self.env['maintenance.equipment.image']._get_ids(
|
||||||
item['suitable_machining_methods']),
|
item['suitable_machining_method']),
|
||||||
"blade_tip_characteristics_id": self.env['maintenance.equipment.image'].search(
|
"blade_tip_characteristics_id": self.env['maintenance.equipment.image'].search(
|
||||||
[('name', '=', item['blade_tip_characteristics'])]).id,
|
[('name', '=', item['blade_tip_characteristics'])]).id,
|
||||||
"handle_type_id": self.env['maintenance.equipment.image'].search(
|
"handle_type_id": self.env['maintenance.equipment.image'].search(
|
||||||
@@ -2442,8 +2434,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[(
|
[(
|
||||||
'code', '=',
|
'code', '=',
|
||||||
integral_tool_item['standard_library_code'].replace("JKM", result[
|
integral_tool_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'total_length': integral_tool_item['total_length'],
|
'total_length': integral_tool_item['total_length'],
|
||||||
'blade_diameter': integral_tool_item['blade_diameter'],
|
'blade_diameter': integral_tool_item['blade_diameter'],
|
||||||
'blade_length': integral_tool_item['blade_length'],
|
'blade_length': integral_tool_item['blade_length'],
|
||||||
@@ -2469,8 +2460,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[(
|
[(
|
||||||
'code', '=',
|
'code', '=',
|
||||||
integral_tool_item['standard_library_code'].replace("JKM", result[
|
integral_tool_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'total_length': integral_tool_item['total_length'],
|
'total_length': integral_tool_item['total_length'],
|
||||||
'blade_diameter': integral_tool_item['blade_diameter'],
|
'blade_diameter': integral_tool_item['blade_diameter'],
|
||||||
'blade_length': integral_tool_item['blade_length'],
|
'blade_length': integral_tool_item['blade_length'],
|
||||||
@@ -2503,8 +2493,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': blade_item['code'],
|
'code': blade_item['code'],
|
||||||
'cutting_tool_type': '刀片',
|
'cutting_tool_type': '刀片',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', blade_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', blade_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'length': blade_item['length'],
|
'length': blade_item['length'],
|
||||||
'thickness': blade_item['thickness'],
|
'thickness': blade_item['thickness'],
|
||||||
'cutting_blade_length': blade_item['cutting_blade_length'],
|
'cutting_blade_length': blade_item['cutting_blade_length'],
|
||||||
@@ -2534,8 +2523,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
self.search([('code', '=', blade_item['code'])]).write({
|
self.search([('code', '=', blade_item['code'])]).write({
|
||||||
'name': blade_item['name'],
|
'name': blade_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', blade_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', blade_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'length': blade_item['length'],
|
'length': blade_item['length'],
|
||||||
'thickness': blade_item['thickness'],
|
'thickness': blade_item['thickness'],
|
||||||
'cutting_blade_length': blade_item['cutting_blade_length'],
|
'cutting_blade_length': blade_item['cutting_blade_length'],
|
||||||
@@ -2574,8 +2562,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': chuck_item['code'],
|
'code': chuck_item['code'],
|
||||||
'cutting_tool_type': '夹头',
|
'cutting_tool_type': '夹头',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', chuck_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', chuck_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'er_size_model': chuck_item['size_model'],
|
'er_size_model': chuck_item['size_model'],
|
||||||
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
||||||
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
||||||
@@ -2594,8 +2581,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
self.search([('code', '=', chuck_item['code'])]).write({
|
self.search([('code', '=', chuck_item['code'])]).write({
|
||||||
'name': chuck_item['name'],
|
'name': chuck_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', chuck_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', chuck_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'er_size_model': chuck_item['size_model'],
|
'er_size_model': chuck_item['size_model'],
|
||||||
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
||||||
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
||||||
@@ -2624,8 +2610,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': cutter_arbor_item['code'],
|
'code': cutter_arbor_item['code'],
|
||||||
'cutting_tool_type': '刀杆',
|
'cutting_tool_type': '刀杆',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_arbor_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_arbor_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'height': cutter_arbor_item['height'],
|
'height': cutter_arbor_item['height'],
|
||||||
'width': cutter_arbor_item['width'],
|
'width': cutter_arbor_item['width'],
|
||||||
'total_length': cutter_arbor_item['total_length'],
|
'total_length': cutter_arbor_item['total_length'],
|
||||||
@@ -2643,8 +2628,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'installing_structure': cutter_arbor_item['mounting_structure'],
|
'installing_structure': cutter_arbor_item['mounting_structure'],
|
||||||
'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else self.env[
|
'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_arbor_item['fit_blade_model_code'].replace("JKM", result[
|
[('code', '=', cutter_arbor_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
||||||
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
||||||
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
||||||
@@ -2656,8 +2640,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
self.search([('code', '=', cutter_arbor_item['code'])]).write({
|
self.search([('code', '=', cutter_arbor_item['code'])]).write({
|
||||||
'name': cutter_arbor_item['name'],
|
'name': cutter_arbor_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_arbor_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_arbor_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'height': cutter_arbor_item['height'],
|
'height': cutter_arbor_item['height'],
|
||||||
'width': cutter_arbor_item['width'],
|
'width': cutter_arbor_item['width'],
|
||||||
'total_length': cutter_arbor_item['total_length'],
|
'total_length': cutter_arbor_item['total_length'],
|
||||||
@@ -2675,8 +2658,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'installing_structure': cutter_arbor_item['mounting_structure'],
|
'installing_structure': cutter_arbor_item['mounting_structure'],
|
||||||
'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else self.env[
|
'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_arbor_item['fit_blade_model_code'].replace("JKM", result[
|
[('code', '=', cutter_arbor_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
||||||
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
||||||
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
||||||
@@ -2698,8 +2680,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': cutter_head_item['code'],
|
'code': cutter_head_item['code'],
|
||||||
'cutting_tool_type': '刀盘',
|
'cutting_tool_type': '刀盘',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_head_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_head_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
||||||
'blade_diameter': cutter_head_item['blade_diameter'],
|
'blade_diameter': cutter_head_item['blade_diameter'],
|
||||||
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
||||||
@@ -2712,8 +2693,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'installing_structure': cutter_head_item['mounting_structure'],
|
'installing_structure': cutter_head_item['mounting_structure'],
|
||||||
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_head_item['fit_blade_model_code'].replace("JKM", result[
|
[('code', '=', cutter_head_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'screw': cutter_head_item['fit_screw_model'],
|
'screw': cutter_head_item['fit_screw_model'],
|
||||||
'spanner': cutter_head_item['fit_wrench_model'],
|
'spanner': cutter_head_item['fit_wrench_model'],
|
||||||
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
||||||
@@ -2724,8 +2704,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
self.search([('code', '=', cutter_head_item['code'])]).write({
|
self.search([('code', '=', cutter_head_item['code'])]).write({
|
||||||
'name': cutter_head_item['name'],
|
'name': cutter_head_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_head_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_head_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
||||||
'blade_diameter': cutter_head_item['blade_diameter'],
|
'blade_diameter': cutter_head_item['blade_diameter'],
|
||||||
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
||||||
@@ -2738,8 +2717,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'installing_structure': cutter_head_item['mounting_structure'],
|
'installing_structure': cutter_head_item['mounting_structure'],
|
||||||
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_head_item['fit_blade_model_code'].replace("JKM", result[
|
[('code', '=', cutter_head_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'screw': cutter_head_item['fit_screw_model'],
|
'screw': cutter_head_item['fit_screw_model'],
|
||||||
'spanner': cutter_head_item['fit_wrench_model'],
|
'spanner': cutter_head_item['fit_wrench_model'],
|
||||||
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
||||||
@@ -2757,8 +2735,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
val = {
|
val = {
|
||||||
'name': knife_handle_item['name'],
|
'name': knife_handle_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', knife_handle_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', knife_handle_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'taper_shank_model': knife_handle_item['taper_shank_model'],
|
'taper_shank_model': knife_handle_item['taper_shank_model'],
|
||||||
'total_length': knife_handle_item['total_length'],
|
'total_length': knife_handle_item['total_length'],
|
||||||
'flange_shank_length': knife_handle_item['flange_length'],
|
'flange_shank_length': knife_handle_item['flange_length'],
|
||||||
@@ -2814,8 +2791,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[(
|
[(
|
||||||
'code', '=',
|
'code', '=',
|
||||||
integral_tool_item['standard_library_code'].replace("JKM", result[
|
integral_tool_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'total_length': integral_tool_item['total_length'],
|
'total_length': integral_tool_item['total_length'],
|
||||||
'blade_diameter': integral_tool_item['blade_diameter'],
|
'blade_diameter': integral_tool_item['blade_diameter'],
|
||||||
'blade_length': integral_tool_item['blade_length'],
|
'blade_length': integral_tool_item['blade_length'],
|
||||||
@@ -2841,8 +2817,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[(
|
[(
|
||||||
'code', '=',
|
'code', '=',
|
||||||
integral_tool_item['standard_library_code'].replace("JKM", result[
|
integral_tool_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'total_length': integral_tool_item['total_length'],
|
'total_length': integral_tool_item['total_length'],
|
||||||
'blade_diameter': integral_tool_item['blade_diameter'],
|
'blade_diameter': integral_tool_item['blade_diameter'],
|
||||||
'blade_length': integral_tool_item['blade_length'],
|
'blade_length': integral_tool_item['blade_length'],
|
||||||
@@ -2875,8 +2850,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': blade_item['code'],
|
'code': blade_item['code'],
|
||||||
'cutting_tool_type': '刀片',
|
'cutting_tool_type': '刀片',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', blade_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', blade_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'length': blade_item['length'],
|
'length': blade_item['length'],
|
||||||
'thickness': blade_item['thickness'],
|
'thickness': blade_item['thickness'],
|
||||||
'cutting_blade_length': blade_item['cutting_blade_length'],
|
'cutting_blade_length': blade_item['cutting_blade_length'],
|
||||||
@@ -2906,8 +2880,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
blade.write({
|
blade.write({
|
||||||
'name': blade_item['name'],
|
'name': blade_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', blade_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', blade_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'length': blade_item['length'],
|
'length': blade_item['length'],
|
||||||
'thickness': blade_item['thickness'],
|
'thickness': blade_item['thickness'],
|
||||||
'cutting_blade_length': blade_item['cutting_blade_length'],
|
'cutting_blade_length': blade_item['cutting_blade_length'],
|
||||||
@@ -2946,8 +2919,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': chuck_item['code'],
|
'code': chuck_item['code'],
|
||||||
'cutting_tool_type': '夹头',
|
'cutting_tool_type': '夹头',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', chuck_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', chuck_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'er_size_model': chuck_item['size_model'],
|
'er_size_model': chuck_item['size_model'],
|
||||||
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
||||||
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
||||||
@@ -2966,8 +2938,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
chuck.write({
|
chuck.write({
|
||||||
'name': chuck_item['name'],
|
'name': chuck_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', chuck_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', chuck_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'er_size_model': chuck_item['size_model'],
|
'er_size_model': chuck_item['size_model'],
|
||||||
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
'min_clamping_diameter': chuck_item['clamping_diameter_min'],
|
||||||
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
'max_clamping_diameter': chuck_item['clamping_diameter_max'],
|
||||||
@@ -2996,8 +2967,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': cutter_arbor_item['code'],
|
'code': cutter_arbor_item['code'],
|
||||||
'cutting_tool_type': '刀杆',
|
'cutting_tool_type': '刀杆',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_arbor_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_arbor_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'height': cutter_arbor_item['height'],
|
'height': cutter_arbor_item['height'],
|
||||||
'width': cutter_arbor_item['width'],
|
'width': cutter_arbor_item['width'],
|
||||||
'total_length': cutter_arbor_item['total_length'],
|
'total_length': cutter_arbor_item['total_length'],
|
||||||
@@ -3015,8 +2985,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'installing_structure': cutter_arbor_item['mounting_structure'],
|
'installing_structure': cutter_arbor_item['mounting_structure'],
|
||||||
'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else self.env[
|
'blade_id': False if not cutter_arbor_item['fit_blade_model_code'] else self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_arbor_item['fit_blade_model_code'].replace("JKM", result[
|
[('code', '=', cutter_arbor_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
||||||
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
||||||
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
||||||
@@ -3028,8 +2997,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
cutter_arbor.write({
|
cutter_arbor.write({
|
||||||
'name': cutter_arbor_item['name'],
|
'name': cutter_arbor_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_arbor_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_arbor_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'height': cutter_arbor_item['height'],
|
'height': cutter_arbor_item['height'],
|
||||||
'width': cutter_arbor_item['width'],
|
'width': cutter_arbor_item['width'],
|
||||||
'total_length': cutter_arbor_item['total_length'],
|
'total_length': cutter_arbor_item['total_length'],
|
||||||
@@ -3049,8 +3017,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
self.env[
|
self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=',
|
[('code', '=',
|
||||||
cutter_arbor_item['fit_blade_model_code'].replace("JKM", result[
|
cutter_arbor_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
'tool_shim': cutter_arbor_item['fit_knife_pad_model'],
|
||||||
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
'cotter_pin': cutter_arbor_item['fit_pin_model'],
|
||||||
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
'pressing_plate': cutter_arbor_item['fit_plate_model'],
|
||||||
@@ -3071,8 +3038,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': cutter_head_item['code'],
|
'code': cutter_head_item['code'],
|
||||||
'cutting_tool_type': '刀盘',
|
'cutting_tool_type': '刀盘',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_head_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_head_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
||||||
'blade_diameter': cutter_head_item['blade_diameter'],
|
'blade_diameter': cutter_head_item['blade_diameter'],
|
||||||
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
||||||
@@ -3085,8 +3051,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'installing_structure': cutter_head_item['mounting_structure'],
|
'installing_structure': cutter_head_item['mounting_structure'],
|
||||||
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_head_item['fit_blade_model_code'].replace("JKM", result[
|
[('code', '=', cutter_head_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'screw': cutter_head_item['fit_screw_model'],
|
'screw': cutter_head_item['fit_screw_model'],
|
||||||
'spanner': cutter_head_item['fit_wrench_model'],
|
'spanner': cutter_head_item['fit_wrench_model'],
|
||||||
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
||||||
@@ -3097,8 +3062,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
cutter_head.write({
|
cutter_head.write({
|
||||||
'name': cutter_head_item['name'],
|
'name': cutter_head_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', cutter_head_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', cutter_head_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
'install_blade_tip_num': cutter_head_item['number_blade_installed'],
|
||||||
'blade_diameter': cutter_head_item['blade_diameter'],
|
'blade_diameter': cutter_head_item['blade_diameter'],
|
||||||
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
'cutter_head_diameter': cutter_head_item['cutter_diameter'],
|
||||||
@@ -3112,8 +3076,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
'blade_id': False if not cutter_head_item['fit_blade_model_code'] else self.env[
|
||||||
'sf.cutting_tool.standard.library'].search(
|
'sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=',
|
[('code', '=',
|
||||||
cutter_head_item['fit_blade_model_code'].replace("JKM", result[
|
cutter_head_item['fit_blade_model_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'screw': cutter_head_item['fit_screw_model'],
|
'screw': cutter_head_item['fit_screw_model'],
|
||||||
'spanner': cutter_head_item['fit_wrench_model'],
|
'spanner': cutter_head_item['fit_wrench_model'],
|
||||||
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
'is_cooling_hole': cutter_head_item['is_cooling_hole'],
|
||||||
@@ -3134,8 +3097,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
'code': knife_handle_item['code'],
|
'code': knife_handle_item['code'],
|
||||||
'cutting_tool_type': '刀柄',
|
'cutting_tool_type': '刀柄',
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', knife_handle_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', knife_handle_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'total_length': knife_handle_item['total_length'],
|
'total_length': knife_handle_item['total_length'],
|
||||||
'taper_shank_model': knife_handle_item['taper_shank_model'],
|
'taper_shank_model': knife_handle_item['taper_shank_model'],
|
||||||
'flange_shank_length': knife_handle_item['flange_length'],
|
'flange_shank_length': knife_handle_item['flange_length'],
|
||||||
@@ -3161,8 +3123,7 @@ class CuttingToolBasicParameters(models.Model):
|
|||||||
knife_handle.write({
|
knife_handle.write({
|
||||||
'name': knife_handle_item['name'],
|
'name': knife_handle_item['name'],
|
||||||
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
'standard_library_id': self.env['sf.cutting_tool.standard.library'].search(
|
||||||
[('code', '=', knife_handle_item['standard_library_code'].replace("JKM", result[
|
[('code', '=', knife_handle_item['standard_library_code'])]).id,
|
||||||
'factory_short_name']))]).id,
|
|
||||||
'total_length': knife_handle_item['total_length'],
|
'total_length': knife_handle_item['total_length'],
|
||||||
'taper_shank_model': knife_handle_item['taper_shank_model'],
|
'taper_shank_model': knife_handle_item['taper_shank_model'],
|
||||||
'flange_shank_length': knife_handle_item['flange_length'],
|
'flange_shank_length': knife_handle_item['flange_length'],
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ class QualityCheck(models.Model):
|
|||||||
operation_id = fields.Many2one('mrp.routing.workcenter', '作业', store=True, compute='_compute_operation_id')
|
operation_id = fields.Many2one('mrp.routing.workcenter', '作业', store=True, compute='_compute_operation_id')
|
||||||
is_inspect = fields.Boolean('需送检', related='point_id.is_inspect')
|
is_inspect = fields.Boolean('需送检', related='point_id.is_inspect')
|
||||||
|
|
||||||
|
lot_name = fields.Char('批次/序列号 名称', compute='_compute_lot_name', store=True)
|
||||||
|
|
||||||
|
@api.depends('move_line_id', 'move_line_id.lot_name')
|
||||||
|
def _compute_lot_name(self):
|
||||||
|
for qc in self:
|
||||||
|
if qc.move_line_id:
|
||||||
|
qc.lot_name = qc.move_line_id.lot_name
|
||||||
|
|
||||||
@api.depends('point_id.operation_id')
|
@api.depends('point_id.operation_id')
|
||||||
def _compute_operation_id(self):
|
def _compute_operation_id(self):
|
||||||
for qc in self:
|
for qc in self:
|
||||||
|
|||||||
@@ -407,12 +407,6 @@ class RePurchaseOrder(models.Model):
|
|||||||
def button_confirm(self):
|
def button_confirm(self):
|
||||||
result = super(RePurchaseOrder, self).button_confirm()
|
result = super(RePurchaseOrder, self).button_confirm()
|
||||||
for item in self:
|
for item in self:
|
||||||
# 确认订单时,自动分配序列号
|
|
||||||
if item.picking_ids:
|
|
||||||
for picking_id in item.picking_ids:
|
|
||||||
if picking_id.move_ids:
|
|
||||||
for move_id in picking_id.move_ids:
|
|
||||||
move_id.put_move_line()
|
|
||||||
for line in item.order_line:
|
for line in item.order_line:
|
||||||
if line.product_id.categ_type == '表面工艺':
|
if line.product_id.categ_type == '表面工艺':
|
||||||
if item.origin:
|
if item.origin:
|
||||||
|
|||||||
@@ -127,6 +127,9 @@
|
|||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="replace">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom_qty']" position="replace">
|
||||||
<field name="product_uom_qty" string="数量" widget="merge_field" optional="show" />
|
<field name="product_uom_qty" string="数量" widget="merge_field" optional="show" />
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom'][2]" position="attributes">
|
||||||
|
<attribute name="optional">hide</attribute>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom']" position="attributes">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_uom']" position="attributes">
|
||||||
<attribute name="optional">hide</attribute>
|
<attribute name="optional">hide</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|||||||
@@ -956,7 +956,7 @@ class SfStockPicking(models.Model):
|
|||||||
qc_ids = self.env['quality.check'].sudo().search(
|
qc_ids = self.env['quality.check'].sudo().search(
|
||||||
[('picking_id', 'in', sp_ids), ('quality_state', 'in', ['waiting', 'none'])])
|
[('picking_id', 'in', sp_ids), ('quality_state', 'in', ['waiting', 'none'])])
|
||||||
if qc_ids:
|
if qc_ids:
|
||||||
raise ValidationError(f'单据{[qc.picking_id.name for qc in qc_ids]}未完成质量检查,完成后再试。')
|
raise ValidationError(f'单据{list(set(qc.picking_id.name for qc in qc_ids))}未完成质量检查,完成后再试。')
|
||||||
for record in self:
|
for record in self:
|
||||||
if record.state != 'assigned':
|
if record.state != 'assigned':
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -79,6 +79,9 @@
|
|||||||
<xpath expr="//field[@name='lot_name']" position="after">
|
<xpath expr="//field[@name='lot_name']" position="after">
|
||||||
<field name="rfid"/>
|
<field name="rfid"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='lot_name']" position="attributes">
|
||||||
|
<attribute name="readonly">True</attribute>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//field[@name='product_uom_id']" position="after">
|
<xpath expr="//field[@name='product_uom_id']" position="after">
|
||||||
<field name="lot_qr_code" widget="image"/>
|
<field name="lot_qr_code" widget="image"/>
|
||||||
<button name="print_single_method" string="打印编码" type="object" class="oe_highlight"/>
|
<button name="print_single_method" string="打印编码" type="object" class="oe_highlight"/>
|
||||||
@@ -154,7 +157,9 @@
|
|||||||
groups="sf_base.group_sf_stock_user"/>
|
groups="sf_base.group_sf_stock_user"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//header" position="inside">
|
<xpath expr="//header" position="inside">
|
||||||
<button name="batch_stock_move" type='object' string="批量调拨"/>
|
<button name="batch_stock_move" type='object' string="批量调拨"
|
||||||
|
invisible="context.get('stock_type','') in ('发料出库')"
|
||||||
|
/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='location_dest_id']" position="after">
|
<xpath expr="//field[@name='location_dest_id']" position="after">
|
||||||
<field name="product_uom_qty_sp"/>
|
<field name="product_uom_qty_sp"/>
|
||||||
@@ -162,6 +167,18 @@
|
|||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record id="view_stock_picking_type_kanban_inherit" model="ir.ui.view">
|
||||||
|
<field name="name">stock.picking.type.kanban.view.inherit</field>
|
||||||
|
<field name="model">stock.picking.type</field>
|
||||||
|
<field name="inherit_id" ref="stock.stock_picking_type_kanban"/>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<!-- 找到按钮所在位置并添加 context -->
|
||||||
|
<xpath expr="//button[@name='get_action_picking_tree_ready']" position="attributes">
|
||||||
|
<attribute name="context">{'stock_type': name}</attribute>
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<record id="sf_view_stock_move_operations" model="ir.ui.view">
|
<record id="sf_view_stock_move_operations" model="ir.ui.view">
|
||||||
<field name="name">sf.stock.move.operations.form</field>
|
<field name="name">sf.stock.move.operations.form</field>
|
||||||
<field name="model">stock.move</field>
|
<field name="model">stock.move</field>
|
||||||
|
|||||||
Reference in New Issue
Block a user