Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化

# Conflicts:
#	sf_manufacturing/models/mrp_workorder.py
This commit is contained in:
mgw
2024-12-05 11:48:07 +08:00
7 changed files with 223 additions and 167 deletions

View File

@@ -721,6 +721,7 @@ class MrpProduction(models.Model):
for product_id, pd in grouped_product_ids.items(): for product_id, pd in grouped_product_ids.items():
product_id_to_production_names[product_id] = [p.name for p in pd] product_id_to_production_names[product_id] = [p.name for p in pd]
for production in production_all: for production in production_all:
proc_workorders = []
process_parameter_workorder = self.env['mrp.workorder'].search( process_parameter_workorder = self.env['mrp.workorder'].search(
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id), [('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
('is_subcontract', '=', True)], order='sequence asc') ('is_subcontract', '=', True)], order='sequence asc')
@@ -737,10 +738,11 @@ class MrpProduction(models.Model):
else: else:
# 处理连续组,如果它不为空 # 处理连续组,如果它不为空
if consecutive_workorders: if consecutive_workorders:
proc_workorders.append(consecutive_workorders)
# 创建外协出入库单和采购订单 # 创建外协出入库单和采购订单
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) # self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production, sorted_workorders)
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, # self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
product_id_to_production_names) # product_id_to_production_names)
if i < len(sorted_workorders) - 1: if i < len(sorted_workorders) - 1:
# 重置连续组,并添加当前工作订单 # 重置连续组,并添加当前工作订单
consecutive_workorders = [workorder] consecutive_workorders = [workorder]
@@ -751,18 +753,22 @@ class MrpProduction(models.Model):
i - 1].supplier_id.id: i - 1].supplier_id.id:
consecutive_workorders = [workorder] consecutive_workorders = [workorder]
else: else:
proc_workorders.append([workorder])
# 立即创建外协出入库单和采购订单 # 立即创建外协出入库单和采购订单
self.env['stock.picking'].create_outcontract_picking(workorder, production) # self.env['stock.picking'].create_outcontract_picking(workorder, production)
self.env['purchase.order'].get_purchase_order(workorder, production, # self.env['purchase.order'].get_purchase_order(workorder, production,
product_id_to_production_names) # product_id_to_production_names)
consecutive_workorders = [] consecutive_workorders = []
# 处理最后一个组,即使它可能只有一个工作订单 # 处理最后一个组,即使它可能只有一个工作订单
if consecutive_workorders: if consecutive_workorders:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production) proc_workorders.append(consecutive_workorders)
self.env['purchase.order'].get_purchase_order(consecutive_workorders, production, # self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
product_id_to_production_names) # self.env['purchase.order'].get_purchase_order(consecutive_workorders, production,
# product_id_to_production_names)
for workorders in reversed(proc_workorders):
self.env['stock.picking'].create_outcontract_picking(workorders, production, sorted_workorders)
self.env['purchase.order'].get_purchase_order(workorders, production, product_id_to_production_names)
# 工单排序 # 工单排序
def _reset_work_order_sequence1(self, k): def _reset_work_order_sequence1(self, k):
for rec in self: for rec in self:

View File

