summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwan <wan@odoo.com>2019-08-28 13:54:41 +0000
committerwan <wan@odoo.com>2019-09-04 09:00:03 +0000
commit737eaf93330b7c4e5ff16311c92f1ad17be0cf72 (patch)
tree6f2520e675791f3af0cdd84252bab393b3a62717
parent16c32f0c25f82b308b50e55e2127a2e6d139f7bf (diff)
[IMP] account: add searchpanel on account.account and account.move.line
Task 2008956 * Add the root of an account (first 2 digits/char) as a searchable model. * Create a custom searchpanel for this account root on account.move.line * Add the account_root searchpanel to the account.account view too.
-rw-r--r--addons/account/models/account.py36
-rw-r--r--addons/account/models/account_move.py1
-rw-r--r--addons/account/models/chart_template.py1
-rw-r--r--addons/account/security/ir.model.access.csv2
-rw-r--r--addons/account/static/src/scss/account_searchpanel.scss14
-rw-r--r--addons/account/views/account.xml1
-rw-r--r--addons/account/views/account_move_views.xml18
-rw-r--r--addons/account/views/account_view.xml3
-rw-r--r--addons/web/static/src/js/views/abstract_view.js11
-rw-r--r--addons/web/static/src/js/views/search_panel.js10
-rw-r--r--odoo/addons/base/rng/search_view.rng1
11 files changed, 91 insertions, 7 deletions
diff --git a/addons/account/models/account.py b/addons/account/models/account.py
index 83d9cb05c1f..f833430b4af 100644
--- a/addons/account/models/account.py
+++ b/addons/account/models/account.py
@@ -8,7 +8,7 @@ from odoo.osv import expression
from odoo.tools.float_utils import float_round as round, float_compare
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.exceptions import UserError, ValidationError
-from odoo import api, fields, models, _
+from odoo import api, fields, models, _, tools
from odoo.tests.common import Form
TYPE_TAX_USE = [
@@ -225,6 +225,7 @@ class AccountAccount(models.Model):
default=lambda self: self.env.company)
tag_ids = fields.Many2many('account.account.tag', 'account_account_account_tag', string='Tags', help="Optional tags you may want to assign for custom reporting")
group_id = fields.Many2one('account.group')
+ root_id = fields.Many2one('account.root', compute='_compute_account_root', store=True)
opening_debit = fields.Monetary(string="Opening debit", compute='_compute_opening_debit_credit', inverse='_set_opening_debit', help="Opening debit value for this account.")
opening_credit = fields.Monetary(string="Opening credit", compute='_compute_opening_debit_credit', inverse='_set_opening_credit', help="Opening credit value for this account.")
@@ -242,6 +243,14 @@ class AccountAccount(models.Model):
if record.tax_ids:
raise UserError(_('An Off-Balance account can not have taxes'))
+ @api.depends('code')
+ def _compute_account_root(self):
+ # this computes the first 2 digits of the account.
+ # This field should have been a char, but the aim is to use it in a side panel view with hierarchy, and it's only supported by many2one fields so far.
+ # So instead, we make it a many2one to a psql view with what we need as records.
+ for record in self:
+ record.root_id = record.code and (ord(record.code[0]) * 1000 + ord(record.code[1])) or False
+
@api.model
def _search_new_account_code(self, company, digits, prefix):
for num in range(1, 10000):
@@ -543,6 +552,31 @@ class AccountGroup(models.Model):
return self.browse(group_ids).name_get()
+class AccountRoot(models.Model):
+ _name = 'account.root'
+ _description = 'Account codes first 2 digits'
+ _auto = False
+
+ name = fields.Char()
+ parent_id = fields.Many2one('account.root')
+
+ def init(self):
+ tools.drop_view_if_exists(self.env.cr, self._table)
+ self.env.cr.execute('''
+ CREATE OR REPLACE VIEW %s AS (
+ SELECT DISTINCT ASCII(code) * 1000 + ASCII(SUBSTRING(code,2,1)) AS id,
+ LEFT(code,2) AS name,
+ ASCII(code) AS parent_id
+ FROM account_account WHERE code IS NOT NULL
+ UNION ALL
+ SELECT DISTINCT ASCII(code) AS id,
+ LEFT(code,1) AS name,
+ NULL::int AS parent_id
+ FROM account_account WHERE code IS NOT NULL
+ )''' % (self._table,)
+ )
+
+
class AccountJournalGroup(models.Model):
_name = 'account.journal.group'
_description = "Account Journal Group"
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 52cf708c80e..604aae8d046 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -2142,6 +2142,7 @@ class AccountMoveLine(models.Model):
index=True, ondelete="cascade",
domain=[('deprecated', '=', False)])
account_internal_type = fields.Selection(related='account_id.user_type_id.type', string="Internal Type", store=True, readonly=True)
+ account_root_id = fields.Many2one(related='account_id.root_id', string="Account Root", store=True, readonly=True)
sequence = fields.Integer(default=10)
name = fields.Char(string='Label')
quantity = fields.Float(string='Quantity',
diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py
index 86a3ca5822e..2170a3ff632 100644
--- a/addons/account/models/chart_template.py
+++ b/addons/account/models/chart_template.py
@@ -57,6 +57,7 @@ class AccountAccountTemplate(models.Model):
"to define chart templates that extend another and complete it with few new accounts (You don't need to define the whole structure that is common to both several times).")
tag_ids = fields.Many2many('account.account.tag', 'account_account_template_account_tag', string='Account tag', help="Optional tags you may want to assign for custom reporting")
group_id = fields.Many2one('account.group')
+ root_id = fields.Many2one('account.root')
@api.depends('name', 'code')
def name_get(self):
diff --git a/addons/account/security/ir.model.access.csv b/addons/account/security/ir.model.access.csv
index 1925e05545f..f310f756c9c 100644
--- a/addons/account/security/ir.model.access.csv
+++ b/addons/account/security/ir.model.access.csv
@@ -13,6 +13,8 @@ access_account_account_user,account.account user,model_account_account,base.grou
access_account_account_partner_manager,account.account partner manager,model_account_account,base.group_partner_manager,1,0,0,0
access_account_group_manager,account.group,model_account_group,account.group_account_manager,1,1,1,1
access_account_group,account.group,model_account_group,account.group_account_user,1,0,0,0
+access_account_root_manager,account.root,model_account_root,account.group_account_manager,1,0,0,0
+access_account_root,account.root,model_account_root,account.group_account_user,1,0,0,0
access_account_tax,account.tax,model_account_tax,account.group_account_invoice,1,0,0,0
access_account_account_template,account.account.template,model_account_account_template,account.group_account_manager,1,1,1,1
access_account_chart_template,account.chart.template,model_account_chart_template,account.group_account_manager,1,1,1,1
diff --git a/addons/account/static/src/scss/account_searchpanel.scss b/addons/account/static/src/scss/account_searchpanel.scss
new file mode 100644
index 00000000000..affa8898732
--- /dev/null
+++ b/addons/account/static/src/scss/account_searchpanel.scss
@@ -0,0 +1,14 @@
+.o_search_panel.account_root {
+ flex: 0 0 48px;
+ padding: 6px;
+ .o_search_panel_section_header {
+ display: none;
+ }
+ .list-group-item span.o_search_panel_label_title {
+ display: contents;
+ }
+ .o_search_panel_category_value header {
+ margin-left: 0;
+ padding-left: 0;
+ }
+}
diff --git a/addons/account/views/account.xml b/addons/account/views/account.xml
index 4bfc5afe7cc..5b3eff87c8e 100644
--- a/addons/account/views/account.xml
+++ b/addons/account/views/account.xml
@@ -14,6 +14,7 @@
<link rel="stylesheet" type="text/scss" href="/account/static/src/scss/account_reconciliation.scss"/>
<link rel="stylesheet" type="text/scss" href="/account/static/src/scss/account_journal_dashboard.scss"/>
<link rel="stylesheet" type="text/scss" href="/account/static/src/scss/account_dashboard.scss"/>
+ <link rel="stylesheet" type="text/scss" href="/account/static/src/scss/account_searchpanel.scss"/>
<link rel="stylesheet" href="/account/static/src/scss/section_and_note_backend.scss"/>
<link rel="stylesheet" type="text/scss" href="/account/static/src/scss/account_activity.scss"/>
diff --git a/addons/account/views/account_move_views.xml b/addons/account/views/account_move_views.xml
index 770072b2cb3..a244fca68bc 100644
--- a/addons/account/views/account_move_views.xml
+++ b/addons/account/views/account_move_views.xml
@@ -311,6 +311,8 @@
('name', 'ilike', self), ('ref', 'ilike', self), ('account_id', 'ilike', self), ('partner_id', 'ilike', self)]"/>
<field name="date"/>
<field name="account_id"/>
+ <field name="account_root_id"/>
+ <field name="account_internal_type"/>
<field name="partner_id"/>
<field name="journal_id"/>
<field name="move_id" string="Journal Entry" filter_domain="[
@@ -347,6 +349,20 @@
</search>
</field>
</record>
+ <record id="view_account_move_line_filter_with_root_selection" model="ir.ui.view">
+ <field name="name">account.move.line.search</field>
+ <field name="model">account.move.line</field>
+ <field name="mode">primary</field>
+ <field name="priority">20</field>
+ <field name="inherit_id" ref="account.view_account_move_line_filter"/>
+ <field name="arch" type="xml">
+ <xpath expr="//group" position="after">
+ <searchpanel class="account_root">
+ <field name="account_root_id" icon="fa-filter"/>
+ </searchpanel>
+ </xpath>
+ </field>
+ </record>
<!-- account.move (Journal Entry) -->
@@ -1056,6 +1072,7 @@
<field name="res_model">account.move.line</field>
<field name="domain">[('display_type', 'not in', ('line_section', 'line_note'))]</field>
<field name="view_id" ref="view_move_line_tree_grouped_general"/>
+ <field name="search_view_id" ref="view_account_move_line_filter_with_root_selection"/>
<field name="view_mode">tree,pivot,graph,form,kanban</field>
</record>
@@ -1065,6 +1082,7 @@
<field name="res_model">account.move.line</field>
<field name="domain">[('display_type', 'not in', ('line_section', 'line_note'))]</field>
<field name="view_id" ref="view_move_line_tree_grouped_partner"/>
+ <field name="search_view_id" ref="view_account_move_line_filter_with_root_selection"/>
<field name="view_mode">tree,pivot,graph,form,kanban</field>
</record>
diff --git a/addons/account/views/account_view.xml b/addons/account/views/account_view.xml
index c5f7657c623..ed5afea3286 100644
--- a/addons/account/views/account_view.xml
+++ b/addons/account/views/account_view.xml
@@ -96,6 +96,9 @@
<group expand="0" string="Group By">
<filter string="Account Type" name="accounttype" domain="" context="{'group_by':'user_type_id'}"/>
</group>
+ <searchpanel class="account_root">
+ <field name="root_id" icon="fa-filter"/>
+ </searchpanel>
</search>
</field>
</record>
diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js
index fc8e73136d8..d581f84308a 100644
--- a/addons/web/static/src/js/views/abstract_view.js
+++ b/addons/web/static/src/js/views/abstract_view.js
@@ -205,11 +205,11 @@ var AbstractView = Factory.extend({
if (this.withSearchPanel) {
var spProto = this.config.SearchPanel.prototype;
var viewInfo = this.controlPanelParams.viewInfo;
- var sections = spProto.computeSearchPanelParams(viewInfo, this.viewType);
- if (sections) {
- this.searchPanelParams.sections = sections;
+ var searchPanelParams = spProto.computeSearchPanelParams(viewInfo, this.viewType);
+ if (searchPanelParams.sections) {
+ this.searchPanelParams.sections = searchPanelParams.sections;
this.rendererParams.withSearchPanel = true;
- spDef = Promise.resolve(cpDef).then(this._createSearchPanel.bind(this, parent));
+ spDef = Promise.resolve(cpDef).then(this._createSearchPanel.bind(this, parent, searchPanelParams));
}
}
@@ -283,7 +283,7 @@ var AbstractView = Factory.extend({
* @param {Widget} parent
* @returns {Promise<SearchPanel>} resolved when the searchPanel is ready
*/
- _createSearchPanel: async function (parent) {
+ _createSearchPanel: async function (parent, params) {
var defaultValues = {};
Object.keys(this.loadParams.context).forEach((key) => {
let match = /^searchpanel_default_(.*)$/.exec(key);
@@ -299,6 +299,7 @@ var AbstractView = Factory.extend({
searchDomain: controlPanelDomain,
sections: this.searchPanelParams.sections,
state: this.searchPanelParams.state,
+ classes: params.classes || [],
});
this.controllerParams.searchPanel = searchPanel;
this.controllerParams.controlPanelDomain = controlPanelDomain;
diff --git a/addons/web/static/src/js/views/search_panel.js b/addons/web/static/src/js/views/search_panel.js
index f09ef071f79..32bfda12594 100644
--- a/addons/web/static/src/js/views/search_panel.js
+++ b/addons/web/static/src/js/views/search_panel.js
@@ -99,6 +99,7 @@ var SearchPanel = Widget.extend({
this.defaultValues = params.defaultValues || {};
this.fields = params.fields;
this.model = params.model;
+ this.className = params.classes.concat(['o_search_panel']).join(' ');
this.searchDomain = params.searchDomain;
},
/**
@@ -157,6 +158,7 @@ var SearchPanel = Widget.extend({
*/
computeSearchPanelParams: function (viewInfo, viewType) {
var searchPanelSections;
+ var classes;
if (viewInfo) {
var arch = viewUtils.parseArch(viewInfo.arch);
viewType = viewType === 'list' ? 'tree' : viewType;
@@ -167,13 +169,19 @@ var SearchPanel = Widget.extend({
if (attrs.view_types) {
viewTypes = attrs.view_types.split(',');
}
+ if (attrs.class) {
+ classes = attrs.class.split(' ');
+ }
if (viewTypes.indexOf(viewType) !== -1) {
searchPanelSections = _processSearchPanelNode(node, viewInfo.fields);
}
}
});
}
- return searchPanelSections;
+ return {
+ sections: searchPanelSections,
+ classes: classes,
+ }
},
/**
* Export the current state (categories and filters) of the searchpanel.
diff --git a/odoo/addons/base/rng/search_view.rng b/odoo/addons/base/rng/search_view.rng
index 08776e8e206..dfa6059da2c 100644
--- a/odoo/addons/base/rng/search_view.rng
+++ b/odoo/addons/base/rng/search_view.rng
@@ -11,6 +11,7 @@
<rng:element name="searchpanel">
<rng:ref name="overload"/>
<rng:optional><rng:attribute name="view_types"/></rng:optional>
+ <rng:optional><rng:attribute name="class"/></rng:optional>
<rng:zeroOrMore>
<rng:ref name="field" />
</rng:zeroOrMore>