from odoo import api, fields, models, modules import datetime from datetime import datetime, timedelta, time from odoo.exceptions import UserError import logging _logger = logging.getLogger(__name__) class YuthonWillTask(models.Model): _name = 'yuthon.will.task' _description = '日程' _rec_name = 'name' # _inherit = ['mail.thread.main.attachment', 'mail.activity.mixin'] request_hour_from = fields.Selection([ ('0', '0:00'), ('0.5', '0:30'), ('1', '01:00'), ('1.5', '01:30'), ('2', '02:00'), ('2.5', '02:30'), ('3', '03:00'), ('3.5', '03:30'), ('4', '04:00'), ('4.5', '04:30'), ('5', '05:00'), ('5.5', '05:30'), ('6', '06:00'), ('6.5', '06:30'), ('7', '07:00'), ('7.5', '07:30'), ('8', '08:00'), ('8.5', '08:30'), ('9', '09:00'), ('9.5', '09:30'), ('10', '10:00'), ('10.5', '10:30'), ('11', '11:00'), ('11.5', '11:30'), ('12', '12:00'), ('12.5', '12:30'), ('13', '13:00'), ('13.5', '13:30'), ('14', '14:00'), ('14.5', '14:30'), ('15', '15:00'), ('15.5', '15:30'), ('16', '16:00'), ('16.5', '16:30'), ('17', '17:00'), ('17.5', '17:30'), ('18', '18:00'), ('18.5', '18:30'), ('19', '19:00'), ('19.5', '19:30'), ('20', '20:00'), ('20.5', '20:30'), ('21', '21:00'), ('21.5', '21:30'), ('22', '22:00'), ('22.5', '22:30'), ('23', '23:00'), ('23.5', '23:30')], string='开始时间', default='9') request_hour_to = fields.Selection([ ('0', '12:00'), ('0.5', '12:30'), ('1', '01:00'), ('1.5', '01:30'), ('2', '02:00'), ('2.5', '02:30'), ('3', '03:00'), ('3.5', '03:30'), ('4', '04:00'), ('4.5', '04:30'), ('5', '05:00'), ('5.5', '05:30'), ('6', '06:00'), ('6.5', '06:30'), ('7', '07:00'), ('7.5', '07:30'), ('8', '08:00'), ('8.5', '08:30'), ('9', '09:00'), ('9.5', '09:30'), ('10', '10:00'), ('10.5', '10:30'), ('11', '11:00'), ('11.5', '11:30'), ('12', '12:00'), ('12.5', '12:30'), ('13', '13:00'), ('13.5', '13:30'), ('14', '14:00'), ('14.5', '14:30'), ('15', '15:00'), ('15.5', '15:30'), ('16', '16:00'), ('16.5', '16:30'), ('17', '17:00'), ('17.5', '17:30'), ('18', '18:00'), ('18.5', '18:30'), ('19', '19:00'), ('19.5', '19:30'), ('20', '20:00'), ('20.5', '20:30'), ('21', '21:00'), ('21.5', '21:30'), ('22', '22:00'), ('22.5', '22:30'), ('23', '23:00'), ('23.5', '23:30')], string='结束时间', default='18') priority = fields.Selection([('general', '不紧急不重要'), ('important', '重要不紧急'), ('urgent', '紧急不重要'), ('very_urgent', '重要且紧急')], string='优先级', default='general') 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) name = fields.Text(string='任务内容') remarks = fields.Text(string='备注') creation_time = fields.Date(string='创建时间', default=fields.Date.today()) employee_ids = fields.Many2many('hr.employee', 'will_task_employee_rel', 'custom_id', 'employee_id', string='人员', store=True, index=True) employee_ids2 = fields.Many2many('hr.employee', 'will_task_employee_rel2', 'custom_id', 'employee_id', string='司机', store=True, index=True) user_role_ids = fields.Many2many('soong.user.role', string='角色', store=True, index=True) task_time_ids = fields.Many2many('yuthon.task.time', string='提醒') document_ids = fields.Many2many('ir.attachment', string="附件") address = fields.Char(string='地点') start_date = fields.Date(string='开始日期', default=fields.Date.today) is_this_company = fields.Boolean(string='本公司', default=True) task_state = fields.Selection([('will', '待办'), ('done', '已办'), ('cancel', '取消')], default='will', string='状态', store=True) users_ids = fields.Many2many( 'res.users', relation='yuthon_will_task_users_rel', # column1='task_id', column2='user_id', string='用户', store=True, index=True, default=lambda self: self.env.user ) self_users_ids = fields.Many2many( 'res.users', relation='yuthon_will_task_current_users_rel', column1='task_id', column2='user_id', string="当前经办人", store=True, default=lambda self: [(6, 0, [self.env.user.id])] ) @api.onchange('employee_ids', 'user_id') def _onchange_employee_ids(self): user_ids = [] if self.user_id: user_ids.append(self.user_id.id) for employee in self.employee_ids: if employee.user_id: user_ids.append(employee.user_id.id) for employee2 in self.employee_ids2: if employee2.user_id: user_ids.append(employee2.user_id.id) roles = self.employee_ids.mapped('user_role_id') self.user_role_ids = roles self.users_ids = [(6, 0, user_ids)] def read_number(self): return self.search_count([('task_state', '=', 'will'), ('users_ids', 'in', self.env.user.id)]) def will_task_time(self): # 任务状态判断 for task in self.search([('task_state', '=', 'will')]): # 计算开始时间(将日期和时间选择转换为datetime对象) hour_from = float(task.request_hour_from) start_hour = int(hour_from) start_minute = int((hour_from - start_hour) * 60) start_datetime = datetime.combine( fields.Date.from_string(task.start_date), time(start_hour, start_minute) ) + timedelta(hours=8) if task.request_hour_to: hour_to = float(task.request_hour_to) end_hour = int(hour_to) end_minute = int((hour_to - end_hour) * 60) end_datetime = start_datetime.replace(hour=end_hour, minute=end_minute) else: end_datetime = start_datetime + timedelta(hours=1) now = datetime.now() + timedelta(hours=8) if now > end_datetime: task.write({'task_state': 'done'}) continue _logger.info("定时任务执行中") _logger.info(f"判断前 now:{now} --- start:{start_datetime}") if now <= start_datetime: if task.task_time_ids: for task_time in task.task_time_ids: duration = self._compute_duration(task_time) trigger_time = now + duration if (trigger_time.day == start_datetime.day and trigger_time.hour == start_datetime.hour and trigger_time.minute == start_datetime.minute): task.add_comment() def _compute_duration(self, task_time): if task_time.task_unit == 'min': return timedelta(minutes=task_time.number) elif task_time.task_unit == 'hour': return timedelta(hours=task_time.number) elif task_time.task_unit == 'day': return timedelta(days=task_time.number) else: return timedelta.max 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] 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}' data_name = "事项名称: " + self.name + '\n' # data_start_time = '开始时间:' + str(self.start_time + timedelta(hours=8)) + '\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 '' data_nota = ('备注:' + self.remarks) if self.remarks else ('') + '\n' # data = data_name + data_start_time + data_user_ids + data_nota + data_employee_id data = data_name + data_user_ids + data_nota + data_employee_id self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id=employee_id.wecom_userid, title="日程事项提醒", description=data, url=url, btntxt="详细信息") # for record in self: # partner_ids = record.employee_ids.user_id.partner_id.ids # record.with_context(lang=record.env.lang)._message_auto_subscribe_notify(partner_ids,'yuthon_will_task.mail_action_yuthon_will_task_add_comment') def button_add_comment(self): self.add_comment() return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'type': 'success', 'message': '已发送提醒消息', 'sticky': False, } } def button_add_comment_cancel(self): self.write({'task_state': 'cancel'}) employee_list = [i.id for i in self.employee_ids] + [i.id for i in self.employee_ids2] 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)) menu_id = self.env['ir.ui.menu'].search([('name', '=', '我的日程')]) url = f'https://oa.thtzjt.com/web#id={self.id}&cids=2&action={menu_id.action.id}&model=yuthon.will.task&view_type=list&menu_id={menu_id.id}' self.sudo().env["wecom.apps"].sync_send_message_textcard(category='task', user_id=employee_id.wecom_userid, title="日程事项提醒", description="事项名称: " + self.name + '\t' + '该事项已取消', url=url, btntxt="详细信息") for record in self: partner_ids = record.employee_ids.user_id.partner_id.ids record.with_context(lang=record.env.lang)._message_auto_subscribe_notify(partner_ids, 'yuthon_will_task.mail_action_yuthon_will_task_add_comment') return { 'type': 'ir.actions.client', 'tag': 'display_notification', 'params': { 'type': 'success', 'message': '已发送取消提醒消息', 'sticky': False, } }