@@ -23,12 +23,15 @@ class ResMrpWorkOrder(models.Model):
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')
product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True, product_tmpl_id_length = fields.Float(string='坯料长度(mm)', related='material_length', readonly=True, store=False)
string="坯料度(mm)") product_tmpl_id_width = fields.Float(string='坯料度(mm)', related='material_width', readonly=True, store=False)
product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True, product_tmpl_id_height = fields.Float(string='坯料高度(mm)', related='material_height', readonly=True, store=False)
string="坯料宽度(mm)") # product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True,
product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True, # string="坯料长度(mm)")
string="坯料高度(mm)") # product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True,
# string="坯料宽度(mm)")
# product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True,
# string="坯料高度(mm)")
product_tmpl_id_materials_id = fields.Many2one(related='production_id.product_tmpl_id.materials_id', readonly=True, product_tmpl_id_materials_id = fields.Many2one(related='production_id.product_tmpl_id.materials_id', readonly=True,
store=True, check_company=True, string="材料") store=True, check_company=True, string="材料")
product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id', product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id',
@@ -134,8 +137,10 @@ class ResMrpWorkOrder(models.Model):
glb_file = fields.Binary("glb模型文件", related='production_id.model_file') glb_file = fields.Binary("glb模型文件", related='production_id.model_file')
is_subcontract = fields.Boolean(string='是否外协') is_subcontract = fields.Boolean(string='是否外协')
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='外协出入库单', compute='_compute_surface_technics_picking_ids') picking_ids = fields.Many2many('stock.picking', string='外协出入库单', compute='_compute_surface_technics_picking_ids')
# purchase_id = fields.Many2one('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')
surface_technics_purchase_count = fields.Integer("外协采购", compute='_compute_surface_technics_purchase_ids') surface_technics_purchase_count = fields.Integer("外协采购", compute='_compute_surface_technics_purchase_ids')
@@ -239,13 +244,11 @@ class ResMrpWorkOrder(models.Model):
previous_workorder = self.env['mrp.workorder'].search( previous_workorder = self.env['mrp.workorder'].search(
[('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'), [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'),
('production_id', '=', workorder.production_id.id)]) ('production_id', '=', workorder.production_id.id)])
if previous_workorder: # if previous_workorder:
if previous_workorder.supplier_id != workorder.supplier_id: # if previous_workorder.supplier_id != workorder.supplier_id:
# process_product = self.env['product.template']._get_process_parameters_product( # domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)]
# previous_workorder.surface_technics_parameters_id) # else:
domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)] domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)]
else:
domain += [('surface_technics_parameters_id', '=', workorder.surface_technics_parameters_id.id)]
picking_ids = self.env['stock.picking'].search(domain, order='id asc') picking_ids = self.env['stock.picking'].search(domain, order='id asc')
workorder.surface_technics_picking_count = len(picking_ids) workorder.surface_technics_picking_count = len(picking_ids)
workorder.picking_ids = picking_ids.ids workorder.picking_ids = picking_ids.ids
@@ -314,24 +317,27 @@ class ResMrpWorkOrder(models.Model):
# if technology_design.is_auto is False: # if technology_design.is_auto is False:
# domain = [('origin', '=', self.production_id.name)] # domain = [('origin', '=', self.production_id.name)]
# else: # else:
domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment'), purchase_orders_id = self._get_surface_technics_purchase_ids()
('state', '!=', 'cancel')] result = {
"type": "ir.actions.act_window",
"res_model": "purchase.order",
"res_id": purchase_orders_id.id,
# "domain": [['id', 'in', self.purchase_id]],
"name": _("Purchase Orders"),
'view_mode': 'form',
}
return result
def _get_surface_technics_purchase_ids(self):
domain = [('origin', '=', self.production_id.name), ('purchase_type', '=', 'consignment')]
purchase_orders = self.env['purchase.order'].search(domain) purchase_orders = self.env['purchase.order'].search(domain)
purchase_orders_id = None purchase_orders_id = None
for po in purchase_orders: for po in purchase_orders:
for line in po.order_line: for line in po.order_line:
if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id: if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id:
if line.product_qty == 1: if line.product_qty == 1:
purchase_orders_id = line.order_id.id purchase_orders_id = line.order_id
result = { return purchase_orders_id
"type": "ir.actions.act_window",
"res_model": "purchase.order",
"res_id": purchase_orders_id,
# "domain": [['id', 'in', self.purchase_id]],
"name": _("Purchase Orders"),
'view_mode': 'form',
}
return result
supplier_id = fields.Many2one('res.partner', string='外协供应商') supplier_id = fields.Many2one('res.partner', string='外协供应商')
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备', tracking=True) equipment_id = fields.Many2one('maintenance.equipment', string='加工设备', tracking=True)
@@ -1029,47 +1035,47 @@ class ResMrpWorkOrder(models.Model):
'production_id.programming_state') 'production_id.programming_state')
def _compute_state(self): def _compute_state(self):
# super()._compute_state() # super()._compute_state()
for workorder in self: # for workorder in self:
if workorder.sequence != 1: # if workorder.sequence != 1:
previous_workorder = self.env['mrp.workorder'].search( # previous_workorder = self.env['mrp.workorder'].search(
[('production_id', '=', workorder.production_id.id), # [('production_id', '=', workorder.production_id.id),
('sequence', '=', workorder.sequence - 1)]) # ('sequence', '=', workorder.sequence - 1)])
if workorder.state == 'pending': # if workorder.state == 'pending':
if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): # 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.production_id.reservation_state == 'assigned' and workorder.production_id.schedule_state == '已排':
if ((workorder.sequence == 1 and not workorder.blocked_by_workorder_ids) # if ((workorder.sequence == 1 and not workorder.blocked_by_workorder_ids)
or (workorder.blocked_by_workorder_ids.state in ('done', 'cancel') # or (workorder.blocked_by_workorder_ids.state in ('done', 'cancel')
and workorder.blocked_by_workorder_ids.test_results not in ['报废', '返工']) # and workorder.blocked_by_workorder_ids.test_results not in ['报废', '返工'])
or (previous_workorder.state in ('done', 'cancel') # or (previous_workorder.state in ('done', 'cancel')
and not workorder.blocked_by_workorder_ids # and not workorder.blocked_by_workorder_ids
and previous_workorder.test_results not in ['报废', '返工']) # and previous_workorder.test_results not in ['报废', '返工'])
): # ):
workorder.state = 'ready' # workorder.state = 'ready'
continue # continue
if workorder.production_id.schedule_state == '未排' and workorder.state in ('waiting', 'ready'): # if workorder.production_id.schedule_state == '未排' and workorder.state in ('waiting', 'ready'):
if workorder.sequence != 1: # if workorder.sequence != 1:
workorder.state = 'pending' # workorder.state = 'pending'
continue # continue
if workorder.state not in ('waiting', 'ready'): # if workorder.state not in ('waiting', 'ready'):
continue # continue
if workorder.state in ( # if workorder.state in (
'waiting') and workorder.sequence == 1 and workorder.production_id.schedule_state == '已排': # 'waiting') and workorder.sequence == 1 and workorder.production_id.schedule_state == '已排':
workorder.state = 'ready' # workorder.state = 'ready'
continue # continue
if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): # if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]):
workorder.state = 'pending' # workorder.state = 'pending'
if workorder.state in ['waiting']: # if workorder.state in ['waiting']:
if previous_workorder.state == 'waiting': # if previous_workorder.state == 'waiting':
workorder.state = 'pending' # workorder.state = 'pending'
if workorder.sequence == 1 and workorder.state == 'pending': # if workorder.sequence == 1 and workorder.state == 'pending':
workorder.state = 'waiting' # workorder.state = 'waiting'
continue # continue
if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'): # if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'):
continue # continue
if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting' and workorder.production_id.schedule_state == '已排': # if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting' and workorder.production_id.schedule_state == '已排':
workorder.state = 'ready' # workorder.state = 'ready'
elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready': # elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready':
workorder.state = 'waiting' # workorder.state = 'waiting'
for workorder in self: for workorder in self:
# 如果工单的工序没有进行排序则跳出循环 # 如果工单的工序没有进行排序则跳出循环
@@ -1120,21 +1126,26 @@ class ResMrpWorkOrder(models.Model):
if workorder.is_subcontract is False: if workorder.is_subcontract is False:
workorder.state = 'ready' workorder.state = 'ready'
else: else:
production_programming = self.env['mrp.production'].search( # production_programming = self.env['mrp.production'].search(
[('origin', '=', self.production_id.origin)], order='name asc') # [('origin', '=', self.production_id.origin)], order='name asc')
production_no_remanufacture = production_programming.filtered( # production_no_remanufacture = production_programming.filtered(
lambda a: a.is_remanufacture is False) # lambda a: a.is_remanufacture is False)
production_list = [production.name for production in production_programming] # production_list = [production.name for production in production_programming]
purchase_orders = self.env['purchase.order'].search( # purchase_orders = self.env['purchase.order'].search(
[('origin', 'ilike', ','.join(production_list))]) # [('origin', 'ilike', ','.join(production_list))])
for line in purchase_orders.order_line: # for line in purchase_orders.order_line:
if ( # if (
line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id # line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id
and line.product_qty == len(production_no_remanufacture)): # and line.product_qty == len(production_no_remanufacture)):
if all(pur_order.state == 'purchase' for pur_order in purchase_orders): # if all(pur_order.state == 'purchase' for pur_order in purchase_orders):
workorder.state = 'ready' # workorder.state = 'ready'
else: # else:
workorder.state = 'waiting' # workorder.state = 'waiting'
purchase_orders_id = self._get_surface_technics_purchase_ids()
if purchase_orders_id:
workorder.state = 'ready' if purchase_orders_id.state == 'purchase' else 'waiting'
else:
workorder.state = 'waiting'
# re_work = self.env['mrp.workorder'].search([('production_id', '=', workorder.production_id.id), # re_work = self.env['mrp.workorder'].search([('production_id', '=', workorder.production_id.id),
# ('processing_panel', '=', workorder.processing_panel), # ('processing_panel', '=', workorder.processing_panel),
@@ -1197,6 +1208,10 @@ class ResMrpWorkOrder(models.Model):
# 重写工单开始按钮方法 # 重写工单开始按钮方法
def button_start(self): def button_start(self):
# 判断工单状态是否为等待组件
if self.state in ['waiting', 'pending']:
raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name)
if self.routing_type == 'CNC加工': if self.routing_type == 'CNC加工':
self.env['sf.production.plan'].sudo().search([('name', '=', self.production_id.name)]).write({ self.env['sf.production.plan'].sudo().search([('name', '=', self.production_id.name)]).write({
'state': 'processing', 'state': 'processing',
@@ -1204,9 +1219,6 @@ class ResMrpWorkOrder(models.Model):
}) })
if self.sequence == 1: if self.sequence == 1:
# 判断工单状态是否为等待组件
if self.state == 'waiting':
raise UserError('制造订单【%s】缺少组件信息!' % self.production_id.name)
# 判断是否有坯料的序列号信息 # 判断是否有坯料的序列号信息
boolean = False boolean = False
if self.production_id.move_raw_ids: if self.production_id.move_raw_ids:
@@ -1243,19 +1255,33 @@ class ResMrpWorkOrder(models.Model):
# 表面工艺外协出库单 # 表面工艺外协出库单
if self.routing_type == '表面工艺': if self.routing_type == '表面工艺':
if self.is_subcontract is True: if self.is_subcontract is True:
move_out = self.env['stock.move'].search( move_out = self.move_subcontract_workorder_ids[1]
[('location_id', '=', self.env['stock.location'].search( # move_out = self.env['stock.move'].search(
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), # [('location_id', '=', self.env['stock.location'].search(
('location_dest_id', '=', self.env['stock.location'].search( # [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
[('barcode', 'ilike', 'VL-SPOC')]).id), # ('location_dest_id', '=', self.env['stock.location'].search(
('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])]) # [('barcode', 'ilike', 'VL-SPOC')]).id),
# ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])])
for mo in move_out: for mo in move_out:
pick = self.env['stock.picking'].search([('id', '=', mo.picking_id.id), ('name', 'ilike', 'OCOUT'), if mo.state != 'done':
('partner_id', '=', self.supplier_id.id)]) mo.write({'state': 'assigned', 'production_id': False})
if pick: if not mo.move_line_ids:
if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False})
self.env['stock.move.line'].create(mo.get_move_line(self.production_id, self)) self.env['stock.move.line'].create(mo.get_move_line(self.production_id, self))
# product_qty = mo.product_uom._compute_quantity(
# mo.product_uom_qty, mo.product_id.uom_id, rounding_method='HALF-UP')
# available_quantity = self.env['stock.quant']._get_available_quantity(
# mo.product_id,
# mo.location_id,
# lot_id=mo.move_line_ids.lot_id,
# strict=False,
# )
# mo._update_reserved_quantity(
# product_qty,
# available_quantity,
# mo.location_id,
# lot_id=mo.move_line_ids.lot_id,
# strict=False,
# )
# move_out._action_assign() # move_out._action_assign()
if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress': if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress':
@@ -1360,6 +1386,13 @@ class ResMrpWorkOrder(models.Model):
picks = record.picking_ids.filtered(lambda p: p.state not in ('done')) picks = record.picking_ids.filtered(lambda p: p.state not in ('done'))
if picks: if picks:
raise UserError('请先完成该工单的工艺外协再进行操作') raise UserError('请先完成该工单的工艺外协再进行操作')
# 表面工艺外协,最后一张工单
workorders = self.production_id.workorder_ids
subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True).sorted('sequence')
if self == subcontract_workorders[-1]:
# 给下一个库存移动就绪
self.move_subcontract_workorder_ids[0].move_dest_ids._action_done()
# self.production_id.button_mark_done()
tem_date_planned_finished = record.date_planned_finished tem_date_planned_finished = record.date_planned_finished
tem_date_finished = record.date_finished tem_date_finished = record.date_finished
logging.info('routing_type:%s' % record.routing_type) logging.info('routing_type:%s' % record.routing_type)
@@ -1402,13 +1435,13 @@ class ResMrpWorkOrder(models.Model):
move_raw_id.quantity_done = move_raw_id.product_uom_qty move_raw_id.quantity_done = move_raw_id.product_uom_qty
record.process_state = '已完工' record.process_state = '已完工'
record.production_id.process_state = '已完工' record.production_id.process_state = '已完工'
if record.routing_type in ['表面工艺']: # if record.routing_type in ['表面工艺']:
raw_move = self.env['stock.move'].sudo().search( # raw_move = self.env['stock.move'].sudo().search(
[('origin', '=', record.production_id.name), # [('origin', '=', record.production_id.name),
('procure_method', 'in', ['make_to_order', 'make_to_stock']), # ('procure_method', 'in', ['make_to_order', 'make_to_stock']),
('state', '!=', 'done')]) # ('state', '!=', 'done')])
if raw_move: # if raw_move:
raw_move.write({'state': 'done'}) # raw_move.write({'state': 'done'})
record.production_id.button_mark_done1() record.production_id.button_mark_done1()
# record.production_id.state = 'done' # record.production_id.state = 'done'
@@ -1528,6 +1561,8 @@ class ResMrpWorkOrder(models.Model):
'default_confirm_button': '确认解除', 'default_confirm_button': '确认解除',
# 'default_feeder_station_start_id': feeder_station_start_id, # 'default_feeder_station_start_id': feeder_station_start_id,
}} }}
move_subcontract_workorder_ids = fields.One2many('stock.move', 'subcontract_workorder_id', string='组件')
class CNCprocessing(models.Model): class CNCprocessing(models.Model):

