chore: 纳入 yuthon_employee 模块(教职工档案,出勤/薪资体系数据根)

This commit is contained in:
qitangbo
2026-10-16 17:04:02 +08:00
parent 77739b113c
commit ccff84e9f5
8 changed files with 238 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
from . import models
+33
View File
@@ -0,0 +1,33 @@
{
'name': 'Yuthon 员工管理',
'version': '18.0.1.0.0',
'summary': '大学人事基础:教职工档案(工号/部门/岗位/基本工资)',
'description': """
教学模块①(基础层):yuthon_employee
======================================
定义教职工(员工)主数据模型 yuthon.employee,是整个「出勤-薪资」体系的
数据根(root)。后续 yuthon_attendance、yuthon_salary 都依赖本模块。
教学要点:
- 模型定义:_name / _description
- 字段类型:Char / Selection / Float / Date / Boolean
- 唯一约束:_sql_constraints(工号不可重复)
- 模块组合:被其它模块通过 _inherit 追加反向关联(attendance_ids / payslip_ids)
- ACL:ir.model.access.csv 授权
""",
'author': 'Yuthon',
'website': '',
'category': 'Education',
'depends': ['base', 'web'],
'data': [
'security/ir.model.access.csv',
'views/employee_views.xml',
],
'demo': [
'data/demo.xml',
],
'license': 'LGPL-3',
'installable': True,
'application': True,
'auto_install': False,
}
+39
View File
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- 演示数据:3 名教职工(数据根)。出勤/薪资 demo 通过 ref 引用这里的 id。 -->
<record id="employee_zhang" model="yuthon.employee">
<field name="employee_no">T2024001</field>
<field name="name">张三</field>
<field name="gender">male</field>
<field name="department">teaching</field>
<field name="job_title">讲师</field>
<field name="phone">13800000001</field>
<field name="email">zhangsan@school.edu</field>
<field name="base_salary">8000.0</field>
<field name="hire_date">2024-09-01</field>
</record>
<record id="employee_li" model="yuthon.employee">
<field name="employee_no">A2024002</field>
<field name="name">李四</field>
<field name="gender">female</field>
<field name="department">admin</field>
<field name="job_title">教务员</field>
<field name="phone">13800000002</field>
<field name="email">lisi@school.edu</field>
<field name="base_salary">6000.0</field>
<field name="hire_date">2024-09-01</field>
</record>
<record id="employee_wang" model="yuthon.employee">
<field name="employee_no">T2024003</field>
<field name="name">王五</field>
<field name="gender">male</field>
<field name="department">teaching</field>
<field name="job_title">副教授</field>
<field name="phone">13800000003</field>
<field name="email">wangwu@school.edu</field>
<field name="base_salary">12000.0</field>
<field name="hire_date">2024-09-01</field>
</record>
</odoo>
+1
View File
@@ -0,0 +1 @@
from . import employee
+74
View File
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from odoo import fields, models, api
class Employee(models.Model):
"""教职工(员工)主数据模型。
这是「出勤-薪资」体系的**数据根**:出勤记录挂在员工下,
工资条在月底把「员工基本工资 + 当月出勤聚合结果」join 在一起算出来。
"""
_name = 'yuthon.employee'
_description = '教职工(员工)'
_order = 'employee_no'
# ---- 基础信息 ----
employee_no = fields.Char(
string='工号',
required=True,
index=True,
help='唯一工号,如 T2024001(教师)/ A2024002(行政)',
)
name = fields.Char(
string='姓名',
required=True,
)
gender = fields.Selection(
[('male', '男'), ('female', '女')],
string='性别',
)
department = fields.Selection(
[
('teaching', '教学部'),
('admin', '行政部'),
('logistics', '后勤部'),
('support', '教辅部'),
],
string='部门',
required=True,
default='teaching',
)
job_title = fields.Char(
string='岗位 / 职称',
help='如:讲师、副教授、教务员',
)
phone = fields.Char(string='联系电话')
email = fields.Char(string='邮箱')
# ---- 薪资相关(被 yuthon_salary 读取)----
base_salary = fields.Float(
string='基本工资',
default=0.0,
help='教学演示用 Float;生产环境建议改用 Monetary + currency_id',
)
hire_date = fields.Date(string='入职日期')
active = fields.Boolean(
string='在职',
default=True,
)
# ---- 反向关联(由 yuthon_attendance / yuthon_salary 通过 _inherit 追加)----
# attendance_ids / payslip_ids 不在此定义,避免基础模块反向依赖业务模块。
# 这是「模块解耦」的核心:根模块不知道子模块的存在。
# ---- 约束 ----
_sql_constraints = [
('uniq_employee_no', 'unique(employee_no)', '工号已存在,不可重复!'),
]
@api.constrains('base_salary')
def _check_base_salary(self):
for rec in self:
if rec.base_salary < 0:
raise models.ValidationError('基本工资不能为负数。')
@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_yuthon_employee,yuthon.employee,yuthon_employee.model_yuthon_employee,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_yuthon_employee yuthon.employee yuthon_employee.model_yuthon_employee base.group_user 1 1 1 1
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

+88
View File
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- ============ 列表视图 ============ -->
<record id="view_yuthon_employee_list" model="ir.ui.view">
<field name="name">yuthon.employee.list</field>
<field name="model">yuthon.employee</field>
<field name="arch" type="xml">
<list string="教职工">
<field name="employee_no"/>
<field name="name"/>
<field name="gender"/>
<field name="department"/>
<field name="job_title"/>
<field name="base_salary"/>
<field name="active" optional="hide"/>
</list>
</field>
</record>
<!-- ============ 表单视图 ============ -->
<record id="view_yuthon_employee_form" model="ir.ui.view">
<field name="name">yuthon.employee.form</field>
<field name="model">yuthon.employee</field>
<field name="arch" type="xml">
<form string="教职工">
<sheet>
<group>
<group>
<field name="employee_no"/>
<field name="name"/>
<field name="gender"/>
<field name="department"/>
<field name="job_title"/>
</group>
<group>
<field name="phone"/>
<field name="email"/>
<field name="base_salary"/>
<field name="hire_date"/>
<field name="active"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- ============ 搜索视图 ============ -->
<record id="view_yuthon_employee_search" model="ir.ui.view">
<field name="name">yuthon.employee搜索</field>
<field name="model">yuthon.employee</field>
<field name="arch" type="xml">
<search string="搜索教职工">
<field name="employee_no"/>
<field name="name"/>
<field name="department"/>
<separator/>
<filter name="filter_teaching" string="教学部"
domain="[('department', '=', 'teaching')]"/>
<filter name="filter_active" string="在职"
domain="[('active', '=', True)]"/>
<separator/>
<group expand="0" string="分组">
<filter name="groupby_department" string="按部门"
context="{'group_by': 'department'}"/>
</group>
</search>
</field>
</record>
<!-- ============ 动作 ============ -->
<record id="action_yuthon_employee" model="ir.actions.act_window">
<field name="name">教职工</field>
<field name="res_model">yuthon.employee</field>
<field name="view_mode">list,form</field>
<field name="search_view_id" ref="view_yuthon_employee_search"/>
</record>
<!-- ============ 根菜单(人事管理) ============ -->
<menuitem id="menu_yuthon_hr_root" name="人事管理"
web_icon="yuthon_employee,static/description/icon.png"
sequence="10"/>
<menuitem id="menu_yuthon_employee" name="教职工"
parent="menu_yuthon_hr_root"
action="action_yuthon_employee" sequence="20"/>
</odoo>