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 - -