From 3baa86175b8d7bb4f4bbc66b6fc4ef569747415b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=8E=E9=B9=8F=E5=AE=87?=
<9664676+pengyuthon@user.noreply.gitee.com>
Date: Fri, 10 Apr 2026 16:29:22 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../models/soong_workflow_record.py | 250 +++++++++++++-----
yuthon_hr_attendance/views/go_approval.xml | 1 -
2 files changed, 182 insertions(+), 69 deletions(-)
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 @@
-