mirror of
https://github.com/bringout/oca-ocb-accounting.git
synced 2026-04-23 18:02:03 +02:00
Initial commit: Accounting packages
This commit is contained in:
commit
4ef34c2317
2661 changed files with 1709616 additions and 0 deletions
5
odoo-bringout-oca-ocb-account/account/report/__init__.py
Normal file
5
odoo-bringout-oca-ocb-account/account/report/__init__.py
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import account_invoice_report
|
||||
from . import account_hash_integrity_templates
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,22 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class ReportAccountHashIntegrity(models.AbstractModel):
|
||||
_name = 'report.account.report_hash_integrity'
|
||||
_description = 'Get hash integrity result as PDF.'
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
if data:
|
||||
data.update(self.env.company._check_hash_integrity())
|
||||
else:
|
||||
data = self.env.company._check_hash_integrity()
|
||||
return {
|
||||
'doc_ids' : docids,
|
||||
'doc_model' : self.env['res.company'],
|
||||
'data' : data,
|
||||
'docs' : self.env['res.company'].browse(self.env.company.id),
|
||||
}
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<odoo>
|
||||
<data>
|
||||
<template id="report_hash_integrity">
|
||||
<t t-call="web.html_container">
|
||||
<t t-foreach="docs" t-as="company">
|
||||
<t t-call="web.external_layout">
|
||||
<div class="page">
|
||||
<div class="row" id="hash_header">
|
||||
<div class="col-12">
|
||||
<br/>
|
||||
<h2>Hash Integrity Result - <span t-esc="data['printing_date']"/></h2>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12" id="hash_config_review">
|
||||
<br/>
|
||||
<h3>Configuration review</h3>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<table class="table table-bordered" style="table-layout: fixed" id="hash_config_table">
|
||||
<thead style="display: table-row-group">
|
||||
<tr>
|
||||
<th class="text-center" style="width: 30%" scope="col">Journal</th>
|
||||
<th class="text-center" style="width: 20%" scope="col">Inalterability check</th>
|
||||
<th class="text-center" style="width: 50%" scope="col">Coverage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="data['results']" t-as="result">
|
||||
<tr>
|
||||
<td>
|
||||
[<span t-esc="result['journal_code']"/>] <span t-esc="result['journal_name']"/>
|
||||
</td>
|
||||
<td class="text-center"><span t-esc="result['restricted_by_hash_table']"/></td>
|
||||
<td><span t-esc="result['msg_cover']"/></td>
|
||||
</tr>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<t t-if="any(result['first_hash'] != 'None' for result in data['results'])">
|
||||
<div class="row" style="page-break-before:always;">
|
||||
<div class="col-12" id="hash_data_consistency">
|
||||
<br/>
|
||||
<h3>Data consistency check</h3>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12" id="hash_data_consistency_table">
|
||||
<table class="table table-bordered" style="table-layout: fixed">
|
||||
<thead style="display: table-row-group">
|
||||
<tr>
|
||||
<th class="text-center" style="width: 20%" scope="col">Journal</th>
|
||||
<th class="text-center" style="width: 20%" scope="col">First Hash</th>
|
||||
<th class="text-center" style="width: 20%" scope="col">First Entry</th>
|
||||
<th class="text-center" style="width: 20%" scope="col">Last Hash</th>
|
||||
<th class="text-center" style="width: 20%" scope="col">Last Entry</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<t t-foreach="data['results']" t-as="result">
|
||||
<t t-if="result['first_hash'] != 'None'">
|
||||
<tr>
|
||||
<td><span t-esc="result['journal_code']"/></td>
|
||||
<td><span t-esc="result['first_hash']"/></td>
|
||||
<td>
|
||||
<span t-esc="result['first_move_name']"/> <br/>
|
||||
<span t-esc="result['first_move_date']"/>
|
||||
</td>
|
||||
<td><span t-esc="result['last_hash']"/></td>
|
||||
<td>
|
||||
<span t-esc="result['last_move_name']"/> <br/>
|
||||
<span t-esc="result['last_move_date']"/>
|
||||
</td>
|
||||
</tr>
|
||||
</t>
|
||||
</t>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="hash_last_div">
|
||||
<div class="col-12" id="hash_chain_compliant">
|
||||
<br/>
|
||||
<h6>
|
||||
The hash chain is compliant: it is not possible to alter the
|
||||
data without breaking the hash chain for subsequent parts.
|
||||
</h6>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</template>
|
||||
</data>
|
||||
</odoo>
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api
|
||||
from odoo.addons.account.models.account_move import PAYMENT_STATE_SELECTION
|
||||
|
||||
from functools import lru_cache
|
||||
|
||||
|
||||
class AccountInvoiceReport(models.Model):
|
||||
_name = "account.invoice.report"
|
||||
_description = "Invoices Statistics"
|
||||
_auto = False
|
||||
_rec_name = 'invoice_date'
|
||||
_order = 'invoice_date desc'
|
||||
|
||||
# ==== Invoice fields ====
|
||||
move_id = fields.Many2one('account.move', readonly=True)
|
||||
journal_id = fields.Many2one('account.journal', string='Journal', readonly=True)
|
||||
company_id = fields.Many2one('res.company', string='Company', readonly=True)
|
||||
company_currency_id = fields.Many2one('res.currency', string='Company Currency', readonly=True)
|
||||
partner_id = fields.Many2one('res.partner', string='Partner', readonly=True)
|
||||
commercial_partner_id = fields.Many2one('res.partner', string='Main Partner')
|
||||
country_id = fields.Many2one('res.country', string="Country")
|
||||
invoice_user_id = fields.Many2one('res.users', string='Salesperson', readonly=True)
|
||||
move_type = fields.Selection([
|
||||
('out_invoice', 'Customer Invoice'),
|
||||
('in_invoice', 'Vendor Bill'),
|
||||
('out_refund', 'Customer Credit Note'),
|
||||
('in_refund', 'Vendor Credit Note'),
|
||||
], readonly=True)
|
||||
state = fields.Selection([
|
||||
('draft', 'Draft'),
|
||||
('posted', 'Open'),
|
||||
('cancel', 'Cancelled')
|
||||
], string='Invoice Status', readonly=True)
|
||||
payment_state = fields.Selection(selection=PAYMENT_STATE_SELECTION, string='Payment Status', readonly=True)
|
||||
fiscal_position_id = fields.Many2one('account.fiscal.position', string='Fiscal Position', readonly=True)
|
||||
invoice_date = fields.Date(readonly=True, string="Invoice Date")
|
||||
|
||||
# ==== Invoice line fields ====
|
||||
quantity = fields.Float(string='Product Quantity', readonly=True)
|
||||
product_id = fields.Many2one('product.product', string='Product', readonly=True)
|
||||
product_uom_id = fields.Many2one('uom.uom', string='Unit of Measure', readonly=True)
|
||||
product_categ_id = fields.Many2one('product.category', string='Product Category', readonly=True)
|
||||
invoice_date_due = fields.Date(string='Due Date', readonly=True)
|
||||
account_id = fields.Many2one('account.account', string='Revenue/Expense Account', readonly=True, domain=[('deprecated', '=', False)])
|
||||
price_subtotal = fields.Float(string='Untaxed Total', readonly=True)
|
||||
price_total = fields.Float(string='Total in Currency', readonly=True)
|
||||
price_average = fields.Float(string='Average Price', readonly=True, group_operator="avg")
|
||||
currency_id = fields.Many2one('res.currency', string='Currency', readonly=True)
|
||||
|
||||
_depends = {
|
||||
'account.move': [
|
||||
'name', 'state', 'move_type', 'partner_id', 'invoice_user_id', 'fiscal_position_id',
|
||||
'invoice_date', 'invoice_date_due', 'invoice_payment_term_id', 'partner_bank_id',
|
||||
],
|
||||
'account.move.line': [
|
||||
'quantity', 'price_subtotal', 'price_total', 'amount_residual', 'balance', 'amount_currency',
|
||||
'move_id', 'product_id', 'product_uom_id', 'account_id',
|
||||
'journal_id', 'company_id', 'currency_id', 'partner_id',
|
||||
],
|
||||
'product.product': ['product_tmpl_id'],
|
||||
'product.template': ['categ_id'],
|
||||
'uom.uom': ['category_id', 'factor', 'name', 'uom_type'],
|
||||
'res.currency.rate': ['currency_id', 'name'],
|
||||
'res.partner': ['country_id'],
|
||||
}
|
||||
|
||||
@property
|
||||
def _table_query(self):
|
||||
return '%s %s %s' % (self._select(), self._from(), self._where())
|
||||
|
||||
@api.model
|
||||
def _select(self):
|
||||
return '''
|
||||
SELECT
|
||||
line.id,
|
||||
line.move_id,
|
||||
line.product_id,
|
||||
line.account_id,
|
||||
line.journal_id,
|
||||
line.company_id,
|
||||
line.company_currency_id,
|
||||
line.partner_id AS commercial_partner_id,
|
||||
account.account_type AS user_type,
|
||||
move.state,
|
||||
move.move_type,
|
||||
move.partner_id,
|
||||
move.invoice_user_id,
|
||||
move.fiscal_position_id,
|
||||
move.payment_state,
|
||||
move.invoice_date,
|
||||
move.invoice_date_due,
|
||||
uom_template.id AS product_uom_id,
|
||||
template.categ_id AS product_categ_id,
|
||||
line.quantity / NULLIF(COALESCE(uom_line.factor, 1) / COALESCE(uom_template.factor, 1), 0.0) * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END)
|
||||
AS quantity,
|
||||
-line.balance * currency_table.rate AS price_subtotal,
|
||||
line.price_total * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END)
|
||||
AS price_total,
|
||||
-COALESCE(
|
||||
-- Average line price
|
||||
(line.balance / NULLIF(line.quantity, 0.0)) * (CASE WHEN move.move_type IN ('in_invoice','out_refund','in_receipt') THEN -1 ELSE 1 END)
|
||||
-- convert to template uom
|
||||
* (NULLIF(COALESCE(uom_line.factor, 1), 0.0) / NULLIF(COALESCE(uom_template.factor, 1), 0.0)),
|
||||
0.0) * currency_table.rate AS price_average,
|
||||
COALESCE(partner.country_id, commercial_partner.country_id) AS country_id,
|
||||
line.currency_id AS currency_id
|
||||
'''
|
||||
|
||||
@api.model
|
||||
def _from(self):
|
||||
return '''
|
||||
FROM account_move_line line
|
||||
LEFT JOIN res_partner partner ON partner.id = line.partner_id
|
||||
LEFT JOIN product_product product ON product.id = line.product_id
|
||||
LEFT JOIN account_account account ON account.id = line.account_id
|
||||
LEFT JOIN product_template template ON template.id = product.product_tmpl_id
|
||||
LEFT JOIN uom_uom uom_line ON uom_line.id = line.product_uom_id
|
||||
LEFT JOIN uom_uom uom_template ON uom_template.id = template.uom_id
|
||||
INNER JOIN account_move move ON move.id = line.move_id
|
||||
LEFT JOIN res_partner commercial_partner ON commercial_partner.id = move.commercial_partner_id
|
||||
JOIN {currency_table} ON currency_table.company_id = line.company_id
|
||||
'''.format(
|
||||
currency_table=self.env['res.currency']._get_query_currency_table({'multi_company': True, 'date': {'date_to': fields.Date.today()}}),
|
||||
)
|
||||
|
||||
@api.model
|
||||
def _where(self):
|
||||
return '''
|
||||
WHERE move.move_type IN ('out_invoice', 'out_refund', 'in_invoice', 'in_refund', 'out_receipt', 'in_receipt')
|
||||
AND line.account_id IS NOT NULL
|
||||
AND line.display_type = 'product'
|
||||
'''
|
||||
|
||||
@api.model
|
||||
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True):
|
||||
"""
|
||||
This is a hack to allow us to correctly calculate the average price.
|
||||
"""
|
||||
set_fields = set(fields)
|
||||
|
||||
if 'price_average:avg' in fields:
|
||||
set_fields.add('quantity:sum')
|
||||
set_fields.add('price_subtotal:sum')
|
||||
|
||||
res = super().read_group(domain, list(set_fields), groupby, offset, limit, orderby, lazy)
|
||||
|
||||
if 'price_average:avg' in fields:
|
||||
for data in res:
|
||||
data['price_average'] = data['price_subtotal'] / data['quantity'] if data['quantity'] else 0
|
||||
|
||||
if 'quantity:sum' not in fields:
|
||||
del data['quantity']
|
||||
if 'price_subtotal:sum' not in fields:
|
||||
del data['price_subtotal']
|
||||
|
||||
return res
|
||||
|
||||
|
||||
class ReportInvoiceWithoutPayment(models.AbstractModel):
|
||||
_name = 'report.account.report_invoice'
|
||||
_description = 'Account report without payment lines'
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
docs = self.env['account.move'].browse(docids)
|
||||
|
||||
qr_code_urls = {}
|
||||
for invoice in docs:
|
||||
if invoice.display_qr_code:
|
||||
new_code_url = invoice._generate_qr_code(silent_errors=data['report_type'] == 'html')
|
||||
if new_code_url:
|
||||
qr_code_urls[invoice.id] = new_code_url
|
||||
|
||||
return {
|
||||
'doc_ids': docids,
|
||||
'doc_model': 'account.move',
|
||||
'docs': docs,
|
||||
'qr_code_urls': qr_code_urls,
|
||||
}
|
||||
|
||||
class ReportInvoiceWithPayment(models.AbstractModel):
|
||||
_name = 'report.account.report_invoice_with_payments'
|
||||
_description = 'Account report with payment lines'
|
||||
_inherit = 'report.account.report_invoice'
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
rslt = super()._get_report_values(docids, data)
|
||||
rslt['report_type'] = data.get('report_type') if data else ''
|
||||
return rslt
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<data>
|
||||
<record id="view_account_invoice_report_pivot" model="ir.ui.view">
|
||||
<field name="name">account.invoice.report.pivot</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<pivot string="Invoices Analysis" sample="1">
|
||||
<field name="product_categ_id" type="col"/>
|
||||
<field name="invoice_date" type="row"/>
|
||||
<field name="price_subtotal" type="measure"/>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_invoice_report_graph" model="ir.ui.view">
|
||||
<field name="name">account.invoice.report.graph</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<graph string="Invoices Analysis" type="line" sample="1">
|
||||
<field name="product_categ_id"/>
|
||||
<field name="price_subtotal" type="measure"/>
|
||||
</graph>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_report_view_tree" model="ir.ui.view">
|
||||
<field name="name">account.invoice.report.view.tree</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Invoices Analysis">
|
||||
<field name="move_id" string="Invoice Number"/>
|
||||
<field name="journal_id" optional="hide"/>
|
||||
<field name="partner_id" optional="show"/>
|
||||
<field name="country_id" optional="hide"/>
|
||||
<field name="invoice_date" optional="show"/>
|
||||
<field name="invoice_date_due" optional="show"/>
|
||||
<field name="invoice_user_id" optional="hide" widget="many2one_avatar_user"/>
|
||||
<field name="product_categ_id" optional="hide"/>
|
||||
<field name="product_id" optional="show"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="price_average" optional="hide" sum="Total"/>
|
||||
<field name="quantity" optional="hide" sum="Total"/>
|
||||
<field name="price_subtotal" optional="show" sum="Total"/>
|
||||
<field name="price_total" optional="show" sum="Total"/>
|
||||
<field name="state" optional="hide"/>
|
||||
<field name="payment_state" optional="hide"/>
|
||||
<field name="move_type" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Custom reports (aka filters) -->
|
||||
<record id="filter_invoice_report_salespersons" model="ir.filters">
|
||||
<field name="name">By Salespersons</field>
|
||||
<field name="model_id">account.invoice.report</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['invoice_date:month', 'invoice_user_id']}</field>
|
||||
</record>
|
||||
<record id="filter_invoice_product" model="ir.filters">
|
||||
<field name="name">By Product</field>
|
||||
<field name="model_id">account.invoice.report</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['invoice_date:month', 'product_id'], 'set_visible':True, 'residual_invisible':True}</field>
|
||||
</record>
|
||||
<record id="filter_invoice_product_category" model="ir.filters">
|
||||
<field name="name">By Product Category</field>
|
||||
<field name="model_id">account.invoice.report</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['invoice_date:month', 'product_categ_id'], 'residual_invisible':True}</field>
|
||||
</record>
|
||||
<record id="filter_invoice_refund" model="ir.filters">
|
||||
<field name="name">By Credit Note</field>
|
||||
<field name="model_id">account.invoice.report</field>
|
||||
<field name="domain">[('move_type', '=', 'out_refund')]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['invoice_date:month', 'invoice_user_id']}</field>
|
||||
</record>
|
||||
<record id="filter_invoice_country" model="ir.filters">
|
||||
<field name="name">By Country</field>
|
||||
<field name="model_id">account.invoice.report</field>
|
||||
<field name="domain">[]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
<field name="context">{'group_by': ['invoice_date:month', 'country_id']}</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_invoice_report_search" model="ir.ui.view">
|
||||
<field name="name">account.invoice.report.search</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Invoices Analysis">
|
||||
<filter string="My Invoices" name="my_invoice" domain="[('invoice_user_id', '=', uid)]"/>
|
||||
<separator/>
|
||||
<field name="invoice_date"/>
|
||||
<separator/>
|
||||
<filter string="To Invoice" name="toinvoice" domain="[('state','=','draft')]" help = "Draft Invoices"/>
|
||||
<filter string="Invoiced" name="current" domain="[('state','not in', ('draft','cancel'))]"/>
|
||||
<separator/>
|
||||
<filter string="Customers" name="customer" domain="['|', ('move_type','=','out_invoice'),('move_type','=','out_refund')]"/>
|
||||
<filter string="Vendors" name="supplier" domain="['|', ('move_type','=','in_invoice'),('move_type','=','in_refund')]"/>
|
||||
<separator/>
|
||||
<filter string="Invoices" name="invoice" domain="['|', ('move_type','=','out_invoice'),('move_type','=','in_invoice')]"/>
|
||||
<filter string="Credit Notes" name="creditnote" domain="['|', ('move_type','=','out_refund'),('move_type','=','in_refund')]"/>
|
||||
<separator/>
|
||||
<filter name="filter_invoice_date" date="invoice_date"/>
|
||||
<filter name="invoice_date_due" date="invoice_date_due"/>
|
||||
<field name="partner_id" operator="child_of"/>
|
||||
<field name="invoice_user_id" />
|
||||
<field name="product_id" />
|
||||
<field name="product_categ_id" filter_domain="[('product_categ_id', 'child_of', self)]"/>
|
||||
<group expand="1" string="Group By">
|
||||
<filter string="Salesperson" name='user' context="{'group_by':'invoice_user_id'}"/>
|
||||
<filter string="Partner" name="partner_id" context="{'group_by':'partner_id','residual_visible':True}"/>
|
||||
<filter string="Product Category" name="category_product" context="{'group_by':'product_categ_id','residual_invisible':True}"/>
|
||||
<filter string="Status" name="status" context="{'group_by':'state'}"/>
|
||||
<filter string="Company" name="company" context="{'group_by':'company_id'}" groups="base.group_multi_company"/>
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Date" name="invoice_date" context="{'group_by':'invoice_date'}"
|
||||
invisible="context.get('invoice_report_view_hide_invoice_date')"/>
|
||||
<filter string="Date" name="group_by_invoice_date_week" context="{'group_by':'invoice_date:week'}"
|
||||
invisible="not context.get('invoice_report_view_hide_invoice_date')"/>
|
||||
<filter string="Due Date" name="duemonth" context="{'group_by':'invoice_date_due:month'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_account_invoice_report_all_supp" model="ir.actions.act_window">
|
||||
<field name="name">Invoices Analysis</field>
|
||||
<field name="res_model">account.invoice.report</field>
|
||||
<field name="view_mode">graph,pivot</field>
|
||||
<field name="context">{'search_default_current':1, 'search_default_supplier': 1, 'group_by':['invoice_date'], 'group_by_no_leaf':1}</field>
|
||||
<field name="search_view_id" ref="view_account_invoice_report_search"/>
|
||||
<field name="help">From this report, you can have an overview of the amount invoiced from your vendors. The search tool can also be used to personalise your Invoices reports and so, match this analysis to your needs.</field>
|
||||
</record>
|
||||
<record id="action_account_invoice_report_all" model="ir.actions.act_window">
|
||||
<field name="name">Invoices Analysis</field>
|
||||
<field name="res_model">account.invoice.report</field>
|
||||
<field name="view_mode">graph,pivot</field>
|
||||
<field name="context">{'search_default_current':1, 'search_default_customer': 1, 'group_by':['invoice_date'], 'group_by_no_leaf':1}</field>
|
||||
<field name="search_view_id" ref="view_account_invoice_report_search"/>
|
||||
<field name="help">From this report, you can have an overview of the amount invoiced to your customers. The search tool can also be used to personalise your Invoices reports and so, match this analysis to your needs.</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
Loading…
Add table
Add a link
Reference in a new issue