Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/订单计划

# Conflicts:
#	sf_maintenance/__manifest__.py
#	sf_manufacturing/views/mrp_workcenter_views.xml
This commit is contained in:
qihao.gong@jikimo.com
2023-07-14 09:02:48 +08:00
41 changed files with 846 additions and 208 deletions

View File

@@ -156,30 +156,27 @@ if env.user.has_group('mrp.group_mrp_workorder_dependencies'):
</field>
</record>
<record model="ir.actions.act_window" id="mrp_workorder_action_tablet">
<field name="name">Work Orders</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.workorder</field>
<field name="view_mode">kanban,tree,form</field>
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'kanban', 'view_id': ref('mrp.workcenter_line_kanban')}),
(0, 0, {'view_mode': 'tree', 'view_id': ref('mrp.mrp_production_workorder_tree_editable_view')}) ]"/>
<field name="target">fullscreen</field>
<field name="domain">[('state', 'not in', ['done', 'cancel'])]</field>
<field name="context">{'search_default_workcenter_id': active_id}</field>
<field name="help" type="html">
<p class="o_view_nocontent_workorder">
No work orders to do!
</p><p>
Work orders are operations to do as part of a manufacturing order.
Operations are defined in the bill of materials or added in the manufacturing order directly.
</p><p>
Use the table work center control panel to register operations in the shop floor directly.
The tablet provides worksheets for your workers and allow them to scrap products, track time,
launch a maintenance request, perform quality tests, etc.
</p>
</field>
</record>
<!-- <record model="ir.actions.act_window" id="mrp_workorder_action_tablet">-->
<!-- <field name="name">Work Orders</field>-->
<!-- <field name="type">ir.actions.act_window</field>-->
<!-- <field name="res_model">mrp.workorder</field>-->
<!-- <field name="target">fullscreen</field>-->
<!-- <field name="domain">[('state', 'not in', ['done', 'cancel'])]</field>-->
<!-- <field name="context">{'search_default_workcenter_id': active_id}</field>-->
<!-- <field name="help" type="html">-->
<!-- <p class="o_view_nocontent_workorder">-->
<!-- No work orders to do!-->
<!-- </p><p>-->
<!-- Work orders are operations to do as part of a manufacturing order.-->
<!-- Operations are defined in the bill of materials or added in the manufacturing order directly.-->
<!-- </p><p>-->
<!-- Use the table work center control panel to register operations in the shop floor directly.-->
<!-- The tablet provides worksheets for your workers and allow them to scrap products, track time,-->
<!-- launch a maintenance request, perform quality tests, etc.-->
<!-- </p>-->
<!-- </field>-->
<!-- </record>-->
<!-- override to change the no content image -->
<record model="ir.actions.act_window" id="mrp.mrp_workorder_todo">

View File

@@ -1,2 +1,4 @@
from . import models
from . import commons
from . import wizard

View File

@@ -18,6 +18,8 @@
'views/common_view.xml',
'views/fixture_view.xml',
'views/functional_fixture_view.xml',
'wizard/workpiece_clamping_wizard_view.xml',
'wizard/stock_removal_wizard_view.xml',
'views/menu_view.xml',
"views/tool_views.xml",
"views/tool_menu.xml",

View File

@@ -16,7 +16,7 @@ class FunctionalFixture(models.Model):
code = fields.Char(string='编码', readonly=True)
name = fields.Char(string="名称", size=15, required=True)
functional_fixture_type_id = fields.Many2one('sf.functional.fixture.type', string="功能夹具类型", required=True)
type_id = fields.Many2one('sf.functional.fixture.type', string="功能夹具类型", required=True)
zero_chuck_model_ids = fields.Many2many('sf.fixture.model', 'rel_fixture_model_zero_chuck', string="零点卡盘型号",
required=True,
domain=[('fixture_material_type', '=', '零点卡盘')])

View File

@@ -14,20 +14,20 @@ access_sf_supplier_sort,sf_supplier_sort,model_sf_supplier_sort,base.group_user,
access_sf_production_process_parameter,sf_production_process_parameter,model_sf_production_process_parameter,base.group_user,1,1,1,1
access_sf_production_process_category,sf_production_process_category,model_sf_production_process_category,base.group_user,1,1,1,1
access_sf_machine_tool_category,sf_machine_tool_category,model_sf_machine_tool_category,base.group_user,1,1,1,1
access_sf_cutting_tool_material,sf_cutting_tool_material,model_sf_cutting_tool_material,base.group_user,1,1,1,1
access_sf_cutting_tool_type,sf_cutting_tool_type,model_sf_cutting_tool_type,base.group_user,1,1,1,1
access_sf_cutting_tool_model,sf_cutting_tool_model,model_sf_cutting_tool_model,base.group_user,1,1,1,1
access_sf_functional_cutting_tool,sf_functional_cutting_tool,model_sf_functional_cutting_tool,base.group_user,1,1,1,1
access_sf_functional_cutting_tool_model,sf_functional_cutting_tool_model,model_sf_functional_cutting_tool_model,base.group_user,1,1,1,1
access_sf_fixture_material,sf_fixture_material,model_sf_fixture_material,base.group_user,1,1,1,1
access_sf_multi_mounting_type,sf_multi_mounting_type,model_sf_multi_mounting_type,base.group_user,1,1,1,1
access_sf_fixture_model,sf_fixture_model,model_sf_fixture_model,base.group_user,1,1,1,1
access_sf_functional_fixture_type,sf_functional_fixture_type,model_sf_functional_fixture_type,base.group_user,1,1,1,1
access_sf_functional_fixture,sf_functional_fixture,model_sf_functional_fixture,base.group_user,1,1,1,1
access_sf_workpiece_clamping_wizard,sf_workpiece_clamping_wizard,model_sf_workpiece_clamping_wizard,base.group_user,1,1,1,1
access_sf_stock_removal_wizard,sf_stock_removal_wizard,model_sf_stock_removal_wizard,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
14 access_sf_production_process_parameter sf_production_process_parameter model_sf_production_process_parameter base.group_user 1 1 1 1
15 access_sf_production_process_category sf_production_process_category model_sf_production_process_category base.group_user 1 1 1 1
16 access_sf_machine_tool_category sf_machine_tool_category model_sf_machine_tool_category base.group_user 1 1 1 1
access_sf_cutting_tool_material sf_cutting_tool_material model_sf_cutting_tool_material base.group_user 1 1 1 1
17 access_sf_cutting_tool_type access_sf_cutting_tool_material sf_cutting_tool_type sf_cutting_tool_material model_sf_cutting_tool_type model_sf_cutting_tool_material base.group_user 1 1 1 1
18 access_sf_cutting_tool_model access_sf_cutting_tool_type sf_cutting_tool_model sf_cutting_tool_type model_sf_cutting_tool_model model_sf_cutting_tool_type base.group_user 1 1 1 1
19 access_sf_functional_cutting_tool access_sf_cutting_tool_model sf_functional_cutting_tool sf_cutting_tool_model model_sf_functional_cutting_tool model_sf_cutting_tool_model base.group_user 1 1 1 1
20 access_sf_functional_cutting_tool_model access_sf_functional_cutting_tool sf_functional_cutting_tool_model sf_functional_cutting_tool model_sf_functional_cutting_tool_model model_sf_functional_cutting_tool base.group_user 1 1 1 1
21 access_sf_fixture_material access_sf_functional_cutting_tool_model sf_fixture_material sf_functional_cutting_tool_model model_sf_fixture_material model_sf_functional_cutting_tool_model base.group_user 1 1 1 1
access_sf_multi_mounting_type sf_multi_mounting_type model_sf_multi_mounting_type base.group_user 1 1 1 1
access_sf_fixture_model sf_fixture_model model_sf_fixture_model base.group_user 1 1 1 1
access_sf_functional_fixture_type sf_functional_fixture_type model_sf_functional_fixture_type base.group_user 1 1 1 1
22 access_sf_functional_fixture access_sf_fixture_material sf_functional_fixture sf_fixture_material model_sf_functional_fixture model_sf_fixture_material base.group_user 1 1 1 1
23 access_sf_multi_mounting_type sf_multi_mounting_type model_sf_multi_mounting_type base.group_user 1 1 1 1
24 access_sf_fixture_model sf_fixture_model model_sf_fixture_model base.group_user 1 1 1 1
25 access_sf_functional_fixture_type sf_functional_fixture_type model_sf_functional_fixture_type base.group_user 1 1 1 1
26 access_sf_functional_fixture sf_functional_fixture model_sf_functional_fixture base.group_user 1 1 1 1
27 access_sf_workpiece_clamping_wizard sf_workpiece_clamping_wizard model_sf_workpiece_clamping_wizard base.group_user 1 1 1 1
28 access_sf_stock_removal_wizard sf_stock_removal_wizard model_sf_stock_removal_wizard base.group_user 1 1 1 1
29
30
31
32
33

