diff --git a/yuthon_report/__manifest__.py b/yuthon_report/__manifest__.py index 01883e771..41134b56a 100644 --- a/yuthon_report/__manifest__.py +++ b/yuthon_report/__manifest__.py @@ -42,6 +42,7 @@ 'views/monthly_maintenance_fee_report.xml', 'views/yuthon_report_res_partner.xml', 'views/att_report_view.xml', + 'views/staff_position_report.xml', ], 'installable': True, 'application': True, diff --git a/yuthon_report/models/__init__.py b/yuthon_report/models/__init__.py index 2694b6c96..d91ade962 100644 --- a/yuthon_report/models/__init__.py +++ b/yuthon_report/models/__init__.py @@ -31,4 +31,5 @@ from . import monthly_expense_total_report from . import monthly_assessment_fee_report from . import monthly_other_expense_report from . import monthly_maintenance_fee_report -from . import att_report \ No newline at end of file +from . import att_report +from . import staff_position_report \ No newline at end of file diff --git a/yuthon_report/models/cumulative_arrears_report.py b/yuthon_report/models/cumulative_arrears_report.py index e9da491e6..58d0b4245 100644 --- a/yuthon_report/models/cumulative_arrears_report.py +++ b/yuthon_report/models/cumulative_arrears_report.py @@ -26,9 +26,7 @@ class CumulativeArrearsReport(models.Model): date_start = params.get("date_start") date_end = params.get("date_end") - if date_start: - start_dt = datetime.datetime.fromisoformat(date_start).date() - domain.append(("due_date", ">=", start_dt)) + # 累计欠收:只限定截止日期,包含截止日之前所有欠收 if date_end: end_dt = datetime.datetime.fromisoformat(date_end).date() domain.append(("due_date", "<=", end_dt)) diff --git a/yuthon_report/models/staff_position_report.py b/yuthon_report/models/staff_position_report.py new file mode 100644 index 000000000..c97c44c87 --- /dev/null +++ b/yuthon_report/models/staff_position_report.py @@ -0,0 +1,85 @@ +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): + """人员岗位报表 + + 返回当前有效岗位的编制、在岗、缺编等信息。 + """ + domain = [ + ("is_enable", "=", True), + ("establishment_quotas", ">", 0), + ] + + company_id = params.get("company_id") + department_id = params.get("department_id") + keyword = params.get("keyword") + + 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, order="department_id, name") + + # 计算上月最后一天 23:59:59 + today = datetime.now().date() + first_day_of_this_month = today.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 {} + + 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 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 8ecb33e5c..1a02f069a 100644 --- a/yuthon_report/static/src/components/yuthon_report/att_report.js +++ b/yuthon_report/static/src/components/yuthon_report/att_report.js @@ -43,7 +43,30 @@ class ReceivableReport extends Component { theme: agGrid.themeMaterial, columnDefs: this.config.columns || [], rowData: [], - sideBar: true, + sideBar: { + toolPanels: [ + { + id: 'columns', + labelDefault: '列', + labelKey: 'columns', + iconKey: 'columns', + toolPanel: 'agColumnsToolPanel', + toolPanelParams: { + suppressValues: true, + suppressPivots: true, + suppressPivotMode: true, + } + }, + { + id: 'filters', + labelDefault: '过滤器', + labelKey: 'filters', + iconKey: 'filter', + toolPanel: 'agFiltersToolPanel' + } + ], + defaultToolPanel: '', + }, enableCharts: true, cellSelection: true, defaultColDef: { @@ -141,14 +164,20 @@ class ReceivableReport extends Component { async onUpdateCompany(v) { this.state.selectCompany = v[0] || {} await this.searchDomain() + // 自动搜索 + await this.onSearch() } async onUpdateStructure(v) { this.state.selectStructure = v[0] || {} + // 自动搜索 + await this.onSearch() } async onUpdateDepartment(v) { this.state.selectDepartment = v[0] + // 自动搜索 + await this.onSearch() } 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 4a29b342d..23d551bdc 100644 --- a/yuthon_report/static/src/components/yuthon_report/att_report.xml +++ b/yuthon_report/static/src/components/yuthon_report/att_report.xml @@ -12,71 +12,71 @@
-
+
-
- - +
+
- +
- -
-
- +
-
- + + +
-
- + + +
-
- +
diff --git a/yuthon_report/views/staff_position_report.xml b/yuthon_report/views/staff_position_report.xml new file mode 100644 index 000000000..dab1954e5 --- /dev/null +++ b/yuthon_report/views/staff_position_report.xml @@ -0,0 +1,38 @@ + + + + + 人员岗位报表 + att_report_client + + { + "report_config": { + "model": "hr.job", + "method": "get_staff_position_report", + "columns": [ + {"headerName": "部门", "field": "部门", "flex": 1.5}, + {"headerName": "岗位", "field": "岗位", "flex": 1.5}, + {"headerName": "编制数", "field": "编制数", "flex": 0.8, "type": "number"}, + {"headerName": "在岗人数", "field": "在岗人数", "flex": 0.8, "type": "number"}, + {"headerName": "上月人数", "field": "上月人数", "flex": 0.8, "type": "number"}, + {"headerName": "变动情况", "field": "变动情况", "flex": 1}, + {"headerName": "缺岗人数", "field": "缺岗人数", "flex": 0.8, "type": "number"}, + {"headerName": "编制外人数", "field": "编制外人数", "flex": 0.8, "type": "number"}, + {"headerName": "状态", "field": "状态", "flex": 0.8}, + {"headerName": "在岗人员", "field": "在岗人员", "flex": 2}, + {"headerName": "公司", "field": "公司", "flex": 1} + ] + } + } + + + + + +