Merge branch 'refs/heads/develop' into feature/delivery_status
# Conflicts: # sf_manufacturing/models/mrp_production.py
This commit is contained in:
@@ -536,3 +536,7 @@ div:has(.o_required_modifier) > label::before {
|
|||||||
position: unset;
|
position: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修复搜索面板checkbox样式
|
||||||
|
.o_search_panel .form-check .form-check-label span {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
@@ -190,7 +190,7 @@ def _create(self, data_list):
|
|||||||
# 如果该用户组被限制创建或更新操作
|
# 如果该用户组被限制创建或更新操作
|
||||||
if rec['is_create_or_update']:
|
if rec['is_create_or_update']:
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_("You are restricted from performing this operation. Please contact the administrator."))
|
_("您没有执行此操作的权限。请联系管理员"))
|
||||||
else:
|
else:
|
||||||
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
# 如果 'access.right' 模型不存在,可以在这里定义备选逻辑
|
||||||
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
# 例如,记录日志、发送通知或者简单地跳过这部分逻辑
|
||||||
|
|||||||
@@ -6,12 +6,11 @@
|
|||||||
'author': 'fox',
|
'author': 'fox',
|
||||||
'website': '',
|
'website': '',
|
||||||
'category': '',
|
'category': '',
|
||||||
'depends': ['sf_dlm', 'sale_stock', 'sf_sale'],
|
'depends': ['sf_dlm', 'sale_stock', 'sf_sale', 'sale'],
|
||||||
"data": [
|
"data": [
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'data/stock_routes.xml',
|
'data/stock_routes.xml',
|
||||||
'data/product_data.xml',
|
'data/product_data.xml',
|
||||||
'views/sale_order_views.xml',
|
|
||||||
# 'views/product_product_views.xml',
|
# 'views/product_product_views.xml',
|
||||||
],'assets': {
|
],'assets': {
|
||||||
# 'web.assets_backend': [
|
# 'web.assets_backend': [
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from . import main
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from . import product_template
|
from . import product_template
|
||||||
from . import sale_order
|
|
||||||
from . import mrp_bom
|
from . import mrp_bom
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class StockRuleInherit(models.Model):
|
|||||||
po = self.env['purchase.order'].sudo().search([
|
po = self.env['purchase.order'].sudo().search([
|
||||||
('partner_id', '=', supplier.partner_id.id),
|
('partner_id', '=', supplier.partner_id.id),
|
||||||
('company_id', '=', procurement.company_id.id), # 保证公司一致
|
('company_id', '=', procurement.company_id.id), # 保证公司一致
|
||||||
('origin', '=', procurement.origin), # 根据来源匹配
|
('origin', 'like', procurement.origin), # 根据来源匹配
|
||||||
('state', '=', 'draft') # 状态为草稿
|
('state', '=', 'draft') # 状态为草稿
|
||||||
], limit=1)
|
], limit=1)
|
||||||
logging.info("po=: %s", po)
|
logging.info("po=: %s", po)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
'views/agv_setting_views.xml',
|
'views/agv_setting_views.xml',
|
||||||
'views/sf_maintenance_equipment.xml',
|
'views/sf_maintenance_equipment.xml',
|
||||||
'views/res_config_settings_views.xml',
|
'views/res_config_settings_views.xml',
|
||||||
|
'views/sale_order_views.xml',
|
||||||
],
|
],
|
||||||
'assets': {
|
'assets': {
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
from . import controllers
|
from . import controllers
|
||||||
from . import workpiece
|
from . import workpiece
|
||||||
|
from . import main
|
||||||
|
|||||||
@@ -13,3 +13,5 @@ from . import agv_scheduling
|
|||||||
from . import res_config_setting
|
from . import res_config_setting
|
||||||
from . import sf_technology_design
|
from . import sf_technology_design
|
||||||
from . import sf_production_common
|
from . import sf_production_common
|
||||||
|
from . import sale_order
|
||||||
|
from . import quick_easy_order
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ class ModelType(models.Model):
|
|||||||
|
|
||||||
name = fields.Char('名称')
|
name = fields.Char('名称')
|
||||||
# embryo_tolerance = fields.Char('坯料容余')
|
# embryo_tolerance = fields.Char('坯料容余')
|
||||||
embryo_tolerance_id = fields.Many2one('sf.embryo.redundancy', string='坯料容余')
|
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',
|
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',
|
embryo_routing_tmpl_ids = fields.One2many('sf.embryo.model.type.routing.sort', 'embryo_model_type_id',
|
||||||
|
|||||||
@@ -788,7 +788,7 @@ class MrpProduction(models.Model):
|
|||||||
# 立即创建外协出入库单和采购订单
|
# 立即创建外协出入库单和采购订单
|
||||||
# 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 = []
|
||||||
|
|
||||||
# 处理最后一个组,即使它可能只有一个工作订单
|
# 处理最后一个组,即使它可能只有一个工作订单
|
||||||
|
|||||||
@@ -86,9 +86,12 @@ class ResMrpRoutingWorkcenter(models.Model):
|
|||||||
@api.model
|
@api.model
|
||||||
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
|
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
|
||||||
if self._context.get('production_id'):
|
if self._context.get('production_id'):
|
||||||
|
route_ids = []
|
||||||
technology_design = self.env['sf.technology.design'].search(
|
technology_design = self.env['sf.technology.design'].search(
|
||||||
[('production_id', '=', self._context.get('production_id'))])
|
[('production_id', '=', self._context.get('production_id'))])
|
||||||
route_ids = [t.route_id.id for t in technology_design]
|
for t in technology_design.filtered(lambda a: a.routing_tag == 'special'):
|
||||||
domain = [('id', 'not in', route_ids)]
|
if not t.process_parameters_id:
|
||||||
|
route_ids.append(t.route_id.surface_technics_id.id)
|
||||||
|
domain = [('id', 'not in', route_ids), ('routing_tag', '=', 'special')]
|
||||||
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
|
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
|
||||||
return super()._name_search(name, args, operator, limit, name_get_uid)
|
return super()._name_search(name, args, operator, limit, name_get_uid)
|
||||||
|
|||||||
@@ -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='外协出入库单')
|
|
||||||
# purchase_id = fields.Many2one('purchase.order', string='外协采购单')
|
picking_ids = fields.Many2many('stock.picking', string='外协出入库单', compute='_compute_surface_technics_picking_ids')
|
||||||
|
|
||||||
|
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 += [('partner_id', '=', process_product.partner_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
|
||||||
@@ -269,65 +272,72 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
@api.depends('state', 'production_id.name')
|
@api.depends('state', 'production_id.name')
|
||||||
def _compute_surface_technics_purchase_ids(self):
|
def _compute_surface_technics_purchase_ids(self):
|
||||||
for order in self:
|
for order in self:
|
||||||
if order.routing_type == '表面工艺':
|
if order.routing_type == '表面工艺' and order.state not in ['cancel']:
|
||||||
if order.production_id.production_type == '自动化产线加工':
|
# if order.production_id.production_type == '自动化产线加工':
|
||||||
domain = [('programming_no', '=', order.production_id.programming_no)]
|
# domain = [('programming_no', '=', order.production_id.programming_no)]
|
||||||
else:
|
# else:buzhdiao
|
||||||
domain = [('origin', '=', order.production_id.origin)]
|
# domain = [('origin', '=', order.production_id.origin)]
|
||||||
production_programming = self.env['mrp.production'].search(domain, order='name asc')
|
# production_programming = self.env['mrp.production'].search(domain, order='name asc')
|
||||||
production_list = [production.name for production in production_programming]
|
# production_list = [production.name for production in production_programming]
|
||||||
production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
|
# production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
|
||||||
# technology_design = self.env['sf.technology.design'].search(
|
# technology_design = self.env['sf.technology.design'].search(
|
||||||
# [('process_parameters_id', '=', order.surface_technics_parameters_id.id),
|
# [('process_parameters_id', '=', order.surface_technics_parameters_id.id),
|
||||||
# ('production_id', '=', order.production_id.id)])
|
# ('production_id', '=', order.production_id.id)])
|
||||||
# if technology_design.is_auto is False:
|
# if technology_design.is_auto is False:
|
||||||
# domain = [('origin', '=', order.production_id.name)]
|
# domain = [('origin', '=', order.production_id.name)]
|
||||||
# else:
|
# else:
|
||||||
domain = [('purchase_type', '=', 'consignment'), ('origin', '=', ','.join(production_list))]
|
domain = [('purchase_type', '=', 'consignment'), ('origin', '=', order.production_id.name),
|
||||||
|
('state', '!=', 'cancel')]
|
||||||
purchase = self.env['purchase.order'].search(domain)
|
purchase = self.env['purchase.order'].search(domain)
|
||||||
purchase_num = 0
|
purchase_num = 0
|
||||||
if not purchase:
|
if not purchase:
|
||||||
order.surface_technics_purchase_count = 0
|
order.surface_technics_purchase_count = 0
|
||||||
for line in purchase.order_line:
|
for po in purchase:
|
||||||
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id:
|
for line in po.order_line:
|
||||||
if line.product_qty == len(production_no_remanufacture):
|
if line.product_id.server_product_process_parameters_id == order.surface_technics_parameters_id:
|
||||||
purchase_num += 1
|
if line.product_qty == 1:
|
||||||
order.surface_technics_purchase_count = purchase_num
|
purchase_num += 1
|
||||||
|
order.surface_technics_purchase_count = purchase_num
|
||||||
else:
|
else:
|
||||||
order.surface_technics_purchase_count = 0
|
order.surface_technics_purchase_count = 0
|
||||||
|
|
||||||
def action_view_surface_technics_purchase(self):
|
def action_view_surface_technics_purchase(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
if self.routing_type == '表面工艺':
|
# if self.routing_type == '表面工艺':
|
||||||
if self.production_id.production_type == '自动化产线加工':
|
# if self.production_id.production_type == '自动化产线加工':
|
||||||
domain = [('programming_no', '=', self.production_id.programming_no)]
|
# domain = [('programming_no', '=', self.production_id.programming_no)]
|
||||||
else:
|
# else:
|
||||||
domain = [('origin', '=', self.production_id.origin)]
|
# domain = [('origin', '=', self.production_id.origin)]
|
||||||
production_programming = self.env['mrp.production'].search(domain, order='name asc')
|
# production_programming = self.env['mrp.production'].search(domain, order='name asc')
|
||||||
production_list = [production.name for production in production_programming]
|
# production_list = [production.name for production in production_programming]
|
||||||
production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
|
# production_no_remanufacture = production_programming.filtered(lambda a: a.is_remanufacture is False)
|
||||||
# technology_design = self.env['sf.technology.design'].search(
|
# technology_design = self.env['sf.technology.design'].search(
|
||||||
# [('process_parameters_id', '=', self.surface_technics_parameters_id.id),
|
# [('process_parameters_id', '=', self.surface_technics_parameters_id.id),
|
||||||
# ('production_id', '=', self.production_id.id)])
|
# ('production_id', '=', self.production_id.id)])
|
||||||
# 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', '=', ','.join(production_list)), ('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 line in purchase_orders.order_line:
|
|
||||||
if line.product_id.server_product_process_parameters_id == self.surface_technics_parameters_id:
|
|
||||||
if line.product_qty == len(production_no_remanufacture):
|
|
||||||
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",
|
||||||
"res_id": purchase_orders_id,
|
"res_id": purchase_orders_id.id,
|
||||||
# "domain": [['id', 'in', self.purchase_id]],
|
# "domain": [['id', 'in', self.purchase_id]],
|
||||||
"name": _("Purchase Orders"),
|
"name": _("Purchase Orders"),
|
||||||
'view_mode': 'form',
|
'view_mode': 'form',
|
||||||
}
|
}
|
||||||
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 = self.env['purchase.order']
|
||||||
|
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
|
||||||
|
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)
|
||||||
@@ -1025,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:
|
||||||
# 如果工单的工序没有进行排序则跳出循环
|
# 如果工单的工序没有进行排序则跳出循环
|
||||||
@@ -1090,13 +1100,21 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
and workorder.production_id.schedule_state == '已排'
|
and workorder.production_id.schedule_state == '已排'
|
||||||
and len(workorder.production_id.picking_ids.filtered(
|
and len(workorder.production_id.picking_ids.filtered(
|
||||||
lambda w: w.state not in ['done', 'cancel'])) == 0):
|
lambda w: w.state not in ['done', 'cancel'])) == 0):
|
||||||
workorder.state = 'ready'
|
if workorder.is_subcontract is True:
|
||||||
|
purchase_orders_id = self._get_surface_technics_purchase_ids()
|
||||||
|
if purchase_orders_id.state == 'purchase':
|
||||||
|
workorder.state = 'ready'
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
workorder.state = 'waiting'
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
workorder.state = 'ready'
|
||||||
continue
|
continue
|
||||||
# ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]==========================
|
# ================= 如果制造订单刀具状态为[无效刀、缺刀] 或者 制造订单状态为[返工]==========================
|
||||||
if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework'
|
if (workorder.production_id.tool_state in ['1', '2'] or workorder.production_id.state == 'rework'
|
||||||
or workorder.production_id.schedule_state != '已排'
|
or workorder.production_id.schedule_state != '已排'
|
||||||
or len(
|
or workorder.production_id.reservation_state not in ['assigned']
|
||||||
workorder.production_id.picking_ids.filtered(lambda w: w.state not in ['done', 'cancel'])) != 0
|
|
||||||
or workorder.production_id.workorder_ids.filtered(
|
or workorder.production_id.workorder_ids.filtered(
|
||||||
lambda wk: wk.sequence == workorder.sequence - 1).test_results in ['报废', '返工']):
|
lambda wk: wk.sequence == workorder.sequence - 1).test_results in ['报废', '返工']):
|
||||||
if workorder.state != 'waiting':
|
if workorder.state != 'waiting':
|
||||||
@@ -1117,21 +1135,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),
|
||||||
@@ -1194,6 +1217,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',
|
||||||
@@ -1201,9 +1228,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:
|
||||||
@@ -1240,15 +1264,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)])
|
# [('barcode', 'ilike', 'VL-SPOC')]).id),
|
||||||
if move_out.state != 'done':
|
# ('origin', '=', self.production_id.name), ('state', 'not in', ['cancel', 'done'])])
|
||||||
move_out.write({'state': 'assigned', 'production_id': False})
|
for mo in move_out:
|
||||||
self.env['stock.move.line'].create(move_out.get_move_line(self.production_id, self))
|
if mo.state != 'done':
|
||||||
|
mo.write({'state': 'assigned', 'production_id': False})
|
||||||
|
if not mo.move_line_ids:
|
||||||
|
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':
|
||||||
@@ -1353,6 +1395,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)
|
||||||
@@ -1371,7 +1420,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# record.recreateManufacturingOrWorkerOrder()
|
# record.recreateManufacturingOrWorkerOrder()
|
||||||
is_production_id = False
|
is_production_id = False
|
||||||
rework_workorder = record.production_id.workorder_ids.filtered(lambda p: p.state == 'rework')
|
rework_workorder = record.production_id.workorder_ids.filtered(lambda p: p.state == 'rework')
|
||||||
done_workorder = record.production_id.workorder_ids.filtered(lambda p1: p1.state == 'done')
|
done_workorder = record.production_id.workorder_ids.filtered(lambda p1: p1.state in ['done'])
|
||||||
if (len(rework_workorder) + len(done_workorder) == len(record.production_id.workorder_ids)) or (
|
if (len(rework_workorder) + len(done_workorder) == len(record.production_id.workorder_ids)) or (
|
||||||
len(done_workorder) == len(record.production_id.workorder_ids)):
|
len(done_workorder) == len(record.production_id.workorder_ids)):
|
||||||
is_production_id = True
|
is_production_id = True
|
||||||
@@ -1388,19 +1437,20 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# workorder.rfid_code_old = rfid_code
|
# workorder.rfid_code_old = rfid_code
|
||||||
# workorder.rfid_code = False
|
# workorder.rfid_code = False
|
||||||
logging.info('workorder.rfid_code:%s' % workorder.rfid_code)
|
logging.info('workorder.rfid_code:%s' % workorder.rfid_code)
|
||||||
if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺']:
|
# if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺', '切割']:
|
||||||
|
if is_production_id is True:
|
||||||
logging.info('product_qty:%s' % record.production_id.product_qty)
|
logging.info('product_qty:%s' % record.production_id.product_qty)
|
||||||
for move_raw_id in record.production_id.move_raw_ids:
|
for move_raw_id in record.production_id.move_raw_ids:
|
||||||
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'
|
||||||
|
|
||||||
@@ -1520,6 +1570,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):
|
||||||
|
|||||||
@@ -859,12 +859,12 @@ class ResProductMo(models.Model):
|
|||||||
raise UserError('请先配置模型类型内的坯料冗余')
|
raise UserError('请先配置模型类型内的坯料冗余')
|
||||||
vals = {
|
vals = {
|
||||||
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
||||||
'model_long': item['model_long'] + embryo_redundancy_id.long,
|
'model_long': self.format_float(item['model_long'] + embryo_redundancy_id.long),
|
||||||
'model_width': item['model_width'] + embryo_redundancy_id.width,
|
'model_width': self.format_float(item['model_width'] + embryo_redundancy_id.width),
|
||||||
'model_height': item['model_height'] + embryo_redundancy_id.height,
|
'model_height': self.format_float(item['model_height'] + embryo_redundancy_id.height),
|
||||||
'model_volume': (item['model_long'] + embryo_redundancy_id.long) * (
|
'model_volume': self.format_float((item['model_long'] + embryo_redundancy_id.long) * (
|
||||||
item['model_width'] + embryo_redundancy_id.width) * (
|
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,
|
'product_model_type_id': model_type.id,
|
||||||
'model_processing_panel': item['processing_panel_detail'],
|
'model_processing_panel': item['processing_panel_detail'],
|
||||||
'model_machining_precision': item['model_machining_precision'],
|
'model_machining_precision': item['model_machining_precision'],
|
||||||
@@ -907,6 +907,20 @@ class ResProductMo(models.Model):
|
|||||||
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
|
self.attachment_update(item['quality_standard_name'], copy_product_id.product_tmpl_id.id,
|
||||||
'quality_standard', item['quality_standard_mimetype'])
|
'quality_standard', item['quality_standard_mimetype'])
|
||||||
return copy_product_id
|
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):
|
def _get_ids(self, param):
|
||||||
type_ids = []
|
type_ids = []
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ class SaleOrder(models.Model):
|
|||||||
|
|
||||||
# 复制成品模板上的属性
|
# 复制成品模板上的属性
|
||||||
line.product_id.product_tmpl_id.copy_template(product_template_id)
|
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
|
order_id = self
|
||||||
product = line.product_id
|
product = line.product_id
|
||||||
@@ -10,8 +10,14 @@ class SfProductionProcessParameter(models.Model):
|
|||||||
@api.model
|
@api.model
|
||||||
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
|
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
|
||||||
if self._context.get('route_id'):
|
if self._context.get('route_id'):
|
||||||
|
parameter = []
|
||||||
routing = self.env['mrp.routing.workcenter'].search([('id', '=', self._context.get('route_id'))])
|
routing = self.env['mrp.routing.workcenter'].search([('id', '=', self._context.get('route_id'))])
|
||||||
domain = [('process_id', '=', routing.surface_technics_id.id)]
|
technology_design = self.env['sf.technology.design'].search(
|
||||||
|
[('production_id', '=', self._context.get('production_id')), ('routing_tag', '=', 'special'),
|
||||||
|
('route_id', '=', self._context.get('route_id'))])
|
||||||
|
for t in technology_design:
|
||||||
|
if t.process_parameters_id:
|
||||||
|
parameter.append(t.process_parameters_id.id)
|
||||||
|
domain = [('process_id', '=', routing.surface_technics_id.id), ('id', 'not in', parameter)]
|
||||||
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
|
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
|
||||||
return super()._name_search(name, args, operator, limit, name_get_uid)
|
return super()._name_search(name, args, operator, limit, name_get_uid)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from odoo import fields, models
|
from odoo import fields, models, api, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
class sf_technology_design(models.Model):
|
class sf_technology_design(models.Model):
|
||||||
@@ -29,3 +30,11 @@ class sf_technology_design(models.Model):
|
|||||||
|
|
||||||
def unlink_technology_design(self):
|
def unlink_technology_design(self):
|
||||||
self.active = False
|
self.active = False
|
||||||
|
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
for vals in vals_list:
|
||||||
|
if not vals.get('route_id'):
|
||||||
|
raise ValidationError(_("工序不能为空"))
|
||||||
|
return super(sf_technology_design, self).create(vals_list)
|
||||||
|
|||||||
@@ -283,24 +283,24 @@ class StockRule(models.Model):
|
|||||||
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
|
sale_order = self.env['sale.order'].sudo().search([('name', '=', production.origin)])
|
||||||
# 如果订单为空,则获取来源制造订单的销售单
|
# 如果订单为空,则获取来源制造订单的销售单
|
||||||
if not sale_order:
|
if not sale_order:
|
||||||
mrp_production = self.env['mrp.production'].sudo().search([('name', '=', production.origin)], limit=1)
|
mrp_production = self.env['mrp.production'].sudo().search([('name', '=', production.origin)],
|
||||||
|
limit=1)
|
||||||
if mrp_production:
|
if mrp_production:
|
||||||
sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)])
|
sale_order = self.env['sale.order'].sudo().search([('name', '=', mrp_production.origin)])
|
||||||
else:
|
else:
|
||||||
mrp_production = production
|
mrp_production = production
|
||||||
if sale_order:
|
# 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({
|
self.env['sf.production.plan'].sudo().with_company(company_id).create({
|
||||||
'name': production.name,
|
'name': production.name,
|
||||||
'order_deadline': sale_order.deadline_of_delivery,
|
'order_deadline': sale_order.deadline_of_delivery,
|
||||||
'production_id': production.id,
|
'production_id': production.id,
|
||||||
'date_planned_start': production.date_planned_start,
|
'date_planned_start': production.date_planned_start,
|
||||||
'origin': mrp_production.origin,
|
'origin': mrp_production.origin,
|
||||||
'product_qty': production.product_qty,
|
'product_qty': production.product_qty,
|
||||||
'product_id': production.product_id.id,
|
'product_id': production.product_id.id,
|
||||||
'state': 'draft',
|
'state': 'draft',
|
||||||
})
|
})
|
||||||
technology_design_values = []
|
|
||||||
all_production = productions
|
all_production = productions
|
||||||
grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)}
|
grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)}
|
||||||
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
|
||||||
@@ -310,6 +310,7 @@ class StockRule(models.Model):
|
|||||||
# 为同一个product_id创建一个生产订单名称列表
|
# 为同一个product_id创建一个生产订单名称列表
|
||||||
product_id_to_production_names[product_id] = [production.name for production in all_production]
|
product_id_to_production_names[product_id] = [production.name for production in all_production]
|
||||||
for production_item in productions:
|
for production_item in productions:
|
||||||
|
technology_design_values = []
|
||||||
production_programming = self.env['mrp.production'].search(
|
production_programming = self.env['mrp.production'].search(
|
||||||
[('product_id.id', '=', production_item.product_id.id),
|
[('product_id.id', '=', production_item.product_id.id),
|
||||||
('origin', '=', production_item.origin)],
|
('origin', '=', production_item.origin)],
|
||||||
@@ -317,77 +318,76 @@ class StockRule(models.Model):
|
|||||||
if production_item.product_id.id in product_id_to_production_names:
|
if production_item.product_id.id in product_id_to_production_names:
|
||||||
# 同一个产品多个制造订单对应一个编程单和模型库
|
# 同一个产品多个制造订单对应一个编程单和模型库
|
||||||
# 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
# 只调用一次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:
|
if not production_programming.programming_no:
|
||||||
production_item.fetchCNC(
|
production_item.fetchCNC(
|
||||||
', '.join(product_id_to_production_names[production_item.product_id.id]))
|
', '.join(product_id_to_production_names[production_item.product_id.id]))
|
||||||
else:
|
else:
|
||||||
production_item.write({'programming_no': production_programming.programming_no,
|
production_item.write({'programming_no': production_programming.programming_no,
|
||||||
'programming_state': '编程中'})
|
'programming_state': '编程中'})
|
||||||
if not technology_design_values:
|
i = 0
|
||||||
i = 0
|
if production_item.product_id.categ_id.type == '成品':
|
||||||
if production_item.product_id.categ_id.type == '成品':
|
# 根据加工面板的面数及成品工序模板生成工序设计
|
||||||
# 根据加工面板的面数及成品工序模板生成工序设计
|
if production_item.production_type == '自动化产线加工':
|
||||||
if production_item.production_type == '自动化产线加工':
|
model = 'sf.product.model.type.routing.sort'
|
||||||
model = 'sf.product.model.type.routing.sort'
|
domain = [
|
||||||
domain = [
|
('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)]
|
||||||
('product_model_type_id', '=', production_item.product_id.product_model_type_id.id)]
|
else:
|
||||||
else:
|
model = 'sf.manual.product.model.type.routing.sort'
|
||||||
model = 'sf.manual.product.model.type.routing.sort'
|
domain = [('manual_product_model_type_id', '=',
|
||||||
domain = [('manual_product_model_type_id', '=',
|
production_item.product_id.product_model_type_id.id)]
|
||||||
production_item.product_id.product_model_type_id.id)]
|
product_routing_workcenter = self.env[model].search(domain, order='sequence asc')
|
||||||
product_routing_workcenter = self.env[model].search(domain, order='sequence asc')
|
if production_item.production_type == '自动化产线加工':
|
||||||
if production_item.production_type == '自动化产线加工':
|
for k in (production_item.product_id.model_processing_panel.split(',')):
|
||||||
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:
|
|
||||||
for route in product_routing_workcenter:
|
for route in product_routing_workcenter:
|
||||||
i += 1
|
i += 1
|
||||||
technology_design_values.append(
|
technology_design_values.append(
|
||||||
self.env['sf.technology.design'].json_technology_design_str(False, route, i, False))
|
self.env['sf.technology.design'].json_technology_design_str(k, route, i, False))
|
||||||
elif production_item.product_id.categ_id.type == '坯料':
|
else:
|
||||||
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
|
for route in product_routing_workcenter:
|
||||||
[('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
|
i += 1
|
||||||
technology_design_values.append(
|
technology_design_values.append(
|
||||||
self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i,
|
self.env['sf.technology.design'].json_technology_design_str(False, route, i, False))
|
||||||
False))
|
elif production_item.product_id.categ_id.type == '坯料':
|
||||||
surface_technics_arr = []
|
embryo_routing_workcenter = self.env['sf.embryo.model.type.routing.sort'].search(
|
||||||
route_workcenter_arr = []
|
[('embryo_model_type_id', '=', production_item.product_id.embryo_model_type_id.id)],
|
||||||
for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
|
order='sequence asc'
|
||||||
if item.route_workcenter_id.surface_technics_id.id:
|
)
|
||||||
for process_param in production_item.product_id.model_process_parameters_ids:
|
for route_embryo in embryo_routing_workcenter:
|
||||||
if item.route_workcenter_id.surface_technics_id == process_param.process_id:
|
i += 1
|
||||||
surface_technics_arr.append(
|
technology_design_values.append(
|
||||||
item.route_workcenter_id.surface_technics_id.id)
|
self.env['sf.technology.design'].json_technology_design_str(False, route_embryo, i,
|
||||||
route_workcenter_arr.append(item.route_workcenter_id.id)
|
False))
|
||||||
if surface_technics_arr:
|
surface_technics_arr = []
|
||||||
production_process = self.env['sf.production.process'].search(
|
route_workcenter_arr = []
|
||||||
[('id', 'in', surface_technics_arr)],
|
for item in production_item.product_id.product_model_type_id.surface_technics_routing_tmpl_ids:
|
||||||
order='sequence asc'
|
if item.route_workcenter_id.surface_technics_id.id:
|
||||||
)
|
for process_param in production_item.product_id.model_process_parameters_ids:
|
||||||
for p in production_process:
|
if item.route_workcenter_id.surface_technics_id == process_param.process_id:
|
||||||
logging.info('production_process:%s' % p.name)
|
surface_technics_arr.append(
|
||||||
process_parameter = production_item.product_id.model_process_parameters_ids.filtered(
|
item.route_workcenter_id.surface_technics_id.id)
|
||||||
lambda pm: pm.process_id.id == p.id)
|
route_workcenter_arr.append(item.route_workcenter_id.id)
|
||||||
if process_parameter:
|
if surface_technics_arr:
|
||||||
i += 1
|
production_process = self.env['sf.production.process'].search(
|
||||||
route_production_process = self.env[
|
[('id', 'in', surface_technics_arr)],
|
||||||
'mrp.routing.workcenter'].search(
|
order='sequence asc'
|
||||||
[('surface_technics_id', '=', p.id),
|
)
|
||||||
('id', 'in', route_workcenter_arr)])
|
for p in production_process:
|
||||||
technology_design_values.append(
|
logging.info('production_process:%s' % p.name)
|
||||||
self.env['sf.technology.design'].json_technology_design_str(False,
|
process_parameter = production_item.product_id.model_process_parameters_ids.filtered(
|
||||||
route_production_process,
|
lambda pm: pm.process_id.id == p.id)
|
||||||
i,
|
if process_parameter:
|
||||||
process_parameter))
|
i += 1
|
||||||
productions.technology_design_ids = technology_design_values
|
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'})
|
productions.write({'state': 'technology_to_confirmed'})
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -423,6 +423,8 @@ class ProductionLot(models.Model):
|
|||||||
"""Generate `lot_names` from a string."""
|
"""Generate `lot_names` from a string."""
|
||||||
if first_lot.__contains__(display_name):
|
if first_lot.__contains__(display_name):
|
||||||
first_lot = first_lot[(len(display_name) + 1):]
|
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.
|
# We look if the first lot contains at least one digit.
|
||||||
caught_initial_number = regex_findall(r"\d+", first_lot)
|
caught_initial_number = regex_findall(r"\d+", first_lot)
|
||||||
@@ -633,80 +635,79 @@ class StockPicking(models.Model):
|
|||||||
return '%s%s' % (rescode, num)
|
return '%s%s' % (rescode, num)
|
||||||
|
|
||||||
def button_validate(self):
|
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)])
|
|
||||||
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()
|
res = super().button_validate()
|
||||||
if res is True and self.picking_type_id.barcode == 'OCIN':
|
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)])
|
if workorder == subcontract_workorders[-1]:
|
||||||
production = self.env['mrp.production'].search([('name', '=', self.origin)])
|
self.env['stock.quant']._update_reserved_quantity(
|
||||||
if move_in.state != 'done':
|
move_in.product_id, move_in.location_dest_id, move_in.product_uom_qty, lot_id=move_in.move_line_ids.lot_id,
|
||||||
move_in.write({'state': 'assigned'})
|
package_id=False, owner_id=False, strict=False
|
||||||
self.env['stock.move.line'].create(move_in.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):
|
||||||
if len(sorted_workorders_arr) > 1:
|
for workorder in workorders:
|
||||||
sorted_workorders_arr = sorted_workorders_arr[0]
|
if workorder.move_subcontract_workorder_ids:
|
||||||
stock_picking = self.env['stock.picking'].search([('origin', '=', item.name), ('name', 'ilike', 'OCOUT')])
|
workorder.move_subcontract_workorder_ids.write({'state': 'draft'})
|
||||||
if not stock_picking or sorted_workorders_arr:
|
workorder.move_subcontract_workorder_ids.picking_id.write({'state': 'draft'})
|
||||||
for sorted_workorders in sorted_workorders_arr:
|
else:
|
||||||
# pick_ids = []
|
# 创建一个新的补货组
|
||||||
if not sorted_workorders.picking_ids:
|
procurement_group_id = self.env['procurement.group'].create({
|
||||||
# outcontract_stock_move = self.env['stock.move'].search([('production_id', '=', item.id)])
|
'name': workorder.name,
|
||||||
# if not outcontract_stock_move:
|
'partner_id': self.partner_id.id,
|
||||||
new_picking = True
|
})
|
||||||
location_id = self.env['stock.location'].search(
|
move_dest_id = False
|
||||||
[('barcode', 'ilike', 'VL-SPOC')]).id,
|
# 如果当前工单是是制造订单的最后一个工单
|
||||||
location_dest_id = self.env['stock.location'].search(
|
if workorder == item.workorder_ids[-1]:
|
||||||
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id,
|
move_dest_id = item.move_raw_ids[0].id
|
||||||
outcontract_picking_type_in = self.env.ref(
|
else:
|
||||||
'sf_manufacturing.outcontract_picking_in').id,
|
# 从sorted_workorders中找到上一工单的move
|
||||||
outcontract_picking_type_out = self.env.ref(
|
if sorted_workorders.index(workorder) > 0:
|
||||||
'sf_manufacturing.outcontract_picking_out').id,
|
move_dest_id = sorted_workorders[sorted_workorders.index(workorder) - 1].move_subcontract_workorder_ids[1].id
|
||||||
moves_out = self.env['stock.move'].sudo().create(
|
new_picking = True
|
||||||
self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id,
|
outcontract_picking_type_in = self.env.ref(
|
||||||
outcontract_picking_type_out))
|
'sf_manufacturing.outcontract_picking_in').id,
|
||||||
picking_out = self.create(
|
outcontract_picking_type_out = self.env.ref(
|
||||||
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/'))
|
'sf_manufacturing.outcontract_picking_out').id,
|
||||||
# pick_ids.append(picking_out.id)
|
moves_in = self.env['stock.move'].sudo().create(
|
||||||
moves_out.write(
|
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_in, procurement_group_id.id, move_dest_id))
|
||||||
{'picking_id': picking_out.id, 'state': 'waiting'})
|
picking_in = self.create(
|
||||||
moves_out._assign_picking_post_process(new=new_picking)
|
moves_in._get_new_picking_values_Res(item, workorder, 'WH/OCIN/'))
|
||||||
moves_in = self.env['stock.move'].sudo().create(
|
# pick_ids.append(picking_in.id)
|
||||||
self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id,
|
moves_in.write(
|
||||||
outcontract_picking_type_in))
|
{'picking_id': picking_in.id, 'state': 'waiting'})
|
||||||
picking_in = self.create(
|
moves_in._assign_picking_post_process(new=new_picking)
|
||||||
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/'))
|
moves_out = self.env['stock.move'].sudo().create(
|
||||||
# pick_ids.append(picking_in.id)
|
self.env['stock.move']._get_stock_move_values_Res(item, outcontract_picking_type_out, procurement_group_id.id, moves_in.id))
|
||||||
moves_in.write(
|
workorder.write({'move_subcontract_workorder_ids': [(6, 0, [moves_in.id, moves_out.id])]})
|
||||||
{'picking_id': picking_in.id, 'state': 'waiting'})
|
picking_out = self.create(
|
||||||
moves_in._assign_picking_post_process(new=new_picking)
|
moves_out._get_new_picking_values_Res(item, workorder, '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)
|
||||||
|
|
||||||
|
|
||||||
|
@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):
|
||||||
@@ -716,17 +717,20 @@ 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):
|
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,
|
||||||
|
'move_dest_ids': [(6, 0, [move_dest_ids])] if move_dest_ids else False,
|
||||||
# 'route_ids': False if not route else [(4, route.id)],
|
# 'route_ids': False if not route else [(4, route.id)],
|
||||||
'date_deadline': datetime.now(),
|
'date_deadline': datetime.now(),
|
||||||
'picking_type_id': picking_type_id,
|
'picking_type_id': picking_type_id,
|
||||||
@@ -750,7 +754,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):
|
||||||
@@ -966,7 +970,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)])
|
||||||
@@ -989,9 +993,12 @@ class ReStockMove(models.Model):
|
|||||||
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)])
|
||||||
res['origin'] = ','.join(productions.mapped('name'))
|
if 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):
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ access_mrp_routing_workcenter_manager_group_sf_mrp_user,mrp.routing.workcenter.m
|
|||||||
access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_base.group_sf_mrp_user,1,1,1,0
|
access_mrp_bom_manager_group_sf_mrp_user,mrp.bom.manager,mrp.model_mrp_bom,sf_base.group_sf_mrp_user,1,1,1,0
|
||||||
access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0
|
access_mrp_bom_line_manager_group_sf_mrp_user,mrp.bom.line.manager,mrp.model_mrp_bom_line,sf_base.group_sf_mrp_user,1,1,1,0
|
||||||
access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0
|
access_mrp_bom_line_group_plan_director,mrp_bom_line_group_plan_director,mrp.model_mrp_bom_line,sf_base.group_plan_director,1,1,1,0
|
||||||
|
access_mrp_bom_line_group_sf_stock_user,mrp_bom_line_group_sf_stock_user,mrp.model_mrp_bom_line,sf_base.group_sf_stock_user,1,1,1,0
|
||||||
access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0
|
access_mrp_bom_line_group_sale_director,mrp_bom_line_group_sale_director,mrp.model_mrp_bom_line,sf_base.group_sale_director,1,1,1,0
|
||||||
access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0
|
access_mrp_bom_line_group_sale_salemanager,mrp_bom_line_group_sale_salemanager,mrp.model_mrp_bom_line,sf_base.group_sale_salemanager,1,0,1,0
|
||||||
access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0
|
access_mrp_bom_line_group_purchase_director,mrp_bom_line_group_purchase_director,mrp.model_mrp_bom_line,sf_base.group_purchase_director,1,1,1,0
|
||||||
@@ -116,7 +117,7 @@ access_mrp_production_group_quality,mrp_production,model_mrp_production,sf_base.
|
|||||||
access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0
|
access_mrp_production_group_quality_director,mrp_production,model_mrp_production,sf_base.group_quality_director,1,1,0,0
|
||||||
access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0
|
access_mrp_workorder_group_quality,mrp_workorder,model_mrp_workorder,sf_base.group_quality,1,1,0,0
|
||||||
access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0
|
access_mrp_workorder_group_quality_director,mrp_workorder,model_mrp_workorder,sf_base.group_quality_director,1,1,0,0
|
||||||
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,0,0
|
access_mrp_workorder,mrp_workorder,model_mrp_workorder,sf_base.group_plan_dispatch,1,1,1,0
|
||||||
access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0
|
access_sf_production_line_group_plan_dispatch,sf.production.line,model_sf_production_line,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0
|
access_sf_production_line_group_plan_director,sf.production.line,model_sf_production_line,sf_base.group_plan_director,1,1,1,0
|
||||||
access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0
|
access_sf_production_line,sf.production.line,model_sf_production_line,sf_maintenance.sf_group_equipment_user,1,1,1,0
|
||||||
@@ -166,10 +167,12 @@ access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_man
|
|||||||
access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0
|
access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0
|
||||||
|
|
||||||
access_sf_technology_design_group_plan_dispatch,sf_technology_design_group_plan_dispatch,model_sf_technology_design,sf_base.group_plan_dispatch,1,1,1,0
|
access_sf_technology_design_group_plan_dispatch,sf_technology_design_group_plan_dispatch,model_sf_technology_design,sf_base.group_plan_dispatch,1,1,1,0
|
||||||
access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,1,1,0
|
access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,0,0,0
|
||||||
access_sf_technology_design_group_production_engineer,sf_technology_design_group_production_engineer,model_sf_technology_design,sf_base.group_production_engineer,1,1,1,0
|
access_sf_technology_design_group_production_engineer,sf_technology_design_group_production_engineer,model_sf_technology_design,sf_base.group_production_engineer,1,1,1,0
|
||||||
|
access_sf_technology_design_group_sf_equipment_user,sf_technology_design_group_sf_equipment_user,model_sf_technology_design,sf_base.group_sf_equipment_user,1,0,0,0
|
||||||
|
access_sf_technology_design_group_sf_order_user,sf_technology_design_group_sf_order_user,model_sf_technology_design,sf_base.group_sf_order_user,1,0,0,0
|
||||||
access_sf_production_technology_wizard_group_plan_dispatch,sf_production_technology_wizard_group_plan_dispatch,model_sf_production_technology_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
access_sf_production_technology_wizard_group_plan_dispatch,sf_production_technology_wizard_group_plan_dispatch,model_sf_production_technology_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
||||||
access_sf_production_technology_wizard_group_sf_mrp_manager,sf_production_technology_wizard_group_sf_mrp_manager,model_sf_production_technology_wizard,sf_base.group_sf_mrp_manager,1,1,1,0
|
access_sf_production_technology_wizard_group_sf_mrp_manager,sf_production_technology_wizard_group_sf_mrp_manager,model_sf_production_technology_wizard,sf_base.group_sf_mrp_manager,1,0,0,0
|
||||||
access_sf_production_technology_wizard_group_production_engineer,sf_production_technology_wizard_group_production_engineer,model_sf_production_technology_wizard,sf_base.group_production_engineer,1,1,1,0
|
access_sf_production_technology_wizard_group_production_engineer,sf_production_technology_wizard_group_production_engineer,model_sf_production_technology_wizard,sf_base.group_production_engineer,1,1,1,0
|
||||||
access_sf_production_technology_re_adjust_wizard_group_plan_dispatch,sf_production_technology_re_adjust_wizard_group_plan_dispatch,model_sf_production_technology_re_adjust_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
access_sf_production_technology_re_adjust_wizard_group_plan_dispatch,sf_production_technology_re_adjust_wizard_group_plan_dispatch,model_sf_production_technology_re_adjust_wizard,sf_base.group_plan_dispatch,1,1,1,0
|
||||||
access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,model_sf_production_technology_re_adjust_wizard,sf_base.group_sf_mrp_manager,1,1,1,0
|
access_sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,sf_production_technology_re_adjust_wizard_group_sf_mrp_manager,model_sf_production_technology_re_adjust_wizard,sf_base.group_sf_mrp_manager,1,1,1,0
|
||||||
|
|||||||
|
@@ -31,7 +31,7 @@
|
|||||||
<form string="模型类型">
|
<form string="模型类型">
|
||||||
<group>
|
<group>
|
||||||
<field name="name" required="1"/>
|
<field name="name" required="1"/>
|
||||||
<field name="embryo_tolerance_id" required="1" string="坯料容余(mm)"/>
|
<field name="embryo_tolerance_id" required="1"/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name='product_routing_tmpl_ids'>
|
<field name='product_routing_tmpl_ids'>
|
||||||
|
|||||||
@@ -370,7 +370,8 @@
|
|||||||
attrs="{'readonly': [('id', '!=', False)]}" options="{'no_create': True}"/>
|
attrs="{'readonly': [('id', '!=', False)]}" options="{'no_create': True}"/>
|
||||||
<field name="process_parameters_id"
|
<field name="process_parameters_id"
|
||||||
attrs="{'readonly': [('id', '!=', False),('routing_tag', '=', 'standard')]}"
|
attrs="{'readonly': [('id', '!=', False),('routing_tag', '=', 'standard')]}"
|
||||||
string="参数" context="{'route_id':route_id}" options="{'no_create': True}"/>
|
string="参数" context="{'route_id':route_id,'production_id': production_id}"
|
||||||
|
options="{'no_create': True}"/>
|
||||||
<field name="panel" readonly="1"/>
|
<field name="panel" readonly="1"/>
|
||||||
<field name="routing_tag" readonly="1" widget="badge"
|
<field name="routing_tag" readonly="1" widget="badge"
|
||||||
decoration-success="routing_tag == 'standard'"
|
decoration-success="routing_tag == 'standard'"
|
||||||
@@ -740,5 +741,19 @@
|
|||||||
<!-- parent="mrp.menu_mrp_manufacturing"-->
|
<!-- parent="mrp.menu_mrp_manufacturing"-->
|
||||||
<!-- sequence="1"/>-->
|
<!-- sequence="1"/>-->
|
||||||
|
|
||||||
|
<menuitem id="mrp.menu_mrp_production_action"
|
||||||
|
name="制造订单"
|
||||||
|
parent="mrp.menu_mrp_manufacturing"
|
||||||
|
action="mrp.mrp_production_action"
|
||||||
|
groups="sf_base.group_plan_dispatch,sf_base.group_sf_mrp_manager"
|
||||||
|
sequence="1"/>
|
||||||
|
|
||||||
|
<menuitem id="stock_picking_type_menu"
|
||||||
|
name="驾驶舱"
|
||||||
|
parent="stock.menu_stock_root"
|
||||||
|
action="stock.stock_picking_type_action"
|
||||||
|
groups="sf_base.group_sf_stock_user"
|
||||||
|
sequence="0"/>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
<button type="object" name="action_view_surface_technics_purchase" class="oe_stat_button"
|
<button type="object" name="action_view_surface_technics_purchase" class="oe_stat_button"
|
||||||
icon="fa-credit-card"
|
icon="fa-credit-card"
|
||||||
groups="base.group_user,sf_base.group_sf_order_user"
|
groups="base.group_user,sf_base.group_sf_order_user"
|
||||||
attrs="{'invisible': [('surface_technics_purchase_count', '=', 0),('routing_type', '!=', '表面工艺')]}">
|
attrs="{'invisible': [('surface_technics_purchase_count', '=', 0)]}">
|
||||||
<div class="o_field_widget o_stat_info">
|
<div class="o_field_widget o_stat_info">
|
||||||
<span class="o_stat_value">
|
<span class="o_stat_value">
|
||||||
<field name="surface_technics_purchase_count"/>
|
<field name="surface_technics_purchase_count"/>
|
||||||
|
|||||||
@@ -1,17 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="view_order_form_inherit_sf" model="ir.ui.view">
|
|
||||||
<field name="name">view.sale.order.form.inherit.sf</field>
|
|
||||||
<field name="inherit_id" ref="sale_stock.view_order_form_inherit_sale_stock_qty"/>
|
|
||||||
<field name="model">sale.order</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<xpath expr="//page/field[@name='order_line']/form/group/group/div[@name='ordered_qty']/widget[@name='qty_at_date_widget']" position="replace">
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//page/field[@name='order_line']/tree/widget[@name='qty_at_date_widget']" position="replace">
|
|
||||||
</xpath>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<record id="view_order_form_inherit_supply_method" model="ir.ui.view">
|
<record id="view_order_form_inherit_supply_method" model="ir.ui.view">
|
||||||
<field name="name">view.sale.order.form.inherit.supply.method</field>
|
<field name="name">view.sale.order.form.inherit.supply.method</field>
|
||||||
<field name="inherit_id" ref="sf_sale.view_sale_order_form_inherit_sf"/>
|
<field name="inherit_id" ref="sf_sale.view_sale_order_form_inherit_sf"/>
|
||||||
@@ -102,7 +90,5 @@
|
|||||||
<record id="sale.res_partner_menu" model="ir.ui.menu">
|
<record id="sale.res_partner_menu" model="ir.ui.menu">
|
||||||
<field name="groups_id" eval="[(4, ref('sf_base.group_production_engineer'))]"/>
|
<field name="groups_id" eval="[(4, ref('sf_base.group_production_engineer'))]"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -51,5 +51,10 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</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>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -49,8 +49,8 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
|
|||||||
if ro.route_id.routing_type == '表面工艺':
|
if ro.route_id.routing_type == '表面工艺':
|
||||||
domain += [('process_parameters_id', '=', ro.process_parameters_id.id)]
|
domain += [('process_parameters_id', '=', ro.process_parameters_id.id)]
|
||||||
elif ro.route_id.routing_tag == 'special' and ro.is_auto is False:
|
elif ro.route_id.routing_tag == 'special' and ro.is_auto is False:
|
||||||
display_name = ro.route_id.display_name
|
# display_name = ro.route_id.display_name
|
||||||
domain += [('name', 'ilike', display_name)]
|
domain += [('id', '=', ro.id)]
|
||||||
elif ro.panel is not False:
|
elif ro.panel is not False:
|
||||||
domain += [('panel', '=', ro.panel)]
|
domain += [('panel', '=', ro.panel)]
|
||||||
td_upd = self.env['sf.technology.design'].sudo().search(domain)
|
td_upd = self.env['sf.technology.design'].sudo().search(domain)
|
||||||
@@ -62,25 +62,34 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
|
|||||||
for special in special_design:
|
for special in special_design:
|
||||||
workorders_values = []
|
workorders_values = []
|
||||||
if special.active is False:
|
if special.active is False:
|
||||||
|
is_cancel = False
|
||||||
# 工单采购单外协出入库单皆需取消
|
# 工单采购单外协出入库单皆需取消
|
||||||
domain = [('production_id', '=', special.production_id.id)]
|
domain = [('production_id', '=', special.production_id.id)]
|
||||||
if special.process_parameters_id:
|
if special.process_parameters_id:
|
||||||
domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id)]
|
domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id), ('state', '!=', 'cancel')]
|
||||||
else:
|
else:
|
||||||
domain += [('name', '=', special.route_id.name)]
|
domain += [('technology_design_id', '=', special.id), ('state', '!=', 'cancel')]
|
||||||
workorder = self.env['mrp.workorder'].search(domain)
|
workorder = self.env['mrp.workorder'].search(domain)
|
||||||
if workorder.state != 'cancel':
|
# previous_workorder = self.env['mrp.workorder'].search(
|
||||||
workorder.write({'state': 'cancel'})
|
# [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'),
|
||||||
workorder.picking_ids.write({'state': 'cancel'})
|
# ('production_id', '=', workorder.production_id.id)])
|
||||||
workorder.picking_ids.move_ids.write({'state': 'cancel'})
|
# if previous_workorder:
|
||||||
purchase_order = self.env['purchase.order'].search(
|
# if previous_workorder.supplier_id != workorder.supplier_id:
|
||||||
[('origin', '=', workorder.production_id.origin)])
|
# is_cancel = True
|
||||||
for line in purchase_order.order_line:
|
# else:
|
||||||
if line.product_id.server_product_process_parameters_id == workorder.surface_technics_parameters_id:
|
# is_cancel = True
|
||||||
purchase_order.write({'state': 'cancel'})
|
# if workorder.state != 'cancel' and is_cancel is True:
|
||||||
|
# workorder.write({'state': 'cancel'})
|
||||||
|
# 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.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'})
|
||||||
else:
|
else:
|
||||||
workorder = self.env['mrp.workorder'].search(
|
workorder = self.env['mrp.workorder'].search(
|
||||||
[('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id)])
|
[('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id), ('state', '!=', 'cancel')])
|
||||||
if not workorder:
|
if not workorder:
|
||||||
if special.route_id.routing_type == '表面工艺':
|
if special.route_id.routing_type == '表面工艺':
|
||||||
product_production_process = self.env['product.template'].search(
|
product_production_process = self.env['product.template'].search(
|
||||||
@@ -95,19 +104,23 @@ class ProductionTechnologyReAdjustWizard(models.TransientModel):
|
|||||||
self.env['mrp.workorder'].json_workorder_str(special.production_id, special))
|
self.env['mrp.workorder'].json_workorder_str(special.production_id, special))
|
||||||
special.production_id.write({'workorder_ids': workorders_values})
|
special.production_id.write({'workorder_ids': workorders_values})
|
||||||
else:
|
else:
|
||||||
|
logging.info(workorder.blocked_by_workorder_ids)
|
||||||
if len(workorder.blocked_by_workorder_ids) > 1:
|
if len(workorder.blocked_by_workorder_ids) > 1:
|
||||||
if workorder.sequence == 1:
|
if workorder.sequence == 1:
|
||||||
workorder.blocked_by_workorder_ids = None
|
workorder.blocked_by_workorder_ids = None
|
||||||
else:
|
else:
|
||||||
workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0]
|
if workorder.blocked_by_workorder_ids:
|
||||||
|
workorder.blocked_by_workorder_ids = workorder.blocked_by_workorder_ids[0]
|
||||||
productions._reset_work_order_sequence()
|
productions._reset_work_order_sequence()
|
||||||
if self.production_id.product_id.categ_id.type == '成品':
|
# 退回时不对外协出入库单和采购单做处理
|
||||||
productions._reset_subcontract_pick_purchase()
|
# if self.production_id.product_id.categ_id.type == '成品':
|
||||||
productions.get_subcontract_pick_purchase()
|
# productions._reset_subcontract_pick_purchase()
|
||||||
|
# productions.get_subcontract_pick_purchase()
|
||||||
productions.is_adjust = True
|
productions.is_adjust = True
|
||||||
for item in productions:
|
for item in productions:
|
||||||
workorders = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted(
|
workorders = item.workorder_ids.filtered(lambda wo: wo.state not in ('cancel')).sorted(
|
||||||
key=lambda a: a.sequence)
|
key=lambda a: a.sequence)
|
||||||
if workorders[0].state in ['pending']:
|
if workorders[0].state in ['pending']:
|
||||||
if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
if workorders[
|
||||||
|
0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
||||||
workorders[0].state = 'waiting'
|
workorders[0].state = 'waiting'
|
||||||
|
|||||||
@@ -53,9 +53,59 @@ class ProductionTechnologyWizard(models.TransientModel):
|
|||||||
td_upd = self.env['sf.technology.design'].sudo().search(domain)
|
td_upd = self.env['sf.technology.design'].sudo().search(domain)
|
||||||
if td_upd:
|
if td_upd:
|
||||||
ro.write({'sequence': td_upd.sequence, 'active': td_upd.active})
|
ro.write({'sequence': td_upd.sequence, 'active': td_upd.active})
|
||||||
# special = production.technology_design_ids.filtered(
|
special_design = self.env['sf.technology.design'].sudo().search(
|
||||||
# lambda td: td.is_auto is False and td.process_parameters_id is not False)
|
[('routing_tag', '=', 'special'), ('production_id', '=', production.id),
|
||||||
# # if special:
|
('is_auto', '=', False), ('active', 'in', [True, False])])
|
||||||
|
for special in special_design:
|
||||||
|
workorders_values = []
|
||||||
|
if special.active is False:
|
||||||
|
# is_cancel = False
|
||||||
|
# 工单采购单外协出入库单皆需取消
|
||||||
|
domain = [('production_id', '=', special.production_id.id)]
|
||||||
|
if special.process_parameters_id:
|
||||||
|
domain += [('surface_technics_parameters_id', '=', special.process_parameters_id.id), ('state', '!=', 'cancel')]
|
||||||
|
else:
|
||||||
|
domain += [('technology_design_id', '=', special.id), ('state', '!=', 'cancel')]
|
||||||
|
workorder = self.env['mrp.workorder'].search(domain)
|
||||||
|
# previous_workorder = self.env['mrp.workorder'].search(
|
||||||
|
# [('sequence', '=', workorder.sequence - 1), ('routing_type', '=', '表面工艺'),
|
||||||
|
# ('production_id', '=', workorder.production_id.id)])
|
||||||
|
# if previous_workorder:
|
||||||
|
# if previous_workorder.supplier_id != workorder.supplier_id:
|
||||||
|
# is_cancel = True
|
||||||
|
# if workorder.state != 'cancel' and is_cancel is True:
|
||||||
|
workorder.write({'state': 'cancel'})
|
||||||
|
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.name), ('purchase_type', '=', 'consignment')])
|
||||||
|
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'})
|
||||||
|
else:
|
||||||
|
if special.production_id.workorder_ids:
|
||||||
|
workorder = self.env['mrp.workorder'].search(
|
||||||
|
[('technology_design_id', '=', special.id), ('production_id', '=', special.production_id.id), ('state', '!=', 'cancel')])
|
||||||
|
if not workorder:
|
||||||
|
if special.route_id.routing_type == '表面工艺':
|
||||||
|
product_production_process = self.env['product.template'].search(
|
||||||
|
[('server_product_process_parameters_id', '=', special.process_parameters_id.id)])
|
||||||
|
workorders_values.append(
|
||||||
|
self.env[
|
||||||
|
'mrp.workorder']._json_workorder_surface_process_str(special.production_id, special,
|
||||||
|
product_production_process.seller_ids[
|
||||||
|
0].partner_id.id))
|
||||||
|
else:
|
||||||
|
workorders_values.append(
|
||||||
|
self.env['mrp.workorder'].json_workorder_str(special.production_id, special))
|
||||||
|
special.production_id.write({'workorder_ids': workorders_values})
|
||||||
|
else:
|
||||||
|
if len(workorder.blocked_by_workorder_ids) > 1:
|
||||||
|
if workorder.sequence == 1:
|
||||||
|
workorder.blocked_by_workorder_ids = None
|
||||||
|
else:
|
||||||
|
if workorder.blocked_by_workorder_ids:
|
||||||
|
workorder.blocked_by_workorder_ids = blocked_by_workorder_ids[0]
|
||||||
productions._create_workorder(False)
|
productions._create_workorder(False)
|
||||||
if self.production_id.product_id.categ_id.type == '成品':
|
if self.production_id.product_id.categ_id.type == '成品':
|
||||||
productions.get_subcontract_pick_purchase()
|
productions.get_subcontract_pick_purchase()
|
||||||
@@ -65,4 +115,4 @@ class ProductionTechnologyWizard(models.TransientModel):
|
|||||||
key=lambda a: a.sequence)
|
key=lambda a: a.sequence)
|
||||||
if workorder[0].state in ['pending']:
|
if workorder[0].state in ['pending']:
|
||||||
if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
if workorder[0].production_id.product_id.categ_id.type == '成品' and item.programming_state != '已编程':
|
||||||
workorders[0].state = 'waiting'
|
workorder[0].state = 'waiting'
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import logging
|
|||||||
from odoo.exceptions import UserError, ValidationError
|
from odoo.exceptions import UserError, ValidationError
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from odoo import models, api, fields, _
|
from odoo import models, api, fields, _
|
||||||
|
from odoo.tools import groupby
|
||||||
|
|
||||||
|
|
||||||
class ReworkWizard(models.TransientModel):
|
class ReworkWizard(models.TransientModel):
|
||||||
@@ -37,6 +38,30 @@ class ReworkWizard(models.TransientModel):
|
|||||||
|
|
||||||
tool_state = fields.Selection(string='功能刀具状态', related='production_id.tool_state')
|
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):
|
def confirm(self):
|
||||||
if self.routing_type in ['装夹预调', 'CNC加工']:
|
if self.routing_type in ['装夹预调', 'CNC加工']:
|
||||||
self.is_clamp_measure = False
|
self.is_clamp_measure = False
|
||||||
@@ -57,8 +82,17 @@ class ReworkWizard(models.TransientModel):
|
|||||||
# 限制判断
|
# 限制判断
|
||||||
# 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工
|
# 1、当制造订单内ZM面的工单都已完成时,返工勾选工序时只能勾选上ZM面的所有工序进行返工
|
||||||
# 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选
|
# 2、当FM工单在CNC工单进行选择返工,并将已全部完成的ZM面工序全部勾选上时,FM工单上所有的已完成的工单(装夹预调工单)也必须进行勾选
|
||||||
done_panel_workorder_ids = self.workorder_ids.filtered(
|
# 获取已完成的标准工单
|
||||||
lambda w: w.state == 'done' and w.processing_panel is not False)
|
# 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:
|
else:
|
||||||
raise ValidationError('请选择返工工单!!!')
|
raise ValidationError('请选择返工工单!!!')
|
||||||
if rework_workorder_ids:
|
if rework_workorder_ids:
|
||||||
|
|||||||
@@ -32,6 +32,12 @@ class Sf_Mrs_Connect(http.Controller, MultiInheritController):
|
|||||||
domain += [('state', 'in', ['confirmed', 'pending_cam'])]
|
domain += [('state', 'in', ['confirmed', 'pending_cam'])]
|
||||||
productions = request.env['mrp.production'].with_user(
|
productions = request.env['mrp.production'].with_user(
|
||||||
request.env.ref("base.user_admin")).search(domain)
|
request.env.ref("base.user_admin")).search(domain)
|
||||||
|
productions_technology_to_confirmed = request.env['mrp.production'].with_user(
|
||||||
|
request.env.ref("base.user_admin")).search(
|
||||||
|
[('programming_no', '=', ret['programming_no']), ('state', 'in', ['technology_to_confirmed'])])
|
||||||
|
if productions_technology_to_confirmed:
|
||||||
|
res = {'status': -2, 'message': '查询到待工艺确认的制造订单'}
|
||||||
|
return json.JSONEncoder().encode(res)
|
||||||
if productions:
|
if productions:
|
||||||
# 拉取所有加工面的程序文件
|
# 拉取所有加工面的程序文件
|
||||||
for r in ret['processing_panel'].split(','):
|
for r in ret['processing_panel'].split(','):
|
||||||
|
|||||||
@@ -231,26 +231,39 @@ class sf_production_plan(models.Model):
|
|||||||
if not record.production_line_id:
|
if not record.production_line_id:
|
||||||
raise ValidationError("未选择生产线")
|
raise ValidationError("未选择生产线")
|
||||||
else:
|
else:
|
||||||
|
# 自动化产线加工
|
||||||
if record.production_id.workorder_ids:
|
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 record.production_id.production_type == '自动化产线加工':
|
||||||
if item.name == 'CNC加工':
|
# 找到第一张CNC加工工单
|
||||||
# 将同一个面的所有工单筛选出来
|
first_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[0]
|
||||||
workorder_list = record.production_id.workorder_ids.filtered(lambda x: x.processing_panel == item.processing_panel)
|
date_start = record.date_planned_start if record.date_planned_start else datetime.now()
|
||||||
routing_workcenter = record.env['mrp.routing.workcenter'].sudo().search(
|
routing_workcenter = first_cnc_workorder.technology_design_id.route_id
|
||||||
[('name', '=', 'CNC加工')], limit=1)
|
# 设置一个小的开始时间
|
||||||
# 设置一个小的开始时间
|
first_cnc_workorder.date_planned_start = datetime.now() - timedelta(days=100)
|
||||||
item.date_planned_start = datetime.now() - timedelta(days=100)
|
first_cnc_workorder.date_planned_finished = date_start + timedelta(
|
||||||
item.date_planned_finished = last_cnc_start + timedelta(
|
minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
|
||||||
minutes=routing_workcenter.time_cycle)
|
first_cnc_workorder.date_planned_start = date_start
|
||||||
item.date_planned_start = last_cnc_start
|
record.sudo().production_id.plan_start_processing_time = first_cnc_workorder.date_planned_start
|
||||||
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
|
first_cnc_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
|
||||||
item.duration_expected = routing_workcenter.time_cycle
|
record.calculate_plan_time(first_cnc_workorder, record.production_id.workorder_ids)
|
||||||
pre_duration , next_duration = record.calculate_plan_time(item, workorder_list)
|
# 找到最后一张CNC加工工单
|
||||||
record.date_planned_finished = item.date_planned_finished
|
last_cnc_workorder = record.production_id.workorder_ids.filtered(lambda x: x.name == 'CNC加工')[-1]
|
||||||
# 计算下一个cnc工单的开始时间
|
record.date_planned_finished = last_cnc_workorder.date_planned_finished
|
||||||
last_cnc_start = workorder_list[-1].date_planned_finished + timedelta(minutes=pre_duration)
|
else:
|
||||||
# 没有工单也能排程
|
# 人工线下加工只排第一张工单
|
||||||
|
item = record.production_id.workorder_ids[0]
|
||||||
|
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 = 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 + 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.state = 'done'
|
||||||
# record.production_id.schedule_state = '已排'
|
# record.production_id.schedule_state = '已排'
|
||||||
record.sudo().production_id.schedule_state = '已排'
|
record.sudo().production_id.schedule_state = '已排'
|
||||||
@@ -306,44 +319,40 @@ class sf_production_plan(models.Model):
|
|||||||
def calculate_plan_time(self, item, workorder_list):
|
def calculate_plan_time(self, item, workorder_list):
|
||||||
"""
|
"""
|
||||||
根据CNC工单的时间去计算之前的其他工单的开始结束时间
|
根据CNC工单的时间去计算之前的其他工单的开始结束时间
|
||||||
|
param:
|
||||||
|
item: 基准工单(根据该工单的开始结束时间去计算其他工单的开始结束时间)
|
||||||
|
workorder_list: 需排程的工单列表
|
||||||
"""
|
"""
|
||||||
item_position = 0
|
item_position = 0
|
||||||
for index, workorder in enumerate(workorder_list):
|
for index, workorder in enumerate(workorder_list):
|
||||||
if workorder.id == item.id:
|
if workorder.id == item.id:
|
||||||
item_position = index
|
item_position = index
|
||||||
break
|
break
|
||||||
routing_workcenters = self.env['mrp.routing.workcenter'].sudo().search([])
|
|
||||||
# 记录所有前序工序时长
|
|
||||||
previous_workorder_duration = 0
|
|
||||||
for i in range(item_position, -1, -1):
|
for i in range(item_position, -1, -1):
|
||||||
if i < 1:
|
if i < 1:
|
||||||
break
|
break
|
||||||
current_workorder = workorder_list[i]
|
current_workorder = workorder_list[i]
|
||||||
next_workorder = workorder_list[i - 1]
|
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_start = datetime.now() - timedelta(days=100)
|
||||||
next_workorder.date_planned_finished = current_workorder.date_planned_start
|
next_workorder.date_planned_finished = current_workorder.date_planned_start
|
||||||
next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta(
|
next_workorder.date_planned_start = next_workorder.date_planned_finished - timedelta(
|
||||||
minutes=routing_workcenter.time_cycle)
|
minutes=routing_workcenter.time_cycle + routing_workcenter.reserved_duration)
|
||||||
next_workorder.duration_expected = routing_workcenter.time_cycle
|
next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
|
||||||
previous_workorder_duration += routing_workcenter.time_cycle
|
|
||||||
# 记录所有后续工序时长
|
|
||||||
next_workorder_duration = 0
|
|
||||||
for i in range(item_position, len(workorder_list) - 1):
|
for i in range(item_position, len(workorder_list) - 1):
|
||||||
if i > len(workorder_list) - 1:
|
if i > len(workorder_list) - 1:
|
||||||
break
|
break
|
||||||
current_workorder = workorder_list[i]
|
current_workorder = workorder_list[i]
|
||||||
next_workorder = workorder_list[i + 1]
|
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_start = datetime.now() - timedelta(days=100)
|
||||||
next_workorder.date_planned_finished = current_workorder.date_planned_finished + timedelta(
|
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.date_planned_start = current_workorder.date_planned_finished
|
||||||
next_workorder.duration_expected = routing_workcenter.time_cycle
|
next_workorder.duration_expected = routing_workcenter.time_cycle + routing_workcenter.reserved_duration
|
||||||
next_workorder_duration += routing_workcenter.time_cycle
|
|
||||||
return previous_workorder_duration, next_workorder_duration
|
|
||||||
|
|
||||||
def calculate_plan_time_after(self, item, workorder_id_list):
|
def calculate_plan_time_after(self, item, workorder_id_list):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -15907,7 +15907,7 @@ msgstr "内部参考"
|
|||||||
#: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view
|
#: model_terms:ir.ui.view,arch_db:account.account_journal_dashboard_kanban_view
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Internal Transfer"
|
msgid "Internal Transfer"
|
||||||
msgstr "内部转账"
|
msgstr "厂内出入库"
|
||||||
|
|
||||||
#. module: account
|
#. module: account
|
||||||
#: model:ir.model.fields,field_description:account.field_res_config_settings__transfer_account_id
|
#: model:ir.model.fields,field_description:account.field_res_config_settings__transfer_account_id
|
||||||
@@ -16133,7 +16133,7 @@ msgstr "库存概览"
|
|||||||
#. module: stock
|
#. module: stock
|
||||||
#: model:ir.actions.act_window,name:stock.stock_picking_type_action
|
#: model:ir.actions.act_window,name:stock.stock_picking_type_action
|
||||||
msgid "Internal Transfers"
|
msgid "Internal Transfers"
|
||||||
msgstr "厂内出入库"
|
msgstr "库存概览"
|
||||||
|
|
||||||
#. module: stock
|
#. module: stock
|
||||||
#: model:ir.model.fields,field_description:stock.field_stock_quant__inventory_quantity_set
|
#: model:ir.model.fields,field_description:stock.field_stock_quant__inventory_quantity_set
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ access_quality_point_group_sf_mrp_manager,quality_point_group_sf_mrp_manager,qua
|
|||||||
access_quality_check_group_quality,quality_check_group_quality,quality.model_quality_check,sf_base.group_quality,1,1,1,0
|
access_quality_check_group_quality,quality_check_group_quality,quality.model_quality_check,sf_base.group_quality,1,1,1,0
|
||||||
access_quality_check_group_quality_director,quality_check_group_quality_director,quality.model_quality_check,sf_base.group_quality_director,1,1,1,0
|
access_quality_check_group_quality_director,quality_check_group_quality_director,quality.model_quality_check,sf_base.group_quality_director,1,1,1,0
|
||||||
access_quality_check_group_plan_dispatch,quality_check_group_plan_dispatch,quality.model_quality_check,sf_base.group_plan_dispatch,1,0,0,0
|
access_quality_check_group_plan_dispatch,quality_check_group_plan_dispatch,quality.model_quality_check,sf_base.group_plan_dispatch,1,0,0,0
|
||||||
|
access_quality_check_group_sf_stock_user,quality_check_group_sf_stock_user,quality.model_quality_check,sf_base.group_sf_stock_user,1,0,0,0
|
||||||
access_quality_check_group_plan_director,quality_check_group_plan_director,quality.model_quality_check,sf_base.group_plan_director,1,0,0,0
|
access_quality_check_group_plan_director,quality_check_group_plan_director,quality.model_quality_check,sf_base.group_plan_director,1,0,0,0
|
||||||
access_quality_check_group_purchase,quality_check_group_purchase,quality.model_quality_check,sf_base.group_purchase,1,0,0,0
|
access_quality_check_group_purchase,quality_check_group_purchase,quality.model_quality_check,sf_base.group_purchase,1,0,0,0
|
||||||
access_quality_check_group_purchase_director,quality_check_group_purchase_director,quality.model_quality_check,sf_base.group_purchase_director,1,0,0,0
|
access_quality_check_group_purchase_director,quality_check_group_purchase_director,quality.model_quality_check,sf_base.group_purchase_director,1,0,0,0
|
||||||
|
|||||||
|
@@ -247,41 +247,27 @@ class RePurchaseOrder(models.Model):
|
|||||||
raise UserError('请对【产品】中的【税】进行选择')
|
raise UserError('请对【产品】中的【税】进行选择')
|
||||||
|
|
||||||
def get_purchase_order(self, consecutive_process_parameters, production, product_id_to_production_names):
|
def get_purchase_order(self, consecutive_process_parameters, production, product_id_to_production_names):
|
||||||
server_product_process = []
|
|
||||||
production_process = product_id_to_production_names.get(
|
|
||||||
production.product_id.id)
|
|
||||||
for pp in consecutive_process_parameters:
|
for pp in consecutive_process_parameters:
|
||||||
server_template = self.env['product.template'].search(
|
server_product_process = []
|
||||||
[('server_product_process_parameters_id', '=', pp.surface_technics_parameters_id.id),
|
purchase_order = pp._get_surface_technics_purchase_ids()
|
||||||
('detailed_type', '=', 'service')])
|
if purchase_order:
|
||||||
purchase_order_line = self.env['purchase.order.line'].search(
|
purchase_order.write({'state': 'draft'})
|
||||||
[('product_id', '=', server_template.product_variant_id.id),
|
else:
|
||||||
('product_qty', '=', len(production_process))], limit=1, order='id desc')
|
server_template = self.env['product.template'].search(
|
||||||
if not purchase_order_line:
|
[('server_product_process_parameters_id', '=', pp.surface_technics_parameters_id.id),
|
||||||
|
('detailed_type', '=', 'service')])
|
||||||
server_product_process.append((0, 0, {
|
server_product_process.append((0, 0, {
|
||||||
'product_id': server_template.product_variant_id.id,
|
'product_id': server_template.product_variant_id.id,
|
||||||
'product_qty': len(production_process),
|
'product_qty': 1,
|
||||||
'product_uom': server_template.uom_id.id
|
'product_uom': server_template.uom_id.id
|
||||||
}))
|
}))
|
||||||
else:
|
purchase_order = self.env['purchase.order'].sudo().create({
|
||||||
if production.name in production_process:
|
'partner_id': server_template.seller_ids[0].partner_id.id,
|
||||||
purchase_order = self.env['purchase.order'].search(
|
'origin': production.name,
|
||||||
[('state', '=', 'draft'), ('origin', '=', ','.join(production_process)),
|
'state': 'draft',
|
||||||
('purchase_type', '=', 'consignment')])
|
'purchase_type': 'consignment',
|
||||||
if not purchase_order:
|
'order_line': server_product_process})
|
||||||
server_product_process.append((0, 0, {
|
pp.purchase_id = [(6, 0, [purchase_order.id])]
|
||||||
'product_id': server_template.product_variant_id.id,
|
|
||||||
'product_qty': len(production_process),
|
|
||||||
'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,
|
|
||||||
'origin': ','.join(production_process),
|
|
||||||
'state': 'draft',
|
|
||||||
'purchase_type': 'consignment',
|
|
||||||
'order_line': server_product_process})
|
|
||||||
# self.env.cr.commit()
|
# self.env.cr.commit()
|
||||||
|
|
||||||
@api.onchange('order_line')
|
@api.onchange('order_line')
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ access_sf_detection_result_group_sale_director,sf_detection_result_group_sale_di
|
|||||||
access_stock_scrap_group_sale_salemanager,stock_scrap_group_sale_salemanager,stock.model_stock_scrap,sf_base.group_sale_salemanager,1,0,0,0
|
access_stock_scrap_group_sale_salemanager,stock_scrap_group_sale_salemanager,stock.model_stock_scrap,sf_base.group_sale_salemanager,1,0,0,0
|
||||||
access_stock_scrap_group_sale_director,stock_scrap_group_sale_director,stock.model_stock_scrap,sf_base.group_sale_director,1,0,0,0
|
access_stock_scrap_group_sale_director,stock_scrap_group_sale_director,stock.model_stock_scrap,sf_base.group_sale_director,1,0,0,0
|
||||||
|
|
||||||
|
access_account_move_group_plan_dispatch,account_move_group_plan_dispatch,account.model_account_move,sf_base.group_plan_dispatch,1,1,1,0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
|
@@ -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>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
'data': [
|
'data': [
|
||||||
# 'security/ir.model.access.csv',
|
# 'security/ir.model.access.csv',
|
||||||
'views/stock_picking.xml',
|
'views/stock_picking.xml',
|
||||||
'views/stock_product_template.xml'
|
'views/stock_product_template.xml',
|
||||||
],
|
],
|
||||||
# only loaded in demonstration mode
|
# only loaded in demonstration mode
|
||||||
'demo': [
|
'demo': [
|
||||||
|
|||||||
@@ -221,5 +221,6 @@ class MrpProduction(models.Model):
|
|||||||
logging.info('调用CAM工单程序用刀计划创建方法!!!')
|
logging.info('调用CAM工单程序用刀计划创建方法!!!')
|
||||||
self.env['sf.cam.work.order.program.knife.plan'].sudo().create_cam_work_plan(cnc_ids)
|
self.env['sf.cam.work.order.program.knife.plan'].sudo().create_cam_work_plan(cnc_ids)
|
||||||
if not invalid_tool and not missing_tool_1:
|
if not invalid_tool and not missing_tool_1:
|
||||||
|
self.sudo().write({'tool_state': '0'})
|
||||||
logging.info('校验cnc用刀正常!!!')
|
logging.info('校验cnc用刀正常!!!')
|
||||||
logging.info('工单cnc程序用刀校验完成!!!')
|
logging.info('工单cnc程序用刀校验完成!!!')
|
||||||
|
|||||||
@@ -602,7 +602,7 @@ var GanttRow = Widget.extend({
|
|||||||
// pill._color = self._getColor(pill[self.colorField]);
|
// pill._color = self._getColor(pill[self.colorField]);
|
||||||
// 设置pill背景颜色2 修改时间2024年6月25日17:09:43
|
// 设置pill背景颜色2 修改时间2024年6月25日17:09:43
|
||||||
let isDelay = false
|
let isDelay = false
|
||||||
if(pill.state != 'processing' && pill.state != 'finished') { // 判断待加工
|
if(pill.state != 'processing' && pill.state != 'finished' && pill.order_deadline) { // 判断待加工
|
||||||
isDelay = pill.order_deadline.isBefore(new Date())
|
isDelay = pill.order_deadline.isBefore(new Date())
|
||||||
}
|
}
|
||||||
if(isDelay) {
|
if(isDelay) {
|
||||||
|
|||||||
Reference in New Issue
Block a user