View File

@@ -82,7 +82,7 @@
<tree string="功能夹具">
<field name="code"/>
<field name="name"/>
<field name="functional_fixture_type_id"/>
<field name="type_id"/>
<field name="zero_chuck_model_ids" widget="many2many_tags"/>
</tree>
</field>
@@ -98,7 +98,7 @@
<group>
<field name="code" force_save="1"/>
<field name="name"/>
<field name="functional_fixture_type_id"/>
<field name="type_id"/>
<field name="zero_chuck_model_ids" widget="many2many_tags"/>
<field name="transfer_tray_model_ids" widget="many2many_tags"/>
<field name="pneumatic_tray_model_ids" widget="many2many_tags"/>

View File

@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import workpiece_clamping_wizard
from . import stock_removal_wizard

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class StockRemovalWizard(models.Model):
_name = 'sf.stock.removal.wizard'
_description = "出库"
code = fields.Char(string="功能夹具编码", size=25, required=True)
name = fields.Char(string="功能夹具名称", size=25, required=True)
type = fields.Char(string="功能夹具类型", required=True)
production_line = fields.Char(string="生产线", required=True)
machine_tool = fields.Many2one('sf.machine_tool', string="机床", required=True)
def submit(self):
return 1

View File

@@ -0,0 +1,36 @@
<openerp>
<data>
<record model="ir.ui.view" id="stock_removal_wizard_form_view">
<field name="name">sf.stock.removal.wizard.form.view</field>
<field name="model">sf.stock.removal.wizard</field>
<field name="arch" type="xml">
<form string="装夹">
<sheet>
<group>
<group>
<field name="code" string="功能夹具编码"></field>
<field name="type" string="类型"></field>
<field name="machine_tool" string="机台"></field>
</group>
<group>
<field name="name" string="功能夹具名称"></field>
<field name="production_line"></field>
</group>
</group>
<footer>
<button string="确定" name="submit" type="object" class="oe_highlight"/>
<button string="取消" class="btn btn-secondary" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
<record id="action_stock_removal_wizard" model="ir.actions.act_window">
<field name="name">出库</field>
<field name="res_model">sf.stock.removal.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class WorkpieceClampingWizard(models.Model):
_name = 'sf.workpiece.clamping.wizard'
_description = "工件装夹"
# 以下为坯料(工件)申请信息
apply_code = fields.Char(string="申请坯料编码", size=25, required=True)
apply_name = fields.Char(string="申请坯料名称", size=25, required=True)
material_id = fields.Many2one('sf.production.materials', string="坯料材料", required=True)
apply_width = fields.Float(string="申请宽度", required=True)
apply_length = fields.Float(string="申请长度", required=True)
apply_height = fields.Float(string="申请高度", required=True)
apply_weight = fields.Float(string="申请重量", required=True)
apply_diameter = fields.Float(string="申请直径", required=True)
surface_accuracy = fields.Char(string="表面精度", required=True)
# 以下为坯料(工件)装夹信息
chuck_name = fields.Char(string="卡盘名称", required=True)
chuck_brand_id = fields.Many2one('sf.machine.brand', string="卡盘品牌", required=True)
chuck_type_id = fields.Char(string="卡盘类型", required=True)
chuck_model_id = fields.Char(string="卡盘型号", required=True)
tray_name = fields.Char(string="托盘名称", required=True)
tray_brand_id = fields.Many2one('sf.machine.brand', string="托盘品牌", required=True)
tray_type_id = fields.Char(string="托盘类型", required=True)
tray_model_id = fields.Char(string="托盘型号", required=True)
real_code = fields.Char(string="真实坯料编码", size=25, required=True)
real_name = fields.Char(string="真实坯料名称", size=25, required=True)
real_width = fields.Float(string="真实宽度", required=True)
real_length = fields.Float(string="真实长度", required=True)
real_height = fields.Float(string="真实高度", required=True)
real_diameter = fields.Float(string="真实直径", required=True)
# 以下为坯料(工件)预调信息
# hole_site = fields.Char(string="孔位", required=True)
# curve = fields.Char(string="曲线", required=True)
# straight_line = fields.Char(string="直线", required=True)
# x_axis = fields.Float(string="X轴", required=True)
# y_axis = fields.Float(string="Y轴", required=True)
# z_axis = fields.Float(string="Z轴", required=True)
# tool_radius = fields.Float(string="刀具半径", required=True)
# tool_length = fields.Float(string="刀具长度", required=True)
# tool_offset_point = fields.Float(string="刀具偏移点", required=True)
# tool_compensation_value = fields.Float(string="刀具补偿值", required=True)
# cutting_spindle_speed = fields.Float(string="切削主轴转速", required=True)
# cutting_feed_rate = fields.Float(string="切削进给速度", required=True)
# depth_of_cutting = fields.Float(string="切削深度", required=True)
# cutting_direction = fields.Char(string="切削方向", required=True)
preset_program_information = fields.Char(string="预调程序信息", required=True)
def submit(self):
return 1

View File

@@ -0,0 +1,87 @@
<openerp>
<data>
<record model="ir.ui.view" id="workpiece_clamping_wizard_form_view">
<field name="name">sf.workpiece.clamping.wizard.form.view</field>
<field name="model">sf.workpiece.clamping.wizard</field>
<field name="arch" type="xml">
<form string="装夹">
<sheet>
<group string="坯料(工件)申请信息">
<group>
<field name="apply_code" string="坯料编码"></field>
<field name="material_id" string="坯料材质"></field>
</group>
<group>
<field name="apply_name" string="坯料名称"></field>
<label for="apply_length" string="尺寸[mm]"/>
<div class="o_address_format">
<label for="apply_length" string="长"/>
<field name="apply_length" class="o_address_zip"
options="{'format': false}"/>
<span>&amp;nbsp;</span>
<label for="apply_width" string="宽"/>
<field name="apply_width" class="o_address_zip"
options="{'format': false}"/>
<span>&amp;nbsp;</span>
<label for="apply_height" string="高"/>
<field name="apply_height" class="o_address_zip"
options="{'format': false}"/>
</div>
<field name="apply_diameter" string="直径[mm]"></field>
</group>
</group>
<group string="坯料(工件)装夹信息">
<group string="卡盘">
<field name="chuck_type_id"></field>
<field name="chuck_name"></field>
<field name="chuck_brand_id"></field>
<field name="chuck_model_id"></field>
</group>
<group string="托盘">
<field name="tray_type_id"></field>
<field name="tray_name"></field>
<field name="tray_brand_id"></field>
<field name="tray_model_id"></field>
</group>
<group string="坯料">
<field name="real_code" string="坯料编码"></field>
<field name="real_name" string="坯料名称"></field>
<label for="real_length" string="尺寸[mm]"/>
<div class="o_address_format">
<label for="real_length" string="长"/>
<field name="real_length" class="o_address_zip"
options="{'format': false}"/>
<span>&amp;nbsp;</span>
<label for="real_width" string="宽"/>
<field name="real_width" class="o_address_zip"
options="{'format': false}"/>
<span>&amp;nbsp;</span>
<label for="real_height" string="高"/>
<field name="real_height" class="o_address_zip"
options="{'format': false}"/>
</div>
<field name="real_diameter" string="直径[mm]"></field>
</group>
</group>
<group>
<group>
<field name="preset_program_information"></field>
</group>
</group>
<footer>
<button string="确定" name="submit" type="object" class="oe_highlight"/>
<button string="取消" class="btn btn-secondary" special="cancel"/>
</footer>
</sheet>
</form>
</field>
</record>
<record id="action_workpiece_clamping_wizard" model="ir.actions.act_window">
<field name="name">装夹</field>
<field name="res_model">sf.workpiece.clamping.wizard</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>