View File

@@ -636,74 +636,85 @@ class StockPicking(models.Model):
def button_validate(self): def button_validate(self):
res = super().button_validate() res = super().button_validate()
if res is True and self.picking_type_id.sequence_code == 'OCOUT': picking_type_in = self.env.ref('sf_manufacturing.outcontract_picking_in').id
# if self.id == move_out.picking_id.id: if res is True and self.picking_type_id.id == picking_type_in:
# if move_out.move_line_ids.workorder_id.state == 'progress': # 如果是最后一张外协入库单,则设置库存位置的预留数量
move_in = self.env['stock.move'].search( move_in = self.move_ids
[('location_dest_id', '=', self.env['stock.location'].search( if move_in:
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), workorder = move_in.subcontract_workorder_id
('location_id', '=', self.env['stock.location'].search( workorders = workorder.production_id.workorder_ids
[('barcode', 'ilike', 'VL-SPOC')]).id), subcontract_workorders = workorders.filtered(lambda wo: wo.is_subcontract == True).sorted('sequence')
('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])]) if workorder == subcontract_workorders[-1]:
production = self.env['mrp.production'].search([('name', '=', self.origin)]) self.env['stock.quant']._update_reserved_quantity(
for mi in move_in: move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty, lot_id=move_in.move_line_ids.lot_id,
pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'), package_id=False, owner_id=False, strict=False
('partner_id', '=', self.partner_id.id)]) )
# if pick:
# if mi.state != 'done':
# mi.write({'state': 'assigned'})
# self.env['stock.move.line'].create(mi.get_move_line(production, None))
return res return res
# 创建 外协出库入单 # 创建 外协出库入单
def create_outcontract_picking(self, sorted_workorders_arr, item): def create_outcontract_picking(self, workorders, item, sorted_workorders):
domain = [('origin', '=', item.name), ('name', 'ilike', 'OCOUT')] domain = [('origin', '=', item.name), ('name', 'ilike', 'OCOUT')]
if len(sorted_workorders_arr) > 1: if len(workorders) > 1:
sorted_workorders_arr = sorted_workorders_arr[0] workorders = workorders[0]
else: else:
domain += [ domain += [
('surface_technics_parameters_id', '=', sorted_workorders_arr[0].surface_technics_parameters_id.id)] ('surface_technics_parameters_id', '=', workorders[0].surface_technics_parameters_id.id)]
stock_picking = self.env['stock.picking'].search(domain) stock_picking = self.env['stock.picking'].search(domain)
if not stock_picking: if not stock_picking:
for sorted_workorders in sorted_workorders_arr: for workorder in workorders:
# pick_ids = [] # pick_ids = []
if not sorted_workorders.picking_ids: if not workorder.picking_ids:
# outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)]) # outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)])
# if not outcontract_stock_move: # if not outcontract_stock_move:
# 创建一个新的补货组 # 创建一个新的补货组
procurement_group_id = self.env['procurement.group'].create({ procurement_group_id = self.env['procurement.group'].create({
'name': sorted_workorders.name, 'name': workorder.name,
'partner_id': self.partner_id.id, 'partner_id': self.partner_id.id,
}) })
move_dest_id = False
# 如果当前工单是是制造订单的最后一个工单
if workorder == item.workorder_ids[-1]:
move_dest_id = item.move_raw_ids[0].id
else:
# 从sorted_workorders中找到上一工单的move
move_dest_id = sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id
new_picking = True 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( outcontract_picking_type_in = self.env.ref(
'sf_manufacturing.outcontract_picking_in').id, 'sf_manufacturing.outcontract_picking_in').id,
outcontract_picking_type_out = self.env.ref( outcontract_picking_type_out = self.env.ref(
'sf_manufacturing.outcontract_picking_out').id, 'sf_manufacturing.outcontract_picking_out').id,
moves_in = self.env['stock.move'].sudo().create( moves_in = self.env['stock.move'].sudo().create(
self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id, self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in, procurement_group_id.id, move_dest_id))
outcontract_picking_type_in, procurement_group_id.id))
picking_in = self.create( picking_in = self.create(
moves_in._get_new_picking_values_Res(item, sorted_workorders, '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, 'state': 'waiting'}) {'picking_id': picking_in.id, 'state': 'waiting'})
moves_in._assign_picking_post_process(new=new_picking) moves_in._assign_picking_post_process(new=new_picking)
moves_out = self.env['stock.move'].sudo().create( moves_out = self.env['stock.move'].sudo().create(
self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id, self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out, procurement_group_id.id, moves_in.id))
outcontract_picking_type_out, procurement_group_id.id, moves_in.id)) workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]})
picking_out = self.create( picking_out = self.create(
moves_out._get_new_picking_values_Res(item, sorted_workorders, '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, 'state': 'waiting'}) {'picking_id': picking_out.id, 'state': 'waiting'})
moves_out._assign_picking_post_process(new=new_picking) moves_out._assign_picking_post_process(new=new_picking)
return moves_in, moves_out
@api.depends('move_type', 'immediate_transfer', 'move_ids.state', 'move_ids.picking_id')
def _compute_state(self):
super(StockPicking, self)._compute_state()
for picking in self:
# 外协出库单根据工单状态,采购单状态来确定
picking_type_id = self.env.ref('sf_manufacturing.outcontract_picking_out').id
if picking.picking_type_id.id == picking_type_id:
if picking.move_ids:
workorder = picking.move_ids[0].subcontract_workorder_id
if picking.state == 'assigned':
if workorder.state in ['pending', 'waiting'] or workorder._get_surface_technics_purchase_ids().state in ['draft', 'sent']:
picking.state = 'waiting'
class ReStockMove(models.Model): class ReStockMove(models.Model):
@@ -713,16 +724,17 @@ class ReStockMove(models.Model):
materiel_width = fields.Float(string='物料宽度', digits=(16, 4)) materiel_width = fields.Float(string='物料宽度', digits=(16, 4))
materiel_height = fields.Float(string='物料高度', digits=(16, 4)) materiel_height = fields.Float(string='物料高度', digits=(16, 4))
def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, 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 = self.env['stock.route'].sudo().search([('name', '=', '表面工艺外协')]) route_id = self.env.ref('sf_manufacturing.route_surface_technology_outsourcing').id
stock_rule = self.env['stock.rule'].sudo().search([('route_id', '=', route_id), ('picking_type_id', '=', picking_type_id)])
move_values = { move_values = {
'name': '', 'name': '',
'company_id': item.company_id.id, 'company_id': item.company_id.id,
'product_id': item.bom_id.bom_line_ids.product_id.id, 'product_id': item.bom_id.bom_line_ids.product_id.id,
'product_uom': item.bom_id.bom_line_ids.product_uom_id.id, 'product_uom': item.bom_id.bom_line_ids.product_uom_id.id,
'product_uom_qty': 1.0, 'product_uom_qty': 1.0,
'location_id': location_src_id, 'location_id': stock_rule.location_src_id.id,
'location_dest_id': location_dest_id, 'location_dest_id': stock_rule.location_dest_id.id,
'origin': item.name, 'origin': item.name,
'group_id': group_id, 'group_id': group_id,
'move_dest_ids': [(6, 0, [move_dest_ids])] if move_dest_ids else False, 'move_dest_ids': [(6, 0, [move_dest_ids])] if move_dest_ids else False,
@@ -749,7 +761,7 @@ class ReStockMove(models.Model):
'picking_type_id': picking_type_id, 'picking_type_id': picking_type_id,
'location_id': self.mapped('location_id').id, 'location_id': self.mapped('location_id').id,
'location_dest_id': self.mapped('location_dest_id').id, 'location_dest_id': self.mapped('location_dest_id').id,
'state': 'confirmed', 'state': 'waiting',
} }
def get_move_line(self, production_id, sorted_workorders): def get_move_line(self, production_id, sorted_workorders):
@@ -965,7 +977,7 @@ class ReStockMove(models.Model):
合并制造订单的完成move单据 合并制造订单的完成move单据
""" """
res = super(ReStockMove, self)._merge_moves_fields() res = super(ReStockMove, self)._merge_moves_fields()
if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨', '生产入库']: if self[0].origin and self.picking_type_id.name in ['生产发料', '内部调拨', '生产入库', '客供料入库']:
production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc') production = self.env['mrp.production'].search([('name', '=', self[0].origin)], limit=1, order='id asc')
productions = self.env['mrp.production'].search( productions = self.env['mrp.production'].search(
[('origin', '=', production.origin), ('product_id', '=', production.product_id.id)]) [('origin', '=', production.origin), ('product_id', '=', production.product_id.id)])
@@ -991,6 +1003,8 @@ class ReStockMove(models.Model):
res['origin'] = ','.join(productions.mapped('name')) res['origin'] = ','.join(productions.mapped('name'))
res['retrospect_ref'] = production.product_id.name res['retrospect_ref'] = production.product_id.name
return res return res
subcontract_workorder_id = fields.Many2one('mrp.workorder', '外协工单组件', check_company=True, index='btree_not_null')
class ReStockQuant(models.Model): class ReStockQuant(models.Model):

View File

@@ -738,7 +738,7 @@
<!-- parent="mrp.menu_mrp_manufacturing"--> <!-- parent="mrp.menu_mrp_manufacturing"-->
<!-- sequence="1"/>--> <!-- sequence="1"/>-->
<menuitem id="menu_mrp_production_action" <menuitem id="mrp.menu_mrp_production_action"
name="制造订单" name="制造订单"
parent="mrp.menu_mrp_manufacturing" parent="mrp.menu_mrp_manufacturing"
action="mrp.mrp_production_action" action="mrp.mrp_production_action"

View File

@@ -257,7 +257,7 @@
<record id="sf_production_plan_action" model="ir.actions.act_window"> <record id="sf_production_plan_action" model="ir.actions.act_window">
<field name="name">制造订单生产计划</field> <field name="name">CNC产线计划排程</field>
<field name="type">ir.actions.act_window</field> <field name="type">ir.actions.act_window</field>
<field name="res_model">sf.production.plan</field> <field name="res_model">sf.production.plan</field>
<field name="view_mode">gantt,tree,form</field> <field name="view_mode">gantt,tree,form</field>

View File

@@ -279,13 +279,14 @@ class RePurchaseOrder(models.Model):
'product_uom': server_template.uom_id.id 'product_uom': server_template.uom_id.id
})) }))
if server_product_process: if server_product_process:
self.env['purchase.order'].sudo().create({ purchase_order = self.env['purchase.order'].sudo().create({
'partner_id': server_template.seller_ids[0].partner_id.id, 'partner_id': server_template.seller_ids[0].partner_id.id,
'origin': production.name, 'origin': production.name,
'state': 'draft', 'state': 'draft',
'purchase_type': 'consignment', 'purchase_type': 'consignment',
'order_line': server_product_process}) 'order_line': server_product_process})
pp.purchase_id = [(6, 0, [purchase_order.id])]
# self.env.cr.commit() # self.env.cr.commit()
@api.onchange('order_line') @api.onchange('order_line')

View File

@@ -128,9 +128,9 @@
<!-- action="account.res_partner_action_customer"--> <!-- action="account.res_partner_action_customer"-->
<!-- groups="sales_team.group_sale_salesman"--> <!-- groups="sales_team.group_sale_salesman"-->
<!-- sequence="40"/>--> <!-- sequence="40"/>-->
<menuitem sequence="21" name="快速订单" id="menu_quick_easy_order" <!-- <menuitem sequence="21" name="快速订单" id="menu_quick_easy_order"-->
action="action_quick_easy_order" <!-- action="action_quick_easy_order"-->
parent="sale.sale_order_menu" <!-- parent="sale.sale_order_menu"-->
groups="sales_team.group_sale_salesman,sf_base.group_sale_salemanager,sf_base.group_sale_director"/> <!-- groups="sales_team.group_sale_salesman,sf_base.group_sale_salemanager,sf_base.group_sale_director"/>-->
</data> </data>
</odoo> </odoo>