修改工艺外协工单

This commit is contained in:
胡尧
2024-12-04 20:42:34 +08:00
parent 4387d343b5
commit ef60f36c90
4 changed files with 163 additions and 123 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

@@ -313,14 +313,7 @@ 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()
purchase_orders = self.env['purchase.order'].search(domain)
purchase_orders_id = None
for po in purchase_orders:
for line in po.order_line:
if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id:
if line.product_qty == 1:
purchase_orders_id = line.order_id.id
result = { result = {
"type": "ir.actions.act_window", "type": "ir.actions.act_window",
"res_model": "purchase.order", "res_model": "purchase.order",
@@ -331,6 +324,17 @@ class ResMrpWorkOrder(models.Model):
} }
return result 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_id = None
for po in purchase_orders:
for line in po.order_line:
if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id:
if line.product_qty == 1:
purchase_orders_id = line.order_id.id
return purchase_orders_id
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)
# 保存名称 # 保存名称
@@ -1027,47 +1031,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:
# 如果工单的工序没有进行排序则跳出循环 # 如果工单的工序没有进行排序则跳出循环
@@ -1118,19 +1122,25 @@ 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:
# workorder.state = 'waiting'
purchase_orders_id = self._get_surface_technics_purchase_ids()
if purchase_orders_id:
purchase_order = self.env['purchase.order'].browse(purchase_orders_id)
workorder.state = 'ready' if purchase_order.state == 'purchase' else 'waiting'
else: else:
workorder.state = 'waiting' workorder.state = 'waiting'
@@ -1241,12 +1251,13 @@ 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'), pick = self.env['stock.picking'].search([('id', '=', mo.picking_id.id), ('name', 'ilike', 'OCOUT'),
('partner_id', '=', self.supplier_id.id)]) ('partner_id', '=', self.supplier_id.id)])
@@ -1254,6 +1265,21 @@ class ResMrpWorkOrder(models.Model):
if mo.state != 'done': if mo.state != 'done':
mo.write({'state': 'assigned', 'production_id': False}) 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':
@@ -1527,6 +1553,8 @@ class ResMrpWorkOrder(models.Model):
# '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):
_name = 'sf.cnc.processing' _name = 'sf.cnc.processing'

View File

@@ -634,71 +634,74 @@ class StockPicking(models.Model):
num = "%04d" % m num = "%04d" % m
return '%s%s' % (rescode, num) return '%s%s' % (rescode, num)
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': # if res is True and self.picking_type_id.sequence_code == 'OCOUT':
# if self.id == move_out.picking_id.id: # # if self.id == move_out.picking_id.id:
# if move_out.move_line_ids.workorder_id.state == 'progress': # # if move_out.move_line_ids.workorder_id.state == 'progress':
move_in = self.env['stock.move'].search( # move_in = self.env['stock.move'].search(
[('location_dest_id', '=', self.env['stock.location'].search( # [('location_dest_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id), # [('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
('location_id', '=', self.env['stock.location'].search( # ('location_id', '=', self.env['stock.location'].search(
[('barcode', 'ilike', 'VL-SPOC')]).id), # [('barcode', 'ilike', 'VL-SPOC')]).id),
('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])]) # ('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])])
production = self.env['mrp.production'].search([('name', '=', self.origin)]) # production = self.env['mrp.production'].search([('name', '=', self.origin)])
for mi in move_in: # for mi in move_in:
pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'), # pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'),
('partner_id', '=', self.partner_id.id)]) # ('partner_id', '=', self.partner_id.id)])
# if pick: # if pick:
# if mi.state != 'done': # if mi.state != 'done':
# mi.write({'state': 'assigned'}) # mi.write({'state': 'assigned'})
# self.env['stock.move.line'].create(mi.get_move_line(production, None)) # 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
# move_dest_id = item.move_raw_ids[0].move_orig_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'})
@@ -713,16 +716,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,
@@ -992,6 +996,8 @@ class ReStockMove(models.Model):
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):
_inherit = 'stock.quant' _inherit = 'stock.quant'

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>