diff --git a/boolean_group_operator/__init__.py b/boolean_group_operator/__init__.py new file mode 100644 index 000000000..a0fdc10fe --- /dev/null +++ b/boolean_group_operator/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import models diff --git a/boolean_group_operator/__manifest__.py b/boolean_group_operator/__manifest__.py new file mode 100644 index 000000000..a6218cfa7 --- /dev/null +++ b/boolean_group_operator/__manifest__.py @@ -0,0 +1,17 @@ +# -*- coding: utf-8 -*- +{ + 'name': 'boolean_group_operator', + 'summary': 'boolean group operator', + 'description': 'boolean_group_operator', + 'author': 'CY', + 'website': '', + 'category': 'Tools', + 'version': '17.0', + 'depends': ['base'], + 'assets': { + 'web.assets_backend': [ + '/boolean_group_operator/static/src/**/*', + ] + } +} + diff --git a/boolean_group_operator/models/__init__.py b/boolean_group_operator/models/__init__.py new file mode 100644 index 000000000..07bf836d5 --- /dev/null +++ b/boolean_group_operator/models/__init__.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# import odoo +# +# from odoo.tools import SQL +# +# odoo.models.READ_GROUP_AGGREGATE.update({ +# 'count_true': lambda table, expr: SQL('COUNT(*) FILTER (WHERE %s = true)', expr), +# 'count_false': lambda table, expr: SQL('COUNT(*) FILTER (WHERE %s = false)', expr), +# }) + +# 哪个模型需要就移植到哪个模型下 +# @api.model +# def web_read_group(self, domain, fields, groupby, limit=None, offset=0, orderby=False, lazy=True): +# result = super().web_read_group(domain, fields, groupby, limit, offset, orderby, lazy) +# fields_dict = self.fields_get(fields) +# for group in result.get('groups'): +# for field in fields: +# if fields_dict[field].get('type') == 'boolean': +# group[field] = len([r for r in self.search_read(group['__domain'], fields=[field]) if r.get(field)]) +# return result diff --git a/yuthon_hr_attendance/static/src/js/list_renderer.js b/boolean_group_operator/static/src/js/list_renderer.js similarity index 62% rename from yuthon_hr_attendance/static/src/js/list_renderer.js rename to boolean_group_operator/static/src/js/list_renderer.js index 621d2bd73..6ed9aa386 100644 --- a/yuthon_hr_attendance/static/src/js/list_renderer.js +++ b/boolean_group_operator/static/src/js/list_renderer.js @@ -5,6 +5,17 @@ import { ListRenderer } from "@web/views/list/list_renderer"; patch(ListRenderer.prototype, { + + getAggregateColumns(group) { + const result = super.getAggregateColumns(group); + result.forEach((column) => { + if (column.type === "field") { + column.field_type = this.props.list.fields[column.name].type; + } + }); + return result; + }, + formatAggregateValue(group, column) { const result = super.formatAggregateValue(group, column); const field = this.props.list.fields[column.name]; diff --git a/yuthon_hr_attendance/static/src/js/relational_model.js b/boolean_group_operator/static/src/js/relational_model.js similarity index 100% rename from yuthon_hr_attendance/static/src/js/relational_model.js rename to boolean_group_operator/static/src/js/relational_model.js diff --git a/boolean_group_operator/static/src/scss/list_renderer.scss b/boolean_group_operator/static/src/scss/list_renderer.scss new file mode 100644 index 000000000..ac542ae61 --- /dev/null +++ b/boolean_group_operator/static/src/scss/list_renderer.scss @@ -0,0 +1,3 @@ +.o_list_boolean { + text-align: left; +} \ No newline at end of file diff --git a/boolean_group_operator/static/src/xml/list_renderer.xml b/boolean_group_operator/static/src/xml/list_renderer.xml new file mode 100644 index 000000000..6f92e34f7 --- /dev/null +++ b/boolean_group_operator/static/src/xml/list_renderer.xml @@ -0,0 +1,12 @@ + + + + + +
+ +
+
+
+ +
diff --git a/yuthon_hr_attendance/__manifest__.py b/yuthon_hr_attendance/__manifest__.py index 55fa317a7..c2372acc9 100644 --- a/yuthon_hr_attendance/__manifest__.py +++ b/yuthon_hr_attendance/__manifest__.py @@ -37,6 +37,7 @@ 'views/attendance_scheme.xml', 'views/duty_approval.xml', 'views/all_attendance_menu.xml', + ], 'assets': { 'web.assets_backend': [ @@ -46,7 +47,6 @@ 'yuthon_hr_attendance/static/src/planning_gantt/planning_gantt_renderer.js', 'yuthon_hr_attendance/static/src/components/*/*.xml', 'yuthon_hr_attendance/static/src/css/*.css', - 'yuthon_hr_attendance/static/src/**/*', ], }, 'installable': True, diff --git a/yuthon_hr_attendance/models/__init__.py b/yuthon_hr_attendance/models/__init__.py index eb3ce5ac9..18d4d1268 100644 --- a/yuthon_hr_attendance/models/__init__.py +++ b/yuthon_hr_attendance/models/__init__.py @@ -15,3 +15,11 @@ from . import yuthon_shift_planning from . import yuthon_run_planning from . import duty_approval from . import yuthon_customer_approval + + +# from odoo.tools import SQL +# import odoo +# odoo.models.READ_GROUP_AGGREGATE.update({ +# 'count_true': lambda table, expr: SQL('COUNT(*) FILTER (WHERE %s = true)', expr), +# 'count_false': lambda table, expr: SQL('COUNT(*) FILTER (WHERE %s = false)', expr), +# }) diff --git a/yuthon_hr_attendance/models/hr_attendance.py b/yuthon_hr_attendance/models/hr_attendance.py index 0f7a9915d..69080b13e 100644 --- a/yuthon_hr_attendance/models/hr_attendance.py +++ b/yuthon_hr_attendance/models/hr_attendance.py @@ -8,18 +8,18 @@ import logging _logger = logging.getLogger(__name__) + class HrAttendance(models.Model): _inherit = "hr.attendance" _description = "Attendance" _rec_name = 'current_data' is_clock_card = fields.Boolean(string="外勤") - is_no_card = fields.Boolean(string="缺卡", compute='_compute_attendance_flags') - is_early_card = fields.Boolean(string="早退", compute='_compute_attendance_flags') - is_late_card = fields.Boolean(string="迟到", compute='_compute_attendance_flags') + is_no_card = fields.Boolean(string="缺卡", compute='_compute_attendance_flags', groups_operator='count_false') + is_early_card = fields.Boolean(string="早退", compute='_compute_attendance_flags', groups_operator='count_false') + is_late_card = fields.Boolean(string="迟到", compute='_compute_attendance_flags', groups_operator='count_false') + is_abnormal = fields.Boolean(string="异常", compute='_compute_is_abnormal', groups_operator='count_false') work_time_type = fields.Selection([('close_day', '休息日'), ('work_day', '工作日')], string="工作时间类型") - is_abnormal = fields.Boolean(string="异常", compute='_compute_is_abnormal') - # 暂时不用 company_id = fields.Many2one('res.company', string='公司', index=True, default=lambda self: self.env.company) on_card_location = fields.Char(string="上班打卡地点") down_card_location = fields.Char(string="下班打卡地点") @@ -33,6 +33,16 @@ class HrAttendance(models.Model): abnormal = fields.Integer(string="异常计算") is_approval = fields.Boolean(string="是否审批修正", default=False) + @api.model + def web_read_group(self, domain, fields, groupby, limit=None, offset=0, orderby=False, lazy=True): + result = super().web_read_group(domain, fields, groupby, limit, offset, orderby, lazy) + fields_dict = self.fields_get(fields) + for group in result.get('groups'): + for field in fields: + if fields_dict[field].get('type') == 'boolean': + group[field] = len([r for r in self.search_read(group['__domain'], fields=[field]) if r.get(field)]) + return result + @api.depends('employee_id', 'check_in', 'check_out') def _compute_display_name(self): for attendance in self: @@ -79,7 +89,7 @@ class HrAttendance(models.Model): attendance_id.is_no_card = True if attendance_id.check_out: check_in = attendance_id.check_in + timedelta(hours=8) - attendance_id.is_early_card = planning_id.end_datetime > check_in + attendance_id.is_early_card = planning_id.end_datetime > check_in else: attendance_id.is_no_card = True else: diff --git a/yuthon_hr_attendance/views/hr_attendance_views.xml b/yuthon_hr_attendance/views/hr_attendance_views.xml index 52387d018..c216591e8 100644 --- a/yuthon_hr_attendance/views/hr_attendance_views.xml +++ b/yuthon_hr_attendance/views/hr_attendance_views.xml @@ -4,43 +4,15 @@ hr.attendance.going.tree2 hr.attendance - + - - - - - - - - - - -