1
0
forked from Mapan/odoo17e
odoo17e-kedaikipas58/addons/account_reports/models/account_partner_ledger.py
2024-12-10 09:04:09 +07:00

711 lines
37 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import json
from odoo import api, models, _, fields
from odoo.exceptions import UserError
from odoo.osv import expression
from odoo.tools.misc import format_date, get_lang
from datetime import timedelta
from collections import defaultdict
class PartnerLedgerCustomHandler(models.AbstractModel):
_name = 'account.partner.ledger.report.handler'
_inherit = 'account.report.custom.handler'
_description = 'Partner Ledger Custom Handler'
def _get_custom_display_config(self):
return {
'css_custom_class': 'partner_ledger',
'templates': {
'AccountReportLineName': 'account_reports.PartnerLedgerLineName',
},
}
def _dynamic_lines_generator(self, report, options, all_column_groups_expression_totals, warnings=None):
partner_lines, totals_by_column_group = self._build_partner_lines(report, options)
lines = report._regroup_lines_by_name_prefix(options, partner_lines, '_report_expand_unfoldable_line_partner_ledger_prefix_group', 0)
# Inject sequence on dynamic lines
lines = [(0, line) for line in lines]
# Report total line.
lines.append((0, self._get_report_line_total(options, totals_by_column_group)))
return lines
def _build_partner_lines(self, report, options, level_shift=0):
lines = []
totals_by_column_group = {
column_group_key: {
total: 0.0
for total in ['debit', 'credit', 'balance']
}
for column_group_key in options['column_groups']
}
partners_results = self._query_partners(options)
search_filter = options.get('filter_search_bar', '')
accept_unknown_in_filter = search_filter.lower() in self._get_no_partner_line_label().lower()
for partner, results in partners_results:
if options['export_mode'] == 'print' and search_filter and not partner and not accept_unknown_in_filter:
# When printing and searching for a specific partner, make it so we only show its lines, not the 'Unknown Partner' one, that would be
# shown in case a misc entry with no partner was reconciled with one of the target partner's entries.
continue
partner_values = defaultdict(dict)
for column_group_key in options['column_groups']:
partner_sum = results.get(column_group_key, {})
partner_values[column_group_key]['debit'] = partner_sum.get('debit', 0.0)
partner_values[column_group_key]['credit'] = partner_sum.get('credit', 0.0)
partner_values[column_group_key]['balance'] = partner_sum.get('balance', 0.0)
totals_by_column_group[column_group_key]['debit'] += partner_values[column_group_key]['debit']
totals_by_column_group[column_group_key]['credit'] += partner_values[column_group_key]['credit']
totals_by_column_group[column_group_key]['balance'] += partner_values[column_group_key]['balance']
lines.append(self._get_report_line_partners(options, partner, partner_values, level_shift=level_shift))
return lines, totals_by_column_group
def _report_expand_unfoldable_line_partner_ledger_prefix_group(self, line_dict_id, groupby, options, progress, offset, unfold_all_batch_data=None):
report = self.env['account.report'].browse(options['report_id'])
matched_prefix = report._get_prefix_groups_matched_prefix_from_line_id(line_dict_id)
prefix_domain = [('partner_id.name', '=ilike', f'{matched_prefix}%')]
if self._get_no_partner_line_label().upper().startswith(matched_prefix):
prefix_domain = expression.OR([prefix_domain, [('partner_id', '=', None)]])
expand_options = {
**options,
'forced_domain': options.get('forced_domain', []) + prefix_domain
}
parent_level = len(matched_prefix) * 2
partner_lines, dummy = self._build_partner_lines(report, expand_options, level_shift=parent_level)
for partner_line in partner_lines:
partner_line['id'] = report._build_subline_id(line_dict_id, partner_line['id'])
partner_line['parent_id'] = line_dict_id
lines = report._regroup_lines_by_name_prefix(
options,
partner_lines,
'_report_expand_unfoldable_line_partner_ledger_prefix_group',
parent_level,
matched_prefix=matched_prefix,
parent_line_dict_id=line_dict_id,
)
return {
'lines': lines,
'offset_increment': len(lines),
'has_more': False,
}
def _custom_options_initializer(self, report, options, previous_options=None):
super()._custom_options_initializer(report, options, previous_options=previous_options)
domain = []
company_ids = report.get_report_company_ids(options)
exch_code = self.env['res.company'].browse(company_ids).mapped('currency_exchange_journal_id')
if exch_code:
domain += ['!', '&', '&', '&', ('credit', '=', 0.0), ('debit', '=', 0.0), ('amount_currency', '!=', 0.0), ('journal_id', 'in', exch_code.ids)]
if options['export_mode'] == 'print' and options.get('filter_search_bar'):
domain += [
'|', ('matched_debit_ids.debit_move_id.partner_id.name', 'ilike', options['filter_search_bar']),
'|', ('matched_credit_ids.credit_move_id.partner_id.name', 'ilike', options['filter_search_bar']),
('partner_id.name', 'ilike', options['filter_search_bar']),
]
options['forced_domain'] = options.get('forced_domain', []) + domain
if self.user_has_groups('base.group_multi_currency'):
options['multi_currency'] = True
def _custom_unfold_all_batch_data_generator(self, report, options, lines_to_expand_by_function):
partner_ids_to_expand = []
# Regular case
for line_dict in lines_to_expand_by_function.get('_report_expand_unfoldable_line_partner_ledger', []):
markup, model, model_id = self.env['account.report']._parse_line_id(line_dict['id'])[-1]
if model == 'res.partner':
partner_ids_to_expand.append(model_id)
elif markup == 'no_partner':
partner_ids_to_expand.append(None)
# In case prefix groups are used
no_partner_line_label = self._get_no_partner_line_label().upper()
partner_prefix_domains = []
for line_dict in lines_to_expand_by_function.get('_report_expand_unfoldable_line_partner_ledger_prefix_group', []):
prefix = report._get_prefix_groups_matched_prefix_from_line_id(line_dict['id'])
partner_prefix_domains.append([('name', '=ilike', f'{prefix}%')])
# amls without partners are regrouped "Unknown Partner", which is also used to create prefix groups
if no_partner_line_label.startswith(prefix):
partner_ids_to_expand.append(None)
if partner_prefix_domains:
partner_ids_to_expand += self.env['res.partner'].with_context(active_test=False).search(expression.OR(partner_prefix_domains)).ids
return {
'initial_balances': self._get_initial_balance_values(partner_ids_to_expand, options) if partner_ids_to_expand else {},
# load_more_limit cannot be passed to this call, otherwise it won't be applied per partner but on the whole result.
# We gain perf from batching, but load every result, even if the limit restricts them later.
'aml_values': self._get_aml_values(options, partner_ids_to_expand) if partner_ids_to_expand else {},
}
@api.model
def action_open_partner(self, options, params):
dummy, record_id = self.env['account.report']._get_model_info_from_id(params['id'])
return {
'type': 'ir.actions.act_window',
'res_model': 'res.partner',
'res_id': record_id,
'views': [[False, 'form']],
'view_mode': 'form',
'target': 'current',
}
def _query_partners(self, options):
""" Executes the queries and performs all the computation.
:return: A list of tuple (partner, column_group_values) sorted by the table's model _order:
- partner is a res.parter record.
- column_group_values is a dict(column_group_key, fetched_values), where
- column_group_key is a string identifying a column group, like in options['column_groups']
- fetched_values is a dictionary containing:
- sum: {'debit': float, 'credit': float, 'balance': float}
- (optional) initial_balance: {'debit': float, 'credit': float, 'balance': float}
- (optional) lines: [line_vals_1, line_vals_2, ...]
"""
def assign_sum(row):
fields_to_assign = ['balance', 'debit', 'credit']
if any(not company_currency.is_zero(row[field]) for field in fields_to_assign):
groupby_partners.setdefault(row['groupby'], defaultdict(lambda: defaultdict(float)))
for field in fields_to_assign:
groupby_partners[row['groupby']][row['column_group_key']][field] += row[field]
company_currency = self.env.company.currency_id
# Execute the queries and dispatch the results.
query, params = self._get_query_sums(options)
groupby_partners = {}
self._cr.execute(query, params)
for res in self._cr.dictfetchall():
assign_sum(res)
# Correct the sums per partner, for the lines without partner reconciled with a line having a partner
query, params = self._get_sums_without_partner(options)
self._cr.execute(query, params)
totals = {}
for total_field in ['debit', 'credit', 'balance']:
totals[total_field] = {col_group_key: 0 for col_group_key in options['column_groups']}
for row in self._cr.dictfetchall():
totals['debit'][row['column_group_key']] += row['debit']
totals['credit'][row['column_group_key']] += row['credit']
totals['balance'][row['column_group_key']] += row['balance']
if row['groupby'] not in groupby_partners:
continue
assign_sum(row)
if None in groupby_partners:
# Debit/credit are inverted for the unknown partner as the computation is made regarding the balance of the known partner
for column_group_key in options['column_groups']:
groupby_partners[None][column_group_key]['debit'] += totals['credit'][column_group_key]
groupby_partners[None][column_group_key]['credit'] += totals['debit'][column_group_key]
groupby_partners[None][column_group_key]['balance'] -= totals['balance'][column_group_key]
# Retrieve the partners to browse.
# groupby_partners.keys() contains all account ids affected by:
# - the amls in the current period.
# - the amls affecting the initial balance.
if groupby_partners:
# Note a search is done instead of a browse to preserve the table ordering.
partners = self.env['res.partner'].with_context(active_test=False).search_fetch([('id', 'in', list(groupby_partners.keys()))], ["id", "name", "trust", "company_registry", "vat"])
else:
partners = []
# Add 'Partner Unknown' if needed
if None in groupby_partners.keys():
partners = [p for p in partners] + [None]
return [(partner, groupby_partners[partner.id if partner else None]) for partner in partners]
def _get_query_sums(self, options):
""" Construct a query retrieving all the aggregated sums to build the report. It includes:
- sums for all partners.
- sums for the initial balances.
:param options: The report options.
:return: (query, params)
"""
params = []
queries = []
report = self.env.ref('account_reports.partner_ledger_report')
# Create the currency table.
ct_query = report._get_query_currency_table(options)
for column_group_key, column_group_options in report._split_options_per_column_group(options).items():
tables, where_clause, where_params = report._query_get(column_group_options, 'normal')
params.append(column_group_key)
params += where_params
queries.append(f"""
SELECT
account_move_line.partner_id AS groupby,
%s AS column_group_key,
SUM(ROUND(account_move_line.debit * currency_table.rate, currency_table.precision)) AS debit,
SUM(ROUND(account_move_line.credit * currency_table.rate, currency_table.precision)) AS credit,
SUM(ROUND(account_move_line.balance * currency_table.rate, currency_table.precision)) AS balance
FROM {tables}
LEFT JOIN {ct_query} ON currency_table.company_id = account_move_line.company_id
WHERE {where_clause}
GROUP BY account_move_line.partner_id
""")
return ' UNION ALL '.join(queries), params
def _get_initial_balance_values(self, partner_ids, options):
queries = []
params = []
report = self.env.ref('account_reports.partner_ledger_report')
ct_query = report._get_query_currency_table(options)
for column_group_key, column_group_options in report._split_options_per_column_group(options).items():
# Get sums for the initial balance.
# period: [('date' <= options['date_from'] - 1)]
new_options = self._get_options_initial_balance(column_group_options)
tables, where_clause, where_params = report._query_get(new_options, 'normal', domain=[('partner_id', 'in', partner_ids)])
params.append(column_group_key)
params += where_params
queries.append(f"""
SELECT
account_move_line.partner_id,
%s AS column_group_key,
SUM(ROUND(account_move_line.debit * currency_table.rate, currency_table.precision)) AS debit,
SUM(ROUND(account_move_line.credit * currency_table.rate, currency_table.precision)) AS credit,
SUM(ROUND(account_move_line.balance * currency_table.rate, currency_table.precision)) AS balance
FROM {tables}
LEFT JOIN {ct_query} ON currency_table.company_id = account_move_line.company_id
WHERE {where_clause}
GROUP BY account_move_line.partner_id
""")
self._cr.execute(" UNION ALL ".join(queries), params)
init_balance_by_col_group = {
partner_id: {column_group_key: {} for column_group_key in options['column_groups']}
for partner_id in partner_ids
}
for result in self._cr.dictfetchall():
init_balance_by_col_group[result['partner_id']][result['column_group_key']] = result
return init_balance_by_col_group
def _get_options_initial_balance(self, options):
""" Create options used to compute the initial balances for each partner.
The resulting dates domain will be:
[('date' <= options['date_from'] - 1)]
:param options: The report options.
:return: A copy of the options, modified to match the dates to use to get the initial balances.
"""
new_date_to = fields.Date.from_string(options['date']['date_from']) - timedelta(days=1)
new_date_options = dict(options['date'], date_from=False, date_to=fields.Date.to_string(new_date_to))
return dict(options, date=new_date_options)
def _get_sums_without_partner(self, options):
""" Get the sum of lines without partner reconciled with a line with a partner, grouped by partner. Those lines
should be considered as belonging to the partner for the reconciled amount as it may clear some of the partner
invoice/bill and they have to be accounted in the partner balance."""
queries = []
params = []
report = self.env.ref('account_reports.partner_ledger_report')
ct_query = report._get_query_currency_table(options)
for column_group_key, column_group_options in report._split_options_per_column_group(options).items():
tables, where_clause, where_params = report._query_get(column_group_options, 'normal')
params += [
column_group_key,
column_group_options['date']['date_to'],
*where_params,
]
queries.append(f"""
SELECT
%s AS column_group_key,
aml_with_partner.partner_id AS groupby,
COALESCE(SUM(CASE WHEN aml_with_partner.balance > 0 THEN 0 ELSE ROUND(
partial.amount * currency_table.rate, currency_table.precision) END), 0) AS debit,
COALESCE(SUM(CASE WHEN aml_with_partner.balance < 0 THEN 0 ELSE ROUND(
partial.amount * currency_table.rate, currency_table.precision) END), 0) AS credit,
COALESCE(SUM(- sign(aml_with_partner.balance) * ROUND(
partial.amount * currency_table.rate, currency_table.precision)), 0) AS balance
FROM {tables}
JOIN account_partial_reconcile partial
ON account_move_line.id = partial.debit_move_id OR account_move_line.id = partial.credit_move_id
JOIN account_move_line aml_with_partner ON
(aml_with_partner.id = partial.debit_move_id OR aml_with_partner.id = partial.credit_move_id)
AND aml_with_partner.partner_id IS NOT NULL
LEFT JOIN {ct_query} ON currency_table.company_id = account_move_line.company_id
WHERE partial.max_date <= %s AND {where_clause}
AND account_move_line.partner_id IS NULL
GROUP BY aml_with_partner.partner_id
""")
return " UNION ALL ".join(queries), params
def _report_expand_unfoldable_line_partner_ledger(self, line_dict_id, groupby, options, progress, offset, unfold_all_batch_data=None):
def init_load_more_progress(line_dict):
return {
column['column_group_key']: line_col.get('no_format', 0)
for column, line_col in zip(options['columns'], line_dict['columns'])
if column['expression_label'] == 'balance'
}
report = self.env.ref('account_reports.partner_ledger_report')
markup, model, record_id = report._parse_line_id(line_dict_id)[-1]
if model != 'res.partner':
raise UserError(_("Wrong ID for partner ledger line to expand: %s", line_dict_id))
prefix_groups_count = 0
for markup, dummy1, dummy2 in report._parse_line_id(line_dict_id):
if markup.startswith('groupby_prefix_group:'):
prefix_groups_count += 1
level_shift = prefix_groups_count * 2
lines = []
# Get initial balance
if offset == 0:
if unfold_all_batch_data:
init_balance_by_col_group = unfold_all_batch_data['initial_balances'][record_id]
else:
init_balance_by_col_group = self._get_initial_balance_values([record_id], options)[record_id]
initial_balance_line = report._get_partner_and_general_ledger_initial_balance_line(options, line_dict_id, init_balance_by_col_group, level_shift=level_shift)
if initial_balance_line:
lines.append(initial_balance_line)
# For the first expansion of the line, the initial balance line gives the progress
progress = init_load_more_progress(initial_balance_line)
limit_to_load = report.load_more_limit + 1 if report.load_more_limit and options['export_mode'] != 'print' else None
if unfold_all_batch_data:
aml_results = unfold_all_batch_data['aml_values'][record_id]
else:
aml_results = self._get_aml_values(options, [record_id], offset=offset, limit=limit_to_load)[record_id]
has_more = False
treated_results_count = 0
next_progress = progress
for result in aml_results:
if options['export_mode'] != 'print' and report.load_more_limit and treated_results_count == report.load_more_limit:
# We loaded one more than the limit on purpose: this way we know we need a "load more" line
has_more = True
break
new_line = self._get_report_line_move_line(options, result, line_dict_id, next_progress, level_shift=level_shift)
lines.append(new_line)
next_progress = init_load_more_progress(new_line)
treated_results_count += 1
return {
'lines': lines,
'offset_increment': treated_results_count,
'has_more': has_more,
'progress': next_progress
}
def _get_additional_column_aml_values(self):
"""
Allows customization of additional fields in the partner ledger query.
This method is intended to be overridden by other modules to add custom fields
to the partner ledger query. By default, it returns an empty string.
"""
return ""
def _get_aml_values(self, options, partner_ids, offset=0, limit=None):
rslt = {partner_id: [] for partner_id in partner_ids}
partner_ids_wo_none = [x for x in partner_ids if x]
directly_linked_aml_partner_clauses = []
directly_linked_aml_partner_params = []
indirectly_linked_aml_partner_params = []
indirectly_linked_aml_partner_clause = 'aml_with_partner.partner_id IS NOT NULL'
if None in partner_ids:
directly_linked_aml_partner_clauses.append('account_move_line.partner_id IS NULL')
if partner_ids_wo_none:
directly_linked_aml_partner_clauses.append('account_move_line.partner_id IN %s')
directly_linked_aml_partner_params.append(tuple(partner_ids_wo_none))
indirectly_linked_aml_partner_clause = 'aml_with_partner.partner_id IN %s'
indirectly_linked_aml_partner_params.append(tuple(partner_ids_wo_none))
directly_linked_aml_partner_clause = '(' + ' OR '.join(directly_linked_aml_partner_clauses) + ')'
ct_query = self.env['account.report']._get_query_currency_table(options)
queries = []
all_params = []
lang = self.env.lang or get_lang(self.env).code
journal_name = f"COALESCE(journal.name->>'{lang}', journal.name->>'en_US')" if \
self.pool['account.journal'].name.translate else 'journal.name'
account_name = f"COALESCE(account.name->>'{lang}', account.name->>'en_US')" if \
self.pool['account.account'].name.translate else 'account.name'
report = self.env.ref('account_reports.partner_ledger_report')
additional_columns = self._get_additional_column_aml_values()
for column_group_key, group_options in report._split_options_per_column_group(options).items():
tables, where_clause, where_params = report._query_get(group_options, 'strict_range')
all_params += [
column_group_key,
*where_params,
*directly_linked_aml_partner_params,
column_group_key,
*indirectly_linked_aml_partner_params,
*where_params,
group_options['date']['date_from'],
group_options['date']['date_to'],
]
# For the move lines directly linked to this partner
queries.append(f'''
SELECT
account_move_line.id,
account_move_line.date_maturity,
account_move_line.name,
account_move_line.ref,
account_move_line.company_id,
account_move_line.account_id,
account_move_line.payment_id,
account_move_line.partner_id,
account_move_line.currency_id,
account_move_line.amount_currency,
account_move_line.matching_number,
{additional_columns}
COALESCE(account_move_line.invoice_date, account_move_line.date) AS invoice_date,
ROUND(account_move_line.debit * currency_table.rate, currency_table.precision) AS debit,
ROUND(account_move_line.credit * currency_table.rate, currency_table.precision) AS credit,
ROUND(account_move_line.balance * currency_table.rate, currency_table.precision) AS balance,
account_move.name AS move_name,
account_move.move_type AS move_type,
account.code AS account_code,
{account_name} AS account_name,
journal.code AS journal_code,
{journal_name} AS journal_name,
%s AS column_group_key,
'directly_linked_aml' AS key,
0 AS partial_id
FROM {tables}
JOIN account_move ON account_move.id = account_move_line.move_id
LEFT JOIN {ct_query} ON currency_table.company_id = account_move_line.company_id
LEFT JOIN res_company company ON company.id = account_move_line.company_id
LEFT JOIN res_partner partner ON partner.id = account_move_line.partner_id
LEFT JOIN account_account account ON account.id = account_move_line.account_id
LEFT JOIN account_journal journal ON journal.id = account_move_line.journal_id
WHERE {where_clause} AND {directly_linked_aml_partner_clause}
ORDER BY account_move_line.date, account_move_line.id
''')
# For the move lines linked to no partner, but reconciled with this partner. They will appear in grey in the report
queries.append(f'''
SELECT
account_move_line.id,
account_move_line.date_maturity,
account_move_line.name,
account_move_line.ref,
account_move_line.company_id,
account_move_line.account_id,
account_move_line.payment_id,
aml_with_partner.partner_id,
account_move_line.currency_id,
account_move_line.amount_currency,
account_move_line.matching_number,
{additional_columns}
COALESCE(account_move_line.invoice_date, account_move_line.date) AS invoice_date,
CASE WHEN aml_with_partner.balance > 0 THEN 0 ELSE ROUND(
partial.amount * currency_table.rate, currency_table.precision
) END AS debit,
CASE WHEN aml_with_partner.balance < 0 THEN 0 ELSE ROUND(
partial.amount * currency_table.rate, currency_table.precision
) END AS credit,
- sign(aml_with_partner.balance) * ROUND(
partial.amount * currency_table.rate, currency_table.precision
) AS balance,
account_move.name AS move_name,
account_move.move_type AS move_type,
account.code AS account_code,
{account_name} AS account_name,
journal.code AS journal_code,
{journal_name} AS journal_name,
%s AS column_group_key,
'indirectly_linked_aml' AS key,
partial.id AS partial_id
FROM {tables}
LEFT JOIN {ct_query} ON currency_table.company_id = account_move_line.company_id,
account_partial_reconcile partial,
account_move,
account_move_line aml_with_partner,
account_journal journal,
account_account account
WHERE
(account_move_line.id = partial.debit_move_id OR account_move_line.id = partial.credit_move_id)
AND account_move_line.partner_id IS NULL
AND account_move.id = account_move_line.move_id
AND (aml_with_partner.id = partial.debit_move_id OR aml_with_partner.id = partial.credit_move_id)
AND {indirectly_linked_aml_partner_clause}
AND journal.id = account_move_line.journal_id
AND account.id = account_move_line.account_id
AND {where_clause}
AND partial.max_date BETWEEN %s AND %s
ORDER BY account_move_line.date, account_move_line.id
''')
query = '(' + ') UNION ALL ('.join(queries) + ')'
if offset:
query += ' OFFSET %s '
all_params.append(offset)
if limit:
query += ' LIMIT %s '
all_params.append(limit)
self._cr.execute(query, all_params)
for aml_result in self._cr.dictfetchall():
if aml_result['key'] == 'indirectly_linked_aml':
# Append the line to the partner found through the reconciliation.
if aml_result['partner_id'] in rslt:
rslt[aml_result['partner_id']].append(aml_result)
# Balance it with an additional line in the Unknown Partner section but having reversed amounts.
if None in rslt:
rslt[None].append({
**aml_result,
'debit': aml_result['credit'],
'credit': aml_result['debit'],
'balance': -aml_result['balance'],
})
else:
rslt[aml_result['partner_id']].append(aml_result)
return rslt
####################################################
# COLUMNS/LINES
####################################################
def _get_report_line_partners(self, options, partner, partner_values, level_shift=0):
company_currency = self.env.company.currency_id
unfoldable = False
column_values = []
report = self.env['account.report'].browse(options['report_id'])
for column in options['columns']:
col_expr_label = column['expression_label']
value = partner_values[column['column_group_key']].get(col_expr_label)
unfoldable = unfoldable or (col_expr_label in ('debit', 'credit') and not company_currency.is_zero(value))
column_values.append(report._build_column_dict(value, column, options=options))
line_id = report._get_generic_line_id('res.partner', partner.id) if partner else report._get_generic_line_id('res.partner', None, markup='no_partner')
return {
'id': line_id,
'name': partner is not None and (partner.name or '')[:128] or self._get_no_partner_line_label(),
'columns': column_values,
'level': 1 + level_shift,
'trust': partner.trust if partner else None,
'unfoldable': unfoldable,
'unfolded': line_id in options['unfolded_lines'] or options['unfold_all'],
'expand_function': '_report_expand_unfoldable_line_partner_ledger',
}
def _get_no_partner_line_label(self):
return _('Unknown Partner')
@api.model
def _format_aml_name(self, line_name, move_ref, move_name=None):
''' Format the display of an account.move.line record. As its very costly to fetch the account.move.line
records, only line_name, move_ref, move_name are passed as parameters to deal with sql-queries more easily.
:param line_name: The name of the account.move.line record.
:param move_ref: The reference of the account.move record.
:param move_name: The name of the account.move record.
:return: The formatted name of the account.move.line record.
'''
names = []
if move_name is not None and move_name != '/':
names.append(move_name)
if move_ref and move_ref != '/':
names.append(move_ref)
if line_name and line_name != move_name and line_name != '/':
names.append(line_name)
name = ' - '.join(names)
return name
def _get_report_line_move_line(self, options, aml_query_result, partner_line_id, init_bal_by_col_group, level_shift=0):
if aml_query_result['payment_id']:
caret_type = 'account.payment'
else:
caret_type = 'account.move.line'
columns = []
report = self.env['account.report'].browse(options['report_id'])
for column in options['columns']:
col_expr_label = column['expression_label']
col_value = aml_query_result[col_expr_label] if column['column_group_key'] == aml_query_result['column_group_key'] else None
if col_value is None:
columns.append(report._build_column_dict(None, None))
else:
currency = False
if col_expr_label == 'balance':
col_value += init_bal_by_col_group[column['column_group_key']]
if col_expr_label == 'amount_currency':
currency = self.env['res.currency'].browse(aml_query_result['currency_id'])
if currency == self.env.company.currency_id:
col_value = ''
columns.append(report._build_column_dict(col_value, column, options=options, currency=currency))
return {
'id': report._get_generic_line_id('account.move.line', aml_query_result['id'], parent_line_id=partner_line_id, markup=aml_query_result['partial_id']),
'parent_id': partner_line_id,
'name': self._format_aml_name(aml_query_result['name'], aml_query_result['ref'], aml_query_result['move_name']),
'columns': columns,
'caret_options': caret_type,
'level': 3 + level_shift,
}
def _get_report_line_total(self, options, totals_by_column_group):
column_values = []
report = self.env['account.report'].browse(options['report_id'])
for column in options['columns']:
col_value = totals_by_column_group[column['column_group_key']].get(column['expression_label'])
column_values.append(report._build_column_dict(col_value, column, options=options))
return {
'id': report._get_generic_line_id(None, None, markup='total'),
'name': _('Total'),
'level': 1,
'columns': column_values,
}
def open_journal_items(self, options, params):
params['view_ref'] = 'account.view_move_line_tree_grouped_partner'
report = self.env['account.report'].browse(options['report_id'])
action = report.open_journal_items(options=options, params=params)
action.get('context', {}).update({'search_default_group_by_account': 0, 'search_default_group_by_partner': 1})
return action