diff --git a/soong_workflow/models/soong_workflow_record.py b/soong_workflow/models/soong_workflow_record.py index b43e1323a..5bae7dd12 100644 --- a/soong_workflow/models/soong_workflow_record.py +++ b/soong_workflow/models/soong_workflow_record.py @@ -315,30 +315,144 @@ class SoongWorkflowRecord(models.Model): return domain - @api.depends('employee_ids', 'soong_state', 'reclaim_state') + @api.depends('employee_ids', 'res_model', 'res_id', 'reclaim_state', 'approve_state', 'employee2_ids') def _compute_is_done(self): current_uid = self.env.user.id - for record in self: - record.is_done = False - condition1 = True if record.soong_state =='done' else False - condition2 = not record.reclaim_state - condition3 = False - if record.users_ids: - condition3 = current_uid in record.users_ids.ids - if condition1 and condition2 and condition3: - record.is_done = True + self.is_done = False + valid_records = self.filtered( + lambda r: (current_uid in r.users_ids.ids) + and not r.reclaim_state + ) + if not valid_records: + return + # 已办只看:审批中、结束 + target_records = valid_records.filtered( + lambda r: r.res_model and r.res_id and r.approve_state in ['pending', 'end'] + ) + if not target_records: + return + # 批量查询日志 + model_res_id_pairs = [(rec.res_model, rec.res_id) for rec in target_records] + log1_domain = [ + ('model', 'in', list({m for m, _ in model_res_id_pairs})), + ('res_id', 'in', list({r for _, r in model_res_id_pairs})), + ('done_by', '=', current_uid), + ] + log2_domain = log1_domain.copy() + + valid_done_pairs = set() + + # log_ids:同一个人多条 → 全部为 2/3 才算已办 + log1_records = self.env['soong.workflow.log'].search(log1_domain) + user_log1_map = {} + for log in log1_records: + key = (log.model, log.res_id) + if key not in user_log1_map: + user_log1_map[key] = [] + user_log1_map[key].append(log.approval_state) + + for key, states in user_log1_map.items(): + if all(s in ['2', '3'] for s in states): + valid_done_pairs.add(key) + + # log_ids2:单条为 2 就算已办 + log2_records = self.env['soong.workflow.log2'].search(log2_domain) + for log in log2_records: + if log.approval_state == '2': + valid_done_pairs.add((log.model, log.res_id)) + + # 赋值 + for rec in target_records: + if (rec.res_model, rec.res_id) in valid_done_pairs: + rec.is_done = True def _search_is_done(self, operator, value): current_uid = self.env.user.id base_domain = [ - ('soong_state', 'in', ['done', 'to_active', 'active']), + ('users_ids', 'in', current_uid), ('reclaim_state', '=', False), - ('users_ids', 'in', current_uid) + ('active', 'in', [True, False]) ] + candidate_records = self.search(base_domain) + if not candidate_records: + return [('id', '=', False)] + if (operator == '=' and value) or (operator == '!=' and not value): - domain = base_domain + # 已办只查 pending、end + target_records = candidate_records.filtered( + lambda r: r.res_model and r.res_id and r.approve_state in ['pending', 'end'] + ) + done_ids = [] + + if target_records: + model_res_id_pairs = [(rec.res_model, rec.res_id) for rec in target_records] + log_domain = [ + ('model', 'in', list({m for m, _ in model_res_id_pairs})), + ('res_id', 'in', list({r for _, r in model_res_id_pairs})), + ('done_by', '=', current_uid), + ] + # log_ids + user_log1_map = {} + for log in self.env['soong.workflow.log'].search(log_domain): + key = (log.model, log.res_id) + if key not in user_log1_map: + user_log1_map[key] = [] + user_log1_map[key].append(log.approval_state) + + valid_done_pairs = set() + for key, states in user_log1_map.items(): + if all(s in ['2', '3'] for s in states): + valid_done_pairs.add(key) + + # log_ids2 + for log in self.env['soong.workflow.log2'].search(log_domain): + if log.approval_state == '2': + valid_done_pairs.add((log.model, log.res_id)) + + for rec in target_records: + if (rec.res_model, rec.res_id) in valid_done_pairs: + done_ids.append(rec.id) + + domain = [('id', 'in', done_ids)] if done_ids else [('id', '=', False)] + elif (operator == '=' and not value) or (operator == '!=' and value): - domain = ['!'] + base_domain + target_records = candidate_records.filtered( + lambda r: r.res_model and r.res_id and r.approve_state in ['pending', 'end'] + ) + done_ids = [] + + if target_records: + model_res_id_pairs = [(rec.res_model, rec.res_id) for rec in target_records] + log_domain = [ + ('model', 'in', list({m for m, _ in model_res_id_pairs})), + ('res_id', 'in', list({r for _, r in model_res_id_pairs})), + ('done_by', '=', current_uid), + ] + + user_log1_map = {} + for log in self.env['soong.workflow.log'].search(log_domain): + key = (log.model, log.res_id) + if key not in user_log1_map: + user_log1_map[key] = [] + user_log1_map[key].append(log.approval_state) + + valid_done_pairs = set() + for key, states in user_log1_map.items(): + if all(s in ['2', '3'] for s in states): + valid_done_pairs.add(key) + + for log in self.env['soong.workflow.log2'].search(log_domain): + if log.approval_state == '2': + valid_done_pairs.add((log.model, log.res_id)) + + for rec in target_records: + if (rec.res_model, rec.res_id) in valid_done_pairs: + done_ids.append(rec.id) + + all_ids = candidate_records.ids + not_done_ids = [rid for rid in all_ids if rid not in done_ids] + domain = [('id', 'in', not_done_ids)] if not_done_ids else [('id', '=', False)] + else: domain = [] return domain @@ -682,60 +796,60 @@ class SoongWorkflowRecord(models.Model): if not all_records: return super(SoongWorkflowRecord, self).get_view(view_id, view_type, **options) - - model_res_ids = {} - for record in all_records: - if record.res_model not in model_res_ids: - model_res_ids[record.res_model] = [] - model_res_ids[record.res_model].append(record.res_id) - - model_records = {} - for model, res_ids in model_res_ids.items(): - model_records[model] = self.env[model].sudo().browse(res_ids) - - record_state_map = {} - for record in all_records: - model_record_set = model_records[record.res_model] - record_id = model_record_set.filtered(lambda r: r.id == record.res_id) - if not record_id or not hasattr(record_id, 'log_ids'): - continue - - new_state = None - current_user_logs = record_id.log_ids.filtered(lambda l: l.done_by.id == current_user.id) - if current_user_logs: - approval_states = current_user_logs.mapped('approval_state') - archive_log = current_user_logs.filtered(lambda l: l.name == '归档') - if archive_log: - if archive_log[0].approval_state in ['0', '1']: - new_state = 'to_active' - elif archive_log[0].approval_state == '2': - new_state = 'active' - else: - if any(state in ['0', '1'] for state in approval_states): - new_state = 'to_do' - elif all(state == '2' for state in approval_states): - new_state = 'done' - - if not new_state and hasattr(record_id, 'log_ids2'): - user_logs2 = record_id.log_ids2.filtered(lambda l: l.done_by.id == current_user.id) - if user_logs2: - log2_states = user_logs2.mapped('approval_state') - if '2' in log2_states: - new_state = 'done' - elif any(s in ['0', '1'] for s in log2_states): - new_state = 'to_do' - - if new_state: - record_state_map[record.id] = new_state - - if record_state_map: - state_groups = {} - for rec_id, state in record_state_map.items(): - if state not in state_groups: - state_groups[state] = [] - state_groups[state].append(rec_id) - for state, rec_ids in state_groups.items(): - self.browse(rec_ids).write({'soong_state': state}) + # + # model_res_ids = {} + # for record in all_records: + # if record.res_model not in model_res_ids: + # model_res_ids[record.res_model] = [] + # model_res_ids[record.res_model].append(record.res_id) + # + # model_records = {} + # for model, res_ids in model_res_ids.items(): + # model_records[model] = self.env[model].sudo().browse(res_ids) + # + # record_state_map = {} + # for record in all_records: + # model_record_set = model_records[record.res_model] + # record_id = model_record_set.filtered(lambda r: r.id == record.res_id) + # if not record_id or not hasattr(record_id, 'log_ids'): + # continue + # + # new_state = None + # current_user_logs = record_id.log_ids.filtered(lambda l: l.done_by.id == current_user.id) + # if current_user_logs: + # approval_states = current_user_logs.mapped('approval_state') + # archive_log = current_user_logs.filtered(lambda l: l.name == '归档') + # if archive_log: + # if archive_log[0].approval_state in ['0', '1']: + # new_state = 'to_active' + # elif archive_log[0].approval_state == '2': + # new_state = 'active' + # else: + # if any(state in ['0', '1'] for state in approval_states): + # new_state = 'to_do' + # elif all(state == '2' for state in approval_states): + # new_state = 'done' + # + # if not new_state and hasattr(record_id, 'log_ids2'): + # user_logs2 = record_id.log_ids2.filtered(lambda l: l.done_by.id == current_user.id) + # if user_logs2: + # log2_states = user_logs2.mapped('approval_state') + # if '2' in log2_states: + # new_state = 'done' + # elif any(s in ['0', '1'] for s in log2_states): + # new_state = 'to_do' + # + # if new_state: + # record_state_map[record.id] = new_state + # + # if record_state_map: + # state_groups = {} + # for rec_id, state in record_state_map.items(): + # if state not in state_groups: + # state_groups[state] = [] + # state_groups[state].append(rec_id) + # for state, rec_ids in state_groups.items(): + # self.browse(rec_ids).write({'soong_state': state}) if all_records: all_records._compute_is_done() diff --git a/yuthon_hr_attendance/views/go_approval.xml b/yuthon_hr_attendance/views/go_approval.xml index 0b2d8fc62..bb1674c70 100644 --- a/yuthon_hr_attendance/views/go_approval.xml +++ b/yuthon_hr_attendance/views/go_approval.xml @@ -68,7 +68,6 @@ -