diff --git a/yuthon_report/models/receivable_flow_report.py b/yuthon_report/models/receivable_flow_report.py index 026984211..37e7515fc 100644 --- a/yuthon_report/models/receivable_flow_report.py +++ b/yuthon_report/models/receivable_flow_report.py @@ -45,21 +45,49 @@ class ReceivableFlowReport(models.Model): domain.append(('company_id', '=', company_id)) receivables = self.search(domain, order="due_date asc") + rec_ids = receivables.ids + + # ===== 批量预加载,避免N+1查询 ===== + # 1. 批量查收款明细行 + all_modify_lines = self.env['receivable.modify.line'].search([ + ('receivable_id', 'in', rec_ids), + ('reconciliation_date', '!=', False), + ]) + # 按 receivable_id 分组 + modify_map = {} # {receivable_id: [lines]} + for ml in all_modify_lines: + modify_map.setdefault(ml.receivable_id.id, []).append(ml) + + # 2. 批量查违约金wizard + all_wizards = self.env['penalty.line.wizard'].search([ + ('receivable_id', 'in', rec_ids), + ]) + # 按 receivable_id 分组,并预取 pay_line_ids + wizard_map = {} # {receivable_id: [wizards]} + for wz in all_wizards: + wizard_map.setdefault(wz.receivable_id.id, []).append(wz) + # 预取所有 pay_line_ids + all_pay_lines = all_wizards.mapped('pay_line_ids') + # 按 wizard_id 分组 + pay_line_map = {} # {wizard_id: [pay_lines]} + for pl in all_pay_lines: + pay_line_map.setdefault(pl.penalty_id.id, []).append(pl) + # ===== 预加载结束 ===== rows = [] for idx, rec in enumerate(receivables, start=1): - # 获取收款信息 - modify_lines = self.env['receivable.modify.line'].search([ - ('receivable_id', '=', rec.id), - ('reconciliation_date', '!=', False) - ]) + # 获取收款信息(从预加载字典取) + modify_lines = modify_map.get(rec.id, []) # 计算收款总金额 total_collected = sum(line.amount for line in modify_lines) # 获取最新的收款时间和备注 - latest_payment = modify_lines.sorted(key=lambda l: l.reconciliation_date or datetime.datetime.min, reverse=True) + latest_payment = sorted( + [l for l in modify_lines if l.reconciliation_date], + key=lambda l: l.reconciliation_date, reverse=True + ) payment_date = latest_payment[0].reconciliation_date if latest_payment else None payment_remark = latest_payment[0].bank_id.remake if latest_payment and latest_payment[0].bank_id else "" @@ -161,15 +189,20 @@ class ReceivableFlowReport(models.Model): penalty_amount = days_diff * per_day penalty_amount = penalty_amount or rec.penalty or rec.original_amount or 0.0 - # 获取违约金收款信息 - wizards = self.env['penalty.line.wizard'].search([('receivable_id', '=', rec.id)]) - penalty_pay_lines = wizards.mapped('pay_line_ids') + # 获取违约金收款信息(从预加载字典取) + wz_list = wizard_map.get(rec.id, []) + penalty_pay_lines = [] + for wz in wz_list: + penalty_pay_lines.extend(pay_line_map.get(wz.id, [])) # 计算违约金收款金额 total_penalty_collected = sum(line.amount for line in penalty_pay_lines) # 获取最新的违约金收款时间 - latest_penalty_payment = penalty_pay_lines.sorted(key=lambda l: l.date or datetime.datetime.min, reverse=True) + latest_penalty_payment = sorted( + [l for l in penalty_pay_lines if l.date], + key=lambda l: l.date, reverse=True + ) penalty_payment_date = latest_penalty_payment[0].date if latest_penalty_payment else None rows.append({