Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造功能优化
This commit is contained in:
@@ -43,6 +43,8 @@ class SaleOrder(models.Model):
|
||||
|
||||
# 复制成品模板上的属性
|
||||
line.product_id.product_tmpl_id.copy_template(product_template_id)
|
||||
# 将模板上的single_manufacturing属性复制到成品上
|
||||
line.product_id.single_manufacturing = product_template_id.single_manufacturing
|
||||
|
||||
order_id = self
|
||||
product = line.product_id
|
||||
|
||||
@@ -309,7 +309,8 @@ class MrpProduction(models.Model):
|
||||
for move in production.move_raw_ids if move.product_id):
|
||||
production.state = 'progress'
|
||||
# 新添加的状态逻辑
|
||||
if production.state in ['to_close', 'progress', 'technology_to_confirmed'] and production.schedule_state == '未排':
|
||||
if production.state in ['to_close', 'progress',
|
||||
'technology_to_confirmed'] and production.schedule_state == '未排':
|
||||
if not production.workorder_ids or production.is_adjust is True:
|
||||
production.state = 'technology_to_confirmed'
|
||||
else:
|
||||
@@ -331,6 +332,9 @@ class MrpProduction(models.Model):
|
||||
production.state = 'pending_cam'
|
||||
if production.is_rework is True:
|
||||
production.state = 'rework'
|
||||
if (production.state == 'rework' and production.tool_state == '0'
|
||||
and production.schedule_state == '已排' and production.is_rework is False):
|
||||
production.state = 'pending_cam'
|
||||
# if production.state == 'pending_cam':
|
||||
# if all(wo_state in 'done' for wo_state in production.workorder_ids.mapped('state')):
|
||||
# production.state = 'done'
|
||||
@@ -845,15 +849,20 @@ class MrpProduction(models.Model):
|
||||
purchase_order = self.env['purchase.order'].search(
|
||||
[('state', '=', 'draft'), ('origin', '=', item.name),
|
||||
('purchase_type', '=', 'consignment')])
|
||||
for line in purchase_order.order_line:
|
||||
server_template = self.env['product.template'].search(
|
||||
[('server_product_process_parameters_id', '=', workorder.surface_technics_parameters_id.id),
|
||||
('detailed_type', '=', 'service')])
|
||||
purchase_order_line = self.env['purchase.order.line'].search(
|
||||
[('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id),
|
||||
('product_qty', '=', 1)], limit=1, order='id desc')
|
||||
if purchase_order_line:
|
||||
line.unlink()
|
||||
server_template = self.env['product.template'].search(
|
||||
[('server_product_process_parameters_id', '=',
|
||||
workorder.surface_technics_parameters_id.id),
|
||||
('detailed_type', '=', 'service')])
|
||||
for po in purchase_order:
|
||||
for line in po.order_line:
|
||||
if line.product_id == server_template.product_variant_id:
|
||||
continue
|
||||
if server_template.server_product_process_parameters_id != line.product_id.server_product_process_parameters_id:
|
||||
purchase_order_line = self.env['purchase.order.line'].search(
|
||||
[('product_id', '=', server_template.product_variant_id.id), ('id', '=', line.id),
|
||||
('product_qty', '=', 1)], limit=1, order='id desc')
|
||||
if purchase_order_line:
|
||||
line.unlink()
|
||||
|
||||
def _reset_work_order_sequence(self):
|
||||
"""
|
||||
@@ -894,8 +903,6 @@ class MrpProduction(models.Model):
|
||||
for cw in cancel_work_ids:
|
||||
cw.sequence = sequence + 1
|
||||
|
||||
|
||||
|
||||
def _reset_work_order_sequence_1(self):
|
||||
"""
|
||||
工单工序排序方法(旧)
|
||||
|
||||
@@ -1097,8 +1097,7 @@ class ResMrpWorkOrder(models.Model):
|
||||
# ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]==========================
|
||||
if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework'
|
||||
or workorder.production_id.schedule_state != '已排'
|
||||
or len(
|
||||
workorder.production_id.picking_ids.filtered(lambda w: w.state not in ['done', 'cancel'])) != 0
|
||||
or workorder.production_id.reservation_state not in ['assigned']
|
||||
or workorder.production_id.workorder_ids.filtered(
|
||||
lambda wk: wk.sequence == workorder.sequence - 1).test_results in ['报废', '返工']):
|
||||
if workorder.state != 'waiting':
|
||||
@@ -1247,10 +1246,14 @@ class ResMrpWorkOrder(models.Model):
|
||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||
('location_dest_id', '=', self.env['stock.location'].search(
|
||||
[('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||
('origin', '=', self.production_id.name)])
|
||||
if move_out.state != 'done':
|
||||
move_out.write({'state': 'assigned', 'production_id': False})
|
||||
self.env['stock.move.line'].create(move_out.get_move_line(self.production_id, self))
|
||||
('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])])
|
||||
for mo in move_out:
|
||||
pick = self.env['stock.picking'].search([('id', '=', mo.picking_id.id), ('name', 'ilike', 'OCOUT'),
|
||||
('partner_id', '=', self.supplier_id.id)])
|
||||
if pick:
|
||||
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))
|
||||
|
||||
# move_out._action_assign()
|
||||
if self.state == 'waiting' or self.state == 'ready' or self.state == 'progress':
|
||||
|
||||
@@ -859,12 +859,12 @@ class ResProductMo(models.Model):
|
||||
raise UserError('请先配置模型类型内的坯料冗余')
|
||||
vals = {
|
||||
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
||||
'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) * (
|
||||
'model_long': self.format_float(item['model_long'] + embryo_redundancy_id.long),
|
||||
'model_width': self.format_float(item['model_width'] + embryo_redundancy_id.width),
|
||||
'model_height': self.format_float(item['model_height'] + embryo_redundancy_id.height),
|
||||
'model_volume': self.format_float((item['model_long'] + embryo_redundancy_id.long) * (
|
||||
item['model_width'] + embryo_redundancy_id.width) * (
|
||||
item['model_height'] + embryo_redundancy_id.height),
|
||||
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'],
|
||||
@@ -884,7 +884,7 @@ class ResProductMo(models.Model):
|
||||
'model_process_parameters_ids': [(6, 0, [])] if not item.get(
|
||||
'process_parameters_code') else self.get_process_parameters_id(item['process_parameters_code']),
|
||||
'model_remark': item['remark'],
|
||||
'single_manufacturing': False,
|
||||
'single_manufacturing': True,
|
||||
'default_code': '%s-%s' % (order_number, i),
|
||||
'manual_quotation': item['manual_quotation'] or False,
|
||||
'part_number': item.get('part_number') or '',
|
||||
@@ -907,6 +907,20 @@ class ResProductMo(models.Model):
|
||||
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
|
||||
'quality_standard', item['quality_standard_mimetype'])
|
||||
return copy_product_id
|
||||
|
||||
def format_float(self, value):
|
||||
# 将浮点数转换为字符串
|
||||
value_str = str(value)
|
||||
# 检查小数点的位置
|
||||
if '.' in value_str:
|
||||
# 获取小数部分
|
||||
decimal_part = value_str.split('.')[1]
|
||||
# 判断小数位数是否超过2位
|
||||
if len(decimal_part) > 2:
|
||||
# 超过2位则保留2位小数
|
||||
return "{:.2f}".format(value)
|
||||
# 否则保持原来的位数
|
||||
return float(value_str)
|
||||
|
||||
def _get_ids(self, param):
|
||||
type_ids = []
|
||||
|
||||
@@ -290,7 +290,7 @@ class StockRule(models.Model):
|
||||
else:
|
||||
mrp_production = production
|
||||
# if sale_order:
|
||||
# sale_order.write({'schedule_status': 'to schedule'})
|
||||
# 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,
|
||||
@@ -301,7 +301,6 @@ class StockRule(models.Model):
|
||||
'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对应的生产订单名称列表
|
||||
@@ -311,6 +310,7 @@ class StockRule(models.Model):
|
||||
# 为同一个product_id创建一个生产订单名称列表
|
||||
product_id_to_production_names[product_id] = [production.name for production in all_production]
|
||||
for production_item in productions:
|
||||
technology_design_values = []
|
||||
production_programming = self.env['mrp.production'].search(
|
||||
[('product_id.id', '=', production_item.product_id.id),
|
||||
('origin', '=', production_item.origin)],
|
||||
@@ -318,77 +318,76 @@ class StockRule(models.Model):
|
||||
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_item.programming_no and production_item.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 == '成品':
|
||||
# 根据加工面板的面数及成品工序模板生成工序设计
|
||||
if production_item.production_type == '自动化产线加工':
|
||||
model = 'sf.product.model.type.routing.sort'
|
||||
domain = [
|
||||
('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)]
|
||||
else:
|
||||
model = 'sf.manual.product.model.type.routing.sort'
|
||||
domain = [('manual_product_model_type_id', '=',
|
||||
production_item.product_id.product_model_type_id.id)]
|
||||
product_routing_workcenter = self.env[model].search(domain, order='sequence asc')
|
||||
if production_item.production_type == '自动化产线加工':
|
||||
for k in (production_item.product_id.model_processing_panel.split(',')):
|
||||
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))
|
||||
else:
|
||||
i = 0
|
||||
if production_item.product_id.categ_id.type == '成品':
|
||||
# 根据加工面板的面数及成品工序模板生成工序设计
|
||||
if production_item.production_type == '自动化产线加工':
|
||||
model = 'sf.product.model.type.routing.sort'
|
||||
domain = [
|
||||
('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)]
|
||||
else:
|
||||
model = 'sf.manual.product.model.type.routing.sort'
|
||||
domain = [('manual_product_model_type_id', '=',
|
||||
production_item.product_id.product_model_type_id.id)]
|
||||
product_routing_workcenter = self.env[model].search(domain, order='sequence asc')
|
||||
if production_item.production_type == '自动化产线加工':
|
||||
for k in (production_item.product_id.model_processing_panel.split(',')):
|
||||
for route in product_routing_workcenter:
|
||||
i += 1
|
||||
technology_design_values.append(
|
||||
self.env['sf.technology.design'].json_technology_design_str(False, route, i, False))
|
||||
elif production_item.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:
|
||||
self.env['sf.technology.design'].json_technology_design_str(k, route, i, False))
|
||||
else:
|
||||
for route in product_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
|
||||
self.env['sf.technology.design'].json_technology_design_str(False, route, i, False))
|
||||
elif production_item.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))
|
||||
production_item.technology_design_ids = technology_design_values
|
||||
productions.write({'state': 'technology_to_confirmed'})
|
||||
return True
|
||||
|
||||
@@ -424,6 +423,8 @@ class ProductionLot(models.Model):
|
||||
"""Generate `lot_names` from a string."""
|
||||
if first_lot.__contains__(display_name):
|
||||
first_lot = first_lot[(len(display_name) + 1):]
|
||||
else:
|
||||
first_lot = first_lot[-3:]
|
||||
|
||||
# We look if the first lot contains at least one digit.
|
||||
caught_initial_number = regex_findall(r"\d+", first_lot)
|
||||
@@ -634,39 +635,24 @@ class StockPicking(models.Model):
|
||||
return '%s%s' % (rescode, num)
|
||||
|
||||
def button_validate(self):
|
||||
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)])
|
||||
res = super().button_validate()
|
||||
if res is True and self.picking_type_id.sequence_code == 'OCOUT':
|
||||
# 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(
|
||||
[('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 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(
|
||||
[('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)])
|
||||
production = self.env['mrp.production'].search([('name', '=', self.origin)])
|
||||
if move_in.state != 'done':
|
||||
move_in.write({'state': 'assigned'})
|
||||
self.env['stock.move.line'].create(move_in.get_move_line(production, None))
|
||||
('origin', '=', self.origin), ('state', 'not in', ['cancel', 'done'])])
|
||||
production = self.env['mrp.production'].search([('name', '=', self.origin)])
|
||||
for mi in move_in:
|
||||
pick = self.env['stock.picking'].search([('id', '=', mi.picking_id.id), ('name', 'ilike', 'OCIN'),
|
||||
('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
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<form string="模型类型">
|
||||
<group>
|
||||
<field name="name" required="1"/>
|
||||
<field name="embryo_tolerance_id" required="1" string="坯料容余(mm)"/>
|
||||
<field name="embryo_tolerance_id" required="1"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name='product_routing_tmpl_ids'>
|
||||
|
||||
@@ -51,5 +51,10 @@
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="stock.action_picking_tree_all" model="ir.actions.act_window">
|
||||
<field name="view_ids" eval="[(5, 0, 0),
|
||||
(0, 0, {'view_mode': 'tree', 'view_id': ref('stock.vpicktree')})]"/>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
@@ -83,7 +83,7 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
|
||||
workorder.picking_ids.write({'state': 'cancel'})
|
||||
workorder.picking_ids.move_ids.write({'state': 'cancel'})
|
||||
purchase_order = self.env['purchase.order'].search(
|
||||
[('origin', '=', workorder.production_id.origin)])
|
||||
[('origin', '=', workorder.production_id.name)])
|
||||
for line in purchase_order.order_line:
|
||||
if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id:
|
||||
purchase_order.write({'state': 'cancel'})
|
||||
@@ -104,6 +104,7 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
|
||||
self.env['mrp.workorder'].json_workorder_str(special.production_id, special))
|
||||
special.production_id.write({'workorder_ids': workorders_values})
|
||||
else:
|
||||
logging.info(workorder.blocked_by_workorder_ids)
|
||||
if len(workorder.blocked_by_workorder_ids) > 1:
|
||||
if workorder.sequence == 1:
|
||||
workorder.blocked_by_workorder_ids = None
|
||||
|
||||
@@ -80,7 +80,7 @@ class ProductionTechnologyWizard(models.TransientModel):
|
||||
workorder.picking_ids.write({'state': 'cancel'})
|
||||
workorder.picking_ids.move_ids.write({'state': 'cancel'})
|
||||
purchase_order = self.env['purchase.order'].search(
|
||||
[('origin', '=', workorder.production_id.origin)])
|
||||
[('origin', '=', workorder.production_id.name)])
|
||||
for line in purchase_order.order_line:
|
||||
if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id:
|
||||
purchase_order.write({'state': 'cancel'})
|
||||
|
||||
@@ -4,6 +4,7 @@ import logging
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from datetime import datetime
|
||||
from odoo import models, api, fields, _
|
||||
from odoo.tools import groupby
|
||||
|
||||
|
||||
class ReworkWizard(models.TransientModel):
|
||||
@@ -37,6 +38,30 @@ class ReworkWizard(models.TransientModel):
|
||||
|
||||
tool_state = fields.Selection(string='功能刀具状态', related='production_id.tool_state')
|
||||
|
||||
@api.onchange('hidden_workorder_ids')
|
||||
def _onchange_hidden_workorder_ids(self):
|
||||
for item in self:
|
||||
if item.hidden_workorder_ids not in ['', None, False]:
|
||||
hidden_workorder_list = item.hidden_workorder_ids.split(',')
|
||||
# 获取加工面对应需要返工的工单
|
||||
rw_ids = item.workorder_ids.filtered(
|
||||
lambda w: str(w.ids[0]) in hidden_workorder_list and w.processing_panel not in ['', None, False])
|
||||
grouped_rw_ids = {key: list(group) for key, group in groupby(rw_ids, key=lambda w: w.processing_panel)}
|
||||
for panel, panel_rw_ids in grouped_rw_ids.items():
|
||||
work_ids = item.workorder_ids.filtered(lambda w: w.state == 'done' and w.processing_panel == panel)
|
||||
if len(work_ids) == 3 and len(panel_rw_ids) != 3:
|
||||
for work_id in work_ids:
|
||||
if work_id not in panel_rw_ids:
|
||||
hidden_workorder_list.append(str(work_id.ids[0]))
|
||||
elif len(work_ids) == 2 and len(panel_rw_ids) < 2 and panel_rw_ids[0].name == 'CNC加工':
|
||||
if rw_ids.filtered(lambda w: (w.sequence < panel_rw_ids[0].sequence
|
||||
and w.processing_panel != panel_rw_ids[0].processing_panel)):
|
||||
hidden_workorder_list.append(str(work_ids.filtered(
|
||||
lambda w: (w.processing_panel == panel_rw_ids[0].processing_panel
|
||||
and w.name == '装夹预调')).ids[0]))
|
||||
hidden_workorder_list.sort()
|
||||
item.hidden_workorder_ids = ','.join(hidden_workorder_list)
|
||||
|
||||
def confirm(self):
|
||||
if self.routing_type in ['装夹预调', 'CNC加工']:
|
||||
self.is_clamp_measure = False
|
||||
@@ -58,16 +83,16 @@ class ReworkWizard(models.TransientModel):
|
||||
# 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工
|
||||
# 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选
|
||||
# 获取已完成的标准工单
|
||||
done_normative_workorder_ids = self.workorder_ids.filtered(
|
||||
lambda w: w.state == 'done' and w.processing_panel is not False)
|
||||
# 获取需要返工的标准工单
|
||||
rework_normative_workorder_ids = rework_workorder_ids.filtered(
|
||||
lambda w: w.processing_panel is not False)
|
||||
if rework_normative_workorder_ids:
|
||||
for rw in rework_normative_workorder_ids:
|
||||
if len(done_normative_workorder_ids.filtered(
|
||||
lambda w: w.processing_panel == rw.processing_panel)) == 3:
|
||||
pass
|
||||
# done_normative_workorder_ids = self.workorder_ids.filtered(
|
||||
# lambda w: w.state == 'done' and w.processing_panel is not False)
|
||||
# # 获取需要返工的标准工单
|
||||
# rework_normative_workorder_ids = rework_workorder_ids.filtered(
|
||||
# lambda w: w.processing_panel is not False)
|
||||
# if rework_normative_workorder_ids:
|
||||
# for rw in rework_normative_workorder_ids:
|
||||
# if len(done_normative_workorder_ids.filtered(
|
||||
# lambda w: w.processing_panel == rw.processing_panel)) == 3:
|
||||
# pass
|
||||
else:
|
||||
raise ValidationError('请选择返工工单!!!')
|
||||
if rework_workorder_ids:
|
||||
|
||||
@@ -232,41 +232,38 @@ class sf_production_plan(models.Model):
|
||||
raise ValidationError("未选择生产线")
|
||||
else:
|
||||
# 自动化产线加工
|
||||
if record.production_id.production_type == '自动化产线加工':
|
||||
if record.production_id.workorder_ids:
|
||||
last_cnc_start = record.date_planned_start if record.date_planned_start else datetime.now()
|
||||
for item in record.production_id.workorder_ids:
|
||||
if item.name == 'CNC加工':
|
||||
# 将同一个面的所有工单筛选出来
|
||||
workorder_list = record.production_id.workorder_ids.filtered(lambda x: x.processing_panel == item.processing_panel)
|
||||
routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search(
|
||||
[('name', '=', 'CNC加工')], limit=1)
|
||||
# 设置一个小的开始时间
|
||||
item.date_planned_start = datetime.now() - timedelta(days=100)
|
||||
item.date_planned_finished = last_cnc_start + timedelta(
|
||||
minutes=routing_workcenter.time_cycle)
|
||||
item.date_planned_start = last_cnc_start
|
||||
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
|
||||
item.duration_expected = routing_workcenter.time_cycle
|
||||
pre_duration , next_duration = record.calculate_plan_time(item, workorder_list)
|
||||
record.date_planned_finished = item.date_planned_finished
|
||||
# 计算下一个cnc工单的开始时间
|
||||
last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration)
|
||||
# 没有工单也能排程
|
||||
else:
|
||||
# 人工线下加工只排第一张工单
|
||||
if record.production_id.workorder_ids:
|
||||
if record.production_id.workorder_ids:
|
||||
# 自动化产线加工
|
||||
if record.production_id.production_type == '自动化产线加工':
|
||||
# 找到第一张CNC加工工单
|
||||
first_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[0]
|
||||
date_start = record.date_planned_start if record.date_planned_start else datetime.now()
|
||||
routing_workcenter = first_cnc_workorder.technology_design_id.route_id
|
||||
# 设置一个小的开始时间
|
||||
first_cnc_workorder.date_planned_start = datetime.now() - timedelta(days=100)
|
||||
first_cnc_workorder.date_planned_finished = date_start + timedelta(
|
||||
minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
|
||||
first_cnc_workorder.date_planned_start = date_start
|
||||
record.sudo().production_id.plan_start_processing_time = first_cnc_workorder.date_planned_start
|
||||
first_cnc_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
|
||||
record.calculate_plan_time(first_cnc_workorder, record.production_id.workorder_ids)
|
||||
# 找到最后一张CNC加工工单
|
||||
last_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[-1]
|
||||
record.date_planned_finished = last_cnc_workorder.date_planned_finished
|
||||
else:
|
||||
# 人工线下加工只排第一张工单
|
||||
item = record.production_id.workorder_ids[0]
|
||||
last_wo_start = record.date_planned_start if record.date_planned_start else datetime.now()
|
||||
routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search(
|
||||
[('name', '=', item.routing_type)], limit=1)
|
||||
wo_start = record.date_planned_start if record.date_planned_start else datetime.now()
|
||||
routing_workcenter = item.technology_design_id.route_id
|
||||
item.date_planned_start = datetime.now() - timedelta(days=100)
|
||||
item.date_planned_finished = last_wo_start + timedelta(
|
||||
minutes=routing_workcenter.time_cycle)
|
||||
item.date_planned_start = last_wo_start
|
||||
item.date_planned_finished = wo_start + timedelta(
|
||||
minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
|
||||
item.date_planned_start = wo_start
|
||||
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
|
||||
item.duration_expected = routing_workcenter.time_cycle
|
||||
record.calculate_plan_time(item, item)
|
||||
item.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
|
||||
record.calculate_plan_time(item, record.production_id.workorder_ids)
|
||||
last_cnc_workorder = record.production_id.workorder_ids[-1]
|
||||
record.date_planned_finished = last_cnc_workorder.date_planned_finished
|
||||
record.state = 'done'
|
||||
# record.production_id.schedule_state = '已排'
|
||||
record.sudo().production_id.schedule_state = '已排'
|
||||
@@ -322,44 +319,40 @@ class sf_production_plan(models.Model):
|
||||
def calculate_plan_time(self, item, workorder_list):
|
||||
"""
|
||||
根据CNC工单的时间去计算之前的其他工单的开始结束时间
|
||||
param:
|
||||
item: 基准工单(根据该工单的开始结束时间去计算其他工单的开始结束时间)
|
||||
workorder_list: 需排程的工单列表
|
||||
"""
|
||||
item_position = 0
|
||||
for index, workorder in enumerate(workorder_list):
|
||||
if workorder.id == item.id:
|
||||
item_position = index
|
||||
break
|
||||
routing_workcenters = self.env['mrp.routing.workcenter'].sudo().search([])
|
||||
# 记录所有前序工序时长
|
||||
previous_workorder_duration = 0
|
||||
for i in range(item_position, -1, -1):
|
||||
if i < 1:
|
||||
break
|
||||
current_workorder = workorder_list[i]
|
||||
next_workorder = workorder_list[i - 1]
|
||||
routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0]
|
||||
routing_workcenter = next_workorder.technology_design_id.route_id
|
||||
# 设置一个小的开始时间
|
||||
next_workorder.date_planned_start = datetime.now() - timedelta(days=100)
|
||||
next_workorder.date_planned_finished = current_workorder.date_planned_start
|
||||
next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta(
|
||||
minutes=routing_workcenter.time_cycle)
|
||||
next_workorder.duration_expected = routing_workcenter.time_cycle
|
||||
previous_workorder_duration += routing_workcenter.time_cycle
|
||||
# 记录所有后续工序时长
|
||||
next_workorder_duration = 0
|
||||
minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
|
||||
next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
|
||||
|
||||
for i in range(item_position, len(workorder_list) - 1):
|
||||
if i > len(workorder_list) - 1:
|
||||
break
|
||||
current_workorder = workorder_list[i]
|
||||
next_workorder = workorder_list[i + 1]
|
||||
routing_workcenter = routing_workcenters.filtered(lambda x: x.name == next_workorder.name)[0]
|
||||
routing_workcenter = next_workorder.technology_design_id.route_id
|
||||
# 设置一个小的开始时间
|
||||
next_workorder.date_planned_start = datetime.now() - timedelta(days=100)
|
||||
next_workorder.date_planned_finished = current_workorder.date_planned_finished + timedelta(
|
||||
minutes=routing_workcenter.time_cycle)
|
||||
minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
|
||||
next_workorder.date_planned_start = current_workorder.date_planned_finished
|
||||
next_workorder.duration_expected = routing_workcenter.time_cycle
|
||||
next_workorder_duration += routing_workcenter.time_cycle
|
||||
return previous_workorder_duration, next_workorder_duration
|
||||
next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
|
||||
|
||||
def calculate_plan_time_after(self, item, workorder_id_list):
|
||||
"""
|
||||
|
||||
@@ -265,17 +265,20 @@ class RePurchaseOrder(models.Model):
|
||||
}))
|
||||
for purchase in purchase_order:
|
||||
for po in purchase.order_line:
|
||||
if server_template.server_product_process_parameters_id == pp.surface_technics_parameters_id:
|
||||
if po.product_id == server_template.product_variant_id:
|
||||
continue
|
||||
if server_template.server_product_process_parameters_id != po.product_id.server_product_process_parameters_id:
|
||||
purchase_order_line = self.env['purchase.order.line'].search(
|
||||
[('product_id', '=', server_template.product_variant_id.id),
|
||||
('product_qty', '=', 1.0), ('id', '=', po.id)], limit=1,
|
||||
('product_qty', '=', 1.0), ('id', '=', purchase.id)], limit=1,
|
||||
order='id desc')
|
||||
if not purchase_order_line and purchase not in purchase_order:
|
||||
if not purchase_order_line:
|
||||
server_product_process.append((0, 0, {
|
||||
'product_id': server_template.product_variant_id.id,
|
||||
'product_qty': 1,
|
||||
'product_uom': server_template.uom_id.id
|
||||
}))
|
||||
|
||||
if server_product_process:
|
||||
self.env['purchase.order'].sudo().create({
|
||||
'partner_id': server_template.seller_ids[0].partner_id.id,
|
||||
|
||||
Reference in New Issue
Block a user