diff --git a/sh_backmate_theme_adv_enterprise/models/inherit_menu.py b/sh_backmate_theme_adv_enterprise/models/inherit_menu.py
index d8299117e..3234f1fcd 100644
--- a/sh_backmate_theme_adv_enterprise/models/inherit_menu.py
+++ b/sh_backmate_theme_adv_enterprise/models/inherit_menu.py
@@ -7,6 +7,12 @@ class MenuInherit(models.Model):
is_phone = fields.Boolean("是否手机显示", default=True)
+ def update_is_phone(self):
+ menu_ids = self.env["ir.ui.menu"].browse(
+ self._context.get('active_ids', self._context.get('active_id')))
+ for menu in menu_ids:
+ menu.is_phone = False
+
def load_web_menus(self, debug):
web_menus = {}
menus = self.search_read([], fields=['id', 'is_phone'])
diff --git a/soong_workflow/models/soong_workflow_mixin.py b/soong_workflow/models/soong_workflow_mixin.py
index b9ff68c77..75ac32e55 100644
--- a/soong_workflow/models/soong_workflow_mixin.py
+++ b/soong_workflow/models/soong_workflow_mixin.py
@@ -725,18 +725,18 @@ class SoongWorkflowMixin(models.AbstractModel):
wkf_rec = wkf_obj.search([("model_id", "=", model), ('is_enable', '=', True)])
for node in wkf_rec.node_ids:
for button in node.button_ids:
- # if self.env.user.has_group("soong_workflow.group_soong_workflow_manager"):
- # btn_exec_action_el = etree.SubElement(header_el, "button")
- # btn_exec_action_el.set("name", "btn_exec_action")
- # btn_exec_action_el.set("string", button.name)
- # btn_exec_action_el.set("type", "object")
- # if button.is_highlight:
- # btn_exec_action_el.set("class", "oe_highlight")
- # if button.has_icon:
- # btn_exec_action_el.set("icon", button.icon)
- # btn_exec_action_el.set("invisible", "state != '%s'" % node.node_name)
- # btn_exec_action_el.set("context", "{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name),)
- # else:
+ if self.env.user.has_group("soong_workflow.group_soong_workflow_manager"):
+ btn_exec_action_el = etree.SubElement(header_el, "button")
+ btn_exec_action_el.set("name", "btn_exec_action")
+ btn_exec_action_el.set("string", button.name)
+ btn_exec_action_el.set("type", "object")
+ if button.is_highlight:
+ btn_exec_action_el.set("class", "oe_highlight")
+ if button.has_icon:
+ btn_exec_action_el.set("icon", button.icon)
+ btn_exec_action_el.set("invisible", "state != '%s'" % node.node_name)
+ btn_exec_action_el.set("context", "{'btn_key':'%s','active_model':'%s'}" % (button.btn_key, self._name),)
+ else:
is_apostille = False
if button.btn_hide:
if button.review_type == "individual":
diff --git a/soong_workflow/views/menuitem.xml b/soong_workflow/views/menuitem.xml
index 2b5934e64..6882833bd 100644
--- a/soong_workflow/views/menuitem.xml
+++ b/soong_workflow/views/menuitem.xml
@@ -11,6 +11,16 @@
parent="menu_soong_workflow_root"
action="action_kklw_workflow_approval_request"
sequence="1"/>
+
+
+
+ 待办
+ ir.actions.act_window
+ soong.workflow.record
+ tree,kanban,search
+
+ {'header_search_default_approve_state': 1, 'header_search_default_to_do':1, 'check_employee': 1}
+ [('users_ids', 'in', uid), ('reclaim_state', '=', False), ('soong_state', '=', 'to_do')]
+
+
+
+
+ 已办
+ ir.actions.act_window
+ soong.workflow.record
+ tree,kanban,search
+ {'header_search_default_approve_state': 1, 'header_search_default_to_do':1, 'check_employee': 1}
+ [('users_ids', 'in', uid), ('reclaim_state', '=', False), ('soong_state', '=', 'done')]
+
+
+
人事相关流程
ir.actions.act_window
diff --git a/soong_workflow/views/yuthon_will_task_views.xml b/soong_workflow/views/yuthon_will_task_views.xml
index 65ff44131..353bd516d 100644
--- a/soong_workflow/views/yuthon_will_task_views.xml
+++ b/soong_workflow/views/yuthon_will_task_views.xml
@@ -8,7 +8,6 @@
decoration-muted="task_state == 'cancel'"
decoration-danger="priority == 'very_urgent'"
decoration-info="priority == 'urgent'"
- decoration-primary="priority == 'general'"
decoration-success="priority == 'important'">
@@ -62,8 +61,6 @@
+
+
+ 定时任务:测试提醒
+
+ code
+ model.task_remind()
+
+
+ 1
+ days
+
+ -1
+
+
diff --git a/yuthon_hr_attendance/models/hr_attendance.py b/yuthon_hr_attendance/models/hr_attendance.py
index bf7f1689b..1e95b1b8b 100644
--- a/yuthon_hr_attendance/models/hr_attendance.py
+++ b/yuthon_hr_attendance/models/hr_attendance.py
@@ -63,6 +63,13 @@ class HrAttendance(models.Model):
is_last_month = fields.Boolean(string="是否为上月数据", compute='_compute_month_status', store=True)
correct_result = fields.Text(string="修正原因")
+ def task_remind(self):
+ all_employees = self.env['hr.employee'].search([('name', 'in', ['Administrator', '叶华锋'])])
+ for employee in all_employees:
+ self.sudo().env["wecom.apps"].sync_send_message_textcard(
+ category='att', user_id=employee.wecom_userid,
+ description="记得打卡", title="测试提醒",btntxt="详细信息", )
+
def create_attendance_data_holiday(self):
"""
定时任务create_attendance_data_holiday
diff --git a/yuthon_notice/views/yuthon_notice_views.xml b/yuthon_notice/views/yuthon_notice_views.xml
index 9c64a2c08..0c355020c 100644
--- a/yuthon_notice/views/yuthon_notice_views.xml
+++ b/yuthon_notice/views/yuthon_notice_views.xml
@@ -72,7 +72,11 @@
-
+
+
+
+
+
diff --git a/yuthon_property/views/property_meter_archives_views.xml b/yuthon_property/views/property_meter_archives_views.xml
index bc8d3b4ef..0b1fb307d 100644
--- a/yuthon_property/views/property_meter_archives_views.xml
+++ b/yuthon_property/views/property_meter_archives_views.xml
@@ -95,7 +95,7 @@
meter.archives.line
+ js_class="custom_meter_button" decoration-success="is_push" default_order="meter_date_month desc">
diff --git a/yuthon_property/views/property_meter_water_views.xml b/yuthon_property/views/property_meter_water_views.xml
index e39046a47..83ec9add6 100644
--- a/yuthon_property/views/property_meter_water_views.xml
+++ b/yuthon_property/views/property_meter_water_views.xml
@@ -98,7 +98,7 @@
meter.water.line.tree
meter.water.line
-
diff --git a/yuthon_property/wizard/meter_price_wizard.py b/yuthon_property/wizard/meter_price_wizard.py
index c5ffe0c4c..72ea6e9a0 100644
--- a/yuthon_property/wizard/meter_price_wizard.py
+++ b/yuthon_property/wizard/meter_price_wizard.py
@@ -86,7 +86,6 @@ class MeterPriceWizard(models.TransientModel):
hydropower_log = self.env['hydropower.logs'].search(search_domain, limit=1)
log_data = {
'meter_type': 'electric',
- 'logs_date': start_date,
'select_time': self.select_time,
'select_year': self.select_year,
'line_loss': self.line_loss,
diff --git a/yuthon_property/wizard/water_price_wizard.py b/yuthon_property/wizard/water_price_wizard.py
index 330d998bd..641685c4b 100644
--- a/yuthon_property/wizard/water_price_wizard.py
+++ b/yuthon_property/wizard/water_price_wizard.py
@@ -86,7 +86,6 @@ class WaterPriceWizard(models.TransientModel):
hydropower_log = self.env['hydropower.logs'].search(search_domain, limit=1)
log_data = {
'meter_type': 'water',
- 'logs_date': start_date,
'select_time': self.select_time,
'select_year': self.select_year,
'line_loss': self.line_loss,
diff --git a/yuthon_property_approval/models/inherit_yuthon_property.py b/yuthon_property_approval/models/inherit_yuthon_property.py
index d6690f950..36cfbbd7e 100644
--- a/yuthon_property_approval/models/inherit_yuthon_property.py
+++ b/yuthon_property_approval/models/inherit_yuthon_property.py
@@ -833,94 +833,6 @@ class PropertyAccountsReceivable(models.Model):
for receivable in receivable_ids:
receivable._compute_property_ids()
- def de_duplicate(self):
- # 查询所有记录并按 id 升序排列
- records = self.search([], order='id ASC')
- # 用于存储已存在的组合
- unique_combinations = set()
- records_to_delete = self.browse() # 创建一个空记录集
- # 遍历所有记录,找出重复项
- for record in records:
- combination = (
- record.contract_id.id,
- record.property_id.id,
- record.lessee_id.id,
- record.due_date
- )
-
- # 如果组合已存在,则添加到删除列表
- if combination in unique_combinations:
- records_to_delete += record
- else:
- # 否则添加到唯一组合集合
- unique_combinations.add(combination)
- # 删除重复记录
- if records_to_delete:
- records_to_delete.unlink()
-
- def initialize_reconciliation(self):
- receivable_ids = self.env["property.accounts.receivable"].browse(
- self._context.get('active_ids', self._context.get('active_id')))
- for receivable in receivable_ids:
- receivable.delivered1 = receivable.submitted
- receivable.submitted = 0
- receivable.is_reconciliation = True
-
- due_year = receivable.due_date.year
- due_month = receivable.due_date.month
- # 构建日期范围条件
- import calendar
- last_day = calendar.monthrange(due_year, due_month)[1]
- # 构建日期范围条件(使用正确的最后一天)
- start_date = f"{due_year}-{due_month:02d}-01"
- end_date = f"{due_year}-{due_month:02d}-{last_day}"
- # 搜索条件使用大于等于当月第一天,小于等于当月最后一天
- statements = self.env['property.bank.statements'].search([
- ('name_account', '=', receivable.lessee_id.name),
- ('bank_state', '=', 'reconciled'),
- ('start_time', '>=', start_date),
- ('start_time', '<=', end_date),
- ])
- if statements:
- for statement in statements:
- receivable.payout_date = statement.start_time.date()
- else:
- receivable.payout_date = receivable.due_date
-
- # @api.model_create_multi
- # def create(self, vals_list):
- # records = super().create(vals_list)
- # for record in records:
- # if record.lessee_id and record.contract_id:
- # lease_address_ids = record.contract_id.lease_ids.mapped('address_id.id')
- # property_ids_value = [(6, 0, lease_address_ids)] if lease_address_ids else [(6, 0, [])]
- # statements = self.env['property.bank.statements'].search([
- # ('name_account', '=', record.lessee_id.name),
- # ('bank_state', '=', 'not_reconciled'),
- # ])
- # contract_id_value = [(4, record.contract_id.id)] if record.contract_id else []
- # for statement in statements:
- # statement.write({
- # 'property_ids': property_ids_value,
- # 'contract_ids': contract_id_value,
- # })
- #
- # contract_account_map = {}
- # for vals in vals_list:
- # if 'contract_id' in vals and vals['contract_id']:
- # contract_id = vals['contract_id']
- # if contract_id not in contract_account_map:
- # contract_account = self.env['contract.accounts.receivable'].search([
- # ('contract_id', '=', contract_id)
- # ], limit=1)
- # if not contract_account:
- # contract_account = self.env['contract.accounts.receivable'].create({
- # 'contract_id': contract_id
- # })
- # contract_account.onchange_contract_id()
- #
- # return records
-
@api.onchange('penalty_date')
def _onchange_penalty_date(self):
for record in self:
@@ -947,32 +859,7 @@ class PropertyAccountsReceivable(models.Model):
penalty = days_difference * receivable.receivable_id.difference_amount
receivable.receivable_id.write({'penalty': penalty})
- # 批量撤销
- def batch_receivable_return(self):
- archives_ids = self.env["property.accounts.receivable"].browse(
- self._context.get('active_ids', self._context.get('active_id')))
- for rec in archives_ids:
- # 银行流水对应的已对账改为未对账
- due_year = rec.due_date.year
- due_month = rec.due_date.month
- import calendar
- last_day = calendar.monthrange(due_year, due_month)[1]
-
- # 构建日期范围条件(使用正确的最后一天)
- start_date = f"{due_year}-{due_month:02d}-01"
- end_date = f"{due_year}-{due_month:02d}-{last_day}"
- # 搜索条件使用大于等于当月第一天,小于等于当月最后一天
- statements = self.env['property.bank.statements'].search([
- ('name_account', '=', rec.lessee_id.name),
- ('bank_state', '=', 'reconciled'),
- ('start_time', '>=', start_date),
- ('start_time', '<=', end_date),
- ])
- rec.is_reconciliation = False
- for statement in statements:
- statement.write({'bank_state': 'not_reconciled'})
-
- # 批量退回
+ # 批量退回
def action_refuse_all(self):
model_type_data = {
'水费': 'meter.water.line',
@@ -983,25 +870,25 @@ class PropertyAccountsReceivable(models.Model):
}
archives_ids = self.env["property.accounts.receivable"].browse(
self._context.get('active_ids', self._context.get('active_id')))
- valid_management_types = list(model_type_data.keys())
+ valid_management_types = list(model_type_data.values())
for rec in archives_ids:
+ if rec.is_reconciliation == True:
+ raise UserError("已对账的记录不能退回!请先银行流水撤销再退回")
model_type = model_type_data.get(rec.management_type_id.name)
if model_type not in valid_management_types:
rec.unlink()
continue
if model_type in ('meter.archives.line', 'meter.water.line'):
- year = rec.due_date_end.year
- month = rec.due_date_end.month
- first_day = date(year, month, 1)
- if month == 12:
- next_month_first_day = date(year + 1, 1, 1)
- else:
- next_month_first_day = date(year, month + 1, 1)
- last_day = next_month_first_day - timedelta(days=1)
+ if not rec.charging_range:
+ raise UserError("请输入计费区间, 按照应为'YYYY-MM-DD 到 YYYY-MM-DD格式")
+ charging_range = rec.charging_range.strip()
+ start_str, end_str = [x.strip() for x in charging_range.split("到")]
+ start_date = (datetime.strptime(end_str, "%Y-%m-%d").date()).replace(day=1)
+ end_date = datetime.strptime(end_str, "%Y-%m-%d").date()
model_id = self.env[model_type].search([
('contract_id', '=', rec.contract_id.id),
- ('meter_date', '>=', first_day),
- ('meter_date', '<=', last_day)
+ ('meter_date', '>=', start_date),
+ ('meter_date', '<=', end_date)
])
else:
last_day = rec.due_date + relativedelta(months=1) - timedelta(days=1)
diff --git a/yuthon_property_approval/views/inherit_yuthon_property_views.xml b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
index e119c8238..60af20fb6 100644
--- a/yuthon_property_approval/views/inherit_yuthon_property_views.xml
+++ b/yuthon_property_approval/views/inherit_yuthon_property_views.xml
@@ -452,26 +452,12 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
应收账单
@@ -608,13 +594,6 @@
code
action = model.all_penalty_date()
-
- 批量撤销
-
-
- code
- action = model.batch_receivable_return()
-
批量退回
diff --git a/yuthon_report/__manifest__.py b/yuthon_report/__manifest__.py
index d800b8327..d6f9ccade 100644
--- a/yuthon_report/__manifest__.py
+++ b/yuthon_report/__manifest__.py
@@ -6,7 +6,7 @@
'category': 'zhou',
'version': '0.1',
'license': 'LGPL-3',
- 'depends': ['base', 'web', 'yuthon_property','yuthon_property_approval'],
+ 'depends': ['base', 'web', 'yuthon_property','yuthon_property_approval', 'hr_attendance'],
'data': [
'views/menu.xml',
'views/ledger_report_views.xml',
@@ -16,6 +16,7 @@
'views/cumulative_income_report.xml',
'views/overdue_amount_report.xml',
'views/yuthon_report_res_partner.xml',
+ 'views/att_report_view.xml',
],
'installable': True,
'application': True,
@@ -38,6 +39,8 @@
'yuthon_report/static/src/components/yuthon_report/yuthon_report.xml',
'yuthon_report/static/src/components/yuthon_report/yuthon_contract_report.js',
'yuthon_report/static/src/components/yuthon_report/yuthon_contract_report.xml',
+ 'yuthon_report/static/src/components/yuthon_report/att_report.js',
+ 'yuthon_report/static/src/components/yuthon_report/att_report.xml',
'yuthon_report/static/src/components/yuthon_report/receivable_message_report.js',
'yuthon_report/static/src/components/yuthon_report/receivable_message.xml',
'yuthon_report/static/src/components/yuthon_report/yuthon_report.scss',
diff --git a/yuthon_report/models/__init__.py b/yuthon_report/models/__init__.py
index 22476b2ab..431e39e45 100644
--- a/yuthon_report/models/__init__.py
+++ b/yuthon_report/models/__init__.py
@@ -5,4 +5,5 @@ from . import receivable_report
from . import receivables_message_report
from . import yuthon_contract_report
from . import cumulative_income_report
-from . import overdue_amount_report
\ No newline at end of file
+from . import overdue_amount_report
+from . import att_report
\ No newline at end of file
diff --git a/yuthon_report/models/att_report.py b/yuthon_report/models/att_report.py
new file mode 100644
index 000000000..89af35d0d
--- /dev/null
+++ b/yuthon_report/models/att_report.py
@@ -0,0 +1,138 @@
+import datetime
+
+from odoo import fields, models, api
+
+
+class AttendanceReport(models.Model):
+ _inherit = 'hr.attendance'
+
+ def _get_common_domain_and_employees(self, params):
+ vacation_domain = []
+ if params.get("date_start"):
+ date_start = datetime.datetime.fromisoformat(params.get("date_start")).date()
+ vacation_domain.append(("vacation_date", ">=", date_start))
+ if params.get("date_end"):
+ date_end = datetime.datetime.fromisoformat(params.get("date_end")).date()
+ vacation_domain.append(("vacation_date", "<=", date_end))
+ salary_group_id = params.get('structure_id', False)
+ department_id = params.get('department_id', False)
+ company_id = params.get('company_id', False)
+
+ employee_domain = []
+ if salary_group_id:
+ employee_domain.append(('contract_id.salary_group_id', '=', salary_group_id))
+ if department_id:
+ employee_domain.append(('department_id', '=', department_id))
+ if company_id:
+ employee_domain.append(('company_id', '=', company_id))
+
+ employee_ids = []
+ if employee_domain:
+ employee_ids = self.env['hr.employee'].search(employee_domain).ids
+ if employee_ids:
+ vacation_domain.append(("employee_id", "in", employee_ids))
+
+ return vacation_domain, employee_ids
+
+ # ---------------------- 年假/其他假期报表 ----------------------
+ @api.model
+ def get_attendance_report(self, params):
+ vacation_domain, employee_ids = self._get_common_domain_and_employees(params)
+ if employee_ids and not employee_ids:
+ return []
+ vacation_reports = self.env['yuthon.vacation.reports'].search(vacation_domain, limit=1000)
+ result_list = []
+ for report in vacation_reports:
+ employee_name = report.employee_id.name or ""
+ company_name = report.company_id.name or ""
+ for leave_line in report.leave_ids.filtered(lambda l: l.workflow_record_id):
+ result_list.append({
+ "员工": employee_name,
+ "公司": company_name,
+ "天数": leave_line.lines or 0.0,
+ "类型": "年假",
+ "流程": leave_line.workflow_record_id.name or ""
+ })
+ for fee_line in report.other_fee_ids.filtered(lambda l: l.workflow_record_id):
+ result_list.append({
+ "员工": employee_name,
+ "公司": company_name,
+ "天数": fee_line.lines or 0.0,
+ "类型": fee_line.holiday_type.name or "其他假期",
+ "流程": fee_line.workflow_record_id.name or ""
+ })
+ return result_list
+
+ # ---------------------- 误餐费报表(外出) ----------------------
+ @api.model
+ def get_meal_fee_report(self, params):
+ vacation_domain, employee_ids = self._get_common_domain_and_employees(params)
+ if employee_ids and not employee_ids:
+ return []
+ vacation_reports = self.env['yuthon.vacation.reports'].search(vacation_domain, limit=1000)
+ result_list = []
+ for report in vacation_reports:
+ employee_name = report.employee_id.name or ""
+ company_name = report.company_id.name or ""
+ for meal_line in report.meal_fee_ids.filtered(lambda l: l.workflow_record_id):
+ result_list.append({
+ "员工": employee_name,
+ "公司": company_name,
+ "次数": meal_line.update_lines or 0,
+ "类型": "外出",
+ "流程": meal_line.workflow_record_id.name or ""
+ })
+ return result_list
+
+ # ---------------------- 加班费报表 ----------------------
+ @api.model
+ def get_overtime_report(self, params):
+ vacation_domain, employee_ids = self._get_common_domain_and_employees(params)
+ if employee_ids and not employee_ids:
+ return []
+ vacation_reports = self.env['yuthon.vacation.reports'].search(vacation_domain, limit=1000)
+ result_list = []
+ for report in vacation_reports:
+ employee_name = report.employee_id.name or ""
+ company_name = report.company_id.name or ""
+ for overtime_line in report.overtime_ids.filtered(lambda l: l.workflow_record_id):
+ overtime_detail = {}
+ if overtime_line.workday > 0:
+ overtime_detail["加班类型"] = "工作日"
+ overtime_detail["时长(小时)"] = overtime_line.workday
+ elif overtime_line.legal_day > 0:
+ overtime_detail["加班类型"] = "法定节假日"
+ overtime_detail["时长(小时)"] = overtime_line.legal_day
+ elif overtime_line.public_holidays > 0:
+ overtime_detail["加班类型"] = "公休日"
+ overtime_detail["时长(小时)"] = overtime_line.public_holidays
+ else:
+ overtime_detail["加班类型"] = "无"
+ overtime_detail["时长(小时)"] = 0.0
+
+ overtime_method_map = {
+ 'leave': '补休',
+ 'fee': '加班费结算'
+ }
+ compensation_method = overtime_method_map.get(overtime_line.overtime_methods, '补休')
+ result_list.append({
+ "员工": employee_name,
+ "公司": company_name,
+ "类型": "加班",
+ "补偿方式": compensation_method,
+ "加班类型": overtime_detail["加班类型"],
+ "时长(小时)": overtime_detail["时长(小时)"],
+ "流程": overtime_line.workflow_record_id.name or ""
+ })
+ return result_list
+
+ @api.model
+ def get_domain(self, company_id=False):
+ if not company_id:
+ return [], []
+
+ department_records = self.env['hr.department'].search([('company_id', '=', company_id)])
+ department_ids = [dept.id for dept in department_records]
+ salary_group_records = self.env['yuthon.salary.group'].search([('company_id', '=', company_id)])
+ salary_group_ids = [struct.id for struct in salary_group_records]
+ return department_ids, salary_group_ids
\ No newline at end of file
diff --git a/yuthon_report/static/src/components/yuthon_report/att_report.js b/yuthon_report/static/src/components/yuthon_report/att_report.js
new file mode 100644
index 000000000..8ecb33e5c
--- /dev/null
+++ b/yuthon_report/static/src/components/yuthon_report/att_report.js
@@ -0,0 +1,179 @@
+/** @odoo-module1 **/
+
+
+import {registry} from "@web/core/registry";
+import {Component, onMounted, useRef, useState} from "@odoo/owl";
+import {useBus, useService} from "@web/core/utils/hooks";
+import {
+ standardActionServiceProps
+} from "@web/webclient/actions/action_service";
+import {DateTimeInput} from "@web/core/datetime/datetime_input";
+import {CheckBox} from "@web/core/checkbox/checkbox";
+import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
+import {formatDate} from "@web/core/l10n/dates"
+
+const {DateTime} = luxon;
+
+class ReceivableReport extends Component {
+ setup() {
+ this.gridRef = useRef("grid");
+ console.log(this.props.action.context.report_config)
+
+ this.serviceOrm = useService("orm")
+
+ this.state = useState({
+ startDate: DateTime.now().startOf("month"),
+ endDate: DateTime.now().endOf("month"),
+ keyword: "",
+ booleanValue: true,
+ selectDepartment: {},
+ selectCompany: {},
+ selectStructure: {},
+ domainDepartment:[],
+ domainStructure:[]
+ });
+
+ this.config = this.props.action.context.report_config || {};
+
+ onMounted(async () => {
+ // 加载 ag-grid
+ //await loadJS("https://cdn.jsdelivr.net/npm/ag-grid-community/dist/ag-grid-community.min.js");
+ this.gridOptions = {
+ localeText: AG_GRID_LOCALE_CN,
+ theme: agGrid.themeMaterial,
+ columnDefs: this.config.columns || [],
+ rowData: [],
+ sideBar: true,
+ enableCharts: true,
+ cellSelection: true,
+ defaultColDef: {
+ sortable: true,
+ filter: true,
+ width: 200,
+ minWidth: 150,
+ flex: false,
+ resizable: false
+ },
+ getContextMenuItems(params) {
+ const items = params.defaultItems.slice();
+ items.push("chartRange");
+ return items;
+ },
+
+ };
+ this.grid = new agGrid.createGrid(this.gridRef.el, this.gridOptions);
+
+ });
+ }
+
+ /**
+ * 改变布尔值
+ * @param e
+ */
+
+ getDomainCompany() {
+ return []
+ }
+
+ getDomainStructure() {
+ console.log(this.state)
+ const isCompanyEmpty = Object.keys(this.state.selectCompany).length === 0;
+ if (isCompanyEmpty) {
+ return [];
+ } else {
+ return [['id','in', this.state.domainStructure]];
+ }
+ }
+
+
+ getDomainDepartment() {
+ console.log(this.state)
+ const isCompanyEmpty = Object.keys(this.state.selectCompany).length === 0;
+ if (isCompanyEmpty) {
+ return [];
+ } else {
+ return [['id','in', this.state.domainDepartment]];
+ }
+ }
+
+ async searchDomain() {
+ let results = await this.serviceOrm.call(
+ 'hr.attendance',
+ 'get_domain',
+ [],
+ {
+ company_id: this.state.selectCompany?.id,
+ }
+ )
+ console.log(results)
+ this.state.domainDepartment = results[0]
+ this.state.domainStructure = results[1]
+ }
+
+ async onSearch() {
+ console.log(this.state)
+ let startDate = formatDate(this.state.startDate, {format: "yyyy-MM-dd"})
+ let endDate = formatDate(this.state.endDate, {format: "yyyy-MM-dd"})
+
+ const params = {
+ date_start: `${startDate} 00:00:00`,
+ date_end: `${endDate} 23:59:59`,
+ department_id: this.state.selectDepartment?.id,
+ company_id: this.state.selectCompany?.id,
+ structure_id: this.state.selectStructure?.id,
+ };
+ const result = await this.serviceOrm.call(
+ this.config.model,
+ this.config.method,
+ [params]
+ );
+ console.log(result)
+ this.grid.setGridOption('rowData', result);
+ }
+
+ onExportExcel() {
+ this.grid.exportDataAsExcel({
+ fileName: 'my-data.xlsx',
+ sheetName: 'Sheet1'
+ });
+ }
+
+ async onUpdateCompany(v) {
+ this.state.selectCompany = v[0] || {}
+ await this.searchDomain()
+ }
+
+ async onUpdateStructure(v) {
+ this.state.selectStructure = v[0] || {}
+ }
+
+ async onUpdateDepartment(v) {
+ this.state.selectDepartment = v[0]
+ }
+
+
+ async onChangeStartDate(date) {
+ console.log(date)
+ if (Array.isArray(date)) {
+ this.state.startDate = date[0];
+ this.state.endDate = date[1]
+ }
+ }
+
+ async onChangeEndDate(date) {
+ if (Array.isArray(date)) {
+ this.state.startDate = date[0];
+ this.state.endDate = date[1]
+ }
+ }
+}
+
+ReceivableReport.props = {...standardActionServiceProps};
+ReceivableReport.template = "att_report.ReceivableReport";
+ReceivableReport.components = {
+ DateTimeInput,
+ CheckBox,
+ Many2XAutocomplete,
+};
+
+registry.category("actions").add("att_report_client", ReceivableReport);
diff --git a/yuthon_report/static/src/components/yuthon_report/att_report.xml b/yuthon_report/static/src/components/yuthon_report/att_report.xml
new file mode 100644
index 000000000..dd94d93f1
--- /dev/null
+++ b/yuthon_report/static/src/components/yuthon_report/att_report.xml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yuthon_report/views/att_report_view.xml b/yuthon_report/views/att_report_view.xml
new file mode 100644
index 000000000..2fdeefb19
--- /dev/null
+++ b/yuthon_report/views/att_report_view.xml
@@ -0,0 +1,88 @@
+
+
+
+
+ 请假扣款报表
+ get_attendance_report
+
+ {
+ "sideBar": true,
+ "report_config": {
+ "model": "hr.attendance",
+ "method": "get_attendance_report",
+ "columns": [
+ {"headerName": "员工", "field": "员工", "flex": 1},
+ {"headerName": "公司", "field": "公司", "flex": 1},
+ {"headerName": "天数", "field": "天数", "flex": 1},
+ {"headerName": "类型", "field": "类型", "flex": 1},
+ {"headerName": "流程", "field": "流程", "flex": 1}
+ ]
+ }
+ }
+
+
+
+ 误餐费报表
+ get_meal_fee_report
+
+ {
+ "sideBar": true,
+ "report_config": {
+ "model": "hr.attendance",
+ "method": "get_meal_fee_report",
+ "columns": [
+ {"headerName": "员工", "field": "员工", "flex": 1},
+ {"headerName": "公司", "field": "公司", "flex": 1},
+ {"headerName": "次数", "field": "次数", "flex": 1},
+ {"headerName": "类型", "field": "类型", "flex": 1},
+ {"headerName": "流程", "field": "流程", "flex": 1}
+ ]
+ }
+ }
+
+
+
+ 加班费报表
+ get_overtime_report
+
+ {
+ "sideBar": true,
+ "report_config": {
+ "model": "hr.attendance",
+ "method": "get_overtime_report",
+ "columns": [
+ {"headerName": "员工", "field": "员工", "flex": 1},
+ {"headerName": "公司", "field": "公司", "flex": 1},
+ {"headerName": "类型", "field": "类型", "flex": 1},
+ {"headerName": "补偿方式", "field": "补偿方式", "flex": 1},
+ {"headerName": "加班类型", "field": "加班类型", "flex": 1},
+ {"headerName": "时长(小时)", "field": "时长(小时)", "flex": 1},
+ {"headerName": "流程", "field": "流程", "flex": 1}
+ ]
+ }
+ }
+
+
+
+
+
+
+
diff --git a/yuthon_will_task/models/yuthon_will_task.py b/yuthon_will_task/models/yuthon_will_task.py
index adef8ffc3..5fa336271 100644
--- a/yuthon_will_task/models/yuthon_will_task.py
+++ b/yuthon_will_task/models/yuthon_will_task.py
@@ -65,8 +65,8 @@ class YuthonWillTask(models.Model):
('22', '22:00'), ('22.25', '22:15'), ('22.5', '22:30'), ('22.75', '22:45'),
('23', '23:00'), ('23.25', '23:15'), ('23.5', '23:30'), ('23.75', '23:45')], string='结束时间', default='18')
- priority = fields.Selection([('general', '不紧急不重要'), ('important', '重要不紧急'),
- ('urgent', '紧急不重要'), ('very_urgent', '重要且紧急')], string='优先级', default='general')
+ priority = fields.Selection([('important', '重要不紧急'),
+ ('urgent', '紧急不重要'), ('very_urgent', '重要且紧急')], string='优先级')
code = fields.Char(string="任务编号", default=lambda self: self.env['ir.sequence'].next_by_code('task_code'))
user_id = fields.Many2one('res.users', string="创建人", default=lambda self: self.env.user)
company_id = fields.Many2one('res.company', string="公司", default=lambda self: self.env.company)
@@ -141,7 +141,7 @@ class YuthonWillTask(models.Model):
from_time = hour_mapping.get(record.request_hour_from, "")
to_time = hour_mapping.get(record.request_hour_to, "")
if date_str and from_time and to_time:
- record.task_time = f"{date_str} ({from_time}--{to_time})"
+ record.task_time = f"{date_str} {from_time}"
else:
record.task_time = ""
@@ -204,11 +204,12 @@ class YuthonWillTask(models.Model):
def add_comment(self):
self.ensure_one()
- employee_list = [i.id for i in self.employee_ids] + [i.id for i in self.employee_ids2]
+ admin = self.env['hr.employee'].search([('name', '=', 'Administrator')])
+ employee_list = [i.id for i in self.employee_ids] + [i.id for i in self.employee_ids2] + admin.id
for employee_id in self.env['hr.employee'].search([('id', 'in', employee_list)]):
if not employee_id.wecom_userid:
raise UserError("请同步{}的企业微信".format(employee_id.name))
- url = f'http:://oa.thtzjt.com/webh5#/journey?id={self.id}'
+ url = f'https://oa.thtzjt.com/webh5#/journey?id={self.id}'
data_name = "事项名称: " + self.name + '\n'
data_user_ids = '参与人: ' + ', '.join(self.employee_ids.mapped('name')) + '\n'
data_employee_id = ('司机:' + ', '.join(self.employee_ids2.mapped('name')) + '\n') if self.employee_ids2 else ''
diff --git a/yuthon_will_task/views/yuthon_will_task_views.xml b/yuthon_will_task/views/yuthon_will_task_views.xml
index 1b11a4d06..047654fd8 100644
--- a/yuthon_will_task/views/yuthon_will_task_views.xml
+++ b/yuthon_will_task/views/yuthon_will_task_views.xml
@@ -8,7 +8,6 @@
decoration-muted = "task_state == 'cancel'"
decoration-danger="priority == 'very_urgent'"
decoration-info="priority == 'urgent'"
- decoration-primary="priority == 'general'"
decoration-success="priority == 'important'">
@@ -49,7 +48,6 @@