From a9793e33209b15a7ee52dd45c20c11f4f91cefce Mon Sep 17 00:00:00 2001 From: hrrr Date: Wed, 10 Jun 2026 16:05:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=A6=E7=94=9F=E7=BB=84=E7=BB=87=E6=9E=B6?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- student_organization/__init__.py | 1 + student_organization/__manifest__.py | 19 ++ .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 184 bytes student_organization/data/basic_grade.xml | 105 ++++++++ student_organization/data/student_org.xml | 249 ++++++++++++++++++ student_organization/models/__init__.py | 3 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 285 bytes .../__pycache__/basic_grade.cpython-312.pyc | Bin 0 -> 1564 bytes .../__pycache__/student_info.cpython-312.pyc | Bin 0 -> 4195 bytes .../student_organization.cpython-312.pyc | Bin 0 -> 3858 bytes student_organization/models/basic_grade.py | 20 ++ student_organization/models/student_info.py | 54 ++++ .../models/student_organization.py | 75 ++++++ .../security/ir.model.access.csv | 5 + .../views/view_student_info.xml | 95 +++++++ .../views/view_student_organization.xml | 105 ++++++++ 16 files changed, 731 insertions(+) create mode 100644 student_organization/__init__.py create mode 100644 student_organization/__manifest__.py create mode 100644 student_organization/__pycache__/__init__.cpython-312.pyc create mode 100644 student_organization/data/basic_grade.xml create mode 100644 student_organization/data/student_org.xml create mode 100644 student_organization/models/__init__.py create mode 100644 student_organization/models/__pycache__/__init__.cpython-312.pyc create mode 100644 student_organization/models/__pycache__/basic_grade.cpython-312.pyc create mode 100644 student_organization/models/__pycache__/student_info.cpython-312.pyc create mode 100644 student_organization/models/__pycache__/student_organization.cpython-312.pyc create mode 100644 student_organization/models/basic_grade.py create mode 100644 student_organization/models/student_info.py create mode 100644 student_organization/models/student_organization.py create mode 100644 student_organization/security/ir.model.access.csv create mode 100644 student_organization/views/view_student_info.xml create mode 100644 student_organization/views/view_student_organization.xml diff --git a/student_organization/__init__.py b/student_organization/__init__.py new file mode 100644 index 0000000..9a7e03e --- /dev/null +++ b/student_organization/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/student_organization/__manifest__.py b/student_organization/__manifest__.py new file mode 100644 index 0000000..bb1e444 --- /dev/null +++ b/student_organization/__manifest__.py @@ -0,0 +1,19 @@ +{ + 'name': 'student_organization', + 'version': '1.3', + 'summary': '', + 'sequence': 11, + 'depends': ['base','hr'], + 'data':[ + 'security/ir.model.access.csv', + 'views/view_student_organization.xml', + 'views/view_student_info.xml', + 'data/basic_grade.xml', + 'data/student_org.xml', + ], + + 'installable': True, + 'application': True, + + 'license': 'LGPL-3', +} diff --git a/student_organization/__pycache__/__init__.cpython-312.pyc b/student_organization/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..af2bdea0e86db380e5742f0e037b95034ae6eb89 GIT binary patch literal 184 zcmX@j%ge<81Y4e~XNdsm#~=<2FhLog1%Qm{3@HpLj5!Rsj8Tk?43$ip%r6;%!kUb? z*mCnzQge#^G?{KO6fpzERx*4B>HKAyVil90lAmvA5mTI6RF+y4lUtbxlIY~;;;c4Selb+SHuA{1!PGvi1C4$k&*EpgGdn@ GkOKhGVlBo1 literal 0 HcmV?d00001 diff --git a/student_organization/data/basic_grade.xml b/student_organization/data/basic_grade.xml new file mode 100644 index 0000000..65ef685 --- /dev/null +++ b/student_organization/data/basic_grade.xml @@ -0,0 +1,105 @@ + + + + 大一 + 1 + + + 大二 + 2 + + + 大三 + 3 + + + 大四 + 4 + + + + + 2010 + 1 + + + 2011 + 2 + + + 2012 + 3 + + + 2013 + 4 + + + 2014 + 5 + + + 2015 + 6 + + + 2016 + 7 + + + 2017 + 8 + + + 2018 + 9 + + + 2019 + 10 + + + 2020 + 11 + + + 2021 + 12 + + + 2022 + 13 + + + 2023 + 14 + + + 2024 + 15 + + + 2025 + 16 + + + 2026 + 17 + + + 2027 + 18 + + + 2028 + 19 + + + 2029 + 20 + + + 2030 + 21 + + \ No newline at end of file diff --git a/student_organization/data/student_org.xml b/student_organization/data/student_org.xml new file mode 100644 index 0000000..9f25991 --- /dev/null +++ b/student_organization/data/student_org.xml @@ -0,0 +1,249 @@ + + + + + + 信息工程学院 + 01 + college + 10 + + + + 经济管理学院 + 02 + college + 20 + + + + + 计算机科学与技术 + 080901 + major + + 10 + 4 + bachelor + + + + 软件工程 + 080902 + major + + 20 + 4 + bachelor + + + + 数据科学与大数据技术 + 080910T + major + + 30 + 4 + bachelor + + + + + 工商管理 + 120201K + major + + 10 + 4 + bachelor + + + + 市场营销 + 120202 + major + + 20 + 4 + bachelor + + + + 会计学 + 120203K + major + + 30 + 4 + bachelor + + + + + 计算机1班 + 08090101 + class + + 10 + 2024级 + + + + 计算机2班 + 08090102 + class + + 20 + 2024级 + + + + 计算机3班 + 08090103 + class + + 30 + 2024级 + + + + + 软件1班 + 08090201 + class + + 10 + 2024级 + + + + 软件2班 + 08090202 + class + + 20 + 2024级 + + + + 软件3班 + 08090203 + class + + 30 + 2024级 + + + + + 大数据1班 + 080910T01 + class + + 10 + 2024级 + + + + 大数据2班 + 080910T02 + class + + 20 + 2024级 + + + + 大数据3班 + 080910T03 + class + + 30 + 2024级 + + + + + 工商1班 + 120201K01 + class + + 10 + 2024级 + + + + 工商2班 + 120201K02 + class + + 20 + 2024级 + + + + 工商3班 + 120201K03 + class + + 30 + 2024级 + + + + + 营销1班 + 12020201 + class + + 10 + 2024级 + + + + 营销2班 + 12020202 + class + + 20 + 2024级 + + + + 营销3班 + 12020203 + class + + 30 + 2024级 + + + + + 会计1班 + 120203K01 + class + + 10 + 2024级 + + + + 会计2班 + 120203K02 + class + + 20 + 2024级 + + + + 会计3班 + 120203K03 + class + + 30 + 2024级 + + + \ No newline at end of file diff --git a/student_organization/models/__init__.py b/student_organization/models/__init__.py new file mode 100644 index 0000000..936e066 --- /dev/null +++ b/student_organization/models/__init__.py @@ -0,0 +1,3 @@ +from . import student_organization +from . import basic_grade +from . import student_info diff --git a/student_organization/models/__pycache__/__init__.cpython-312.pyc b/student_organization/models/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..67717f4321ccfe09c0e91aa44e89dfd8f11c1474 GIT binary patch literal 285 zcmX@j%ge<81fg7-SusHRF^B^LOi;#W4IpDWLkdF*V-7q|zUa!tltBE==8DXDoS@%csRiFuh-i6xo&c|dXQq{QOPqLlHC3fFc$U!3rc+GJFP-48L4ctYY$0^79QXVv19X%2JDBaw`*o z{Ji3r)S`kIm@&w<#pLFvq~;XI#K&jmWtPOp>lIY~;;;bUX`IjbY|1cV+LU8Yl)%nG82;tKMxjXllQJl)nYtZ5bE5u0G7q0@-! zi-;1YmzCF^qi9}}{()>$SsK#P{2$9$BWA@nV3VZ_-JLB7bEd>9G!Uj&rK}QISj4Ft zvasZ_0@(Ga8w+(7<;n_T$i@`e8pXCwHJfON8Rb;ZxIa_5UJyCP%50}E@jj8=DQa_8YzM}Qm+d`aW74|=jm_1JbQTO z9u{U0@{(VS79X~rwtg*ilT)5!5~0w}_Yzi6_*z%ilztoZk|~pI%SyP6DW+No{uIq& zsyF2k_F6HcOFh}9H=5G2uPo;#CJW`)Q%q6fG|yM{Ky7mWf2aA3Ei)LCrE?2 zT{W4#r)#~A~e8Bi6#`9jom9ih?8K2DuVU03BbgI1Q z`lY5Dma2X}x(#{NQYUKZY(wmGiY#;rHO^rJM0L397nwt=o?G&p!&?tz9>9R6wY z=k#+Oj~;uDaCQPqOibX8bcCj?w1_(nbj)!?(s5)JwF>Yl$GKQ@D_xDDOhm%rte{v9 zy%prdw=U-iU}I4Oxkf z%uK{a0l;@bj@JY+fI8rT7ZzA9~cN6?+wD1y1R;BYV7r|G0 literal 0 HcmV?d00001 diff --git a/student_organization/models/__pycache__/student_info.cpython-312.pyc b/student_organization/models/__pycache__/student_info.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7fb7d16d3fcc72d4f371773a8f6f87053689335 GIT binary patch literal 4195 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 literal 0 HcmV?d00001 diff --git a/student_organization/models/__pycache__/student_organization.cpython-312.pyc b/student_organization/models/__pycache__/student_organization.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c218c9eae7eb3a2abdbedfa6069628449692f4a3 GIT binary patch literal 3858 zcmb7HUrbY38b7!HXep%y3aEfBiiHkLb={0{bymk&2Xz#T>%=jI*?R3cK(T-D+}23r zpU#HOz^DPTW6+sVt0wA1R7~7mMt8IB)0*r{tKC4(J}k+A$Q!Qii%bXG8H0tJ}Yx}n~ezlz&Dvkn_j&75Edf{BP{q)KyV8Im0J~1yVU|x zp&baT`VdwVb+b$2U$jQ;R)5rt9z#KbDv-5W>VSc^8-v%4%K* z{3D1Uw}6pbg$1`7tK1r_c5AW5t;1S(0oJ+oDntz3)?5L~8W&(K){g44Rv4E=8b%9m z3ksLJNJg#5BhQG7MoqU>XhY zBQMg5%fZr2RIM^HpXb`qimX57OQI_AGO%%ZR$j%DHm<-`pf}@r<&qMsbK=HQ|Awe%`vitBS(c*YIJ^1?UhZ zuZT&;0DUM3jfsQ_Gi2kC<~oz*atciA1Ke>Xkay2MKmR}p1S|D;LxG-1n0T@gb*j_8 zrB9ev3Wq3(8Yq!m5s6SK!b9@n!Ic*eu1`OFsM!A1A70$MBrl&2oO%AOLY@2V-PybM z6|G-hp84JA%(r7Rmtv6;;Gh2MT?od^_YdYS4mH4!b56qp%LA!DEPA_$KOHql{LJ;+ zK-L9BDNK}5&R#vACgPA6%#$_GockJx%JR;Q>A##)mft^sNJNcY)I|b4{!lMTXXxIa zXNE7xzNBmG{1~gq#v@&bu#W`8nWR*JiP5rbq+QvdF%2&9I3aWcW${BB^V7T2cRUyW4NN&ea}A50Z_p+63Bi-KYPaPH0biCVsgWxm_8fdCy!uy|f%8M;&?kf-9SrY{Y*7Sm`5p#n2BGEBc!!&E*qj z+f%b`($O^G*pPH=m~ecMbbOFlv+Z%&;{$(h`&--Nmc;5`59$7Cu}`gb-rRh3v%G$3 zK$TUmKoEK>eFZ>})7JsPOs8*j>GWaYNCO0H{RxyWVOX^s#C2yr8Mw0agVk6ADdN3p z(bJ*s6f)xx(v?m2+3kSm-C@x~*Z!n#(;_%*;lo3hUltTt!6j9$1;LvCS9&MPSbtI# zHfOY-P-UoZ`E*w9%Drk5vjLJxw=dRjHXOA%D0&r(>GX_qf^jK?I%Gfej6A-?eJpyG?OIp zI2j@LgmJE!U!ZyvvTe5^QGzjdO1 zPqKc`lW3ytH;F?X6Nh}sL%u|7ccSIUvwA?N>Hl+!$|7 zR{eaUYE!am(`30VUU92=qG?OAX-lGU>-f=xb6djt;k;V)e(7tZsxF&yt-sgxUDw#D zq^o(t)sl3zJURT#wGV`qEPt&-4UM-pUOy?TdRYdSg7Qy=R;PpMJ@Tyecvzvw19v#$ zC$KK^c#cLyKW}`n)5;JaVj_8|uZNFwX7E7IP!4n+=pBSI6J$>w*z#0a*vhArS2@%C zs!ODD?_nA*e0Z~hUBNI6RthOePk3h74`a{El~5<=(YJ`f-u0m%k-Hbu?+udm0U$Ah zx69|pP(2cL0Z{I1tPqYw5Xg&4+tUSX{1gAM&rg_^1Vo>oX+9yx!>mBW7{;E&^f*H0 zFBGQ3q>~cBbyAqa%+eJK5E=>vJYmA87NzfUExcm**Fg^nf@0p+tk!m*c{tFX{^Z5QpS4Nn``=y4W1e}6+bveQ|3*vol|C8|1s!}Nwe)gNK>nu*CTUf z-1^#}vDC+Q&KIK+`;czLJZw(bH;kW3928TQ!=T(^Tc8@Bw5BX=KrF2pa*Q+%H^#T8 zN}aLYU{Xmnz>LGj_?E=xy@^lTQkM4EE})mz4pofUhHdexv9?snw%Er&GcD_H9^5^! z`@->5Q3H4i`vZe*18s4A%H#xB!M(T6i2O;2EOKkraZJ)O#N*uRz&$Me_seMj}ABS@419x662*STnT@uy3 V*6k34_bxcDG+k`^FXC&N{eQ5d-g5u| literal 0 HcmV?d00001 diff --git a/student_organization/models/basic_grade.py b/student_organization/models/basic_grade.py new file mode 100644 index 0000000..f745475 --- /dev/null +++ b/student_organization/models/basic_grade.py @@ -0,0 +1,20 @@ +from odoo import api,fields,models +from datetime import datetime +class BasicGradeXx(models.Model): + _name = 'basic.grade.xx' #xx 详细 + _rec_name = 'grade' + grade=fields.Char(string='年级') + sequence=fields.Integer(string='序号') + @api.model + def _get_current_year_range_domain(self): + year = datetime.now().year + return [('name', '>=', str(year - 4)), ('name', '<=', + str(year + 1))] # 别的直接调用domain = lambda self: self.env['basic.grade.xx']._get_current_year_range_domain() + + +class BasicGradeBx(models.Model): + _name = 'basic.grade.bx' #xx 不详细 + _rec_name = 'grade' + grade=fields.Char(string='年级') + sequence = fields.Integer(string='序号') + diff --git a/student_organization/models/student_info.py b/student_organization/models/student_info.py new file mode 100644 index 0000000..ca54486 --- /dev/null +++ b/student_organization/models/student_info.py @@ -0,0 +1,54 @@ +from odoo import api,models,fields + +class StudentInfo(models.Model): + _name="student.info" + + stu_name=fields.Char(string="姓名",tracking=True) + stu_num=fields.Char(string="学号",tracking=True) + stu_sex = fields.Selection([('male', '男'),('female', '女')], string="性别", default='male', required=True) + stu_birthday = fields.Date(string="出生日期", tracking=True) + stu_id_card = fields.Char(string="身份证号", index=True, tracking=True) + stu_nation = fields.Char(string="民族", default="汉族") + stu_shenfen = fields.Selection([ + ('mass', '群众'), + ('league', '共青团员'), + ('party', '中共党员'), + ('other', '其他') + ], string="政治面貌", default='mass') + stu_phone = fields.Char(string="手机号") + stu_email = fields.Char(string="邮箱") + stu_address = fields.Text(string="家庭地址") + stu_emergency_contact = fields.Char(string="紧急联系人") + stu_emergency_phone = fields.Char(string="紧急联系电话") + stu_photo = fields.Binary(string="照片", attachment=True) + stu_begin_date = fields.Date(string="入学日期", required=True, tracking=True) + stu_end_date = fields.Date(string="毕业日期") + stu_grade_xx = fields.Many2one('basic.grade.xx',string="年级", tracking=True,domain = lambda self: self.env['basic.grade.xx']._get_current_year_range_domain()) + stu_grade_bx=fields.Many2one('basic.grade.xx',string='年级',readonle=1) + stu_status = fields.Selection([ + ('studying', '在读'), + ('graduated', '已毕业'), + ('suspended', '休学'), + ('expelled', '退学'), + ('transferred', '转出') + ], string="学籍状态", default='studying', tracking=True) + org_path = fields.Char(string='组织路径', compute='_compute_org_path', + store=True, index=True) + + class_id = fields.Many2one('student.organization', string="行政班", tracking=True,domain="[('org_type', '=', 'class')]") + parent_path = fields.Char(related='class_id.parent_path',store=True) + class_name = fields.Char(string="班级名称", related='class_id.name', store=True) + major_id = fields.Many2one('student.organization', string="专业", tracking=True,domain="[('org_type', '=', 'major')]") + major_name = fields.Char(string="专业名称", related='major_id.name', store=True) + department_id = fields.Many2one('student.organization', string="院系",store=True,domain="[('org_type', '=', 'college')]") + + + # user_id = fields.Many2one('res.users', string="系统用户", ondelete='restrict') + @api.depends('parent_path') + def _compute_org_path(self): + for record in self: + if record.class_id: + # 直接使用班级的 parent_path + 班级ID + record.org_path = f"{record.class_id.parent_path}{record.class_id.id}/" + else: + record.org_path = False \ No newline at end of file diff --git a/student_organization/models/student_organization.py b/student_organization/models/student_organization.py new file mode 100644 index 0000000..5e9eccd --- /dev/null +++ b/student_organization/models/student_organization.py @@ -0,0 +1,75 @@ +from odoo import api, fields, models + + +class StudentOrganization(models.Model): + _name = 'student.organization' + _description = '学生架构' + _rec_name = 'full_name' + _order = 'parent_id, sequence, id' + _parent_store = True + + _parent_order = 'sequence, name' + + # 基本信息 + name = fields.Char(string='名称', required=True, translate=True) + code = fields.Char(string='代码') + sequence = fields.Integer(string='序号', default=10) + + org_type = fields.Selection([ + ('college', '学院'), + ('major', '专业'), + ('class', '班级'), #用法 domain="[('org_type', '=', 'class')]" + ], string='类型', required=True) + + # 层级关系 + parent_id = fields.Many2one('student.organization', string='上级组织', ondelete='cascade') + child_ids = fields.One2many('student.organization', 'parent_id', string='下级组织') + parent_path = fields.Char(index=True) + + # 完整名称(显示层级) + full_name = fields.Char(string='完整名称', compute='_compute_full_name', store=True) + + # 负责人信息(学院用) + manager_id = fields.Many2one('res.users', string='负责人') + + # 联系方式(学院用) + phone = fields.Char(string='电话') + mobile = fields.Char(string='手机') + email = fields.Char(string='邮箱') + address = fields.Text(string='办公地址') + + # 专业专用字段 + duration = fields.Integer(string='修业年限(年)', default=4) + degree = fields.Selection([ + ('bachelor', '学士'), + ('master', '硕士'), + ('doctor', '博士'), + ], string='学位') + + # 班级专用字段 + grade = fields.Char(string='年级') + + homeroom_teacher = fields.Many2one('hr.employee', string='导员') + + # 统计字段 + student_count = fields.Integer(string='学生数', compute='_compute_student_count') + + @api.depends('parent_id.full_name', 'name') + def _compute_full_name(self): + for record in self: + if record.parent_id: + record.full_name = f'{record.parent_id.full_name} / {record.name}' + else: + record.full_name = record.name + + def _compute_student_count(self): + for record in self: + if record.org_type == 'class': + # 班级的学生数 + record.student_count = self.env['student.info'].search_count([('class_id', '=', record.id)]) + else: + # 学院/专业的学生数(统计下级) + students = self.env['student.info'].search([ + ('org_path', 'like', f'{record.parent_path}%') + ]) if record.parent_path else self.env['student.info'].search([]) + record.student_count = len(students) \ No newline at end of file diff --git a/student_organization/security/ir.model.access.csv b/student_organization/security/ir.model.access.csv new file mode 100644 index 0000000..bf78021 --- /dev/null +++ b/student_organization/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_student_organization_sys,student.organization.access.sys,model_student_organization,base.group_system,1,1,1,1 +access_student_info_sys,student.info.access.sys,model_student_info,base.group_system,1,1,1,1 +access_basic_grade_xx_sys,basic.grade.access.sys,model_basic_grade_xx,base.group_system,1,1,1,1 +access_basic_grade_bx_sys,basic.grade.access.sys,model_basic_grade_bx,base.group_system,1,1,1,1 \ No newline at end of file diff --git a/student_organization/views/view_student_info.xml b/student_organization/views/view_student_info.xml new file mode 100644 index 0000000..4cfd0ec --- /dev/null +++ b/student_organization/views/view_student_info.xml @@ -0,0 +1,95 @@ + + + student.info.list + student.info + + + + + + + + + + + + + + student.info.form + student.info + +
+ +
+
+
+

+ +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 学生信息 + student.info + list,form + + + + student.info.search + student.info + + + + + + + + + + + 学生 + + 9 + + + \ No newline at end of file diff --git a/student_organization/views/view_student_organization.xml b/student_organization/views/view_student_organization.xml new file mode 100644 index 0000000..fbf46be --- /dev/null +++ b/student_organization/views/view_student_organization.xml @@ -0,0 +1,105 @@ + + + + student.organization.list + student.organization + + + + + + + + + + + + + + + student.organization.form + student.organization + +
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + + + student.organization.sub.list + student.organization + + + + + + + + + + + + + + 组织架构 + student.organization + list,form,search + + + + + + + 学生架构 + 11 + + + + 组织架构 + + + +
\ No newline at end of file