报表
This commit is contained in:
@@ -75,6 +75,8 @@
|
||||
'yuthon_report/static/src/components/yuthon_report/receivable_message.xml',
|
||||
'yuthon_report/static/src/components/yuthon_report/yuthon_report.scss',
|
||||
'yuthon_report/static/src/components/yuthon_report/receivable_report.js',
|
||||
'yuthon_report/static/src/components/yuthon_report/multi_select_autocomplete.js',
|
||||
'yuthon_report/static/src/components/yuthon_report/multi_select_autocomplete.xml',
|
||||
'yuthon_report/static/src/components/yuthon_report/receivable_report.xml',
|
||||
'yuthon_report/static/src/components/yuthon_report/receivable_flow_report.js',
|
||||
'yuthon_report/static/src/components/yuthon_report/text_summary_report.js',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import report_utils
|
||||
from . import res_partner
|
||||
from . import ledger_report
|
||||
from . import receivable_report
|
||||
|
||||
@@ -3,6 +3,7 @@ import calendar
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -55,14 +56,14 @@ class PropertyBillsList(models.Model):
|
||||
]
|
||||
|
||||
# 公司/片区过滤
|
||||
company_id = params.get('company_id')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
if company_id:
|
||||
domain.append(('lessor_id', '=', int(company_id)))
|
||||
domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id), # 合同片区过滤(多选支持)
|
||||
('receivables_id.precinct_id', 'in', partner_id), # 应收记录片区过滤(多选支持)
|
||||
]
|
||||
|
||||
# 查询记录
|
||||
|
||||
@@ -3,6 +3,7 @@ import calendar
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -55,14 +56,14 @@ class PropertyBillsList(models.Model):
|
||||
]
|
||||
|
||||
# 公司/片区过滤
|
||||
company_id = params.get('company_id')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
if company_id:
|
||||
domain.append(('lessor_id', '=', int(company_id)))
|
||||
domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id), # 合同片区过滤(多选支持)
|
||||
('receivables_id.precinct_id', 'in', partner_id), # 应收记录片区过滤(多选支持)
|
||||
]
|
||||
|
||||
# 查询记录
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import datetime
|
||||
|
||||
from .report_utils import _id_list
|
||||
from odoo import fields, models, api
|
||||
|
||||
|
||||
@@ -16,7 +17,7 @@ class AttendanceReport(models.Model):
|
||||
vacation_domain.append(("vacation_date", "<=", date_end))
|
||||
salary_group_id = params.get('structure_id', False)
|
||||
department_id = params.get('department_id', False)
|
||||
company_id = params.get('company_id', False)
|
||||
company_id = _id_list(params.get('company_id', False))
|
||||
|
||||
employee_domain = []
|
||||
if salary_group_id:
|
||||
@@ -24,7 +25,7 @@ class AttendanceReport(models.Model):
|
||||
if department_id:
|
||||
employee_domain.append(('department_id', '=', department_id))
|
||||
if company_id:
|
||||
employee_domain.append(('company_id', '=', company_id))
|
||||
employee_domain.append(('company_id', 'in', company_id))
|
||||
|
||||
employee_ids = []
|
||||
if employee_domain:
|
||||
@@ -146,11 +147,13 @@ class AttendanceReport(models.Model):
|
||||
|
||||
@api.model
|
||||
def get_domain(self, company_id=False):
|
||||
if not company_id:
|
||||
# 多选:company_id 标准化为列表
|
||||
cid_list = _id_list(company_id)
|
||||
if not cid_list:
|
||||
return [], []
|
||||
|
||||
department_records = self.env['hr.department'].search([('company_id', '=', company_id)])
|
||||
department_records = self.env['hr.department'].search([('company_id', 'in', cid_list)])
|
||||
department_ids = [dept.id for dept in department_records]
|
||||
salary_group_records = self.env['yuthon.salary.group'].search([('company_id', '=', company_id)])
|
||||
salary_group_records = self.env['yuthon.salary.group'].search([('company_id', 'in', cid_list)])
|
||||
salary_group_ids = [struct.id for struct in salary_group_records]
|
||||
return department_ids, salary_group_ids
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from .report_utils import _id_list
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
@@ -23,9 +24,9 @@ class BankStatementsReport(models.Model):
|
||||
domain.append(('lending_direction', '=', 'loan'))
|
||||
|
||||
# 公司搜索条件
|
||||
company_id = params.get('company_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
# 账号单位搜索条件
|
||||
your_own_unit = params.get('your_own_unit')
|
||||
|
||||
@@ -2,6 +2,7 @@ import calendar
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class CumArrearsReport(models.Model):
|
||||
@@ -50,8 +51,8 @@ class CumArrearsReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -60,9 +61,9 @@ class CumArrearsReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('receivable_id.property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import calendar
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class CumIncomeReport(models.Model):
|
||||
@@ -52,16 +53,16 @@ class CumIncomeReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if management_type_id:
|
||||
domain.append(('receivable_id.management_type_id', '=', management_type_id))
|
||||
else:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class CurrentMonthReceivedReport(models.Model):
|
||||
@@ -39,8 +40,8 @@ class CurrentMonthReceivedReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -49,9 +50,9 @@ class CurrentMonthReceivedReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('receivable_id.property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class CurrentReceivablePropertyFeeReport(models.Model):
|
||||
@@ -36,16 +37,16 @@ class CurrentReceivablePropertyFeeReport(models.Model):
|
||||
domain.append(("due_date", "<=", end_dt))
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
if management_type_id:
|
||||
domain.append(('management_type_id', '=', management_type_id))
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class DepositCumArrearsReport(models.Model):
|
||||
@@ -49,17 +50,17 @@ class DepositCumArrearsReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
@@ -142,13 +143,13 @@ class DepositCumArrearsReport(models.Model):
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
company_id = params.get('company_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class DepositMonthReceivableReport(models.Model):
|
||||
@@ -39,14 +40,14 @@ class DepositMonthReceivableReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
lines = self.sudo().search(domain, order="contract_id asc")
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class DepositMonthReceivedReport(models.Model):
|
||||
@@ -44,17 +45,17 @@ class DepositMonthReceivedReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
@@ -141,13 +142,13 @@ class DepositMonthReceivedReport(models.Model):
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
company_id = params.get('company_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class DepositMonthRefundReport(models.Model):
|
||||
@@ -42,8 +43,8 @@ class DepositMonthRefundReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -51,9 +52,9 @@ class DepositMonthRefundReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class DepositPreReceivedReport(models.Model):
|
||||
@@ -44,17 +45,17 @@ class DepositPreReceivedReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
@@ -157,13 +158,13 @@ class DepositPreReceivedReport(models.Model):
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
company_id = params.get('company_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class DepositTotalReport(models.Model):
|
||||
@@ -59,8 +60,8 @@ class DepositTotalReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -68,9 +69,9 @@ class DepositTotalReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -3,6 +3,7 @@ import datetime
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -41,8 +42,8 @@ class LeasedAreaReport(models.Model):
|
||||
|
||||
keyword = params.get("keyword")
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
# 前端侧边栏下拉选择器传入的 ID
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -202,7 +203,7 @@ class LeasedAreaReport(models.Model):
|
||||
matched = False
|
||||
for cl in lines:
|
||||
ml = manage_map.get(cl.address_id.id) if cl.address_id else None
|
||||
if ml and ml.precinct_id and ml.precinct_id.id == int(partner_id):
|
||||
if ml and ml.precinct_id and ml.precinct_id.id in partner_id: # 片区匹配(多选支持)
|
||||
matched = True
|
||||
break
|
||||
if not matched:
|
||||
@@ -211,7 +212,7 @@ class LeasedAreaReport(models.Model):
|
||||
matched = False
|
||||
for cl in lines:
|
||||
ml = manage_map.get(cl.address_id.id) if cl.address_id else None
|
||||
if ml and ml.company_id and ml.company_id.id == int(company_id):
|
||||
if ml and ml.company_id and ml.company_id.id in company_id:
|
||||
matched = True
|
||||
break
|
||||
if not matched:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import fields, models, api
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class YuthonProperty(models.Model):
|
||||
@@ -32,16 +33,16 @@ class YuthonProperty(models.Model):
|
||||
|
||||
# 基础过滤条件
|
||||
condition = params.get('condition', False)
|
||||
partner_id = params.get('partner_id', False)
|
||||
company_id = params.get('company_id', False)
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id', False))
|
||||
|
||||
domain = []
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
properties = self.search(domain, limit=500)
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import calendar
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -55,14 +56,14 @@ class PropertyBillsList(models.Model):
|
||||
]
|
||||
|
||||
# 公司/片区过滤
|
||||
company_id = params.get('company_id')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
if company_id:
|
||||
domain.append(('lessor_id', '=', int(company_id)))
|
||||
domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id), # 合同片区过滤(多选支持)
|
||||
('receivables_id.precinct_id', 'in', partner_id), # 应收记录片区过滤(多选支持)
|
||||
]
|
||||
|
||||
# 查询记录
|
||||
|
||||
@@ -3,6 +3,7 @@ import calendar
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -55,14 +56,14 @@ class PropertyBillsList(models.Model):
|
||||
]
|
||||
|
||||
# 公司/片区过滤
|
||||
company_id = params.get('company_id')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
if company_id:
|
||||
domain.append(('lessor_id', '=', int(company_id)))
|
||||
domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id), # 合同片区过滤(多选支持)
|
||||
('receivables_id.precinct_id', 'in', partner_id), # 应收记录片区过滤(多选支持)
|
||||
]
|
||||
|
||||
# 查询记录
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -33,8 +34,8 @@ class ManagementAreaReport(models.Model):
|
||||
|
||||
keyword = params.get("keyword")
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
# 前端侧边栏下拉选择器传入的 ID
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -65,9 +66,9 @@ class ManagementAreaReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
# 物业名称下拉选择器:直接过滤 yuthon_property_id
|
||||
if property_id:
|
||||
domain.append(('yuthon_property_id', '=', int(property_id)))
|
||||
|
||||
@@ -3,6 +3,7 @@ import calendar
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -55,14 +56,14 @@ class PropertyBillsList(models.Model):
|
||||
]
|
||||
|
||||
# 公司/片区过滤
|
||||
company_id = params.get('company_id')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
if company_id:
|
||||
domain.append(('lessor_id', '=', int(company_id)))
|
||||
domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id), # 合同片区过滤(多选支持)
|
||||
('receivables_id.precinct_id', 'in', partner_id), # 应收记录片区过滤(多选支持)
|
||||
]
|
||||
|
||||
# 查询记录
|
||||
|
||||
@@ -3,6 +3,7 @@ import calendar
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -55,14 +56,14 @@ class PropertyBillsList(models.Model):
|
||||
]
|
||||
|
||||
# 公司/片区过滤
|
||||
company_id = params.get('company_id')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
if company_id:
|
||||
domain.append(('lessor_id', '=', int(company_id)))
|
||||
domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id), # 合同片区过滤(多选支持)
|
||||
('receivables_id.precinct_id', 'in', partner_id), # 应收记录片区过滤(多选支持)
|
||||
]
|
||||
|
||||
# 查询记录
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class MonthReceivableReport(models.Model):
|
||||
@@ -38,8 +39,8 @@ class MonthReceivableReport(models.Model):
|
||||
('receivable_id.contract_id.contract_code', 'ilike', keyword)]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -48,9 +49,9 @@ class MonthReceivableReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('receivable_id.property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class MonthlyPrecollectionReport(models.Model):
|
||||
@@ -43,8 +44,8 @@ class MonthlyPrecollectionReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -53,9 +54,9 @@ class MonthlyPrecollectionReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('receivable_id.property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class ParkingFeeCurrentMonthReceivable(models.Model):
|
||||
@@ -46,16 +47,16 @@ class ParkingFeeCurrentMonthReceivable(models.Model):
|
||||
|
||||
# 其他过滤
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
# 管理类型
|
||||
if management_type_id:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class ParkingFeeCurrentMonthReport(models.Model):
|
||||
@@ -41,16 +42,16 @@ class ParkingFeeCurrentMonthReport(models.Model):
|
||||
end_dt = datetime.datetime.fromisoformat(date_end).date() if date_end else month_end
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
# 管理类型
|
||||
if management_type_id:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
|
||||
class ParkingFeeYearlyReport(models.Model):
|
||||
@@ -42,16 +43,16 @@ class ParkingFeeYearlyReport(models.Model):
|
||||
|
||||
# 过滤条件
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
if management_type_id:
|
||||
domain.append(('management_type_id', '=', management_type_id))
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime # 日期时间处理模块,用于日期解析、计算、格
|
||||
import logging # 日志模块,用于调试输出
|
||||
|
||||
from odoo import api, models # Odoo 核心 API:api 装饰器、models 模型基类
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__) # 获取当前模块的日志记录器
|
||||
|
||||
@@ -42,8 +43,8 @@ class PenaltyArrearsReport(models.Model):
|
||||
# ========== 二、构建公共筛选条件 ==========
|
||||
keyword = params.get("keyword") # 关键字搜索
|
||||
condition = params.get('condition') # 租赁类型
|
||||
partner_id = params.get('partner_id') # 片区 ID
|
||||
company_id = params.get('company_id') # 公司 ID
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
company_id = _id_list(params.get('company_id')) # 公司 ID
|
||||
property_id = params.get('property_id') # 物业 ID
|
||||
lessee_id = params.get('lessee_id') # 承租方 ID
|
||||
contract_id = params.get('contract_id') # 合同 ID
|
||||
@@ -64,9 +65,9 @@ class PenaltyArrearsReport(models.Model):
|
||||
return False
|
||||
if condition and rec.tenure_type != condition:
|
||||
return False
|
||||
if partner_id and rec.precinct_id.id != int(partner_id):
|
||||
if partner_id and rec.precinct_id.id not in partner_id: # 片区过滤(多选支持)
|
||||
return False
|
||||
if company_id and rec.company_id.id != int(company_id):
|
||||
if company_id and rec.company_id.id not in company_id:
|
||||
return False
|
||||
if property_id and int(property_id) not in (rec.property_ids.ids or []):
|
||||
return False
|
||||
|
||||
@@ -3,6 +3,7 @@ import logging # 日志模块,用于调试输出
|
||||
import re # 正则表达式模块,用于解析收费区间字符串
|
||||
|
||||
from odoo import api, models # Odoo 核心 API:api 装饰器、models 模型基类
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__) # 获取当前模块的日志记录器
|
||||
|
||||
@@ -42,8 +43,8 @@ class PenaltyMonthReceivedReport(models.Model):
|
||||
# 其他筛选条件参数
|
||||
keyword = params.get("keyword")
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
@@ -64,9 +65,9 @@ class PenaltyMonthReceivedReport(models.Model):
|
||||
return False
|
||||
if condition and rec.tenure_type != condition:
|
||||
return False
|
||||
if partner_id and rec.precinct_id.id != int(partner_id):
|
||||
if partner_id and rec.precinct_id.id not in partner_id: # 片区过滤(多选支持)
|
||||
return False
|
||||
if company_id and rec.company_id.id != int(company_id):
|
||||
if company_id and rec.company_id.id not in company_id:
|
||||
return False
|
||||
if property_id and int(property_id) not in (rec.property_ids.ids or []):
|
||||
return False
|
||||
@@ -90,9 +91,9 @@ class PenaltyMonthReceivedReport(models.Model):
|
||||
match = True
|
||||
if not match:
|
||||
return False
|
||||
if partner_id and ml.precinct_id and ml.precinct_id.id != int(partner_id):
|
||||
if partner_id and ml.precinct_id and ml.precinct_id.id not in partner_id: # modify.line 片区过滤(多选支持)
|
||||
return False
|
||||
if company_id and ml.company_id and ml.company_id.id != int(company_id):
|
||||
if company_id and ml.company_id and ml.company_id.id not in company_id:
|
||||
return False
|
||||
if lessee_id and (not ml.lessee_id or ml.lessee_id.id != int(lessee_id)):
|
||||
return False
|
||||
|
||||
@@ -3,6 +3,7 @@ import logging # 日志模块,用于调试输出
|
||||
import re # 正则表达式模块,用于解析收费区间字符串
|
||||
|
||||
from odoo import api, models # Odoo 核心 API:api 装饰器、models 模型基类
|
||||
from .report_utils import _id_list # 导入 ID 列表解析工具函数,支持多选参数
|
||||
|
||||
_logger = logging.getLogger(__name__) # 获取当前模块的日志记录器
|
||||
|
||||
@@ -44,8 +45,8 @@ class PenaltyYearCumReport(models.Model):
|
||||
# 其他筛选条件参数
|
||||
keyword = params.get("keyword")
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 解析片区 ID 为整数列表(多选支持)
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
@@ -66,9 +67,9 @@ class PenaltyYearCumReport(models.Model):
|
||||
return False
|
||||
if condition and rec.tenure_type != condition:
|
||||
return False
|
||||
if partner_id and rec.precinct_id.id != int(partner_id):
|
||||
if partner_id and rec.precinct_id.id not in partner_id: # 片区过滤(多选支持)
|
||||
return False
|
||||
if company_id and rec.company_id.id != int(company_id):
|
||||
if company_id and rec.company_id.id not in company_id:
|
||||
return False
|
||||
if property_id and int(property_id) not in (rec.property_ids.ids or []):
|
||||
return False
|
||||
@@ -92,9 +93,9 @@ class PenaltyYearCumReport(models.Model):
|
||||
match = True
|
||||
if not match:
|
||||
return False
|
||||
if partner_id and ml.precinct_id and ml.precinct_id.id != int(partner_id):
|
||||
if partner_id and ml.precinct_id and ml.precinct_id.id not in partner_id: # modify.line 片区过滤(多选支持)
|
||||
return False
|
||||
if company_id and ml.company_id and ml.company_id.id != int(company_id):
|
||||
if company_id and ml.company_id and ml.company_id.id not in company_id:
|
||||
return False
|
||||
if lessee_id and (not ml.lessee_id or ml.lessee_id.id != int(lessee_id)):
|
||||
return False
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class PreAdvanceReport(models.Model):
|
||||
@@ -50,8 +51,8 @@ class PreAdvanceReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -60,9 +61,9 @@ class PreAdvanceReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('receivable_id.property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -40,8 +41,9 @@ class PreArrearsReport(models.Model):
|
||||
# 提取筛选参数
|
||||
keyword = params.get("keyword")
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
# 多选标准化:partner_id 统一为列表
|
||||
partner_id = _id_list(params.get('partner_id'))
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -67,9 +69,10 @@ class PreArrearsReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
# 多选:片区管理员用 'in' 操作符
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id))
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('receivable_id.property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
@@ -151,9 +154,10 @@ class PreArrearsReport(models.Model):
|
||||
if condition:
|
||||
receivable_domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
receivable_domain.append(('precinct_id', '=', partner_id))
|
||||
# 多选:片区管理员用 'in' 操作符
|
||||
receivable_domain.append(('precinct_id', 'in', partner_id))
|
||||
if company_id:
|
||||
receivable_domain.append(('company_id', '=', company_id))
|
||||
receivable_domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
receivable_domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import re
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class ReceivableFlowReport(models.Model):
|
||||
@@ -20,13 +21,13 @@ class ReceivableFlowReport(models.Model):
|
||||
('is_invalid', '!=', True),
|
||||
]
|
||||
|
||||
company_id = params.get('company_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
@@ -74,8 +75,8 @@ class ReceivableFlowReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
contract_id = params.get('contract_id')
|
||||
@@ -83,9 +84,9 @@ class ReceivableFlowReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
if property_id:
|
||||
domain.append(('property_ids', 'in', [property_id]))
|
||||
if lessee_id:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from odoo import fields, models, api
|
||||
from .report_utils import _id_list # 导入工具函数:将参数转换为列表格式,支持多选筛选
|
||||
|
||||
|
||||
class YuthonProperty(models.Model):
|
||||
@@ -63,15 +64,15 @@ class YuthonProperty(models.Model):
|
||||
domain.append(("due_date", "<=", date_end))
|
||||
|
||||
condition = params.get('condition', False)
|
||||
partner_id = params.get('partner_id', False)
|
||||
company_id = params.get('company_id', False)
|
||||
partner_id = _id_list(params.get('partner_id', False)) # 将partner_id转换为列表,用于多选筛选
|
||||
company_id = _id_list(params.get('company_id', False))
|
||||
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 使用in操作符支持多选片区筛选
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
|
||||
receivables = self.search(domain, order="contract_id asc, due_date asc")
|
||||
|
||||
@@ -163,11 +164,13 @@ class YuthonProperty(models.Model):
|
||||
def get_domain(self, start_date=False, end_date=False, company_id=False):
|
||||
if not start_date or not end_date:
|
||||
return []
|
||||
if not company_id:
|
||||
# 多选:company_id 标准化为列表
|
||||
cid_list = _id_list(company_id)
|
||||
if not cid_list:
|
||||
return []
|
||||
|
||||
# 这里进行条件的修改
|
||||
property_records = self.env['yuthon.property'].search([('company_id', '=', company_id)])
|
||||
# 按公司ID列表查询物业,获取片区管理员ID集合
|
||||
property_records = self.env['yuthon.property'].search([('company_id', 'in', cid_list)])
|
||||
|
||||
user_ids = set()
|
||||
for property_record in property_records:
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list # partner_id 多选适配工具
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -33,8 +34,8 @@ class RentAreaReport(models.Model):
|
||||
|
||||
keyword = params.get("keyword")
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
partner_id = _id_list(params.get('partner_id')) # 支持多选,转为列表
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
# 前端侧边栏下拉选择器传入的 ID
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -64,9 +65,9 @@ class RentAreaReport(models.Model):
|
||||
if condition:
|
||||
domain.append(('tenure_type', '=', condition))
|
||||
if partner_id:
|
||||
domain.append(('precinct_id', '=', partner_id))
|
||||
domain.append(('precinct_id', 'in', partner_id)) # 多选用 in
|
||||
if company_id:
|
||||
domain.append(('company_id', '=', company_id))
|
||||
domain.append(('company_id', 'in', company_id))
|
||||
# 物业名称下拉选择器:直接过滤 yuthon_property_id
|
||||
if property_id:
|
||||
domain.append(('yuthon_property_id', '=', int(property_id)))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""报表公共工具函数"""
|
||||
import logging
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _id_list(val):
|
||||
"""将参数标准化为扁平整数列表,用于多选场景下 'in' 操作符
|
||||
|
||||
- 列表/元组 → 递归展平后返回列表(防止 [[20, 30]] 嵌套导致 SQL 类型错误)
|
||||
- 单个整数 → [val]
|
||||
- None/False/0/空字符串 → [](空列表,使 if partner_id 为 False,不追加条件)
|
||||
|
||||
单选时 _id_list(20) → [20],配合 'in' [20] 等价于原来的 = 20,数据一致
|
||||
多选时 _id_list([20, 30]) → [20, 30],配合 'in' [20, 30] 正常
|
||||
嵌套时 _id_list([[20, 30]]) → [20, 30],防止 psycopg2 把 list 转为 ARRAY 导致 SQL 类型错误
|
||||
"""
|
||||
if isinstance(val, (list, tuple)):
|
||||
result = []
|
||||
for item in val:
|
||||
# 递归展平嵌套的列表/元组
|
||||
if isinstance(item, (list, tuple)):
|
||||
result.extend(_id_list(item))
|
||||
elif item is not None and item is not False and item != 0 and item != '':
|
||||
result.append(item)
|
||||
return result
|
||||
if val is None or val is False or val == 0 or val == '':
|
||||
return []
|
||||
return [val]
|
||||
@@ -1,3 +1,4 @@
|
||||
from .report_utils import _id_list
|
||||
from odoo import api, models
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
@@ -15,7 +16,7 @@ class StaffPositionReport(models.Model):
|
||||
# 不再过滤is_enable和establishment_quotas,查询所有岗位
|
||||
domain = []
|
||||
|
||||
company_id = params.get("company_id")
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
department_id = params.get("department_id")
|
||||
keyword = params.get("keyword")
|
||||
date_end = params.get("date_end") # 获取截止日期
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import datetime
|
||||
import calendar
|
||||
|
||||
from .report_utils import _id_list
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
@@ -31,7 +32,7 @@ class TextSummaryReport(models.Model):
|
||||
query_date = today
|
||||
|
||||
# 获取筛选条件
|
||||
company_id = params.get('company_id')
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
precinct_id = params.get('partner_id')
|
||||
|
||||
# 构建报表数据结构
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import calendar
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list
|
||||
|
||||
|
||||
class TotalReceivedReport(models.Model):
|
||||
@@ -38,8 +39,9 @@ class TotalReceivedReport(models.Model):
|
||||
]
|
||||
|
||||
condition = params.get('condition')
|
||||
partner_id = params.get('partner_id')
|
||||
company_id = params.get('company_id')
|
||||
# 多选标准化:partner_id 统一为列表,配合 'in' 操作符
|
||||
partner_id = _id_list(params.get('partner_id'))
|
||||
company_id = _id_list(params.get('company_id'))
|
||||
management_type_id = params.get('management_type_id')
|
||||
property_id = params.get('property_id')
|
||||
lessee_id = params.get('lessee_id')
|
||||
@@ -47,10 +49,11 @@ class TotalReceivedReport(models.Model):
|
||||
|
||||
if condition:
|
||||
domain.append(('receivable_id.tenure_type', '=', condition))
|
||||
# 片区管理员:多选,用 'in' 操作符
|
||||
if partner_id:
|
||||
domain.append(('receivable_id.precinct_id', '=', partner_id))
|
||||
domain.append(('receivable_id.precinct_id', 'in', partner_id))
|
||||
if company_id:
|
||||
domain.append(('receivable_id.company_id', '=', company_id))
|
||||
domain.append(('receivable_id.company_id', 'in', company_id))
|
||||
if management_type_id:
|
||||
domain.append(('receivable_id.management_type_id', '=', management_type_id))
|
||||
if property_id:
|
||||
|
||||
@@ -4,6 +4,7 @@ import calendar
|
||||
import logging
|
||||
|
||||
from odoo import api, models
|
||||
from .report_utils import _id_list
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -150,6 +151,7 @@ class YuthonDashboard(models.Model):
|
||||
# ==================== 汇总信息 ====================
|
||||
filters = {
|
||||
'统计时间': f"{query_date.year}-{query_date.month:02d}",
|
||||
# 多选:所属公司传ID列表
|
||||
'所属公司': self._get_company_display(params.get('company_id')),
|
||||
'管理员': self._get_admin_display(params.get('partner_id')),
|
||||
}
|
||||
@@ -157,10 +159,12 @@ class YuthonDashboard(models.Model):
|
||||
# ==================== 构建筛选条件上下文(透传给子报表) ====================
|
||||
# 子报表从 action.context.dashboard_filter 中读取并初始化筛选状态
|
||||
# date_str: "YYYY-MM" 格式,子报表据此还原 DateTime 对象
|
||||
# 多选:company_id/partner_id 透传ID列表,名称拼接
|
||||
cid_list = _id_list(params.get('company_id'))
|
||||
dashboard_filter = {
|
||||
'date_str': f"{query_date.year}-{query_date.month:02d}" if has_date else '',
|
||||
'company_id': params.get('company_id') or False,
|
||||
'company_name': self._get_company_display(params.get('company_id')) if params.get('company_id') else '',
|
||||
'company_id': cid_list or False,
|
||||
'company_name': self._get_company_display(params.get('company_id')) if cid_list else '',
|
||||
'partner_id': params.get('partner_id') or False,
|
||||
'partner_name': self._get_admin_display(params.get('partner_id')) if params.get('partner_id') else '',
|
||||
'condition': params.get('condition') or '',
|
||||
@@ -276,24 +280,40 @@ class YuthonDashboard(models.Model):
|
||||
# -------------------------------------------------------
|
||||
|
||||
def _get_company_display(self, company_id):
|
||||
"""根据公司ID列表获取公司显示名(多选支持)
|
||||
company_id 是 yuthon.property.company 的 ID 列表(多选)或单值
|
||||
"""
|
||||
if not company_id:
|
||||
return '全部'
|
||||
try:
|
||||
company = self.env['yuthon.property.company'].browse(int(company_id))
|
||||
return company.name if company else '未知'
|
||||
# 多选:company_id 是列表,获取所有名称用逗号拼接
|
||||
cid_list = _id_list(company_id)
|
||||
if not cid_list:
|
||||
return '全部'
|
||||
companies = self.env['yuthon.property.company'].browse(cid_list)
|
||||
names = [c.name for c in companies if c.name]
|
||||
return ', '.join(names) if names else '未知'
|
||||
except Exception:
|
||||
return '未知'
|
||||
|
||||
def _get_admin_display(self, partner_id):
|
||||
"""根据片区ID获取管理员显示名
|
||||
partner_id 是 yuthon.precinct.message 的 ID(前端 Many2XAutocomplete 绑定该模型)
|
||||
"""根据片区ID列表获取管理员显示名(多选支持)
|
||||
partner_id 是 yuthon.precinct.message 的 ID 列表(多选)或单值
|
||||
display_name 已自动拼接为 "{片区名称}{管理员姓名}",如 "二B梁嘉辉"
|
||||
"""
|
||||
if not partner_id:
|
||||
return '全部'
|
||||
try:
|
||||
precinct = self.env['yuthon.precinct.message'].browse(int(partner_id))
|
||||
return precinct.display_name if precinct else '未知'
|
||||
# 多选:partner_id 是列表,获取所有名称用逗号拼接
|
||||
pid_list = _id_list(partner_id)
|
||||
if not pid_list:
|
||||
return '全部'
|
||||
names = []
|
||||
for pid in pid_list:
|
||||
precinct = self.env['yuthon.precinct.message'].browse(pid)
|
||||
if precinct:
|
||||
names.append(precinct.display_name)
|
||||
return '、'.join(names) if names else '未知'
|
||||
except Exception:
|
||||
return '未知'
|
||||
|
||||
@@ -304,8 +324,9 @@ class YuthonDashboard(models.Model):
|
||||
last_day = calendar.monthrange(query_date.year, query_date.month)[1]
|
||||
month_last = query_date.replace(day=last_day)
|
||||
|
||||
company_id = base_params.get('company_id')
|
||||
partner_id = base_params.get('partner_id')
|
||||
company_id = _id_list(base_params.get('company_id'))
|
||||
# 多选标准化:partner_id 统一为列表
|
||||
partner_id = _id_list(base_params.get('partner_id'))
|
||||
keyword = base_params.get('keyword')
|
||||
|
||||
# 按费用类型分别统计(数据源:property.bills.list)
|
||||
@@ -323,11 +344,12 @@ class YuthonDashboard(models.Model):
|
||||
('actual_date', '<=', month_last),
|
||||
]
|
||||
if company_id:
|
||||
domain.append(('lessor_id', '=', int(company_id)))
|
||||
domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
# 多选:片区管理员用 'in' 操作符
|
||||
domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id),
|
||||
('receivables_id.precinct_id', 'in', partner_id),
|
||||
]
|
||||
if keyword:
|
||||
domain += ['|', '|', '|',
|
||||
@@ -347,11 +369,12 @@ class YuthonDashboard(models.Model):
|
||||
('actual_date', '<=', month_last),
|
||||
]
|
||||
if company_id:
|
||||
year_domain.append(('lessor_id', '=', int(company_id)))
|
||||
year_domain.append(('lessor_id', 'in', company_id))
|
||||
if partner_id:
|
||||
# 多选:片区管理员用 'in' 操作符
|
||||
year_domain += ['|',
|
||||
('contract_id.precinct_id', '=', int(partner_id)),
|
||||
('receivables_id.precinct_id', '=', int(partner_id)),
|
||||
('contract_id.precinct_id', 'in', partner_id),
|
||||
('receivables_id.precinct_id', 'in', partner_id),
|
||||
]
|
||||
year_records = self.env['property.bills.list'].sudo().search(year_domain)
|
||||
year_total = sum((r.amount_actual or 0.0) for r in year_records)
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Component, onMounted, useState } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { standardActionServiceProps } from "@web/webclient/actions/action_service";
|
||||
import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
|
||||
import { MultiSelectAutocomplete } from "../yuthon_report/multi_select_autocomplete";
|
||||
|
||||
class YuthonDashboard extends Component {
|
||||
setup() {
|
||||
@@ -18,8 +19,10 @@ class YuthonDashboard extends Component {
|
||||
loading: false,
|
||||
collapsedSections: {},
|
||||
// 筛选器
|
||||
selectCompany: {},
|
||||
selectPartner: {},
|
||||
// 多选:所属公司改为数组
|
||||
selectCompany: [],
|
||||
// 多选:片区管理员改为数组
|
||||
selectPartner: [],
|
||||
condition: "",
|
||||
conditions: [
|
||||
{ name: "", value: "" },
|
||||
@@ -37,12 +40,15 @@ class YuthonDashboard extends Component {
|
||||
const cached = sessionStorage.getItem("yuthon_dashboard_cache");
|
||||
if (cached) {
|
||||
const snapshot = JSON.parse(cached);
|
||||
// 从缓存恢复时,selectCompany/selectPartner 必须是数组,
|
||||
// 旧格式({})或非数组值一律回退为空数组,防止 .map() 报错
|
||||
const safeArr = (val) => (Array.isArray(val) ? val : []);
|
||||
Object.assign(this.state, {
|
||||
dateStart: snapshot.dateStart || this.state.dateStart,
|
||||
selectCompany: snapshot.selectCompany || this.state.selectCompany,
|
||||
selectPartner: snapshot.selectPartner || this.state.selectPartner,
|
||||
selectCompany: safeArr(snapshot.selectCompany),
|
||||
selectPartner: safeArr(snapshot.selectPartner),
|
||||
condition: snapshot.condition || this.state.condition,
|
||||
domainUsers: snapshot.domainUsers || this.state.domainUsers,
|
||||
domainUsers: safeArr(snapshot.domainUsers),
|
||||
dashboardData: snapshot.dashboardData || this.state.dashboardData,
|
||||
collapsedSections: snapshot.collapsedSections || this.state.collapsedSections,
|
||||
});
|
||||
@@ -86,8 +92,8 @@ class YuthonDashboard extends Component {
|
||||
}
|
||||
|
||||
getDomain() {
|
||||
const isCompanyEmpty = Object.keys(this.state.selectCompany).length === 0;
|
||||
if (isCompanyEmpty) {
|
||||
// 多选:检查公司数组是否为空
|
||||
if (!this.state.selectCompany.length) {
|
||||
return [];
|
||||
} else {
|
||||
return [["id", "in", this.state.domainUsers]];
|
||||
@@ -95,7 +101,8 @@ class YuthonDashboard extends Component {
|
||||
}
|
||||
|
||||
async searchUserDomain() {
|
||||
this.state.selectPartner = {};
|
||||
// 多选:重置片区管理员为空数组
|
||||
this.state.selectPartner = [];
|
||||
|
||||
// get_domain 需要 start_date 和 end_date,否则直接返回 []
|
||||
// 从当前选择的月份推算,没选月份就用当月
|
||||
@@ -115,6 +122,8 @@ class YuthonDashboard extends Component {
|
||||
endDate = `${y}-${m}-${String(lastDay).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
// 多选:传公司ID列表
|
||||
const companyIdList = this.state.selectCompany.map(item => item.id);
|
||||
const results = await this.serviceOrm.call(
|
||||
"property.accounts.receivable",
|
||||
"get_domain",
|
||||
@@ -122,33 +131,28 @@ class YuthonDashboard extends Component {
|
||||
{
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
company_id: this.state.selectCompany?.id,
|
||||
company_id: companyIdList,
|
||||
}
|
||||
);
|
||||
this.state.domainUsers = results || [];
|
||||
}
|
||||
|
||||
async onUpdateCompany(v) {
|
||||
if (!v || !v[0]) {
|
||||
this.state.selectCompany = {};
|
||||
this.state.selectPartner = {};
|
||||
this.state.domainUsers = [];
|
||||
await this.onSearch();
|
||||
return;
|
||||
async onUpdateCompany(items) {
|
||||
// 多选:items 是已选项数组 [{id, display_name}, ...]
|
||||
this.state.selectCompany = items;
|
||||
// 多选:片区管理员重置为空数组
|
||||
this.state.selectPartner = [];
|
||||
this.state.domainUsers = [];
|
||||
// 有公司选中时才查询domain
|
||||
if (items.length) {
|
||||
await this.searchUserDomain();
|
||||
}
|
||||
const values = await this.serviceOrm.call(
|
||||
"yuthon.property.company",
|
||||
"read",
|
||||
[[v[0].id]],
|
||||
{ fields: ["display_name"] }
|
||||
);
|
||||
this.state.selectCompany = values[0] || {};
|
||||
await this.searchUserDomain();
|
||||
await this.onSearch();
|
||||
}
|
||||
|
||||
async onUpdatePartner(v) {
|
||||
this.state.selectPartner = v[0] || {};
|
||||
async onUpdatePartner(items) {
|
||||
// 多选:items 是已选项数组 [{id, display_name}, ...]
|
||||
this.state.selectPartner = items;
|
||||
await this.onSearch();
|
||||
}
|
||||
|
||||
@@ -164,8 +168,10 @@ class YuthonDashboard extends Component {
|
||||
const params = {
|
||||
date_start: this.state.dateStart,
|
||||
keyword: this.state.keyword,
|
||||
company_id: this.state.selectCompany?.id || false,
|
||||
partner_id: this.state.selectPartner?.id || false,
|
||||
// 多选:所属公司传ID列表
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
// 多选:片区管理员传ID列表
|
||||
partner_id: this.state.selectPartner.map(item => item.id),
|
||||
condition: this.state.condition || false,
|
||||
};
|
||||
|
||||
@@ -205,10 +211,12 @@ class YuthonDashboard extends Component {
|
||||
// 构建当前看板的筛选参数,透传给子报表
|
||||
const dashboardFilter = {
|
||||
date_str: this.state.dateStart || "", // "YYYY-MM"
|
||||
company_id: this.state.selectCompany?.id || false,
|
||||
company_name: this.state.selectCompany?.display_name || "",
|
||||
partner_id: this.state.selectPartner?.id || false,
|
||||
partner_name: this.state.selectPartner?.display_name || "",
|
||||
// 多选:所属公司传ID列表和名称拼接
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
company_name: this.state.selectCompany.map(item => item.display_name).join(", "),
|
||||
// 多选:片区管理员传ID列表和名称拼接
|
||||
partner_id: this.state.selectPartner.map(item => item.id),
|
||||
partner_name: this.state.selectPartner.map(item => item.display_name).join(", "),
|
||||
condition: this.state.condition || "",
|
||||
};
|
||||
|
||||
@@ -247,6 +255,7 @@ YuthonDashboard.props = { ...standardActionServiceProps };
|
||||
YuthonDashboard.template = "yuthon_dashboard.YuthonDashboard";
|
||||
YuthonDashboard.components = {
|
||||
Many2XAutocomplete,
|
||||
MultiSelectAutocomplete,
|
||||
};
|
||||
|
||||
registry.category("actions").add("yuthon_dashboard_client", YuthonDashboard);
|
||||
|
||||
@@ -18,14 +18,15 @@
|
||||
</div>
|
||||
|
||||
<div style="width: 160px;">
|
||||
<Many2XAutocomplete
|
||||
value="state.selectCompany?.display_name"
|
||||
getDomain="getDomainCompany"
|
||||
<!-- 所属公司(多选) -->
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectCompany"
|
||||
getDomain="() => this.getDomainCompany()"
|
||||
resModel="'yuthon.property.company'"
|
||||
fieldString="'所属公司'"
|
||||
placeholder="'所属公司'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdateCompany"
|
||||
update="(items) => this.onUpdateCompany(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -43,14 +44,15 @@
|
||||
</div>
|
||||
|
||||
<div style="width: 160px;">
|
||||
<Many2XAutocomplete
|
||||
value="state.selectPartner?.display_name"
|
||||
getDomain.bind="getDomain"
|
||||
<!-- 片区管理员(多选) -->
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectPartner"
|
||||
getDomain="() => this.getDomain()"
|
||||
resModel="'yuthon.precinct.message'"
|
||||
fieldString="'片区管理员'"
|
||||
placeholder="'片区管理员'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdatePartner"
|
||||
update="(items) => this.onUpdatePartner(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import {DateTimeInput} from "@web/core/datetime/datetime_input";
|
||||
import {CheckBox} from "@web/core/checkbox/checkbox";
|
||||
import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
|
||||
import {MultiSelectAutocomplete} from "./multi_select_autocomplete";
|
||||
import {formatDate} from "@web/core/l10n/dates"
|
||||
|
||||
const {DateTime} = luxon;
|
||||
@@ -27,7 +28,8 @@ class ReceivableReport extends Component {
|
||||
keyword: "",
|
||||
booleanValue: true,
|
||||
selectDepartment: {},
|
||||
selectCompany: {},
|
||||
// 多选:所属公司改为数组
|
||||
selectCompany: [],
|
||||
selectStructure: {},
|
||||
domainDepartment:[],
|
||||
domainStructure:[],
|
||||
@@ -101,8 +103,8 @@ class ReceivableReport extends Component {
|
||||
|
||||
getDomainStructure() {
|
||||
console.log(this.state)
|
||||
const isCompanyEmpty = Object.keys(this.state.selectCompany).length === 0;
|
||||
if (isCompanyEmpty) {
|
||||
// 多选:检查公司数组是否为空
|
||||
if (!this.state.selectCompany.length) {
|
||||
return [];
|
||||
} else {
|
||||
return [['id','in', this.state.domainStructure]];
|
||||
@@ -112,8 +114,8 @@ class ReceivableReport extends Component {
|
||||
|
||||
getDomainDepartment() {
|
||||
console.log(this.state)
|
||||
const isCompanyEmpty = Object.keys(this.state.selectCompany).length === 0;
|
||||
if (isCompanyEmpty) {
|
||||
// 多选:检查公司数组是否为空
|
||||
if (!this.state.selectCompany.length) {
|
||||
return [];
|
||||
} else {
|
||||
return [['id','in', this.state.domainDepartment]];
|
||||
@@ -121,12 +123,14 @@ class ReceivableReport extends Component {
|
||||
}
|
||||
|
||||
async searchDomain() {
|
||||
// 多选:传公司ID列表
|
||||
const companyIdList = this.state.selectCompany.map(item => item.id)
|
||||
let results = await this.serviceOrm.call(
|
||||
'hr.attendance',
|
||||
'get_domain',
|
||||
[],
|
||||
{
|
||||
company_id: this.state.selectCompany?.id,
|
||||
company_id: companyIdList,
|
||||
}
|
||||
)
|
||||
console.log(results)
|
||||
@@ -143,7 +147,8 @@ class ReceivableReport extends Component {
|
||||
date_start: `${startDate} 00:00:00`,
|
||||
date_end: `${endDate} 23:59:59`,
|
||||
department_id: this.state.selectDepartment?.id,
|
||||
company_id: this.state.selectCompany?.id,
|
||||
// 多选:所属公司传ID列表
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
structure_id: this.state.selectStructure?.id,
|
||||
};
|
||||
const result = await this.serviceOrm.call(
|
||||
@@ -169,9 +174,12 @@ class ReceivableReport extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
async onUpdateCompany(v) {
|
||||
this.state.selectCompany = v[0] || {}
|
||||
await this.searchDomain()
|
||||
async onUpdateCompany(items) {
|
||||
// 多选:items 是已选项数组
|
||||
this.state.selectCompany = items
|
||||
if (items.length) {
|
||||
await this.searchDomain()
|
||||
}
|
||||
// 自动搜索
|
||||
await this.onSearch()
|
||||
}
|
||||
@@ -211,6 +219,7 @@ ReceivableReport.components = {
|
||||
DateTimeInput,
|
||||
CheckBox,
|
||||
Many2XAutocomplete,
|
||||
MultiSelectAutocomplete,
|
||||
};
|
||||
|
||||
registry.category("actions").add("att_report_client", ReceivableReport);
|
||||
|
||||
@@ -36,16 +36,16 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 所属公司 -->
|
||||
<!-- 所属公司(多选) -->
|
||||
<div class="col">
|
||||
<Many2XAutocomplete
|
||||
value="state.selectCompany?.display_name"
|
||||
getDomain="getDomainCompany"
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectCompany"
|
||||
getDomain="() => this.getDomainCompany()"
|
||||
resModel="'res.company'"
|
||||
fieldString="'所属公司'"
|
||||
placeholder="'所属公司'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdateCompany"
|
||||
update="(items) => this.onUpdateCompany(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
/**
|
||||
* 多选自动完成组件(MultiSelectAutocomplete)
|
||||
* 用于报表搜索栏,支持选择多个记录,以标签(chip)形式显示已选项
|
||||
* 基于 Odoo 的 name_search API 实现搜索
|
||||
*/
|
||||
import { Component, onMounted, useRef, useState } from "@odoo/owl";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
export class MultiSelectAutocomplete extends Component {
|
||||
setup() {
|
||||
this.orm = useService("orm");
|
||||
this.inputRef = useRef("input");
|
||||
this.containerRef = useRef("container");
|
||||
|
||||
// 响应式状态
|
||||
this.state = useState({
|
||||
searchText: "", // 输入框中的搜索文字
|
||||
options: [], // 下拉候选列表
|
||||
showDropdown: false, // 是否显示下拉框
|
||||
isLoading: false, // 是否正在加载
|
||||
});
|
||||
|
||||
// 绑定外部点击关闭事件
|
||||
this._boundCloseOutside = this._closeOnOutside.bind(this);
|
||||
}
|
||||
|
||||
mounted() {
|
||||
document.addEventListener("click", this._boundCloseOutside);
|
||||
}
|
||||
|
||||
willUnmount() {
|
||||
document.removeEventListener("click", this._boundCloseOutside);
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击外部区域时关闭下拉框
|
||||
*/
|
||||
_closeOnOutside(ev) {
|
||||
if (this.containerRef.el && !this.containerRef.el.contains(ev.target)) {
|
||||
this.state.showDropdown = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 已选项列表(从 props.value 获取) */
|
||||
get selectedItems() {
|
||||
return this.props.value || [];
|
||||
}
|
||||
|
||||
/** 获取已选ID列表(用于排除已选的) */
|
||||
getSelectedIds() {
|
||||
return this.selectedItems.map((item) => item.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 Odoo 的 name_search 搜索候选记录
|
||||
*/
|
||||
async _searchRecords(name) {
|
||||
const limit = this.props.searchLimit || 20;
|
||||
let domain = [];
|
||||
// getDomain 是可选的,没有传则用空 domain(不过滤)
|
||||
if (this.props.getDomain) {
|
||||
try {
|
||||
domain = this.props.getDomain();
|
||||
} catch (e) {
|
||||
console.error("[MultiSelect] getDomain error:", e);
|
||||
domain = [];
|
||||
}
|
||||
}
|
||||
// 排除已选中的记录
|
||||
const excludeIds = this.getSelectedIds();
|
||||
if (excludeIds.length > 0) {
|
||||
domain.push(["id", "not in", excludeIds]);
|
||||
}
|
||||
|
||||
// 调用后端 name_search 接口获取候选列表
|
||||
const results = await this.orm.call(
|
||||
this.props.resModel,
|
||||
"name_search",
|
||||
[],
|
||||
{
|
||||
name: name || "",
|
||||
operator: "ilike",
|
||||
args: domain,
|
||||
limit: limit,
|
||||
context: this.props.context || {},
|
||||
}
|
||||
);
|
||||
// 将 [id, display_name] 格式转为对象数组
|
||||
return results.map((r) => ({
|
||||
id: r[0],
|
||||
display_name: r[1] ? r[1].split("\n")[0] : "未命名",
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入框获得焦点时:立即打开下拉并开始搜索
|
||||
*/
|
||||
async onInputFocus() {
|
||||
// 立即显示下拉框(先显示加载中,数据到了再更新)
|
||||
this.state.showDropdown = true;
|
||||
await this._doSearch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入框失焦时:延迟关闭下拉(让点击候选项的事件先执行)
|
||||
*/
|
||||
onInputBlur() {
|
||||
// 延迟关闭,避免点击候选项时先 blur 关闭了下拉,导致点击失效
|
||||
setTimeout(() => {
|
||||
this.state.showDropdown = false;
|
||||
}, 150);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入内容变化时:重新搜索
|
||||
*/
|
||||
async onInputChange(ev) {
|
||||
// 从 DOM 直接读取输入值(避免 t-att-value 重置问题)
|
||||
this.state.searchText = ev.target.value;
|
||||
this.state.showDropdown = true;
|
||||
await this._doSearch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行搜索:调用后端接口更新候选项
|
||||
*/
|
||||
async _doSearch() {
|
||||
this.state.isLoading = true;
|
||||
try {
|
||||
const options = await this._searchRecords(this.state.searchText);
|
||||
this.state.options = options;
|
||||
} catch (e) {
|
||||
console.error("[MultiSelect] search error:", e);
|
||||
this.state.options = [];
|
||||
} finally {
|
||||
this.state.isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击下拉候选项:添加到已选列表
|
||||
*/
|
||||
onSelect(option) {
|
||||
const newItem = { id: option.id, display_name: option.display_name };
|
||||
const currentItems = [...this.selectedItems];
|
||||
// 防止重复添加
|
||||
if (!currentItems.find((item) => item.id === newItem.id)) {
|
||||
currentItems.push(newItem);
|
||||
}
|
||||
// 通知父组件更新
|
||||
this.props.update(currentItems);
|
||||
// 清空搜索文字,关闭下拉
|
||||
this.state.searchText = "";
|
||||
this.state.showDropdown = false;
|
||||
// 选中后触发搜索回调(如报表查询)
|
||||
if (this.props.searchOnChange !== false && this.props.onSearch) {
|
||||
this.props.onSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击标签删除按钮:移除一个已选项
|
||||
*/
|
||||
onRemoveItem(id) {
|
||||
const currentItems = this.selectedItems.filter((item) => item.id !== id);
|
||||
this.props.update([...currentItems]);
|
||||
if (this.props.searchOnChange !== false && this.props.onSearch) {
|
||||
this.props.onSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击清空按钮:清空所有已选项
|
||||
*/
|
||||
clearAll() {
|
||||
this.props.update([]);
|
||||
if (this.props.searchOnChange !== false && this.props.onSearch) {
|
||||
this.props.onSearch();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 键盘事件:Backspace 删除最后一项,Enter 阻止默认行为
|
||||
*/
|
||||
onKeyDown(ev) {
|
||||
if (ev.key === "Backspace" && !this.state.searchText && this.selectedItems.length > 0) {
|
||||
// 删除键且输入为空时,移除最后一个已选项
|
||||
const lastItem = this.selectedItems[this.selectedItems.length - 1];
|
||||
this.onRemoveItem(lastItem.id);
|
||||
} else if (ev.key === "Enter") {
|
||||
// 回车时阻止表单提交
|
||||
ev.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 注册模板和属性
|
||||
MultiSelectAutocomplete.template = "yuthon_report.MultiSelectAutocomplete";
|
||||
MultiSelectAutocomplete.props = {
|
||||
value: { type: Array, optional: true },
|
||||
resModel: String,
|
||||
getDomain: { type: Function, optional: true },
|
||||
update: Function,
|
||||
placeholder: { type: String, optional: true },
|
||||
fieldString: { type: String, optional: true },
|
||||
context: { type: Object, optional: true },
|
||||
searchLimit: { type: Number, optional: true },
|
||||
/** 选中/删除后是否自动调用 onSearch 回调,默认 true */
|
||||
searchOnChange: { type: Boolean, optional: true },
|
||||
/** 选中/删除后的回调(如触发报表查询) */
|
||||
onSearch: { type: Function, optional: true },
|
||||
};
|
||||
MultiSelectAutocomplete.defaultProps = {
|
||||
value: [],
|
||||
searchLimit: 20,
|
||||
searchOnChange: true,
|
||||
context: {},
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<!-- 多选自动完成组件:标签 + 输入框 + 下拉候选列表 -->
|
||||
<t t-name="yuthon_report.MultiSelectAutocomplete">
|
||||
<div class="multi-select-autocomplete" t-ref="container" style="position:relative; width:100%;">
|
||||
|
||||
<!-- 已选标签区域 + 搜索输入框 -->
|
||||
<div class="multi-select-input-wrapper"
|
||||
style="display:flex; flex-wrap:wrap; align-items:center; gap:3px;
|
||||
border:1px solid #ced4da; border-radius:0.25rem; padding:2px 6px;
|
||||
min-height:34px; background:#fff; cursor:text;"
|
||||
t-on-click="() => { this.inputRef.el && this.inputRef.el.focus(); }">
|
||||
|
||||
<!-- 已选标签(chip) -->
|
||||
<t t-foreach="selectedItems" t-as="item" t-key="item.id">
|
||||
<span class="badge bg-light text-dark border d-flex align-items-center"
|
||||
style="font-size:0.78rem; padding:2px 7px; cursor:pointer;"
|
||||
t-on-mousedown="(ev) => ev.preventDefault()"
|
||||
title="点击删除">
|
||||
<t t-esc="item.display_name"/>
|
||||
<i class="oi oi-close ms-1" style="font-size:10px;" role="presentation"
|
||||
t-on-click.stop.prevent="() => this.onRemoveItem(item.id)"/>
|
||||
</span>
|
||||
</t>
|
||||
|
||||
<!-- 搜索输入框(不使用 t-att-value 避免重置问题) -->
|
||||
<input type="text"
|
||||
t-ref="input"
|
||||
class="multi-select-search-input border-0 outline-none"
|
||||
style="flex:1; min-width:80px; padding:3px 0; font-size:0.88rem; background:transparent;"
|
||||
t-att-placeholder="props.placeholder || props.fieldString || '搜索...'"
|
||||
t-on-focus="onInputFocus"
|
||||
t-on-blur="onInputBlur"
|
||||
t-on-input="onInputChange"
|
||||
t-on-keydown="onKeyDown"/>
|
||||
</div>
|
||||
|
||||
<!-- 下拉候选列表(点击输入框或获得焦点时显示) -->
|
||||
<div t-if="state.showDropdown"
|
||||
class="dropdown-menu show position-absolute w-100 mt-1 shadow"
|
||||
style="max-height:220px; overflow-y:auto; z-index:1050; display:block;">
|
||||
|
||||
<!-- 状态1:正在加载 -->
|
||||
<div t-if="state.isLoading" class="dropdown-item text-muted text-center py-2">
|
||||
搜索中...
|
||||
</div>
|
||||
|
||||
<!-- 状态2:加载完成 - 分两种情况 -->
|
||||
<t t-if="!state.isLoading">
|
||||
|
||||
<!-- 2a:没有候选项 -->
|
||||
<div t-if="state.options.length === 0"
|
||||
class="dropdown-item text-muted text-center py-2">
|
||||
无匹配记录
|
||||
</div>
|
||||
|
||||
<!-- 2b:有候选项列表 -->
|
||||
<t t-if="state.options.length > 0">
|
||||
<a t-foreach="state.options" t-as="opt" t-key="opt.id"
|
||||
class="dropdown-item d-flex justify-content-between align-items-center"
|
||||
href="#"
|
||||
style="cursor:pointer; font-size:0.88rem;"
|
||||
t-on-click.stop.prevent="(ev) => this.onSelect(opt)"
|
||||
t-on-mousedown="(ev) => ev.preventDefault()">
|
||||
<span t-esc="opt.display_name"/>
|
||||
</a>
|
||||
</t>
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import {DateTimeInput} from "@web/core/datetime/datetime_input";
|
||||
import {CheckBox} from "@web/core/checkbox/checkbox";
|
||||
import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
|
||||
import {MultiSelectAutocomplete} from "./multi_select_autocomplete";
|
||||
import {formatDate} from "@web/core/l10n/dates"
|
||||
|
||||
const {DateTime} = luxon;
|
||||
@@ -30,8 +31,9 @@ class ReceivableFlowReport extends Component {
|
||||
singleDate: DateTime.now().startOf("month"),
|
||||
keyword: "",
|
||||
booleanValue: true,
|
||||
selectPartner: {},
|
||||
selectCompany: {},
|
||||
// 多选:片区管理员和所属公司改为数组
|
||||
selectPartner: [],
|
||||
selectCompany: [],
|
||||
selectManagementType: {},
|
||||
selectProperty: {},
|
||||
selectLessee: {},
|
||||
@@ -287,30 +289,33 @@ class ReceivableFlowReport extends Component {
|
||||
}
|
||||
|
||||
getDomain() {
|
||||
const isCompanyEmpty = Object.keys(this.state.selectCompany).length === 0;
|
||||
if (isCompanyEmpty) {
|
||||
// 多选:检查公司数组是否为空
|
||||
if (!this.state.selectCompany.length) {
|
||||
return [];
|
||||
} else {
|
||||
return [['id', 'in', this.state.domainUsers]];
|
||||
}
|
||||
}
|
||||
|
||||
async onUpdatePartner(v) {
|
||||
this.state.selectPartner = v[0]
|
||||
async onUpdatePartner(items) {
|
||||
// 多选:items 是已选项数组
|
||||
this.state.selectPartner = items
|
||||
await this.onSearch()
|
||||
}
|
||||
|
||||
async searchUserDomain() {
|
||||
this.state.selectPartner = {}
|
||||
this.state.selectPartner = []
|
||||
let startDate = formatDate(this.state.startDate, {format: "yyyy-MM-dd"})
|
||||
let endDate = formatDate(this.state.endDate, {format: "yyyy-MM-dd"})
|
||||
|
||||
// 多选:传公司ID列表
|
||||
const companyIdList = this.state.selectCompany.map(item => item.id)
|
||||
let results = await this.serviceOrm.call(
|
||||
'property.accounts.receivable',
|
||||
'get_domain',
|
||||
[],
|
||||
{
|
||||
company_id: this.state.selectCompany?.id,
|
||||
company_id: companyIdList,
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
}
|
||||
@@ -318,24 +323,14 @@ class ReceivableFlowReport extends Component {
|
||||
this.state.domainUsers = results
|
||||
}
|
||||
|
||||
async onUpdateCompany(v) {
|
||||
if (!v || !v[0]) {
|
||||
this.state.selectCompany = {};
|
||||
this.state.selectPartner = {};
|
||||
this.state.domainUsers = [];
|
||||
await this.onSearch();
|
||||
return;
|
||||
async onUpdateCompany(items) {
|
||||
// 多选:items 是已选项数组
|
||||
this.state.selectCompany = items
|
||||
this.state.selectPartner = [];
|
||||
this.state.domainUsers = [];
|
||||
if (items.length) {
|
||||
await this.searchUserDomain()
|
||||
}
|
||||
let values = await this.serviceOrm.call(
|
||||
'yuthon.property.company',
|
||||
'read',
|
||||
[[v[0].id]],
|
||||
{
|
||||
fields: ['display_name'],
|
||||
}
|
||||
)
|
||||
this.state.selectCompany = values[0] || {}
|
||||
await this.searchUserDomain()
|
||||
await this.onSearch()
|
||||
}
|
||||
|
||||
@@ -369,8 +364,9 @@ class ReceivableFlowReport extends Component {
|
||||
date_end: `${singleDate} 23:59:59`,
|
||||
keyword: this.state.keyword || false,
|
||||
condition: this.state.condition || false,
|
||||
partner_id: this.state.selectPartner?.id,
|
||||
company_id: this.state.selectCompany?.id,
|
||||
// 多选:片区管理员、所属公司传ID列表
|
||||
partner_id: this.state.selectPartner.map(item => item.id),
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
management_type_id: this.state.selectManagementType?.id || false,
|
||||
property_id: this.state.selectProperty?.id || false,
|
||||
lessee_id: this.state.selectLessee?.id || false,
|
||||
@@ -384,8 +380,9 @@ class ReceivableFlowReport extends Component {
|
||||
date_end: `${endDate} 23:59:59`,
|
||||
keyword: this.state.keyword || false,
|
||||
condition: this.state.condition || false,
|
||||
partner_id: this.state.selectPartner?.id,
|
||||
company_id: this.state.selectCompany?.id,
|
||||
// 多选:片区管理员、所属公司传ID列表
|
||||
partner_id: this.state.selectPartner.map(item => item.id),
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
management_type_id: this.state.selectManagementType?.id || false,
|
||||
property_id: this.state.selectProperty?.id || false,
|
||||
lessee_id: this.state.selectLessee?.id || false,
|
||||
@@ -552,6 +549,7 @@ ReceivableFlowReport.components = {
|
||||
DateTimeInput,
|
||||
CheckBox,
|
||||
Many2XAutocomplete,
|
||||
MultiSelectAutocomplete,
|
||||
};
|
||||
|
||||
registry.category("actions").add("receivable_flow_report_client", ReceivableFlowReport);
|
||||
|
||||
@@ -36,29 +36,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 所属片区 -->
|
||||
<!-- 所属片区(多选) -->
|
||||
<div class="col-3">
|
||||
<label>所属片区</label>
|
||||
<Many2XAutocomplete
|
||||
value="state.selectPrecinct?.display_name"
|
||||
getDomain="getDomainPrecinct"
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectPrecinct"
|
||||
getDomain="() => this.getDomainPrecinct()"
|
||||
resModel="'yuthon.precinct.message'"
|
||||
fieldString="'所属片区'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdatePrecinct"
|
||||
placeholder="'所属片区'"
|
||||
update="(items) => this.onUpdatePrecinct(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 所属公司 -->
|
||||
<!-- 所属公司(多选) -->
|
||||
<div class="col-3">
|
||||
<label>所属公司</label>
|
||||
<Many2XAutocomplete
|
||||
value="state.selectCompany?.display_name"
|
||||
getDomain="getDomainCompany"
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectCompany"
|
||||
getDomain="() => this.getDomainCompany()"
|
||||
resModel="'yuthon.property.company'"
|
||||
fieldString="'所属公司'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdateCompany"
|
||||
placeholder="'所属公司'"
|
||||
update="(items) => this.onUpdateCompany(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import {useService} from "@web/core/utils/hooks";
|
||||
import {standardActionServiceProps} from "@web/webclient/actions/action_service";
|
||||
import {DateTimeInput} from "@web/core/datetime/datetime_input";
|
||||
import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
|
||||
import {MultiSelectAutocomplete} from "./multi_select_autocomplete";
|
||||
import {formatDate} from "@web/core/l10n/dates"
|
||||
|
||||
const {DateTime} = luxon;
|
||||
@@ -19,8 +20,9 @@ class ReceiptLedgerReport extends Component {
|
||||
this.state = useState({
|
||||
startDate: null,
|
||||
endDate: null,
|
||||
selectPrecinct: {},
|
||||
selectCompany: {},
|
||||
// 多选:片区管理员和所属公司改为数组
|
||||
selectPrecinct: [],
|
||||
selectCompany: [],
|
||||
selectManagementType: {},
|
||||
conditions: [{
|
||||
'name': '自有',
|
||||
@@ -74,15 +76,16 @@ class ReceiptLedgerReport extends Component {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 选择所属片区
|
||||
async onUpdatePrecinct(v) {
|
||||
console.log("选择所属片区:", v);
|
||||
this.state.selectPrecinct = v[0] || {};
|
||||
// 选择所属片区(多选)
|
||||
async onUpdatePrecinct(items) {
|
||||
console.log("选择所属片区:", items);
|
||||
this.state.selectPrecinct = items;
|
||||
}
|
||||
|
||||
async onUpdateCompany(v) {
|
||||
console.log("选择所属公司:", v);
|
||||
this.state.selectCompany = v[0] || {};
|
||||
// 选择所属公司(多选)
|
||||
async onUpdateCompany(items) {
|
||||
console.log("选择所属公司:", items);
|
||||
this.state.selectCompany = items;
|
||||
}
|
||||
|
||||
async onUpdateManagementType(v) {
|
||||
@@ -109,10 +112,11 @@ class ReceiptLedgerReport extends Component {
|
||||
const params = {
|
||||
date_start: this.state.startDate,
|
||||
date_end: this.state.endDate,
|
||||
precinct_id: this.state.selectPrecinct?.id || false,
|
||||
// 多选:片区管理员和所属公司传ID列表
|
||||
precinct_id: this.state.selectPrecinct.map(item => item.id),
|
||||
condition: this.state.condition || false,
|
||||
|
||||
company_id: this.state.selectCompany?.id || false,
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
management_type_id: this.state.selectManagementType?.id || false,
|
||||
};
|
||||
|
||||
@@ -142,6 +146,7 @@ ReceiptLedgerReport.template = "yuthon_report.ReceiptLedgerReport";
|
||||
ReceiptLedgerReport.components = {
|
||||
DateTimeInput,
|
||||
Many2XAutocomplete,
|
||||
MultiSelectAutocomplete,
|
||||
};
|
||||
|
||||
registry.category("actions").add("receipt_ledger_report_client", ReceiptLedgerReport);
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import {DateTimeInput} from "@web/core/datetime/datetime_input";
|
||||
import {CheckBox} from "@web/core/checkbox/checkbox";
|
||||
import {Many2XAutocomplete} from "@web/views/fields/relational_utils";
|
||||
import {MultiSelectAutocomplete} from "./multi_select_autocomplete";
|
||||
import {formatDate} from "@web/core/l10n/dates"
|
||||
|
||||
const {DateTime} = luxon;
|
||||
@@ -40,14 +41,32 @@ class ReceivableReport extends Component {
|
||||
initSingleDate = parsed.startOf("month");
|
||||
}
|
||||
}
|
||||
// 解析所属公司:有 id+name 才初始化,否则为空
|
||||
const initCompany = df.company_id
|
||||
? { id: df.company_id, display_name: df.company_name || '' }
|
||||
: {};
|
||||
// 解析片区管理员
|
||||
const initPartner = df.partner_id
|
||||
? { id: df.partner_id, display_name: df.partner_name || '' }
|
||||
: {};
|
||||
// 解析所属公司(多选:从看板跳转时 company_id 可能是数组 [1, 2] 或单值 1)
|
||||
let initCompany = [];
|
||||
if (df.company_id) {
|
||||
// company_name 可能是逗号拼接的多个名称
|
||||
const nameList = (df.company_name || '').split(/[,,、]/).map(s => s.trim()).filter(Boolean);
|
||||
// 统一转为数组
|
||||
const cidArr = Array.isArray(df.company_id) ? df.company_id : [df.company_id];
|
||||
// 每个 ID 创建一个选项对象
|
||||
initCompany = cidArr.map((cid, idx) => ({
|
||||
id: cid,
|
||||
display_name: nameList[idx] || '',
|
||||
}));
|
||||
}
|
||||
// 解析片区管理员(多选:从看板跳转时 partner_id 可能是数组 [20, 30] 或单值 20)
|
||||
let initPartner = [];
|
||||
if (df.partner_id) {
|
||||
// partner_name 可能是逗号拼接的多个名称
|
||||
const nameList = (df.partner_name || '').split(/[,,、]/).map(s => s.trim()).filter(Boolean);
|
||||
// 统一转为数组
|
||||
const pidArr = Array.isArray(df.partner_id) ? df.partner_id : [df.partner_id];
|
||||
// 每个 ID 创建一个选项对象
|
||||
initPartner = pidArr.map((pid, idx) => ({
|
||||
id: pid,
|
||||
display_name: nameList[idx] || '',
|
||||
}));
|
||||
}
|
||||
// 解析权属类型
|
||||
const initCondition = df.condition || false;
|
||||
|
||||
@@ -313,8 +332,8 @@ class ReceivableReport extends Component {
|
||||
|
||||
getDomain() {
|
||||
console.log(this.state)
|
||||
const isCompanyEmpty = Object.keys(this.state.selectCompany).length === 0;
|
||||
if (isCompanyEmpty) {
|
||||
// 多选:检查公司数组是否为空
|
||||
if (!this.state.selectCompany.length) {
|
||||
return [];
|
||||
} else {
|
||||
return [['id', 'in', this.state.domainUsers]];
|
||||
@@ -322,24 +341,27 @@ class ReceivableReport extends Component {
|
||||
}
|
||||
|
||||
|
||||
async onUpdatePartner(v) {
|
||||
console.log(v)
|
||||
this.state.selectPartner = v[0]
|
||||
async onUpdatePartner(items) {
|
||||
// 多选:items 是已选项数组 [{id, display_name}, ...]
|
||||
this.state.selectPartner = items
|
||||
// 自动搜索
|
||||
await this.onSearch()
|
||||
}
|
||||
|
||||
async searchUserDomain() {
|
||||
this.state.selectPartner = {}
|
||||
// 多选:重置片区管理员为空数组
|
||||
this.state.selectPartner = []
|
||||
let startDate = formatDate(this.state.startDate, {format: "yyyy-MM-dd"})
|
||||
let endDate = formatDate(this.state.endDate, {format: "yyyy-MM-dd"})
|
||||
|
||||
// 多选:传公司ID列表
|
||||
const companyIdList = this.state.selectCompany.map(item => item.id)
|
||||
let results = await this.serviceOrm.call(
|
||||
'property.accounts.receivable',
|
||||
'get_domain',
|
||||
[],
|
||||
{
|
||||
company_id: this.state.selectCompany?.id,
|
||||
company_id: companyIdList,
|
||||
start_date: startDate,
|
||||
end_date: endDate,
|
||||
}
|
||||
@@ -349,32 +371,16 @@ class ReceivableReport extends Component {
|
||||
}
|
||||
|
||||
|
||||
async onUpdateCompany(v) {
|
||||
console.log(v)
|
||||
// 检查v是否为空或v[0]不存在
|
||||
if (!v || !v[0]) {
|
||||
this.state.selectCompany = {};
|
||||
this.state.selectPartner = {};
|
||||
this.state.domainUsers = [];
|
||||
await this.onSearch();
|
||||
return;
|
||||
async onUpdateCompany(items) {
|
||||
// 多选:items 是已选项数组 [{id, display_name}, ...]
|
||||
this.state.selectCompany = items
|
||||
// 多选:片区管理员重置为空数组
|
||||
this.state.selectPartner = [];
|
||||
this.state.domainUsers = [];
|
||||
// 有公司选中时才查询domain
|
||||
if (items.length) {
|
||||
await this.searchUserDomain()
|
||||
}
|
||||
// 执行一次 查询
|
||||
// 通过 read 重新查询一次, 更多只返回了 id
|
||||
let values = await this.serviceOrm.call(
|
||||
'yuthon.property.company',
|
||||
'read',
|
||||
[[v[0].id]],
|
||||
{
|
||||
fields: ['display_name'],
|
||||
}
|
||||
)
|
||||
console.log(values)
|
||||
this.state.selectCompany = values[0] || {}
|
||||
// 查询这个过程中的 user_id 组合成列表.返回.
|
||||
// 重置 partner 筛选结果
|
||||
// 修改过滤条件
|
||||
await this.searchUserDomain()
|
||||
// 自动搜索
|
||||
await this.onSearch()
|
||||
}
|
||||
@@ -413,8 +419,10 @@ class ReceivableReport extends Component {
|
||||
date_end: `${singleDate} 23:59:59`,
|
||||
keyword: this.state.keyword || false,
|
||||
condition: this.state.condition || false,
|
||||
partner_id: this.state.selectPartner?.id,
|
||||
company_id: this.state.selectCompany?.id,
|
||||
// 多选:片区管理员传ID列表
|
||||
partner_id: this.state.selectPartner.map(item => item.id),
|
||||
// 多选:所属公司传ID列表
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
management_type_id: this.state.selectManagementType?.id || false,
|
||||
property_id: this.state.selectProperty?.id || false,
|
||||
lessee_id: this.state.selectLessee?.id || false,
|
||||
@@ -428,8 +436,10 @@ class ReceivableReport extends Component {
|
||||
date_end: `${endDate} 23:59:59`,
|
||||
keyword: this.state.keyword || false,
|
||||
condition: this.state.condition || false,
|
||||
partner_id: this.state.selectPartner?.id,
|
||||
company_id: this.state.selectCompany?.id,
|
||||
// 多选:片区管理员传ID列表
|
||||
partner_id: this.state.selectPartner.map(item => item.id),
|
||||
// 多选:所属公司传ID列表
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
management_type_id: this.state.selectManagementType?.id || false,
|
||||
property_id: this.state.selectProperty?.id || false,
|
||||
lessee_id: this.state.selectLessee?.id || false,
|
||||
@@ -619,6 +629,7 @@ ReceivableReport.components = {
|
||||
DateTimeInput,
|
||||
CheckBox,
|
||||
Many2XAutocomplete,
|
||||
MultiSelectAutocomplete,
|
||||
};
|
||||
|
||||
registry.category("actions").add("receivable_report_client", ReceivableReport);
|
||||
|
||||
@@ -63,16 +63,16 @@
|
||||
</t>
|
||||
</div>
|
||||
|
||||
<!-- 所属公司 -->
|
||||
<!-- 所属公司(多选) -->
|
||||
<div class="col">
|
||||
<Many2XAutocomplete
|
||||
value="state.selectCompany?.display_name"
|
||||
getDomain="getDomainCompany"
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectCompany"
|
||||
getDomain="() => this.getDomainCompany()"
|
||||
resModel="'yuthon.property.company'"
|
||||
fieldString="'所属公司'"
|
||||
placeholder="'所属公司'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdateCompany"
|
||||
update="(items) => this.onUpdateCompany(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
<div class="col">
|
||||
@@ -86,16 +86,16 @@
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<!-- 片区管理员 -->
|
||||
<!-- 片区管理员(多选) -->
|
||||
<div class="col">
|
||||
<Many2XAutocomplete
|
||||
value="state.selectPartner?.display_name"
|
||||
getDomain.bind="getDomain"
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectPartner"
|
||||
getDomain="() => this.getDomain()"
|
||||
resModel="'yuthon.precinct.message'"
|
||||
fieldString="'片区管理员'"
|
||||
placeholder="'片区管理员'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdatePartner"
|
||||
update="(items) => this.onUpdatePartner(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { standardActionServiceProps } from "@web/webclient/actions/action_servic
|
||||
import { DateTimeInput } from "@web/core/datetime/datetime_input";
|
||||
import { CheckBox } from "@web/core/checkbox/checkbox";
|
||||
import { Many2XAutocomplete } from "@web/views/fields/relational_utils";
|
||||
import { MultiSelectAutocomplete } from "./multi_select_autocomplete";
|
||||
import {formatDate} from "@web/core/l10n/dates"
|
||||
|
||||
const {DateTime} = luxon;
|
||||
@@ -34,12 +35,26 @@ class YouthonReport extends Component {
|
||||
initEndDate = parsed.endOf("month");
|
||||
}
|
||||
}
|
||||
const initCompany = df.company_id
|
||||
? { id: df.company_id, display_name: df.company_name || '' }
|
||||
: {};
|
||||
const initPartner = df.partner_id
|
||||
? { id: df.partner_id, display_name: df.partner_name || '' }
|
||||
: {};
|
||||
// 多选:解析所属公司
|
||||
let initCompany = [];
|
||||
if (df.company_id) {
|
||||
const nameList = (df.company_name || '').split(/[,,、]/).map(s => s.trim()).filter(Boolean);
|
||||
const cidArr = Array.isArray(df.company_id) ? df.company_id : [df.company_id];
|
||||
initCompany = cidArr.map((cid, idx) => ({
|
||||
id: cid,
|
||||
display_name: nameList[idx] || '',
|
||||
}));
|
||||
}
|
||||
// 多选:解析片区管理员
|
||||
let initPartner = [];
|
||||
if (df.partner_id) {
|
||||
const nameList = (df.partner_name || '').split(/[,,、]/).map(s => s.trim()).filter(Boolean);
|
||||
const pidArr = Array.isArray(df.partner_id) ? df.partner_id : [df.partner_id];
|
||||
initPartner = pidArr.map((pid, idx) => ({
|
||||
id: pid,
|
||||
display_name: nameList[idx] || '',
|
||||
}));
|
||||
}
|
||||
const initCondition = df.condition || false;
|
||||
|
||||
// 是否从经营看板跳转过来(控制"返回看板"按钮显示)
|
||||
@@ -53,8 +68,7 @@ class YouthonReport extends Component {
|
||||
endDate: initEndDate,
|
||||
keyword: "",
|
||||
selectPartner: initPartner,
|
||||
selectCompany: initCompany,
|
||||
condition: initCondition,
|
||||
selectCompany: initCompany, condition: initCondition,
|
||||
conditions:[{
|
||||
'name':'自有',
|
||||
'value':'self'
|
||||
@@ -104,13 +118,14 @@ class YouthonReport extends Component {
|
||||
// 过滤条件
|
||||
return [['id', 'in', [107,106, 215,112,110,214,218,173,219]]]
|
||||
}
|
||||
async onUpdatePartner(v){
|
||||
console.log(v)
|
||||
this.state.selectPartner = v[0]
|
||||
async onUpdatePartner(items){
|
||||
// 多选:items 是已选项数组
|
||||
this.state.selectPartner = items
|
||||
}
|
||||
|
||||
async onUpdateCompany(v){
|
||||
this.state.selectCompany = v[0]
|
||||
async onUpdateCompany(items){
|
||||
// 多选:items 是已选项数组
|
||||
this.state.selectCompany = items
|
||||
}
|
||||
|
||||
async onSearch() {
|
||||
@@ -130,8 +145,9 @@ class YouthonReport extends Component {
|
||||
date_end: endStr ? `${endStr} 23:59:59` : false,
|
||||
keyword: this.state.keyword || false,
|
||||
condition:this.state.condition || false,
|
||||
partner_id:this.state.selectPartner?.id,
|
||||
company_id:this.state.selectCompany?.id ,
|
||||
// 多选:片区管理员、所属公司传ID列表
|
||||
partner_id: this.state.selectPartner.map(item => item.id),
|
||||
company_id: this.state.selectCompany.map(item => item.id),
|
||||
};
|
||||
const result = await this.serviceOrm.call(
|
||||
this.config.model,
|
||||
@@ -178,6 +194,7 @@ YouthonReport.components = {
|
||||
DateTimeInput,
|
||||
CheckBox,
|
||||
Many2XAutocomplete,
|
||||
MultiSelectAutocomplete,
|
||||
};
|
||||
|
||||
registry.category("actions").add("youthon_report_client", YouthonReport);
|
||||
|
||||
@@ -87,16 +87,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 所属公司 -->
|
||||
<!-- 所属公司(多选) -->
|
||||
<div class="col-3">
|
||||
<label>所属公司</label>
|
||||
<Many2XAutocomplete
|
||||
value="state.selectCompany?.display_name"
|
||||
getDomain="getDomainCompany"
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectCompany"
|
||||
getDomain="() => this.getDomainCompany()"
|
||||
resModel="'yuthon.property.company'"
|
||||
fieldString="'所属公司'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdateCompany"
|
||||
placeholder="'所属公司'"
|
||||
update="(items) => this.onUpdateCompany(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
@@ -108,16 +109,17 @@
|
||||
<t t-esc="cond.name"/>
|
||||
</option>
|
||||
</select>
|
||||
</div><!-- 片区管理员 -->
|
||||
</div><!-- 片区管理员(多选) -->
|
||||
<div class="col-3">
|
||||
<label>片区管理员</label>
|
||||
<Many2XAutocomplete
|
||||
value="state.selectPartner?.display_name"
|
||||
getDomain="getDomain"
|
||||
<MultiSelectAutocomplete
|
||||
value="state.selectPartner"
|
||||
getDomain="() => this.getDomain()"
|
||||
resModel="'res.users'"
|
||||
fieldString="'片区管理员'"
|
||||
activeActions="{}"
|
||||
update.bind="onUpdatePartner"
|
||||
placeholder="'片区管理员'"
|
||||
update="(items) => this.onUpdatePartner(items)"
|
||||
onSearch="() => this.onSearch()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user