[IMP] account: new journals audit report

Improvement in two ways:

- Implement a new, accounting report version of the existing journals audit
pdf report, and remove the old journal audit report (PDF only).
- Remove the menu items in "accounting" that opens the group by view of journal
items with different filters. Now, these will be linked to actions on lines in
the different reports available to the user.
Also render the "journal items" menu visible without debug mode.

Task id #2838182

closes odoo/odoo#92438

Related: odoo/upgrade#3560
Related: odoo/enterprise#27840
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
This commit is contained in:
Nicolas (vin)
2022-06-02 12:05:07 +02:00
parent 143f632d96
commit f5541768a6
6 changed files with 4 additions and 362 deletions
-1
View File
@@ -55,7 +55,6 @@ You could use this simplified accounting in case you work with an (external) acc
'report/account_invoice_report_view.xml',
'views/account_cash_rounding_view.xml',
'wizard/account_report_common_view.xml',
'views/report_journal.xml',
'views/tax_adjustments.xml',
'wizard/wizard_tax_adjustments_view.xml',
'views/ir_module_views.xml',
-1
View File
@@ -2,5 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import account_invoice_report
from . import account_journal
from . import account_hash_integrity_templates
-121
View File
@@ -1,121 +0,0 @@
# -*- coding: utf-8 -*-
import time
from odoo import api, models, _
from odoo.exceptions import UserError
class ReportJournal(models.AbstractModel):
_name = 'report.account.report_journal'
_description = 'Account Journal Report'
def lines(self, target_move, journal_ids, sort_selection, data):
if isinstance(journal_ids, int):
journal_ids = [journal_ids]
move_state = ['draft', 'posted']
if target_move == 'posted':
move_state = ['posted']
query_get_clause = self._get_query_get_clause(data)
params = [tuple(move_state), tuple(journal_ids)] + query_get_clause[2]
query = 'SELECT "account_move_line".id FROM ' + query_get_clause[0] + ', account_move am, account_account acc WHERE "account_move_line".account_id = acc.id AND "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' ORDER BY '
if sort_selection == 'date':
query += '"account_move_line".date'
else:
query += 'am.name'
query += ', "account_move_line".move_id, acc.code'
self.env.cr.execute(query, tuple(params))
ids = (x[0] for x in self.env.cr.fetchall())
return self.env['account.move.line'].browse(ids)
def _sum_debit(self, data, journal_id):
move_state = ['draft', 'posted']
if data['form'].get('target_move', 'all') == 'posted':
move_state = ['posted']
query_get_clause = self._get_query_get_clause(data)
params = [tuple(move_state), tuple(journal_id.ids)] + query_get_clause[2]
self.env.cr.execute('SELECT SUM(debit) FROM ' + query_get_clause[0] + ', account_move am '
'WHERE "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' ',
tuple(params))
return self.env.cr.fetchone()[0] or 0.0
def _sum_credit(self, data, journal_id):
move_state = ['draft', 'posted']
if data['form'].get('target_move', 'all') == 'posted':
move_state = ['posted']
query_get_clause = self._get_query_get_clause(data)
params = [tuple(move_state), tuple(journal_id.ids)] + query_get_clause[2]
self.env.cr.execute('SELECT SUM(credit) FROM ' + query_get_clause[0] + ', account_move am '
'WHERE "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' ',
tuple(params))
return self.env.cr.fetchone()[0] or 0.0
def _get_taxes(self, data, journal_id):
move_state = ['draft', 'posted']
if data['form'].get('target_move', 'all') == 'posted':
move_state = ['posted']
query_get_clause = self._get_query_get_clause(data)
params = [tuple(move_state), tuple(journal_id.ids)] + query_get_clause[2]
query = """
SELECT rel.account_tax_id, SUM("account_move_line".balance) AS base_amount
FROM account_move_line_account_tax_rel rel, """ + query_get_clause[0] + """
LEFT JOIN account_move am ON "account_move_line".move_id = am.id
WHERE "account_move_line".id = rel.account_move_line_id
AND am.state IN %s
AND "account_move_line".journal_id IN %s
AND """ + query_get_clause[1] + """
GROUP BY rel.account_tax_id"""
self.env.cr.execute(query, tuple(params))
ids = []
base_amounts = {}
for row in self.env.cr.fetchall():
ids.append(row[0])
base_amounts[row[0]] = row[1]
res = {}
for tax in self.env['account.tax'].browse(ids):
self.env.cr.execute('SELECT sum(debit - credit) FROM ' + query_get_clause[0] + ', account_move am '
'WHERE "account_move_line".move_id=am.id AND am.state IN %s AND "account_move_line".journal_id IN %s AND ' + query_get_clause[1] + ' AND tax_line_id = %s',
tuple(params + [tax.id]))
res[tax] = {
'base_amount': base_amounts[tax.id],
'tax_amount': self.env.cr.fetchone()[0] or 0.0,
}
if journal_id.type == 'sale':
#sales operation are credits
res[tax]['base_amount'] = res[tax]['base_amount'] * -1
res[tax]['tax_amount'] = res[tax]['tax_amount'] * -1
return res
def _get_query_get_clause(self, data):
return self.env['account.move.line'].with_context(data['form'].get('used_context', {}))._query_get()
@api.model
def _get_report_values(self, docids, data=None):
if not data.get('form'):
raise UserError(_("Form content is missing, this report cannot be printed."))
target_move = data['form'].get('target_move', 'all')
sort_selection = data['form'].get('sort_selection', 'date')
res = {}
for journal in data['form']['journal_ids']:
res[journal] = self.with_context(data['form'].get('used_context', {})).lines(target_move, journal, sort_selection, data)
return {
'doc_ids': data['form']['journal_ids'],
'doc_model': self.env['account.journal'],
'data': data,
'docs': self.env['account.journal'].browse(data['form']['journal_ids']),
'time': time,
'lines': res,
'sum_credit': self._sum_credit,
'sum_debit': self._sum_debit,
'get_taxes': self._get_taxes,
'company_id': self.env['res.company'].browse(
data['form']['company_id'][0]),
}
+1 -11
View File
@@ -26,17 +26,7 @@
<menuitem id="menu_finance_entries" name="Accounting" sequence="4" groups="account.group_account_readonly">
<menuitem id="menu_finance_entries_accounting_miscellaneous" name="Miscellaneous" sequence="1">
<menuitem id="menu_action_move_journal_line_form" action="action_move_journal_line" groups="account.group_account_readonly" sequence="1"/>
<menuitem id="menu_action_account_moves_all" action="action_account_moves_all" groups="base.group_no_one" sequence="10"/>
</menuitem>
<menuitem id="menu_finance_entries_accounting_journals" name="Journals" sequence="2">
<menuitem id="menu_action_account_moves_journal_sales" action="action_account_moves_journal_sales" groups="account.group_account_readonly" sequence="1"/>
<menuitem id="menu_action_account_moves_journal_purchase" action="action_account_moves_journal_purchase" groups="account.group_account_readonly" sequence="2"/>
<menuitem id="menu_action_account_moves_journal_bank_cash" action="action_account_moves_journal_bank_cash" groups="account.group_account_readonly" sequence="3"/>
<menuitem id="menu_action_account_moves_journal_misc" action="action_account_moves_journal_misc" groups="account.group_account_readonly" sequence="4"/>
</menuitem>
<menuitem id="menu_finance_entries_accounting_ledgers" name="Ledgers" sequence="3">
<menuitem id="menu_action_account_moves_ledger_general" action="action_account_moves_ledger_general" groups="account.group_account_readonly" sequence="1"/>
<menuitem id="menu_action_account_moves_ledger_partner" action="action_account_moves_ledger_partner" groups="account.group_account_readonly" sequence="2"/>
<menuitem id="menu_action_account_moves_all" action="action_account_moves_all" groups="account.group_account_readonly" sequence="10"/>
</menuitem>
<menuitem id="menu_finance_entries_management" name="Management" sequence="10" groups="account.group_account_invoice,account.group_account_readonly"/>
<menuitem id="menu_finance_entries_generate_entries" name="Generate Entries"/>
@@ -370,6 +370,9 @@
<separator/>
<filter string="Date" name="date" date="date"/>
<separator/>
<filter string="Report Dates" name="date_between" domain="[('date', '&gt;=', context.get('date_from')), ('date', '&lt;=', context.get('date_to'))]" invisible="1"/>
<separator/>
<filter string="Report Analytic Accounts" name="analytic_accounts" domain="[('analytic_account_id', 'in', context.get('analytic_ids'))]" invisible="1"/>
<group expand="0" string="Group By">
<filter string="Journal Entry" name="group_by_move" domain="[]" context="{'group_by': 'move_id'}"/>
<filter string="Account" name="group_by_account" domain="[]" context="{'group_by': 'account_id'}"/>
-228
View File
@@ -1,228 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_journal">
<t t-call="web.html_container">
<t t-set="data_report_margin_top" t-value="12"/>
<t t-set="data_report_header_spacing" t-value="9"/>
<t t-set="data_report_dpi" t-value="110"/>
<t t-foreach="docs" t-as="o">
<t t-if="lines[o.id]">
<t t-if="not o" t-set="o" t-value="doc"/>
<t t-if="not company">
<!-- Multicompany -->
<t t-if="company_id">
<t t-set="company" t-value="company_id"/>
</t>
<t t-elif="o and 'company_id' in o and o.company_id.sudo()">
<t t-set="company" t-value="o.company_id.sudo()"/>
</t>
<t t-else="else">
<t t-set="company" t-value="res_company"/>
</t>
</t>
<div class="header">
<div class="row">
<div class="col-2">
<span t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"/>
</div>
<div class="col-8 text-center">
<span t-esc="company.name"/> - <span t-esc="o.name"/>
(<span t-if="data['form']['target_move'] == 'all'">Posted and Draft Entries</span><span t-if="data['form']['target_move'] == 'posted'">Posted Entries only</span>)
</div>
<div class="col-2 text-right">
<ul class="list-inline">
<li class="list-inline-item"><span class="page"/></li>
<li class="list-inline-item">/</li>
<li class="list-inline-item"><span class="topage"/></li>
</ul>
</div>
</div>
<t t-if="data['form'].get('date_from') or data['form'].get('date_to')">
<div class="row">
<div class="col-8 offset-2 text-center">
<t t-if="data['form'].get('date_from')">
From : <span t-esc="data['form'].get('date_from')"/>
</t>
<t t-if="data['form'].get('date_from') and data['form'].get('date_to')">
-
</t>
<t t-if="data['form'].get('date_to')">
To : <span t-esc="data['form'].get('date_to')"/>
</t>
</div>
</div>
</t>
</div>
<div class="article" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id" t-att-data-oe-lang="o and o.env.context.get('lang')">
<div class="page">
<h2><t t-esc="o.name"/> Journal<span t-if="data['form']['target_move'] == 'all'"> - Posted and Draft Entries</span><span t-if="data['form']['target_move'] == 'posted'"> - Posted Entries Only</span></h2>
<table class="table table-sm table-striped mt-4" id="move_table">
<thead>
<tr>
<th t-if="data['form'].get('sort_selection') == 'move_name'">Move</th>
<th t-if="data['form'].get('sort_selection') == 'move_name'">Date</th>
<th t-if="data['form'].get('sort_selection') == 'date'">Date</th>
<th t-if="data['form'].get('sort_selection') == 'date'">Move</th>
<!-- Set a minimum width for columns, otherwise the line breaks too early -->
<th style="min-width: 150px">Partner</th>
<th style="min-width: 250px">Account</th>
<th style="min-width: 350px">Label</th>
<th t-if="data['form']['amount_currency']" style="text-align: right;">Currency</th>
<th style="text-align: right;">Debit</th>
<th style="text-align: right;">Credit</th>
</tr>
</thead>
<tbody>
<t t-set="last_am" t-value=""/>
<t t-set="last_date" t-value=""/>
<t t-set="last_partner" t-value=""/>
<tr t-foreach="lines[o.id]" t-as="aml">
<t t-if="data['form'].get('sort_selection') == 'move_name'">
<t t-set="am_name" t-value="aml.move_id.name != '/' and aml.move_id.name or ('*'+str(aml.move_id.id))"/>
<t t-if="last_am == am_name">
<td/>
</t>
<t t-else="">
<td><span t-esc="am_name" class="font-weight-bold"/></td>
<t t-set="last_am" t-value="am_name"/>
<!-- Reset these when changing move -->
<t t-set="last_date" t-value=""/>
<t t-set="last_partner" t-value=""/>
</t>
<t t-if="last_date == aml.date">
<td/>
</t>
<t t-else="">
<td><span t-field="aml.date"/></td>
<t t-set="last_date" t-value="aml.date"/>
</t>
</t>
<t t-else="">
<t t-set="am_name" t-value="aml.move_id.name != '/' and aml.move_id.name or ('*'+str(aml.move_id.id))"/>
<t t-if="last_date == aml.date and last_am == am_name">
<td/>
</t>
<t t-else="">
<td><span t-field="aml.date" class="font-weight-bold"/></td>
<t t-set="last_date" t-value="aml.date"/>
<!-- Reset these when changing data -->
<t t-set="last_am" t-value=""/>
<t t-set="last_partner" t-value=""/>
</t>
<t t-if="last_am == am_name">
<td/>
</t>
<t t-else="">
<td><span t-esc="am_name"/></td>
<t t-set="last_am" t-value="am_name"/>
<t t-set="last_partner" t-value=""/>
</t>
</t>
<t t-set="partner_name" t-value="aml.sudo().partner_id and aml.sudo().partner_id.name and aml.sudo().partner_id.name or ''"/>
<!-- general journals always show partners, as we can have multiple != ones in a single move -->
<t t-if="last_partner == partner_name and o.type != 'general'">
<td/>
</t>
<t t-else="">
<td><span t-esc="partner_name"/></td>
<t t-set="last_partner" t-value="partner_name"/>
</t>
<td><span t-field="aml.account_id.code"/> <span t-field="aml.account_id.name"/></td>
<td><span t-esc="aml.name"/></td>
<td t-if="data['form']['amount_currency'] and aml.amount_currency" class="pull-right">
<span class="text-monospace"
t-esc="aml.amount_currency"
t-options="{'widget': 'monetary', 'display_currency': aml.currency_id}"/>
</td>
<td style="text-align: right;">
<span t-if="not (company_id or res_company).currency_id.is_zero(aml.debit)"
t-esc="aml.debit"
t-options="{
'widget': 'monetary',
'display_currency': (company_id or res_company).currency_id
}"
class="text-monospace"/>
</td>
<td style="text-align: right;">
<span t-if="not (company_id or res_company).currency_id.is_zero(aml.credit)"
t-esc="aml.credit"
t-options="{
'widget': 'monetary',
'display_currency': (company_id or res_company).currency_id
}"
class="text-monospace"/>
</td>
</tr>
<tr class="bg-white">
<td/>
<td/>
<td/>
<td/>
<td class="text-right"><strong>Total</strong></td>
<td style="text-align: right;">
<span t-esc="sum_debit(data, o)"
t-options="{
'widget': 'monetary',
'display_currency': (company_id or res_company).currency_id
}"
class="font-weight-bold text-monospace"/>
</td>
<td style="text-align: right;">
<span t-esc="sum_credit(data, o)"
t-options="{
'widget': 'monetary',
'display_currency': (company_id or res_company).currency_id
}"
class="font-weight-bold text-monospace"/>
</td>
<td t-if="data['form']['amount_currency']"/>
</tr>
</tbody>
</table>
<div class="row" style="page-break-inside: avoid" id="tax_section">
<t t-set="taxes" t-value="get_taxes(data, o)"/>
<div class="col-5" t-if="taxes">
<table class="table table-sm table-striped" id="tax_table">
<thead>
<tr><th colspan="3">Taxes Applied</th></tr>
<tr>
<th>Name</th>
<th style="text-align: right;">Base Amount</th>
<th style="text-align: right;">Tax Amount</th>
</tr>
</thead>
<tbody>
<tr t-foreach="taxes" t-as="tax">
<td><span t-esc="tax.name"/></td>
<td style="text-align: right;">
<span t-esc="taxes[tax]['base_amount']"
t-options="{
'widget': 'monetary',
'display_currency': (company_id or res_company).currency_id
}"
class="text-monospace"/>
</td>
<td style="text-align: right;">
<span t-esc="taxes[tax]['tax_amount']"
t-options="{
'widget': 'monetary',
'display_currency': (company_id or res_company).currency_id
}"
class="text-monospace"/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</t>
</t>
</t>
</template>
</odoo>