163 lines
6.6 KiB
Python
163 lines
6.6 KiB
Python
from odoo import api, models
|
|
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
|
|
class StaffPositionReport(models.Model):
|
|
_inherit = "hr.job"
|
|
|
|
@api.model
|
|
def get_staff_position_report(self, params):
|
|
"""人员岗位报表
|
|
|
|
返回当前有效岗位的编制、在岗、缺编等信息。
|
|
"""
|
|
# 不再过滤is_enable和establishment_quotas,查询所有岗位
|
|
domain = []
|
|
|
|
company_id = params.get("company_id")
|
|
department_id = params.get("department_id")
|
|
keyword = params.get("keyword")
|
|
date_end = params.get("date_end") # 获取截止日期
|
|
|
|
if company_id:
|
|
domain.append(("company_id", "=", company_id))
|
|
if department_id:
|
|
domain.append(("department_id", "=", department_id))
|
|
if keyword:
|
|
domain += [
|
|
"|",
|
|
("name", "ilike", keyword),
|
|
("department_id.name", "ilike", keyword),
|
|
]
|
|
|
|
# 先查询所有符合条件的岗位
|
|
jobs = self.search(domain)
|
|
|
|
# 定义固定的部门排序(按照图二的顺序)
|
|
# 部门序号 -> 排序优先级
|
|
dept_order_map = {
|
|
'010102': 1, # 党群人力资源部
|
|
'010103': 2, # 办公室
|
|
'01010301': 2.5, # 办公室-厨卫(子部门)
|
|
'010104': 3, # 财务部
|
|
'010105': 4, # 风控审计部/纪检审计部
|
|
'010106': 4, # 风控法务部
|
|
'010107': 5, # 企业管理部
|
|
'010108': 6, # 资本运营部/产业投资部
|
|
'010109': 7, # 投资发展部/城市开发部
|
|
}
|
|
|
|
# 在Python层排序
|
|
def sort_key(j):
|
|
dept_code = j.department_id.department_code or ''
|
|
job_number = j.number or ''
|
|
job_name = j.name or ''
|
|
|
|
# 获取部门排序优先级,如果不在映射表中则使用序号数字值
|
|
dept_priority = dept_order_map.get(dept_code, 999)
|
|
if dept_priority == 999 and dept_code:
|
|
try:
|
|
dept_priority = float(dept_code)
|
|
except ValueError:
|
|
dept_priority = 9999
|
|
|
|
# 岗位排序:需要特殊处理某些岗位
|
|
# 办公室的岗位顺序:主任(4) → 副主任(空) → 行政(9) → 后勤(6) → 工勤(10) → 其他
|
|
if job_number:
|
|
try:
|
|
base_sort = float(job_number)
|
|
|
|
# 特殊处理:办公室的行政管理岗虽然序号9,但应该排在后勤(6)前面
|
|
if '办公室' in j.department_id.name:
|
|
if '行政' in job_name and '管理' in job_name:
|
|
job_sort = 5.5 # 排在副主任(4.5)和后勤(6)之间
|
|
elif '后勤' in job_name and '管理' in job_name:
|
|
job_sort = 6
|
|
else:
|
|
job_sort = base_sort
|
|
else:
|
|
job_sort = base_sort
|
|
except ValueError:
|
|
job_sort = 999
|
|
else:
|
|
# 序号为空时,根据岗位名称判断位置
|
|
if '副' in job_name and ('经理' in job_name or '主任' in job_name):
|
|
# 副经理/副主任排在4.5(介于经理4和其他岗位之间)
|
|
job_sort = 4.5
|
|
else:
|
|
# 其他没有序号的岗位排在最后
|
|
job_sort = 999
|
|
|
|
return (dept_priority, job_sort, job_name) # 最后按名称排序保证稳定性
|
|
|
|
jobs = jobs.sorted(key=sort_key)
|
|
|
|
# 计算上月最后一天 23:59:59
|
|
# 如果传入了截止日期,使用截止日期,否则使用当前日期
|
|
if date_end:
|
|
try:
|
|
end_date = datetime.fromisoformat(date_end.replace(' 23:59:59', '')).date()
|
|
except:
|
|
end_date = datetime.now().date()
|
|
else:
|
|
end_date = datetime.now().date()
|
|
|
|
first_day_of_this_month = end_date.replace(day=1)
|
|
last_day_of_last_month = first_day_of_this_month - relativedelta(days=1)
|
|
last_moment_of_last_month = datetime.combine(last_day_of_last_month, datetime.max.time())
|
|
|
|
# selection 字段映射成中文
|
|
compiling_status_field = self._fields.get("compiling_status")
|
|
status_selection = dict(compiling_status_field.selection) if compiling_status_field else {}
|
|
|
|
# 生成报表标题
|
|
company_name = ""
|
|
if company_id:
|
|
company = self.env['res.company'].browse(company_id)
|
|
company_name = company.name if company else ""
|
|
|
|
# 年月格式:YYYY年MM月
|
|
year_month = end_date.strftime("%Y年%m月")
|
|
report_title = f"{company_name}{year_month}各部门岗位在岗人员情况表"
|
|
|
|
rows = []
|
|
for job in jobs:
|
|
# 统计上月人数:上月最后一天 + active=True + 合同有效
|
|
last_month_count = self.env['hr.employee'].search_count([
|
|
('job_id', '=', job.id),
|
|
('active', '=', True),
|
|
('contract_id.date_start', '<=', last_day_of_last_month),
|
|
'|',
|
|
('contract_id.date_end', '>=', last_day_of_last_month),
|
|
('contract_id.date_end', '=', False),
|
|
])
|
|
|
|
# 当前在岗人数
|
|
current_count = job.no_of_employee or 0
|
|
|
|
# 变动情况
|
|
change = current_count - last_month_count
|
|
if change > 0:
|
|
change_text = f"新增 {change} 人"
|
|
elif change < 0:
|
|
change_text = f"减少 {abs(change)} 人"
|
|
else:
|
|
change_text = ""
|
|
|
|
rows.append({
|
|
"部门": job.department_id.name if job.department_id else "",
|
|
"岗位": job.name or "",
|
|
"编制数": job.establishment_quotas or 0,
|
|
"在岗人数": current_count,
|
|
"上月人数": last_month_count,
|
|
"变动情况": change_text,
|
|
"缺岗人数": job.missing_number or 0,
|
|
"编制外人数": job.compiling_external or 0,
|
|
"状态": status_selection.get(job.compiling_status, "") if job.compiling_status else "",
|
|
"在岗人员": job.job_personnel or "",
|
|
"公司": job.company_id.name if job.company_id else "",
|
|
})
|
|
|
|
return {"rows": rows, "title": report_title}
|