diff --git a/yuthon_salary/__init__.py b/yuthon_salary/__init__.py
deleted file mode 100644
index a0fdc10..0000000
--- a/yuthon_salary/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# -*- coding: utf-8 -*-
-from . import models
diff --git a/yuthon_salary/__manifest__.py b/yuthon_salary/__manifest__.py
deleted file mode 100644
index 6db0a3d..0000000
--- a/yuthon_salary/__manifest__.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- coding: utf-8 -*-
-{
- 'name': '宇森教育薪资管理',
- 'summary': '学校教育行业教职工薪资管理系统',
- 'description': '''
- 专为学校教育行业设计的教职工薪资管理系统,主要功能包括:
-
- - 教职工薪资档案管理
- - 薪资结构配置(基本工资、岗位工资、绩效工资)
- - 课时费管理(按科目、年级、职称差异化计费)
- - 班主任津贴管理
- - 社保公积金扣缴配置
- - 个人所得税自动计算
- - 薪资单生成与审批
- - 薪资条发放与查询
- - 薪资报表统计分析
-
- 适用于幼儿园、小学、中学、高中、职业院校等各类教育机构。
- ''',
- 'author': '宇森科技',
- 'version': '18.0.1.0',
- 'category': 'Human Resources/Payroll',
- 'sequence': 250,
- 'depends': ['base', 'hr', 'hr_contract', 'mail', 'yuthon_base'],
- 'data': [
- 'security/yuthon_salary_groups.xml',
- 'security/ir.model.access.csv',
- 'security/yuthon_salary_security.xml',
- 'data/salary_item_data.xml',
- 'views/salary_item_views.xml',
- 'views/salary_structure_views.xml',
- 'views/employee_salary_views.xml',
- 'views/class_hour_views.xml',
- 'views/class_teacher_allowance_views.xml',
- 'views/salary_slip_views.xml',
- 'views/salary_report_views.xml',
- 'views/menu_views.xml',
- ],
- 'installable': True,
- 'application': True,
- 'license': 'LGPL-3',
-}
diff --git a/yuthon_salary/data/salary_item_data.xml b/yuthon_salary/data/salary_item_data.xml
deleted file mode 100644
index 61bf3de..0000000
--- a/yuthon_salary/data/salary_item_data.xml
+++ /dev/null
@@ -1,152 +0,0 @@
-
-
-
-
-
- 基本工资
- BASIC
- basic
- income
- fixed
- 10
-
-
-
- 岗位工资
- POSITION
- position
- income
- fixed
- 20
-
-
-
- 绩效工资
- PERFORMANCE
- performance
- income
- formula
- 30
-
-
-
- 课时费
- CLASS_HOUR
- class_hour
- income
- formula
- 40
-
-
-
- 班主任津贴
- CLASS_TEACHER
- allowance
- income
- manual
- 50
-
-
-
- 工龄津贴
- SENIORITY
- allowance
- income
- fixed
- 60
-
-
-
- 学历津贴
- EDUCATION
- allowance
- income
- fixed
- 70
-
-
-
- 职称津贴
- TITLE
- allowance
- income
- fixed
- 80
-
-
-
- 养老保险(个人)
- PENSION
- social
- deduction
- formula
- 110
-
-
-
- 医疗保险(个人)
- MEDICAL
- social
- deduction
- formula
- 120
-
-
-
- 失业保险(个人)
- UNEMPLOYMENT
- social
- deduction
- formula
- 130
-
-
-
- 住房公积金(个人)
- PROVIDENT_FUND
- social
- deduction
- formula
- 140
-
-
-
- 个人所得税
- INCOME_TAX
- tax
- deduction
- formula
- True
- 150
-
-
-
-
- 教职工薪资档案编号
- yuthon.employee.salary
- ESA%(year)s
- 4
-
-
-
- 课时记录编号
- yuthon.class.hour
- CH%(year)s
- 4
-
-
-
- 班主任津贴编号
- yuthon.class.teacher.allowance
- CTA%(year)s%(month)s
- 3
-
-
-
- 薪资单编号
- yuthon.salary.slip
- SLIP%(year)s%(month)s
- 3
-
-
-
diff --git a/yuthon_salary/models/.gitkeep b/yuthon_salary/models/.gitkeep
deleted file mode 100644
index 867e2c8..0000000
--- a/yuthon_salary/models/.gitkeep
+++ /dev/null
@@ -1 +0,0 @@
-# Placeholder
\ No newline at end of file
diff --git a/yuthon_salary/models/__init__.py b/yuthon_salary/models/__init__.py
deleted file mode 100644
index f8cbd3c..0000000
--- a/yuthon_salary/models/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-# -*- coding: utf-8 -*-
-from . import salary_item
-from . import salary_structure
-from . import employee_salary
-from . import class_hour
-from . import class_teacher_allowance
-from . import salary_slip
diff --git a/yuthon_salary/models/class_hour.py b/yuthon_salary/models/class_hour.py
deleted file mode 100644
index 1125ba5..0000000
--- a/yuthon_salary/models/class_hour.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import models, fields, api
-
-
-class ClassHour(models.Model):
- """课时记录 - 记录教职工的授课课时"""
- _name = 'yuthon.class.hour'
- _description = '课时记录'
- _inherit = ['mail.thread', 'mail.activity.mixin']
- _order = 'date desc, id desc'
-
- name = fields.Char(string='课时编号', required=True, copy=False, readonly=True, default='新建')
- employee_id = fields.Many2one('hr.employee', string='授课教师', required=True)
- department_id = fields.Many2one('hr.department', string='所属部门', related='employee_id.department_id', store=True)
-
- # 授课信息
- date = fields.Date(string='授课日期', required=True, default=fields.Date.today)
- subject = fields.Char(string='科目', required=True)
- grade = fields.Char(string='年级/班级')
- class_type = fields.Selection([
- ('normal', '常规课'),
- ('overtime', '超课时'),
- ('weekend', '周末课'),
- ('holiday', '节假日课'),
- ('makeup', '补课'),
- ('exam', '考试监考'),
- ('activity', '课外活动'),
- ], string='课程类型', required=True, default='normal')
-
- # 课时计算
- hours = fields.Float(string='课时数', required=True, default=1.0)
- rate = fields.Float(string='课时费标准(元/课时)', required=True, default=0.0)
- amount = fields.Float(string='课时费金额', compute='_compute_amount', store=True)
-
- # 状态
- state = fields.Selection([
- ('draft', '草稿'),
- ('submitted', '已提交'),
- ('approved', '已确认'),
- ('paid', '已发薪'),
- ], string='状态', default='draft', tracking=True)
-
- # 关联薪资单
- salary_slip_id = fields.Many2one('yuthon.salary.slip', string='关联薪资单', readonly=True)
-
- note = fields.Text(string='备注')
- company_id = fields.Many2one('res.company', string='学校', default=lambda self: self.env.company)
-
- @api.depends('hours', 'rate')
- def _compute_amount(self):
- for record in self:
- record.amount = record.hours * record.rate
-
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- if vals.get('name', '新建') == '新建':
- vals['name'] = self.env['ir.sequence'].next_by_code('yuthon.class.hour') or '新建'
- return super(ClassHour, self).create(vals_list)
-
- def action_submit(self):
- self.write({'state': 'submitted'})
-
- def action_approve(self):
- self.write({'state': 'approved'})
-
- def action_draft(self):
- self.write({'state': 'draft'})
-
- @api.onchange('employee_id', 'class_type')
- def _onchange_employee_class_type(self):
- if self.employee_id and self.employee_id.user_id:
- salary_record = self.env['yuthon.employee.salary'].search([
- ('employee_id', '=', self.employee_id.id),
- ('state', '=', 'active')
- ], limit=1, order='id desc')
- if salary_record:
- if self.class_type == 'normal':
- self.rate = salary_record.class_hour_rate_normal
- elif self.class_type == 'overtime':
- self.rate = salary_record.class_hour_rate_overtime
- elif self.class_type == 'weekend':
- self.rate = salary_record.class_hour_rate_weekend
- elif self.class_type == 'holiday':
- self.rate = salary_record.class_hour_rate_holiday
diff --git a/yuthon_salary/models/class_teacher_allowance.py b/yuthon_salary/models/class_teacher_allowance.py
deleted file mode 100644
index 90f27c1..0000000
--- a/yuthon_salary/models/class_teacher_allowance.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import models, fields, api
-
-
-class ClassTeacherAllowance(models.Model):
- """班主任津贴 - 管理班主任的月度津贴"""
- _name = 'yuthon.class.teacher.allowance'
- _description = '班主任津贴'
- _inherit = ['mail.thread', 'mail.activity.mixin']
- _order = 'year desc, month desc, id desc'
-
- name = fields.Char(string='津贴编号', required=True, copy=False, readonly=True, default='新建')
- employee_id = fields.Many2one('hr.employee', string='班主任', required=True)
- department_id = fields.Many2one('hr.department', string='所属部门', related='employee_id.department_id', store=True)
-
- # 班级信息
- class_name = fields.Char(string='班级名称', required=True)
- grade_level = fields.Selection([
- ('junior', '低年级'),
- ('middle', '中年级'),
- ('senior', '高年级'),
- ('junior_high', '初中'),
- ('senior_high', '高中'),
- ], string='年级段')
- student_count = fields.Integer(string='学生人数', default=0)
-
- # 考核评分
- year = fields.Integer(string='年度', required=True, default=lambda self: fields.Date.today().year)
- month = fields.Integer(string='月份', required=True, default=lambda self: fields.Date.today().month)
-
- # 津贴构成
- base_allowance = fields.Float(string='基础津贴', required=True, default=0.0)
- student_count_bonus = fields.Float(string='学生人数补贴', default=0.0)
- performance_bonus = fields.Float(string='绩效奖金', default=0.0)
- special_allowance = fields.Float(string='特殊补贴', default=0.0)
- deduction = fields.Float(string='扣款', default=0.0)
-
- total_amount = fields.Float(string='津贴合计', compute='_compute_total', store=True)
-
- # 考核维度
- discipline_score = fields.Float(string='纪律管理评分', default=100.0)
- hygiene_score = fields.Float(string='卫生管理评分', default=100.0)
- activity_score = fields.Float(string='活动组织评分', default=100.0)
- parent_score = fields.Float(string='家长沟通评分', default=100.0)
- overall_score = fields.Float(string='综合评分', compute='_compute_score', store=True)
-
- # 状态
- state = fields.Selection([
- ('draft', '草稿'),
- ('submitted', '已提交'),
- ('approved', '已审核'),
- ('paid', '已发薪'),
- ], string='状态', default='draft', tracking=True)
-
- salary_slip_id = fields.Many2one('yuthon.salary.slip', string='关联薪资单', readonly=True)
- note = fields.Text(string='备注')
- company_id = fields.Many2one('res.company', string='学校', default=lambda self: self.env.company)
-
- @api.depends('base_allowance', 'student_count_bonus', 'performance_bonus', 'special_allowance', 'deduction')
- def _compute_total(self):
- for record in self:
- record.total_amount = (
- record.base_allowance +
- record.student_count_bonus +
- record.performance_bonus +
- record.special_allowance -
- record.deduction
- )
-
- @api.depends('discipline_score', 'hygiene_score', 'activity_score', 'parent_score')
- def _compute_score(self):
- for record in self:
- record.overall_score = (
- record.discipline_score +
- record.hygiene_score +
- record.activity_score +
- record.parent_score
- ) / 4.0
-
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- if vals.get('name', '新建') == '新建':
- vals['name'] = self.env['ir.sequence'].next_by_code('yuthon.class.teacher.allowance') or '新建'
- return super(ClassTeacherAllowance, self).create(vals_list)
-
- def action_submit(self):
- self.write({'state': 'submitted'})
-
- def action_approve(self):
- self.write({'state': 'approved'})
-
- def action_draft(self):
- self.write({'state': 'draft'})
-
- @api.onchange('employee_id')
- def _onchange_employee(self):
- if self.employee_id:
- salary_record = self.env['yuthon.employee.salary'].search([
- ('employee_id', '=', self.employee_id.id),
- ('state', '=', 'active')
- ], limit=1, order='id desc')
- if salary_record:
- self.base_allowance = salary_record.class_teacher_allowance
diff --git a/yuthon_salary/models/employee_salary.py b/yuthon_salary/models/employee_salary.py
deleted file mode 100644
index aa75962..0000000
--- a/yuthon_salary/models/employee_salary.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import models, fields, api
-
-
-class EmployeeSalary(models.Model):
- """教职工薪资档案 - 记录每位教职工的薪资配置"""
- _name = 'yuthon.employee.salary'
- _description = '教职工薪资档案'
- _inherit = ['mail.thread', 'mail.activity.mixin']
- _order = 'employee_id'
-
- name = fields.Char(string='档案编号', required=True, copy=False, readonly=True, default='新建')
- employee_id = fields.Many2one('hr.employee', string='教职工', required=True)
- department_id = fields.Many2one('hr.department', string='所属部门', related='employee_id.department_id', store=True)
- job_id = fields.Many2one('hr.job', string='岗位', related='employee_id.job_id', store=True)
-
- # 基本信息
- employee_type = fields.Selection([
- ('full_time', '正式编制'),
- ('contract', '合同制'),
- ('temporary', '临聘'),
- ('intern', '实习'),
- ('part_time', '兼职'),
- ], string='用工类型', required=True, default='full_time')
- teacher_title = fields.Selection([
- ('none', '无职称'),
- ('third', '三级教师'),
- ('second', '二级教师'),
- ('first', '一级教师'),
- ('senior', '高级教师'),
- ('special', '特级教师'),
- ('lecturer', '讲师'),
- ('associate_prof', '副教授'),
- ('professor', '教授'),
- ], string='教师职称', default='none')
- education_level = fields.Selection([
- ('college', '大专'),
- ('bachelor', '本科'),
- ('master', '硕士'),
- ('doctor', '博士'),
- ], string='学历层次', default='bachelor')
-
- # 薪资结构
- structure_id = fields.Many2one('yuthon.salary.structure', string='适用薪资结构')
-
- # 基本工资
- basic_salary = fields.Float(string='基本工资', required=True, default=0.0, tracking=True)
- position_salary = fields.Float(string='岗位工资', default=0.0, tracking=True)
- performance_salary = fields.Float(string='绩效工资基数', default=0.0, tracking=True)
-
- # 课时费标准(按职称/科目差异化)
- class_hour_rate_normal = fields.Float(string='常规课时费标准(元/课时)', default=0.0)
- class_hour_rate_overtime = fields.Float(string='超课时费标准(元/课时)', default=0.0)
- class_hour_rate_weekend = fields.Float(string='周末课时费标准(元/课时)', default=0.0)
- class_hour_rate_holiday = fields.Float(string='节假日课时费标准(元/课时)', default=0.0)
-
- # 班主任津贴
- is_class_teacher = fields.Boolean(string='是否班主任', default=False)
- class_teacher_allowance = fields.Float(string='班主任津贴', default=0.0)
- class_level = fields.Selection([
- ('junior', '低年级'),
- ('middle', '中年级'),
- ('senior', '高年级'),
- ('junior_high', '初中'),
- ('senior_high', '高中'),
- ], string='任教年级段')
-
- # 其他固定津贴
- seniority_allowance = fields.Float(string='工龄津贴', default=0.0)
- education_allowance = fields.Float(string='学历津贴', default=0.0)
- title_allowance = fields.Float(string='职称津贴', default=0.0)
- other_allowance = fields.Float(string='其他津贴', default=0.0)
-
- # 社保公积金
- social_insurance_base = fields.Float(string='社保基数', default=0.0)
- provident_fund_base = fields.Float(string='公积金基数', default=0.0)
- pension_rate_personal = fields.Float(string='养老保险个人比例(%)', default=8.0)
- medical_rate_personal = fields.Float(string='医疗保险个人比例(%)', default=2.0)
- unemployment_rate_personal = fields.Float(string='失业保险个人比例(%)', default=0.5)
- provident_fund_rate_personal = fields.Float(string='公积金个人比例(%)', default=12.0)
-
- # 个税
- tax_deduction_point = fields.Float(string='个税起征点', default=5000.0)
- special_deduction = fields.Float(string='专项附加扣除', default=0.0)
-
- # 银行卡信息
- bank_name = fields.Char(string='开户银行')
- bank_account = fields.Char(string='银行卡号')
- bank_branch = fields.Char(string='开户支行')
-
- # 状态
- state = fields.Selection([
- ('draft', '草稿'),
- ('active', '生效'),
- ('suspended', '停薪'),
- ('resigned', '离职'),
- ], string='状态', default='draft', tracking=True)
-
- effective_date = fields.Date(string='生效日期', default=fields.Date.today)
- note = fields.Text(string='备注')
- company_id = fields.Many2one('res.company', string='学校', default=lambda self: self.env.company)
-
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- if vals.get('name', '新建') == '新建':
- vals['name'] = self.env['ir.sequence'].next_by_code('yuthon.employee.salary') or '新建'
- return super(EmployeeSalary, self).create(vals_list)
-
- def action_activate(self):
- self.write({'state': 'active'})
-
- def action_suspend(self):
- self.write({'state': 'suspended'})
-
- def action_resign(self):
- self.write({'state': 'resigned'})
diff --git a/yuthon_salary/models/salary_item.py b/yuthon_salary/models/salary_item.py
deleted file mode 100644
index 37d0ed5..0000000
--- a/yuthon_salary/models/salary_item.py
+++ /dev/null
@@ -1,44 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import models, fields, api
-
-
-class SalaryItem(models.Model):
- """薪资项目 - 定义薪资单中的各个项目"""
- _name = 'yuthon.salary.item'
- _description = '薪资项目'
- _order = 'sequence, id'
-
- name = fields.Char(string='项目名称', required=True)
- code = fields.Char(string='项目编码', required=True)
- sequence = fields.Integer(string='排序', default=10)
- category = fields.Selection([
- ('basic', '基本工资'),
- ('position', '岗位工资'),
- ('performance', '绩效工资'),
- ('class_hour', '课时费'),
- ('allowance', '津贴补贴'),
- ('deduction', '扣款项'),
- ('social', '社保公积金'),
- ('tax', '个人所得税'),
- ('other_income', '其他收入'),
- ('other_deduction', '其他扣款'),
- ], string='项目类别', required=True)
- item_type = fields.Selection([
- ('income', '收入项'),
- ('deduction', '扣款项'),
- ], string='项目类型', required=True, default='income')
- calculation_method = fields.Selection([
- ('fixed', '固定金额'),
- ('formula', '公式计算'),
- ('manual', '手动录入'),
- ], string='计算方式', required=True, default='fixed')
- formula = fields.Text(string='计算公式')
- is_taxable = fields.Boolean(string='是否计税', default=False)
- is_social_base = fields.Boolean(string='是否社保基数', default=False)
- is_required = fields.Boolean(string='必填项', default=False)
- active = fields.Boolean(string='启用', default=True)
- note = fields.Text(string='备注')
-
- _sql_constraints = [
- ('code_uniq', 'unique(code)', '项目编码必须唯一!'),
- ]
diff --git a/yuthon_salary/models/salary_slip.py b/yuthon_salary/models/salary_slip.py
deleted file mode 100644
index a367add..0000000
--- a/yuthon_salary/models/salary_slip.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import models, fields, api, _
-from odoo.exceptions import ValidationError
-
-
-class SalarySlip(models.Model):
- """薪资单 - 教职工月度薪资发放记录"""
- _name = 'yuthon.salary.slip'
- _description = '薪资单'
- _inherit = ['mail.thread', 'mail.activity.mixin']
- _order = 'year desc, month desc, employee_id'
-
- name = fields.Char(string='薪资单编号', required=True, copy=False, readonly=True, default='新建')
- employee_id = fields.Many2one('hr.employee', string='教职工', required=True)
- department_id = fields.Many2one('hr.department', string='所属部门', related='employee_id.department_id', store=True)
- job_id = fields.Many2one('hr.job', string='岗位', related='employee_id.job_id', store=True)
-
- # 薪资周期
- year = fields.Integer(string='年度', required=True, default=lambda self: fields.Date.today().year)
- month = fields.Integer(string='月份', required=True, default=lambda self: fields.Date.today().month)
- date_from = fields.Date(string='开始日期', required=True)
- date_to = fields.Date(string='结束日期', required=True)
-
- # 关联档案
- salary_record_id = fields.Many2one('yuthon.employee.salary', string='薪资档案')
-
- # 收入项
- basic_salary = fields.Float(string='基本工资', default=0.0)
- position_salary = fields.Float(string='岗位工资', default=0.0)
- performance_salary = fields.Float(string='绩效工资', default=0.0)
- class_hour_fee = fields.Float(string='课时费', default=0.0)
- class_teacher_allowance = fields.Float(string='班主任津贴', default=0.0)
- seniority_allowance = fields.Float(string='工龄津贴', default=0.0)
- education_allowance = fields.Float(string='学历津贴', default=0.0)
- title_allowance = fields.Float(string='职称津贴', default=0.0)
- other_income = fields.Float(string='其他收入', default=0.0)
-
- # 扣款项
- pension_personal = fields.Float(string='养老保险(个人)', default=0.0)
- medical_personal = fields.Float(string='医疗保险(个人)', default=0.0)
- unemployment_personal = fields.Float(string='失业保险(个人)', default=0.0)
- provident_fund_personal = fields.Float(string='公积金(个人)', default=0.0)
- other_deduction = fields.Float(string='其他扣款', default=0.0)
-
- # 个税
- taxable_income = fields.Float(string='应纳税所得额', compute='_compute_totals', store=True)
- personal_income_tax = fields.Float(string='个人所得税', compute='_compute_tax', store=True)
-
- # 合计
- total_income = fields.Float(string='应发合计', compute='_compute_totals', store=True)
- total_deduction = fields.Float(string='扣款合计', compute='_compute_totals', store=True)
- net_salary = fields.Float(string='实发工资', compute='_compute_totals', store=True)
-
- # 银行信息
- bank_name = fields.Char(string='开户银行')
- bank_account = fields.Char(string='银行卡号')
-
- # 状态
- state = fields.Selection([
- ('draft', '草稿'),
- ('confirmed', '已确认'),
- ('approved', '已审核'),
- ('paid', '已发放'),
- ], string='状态', default='draft', tracking=True)
-
- line_ids = fields.One2many('yuthon.salary.slip.line', 'slip_id', string='薪资明细')
- note = fields.Text(string='备注')
- company_id = fields.Many2one('res.company', string='学校', default=lambda self: self.env.company)
-
- @api.depends('basic_salary', 'position_salary', 'performance_salary', 'class_hour_fee',
- 'class_teacher_allowance', 'seniority_allowance', 'education_allowance',
- 'title_allowance', 'other_income',
- 'pension_personal', 'medical_personal', 'unemployment_personal',
- 'provident_fund_personal', 'other_deduction', 'personal_income_tax')
- def _compute_totals(self):
- for slip in self:
- income = (
- slip.basic_salary + slip.position_salary + slip.performance_salary +
- slip.class_hour_fee + slip.class_teacher_allowance +
- slip.seniority_allowance + slip.education_allowance +
- slip.title_allowance + slip.other_income
- )
- deduction = (
- slip.pension_personal + slip.medical_personal +
- slip.unemployment_personal + slip.provident_fund_personal +
- slip.other_deduction + slip.personal_income_tax
- )
- slip.total_income = income
- slip.total_deduction = deduction
- slip.taxable_income = max(0, income - deduction + slip.personal_income_tax - 5000)
- slip.net_salary = income - deduction
-
- @api.depends('taxable_income')
- def _compute_tax(self):
- """简化版个税计算(中国个税累进税率)"""
- for slip in self:
- taxable = slip.taxable_income
- if taxable <= 0:
- slip.personal_income_tax = 0
- elif taxable <= 3000:
- slip.personal_income_tax = taxable * 0.03
- elif taxable <= 12000:
- slip.personal_income_tax = taxable * 0.10 - 210
- elif taxable <= 25000:
- slip.personal_income_tax = taxable * 0.20 - 1410
- elif taxable <= 35000:
- slip.personal_income_tax = taxable * 0.25 - 2660
- elif taxable <= 55000:
- slip.personal_income_tax = taxable * 0.30 - 4410
- elif taxable <= 80000:
- slip.personal_income_tax = taxable * 0.35 - 7160
- else:
- slip.personal_income_tax = taxable * 0.45 - 15160
-
- @api.model_create_multi
- def create(self, vals_list):
- for vals in vals_list:
- if vals.get('name', '新建') == '新建':
- vals['name'] = self.env['ir.sequence'].next_by_code('yuthon.salary.slip') or '新建'
- return super(SalarySlip, self).create(vals_list)
-
- def action_calculate(self):
- """自动计算薪资"""
- for slip in self:
- if slip.salary_record_id:
- record = slip.salary_record_id
- slip.basic_salary = record.basic_salary
- slip.position_salary = record.position_salary
- slip.performance_salary = record.performance_salary
- slip.seniority_allowance = record.seniority_allowance
- slip.education_allowance = record.education_allowance
- slip.title_allowance = record.title_allowance
- slip.bank_name = record.bank_name
- slip.bank_account = record.bank_account
-
- # 计算社保
- if record.social_insurance_base > 0:
- slip.pension_personal = record.social_insurance_base * record.pension_rate_personal / 100
- slip.medical_personal = record.social_insurance_base * record.medical_rate_personal / 100
- slip.unemployment_personal = record.social_insurance_base * record.unemployment_rate_personal / 100
- if record.provident_fund_base > 0:
- slip.provident_fund_personal = record.provident_fund_base * record.provident_fund_rate_personal / 100
-
- # 统计课时费
- class_hours = self.env['yuthon.class.hour'].search([
- ('employee_id', '=', slip.employee_id.id),
- ('date', '>=', slip.date_from),
- ('date', '<=', slip.date_to),
- ('state', 'in', ['approved', 'paid']),
- ])
- slip.class_hour_fee = sum(ch.amount for ch in class_hours)
-
- # 统计班主任津贴
- allowances = self.env['yuthon.class.teacher.allowance'].search([
- ('employee_id', '=', slip.employee_id.id),
- ('year', '=', slip.year),
- ('month', '=', slip.month),
- ('state', 'in', ['approved', 'paid']),
- ])
- slip.class_teacher_allowance = sum(a.total_amount for a in allowances)
-
- slip._compute_totals()
- slip._compute_tax()
-
- def action_confirm(self):
- self.write({'state': 'confirmed'})
-
- def action_approve(self):
- self.write({'state': 'approved'})
-
- def action_pay(self):
- self.write({'state': 'paid'})
-
- def action_draft(self):
- self.write({'state': 'draft'})
-
- @api.constrains('year', 'month')
- def _check_year_month(self):
- for slip in self:
- if slip.month < 1 or slip.month > 12:
- raise ValidationError(_('月份必须在 1-12 之间!'))
- if slip.year < 2000 or slip.year > 2100:
- raise ValidationError(_('年度格式不正确!'))
-
-
-class SalarySlipLine(models.Model):
- """薪资单明细行"""
- _name = 'yuthon.salary.slip.line'
- _description = '薪资单明细'
- _order = 'sequence, id'
-
- slip_id = fields.Many2one('yuthon.salary.slip', string='薪资单', required=True, ondelete='cascade')
- sequence = fields.Integer(string='排序', default=10)
- item_id = fields.Many2one('yuthon.salary.item', string='薪资项目')
- name = fields.Char(string='项目名称')
- item_type = fields.Selection([
- ('income', '收入'),
- ('deduction', '扣款'),
- ], string='类型')
- amount = fields.Float(string='金额', default=0.0)
- note = fields.Char(string='备注')
diff --git a/yuthon_salary/models/salary_structure.py b/yuthon_salary/models/salary_structure.py
deleted file mode 100644
index 4c24c3c..0000000
--- a/yuthon_salary/models/salary_structure.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# -*- coding: utf-8 -*-
-from odoo import models, fields, api
-
-
-class SalaryStructure(models.Model):
- """薪资结构 - 定义不同岗位/职称的薪资构成"""
- _name = 'yuthon.salary.structure'
- _description = '薪资结构'
- _order = 'name'
-
- name = fields.Char(string='结构名称', required=True)
- code = fields.Char(string='结构编码', required=True)
- description = fields.Text(string='说明')
- # 适用对象
- applicable_type = fields.Selection([
- ('teacher', '任课教师'),
- ('admin', '行政人员'),
- ('leadership', '领导班子'),
- ('support', '后勤人员'),
- ('intern', '实习教师'),
- ('all', '全体适用'),
- ], string='适用类型', required=True, default='teacher')
- # 适用学校类型
- school_type = fields.Selection([
- ('kindergarten', '幼儿园'),
- ('primary', '小学'),
- ('junior', '初中'),
- ('senior', '高中'),
- ('vocational', '职业院校'),
- ('university', '高等院校'),
- ('all', '全部适用'),
- ], string='适用学校类型', required=True, default='all')
- line_ids = fields.One2many('yuthon.salary.structure.line', 'structure_id', string='薪资项目明细')
- active = fields.Boolean(string='启用', default=True)
- company_id = fields.Many2one('res.company', string='学校', default=lambda self: self.env.company)
-
- # 合计字段
- total_basic = fields.Float(string='基本收入合计', compute='_compute_totals', store=True)
- total_deduction = fields.Float(string='扣款合计', compute='_compute_totals', store=True)
- total_net = fields.Float(string='实发合计', compute='_compute_totals', store=True)
-
- @api.depends('line_ids.amount', 'line_ids.item_id.item_type')
- def _compute_totals(self):
- for structure in self:
- income = sum(line.amount for line in structure.line_ids if line.item_id.item_type == 'income')
- deduction = sum(line.amount for line in structure.line_ids if line.item_id.item_type == 'deduction')
- structure.total_basic = income
- structure.total_deduction = deduction
- structure.total_net = income - deduction
-
- _sql_constraints = [
- ('code_uniq', 'unique(code)', '结构编码必须唯一!'),
- ]
-
-
-class SalaryStructureLine(models.Model):
- """薪资结构明细行"""
- _name = 'yuthon.salary.structure.line'
- _description = '薪资结构明细'
- _order = 'sequence, id'
-
- structure_id = fields.Many2one('yuthon.salary.structure', string='薪资结构', required=True, ondelete='cascade')
- sequence = fields.Integer(string='排序', default=10)
- item_id = fields.Many2one('yuthon.salary.item', string='薪资项目', required=True)
- amount = fields.Float(string='默认金额', default=0.0)
- note = fields.Char(string='备注')
diff --git a/yuthon_salary/security/ir.model.access.csv b/yuthon_salary/security/ir.model.access.csv
deleted file mode 100644
index 4d32468..0000000
--- a/yuthon_salary/security/ir.model.access.csv
+++ /dev/null
@@ -1,19 +0,0 @@
-id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
-access_salary_item_user,yuthon.salary.item.user,model_yuthon_salary_item,base.group_user,1,0,0,0
-access_salary_item_manager,yuthon.salary.item.manager,model_yuthon_salary_item,yuthon_salary.group_manager,1,1,1,1
-access_salary_structure_user,yuthon.salary.structure.user,model_yuthon_salary_structure,base.group_user,1,0,0,0
-access_salary_structure_manager,yuthon.salary.structure.manager,model_yuthon_salary_structure,yuthon_salary.group_manager,1,1,1,1
-access_salary_structure_line_user,yuthon.salary.structure.line.user,model_yuthon_salary_structure_line,base.group_user,1,0,0,0
-access_salary_structure_line_manager,yuthon.salary.structure.line.manager,model_yuthon_salary_structure_line,yuthon_salary.group_manager,1,1,1,1
-access_employee_salary_user,yuthon.employee.salary.user,model_yuthon_employee_salary,base.group_user,1,0,0,0
-access_employee_salary_manager,yuthon.employee.salary.manager,model_yuthon_employee_salary,yuthon_salary.group_manager,1,1,1,1
-access_employee_salary_hr,yuthon.employee.salary.hr,model_yuthon_employee_salary,yuthon_salary.group_hr,1,1,1,0
-access_class_hour_user,yuthon.class.hour.user,model_yuthon_class_hour,base.group_user,1,1,1,0
-access_class_hour_manager,yuthon.class.hour.manager,model_yuthon_class_hour,yuthon_salary.group_manager,1,1,1,1
-access_class_teacher_allowance_user,yuthon.class.teacher.allowance.user,model_yuthon_class_teacher_allowance,base.group_user,1,1,1,0
-access_class_teacher_allowance_manager,yuthon.class.teacher.allowance.manager,model_yuthon_class_teacher_allowance,yuthon_salary.group_manager,1,1,1,1
-access_salary_slip_user,yuthon.salary.slip.user,model_yuthon_salary_slip,base.group_user,1,0,0,0
-access_salary_slip_manager,yuthon.salary.slip.manager,model_yuthon_salary_slip,yuthon_salary.group_manager,1,1,1,1
-access_salary_slip_hr,yuthon.salary.slip.hr,model_yuthon_salary_slip,yuthon_salary.group_hr,1,1,1,0
-access_salary_slip_line_user,yuthon.salary.slip.line.user,model_yuthon_salary_slip_line,base.group_user,1,0,0,0
-access_salary_slip_line_manager,yuthon.salary.slip.line.manager,model_yuthon_salary_slip_line,yuthon_salary.group_manager,1,1,1,1
diff --git a/yuthon_salary/security/yuthon_salary_groups.xml b/yuthon_salary/security/yuthon_salary_groups.xml
deleted file mode 100644
index 8df8a1d..0000000
--- a/yuthon_salary/security/yuthon_salary_groups.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
- 薪资专员
-
-
-
-
-
- 薪资管理员
-
-
-
-
-
diff --git a/yuthon_salary/security/yuthon_salary_security.xml b/yuthon_salary/security/yuthon_salary_security.xml
deleted file mode 100644
index bc2e0d6..0000000
--- a/yuthon_salary/security/yuthon_salary_security.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
- 教职工薪资档案:多学校隔离
-
-
- ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
-
-
-
- 薪资单:多学校隔离
-
-
- ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
-
-
-
- 课时记录:多学校隔离
-
-
- ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
-
-
-
- 班主任津贴:多学校隔离
-
-
- ['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]
-
-
-
-
- 教职工只能查看自己的薪资单
-
-
- [('employee_id.user_id', '=', user.id)]
-
-
-
-
- 教职工只能查看自己的课时记录
-
-
- [('employee_id.user_id', '=', user.id)]
-
-
-
-
diff --git a/yuthon_salary/views/class_hour_views.xml b/yuthon_salary/views/class_hour_views.xml
deleted file mode 100644
index 8be45fb..0000000
--- a/yuthon_salary/views/class_hour_views.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
- yuthon.class.hour.tree
- yuthon.class.hour
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- yuthon.class.hour.form
- yuthon.class.hour
-
-
-
-
-
-
- yuthon.class.hour.search
- yuthon.class.hour
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 课时记录
- yuthon.class.hour
- list,form
-
-
diff --git a/yuthon_salary/views/class_teacher_allowance_views.xml b/yuthon_salary/views/class_teacher_allowance_views.xml
deleted file mode 100644
index 1000f35..0000000
--- a/yuthon_salary/views/class_teacher_allowance_views.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-
- yuthon.class.teacher.allowance.tree
- yuthon.class.teacher.allowance
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- yuthon.class.teacher.allowance.form
- yuthon.class.teacher.allowance
-
-
-
-
-
-
- yuthon.class.teacher.allowance.search
- yuthon.class.teacher.allowance
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 班主任津贴
- yuthon.class.teacher.allowance
- list,form
-
-
diff --git a/yuthon_salary/views/employee_salary_views.xml b/yuthon_salary/views/employee_salary_views.xml
deleted file mode 100644
index 58e5793..0000000
--- a/yuthon_salary/views/employee_salary_views.xml
+++ /dev/null
@@ -1,138 +0,0 @@
-
-
-
- yuthon.employee.salary.tree
- yuthon.employee.salary
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- yuthon.employee.salary.form
- yuthon.employee.salary
-
-
-
-
-
-
- yuthon.employee.salary.search
- yuthon.employee.salary
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 教职工薪资档案
- yuthon.employee.salary
- list,form
-
-
diff --git a/yuthon_salary/views/menu_views.xml b/yuthon_salary/views/menu_views.xml
deleted file mode 100644
index 794017b..0000000
--- a/yuthon_salary/views/menu_views.xml
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/yuthon_salary/views/salary_item_views.xml b/yuthon_salary/views/salary_item_views.xml
deleted file mode 100644
index 7133c60..0000000
--- a/yuthon_salary/views/salary_item_views.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
- yuthon.salary.item.tree
- yuthon.salary.item
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- yuthon.salary.item.form
- yuthon.salary.item
-
-
-
-
-
-
- yuthon.salary.item.search
- yuthon.salary.item
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 薪资项目
- yuthon.salary.item
- list,form
-
-
diff --git a/yuthon_salary/views/salary_report_views.xml b/yuthon_salary/views/salary_report_views.xml
deleted file mode 100644
index 395fdc1..0000000
--- a/yuthon_salary/views/salary_report_views.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- yuthon.salary.slip.pivot
- yuthon.salary.slip
-
-
-
-
-
-
-
-
-
-
-
-
-
- yuthon.salary.slip.graph
- yuthon.salary.slip
-
-
-
-
-
-
-
-
diff --git a/yuthon_salary/views/salary_slip_views.xml b/yuthon_salary/views/salary_slip_views.xml
deleted file mode 100644
index 84c43fd..0000000
--- a/yuthon_salary/views/salary_slip_views.xml
+++ /dev/null
@@ -1,137 +0,0 @@
-
-
-
- yuthon.salary.slip.tree
- yuthon.salary.slip
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- yuthon.salary.slip.form
- yuthon.salary.slip
-
-
-
-
-
-
- yuthon.salary.slip.search
- yuthon.salary.slip
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 薪资单
- yuthon.salary.slip
- list,form
-
-
-
-
- 薪资报表
- yuthon.salary.slip
- list,form,pivot,graph
-
-
diff --git a/yuthon_salary/views/salary_structure_views.xml b/yuthon_salary/views/salary_structure_views.xml
deleted file mode 100644
index edac514..0000000
--- a/yuthon_salary/views/salary_structure_views.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
- yuthon.salary.structure.tree
- yuthon.salary.structure
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- yuthon.salary.structure.form
- yuthon.salary.structure
-
-
-
-
-
-
- 薪资结构
- yuthon.salary.structure
- list,form
-
-