diff --git a/ext/custom-addons/dp_custom/models/material_type.py b/ext/custom-addons/dp_custom/models/material_type.py
index 6f95d4bd..7f1ae414 100644
--- a/ext/custom-addons/dp_custom/models/material_type.py
+++ b/ext/custom-addons/dp_custom/models/material_type.py
@@ -28,6 +28,8 @@ class MaterialType(models.Model):
name = fields.Char(string='Bezeichnung', required=True)
print_default_code = fields.Boolean(string='Drucke Artikelnummer', required=True, help='Definiert, ob die Artikelnummer gedruckt wird')
+ print_sales_pic = fields.Boolean(string='Drucke Artikelbild', default=True, required=False, help='Definiert, ob ein Artikelbild gedruckt wird (Angebot/Auftrag)')
+ print_production_pic = fields.Boolean(string='Drucke Produktionsbild', default=False, required=False, help='Definiert, ob ein Produktionsbild gedruckt wird (Produktionsauftrag)')
_sql_constraints = [
('name_uniq', 'unique(name)', 'Die Bezeichnung muss eindeutig sein')
diff --git a/ext/custom-addons/dp_custom/models/res_partner.py b/ext/custom-addons/dp_custom/models/res_partner.py
index e9a99530..119f6269 100644
--- a/ext/custom-addons/dp_custom/models/res_partner.py
+++ b/ext/custom-addons/dp_custom/models/res_partner.py
@@ -67,6 +67,7 @@ class Partner(models.Model):
collective_bill = fields.Boolean(string='Sammelrechnung', default=True)
country_id = fields.Many2one('res.country', string='Country', ondelete='restrict', default=_default_country_id)
commission_account_ids = fields.Many2many(comodel_name='commission.account', string='Provisionsempfänger')
+ partner_flash = fields.Char()
_sql_constraints = [
('ref_uniq', 'unique(ref)', 'Die Interne Referenz muss eindeutig sein'),
@@ -281,7 +282,7 @@ class Partner(models.Model):
common_list.extend(
['name', 'ref', 'partner_sector_id', 'info_uid', 'comment', 'vat', 'property_payment_term_id',
'date_vat_check', 'active', 'property_product_pricelist', 'retail_partner_id',
- 'is_retailer', 'name2', 'carrier_id', 'collective_bill', 'fiscal_position'])
+ 'is_retailer', 'name2', 'carrier_id', 'collective_bill', 'fiscal_position', 'partner_flash'])
return common_list
elif self.env.context.get('sst_14', False):
common_list = ['firstname', 'lastname', 'midname', 'email', 'company_odoo_id', 'portal_id', 'opt_out']
diff --git a/ext/custom-addons/dp_custom/models/sale.py b/ext/custom-addons/dp_custom/models/sale.py
index d8932ca1..bbe0677f 100644
--- a/ext/custom-addons/dp_custom/models/sale.py
+++ b/ext/custom-addons/dp_custom/models/sale.py
@@ -65,6 +65,8 @@ class SaleOrder(models.Model):
# pg9_call = fields.Char(string='PG9-Auftrag', compute='_pg9_call', store=False)
pg9_call_D = fields.Char(string='PG9-Auftrag_D', compute='_pg9_call', store=False)
pg9_call_T = fields.Char(string='PG9-Auftrag_T', compute='_pg9_call', store=False)
+ partner_flash = fields.Text(compute='_get_partner_flash', store=False)
+# partner_flash = fields.Char(store=False)
@api.multi
def _reset_sequence(self):
@@ -87,10 +89,16 @@ class SaleOrder(models.Model):
# end def _pg9_call
+ @api.multi
+ def _get_partner_flash(self):
+ for record in self:
+ record.partner_flash = record.partner_id.partner_flash
+
@api.multi
@api.onchange('partner_invoice_id')
def _onchange_partner_invoice_id(self):
for record in self:
+# record.partner_flash = record.partner_id.partner_flash
if record.partner_invoice_id.is_retailer:
record.payment_term_id = record.partner_invoice_id.property_payment_term_id
@@ -452,6 +460,9 @@ class SaleOrder(models.Model):
@api.multi
@api.onchange('partner_id')
def onchange_partner_id(self):
+ # for record in self:
+ # record.partner_flash = record.partner_id.partner_flash
+
if not self.partner_id:
self.update({
'partner_invoice_id': False,
@@ -472,6 +483,10 @@ class SaleOrder(models.Model):
if self.partner_id.team_id:
values['team_id'] = self.partner_id.team_id.id
+
+ if self.partner_id:
+ values['partner_flash'] = self.partner_id.partner_flash
+
self.update(values)
@api.multi
@@ -504,6 +519,14 @@ class SaleOrderLine(models.Model):
weight = fields.Float(string='Gewicht', compute='_compute_weight')
intrastat_id = fields.Many2one(comodel_name='report.intrastat.code', string='Intrastat Code')
sequence = fields.Integer(string='Sequence', default=9999)
+ item_notes = fields.Text(string='Notes', related='lot_id.notes', store=False)
+ item_warn = fields.Boolean(string='Notes!!!', compute='_compute_item_warn', store=False)
+
+ @api.multi
+ def _compute_item_warn(self):
+ for record in self:
+ iNote = str(record.lot_id.notes)
+ record.item_warn = True if iNote.startswith('!') else False
@api.multi
@api.onchange('product_id')
diff --git a/ext/custom-addons/dp_custom/models/stock.py b/ext/custom-addons/dp_custom/models/stock.py
index 3ca1c36e..ceb356cd 100644
--- a/ext/custom-addons/dp_custom/models/stock.py
+++ b/ext/custom-addons/dp_custom/models/stock.py
@@ -19,7 +19,9 @@
#
##############################################################################
-from odoo import fields, models, api, tools
+from odoo import fields, models, api, tools, _
+from odoo.exceptions import ValidationError
+from odoo.tools.float_utils import float_compare, float_is_zero
class StockProductionLot(models.Model):
@@ -60,3 +62,67 @@ class StockPicking(models.Model):
res = lang_obj.format('%.' + str(2) + 'f', value, grouping=True, monetary=True)
return res
+
+
+class StockMove(models.Model):
+ _inherit = "stock.move"
+
+ manu_lots_visible = fields.Boolean(compute='_compute_manu_lots_visible')
+
+ @api.model
+ def create(self, vals):
+ res = super(StockMove, self).create(vals)
+ for move in res:
+ move.update({'sequence': move.sale_line_id.sequence,})
+ return res
+
+ @api.multi
+ def _prepare_move_line_vals(self, quantity=None, reserved_quant=None):
+ self.ensure_one()
+ vals = super(StockMove, self)._prepare_move_line_vals(quantity=quantity, reserved_quant=reserved_quant)
+ if self.sale_line_id.lot_id and not self.sale_line_id.product_id.can_be_sold_unconfigured:
+ move_lot = self.sale_line_id.lot_id.id
+ vals.update({'lot_id': move_lot,})
+ return vals
+
+ def _compute_manu_lots_visible(self):
+ for move_line in self:
+ if not move_line.product_id.can_be_sold_unconfigured:
+ move_line.manu_lots_visible = True
+
+ @api.multi
+ def action_show_lot(self):
+ self.ensure_one()
+ action = self.env.ref('stock.action_production_lot_form').read()[0]
+ action['res_id'] = self.move_line_ids.lot_id.id
+ action['view_mode'] = 'form'
+ action['views'] = [(False, 'form')]
+
+ return action
+
+ @api.depends('product_id', 'product_uom_qty', 'product_uom')
+ def _cal_move_weight(self):
+ for move in self:
+ if move.sale_line_id.lot_id and not move.product_id.can_be_sold_unconfigured:
+ move.weight += (move.product_qty * move.sale_line_id.lot_id.weight)
+ else:
+ move.weight += (move.product_qty * move.product_id.weight)
+
+# print(move.weight)
+
+
+class StockQuant(models.Model):
+ _inherit = "stock.quant"
+
+ @api.constrains('quantity')
+ def check_quantity(self):
+ info = ''
+ for quant in self:
+ if float_compare(quant.quantity, 1, precision_rounding=quant.product_uom_id.rounding) > 0 and quant.lot_id and quant.product_id.tracking == 'serial':
+ smls = self.env['stock.move.line'].search([('lot_id', '=', quant.lot_id.id)])
+ for sml in smls:
+ sm = self.env['stock.move'].search([('id', '=', sml.move_id.id)])
+ info += '\n %s; %s; %s: %s' % (sm.origin,sm.reference,sm.sequence,quant.lot_id.name)
+
+ if info:
+ raise ValidationError(_('A serial number should only be linked to a single product.') + info)
diff --git a/ext/custom-addons/dp_custom/views/material_type_views.xml b/ext/custom-addons/dp_custom/views/material_type_views.xml
index adb1fc84..bf239aea 100644
--- a/ext/custom-addons/dp_custom/views/material_type_views.xml
+++ b/ext/custom-addons/dp_custom/views/material_type_views.xml
@@ -9,6 +9,8 @@
+
+
@@ -21,6 +23,8 @@
+
+
diff --git a/ext/custom-addons/dp_custom/views/res_partner_views.xml b/ext/custom-addons/dp_custom/views/res_partner_views.xml
index 971457b9..19448302 100644
--- a/ext/custom-addons/dp_custom/views/res_partner_views.xml
+++ b/ext/custom-addons/dp_custom/views/res_partner_views.xml
@@ -31,6 +31,9 @@
+
+
+
diff --git a/ext/custom-addons/dp_custom/views/sale_views.xml b/ext/custom-addons/dp_custom/views/sale_views.xml
index 006131c6..f1915e35 100644
--- a/ext/custom-addons/dp_custom/views/sale_views.xml
+++ b/ext/custom-addons/dp_custom/views/sale_views.xml
@@ -6,12 +6,20 @@
sale.order
+
+
+ item_warn
+
+
+
+
+
@@ -66,9 +74,29 @@
-
+
+
+
+
+
+
+
+
@@ -128,6 +156,7 @@
+
@@ -143,6 +172,7 @@
+
@@ -162,9 +192,19 @@
-
+
+
+
+
+
+
diff --git a/ext/custom-addons/dp_custom/views/stock_views.xml b/ext/custom-addons/dp_custom/views/stock_views.xml
index 4c012e2a..e974a8a8 100644
--- a/ext/custom-addons/dp_custom/views/stock_views.xml
+++ b/ext/custom-addons/dp_custom/views/stock_views.xml
@@ -22,4 +22,17 @@
0
+
+ view_delivery_manu_lot
+ stock.picking
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/custom-addons/dp_reports/reports/report_templates.xml b/ext/custom-addons/dp_reports/reports/report_templates.xml
index 801573bf..c426c32d 100644
--- a/ext/custom-addons/dp_reports/reports/report_templates.xml
+++ b/ext/custom-addons/dp_reports/reports/report_templates.xml
@@ -45,8 +45,11 @@
- Auftragsbestätigung
- Angebot
+
+ Auftragsbestätigung
+ Angebot
+ ProduktionsscheinProformarechnung
diff --git a/ext/custom-addons/dp_reports_account/models/account_invoice.py b/ext/custom-addons/dp_reports_account/models/account_invoice.py
index d354d342..c6a557fc 100644
--- a/ext/custom-addons/dp_reports_account/models/account_invoice.py
+++ b/ext/custom-addons/dp_reports_account/models/account_invoice.py
@@ -48,6 +48,7 @@ class AccountInvoiceLine(models.Model):
)
lot_formatted_note = fields.Html(
+ comodel_name='stock.production.lot',
string='Formatted Note',
compute='_compute_line_lots',
)
@@ -57,9 +58,8 @@ class AccountInvoiceLine(models.Model):
for line in self:
if not line.order_line_ids:
return
- line.prod_lot_ids = self.mapped(
+ line.prod_lot_ids = line.mapped(
'order_line_ids.move_ids.move_line_ids.lot_id')
- print('End')
@api.multi
def _compute_line_lots(self):
diff --git a/ext/custom-addons/dp_reports_stock/reports/stock.xml b/ext/custom-addons/dp_reports_stock/reports/stock.xml
index 21ac8dc5..28e3bd88 100644
--- a/ext/custom-addons/dp_reports_stock/reports/stock.xml
+++ b/ext/custom-addons/dp_reports_stock/reports/stock.xml
@@ -24,6 +24,11 @@
+
+
+ Tel:
+
+
@@ -41,6 +46,11 @@
+
+
+ Tel:
+
+
@@ -101,6 +111,7 @@
+
+
+
+
@@ -161,10 +176,14 @@
Product
-
+
+
Lot/Serial Number
+ Weight
+
+
Ordered Quantity
-
-
+
+
-
-
-
-
+
-
+
@@ -213,6 +229,16 @@
+
+
+
+
+
+
+
+
+
+
:
+
+
+
+
+
+
+
+
+
+ Lieferadresse
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Kundennr.:
+
+
+
+
+ Ansprechpartner:
+
+
+
+ Positionen:
+
+
+
+
+
+
+ Angebotsdatum:
+
+
+
+
+ Email:
+
+
+
+
+ Ref:
+
+
+
+
+
+
+
+ Lieferdatum:
+
+
+
+
+ Telefon:
+
+
+
+ Bezeichnung:
+
+
+
+
+
+
+
+
+
+
+
Pos.
+
+
Artikel
+
+
Anzahl
+
Gewicht
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ kg
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ext/custom-addons/tz_reports_production/security/ir.model.access.csv b/ext/custom-addons/tz_reports_production/security/ir.model.access.csv
new file mode 100644
index 00000000..0343f29f
--- /dev/null
+++ b/ext/custom-addons/tz_reports_production/security/ir.model.access.csv
@@ -0,0 +1 @@
+"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
diff --git a/ext/custom-addons/tz_reports_production/static/description/icon.png b/ext/custom-addons/tz_reports_production/static/description/icon.png
new file mode 100644
index 00000000..32c1481d
Binary files /dev/null and b/ext/custom-addons/tz_reports_production/static/description/icon.png differ
diff --git a/ext/custom-addons/tz_reports_production/static/src/img/favicon.ico b/ext/custom-addons/tz_reports_production/static/src/img/favicon.ico
new file mode 100644
index 00000000..90f1e91c
Binary files /dev/null and b/ext/custom-addons/tz_reports_production/static/src/img/favicon.ico differ
diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/README.rst b/ext/custom-addons/web_tree_dynamic_colored_field/README.rst
new file mode 100644
index 00000000..2b647f42
--- /dev/null
+++ b/ext/custom-addons/web_tree_dynamic_colored_field/README.rst
@@ -0,0 +1,108 @@
+.. image:: https://img.shields.io/badge/license-LGPL--3-blue.svg
+ :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
+ :alt: License: LGPL-3
+
+============================
+Colorize field in tree views
+============================
+
+This module aims to add support for dynamically coloring fields in tree view
+according to data in the record.
+
+It provides attributes on fields with the similar syntax as the ``colors`` attribute
+in tree tags.
+
+Further, it provides a ``color_field`` attribute on tree tags's ``colors`` to use
+a field's value as color.
+
+Features
+========
+
+* Add attribute ``bg_color`` on field's ``options`` to color background of a cell in tree view
+* Add attribute ``fg_color`` on field's ``options`` to change text color of a cell in tree view
+* Add attribute ``color_field`` on the tree element's ``colors`` to use as color
+
+Usage
+=====
+
+* In the tree view declaration, put ``options='{"bg_color": "red: customer==True"}`` attribute in the ``field`` tag::
+
+ ...
+
+
+ ...
+
+ ...
+
+
+ ...
+
+ With this example, column which renders 'name' field will have its background colored in red.
+
+* In the tree view declaration, put ``options='{"fg_color": "white:customer == True"}'`` attribute in the ``field`` tag::
+
+ ...
+
+
+ ...
+
+ ...
+
+
+ ...
+
+ With this example, column which renders 'name' field will have its text colored in white on a customer records.
+
+* In the tree view declaration, use ``options='"color_field": "my_color"'`` attribute in the ``tree`` tag::
+
+ ...
+
+
+ ...
+
+ ...
+
+
+ ...
+
+ With this example, the content of the field named `my_color` will be used to
+ populate the `my_color` CSS value. Use a function field to return whichever
+ color you want depending on the other record values. Note that this
+ overrides the rest of `colors` attributes, and that you need the tree
+ to load your field in the first place by adding it as invisible field.
+
+**Note that you should always use single quotes for fields' ``options`` and wrap nested values in double quotes since ``options`` is a JSON object.**
+
+Bug Tracker
+===========
+
+Bugs are tracked on `GitHub Issues
+`_. In case of trouble, please
+check there if your issue has already been reported. If you spotted it first,
+help us smash it by providing a detailed and welcomed feedback.
+
+Credits
+=======
+
+Contributors
+------------
+
+* Damien Crier
+* Holger Brunn
+* Artem Kostyuk
+* Guewen Baconnier
+
+Maintainer
+----------
+
+.. image:: https://odoo-community.org/logo.png
+ :alt: Odoo Community Association
+ :target: https://odoo-community.org
+
+This module is maintained by the OCA.
+
+OCA, or the Odoo Community Association, is a nonprofit organization whose
+mission is to support the collaborative development of Odoo features and
+promote its widespread use.
+
+To contribute to this module, please visit https://odoo-community.org.
diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/__init__.py b/ext/custom-addons/web_tree_dynamic_colored_field/__init__.py
new file mode 100644
index 00000000..8945c43c
--- /dev/null
+++ b/ext/custom-addons/web_tree_dynamic_colored_field/__init__.py
@@ -0,0 +1,2 @@
+# Copyright 2015-2018 Camptocamp SA, Damien Crier
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/__manifest__.py b/ext/custom-addons/web_tree_dynamic_colored_field/__manifest__.py
new file mode 100644
index 00000000..146c30db
--- /dev/null
+++ b/ext/custom-addons/web_tree_dynamic_colored_field/__manifest__.py
@@ -0,0 +1,19 @@
+# Copyright 2015-2018 Camptocamp SA, Damien Crier
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+{
+ 'name': 'Colorize field in tree views',
+ 'summary': 'Allows you to dynamically color fields on tree views',
+ 'category': 'Hidden/Dependency',
+ 'version': '11.0.1.0.1',
+ 'depends': ['web'],
+ 'author': "Camptocamp, Therp BV, Odoo Community Association (OCA)",
+ 'license': 'AGPL-3',
+ 'website': 'https://github.com/OCA/web',
+ 'demo': [
+ "demo/res_users.xml",
+ ],
+ 'data': [
+ 'views/web_tree_dynamic_colored_field.xml',
+ ],
+ 'installable': True,
+}
diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/static/description/icon.png b/ext/custom-addons/web_tree_dynamic_colored_field/static/description/icon.png
new file mode 100644
index 00000000..3a0328b5
Binary files /dev/null and b/ext/custom-addons/web_tree_dynamic_colored_field/static/description/icon.png differ
diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js b/ext/custom-addons/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js
new file mode 100644
index 00000000..d9e14c11
--- /dev/null
+++ b/ext/custom-addons/web_tree_dynamic_colored_field/static/src/js/web_tree_dynamic_colored_field.js
@@ -0,0 +1,134 @@
+odoo.define('web_tree_dynamic_colored_field', function (require) {
+ 'use strict';
+
+ var ListRenderer = require('web.ListRenderer');
+ var pyeval = require('web.pyeval');
+
+ ListRenderer.include({
+ /**
+ * Look up for a `color_field` parameter in tree `colors` attribute
+ *
+ * @override
+ */
+ _renderBody: function () {
+ if (this.arch.attrs.colors) {
+ var colorAttr = this.arch.attrs.colors.split(';')
+ .filter(color => color.trim().startsWith('color_field'));
+ if (colorAttr.length > 0) {
+ var colorField = colorAttr[0].split(':')[1].trim();
+ // validate the presence of that field in tree view
+ var fieldNames = _(this.columns).map(
+ (value) => { return value.attrs.name; }
+ );
+ if (fieldNames.indexOf(colorField) === -1) {
+ console.warn(
+ "No field named '" + colorField + "' present in view."
+ );
+ } else {
+ this.colorField = colorField;
+ }
+ }
+ }
+ return this._super();
+ },
+ /**
+ * Colorize a cell during it's render
+ *
+ * @override
+ */
+ _renderBodyCell: function (record, node, colIndex, options) {
+ var $td = this._super.apply(this, arguments);
+ var ctx = this.getEvalContext(record);
+ this.applyColorize($td, record, node, ctx);
+ return $td;
+ },
+
+ /**
+ * Colorize the current cell depending on expressions provided.
+ *
+ * @param {Query Node} $td a
tag inside a table representing a list view
+ * @param {Object} node an XML node (must be a )
+ */
+ applyColorize: function ($td, record, node, ctx) {
+ // safely resolve value of `color_field` given in
+ var treeColor = record.data[this.colorField];
+ if (treeColor) {
+ $td.css('color', treeColor);
+ }
+ // apply 's own `options`
+ if (!node.attrs.options) { return; }
+ if (node.tag !== 'field') { return; }
+ var nodeOptions = node.attrs.options;
+ if (!_.isObject(nodeOptions)) {
+ nodeOptions = pyeval.py_eval(nodeOptions);
+ }
+ this.applyColorizeHelper($td, nodeOptions, node, 'fg_color', 'color', ctx);
+ this.applyColorizeHelper($td, nodeOptions, node, 'bg_color', 'background-color', ctx);
+ },
+ /**
+ * @param {Object} nodeOptions a mapping of nodeOptions parameters to the color itself
+ * @param {Object} node an XML node (must be a )
+ * @param {string} nodeAttribute an attribute of a node to apply a style onto
+ * @param {string} cssAttribute a real CSS-compatible attribute
+ */
+ applyColorizeHelper: function ($td, nodeOptions, node, nodeAttribute, cssAttribute, ctx) {
+ if (nodeOptions[nodeAttribute]) {
+ var colors = _(nodeOptions[nodeAttribute].split(';'))
+ .chain()
+ .map(this.pairColors)
+ .value()
+ .filter(function CheckUndefined(value, index, ar) {
+ return value !== undefined;
+ });
+ for (var i=0, len=colors.length; i: ` forms to
+ * evaluatable expressions
+ *
+ * @param {string} pairColor `color: expression` pair
+ */
+ pairColors: function (pairColor) {
+ if (pairColor !== "") {
+ var pairList = pairColor.split(':'),
+ color = pairList[0],
+ // if one passes a bare color instead of an expression,
+ // then we consider that color is to be shown in any case
+ expression = pairList[1]? pairList[1] : 'True';
+ return [color, py.parse(py.tokenize(expression)), expression];
+ }
+ return undefined;
+ },
+ /**
+ * Construct domain evaluation context, mostly by passing
+ * record's fields's values to local scope.
+ *
+ * @param {Object} record a record to build a context from
+ */
+ getEvalContext: function (record) {
+ var ctx = _.extend(
+ {},
+ record.data,
+ pyeval.context()
+ );
+ for (var key in ctx) {
+ var value = ctx[key];
+ if (ctx[key] instanceof moment) {
+ // date/datetime fields are represented w/ Moment objects
+ // docs: https://momentjs.com/
+ ctx[key] = value.format('YYYY-MM-DD hh:mm:ss');
+ }
+ }
+ return ctx;
+ }
+ });
+});
diff --git a/ext/custom-addons/web_tree_dynamic_colored_field/views/web_tree_dynamic_colored_field.xml b/ext/custom-addons/web_tree_dynamic_colored_field/views/web_tree_dynamic_colored_field.xml
new file mode 100644
index 00000000..ea8e1129
--- /dev/null
+++ b/ext/custom-addons/web_tree_dynamic_colored_field/views/web_tree_dynamic_colored_field.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+