Merge branch 'master' into dev
This commit is contained in:
@@ -47,15 +47,21 @@ class CumulativeArrearsReport(models.Model):
|
||||
if management_type_id:
|
||||
domain.append(('management_type_id', '=', management_type_id))
|
||||
|
||||
receivables = self.search(domain, limit=3000, order="due_date asc")
|
||||
receivables = self.search(domain, order="due_date asc")
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_arrears = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
contract = rec.contract_id
|
||||
rent = contract.rent or rec.original_amount or 0.0
|
||||
arrears = rec.submitted or 0.0
|
||||
total_arrears += arrears
|
||||
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'arrears': 0.0}
|
||||
type_totals[type_name]['arrears'] += arrears
|
||||
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -70,19 +76,10 @@ class CumulativeArrearsReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"物业名称": False,
|
||||
"面积": False,
|
||||
"承租方名称": False,
|
||||
"合同编号": False,
|
||||
"月租金": False,
|
||||
"欠租金额": round(total_arrears, 2),
|
||||
"欠租所属月份": False,
|
||||
"所属公司": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['arrears'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_arrears, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -66,11 +66,13 @@ class CurrentReceivablePropertyFeeReport(models.Model):
|
||||
type_domain = domain[:]
|
||||
|
||||
# 先按类型+日期,再放宽日期,再放宽类型
|
||||
receivables = self.search(type_domain, limit=3000, order="due_date asc")
|
||||
receivables = self.search(type_domain, order="due_date asc")
|
||||
if not receivables and type_domain != domain:
|
||||
receivables = self.search(domain, limit=3000, order="due_date asc")
|
||||
receivables = self.search(domain, order="due_date asc")
|
||||
|
||||
rows = []
|
||||
# 按管理类型分组统计
|
||||
type_totals = {} # {'管理类型名称': {'amount': 0, 'amount_nt': 0}}
|
||||
total_amount = 0.0
|
||||
total_amount_nt = 0.0
|
||||
|
||||
@@ -80,6 +82,13 @@ class CurrentReceivablePropertyFeeReport(models.Model):
|
||||
amt_nt = amt / (1 + tax_rate / 100) if tax_rate else amt
|
||||
total_amount += amt
|
||||
total_amount_nt += amt_nt
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0, 'amount_nt': 0.0}
|
||||
type_totals[type_name]['amount'] += amt
|
||||
type_totals[type_name]['amount_nt'] += amt_nt
|
||||
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -94,19 +103,18 @@ class CurrentReceivablePropertyFeeReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"应收租期": False,
|
||||
"承租方名称": "合计:",
|
||||
"金额(含税)": round(total_amount, 2),
|
||||
"税率": False,
|
||||
"金额(不含税)": round(total_amount_nt, 2),
|
||||
"物业名称": False,
|
||||
"产权证": False,
|
||||
"合同编号": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
# 构造合计数据:将各分类合计作为独立的统计数据返回
|
||||
summary_stats = []
|
||||
# 按管理类型名称排序
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
totals = type_totals[type_name]
|
||||
summary_stats.append({
|
||||
'name': type_name,
|
||||
'amount': round(totals['amount'], 2),
|
||||
'amount_nt': round(totals['amount_nt'], 2)
|
||||
})
|
||||
# 添加总合计卡片
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2), 'amount_nt': round(total_amount_nt, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -105,25 +105,17 @@ class CurrentReceivableRentReport(models.Model):
|
||||
'amount': round(totals['amount'], 2),
|
||||
'amount_nt': round(totals['amount_nt'], 2)
|
||||
})
|
||||
|
||||
# 添加总合计卡片
|
||||
summary_stats.append({
|
||||
'name': '总合计',
|
||||
'amount': round(total_all_amount, 2),
|
||||
'amount_nt': round(total_all_amount_nt, 2)
|
||||
})
|
||||
|
||||
# 返回字典格式,包含数据行、简化的表格合计行、独立的统计卡片数据
|
||||
# 返回字典格式,只包含数据行和统计卡片数据
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": "",
|
||||
"应收开始": "",
|
||||
"应收结束": "",
|
||||
"承租方名称": "总合计:",
|
||||
"原始金额": "",
|
||||
"减免金额": "",
|
||||
"实际金额(含税)": round(total_all_amount, 2),
|
||||
"税率": "",
|
||||
"实际金额(不含税)": round(total_all_amount_nt, 2),
|
||||
"物业名称": "",
|
||||
"产权证": "",
|
||||
"合同编号": "",
|
||||
"管理员": "",
|
||||
},
|
||||
"stats": summary_stats # 新增统计卡片数据
|
||||
"stats": summary_stats
|
||||
}
|
||||
|
||||
|
||||
@@ -45,16 +45,24 @@ class DepositTotalReport(models.Model):
|
||||
else:
|
||||
type_domain = domain[:]
|
||||
|
||||
receivables = self.search(type_domain, limit=3000, order="due_date asc")
|
||||
receivables = self.search(type_domain, order="due_date asc")
|
||||
if not receivables and type_domain != domain:
|
||||
receivables = self.search(domain, limit=3000, order="due_date asc")
|
||||
receivables = self.search(domain, order="due_date asc")
|
||||
|
||||
rows = []
|
||||
# 按管理类型分组统计
|
||||
type_totals = {} # {'管理类型名称': {'amount': 0}}
|
||||
total_amount = 0.0
|
||||
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": rec.contract_id.contract_code if rec.contract_id else "",
|
||||
@@ -65,16 +73,17 @@ class DepositTotalReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"合同编号": False,
|
||||
"物业名称": False,
|
||||
"承租方名称": "合计:",
|
||||
"金额": round(total_amount, 2),
|
||||
"所属公司": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
# 构造合计数据:将各分类合计作为独立的统计数据返回
|
||||
summary_stats = []
|
||||
# 按管理类型名称排序
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
totals = type_totals[type_name]
|
||||
summary_stats.append({
|
||||
'name': type_name,
|
||||
'amount': round(totals['amount'], 2),
|
||||
})
|
||||
# 添加总合计卡片
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -72,17 +72,22 @@ class MonthlyAssessmentFeeReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -95,17 +100,10 @@ class MonthlyAssessmentFeeReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"日期": False,
|
||||
"物业名称": False,
|
||||
"金额": round(total_amount, 2),
|
||||
"备注": False,
|
||||
"所属公司": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -72,17 +72,22 @@ class MonthlyMaintenanceFeeReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -95,17 +100,10 @@ class MonthlyMaintenanceFeeReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"日期": False,
|
||||
"物业名称": False,
|
||||
"金额": round(total_amount, 2),
|
||||
"备注": False,
|
||||
"所属公司": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -73,17 +73,25 @@ class MonthlyManagementFeeReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
# 按管理类型分组统计
|
||||
type_totals = {} # {'管理类型名称': {'amount': 0}}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -96,17 +104,12 @@ class MonthlyManagementFeeReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"日期": False,
|
||||
"物业名称": False,
|
||||
"金额": round(total_amount, 2),
|
||||
"备注": False,
|
||||
"所属公司": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
# 构造合计数据
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
totals = type_totals[type_name]
|
||||
summary_stats.append({'name': type_name, 'amount': round(totals['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -72,17 +72,22 @@ class MonthlyOtherExpenseReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -95,17 +100,10 @@ class MonthlyOtherExpenseReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"日期": False,
|
||||
"物业名称": False,
|
||||
"金额": round(total_amount, 2),
|
||||
"备注": False,
|
||||
"所属公司": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -32,8 +32,9 @@ class OverdueAmountReport(models.Model):
|
||||
if management_type_id:
|
||||
domain.append(('management_type_id', '=', management_type_id))
|
||||
|
||||
receivables = self.search(domain, limit=1000)
|
||||
receivables = self.search(domain)
|
||||
sum_dict = {}
|
||||
type_totals = {}
|
||||
|
||||
for rec in receivables:
|
||||
# 提取基础数据
|
||||
@@ -44,9 +45,15 @@ class OverdueAmountReport(models.Model):
|
||||
rent = round(rec.contract_id.rent, 2) if (rec.contract_id and rec.contract_id.rent) else 0.0
|
||||
submitted = round(rec.submitted, 2) if rec.submitted else 0.0
|
||||
due_month = rec.due_date.strftime("%Y-%m-%d") if rec.due_date else ""
|
||||
management_type_id = rec.management_type_id.name
|
||||
lessor_referred = rec.contract_id.lessor_id.referred
|
||||
admin_name = rec.contract_id.admin_id.name
|
||||
management_type_id = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
lessor_referred = rec.contract_id.lessor_id.referred if rec.contract_id and rec.contract_id.lessor_id and hasattr(rec.contract_id.lessor_id, 'referred') else rec.contract_id.lessor_id.name if rec.contract_id and rec.contract_id.lessor_id else ""
|
||||
admin_name = rec.contract_id.admin_id.name if rec.contract_id and rec.contract_id.admin_id else ""
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
if management_type_id not in type_totals:
|
||||
type_totals[management_type_id] = {'amount': 0.0, 'arrears': 0.0}
|
||||
type_totals[management_type_id]['amount'] += rent
|
||||
type_totals[management_type_id]['arrears'] += submitted
|
||||
|
||||
# 构建唯一标识key(合同编号 + 欠费日期)
|
||||
key = (contract_code, due_month)
|
||||
@@ -67,7 +74,23 @@ class OverdueAmountReport(models.Model):
|
||||
"管理员": admin_name
|
||||
}
|
||||
|
||||
return list(sum_dict.values())
|
||||
rows = []
|
||||
total_amount = 0.0
|
||||
total_arrears = 0.0
|
||||
for idx, item in enumerate(sum_dict.values(), start=1):
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
**item
|
||||
})
|
||||
total_amount += item["金额"]
|
||||
total_arrears += item["欠费金额"]
|
||||
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['arrears'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_arrears, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
@api.model
|
||||
def get_domain(self, start_date=False, end_date=False, company_id=False):
|
||||
|
||||
@@ -60,11 +60,13 @@ class PenaltyDetailReport(models.Model):
|
||||
date_domain = ['|', ('due_date', '<=', end_dt), ('payout_date', '<=', end_dt)]
|
||||
|
||||
# 先按日期过滤查,如果无结果且传了日期,则去掉日期过滤再查一遍,避免漏数据
|
||||
receivables = self.search(domain + date_domain, limit=2000, order="due_date asc")
|
||||
receivables = self.search(domain + date_domain, order="due_date asc")
|
||||
if not receivables and date_domain:
|
||||
receivables = self.search(domain, limit=2000, order="due_date asc")
|
||||
receivables = self.search(domain, order="due_date asc")
|
||||
|
||||
rows = []
|
||||
# 按管理类型分组统计
|
||||
type_totals = {} # {'管理类型名称': {...}}
|
||||
total_amount = total_penalty = total_owed = total_collected = total_uncollected = 0.0
|
||||
total_per_day = 0.0
|
||||
|
||||
@@ -85,6 +87,20 @@ class PenaltyDetailReport(models.Model):
|
||||
total_collected += collected
|
||||
total_uncollected += uncollected
|
||||
total_per_day += per_day
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {
|
||||
'amount': 0.0, 'penalty': 0.0, 'owed': 0.0,
|
||||
'collected': 0.0, 'uncollected': 0.0, 'per_day': 0.0
|
||||
}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
type_totals[type_name]['penalty'] += penalty_amount
|
||||
type_totals[type_name]['owed'] += rent_owed
|
||||
type_totals[type_name]['collected'] += collected
|
||||
type_totals[type_name]['uncollected'] += uncollected
|
||||
type_totals[type_name]['per_day'] += per_day
|
||||
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -105,25 +121,22 @@ class PenaltyDetailReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"合同编号": "合计",
|
||||
"物业名称": False,
|
||||
"承租方名称": False,
|
||||
"金额": round(total_amount, 2),
|
||||
"违约金计费时间(天)": False,
|
||||
"欠租金额": round(total_owed, 2),
|
||||
"每天违约金(元/天)": round(total_per_day, 2),
|
||||
"违约金金额": round(total_penalty, 2),
|
||||
"总已收金额": round(total_collected, 2),
|
||||
"总未收金额": round(total_uncollected, 2),
|
||||
"当月收款时间": False,
|
||||
"当月收款金额": round(total_collected, 2),
|
||||
"所属公司": False,
|
||||
"产权证号": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
# 构造合计数据:将各分类合计作为独立的统计数据返回
|
||||
summary_stats = []
|
||||
# 按管理类型名称排序
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
totals = type_totals[type_name]
|
||||
summary_stats.append({
|
||||
'name': type_name,
|
||||
'amount': round(totals['amount'], 2),
|
||||
'penalty': round(totals['penalty'], 2),
|
||||
})
|
||||
# 添加总合计卡片
|
||||
summary_stats.append({
|
||||
'name': '总合计',
|
||||
'amount': round(total_owed, 2),
|
||||
'penalty': round(total_penalty, 2)
|
||||
})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -38,28 +38,46 @@ class YuthonProperty(models.Model):
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
|
||||
print(domain)
|
||||
receivables = self.search(domain, limit=1000)
|
||||
receivables = self.search(domain)
|
||||
management_type_map = dict(
|
||||
self.env['yuthon.management.type'].search([]).mapped(lambda r: (r.id, r.name))
|
||||
)
|
||||
invoice_type_map = dict(
|
||||
self._fields['invoice_type']._description_selection(self.env)
|
||||
)
|
||||
return [
|
||||
{
|
||||
"应收类型": management_type_map.get(rec.management_type_id.id, "") if rec.management_type_id else "",
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_amount = 0.0
|
||||
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
mgmt_type = management_type_map.get(rec.management_type_id.id, "") if rec.management_type_id else "未分类"
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
|
||||
if mgmt_type not in type_totals:
|
||||
type_totals[mgmt_type] = {'amount': 0.0}
|
||||
type_totals[mgmt_type]['amount'] += amount
|
||||
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"应收类型": mgmt_type,
|
||||
"应收开始": rec.due_date.strftime("%Y-%m-%d") if rec.due_date else "",
|
||||
"应收结束": rec.due_date_end.strftime("%Y-%m-%d") if rec.due_date_end else "",
|
||||
"承租方": rec.lessee_id.name or "" if rec.lessee_id else "",
|
||||
"当期金额": rec.original_amount or 0.0,
|
||||
"当期金额": round(amount, 2),
|
||||
"物业名称": rec.property_name or "",
|
||||
"产权证号": rec.title_deed or "",
|
||||
"发票类型": invoice_type_map.get(rec.invoice_type, ""),
|
||||
"税率": f"{rec.tax}%" if rec.tax else "0%"
|
||||
}
|
||||
for rec in receivables
|
||||
]
|
||||
})
|
||||
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
@api.model
|
||||
def get_domain(self, start_date=False, end_date=False, company_id=False):
|
||||
|
||||
@@ -68,17 +68,22 @@ class YearlyAssessmentFeeReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -91,17 +96,10 @@ class YearlyAssessmentFeeReport(models.Model):
|
||||
"备注": rec.remark or "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"日期": False,
|
||||
"物业名称": False,
|
||||
"管理员": "合计:",
|
||||
"金额": round(total_amount, 2),
|
||||
"所属公司": False,
|
||||
"备注": False,
|
||||
}
|
||||
}
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -68,17 +68,22 @@ class YearlyMaintenanceFeeReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -91,17 +96,10 @@ class YearlyMaintenanceFeeReport(models.Model):
|
||||
"备注": rec.remark or "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"支出日期": False,
|
||||
"物业名称": False,
|
||||
"管理员": "合计:",
|
||||
"金额": round(total_amount, 2),
|
||||
"所属公司": False,
|
||||
"备注": False,
|
||||
}
|
||||
}
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -70,17 +70,25 @@ class YearlyManagementFeeReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=2000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
# 按管理类型分组统计
|
||||
type_totals = {} # {'管理类型名称': {'amount': 0}}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -93,17 +101,12 @@ class YearlyManagementFeeReport(models.Model):
|
||||
"备注": rec.remark or "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"支出日期": False,
|
||||
"物业名称": False,
|
||||
"管理员": "合计:",
|
||||
"金额": round(total_amount, 2),
|
||||
"所属公司": False,
|
||||
"备注": False,
|
||||
}
|
||||
}
|
||||
# 构造合计数据
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
totals = type_totals[type_name]
|
||||
summary_stats.append({'name': type_name, 'amount': round(totals['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -68,17 +68,22 @@ class YearlyOtherFeeReport(models.Model):
|
||||
else:
|
||||
type_domain = base_domain[:]
|
||||
|
||||
receivables = self.search(type_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(type_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain + date_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain + date_domain, order="payout_date asc, due_date asc")
|
||||
if not receivables and type_domain != base_domain:
|
||||
receivables = self.search(base_domain, limit=3000, order="payout_date asc, due_date asc")
|
||||
receivables = self.search(base_domain, order="payout_date asc, due_date asc")
|
||||
|
||||
rows = []
|
||||
type_totals = {}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
pay_date = rec.payout_date or rec.due_date
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
@@ -91,17 +96,10 @@ class YearlyOtherFeeReport(models.Model):
|
||||
"备注": rec.remark or "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"编码": False,
|
||||
"支出日期": False,
|
||||
"物业名称": False,
|
||||
"管理员": "合计:",
|
||||
"金额": round(total_amount, 2),
|
||||
"所属公司": False,
|
||||
"备注": False,
|
||||
}
|
||||
}
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
summary_stats.append({'name': type_name, 'amount': round(type_totals[type_name]['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -62,10 +62,18 @@ class YearlyPenaltyReport(models.Model):
|
||||
receivables = self.search(domain, order="due_date asc")
|
||||
|
||||
rows = []
|
||||
# 按管理类型分组统计
|
||||
type_totals = {} # {'管理类型名称': {'amount': 0}}
|
||||
total_amount = 0.0
|
||||
for idx, rec in enumerate(receivables, start=1):
|
||||
amount = rec.penalty or rec.submitted or rec.original_amount or 0.0
|
||||
total_amount += amount
|
||||
|
||||
# 统计每个管理类型的合计
|
||||
type_name = rec.management_type_id.name if rec.management_type_id else "未分类"
|
||||
if type_name not in type_totals:
|
||||
type_totals[type_name] = {'amount': 0.0}
|
||||
type_totals[type_name]['amount'] += amount
|
||||
rows.append({
|
||||
"序号": idx,
|
||||
"合同编号": rec.contract_id.contract_code if rec.contract_id else "",
|
||||
@@ -76,16 +84,12 @@ class YearlyPenaltyReport(models.Model):
|
||||
"管理员": rec.admin_id.name if rec.admin_id else "",
|
||||
})
|
||||
|
||||
return {
|
||||
"rows": rows,
|
||||
"summary": {
|
||||
"序号": False,
|
||||
"合同编号": False,
|
||||
"物业名称": False,
|
||||
"承租方名称": "合计:",
|
||||
"金额": round(total_amount, 2),
|
||||
"所属公司": False,
|
||||
"管理员": False,
|
||||
}
|
||||
}
|
||||
# 构造合计数据
|
||||
summary_stats = []
|
||||
for type_name in sorted(type_totals.keys()):
|
||||
totals = type_totals[type_name]
|
||||
summary_stats.append({'name': type_name, 'amount': round(totals['amount'], 2)})
|
||||
summary_stats.append({'name': '总合计', 'amount': round(total_amount, 2)})
|
||||
|
||||
return {"rows": rows, "stats": summary_stats}
|
||||
|
||||
|
||||
@@ -226,19 +226,21 @@ class ReceivableReport extends Component {
|
||||
);
|
||||
console.log(result)
|
||||
|
||||
// 处理返回的数据结构,支持固定底部合计行
|
||||
if (result && typeof result === 'object' && result.rows && result.summary) {
|
||||
// 新格式:分离数据行和合计行
|
||||
this.grid.setGridOption('rowData', result.rows);
|
||||
// summary可能是单个对象或数组
|
||||
const summaryData = Array.isArray(result.summary) ? result.summary : [result.summary];
|
||||
this.grid.setGridOption('pinnedBottomRowData', summaryData);
|
||||
// 更新统计卡片数据
|
||||
this.state.stats = result.stats || [];
|
||||
} else {
|
||||
// 兼容旧格式:数组
|
||||
this.grid.setGridOption('rowData', result);
|
||||
this.state.stats = [];
|
||||
// 处理返回的数据结构
|
||||
if (result && typeof result === 'object') {
|
||||
if (result.rows) {
|
||||
// 新格式:分离数据行和统计数据
|
||||
this.grid.setGridOption('rowData', result.rows);
|
||||
// 取消固定底部合计行
|
||||
this.grid.setGridOption('pinnedBottomRowData', []);
|
||||
// 更新统计卡片数据
|
||||
this.state.stats = result.stats || [];
|
||||
} else {
|
||||
// 兼容旧格式:直接是数组
|
||||
this.grid.setGridOption('rowData', result);
|
||||
this.grid.setGridOption('pinnedBottomRowData', []);
|
||||
this.state.stats = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user