Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
@@ -169,154 +169,142 @@ class SoongWorkflowRecord(models.Model):
|
||||
_logger.warning(f"Failed to get urgency_level from {record.res_model}: {e}")
|
||||
record.urgency_level = 'normal'
|
||||
|
||||
@api.depends('employee_ids', 'res_model', 'res_id', 'soong_state', 'reclaim_state', 'approve_state')
|
||||
@api.depends('employee_ids', 'res_model', 'res_id', 'soong_state', 'reclaim_state', 'approve_state',
|
||||
'employee2_ids')
|
||||
def _compute_is_to_do(self):
|
||||
"""保留原有计算逻辑(已优化批量查询,参考之前的版本)"""
|
||||
current_uid = self.env.user.id
|
||||
current_employees = self.env['hr.employee'].search([('user_id', '=', current_uid)])
|
||||
active_employee_ids = current_employees.ids if current_employees else []
|
||||
if not active_employee_ids:
|
||||
self.is_to_do = False
|
||||
# 关键修改:不再查users_ids,改为查当前用户对应的hr.employee记录
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', current_uid)], limit=1)
|
||||
if not current_employee:
|
||||
# 若当前用户无对应员工记录,所有记录均为非待办
|
||||
for rec in self:
|
||||
rec.is_to_do = False
|
||||
return
|
||||
# 批量优化:预加载员工映射(仅查1次)
|
||||
all_employees = self.env['hr.employee'].search([('user_state', '=', 'in')])
|
||||
emp_to_user = {emp.id: emp.user_id.id for emp in all_employees if emp.user_id}
|
||||
|
||||
# 第一步:批量处理条件1(approve_state=start)
|
||||
condition1_records = self.filtered(
|
||||
lambda r: not r.reclaim_state and r.approve_state == 'start' and
|
||||
set(active_employee_ids) & set(r.employee_ids.ids + r.employee2_ids.ids)
|
||||
# 初始化所有记录为非待办(上下文流畅,保留原有初始化逻辑)
|
||||
self.is_to_do = False
|
||||
valid_records = self.filtered(
|
||||
lambda r: (current_employee.id in r.employee_ids.ids or current_employee.id in r.employee2_ids.ids)
|
||||
and not r.reclaim_state
|
||||
)
|
||||
condition1_records.is_to_do = True
|
||||
if not valid_records:
|
||||
return
|
||||
# 以下逻辑完全不变,和你原来一致
|
||||
start_records = valid_records.filtered(lambda r: r.approve_state == 'start')
|
||||
start_records.is_to_do = True
|
||||
remaining_records = valid_records - start_records
|
||||
if not remaining_records:
|
||||
return
|
||||
|
||||
# 第二步:批量处理条件2(log_ids/log_ids2)
|
||||
remaining_records = self - condition1_records
|
||||
remaining_records.is_to_do = False
|
||||
target_records = remaining_records.filtered(
|
||||
lambda r: r.res_model and r.res_id and r.approve_state not in ['draft', 'start']
|
||||
)
|
||||
if not target_records:
|
||||
return
|
||||
|
||||
# 按res_model分组批量查询log(核心优化)
|
||||
model_res_ids = defaultdict(list)
|
||||
rec_model_res_map = {}
|
||||
for rec in remaining_records.filtered(lambda r: not r.reclaim_state and r.res_model and r.res_id):
|
||||
model_res_ids[rec.res_model].append(rec.res_id)
|
||||
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
|
||||
# 批量查询日志(性能优化保留,逻辑不变)
|
||||
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),
|
||||
('approval_state', 'in', ['0', '1'])
|
||||
]
|
||||
log2_domain = log1_domain.copy()
|
||||
|
||||
# 批量查log满足条件的记录ID
|
||||
valid_rec_ids = []
|
||||
for model_name, res_ids in model_res_ids.items():
|
||||
if not res_ids:
|
||||
continue
|
||||
TargetModel = self.env[model_name].sudo()
|
||||
log_domain = [
|
||||
('res_id', 'in', res_ids),
|
||||
('done_by', 'in', list(emp_to_user.values())),
|
||||
('approval_state', 'in', ['0', '1'])
|
||||
]
|
||||
# 批量查log_ids
|
||||
log1_valid_res_ids = TargetModel.log_ids.search(log_domain).mapped('res_id')
|
||||
# 批量查log_ids2
|
||||
log2_valid_res_ids = TargetModel.log_ids2.search(log_domain).mapped('res_id')
|
||||
valid_log1_pairs = set()
|
||||
log1_records = self.env['soong.workflow.log'].search(log1_domain)
|
||||
for log in log1_records:
|
||||
valid_log1_pairs.add((log.model, log.res_id))
|
||||
|
||||
valid_res_ids = set(log1_valid_res_ids + log2_valid_res_ids)
|
||||
for rec_id, (model, res_id) in rec_model_res_map.items():
|
||||
if model == model_name and res_id in valid_res_ids:
|
||||
valid_rec_ids.append(rec_id)
|
||||
self.browse(valid_rec_ids).is_to_do = True
|
||||
valid_log2_pairs = set()
|
||||
log2_records = self.env['soong.workflow.log2'].search(log2_domain)
|
||||
for log in log2_records:
|
||||
valid_log2_pairs.add((log.model, log.res_id))
|
||||
|
||||
valid_pairs = valid_log1_pairs | valid_log2_pairs
|
||||
for rec in target_records:
|
||||
if (rec.res_model, rec.res_id) in valid_pairs:
|
||||
rec.is_to_do = True
|
||||
|
||||
def _search_is_to_do(self, operator, value):
|
||||
"""搜索待办状态:仅打印总耗时"""
|
||||
|
||||
current_uid = self.env.user.id
|
||||
current_employees = self.env['hr.employee'].sudo().search([('user_id', '=', current_uid)])
|
||||
active_employee_ids = current_employees.ids if current_employees else []
|
||||
if not active_employee_ids:
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', current_uid)], limit=1)
|
||||
if not current_employee:
|
||||
return [('id', '=', False)]
|
||||
base_domain = [
|
||||
'|',
|
||||
('employee_ids', 'in', [current_employee.id]),
|
||||
('employee2_ids', 'in', [current_employee.id]),
|
||||
('reclaim_state', '=', False)
|
||||
]
|
||||
candidate_records = self.search(base_domain)
|
||||
if not candidate_records:
|
||||
return [('id', '=', False)]
|
||||
|
||||
base_domain = [
|
||||
('reclaim_state', '=', False),
|
||||
'|',
|
||||
('employee_ids', 'in', active_employee_ids),
|
||||
('employee2_ids', 'in', active_employee_ids)
|
||||
]
|
||||
|
||||
# 以下所有逻辑完全不变,和你原来一致
|
||||
if (operator == '=' and value) or (operator == '!=' and not value):
|
||||
candidate_records = self.search(base_domain)
|
||||
if not candidate_records:
|
||||
return [('id', '=', False)]
|
||||
|
||||
condition1_ids = candidate_records.filtered(
|
||||
lambda r: r.approve_state == 'start' and not r.reclaim_state
|
||||
lambda r: r.approve_state == 'start'
|
||||
).ids
|
||||
|
||||
model_res_ids = defaultdict(list)
|
||||
rec_model_res_map = {}
|
||||
for rec in candidate_records - self.browse(condition1_ids):
|
||||
if rec.res_model and rec.res_id:
|
||||
model_res_ids[rec.res_model].append(rec.res_id)
|
||||
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
|
||||
remaining_records = candidate_records - self.browse(condition1_ids)
|
||||
target_records = remaining_records.filtered(
|
||||
lambda r: r.res_model and r.res_id and r.approve_state not in ['draft', 'start']
|
||||
)
|
||||
|
||||
condition2_rec_ids = []
|
||||
for model_name, res_ids in model_res_ids.items():
|
||||
if not res_ids:
|
||||
continue
|
||||
TargetModel = self.env[model_name].sudo()
|
||||
log1_domain = [
|
||||
('res_id', 'in', res_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),
|
||||
('approval_state', 'in', ['0', '1'])
|
||||
]
|
||||
log1_valid_res_ids = TargetModel.log_ids.search(log1_domain).mapped('res_id')
|
||||
log2_domain = [
|
||||
('res_id', 'in', res_ids),
|
||||
('done_by', '=', current_uid),
|
||||
('approval_state', 'in', ['0', '1'])
|
||||
]
|
||||
log2_valid_res_ids = TargetModel.log_ids2.search(log2_domain).mapped('res_id')
|
||||
log1_valid_pairs = set(
|
||||
(log.model, log.res_id) for log in self.env['soong.workflow.log'].search(log_domain))
|
||||
log2_valid_pairs = set(
|
||||
(log.model, log.res_id) for log in self.env['soong.workflow.log2'].search(log_domain))
|
||||
valid_pairs = log1_valid_pairs | log2_valid_pairs
|
||||
|
||||
valid_res_ids = set(log1_valid_res_ids + log2_valid_res_ids)
|
||||
for rec_id, (model, res_id) in rec_model_res_map.items():
|
||||
if model == model_name and res_id in valid_res_ids:
|
||||
condition2_rec_ids.append(rec_id)
|
||||
for rec in target_records:
|
||||
if (rec.res_model, rec.res_id) in valid_pairs:
|
||||
condition2_rec_ids.append(rec.id)
|
||||
|
||||
valid_ids = list(set(condition1_ids + condition2_rec_ids))
|
||||
domain = [('id', 'in', valid_ids)]
|
||||
domain = [('id', 'in', valid_ids)] if valid_ids else [('id', '=', False)]
|
||||
|
||||
elif (operator == '=' and not value) or (operator == '!=' and value):
|
||||
candidate_records = self.search(base_domain)
|
||||
if not candidate_records:
|
||||
return [('id', '=', False)]
|
||||
condition1_todo_ids = candidate_records.filtered(lambda r: r.approve_state == 'start').ids
|
||||
|
||||
condition1_invalid_ids = candidate_records.filtered(
|
||||
lambda r: r.approve_state == 'start' and not r.reclaim_state
|
||||
).ids
|
||||
remaining_records = candidate_records - self.browse(condition1_todo_ids)
|
||||
target_records = remaining_records.filtered(
|
||||
lambda r: r.res_model and r.res_id and r.approve_state not in ['draft', 'start']
|
||||
)
|
||||
|
||||
model_res_ids = defaultdict(list)
|
||||
rec_model_res_map = {}
|
||||
for rec in candidate_records - self.browse(condition1_invalid_ids):
|
||||
if rec.res_model and rec.res_id:
|
||||
model_res_ids[rec.res_model].append(rec.res_id)
|
||||
rec_model_res_map[rec.id] = (rec.res_model, rec.res_id)
|
||||
|
||||
condition2_invalid_ids = []
|
||||
for model_name, res_ids in model_res_ids.items():
|
||||
if not res_ids:
|
||||
continue
|
||||
TargetModel = self.env[model_name].sudo()
|
||||
log1_domain = [
|
||||
('res_id', 'in', res_ids),
|
||||
condition2_todo_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),
|
||||
('approval_state', 'in', ['0', '1'])
|
||||
]
|
||||
log1_valid_res_ids = TargetModel.log_ids.search(log1_domain).mapped('res_id')
|
||||
log2_domain = log1_domain.copy()
|
||||
log2_valid_res_ids = TargetModel.log_ids2.search(log2_domain).mapped('res_id')
|
||||
log1_valid_pairs = set(
|
||||
(log.model, log.res_id) for log in self.env['soong.workflow.log'].search(log_domain))
|
||||
log2_valid_pairs = set(
|
||||
(log.model, log.res_id) for log in self.env['soong.workflow.log2'].search(log_domain))
|
||||
valid_pairs = log1_valid_pairs | log2_valid_pairs
|
||||
|
||||
valid_res_ids = set(log1_valid_res_ids + log2_valid_res_ids)
|
||||
for rec_id, (model, res_id) in rec_model_res_map.items():
|
||||
if model == model_name and res_id in valid_res_ids:
|
||||
condition2_invalid_ids.append(rec_id)
|
||||
for rec in target_records:
|
||||
if (rec.res_model, rec.res_id) in valid_pairs:
|
||||
condition2_todo_ids.append(rec.id)
|
||||
|
||||
invalid_ids = list(set(condition1_invalid_ids + condition2_invalid_ids))
|
||||
domain = [('id', 'not in', invalid_ids)]
|
||||
todo_ids = list(set(condition1_todo_ids + condition2_todo_ids))
|
||||
all_candidate_ids = candidate_records.ids
|
||||
non_todo_ids = [rec_id for rec_id in all_candidate_ids if rec_id not in todo_ids]
|
||||
domain = [('id', 'in', non_todo_ids)] if non_todo_ids else [('id', '=', False)]
|
||||
else:
|
||||
domain = [('id', '=', False)]
|
||||
|
||||
@@ -669,93 +657,22 @@ class SoongWorkflowRecord(models.Model):
|
||||
|
||||
@api.model
|
||||
def get_view(self, view_id=None, view_type='form', **options):
|
||||
"""优化后:批量查询+批量写入,消除嵌套循环"""
|
||||
# ========== 第一步:批量查询所有目标记录(仅1次搜索) ==========
|
||||
current_user_id = self.env.user.id
|
||||
all_records = self.search([
|
||||
('users_ids', 'in', current_user_id),
|
||||
('soong_state', '!=', 'active'),
|
||||
])
|
||||
if not all_records:
|
||||
return super().get_view(view_id, view_type, **options)
|
||||
|
||||
model_res_ids = defaultdict(list)
|
||||
rec_model_res_map = {rec.id: (rec.res_model, rec.res_id) for rec in all_records if rec.res_model and rec.res_id}
|
||||
for rec_id, (model, res_id) in rec_model_res_map.items():
|
||||
model_res_ids[model].append(res_id)
|
||||
|
||||
log_data = defaultdict(dict)
|
||||
for model_name, res_ids in model_res_ids.items():
|
||||
if not res_ids:
|
||||
continue
|
||||
try:
|
||||
TargetModel = self.env[model_name].sudo()
|
||||
has_log1 = 'log_ids' in TargetModel._fields
|
||||
has_log2 = 'log_ids2' in TargetModel._fields
|
||||
|
||||
# 批量查log_ids(当前用户,仅当字段存在时)
|
||||
if has_log1:
|
||||
log1_domain = [('res_id', 'in', res_ids), ('done_by', '=', current_user_id)]
|
||||
log1_records = TargetModel.log_ids.search(log1_domain)
|
||||
for log in log1_records:
|
||||
if log.res_id not in log_data[model_name]:
|
||||
log_data[model_name][log.res_id] = {'log1_states': [], 'log2_states': [],
|
||||
'has_archive_log': False}
|
||||
log_data[model_name][log.res_id]['log1_states'].append(log.approval_state)
|
||||
if log.name == '归档':
|
||||
log_data[model_name][log.res_id]['has_archive_log'] = True
|
||||
log_data[model_name][log.res_id]['archive_state'] = log.approval_state
|
||||
|
||||
# 批量查log_ids2(当前用户,仅当字段存在时)
|
||||
if has_log2:
|
||||
log2_domain = [('res_id', 'in', res_ids), ('done_by.name', '=', self.env.user.name)]
|
||||
log2_records = TargetModel.log_ids2.search(log2_domain)
|
||||
for log2 in log2_records:
|
||||
if log2.res_id not in log_data[model_name]:
|
||||
log_data[model_name][log2.res_id] = {'log1_states': [], 'log2_states': [],
|
||||
'has_archive_log': False}
|
||||
log_data[model_name][log2.res_id]['log2_states'].append(log2.approval_state)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
to_write = defaultdict(list) # {状态: [记录ID]}
|
||||
for rec in all_records:
|
||||
if rec.id not in rec_model_res_map:
|
||||
continue
|
||||
model, res_id = rec_model_res_map[rec.id]
|
||||
if model not in log_data or res_id not in log_data[model]:
|
||||
continue
|
||||
|
||||
log_info = log_data[model][res_id]
|
||||
# 处理归档日志优先级最高
|
||||
if log_info['has_archive_log']:
|
||||
if log_info['archive_state'] in ['0', '1']:
|
||||
to_write['to_active'].append(rec.id)
|
||||
elif log_info['archive_state'] == '2':
|
||||
to_write['active'].append(rec.id)
|
||||
continue
|
||||
|
||||
# 处理普通log_ids
|
||||
log1_states = log_info['log1_states']
|
||||
if any(s in ['0', '1'] for s in log1_states):
|
||||
to_write['to_do'].append(rec.id)
|
||||
elif all(s == '2' for s in log1_states if s):
|
||||
to_write['done'].append(rec.id)
|
||||
|
||||
# 处理log_ids2
|
||||
log2_states = log_info['log2_states']
|
||||
if log2_states:
|
||||
if any(s in ['0', '1'] for s in log2_states):
|
||||
to_write['to_do'].append(rec.id)
|
||||
elif all(s == '2' for s in log2_states):
|
||||
to_write['done'].append(rec.id)
|
||||
|
||||
for state, rec_ids in to_write.items():
|
||||
if rec_ids:
|
||||
self.browse(rec_ids).write({'soong_state': state})
|
||||
all_records._compute_is_done()
|
||||
all_records._compute_is_to_do()
|
||||
return super().get_view(view_id, view_type, **options)
|
||||
current_employee = self.env['hr.employee'].search([('user_id', '=', current_user_id)], limit=1)
|
||||
view = super().get_view(view_id, view_type, **options)
|
||||
if not current_employee:
|
||||
return view
|
||||
if view_type == 'list':
|
||||
all_records = self.search([
|
||||
'|',
|
||||
('employee_ids', 'in', [current_employee.id]),
|
||||
('employee2_ids', 'in', [current_employee.id]),
|
||||
('reclaim_state', '=', False) # 补回丢失的过滤条件
|
||||
]) # 限制最大记录数,避免性能问题
|
||||
if all_records:
|
||||
all_records._compute_is_done()
|
||||
all_records._compute_is_to_do()
|
||||
return view
|
||||
|
||||
def to_do_process_reminders(self):
|
||||
workflow_records = self.env['soong.workflow.record'].search([
|
||||
|
||||
@@ -387,7 +387,7 @@ class SoongWorkflowCommentWizard(models.TransientModel):
|
||||
|
||||
elif link_users_group_ids:
|
||||
role_domain = ['|', ('user_role_id', 'in', link_users_group_ids.user_role_ids.ids),
|
||||
('user_role_ids', 'in', link_users_group_ids.user_role_ids.ids)]
|
||||
('user_role_ids', 'in', link_users_group_ids.user_role_ids.ids),]
|
||||
if user_role_domain:
|
||||
role_domain = ['|'] + role_domain + user_role_domain
|
||||
domain = role_domain + company_domain + department_domain
|
||||
|
||||
@@ -178,7 +178,7 @@ class AppletAttendance(Controller):
|
||||
check_in_str = check_in.strftime('%H:%M:%S') if check_in else ' '
|
||||
check_out_str = check_out.strftime('%H:%M:%S') if check_out else ' '
|
||||
has_leave_batch_workflow = False
|
||||
if attendance_id.workflow_id and attendance_id.workflow_id.res_model == 'hr.leave.batch':
|
||||
if attendance_id.workflow_id and attendance_id.workflow_id.res_model in ['hr.leave.batch', 'go.approval']:
|
||||
has_leave_batch_workflow = True
|
||||
|
||||
check_in_html = f'<p style="color:green">{check_in_str}</p>' if has_leave_batch_workflow else (
|
||||
@@ -299,7 +299,7 @@ class AppletAttendance(Controller):
|
||||
check_out_str = check_out.strftime('%H:%M:%S') if check_out else ' '
|
||||
has_leave_batch_workflow = False
|
||||
if hasattr(attendance_id, 'workflow_id') and attendance_id.workflow_id:
|
||||
if attendance_id.workflow_id.res_model == 'hr.leave.batch':
|
||||
if attendance_id.workflow_id.res_model in ['hr.leave.batch', 'go.approval']:
|
||||
has_leave_batch_workflow = True
|
||||
|
||||
check_in_html = (
|
||||
@@ -737,7 +737,7 @@ class AppletAttendance(Controller):
|
||||
|
||||
has_leave_batch_workflow = False
|
||||
if hasattr(att, 'workflow_id') and att.workflow_id:
|
||||
if att.workflow_id.res_model == 'hr.leave.batch':
|
||||
if att.workflow_id.res_model in ['hr.leave.batch', 'go.approval']:
|
||||
has_leave_batch_workflow = True
|
||||
|
||||
if not check_in_status and not check_out_status:
|
||||
|
||||
@@ -63,7 +63,7 @@ class YuthonRenewalApproval(models.Model):
|
||||
new_contract_type_id = no_fixed_type.id
|
||||
new_contract_vals.update({
|
||||
'date_end': self.renewal_date,
|
||||
# 'date_start': original_contract.date_end + relativedelta(days=1),
|
||||
'date_start': original_contract.date_end + relativedelta(days=1),
|
||||
'state': 'open',
|
||||
'job_id': self.job_id.id,
|
||||
'version': new_version,
|
||||
|
||||
@@ -237,6 +237,19 @@ class IssueMeetingLine(models.Model):
|
||||
decision_results = fields.Selection([('agree', '通过'), ('disagree', '重新上会'), ('rejected', '驳回')], string="决策结果")
|
||||
decision_details = fields.Text(string="决策详情")
|
||||
|
||||
@api.onchange('issue_library_id')
|
||||
def onchange_issue_library_id(self):
|
||||
if self.issue_library_id:
|
||||
dept_manager = self.env['hr.employee'].search([
|
||||
('active', '=', True),
|
||||
('user_role_id.name', '=', '部门经理'),
|
||||
'|',
|
||||
('department_id', '=', self.issue_library_id.department_id.id),
|
||||
('department_ids', 'in', [self.issue_library_id.department_id.id])
|
||||
], limit=1)
|
||||
if dept_manager:
|
||||
self.employee_id = dept_manager.id
|
||||
|
||||
def open_record(self):
|
||||
form_id = self.env.ref('yuthon_issue.view_issue_library_form').id
|
||||
return {
|
||||
|
||||
@@ -71,44 +71,82 @@ class DepositMonthReceivedReport(models.Model):
|
||||
for line in modify_lines:
|
||||
if not line.receivable_id:
|
||||
continue
|
||||
receivable_id = line.receivable_id.id
|
||||
|
||||
rec = line.receivable_id
|
||||
# 使用receivable.modify.line的delivered1字段作为金额
|
||||
amount = round(line.delivered1 or 0.0, 2)
|
||||
# 获取收款日期
|
||||
payout_date = rec.payout_date
|
||||
if not payout_date:
|
||||
continue
|
||||
# 检查日期是否在本月范围内
|
||||
if period_start <= payout_date <= period_end:
|
||||
total_amount += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": {
|
||||
'model': 'property.lease.contract',
|
||||
'id': rec.contract_id.id,
|
||||
'display_name': rec.contract_id.contract_code,
|
||||
} if rec.contract_id else "",
|
||||
"物业名称": {
|
||||
'model': 'yuthon.property',
|
||||
'id': rec.contract_id.lease_ids[0].address_id.id,
|
||||
'display_name': rec.property_name,
|
||||
} if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else rec.property_name or "",
|
||||
"承租方名称": {
|
||||
'model': 'property.tenant.information',
|
||||
'id': rec.lessee_id.id,
|
||||
'display_name': rec.lessee_id.name,
|
||||
} if rec.lessee_id else "",
|
||||
"收款日期": payout_date.strftime("%Y-%m-%d"),
|
||||
"金额": amount,
|
||||
"所属公司": rec.company_id.name if rec.company_id else "",
|
||||
"管理员": {
|
||||
'model': 'res.users',
|
||||
'id': rec.admin_id.id,
|
||||
'display_name': rec.admin_id.name,
|
||||
} if rec.admin_id else "",
|
||||
})
|
||||
idx += 1
|
||||
wizards = self.env['penalty.line.wizard'].search(
|
||||
[('receivable_id', '=', receivable_id)]
|
||||
)
|
||||
if not wizards:
|
||||
# 如果没有关联的wizard,尝试直接从line获取信息
|
||||
if line.delivered1 and (line.receivable_id.payout_date or line.create_date):
|
||||
# 使用payout_date作为收款日期,如果没有则使用create_date
|
||||
payment_date = line.receivable_id.payout_date or line.create_date.date()
|
||||
if period_start <= payment_date <= period_end:
|
||||
amount = round(line.delivered1, 2)
|
||||
total_amount += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": {
|
||||
'model': 'property.lease.contract',
|
||||
'id': rec.contract_id.id,
|
||||
'display_name': rec.contract_id.contract_code,
|
||||
} if rec.contract_id else "",
|
||||
"物业名称": {
|
||||
'model': 'yuthon.property',
|
||||
'id': rec.contract_id.lease_ids[0].address_id.id,
|
||||
'display_name': rec.property_name,
|
||||
} if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else rec.property_name or "",
|
||||
"承租方名称": {
|
||||
'model': 'property.tenant.information',
|
||||
'id': rec.lessee_id.id,
|
||||
'display_name': rec.lessee_id.name,
|
||||
} if rec.lessee_id else "",
|
||||
"收款日期": payment_date.strftime("%Y-%m-%d"),
|
||||
"金额": amount,
|
||||
"所属公司": rec.company_id.name if rec.company_id else "",
|
||||
"管理员": {
|
||||
'model': 'res.users',
|
||||
'id': rec.admin_id.id,
|
||||
'display_name': rec.admin_id.name,
|
||||
} if rec.admin_id else "",
|
||||
})
|
||||
idx += 1
|
||||
else:
|
||||
for wizard in wizards:
|
||||
for pay in wizard.pay_line_ids:
|
||||
if not pay.date:
|
||||
continue
|
||||
if period_start <= pay.date <= period_end:
|
||||
amount = round(pay.amount, 2)
|
||||
total_amount += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": {
|
||||
'model': 'property.lease.contract',
|
||||
'id': rec.contract_id.id,
|
||||
'display_name': rec.contract_id.contract_code,
|
||||
} if rec.contract_id else "",
|
||||
"物业名称": {
|
||||
'model': 'yuthon.property',
|
||||
'id': rec.contract_id.lease_ids[0].address_id.id,
|
||||
'display_name': rec.property_name,
|
||||
} if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else rec.property_name or "",
|
||||
"承租方名称": {
|
||||
'model': 'property.tenant.information',
|
||||
'id': rec.lessee_id.id,
|
||||
'display_name': rec.lessee_id.name,
|
||||
} if rec.lessee_id else "",
|
||||
"收款日期": pay.date.strftime("%Y-%m-%d"),
|
||||
"金额": amount,
|
||||
"所属公司": rec.company_id.name if rec.company_id else "",
|
||||
"管理员": {
|
||||
'model': 'res.users',
|
||||
'id': rec.admin_id.id,
|
||||
'display_name': rec.admin_id.name,
|
||||
} if rec.admin_id else "",
|
||||
})
|
||||
idx += 1
|
||||
|
||||
stats = [
|
||||
{'name': '记录总数', 'amount': len(rows)},
|
||||
|
||||
@@ -12,8 +12,7 @@ class DepositPreReceivedReport(models.Model):
|
||||
押金前期实收报表:
|
||||
- 数据源: receivable.modify.line(应收类型为押金)
|
||||
- 金额: penalty.pay.line.amount(支付金额)
|
||||
- 日期过滤: penalty.pay.line.date 在本年1月至查询月上个月最后一天(不含查询月)
|
||||
- 查1月返回空数据
|
||||
- 日期过滤: penalty.pay.line.date 在无限制至查询月上个月最后一天(不含查询月)
|
||||
"""
|
||||
date_start = params.get("date_start")
|
||||
if date_start:
|
||||
@@ -21,19 +20,11 @@ class DepositPreReceivedReport(models.Model):
|
||||
else:
|
||||
query_date = datetime.date.today()
|
||||
|
||||
query_year = query_date.year
|
||||
query_month = query_date.month
|
||||
|
||||
# 查询月为1月时返回空数据
|
||||
if query_month == 1:
|
||||
return {
|
||||
"rows": [],
|
||||
"stats": [{'name': '记录总数', 'amount': 0}, {'name': '合计金额', 'amount': 0}]
|
||||
}
|
||||
|
||||
# 前期范围:本年1月至1日 ~ 查询月上个月最后一天
|
||||
period_start = datetime.date(query_year, 1, 1)
|
||||
period_end = datetime.date(query_year, query_month, 1) - datetime.timedelta(days=1)
|
||||
# 前期范围:无限制 ~ 查询月上个月最后一天
|
||||
# 只设置结束日期,不设置开始日期,实现完全无限制
|
||||
period_end = datetime.date(query_date.year, query_month, 1) - datetime.timedelta(days=1)
|
||||
|
||||
deposit_type = self.env['yuthon.management.type'].search([('name', '=', '押金')], limit=1)
|
||||
|
||||
@@ -68,44 +59,82 @@ class DepositPreReceivedReport(models.Model):
|
||||
for line in modify_lines:
|
||||
if not line.receivable_id:
|
||||
continue
|
||||
receivable_id = line.receivable_id.id
|
||||
|
||||
rec = line.receivable_id
|
||||
# 使用receivable.modify.line的delivered1字段作为金额
|
||||
amount = round(line.delivered1 or 0.0, 2)
|
||||
# 获取收款日期
|
||||
payout_date = rec.payout_date
|
||||
if not payout_date:
|
||||
continue
|
||||
# 检查日期是否在前期范围内
|
||||
if period_start <= payout_date <= period_end:
|
||||
total_amount += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": {
|
||||
'model': 'property.lease.contract',
|
||||
'id': rec.contract_id.id,
|
||||
'display_name': rec.contract_id.contract_code,
|
||||
} if rec.contract_id else "",
|
||||
"物业名称": {
|
||||
'model': 'yuthon.property',
|
||||
'id': rec.contract_id.lease_ids[0].address_id.id,
|
||||
'display_name': rec.property_name,
|
||||
} if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else rec.property_name or "",
|
||||
"承租方名称": {
|
||||
'model': 'property.tenant.information',
|
||||
'id': rec.lessee_id.id,
|
||||
'display_name': rec.lessee_id.name,
|
||||
} if rec.lessee_id else "",
|
||||
"收款日期": payout_date.strftime("%Y-%m-%d"),
|
||||
"金额": amount,
|
||||
"所属公司": rec.company_id.name if rec.company_id else "",
|
||||
"管理员": {
|
||||
'model': 'res.users',
|
||||
'id': rec.admin_id.id,
|
||||
'display_name': rec.admin_id.name,
|
||||
} if rec.admin_id else "",
|
||||
})
|
||||
idx += 1
|
||||
wizards = self.env['penalty.line.wizard'].search(
|
||||
[('receivable_id', '=', receivable_id)]
|
||||
)
|
||||
if not wizards:
|
||||
# 如果没有关联的wizard,尝试直接从line获取信息
|
||||
if line.delivered1 and (line.receivable_id.payout_date or line.create_date):
|
||||
# 使用payout_date作为收款日期,如果没有则使用create_date
|
||||
payment_date = line.receivable_id.payout_date or line.create_date.date()
|
||||
if payment_date <= period_end:
|
||||
amount = round(line.delivered1, 2)
|
||||
total_amount += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": {
|
||||
'model': 'property.lease.contract',
|
||||
'id': rec.contract_id.id,
|
||||
'display_name': rec.contract_id.contract_code,
|
||||
} if rec.contract_id else "",
|
||||
"物业名称": {
|
||||
'model': 'yuthon.property',
|
||||
'id': rec.contract_id.lease_ids[0].address_id.id,
|
||||
'display_name': rec.property_name,
|
||||
} if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else rec.property_name or "",
|
||||
"承租方名称": {
|
||||
'model': 'property.tenant.information',
|
||||
'id': rec.lessee_id.id,
|
||||
'display_name': rec.lessee_id.name,
|
||||
} if rec.lessee_id else "",
|
||||
"收款日期": payment_date.strftime("%Y-%m-%d"),
|
||||
"金额": amount,
|
||||
"所属公司": rec.company_id.name if rec.company_id else "",
|
||||
"管理员": {
|
||||
'model': 'res.users',
|
||||
'id': rec.admin_id.id,
|
||||
'display_name': rec.admin_id.name,
|
||||
} if rec.admin_id else "",
|
||||
})
|
||||
idx += 1
|
||||
else:
|
||||
for wizard in wizards:
|
||||
for pay in wizard.pay_line_ids:
|
||||
if not pay.date:
|
||||
continue
|
||||
if pay.date <= period_end:
|
||||
amount = round(pay.amount, 2)
|
||||
total_amount += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": {
|
||||
'model': 'property.lease.contract',
|
||||
'id': rec.contract_id.id,
|
||||
'display_name': rec.contract_id.contract_code,
|
||||
} if rec.contract_id else "",
|
||||
"物业名称": {
|
||||
'model': 'yuthon.property',
|
||||
'id': rec.contract_id.lease_ids[0].address_id.id,
|
||||
'display_name': rec.property_name,
|
||||
} if rec.contract_id and rec.contract_id.lease_ids and rec.contract_id.lease_ids[0].address_id else rec.property_name or "",
|
||||
"承租方名称": {
|
||||
'model': 'property.tenant.information',
|
||||
'id': rec.lessee_id.id,
|
||||
'display_name': rec.lessee_id.name,
|
||||
} if rec.lessee_id else "",
|
||||
"收款日期": pay.date.strftime("%Y-%m-%d"),
|
||||
"金额": amount,
|
||||
"所属公司": rec.company_id.name if rec.company_id else "",
|
||||
"管理员": {
|
||||
'model': 'res.users',
|
||||
'id': rec.admin_id.id,
|
||||
'display_name': rec.admin_id.name,
|
||||
} if rec.admin_id else "",
|
||||
})
|
||||
idx += 1
|
||||
|
||||
stats = [
|
||||
{'name': '记录总数', 'amount': len(rows)},
|
||||
|
||||
Reference in New Issue
Block a user