View File

@@ -33,8 +33,8 @@ class StatusChange(models.Model):
'process_start_time': process_start_time,
},
}
url1 = config['bfm_url'] + '/api/get/state/get_order'
requests.post(url1, json=json1, data=None)
# url1 = config['bfm_url'] + '/api/get/state/get_order'
# requests.post(url1, json=json1, data=None)
logging.info('接口已经执行=============')
return res
@@ -57,8 +57,8 @@ class StatusChange(models.Model):
'state': '待派单',
},
}
url1 = config['bfm_url'] + '/api/get/state/cancel_order'
requests.post(url1, json=json1, data=None)
# url1 = config['bfm_url'] + '/api/get/state/cancel_order'
# requests.post(url1, json=json1, data=None)
return res

View File

@@ -12,7 +12,6 @@
'data': [
'security/group_security.xml',
'security/ir.model.access.csv',
'views/production_line_view.xml',
'views/maintenance_views.xml',
'views/maintenance_logs_views.xml',
'views/equipment_maintenance_standards_views.xml',

View File

@@ -3,4 +3,3 @@ from . import sf_maintenance
from . import sf_maintenance_logs
from . import sf_equipment_maintenance_standards
from . import sf_maintenance_requests
from . import production_line_base

View File

@@ -66,7 +66,7 @@ class SfMaintenanceEquipment(models.Model):
MTcode = fields.Char("编码", default=get_no)
created_user = fields.Many2one('res.users', string='创建人', default=lambda self: self.env.user)
equipment_type = fields.Selection([('机床', '机床')], related='category_id.equipment_type')
code = fields.Char('行业编码')
code = fields.Char('机台号')
name = fields.Char('名称')
knife_type = fields.Selection(
[("BT40", "BT40"), ("BT30", "BT30")],
@@ -144,7 +144,16 @@ class SfMaintenanceEquipment(models.Model):
control_system_id = fields.Many2one('sf.machine.control_system',
string="控制系统")
active = fields.Boolean('有效', default=True)
code = fields.Char('编码')
def name_get(self):
result = []
for parameter in self:
if parameter.code:
name = parameter.name + '-' + parameter.code
else:
name = parameter.name
result.append((parameter.id, name))
return result
@api.constrains('rotate_speed')
def _check_rotate_speed(self):

View File

@@ -4,6 +4,6 @@ access_sf_maintenance_logs,sf_maintenance_logs,model_sf_maintenance_logs,base.gr
access_maintenance_equipment,maintenance_equipment,model_maintenance_equipment,base.group_user,1,1,1,1
access_maintenance_standards,maintenance_standards,model_maintenance_standards,base.group_user,1,1,1,1
access_sf_production_line,sf.production.line,model_sf_production_line,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
4 access_maintenance_equipment maintenance_equipment model_maintenance_equipment base.group_user 1 1 1 1
5 access_maintenance_standards maintenance_standards model_maintenance_standards base.group_user 1 1 1 1
6
7
8
9

View File

@@ -20,6 +20,7 @@
'views/mrp_routing_workcenter_view.xml',
'views/mrp_workcenter_views.xml',
'views/mrp_workorder_view.xml',
'views/production_line_view.xml',
'views/tray_view.xml',
'views/model_type_view.xml',

View File

@@ -8,6 +8,7 @@ from . import mrp_maintenance
from . import mrp_routing_workcenter
from . import stock
from . import res_user
from . import production_line_base

View File

@@ -6,11 +6,14 @@ from odoo import api, fields, models, _
class MrpProduction(models.Model):
_inherit = 'mrp.production'
_description = "制造订单"
_order = 'create_date desc'
tray_ids = fields.One2many('sf.tray', 'production_id', string="托盘")
maintenance_count = fields.Integer(compute='_compute_maintenance_count', string="Number of maintenance requests")
request_ids = fields.One2many('maintenance.request', 'production_id')
model_file = fields.Binary('模型文件', related='product_id.model_file')
schedule_state = fields.Selection([('未排', '未排'), ('已排', '已排')],
string='排程状态', default='未排')
@api.depends('request_ids')
def _compute_maintenance_count(self):
@@ -336,7 +339,7 @@ class MrpProduction(models.Model):
current_sequence += 1
if work.name == '获取CNC加工程序':
work.button_start()
work.fetchCNC()
#work.fetchCNC()
# 创建工单并进行排序
def _create_workorder(self):

View File

@@ -6,7 +6,9 @@ from odoo.addons.resource.models.resource import Intervals
class ResWorkcenter(models.Model):
_inherit = "mrp.workcenter"
machine_tool_id = fields.Many2one('sf.machine_tool', '机床')
equipment_id = fields.Many2one('maintenance.equipment', string='设备')
machine_tool_id = fields.Many2one('sf.machine_tool', string='机床')
production_line_id = fields.Many2one('sf.production.line', string='生产线')
is_process_outsourcing = fields.Boolean('工艺外协')
users_ids = fields.Many2many("res.users", 'users_workcenter')

View File

@@ -16,7 +16,7 @@ from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
_order = 'sequence'
_order = 'sequence asc,create_date desc'
product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True,
check_company=True, string="坯料长度(mm)")
@@ -28,7 +28,7 @@ class ResMrpWorkOrder(models.Model):
store=True, check_company=True, string="材料")
product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id',
readonly=True, store=True, check_company=True, string="型号")
workcenter_id = fields.Many2one('mrp.workcenter', required=False)
workcenter_id = fields.Many2one('mrp.workcenter', string='工作中心', required=False)
users_ids = fields.Many2many("res.users", 'users_workorder', related="workcenter_id.users_ids")
processing_panel = fields.Char('加工面')
sequence = fields.Integer(string='工序')
@@ -106,6 +106,35 @@ class ResMrpWorkOrder(models.Model):
picking_in_id = fields.Many2one('stock.picking', string='外协入库单')
picking_out_id = fields.Many2one('stock.picking', string='外协出库单')
supplier_id = fields.Many2one('res.partner', string='外协供应商')
equipment_id = fields.Many2one('maintenance.equipment', string='加工设备')
schedule_state = fields.Selection(related='production_id.schedule_state', store=True)
# 工件装夹信息
functional_fixture_code = fields.Char(string="功能夹具编码", readonly=True)
functional_fixture_serial_number = fields.Char(string="功能夹具序列号", readonly=True)
functional_fixture_id = fields.Many2one('sf.functional.fixture', string="功能夹具")
functional_fixture_type_id = fields.Many2one('sf.functional.fixture.type', string="功能夹具类型", readonly=True)
chuck_serial_number = fields.Char(string="卡盘序列号")
chuck_name = fields.Char(string="卡盘名称")
chuck_brand_id = fields.Many2one('sf.machine.brand', string="卡盘品牌")
chuck_type_id = fields.Char(string="卡盘类型")
chuck_model_id = fields.Char(string="卡盘型号")
tray_serial_number = fields.Char(string="卡盘序列号")
tray_name = fields.Char(string="托盘名称")
tray_brand_id = fields.Many2one('sf.machine.brand', string="托盘品牌")
tray_type_id = fields.Char(string="托盘类型")
tray_model_id = fields.Char(string="托盘型号")
total_wight = fields.Float(string="总重量")
maximum_carrying_weight = fields.Char(string="最大承载重量[kg]")
maximum_clamping_force = fields.Char(string="最大夹持力[n]")
production_line = fields.Char(string="生产线")
preset_program_information = fields.Char(string="预调程序信息")
@api.onchange('functional_fixture_id')
def _onchange_functional_fixture_id(self):
if self.functional_fixture_id:
self.functional_fixture_code = self.functional_fixture_id.code
self.functional_fixture_type_id = self.functional_fixture_id.type_id.id
def get_no_data(self, production_id):
process_parameter_workorder = self.search(
@@ -165,7 +194,7 @@ class ResMrpWorkOrder(models.Model):
'operation_id': False,
'name': route.route_workcenter_id.name,
'processing_panel': k,
'quality_point_ids':route.route_workcenter_id.quality_point_ids,
'quality_point_ids': route.route_workcenter_id.quality_point_ids,
'routing_type': route.routing_type,
'work_state': '' if not route.routing_type == '获取CNC加工程序' else '待发起',
'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids,

View File

@@ -231,18 +231,8 @@ class ProductionLot(models.Model):
1]
now = datetime.now().strftime("%Y-%m-%d")
# formatted_date = now.strftime("%Y-%m-%d")
if product.integral_cutting_tool_type_id:
return "%s-%s-%03d" % (product.integral_cutting_tool_type_id.code, now, 1)
if product.blade_type_id:
return "%s-%s-%03d" % (product.blade_type_id.code, now, 1)
if product.cutter_bar_type_id:
return "%s-%s-%03d" % (product.cutter_bar_type_id.code, now, 1)
if product.cutter_pad_type_id:
return "%s-%s-%03d" % (product.cutter_pad_type_id.code, now, 1)
if product.handle_type_id:
return "%s-%s-%03d" % (product.handle_type_id.code, now, 1)
if product.chuck_type_id:
return "%s-%s-%03d" % (product.chuck_type_id.code, now, 1)
if product.cutting_tool_model_id:
return "%s-%s-%03d" % (product.cutting_tool_model_id.code, now, 1)
return "%s-%03d" % (product.name, 1)

