Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/制造代码优化
This commit is contained in:
@@ -329,7 +329,7 @@ class ToolInventory(models.Model):
|
|||||||
blade_number = fields.Integer('刃数(个)')
|
blade_number = fields.Integer('刃数(个)')
|
||||||
extension = fields.Float('伸出长度(mm)')
|
extension = fields.Float('伸出长度(mm)')
|
||||||
work_material = fields.Selection([('钢', '钢'), ('铝', '铝')], string='加工材料')
|
work_material = fields.Selection([('钢', '钢'), ('铝', '铝')], string='加工材料')
|
||||||
life_span = fields.Float('寿命(h)')
|
life_span = fields.Float('寿命(min)')
|
||||||
|
|
||||||
tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组')
|
tool_groups_id = fields.Many2one('sf.tool.groups', string='刀具组')
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ access_sf_functional_cutting_tool_admin,sf_functional_cutting_tool_admin,model_s
|
|||||||
access_sf_functional_cutting_tool_model,sf_functional_cutting_tool_model,model_sf_functional_cutting_tool_model,base.group_user,1,1,1,0
|
access_sf_functional_cutting_tool_model,sf_functional_cutting_tool_model,model_sf_functional_cutting_tool_model,base.group_user,1,1,1,0
|
||||||
access_sf_functional_cutting_tool_model_admin,sf_functional_cutting_tool_model_admin,model_sf_functional_cutting_tool_model,base.group_system,1,1,1,0
|
access_sf_functional_cutting_tool_model_admin,sf_functional_cutting_tool_model_admin,model_sf_functional_cutting_tool_model,base.group_system,1,1,1,0
|
||||||
access_sf_fixture_material,sf_fixture_material,model_sf_fixture_material,base.group_user,1,1,1,0
|
access_sf_fixture_material,sf_fixture_material,model_sf_fixture_material,base.group_user,1,1,1,0
|
||||||
|
access_sf_fixture_material_group_sf_stock_user,sf_fixture_material_group_sf_stock_user,model_sf_fixture_material,sf_warehouse.group_sf_stock_user,1,1,1,0
|
||||||
access_sf_fixture_material_admin,sf_fixture_material_admin,model_sf_fixture_material,base.group_system,1,1,1,0
|
access_sf_fixture_material_admin,sf_fixture_material_admin,model_sf_fixture_material,base.group_system,1,1,1,0
|
||||||
access_sf_fixture_materials_basic_parameters,sf_fixture_materials_basic_parameters,model_sf_fixture_materials_basic_parameters,base.group_user,1,1,1,0
|
access_sf_fixture_materials_basic_parameters,sf_fixture_materials_basic_parameters,model_sf_fixture_materials_basic_parameters,base.group_user,1,1,1,0
|
||||||
access_sf_fixture_materials_basic_parameters_admin,sf_fixture_materials_basic_parameters_admin,model_sf_fixture_materials_basic_parameters,base.group_system,1,1,1,0
|
access_sf_fixture_materials_basic_parameters_admin,sf_fixture_materials_basic_parameters_admin,model_sf_fixture_materials_basic_parameters,base.group_system,1,1,1,0
|
||||||
|
|||||||
|
@@ -52,7 +52,7 @@ class Sf_Bf_Connect(http.Controller):
|
|||||||
self_machining_embryo = request.env['product.template'].sudo().no_bom_product_create(
|
self_machining_embryo = request.env['product.template'].sudo().no_bom_product_create(
|
||||||
self_machining_id,
|
self_machining_id,
|
||||||
item,
|
item,
|
||||||
order_id, 'self_machining', i)
|
order_id, 'self_machining', i, product)
|
||||||
# 创建坯料的bom
|
# 创建坯料的bom
|
||||||
self_machining_bom = request.env['mrp.bom'].with_user(
|
self_machining_bom = request.env['mrp.bom'].with_user(
|
||||||
request.env.ref("base.user_admin")).bom_create(
|
request.env.ref("base.user_admin")).bom_create(
|
||||||
@@ -78,7 +78,7 @@ class Sf_Bf_Connect(http.Controller):
|
|||||||
item,
|
item,
|
||||||
order_id,
|
order_id,
|
||||||
'subcontract',
|
'subcontract',
|
||||||
i)
|
i, product)
|
||||||
if outsource_embryo == -3:
|
if outsource_embryo == -3:
|
||||||
res['status'] = -3
|
res['status'] = -3
|
||||||
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
|
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
|
||||||
@@ -105,7 +105,8 @@ class Sf_Bf_Connect(http.Controller):
|
|||||||
purchase_embryo = request.env['product.template'].sudo().no_bom_product_create(purchase_id,
|
purchase_embryo = request.env['product.template'].sudo().no_bom_product_create(purchase_id,
|
||||||
item,
|
item,
|
||||||
order_id,
|
order_id,
|
||||||
'purchase', i)
|
'purchase', i,
|
||||||
|
product)
|
||||||
if purchase_embryo == -3:
|
if purchase_embryo == -3:
|
||||||
res['status'] = -3
|
res['status'] = -3
|
||||||
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
|
res['message'] = '该订单模型的材料型号在您分配的工厂里暂未设置获取方式和供应商,请先配置再进行分配'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<data noupdate="1">
|
<data noupdate="1">
|
||||||
<record id="sequence_routing_workcenter" model="ir.sequence">
|
<record id="sequence_routing_workcenter" model="ir.sequence">
|
||||||
<field name="name">工序编码规则</field>
|
<field name="name">工序编码规则</field>
|
||||||
<field name="code">mrp.routing.workcenter</field>
|
<field name="code">mrp.routing.workcenter</field>
|
||||||
<field name="padding">4</field>
|
<field name="padding">4</field>
|
||||||
@@ -74,12 +74,23 @@
|
|||||||
<field name="active">True</field>
|
<field name="active">True</field>
|
||||||
<field name="sequence">11</field>
|
<field name="sequence">11</field>
|
||||||
</record>
|
</record>
|
||||||
<!-- <record id="route_surface_technology_outsourcing" model="stock.rule">-->
|
<!-- <record id="rule_surface_technology_in" model="stock.rule">-->
|
||||||
<!-- <field name="name">外协出库单</field>-->
|
<!-- <field name="name">外协出库单</field>-->
|
||||||
<!-- <field name="action">push</field>-->
|
<!-- <field name="route_id" ref="route_surface_technology_outsourcing"/>-->
|
||||||
<!-- <field name="pick_type_id" ref="outcontract_picking_out"></field>-->
|
<!--<!– <field name="action">push</field>–>-->
|
||||||
<!-- <field name="location_src_id" ref=""/>-->
|
<!-- <field name="pick_type_id" ref="outcontract_picking_in"/>-->
|
||||||
<!-- <field name="location_dest_id" ref="stock_location_locations_virtual_outcontract"/>-->
|
<!-- <!– <field name="location_src_id" search="[('barcode','=','WH-PREPRODUCTION')]"/>–>-->
|
||||||
|
<!-- <!– <field name="location_dest_id" ref="stock_location_locations_virtual_outcontract"/>–>-->
|
||||||
|
<!-- <!– <field name="active">True</field>–>-->
|
||||||
|
<!-- <!– <field name="sequence">11</field>–>-->
|
||||||
|
<!-- </record>-->
|
||||||
|
<!-- <record id="rule_surface_technology_in" model="stock.rule">-->
|
||||||
|
<!-- <field name="name">外协入库单</field>-->
|
||||||
|
<!-- <field name="route_id" ref="route_surface_technology_outsourcing"/>-->
|
||||||
|
<!-- <field name="action">pull</field>-->
|
||||||
|
<!-- <field name="pick_type_id" ref="outcontract_picking_out"/>-->
|
||||||
|
<!-- <field name="location_src_id" ref="stock_location_locations_virtual_outcontract"/>-->
|
||||||
|
<!-- <field name="location_dest_id" search="[('barcode','=','WH-PREPRODUCTION')]"/>-->
|
||||||
<!-- <field name="active">True</field>-->
|
<!-- <field name="active">True</field>-->
|
||||||
<!-- <field name="sequence">11</field>-->
|
<!-- <field name="sequence">11</field>-->
|
||||||
<!-- </record>-->
|
<!-- </record>-->
|
||||||
|
|||||||
@@ -305,8 +305,8 @@ class MrpProduction(models.Model):
|
|||||||
}]
|
}]
|
||||||
if production.product_id.categ_id.type == '成品':
|
if production.product_id.categ_id.type == '成品':
|
||||||
if production.product_id.id in product_id_to_production_names:
|
if production.product_id.id in product_id_to_production_names:
|
||||||
# 同一个产品多个制造订单对应一个编程单和模型库
|
# # 同一个产品多个制造订单对应一个编程单和模型库
|
||||||
# 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
# # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递
|
||||||
if not production.programming_no:
|
if not production.programming_no:
|
||||||
production_programming = self.search(
|
production_programming = self.search(
|
||||||
[('product_id.id', '=', production.product_id.id), ('origin', '=', production.origin)],
|
[('product_id.id', '=', production.product_id.id), ('origin', '=', production.origin)],
|
||||||
@@ -318,7 +318,7 @@ class MrpProduction(models.Model):
|
|||||||
logging.info('production_programming2:%s' % production_programming.programming_no)
|
logging.info('production_programming2:%s' % production_programming.programming_no)
|
||||||
production.write({'programming_no': production_programming.programming_no,
|
production.write({'programming_no': production_programming.programming_no,
|
||||||
'programming_state': '编程中'})
|
'programming_state': '编程中'})
|
||||||
# 根据加工面板的面数及对应的工序模板生成工单
|
# # 根据加工面板的面数及对应的工序模板生成工单
|
||||||
i = 0
|
i = 0
|
||||||
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
|
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
|
||||||
for k in (production.product_id.model_processing_panel.split(',')):
|
for k in (production.product_id.model_processing_panel.split(',')):
|
||||||
@@ -381,49 +381,6 @@ class MrpProduction(models.Model):
|
|||||||
workorders_values.append(
|
workorders_values.append(
|
||||||
self.env['mrp.workorder'].json_workorder_str('', production, route))
|
self.env['mrp.workorder'].json_workorder_str('', production, route))
|
||||||
production.workorder_ids = workorders_values
|
production.workorder_ids = workorders_values
|
||||||
process_parameter_workorder = self.env['mrp.workorder'].search(
|
|
||||||
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
|
|
||||||
('is_subcontract', '=', True)])
|
|
||||||
if process_parameter_workorder:
|
|
||||||
is_pick = False
|
|
||||||
consecutive_workorders = []
|
|
||||||
m = 0
|
|
||||||
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
|
|
||||||
for i in range(len(sorted_workorders) - 1):
|
|
||||||
if m == 0:
|
|
||||||
is_pick = False
|
|
||||||
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
|
|
||||||
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
|
|
||||||
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
|
|
||||||
if sorted_workorders[i] not in consecutive_workorders:
|
|
||||||
consecutive_workorders.append(sorted_workorders[i])
|
|
||||||
consecutive_workorders.append(sorted_workorders[i + 1])
|
|
||||||
m += 1
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
|
||||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
|
||||||
if sorted_workorders[i] in consecutive_workorders:
|
|
||||||
is_pick = True
|
|
||||||
consecutive_workorders = []
|
|
||||||
m = 0
|
|
||||||
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
|
|
||||||
if is_pick is False:
|
|
||||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production)
|
|
||||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
|
||||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
|
||||||
if sorted_workorders[i] in consecutive_workorders:
|
|
||||||
is_pick = True
|
|
||||||
consecutive_workorders = []
|
|
||||||
m = 0
|
|
||||||
if m == len(consecutive_workorders) - 1 and m != 0:
|
|
||||||
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production)
|
|
||||||
if is_pick is False and m == 0:
|
|
||||||
if len(sorted_workorders) == 1:
|
|
||||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production)
|
|
||||||
else:
|
|
||||||
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production)
|
|
||||||
|
|
||||||
for workorder in production.workorder_ids:
|
for workorder in production.workorder_ids:
|
||||||
workorder.duration_expected = workorder._get_duration_expected()
|
workorder.duration_expected = workorder._get_duration_expected()
|
||||||
|
|
||||||
@@ -449,20 +406,6 @@ class MrpProduction(models.Model):
|
|||||||
'user_id': production.user_id.id}
|
'user_id': production.user_id.id}
|
||||||
return production_values_str
|
return production_values_str
|
||||||
|
|
||||||
def _get_stock_move_values_Res(self, item, location_src_id, location_dest_id, picking_type_id):
|
|
||||||
move_values = {
|
|
||||||
'name': item.name if item.name else '/',
|
|
||||||
'company_id': item.company_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_qty': 1.0,
|
|
||||||
'location_id': location_src_id,
|
|
||||||
'location_dest_id': location_dest_id,
|
|
||||||
'origin': item.origin,
|
|
||||||
'picking_type_id': picking_type_id,
|
|
||||||
}
|
|
||||||
return move_values
|
|
||||||
|
|
||||||
# 工单排序
|
# 工单排序
|
||||||
def _reset_work_order_sequence1(self, k):
|
def _reset_work_order_sequence1(self, k):
|
||||||
sequen = 0
|
sequen = 0
|
||||||
|
|||||||
@@ -109,8 +109,29 @@ 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_in_id = fields.Many2one('stock.picking', string='外协入库单')
|
picking_ids = fields.Many2many('stock.picking', string='外协出入库单')
|
||||||
picking_out_id = fields.Many2one('stock.picking', string='外协出库单')
|
surface_technics_picking_count = fields.Integer("外协出入库", compute='_compute_surface_technics_picking_ids')
|
||||||
|
|
||||||
|
@api.depends('name', 'production_id.name')
|
||||||
|
def _compute_surface_technics_picking_ids(self):
|
||||||
|
for order in self:
|
||||||
|
picking_ids = self.env['stock.picking'].search([('id', 'in', order.picking_ids.ids)])
|
||||||
|
order.surface_technics_picking_count = len(picking_ids)
|
||||||
|
|
||||||
|
def action_view_surface_technics_picking(self):
|
||||||
|
self.ensure_one()
|
||||||
|
action = self.env["ir.actions.actions"]._for_xml_id("stock.action_picking_tree_all")
|
||||||
|
if len(self.picking_ids) > 1:
|
||||||
|
action['domain'] = [('id', 'in', self.picking_ids.ids)]
|
||||||
|
elif self.picking_ids:
|
||||||
|
# action['name'] = '工艺外协'
|
||||||
|
action['res_id'] = self.picking_ids.id
|
||||||
|
action['views'] = [(self.env.ref('stock.view_picking_form').id, 'form')]
|
||||||
|
if 'views' in action:
|
||||||
|
action['views'] += [(state, view) for state, view in action['views'] if view != 'form']
|
||||||
|
action['context'] = dict(self._context, default_origin=self.name)
|
||||||
|
return action
|
||||||
|
|
||||||
supplier_id = fields.Many2one('res.partner', string='外协供应商')
|
supplier_id = fields.Many2one('res.partner', string='外协供应商')
|
||||||
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备')
|
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备')
|
||||||
is_ok = fields.Boolean(string='是否合格')
|
is_ok = fields.Boolean(string='是否合格')
|
||||||
@@ -769,11 +790,21 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
记录开始时间
|
记录开始时间
|
||||||
'''
|
'''
|
||||||
self.date_start = datetime.now()
|
self.date_start = datetime.now()
|
||||||
# 外协出库单,从“正在等待”变为“就绪”状态
|
# 表面工艺外协出库单
|
||||||
if self.is_subcontract is True:
|
if self.routing_type == '表面工艺':
|
||||||
picking_out = self.env['stock.picking'].search([('id', '=', self.picking_out_id.id)])
|
if self.is_subcontract is True:
|
||||||
if picking_out.state == 'confirmed':
|
move_out = self.env['stock.move'].search(
|
||||||
picking_out.write({'state': 'assigned'})
|
[('location_id', '=', self.env['stock.location'].search(
|
||||||
|
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||||
|
('location_dest_id', '=', self.env.ref(
|
||||||
|
'sf_manufacturing.stock_location_locations_virtual_outcontract').id),
|
||||||
|
('origin', '=', self.production_id.name)])
|
||||||
|
purchase = self.env['purchase.order'].search([('origin', '=', self.production_id.name)])
|
||||||
|
if purchase and move_out:
|
||||||
|
move_out.write({'state': 'assigned'})
|
||||||
|
self.env['stock.move.line'].create(move_out.get_move_line(purchase, self))
|
||||||
|
|
||||||
|
# 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':
|
||||||
self.move_raw_ids = self.production_id.move_raw_ids
|
self.move_raw_ids = self.production_id.move_raw_ids
|
||||||
self.move_raw_ids[0].write({
|
self.move_raw_ids[0].write({
|
||||||
@@ -852,29 +883,32 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
记录结束时间
|
记录结束时间
|
||||||
'''
|
'''
|
||||||
record.date_finished = datetime.now()
|
record.date_finished = datetime.now()
|
||||||
|
if record.routing_type == '表面工艺':
|
||||||
if record.picking_out_id:
|
if record.picking_ids[0]:
|
||||||
picking_out = record.env['stock.picking'].search([('id', '=', record.picking_out_id.id)])
|
picking_out = record.env['stock.move.line'].search(
|
||||||
if picking_out.workorder_out_id:
|
[('picking_id', '=', record.picking_ids[0].id), ('workorder_id', '=', record.id)])
|
||||||
order_line_ids = []
|
if picking_out:
|
||||||
for item in picking_out.workorder_out_id:
|
order_line_ids = []
|
||||||
server_product = record.env['product.template'].search(
|
for item in picking_out.workorder_id:
|
||||||
[('server_product_process_parameters_id', '=', item.surface_technics_parameters_id.id),
|
server_product = self.env['product.template'].search(
|
||||||
('detailed_type', '=', 'service')])
|
[('server_product_process_parameters_id', '=', item.surface_technics_parameters_id.id),
|
||||||
if server_product:
|
('detailed_type', '=', 'service')])
|
||||||
order_line_ids.append((0, 0, {
|
if server_product:
|
||||||
'product_id': server_product.product_variant_id.id,
|
order_line_ids.append((0, 0, {
|
||||||
'product_qty': 1,
|
'product_id': server_product.product_variant_id.id,
|
||||||
'product_uom': server_product.uom_id.id
|
'product_qty': 1,
|
||||||
}))
|
'origin': record.production_id.name,
|
||||||
else:
|
'product_uom': server_product.uom_id.id
|
||||||
raise UserError(
|
}))
|
||||||
'请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
|
else:
|
||||||
record.env['purchase.order'].create({
|
raise UserError(
|
||||||
'partner_id': server_product.seller_ids.partner_id.id,
|
'请先在产品中配置表面工艺为%s相关的外协服务产品' % item.surface_technics_parameters_id.name)
|
||||||
'state': 'draft',
|
if order_line_ids:
|
||||||
'order_line': order_line_ids,
|
self.env['purchase.order'].create({
|
||||||
})
|
'partner_id': server_product.seller_ids.partner_id.id,
|
||||||
|
'state': 'draft',
|
||||||
|
'order_line': order_line_ids,
|
||||||
|
})
|
||||||
tem_date_planned_finished = record.date_planned_finished
|
tem_date_planned_finished = record.date_planned_finished
|
||||||
super().button_finish()
|
super().button_finish()
|
||||||
record.write({
|
record.write({
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ import os
|
|||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
from odoo.modules import get_resource_path
|
from odoo.modules import get_resource_path
|
||||||
|
|
||||||
|
|
||||||
from OCC.Extend.DataExchange import read_step_file
|
from OCC.Extend.DataExchange import read_step_file
|
||||||
from OCC.Extend.DataExchange import write_stl_file
|
from OCC.Extend.DataExchange import write_stl_file
|
||||||
|
|
||||||
@@ -660,8 +658,12 @@ class ResProductMo(models.Model):
|
|||||||
return attachment
|
return attachment
|
||||||
|
|
||||||
# 创建坯料
|
# 创建坯料
|
||||||
def no_bom_product_create(self, product_id, item, order_id, route_type, i):
|
def no_bom_product_create(self, product_id, item, order_id, route_type, i, finish_product):
|
||||||
no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
||||||
|
# if finish_product.model_process_parameters_ids:
|
||||||
|
# surface_technology = self.env['stock.route'].sudo().search([('name', '=', '表面工艺外协')])
|
||||||
|
# if surface_technology:
|
||||||
|
# no_bom_copy_product_id.route_ids |= surface_technology
|
||||||
no_bom_copy_product_id.product_tmpl_id.active = True
|
no_bom_copy_product_id.product_tmpl_id.active = True
|
||||||
materials_id = self.env['sf.production.materials'].search(
|
materials_id = self.env['sf.production.materials'].search(
|
||||||
[('materials_no', '=', item['texture_code'])])
|
[('materials_no', '=', item['texture_code'])])
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ class StockRule(models.Model):
|
|||||||
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
productions = self.env['mrp.production'].with_user(SUPERUSER_ID).sudo().with_company(company_id).create(
|
||||||
productions_values)
|
productions_values)
|
||||||
|
|
||||||
self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
|
||||||
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||||
'''
|
'''
|
||||||
创建工单
|
创建工单
|
||||||
@@ -213,6 +213,52 @@ class StockRule(models.Model):
|
|||||||
(
|
(
|
||||||
p.move_dest_ids.procure_method != 'make_to_order' and not
|
p.move_dest_ids.procure_method != 'make_to_order' and not
|
||||||
p.move_raw_ids and not p.workorder_ids)).action_confirm()
|
p.move_raw_ids and not p.workorder_ids)).action_confirm()
|
||||||
|
for production_item in productions:
|
||||||
|
process_parameter_workorder = self.env['mrp.workorder'].search(
|
||||||
|
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_item.id),
|
||||||
|
('is_subcontract', '=', True)])
|
||||||
|
if process_parameter_workorder:
|
||||||
|
is_pick = False
|
||||||
|
consecutive_workorders = []
|
||||||
|
m = 0
|
||||||
|
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
|
||||||
|
for i in range(len(sorted_workorders) - 1):
|
||||||
|
if m == 0:
|
||||||
|
is_pick = False
|
||||||
|
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
|
||||||
|
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
|
||||||
|
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
|
||||||
|
if sorted_workorders[i] not in consecutive_workorders:
|
||||||
|
consecutive_workorders.append(sorted_workorders[i])
|
||||||
|
consecutive_workorders.append(sorted_workorders[i + 1])
|
||||||
|
m += 1
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||||
|
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||||
|
production_item)
|
||||||
|
if sorted_workorders[i] in consecutive_workorders:
|
||||||
|
is_pick = True
|
||||||
|
consecutive_workorders = []
|
||||||
|
m = 0
|
||||||
|
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
|
||||||
|
if is_pick is False:
|
||||||
|
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
|
||||||
|
production_item)
|
||||||
|
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||||
|
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
|
||||||
|
production_item)
|
||||||
|
if sorted_workorders[i] in consecutive_workorders:
|
||||||
|
is_pick = True
|
||||||
|
consecutive_workorders = []
|
||||||
|
m = 0
|
||||||
|
if m == len(consecutive_workorders) - 1 and m != 0:
|
||||||
|
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production_item)
|
||||||
|
if is_pick is False and m == 0:
|
||||||
|
if len(sorted_workorders) == 1:
|
||||||
|
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item)
|
||||||
|
else:
|
||||||
|
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production_item)
|
||||||
|
|
||||||
for production in productions:
|
for production in productions:
|
||||||
'''
|
'''
|
||||||
@@ -425,12 +471,24 @@ class ProductionLot(models.Model):
|
|||||||
# 'target': 'self',
|
# 'target': 'self',
|
||||||
# }
|
# }
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
for vals in vals_list:
|
||||||
|
if vals.get('rfid'):
|
||||||
|
lots = self.env['stock.lot'].search([('rfid', '=', vals['rfid'])])
|
||||||
|
if lots:
|
||||||
|
for lot in lots:
|
||||||
|
raise ValidationError('Rfid【%s】已被序列号为【%s】的【%s】产品占用!' % (
|
||||||
|
lot.rfid, lot.name, lot.product_id.name))
|
||||||
|
records = super(ProductionLot, self).create(vals_list)
|
||||||
|
return records
|
||||||
|
|
||||||
|
|
||||||
class StockPicking(models.Model):
|
class StockPicking(models.Model):
|
||||||
_inherit = 'stock.picking'
|
_inherit = 'stock.picking'
|
||||||
|
|
||||||
workorder_in_id = fields.One2many('mrp.workorder', 'picking_in_id')
|
# workorder_in_id = fields.One2many('mrp.workorder', 'picking_in_id')
|
||||||
workorder_out_id = fields.One2many('mrp.workorder', 'picking_out_id')
|
# workorder_out_id = fields.One2many('mrp.workorder', 'picking_out_id')
|
||||||
|
|
||||||
# 设置外协出入单的名称
|
# 设置外协出入单的名称
|
||||||
def _get_name_Res(self, rescode):
|
def _get_name_Res(self, rescode):
|
||||||
@@ -444,47 +502,56 @@ class StockPicking(models.Model):
|
|||||||
return '%s%s' % (rescode, num)
|
return '%s%s' % (rescode, num)
|
||||||
|
|
||||||
def button_validate(self):
|
def button_validate(self):
|
||||||
# 出库单验证
|
move_out = self.env['stock.move'].search(
|
||||||
if self.workorder_out_id:
|
[('location_id', '=', self.env['stock.location'].search(
|
||||||
workorder_in = self.workorder_out_id.filtered(lambda p: p.state == 'progress' and p.is_subcontract is True)
|
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||||
if workorder_in:
|
('location_dest_id', '=', self.env.ref(
|
||||||
picking_in = self.sudo().search([('id', '=', workorder_in.picking_in_id.id)])
|
'sf_manufacturing.stock_location_locations_virtual_outcontract').id),
|
||||||
if picking_in:
|
('origin', '=', self.origin)])
|
||||||
picking_in.write({'state': 'assigned'})
|
if self.id == move_out.picking_id.id:
|
||||||
else:
|
if move_out.move_line_ids.workorder_id.state not in ['progress']:
|
||||||
workorder_subcontract = self.workorder_out_id.filtered(
|
raise UserError(
|
||||||
lambda p: p.state == 'pending' and p.is_subcontract is True)
|
_('该出库单里源单据内的单号为%s的工单还未开始,不能进行验证操作!' % move_out.move_line_ids.workorder_id.name))
|
||||||
if workorder_subcontract:
|
|
||||||
raise UserError(
|
|
||||||
_('该出库单里源单据内的单号为%s的工单还未开始,不能进行验证操作!' % workorder_subcontract[
|
|
||||||
0].name))
|
|
||||||
# 入库单验证
|
# 入库单验证
|
||||||
if self.workorder_in_id:
|
move_in = self.env['stock.move'].search(
|
||||||
workorder_out = self.workorder_in_id.filtered(lambda p: p.state == 'progress' and p.is_subcontract is True)
|
[('location_dest_id', '=', self.env['stock.location'].search(
|
||||||
if workorder_out:
|
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||||
picking_out = self.sudo().search([('id', '=', workorder_out.picking_out_id.id)])
|
('location_id', '=', self.env.ref(
|
||||||
if picking_out.state != 'done':
|
'sf_manufacturing.stock_location_locations_virtual_outcontract').id),
|
||||||
|
('origin', '=', self.origin)])
|
||||||
|
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:
|
||||||
|
if move_out.picking_id.state != 'done':
|
||||||
raise UserError(
|
raise UserError(
|
||||||
_('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % picking_out.name))
|
_('该入库单对应的单号为%s的出库单还未完成,不能进行验证操作!' % move_out.picking_id.name))
|
||||||
|
|
||||||
res = super().button_validate()
|
res = super().button_validate()
|
||||||
# 采购单验证(夹具)
|
if res is True:
|
||||||
# for item in self.move_ids_without_package:
|
if self.id == move_out.picking_id.id:
|
||||||
# if item.quantity_done > 0:
|
if move_out.move_line_ids.workorder_id.state == 'progress':
|
||||||
# if item.product_id.categ_type == '夹具':
|
move_in = self.env['stock.move'].search(
|
||||||
# item._register_fixture()
|
[('location_dest_id', '=', self.env['stock.location'].search(
|
||||||
# elif item.product_id.categ_type == '刀具':
|
[('barcode', 'ilike', 'WH-PREPRODUCTION')]).id),
|
||||||
# item._register_cutting_tool()
|
('location_id', '=', self.env.ref(
|
||||||
|
'sf_manufacturing.stock_location_locations_virtual_outcontract').id),
|
||||||
|
('origin', '=', self.origin)])
|
||||||
|
# purchase = self.env['purchase.order'].search([('origin', '=', self.origin)])
|
||||||
|
if move_in:
|
||||||
|
move_in.write({'state': 'assigned'})
|
||||||
|
purchase = self.env['purchase.order'].search([('origin', '=', self.origin)])
|
||||||
|
self.env['stock.move.line'].create(move_in.get_move_line(purchase, None))
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
# 创建 外协出库入单
|
# 创建 外协出库入单
|
||||||
def create_outcontract_picking(self, sorted_workorders_arr, item):
|
def create_outcontract_picking(self, sorted_workorders_arr, item):
|
||||||
m = 0
|
m = 0
|
||||||
for sorted_workorders in sorted_workorders_arr:
|
for sorted_workorders in sorted_workorders_arr:
|
||||||
|
pick_ids = []
|
||||||
if m == 0:
|
if m == 0:
|
||||||
outcontract_stock_move = self.env['stock.move'].search(
|
outcontract_stock_move = self.env['stock.move'].search(
|
||||||
[('workorder_id', '=', sorted_workorders.id), ('production_id', '=', item.id)])
|
[('workorder_id', '=', sorted_workorders.id), ('production_id', '=', item.id)])
|
||||||
if not outcontract_stock_move:
|
if not outcontract_stock_move:
|
||||||
|
new_picking = True
|
||||||
location_id = self.env.ref(
|
location_id = self.env.ref(
|
||||||
'sf_manufacturing.stock_location_locations_virtual_outcontract').id,
|
'sf_manufacturing.stock_location_locations_virtual_outcontract').id,
|
||||||
location_dest_id = self.env['stock.location'].search(
|
location_dest_id = self.env['stock.location'].search(
|
||||||
@@ -493,23 +560,26 @@ class StockPicking(models.Model):
|
|||||||
'sf_manufacturing.outcontract_picking_in').id,
|
'sf_manufacturing.outcontract_picking_in').id,
|
||||||
outcontract_picking_type_out = self.env.ref(
|
outcontract_picking_type_out = self.env.ref(
|
||||||
'sf_manufacturing.outcontract_picking_out').id,
|
'sf_manufacturing.outcontract_picking_out').id,
|
||||||
moves_in = self.env['stock.move'].sudo().create(
|
|
||||||
item._get_stock_move_values_Res(item, location_id, location_dest_id,
|
|
||||||
outcontract_picking_type_in))
|
|
||||||
moves_out = self.env['stock.move'].sudo().create(
|
moves_out = self.env['stock.move'].sudo().create(
|
||||||
item._get_stock_move_values_Res(item, location_dest_id, location_id,
|
self.env['stock.move']._get_stock_move_values_Res(item, location_dest_id, location_id,
|
||||||
outcontract_picking_type_out))
|
outcontract_picking_type_out))
|
||||||
new_picking = True
|
|
||||||
picking_in = self.create(
|
|
||||||
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/'))
|
|
||||||
picking_out = self.create(
|
picking_out = self.create(
|
||||||
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/'))
|
moves_out._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCOUT/'))
|
||||||
moves_in.write({'picking_id': picking_in.id, 'state': 'confirmed'})
|
pick_ids.append(picking_out.id)
|
||||||
moves_out.write({'picking_id': picking_out.id, 'state': 'confirmed'})
|
moves_out.write(
|
||||||
moves_in._assign_picking_post_process(new=new_picking)
|
{'picking_id': picking_out.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
|
||||||
moves_out._assign_picking_post_process(new=new_picking)
|
moves_out._assign_picking_post_process(new=new_picking)
|
||||||
|
moves_in = self.env['stock.move'].sudo().create(
|
||||||
|
self.env['stock.move']._get_stock_move_values_Res(item, location_id, location_dest_id,
|
||||||
|
outcontract_picking_type_in))
|
||||||
|
picking_in = self.create(
|
||||||
|
moves_in._get_new_picking_values_Res(item, sorted_workorders, 'WH/OCIN/'))
|
||||||
|
pick_ids.append(picking_in.id)
|
||||||
|
moves_in.write(
|
||||||
|
{'picking_id': picking_in.id, 'state': 'waiting', 'workorder_id': sorted_workorders.id})
|
||||||
|
moves_in._assign_picking_post_process(new=new_picking)
|
||||||
m += 1
|
m += 1
|
||||||
sorted_workorders.write({'picking_in_id': picking_in.id, 'picking_out_id': picking_out.id})
|
sorted_workorders.write({'picking_ids': [(6, 0, pick_ids)]})
|
||||||
|
|
||||||
|
|
||||||
class ReStockMove(models.Model):
|
class ReStockMove(models.Model):
|
||||||
@@ -519,6 +589,23 @@ 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):
|
||||||
|
route = self.env['stock.route'].sudo().search([('name', '=', '表面工艺外协')])
|
||||||
|
move_values = {
|
||||||
|
'name': '推',
|
||||||
|
'company_id': item.company_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_qty': 1.0,
|
||||||
|
'location_id': location_src_id,
|
||||||
|
'location_dest_id': location_dest_id,
|
||||||
|
'origin': item.name,
|
||||||
|
# 'route_ids': False if not route else [(4, route.id)],
|
||||||
|
'date_deadline': datetime.now(),
|
||||||
|
'picking_type_id': picking_type_id,
|
||||||
|
}
|
||||||
|
return move_values
|
||||||
|
|
||||||
def _get_new_picking_values_Res(self, item, sorted_workorders, rescode):
|
def _get_new_picking_values_Res(self, item, sorted_workorders, rescode):
|
||||||
return {
|
return {
|
||||||
'name': self.env['stock.picking']._get_name_Res(rescode),
|
'name': self.env['stock.picking']._get_name_Res(rescode),
|
||||||
@@ -533,6 +620,22 @@ class ReStockMove(models.Model):
|
|||||||
'state': 'confirmed',
|
'state': 'confirmed',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_move_line(self, purchase, sorted_workorders):
|
||||||
|
return {
|
||||||
|
'move_id': self.id,
|
||||||
|
'product_id': self.product_id.id,
|
||||||
|
'product_uom_id': self.product_uom.id,
|
||||||
|
'location_id': self.picking_id.location_id.id,
|
||||||
|
'location_dest_id': self.picking_id.location_dest_id.id,
|
||||||
|
'picking_id': self.picking_id.id,
|
||||||
|
'reserved_uom_qty': 1.0,
|
||||||
|
'lot_id': purchase.picking_ids.move_line_ids.lot_id.id,
|
||||||
|
'company_id': self.company_id.id,
|
||||||
|
'workorder_id': '' if not sorted_workorders else sorted_workorders.id,
|
||||||
|
'production_id': '' if not sorted_workorders else sorted_workorders.production_id.id,
|
||||||
|
'state': 'assigned',
|
||||||
|
}
|
||||||
|
|
||||||
def print_serial_numbers(self):
|
def print_serial_numbers(self):
|
||||||
if not self.next_serial:
|
if not self.next_serial:
|
||||||
raise UserError(_("请先分配序列号再进行打印"))
|
raise UserError(_("请先分配序列号再进行打印"))
|
||||||
|
|||||||
@@ -25,7 +25,8 @@
|
|||||||
parent="sf_base.menu_sf_base"
|
parent="sf_base.menu_sf_base"
|
||||||
name="AGV站点"
|
name="AGV站点"
|
||||||
sequence="12"
|
sequence="12"
|
||||||
action="action_agv_site_form"/>
|
action="action_agv_site_form"
|
||||||
|
groups="sf_base.group_sf_order_user,sf_base.group_plan_dispatch,sf_base.group_plan_director,sf_base.group_sf_mrp_manager"/>
|
||||||
|
|
||||||
<!-- agv任务路线 -->
|
<!-- agv任务路线 -->
|
||||||
<record id="view_agv_task_route_tree" model="ir.ui.view">
|
<record id="view_agv_task_route_tree" model="ir.ui.view">
|
||||||
|
|||||||
@@ -106,6 +106,13 @@
|
|||||||
<field name="model">mrp.workorder</field>
|
<field name="model">mrp.workorder</field>
|
||||||
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
|
<field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
|
<xpath expr="//div[@name='button_box']" position="inside">
|
||||||
|
<button type="object" name="action_view_surface_technics_picking" class="oe_stat_button" icon="fa-truck"
|
||||||
|
groups="base.group_user,sf_base.group_sf_order_user"
|
||||||
|
attrs="{'invisible': [('surface_technics_picking_count', '=', 0)]}">
|
||||||
|
<field name="surface_technics_picking_count" widget="statinfo" string="工艺外协"/>
|
||||||
|
</button>
|
||||||
|
</xpath>
|
||||||
<xpath expr="//field[@name='state']" position="before">
|
<xpath expr="//field[@name='state']" position="before">
|
||||||
<field name='user_permissions' invisible="1"/>
|
<field name='user_permissions' invisible="1"/>
|
||||||
<field name='name' invisible="1"/>
|
<field name='name' invisible="1"/>
|
||||||
@@ -454,7 +461,7 @@
|
|||||||
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
|
<field name="feeder_station_start_id" readonly="1" force_save="1"/>
|
||||||
<field name="feeder_station_destination_id" readonly="1" force_save="1"/>
|
<field name="feeder_station_destination_id" readonly="1" force_save="1"/>
|
||||||
<field name="is_cnc_program_down" readonly="1"/>
|
<field name="is_cnc_program_down" readonly="1"/>
|
||||||
<field name="production_line_id"/>
|
<field name="production_line_id" readonly="1"/>
|
||||||
<field name="task_delivery_time" readonly="1"/>
|
<field name="task_delivery_time" readonly="1"/>
|
||||||
<field name="task_completion_time" readonly="1"/>
|
<field name="task_completion_time" readonly="1"/>
|
||||||
<field name="status" readonly="1"/>
|
<field name="status" readonly="1"/>
|
||||||
|
|||||||
@@ -67,7 +67,8 @@ class Sf_Mrs_Connect(http.Controller):
|
|||||||
logging.info('cnc_processing_arr:%s' % cnc_processing_arr)
|
logging.info('cnc_processing_arr:%s' % cnc_processing_arr)
|
||||||
cnc_program.write({'programming_state': '已编程', 'work_state': '已编程'})
|
cnc_program.write({'programming_state': '已编程', 'work_state': '已编程'})
|
||||||
cnc_program.workorder_ids.filtered(lambda b: b.routing_type == 'CNC加工').write(
|
cnc_program.workorder_ids.filtered(lambda b: b.routing_type == 'CNC加工').write(
|
||||||
{'cnc_ids': cnc_processing_arr})
|
{'cnc_ids': cnc_processing_arr, 'cnc_worksheet': cnc_production.workorder_ids.filtered(
|
||||||
|
lambda b: b.routing_type == 'CNC加工').cnc_worksheet})
|
||||||
cnc_program_ids = [item.id for item in cnc_program]
|
cnc_program_ids = [item.id for item in cnc_program]
|
||||||
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
|
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
|
||||||
[('production_id', 'in', cnc_program_ids)])
|
[('production_id', 'in', cnc_program_ids)])
|
||||||
|
|||||||
1
sf_oca/__init__.py
Normal file
1
sf_oca/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import models
|
||||||
23
sf_oca/__manifest__.py
Normal file
23
sf_oca/__manifest__.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Copyright 2017-19 ForgeFlow S.L. (https://www.forgeflow.com)
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
{
|
||||||
|
"name": "sf_oca",
|
||||||
|
"version": "1.0",
|
||||||
|
'summary': '智能工厂oca模块',
|
||||||
|
'sequence': 1,
|
||||||
|
'description': """
|
||||||
|
在本模块,进行流程的审核
|
||||||
|
""",
|
||||||
|
'category': 'sf',
|
||||||
|
'website': 'https://www.sf.jikimo.com',
|
||||||
|
"depends": ["base_tier_validation_forward"],
|
||||||
|
"data": [
|
||||||
|
"security/ir.model.access.csv",
|
||||||
|
"templates/tier_validation_templates.xml",
|
||||||
|
],
|
||||||
|
"assets": {},
|
||||||
|
'license': 'LGPL-3',
|
||||||
|
'installable': True,
|
||||||
|
'application': False,
|
||||||
|
'auto_install': False,
|
||||||
|
}
|
||||||
1
sf_oca/models/__init__.py
Normal file
1
sf_oca/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import tier_validation
|
||||||
18
sf_oca/models/tier_validation.py
Normal file
18
sf_oca/models/tier_validation.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Copyright 2017-19 ForgeFlow S.L. (https://www.forgeflow.com)
|
||||||
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
|
from ast import literal_eval
|
||||||
|
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
from odoo import _, api, fields, models
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from odoo.tools.misc import frozendict
|
||||||
|
|
||||||
|
|
||||||
|
class TierValidation(models.AbstractModel):
|
||||||
|
_inherit = "tier.validation"
|
||||||
|
|
||||||
|
def _notify_restarted_review_body(self):
|
||||||
|
return _("%s 取消审批请求.") % (self.env.user.name)
|
||||||
|
|
||||||
1
sf_oca/security/ir.model.access.csv
Normal file
1
sf_oca/security/ir.model.access.csv
Normal file
@@ -0,0 +1 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
122
sf_oca/templates/tier_validation_templates.xml
Normal file
122
sf_oca/templates/tier_validation_templates.xml
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<template id="tier_validation_buttons">
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
name="request_validation"
|
||||||
|
string="发起审批"
|
||||||
|
t-attf-attrs="{'invisible': ['|','|',('need_validation', '!=', True),('rejected','=',True),('#{state_field}', '#{state_operator}', #{state_value})]}"
|
||||||
|
type="object"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
name="restart_validation"
|
||||||
|
string="取消审批"
|
||||||
|
t-attf-attrs="{'invisible': ['|',('review_ids', '=', []),('#{state_field}', '#{state_operator}', #{state_value})]}"
|
||||||
|
type="object"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template id="tier_validation_label">
|
||||||
|
<div>
|
||||||
|
<field name="need_validation" invisible="1" />
|
||||||
|
<field name="validated" invisible="1" />
|
||||||
|
<field name="rejected" invisible="1" />
|
||||||
|
<div
|
||||||
|
class="alert alert-warning"
|
||||||
|
role="alert"
|
||||||
|
t-attf-attrs="{'invisible': ['|', '|', '|',
|
||||||
|
('validated', '=', True), ('#{state_field}', '#{state_operator}', #{state_value}),
|
||||||
|
('rejected', '=', True), ('review_ids', '=', [])]}"
|
||||||
|
style="margin-bottom:0px;"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
<i class="fa fa-info-circle" />
|
||||||
|
这个单据需要验证.
|
||||||
|
<field name="can_review" invisible="1" />
|
||||||
|
<button
|
||||||
|
name="validate_tier"
|
||||||
|
string="验证"
|
||||||
|
attrs="{'invisible': [('can_review', '=', False)]}"
|
||||||
|
type="object"
|
||||||
|
class="oe_inline oe_button btn-success"
|
||||||
|
icon="fa-thumbs-up"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
name="reject_tier"
|
||||||
|
string="拒绝"
|
||||||
|
attrs="{'invisible': [('can_review', '=', False)]}"
|
||||||
|
type="object"
|
||||||
|
class="btn-icon btn-danger"
|
||||||
|
icon="fa-thumbs-down"
|
||||||
|
/>
|
||||||
|
<br /><field name="next_review" readonly="1" />
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="alert alert-success"
|
||||||
|
role="alert"
|
||||||
|
t-attf-attrs="{'invisible': ['|', '|', ('validated', '!=', True), ('#{state_field}', '#{state_operator}', #{state_value}), ('review_ids', '=', [])]}"
|
||||||
|
style="margin-bottom:0px;"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
<i class="fa fa-thumbs-up" />
|
||||||
|
Operation has been
|
||||||
|
<b>validated</b>
|
||||||
|
!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="alert alert-danger"
|
||||||
|
role="alert"
|
||||||
|
t-attf-attrs="{'invisible': ['|', '|', ('rejected', '!=', True), ('#{state_field}', '#{state_operator}', #{state_value}), ('review_ids', '=', [])]}"
|
||||||
|
style="margin-bottom:0px;"
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
<i class="fa fa-thumbs-down" />
|
||||||
|
Operation has been
|
||||||
|
<b>rejected</b>
|
||||||
|
.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template id="tier_validation_reviews">
|
||||||
|
<field
|
||||||
|
name="review_ids"
|
||||||
|
widget="tier_validation"
|
||||||
|
attrs="{'invisible':[('review_ids', '=', [])]}"
|
||||||
|
style="width:100%%; margin-top: 10px;"
|
||||||
|
>
|
||||||
|
<tree>
|
||||||
|
<field name="id" />
|
||||||
|
<field name="name" />
|
||||||
|
<field name="sequence" />
|
||||||
|
<field name="requested_by" />
|
||||||
|
<field name="status" />
|
||||||
|
<field name="todo_by" />
|
||||||
|
<field name="done_by" />
|
||||||
|
<field name="reviewed_date" />
|
||||||
|
<field name="reviewed_formated_date" />
|
||||||
|
<field name="comment" />
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<template
|
||||||
|
id="tier_validation_label_forward"
|
||||||
|
inherit_id="sf_oca.tier_validation_label"
|
||||||
|
>
|
||||||
|
<xpath expr="//button[@name='reject_tier']" position="after">
|
||||||
|
<field name="can_forward" invisible="1" />
|
||||||
|
<button
|
||||||
|
name="forward_tier"
|
||||||
|
string="Forward"
|
||||||
|
attrs="{'invisible': [('can_forward', '=', False)]}"
|
||||||
|
type="object"
|
||||||
|
class="oe_inline oe_button btn-warning"
|
||||||
|
icon="fa-arrow-circle-right"
|
||||||
|
/>
|
||||||
|
</xpath>
|
||||||
|
</template>
|
||||||
|
</odoo>
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//form/header/button[@name='action_confirm']" position="after">
|
<xpath expr="//form/header/button[@name='action_confirm']" position="after">
|
||||||
<field name="check_status" invisible="1"/>
|
<field name="check_status" invisible="1"/>
|
||||||
<!-- <field name="schedule_status" invisible="1"/> -->
|
<field name="mrp_production_count" invisible="1"/>
|
||||||
<button name="sf_sale.action_sale_order_check_wizard" string="审核" type="action"
|
<button name="sf_sale.action_sale_order_check_wizard" string="审核" type="action"
|
||||||
context="{'default_order_id':active_id}" groups="sf_base.group_sale_director"
|
context="{'default_order_id':active_id}" groups="sf_base.group_sale_director"
|
||||||
attrs="{'invisible': ['|',('check_status','in', ['approved',False,'fail']),('state', 'in', ['cancel'])]}"
|
attrs="{'invisible': ['|',('check_status','in', ['approved',False,'fail']),('state', 'in', ['cancel'])]}"
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
<xpath expr="//form/header/button[@name='action_confirm'][2]" position="replace">
|
<xpath expr="//form/header/button[@name='action_confirm'][2]" position="replace">
|
||||||
<button name="action_confirm" data-hotkey="v"
|
<button name="action_confirm" data-hotkey="v"
|
||||||
string="确认" type="object" context="{'validate_analytic': True}"
|
string="确认" type="object" context="{'validate_analytic': True}"
|
||||||
attrs="{'invisible': ['|','&',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel'])]}"/>
|
attrs="{'invisible': ['|','&',('check_status', '!=', 'approved'),('state', 'in', ['draft','cancel']),'&','&',('check_status', '=', 'approved'),('state', 'in', ['sale','cancel']),('mrp_production_count', '>', 0)]}"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//form/header/button[@name='action_cancel']" position="attributes">
|
<xpath expr="//form/header/button[@name='action_cancel']" position="attributes">
|
||||||
<attribute name="attrs">{'invisible': ['|','&',('state', 'in',
|
<attribute name="attrs">{'invisible': ['|','&',('state', 'in',
|
||||||
@@ -112,15 +112,15 @@
|
|||||||
<field name="deadline_of_delivery" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
<field name="deadline_of_delivery" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
||||||
<field name="payments_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
<field name="payments_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
||||||
<field name="pay_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
<field name="pay_way" attrs="{'readonly': [('state', 'in', ('sale','cancel'))]}"/>
|
||||||
<!-- <field name="schedule_status" readonly="1"/> -->
|
<!-- <field name="schedule_status" readonly="1"/> -->
|
||||||
</field>
|
</field>
|
||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='name']" position="before">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='name']" position="before">
|
||||||
<field name="model_glb_file" widget="Viewer3D" optional="show"
|
<field name="model_glb_file" widget="Viewer3D" optional="show"
|
||||||
string="模型文件" attrs="{'readonly': [('state', 'in', ['draft'])]}"/>
|
string="模型文件" attrs="{'readonly': [('state', 'in', ['draft'])]}"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='order_line']/tree/field[@name='product_template_id']" position="attributes">
|
<xpath expr="//field[@name='order_line']/tree/field[@name='product_template_id']" position="attributes">
|
||||||
<attribute name="options">{'no_create': True, 'no_quick_create': True}</attribute>
|
<attribute name="options">{'no_create': True}</attribute>
|
||||||
<attribute name="context">{'is_sale_order_line': True }</attribute>
|
<attribute name="context">{'is_sale_order_line': True }</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='order_line']" position="attributes">
|
<xpath expr="//field[@name='order_line']" position="attributes">
|
||||||
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
|
<attribute name="attrs">{'readonly': [('state', 'in', ['cancel','sale'])]}</attribute>
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
<field name="inherit_id" ref="sale.view_quotation_tree_with_onboarding"/>
|
<field name="inherit_id" ref="sale.view_quotation_tree_with_onboarding"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree position="attributes">
|
<tree position="attributes">
|
||||||
<attribute name="default_order">check_status desc,create_date asc</attribute>
|
<attribute name="default_order">create_date desc</attribute>
|
||||||
<attribute name="delete">False</attribute>
|
<attribute name="delete">False</attribute>
|
||||||
</tree>
|
</tree>
|
||||||
<field name="name" position="attributes">
|
<field name="name" position="attributes">
|
||||||
@@ -222,21 +222,21 @@
|
|||||||
<field name="inherit_id" ref="sale.view_order_tree"/>
|
<field name="inherit_id" ref="sale.view_order_tree"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree position="attributes">
|
<tree position="attributes">
|
||||||
<!-- <attribute name="default_order">schedule_status desc,date_order asc</attribute> -->
|
<!-- <attribute name="default_order">schedule_status desc,date_order asc</attribute> -->
|
||||||
<attribute name="default_order">create_date desc</attribute>
|
<attribute name="default_order">create_date desc</attribute>
|
||||||
<attribute name="create">False</attribute>
|
<attribute name="create">False</attribute>
|
||||||
</tree>
|
</tree>
|
||||||
<field name="name" position="attributes">
|
<field name="name" position="attributes">
|
||||||
<attribute name="string">订单号</attribute>
|
<attribute name="string">订单号</attribute>
|
||||||
</field>
|
</field>
|
||||||
<!-- <field name="amount_total" position="after"> -->
|
<!-- <field name="amount_total" position="after"> -->
|
||||||
<!-- <field name="schedule_status" widget="badge" -->
|
<!-- <field name="schedule_status" widget="badge" -->
|
||||||
<!-- decoration-success="schedule_status == 'received'" -->
|
<!-- decoration-success="schedule_status == 'received'" -->
|
||||||
<!-- decoration-warning="schedule_status == 'to process'" -->
|
<!-- decoration-warning="schedule_status == 'to process'" -->
|
||||||
<!-- decoration-danger="schedule_status == 'to receive'" -->
|
<!-- decoration-danger="schedule_status == 'to receive'" -->
|
||||||
<!-- decoration-muted="schedule_status == 'to process'" -->
|
<!-- decoration-muted="schedule_status == 'to process'" -->
|
||||||
<!-- decoration-info="schedule_status == 'to schedule'"/> -->
|
<!-- decoration-info="schedule_status == 'to schedule'"/> -->
|
||||||
<!-- </field> -->
|
<!-- </field> -->
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class MachineTableToolChangingApply(models.Model):
|
|||||||
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
|
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
|
||||||
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
|
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
|
||||||
('直装固定式', '直装固定式')], string='刀位接口型号')
|
('直装固定式', '直装固定式')], string='刀位接口型号')
|
||||||
diameter = fields.Integer(string='刀具直径(mm)')
|
diameter = fields.Float(string='刀具直径(mm)')
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
|
||||||
max_lifetime_value = fields.Integer(string='最大寿命值(min)')
|
max_lifetime_value = fields.Integer(string='最大寿命值(min)')
|
||||||
alarm_value = fields.Integer(string='报警值(min)')
|
alarm_value = fields.Integer(string='报警值(min)')
|
||||||
@@ -209,7 +209,7 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
|
|||||||
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
|
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
|
||||||
compute='_compute_tool_number', store=True)
|
compute='_compute_tool_number', store=True)
|
||||||
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_tool_number', store=True)
|
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_tool_number', store=True)
|
||||||
diameter = fields.Integer(string='刀具直径(mm)', compute='_compute_tool_number', store=True)
|
diameter = fields.Float(string='刀具直径(mm)', compute='_compute_tool_number', store=True)
|
||||||
tool_included_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_tool_number', store=True)
|
tool_included_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_tool_number', store=True)
|
||||||
tool_loading_length = fields.Float(string='总长度(mm)', compute='_compute_tool_number', store=True)
|
tool_loading_length = fields.Float(string='总长度(mm)', compute='_compute_tool_number', store=True)
|
||||||
extension_length = fields.Float(string='伸出长(mm)')
|
extension_length = fields.Float(string='伸出长(mm)')
|
||||||
@@ -368,7 +368,7 @@ class FunctionalToolAssembly(models.Model):
|
|||||||
functional_tool_name = fields.Char(string='功能刀具名称', readonly=True)
|
functional_tool_name = fields.Char(string='功能刀具名称', readonly=True)
|
||||||
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
|
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
|
||||||
group_expand='_read_group_functional_tool_type_ids')
|
group_expand='_read_group_functional_tool_type_ids')
|
||||||
functional_tool_diameter = fields.Integer(string='功能刀具直径(mm)', readonly=True)
|
functional_tool_diameter = fields.Float(string='功能刀具直径(mm)', readonly=True)
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
||||||
coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
|
coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
|
||||||
new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
|
new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
|
||||||
@@ -542,7 +542,7 @@ class FunctionalToolAssembly(models.Model):
|
|||||||
after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', readonly=True)
|
after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', readonly=True)
|
||||||
after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model',
|
after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model',
|
||||||
string='组装后功能刀具类型', readonly=True)
|
string='组装后功能刀具类型', readonly=True)
|
||||||
after_assembly_functional_tool_diameter = fields.Integer(string='组装后功能刀具直径(mm)', readonly=True)
|
after_assembly_functional_tool_diameter = fields.Float(string='组装后功能刀具直径(mm)', readonly=True)
|
||||||
after_assembly_knife_tip_r_angle = fields.Float(string='组装后刀尖R角(mm)', readonly=True)
|
after_assembly_knife_tip_r_angle = fields.Float(string='组装后刀尖R角(mm)', readonly=True)
|
||||||
after_assembly_new_former = fields.Selection([('0', '新'), ('1', '旧')], string='组装后新/旧', readonly=True)
|
after_assembly_new_former = fields.Selection([('0', '新'), ('1', '旧')], string='组装后新/旧', readonly=True)
|
||||||
cut_time = fields.Integer(string='已切削时间(min)', readonly=True)
|
cut_time = fields.Integer(string='已切削时间(min)', readonly=True)
|
||||||
@@ -696,7 +696,7 @@ class FunctionalToolDismantle(models.Model):
|
|||||||
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
|
tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
|
||||||
compute='_compute_functional_tool_num')
|
compute='_compute_functional_tool_num')
|
||||||
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True)
|
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', compute='_compute_functional_tool_num', store=True)
|
||||||
diameter = fields.Integer(string='刀具直径(mm)', compute='_compute_functional_tool_num', store=True)
|
diameter = fields.Float(string='刀具直径(mm)', compute='_compute_functional_tool_num', store=True)
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_functional_tool_num', store=True)
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', compute='_compute_functional_tool_num', store=True)
|
||||||
rfid = fields.Char('Rfid', compute='_compute_functional_tool_num', store=True)
|
rfid = fields.Char('Rfid', compute='_compute_functional_tool_num', store=True)
|
||||||
rfid_dismantle = fields.Char('Rfid(已拆解)', readonly=True)
|
rfid_dismantle = fields.Char('Rfid(已拆解)', readonly=True)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class FunctionalCuttingToolEntity(models.Model):
|
|||||||
sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
|
sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型',
|
||||||
group_expand='_read_group_mrs_cutting_tool_type_id', compute_sudo=True)
|
group_expand='_read_group_mrs_cutting_tool_type_id', compute_sudo=True)
|
||||||
|
|
||||||
functional_tool_diameter = fields.Integer(string='刀具直径(mm)', readonly=True)
|
functional_tool_diameter = fields.Float(string='刀具直径(mm)', readonly=True)
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
||||||
coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
|
coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
|
||||||
new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
|
new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
|
||||||
@@ -244,7 +244,7 @@ class FunctionalToolWarning(models.Model):
|
|||||||
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
|
functional_tool_name_id = fields.Many2one('sf.functional.tool.assembly', string='功能刀具名称')
|
||||||
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id')
|
barcode_id = fields.Many2one('stock.lot', string='功能刀具序列号', related='functional_tool_name_id.barcode_id')
|
||||||
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
|
mrs_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型')
|
||||||
diameter = fields.Integer(string='刀具直径(mm)')
|
diameter = fields.Float(string='刀具直径(mm)')
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
|
||||||
# 其他信息
|
# 其他信息
|
||||||
install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time')
|
install_tool_time = fields.Datetime("刀具组装时间", related='functional_tool_name_id.tool_loading_time')
|
||||||
@@ -298,7 +298,7 @@ class StockMoveLine(models.Model):
|
|||||||
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
|
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', store=True,
|
||||||
group_expand='_read_group_functional_tool_type_id')
|
group_expand='_read_group_functional_tool_type_id')
|
||||||
functional_tool_name = fields.Char('刀具名称')
|
functional_tool_name = fields.Char('刀具名称')
|
||||||
diameter = fields.Integer(string='刀具直径(mm)')
|
diameter = fields.Float(string='刀具直径(mm)')
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)')
|
||||||
install_tool_time = fields.Datetime("刀具组装时间", default=fields.Datetime.now())
|
install_tool_time = fields.Datetime("刀具组装时间", default=fields.Datetime.now())
|
||||||
code = fields.Char('编码')
|
code = fields.Char('编码')
|
||||||
@@ -320,7 +320,7 @@ class RealTimeDistributionOfFunctionalTools(models.Model):
|
|||||||
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=False, required=True)
|
tool_groups_id = fields.Many2one('sf.tool.groups', '刀具组', readonly=False, required=True)
|
||||||
sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False,
|
sf_cutting_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=False,
|
||||||
group_expand='_read_mrs_cutting_tool_type_ids', store=True)
|
group_expand='_read_mrs_cutting_tool_type_ids', store=True)
|
||||||
diameter = fields.Integer(string='刀具直径(mm)', readonly=False)
|
diameter = fields.Float(string='刀具直径(mm)', readonly=False)
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=False)
|
||||||
tool_stock_num = fields.Integer(string='刀具房数量')
|
tool_stock_num = fields.Integer(string='刀具房数量')
|
||||||
side_shelf_num = fields.Integer(string='线边刀库数量')
|
side_shelf_num = fields.Integer(string='线边刀库数量')
|
||||||
|
|||||||
@@ -13,9 +13,10 @@ class SfMaintenanceEquipmentTool(models.Model):
|
|||||||
|
|
||||||
image = fields.Binary('图片', related='functional_tool_name_id.image')
|
image = fields.Binary('图片', related='functional_tool_name_id.image')
|
||||||
tool_code = fields.Char('功能刀具编码', related='functional_tool_name_id.code')
|
tool_code = fields.Char('功能刀具编码', related='functional_tool_name_id.code')
|
||||||
|
rfid = fields.Char('Rfid', related='functional_tool_name_id.rfid')
|
||||||
functional_tool_type = fields.Char('功能刀具类型', related='functional_tool_name_id.sf_cutting_tool_type_id.name')
|
functional_tool_type = fields.Char('功能刀具类型', related='functional_tool_name_id.sf_cutting_tool_type_id.name')
|
||||||
tool_groups = fields.Char('刀具组', related='functional_tool_name_id.tool_groups_id.name')
|
tool_groups = fields.Char('刀具组', related='functional_tool_name_id.tool_groups_id.name')
|
||||||
diameter = fields.Integer('直径(mm)', related='functional_tool_name_id.functional_tool_diameter')
|
diameter = fields.Float('直径(mm)', related='functional_tool_name_id.functional_tool_diameter')
|
||||||
knife_tip_r_angle = fields.Float('刀尖R角(mm)', related='functional_tool_name_id.knife_tip_r_angle')
|
knife_tip_r_angle = fields.Float('刀尖R角(mm)', related='functional_tool_name_id.knife_tip_r_angle')
|
||||||
life_value_max = fields.Integer('最大寿命值(min)', related='functional_tool_name_id.max_lifetime_value')
|
life_value_max = fields.Integer('最大寿命值(min)', related='functional_tool_name_id.max_lifetime_value')
|
||||||
alarm_value = fields.Integer('报警值(min)', related='functional_tool_name_id.alarm_value')
|
alarm_value = fields.Integer('报警值(min)', related='functional_tool_name_id.alarm_value')
|
||||||
@@ -26,15 +27,15 @@ class SfMaintenanceEquipmentTool(models.Model):
|
|||||||
# if datas:
|
# if datas:
|
||||||
# print(datas)
|
# print(datas)
|
||||||
|
|
||||||
@api.model_create_multi
|
# @api.model_create_multi
|
||||||
def create(self, vals_list):
|
# def create(self, vals_list):
|
||||||
tools = super().create(vals_list)
|
# tools = super().create(vals_list)
|
||||||
for tool in tools:
|
# for tool in tools:
|
||||||
self.env['sf.machine.table.tool.changing.apply'].sudo().create({
|
# self.env['sf.machine.table.tool.changing.apply'].sudo().create({
|
||||||
'maintenance_equipment_id': tool.equipment_id.id,
|
# 'maintenance_equipment_id': tool.equipment_id.id,
|
||||||
'cutter_spacing_code_id': tool.id
|
# 'cutter_spacing_code_id': tool.id
|
||||||
})
|
# })
|
||||||
return tools
|
# return tools
|
||||||
|
|
||||||
|
|
||||||
class SfMaintenanceEquipment(models.Model):
|
class SfMaintenanceEquipment(models.Model):
|
||||||
@@ -68,6 +69,18 @@ class SfMaintenanceEquipment(models.Model):
|
|||||||
[('equipment_id', '=', maintenance_equipment_id.id), ('code', '=', tool_id)])
|
[('equipment_id', '=', maintenance_equipment_id.id), ('code', '=', tool_id)])
|
||||||
functional_tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
|
functional_tool_id = self.env['sf.functional.cutting.tool.entity'].sudo().search(
|
||||||
[('rfid', '=', data['RfidCode'])])
|
[('rfid', '=', data['RfidCode'])])
|
||||||
|
if functional_tool_id:
|
||||||
|
# 查询该功能刀具是否已经装在机床内其他位置,如果是就删除
|
||||||
|
equipment_tools = self.env['maintenance.equipment.tool'].sudo().search(
|
||||||
|
[('functional_tool_name_id', '=', functional_tool_id.id), ('code', '!=', tool_id)])
|
||||||
|
if equipment_tools:
|
||||||
|
for item in equipment_tools:
|
||||||
|
item.write({
|
||||||
|
'functional_tool_name_id': False,
|
||||||
|
'tool_install_time': None
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
logging.info('Rfid为【%s】的功能刀具不存在!' % data['RfidCode'])
|
||||||
time = None
|
time = None
|
||||||
if data['AddDatetime']:
|
if data['AddDatetime']:
|
||||||
datatime = str(data['AddDatetime'])
|
datatime = str(data['AddDatetime'])
|
||||||
|
|||||||
@@ -184,27 +184,10 @@
|
|||||||
<field name="model">sf.functional.cutting.tool.entity</field>
|
<field name="model">sf.functional.cutting.tool.entity</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search>
|
<search>
|
||||||
<field name="barcode_id"/>
|
|
||||||
<field name="rfid"/>
|
<field name="rfid"/>
|
||||||
<field name="functional_tool_name_id"/>
|
<field name="tool_name_id"/>
|
||||||
<field name="image" widget='image'/>
|
|
||||||
<field name="functional_tool_diameter"/>
|
<field name="functional_tool_diameter"/>
|
||||||
<field name="knife_tip_r_angle"/>
|
<field name="knife_tip_r_angle"/>
|
||||||
<field name="coarse_middle_thin" optional="hide"/>
|
|
||||||
<field name="new_former" optional="hide"/>
|
|
||||||
<field name="tool_loading_length" optional="hide"/>
|
|
||||||
<field name="functional_tool_length" optional="hide"/>
|
|
||||||
<field name="effective_length" optional="hide"/>
|
|
||||||
<field name="tool_room_num"/>
|
|
||||||
<field name="line_edge_knife_library_num"/>
|
|
||||||
<field name="machine_knife_library_num"/>
|
|
||||||
<field name="max_lifetime_value"/>
|
|
||||||
<field name="alarm_value"/>
|
|
||||||
<field name="used_value"/>
|
|
||||||
<field name="functional_tool_status" optional="hide"/>
|
|
||||||
|
|
||||||
<field name="current_location_id" invisible="True"/>
|
|
||||||
<field name="sf_cutting_tool_type_id" invisible="True"/>
|
|
||||||
<filter string="未拆除" name="no_state_removed" domain="[('functional_tool_status', '!=', '已拆除')]"/>
|
<filter string="未拆除" name="no_state_removed" domain="[('functional_tool_status', '!=', '已拆除')]"/>
|
||||||
<filter string="已拆除" name="state_removed" domain="[('functional_tool_status', '=', '已拆除')]"/>
|
<filter string="已拆除" name="state_removed" domain="[('functional_tool_status', '=', '已拆除')]"/>
|
||||||
<separator/>
|
<separator/>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
<field name='product_template_ids'>
|
<field name='product_template_ids'>
|
||||||
<tree editable='bottom'>
|
<tree editable='bottom'>
|
||||||
<field name="code" readonly="1"/>
|
<field name="code" readonly="1"/>
|
||||||
|
<field name="rfid"/>
|
||||||
<field name="tool_code"/>
|
<field name="tool_code"/>
|
||||||
<field name="functional_tool_type"/>
|
<field name="functional_tool_type"/>
|
||||||
<field name="functional_tool_name_id" readonly="1"/>
|
<field name="functional_tool_name_id" readonly="1"/>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class ToolChangeRequirementInformation(models.TransientModel):
|
|||||||
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
|
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
|
||||||
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
|
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
|
||||||
('直装固定式', '直装固定式')], string='刀位接口型号', readonly=True)
|
('直装固定式', '直装固定式')], string='刀位接口型号', readonly=True)
|
||||||
diameter = fields.Integer(string='刀具直径(mm)', readonly=True)
|
diameter = fields.Float(string='刀具直径(mm)', readonly=True)
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
||||||
max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
|
max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
|
||||||
alarm_value = fields.Integer(string='报警值(min)', readonly=True)
|
alarm_value = fields.Integer(string='报警值(min)', readonly=True)
|
||||||
@@ -39,7 +39,7 @@ class ToolChangeRequirementInformation(models.TransientModel):
|
|||||||
# 待换功能刀具信息
|
# 待换功能刀具信息
|
||||||
replacement_tool_name = fields.Char(string='待换功能刀具名称', compute='_compute_name')
|
replacement_tool_name = fields.Char(string='待换功能刀具名称', compute='_compute_name')
|
||||||
replacement_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='待换功能刀具类型')
|
replacement_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='待换功能刀具类型')
|
||||||
replacement_diameter = fields.Integer(string='待换刀具直径(mm)')
|
replacement_diameter = fields.Float(string='待换刀具直径(mm)')
|
||||||
replacement_knife_tip_r_angle = fields.Float(string='待换刀具刀尖R角(mm)', required=True)
|
replacement_knife_tip_r_angle = fields.Float(string='待换刀具刀尖R角(mm)', required=True)
|
||||||
replacement_tool_setting_length = fields.Float(string='待换刀具总长度(mm)', required=True)
|
replacement_tool_setting_length = fields.Float(string='待换刀具总长度(mm)', required=True)
|
||||||
replacement_extension_length = fields.Float(string='待换刀具伸出长(mm)')
|
replacement_extension_length = fields.Float(string='待换刀具伸出长(mm)')
|
||||||
@@ -153,7 +153,7 @@ class ToolTransferRequestInformation(models.TransientModel):
|
|||||||
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
|
[('BT刀柄式', 'BT刀柄式'), ('SK刀柄式', 'SK刀柄式'), ('HSK刀柄式', 'HSK刀柄式'),
|
||||||
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
|
('CAT刀柄式', 'CAT刀柄式'), ('ISO刀盘式', 'ISO刀盘式'), ('DIN刀盘式', 'DIN刀盘式'),
|
||||||
('直装固定式', '直装固定式')], string='刀位接口型号', readonly=True)
|
('直装固定式', '直装固定式')], string='刀位接口型号', readonly=True)
|
||||||
diameter = fields.Integer(string='刀具直径(mm)', readonly=True)
|
diameter = fields.Float(string='刀具直径(mm)', readonly=True)
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
||||||
max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
|
max_lifetime_value = fields.Integer(string='最大寿命值(min)', readonly=True)
|
||||||
alarm_value = fields.Integer(string='报警值(min)', readonly=True)
|
alarm_value = fields.Integer(string='报警值(min)', readonly=True)
|
||||||
@@ -197,7 +197,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
|
|||||||
functional_tool_name = fields.Char(string='功能刀具名称', readonly=True)
|
functional_tool_name = fields.Char(string='功能刀具名称', readonly=True)
|
||||||
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
|
functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型', readonly=True,
|
||||||
group_expand='_read_group_functional_tool_type_ids')
|
group_expand='_read_group_functional_tool_type_ids')
|
||||||
functional_tool_diameter = fields.Integer(string='功能刀具直径(mm)', readonly=True)
|
functional_tool_diameter = fields.Float(string='功能刀具直径(mm)', readonly=True)
|
||||||
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
knife_tip_r_angle = fields.Float(string='刀尖R角(mm)', readonly=True)
|
||||||
coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
|
coarse_middle_thin = fields.Selection([("1", "粗"), ('2', '中'), ('3', '精')], string='粗/中/精', readonly=True)
|
||||||
new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
|
new_former = fields.Selection([('0', '新'), ('1', '旧')], string='新/旧', readonly=True)
|
||||||
@@ -463,7 +463,7 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
|
|||||||
after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', compute='_compute_name', store=True)
|
after_assembly_functional_tool_name = fields.Char(string='组装后功能刀具名称', compute='_compute_name', store=True)
|
||||||
after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model',
|
after_assembly_functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model',
|
||||||
string='组装后功能刀具类型')
|
string='组装后功能刀具类型')
|
||||||
after_assembly_functional_tool_diameter = fields.Integer(string='组装后功能刀具直径(mm)')
|
after_assembly_functional_tool_diameter = fields.Float(string='组装后功能刀具直径(mm)')
|
||||||
after_assembly_knife_tip_r_angle = fields.Float(string='组装后刀尖R角(mm)')
|
after_assembly_knife_tip_r_angle = fields.Float(string='组装后刀尖R角(mm)')
|
||||||
after_assembly_new_former = fields.Selection([('0', '新'), ('1', '旧')], string='组装后新/旧', default='0')
|
after_assembly_new_former = fields.Selection([('0', '新'), ('1', '旧')], string='组装后新/旧', default='0')
|
||||||
cut_time = fields.Integer(string='已切削时间(min)')
|
cut_time = fields.Integer(string='已切削时间(min)')
|
||||||
@@ -615,17 +615,17 @@ class FunctionalToolAssemblyOrder(models.TransientModel):
|
|||||||
self.env['stock.picking'].create_stocking_picking(stock_lot, functional_tool_assembly, self)
|
self.env['stock.picking'].create_stocking_picking(stock_lot, functional_tool_assembly, self)
|
||||||
# 刀具物料出库
|
# 刀具物料出库
|
||||||
if self.handle_code_id:
|
if self.handle_code_id:
|
||||||
product_id.tool_material_stock_moves(self.handle_code_id)
|
product_id.tool_material_stock_moves(self.handle_code_id, self.assembly_order_code)
|
||||||
if self.integral_product_id:
|
if self.integral_product_id:
|
||||||
self.integral_product_id.material_stock_moves(self.integral_freight_barcode)
|
self.integral_product_id.material_stock_moves(self.integral_freight_barcode,self.assembly_order_code)
|
||||||
if self.blade_product_id:
|
if self.blade_product_id:
|
||||||
self.blade_product_id.material_stock_moves(self.blade_freight_barcode)
|
self.blade_product_id.material_stock_moves(self.blade_freight_barcode,self.assembly_order_code)
|
||||||
if self.bar_product_id:
|
if self.bar_product_id:
|
||||||
self.bar_product_id.material_stock_moves(self.bar_freight_barcode)
|
self.bar_product_id.material_stock_moves(self.bar_freight_barcode,self.assembly_order_code)
|
||||||
if self.pad_product_id:
|
if self.pad_product_id:
|
||||||
self.pad_product_id.material_stock_moves(self.pad_freight_barcode)
|
self.pad_product_id.material_stock_moves(self.pad_freight_barcode,self.assembly_order_code)
|
||||||
if self.chuck_product_id:
|
if self.chuck_product_id:
|
||||||
self.chuck_product_id.material_stock_moves(self.chuck_freight_barcode)
|
self.chuck_product_id.material_stock_moves(self.chuck_freight_barcode,self.assembly_order_code)
|
||||||
|
|
||||||
# ============================创建功能刀具列表、安全库存记录===============================
|
# ============================创建功能刀具列表、安全库存记录===============================
|
||||||
# 封装功能刀具数据
|
# 封装功能刀具数据
|
||||||
@@ -820,7 +820,7 @@ class ProductProduct(models.Model):
|
|||||||
stock_location_id = self.env['stock.location'].search([('name', '=', '组装后')])
|
stock_location_id = self.env['stock.location'].search([('name', '=', '组装后')])
|
||||||
# 创建功能刀具该批次/序列号 库存移动和移动历史
|
# 创建功能刀具该批次/序列号 库存移动和移动历史
|
||||||
stock_lot.create_stock_quant(location_inventory_id, stock_location_id, functional_tool_assembly.id,
|
stock_lot.create_stock_quant(location_inventory_id, stock_location_id, functional_tool_assembly.id,
|
||||||
'功能刀具组装', obj, obj.after_tool_groups_id)
|
self.assembly_order_code, obj, obj.after_tool_groups_id)
|
||||||
|
|
||||||
return stock_lot
|
return stock_lot
|
||||||
|
|
||||||
@@ -846,7 +846,7 @@ class ProductProduct(models.Model):
|
|||||||
num = "%03d" % m
|
num = "%03d" % m
|
||||||
return code + str(num)
|
return code + str(num)
|
||||||
|
|
||||||
def tool_material_stock_moves(self, tool_material):
|
def tool_material_stock_moves(self, tool_material, assembly_order_code):
|
||||||
"""
|
"""
|
||||||
对刀具物料进行库存移动到 刀具组装位置
|
对刀具物料进行库存移动到 刀具组装位置
|
||||||
"""
|
"""
|
||||||
@@ -854,12 +854,12 @@ class ProductProduct(models.Model):
|
|||||||
location_inventory_id = tool_material.quant_ids.location_id[-1]
|
location_inventory_id = tool_material.quant_ids.location_id[-1]
|
||||||
stock_location_id = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
|
stock_location_id = self.env['stock.location'].search([('name', '=', '刀具组装位置')])
|
||||||
# 创建功能刀具该批次/序列号 库存移动和移动历史
|
# 创建功能刀具该批次/序列号 库存移动和移动历史
|
||||||
tool_material.create_stock_quant(location_inventory_id, stock_location_id, None, '功能刀具组装', False, False)
|
tool_material.create_stock_quant(location_inventory_id, stock_location_id, None, assembly_order_code, False, False)
|
||||||
|
|
||||||
def material_stock_moves(self, shelf_location_barcode):
|
def material_stock_moves(self, shelf_location_barcode, assembly_order_code):
|
||||||
# 创建库存移动记录
|
# 创建库存移动记录
|
||||||
stock_move_id = self.env['stock.move'].sudo().create({
|
stock_move_id = self.env['stock.move'].sudo().create({
|
||||||
'name': '功能刀具组装',
|
'name': assembly_order_code,
|
||||||
'product_id': self.id,
|
'product_id': self.id,
|
||||||
'location_id': self.env['stock.location'].search([('name', '=', '刀具房')]).id,
|
'location_id': self.env['stock.location'].search([('name', '=', '刀具房')]).id,
|
||||||
'location_dest_id': self.env['stock.location'].search([('name', '=', '刀具组装位置')]).id,
|
'location_dest_id': self.env['stock.location'].search([('name', '=', '刀具组装位置')]).id,
|
||||||
|
|||||||
Reference in New Issue
Block a user