@@ -31,7 +31,7 @@ class CumArrearsReport(models.Model):
|
||||
# 核心逻辑:due_date <= query_month_end(应收日期在查询月及之前,包含查询月)
|
||||
domain = [
|
||||
('receivable_id.due_date', '<=', query_month_end),
|
||||
('receivable_id.is_invalid', '=', False),
|
||||
('receivable_id.is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
keyword = params.get("keyword")
|
||||
|
||||
@@ -31,7 +31,7 @@ class CumIncomeReport(models.Model):
|
||||
domain = [
|
||||
('receivable_id.due_date', '>=', year_start),
|
||||
('receivable_id.due_date', '<=', year_end),
|
||||
('receivable_id.is_invalid', '=', False),
|
||||
('receivable_id.is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
keyword = params.get("keyword")
|
||||
|
||||
@@ -26,7 +26,7 @@ class DepositCumArrearsReport(models.Model):
|
||||
|
||||
domain = [
|
||||
('management_type_id.name', '=', '押金'),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('due_date', '>=', month_first),
|
||||
('due_date', '<=', month_last),
|
||||
('submitted', '>', 0),
|
||||
|
||||
@@ -25,7 +25,7 @@ class DepositMonthReceivableReport(models.Model):
|
||||
domain = [
|
||||
('due_date', '>=', month_first),
|
||||
('due_date', '<=', month_last),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('management_type_id.name', '=', '押金'),
|
||||
]
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class DepositMonthReceivedReport(models.Model):
|
||||
domain = [
|
||||
('management_type_id.name', '=', '押金'),
|
||||
('deposit_state', 'in', ['paid', 'no_paid']),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('payout_date', '>=', month_first),
|
||||
('payout_date', '<=', month_last),
|
||||
]
|
||||
|
||||
@@ -25,7 +25,7 @@ class DepositPreReceivedReport(models.Model):
|
||||
domain = [
|
||||
('management_type_id.name', '=', '押金'),
|
||||
('deposit_state', '=', 'paid'),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('payout_date', '!=', False),
|
||||
('payout_date', '<', month_first),
|
||||
]
|
||||
|
||||
@@ -36,7 +36,7 @@ class DepositTotalReport(models.Model):
|
||||
domain = [
|
||||
('management_type_id.name', '=', '押金'),
|
||||
('deposit_state', '=', 'paid'),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('payout_date', '>=', month_first),
|
||||
('payout_date', '<=', month_last),
|
||||
]
|
||||
|
||||
@@ -30,14 +30,14 @@ class HydropowerReport(models.Model):
|
||||
('payout_date', '>=', start_date),
|
||||
('payout_date', '<=', end_date),
|
||||
('management_type_id.name', '=', '水费'),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
])
|
||||
|
||||
electric_records = self.env['property.accounts.receivable'].search([
|
||||
('payout_date', '>=', start_date),
|
||||
('payout_date', '<=', end_date),
|
||||
('management_type_id.name', '=', '电费'),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
])
|
||||
|
||||
# 整合数据,按物业(合同关联的第一个物业)聊合
|
||||
|
||||
@@ -26,7 +26,7 @@ class MonthReceivableReport(models.Model):
|
||||
('reconciliation_date', '!=', False),
|
||||
('receivable_id.due_date', '>=', month_first),
|
||||
('receivable_id.due_date', '<=', month_last),
|
||||
('receivable_id.is_invalid', '=', False),
|
||||
('receivable_id.is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
if params.get('keyword'):
|
||||
|
||||
@@ -29,7 +29,7 @@ class MonthlyPrecollectionReport(models.Model):
|
||||
domain = [
|
||||
('reconciliation_date', '>=', month_start),
|
||||
('reconciliation_date', '<=', month_end),
|
||||
('receivable_id.is_invalid', '=', False),
|
||||
('receivable_id.is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
keyword = params.get("keyword")
|
||||
|
||||
@@ -19,7 +19,7 @@ class PenaltyArrearsReport(models.Model):
|
||||
|
||||
domain = [
|
||||
('submitted', '>', 0),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
date_start = params.get("date_start")
|
||||
|
||||
@@ -32,7 +32,7 @@ class PenaltyMonthReceivedReport(models.Model):
|
||||
domain = [
|
||||
('payout_date', '>=', start_dt),
|
||||
('payout_date', '<=', end_dt),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
# 违约金过滤
|
||||
|
||||
@@ -29,7 +29,7 @@ class PenaltyYearCumReport(models.Model):
|
||||
domain = [
|
||||
('payout_date', '>=', start_dt),
|
||||
('payout_date', '<=', end_dt),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
# 违约金过滤
|
||||
|
||||
@@ -33,7 +33,7 @@ class PreAdvanceReport(models.Model):
|
||||
domain = [
|
||||
('reconciliation_date', '!=', False),
|
||||
('receivable_id.due_date', '>=', cutoff_month_first),
|
||||
('receivable_id.is_invalid', '=', False),
|
||||
('receivable_id.is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
keyword = params.get("keyword")
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PreArrearsReport(models.Model):
|
||||
_inherit = 'receivable.modify.line'
|
||||
@@ -10,15 +13,17 @@ class PreArrearsReport(models.Model):
|
||||
def get_pre_arrears_report(self, params):
|
||||
"""
|
||||
前期欠收报表(数据源:receivable.modify.line):
|
||||
- 查询条件的日期对应应收账单的 due_date(应收日期在查询月及之前)
|
||||
- 查询条件的日期对应应收账单的 due_date(应收日期在查询月之前,不包含查询月)
|
||||
- 欠收条件:
|
||||
- 收款日期在查询月之后(查询月时点还没收到钱)
|
||||
- 或者 not_collected > 0 (部分收款,还没交完)
|
||||
- 收款日期(payout_date)为空: 从未收款 → 欠收
|
||||
- 收款日期在查询月之后: 查询月时点还没收到钱 → 欠收
|
||||
- 收款日期 <= 查询月末: 已经交过了 → 不算欠收
|
||||
- 金额取值:
|
||||
- 如果 not_collected > 0,取 not_collected (当前还欠的金额)
|
||||
- 否则取 amount (已收金额)
|
||||
- 否则取 amount (已对金额)
|
||||
- 按应收账单聚合,每张账单只出一行(汇总该账单下所有欠收收款金额)
|
||||
- 补充: 对于从未对过账但 submitted > 0 的应收账单,直接从 accounts.receivable 取数
|
||||
- 补充: 对于真正从未对过账(在 modify.line 表中无任何记录)但 submitted > 0 的应收账单,
|
||||
直接从 accounts.receivable 取数补齐
|
||||
"""
|
||||
today = datetime.date.today()
|
||||
this_month_first = today.replace(day=1)
|
||||
@@ -47,7 +52,7 @@ class PreArrearsReport(models.Model):
|
||||
# 核心逻辑:due_date < query_month_start(应收日期在查询月之前,不包含查询月)
|
||||
domain = [
|
||||
('receivable_id.due_date', '<', query_month_start),
|
||||
('receivable_id.is_invalid', '=', False),
|
||||
('receivable_id.is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
if keyword:
|
||||
@@ -75,19 +80,19 @@ class PreArrearsReport(models.Model):
|
||||
else:
|
||||
domain.append(('receivable_id.management_type_id.name', 'not in', ['押金', '违约金']))
|
||||
|
||||
_logger.info("=== PRE_ARREARS Part1: modify.line search ===")
|
||||
_logger.info("query_month_start=%s, query_month_end=%s", query_month_start, query_month_end)
|
||||
_logger.info("Part1 domain: %s", domain)
|
||||
|
||||
lines = self.sudo().search(domain, order="receivable_id asc, payout_date asc")
|
||||
|
||||
# 欠收条件(同时满足):
|
||||
# 1. payout_date >= query_month_start (收款日期不能小于查询月)
|
||||
# 2. 满足以下任一:
|
||||
# a. payout_date > query_month_end (收款日期在查询月之后,查询月时点还没收到钱)
|
||||
# b. not_collected > 0 (部分收款,还没交完)
|
||||
_logger.info("Part1 search found %s modify.line records", len(lines))
|
||||
|
||||
# 欠收条件:收款日期为空(从未收款) 或 收款日期在查询月之后(查询月时点还没收到钱)
|
||||
# 如果 payout_date <= query_month_end,说明查询月及之前已经交过了,不算欠收
|
||||
lines = lines.filtered(
|
||||
lambda l: l.payout_date and l.payout_date >= query_month_start and (
|
||||
(l.payout_date > query_month_end) or
|
||||
(l.not_collected and l.not_collected > 0)
|
||||
)
|
||||
lambda l: not l.payout_date or l.payout_date > query_month_end
|
||||
)
|
||||
_logger.info("Part1 after欠收filter: %s records remain", len(lines))
|
||||
|
||||
# 按应收账单聚合
|
||||
rec_map = {}
|
||||
@@ -104,19 +109,31 @@ class PreArrearsReport(models.Model):
|
||||
rec_map[rid]['discount_amount'] = line.receivable_id.discount_amount or 0.0
|
||||
|
||||
# ============================================================
|
||||
# 第二部分:补充从未对过账但 submitted > 0 的应收账单
|
||||
# modify.line 只能查到已对过账的记录。如果一笔应收账单从未对过账,
|
||||
# submitted > 0(未收金额>0)但 modify.line 中没有对应记录,
|
||||
# 直接从 property.accounts.receivable 取数补齐
|
||||
# 第二部分:补充真正从未对过账 but submitted > 0 的应收账单
|
||||
# Part 1 只能查到有 modify.line 记录且 payout_date > query_month_end 的数据。
|
||||
# 对于那些真正从未对过账(在 modify.line 表中无任何记录)的应收账单,
|
||||
# 直接从 property.accounts.receivable 取数补齐。
|
||||
#
|
||||
# 关键:需要排除所有在 modify.line 中出现过的 receivable_id,
|
||||
# 不仅仅是 Part 1 覆盖的那些。否则,有 modify.line 但 payout_date
|
||||
# 早于查询月的 receivable 会被错误地纳入欠收。
|
||||
# ============================================================
|
||||
covered_ids = list(rec_map.keys())
|
||||
|
||||
# 找出所有在 modify.line 中有记录的 receivable_id(不管 payout_date 是什么时候)
|
||||
all_line_receivable_ids = set(
|
||||
self.sudo().search([('receivable_id', '!=', False)]).mapped('receivable_id.id')
|
||||
)
|
||||
# Part 2 只查真正"从未对过账"的 receivable
|
||||
exclude_ids = all_line_receivable_ids # 包含 covered_ids 和 payout_date 被过滤掉的
|
||||
|
||||
receivable_domain = [
|
||||
('due_date', '<', query_month_start),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('submitted', '>', 0),
|
||||
]
|
||||
if covered_ids:
|
||||
receivable_domain.append(('id', 'not in', covered_ids))
|
||||
if exclude_ids:
|
||||
receivable_domain.append(('id', 'not in', list(exclude_ids)))
|
||||
|
||||
# 同样的筛选条件(去掉 receivable_id. 前缀,直接查 accounts.receivable 自身字段)
|
||||
if keyword:
|
||||
|
||||
@@ -15,7 +15,7 @@ class ReceivableFlowReport(models.Model):
|
||||
- 仅考虑当前公司/日期范围内的应收记录
|
||||
"""
|
||||
domain = [
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
date_start = params.get("date_start")
|
||||
@@ -59,7 +59,7 @@ class ReceivableFlowReport(models.Model):
|
||||
- 包括基本信息、收款情况和违约金相关信息
|
||||
"""
|
||||
domain = [
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
date_start = params.get("date_start")
|
||||
@@ -112,7 +112,7 @@ class ReceivableFlowReport(models.Model):
|
||||
|
||||
penalty_receivables = self.env['property.accounts.receivable'].sudo().search([
|
||||
('contract_id', 'in', receivables.mapped('contract_id').ids),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('management_type_id.name', '=', '违约金'),
|
||||
])
|
||||
penalty_source_map = {}
|
||||
@@ -230,7 +230,7 @@ class ReceivableFlowReport(models.Model):
|
||||
'model': 'property.accounts.receivable',
|
||||
'display_name': str(round(contract_total_receivable, 2)),
|
||||
'view_mode': 'tree',
|
||||
'domain': [('contract_id', '=', contract.id if contract else 0), ('is_invalid', '=', False)],
|
||||
'domain': [('contract_id', '=', contract.id if contract else 0), ('is_invalid', '!=', True)],
|
||||
},
|
||||
"收款总金额": {
|
||||
'model': 'receivable.modify.line',
|
||||
|
||||
@@ -44,7 +44,7 @@ class YuthonProperty(models.Model):
|
||||
|
||||
@api.model
|
||||
def get_complete_ledger_report(self, params):
|
||||
domain = [('is_invalid', '=', False)]
|
||||
domain = [('is_invalid', '!=', True)]
|
||||
if params.get("keyword"):
|
||||
keyword = params["keyword"]
|
||||
domain += [
|
||||
|
||||
@@ -14,7 +14,7 @@ class TotalReceivedReport(models.Model):
|
||||
"""
|
||||
domain = [
|
||||
('reconciliation_date', '!=', False),
|
||||
('receivable_id.is_invalid', '=', False),
|
||||
('receivable_id.is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
# 收款日期在查询月内
|
||||
|
||||
@@ -296,7 +296,7 @@ class YuthonDashboard(models.Model):
|
||||
domain = [
|
||||
('due_date', '>=', month_first),
|
||||
('due_date', '<=', month_last),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('management_type_id.name', 'ilike', keyword_match),
|
||||
]
|
||||
if company_id:
|
||||
@@ -317,7 +317,7 @@ class YuthonDashboard(models.Model):
|
||||
year_domain = [
|
||||
('due_date', '>=', year_start),
|
||||
('due_date', '<=', month_last),
|
||||
('is_invalid', '=', False),
|
||||
('is_invalid', '!=', True),
|
||||
('management_type_id.name', 'ilike', keyword_match),
|
||||
]
|
||||
if company_id:
|
||||
|
||||
Reference in New Issue
Block a user