View File

@@ -5,7 +5,7 @@ access_sf_product_model_type_routing_sort,sf_product_model_type_routing_sort,mod
access_sf_embryo_model_type_routing_sort,sf_embryo_model_type_routing_sort,model_sf_embryo_model_type_routing_sort,base.group_user,1,1,1,1
access_sf_surface_technics_model_type_routing_sort,sf_surface_technics_model_type_routing_sort,model_sf_surface_technics_model_type_routing_sort,base.group_user,1,1,1,1
access_sf_production_line,sf.production.line,model_sf_production_line,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
5 access_sf_embryo_model_type_routing_sort sf_embryo_model_type_routing_sort model_sf_embryo_model_type_routing_sort base.group_user 1 1 1 1
6 access_sf_surface_technics_model_type_routing_sort sf_surface_technics_model_type_routing_sort model_sf_surface_technics_model_type_routing_sort base.group_user 1 1 1 1
7 access_sf_production_line sf.production.line model_sf_production_line base.group_user 1 1 1 1
8
9
10
11

View File

@@ -91,8 +91,8 @@
<xpath expr="//field[@name='company_id']" position="after">
<field name="users_ids" widget="many2many_tags" string="可操作用户"/>
</xpath>
<xpath expr="//field[@name='alternative_workcenter_ids']" position="after">
<field name="production_line_id"/>
<field name="equipment_id"/>
</xpath>
<xpath expr="//field[@name='resource_calendar_id']" position="after">

View File

@@ -7,6 +7,7 @@
<field name="arch" type="xml">
<field name="name" position="replace">
<field name="is_subcontract" invisible="1"/>
<field name="name" decoration-success="is_subcontract" decoration-bf="is_subcontract"/>
</field>
<field name="name" position="before">
@@ -19,6 +20,9 @@
<field name="state" position="after">
<field name="work_state" optional="hide"/>
</field>
<field name="product_id" position="after">
<field name="equipment_id" optional="hide"/>
</field>
<xpath expr="//field[@name='date_planned_start']" position="replace">
<field name="date_planned_start" string="计划开始日期" optional="show"/>
</xpath>
@@ -73,7 +77,7 @@
(0, 0, {'view_mode': 'kanban', 'view_id': ref('mrp.workcenter_line_kanban')}) ]"/>
<!-- <field name="target">fullscreen</field>-->
<field name="target">current</field>
<field name="domain">[('state', '!=', 'cancel')]</field>
<field name="domain">[('state', '!=', 'cancel'),('schedule_state', '=', '已排')]</field>
<field name="context">{'search_default_workcenter_id': active_id}</field>
<field name="help" type="html">
<p class="o_view_nocontent_workorder">
@@ -91,17 +95,6 @@
</field>
</record>
<!-- <record model="ir.ui.view" id="view_mrp_production_workorder_form_inherit_sf">-->
<!-- <field name="name">mrp.production.workorder.form.inherit.sf</field>-->
<!-- <field name="model">mrp.workorder</field>-->
<!-- <field name="inherit_id" ref="mrp.mrp_production_workorder_form_view_inherit"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <field name="production_id" position="after">-->
<!-- <field name="processing_panel" readonly="1"/>-->
<!-- </field>-->
<!-- </field>-->
<!-- </record>-->
<record id="view_mrp_production_workorder_tray_form_inherit_sf" model="ir.ui.view">
<field name="name">mrp.production.workorder.tray.form.inherit.sf</field>
<field name="model">mrp.workorder</field>
@@ -111,13 +104,15 @@
<field name='user_permissions' invisible="1"/>
<field name='name' invisible="1"/>
<field name='routing_type' invisible="1"/>
<button name="button_start" type="object" string="开始" class="btn-success"
attrs="{'invisible': ['|', '|', '|','|','|', ('production_state','in', ('draft', 'done',
'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),
('is_user_working', '!=', False),('user_permissions','=',False),('name','=','获取CNC加工程序')]}"/>
<button name="button_pending" type="object" string="暂停" class="btn-warning"
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False),('name','=','获取CNC加工程序')]}"/>
<button name="button_finish" type="object" string="完成" class="btn-success"/>
<button name="button_finish" type="object" string="完成" class="btn-success"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/>
<button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="停工"
context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
attrs="{'invisible': ['|', '|','|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'),('user_permissions','=',False),('name','=','获取CNC加工程序')]}"/>
@@ -125,12 +120,15 @@
context="{'default_workcenter_id': workcenter_id}" class="btn-danger"
attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked'),('name','=','获取CNC加工程序')]}"/>
</xpath>
<!-- 隐藏物料清单-->
<!-- <xpath expr="//page[@name='components']" position="attributes">-->
<!-- <attribute name="invisible">1</attribute>-->
<!-- </xpath>-->
<!-- 隐藏物料清单-->
<!-- 隐藏物料清单-->
<!-- <xpath expr="//page[@name='components']" position="attributes">-->
<!-- <attribute name="invisible">1</attribute>-->
<!-- </xpath>-->
<!-- 隐藏物料清单-->
<xpath expr="//page[@name='components']" position="attributes">
<attribute name="string">物料</attribute>
</xpath>
<field name="production_id" position="after" invisible="0">
<group>
<field name="date_planned_start" invisible="1"/>
@@ -141,6 +139,14 @@
sum="real duration"/>
<field name="processing_panel" readonly="1"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
<field name="equipment_id"
attrs='{"invisible": [("routing_type","in",("获取CNC加工程序","切割"))]}'/>
<field name="functional_fixture_id"
attrs='{"invisible": [("routing_type","!=","装夹")]}'/>
<field name="functional_fixture_code" force_save="1"
attrs='{"invisible": [("routing_type","!=","装夹")]}'/>
<field name="functional_fixture_type_id" force_save="1"
attrs='{"invisible": [("routing_type","!=","装夹")]}'/>
</group>
<group attrs='{"invisible": [("routing_type","=","获取CNC加工程序")]}'>
<div>
@@ -165,36 +171,55 @@
<group>
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
<button type="object" class="oe_highlight" name="fetchCNC" string="获取CNC程序代码"
/>
/>
</div>
</group>
</page>
</xpath>
<!-- <page string="Components" name="components">-->
<xpath expr="//page[1]" position="before">
<page string="装夹托盘" attrs='{"invisible": [("routing_type","!=","装夹")]}'>
<group>
<field name="routing_type" invisible="1"/>
<field name="tray_code"/>
<field name="tray_id" readonly="1"/>
</group>
<group>
<field name="pro_code" readonly="1" attrs='{"invisible": [("pro_code_ok","=",False)]}'
style="color:green"/>
<field name="pro_code" readonly="1" attrs='{"invisible": [("pro_code_ok","!=",False)]}'/>
<div>
<field name="pro_code_ok" invisible="1"/>
</div>
<!-- <page string="装夹托盘" attrs='{"invisible": [("routing_type","!=","装夹")]}'>-->
<!-- <group>-->
<!-- <field name="routing_type" invisible="1"/>-->
<!-- <field name="tray_code"/>-->
<!-- <field name="tray_id" readonly="1"/>-->
<!-- </group>-->
<!-- <group>-->
<!-- <field name="pro_code" readonly="1" attrs='{"invisible": [("pro_code_ok","=",False)]}'-->
<!-- style="color:green"/>-->
<!-- <field name="pro_code" readonly="1" attrs='{"invisible": [("pro_code_ok","!=",False)]}'/>-->
<!-- <div>-->
<!-- <field name="pro_code_ok" invisible="1"/>-->
<!-- </div>-->
</group>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="gettray" string="绑定托盘"
attrs='{"invisible": ["|","|",("tray_id","!=",False),("state","!=","progress"),("production_id","=",False)]}'/>
<!-- </group>-->
<!-- <div class="col-12 col-lg-6 o_setting_box">-->
<!-- <button type="object" class="oe_highlight" name="gettray" string="绑定托盘"-->
<!-- attrs='{"invisible": ["|","|",("tray_id","!=",False),("state","!=","progress"),("production_id","=",False)]}'/>-->
</div>
<!-- </div>-->
<!-- </page>-->
<page string="工件装夹" attrs='{"invisible": [("routing_type","!=","装夹")]}'>
<group>
<group string="卡盘">
<field name="chuck_serial_number"/>
<field name="chuck_name"/>
<field name="chuck_brand_id"/>
<field name="chuck_type_id"/>
<field name="chuck_model_id"/>
</group>
<group string="托盘">
<field name="tray_serial_number"/>
<field name="tray_name"/>
<field name="tray_brand_id"/>
<field name="tray_type_id"/>
<field name="tray_model_id"/>
</group>
</group>
<group string="预调程序信息">
<field name="preset_program_information" colspan="2" nolabel="1"
placeholder="如有预调程序信息请在此处输入....."/>
</group>
</page>
</xpath>
@@ -410,5 +435,25 @@
</xpath>
</field>
</record>
<record id="mrp_workorder_action_schedule" model="ir.actions.act_window">
<field name="name">工单</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">mrp.workorder</field>
<field name="view_mode">tree,kanban,form</field>
<field name="view_id" ref="mrp.mrp_production_workorder_tree_editable_view"/>
<field name="search_view_id" ref="mrp.view_mrp_production_work_order_search"/>
<field name="domain">[('schedule_state', '=', '已排')]</field>
</record>
<menuitem id="menu_mrp_workorder_schedule_todo"
name="工单"
action="mrp_workorder_action_schedule"
parent="mrp.menu_mrp_manufacturing"
sequence="15"/>
<record id="mrp.menu_mrp_workorder_todo" model="ir.ui.menu">
<field name="active" eval="False"/>
</record>
</odoo>

