Merge branch 'refs/heads/develop' into feature/delivery_status
# Conflicts: # sf_manufacturing/models/mrp_production.py
This commit is contained in:
@@ -6,7 +6,8 @@ class ModelType(models.Model):
|
||||
_description = '模型类型'
|
||||
|
||||
name = fields.Char('名称')
|
||||
embryo_tolerance = fields.Integer('坯料容余')
|
||||
# embryo_tolerance = fields.Char('坯料容余')
|
||||
embryo_tolerance_id = fields.Many2one('sf.embryo.redundancy', string='坯料容余')
|
||||
product_routing_tmpl_ids = fields.One2many('sf.product.model.type.routing.sort', 'product_model_type_id',
|
||||
'成品工序模板(自动化产线加工')
|
||||
embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id',
|
||||
|
||||
@@ -306,16 +306,17 @@ class MrpProduction(models.Model):
|
||||
precision_rounding=move.product_uom.rounding or move.product_id.uom_id.rounding)
|
||||
for move in production.move_raw_ids if move.product_id):
|
||||
production.state = 'progress'
|
||||
|
||||
# 新添加的状态逻辑
|
||||
if (
|
||||
production.state == 'to_close' or production.state == 'progress') and production.schedule_state == '未排':
|
||||
production.state = 'confirmed'
|
||||
if not production.workorder_ids:
|
||||
production.state = 'technology_to_confirmed'
|
||||
else:
|
||||
production.state = 'confirmed'
|
||||
elif production.state == 'pending_cam' and production.schedule_state == '未排':
|
||||
production.state = 'confirmed'
|
||||
elif production.state == 'to_close' and production.schedule_state == '已排':
|
||||
production.state = 'pending_cam'
|
||||
|
||||
if production.state == 'progress':
|
||||
if all(wo_state not in ('progress', 'done', 'rework', 'scrap') for wo_state in
|
||||
production.workorder_ids.mapped('state')):
|
||||
@@ -344,11 +345,44 @@ class MrpProduction(models.Model):
|
||||
if production.tool_state == '2':
|
||||
production.state = 'rework'
|
||||
|
||||
# 退回调整
|
||||
def technology_back_adjust(self):
|
||||
process_parameters = []
|
||||
domain = [('state', '=', 'confirmed'), ('origin', '=', self.origin)]
|
||||
if self.production_type == '自动化产线加工':
|
||||
cloud_programming = self._cron_get_programming_state()
|
||||
if cloud_programming['send_state'] == 'sending':
|
||||
raise UserError(_("编程文件正在下发中,请稍后重试"))
|
||||
domain += [('programming_no', '=', self.programming_no)]
|
||||
# 带排程的制造订单
|
||||
production_confirmed = self.env['mrp.production'].search(domain)
|
||||
for special in production_confirmed.technology_design_ids:
|
||||
if special.process_parameters_id:
|
||||
product_production_process = self.env['product.template'].search(
|
||||
[('server_product_process_parameters_id', '=', special.process_parameters_id.id)])
|
||||
if not product_production_process:
|
||||
if special.process_parameters_id not in process_parameters:
|
||||
process_parameters.append(special.process_parameters_id.display_name)
|
||||
if process_parameters:
|
||||
raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters)))
|
||||
if production_confirmed:
|
||||
return {
|
||||
'name': _('退回调整'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'sf.production.technology.re_adjust.wizard',
|
||||
'target': 'new',
|
||||
'context': {
|
||||
'default_production_id': self.id,
|
||||
'default_origin': self.origin,
|
||||
}}
|
||||
|
||||
# 工艺确认
|
||||
def technology_confirm(self):
|
||||
process_parameters = []
|
||||
account_moves = []
|
||||
special_design = self.technology_design_ids.filtered(
|
||||
lambda a: a.routing_tag == 'special' and a.process_parameters_id is not False)
|
||||
lambda a: a.routing_tag == 'special' and a.is_auto is False)
|
||||
for special in special_design:
|
||||
if special.process_parameters_id:
|
||||
product_production_process = self.env['product.template'].search(
|
||||
@@ -356,6 +390,13 @@ class MrpProduction(models.Model):
|
||||
if not product_production_process:
|
||||
if special.process_parameters_id not in process_parameters:
|
||||
process_parameters.append(special.process_parameters_id.display_name)
|
||||
purchase = self.env['purchase.order'].search([('origin', '=', special.production_id.name)])
|
||||
account = self.env['account.move'].search([('id', 'in', purchase.invoice_ids)])
|
||||
if account.state not in ['cancel', False]:
|
||||
if purchase.name not in account_moves:
|
||||
account_moves.append(purchase.name)
|
||||
if account_moves:
|
||||
raise UserError(_("请联系工厂生产经理对采购订单为%s生成的账单进行取消", ", ".join(account_moves)))
|
||||
if process_parameters:
|
||||
raise UserError(_("【工艺设计】-【参数】为%s的在【产品】中不存在,请先创建", ", ".join(process_parameters)))
|
||||
# 判断同一个加工面的标准工序的顺序是否依次排序
|
||||
@@ -368,8 +409,8 @@ class MrpProduction(models.Model):
|
||||
next_index = index + 1
|
||||
next_design = technology_design[next_index]
|
||||
next_design_routing_type = next_design.route_id.routing_type
|
||||
logging.info('当前工序和加工面: %s-%s' % (design.route_id.name, design.panel))
|
||||
logging.info('下一个工序和加工面: %s-%s' % (next_design.route_id.name, next_design.panel))
|
||||
# logging.info('当前工序和加工面: %s-%s' % (design.route_id.name, design.panel))
|
||||
# logging.info('下一个工序和加工面: %s-%s' % (next_design.route_id.name, next_design.panel))
|
||||
if design.panel is not False:
|
||||
if design.panel != next_design.panel:
|
||||
if index == 0:
|
||||
@@ -636,19 +677,13 @@ class MrpProduction(models.Model):
|
||||
}]
|
||||
if production.product_id.categ_id.type == '成品':
|
||||
# # 根据工序设计生成工单
|
||||
for route in item.technology_design_ids:
|
||||
for route in production.technology_design_ids:
|
||||
if route.route_id.routing_type not in ['表面工艺']:
|
||||
workorders_values.append(
|
||||
self.env['mrp.workorder'].json_workorder_str(production, route))
|
||||
else:
|
||||
product_production_process = self.env['product.template'].search(
|
||||
[('server_product_process_parameters_id', '=', route.process_parameters_id.id)])
|
||||
# if product_production_process:
|
||||
# route_production_process = self.env[
|
||||
# 'mrp.routing.workcenter'].search(
|
||||
# [('surface_technics_id', '=', p.id),
|
||||
# ('id', 'in', route_workcenter_arr)])
|
||||
# if route_production_process:
|
||||
workorders_values.append(
|
||||
self.env[
|
||||
'mrp.workorder']._json_workorder_surface_process_str(
|
||||
@@ -662,54 +697,60 @@ class MrpProduction(models.Model):
|
||||
workorders_values.append(
|
||||
self.env['mrp.workorder'].json_workorder_str('', production, route_embryo))
|
||||
production.workorder_ids = workorders_values
|
||||
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
|
||||
('is_subcontract', '=', True)])
|
||||
if process_parameter_workorder:
|
||||
is_pick = False
|
||||
consecutive_workorders = []
|
||||
m = 0
|
||||
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
|
||||
for i in range(len(sorted_workorders) - 1):
|
||||
if m == 0:
|
||||
is_pick = False
|
||||
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
|
||||
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
|
||||
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
|
||||
if sorted_workorders[i] not in consecutive_workorders:
|
||||
consecutive_workorders.append(sorted_workorders[i])
|
||||
consecutive_workorders.append(sorted_workorders[i + 1])
|
||||
m += 1
|
||||
continue
|
||||
else:
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production)
|
||||
if sorted_workorders[i] in consecutive_workorders:
|
||||
is_pick = True
|
||||
consecutive_workorders = []
|
||||
m = 0
|
||||
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
|
||||
if is_pick is False:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
|
||||
production)
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||
production)
|
||||
if sorted_workorders[i] in consecutive_workorders:
|
||||
is_pick = True
|
||||
consecutive_workorders = []
|
||||
m = 0
|
||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
||||
if is_pick is False and m == 0:
|
||||
if len(sorted_workorders) == 1:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production)
|
||||
else:
|
||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production)
|
||||
for workorder in production.workorder_ids:
|
||||
workorder.duration_expected = workorder._get_duration_expected()
|
||||
|
||||
# 外协出入库单处理
|
||||
def get_subcontract_pick_purchase(self):
|
||||
production_all = self.sorted(lambda x: x.id)
|
||||
product_id_to_production_names = {}
|
||||
grouped_product_ids = {k: list(g) for k, g in
|
||||
groupby(production_all, key=lambda x: x.product_id.id)}
|
||||
for product_id, pd in grouped_product_ids.items():
|
||||
product_id_to_production_names[product_id] = [p.name for p in pd]
|
||||
for production in production_all:
|
||||
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
|
||||
('is_subcontract', '=', True)], order='sequence asc')
|
||||
if process_parameter_workorder:
|
||||
consecutive_workorders = []
|
||||
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.sequence)
|
||||
for i, workorder in enumerate(sorted_workorders):
|
||||
# 检查当前工作订单和下一个工作订单是否连续,并且供应商相同
|
||||
if workorder.sequence == 1:
|
||||
consecutive_workorders.append(workorder)
|
||||
elif workorder.sequence == sorted_workorders[
|
||||
i - 1].sequence + 1 and workorder.supplier_id.id == sorted_workorders[i - 1].supplier_id.id:
|
||||
consecutive_workorders.append(workorder)
|
||||
else:
|
||||
# 处理连续组,如果它不为空
|
||||
if consecutive_workorders:
|
||||
# 创建出库拣货单和采购订单
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
||||
product_id_to_production_names)
|
||||
if i < len(sorted_workorders) - 1:
|
||||
# 重置连续组,并添加当前工作订单
|
||||
consecutive_workorders = [workorder]
|
||||
else:
|
||||
# 判断最后一笔:
|
||||
if workorder.sequence == sorted_workorders[
|
||||
i - 1].sequence and workorder.supplier_id.id == sorted_workorders[
|
||||
i - 1].supplier_id.id:
|
||||
consecutive_workorders = [workorder]
|
||||
else:
|
||||
# 立即创建出库拣货单和采购订单
|
||||
self.env['stock.picking'].create_outcontract_picking(workorder, production)
|
||||
self.env['purchase.order'].get_purchase_order(workorder, production,
|
||||
product_id_to_production_names)
|
||||
consecutive_workorders = []
|
||||
|
||||
# 处理最后一个组,即使它可能只有一个工作订单
|
||||
if consecutive_workorders:
|
||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
||||
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
|
||||
product_id_to_production_names)
|
||||
|
||||
# 工单排序
|
||||
def _reset_work_order_sequence1(self, k):
|
||||
for rec in self:
|
||||
@@ -1305,17 +1346,17 @@ class MrpProduction(models.Model):
|
||||
return production_values_str
|
||||
|
||||
# 增加制造订单类型
|
||||
# production_type = fields.Selection(
|
||||
# [('自动化产线加工', '自动化产线加工'), ('人工线下加工', '人工线下加工')],
|
||||
# string='制造类型',
|
||||
# compute='_compute_production_type',
|
||||
# store=True
|
||||
# )
|
||||
production_type = fields.Selection(
|
||||
[('自动化产线加工', '自动化产线加工'), ('人工线下加工', '人工线下加工')],
|
||||
string='制造类型',
|
||||
compute='_compute_production_type',
|
||||
store=True
|
||||
)
|
||||
|
||||
# @api.depends('product_id.is_manual_processing')
|
||||
# def _compute_production_type(self):
|
||||
# for production in self:
|
||||
# production.production_type = '自动化产线加工' if not production.product_id.is_manual_processing else '人工线下加工'
|
||||
@api.depends('product_id.is_manual_processing')
|
||||
def _compute_production_type(self):
|
||||
for production in self:
|
||||
production.production_type = '自动化产线加工' if not production.product_id.is_manual_processing else '人工线下加工'
|
||||
|
||||
|
||||
class sf_detection_result(models.Model):
|
||||
|
||||
@@ -38,13 +38,10 @@ class ResMrpWorkOrder(models.Model):
|
||||
processing_panel = fields.Char('加工面')
|
||||
sequence = fields.Integer(string='工序')
|
||||
routing_type = fields.Selection([
|
||||
# ('获取CNC加工程序', '获取CNC加工程序'),
|
||||
('装夹预调', '装夹预调'),
|
||||
# ('前置三元定位检测', '前置三元定位检测'),
|
||||
('CNC加工', 'CNC加工'),
|
||||
# ('后置三元质量检测', '后置三元质量检测'),
|
||||
('解除装夹', '解除装夹'),
|
||||
('切割', '切割'), ('表面工艺', '表面工艺')
|
||||
('切割', '切割'), ('表面工艺', '表面工艺'), ('线切割', '线切割')
|
||||
], string="工序类型")
|
||||
results = fields.Char('结果')
|
||||
state = fields.Selection([
|
||||
@@ -233,7 +230,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
def _compute_surface_technics_picking_ids(self):
|
||||
for workorder in self:
|
||||
if workorder.routing_type == '表面工艺':
|
||||
domain = [('origin', '=', workorder.production_id.name)]
|
||||
domain = [('origin', '=', workorder.production_id.name), ('state', 'not in', ['cancel'])]
|
||||
previous_workorder = self.env['mrp.workorder'].search(
|
||||
[('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'),
|
||||
('production_id', '=', workorder.production_id.id)])
|
||||
@@ -267,24 +264,47 @@ class ResMrpWorkOrder(models.Model):
|
||||
def _compute_surface_technics_purchase_ids(self):
|
||||
for order in self:
|
||||
if order.routing_type == '表面工艺':
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('programming_no', '=', order.production_id.programming_no)], order='name asc')
|
||||
production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
|
||||
if order.production_id.production_type == '自动化产线加工':
|
||||
domain = [('programming_no', '=', order.production_id.programming_no)]
|
||||
else:
|
||||
domain = [('origin', '=', order.production_id.origin)]
|
||||
production_programming = self.env['mrp.production'].search(domain, order='name asc')
|
||||
production_list = [production.name for production in production_programming]
|
||||
purchase = self.env['purchase.order'].search([('origin', '=', ','.join(production_list))])
|
||||
production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
|
||||
technology_design = self.env['sf.technology.design'].search(
|
||||
[('process_parameters_id', '=', order.surface_technics_parameters_id.id),
|
||||
('production_id', '=', order.production_id.id)])
|
||||
if technology_design.is_auto is False:
|
||||
domain = [('origin', '=', order.production_id.name)]
|
||||
else:
|
||||
domain = [('origin', '=', ','.join(production_list))]
|
||||
purchase = self.env['purchase.order'].search(domain)
|
||||
if not purchase:
|
||||
order.surface_technics_purchase_count = 0
|
||||
for line in purchase.order_line:
|
||||
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id and line.product_qty == len(
|
||||
production_no_remanufacture):
|
||||
order.surface_technics_purchase_count = len(purchase)
|
||||
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id:
|
||||
if (line.product_qty == len(production_no_remanufacture)) or technology_design.is_auto is False:
|
||||
order.surface_technics_purchase_count = len(purchase)
|
||||
else:
|
||||
order.surface_technics_purchase_count = 0
|
||||
|
||||
def action_view_surface_technics_purchase(self):
|
||||
self.ensure_one()
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('programming_no', '=', self.production_id.programming_no)], order='name asc')
|
||||
if self.routing_type == '表面工艺':
|
||||
if self.production_id.production_type == '自动化产线加工':
|
||||
domain = [('programming_no', '=', self.production_id.programming_no)]
|
||||
else:
|
||||
domain = [('origin', '=', self.production_id.origin)]
|
||||
production_programming = self.env['mrp.production'].search(domain, order='name asc')
|
||||
production_list = [production.name for production in production_programming]
|
||||
purchase_orders = self.env['purchase.order'].search([('origin', '=', ','.join(production_list))])
|
||||
technology_design = self.env['sf.technology.design'].search(
|
||||
[('process_parameters_id', '=', self.surface_technics_parameters_id.id),
|
||||
('production_id', '=', self.production_id.id)])
|
||||
if technology_design.is_auto is False:
|
||||
domain = [('origin', '=', self.production_id.name)]
|
||||
else:
|
||||
domain = [('origin', '=', ','.join(production_list))]
|
||||
purchase_orders = self.env['purchase.order'].search(domain)
|
||||
result = {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "purchase.order",
|
||||
@@ -410,7 +430,8 @@ class ResMrpWorkOrder(models.Model):
|
||||
|
||||
@api.constrains('blocked_by_workorder_ids')
|
||||
def _check_no_cyclic_dependencies(self):
|
||||
if self.production_id.state not in ['rework'] and self.state not in ['rework']:
|
||||
if self.production_id.state not in ['rework', 'technology_to_confirmed', 'confirmed'] and self.state not in [
|
||||
'rework']:
|
||||
if not self._check_m2m_recursion('blocked_by_workorder_ids'):
|
||||
raise ValidationError(_("您不能创建周期性的依赖关系."))
|
||||
|
||||
@@ -421,8 +442,9 @@ class ResMrpWorkOrder(models.Model):
|
||||
for workorder in self.blocked_by_workorder_ids:
|
||||
if workorder.state in ['done', 'cancel', 'rework']:
|
||||
continue
|
||||
workorder._plan_workorder(replan)
|
||||
start_date = max(start_date, workorder.date_planned_finished)
|
||||
if workorder.production_id.state not in ['technology_to_confirmed', 'confirmed']:
|
||||
workorder._plan_workorder(replan)
|
||||
start_date = max(start_date, workorder.date_planned_finished)
|
||||
# Plan only suitable workorders
|
||||
if self.state not in ['pending', 'waiting', 'ready']:
|
||||
return
|
||||
@@ -769,6 +791,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
'operation_id': False,
|
||||
'name': route.route_id.name,
|
||||
'processing_panel': route.panel,
|
||||
'sequence': route.sequence,
|
||||
'quality_point_ids': route.route_id.quality_point_ids,
|
||||
'routing_type': route.route_id.routing_type,
|
||||
'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.route_id.workcenter_ids.ids,
|
||||
@@ -817,6 +840,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
'operation_id': False,
|
||||
'name': route.process_parameters_id.display_name,
|
||||
'processing_panel': '',
|
||||
'sequence': route.sequence,
|
||||
'routing_type': '表面工艺',
|
||||
'surface_technics_parameters_id': route.process_parameters_id.id,
|
||||
'work_state': '',
|
||||
@@ -977,10 +1001,47 @@ class ResMrpWorkOrder(models.Model):
|
||||
return workorders_values_str
|
||||
|
||||
@api.depends('production_availability', 'blocked_by_workorder_ids', 'blocked_by_workorder_ids.state',
|
||||
'production_id.tool_state')
|
||||
'production_id.tool_state', 'production_id.schedule_state')
|
||||
def _compute_state(self):
|
||||
super()._compute_state()
|
||||
# super()._compute_state()
|
||||
for workorder in self:
|
||||
if workorder.sequence != 1:
|
||||
previous_workorder = self.env['mrp.workorder'].search(
|
||||
[('production_id', '=', workorder.production_id.id),
|
||||
('sequence', '=', workorder.sequence - 1)])
|
||||
if workorder.state == 'pending':
|
||||
if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]):
|
||||
if workorder.production_id.reservation_state == 'assigned' and workorder.production_id.schedule_state == '已排':
|
||||
if (workorder.sequence == 1 and not workorder.blocked_by_workorder_ids) or (
|
||||
workorder.blocked_by_workorder_ids.state in ('done', 'cancel')) or (
|
||||
previous_workorder.state in (
|
||||
'done', 'cancel') and not workorder.blocked_by_workorder_ids):
|
||||
workorder.state = 'ready'
|
||||
continue
|
||||
if workorder.production_id.schedule_state == '未排' and workorder.state in ('waiting', 'ready'):
|
||||
if workorder.sequence != 1:
|
||||
workorder.state = 'pending'
|
||||
continue
|
||||
if workorder.state not in ('waiting', 'ready'):
|
||||
continue
|
||||
if workorder.state in (
|
||||
'waiting') and workorder.sequence == 1 and workorder.production_id.schedule_state == '已排':
|
||||
workorder.state = 'ready'
|
||||
continue
|
||||
if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]):
|
||||
workorder.state = 'pending'
|
||||
if workorder.state in ['waiting']:
|
||||
if previous_workorder.state == 'waiting':
|
||||
workorder.state = 'pending'
|
||||
if workorder.sequence == 1 and workorder.state == 'pending':
|
||||
workorder.state = 'waiting'
|
||||
continue
|
||||
if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'):
|
||||
continue
|
||||
if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting' and workorder.production_id.schedule_state == '已排':
|
||||
workorder.state = 'ready'
|
||||
elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready':
|
||||
workorder.state = 'waiting'
|
||||
re_work = self.env['mrp.workorder'].search([('production_id', '=', workorder.production_id.id),
|
||||
('processing_panel', '=', workorder.processing_panel),
|
||||
('is_rework', '=', True), ('state', 'in', ['done', 'rework'])])
|
||||
@@ -1044,7 +1105,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
workorder.state = 'ready'
|
||||
else:
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('programming_no', '=', self.production_id.programming_no)], order='name asc')
|
||||
[('origin', '=', self.production_id.origin)], order='name asc')
|
||||
production_no_remanufacture = production_programming.filtered(
|
||||
lambda a: a.is_remanufacture is False)
|
||||
production_list = [production.name for production in production_programming]
|
||||
@@ -1060,68 +1121,68 @@ class ResMrpWorkOrder(models.Model):
|
||||
elif workorder.production_id.state == 'scrap':
|
||||
if workorder.routing_type == '解除装夹' and unclamp_workorder.test_results == '报废':
|
||||
workorder.state = 'waiting'
|
||||
if workorder.routing_type == '装夹预调' and workorder.state in ['waiting', 'ready', 'pending']:
|
||||
workorder_ids = workorder.production_id.workorder_ids
|
||||
work_bo = True
|
||||
for wo in workorder_ids.filtered(lambda a: a.routing_type == '装夹预调' and a.state == 'rework'):
|
||||
if not workorder_ids.filtered(
|
||||
lambda a: (a.routing_type == '装夹预调' and a.state not in ['rework', 'cancel']
|
||||
and a.processing_panel == wo.processing_panel)):
|
||||
work_bo = False
|
||||
break
|
||||
if (workorder.production_id.programming_state == '已编程' and work_bo
|
||||
and not workorder_ids.filtered(lambda a: a.sequence == 0)):
|
||||
# 当工单对应制造订单的功能刀具状态为 【无效刀】时,先对的第一个装夹预调工单状态设置为 【等待组件】
|
||||
if workorder.production_id.tool_state in ['1', '2']:
|
||||
if workorder.state in ['ready']:
|
||||
workorder.state = 'waiting'
|
||||
continue
|
||||
elif workorder.state in ['waiting']:
|
||||
continue
|
||||
elif workorder.state == 'pending' and workorder == self.search(
|
||||
[('production_id', '=', workorder.production_id.id),
|
||||
('routing_type', '=', '装夹预调'),
|
||||
('state', 'not in', ['rework', 'done', 'cancel'])],
|
||||
limit=1,
|
||||
order="sequence"):
|
||||
workorder.state = 'waiting'
|
||||
continue
|
||||
elif workorder.production_id.tool_state in ['0']:
|
||||
if workorder_ids.filtered(lambda a: a.state == 'rework'):
|
||||
if not workorder_ids.filtered(
|
||||
lambda a: (a.routing_type not in ['装夹预调'] and
|
||||
a.state not in ['pending', 'done', 'rework', 'cancel'])):
|
||||
# 查询工序最小的非完工、非返工的装夹预调工单
|
||||
work_id = self.search(
|
||||
[('production_id', '=', workorder.production_id.id),
|
||||
('state', 'not in', ['rework', 'done', 'cancel'])],
|
||||
limit=1,
|
||||
order="sequence")
|
||||
if work_id.routing_type == '装夹预调':
|
||||
if workorder == work_id:
|
||||
if workorder.production_id.reservation_state == 'assigned':
|
||||
workorder.state = 'ready'
|
||||
elif workorder.production_id.reservation_state != 'assigned':
|
||||
workorder.state = 'waiting'
|
||||
continue
|
||||
elif (workorder.name == '装夹预调' and
|
||||
workorder.state not in ['rework', 'done', 'cancel']):
|
||||
if workorder.state != 'pending':
|
||||
workorder.state = 'pending'
|
||||
if workorder.production_id.tool_state in ['1', '2'] and workorder.state == 'ready':
|
||||
workorder.state = 'waiting'
|
||||
continue
|
||||
if (workorder.production_id.tool_state in ['1', '2']
|
||||
and not workorder.production_id.workorder_ids.filtered(lambda a: a.sequence == 0)
|
||||
and workorder.production_id.programming_state == '编程中' and workorder.name == '装夹预调'):
|
||||
if workorder.state == 'pending' and workorder == self.search(
|
||||
[('production_id', '=', workorder.production_id.id),
|
||||
('routing_type', '=', '装夹预调'),
|
||||
('state', 'not in', ['rework', 'done', 'cancel'])],
|
||||
limit=1,
|
||||
order="sequence"):
|
||||
workorder.state = 'waiting'
|
||||
continue
|
||||
# if workorder.routing_type == '装夹预调' and workorder.state in ['waiting', 'ready', 'pending']:
|
||||
# workorder_ids = workorder.production_id.workorder_ids
|
||||
# work_bo = True
|
||||
# for wo in workorder_ids.filtered(lambda a: a.routing_type == '装夹预调' and a.state == 'rework'):
|
||||
# if not workorder_ids.filtered(
|
||||
# lambda a: (a.routing_type == '装夹预调' and a.state not in ['rework', 'cancel']
|
||||
# and a.processing_panel == wo.processing_panel)):
|
||||
# work_bo = False
|
||||
# break
|
||||
# if (workorder.production_id.programming_state == '已编程' and work_bo
|
||||
# and not workorder_ids.filtered(lambda a: a.sequence == 0)):
|
||||
# # 当工单对应制造订单的功能刀具状态为 【无效刀】时,先对的第一个装夹预调工单状态设置为 【等待组件】
|
||||
# if workorder.production_id.tool_state in ['1', '2']:
|
||||
# if workorder.state in ['ready']:
|
||||
# workorder.state = 'waiting'
|
||||
# continue
|
||||
# elif workorder.state in ['waiting']:
|
||||
# continue
|
||||
# elif workorder.state == 'pending' and workorder == self.search(
|
||||
# [('production_id', '=', workorder.production_id.id),
|
||||
# ('routing_type', '=', '装夹预调'),
|
||||
# ('state', 'not in', ['rework', 'done', 'cancel'])],
|
||||
# limit=1,
|
||||
# order="sequence"):
|
||||
# workorder.state = 'waiting'
|
||||
# continue
|
||||
# elif workorder.production_id.tool_state in ['0']:
|
||||
# if workorder_ids.filtered(lambda a: a.state == 'rework'):
|
||||
# if not workorder_ids.filtered(
|
||||
# lambda a: (a.routing_type not in ['装夹预调'] and
|
||||
# a.state not in ['pending', 'done', 'rework', 'cancel'])):
|
||||
# # 查询工序最小的非完工、非返工的装夹预调工单
|
||||
# work_id = self.search(
|
||||
# [('production_id', '=', workorder.production_id.id),
|
||||
# ('state', 'not in', ['rework', 'done', 'cancel'])],
|
||||
# limit=1,
|
||||
# order="sequence")
|
||||
# if work_id.routing_type == '装夹预调':
|
||||
# if workorder == work_id:
|
||||
# if workorder.production_id.reservation_state == 'assigned':
|
||||
# workorder.state = 'ready'
|
||||
# elif workorder.production_id.reservation_state != 'assigned':
|
||||
# workorder.state = 'waiting'
|
||||
# continue
|
||||
# elif (workorder.name == '装夹预调' and
|
||||
# workorder.state not in ['rework', 'done', 'cancel']):
|
||||
# if workorder.state != 'pending':
|
||||
# workorder.state = 'pending'
|
||||
# if workorder.production_id.tool_state in ['1', '2'] and workorder.state == 'ready':
|
||||
# workorder.state = 'waiting'
|
||||
# continue
|
||||
# if (workorder.production_id.tool_state in ['1', '2']
|
||||
# and not workorder.production_id.workorder_ids.filtered(lambda a: a.sequence == 0)
|
||||
# and workorder.production_id.programming_state == '编程中' and workorder.name == '装夹预调'):
|
||||
# if workorder.state == 'pending' and workorder == self.search(
|
||||
# [('production_id', '=', workorder.production_id.id),
|
||||
# ('routing_type', '=', '装夹预调'),
|
||||
# ('state', 'not in', ['rework', 'done', 'cancel'])],
|
||||
# limit=1,
|
||||
# order="sequence"):
|
||||
# workorder.state = 'waiting'
|
||||
# continue
|
||||
|
||||
# 重写工单开始按钮方法
|
||||
def button_start(self):
|
||||
@@ -1131,7 +1192,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
'actual_start_time': datetime.now()
|
||||
})
|
||||
|
||||
if self.routing_type == '装夹预调':
|
||||
if self.sequence == 1:
|
||||
# 判断是否有坯料的序列号信息
|
||||
boolean = False
|
||||
if self.production_id.move_raw_ids:
|
||||
@@ -1242,8 +1303,8 @@ class ResMrpWorkOrder(models.Model):
|
||||
if record.is_rework is False:
|
||||
if not record.material_center_point:
|
||||
raise UserError("坯料中心点为空,请检查")
|
||||
# if record.X_deviation_angle <= 0:
|
||||
# raise UserError("X偏差角度小于等于0,请检查!本次计算的X偏差角度为:%s" % record.X_deviation_angle)
|
||||
# if record.X_deviation_angle <= 0:
|
||||
# raise UserError("X偏差角度小于等于0,请检查!本次计算的X偏差角度为:%s" % record.X_deviation_angle)
|
||||
record.process_state = '待加工'
|
||||
# record.write({'process_state': '待加工'})
|
||||
record.production_id.process_state = '待加工'
|
||||
@@ -1273,23 +1334,10 @@ class ResMrpWorkOrder(models.Model):
|
||||
'''
|
||||
record.date_finished = datetime.now()
|
||||
if record.routing_type == '表面工艺':
|
||||
logging.info('record.picking_ids:%s' % record.picking_ids)
|
||||
logging.info('record.picking_out:%s' % record.picking_ids[0])
|
||||
if record.picking_ids:
|
||||
for pick_item in record.picking_ids:
|
||||
if pick_item.state not in ['done']:
|
||||
raise UserError(
|
||||
'请先完成该工单的工艺外协再进行操作')
|
||||
picking_out = record.env['stock.move.line'].search(
|
||||
[('picking_id', '=', record.picking_ids[0].id)])
|
||||
logging.info('picking_out:%s' % picking_out.picking_id.name)
|
||||
# if picking_out:
|
||||
# order_line_ids = []
|
||||
# logging.info('surface_technics_parameters_id:%s' % record.surface_technics_parameters_id.name)
|
||||
#
|
||||
# else:
|
||||
# raise UserError(
|
||||
# '请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
|
||||
picks = record.picking_ids.filtered(lambda p: p.state not in ('done'))
|
||||
if picks:
|
||||
raise UserError('请先完成该工单的工艺外协再进行操作')
|
||||
tem_date_planned_finished = record.date_planned_finished
|
||||
tem_date_finished = record.date_finished
|
||||
logging.info('routing_type:%s' % record.routing_type)
|
||||
|
||||
@@ -850,14 +850,21 @@ class ResProductMo(models.Model):
|
||||
copy_product_id.product_tmpl_id.active = True
|
||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||
attachment = self.attachment_create(item['model_name'], item['model_data'])
|
||||
# 获取坯料冗余配置
|
||||
if not item.get('embryo_redundancy'):
|
||||
embryo_redundancy_id = model_type.embryo_tolerance_id
|
||||
else:
|
||||
embryo_redundancy_id = item.get('embryo_redundancy')
|
||||
if not embryo_redundancy_id:
|
||||
raise UserError('请先配置模型类型内的坯料冗余')
|
||||
vals = {
|
||||
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
||||
'model_long': item['model_long'] + model_type.embryo_tolerance,
|
||||
'model_width': item['model_width'] + model_type.embryo_tolerance,
|
||||
'model_height': item['model_height'] + model_type.embryo_tolerance,
|
||||
'model_volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||
item['model_width'] + model_type.embryo_tolerance) * (
|
||||
item['model_height'] + model_type.embryo_tolerance),
|
||||
'model_long': item['model_long'] + embryo_redundancy_id.long,
|
||||
'model_width': item['model_width'] + embryo_redundancy_id.width,
|
||||
'model_height': item['model_height'] + embryo_redundancy_id.height,
|
||||
'model_volume': (item['model_long'] + embryo_redundancy_id.long) * (
|
||||
item['model_width'] + embryo_redundancy_id.width) * (
|
||||
item['model_height'] + embryo_redundancy_id.height),
|
||||
'product_model_type_id': model_type.id,
|
||||
'model_processing_panel': item['processing_panel_detail'],
|
||||
'model_machining_precision': item['model_machining_precision'],
|
||||
@@ -941,19 +948,26 @@ class ResProductMo(models.Model):
|
||||
[('materials_no', '=', item['texture_type_code'])])
|
||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||
supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
|
||||
# 获取坯料冗余配置
|
||||
if not item.get('embryo_redundancy_id'):
|
||||
embryo_redundancy_id = model_type.embryo_tolerance_id
|
||||
else:
|
||||
embryo_redundancy_id = item.get('embryo_redundancy_id')
|
||||
if not embryo_redundancy_id:
|
||||
raise UserError('请先配置模型类型内的坯料冗余')
|
||||
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
||||
vals = {
|
||||
'name': '%s-%s-%s [%s %s-%s * %s * %s]' % ('R',
|
||||
order_id.name, i, materials_id.name, materials_type_id.name,
|
||||
item['model_long'] + model_type.embryo_tolerance,
|
||||
item['model_width'] + model_type.embryo_tolerance,
|
||||
item['model_height'] + model_type.embryo_tolerance),
|
||||
'length': item['model_long'] + model_type.embryo_tolerance,
|
||||
'width': item['model_width'] + model_type.embryo_tolerance,
|
||||
'height': item['model_height'] + model_type.embryo_tolerance,
|
||||
'volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||
item['model_width'] + model_type.embryo_tolerance) * (
|
||||
item['model_height'] + model_type.embryo_tolerance),
|
||||
item['model_long'] + embryo_redundancy_id.long,
|
||||
item['model_width'] + embryo_redundancy_id.width,
|
||||
item['model_height'] + embryo_redundancy_id.height),
|
||||
'length': item['model_long'] + embryo_redundancy_id.long,
|
||||
'width': item['model_width'] + embryo_redundancy_id.width,
|
||||
'height': item['model_height'] + embryo_redundancy_id.height,
|
||||
'volume': (item['model_long'] + embryo_redundancy_id.long) * (
|
||||
item['model_width'] + embryo_redundancy_id.width) * (
|
||||
item['model_height'] + embryo_redundancy_id.height),
|
||||
'embryo_model_type_id': model_type.id,
|
||||
'list_price': item['price'],
|
||||
'materials_id': materials_id.id,
|
||||
|
||||
@@ -16,13 +16,13 @@ class sf_technology_design(models.Model):
|
||||
is_auto = fields.Boolean('是否自动生成', default=False)
|
||||
active = fields.Boolean('有效', default=True)
|
||||
|
||||
def json_technology_design_str(self, k, route, i):
|
||||
def json_technology_design_str(self, k, route, i, process_parameter):
|
||||
workorders_values_str = [0, '', {
|
||||
'route_id': route.id,
|
||||
'panel': k,
|
||||
'process_parameters_id': False if route.routing_type != '表面工艺' else self.env[
|
||||
'sf.production.process.parameter'].search(
|
||||
[('process_id', '=', route.surface_technics_id.id)]).id,
|
||||
[('id', '=', process_parameter.id)]).id,
|
||||
'sequence': i,
|
||||
'is_auto': True}]
|
||||
return workorders_values_str
|
||||
|
||||
@@ -66,358 +66,311 @@ class stockWarehouse(models.Model):
|
||||
class StockRule(models.Model):
|
||||
_inherit = 'stock.rule'
|
||||
|
||||
# @api.model
|
||||
# def _run_pull(self, procurements):
|
||||
# logging.info(procurements)
|
||||
# moves_values_by_company = defaultdict(list)
|
||||
# mtso_products_by_locations = defaultdict(list)
|
||||
@api.model
|
||||
def _run_pull(self, procurements):
|
||||
logging.info(procurements)
|
||||
moves_values_by_company = defaultdict(list)
|
||||
mtso_products_by_locations = defaultdict(list)
|
||||
|
||||
# # To handle the `mts_else_mto` procure method, we do a preliminary loop to
|
||||
# # isolate the products we would need to read the forecasted quantity,
|
||||
# # in order to to batch the read. We also make a sanitary check on the
|
||||
# # `location_src_id` field.
|
||||
# To handle the `mts_else_mto` procure method, we do a preliminary loop to
|
||||
# isolate the products we would need to read the forecasted quantity,
|
||||
# in order to to batch the read. We also make a sanitary check on the
|
||||
# `location_src_id` field.
|
||||
|
||||
# # list1 = []
|
||||
# # for item in procurements:
|
||||
# # num = int(item[0].product_qty)
|
||||
# # if num > 1:
|
||||
# # for no in range(1, num+1):
|
||||
# #
|
||||
# # Procurement = namedtuple('Procurement', ['product_id', 'product_qty',
|
||||
# # 'product_uom', 'location_id', 'name', 'origin',
|
||||
# # 'company_id',
|
||||
# # 'values'])
|
||||
# # s = Procurement(product_id=item[0].product_id,product_qty=1.0,product_uom=item[0].product_uom,
|
||||
# # location_id=item[0].location_id,
|
||||
# # name=item[0].name,
|
||||
# # origin=item[0].origin,
|
||||
# # company_id=item[0].company_id,
|
||||
# # values=item[0].values,
|
||||
# # )
|
||||
# # item1 = list(item)
|
||||
# # item1[0]=s
|
||||
# #
|
||||
# # list1.append(tuple(item1))
|
||||
# # else:
|
||||
# # list1.append(item)
|
||||
# list1 = []
|
||||
# for item in procurements:
|
||||
# num = int(item[0].product_qty)
|
||||
# if num > 1:
|
||||
# for no in range(1, num+1):
|
||||
#
|
||||
# Procurement = namedtuple('Procurement', ['product_id', 'product_qty',
|
||||
# 'product_uom', 'location_id', 'name', 'origin',
|
||||
# 'company_id',
|
||||
# 'values'])
|
||||
# s = Procurement(product_id=item[0].product_id,product_qty=1.0,product_uom=item[0].product_uom,
|
||||
# location_id=item[0].location_id,
|
||||
# name=item[0].name,
|
||||
# origin=item[0].origin,
|
||||
# company_id=item[0].company_id,
|
||||
# values=item[0].values,
|
||||
# )
|
||||
# item1 = list(item)
|
||||
# item1[0]=s
|
||||
#
|
||||
# list1.append(tuple(item1))
|
||||
# else:
|
||||
# list1.append(item)
|
||||
|
||||
# for procurement, rule in procurements:
|
||||
# if not rule.location_src_id:
|
||||
# msg = _('No source location defined on stock rule: %s!') % (rule.name,)
|
||||
# raise ProcurementException([(procurement, msg)])
|
||||
for procurement, rule in procurements:
|
||||
if not rule.location_src_id:
|
||||
msg = _('No source location defined on stock rule: %s!') % (rule.name,)
|
||||
raise ProcurementException([(procurement, msg)])
|
||||
|
||||
# if rule.procure_method == 'mts_else_mto':
|
||||
# mtso_products_by_locations[rule.location_src_id].append(procurement.product_id.id)
|
||||
if rule.procure_method == 'mts_else_mto':
|
||||
mtso_products_by_locations[rule.location_src_id].append(procurement.product_id.id)
|
||||
|
||||
# # Get the forecasted quantity for the `mts_else_mto` procurement.
|
||||
# forecasted_qties_by_loc = {}
|
||||
# for location, product_ids in mtso_products_by_locations.items():
|
||||
# products = self.env['product.product'].browse(product_ids).with_context(location=location.id)
|
||||
# forecasted_qties_by_loc[location] = {product.id: product.free_qty for product in products}
|
||||
# Get the forecasted quantity for the `mts_else_mto` procurement.
|
||||
forecasted_qties_by_loc = {}
|
||||
for location, product_ids in mtso_products_by_locations.items():
|
||||
products = self.env['product.product'].browse(product_ids).with_context(location=location.id)
|
||||
forecasted_qties_by_loc[location] = {product.id: product.free_qty for product in products}
|
||||
|
||||
# # Prepare the move values, adapt the `procure_method` if needed.
|
||||
# procurements = sorted(procurements, key=lambda proc: float_compare(proc[0].product_qty, 0.0,
|
||||
# precision_rounding=proc[
|
||||
# 0].product_uom.rounding) > 0)
|
||||
# list2 = []
|
||||
# for item in procurements:
|
||||
# num = int(item[0].product_qty)
|
||||
# Prepare the move values, adapt the `procure_method` if needed.
|
||||
procurements = sorted(procurements, key=lambda proc: float_compare(proc[0].product_qty, 0.0,
|
||||
precision_rounding=proc[
|
||||
0].product_uom.rounding) > 0)
|
||||
list2 = []
|
||||
for item in procurements:
|
||||
num = int(item[0].product_qty)
|
||||
|
||||
# product = self.env['product.product'].search(
|
||||
# [("id", '=', item[0].product_id.id)])
|
||||
# product_tmpl = self.env['product.template'].search(
|
||||
# ["&", ("id", '=', product.product_tmpl_id.id), ('single_manufacturing', "!=", False)])
|
||||
# if product_tmpl:
|
||||
# if num > 1:
|
||||
# for no in range(1, num + 1):
|
||||
# Procurement = namedtuple('Procurement', ['product_id', 'product_qty',
|
||||
# 'product_uom', 'location_id', 'name', 'origin',
|
||||
# 'company_id',
|
||||
# 'values'])
|
||||
# s = Procurement(product_id=item[0].product_id, product_qty=1.0, product_uom=item[0].product_uom,
|
||||
# location_id=item[0].location_id,
|
||||
# name=item[0].name,
|
||||
# origin=item[0].origin,
|
||||
# company_id=item[0].company_id,
|
||||
# values=item[0].values,
|
||||
# )
|
||||
# item1 = list(item)
|
||||
# item1[0] = s
|
||||
product = self.env['product.product'].search(
|
||||
[("id", '=', item[0].product_id.id)])
|
||||
product_tmpl = self.env['product.template'].search(
|
||||
["&", ("id", '=', product.product_tmpl_id.id), ('single_manufacturing', "!=", False)])
|
||||
if product_tmpl:
|
||||
if num > 1:
|
||||
for no in range(1, num + 1):
|
||||
Procurement = namedtuple('Procurement', ['product_id', 'product_qty',
|
||||
'product_uom', 'location_id', 'name', 'origin',
|
||||
'company_id',
|
||||
'values'])
|
||||
s = Procurement(product_id=item[0].product_id, product_qty=1.0, product_uom=item[0].product_uom,
|
||||
location_id=item[0].location_id,
|
||||
name=item[0].name,
|
||||
origin=item[0].origin,
|
||||
company_id=item[0].company_id,
|
||||
values=item[0].values,
|
||||
)
|
||||
item1 = list(item)
|
||||
item1[0] = s
|
||||
|
||||
# list2.append(tuple(item1))
|
||||
# else:
|
||||
# list2.append(item)
|
||||
# else:
|
||||
# list2.append(item)
|
||||
list2.append(tuple(item1))
|
||||
else:
|
||||
list2.append(item)
|
||||
else:
|
||||
list2.append(item)
|
||||
|
||||
# for procurement, rule in list2:
|
||||
# procure_method = rule.procure_method
|
||||
# if rule.procure_method == 'mts_else_mto':
|
||||
# qty_needed = procurement.product_uom._compute_quantity(procurement.product_qty,
|
||||
# procurement.product_id.uom_id)
|
||||
# if float_compare(qty_needed, 0, precision_rounding=procurement.product_id.uom_id.rounding) <= 0:
|
||||
# procure_method = 'make_to_order'
|
||||
# for move in procurement.values.get('group_id', self.env['procurement.group']).stock_move_ids:
|
||||
# if move.rule_id == rule and float_compare(move.product_uom_qty, 0,
|
||||
# precision_rounding=move.product_uom.rounding) > 0:
|
||||
# procure_method = move.procure_method
|
||||
# break
|
||||
# forecasted_qties_by_loc[rule.location_src_id][procurement.product_id.id] -= qty_needed
|
||||
# elif float_compare(qty_needed, forecasted_qties_by_loc[rule.location_src_id][procurement.product_id.id],
|
||||
# precision_rounding=procurement.product_id.uom_id.rounding) > 0:
|
||||
# procure_method = 'make_to_order'
|
||||
# else:
|
||||
# forecasted_qties_by_loc[rule.location_src_id][procurement.product_id.id] -= qty_needed
|
||||
# procure_method = 'make_to_stock'
|
||||
# move_values = rule._get_stock_move_values(*procurement)
|
||||
# move_values['procure_method'] = procure_method
|
||||
# moves_values_by_company[procurement.company_id.id].append(move_values)
|
||||
for procurement, rule in list2:
|
||||
procure_method = rule.procure_method
|
||||
if rule.procure_method == 'mts_else_mto':
|
||||
qty_needed = procurement.product_uom._compute_quantity(procurement.product_qty,
|
||||
procurement.product_id.uom_id)
|
||||
if float_compare(qty_needed, 0, precision_rounding=procurement.product_id.uom_id.rounding) <= 0:
|
||||
procure_method = 'make_to_order'
|
||||
for move in procurement.values.get('group_id', self.env['procurement.group']).stock_move_ids:
|
||||
if move.rule_id == rule and float_compare(move.product_uom_qty, 0,
|
||||
precision_rounding=move.product_uom.rounding) > 0:
|
||||
procure_method = move.procure_method
|
||||
break
|
||||
forecasted_qties_by_loc[rule.location_src_id][procurement.product_id.id] -= qty_needed
|
||||
elif float_compare(qty_needed, forecasted_qties_by_loc[rule.location_src_id][procurement.product_id.id],
|
||||
precision_rounding=procurement.product_id.uom_id.rounding) > 0:
|
||||
procure_method = 'make_to_order'
|
||||
else:
|
||||
forecasted_qties_by_loc[rule.location_src_id][procurement.product_id.id] -= qty_needed
|
||||
procure_method = 'make_to_stock'
|
||||
move_values = rule._get_stock_move_values(*procurement)
|
||||
move_values['procure_method'] = procure_method
|
||||
moves_values_by_company[procurement.company_id.id].append(move_values)
|
||||
|
||||
# for company_id, moves_values in moves_values_by_company.items():
|
||||
# # create the move as SUPERUSER because the current user may not have the rights to do it (mto product
|
||||
# # launched by a sale for example)
|
||||
# moves = self.env['stock.move'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
||||
# moves_values)
|
||||
# # Since action_confirm launch following procurement_group we should activate it.
|
||||
# moves._action_confirm()
|
||||
# return True
|
||||
for company_id, moves_values in moves_values_by_company.items():
|
||||
# create the move as SUPERUSER because the current user may not have the rights to do it (mto product
|
||||
# launched by a sale for example)
|
||||
moves = self.env['stock.move'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
||||
moves_values)
|
||||
# Since action_confirm launch following procurement_group we should activate it.
|
||||
moves._action_confirm()
|
||||
return True
|
||||
|
||||
def attachment_update(self, name, res_id, res_field):
|
||||
attachment_info = self.env['ir.attachment'].sudo().search(
|
||||
[('res_id', '=', res_id), ('res_field', '=', res_field)], limit=1)
|
||||
attachment_info.write({'name': name})
|
||||
|
||||
# @api.model
|
||||
# def _run_manufacture(self, procurements):
|
||||
# productions_values_by_company = defaultdict(list)
|
||||
# errors = []
|
||||
# for procurement, rule in procurements:
|
||||
# if float_compare(procurement.product_qty, 0, precision_rounding=procurement.product_uom.rounding) <= 0:
|
||||
# # If procurement contains negative quantity, don't create a MO that would be for a negative value.
|
||||
# continue
|
||||
# bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values)
|
||||
@api.model
|
||||
def _run_manufacture(self, procurements):
|
||||
productions_values_by_company = defaultdict(list)
|
||||
errors = []
|
||||
for procurement, rule in procurements:
|
||||
if float_compare(procurement.product_qty, 0, precision_rounding=procurement.product_uom.rounding) <= 0:
|
||||
# If procurement contains negative quantity, don't create a MO that would be for a negative value.
|
||||
continue
|
||||
bom = rule._get_matching_bom(procurement.product_id, procurement.company_id, procurement.values)
|
||||
|
||||
# productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom))
|
||||
productions_values_by_company[procurement.company_id.id].append(rule._prepare_mo_vals(*procurement, bom))
|
||||
|
||||
# if errors:
|
||||
# raise ProcurementException(errors)
|
||||
if errors:
|
||||
raise ProcurementException(errors)
|
||||
|
||||
# for company_id, productions_values in productions_values_by_company.items():
|
||||
# # create the MO as SUPERUSER because the current user may not have the rights to do it
|
||||
# # (mto product launched by a sale for example)
|
||||
# '''创建制造订单'''
|
||||
# productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
||||
# productions_values)
|
||||
for company_id, productions_values in productions_values_by_company.items():
|
||||
# create the MO as SUPERUSER because the current user may not have the rights to do it
|
||||
# (mto product launched by a sale for example)
|
||||
'''创建制造订单'''
|
||||
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
||||
productions_values)
|
||||
|
||||
# # self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
||||
# # self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
||||
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||
|
||||
# '''
|
||||
# 创建工单
|
||||
# '''
|
||||
# # productions._create_workorder()
|
||||
# #
|
||||
# self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||
# productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
|
||||
# (
|
||||
# p.move_dest_ids.procure_method != 'make_to_order' and not
|
||||
# p.move_raw_ids and not p.workorder_ids)).action_confirm()
|
||||
# # 处理 根据制造订单生成的采购单坯料入库时到原材料库,手动将原材料位置该为坯料存货区
|
||||
# for production in productions:
|
||||
# if production.picking_ids:
|
||||
# product_type_id = production.picking_ids[0].move_ids[0].product_id.categ_id
|
||||
# if product_type_id.name == '坯料':
|
||||
# location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')])
|
||||
# if not location_id:
|
||||
# logging.info(f'没有搜索到【坯料存货区】: {location_id}')
|
||||
# break
|
||||
# for picking_id in production.picking_ids:
|
||||
# if picking_id.picking_type_id.name == '内部调拨':
|
||||
# if picking_id.location_dest_id.product_type != product_type_id:
|
||||
# picking_id.location_dest_id = location_id.id
|
||||
# elif picking_id.picking_type_id.name == '生产发料':
|
||||
# if picking_id.location_id.product_type != product_type_id:
|
||||
# picking_id.location_id = location_id.id
|
||||
'''
|
||||
创建工单
|
||||
'''
|
||||
# productions._create_workorder()
|
||||
#
|
||||
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
|
||||
(
|
||||
p.move_dest_ids.procure_method != 'make_to_order' and not
|
||||
p.move_raw_ids and not p.workorder_ids)).action_confirm()
|
||||
# 处理 根据制造订单生成的采购单坯料入库时到原材料库,手动将原材料位置该为坯料存货区
|
||||
for production in productions:
|
||||
if production.picking_ids:
|
||||
product_type_id = production.picking_ids[0].move_ids[0].product_id.categ_id
|
||||
if product_type_id.name == '坯料':
|
||||
location_id = self.env['stock.location'].search([('name', '=', '坯料存货区')])
|
||||
if not location_id:
|
||||
logging.info(f'没有搜索到【坯料存货区】: {location_id}')
|
||||
break
|
||||
for picking_id in production.picking_ids:
|
||||
if picking_id.picking_type_id.name == '内部调拨':
|
||||
if picking_id.location_dest_id.product_type != product_type_id:
|
||||
picking_id.location_dest_id = location_id.id
|
||||
elif picking_id.picking_type_id.name == '生产发料':
|
||||
if picking_id.location_id.product_type != product_type_id:
|
||||
picking_id.location_id = location_id.id
|
||||
|
||||
# for production in productions:
|
||||
# '''
|
||||
# 创建制造订单时生成序列号
|
||||
# '''
|
||||
# production.action_generate_serial()
|
||||
# origin_production = production.move_dest_ids and production.move_dest_ids[
|
||||
# 0].raw_material_production_id or False
|
||||
# orderpoint = production.orderpoint_id
|
||||
# if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual':
|
||||
# production.message_post(
|
||||
# body=_('This production order has been created from Replenishment Report.'),
|
||||
# message_type='comment',
|
||||
# subtype_xmlid='mail.mt_note')
|
||||
# elif orderpoint:
|
||||
# production.message_post_with_view(
|
||||
# 'mail.message_origin_link',
|
||||
# values={'self': production, 'origin': orderpoint},
|
||||
# subtype_id=self.env.ref('mail.mt_note').id)
|
||||
# elif origin_production:
|
||||
# production.message_post_with_view(
|
||||
# 'mail.message_origin_link',
|
||||
# values={'self': production, 'origin': origin_production},
|
||||
# subtype_id=self.env.ref('mail.mt_note').id)
|
||||
for production in productions:
|
||||
'''
|
||||
创建制造订单时生成序列号
|
||||
'''
|
||||
production.action_generate_serial()
|
||||
origin_production = production.move_dest_ids and production.move_dest_ids[
|
||||
0].raw_material_production_id or False
|
||||
orderpoint = production.orderpoint_id
|
||||
if orderpoint and orderpoint.create_uid.id == SUPERUSER_ID and orderpoint.trigger == 'manual':
|
||||
production.message_post(
|
||||
body=_('This production order has been created from Replenishment Report.'),
|
||||
message_type='comment',
|
||||
subtype_xmlid='mail.mt_note')
|
||||
elif orderpoint:
|
||||
production.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': production, 'origin': orderpoint},
|
||||
subtype_id=self.env.ref('mail.mt_note').id)
|
||||
elif origin_production:
|
||||
production.message_post_with_view(
|
||||
'mail.message_origin_link',
|
||||
values={'self': production, 'origin': origin_production},
|
||||
subtype_id=self.env.ref('mail.mt_note').id)
|
||||
|
||||
# '''
|
||||
# 创建生产计划
|
||||
# '''
|
||||
# # 工单耗时
|
||||
# workorder_duration = 0
|
||||
# for workorder in production.workorder_ids:
|
||||
# workorder_duration += workorder.duration_expected
|
||||
'''
|
||||
创建生产计划
|
||||
'''
|
||||
# 工单耗时
|
||||
workorder_duration = 0
|
||||
for workorder in production.workorder_ids:
|
||||
workorder_duration += workorder.duration_expected
|
||||
|
||||
# sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
|
||||
# if sale_order:
|
||||
# # sale_order.write({'schedule_status': 'to schedule'})
|
||||
# self.env['sf.production.plan'].sudo().with_company(company_id).create({
|
||||
# 'name': production.name,
|
||||
# 'order_deadline': sale_order.deadline_of_delivery,
|
||||
# 'production_id': production.id,
|
||||
# 'date_planned_start': production.date_planned_start,
|
||||
# 'origin': production.origin,
|
||||
# 'product_qty': production.product_qty,
|
||||
# 'product_id': production.product_id.id,
|
||||
# 'state': 'draft',
|
||||
# })
|
||||
# technology_design_values = []
|
||||
# all_production = productions
|
||||
# grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)}
|
||||
# # 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
||||
# product_id_to_production_names = {}
|
||||
# # 对于每个product_id,获取其所有生产订单的名称
|
||||
# for product_id, all_production in grouped_product_ids.items():
|
||||
# # 为同一个product_id创建一个生产订单名称列表
|
||||
# product_id_to_production_names[product_id] = [production.name for production in all_production]
|
||||
# for production_item in productions:
|
||||
# # production_programming = self.env['mrp.production'].search(
|
||||
# # [('product_id.id', '=', production_item.product_id.id),
|
||||
# # ('origin', '=', production_item.origin)],
|
||||
# # limit=1, order='id asc')
|
||||
# if production_item.product_id.id in product_id_to_production_names:
|
||||
# if production_item.product_id.model_process_parameters_ids:
|
||||
# is_purchase = False
|
||||
# sorted_process_parameters = sorted(production_item.product_id.model_process_parameters_ids,
|
||||
# key=lambda w: w.id)
|
||||
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
|
||||
if sale_order:
|
||||
# sale_order.write({'schedule_status': 'to schedule'})
|
||||
self.env['sf.production.plan'].sudo().with_company(company_id).create({
|
||||
'name': production.name,
|
||||
'order_deadline': sale_order.deadline_of_delivery,
|
||||
'production_id': production.id,
|
||||
'date_planned_start': production.date_planned_start,
|
||||
'origin': production.origin,
|
||||
'product_qty': production.product_qty,
|
||||
'product_id': production.product_id.id,
|
||||
'state': 'draft',
|
||||
})
|
||||
technology_design_values = []
|
||||
all_production = productions
|
||||
grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)}
|
||||
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
||||
product_id_to_production_names = {}
|
||||
# 对于每个product_id,获取其所有生产订单的名称
|
||||
for product_id, all_production in grouped_product_ids.items():
|
||||
# 为同一个product_id创建一个生产订单名称列表
|
||||
product_id_to_production_names[product_id] = [production.name for production in all_production]
|
||||
for production_item in productions:
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('product_id.id', '=', production_item.product_id.id),
|
||||
('origin', '=', production_item.origin)],
|
||||
limit=1, order='id asc')
|
||||
if production_item.product_id.id in product_id_to_production_names:
|
||||
# 同一个产品多个制造订单对应一个编程单和模型库
|
||||
# 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||
if not production_item.programming_no and production.production_type == '自动化产线加工':
|
||||
if not production_programming.programming_no:
|
||||
production_item.fetchCNC(
|
||||
', '.join(product_id_to_production_names[production_item.product_id.id]))
|
||||
else:
|
||||
production_item.write({'programming_no': production_programming.programming_no,
|
||||
'programming_state': '编程中'})
|
||||
if not technology_design_values:
|
||||
i = 0
|
||||
if production_item.product_id.categ_id.type == '成品':
|
||||
# 根据加工面板的面数及成品工序模板生成工序设计
|
||||
|
||||
for k in (production_item.product_id.model_processing_panel.split(',')):
|
||||
if production_item.production_type == '自动化产线加工':
|
||||
product_routing_workcenter = self.env['sf.product.model.type.routing.sort'].search(
|
||||
[('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)],
|
||||
order='sequence asc'
|
||||
)
|
||||
else:
|
||||
product_routing_workcenter = self.env['sf.manual.product.model.type.routing.sort'].search(
|
||||
[('manual_product_model_type_id', '=', production_item.product_id.product_model_type_id.id)],
|
||||
order='sequence asc'
|
||||
)
|
||||
for route in product_routing_workcenter:
|
||||
i += 1
|
||||
technology_design_values.append(
|
||||
self.env['sf.technology.design'].json_technology_design_str(k, route, i, False))
|
||||
elif production.product_id.categ_id.type == '坯料':
|
||||
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
|
||||
[('embryo_model_type_id', '=', production_item.product_id.embryo_model_type_id.id)],
|
||||
order='sequence asc'
|
||||
)
|
||||
for route_embryo in embryo_routing_workcenter:
|
||||
i += 1
|
||||
technology_design_values.append(
|
||||
self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i,
|
||||
False))
|
||||
surface_technics_arr = []
|
||||
route_workcenter_arr = []
|
||||
for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
|
||||
if item.route_workcenter_id.surface_technics_id.id:
|
||||
for process_param in production_item.product_id.model_process_parameters_ids:
|
||||
if item.route_workcenter_id.surface_technics_id == process_param.process_id:
|
||||
surface_technics_arr.append(
|
||||
item.route_workcenter_id.surface_technics_id.id)
|
||||
route_workcenter_arr.append(item.route_workcenter_id.id)
|
||||
if surface_technics_arr:
|
||||
production_process = self.env['sf.production.process'].search(
|
||||
[('id', 'in', surface_technics_arr)],
|
||||
order='sequence asc'
|
||||
)
|
||||
for p in production_process:
|
||||
logging.info('production_process:%s' % p.name)
|
||||
process_parameter = production_item.product_id.model_process_parameters_ids.filtered(
|
||||
lambda pm: pm.process_id.id == p.id)
|
||||
if process_parameter:
|
||||
i += 1
|
||||
route_production_process = self.env[
|
||||
'mrp.routing.workcenter'].search(
|
||||
[('surface_technics_id', '=', p.id),
|
||||
('id', 'in', route_workcenter_arr)])
|
||||
technology_design_values.append(
|
||||
self.env['sf.technology.design'].json_technology_design_str(False,
|
||||
route_production_process,
|
||||
i,
|
||||
process_parameter))
|
||||
productions.technology_design_ids = technology_design_values
|
||||
|
||||
# consecutive_process_parameters = []
|
||||
# m = 0
|
||||
# for i in range(len(sorted_process_parameters) - 1):
|
||||
# if m == 0:
|
||||
# is_purchase = False
|
||||
# if self.env['product.template']._get_process_parameters_product(
|
||||
# sorted_process_parameters[i]).partner_id == self.env[
|
||||
# 'product.template']._get_process_parameters_product(sorted_process_parameters[
|
||||
# i + 1]).partner_id and \
|
||||
# sorted_process_parameters[i].gain_way == '外协':
|
||||
# if sorted_process_parameters[i] not in consecutive_process_parameters:
|
||||
# consecutive_process_parameters.append(sorted_process_parameters[i])
|
||||
# consecutive_process_parameters.append(sorted_process_parameters[i + 1])
|
||||
# m += 1
|
||||
# continue
|
||||
# else:
|
||||
# if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
# self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
# production_item,
|
||||
# product_id_to_production_names)
|
||||
# if sorted_process_parameters[i] in consecutive_process_parameters:
|
||||
# is_purchase = True
|
||||
# consecutive_process_parameters = []
|
||||
# m = 0
|
||||
# # 当前面的连续外协采购单生成再生成当前外协采购单
|
||||
# if is_purchase is False:
|
||||
# self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
# production_item,
|
||||
# product_id_to_production_names)
|
||||
# if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
# self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
# production_item,
|
||||
# product_id_to_production_names)
|
||||
# if sorted_process_parameters[i] in consecutive_process_parameters:
|
||||
# is_purchase = True
|
||||
# consecutive_process_parameters = []
|
||||
# m = 0
|
||||
# if m == len(consecutive_process_parameters) - 1 and m != 0:
|
||||
# self.env['purchase.order'].get_purchase_order(consecutive_process_parameters,
|
||||
# production_item,
|
||||
# product_id_to_production_names)
|
||||
# if is_purchase is False and m == 0:
|
||||
# if len(sorted_process_parameters) == 1:
|
||||
# self.env['purchase.order'].get_purchase_order(sorted_process_parameters,
|
||||
# production_item,
|
||||
# product_id_to_production_names)
|
||||
# else:
|
||||
# self.env['purchase.order'].get_purchase_order(sorted_process_parameters[i],
|
||||
# production_item,
|
||||
# product_id_to_production_names)
|
||||
# if not technology_design_values:
|
||||
# if production.product_id.categ_id.type == '成品':
|
||||
# production.product_id.model_processing_panel = 'ZM,FM'
|
||||
# # 根据加工面板的面数及成品工序模板生成工序设计
|
||||
# i = 0
|
||||
# for k in (production.product_id.model_processing_panel.split(',')):
|
||||
# product_routing_workcenter = self.env['sf.product.model.type.routing.sort'].search(
|
||||
# [('product_model_type_id', '=', production.product_id.product_model_type_id.id)],
|
||||
# order='sequence asc'
|
||||
# )
|
||||
# for route in product_routing_workcenter:
|
||||
# i += 1
|
||||
# technology_design_values.append(
|
||||
# self.env['sf.technology.design'].json_technology_design_str(k, route, i))
|
||||
# surface_technics_arr = []
|
||||
# route_workcenter_arr = []
|
||||
# for process_param in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids.filtered(
|
||||
# lambda st: st.id in production.product_id.model_process_parameters_ids.ids):
|
||||
# # if item.route_workcenter_id.surface_technics_id.id:
|
||||
# # for process_param in production.product_id.model_process_parameters_ids:
|
||||
# logging.info('process_param:%s%s' % (process_param.id, process_param.name))
|
||||
# if item.route_workcenter_id.surface_technics_id == process_param.process_id:
|
||||
# logging.info(
|
||||
# 'surface_technics_id:%s%s' % (
|
||||
# item.route_workcenter_id.surface_technics_id.id,
|
||||
# item.route_workcenter_id.surface_technics_id.name))
|
||||
# surface_technics_arr.append(
|
||||
# item.route_workcenter_id.surface_technics_id.id)
|
||||
# route_workcenter_arr.append(item.route_workcenter_id.id)
|
||||
# if surface_technics_arr:
|
||||
# production_process = self.env['sf.production.process'].search(
|
||||
# [('id', 'in', surface_technics_arr)],
|
||||
# order='sequence asc'
|
||||
# )
|
||||
# for p in production_process:
|
||||
# logging.info('production_process:%s' % p.name)
|
||||
# process_parameter = production.product_id.model_process_parameters_ids.filtered(
|
||||
# lambda pm: pm.process_id.id == p.id)
|
||||
# product_production_process = self.env['product.template'].search(
|
||||
# [('server_product_process_parameters_id', '=',
|
||||
# process_parameter.id)])
|
||||
# if process_parameter:
|
||||
# i += 1
|
||||
# route_production_process = self.env[
|
||||
# 'mrp.routing.workcenter'].search(
|
||||
# [('surface_technics_id', '=', p.id),
|
||||
# ('id', 'in', route_workcenter_arr)])
|
||||
# technology_design_values.append(
|
||||
# self.env['sf.technology.design'].json_technology_design_str(k,
|
||||
# route_production_process,
|
||||
# product_production_process,
|
||||
# i))
|
||||
# productions.technology_design_ids = technology_design_values
|
||||
|
||||
# # # 同一个产品多个制造订单对应一个编程单和模型库
|
||||
# # # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||
# # if not production_item.programming_no:
|
||||
# # if not production_programming.programming_no:
|
||||
# # production_item.fetchCNC(
|
||||
# # ', '.join(product_id_to_production_names[production_item.product_id.id]))
|
||||
# # else:
|
||||
# # production_item.write({'programming_no': production_programming.programming_no,
|
||||
# # 'programming_state': '编程中'})
|
||||
# return True
|
||||
return True
|
||||
|
||||
|
||||
class ProductionLot(models.Model):
|
||||
@@ -659,31 +612,27 @@ class StockPicking(models.Model):
|
||||
return '%s%s' % (rescode, num)
|
||||
|
||||
def button_validate(self):
|
||||
move_out = self.env['stock.move'].search(
|
||||
[('location_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||
('location_dest_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||
('origin', '=', self.origin)])
|
||||
# if self.id == move_out.picking_id.id:
|
||||
# if move_out.move_line_ids.workorder_id.state not in ['progress']:
|
||||
# raise UserError(
|
||||
# _('该出库单里源单据内的单号为%s的工单还未开始,不能进行验证操作!' % move_out.move_line_ids.workorder_id.name))
|
||||
# 入库单验证
|
||||
move_in = self.env['stock.move'].search(
|
||||
[('location_dest_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||
('location_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||
('origin', '=', self.origin), ('picking_id', '=', self.id)])
|
||||
if self.location_id == move_in.location_id and self.location_dest_id == move_in.location_dest_id:
|
||||
if move_out.origin == move_in.origin:
|
||||
move_in.write({'production_id': False})
|
||||
if move_out.picking_id.state != 'done':
|
||||
raise UserError(
|
||||
_('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name))
|
||||
if self.picking_type_id.barcode == 'OCOUT':
|
||||
move_out = self.env['stock.move'].search(
|
||||
[('location_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||
('location_dest_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||
('origin', '=', self.origin)])
|
||||
move_in = self.env['stock.move'].search(
|
||||
[('location_dest_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||
('location_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||
('origin', '=', self.origin), ('picking_id', '=', self.id)])
|
||||
if self.location_id == move_in.location_id and self.location_dest_id == move_in.location_dest_id:
|
||||
if move_out.origin == move_in.origin:
|
||||
move_in.write({'production_id': False})
|
||||
if move_out.picking_id.state != 'done':
|
||||
raise UserError(
|
||||
_('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name))
|
||||
res = super().button_validate()
|
||||
if res is True:
|
||||
if res is True and self.picking_type_id.barcode == 'OCIN':
|
||||
if self.id == move_out.picking_id.id:
|
||||
# if move_out.move_line_ids.workorder_id.state == 'progress':
|
||||
move_in = self.env['stock.move'].search(
|
||||
@@ -701,42 +650,43 @@ class StockPicking(models.Model):
|
||||
|
||||
# 创建 外协出库入单
|
||||
def create_outcontract_picking(self, sorted_workorders_arr, item):
|
||||
m = 0
|
||||
for sorted_workorders in sorted_workorders_arr:
|
||||
# pick_ids = []
|
||||
if m == 0:
|
||||
outcontract_stock_move = self.env['stock.move'].search(
|
||||
[('workorder_id', '=', sorted_workorders.id), ('production_id', '=', item.id)])
|
||||
if not outcontract_stock_move:
|
||||
new_picking = True
|
||||
location_id = self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'VL-SPOC')]).id,
|
||||
location_dest_id = self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id,
|
||||
outcontract_picking_type_in = self.env.ref(
|
||||
'sf_manufacturing.outcontract_picking_in').id,
|
||||
outcontract_picking_type_out = self.env.ref(
|
||||
'sf_manufacturing.outcontract_picking_out').id,
|
||||
moves_out = self.env['stock.move'].sudo().create(
|
||||
self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id,
|
||||
outcontract_picking_type_out))
|
||||
picking_out = self.create(
|
||||
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/'))
|
||||
# pick_ids.append(picking_out.id)
|
||||
moves_out.write(
|
||||
{'picking_id': picking_out.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
|
||||
moves_out._assign_picking_post_process(new=new_picking)
|
||||
moves_in = self.env['stock.move'].sudo().create(
|
||||
self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id,
|
||||
outcontract_picking_type_in))
|
||||
picking_in = self.create(
|
||||
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/'))
|
||||
# pick_ids.append(picking_in.id)
|
||||
moves_in.write(
|
||||
{'picking_id': picking_in.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
|
||||
moves_in._assign_picking_post_process(new=new_picking)
|
||||
m += 1
|
||||
# sorted_workorders.write({'picking_ids': [(6, 0, pick_ids)]})
|
||||
if len(sorted_workorders_arr) > 1:
|
||||
sorted_workorders_arr = sorted_workorders_arr[0]
|
||||
stock_picking = self.env['stock.picking'].search(
|
||||
[('origin', '=', sorted_workorders_arr.production_id.name), ('name', 'ilike', 'OCOUT')])
|
||||
if not stock_picking:
|
||||
for sorted_workorders in sorted_workorders_arr:
|
||||
# pick_ids = []
|
||||
if not sorted_workorders.picking_ids:
|
||||
outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)])
|
||||
if not outcontract_stock_move:
|
||||
new_picking = True
|
||||
location_id = self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'VL-SPOC')]).id,
|
||||
location_dest_id = self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id,
|
||||
outcontract_picking_type_in = self.env.ref(
|
||||
'sf_manufacturing.outcontract_picking_in').id,
|
||||
outcontract_picking_type_out = self.env.ref(
|
||||
'sf_manufacturing.outcontract_picking_out').id,
|
||||
moves_out = self.env['stock.move'].sudo().create(
|
||||
self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id,
|
||||
outcontract_picking_type_out))
|
||||
picking_out = self.create(
|
||||
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/'))
|
||||
# pick_ids.append(picking_out.id)
|
||||
moves_out.write(
|
||||
{'picking_id': picking_out.id, 'state': 'waiting'})
|
||||
moves_out._assign_picking_post_process(new=new_picking)
|
||||
moves_in = self.env['stock.move'].sudo().create(
|
||||
self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id,
|
||||
outcontract_picking_type_in))
|
||||
picking_in = self.create(
|
||||
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/'))
|
||||
# pick_ids.append(picking_in.id)
|
||||
moves_in.write(
|
||||
{'picking_id': picking_in.id, 'state': 'waiting'})
|
||||
moves_in._assign_picking_post_process(new=new_picking)
|
||||
|
||||
|
||||
class ReStockMove(models.Model):
|
||||
@@ -772,7 +722,7 @@ class ReStockMove(models.Model):
|
||||
return {
|
||||
'name': self.env['stock.picking']._get_name_Res(rescode),
|
||||
'origin': item.name,
|
||||
'surface_technics_parameters_id': sorted_workorders.surface_technics_parameters_id.id,
|
||||
# 'surface_technics_parameters_id': sorted_workorders.surface_technics_parameters_id.id,
|
||||
'company_id': self.mapped('company_id').id,
|
||||
'user_id': False,
|
||||
'move_type': self.mapped('group_id').move_type or 'direct',
|
||||
@@ -793,7 +743,7 @@ class ReStockMove(models.Model):
|
||||
'picking_id': self.picking_id.id,
|
||||
'reserved_uom_qty': 1.0,
|
||||
'lot_id': production_id.move_line_raw_ids.lot_id.id,
|
||||
'company_id': self.company_id.id,
|
||||
'company_id': self.env.company.id,
|
||||
# 'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
||||
# 'production_id': '' if not sorted_workorders else sorted_workorders.production_id.id,
|
||||
'state': 'assigned',
|
||||
@@ -842,7 +792,6 @@ class ReStockMove(models.Model):
|
||||
elif self.product_id.tracking == "lot":
|
||||
self._put_tool_lot(self.company_id, self.product_id, self.origin)
|
||||
|
||||
|
||||
return {
|
||||
'name': _('Detailed Operations'),
|
||||
'type': 'ir.actions.act_window',
|
||||
@@ -991,6 +940,11 @@ class ReStockMove(models.Model):
|
||||
move_lines_commands.append((0, 0, move_line_cmd))
|
||||
qty_by_location[loc.id] += 1
|
||||
return move_lines_commands
|
||||
|
||||
# def _prepare_procurement_origin(self):
|
||||
# """修改采购来源"""
|
||||
# self.ensure_one()
|
||||
# return self.group_id and self.group_id.name or (self.origin or self.picking_id.name or "/")
|
||||
|
||||
|
||||
class ReStockQuant(models.Model):
|
||||
|
||||
Reference in New Issue
Block a user