diff --git a/yuthon_report/models/staff_position_report.py b/yuthon_report/models/staff_position_report.py index c97c44c87..6e57594e7 100644 --- a/yuthon_report/models/staff_position_report.py +++ b/yuthon_report/models/staff_position_report.py @@ -20,6 +20,7 @@ class StaffPositionReport(models.Model): 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)) @@ -32,11 +33,79 @@ class StaffPositionReport(models.Model): ("department_id.name", "ilike", keyword), ] - jobs = self.search(domain, order="department_id, name") + # 先查询所有符合条件的岗位 + 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 - today = datetime.now().date() - first_day_of_this_month = today.replace(day=1) + # 如果传入了截止日期,使用截止日期,否则使用当前日期 + 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()) @@ -44,6 +113,16 @@ class StaffPositionReport(models.Model): 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 + 合同有效 @@ -82,4 +161,4 @@ class StaffPositionReport(models.Model): "公司": job.company_id.name if job.company_id else "", }) - return rows + return {"rows": rows, "title": report_title} diff --git a/yuthon_report/static/src/components/yuthon_report/att_report.js b/yuthon_report/static/src/components/yuthon_report/att_report.js index 1a02f069a..1e0f1ad6f 100644 --- a/yuthon_report/static/src/components/yuthon_report/att_report.js +++ b/yuthon_report/static/src/components/yuthon_report/att_report.js @@ -30,7 +30,8 @@ class ReceivableReport extends Component { selectCompany: {}, selectStructure: {}, domainDepartment:[], - domainStructure:[] + domainStructure:[], + reportTitle: "" // 添加报表标题状态 }); this.config = this.props.action.context.report_config || {}; @@ -151,7 +152,14 @@ class ReceivableReport extends Component { [params] ); console.log(result) - this.grid.setGridOption('rowData', result); + // 支持返回对象格式 {rows: [], title: ""} 或直接返回数组 + if (result && typeof result === 'object' && 'rows' in result) { + this.grid.setGridOption('rowData', result.rows); + this.state.reportTitle = result.title || ""; + } else { + this.grid.setGridOption('rowData', result); + this.state.reportTitle = ""; + } } onExportExcel() { diff --git a/yuthon_report/static/src/components/yuthon_report/att_report.xml b/yuthon_report/static/src/components/yuthon_report/att_report.xml index 23d551bdc..e482c9148 100644 --- a/yuthon_report/static/src/components/yuthon_report/att_report.xml +++ b/yuthon_report/static/src/components/yuthon_report/att_report.xml @@ -4,11 +4,11 @@
- - - - - +
+
+
+
+