View File

@@ -1771,7 +1771,7 @@ class SyncFunctionalFixture(models.Model):
self.env['sf.functional.fixture'].create({
"name": item['name'],
"code": item['code'],
"functional_fixture_type_id": self.env['sf.functional.fixture.type'].search(
"type_id": self.env['sf.functional.fixture.type'].search(
[("code", '=', item['functional_fixture_type_code'])]).id,
"zero_chuck_model_ids": self._get_fixture_model_ids(item['zero_chuck_model_codes']),
"transfer_tray_model_ids": self._get_fixture_model_ids(
@@ -1785,7 +1785,7 @@ class SyncFunctionalFixture(models.Model):
else:
functional_fixture.write({
"name": item['name'],
"functional_fixture_type_id": self.env['sf.functional.fixture.type'].search(
"type_id": self.env['sf.functional.fixture.type'].search(
[("code", '=', item['functional_fixture_type_code'])]).id,
"zero_chuck_model_ids": self._get_fixture_model_ids(item['zero_chuck_model_codes']),
"transfer_tray_model_ids": self._get_fixture_model_ids(
@@ -1820,7 +1820,7 @@ class SyncFunctionalFixture(models.Model):
self.env['sf.functional.fixture'].create({
"name": item['name'],
"code": item['code'],
"functional_fixture_type_id": self.env['sf.functional.fixture.type'].search(
"type_id": self.env['sf.functional.fixture.type'].search(
[("code", '=', item['functional_fixture_type_code'])]).id,
"zero_chuck_model_ids": self._get_fixture_model_ids(item['zero_chuck_model_codes']),
"transfer_tray_model_ids": self._get_fixture_model_ids(
@@ -1834,7 +1834,7 @@ class SyncFunctionalFixture(models.Model):
else:
functional_fixture.write({
"name": item['name'],
"functional_fixture_type_id": self.env['sf.functional.fixture.type'].search(
"type_id": self.env['sf.functional.fixture.type'].search(
[("code", '=', item['functional_fixture_type_code'])]).id,
"zero_chuck_model_ids": self._get_fixture_model_ids(item['zero_chuck_model_codes']),
"transfer_tray_model_ids": self._get_fixture_model_ids(

View File

@@ -10,11 +10,11 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['sf_maintenance'],
'depends': ['sf_manufacturing'],
'data': [
'security/ir.model.access.csv',
# 'security/ir.model.access.csv',
'views/paln_base_view.xml',
'views/plan_base_view.xml',
'views/menu_view.xml',
],
'demo': [

View File

@@ -19,7 +19,7 @@ class ProcedureEquipmentResourceSetting(models.Model):
working_procedure = fields.Char(string='工序', readonly=True)
production_capacity = fields.Float(string='产能', required=True, digits=(4, 1))
working_calendar_id = fields.Many2one('sf.work.log.setting', string='工作日历')
working_shift = fields.Char(string='班次', readonly=True, compute='_onchange_working_calendar_id')
working_shift_id = fields.Many2many('sf.working.shift', string='班次', readonly=True, compute='_onchange_working_calendar_id')
create_time = fields.Datetime(string='新增时间', default=lambda self: fields.Datetime.now(), readonly=True)
status = fields.Selection([('正常', '正常'), ('1', '故障停机'), ('2', '计划停机')],
string='设备状态',
@@ -49,7 +49,7 @@ class ProcedureEquipmentResourceSetting(models.Model):
@api.depends('working_calendar_id')
def _onchange_working_calendar_id(self):
for record in self:
record.working_shift = record.working_calendar_id.working_shift
record.working_shift_id = record.working_calendar_id.working_shift_id

View File

@@ -1,3 +1,5 @@
from datetime import datetime, timedelta, date
from odoo import models, fields, api
import re
@@ -45,29 +47,21 @@ class WorkLogSetting(models.Model):
end_time_M = fields.Selection(time_M_or_S_selection(), '', required=True)
duration = fields.Char(string='时长', readonly=True, compute='_compute_duration')
day_off = fields.Char(string='休息日', required=True)
day_off_id = fields.Many2many('sf.day.off', string='休息日', required=True)
user_defined_working_shift_status = fields.Boolean(string='自定义班次', default=False)
working_shift = fields.Char(string='班次')
working_shift_char = fields.Char(string='班次', readonly=True, compute='_compute_working_shift_time')
working_shift_select = fields.Selection([('早班00:00-08:00', '早班00:00-08:00'),
('白班08:00-16:00', '白班08:00-16:00'),
('晚班16:00-24:00', '晚班16:00-24:00'),
('长白班08:00-20:00', '长白班08:00-20:00'),
('长晚班20:00-08:00', '长晚班20:00-08:00')], string='班次')
working_shift_start_time_H = fields.Selection(time_H_selection(), '班次开始时间:时',
attr={'required': [('user_defined_working_shift_status', '=', 'True')]})
working_shift_start_time_M = fields.Selection(time_M_or_S_selection(), '',
attr={'required': [('user_defined_working_shift_status', '=', 'True')]})
working_shift_end_time_H = fields.Selection(time_H_selection(), '班次结束时间:时',
attr={'required': [('user_defined_working_shift_status', '=', 'True')]})
working_shift_end_time_M = fields.Selection(time_M_or_S_selection(), '',
attr={'required': [('user_defined_working_shift_status', '=', 'True')]})
working_shift_id = fields.Many2many('sf.working.shift', string='班次')
status = fields.Boolean(string='状态', default=True)
update_person = fields.Char(string='更新人', default=lambda self: self.env.user.name)
update_time = fields.Datetime(string='更新时间', default=lambda self: fields.Datetime.now())
setting_to_calendar_ids = fields.One2many('sf.work.schedule.calendar', 'name_id', '工作日历')
# @api.model
# def create(self, vals):
# vals['setting_to_calendar_ids'] = [(4, child.id)]
# return super(WorkLogSetting, self).create(vals)
@api.depends('start_time_H', 'start_time_M')
def _compute_start_time(self):
"""
@@ -86,27 +80,7 @@ class WorkLogSetting(models.Model):
for record in self:
record.end_time = f"{record.end_time_H}:{record.end_time_M}:00"
@api.onchange('working_shift_char', 'working_shift_select')
def _onchange_working_shift(self):
"""
对班次是否手动输入是进行不同的展示
:return:
"""
for record in self:
if record.working_shift_select:
record.working_shift = record.working_shift_select
else:
record.working_shift = record.working_shift_char
@api.depends(
'working_shift_start_time_H', 'working_shift_start_time_M',
'working_shift_end_time_H', 'working_shift_end_time_M')
def _compute_working_shift_time(self):
start_time = f"{self.working_shift_start_time_H}:{self.working_shift_start_time_M}:00"
end_time = f"{self.working_shift_end_time_H}:{self.working_shift_end_time_M}:00"
self.working_shift_char = f"自定义班次{start_time}-{end_time}"
@api.depends('start_time_H', 'start_time_M', 'end_time_H', 'end_time_M')
@api.depends('start_time_H', 'start_time_M', 'end_time_H', 'end_time_M')
def _compute_duration(self):
"""
根据日开始时间和日结束时间计算每日工作时长
@@ -119,6 +93,160 @@ class WorkLogSetting(models.Model):
end_m = float(record.end_time_M)
# 日开始时间小于日结束时间
if st_h < end_h:
record.duration = str(round(end_h-st_h+(end_m-st_m)/60, 2))
record.duration = str(round(end_h - st_h + (end_m - st_m) / 60, 2))
else:
record.duration = str(round(end_h-st_h+(end_m-st_m)/60+24, 2))
record.duration = str(round(end_h - st_h + (end_m - st_m) / 60 + 24, 2))
# @api.onchange('day_off_id')
# def _onchange_day_off_id(self):
# # 先删除之前创建的工作日历事件记录
# self.env['sf.work.schedule.calendar'].search([('calendar_code', '=', self.code)]).unlink()
#
# # 获取当年的一月一号的日期
# year = fields.Datetime.now().year # 2023
# first_day = datetime(year, 1, 1).date() # 2023-01-01
# day_of_week = first_day.strftime("%A") # 星期日
#
# # 根据day_of_week将其设置为起始0循环周一到周日按循环顺序设置为0-6
# # 列:{'星期日': 0, '星期一': 1, '星期二': 2, '星期三': 3, '星期四': 4, '星期五': 5, '星期六': 6}
# desc = {}
# desc_weekdays = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
# status = False
# ints = 0
# while len(desc) < 7:
# if len(desc) != 0:
# for week in desc_weekdays:
# if len(desc) < 7:
# desc.update({week: ints})
# ints += 1
# else:
# for week in desc_weekdays:
# if status:
# desc.update({week: ints})
# ints += 1
# if day_of_week == week:
# desc.update({week: ints})
# status = True
# ints += 1
#
# # 创建工作日历的休息日事件
# day_off_ids = self.day_off_id.mapped('name')
# record = self.env['sf.work.log.setting'].search([('code', '=', self.code)])
# # record.setting_to_calendar_ids.unlink()
# # self.env.cr.commit()
# for week in day_off_ids:
# num = desc[week]
# while num <= 30:
# target_date = first_day + timedelta(days=num)
# num += 7
# self.env['sf.work.schedule.calendar'].create({'name': '休息日',
# 'name_id': record.id,
# 'calendar_code': self.code,
# 'date_time': target_date})
@api.model
def create(self, vals):
"""
创建记录时,生成工作日历
"""
record = super(WorkLogSetting, self).create(vals)
record.generate_work_calendar()
return record
def write(self, vals):
"""
更新记录时,生成工作日历
"""
# 先删除之前创建的工作日历事件记录
self.env['sf.work.schedule.calendar'].search([('calendar_code', '=', self.code)]).unlink()
result = super(WorkLogSetting, self).write(vals)
self.generate_work_calendar()
return result
def generate_work_calendar(self):
"""
生成工作日历
"""
self.ensure_one()
# start_date = date.today() # 开始日期
# end_date = start_date + timedelta(days=365) # 结束日期
# 获取本年第一天和最后一天
start_date = datetime.now().replace(month=1, day=1).date()
end_date = datetime.now().replace(month=12, day=31).date()
# 休息日列表
rest_days = self.day_off_id.mapped('name')
for single_date in self.daterange(start_date, end_date):
is_workday = single_date.strftime("%A")
if is_workday in rest_days:
print('is_workday in rest_days', is_workday)
self.env['sf.work.schedule.calendar'].create({
'name': '休息日',
'name_id': self.id,
'calendar_code': self.code,
'date_time': single_date})
@staticmethod
def daterange(start_date, end_date):
"""
生成日期范围
"""
# 生成日期范围
for n in range(int((end_date - start_date).days)):
yield start_date + timedelta(n)
class WorkingShift(models.Model):
_name = 'sf.working.shift'
_description = '班次'
def _get_code(self):
"""
自动生成编码
:return:
"""
fixture_material = self.env['sf.working.shift'].sudo().search(
[('code', '!=', '')],
limit=1,
order="id desc")
if not fixture_material:
num = "%03d" % 1
else:
m = int(fixture_material.code) + 1
num = "%03d" % m
return num
code = fields.Char('编码', default=_get_code, readonly=True)
name = fields.Char('名称', required=True)
start_time = fields.Datetime('班次开始时间')
end_time = fields.Datetime('班次结束时间')
remark = fields.Char('备注')
class DayOff(models.Model):
_name = 'sf.day.off'
_description = '休息日'
name = fields.Selection([
('星期一', '星期一'),
('星期二', '星期二'),
('星期三', '星期三'),
('星期四', '星期四'),
('星期五', '星期五'),
('星期六', '星期六'),
('星期日', '星期日')], '休息日名称')
class WorkScheduleCalendar(models.Model):
_name = 'sf.work.schedule.calendar'
_description = '工作日历'
name = fields.Selection([('休息日', '休息日'), ('计划停机', '计划停机'), ('工作日', '工作日')], '日历事件名称')
date_time = fields.Date('休息时间')
name_id = fields.Many2one('sf.work.log.setting', '工作日历名称')
calendar_code = fields.Char('工作日历编码')
day_off_id = fields.Many2many('sf.day.off', string='休息日')
scheduled_outage = fields.Char('计划停机')
monthly_rest_days = fields.Char('月休息天数', readonly=True)
annual_rest_days = fields.Char('年休息天数', readonly=True)
monthly_planned_downtime = fields.Char('月计划停机时长', readonly=True)
annual_planned_downtime = fields.Char('年计划停机时长', readonly=True)

View File

@@ -2,6 +2,10 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_work_log_setting,sf.work.log.setting,model_sf_work_log_setting,base.group_user,1,1,1,1
access_sf_procedure_equipment_resource_setting,sf.procedure.equipment.resource.setting,model_sf_procedure_equipment_resource_setting,base.group_user,1,1,1,1
access_sf_day_off,sf.day.off,model_sf_day_off,base.group_user,1,1,1,1
access_sf_working_shift,sf.working.shift,model_sf_working_shift,base.group_user,1,1,1,1
access_sf_work_schedule_calendar,sf.work.schedule.calendar,model_sf_work_schedule_calendar,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sf_work_log_setting sf.work.log.setting model_sf_work_log_setting base.group_user 1 1 1 1
3 access_sf_procedure_equipment_resource_setting sf.procedure.equipment.resource.setting model_sf_procedure_equipment_resource_setting base.group_user 1 1 1 1
4 access_sf_day_off sf.day.off model_sf_day_off base.group_user 1 1 1 1
5 access_sf_working_shift sf.working.shift model_sf_working_shift base.group_user 1 1 1 1
6 access_sf_work_schedule_calendar sf.work.schedule.calendar model_sf_work_schedule_calendar base.group_user 1 1 1 1
7
8
9
10
11

View File

@@ -25,4 +25,25 @@
action="sf_procedure_equipment_resource_setting_act"
sequence="10"
/>
<menuitem id="menu_sf_working_shift"
name="班次"
parent="menu_sf_basic_setting"
action="sf_working_shift_act"
sequence="12"
/>
<menuitem id="menu_sf_day_off"
name="休息日"
parent="menu_sf_basic_setting"
action="sf_day_off_act"
sequence="15"
/>
<menuitem id="menu_sf_work_schedule_calendar"
name="工作日历"
parent="menu_sf_basic_setting"
action="sf_work_schedule_calendar_act"
sequence="15"
/>
</odoo>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--========================================工作日历设置========================================-->
<!--================================================工作日历设置================================================-->
<record id="sf_work_log_setting_tree" model="ir.ui.view">
<field name="name">工作日历设置</field>
<field name="model">sf.work.log.setting</field>
@@ -11,11 +11,12 @@
<field name="start_time"/>
<field name="end_time"/>
<field name="duration"/>
<field name="day_off"/>
<field name="working_shift"/>
<field name="day_off_id" widget="many2many_tags"/>
<field name="working_shift_id" widget="many2many_tags"/>
<field name="status"/>
<field name="update_person"/>
<field name="update_time"/>
<!-- <button string="查看日历" type="object" name="sf_work_schedule_calendar_act"/>-->
</tree>
</field>
</record>
@@ -35,29 +36,7 @@
</group>
</group>
<group string="选择班次">
<group>
<group>
<field name="working_shift_char" attrs="{'invisible': [('user_defined_working_shift_status', '=', False)]}"/>
<field name="working_shift_select" attrs="{'invisible': [('user_defined_working_shift_status', '!=', False)]}"/>
</group>
<group>
<field name="user_defined_working_shift_status"/>
<field name="working_shift" invisible="True"/>
</group>
</group>
</group>
<group>
<group>
<group>
<field name="working_shift_start_time_H" attrs="{'invisible': [('user_defined_working_shift_status', '=', False)]}"/>
<field name="working_shift_end_time_H" attrs="{'invisible': [('user_defined_working_shift_status', '=', False)]}"/>
</group>
<group>
<field name="working_shift_start_time_M" attrs="{'invisible': [('user_defined_working_shift_status', '=', False)]}"/>
<field name="working_shift_end_time_M" attrs="{'invisible': [('user_defined_working_shift_status', '=', False)]}"/>
</group>
</group>
<field name="working_shift_id"/>
</group>
<group string="工作时间">
<group>
@@ -80,13 +59,14 @@
<group>
<group>
<field name="duration"/>
</group>
<group>
<field name="day_off"/>
<field name="day_off_id"
widget="many2many_tags"
options="{'no_create': True, 'no_quick_create': True}"/>
</group>
</group>
<group string="日历状态">
<field name="status"/>
<field name="setting_to_calendar_ids"/>
</group>
</sheet>
</form>
@@ -100,7 +80,138 @@
</record>
<!--========================================产线设备资源设置========================================-->
<!--================================================休息日================================================-->
<record id="sf_day_off_tree" model="ir.ui.view">
<field name="name">休息日</field>
<field name="model">sf.day.off</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
</tree>
</field>
</record>
<record id="sf_day_off_act" model="ir.actions.act_window">
<field name="name">休息日</field>
<field name="res_model">sf.day.off</field>
<field name="view_mode">tree,form</field>
</record>
<!--================================================班次================================================-->
<record id="sf_working_shift_tree" model="ir.ui.view">
<field name="name">班次</field>
<field name="model">sf.working.shift</field>
<field name="arch" type="xml">
<tree>
<field name="code"/>
<field name="name"/>
<field name="start_time"/>
<field name="end_time"/>
<field name="remark"/>
</tree>
</field>
</record>
<record id="sf_working_shift_form" model="ir.ui.view">
<field name="name">班次</field>
<field name="model">sf.working.shift</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="name"/>
<field name="start_time"/>
<field name="end_time"/>
<field name="remark"/>
</group>
<group>
<field name="code"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="sf_working_shift_act" model="ir.actions.act_window">
<field name="name">班次</field>
<field name="res_model">sf.working.shift</field>
<field name="view_mode">tree,form</field>
</record>
<!--================================================工作日历================================================-->
<record id="sf_work_schedule_calendar_tree" model="ir.ui.view">
<field name="name">工作日历</field>
<field name="model">sf.work.schedule.calendar</field>
<field name="arch" type="xml">
<tree>
<field name="name_id" invisible="True"/>
<field name="name"/>
<field name="date_time"/>
</tree>
</field>
</record>
<record id="sf_work_schedule_calendar_form" model="ir.ui.view">
<field name="name">工作日历</field>
<field name="model">sf.work.schedule.calendar</field>
<field name="arch" type="xml">
<form>
<sheet>
<group string="日历基本信息">
<group>
<field name="name"/>
<field name="date_time"/>
</group>
<group>
<field name="name_id"/>
<field name="calendar_code"/>
</group>
</group>
<group string="其他">
<field name="monthly_rest_days"/>
<field name="annual_rest_days"/>
<field name="monthly_planned_downtime"/>
<field name="annual_planned_downtime"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="sf_work_schedule_calendar_search" model="ir.ui.view">
<field name="name">工作日历</field>
<field name="model">sf.work.schedule.calendar</field>
<field name="arch" type="xml">
<search>
<searchpanel>
<field name="name_id" icon="fa-building" enable_counters="1"/>
</searchpanel>
</search>
</field>
</record>
<record id="sf_work_schedule_calendar_calendar" model="ir.ui.view">
<field name="name">工作日历</field>
<field name="model">sf.work.schedule.calendar</field>
<field name="arch" type="xml">
<calendar string="工作日历" mode="year" date_start="date_time">
<field name="name"/>
</calendar>
</field>
</record>
<record id="sf_work_schedule_calendar_act" model="ir.actions.act_window">
<field name="name">工作日历</field>
<field name="res_model">sf.work.schedule.calendar</field>
<field name="view_mode">calendar,search,tree,form</field>
</record>
<!--================================================产线设备资源设置================================================-->
<record id="sf_procedure_equipment_resource_setting_tree" model="ir.ui.view">
<field name="name">产线设备资源设置</field>
<field name="model">sf.procedure.equipment.resource.setting</field>
@@ -114,7 +225,7 @@
<field name="working_procedure"/>
<field name="production_capacity"/>
<field name="working_calendar_id"/>
<field name="working_shift"/>
<field name="working_shift_id" widget="many2many_tags"/>
<field name="create_time"/>
<field name="status"/>
<field name="participate_in_scheduling"/>
@@ -161,7 +272,7 @@
<field name="create_time"/>
</group>
<group>
<field name="working_shift"/>
<field name="working_shift_id" widget="many2many_tags"/>
</group>
</group>
</sheet>
@@ -182,7 +293,7 @@
<field name="working_procedure"/>
<field name="production_capacity"/>
<field name="working_calendar_id"/>
<field name="working_shift"/>
<field name="working_shift_id"/>
<field name="create_time"/>
<field name="status"/>
<field name="participate_in_scheduling"/>

View File

@@ -23,7 +23,11 @@
'web.assets_qweb': [
],
'web.assets_backend':[
'sf_warehouse/static/src/kanban_color_change.scss'
# 'sf_warehouse/static/src/js/vanilla-masker.min.js',
'sf_warehouse/static/src/css/kanban_color_change.scss',
'sf_warehouse/static/src/js/custom_kanban_controller.js',
'sf_warehouse/static/src/xml/custom_kanban_controller.xml',
]

View File

@@ -10,22 +10,12 @@ class SfLocation(models.Model):
name = fields.Char('Location Name', required=True, size=20)
barcode = fields.Char('Barcode', copy=False, required=True, size=15)
# 仓库类别selection仓库、库区、库位、货位)
# 仓库类别selection库区、库位、货位
location_type = fields.Selection([
('仓库', '仓库'),
('库区', '库区'),
('货架', '货架'),
('货位', '货位')
], string='仓库类别')
# 仓库类型(分类:成品库、坯料库、原材料库、刀具库、线边料库、线边刀库)
location_category = fields.Selection([
('成品库', '成品库'),
('坯料库', '坯料库'),
('原材料库', '原材料库'),
('刀具库', '刀具库'),
('线边料库', '线边料库'),
('线边刀库', '线边刀库')
], string='仓库类型')
# 库区类型selection拣货区、存货区、收货区、退货区、次品区
area_type = fields.Selection([
('拣货区', '拣货区'),
@@ -34,6 +24,13 @@ class SfLocation(models.Model):
('退货区', '退货区'),
('次品区', '次品区')
], string='库区类型')
# 存储类型selection库区、货架
storage_type = fields.Selection([
('库区', '库区'),
('货架', '货架')
], string='存储类型')
# 产品类别 关联product.category
product_type = fields.Many2many('product.category', string='产品类别')
# 货架独有字段通道、方向、货架高度m、货架层数、层数容量
channel = fields.Char(string='通道', required=True)
direction = fields.Selection([
@@ -64,6 +61,27 @@ class SfLocation(models.Model):
hide_shelf = fields.Boolean(compute='_compute_hide_what', string='隐藏货架')
hide_location = fields.Boolean(compute='_compute_hide_what', string='隐藏货位')
@api.model
def create(self, vals):
"""
重写create方法添加自定义的约束
"""
print('create', vals)
if vals.get('location_id'):
location = self.env['stock.location'].browse(vals.get('location_id'))
if location.storage_type == '库区':
raise UserError('库区不能作为父级仓库')
return super().create(vals)
@api.onchange('location_id')
def _onchange_location_id(self):
"""
重写onchange方法添加自定义的约束
"""
if self.location_id:
if self.location_id.storage_type == '库区':
raise UserError('库区不能作为父级仓库')
# @api.constrains('shelf_height')
# def _check_shelf_height(self):
# for record in self:
@@ -84,6 +102,9 @@ class SfLocation(models.Model):
@api.depends('product_sn_id')
def _compute_product_id(self):
"""
根据产品序列号,获取产品
"""
for record in self:
if record.product_sn_id:
record.product_id = record.product_sn_id.product_id
@@ -153,6 +174,9 @@ class SfLocation(models.Model):
# 生成货位
def create_location(self):
"""
当仓库类型为货架时,自动生成其下面的货位,数量为货架层数*层数容量
"""
if self.location_type == '货架':
for i in range(self.shelf_layer):
for j in range(self.layer_capacity):
@@ -165,8 +189,12 @@ class SfLocation(models.Model):
})
def generate_barcode(self, i, j):
"""
生成货位条码
"""
# 这里是你生成barcode的代码
area_type_barcode = self.location_id.barcode
# area_type_barcode = self.location_id.barcode
area_type_barcode = self.barcode
i_str = str(i + 1).zfill(3) # 确保是两位数如果不足两位左侧补0
j_str = str(j + 1).zfill(3) # 确保是两位数如果不足两位左侧补0
return area_type_barcode + self.channel + self.direction + '-' + self.barcode + '-' + i_str + '-' + j_str

View File

@@ -0,0 +1,25 @@
.oe_kanban_card.kanban_color_1 {
background-color: #73b9a2 !important;
}
.oe_kanban_card.kanban_color_2 {
background-color: #ac6767 !important;
}
.oe_kanban_card.kanban_color_3 {
background-color: #77787b !important;
}
.color-guide {
border: 1px solid #ccc;
background-color: #f9f9f9;
padding: 10px;
}
.color-guide-item {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
border-radius: 50%;
}

View File

@@ -0,0 +1,21 @@
/** @odoo-module */
import { KanbanController } from "@web/views/kanban/kanban_controller";
import { kanbanView } from "@web/views/kanban/kanban_view";
import { registry } from "@web/core/registry";
// the controller usually contains the Layout and the renderer.
class CustomKanbanController extends KanbanController {
// Your logic here, override or insert new methods...
// if you override setup(), don't forget to call super.setup()
}
CustomKanbanController.template = "sf_warehouse.CustomKanbanView";
export const customKanbanView = {
...kanbanView, // contains the default Renderer/Controller/Model
Controller: CustomKanbanController,
};
// Register it to the views registry
registry.category("views").add("custom_kanban", customKanbanView);

View File

@@ -1,11 +0,0 @@
.oe_kanban_card.kanban_color_1 {
background-color: red !important;
}
.oe_kanban_card.kanban_color_2 {
background-color: blue !important;
}
.oe_kanban_card.kanban_color_3 {
background-color: green !important;
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
<t t-name="sf_warehouse.CustomKanbanView" t-inherit="web.KanbanView" owl="1">
<!-- <xpath expr="//Layout" position="before"> -->
<!-- <div> -->
<!-- Hello world ! -->
<!-- </div> -->
<!-- </xpath> -->
<xpath expr="//t[@t-component='props.Renderer']" position="before">
<div>
Hello world !
</div>
</xpath>
</t>
</templates>

View File

@@ -30,11 +30,13 @@
<field name="channel" attrs="{'invisible': [('hide_shelf', '=', False)], 'required': [('hide_shelf', '!=', False)]}"/>
<field name="direction" attrs="{'invisible': [('hide_shelf', '=', False)], 'required': [('hide_shelf', '!=', False)]}"/>
<field name="product_sn_id" attrs="{'invisible': [('hide_location', '=', False)], 'required': [('hide_location', '!=', False), ('location_status', '=', '空闲')]}"/>
<field name="area_type" attrs="{'invisible': [('hide_area', '=', False)], 'required': [('hide_area', '!=', False)]}"/>
</group>
<group>
<field name="location_category" attrs="{'invisible': [('hide_location_type', '=', False)], 'required': [('hide_location_type', '!=', False)]}"/>
<field name="area_type" attrs="{'invisible': [('hide_area', '=', False)], 'required': [('hide_area', '!=', False)]}"/>
<field name="storage_type" attrs="{'invisible': [('hide_area', '=', False)], 'required': [('hide_area', '!=', False)]}"/>
<field name="product_type" widget="many2many_tags" attrs="{'invisible': [('hide_area', '=', False)], 'required': [('hide_area', '!=', False)]}"/>
<field name="shelf_height" attrs="{'invisible': [('hide_shelf', '=', False)], 'required': [('hide_shelf', '!=', False)]}"/>
<field name="shelf_layer" attrs="{'invisible': [('hide_shelf', '=', False)], 'required': [('hide_shelf', '!=', False)]}"/>
<field name="layer_capacity" attrs="{'invisible': [('hide_shelf', '=', False)], 'required': [('hide_shelf', '!=', False)]}"/>
@@ -53,7 +55,13 @@
<button string="生成货位" name="create_location" type="object" class="oe_highlight" attrs="{'invisible': [('hide_shelf', '=', False)]}"/>
</header>
</xpath>
<xpath expr="//form/sheet/group[last()]">
<notebook position="after" attrs="{'invisible': [('hide_area', '=', False)]}">
<page string="库存信息">
<field name="quant_ids" widget="one2many_list" context="{'location': active_id}"/>
</page>
</notebook>
</xpath>
</field>
</record>
@@ -74,7 +82,7 @@
<field name="name">example.kanban</field>
<field name="model">stock.location</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
<kanban class="o_kanban_mobile" js_class="custom_kanban">
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click