summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-04-16 18:34:56 +0200
committerChristophe Simonis <chs@odoo.com>2018-04-16 18:34:56 +0200
commit5f2d080cf85d54bc52895f9dbc4075b10989d324 (patch)
treec925509b609fb07f6fbef8896710b756c3c6a86f
parent026be48ccbbb15daefda070697b135f089f49564 (diff)
parentad825b673b57344a6a1571234f62a0b3aa543bf7 (diff)
[MERGE] forward port branch 11.0 up to ad825b673b5
-rw-r--r--addons/account/models/partner.py8
-rw-r--r--addons/account/views/partner_view.xml1
-rw-r--r--addons/account/wizard/wizard_tax_adjustments.py17
-rw-r--r--addons/account/wizard/wizard_tax_adjustments_view.xml9
-rw-r--r--addons/account_asset/models/account_asset.py2
-rw-r--r--addons/account_payment/controllers/payment.py30
-rw-r--r--addons/base_import/models/base_import.py1
-rw-r--r--addons/base_import/static/src/js/import_action.js1
-rw-r--r--addons/base_import/static/src/xml/base_import.xml2
-rw-r--r--addons/base_import/tests/test_base_import.py8
-rw-r--r--addons/board/static/src/js/dashboard.js26
-rw-r--r--addons/board/static/tests/dashboard_tests.js44
-rw-r--r--addons/google_calendar/views/res_config_settings_views.xml3
-rw-r--r--addons/hr_timesheet/models/hr_timesheet.py14
-rw-r--r--addons/hr_timesheet/report/report_timesheet_templates.xml4
-rw-r--r--addons/http_routing/__init__.py1
-rw-r--r--addons/http_routing/controllers/__init__.py4
-rw-r--r--addons/http_routing/controllers/main.py23
-rw-r--r--addons/http_routing/geoipresolver.py60
-rw-r--r--addons/http_routing/models/ir_http.py26
-rw-r--r--addons/l10n_ch/data/l10n_ch_chart_data.xml2
-rw-r--r--addons/l10n_ch/i18n_extra/de.po (renamed from addons/l10n_ch/i18n_extra/de_CH.po)191
-rw-r--r--addons/l10n_do/data/account.account.template.csv354
-rw-r--r--addons/l10n_do/data/account.tax.template.xml356
-rw-r--r--addons/l10n_do/data/account_account_tag_data.xml46
-rw-r--r--addons/l10n_do/data/account_chart_template_data.xml4
-rw-r--r--addons/l10n_do/data/account_data.xml38
-rw-r--r--addons/l10n_do/data/fiscal_position_template.xml116
-rw-r--r--addons/l10n_do/models/chart_template.py8
-rw-r--r--addons/mail/static/src/less/composer.less2
-rw-r--r--addons/mail/static/src/less/thread.less4
-rw-r--r--addons/note/views/note_views.xml2
-rw-r--r--addons/payment/controllers/portal.py4
-rw-r--r--addons/payment/static/src/js/payment_form.js14
-rw-r--r--addons/payment_authorize/models/payment.py4
-rw-r--r--addons/payment_authorize/tests/test_authorize.py4
-rw-r--r--addons/payment_stripe/models/payment.py2
-rw-r--r--addons/point_of_sale/models/pos_order.py14
-rw-r--r--addons/point_of_sale/static/src/js/models.js4
-rw-r--r--addons/portal/controllers/portal.py2
-rw-r--r--addons/portal/models/__init__.py1
-rw-r--r--addons/portal/models/ir_http.py15
-rw-r--r--addons/portal/views/portal_templates.xml1
-rw-r--r--addons/pos_mercury/data/pos_mercury_demo.xml4
-rw-r--r--addons/pos_mercury/models/pos_mercury.py6
-rw-r--r--addons/pos_mercury/models/pos_mercury_transaction.py8
-rw-r--r--addons/project/models/project.py2
-rw-r--r--addons/purchase/data/purchase_demo.xml8
-rw-r--r--addons/purchase/models/purchase.py6
-rw-r--r--addons/repair/views/repair_views.xml2
-rw-r--r--addons/sale/__manifest__.py4
-rw-r--r--addons/sale/models/account_invoice.py3
-rw-r--r--addons/sale/report/sale_report.xml1
-rw-r--r--addons/sale/report/sale_report_templates.xml4
-rw-r--r--addons/sale/wizard/sale_make_invoice_advance.py2
-rw-r--r--addons/stock/models/stock_move_line.py3
-rw-r--r--addons/stock/models/stock_production_lot.py12
-rw-r--r--addons/stock/report/report_location_barcode.xml4
-rw-r--r--addons/stock/views/stock_move_line_views.xml8
-rw-r--r--addons/stock/views/stock_move_views.xml7
-rw-r--r--addons/stock_account/data/stock_account_data.xml11
-rw-r--r--addons/stock_account/models/product.py118
-rw-r--r--addons/stock_account/models/stock.py116
-rw-r--r--addons/stock_account/tests/test_stockvaluation.py630
-rw-r--r--addons/stock_account/views/product_views.xml82
-rw-r--r--addons/stock_account/views/stock_account_views.xml80
-rw-r--r--addons/stock_account/wizard/__init__.py1
-rw-r--r--addons/stock_account/wizard/stock_quantity_history.py32
-rw-r--r--addons/stock_landed_costs/models/stock_landed_cost.py42
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js15
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js25
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js12
-rw-r--r--addons/web/static/src/js/views/abstract_renderer.js8
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js37
-rw-r--r--addons/web/static/src/js/views/calendar/calendar_model.js5
-rw-r--r--addons/web/static/src/js/views/form/form_controller.js1
-rw-r--r--addons/web/static/src/js/views/graph/graph_renderer.js64
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_controller.js48
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_model.js5
-rw-r--r--addons/web/static/src/less/datepicker.less3
-rw-r--r--addons/web/static/src/less/fields.less2
-rw-r--r--addons/web/static/src/less/form_view.less4
-rw-r--r--addons/web/static/src/less/kanban_column_progressbar.less1
-rw-r--r--addons/web/static/src/less/kanban_dashboard.less1
-rw-r--r--addons/web/static/src/less/list_view.less6
-rw-r--r--addons/web/static/tests/fields/basic_fields_tests.js11
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js146
-rw-r--r--addons/web/static/tests/views/calendar_tests.js35
-rw-r--r--addons/web/static/tests/views/kanban_tests.js112
-rw-r--r--addons/web_editor/models/ir_http.py6
-rw-r--r--addons/web_editor/static/src/js/editor/summernote.js11
-rw-r--r--addons/website/controllers/main.py11
-rw-r--r--addons/website/models/ir_http.py7
-rw-r--r--addons/website_event_sale/static/src/js/website.tour.event_sale.js1
-rw-r--r--addons/website_form/static/src/js/website_form.js6
-rw-r--r--addons/website_quote/report/sale_order_templates.xml6
-rw-r--r--addons/website_sale/models/res_config_settings.py2
-rw-r--r--addons/website_sale/static/src/js/website_sale_tour_buy.js1
-rw-r--r--addons/website_sale/views/templates.xml2
-rw-r--r--addons/website_sale_wishlist/controllers/main.py5
-rw-r--r--addons/website_sale_wishlist/static/src/js/website_sale_tour_wishlist.js130
-rw-r--r--addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js15
-rw-r--r--addons/website_sale_wishlist/tests/__init__.py1
-rw-r--r--addons/website_sale_wishlist/tests/test_wishlist_process.py10
-rw-r--r--addons/website_sale_wishlist/views/website_sale_wishlist_template.xml1
-rw-r--r--doc/_extensions/odoo_ext/switcher.py3
-rw-r--r--doc/cla/corporate/iterativo.md4
-rw-r--r--doc/cla/individual/eternalharvest.md11
-rw-r--r--doc/cla/individual/kirca.md1
-rw-r--r--doc/howtos/backend.rst11
-rw-r--r--doc/howtos/profilecode.rst52
-rw-r--r--odoo/addons/base/data/res_country_data.xml2
-rw-r--r--odoo/addons/base/data/res_currency_data.xml8
-rw-r--r--odoo/addons/base/data/res_currency_rate_demo.xml6
-rw-r--r--odoo/addons/base/models/ir_module.py2
-rw-r--r--odoo/addons/base/models/res_currency.py13
-rw-r--r--odoo/addons/base/tests/test_float.py9
-rw-r--r--odoo/http.py2
-rw-r--r--odoo/models.py20
-rw-r--r--odoo/tools/config.py2
120 files changed, 2632 insertions, 938 deletions
diff --git a/addons/account/models/partner.py b/addons/account/models/partner.py
index a1fa22a824c..40b1cd90ff5 100644
--- a/addons/account/models/partner.py
+++ b/addons/account/models/partner.py
@@ -394,7 +394,8 @@ class ResPartner(models.Model):
required=True)
property_account_position_id = fields.Many2one('account.fiscal.position', company_dependent=True,
string="Fiscal Position",
- help="The fiscal position will determine taxes and accounts used for the partner.", oldname="property_account_position")
+ help="The fiscal position will determine taxes and accounts used for the partner.", oldname="property_account_position",
+ domain="[('company_id', 'in', [company_id, False])]")
property_payment_term_id = fields.Many2one('account.payment.term', company_dependent=True,
string='Customer Payment Terms',
help="This payment term will be used instead of the default one for sales orders and customer invoices", oldname="property_payment_term")
@@ -441,3 +442,8 @@ class ResPartner(models.Model):
action['domain'] = literal_eval(action['domain'])
action['domain'].append(('partner_id', 'child_of', self.id))
return action
+
+ @api.onchange('company_id')
+ def _onchange_company_id(self):
+ if self.company_id:
+ return {'domain': {'property_account_position_id': [('company_id', 'in', [self.company_id.id, False])]}}
diff --git a/addons/account/views/partner_view.xml b/addons/account/views/partner_view.xml
index b4157614966..bc325f129bd 100644
--- a/addons/account/views/partner_view.xml
+++ b/addons/account/views/partner_view.xml
@@ -108,6 +108,7 @@
<field name="priority" eval="20"/>
<field name="arch" type="xml">
<field name="email" position="after">
+ <field name="company_id" invisible="1"/>
<field name="property_payment_term_id" widget="selection"/>
<field name="property_account_position_id" options="{'no_create': True, 'no_open': True}"/>
</field>
diff --git a/addons/account/wizard/wizard_tax_adjustments.py b/addons/account/wizard/wizard_tax_adjustments.py
index d498bb62afb..2f188b1abab 100644
--- a/addons/account/wizard/wizard_tax_adjustments.py
+++ b/addons/account/wizard/wizard_tax_adjustments.py
@@ -18,24 +18,26 @@ class TaxAdjustments(models.TransientModel):
debit_account_id = fields.Many2one('account.account', string='Debit account', required=True, domain=[('deprecated', '=', False)])
credit_account_id = fields.Many2one('account.account', string='Credit account', required=True, domain=[('deprecated', '=', False)])
amount = fields.Monetary(currency_field='company_currency_id', required=True)
+ adjustment_type = fields.Selection([('debit', 'Adjustment in favor of the Estate'), ('credit', 'Adjustment in your favor')], string="Adjustment Type", store=False, required=True)
company_currency_id = fields.Many2one('res.currency', readonly=True, default=lambda self: self.env.user.company_id.currency_id)
tax_id = fields.Many2one('account.tax', string='Adjustment Tax', ondelete='restrict', domain=[('type_tax_use', '=', 'adjustment')], required=True)
@api.multi
def _create_move(self):
+ adjustment_type = self.env.context.get('adjustment_type', (self.amount > 0.0 and 'debit' or 'credit'))
debit_vals = {
'name': self.reason,
- 'debit': self.amount,
+ 'debit': abs(self.amount),
'credit': 0.0,
'account_id': self.debit_account_id.id,
- 'tax_line_id': self.tax_id.id,
+ 'tax_line_id': adjustment_type == 'debit' and self.tax_id.id or False,
}
credit_vals = {
'name': self.reason,
'debit': 0.0,
- 'credit': self.amount,
+ 'credit': abs(self.amount),
'account_id': self.credit_account_id.id,
- 'tax_line_id': self.tax_id.id,
+ 'tax_line_id': adjustment_type == 'credit' and self.tax_id.id or False,
}
vals = {
'journal_id': self.journal_id.id,
@@ -48,6 +50,13 @@ class TaxAdjustments(models.TransientModel):
return move.id
@api.multi
+ def create_move_debit(self):
+ return self.with_context(adjustment_type='debit').create_move()
+
+ @api.multi
+ def create_move_credit(self):
+ return self.with_context(adjustment_type='credit').create_move()
+
def create_move(self):
#create the adjustment move
move_id = self._create_move()
diff --git a/addons/account/wizard/wizard_tax_adjustments_view.xml b/addons/account/wizard/wizard_tax_adjustments_view.xml
index 3d4ed0a9e9a..dba164388b9 100644
--- a/addons/account/wizard/wizard_tax_adjustments_view.xml
+++ b/addons/account/wizard/wizard_tax_adjustments_view.xml
@@ -12,6 +12,7 @@
<group>
<group>
<field name="amount"/>
+ <field name="adjustment_type"/>
</group>
<group>
<field name="tax_id" widget="selection"/>
@@ -26,8 +27,14 @@
</group>
</group>
<footer>
- <button name="create_move" string="Create and post move" type="object" default_focus="1" class="oe_highlight"/>
+ <div attrs="{'invisible': [('adjustment_type', '=', 'credit')]}">
+ <button name="create_move_debit" string="Create and post move" type="object" default_focus="1" class="oe_highlight"/>
<button string="Cancel" class="btn btn-default" special="cancel" />
+ </div>
+ <div attrs="{'invisible': [('adjustment_type', '!=', 'credit')]}">
+ <button name="create_move_credit" string="Create and post move" type="object" default_focus="1" class="oe_highlight"/>
+ <button string="Cancel" class="btn btn-default" special="cancel" />
+ </div>
</footer>
</form>
</field>
diff --git a/addons/account_asset/models/account_asset.py b/addons/account_asset/models/account_asset.py
index 3bb25d93e73..3b29938007c 100644
--- a/addons/account_asset/models/account_asset.py
+++ b/addons/account_asset/models/account_asset.py
@@ -419,7 +419,7 @@ class AccountAssetAsset(models.Model):
@api.model
def create(self, vals):
asset = super(AccountAssetAsset, self.with_context(mail_create_nolog=True)).create(vals)
- asset.compute_depreciation_board()
+ asset.sudo().compute_depreciation_board()
return asset
@api.multi
diff --git a/addons/account_payment/controllers/payment.py b/addons/account_payment/controllers/payment.py
index e2a5e6dbea9..2916a512b51 100644
--- a/addons/account_payment/controllers/payment.py
+++ b/addons/account_payment/controllers/payment.py
@@ -8,7 +8,7 @@ from odoo.http import request, route
class PaymentPortal(http.Controller):
- @route('/invoice/pay/<int:invoice_id>/form_tx', type='json', auth="user", website=True)
+ @route('/invoice/pay/<int:invoice_id>/form_tx', type='json', auth="public", website=True)
def invoice_pay_form(self, acquirer_id, invoice_id, save_token=False, access_token=None, **kwargs):
""" Json method that creates a payment.transaction, used to create a
transaction when the user clicks on 'pay now' button on the payment
@@ -17,13 +17,11 @@ class PaymentPortal(http.Controller):
:return html: form containing all values related to the acquirer to
redirect customers to the acquirer website """
success_url = kwargs.get('success_url', '/my')
+ callback_method = kwargs.get('callback_method', '')
+
invoice_sudo = request.env['account.invoice'].sudo().browse(invoice_id)
if not invoice_sudo:
return False
- # Check if the current user has access to this invoice
- commercial_partner_id = request.env.user.partner_id.commercial_partner_id.id
- if request.env['account.invoice'].sudo().search_count([('id', '=', invoice_id), ('message_partner_ids', 'child_of', commercial_partner_id)]) == 0:
- return False
try:
acquirer = request.env['payment.acquirer'].browse(int(acquirer_id))
@@ -35,7 +33,12 @@ class PaymentPortal(http.Controller):
invoice_sudo,
acquirer,
payment_token=token,
- tx_type='form_save' if save_token else 'form')
+ tx_type='form_save' if save_token else 'form',
+ add_tx_values={
+ 'callback_model_id': request.env['ir.model'].sudo().search([('model', '=', invoice_sudo._name)], limit=1).id,
+ 'callback_res_id': invoice_sudo.id,
+ 'callback_method': callback_method,
+ })
# set the transaction id into the session
request.session['portal_invoice_%s_transaction_id' % invoice_sudo.id] = tx.id
@@ -50,11 +53,12 @@ class PaymentPortal(http.Controller):
}
)
- @http.route('/invoice/pay/<int:invoice_id>/s2s_token_tx', type='http', auth='user', website=True)
+ @http.route('/invoice/pay/<int:invoice_id>/s2s_token_tx', type='http', auth='public', website=True)
def invoice_pay_token(self, invoice_id, pm_id=None, **kwargs):
""" Use a token to perform a s2s transaction """
error_url = kwargs.get('error_url', '/my')
success_url = kwargs.get('success_url', '/my')
+ callback_method = kwargs.get('callback_method', '')
access_token = kwargs.get('access_token')
params = {}
if access_token:
@@ -65,11 +69,6 @@ class PaymentPortal(http.Controller):
params['error'] = 'pay_invoice_invalid_doc'
return request.redirect(_build_url_w_params(error_url, params))
- # Check if the current user has access to this invoice
- commercial_partner_id = request.env.user.partner_id.commercial_partner_id.id
- if request.env['account.invoice'].sudo().search_count([('id', '=', invoice_id), ('message_partner_ids', 'child_of', commercial_partner_id)]) == 0:
- return False
-
try:
token = request.env['payment.token'].sudo().browse(int(pm_id))
except (ValueError, TypeError):
@@ -83,7 +82,12 @@ class PaymentPortal(http.Controller):
invoice_sudo,
token.acquirer_id,
payment_token=token,
- tx_type='server2server')
+ tx_type='server2server',
+ add_tx_values={
+ 'callback_model_id': request.env['ir.model'].sudo().search([('model', '=', invoice_sudo._name)], limit=1).id,
+ 'callback_res_id': invoice_sudo.id,
+ 'callback_method': callback_method,
+ })
# set the transaction id into the session
request.session['portal_invoice_%s_transaction_id' % invoice_sudo.id] = tx.id
diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py
index ff59aff918a..70ac02fefef 100644
--- a/addons/base_import/models/base_import.py
+++ b/addons/base_import/models/base_import.py
@@ -497,7 +497,6 @@ class Import(models.TransientModel):
'headers_type': header_types or False,
'preview': preview,
'options': options,
- 'advanced_mode': any([len(models.fix_import_export_id_paths(col)) > 1 for col in headers or []]),
'debug': self.user_has_groups('base.group_no_one'),
}
except Exception as error:
diff --git a/addons/base_import/static/src/js/import_action.js b/addons/base_import/static/src/js/import_action.js
index 11b81a6373a..a2dc616ee2c 100644
--- a/addons/base_import/static/src/js/import_action.js
+++ b/addons/base_import/static/src/js/import_action.js
@@ -307,7 +307,6 @@ var DataImport = Widget.extend(ControlPanelMixin, {
this.$buttons.filter('.o_import_button').add(this.$('.oe_import_file_reload'))
.prop('disabled', false);
this.$el.addClass('oe_import_preview');
- this.$('input.oe_import_advanced_mode').prop('checked', result.advanced_mode);
this.$('.oe_import_grid').html(QWeb.render('ImportView.preview', result));
if (result.headers.length === 1) {
diff --git a/addons/base_import/static/src/xml/base_import.xml b/addons/base_import/static/src/xml/base_import.xml
index 4130b1d0347..f882bf7f557 100644
--- a/addons/base_import/static/src/xml/base_import.xml
+++ b/addons/base_import/static/src/xml/base_import.xml
@@ -81,7 +81,7 @@
id="oe_import_has_header" checked="checked"/>
<label for="oe_import_has_header">The first row
contains the label of the column</label>
- <input type="checkbox" class="oe_import_advanced_mode" disabled="disabled"
+ <input type="checkbox" class="oe_import_advanced_mode" checked="checked"
id="oe_import_advanced_mode"/>
<label for="oe_import_advanced_mode">Show fields of relation fields (advanced)</label>
<p class="oe_import_noheaders">If the file contains
diff --git a/addons/base_import/tests/test_base_import.py b/addons/base_import/tests/test_base_import.py
index 55f3300da91..df2d18a3feb 100644
--- a/addons/base_import/tests/test_base_import.py
+++ b/addons/base_import/tests/test_base_import.py
@@ -258,7 +258,7 @@ class TestPreview(TransactionCase):
['qux', '5', '6'],
])
# Ensure we only have the response fields we expect
- self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options', 'advanced_mode', 'debug'])
+ self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options', 'debug'])
@unittest.skipUnless(can_import('xlrd'), "XLRD module not available")
def test_xls_success(self):
@@ -288,7 +288,7 @@ class TestPreview(TransactionCase):
['qux', '5', '6'],
])
# Ensure we only have the response fields we expect
- self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options', 'advanced_mode', 'debug'])
+ self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options', 'debug'])
@unittest.skipUnless(can_import('xlrd.xlsx'), "XLRD/XLSX not available")
def test_xlsx_success(self):
@@ -318,7 +318,7 @@ class TestPreview(TransactionCase):
['qux', '5', '6'],
])
# Ensure we only have the response fields we expect
- self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options','advanced_mode', 'debug'])
+ self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options', 'debug'])
@unittest.skipUnless(can_import('odf'), "ODFPY not available")
def test_ods_success(self):
@@ -348,7 +348,7 @@ class TestPreview(TransactionCase):
['aux', '5', '6'],
])
# Ensure we only have the response fields we expect
- self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options', 'advanced_mode', 'debug'])
+ self.assertItemsEqual(list(result), ['matches', 'headers', 'fields', 'preview', 'headers_type', 'options', 'debug'])
class test_convert_import_data(TransactionCase):
diff --git a/addons/board/static/src/js/dashboard.js b/addons/board/static/src/js/dashboard.js
index 2e56eb39685..5793908c02b 100644
--- a/addons/board/static/src/js/dashboard.js
+++ b/addons/board/static/src/js/dashboard.js
@@ -141,6 +141,31 @@ FormRenderer.include({
this._super.apply(this, arguments);
this.noContentHelp = params.noContentHelp;
this.actionsDescr = {};
+ this._boardSubcontrollers = []; // for board: controllers of subviews
+ },
+ /**
+ * Call `on_attach_callback` for each subview
+ *
+ * @override
+ */
+ on_attach_callback: function () {
+ _.each(this._boardSubcontrollers, function (controller) {
+ if ('on_attach_callback' in controller) {
+ controller.on_attach_callback();
+ }
+ });
+ },
+ /**
+ * Call `on_detach_callback` for each subview
+ *
+ * @override
+ */
+ on_detach_callback: function () {
+ _.each(this._boardSubcontrollers, function (controller) {
+ if ('on_detach_callback' in controller) {
+ controller.on_detach_callback();
+ }
+ });
},
//--------------------------------------------------------------------------
@@ -243,6 +268,7 @@ FormRenderer.include({
hasSelectors: false,
});
return view.getController(self).then(function (controller) {
+ self._boardSubcontrollers.push(controller);
return controller.appendTo(params.$node);
});
});
diff --git a/addons/board/static/tests/dashboard_tests.js b/addons/board/static/tests/dashboard_tests.js
index 0a1264dc589..6eaeae518b1 100644
--- a/addons/board/static/tests/dashboard_tests.js
+++ b/addons/board/static/tests/dashboard_tests.js
@@ -3,6 +3,7 @@ odoo.define('board.dashboard_tests', function (require) {
var testUtils = require('web.test_utils');
var FormView = require('web.FormView');
+var ListRenderer = require('web.ListRenderer');
var createView = testUtils.createView;
@@ -454,5 +455,48 @@ QUnit.test('clicking on a kanban\'s button should trigger the action', function
form.destroy();
});
+QUnit.test('subviews are aware of attach in or detach from the DOM', function (assert) {
+ assert.expect(2);
+
+ // patch list renderer `on_attach_callback` for the test only
+ testUtils.patch(ListRenderer, {
+ on_attach_callback: function () {
+ assert.step('subview on_attach_callback');
+ }
+ });
+
+ var form = createView({
+ View: FormView,
+ model: 'board',
+ data: this.data,
+ arch: '<form string="My Dashboard">' +
+ '<board style="2-1">' +
+ '<column>' +
+ '<action context="{}" view_mode="list" string="ABC" name="51" domain="[]"></action>' +
+ '</column>' +
+ '</board>' +
+ '</form>',
+ mockRPC: function (route) {
+ if (route === '/web/action/load') {
+ return $.when({
+ res_model: 'partner',
+ views: [[4, 'list']],
+ });
+ }
+ return this._super.apply(this, arguments);
+ },
+ archs: {
+ 'partner,4,list':
+ '<list string="Partner"><field name="foo"/></list>',
+ },
+ });
+
+ assert.verifySteps(['subview on_attach_callback']);
+
+ // restore on_attach_callback of ListRenderer
+ testUtils.unpatch(ListRenderer);
+
+ form.destroy();
+});
});
diff --git a/addons/google_calendar/views/res_config_settings_views.xml b/addons/google_calendar/views/res_config_settings_views.xml
index a7874c34c69..c5c7d19a1b7 100644
--- a/addons/google_calendar/views/res_config_settings_views.xml
+++ b/addons/google_calendar/views/res_config_settings_views.xml
@@ -13,12 +13,13 @@
<label for="cal_client_secret" string="Client Secret" class="col-xs-3 col-md-3 o_light_label"/>
<field name="cal_client_secret" password="True" nolabel="1"/>
</div>
- <a href="https://www.odoo.com/documentation/user/online/crm/calendar/google_calendar_credentials.html" class="oe-link" target="_blank"><i class="fa fa-fw fa-arrow-right"/>Tutorial</a>
+ <a href="https://www.odoo.com/documentation/user/11.0/crm/optimize/google_calendar_credentials.html" class="oe-link" target="_blank"><i class="fa fa-fw fa-arrow-right"/>Tutorial</a>
</div>
</div>
</field>
</record>
+ <field name="context">{'module' : 'general_settings'}</field>
<menuitem id="menu_calendar_google_tech_config"
name="API Credentials"
parent="calendar.menu_calendar_configuration"
diff --git a/addons/hr_timesheet/models/hr_timesheet.py b/addons/hr_timesheet/models/hr_timesheet.py
index 30bb3c9dff2..fa2ce2b944b 100644
--- a/addons/hr_timesheet/models/hr_timesheet.py
+++ b/addons/hr_timesheet/models/hr_timesheet.py
@@ -41,6 +41,13 @@ class AccountAnalyticLine(models.Model):
@api.model
def create(self, vals):
+ # compute employee only for timesheet lines, makes no sense for other lines
+ if not vals.get('employee_id') and vals.get('project_id'):
+ if vals.get('user_id'):
+ ts_user_id = vals['user_id']
+ else:
+ ts_user_id = self._default_user()
+ vals['employee_id'] = self.env['hr.employee'].search([('user_id', '=', ts_user_id)], limit=1).id
vals = self._timesheet_preprocess(vals)
return super(AccountAnalyticLine, self).create(vals)
@@ -62,13 +69,6 @@ class AccountAnalyticLine(models.Model):
if vals.get('employee_id') and not vals.get('user_id'):
employee = self.env['hr.employee'].browse(vals['employee_id'])
vals['user_id'] = employee.user_id.id
- # compute employee only for timesheet lines, makes no sense for other lines
- if not vals.get('employee_id') and vals.get('project_id'):
- if vals.get('user_id'):
- ts_user_id = vals['user_id']
- else:
- ts_user_id = self._default_user()
- vals['employee_id'] = self.env['hr.employee'].search([('user_id', '=', ts_user_id)], limit=1).id
# force customer partner, from the task or the project
if (vals.get('project_id') or vals.get('task_id')) and not vals.get('partner_id'):
partner_id = False
diff --git a/addons/hr_timesheet/report/report_timesheet_templates.xml b/addons/hr_timesheet/report/report_timesheet_templates.xml
index e6d0f0905cf..fea714a5d7a 100644
--- a/addons/hr_timesheet/report/report_timesheet_templates.xml
+++ b/addons/hr_timesheet/report/report_timesheet_templates.xml
@@ -36,7 +36,7 @@
<span t-field="l.user_id.partner_id.name"/>
</td>
<td >
- <span t-field="l.name"/>
+ <span t-field="l.name" t-options="{'widget': 'text'}"/>
</td>
<td t-if="show_task or show_project">
<t t-if="show_project"><span t-field="l.project_id.name"/></t>
@@ -72,4 +72,4 @@
name="hr_timesheet.report_timesheet"
file="report_timesheet"
/>
-</odoo> \ No newline at end of file
+</odoo>
diff --git a/addons/http_routing/__init__.py b/addons/http_routing/__init__.py
index dc5e6b693d1..7d34c7c054a 100644
--- a/addons/http_routing/__init__.py
+++ b/addons/http_routing/__init__.py
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from . import controllers
from . import models
diff --git a/addons/http_routing/controllers/__init__.py b/addons/http_routing/controllers/__init__.py
new file mode 100644
index 00000000000..5d4b25db9c0
--- /dev/null
+++ b/addons/http_routing/controllers/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import main
diff --git a/addons/http_routing/controllers/main.py b/addons/http_routing/controllers/main.py
new file mode 100644
index 00000000000..206aff1d639
--- /dev/null
+++ b/addons/http_routing/controllers/main.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import odoo
+
+from odoo import http
+from odoo.http import request
+from odoo.osv import expression
+from odoo.addons.web.controllers.main import WebClient, Home
+
+class Routing(Home):
+
+ @http.route('/website/translations', type='json', auth="public", website=True)
+ def get_website_translations(self, lang, mods=None):
+ Modules = request.env['ir.module.module'].sudo()
+ IrHttp = request.env['ir.http'].sudo()
+ domain = IrHttp._get_translation_frontend_modules_domain()
+ modules = Modules.search(
+ expression.AND([domain, [('state', '=', 'installed')]])
+ ).mapped('name')
+ if mods:
+ modules += mods
+ return WebClient().translations(mods=modules, lang=lang)
diff --git a/addons/http_routing/geoipresolver.py b/addons/http_routing/geoipresolver.py
new file mode 100644
index 00000000000..1f9b0e22724
--- /dev/null
+++ b/addons/http_routing/geoipresolver.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+import os.path
+
+try:
+ import GeoIP # Legacy
+except ImportError:
+ GeoIP = None
+
+try:
+ import geoip2
+ import geoip2.database
+except ImportError:
+ geoip2 = None
+
+class GeoIPResolver(object):
+ def __init__(self, fname):
+ self.fname = fname
+ try:
+ self._db = geoip2.database.Reader(fname)
+ self.version = 2
+ except Exception:
+ try:
+ self._db = GeoIP.open(fname, GeoIP.GEOIP_STANDARD)
+ self.version = 1
+ assert self._db.database_info is not None
+ except Exception:
+ raise ValueError('Invalid GeoIP database: %r' % fname)
+
+ def __del__(self):
+ if self.version == 2:
+ self._db.close()
+
+ @classmethod
+ def open(cls, fname):
+ if not GeoIP and not geoip2:
+ return None
+ if not os.path.exists(fname):
+ return None
+ return GeoIPResolver(fname)
+
+ def resolve(self, ip):
+ if self.version == 1:
+ return self._db.record_by_addr(ip) or {}
+ elif self.version == 2:
+ try:
+ r = self._db.city(ip)
+ except (ValueError, geoip2.errors.AddressNotFoundError):
+ return {}
+ return {
+ 'city': r.city.name,
+ 'country_code': r.country.iso_code,
+ 'country_name': r.country.name,
+ 'region': r.subdivisions[0].iso_code if r.subdivisions else None,
+ 'time_zone': r.location.time_zone,
+ }
+
+ # compat
+ def record_by_addr(self, addr):
+ return self.resolve(addr)
diff --git a/addons/http_routing/models/ir_http.py b/addons/http_routing/models/ir_http.py
index 4011f4987d7..5a9343e03ff 100644
--- a/addons/http_routing/models/ir_http.py
+++ b/addons/http_routing/models/ir_http.py
@@ -18,6 +18,8 @@ from odoo.addons.base.models.ir_http import RequestUID, ModelConverter
from odoo.http import request
from odoo.tools import config, ustr, pycompat
+from ..geoipresolver import GeoIPResolver
+
_logger = logging.getLogger(__name__)
# global resolver (GeoIP API is thread-safe, for multithreaded workers)
@@ -229,6 +231,13 @@ class IrHttp(models.AbstractModel):
return request.env['res.lang'].search([('code', '=', lang_code)], limit=1)
return request.env['res.lang'].search([], limit=1)
+ @classmethod
+ def _get_translation_frontend_modules_domain(cls):
+ """ Return a domain to list the domain adding web-translations and
+ dynamic resources that may be used frontend views
+ """
+ return []
+
bots = "bot|crawl|slurp|spider|curl|wget|facebookexternalhit".split("|")
@classmethod
@@ -258,25 +267,18 @@ class IrHttp(models.AbstractModel):
# Lazy init of GeoIP resolver
if odoo._geoip_resolver is not None:
return
+ geofile = config.get('geoip_database')
try:
- import GeoIP
- # updated database can be downloaded on MaxMind website
- # http://dev.maxmind.com/geoip/legacy/install/city/
- geofile = config.get('geoip_database')
- if os.path.exists(geofile):
- odoo._geoip_resolver = GeoIP.open(geofile, GeoIP.GEOIP_STANDARD)
- else:
- odoo._geoip_resolver = False
- _logger.warning('GeoIP database file %r does not exists, apt-get install geoip-database-contrib or download it from http://dev.maxmind.com/geoip/legacy/install/city/', geofile)
- except ImportError:
- odoo._geoip_resolver = False
+ odoo._geoip_resolver = GeoIPResolver.open(geofile) or False
+ except Exception as e:
+ _logger.warning('Cannot load GeoIP: %s', ustr(e))
@classmethod
def _geoip_resolve(cls):
if 'geoip' not in request.session:
record = {}
if odoo._geoip_resolver and request.httprequest.remote_addr:
- record = odoo._geoip_resolver.record_by_addr(request.httprequest.remote_addr) or {}
+ record = odoo._geoip_resolver.resolve(request.httprequest.remote_addr) or {}
request.session['geoip'] = record
@classmethod
diff --git a/addons/l10n_ch/data/l10n_ch_chart_data.xml b/addons/l10n_ch/data/l10n_ch_chart_data.xml
index e2ef5e99a29..a2933bac856 100644
--- a/addons/l10n_ch/data/l10n_ch_chart_data.xml
+++ b/addons/l10n_ch/data/l10n_ch_chart_data.xml
@@ -18,7 +18,7 @@
<field name="cash_account_code_prefix">100</field>
<field name="currency_id" ref="base.CHF"/>
<field name="transfer_account_id" ref="transfer_account_id"/>
- <field name="spoken_languages" eval="'it_IT;de_CH'"/>
+ <field name="spoken_languages" eval="'it_IT;de_DE;de_CH'"/>
</record>
<record id="transfer_account_id" model="account.account.template">
<field name="chart_template_id" ref="l10nch_chart_template"/>
diff --git a/addons/l10n_ch/i18n_extra/de_CH.po b/addons/l10n_ch/i18n_extra/de.po
index 0f9c0b78726..dfe19384420 100644
--- a/addons/l10n_ch/i18n_extra/de_CH.po
+++ b/addons/l10n_ch/i18n_extra/de.po
@@ -29,7 +29,6 @@ msgid "0% import."
msgstr "0% Import."
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_100_import
#: model:account.tax.template,name:l10n_ch.vat_100_import
msgid "100% dédouanement TVA"
msgstr "100% Verzollung MwSt."
@@ -149,69 +148,57 @@ msgid "8.0% invest. Incl."
msgstr "8.0% Invest. Inkl."
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4200
#: model:account.account.template,name:l10n_ch.ch_coa_4200
msgid "Achats de marchandises destinées à la revente"
msgstr "Handelswarenaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2030
#: model:account.account.template,name:l10n_ch.ch_coa_2030
msgid "Acomptes de clients"
msgstr "Erhaltene Anzahlungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1208
#: model:account.account.template,name:l10n_ch.ch_coa_1208
msgid "Acomptes sur les marchandises commerciales"
msgstr "Akonto auf Zwischenhandelswaren"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1218
#: model:account.account.template,name:l10n_ch.ch_coa_1218
msgid "Acomptes sur matières premières"
msgstr "Akonto auf Rohstoffe"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1149
#: model:account.account.template,name:l10n_ch.ch_coa_1149
msgid "Ajustement de la valeur des avances et des prêts"
msgstr "Wertberichtigungen Vorschüsse und Darlehen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1199
#: model:account.account.template,name:l10n_ch.ch_coa_1199
msgid "Ajustement de la valeur des créances à court terme"
msgstr "Wertberichtigungen sonstige kurzfristige Forderungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1449
#: model:account.account.template,name:l10n_ch.ch_coa_1449
msgid "Ajustement de la valeur des créances à long terme"
msgstr "Wertberichtigungen langfristige Forderungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1779
#: model:account.account.template,name:l10n_ch.ch_coa_1779
msgid "Ajustement de la valeur des goodwill"
msgstr "Wertberichtigungen Goodwill"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1489
#: model:account.account.template,name:l10n_ch.ch_coa_1489
msgid "Ajustement de la valeur des participations"
msgstr "Wertberichtigungen Beteiligungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1069
-#: model:account.account,name:l10n_ch.1_ch_coa_1409
#: model:account.account.template,name:l10n_ch.ch_coa_1069
#: model:account.account.template,name:l10n_ch.ch_coa_1409
msgid "Ajustement de la valeur des titres"
msgstr "Wertberichtigungen Wertschriften"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6800
#: model:account.account.template,name:l10n_ch.ch_coa_6800
msgid ""
"Amortissements et ajustements de valeur des postes sur immobilisations "
@@ -220,128 +207,107 @@ msgstr ""
"Abschreibungen und Wertberichtigungen auf Positionen des Anlagevermögens"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1519
#: model:account.account.template,name:l10n_ch.ch_coa_1519
msgid "Amortissements sur le mobilier et les installations"
msgstr "Abschreibungen auf Mobiliar und Einrichtungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1599
#: model:account.account.template,name:l10n_ch.ch_coa_1599
msgid "Amortissements sur les autres immobilisations corporelles meubles"
msgstr "Abschreibungen andere Sachanlagen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1709
#: model:account.account.template,name:l10n_ch.ch_coa_1709
msgid "Amortissements sur les brevets, know-how, licences, droits, dév."
msgstr "Abschreibungen auf Patente, Know-how, Lizenzen, Rechte, Entwicklungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1609
#: model:account.account.template,name:l10n_ch.ch_coa_1609
msgid "Amortissements sur les immeubles d’exploitation"
msgstr "Abschreibungen auf Geschäftsliegenschaften"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1559
#: model:account.account.template,name:l10n_ch.ch_coa_1559
msgid "Amortissements sur les installations de stockage"
msgstr "Abschreibungen und Wertberichtigungen Lagereinrichtungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1529
#: model:account.account.template,name:l10n_ch.ch_coa_1529
msgid "Amortissements sur les machines de bureau, inf. et syst. comm."
msgstr ""
"Abschreibungen auf Büromaschinen, Informatik, Kommunikationstechnologie"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1509
#: model:account.account.template,name:l10n_ch.ch_coa_1509
msgid "Amortissements sur les machines et appareils"
msgstr "Abschreibungen auf Maschinen und Apparate"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1549
#: model:account.account.template,name:l10n_ch.ch_coa_1549
msgid "Amortissements sur les outillages et appareils"
msgstr "Abschreibungen auf Werkzeuge und Geräte"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1539
#: model:account.account.template,name:l10n_ch.ch_coa_1539
msgid "Amortissements sur les véhicules"
msgstr "Abschreibungen auf Fahrzeuge"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1579
#: model:account.account.template,name:l10n_ch.ch_coa_1579
msgid "Amortissements sur les équipements et installations"
msgstr "Abschreibungen und Wertberichtigungen feste Einrichtungen und Installationen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2270
#: model:account.account.template,name:l10n_ch.ch_coa_2270
msgid "Assurances sociales et institutions de prévoyance"
msgstr "Sozialversicherungen und Vorsorgeeinrichtungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6300
#: model:account.account.template,name:l10n_ch.ch_coa_6300
msgid "Assurances-choses, droits, taxes, autorisations"
msgstr "Sachversicherungen, Abgaben, Gebühren, Bewilligungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_5800
#: model:account.account.template,name:l10n_ch.ch_coa_5800
msgid "Autres charges du personnel"
msgstr "Übriger Personalaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6700
#: model:account.account.template,name:l10n_ch.ch_coa_6700
msgid "Autres charges d‘exploitation"
msgstr "Übriger betrieblicher Aufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1190
#: model:account.account.template,name:l10n_ch.ch_coa_1190
msgid "Autres créances à court terme"
msgstr "Übrige kurzfristige Forderungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2210
#: model:account.account.template,name:l10n_ch.ch_coa_2210
msgid "Autres dettes à court terme"
msgstr "Übrige kurzfristige Verbindlichkeiten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2140
#: model:account.account.template,name:l10n_ch.ch_coa_2140
msgid "Autres dettes à court terme rémunérées"
msgstr "Übrige verzinsliche Verbindlichkeiten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2500
#: model:account.account.template,name:l10n_ch.ch_coa_2500
msgid "Autres dettes à long terme"
msgstr "Übrige langfristige Verbindlichkeiten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1590
#: model:account.account.template,name:l10n_ch.ch_coa_1590
msgid "Autres immobilisations corporelles meubles"
msgstr "Autres immobilisations corporelles meubles"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3600
#: model:account.account.template,name:l10n_ch.ch_coa_3600
msgid "Autres ventes et prestations de services"
msgstr "Übrige Erlöse aus Lieferungen und Leistungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1140
#: model:account.account.template,name:l10n_ch.ch_coa_1140
msgid "Avances et prêts"
msgstr "Vorschüsse und Darlehen"
@@ -378,19 +344,16 @@ msgid ""
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1700
#: model:account.account.template,name:l10n_ch.ch_coa_1700
msgid "Brevets, know-how, licences, droits, développement"
msgstr "Patente, Know-how, Lizenzen, Rechte, Entwicklungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2979
#: model:account.account.template,name:l10n_ch.ch_coa_2979
msgid "Bénéfice / perte de l’exercice"
msgstr "Jahresgewinn oder Jahresverlust"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2970
#: model:account.account.template,name:l10n_ch.ch_coa_2970
msgid "Bénéfice / perte reporté"
msgstr "Gewinnvortrag oder Verlustvortrag"
@@ -401,7 +364,6 @@ msgid "CHF ISR reference"
msgstr "CHF ESR Referenznummer"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1850
#: model:account.account.template,name:l10n_ch.ch_coa_1850
msgid ""
"Capital actions, capital social, droits de participations ou capital de "
@@ -409,115 +371,96 @@ msgid ""
msgstr "Nicht einbezahltes Aktien-, Stamm-, Anteilschein- oder"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2800
#: model:account.account.template,name:l10n_ch.ch_coa_2800
msgid "Capital-actions, capital social, capital de fondation"
msgstr "Aktien-, Stamm-, Anteilschein- oder Stiftungskapital"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4521
#: model:account.account.template,name:l10n_ch.ch_coa_4521
msgid "Charbon, briquettes, bois"
msgstr "Kohle, Briketts, Holz"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_7010
#: model:account.account.template,name:l10n_ch.ch_coa_7010
msgid "Charges accessoires"
msgstr "Aufwand Nebenbetrieb"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6000
#: model:account.account.template,name:l10n_ch.ch_coa_6000
msgid "Charges de locaux"
msgstr "Raumaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4000
#: model:account.account.template,name:l10n_ch.ch_coa_4000
msgid "Charges de matériel de l‘atelier"
msgstr "Materialaufwand Produktion"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_5900
#: model:account.account.template,name:l10n_ch.ch_coa_5900
msgid "Charges de personnels temporaires"
msgstr "Leistungen Dritter"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6200
#: model:account.account.template,name:l10n_ch.ch_coa_6200
msgid "Charges de véhicules et de transport"
msgstr "Fahrzeug- und Transportaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_7510
#: model:account.account.template,name:l10n_ch.ch_coa_7510
msgid "Charges des immeubles d‘exploitation"
msgstr "Aufwand betriebliche Liegenschaft"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6500
#: model:account.account.template,name:l10n_ch.ch_coa_6500
msgid "Charges d‘administration"
msgstr "Verwaltungsaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6400
#: model:account.account.template,name:l10n_ch.ch_coa_6400
msgid "Charges d’énergie et évacuation des déchets"
msgstr "Energie- und Entsorgungsaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6570
#: model:account.account.template,name:l10n_ch.ch_coa_6570
msgid "Charges et leasing d’informatique"
msgstr "Informatikaufwand inkl. Leasing"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_8500
#: model:account.account.template,name:l10n_ch.ch_coa_8500
msgid "Charges extraordinaires, exceptionnelles ou hors période"
msgstr "Ausserordentlicher, einmaliger oder periodenfremder Aufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6900
#: model:account.account.template,name:l10n_ch.ch_coa_6900
msgid "Charges financières"
msgstr "Finanzaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_8000
#: model:account.account.template,name:l10n_ch.ch_coa_8000
msgid "Charges hors exploitation"
msgstr "Betriebsfremder Aufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1300
#: model:account.account.template,name:l10n_ch.ch_coa_1300
msgid "Charges payées d‘avance"
msgstr "Bezahlter Aufwand des Folgejahres"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_5700
#: model:account.account.template,name:l10n_ch.ch_coa_5700
msgid "Charges sociales"
msgstr "Sozialversicherungsaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2300
#: model:account.account.template,name:l10n_ch.ch_coa_2300
msgid "Charges à payer"
msgstr "Noch nicht bezahlter Aufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3803
#: model:account.account.template,name:l10n_ch.ch_coa_3803
msgid "Commissions de tiers"
msgstr "Provisionen an Dritte"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4903
#: model:account.account.template,name:l10n_ch.ch_coa_4903
msgid "Commissions obtenues sur achats"
msgstr "Einkaufsprovisionen"
@@ -528,61 +471,51 @@ msgid "Companies"
msgstr "Unternehmen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1099
#: model:account.account.template,name:l10n_ch.ch_coa_1099
msgid "Compte d'attente autre"
msgstr "Unklare Beträge"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1091
#: model:account.account.template,name:l10n_ch.ch_coa_1091
msgid "Compte d'attente pour salaires"
msgstr "Lohndurchlaufkonto"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3710
#: model:account.account.template,name:l10n_ch.ch_coa_3710
msgid "Consommations propres"
msgstr "Eigenverbrauch"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1269
#: model:account.account.template,name:l10n_ch.ch_coa_1269
msgid "Correction de la valeur de stocks de produits finis"
msgstr "Wertberichtigungen fertige Erzeugnisse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1279
#: model:account.account.template,name:l10n_ch.ch_coa_1279
msgid "Corrections de la valeur des stock produits semi-ouvrés"
msgstr "Wertberichtigungen unfertige Erzeugnisse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1209
#: model:account.account.template,name:l10n_ch.ch_coa_1209
msgid "Corrections de la valeur des stocks de marchandises"
msgstr "Wertberichtigungen Handelswaren"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1289
#: model:account.account.template,name:l10n_ch.ch_coa_1289
msgid "Corrections de la valeur des travaux en cours"
msgstr "Wertberichtigungen nicht fakturierte Dienstleistungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1219
#: model:account.account.template,name:l10n_ch.ch_coa_1219
msgid "Corrections de la valeur sur matières premières"
msgstr "Wertberichtigungen Rohstoffe"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1180
#: model:account.account.template,name:l10n_ch.ch_coa_1180
msgid "Créances envers les assurances sociales et institutions de prévoyance"
msgstr "Forderungen gegenüber Sozialversicherungen und Vorsorgeeinrichtungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2000
#: model:account.account.template,name:l10n_ch.ch_coa_2000
msgid "Créanciers"
msgstr "Verbindlichkeiten aus Lieferungen und Leistungen (Kreditoren)"
@@ -593,65 +526,53 @@ msgid "Currency"
msgstr "Währung"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2100
-#: model:account.account,name:l10n_ch.1_ch_coa_2400
#: model:account.account.template,name:l10n_ch.ch_coa_2100
#: model:account.account.template,name:l10n_ch.ch_coa_2400
msgid "Dettes bancaires"
msgstr "Bankverbindlichkeiten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2160
#: model:account.account.template,name:l10n_ch.ch_coa_2160
msgid "Dettes envers l'actionnaire"
msgstr "Gesellschafterverbindlichkeiten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3806
-#: model:account.account,name:l10n_ch.1_ch_coa_4906
#: model:account.account.template,name:l10n_ch.ch_coa_3806
#: model:account.account.template,name:l10n_ch.ch_coa_4906
msgid "Différences de change"
msgstr "Währungsdifferenzen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2261
#: model:account.account.template,name:l10n_ch.ch_coa_2261
msgid "Dividendes"
msgstr "Beschlossene Ausschüttungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4071
#: model:account.account.template,name:l10n_ch.ch_coa_4071
msgid "Droits de douanes à l'importation"
msgstr "Einfuhrzölle"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1109
#: model:account.account.template,name:l10n_ch.ch_coa_1109
msgid "Ducroire"
msgstr "Delkredere"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1100
#: model:account.account.template,name:l10n_ch.ch_coa_1100
msgid "Débiteurs"
msgstr "Forderungen aus Lieferungen und Leistungen (Debitoren)"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2201
#: model:account.account.template,name:l10n_ch.ch_coa_2201
msgid "Décompte TVA"
msgstr "Abrechnungskonto MWST"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4009
#: model:account.account.template,name:l10n_ch.ch_coa_4009
msgid "Déductions obtenues sur achats"
msgstr "Einkaufsrabatte"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3009
#: model:account.account.template,name:l10n_ch.ch_coa_3009
msgid "Déductions sur ventes"
msgstr "Erlösminderungen"
@@ -662,13 +583,11 @@ msgid "EUR ISR reference"
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4540
#: model:account.account.template,name:l10n_ch.ch_coa_4540
msgid "Eau"
msgstr "Wasser"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4500
#: model:account.account.template,name:l10n_ch.ch_coa_4500
msgid "Electricité"
msgstr "Strom"
@@ -684,91 +603,74 @@ msgid "Email composition wizard"
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2450
#: model:account.account.template,name:l10n_ch.ch_coa_2450
msgid "Emprunts"
msgstr "Darlehen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2430
#: model:account.account.template,name:l10n_ch.ch_coa_2430
msgid "Emprunts obligataires"
msgstr "Obligationenanleihen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2120
-#: model:account.account,name:l10n_ch.1_ch_coa_2420
#: model:account.account.template,name:l10n_ch.ch_coa_2120
#: model:account.account.template,name:l10n_ch.ch_coa_2420
msgid "Engagements de financement par leasing"
msgstr "Verbindlichkeiten aus Finanzierungsleasing"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6100
#: model:account.account.template,name:l10n_ch.ch_coa_6100
msgid ""
"Entretien, réparations et remplacement des inst. servant à l’exploitation"
msgstr "Unterhalt, Reparaturen, Ersatz mobile Sachanlagen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1570
#: model:account.account.template,name:l10n_ch.ch_coa_1570
msgid "Equipements et Installations"
msgstr "Feste Einrichtungen und Installationen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3800
-#: model:account.account,name:l10n_ch.1_ch_coa_4900
#: model:account.account.template,name:l10n_ch.ch_coa_3800
#: model:account.account.template,name:l10n_ch.ch_coa_4900
msgid "Escomptes"
msgstr "Erlösminderungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4530
#: model:account.account.template,name:l10n_ch.ch_coa_4530
msgid "Essence"
msgstr "Benzin"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3804
#: model:account.account.template,name:l10n_ch.ch_coa_3804
msgid "Frais d'encaissement"
msgstr "Inkassoaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3807
#: model:account.account.template,name:l10n_ch.ch_coa_3807
msgid "Frais d'expédition"
msgstr "Versandkosten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4072
#: model:account.account.template,name:l10n_ch.ch_coa_4072
msgid "Frais de transport à l'achat"
msgstr "Transportkosten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4070
#: model:account.account.template,name:l10n_ch.ch_coa_4070
msgid "Frêts à l'achat"
msgstr "Frachtkosten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4510
#: model:account.account.template,name:l10n_ch.ch_coa_4510
msgid "Gaz"
msgstr "Gas"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1770
#: model:account.account.template,name:l10n_ch.ch_coa_1770
msgid "Goodwill"
msgstr "Goodwill"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1441
-#: model:account.account,name:l10n_ch.1_ch_coa_2451
#: model:account.account.template,name:l10n_ch.ch_coa_1441
#: model:account.account.template,name:l10n_ch.ch_coa_2451
msgid "Hypothèques"
@@ -803,59 +705,48 @@ msgid "ISR sent"
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1600
#: model:account.account.template,name:l10n_ch.ch_coa_1600
msgid "Immeubles d’exploitation"
msgstr "Geschäftsliegenschaften"
#. module: l10n_ch
-#: model:account.fiscal.position,name:l10n_ch.1_fiscal_position_template_import
#: model:account.fiscal.position.template,name:l10n_ch.fiscal_position_template_import
msgid "Import/Export"
msgstr "Import/Export"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1176
#: model:account.account.template,name:l10n_ch.ch_coa_1176
msgid "Impôt anticipé"
msgstr "Verrechnungssteuer"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2206
#: model:account.account.template,name:l10n_ch.ch_coa_2206
msgid "Impôt anticipé dû"
msgstr "Verrechnungssteuer"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1171
#: model:account.account.template,name:l10n_ch.ch_coa_1171
msgid "Impôt préalable: TVA s/investissements et autres charges d’exploitation"
msgstr "Vorsteuer MWST Investitionen, übriger Betriebsaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1170
#: model:account.account.template,name:l10n_ch.ch_coa_1170
msgid "Impôt préalable: TVA s/matériel, marchandises, prestations et énergie"
msgstr "Vorsteuer MWST Material, Waren, Dienstleistungen, Energie"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1189
-#: model:account.account,name:l10n_ch.1_ch_coa_2279
#: model:account.account.template,name:l10n_ch.ch_coa_1189
#: model:account.account.template,name:l10n_ch.ch_coa_2279
msgid "Impôt à la source"
msgstr "Quellensteuer"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2208
-#: model:account.account,name:l10n_ch.1_ch_coa_8900
#: model:account.account.template,name:l10n_ch.ch_coa_2208
#: model:account.account.template,name:l10n_ch.ch_coa_8900
msgid "Impôts directs"
msgstr "Direkte Steuern"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1550
#: model:account.account.template,name:l10n_ch.ch_coa_1550
msgid "Installations de stockage"
msgstr "Installations de stockage"
@@ -906,67 +797,56 @@ msgid "L10N Ch Postal"
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6260
#: model:account.account.template,name:l10n_ch.ch_coa_6260
msgid "Leasing et location de véhicules"
msgstr "Fahrzeugleasing und -mieten"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6105
#: model:account.account.template,name:l10n_ch.ch_coa_6105
msgid "Leasing immobilisations corporelles meubles"
msgstr "Leasingaufwand mobile Sachanlagen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1520
#: model:account.account.template,name:l10n_ch.ch_coa_1520
msgid "Machines de bureau, informatique, systèmes de communication"
msgstr "Büromaschinen, Informatik, Kommunikationstechnologie"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1500
#: model:account.account.template,name:l10n_ch.ch_coa_1500
msgid "Machines et appareils"
msgstr "Maschinen und Apparate"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1200
#: model:account.account.template,name:l10n_ch.ch_coa_1200
msgid "Marchandises commerciales"
msgstr "Handelswaren"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1250
#: model:account.account.template,name:l10n_ch.ch_coa_1250
msgid "Marchandises en consignation"
msgstr "Handelswaren in Konsignation"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1220
#: model:account.account.template,name:l10n_ch.ch_coa_1220
msgid "Matières auxiliaires"
msgstr "Werkstoffe"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1230
#: model:account.account.template,name:l10n_ch.ch_coa_1230
msgid "Matières consommables"
msgstr "Hilfs- und Verbrauchsmaterial"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1210
#: model:account.account.template,name:l10n_ch.ch_coa_1210
msgid "Matières premières"
msgstr "Rohstoffe"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4520
#: model:account.account.template,name:l10n_ch.ch_coa_4520
msgid "Mazout"
msgstr "Heizöl"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1510
#: model:account.account.template,name:l10n_ch.ch_coa_1510
msgid "Mobilier et installations"
msgstr "Mobiliar und Einrichtungen"
@@ -977,25 +857,21 @@ msgid "Optical reading line, as it will be printed on ISR"
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1540
#: model:account.account.template,name:l10n_ch.ch_coa_1540
msgid "Outillages et appareils"
msgstr "Werkzeuge und Geräte"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1480
#: model:account.account.template,name:l10n_ch.ch_coa_1480
msgid "Participations"
msgstr "Beteiligungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4086
#: model:account.account.template,name:l10n_ch.ch_coa_4086
msgid "Pertes de matières"
msgstr "Warenschwund"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3805
#: model:account.account.template,name:l10n_ch.ch_coa_3805
msgid "Pertes sur créances clients, variation ducroire"
msgstr "Verluste Forderungen (Debitoren), Veränderung Delkredere"
@@ -1013,13 +889,11 @@ msgid ""
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4400
#: model:account.account.template,name:l10n_ch.ch_coa_4400
msgid "Prestations / travaux de tiers"
msgstr "Aufwand für bezogene Dienstleistungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3700
#: model:account.account.template,name:l10n_ch.ch_coa_3700
msgid "Prestations propres"
msgstr "Eigenleistungen"
@@ -1049,136 +923,113 @@ msgid ""
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_7000
#: model:account.account.template,name:l10n_ch.ch_coa_7000
msgid "Produits accessoires"
msgstr "Ertrag Nebenbetrieb"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_7500
#: model:account.account.template,name:l10n_ch.ch_coa_7500
msgid "Produits des immeubles d‘exploitation"
msgstr "Ertrag betriebliche Liegenschaft"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2301
#: model:account.account.template,name:l10n_ch.ch_coa_2301
msgid "Produits encaissés d’avance"
msgstr "Erhaltener Ertrag des Folgejahres"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_8510
#: model:account.account.template,name:l10n_ch.ch_coa_8510
msgid "Produits extraordinaires, exceptionnels ou hors période"
msgstr "Ausserordentlicher, einmaliger oder periodenfremder Ertrag"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6950
#: model:account.account.template,name:l10n_ch.ch_coa_6950
msgid "Produits financiers"
msgstr "Finanzertrag"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_8100
#: model:account.account.template,name:l10n_ch.ch_coa_8100
msgid "Produits hors exploitation"
msgstr "Betriebsfremder Ertrag"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1301
#: model:account.account.template,name:l10n_ch.ch_coa_1301
msgid "Produits à recevoir"
msgstr "Noch nicht erhaltener Ertrag"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2980
#: model:account.account.template,name:l10n_ch.ch_coa_2980
msgid ""
"Propres actions, parts sociales, droits de participations (poste négatif)"
msgstr "Eigene Aktien, Stammanteile oder Anteilscheine (Minusposten)"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2600
#: model:account.account.template,name:l10n_ch.ch_coa_2600
msgid "Provisions"
msgstr "Rückstellungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2330
#: model:account.account.template,name:l10n_ch.ch_coa_2330
msgid "Provisions à court terme"
msgstr "Kurzfristige Rückstellungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1440
#: model:account.account.template,name:l10n_ch.ch_coa_1440
msgid "Prêts"
msgstr "Darlehen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_6600
#: model:account.account.template,name:l10n_ch.ch_coa_6600
msgid "Publicité"
msgstr "Werbeaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3801
#: model:account.account.template,name:l10n_ch.ch_coa_3801
msgid "Rabais et réduction de prix"
msgstr "Rabatte und Preisreduktionen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4901
#: model:account.account.template,name:l10n_ch.ch_coa_4901
msgid "Rabais et réductions de prix"
msgstr "Rabatte und Preisreduktionen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3802
-#: model:account.account,name:l10n_ch.1_ch_coa_4092
#: model:account.account.template,name:l10n_ch.ch_coa_3802
#: model:account.account.template,name:l10n_ch.ch_coa_4092
msgid "Ristournes"
msgstr "Rückvergütungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2940
#: model:account.account.template,name:l10n_ch.ch_coa_2940
msgid "Réserves d‘évaluation"
msgstr "Aufwertungsreserve"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2960
#: model:account.account.template,name:l10n_ch.ch_coa_2960
msgid "Réserves libres"
msgstr "Freiwillige Gewinnreserven"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2950
#: model:account.account.template,name:l10n_ch.ch_coa_2950
msgid "Réserves légales issues du bénéfice"
msgstr "Gesetzliche Gewinnreserve"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2900
#: model:account.account.template,name:l10n_ch.ch_coa_2900
msgid "Réserves légales issues du capital"
msgstr "Gesetzliche Kapitalreserve"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_5000
#: model:account.account.template,name:l10n_ch.ch_coa_5000
msgid "Salaires"
msgstr "Lohnaufwand"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1260
#: model:account.account.template,name:l10n_ch.ch_coa_1260
msgid "Stocks de produits finis"
msgstr "Fertige Erzeugnisse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1270
#: model:account.account.template,name:l10n_ch.ch_coa_1270
msgid "Stocks de produits semi-ouvrés"
msgstr ""
@@ -1294,133 +1145,111 @@ msgid "Switzerland VAT Form: grid 420"
msgstr ""
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_O_import
#: model:account.tax.template,name:l10n_ch.vat_O_import
msgid "TVA 0% Importations de biens et services"
msgstr "MwSt. 0% auf Importe von Gütern und Dienstleistungen"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_O_exclude
#: model:account.tax.template,name:l10n_ch.vat_O_exclude
msgid "TVA 0% exclue"
msgstr "MwSt. 0% ausgeschlossen"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_25_purchase_incl
#: model:account.tax.template,name:l10n_ch.vat_25_purchase_incl
msgid "TVA 2.5% sur achat B&S (Incl. TR)"
msgstr "MwSt. 2,5 % auf Einkäufe B&S (inkl. USt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_25_purchase
#: model:account.tax.template,name:l10n_ch.vat_25_purchase
msgid "TVA 2.5% sur achat B&S (TR)"
msgstr "MwSt. 2,5 % auf Einkäufe B&S (USt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_25_invest_incl
#: model:account.tax.template,name:l10n_ch.vat_25_invest_incl
msgid "TVA 2.5% sur invest. et autres ch. (Incl. TR)"
msgstr "MwSt. 2,5% auf Invest. und sonst. Aufw. (inkl. USt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_25_invest
#: model:account.tax.template,name:l10n_ch.vat_25_invest
msgid "TVA 2.5% sur invest. et autres ch. (TR)"
msgstr "MwSt. 2,5% auf Invest. und sonst. Aufw. (USt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_38_purchase_incl
#: model:account.tax.template,name:l10n_ch.vat_38_purchase_incl
msgid "TVA 3.8% sur achat B&S (Incl. TS)"
msgstr "MwSt. 3,8% auf Einkäufe B&S (inkl. LSt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_38_purchase
#: model:account.tax.template,name:l10n_ch.vat_38_purchase
msgid "TVA 3.8% sur achat B&S (TS)"
msgstr "MwSt. 3,8% auf Einkäufe B&S (LSt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_38_invest_incl
#: model:account.tax.template,name:l10n_ch.vat_38_invest_incl
msgid "TVA 3.8% sur invest. et autres ch. (Incl. TS)"
msgstr "MwSt. 3,8% auf Invest. und sonst. Aufw. (inkl. LSt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_38_invest
#: model:account.tax.template,name:l10n_ch.vat_38_invest
msgid "TVA 3.8% sur invest. et autres ch. (TS)"
msgstr "MwSt. 3,8% auf Invest. und sonst. Aufw. (LSt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_80_purchase_incl
#: model:account.tax.template,name:l10n_ch.vat_80_purchase_incl
msgid "TVA 8.0% sur achat B&S (Incl. TN)"
msgstr "MwSt. 8.0% auf Einkäufe B&S (inkl. NRZ)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_80_purchase
#: model:account.tax.template,name:l10n_ch.vat_80_purchase
msgid "TVA 8.0% sur achat B&S (TN)"
msgstr "MwSt. 8,0% auf Einkäufe B&S (NRZ)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_80_invest_incl
#: model:account.tax.template,name:l10n_ch.vat_80_invest_incl
msgid "TVA 8.0% sur invest. et autres ch. (Incl. TN)"
msgstr "MwSt. 8,0% auf Invest. und sonst. Aufw. (inkl. NRZ)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_80_invest
#: model:account.tax.template,name:l10n_ch.vat_80_invest
msgid "TVA 8.0% sur invest. et autres ch. (TN)"
msgstr "MwSt. 8,0% auf Invest. und sonst. Aufw. (NRZ)"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_2200
#: model:account.account.template,name:l10n_ch.ch_coa_2200
msgid "TVA due"
msgstr "Geschuldete MwSt. (Umsatzsteuer)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_XO
#: model:account.tax.template,name:l10n_ch.vat_XO
msgid "TVA due a 0% (Exportations)"
msgstr "Zu zahlende MwSt. bei 0% (Exporte)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_25
#: model:account.tax.template,name:l10n_ch.vat_25
msgid "TVA due a 2.5% (TR)"
msgstr "Zu zahlende MwSt. bei 2,5% (USt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_38
#: model:account.tax.template,name:l10n_ch.vat_38
msgid "TVA due a 3.8% (TS)"
msgstr "Zu zahlende MwSt. bei 3,8% (LSt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_80
#: model:account.tax.template,name:l10n_ch.vat_80
msgid "TVA due a 8.0% (TN)"
msgstr "Zu zahlende MwSt. bei 8,0% (NRZ)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_25_incl
#: model:account.tax.template,name:l10n_ch.vat_25_incl
msgid "TVA due à 2.5% (Incl. TR)"
msgstr "Zu zahlende MwSt. bei 2,5% (inkl. USt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_38_incl
#: model:account.tax.template,name:l10n_ch.vat_38_incl
msgid "TVA due à 3.8% (Incl. TS)"
msgstr "Zu zahlende MwSt. bei 3,8% (inkl. LSt)"
#. module: l10n_ch
-#: model:account.tax,name:l10n_ch.1_vat_80_incl
#: model:account.tax.template,name:l10n_ch.vat_80_incl
msgid "TVA due à 8.0% (Incl. TN)"
msgstr "Zu zahlende MwSt. bei 8,0% (inkl. NRZ)"
@@ -1458,113 +1287,93 @@ msgid "The reference number associated with this invoice"
msgstr ""
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1060
#: model:account.account.template,name:l10n_ch.ch_coa_1060
msgid "Titres"
msgstr "Wertschriften"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1400
#: model:account.account.template,name:l10n_ch.ch_coa_1400
msgid "Titres à long terme"
msgstr "Wertschriften"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_transfer_account_id
#: model:account.account.template,name:l10n_ch.transfer_account_id
msgid "Transferts internes"
msgstr "Interne Verrechnungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1280
#: model:account.account.template,name:l10n_ch.ch_coa_1280
msgid "Travaux en cours"
msgstr "Nicht fakturierte Dienstleistungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3940
#: model:account.account.template,name:l10n_ch.ch_coa_3940
msgid "Variation de la valeur des prestations non facturées"
msgstr "Bestandesänderungen nicht fakturierte Dienstleistungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1287
#: model:account.account.template,name:l10n_ch.ch_coa_1287
msgid "Variation de la valeur des travaux en cours"
msgstr "Bestandesänderungen nicht fakturierte Dienstleistungen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1277
#: model:account.account.template,name:l10n_ch.ch_coa_1277
msgid "Variation de stock produits semi-ouvrés"
msgstr "Bestandesänderungen unfertige Erzeugnisse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1267
#: model:account.account.template,name:l10n_ch.ch_coa_1267
msgid "Variation de stocks de produits finis"
msgstr "Bestandesänderungen fertige Erzeugnisse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1207
-#: model:account.account,name:l10n_ch.1_ch_coa_4800
#: model:account.account.template,name:l10n_ch.ch_coa_1207
#: model:account.account.template,name:l10n_ch.ch_coa_4800
msgid "Variation des stocks de marchandises"
msgstr "Bestandesänderungen Handelsware"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4801
#: model:account.account.template,name:l10n_ch.ch_coa_4801
msgid "Variation des stocks de matières premières"
msgstr "Bestandesänderungen Rohstoffe"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3901
#: model:account.account.template,name:l10n_ch.ch_coa_3901
msgid "Variation des stocks de produits finis"
msgstr "Bestandesänderungen fertige Erzeugnisse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3900
#: model:account.account.template,name:l10n_ch.ch_coa_3900
msgid "Variation des stocks de produits semi-finis"
msgstr "Bestandesänderungen unfertige Erzeugnisse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1217
#: model:account.account.template,name:l10n_ch.ch_coa_1217
msgid "Variation des stocks des matières premières"
msgstr "Bestandesänderungen Rohstoffe"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_4008
-#: model:account.account,name:l10n_ch.1_ch_coa_4080
#: model:account.account.template,name:l10n_ch.ch_coa_4008
#: model:account.account.template,name:l10n_ch.ch_coa_4080
msgid "Variations de stocks"
msgstr "Inventurdifferenzen"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3200
#: model:account.account.template,name:l10n_ch.ch_coa_3200
msgid "Ventes de marchandises"
msgstr "Handelserlöse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3400
#: model:account.account.template,name:l10n_ch.ch_coa_3400
msgid "Ventes de prestations"
msgstr "Dienstleistungserlöse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_3000
#: model:account.account.template,name:l10n_ch.ch_coa_3000
msgid "Ventes de produits fabriqués"
msgstr "Produktionserlöse"
#. module: l10n_ch
-#: model:account.account,name:l10n_ch.1_ch_coa_1530
#: model:account.account.template,name:l10n_ch.ch_coa_1530
msgid "Véhicules"
msgstr "Fahrzeuge"
diff --git a/addons/l10n_do/data/account.account.template.csv b/addons/l10n_do/data/account.account.template.csv
index c24b83d6e1d..edc22fcd988 100644
--- a/addons/l10n_do/data/account.account.template.csv
+++ b/addons/l10n_do/data/account.account.template.csv
@@ -6,66 +6,71 @@ do_niif_11020200,11020200,Operaciones en Bolsa,account.data_account_type_current
do_niif_11020300,11020300,Otros Valores Negociables,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1102"
do_niif_11030101,11030101,Cheques Devueltos por Cobrar,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110301"
do_niif_11030102,11030102,Intereses por Cobrar,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110301"
-do_niif_11030201,11030201,Cuenta por Cobrar a Clientes,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
-do_niif_11030202,11030202,Cuenta por Cobrar a Funcionarios y Empleados,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
-do_niif_11030203,11030203,Cuenta por Cobrar a Afiliadas,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
-do_niif_11030204,11030204,Cuenta por Cobrar a Accionistas,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
+do_niif_11030201,11030201,Cuentas por Cobrar a Clientes,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
+do_niif_11030202,11030202,Cuentas por Cobrar a Funcionarios y Empleados,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
+do_niif_11030203,11030203,Cuentas por Cobrar a Afiliadas,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
+do_niif_11030204,11030204,Cuentas por Cobrar a Accionistas,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
do_niif_11030205,11030205,Otras Cuentas por Cobrar,account.data_account_type_receivable,TRUE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1103,account_tag_110302"
-do_niif_11040100,11040100,Provisión Incobrables a Clientes,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
-do_niif_11040200,11040200,Provisión Incobrables a Funcionarios y Empleados,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
-do_niif_11040300,11040300,Provisión Incobrables a Afiliadas,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
-do_niif_11040400,11040400,Provisión Incobrables a Accionistas,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
-do_niif_11040500,11040500,Provisión Otras Cuentas Incobrables,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
+do_niif_11040100,11040100,Provisiones de Incobrables a Clientes,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
+do_niif_11040200,11040200,Provisiones de Incobrables a Funcionarios y Empleados,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
+do_niif_11040300,11040300,Provisiones de Incobrables a Afiliadas,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
+do_niif_11040400,11040400,Provisiones de Incobrables a Accionistas,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
+do_niif_11040500,11040500,Provisiones de Otras Cuentas Incobrables,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1104"
do_niif_11050100,11050100,Inventario de Mercancías o Productos Terminados,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
do_niif_11050200,11050200,Inventario de Materia Prima,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
do_niif_11050300,11050300,Inventario en Tránsito,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
-do_niif_11050400,11050400,Materiales y Suministros en Inventario,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
-do_niif_11050500,11050500,Combustibles en Inventario,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
+do_niif_11050400,11050400,Inventario de Materiales y Suministros,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
+do_niif_11050500,11050500,Inventario de Combustibles,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
do_niif_11050600,11050600,Bienes Enviados No Facturados,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1105"
do_niif_11060100,11060100,Deterioro Acum. de Inventario en Almacen,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1106"
do_niif_11060200,11060200,Deterioro Acum. de Materiales y Suministros,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1106"
do_niif_11060300,11060300,Deterioro Acum. de Combustibles,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1106"
-do_niif_11070100,11070100,Obsolescencia Inventario en Almacen,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1107"
-do_niif_11070200,11070200,Obsolescencia Materiales y Suministros,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1107"
-do_niif_11070300,11070300,Obsolescencia Combustibles,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1107"
-do_niif_11080101,11080101,ITBIS Pagado en Compras Locales,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
-do_niif_11080102,11080102,ITBIS Pagado en Servicios Locales,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
-do_niif_11080103,11080103,ITBIS Pagado por Importaciones,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
-do_niif_11080301,11080301,ITBIS Pagado en Ventas con Tarjeta de Crédito (Norma 08-04),account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110803"
-do_niif_11080302,11080302,Saldo a Favor ITBIS,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110803"
-do_niif_11080303,11080303,Saldo a Favor ISR,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110803"
+do_niif_11070100,11070100,Obsolescencia de Inventario en Almacen,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1107"
+do_niif_11070200,11070200,Obsolescencia de Materiales y Suministros,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1107"
+do_niif_11070300,11070300,Obsolescencia de Combustibles,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1107"
+do_niif_11080101,11080101,ITBIS Pagado en Compras de Bienes Locales,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
+do_niif_11080102,11080102,ITBIS Pagado en Compras de Servicios Deducibles,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
+do_niif_11080103,11080103,ITBIS Pagado en Importaciones,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
+do_niif_11080104,11080104,ITBIS en Compras de Bienes o Servicios Sujetos a Proporcionalidad,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
+do_niif_11080105,11080105,ITBIS en Importaciones Sujeto a Proporcionalidad,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
+do_niif_11080106,11080106,ITBIS Pagado en Importaciones Sujeto a Proporcionalidad,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110801"
+do_niif_11080301,11080301,ITBIS Retenido por Ventas (N08-04 y N02-05),account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110803"
+do_niif_11080302,11080302,ITBIS Retenido por Entidades del Estado (5%),account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110803"
+do_niif_11080303,11080303,Saldo a Favor Anterior,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1108,account_tag_110803"
do_niif_11090100,11090100,Acciones Temporales,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1109"
do_niif_11090200,11090200,Depósitos a Plazo Temporales,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1109"
do_niif_11090300,11090300,Bonos Temporales,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1109"
do_niif_11090400,11090400,Fianzas y Depósitos,account.data_account_type_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1109"
-do_niif_11100100,11100100,Gastos Pagados por Anticipado,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
-do_niif_11100200,11100200,Renta Pagada por Anticipado,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
-do_niif_11100300,11100300,Seguros Pagados por Anticipado,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
-do_niif_11100400,11100400,Anticipos ISR,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
-do_niif_11100500,11100500,Anticipos Gastos,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
-do_niif_11100600,11100600,Anticipos 1% Activos,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
+do_niif_11100100,11100100,Avance a Proveedores,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
+do_niif_11100200,11100200,Alquileres pagados por Anticipado,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
+do_niif_11100300,11100300,Anticipos para Seguros,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
+do_niif_11100400,11100400,Anticipos para ISR,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
+do_niif_11100500,11100500,Anticipos para Gastos,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
+do_niif_11100600,11100600,Anticipos para 1% Activos,account.data_account_type_prepayments,FALSE,do_chart_template,"account_tag_1,account_tag_11,account_tag_1110"
do_niif_12010101,12010101,Terrenos,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120101"
do_niif_12010102,12010102,Edificaciones,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120101"
do_niif_12010103,12010103,Mejoras en Edificaciones,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120101"
-do_niif_12010201,12010201,Equipo de Transporte,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120102"
-do_niif_12010202,12010202,Mobiliario y Equipos,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120102"
-do_niif_12010301,12010301,Maquinaria,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120103"
+do_niif_12010104,12010104,Mejoras en Edificaciones y Locales Arrendados,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120101"
+do_niif_12010201,12010201,Equipos de Transporte Liviano,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120102"
+do_niif_12010202,12010202,Mobiliarios y Equipos de Oficina,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120102"
+do_niif_12010301,12010301,Maquinarias,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120103"
do_niif_12010302,12010302,Herramientas,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120103"
do_niif_12010303,12010303,Instalaciones,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120103"
-do_niif_12010304,12010304,Misceláneos u otros activos,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120103"
+do_niif_12010304,12010304,Sistemas de Cámara y Seguridad,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120103"
+do_niif_12010305,12010305,Misceláneos u otros activos,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1201,account_tag_120103"
do_niif_12020100,12020100,Depreciación Acum. de Edificios,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
-do_niif_12020200,12020200,Depreciación Acum. de Equipo de Transporte,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
-do_niif_12020300,12020300,Depreciación Acum. de Mobiliario y Equipos,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
-do_niif_12020400,12020400,Depreciación Acum. de Maquinaria,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
+do_niif_12020200,12020200,Depreciación Acum. de Equipos de Transporte,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
+do_niif_12020300,12020300,Depreciación Acum. de Mobiliarios y Equipos,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
+do_niif_12020400,12020400,Depreciación Acum. de Maquinarias,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
do_niif_12020500,12020500,Depreciación Acum. de Herramientas,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
do_niif_12020600,12020600,Depreciación Acum. de Instalaciones,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1202"
do_niif_12040100,12040100,Marcas y Patentes,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1204"
-do_niif_12040200,12040200,Programas Informáticos,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1204"
-do_niif_12050100,12050100,Edificios y Locales Arrendados,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1205"
-do_niif_12050200,12050200,Maquinaria y Equipo Arrendados,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1205"
-do_niif_12050300,12050300,Instalaciones Arrendadas,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1205"
-do_niif_12060100,12060100,Depreciación Acum. Edificios y Locales Arrendados,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1206"
-do_niif_12060200,12060200,Depreciación Acum. Maquinaria y Equipo Arrendados,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1206"
+do_niif_12040200,12040200,Licencias y Programas Informáticos,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1204"
+do_niif_12050100,12050100,Edificaciones y Locales Arrendados,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1205"
+do_niif_12050200,12050200,Maquinarias y Equipos Arrendados,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1205"
+do_niif_12050300,12050300,Instalaciones Arrendadas,account.data_account_type_fixed_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1205"
+do_niif_12060100,12060100,Depreciación Acum. Edificaciones y Locales Arrendados,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1206"
+do_niif_12060200,12060200,Depreciación Acum. Maquinarias y Equipos Arrendados,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1206"
do_niif_12060300,12060300,Depreciación Acum. Instalaciones Arrendadas,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1206"
do_niif_12070100,12070100,Deterioro Valor Acum. Edificios y Locales Arrendados,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1207"
do_niif_12070200,12070200,Deterioro Valor Acum. Maquinaria y Equipo Arrendado,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1207"
@@ -74,11 +79,12 @@ do_niif_12080100,12080100,Acciones en otras sociedades,account.data_account_type
do_niif_12090100,12090100,Diferencias temporales deducibles,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1209"
do_niif_12090200,12090200,Gastos Organizacionales Diferidos,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1209"
do_niif_12090300,12090300,ISR Deducible,account.data_account_type_non_current_assets,FALSE,do_chart_template,"account_tag_1,account_tag_12,account_tag_1209"
+do_niif_13010100,13010101,Costos de Construcción en Proceso,account.data_account_type_non_current_assets,FALSE,do_chart_template,
do_niif_21010100,21010100,Préstamos Bancarios por Pagar,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
-do_niif_21010200,21010200,Cuenta por Pagar Proveedores Locales,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
-do_niif_21010300,21010300,Cuenta por Pagar Proveedores del Exterior,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
-do_niif_21010400,21010400,Cuenta por Pagar a Afiliadas,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
-do_niif_21010500,21010500,Cuenta por Pagar a Accionistas,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
+do_niif_21010200,21010200,Cuentas por Pagar a Proveedores Locales,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
+do_niif_21010300,21010300,Cuentas por Pagar a Proveedores del Exterior,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
+do_niif_21010400,21010400,Cuentas por Pagar a Afiliadas,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
+do_niif_21010500,21010500,Cuentas por Pagar a Accionistas,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
do_niif_21010600,21010600,Nóminas por Pagar,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
do_niif_21010700,21010700,Intereses por Pagar,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
do_niif_21010800,21010800,Otras Cuentas por Pagar,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2101"
@@ -91,48 +97,48 @@ do_niif_21020600,21020600,Seguro Médico por Pagar,account.data_account_type_non
do_niif_21020700,21020700,Seguro Familiar de Salud (SFS) por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
do_niif_21020800,21020800,Aporte a Fondo de Pensiones (AFP) por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
do_niif_21020900,21020900,Seguro de Riesgo Laboral (SRL) por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
-do_niif_21021000,21021000,INFOTEP por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
-do_niif_21021100,21021100,Otras Remuneraciones por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
-do_niif_21021200,21021200,Bienes Recibidos no Pagados,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
+do_niif_21021000,21021000,INFOTEP por Pagar,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
+do_niif_21021100,21021100,Tesorería de la Seguridad Social (TSS) por Pagar,account.data_account_type_payable,TRUE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
+do_niif_21021200,21021200,Bienes Recibidos no Facturados,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2102"
do_niif_21030101,21030101,ITBIS por Venta Servicios,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210301"
do_niif_21030102,21030102,ITBIS por Venta Bienes,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210301"
-do_niif_21030103,21030103,ITBIS por Venta Bienes - al Exterior,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210301"
-do_niif_21030201,21030201,ITBIS Retenido Persona Jurídica (N 02-05),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
-do_niif_21030202,21030202,ITBIS Retenido Persona Física (R 293-11),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
-do_niif_21030203,21030203,ITBIS Retenido a Entidades No Lucrativas (N 01-2011),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
-do_niif_21030204,21030204,ITBIS Retenido por Servicios Profesionales Liberales (N 02-05),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
-do_niif_21030205,21030205,ITBIS Retenido a Proveedores Informales de Bienes (N 08-10),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
+do_niif_21030103,21030103,ITBIS por Venta Servicios en Nombre de Terceros,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210301"
+do_niif_21030201,21030201,ITBIS Retenido a Persona Jurídica (N02-05),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
+do_niif_21030202,21030202,ITBIS Retenido a Persona Física (R293-11),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
+do_niif_21030203,21030203,ITBIS Retenido a Entidades No Lucrativas (N01-11),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
+do_niif_21030204,21030204,ITBIS Retenido por Servicios Profesionales (N02-05),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
+do_niif_21030205,21030205,ITBIS Retenido a Informales de Bienes (N08-10),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210302"
do_niif_21030301,21030301,ISR Retenido por Honorarios Profesionales de Personas Físicas,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
do_niif_21030302,21030302,ISR Retenido por Alquileres Pagados a Personas Físicas,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
do_niif_21030303,21030303,ISR Retenido por Dividendos Pagados,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
do_niif_21030304,21030304,ISR Retenido por Intereses Pagados al Exterior,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
do_niif_21030305,21030305,ISR Retenido por Intereses Pagados,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
do_niif_21030306,21030306,ISR Retenido por Transferencias de Títulos y Propiedades,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
-do_niif_21030307,21030307,ISR Retenido por Remesas al Exterior (Ley 253-12),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
-do_niif_21030308,21030308,Otras Retenciones (N 07-07),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
+do_niif_21030307,21030307,ISR Retenido por Remesas al Exterior (L253-12),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
+do_niif_21030308,21030308,Otras Retenciones (N07-07),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
do_niif_21030309,21030309,Otras Retenciones,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210303"
-do_niif_21030401,21030401,Impuesto al Salario (ISR),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210304"
+do_niif_21030401,21030401,Retención de Impuesto al Salario (ISR del IR3),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210304"
do_niif_21030402,21030402,Retención de Seguro Familiar de Salud (SFS),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210304"
do_niif_21030403,21030403,Retención de Fondo de Pensiones (AFP),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210304"
do_niif_21030404,21030404,Retención de INFOTEP (0.5%),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210304"
do_niif_21030501,21030501,ISR por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210305"
do_niif_21030502,21030502,Anticipos ISR por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210305"
-do_niif_21030503,21030503,Propina por Pagar (Ley 16-92),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210305"
+do_niif_21030503,21030503,Propina Legal por Pagar (L16-92),account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210305"
do_niif_21030504,21030504,Otros Impuestos por Pagar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2103,account_tag_210305"
-do_niif_21040100,21040100,Provisión Pago Alquileres,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2104"
-do_niif_21040200,21040200,Provisión Arrendamiento Financiero,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2104"
-do_niif_21040300,21040300,Provisión Gastos Fijos,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2104"
+do_niif_21040100,21040100,Provisiones Pago Alquileres,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2104"
+do_niif_21040200,21040200,Provisiones Arrendamiento Financiero,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2104"
+do_niif_21040300,21040300,Provisiones Gastos Fijos,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2104"
do_niif_21050100,21050100,Tarjeta de Crédito Empresarial,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2105"
do_niif_21050200,21050200,Prima de Tarjetas de Crédito,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_21,account_tag_2105"
do_niif_22010100,22010100,Préstamos Bancarios Largo Plazo,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2201"
do_niif_22010200,22010200,Préstamos Hipotecarios LP,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2201"
do_niif_22012300,22012300,Préstamos Accionistas / Particulares,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2201"
-do_niif_22020100,22020100,Provisión Beneficios de Empleados LP,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2202"
-do_niif_22020200,22020200,Provisión Prestaciones Laborales,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2202"
-do_niif_22020300,22020300,Provisión Indemnizaciones,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2202"
-do_niif_22030100,22030100,Anticipos de Clientes,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2203"
-do_niif_22030200,22030200,Garantías de Clientes,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2203"
-do_niif_22040100,22040100,Provisión Arrendamiento Financiero LP,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2204"
+do_niif_22020100,22020100,Provisiones Beneficios de Empleados LP,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2202"
+do_niif_22020200,22020200,Provisiones Prestaciones Laborales,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2202"
+do_niif_22020300,22020300,Provisiones Indemnizaciones,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2202"
+do_niif_22030100,22030100,Anticipos o Garantías de Clientes,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2203"
+do_niif_22030200,22030200,Depósitos por Identificar,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2203"
+do_niif_22040100,22040100,Provisiones Arrendamiento Financiero LP,account.data_account_type_non_current_liabilities,FALSE,do_chart_template,"account_tag_2,account_tag_22,account_tag_2204"
do_niif_31010100,31010100,Capital Social Autorizado,account.data_account_type_equity,FALSE,do_chart_template,"account_tag_3,account_tag_31,account_tag_3101"
do_niif_31010200,31010200,Capital Social en Acciones no Emitidas,account.data_account_type_equity,FALSE,do_chart_template,"account_tag_3,account_tag_31,account_tag_3101"
do_niif_31010300,31010300,Capital Social Pagado,account.data_account_type_equity,FALSE,do_chart_template,"account_tag_3,account_tag_31,account_tag_3101"
@@ -149,123 +155,127 @@ do_niif_33020100,33020100,Utilidad del Ejercicio,account.data_account_type_equit
do_niif_33020200,33020200,Pérdidas del Ejercicio,account.data_account_type_equity,FALSE,do_chart_template,"account_tag_3,account_tag_33,account_tag_3302"
do_niif_33040100,33040100,Superávit en Reserva,account.data_account_type_equity,FALSE,do_chart_template,"account_tag_3,account_tag_33,account_tag_3304"
do_niif_33040200,33040200,Déficit en Reserva,account.data_account_type_equity,FALSE,do_chart_template,"account_tag_3,account_tag_33,account_tag_3304"
-do_niif_41010100,41010100,Ventas Bienes,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4101"
-do_niif_41010200,41010200,Ventas Bienes - Al Exterior,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4101"
-do_niif_41020100,41020100,Ventas Servicios,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4102"
-do_niif_41020200,41020200,Ventas Servicios - Al Exterior,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4102"
+do_niif_41010100,41010100,Ventas de Bienes,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4101"
+do_niif_41010200,41010200,Ventas por Exportaciones de Bienes,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4101"
+do_niif_41020100,41020100,Ventas de Servicios,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4102"
+do_niif_41020200,41020200,Ventas por Exportaciones de Servicios,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4102"
do_niif_41030100,41030100,Devoluciones de Bienes,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4103"
do_niif_41030200,41030200,Devoluciones por Servicios,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4103"
do_niif_41040100,41040100,Descuentos por Ventas (por NC),account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_41,account_tag_4104"
do_niif_42010100,42010100,Intereses sobre Certificados,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4201"
-do_niif_42010200,42010200,Intereses en Cuentas Bancarias,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4201"
+do_niif_42010200,42010200,Intereses por Cuentas Bancarias,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4201"
do_niif_42010300,42010300,Intereses por Financiamientos,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4201"
-do_niif_42020100,42020100,Ingresos por Ventas de Activos,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4202"
+do_niif_42020100,42020100,Ingresos por Ventas de Activos Depreciables (CAT II y III) ,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4202"
do_niif_42030100,42030100,Ingresos por Dividendos Ganados,account.data_account_type_revenue,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4203"
do_niif_42040100,42040100,Ingresos por Diferencia Cambiaria,account.data_account_type_other_income,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4204"
do_niif_42040200,42040200,Cobro de Cuentas Incobrables,account.data_account_type_other_income,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4204"
-do_niif_42040300,42040300,Otros Ingresos,account.data_account_type_other_income,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4204"
+do_niif_42040300,42040300,Ingresos por Sobrante en Caja,account.data_account_type_other_income,FALSE,do_chart_template,"account_tag_4,account_tag_42,account_tag_4204"
do_niif_51010100,51010100,Costos de Bienes,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5101"
do_niif_51010200,51010200,Costos de Servicios,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5101"
-do_niif_51010300,51010300,Diferencia de Precio,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5101"
+do_niif_51010300,51010300,Diferencia en Precio,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5101"
+do_niif_51020400,51020400,Costos de Importación,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5102"
+do_niif_51010500,51010500,ITBIS llevado al Costo,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5101"
do_niif_51020100,51020100,Costos de Materia Prima,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5102"
do_niif_51020200,51020200,Costos de Mano de Obra,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5102"
do_niif_51020300,51020300,Costos Indirectos,account.data_account_type_direct_costs,FALSE,do_chart_template,"account_tag_5,account_tag_51,account_tag_5102"
-do_niif_52010100,52010100,Sueldos y Salarios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010200,52010200,Regalía Pascual,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010300,52010300,Retribuciones Complementarias,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010400,52010400,Bono Vacacional,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010500,52010500,Bono por Desempeño,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010600,52010600,Comisiones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010700,52010700,Indemnizaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010800,52010800,Bonificaciones y Gratificaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010900,52010900,Dietas al Personal,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52011000,52011000,Cursos y Entrenamientos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52011100,52011100,Prestaciones Laborales (Preaviso y Cesantia),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52011200,52011200,Incentivos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52011300,52011300,Horas Extras,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52011400,52011400,Otros Gastos de Personal,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201"
-do_niif_52010102,52010102,Contribución a la Administradora de Fondos de Pensiones (AFP),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520101"
-do_niif_52010103,52010103,Contribución al Seguro Riesgo Laboral (SRL),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520101"
-do_niif_52010104,52010104,Contribución al Seguro Familiar de Salud (SFS),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520101"
-do_niif_52010201,52010201,Contribución a la Administradora de Riesgos de Salud (ARS),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520102"
-do_niif_52010202,52010202,Contribución a Seguros del Personal,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520102"
-do_niif_52010203,52010203,Contribución a Planes Complementarios de Salud,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520102"
-do_niif_52010204,52010204,Contribución Seguros de Vida,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520102"
-do_niif_52010205,52010205,Contribución al INFOTEP,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5201,account_tag_520102"
-do_niif_52020100,52020100,Energía Eléctrica,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020200,52020200,Comunicaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020300,52020300,Papelería y útiles,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020400,52020400,Útiles de Aseo y Limpieza,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020500,52020500,Agua y Basura,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020600,52020600,Seguro de Edificio,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020700,52020700,Combustibles y Lubricantes,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020800,52020800,Alquileres,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52020900,52020900,Franquicias,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52021000,52021000,Eventos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52021100,52021100,Seguros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52021200,52021200,Servicios de Mensajería,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52021300,52021300,Flete y Carga,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52021400,52021400,Cuotas y Suscripciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52021500,52021500,Otros Gastos de Administración,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5202"
-do_niif_52030101,52030101,Legales (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030102,52030102,Contabilidad y Auditoría (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030103,52030103,Tecnología (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030104,52030104,Mantenimiento de Planta (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030105,52030105,Mantenimiento del Local (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030106,52030106,Mantenimiento Mobiliario y Equipos (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030107,52030107,Asesorías (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030108,52030108,Fumigaciones (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030109,52030109,Copias y Escaneos (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030110,52030110,Servicios de Vigilancia (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030111,52030111,Otros Servicios Profesionales (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520301"
-do_niif_52030201,52030201,Legales (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030202,52030202,Contabilidad y Auditoría (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030203,52030203,Tecnología (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030204,52030204,Mantenimiento de Planta (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030205,52030205,Mantenimiento del Local (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030206,52030206,Mantenimiento Mobiliario y Equipos (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030207,52030207,Asesorías (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030208,52030208,Fumigaciones (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030209,52030209,Copias y Escaneos (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030210,52030210,Servicios de Vigilancia (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030211,52030211,Otros Servicios Profesionales (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520302"
-do_niif_52030301,52030301,Honorarios por Servicios del Exterior - Relacionadas,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520303"
-do_niif_52030302,52030302,Honorarios por Servicios del Exterior - Terceros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5203,account_tag_520303"
-do_niif_52040100,52040100,Gastos por Depreciación de Edificios,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5204"
-do_niif_52040200,52040200,Gastos por Depreciación de Equipo de Transporte,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5204"
-do_niif_52040300,52040300,Gastos por Depreciación de Mobiliario y Equipos,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5204"
-do_niif_52040400,52040400,Gastos por Depreciación de Maquinaria,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5204"
-do_niif_52040500,52040500,Gastos por Depreciación de Herramientas,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5204"
-do_niif_52040600,52040600,Gastos por Depreciación de Instalaciones,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5204"
-do_niif_52050100,52050100,Gastos por Reparación de Edificios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5205"
-do_niif_52050200,52050200,Gastos por Reparación de Equipo de Transporte,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5205"
-do_niif_52050300,52050300,Gastos por Reparación de Mobiliario y Equipos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5205"
-do_niif_52050400,52050400,Gastos por Reparación de Maquinaria,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5205"
-do_niif_52050500,52050500,Gastos por Reparación de Herramientas,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5205"
-do_niif_52050600,52050600,Gastos por Reparación de Instalaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5205"
-do_niif_52060100,52060100,Relaciones Públicas,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5206"
-do_niif_52060200,52060200,Publicidad,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5206"
-do_niif_52060300,52060300,Viajes,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5206"
-do_niif_52060400,52060400,Donaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5206"
-do_niif_52060500,52060500,Donaciones a ProIndustria (Ley 392-07),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5206"
-do_niif_52060600,52060600,Promociones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5206"
-do_niif_52060700,52060700,Otros Gastos de Representación,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5206"
-do_niif_52070100,52070100,Gastos por Préstamos Financieros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070200,52070200,Retención por Cheques y Transferencias Electrónicas (0.15%),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070300,52070300,Intereses Bancarios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070400,52070400,Comisiones Bancarias,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070500,52070500,Comisión de Tarjeta de Crédito,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070600,52070600,Nota de Cargos por Banco,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070700,52070700,Seguro sobre Préstamos Bancarios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070800,52070800,Pérdidas por Diferencia Cambiaria,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52070900,52070900,Otro Gastos Financieros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5207"
-do_niif_52080100,52080100,Gastos por Siniestros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080200,52080200,Pérdidas por Ventas de Activos Fijos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080300,52080300,Pérdidas por Cuentas Incobrables,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080400,52080400,Gastos por ISR,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080500,52080500,Impuestos a los Activos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080600,52080600,Penalidades/Recargos de DGII,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080700,52080700,Penalidades/Recargos de TSS,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080800,52080800,Gastos Sin Comprobante,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_52080900,52080900,Gastos por Impuestos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_5,account_tag_52,account_tag_5208"
-do_niif_61010100,61010100,Pérdidas y Ganancias,account.data_unaffected_earnings,FALSE,do_chart_template,"account_tag_6,account_tag_61,account_tag_6101"
+do_niif_52010100,61010100,Sueldos y Salarios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010200,61010200,Regalía Pascual,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010300,61010300,Retribuciones Complementarias,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010400,61010400,Bono Vacacional,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010500,61010500,Bono por Desempeño,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010600,61010600,Comisiones a Empleados,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010700,61010700,Indemnizaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010800,61010800,Bonificaciones y Gratificaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010900,61010900,Comidas o Dietas al Personal,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52011000,61011000,Cursos y Entrenamientos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52011100,61011100,Prestaciones Laborales (Preaviso y Cesantia),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52011200,61011200,Incentivos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52011300,61011300,Horas Extras,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52011400,61011400,Uniformes,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52011500,61011500,Otros Gastos de Personal,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201"
+do_niif_52010102,61010102,Contribución a la Administradora de Fondos de Pensiones (AFP),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520101"
+do_niif_52010103,61010103,Contribución al Seguro Riesgo Laboral (SRL),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520101"
+do_niif_52010104,61010104,Contribución al Seguro Familiar de Salud (SFS),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520101"
+do_niif_52010201,61010201,Contribución a la Administradora de Riesgos de Salud (ARS),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520102"
+do_niif_52010202,61010202,Contribución a Seguros del Personal,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520102"
+do_niif_52010203,61010203,Contribución a Planes Complementarios de Salud,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520102"
+do_niif_52010204,61010204,Contribución Seguros de Vida,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520102"
+do_niif_52010205,61010205,Contribución al INFOTEP,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5201,account_tag_520102"
+do_niif_52020100,61020100,Energía Eléctrica,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020200,61020200,Comunicaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020300,61020300,Suministros de Oficina (Papelería y útiles),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020400,61020400,Útiles de Aseo y Limpieza,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020500,61020500,Agua y Basura,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020600,61020600,Seguro de Edificio y Locales,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020700,61020700,Combustibles y Lubricantes,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020800,61020800,Alquileres / Arrendamientos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52020900,61020900,Franquicias,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52021000,61021000,Eventos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52021100,61021100,Seguros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52021200,61021200,Servicios de Mensajería,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52021300,61021300,Flete y Carga,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52021400,61021400,Cuotas y Suscripciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52021500,61021500,Alojamiento en Hoteles,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5202"
+do_niif_52030101,61030101,Legales (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030102,61030102,Contabilidad y Auditoría (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030103,61030103,Tecnología (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030104,61030104,Mantenimientos de Planta (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030105,61030105,Mantenimientos de Local (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030106,61030106,Mantenimientos Mobiliarios y Equipos (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030107,61030107,Asesorías (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030108,61030108,Fumigaciones (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030109,61030109,Copias y Escaneos (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030110,61030110,Servicios de Vigilancia (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030111,61030111,Otros Servicios Profesionales (P. Física),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520301"
+do_niif_52030201,61030201,Legales (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030202,61030202,Contabilidad y Auditoría (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030203,61030203,Tecnología (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030204,61030204,Mantenimiento de Planta (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030205,61030205,Mantenimiento del Local (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030206,61030206,Mantenimiento Mobiliario y Equipos (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030207,61030207,Asesorías (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030208,61030208,Fumigaciones (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030209,61030209,Copias y Escaneos (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030210,61030210,Servicios de Vigilancia (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030211,61030211,Otros Servicios Profesionales (P. Jurídica),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520302"
+do_niif_52030301,61030301,Honorarios por Servicios del Exterior - Relacionadas,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520303"
+do_niif_52030302,61030302,Honorarios por Servicios del Exterior - Terceros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5203,account_tag_520303"
+do_niif_52040100,61040100,Gastos por Depreciación de Edificios,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5204"
+do_niif_52040200,61040200,Gastos por Depreciación de Equipo de Transporte,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5204"
+do_niif_52040300,61040300,Gastos por Depreciación de Mobiliario y Equipos,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5204"
+do_niif_52040400,61040400,Gastos por Depreciación de Maquinaria,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5204"
+do_niif_52040500,61040500,Gastos por Depreciación de Herramientas,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5204"
+do_niif_52040600,61040600,Gastos por Depreciación de Instalaciones,account.data_account_type_depreciation,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5204"
+do_niif_52050100,61050100,Gastos por Reparación de Edificios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5205"
+do_niif_52050200,61050200,Gastos por Reparación de Equipo de Transporte,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5205"
+do_niif_52050300,61050300,Gastos por Reparación de Mobiliario y Equipos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5205"
+do_niif_52050400,61050400,Gastos por Reparación de Maquinaria,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5205"
+do_niif_52050500,61050500,Gastos por Reparación de Herramientas,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5205"
+do_niif_52050600,61050600,Gastos por Reparación de Instalaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5205"
+do_niif_52060100,61060100,Relaciones Públicas,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5206"
+do_niif_52060200,61060200,Publicidad,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5206"
+do_niif_52060300,61060300,Gastos de Viajes y Representación,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5206"
+do_niif_52060400,61060400,Donaciones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5206"
+do_niif_52060500,61060500,Donaciones a ProIndustria (Ley 392-07),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5206"
+do_niif_52060600,61060600,Promociones,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5206"
+do_niif_52060700,61060700,Gastos en Restaurantes,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5206"
+do_niif_52070100,61070100,Gastos por Préstamos Financieros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070200,61070200,Retención por Cheques o Transferencias Electrónicas (0.15%),account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070300,61070300,Intereses Bancarios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070400,61070400,Comisiones Bancarias,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070500,61070500,Comisiones de Tarjeta de Crédito,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070600,61070600,Cargos Bancarios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070700,61070700,Seguro sobre Préstamos Bancarios,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070800,61070800,Pérdidas por Diferencia Cambiaria,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52070900,61070900,Otro Gastos Financieros,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5207"
+do_niif_52080100,61080100,Pérdidas por Faltante en Caja,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080200,61080200,Pérdidas por Ventas de Activos Fijos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080300,61080300,Pérdidas por Cuentas Incobrables,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080400,61080400,Gastos por ISR,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080500,61080500,Impuestos a los Activos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080600,61080600,Gastos por Penalidades/Recargos de DGII,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080700,61080700,Gastos por Penalidades/Recargos de TSS,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080800,61080800,Gastos sin Comprobantes,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52080900,61080900,Gastos No Deducibles,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_52081000,61081000,Gastos por Impuestos,account.data_account_type_expenses,FALSE,do_chart_template,"account_tag_6,account_tag_52,account_tag_5208"
+do_niif_61010100,71010100,Ganancias o Pérdidas,account.data_unaffected_earnings,FALSE,do_chart_template,"account_tag_7,account_tag_61,account_tag_6101"
diff --git a/addons/l10n_do/data/account.tax.template.xml b/addons/l10n_do/data/account.tax.template.xml
index 135eb7f24c8..61bc5d5d2a7 100644
--- a/addons/l10n_do/data/account.tax.template.xml
+++ b/addons/l10n_do/data/account.tax.template.xml
@@ -2,20 +2,9 @@
<odoo>
<data noupdate="1">
<!-- Chart template for Taxes -->
- <!-- Taxes Groups -->
- <record id="group_itbis" model="account.tax.group">
- <field name="name">ITBIS</field>
- </record>
- <record id="group_ret" model="account.tax.group">
- <field name="name">Retenciones</field>
- </record>
- <record id="group_tax" model="account.tax.group">
- <field name="name">Otros Impuestos</field>
- </record>
- <!-- Taxes Template -->
<record id="tax_0_sale" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">50</field>
+ <field name="sequence">4</field>
<field name="name">Exento ITBIS Ventas</field>
<field name="description">Exento</field>
<field name="amount">0</field>
@@ -27,7 +16,7 @@
</record>
<record id="tax_0_purch" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">50</field>
+ <field name="sequence">10</field>
<field name="name">Exento ITBIS Compras</field>
<field name="description">Exento</field>
<field name="amount">0</field>
@@ -49,11 +38,11 @@
<field name="refund_account_id" ref="do_niif_21030102"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_V_ITBIS_18')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_18"/>
+ <field name="tax_group_id" ref="group_itbis"/>
</record>
<record id="tax_18_sale_incl" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">10</field>
+ <field name="sequence">2</field>
<field name="name">18% ITBIS Incl. Ventas</field>
<field name="description">18% Incl</field>
<field name="amount">18</field>
@@ -63,35 +52,139 @@
<field name="refund_account_id" ref="do_niif_21030102"/>
<field eval="1" name="price_include"/>
<field eval="[(6,0,[ref('tag_V_ITBIS_18')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_18"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_tip_sale" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="sequence">3</field>
+ <field name="name">10% Propina Legal</field>
+ <field name="description">10%</field>
+ <field name="amount">10</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">sale</field>
+ <field name="account_id" ref="do_niif_21030503"/>
+ <field name="refund_account_id" ref="do_niif_21030503"/>
+ <field eval="0" name="price_include"/>
+ <field name="tax_group_id" ref="tax_group_tip"/>
</record>
<record id="tax_18_purch" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
<field name="name">18% ITBIS Compras</field>
- <field name="sequence">2</field>
+ <field name="sequence">11</field>
<field name="description">18%</field>
<field name="amount">18</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_11080101"/>
- <field name="refund_account_id" ref="do_niif_11080302"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_C_ITBIS_18')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="group_itbis"/>
</record>
<record id="tax_18_purch_incl" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">20</field>
+ <field name="sequence">12</field>
<field name="name">18% ITBIS Incl. Compras</field>
<field name="description">18%</field>
<field name="amount">18</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_11080101"/>
- <field name="refund_account_id" ref="do_niif_11080302"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
<field eval="1" name="price_include"/>
<field eval="[(6,0,[ref('tag_C_ITBIS_18_Incluido')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_18"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_16_purch" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">16% ITBIS Compras</field>
+ <field name="sequence">13</field>
+ <field name="description">16%</field>
+ <field name="amount">16</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_11080101"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
+ <field eval="0" name="price_include"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_16_purch_incl" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">16% ITBIS Incl. Compras</field>
+ <field name="sequence">14</field>
+ <field name="description">16%</field>
+ <field name="amount">16</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_11080101"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
+ <field eval="1" name="price_include"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_9_purch" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">9% ITBIS Compras</field>
+ <field name="sequence">15</field>
+ <field name="description">9% (L690-16)</field>
+ <field name="amount">9</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_11080101"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
+ <field eval="0" name="price_include"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_9_purch_incl" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">9% ITBIS Incl. Compras</field>
+ <field name="sequence">16</field>
+ <field name="description">9% (L690-16)</field>
+ <field name="amount">9</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_11080101"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
+ <field eval="1" name="price_include"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_8_purch" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">8% ITBIS Compras</field>
+ <field name="sequence">17</field>
+ <field name="description">8% (L690-16)</field>
+ <field name="amount">8</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_11080101"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
+ <field eval="0" name="price_include"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_8_purch_incl" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">8% ITBIS Incl. Compras</field>
+ <field name="sequence">18</field>
+ <field name="description">8% (L690-16)</field>
+ <field name="amount">8</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_11080101"/>
+ <field name="refund_account_id" ref="do_niif_11080101"/>
+ <field eval="1" name="price_include"/>
+ <field name="tax_group_id" ref="group_itbis"/>
+ </record>
+ <record id="tax_tip_purch" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="sequence">19</field>
+ <field name="name">10% Propina Legal</field>
+ <field name="description">10%</field>
+ <field name="amount">10</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_52080900"/>
+ <field name="refund_account_id" ref="do_niif_52080900"/>
+ <field eval="0" name="price_include"/>
+ <field name="tax_group_id" ref="tax_group_tip"/>
</record>
<record id="tax_18_purch_serv" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -100,12 +193,12 @@
<field name="description">18%</field>
<field name="amount">18</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
+ <field name="type_tax_use">none</field>
<field name="account_id" ref="do_niif_11080102"/>
- <field name="refund_account_id" ref="do_niif_11080302"/>
+ <field name="refund_account_id" ref="do_niif_11080102"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_C_ITBIS_18')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_18"/>
+ <field name="tax_group_id" ref="group_itbis"/>
</record>
<record id="tax_18_purch_serv_incl" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -114,12 +207,12 @@
<field name="description">18%</field>
<field name="amount">18</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
+ <field name="type_tax_use">none</field>
<field name="account_id" ref="do_niif_11080102"/>
- <field name="refund_account_id" ref="do_niif_11080302"/>
+ <field name="refund_account_id" ref="do_niif_11080102"/>
<field eval="1" name="price_include"/>
<field eval="[(6,0,[ref('tag_C_ITBIS_18_Incluido')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_18"/>
+ <field name="tax_group_id" ref="group_itbis"/>
</record>
<record id="tax_18_importation" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -128,12 +221,12 @@
<field name="description">18%</field>
<field name="amount">18</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
+ <field name="type_tax_use">none</field>
<field name="account_id" ref="do_niif_11080103"/>
- <field name="refund_account_id" ref="do_niif_11080302"/>
+ <field name="refund_account_id" ref="do_niif_11080103"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_IMP_ITBIS_18')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_18"/>
+ <field name="tax_group_id" ref="group_itbis"/>
</record>
<record id="tax_18_of_10" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -142,11 +235,11 @@
<field name="description">18% del 10%</field>
<field name="amount">1.8</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
- <field name="account_id" ref="do_niif_11080101"/>
- <field name="refund_account_id" ref="do_niif_11080302"/>
+ <field name="type_tax_use">sale</field>
+ <field name="account_id" ref="do_niif_21030102"/>
+ <field name="refund_account_id" ref="do_niif_21030102"/>
<field eval="0" name="price_include"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="group_itbis"/>
</record>
<record id="tax_0015_bank" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -159,7 +252,7 @@
<field name="account_id" ref="do_niif_52070200"/>
<field name="refund_account_id" ref="do_niif_11080303"/>
<field eval="1" name="price_include"/>
- <field name="tax_group_id" ref="tax_group_itbis_00015"/>
+ <field name="tax_group_id" ref="group_tax"/>
</record>
<record id="tax_10_telco" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -168,12 +261,12 @@
<field name="description">ISC</field>
<field name="amount">10</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
+ <field name="type_tax_use">none</field>
<field name="account_id" ref="do_niif_52020200"/>
<field name="refund_account_id" ref="do_niif_52020200"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_TELE_ISC')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="tax_group_isc"/>
</record>
<record id="tax_2_telco" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -182,12 +275,12 @@
<field name="description">CDT</field>
<field name="amount">2</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
+ <field name="type_tax_use">none</field>
<field name="account_id" ref="do_niif_52020200"/>
<field name="refund_account_id" ref="do_niif_52020200"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_TELE_CDT')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="group_tax"/>
</record>
<record id="tax_group_telco" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -197,13 +290,26 @@
<field name="amount_type">group</field>
<field name="type_tax_use">purchase</field>
<field eval="[(6, 0, [ref('tax_10_telco'), ref('tax_2_telco')])]" name="children_tax_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="tax_group_isc"/>
</record>
- <record id="ret_100_tax_nonprofit" model="account.tax.template">
+ <record id="ret_100_tax_security" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
<field name="sequence">40</field>
- <field name="name">Retención ITBIS 100% a No Lucrativas (Servicios)</field>
- <field name="description">100% del ITBIS</field>
+ <field name="name">Retención ITBIS 100% Servicios de Seguridad (N07-09)</field>
+ <field name="description">100% ITBIS</field>
+ <field name="amount">-18</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">purchase</field>
+ <field name="account_id" ref="do_niif_21030201"/>
+ <field name="refund_account_id" ref="do_niif_21030201"/>
+ <field eval="0" name="price_include"/>
+ <field name="tax_group_id" ref="group_ret"/>
+ </record>
+ <record id="ret_100_tax_nonprofit" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="sequence">41</field>
+ <field name="name">Retención ITBIS 100% Servicios No Lucrativas (N01-11)</field>
+ <field name="description">100% ITBIS</field>
<field name="amount">-18</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
@@ -211,13 +317,13 @@
<field name="refund_account_id" ref="do_niif_21030203"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_R_ITBIS_18')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_retencion_18"/>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="ret_100_tax_person" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
- <field name="name">Retención ITBIS 100% a Persona Física</field>
- <field name="description">100% del ITBIS</field>
+ <field name="sequence">42</field>
+ <field name="name">Retención ITBIS 100% Servicios a Físicas (R293-11)</field>
+ <field name="description">100% ITBIS</field>
<field name="amount">-18</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
@@ -225,169 +331,211 @@
<field name="refund_account_id" ref="do_niif_21030202"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_R_ITBIS_18')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="ret_30_tax_moral" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
- <field name="name">Retención ITBIS 30% a Persona Jurídica (Construcción)</field>
- <field name="description">30% del ITBIS</field>
+ <field name="sequence">43</field>
+ <field name="name">Retención ITBIS 30% Servicios a Jurídicas (N02-05)</field>
+ <field name="description">30% ITBIS</field>
<field name="amount">-5.4</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_21030201"/>
<field name="refund_account_id" ref="do_niif_21030201"/>
<field eval="0" name="price_include"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="ret_30_tax_freelance" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
- <field name="name">Retención ITBIS 30% a Profesionales Liberales (Servicios)</field>
- <field name="description">30% del ITBIS</field>
+ <field name="sequence">43</field>
+ <field name="name">Retención ITBIS 30% Servicios Profesionales (N02-05)</field>
+ <field name="description">30% ITBIS</field>
<field name="amount">-5.4</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
- <field name="account_id" ref="do_niif_21030204"/>
- <field name="refund_account_id" ref="do_niif_21030204"/>
+ <field name="type_tax_use">none</field>
+ <field name="account_id" ref="do_niif_21030201"/>
+ <field name="refund_account_id" ref="do_niif_21030201"/>
<field eval="0" name="price_include"/>
- <field name="tax_group_id" ref="tax_group_retencion_54"/>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="ret_75_tax_nonformal" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
- <field name="name">Retención ITBIS 75% a Proveedores Informales (Bienes)</field>
- <field name="description">75% del ITBIS</field>
+ <field name="sequence">44</field>
+ <field name="name">Retención ITBIS 75% Bienes a Informales (N08-10)</field>
+ <field name="description">75% ITBIS</field>
<field name="amount">-13.5</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_21030205"/>
<field name="refund_account_id" ref="do_niif_21030205"/>
<field eval="0" name="price_include"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="ret_10_income_person" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
<field name="sequence">40</field>
- <field name="name">Retención ISR 10% Honorarios a Persona Física (Servicios)</field>
+ <field name="name">Retención ISR 10% Servicios a Físicas</field>
<field name="description">10% ISR</field>
<field name="amount">-10</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
+ <field name="type_tax_use">none</field>
<field name="account_id" ref="do_niif_21030301"/>
- <field name="refund_account_id" ref="do_niif_11080303"/>
+ <field name="refund_account_id" ref="do_niif_21030301"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_R_ISR_10')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_retencion_10"/>
+ <field name="tax_group_id" ref="group_isr"/>
</record>
<record id="ret_10_income_rent" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
- <field name="name">Retención ISR 10% a Persona Física (Alquiler)</field>
+ <field name="sequence">50</field>
+ <field name="name">Retención ISR 10% Alquileres a Físicas</field>
<field name="description">10% ISR</field>
<field name="amount">-10</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_21030302"/>
- <field name="refund_account_id" ref="do_niif_11080303"/>
+ <field name="refund_account_id" ref="do_niif_21030302"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_R_ISR_10')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_retencion_10"/>
+ <field name="tax_group_id" ref="group_isr"/>
</record>
<record id="ret_10_income_dividend" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
- <field name="name">Retención ISR 10% por Dividendos</field>
+ <field name="sequence">51</field>
+ <field name="name">Retención ISR 10% por Dividendos (L253-12)</field>
<field name="description">10% ISR</field>
<field name="amount">-10</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_21030303"/>
- <field name="refund_account_id" ref="do_niif_11080303"/>
+ <field name="refund_account_id" ref="do_niif_21030303"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_R_ISR_10')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_retencion_10"/>
+ <field name="tax_group_id" ref="group_isr"/>
</record>
<record id="ret_2_income_person" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
+ <field name="sequence">52</field>
<field name="name">Retención ISR 2% a Persona Física (Servicios)</field>
- <field name="description">2% ISR (N 07-07)</field>
+ <field name="description">2% ISR (N07-07)</field>
<field name="amount">-2</field>
<field name="amount_type">percent</field>
- <field name="type_tax_use">purchase</field>
+ <field name="type_tax_use">none</field>
<field name="account_id" ref="do_niif_21030308"/>
- <field name="refund_account_id" ref="do_niif_11080303"/>
+ <field name="refund_account_id" ref="do_niif_21030308"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_R_ISR_2')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="tax_group_id" ref="group_isr"/>
</record>
<record id="ret_2_income_transfer" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
+ <field name="sequence">53</field>
<field name="name">Retención ISR 2% por Transferencia de Títulos</field>
<field name="description">2% ISR</field>
<field name="amount">-2</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_21030306"/>
- <field name="refund_account_id" ref="do_niif_11080303"/>
+ <field name="refund_account_id" ref="do_niif_21030306"/>
<field eval="0" name="price_include"/>
<field eval="[(6,0,[ref('tag_R_ISR_2')])]" name="tag_ids"/>
- <field name="tax_group_id" ref="tax_group_retencion_2"/>
+ <field name="tax_group_id" ref="group_isr"/>
</record>
<record id="ret_27_income_remittance" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">40</field>
- <field name="name">Retención ISR 27% por Remesas al Exterior</field>
+ <field name="sequence">49</field>
+ <field name="name">Retención ISR 27% por Remesas al Exterior (L253-12)</field>
<field name="description">27% ISR</field>
<field name="amount">-27</field>
<field name="amount_type">percent</field>
<field name="type_tax_use">purchase</field>
<field name="account_id" ref="do_niif_21030307"/>
- <field name="refund_account_id" ref="do_niif_11080303"/>
+ <field name="refund_account_id" ref="do_niif_21030307"/>
<field eval="0" name="price_include"/>
- <field name="tax_group_id" ref="tax_group_retencion_27"/>
+ <field name="tax_group_id" ref="group_isr"/>
+ </record>
+ <record id="ret_5_income_gov" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="sequence">50</field>
+ <field name="name">Retención ISR 5% Gubernamentales</field>
+ <field name="description">-5% ISR</field>
+ <field name="amount">-5</field>
+ <field name="amount_type">percent</field>
+ <field name="type_tax_use">none</field>
+ <field name="account_id" ref="do_niif_21030308"/>
+ <field name="refund_account_id" ref="do_niif_21030308"/>
+ <field eval="0" name="price_include"/>
+ <field name="tax_group_id" ref="group_isr"/>
</record>
<record id="tax_group_nonformal" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
<field name="sequence">60</field>
- <field name="name">Retención a Proveedores Informales (Bienes)</field>
+ <field name="name">Retención a Proveedores Informales de Bienes</field>
<field name="amount_type">group</field>
<field eval="0" name="amount"/>
<field name="type_tax_use">purchase</field>
- <field eval="[(6, 0, [ref('ret_75_tax_nonformal'), ref('tax_18_purch')])]" name="children_tax_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field eval="[(6, 0, [ref('tax_18_purch'), ref('ret_75_tax_nonformal')])]" name="children_tax_ids"/>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="tax_group_person_construction" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">60</field>
+ <field name="sequence">61</field>
<field name="name">Retención a Persona Física (Servicios Construcción con Materiales)</field>
<field name="amount_type">group</field>
<field eval="0" name="amount"/>
- <field name="type_tax_use">purchase</field>
- <field eval="[(6, 0, [ref('tax_18_of_10'), ref('ret_2_income_person'), ref('ret_100_tax_person')])]" name="children_tax_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="type_tax_use">none</field>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="tax_group_moral_construction" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">60</field>
+ <field name="sequence">62</field>
<field name="name">Retención a Jurídica (Servicios Construcción con Materiales)</field>
<field name="amount_type">group</field>
<field eval="0" name="amount"/>
- <field name="type_tax_use">purchase</field>
- <field eval="[(6, 0, [ref('ret_30_tax_moral'), ref('tax_18_of_10')])]" name="children_tax_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field name="type_tax_use">none</field>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
<record id="tax_group_person_services" model="account.tax.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="sequence">60</field>
- <field name="name">Retención a Persona Física por Servicios Profesionales</field>
+ <field name="sequence">58</field>
+ <field name="name">Retención a Físicas por Servicios Profesionales</field>
<field name="amount_type">group</field>
<field eval="0" name="amount"/>
<field name="type_tax_use">purchase</field>
- <field eval="[(6, 0, [ref('ret_2_income_person'), ref('ret_100_tax_person')])]" name="children_tax_ids"/>
- <field name="tax_group_id" ref="tax_group_itbis_0"/>
+ <field eval="[(6, 0, [ref('tax_18_purch'), ref('ret_100_tax_person'), ref('ret_2_income_person')])]" name="children_tax_ids"/>
+ <field name="tax_group_id" ref="group_ret"/>
+ </record>
+ <record id="tax_group_moral_services" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="sequence">58</field>
+ <field name="name">Retención a Jurídicas por Servicios Profesionales</field>
+ <field name="amount_type">group</field>
+ <field eval="0" name="amount"/>
+ <field name="type_tax_use">purchase</field>
+ <field eval="[(6, 0, [ref('tax_18_purch'), ref('ret_30_tax_moral')])]" name="children_tax_ids"/>
+ <field name="tax_group_id" ref="group_ret"/>
+ </record>
+ <record id="tax_group_restaurant_sale" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="sequence">64</field>
+ <field name="name">Ventas del Restaurante</field>
+ <field name="amount_type">group</field>
+ <field eval="0" name="amount"/>
+ <field name="type_tax_use">sale</field>
+ <field eval="[(6, 0, [ref('tax_18_sale'), ref('tax_tip_sale')])]" name="children_tax_ids"/>
+ <field name="tax_group_id" ref="group_ret"/>
+ </record>
+ <record id="tax_group_restaurant_purch" model="account.tax.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="sequence">65</field>
+ <field name="name">Compras a Restaurantes</field>
+ <field name="amount_type">group</field>
+ <field eval="0" name="amount"/>
+ <field name="type_tax_use">purchase</field>
+ <field eval="[(6, 0, [ref('tax_18_purch'), ref('tax_tip_purch')])]" name="children_tax_ids"/>
+ <field name="tax_group_id" ref="group_ret"/>
</record>
+
</data>
-</odoo>
+</odoo> \ No newline at end of file
diff --git a/addons/l10n_do/data/account_account_tag_data.xml b/addons/l10n_do/data/account_account_tag_data.xml
index db5bf0864ac..70826b6bbf5 100644
--- a/addons/l10n_do/data/account_account_tag_data.xml
+++ b/addons/l10n_do/data/account_account_tag_data.xml
@@ -425,7 +425,7 @@
</record>
<record id='account_tag_5' model='account.account.tag'>
- <field name='name'>5 Costos, Gastos y Pérdidas</field>
+ <field name='name'>5 Costos Directos e Indirectos</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
@@ -448,110 +448,116 @@
<field name='applicability'>accounts</field>
</record>
+ <record id='account_tag_6' model='account.account.tag'>
+ <field name='name'>6 Gastos y Pérdidas</field>
+ <field name='color'>4</field>
+ <field name='applicability'>accounts</field>
+ </record>
+
<record id='account_tag_52' model='account.account.tag'>
- <field name='name'>52 Gastos de Operación</field>
+ <field name='name'>61 Gastos de Operación</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5201' model='account.account.tag'>
- <field name='name'>5201 Gastos de Personal</field>
+ <field name='name'>6101 Gastos de Personal</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_520101' model='account.account.tag'>
- <field name='name'>520101 Aportes a la Seguridad Social</field>
+ <field name='name'>610101 Aportes a la Seguridad Social</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_520102' model='account.account.tag'>
- <field name='name'>520102 Otras Cargas Patronales</field>
+ <field name='name'>610102 Otras Cargas Patronales</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5202' model='account.account.tag'>
- <field name='name'>5202 Gastos de Administración</field>
+ <field name='name'>6102 Gastos de Administración</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5203' model='account.account.tag'>
- <field name='name'>5203 Gastos por Trabajo, Suministros y Servicios</field>
+ <field name='name'>6103 Gastos por Trabajo, Suministros y Servicios</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_520301' model='account.account.tag'>
- <field name='name'>520301 Gastos Honorarios por Servicios Profesionales (P. Física)</field>
+ <field name='name'>610301 Gastos Honorarios por Servicios Profesionales (P. Física)</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_520302' model='account.account.tag'>
- <field name='name'>520302 Gastos Honorarios por Servicios Profesionales (P. Jurídica)</field>
+ <field name='name'>610302 Gastos Honorarios por Servicios Profesionales (P. Jurídica)</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_520303' model='account.account.tag'>
- <field name='name'>520303 Gastos Honorarios por Servicios Profesionales (P. Jurídica)</field>
+ <field name='name'>610303 Gastos Honorarios por Servicios Profesionales (P. Jurídica)</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5204' model='account.account.tag'>
- <field name='name'>5204 Gastos por Depreciación</field>
+ <field name='name'>6104 Gastos por Depreciación</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5205' model='account.account.tag'>
- <field name='name'>5205 Gastos por Reparaciones</field>
+ <field name='name'>6105 Gastos por Reparaciones</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5206' model='account.account.tag'>
- <field name='name'>5206 Gastos de Representación</field>
+ <field name='name'>6106 Gastos de Representación</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5207' model='account.account.tag'>
- <field name='name'>5207 Gastos Financieros</field>
+ <field name='name'>6107 Gastos Financieros</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_5208' model='account.account.tag'>
- <field name='name'>5208 Gastos Extraordinarios</field>
+ <field name='name'>6108 Gastos Extraordinarios</field>
<field name='color'>4</field>
<field name='applicability'>accounts</field>
</record>
- <record id='account_tag_6' model='account.account.tag'>
- <field name='name'>6 Cuentas Liquidadoras de Resultados</field>
+ <record id='account_tag_7' model='account.account.tag'>
+ <field name='name'>7 Cuentas Liquidadoras de Resultados</field>
<field name='color'>5</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_61' model='account.account.tag'>
- <field name='name'>61 Cuenta Liquidadora</field>
+ <field name='name'>71 Cuenta Liquidadora</field>
<field name='color'>5</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_6101' model='account.account.tag'>
- <field name='name'>6101 Pérdidas y Ganancias</field>
+ <field name='name'>7101 Pérdidas y Ganancias</field>
<field name='color'>5</field>
<field name='applicability'>accounts</field>
</record>
<record id='account_tag_6102' model='account.account.tag'>
- <field name='name'>6102 Gastos por Impuestos</field>
+ <field name='name'>7102 Gastos por Impuestos</field>
<field name='color'>5</field>
<field name='applicability'>accounts</field>
</record>
diff --git a/addons/l10n_do/data/account_chart_template_data.xml b/addons/l10n_do/data/account_chart_template_data.xml
index 696cae7b228..d616459cf6b 100644
--- a/addons/l10n_do/data/account_chart_template_data.xml
+++ b/addons/l10n_do/data/account_chart_template_data.xml
@@ -2,11 +2,11 @@
<odoo>
<!-- Chart Template for Defaults -->
<record id="do_chart_template" model="account.chart.template">
+ <field eval="True" name="use_anglo_saxon"/>
<field name="property_account_receivable_id" ref="do_niif_11030201"/>
<field name="property_account_payable_id" ref="do_niif_21010200"/>
- <field name="property_account_expense_categ_id" ref="do_niif_51010100"/>
<field name="property_account_income_categ_id" ref="do_niif_41010100"/>
- <field eval="False" name="use_anglo_saxon"/>
+ <field name="property_account_expense_categ_id" ref="do_niif_51010100"/>
<field name="property_stock_account_input_categ_id" ref="do_niif_21021200"/>
<field name="property_stock_account_output_categ_id" ref="do_niif_11050600"/>
<field name="property_stock_valuation_account_id" ref="do_niif_11050100"/>
diff --git a/addons/l10n_do/data/account_data.xml b/addons/l10n_do/data/account_data.xml
index 698a011b518..462fb38760d 100644
--- a/addons/l10n_do/data/account_data.xml
+++ b/addons/l10n_do/data/account_data.xml
@@ -3,8 +3,26 @@
<data noupdate="1">
<!-- Account Tax Group -->
+ <record id="group_itbis" model="account.tax.group">
+ <field name="name">ITBIS</field>
+ </record>
+ <record id="group_isr" model="account.tax.group">
+ <field name="name">ISR</field>
+ </record>
+ <record id="group_ret" model="account.tax.group">
+ <field name="name">Retenciones</field>
+ </record>
+ <record id="group_tax" model="account.tax.group">
+ <field name="name">Otros Impuestos</field>
+ </record>
+ <record id="tax_group_isc" model="account.tax.group">
+ <field name="name">ISC</field>
+ </record>
<record id="tax_group_itbis_0" model="account.tax.group">
- <field name="name">ITBIS 0%</field>
+ <field name="name">Exento</field>
+ </record>
+ <record id="tax_group_tip" model="account.tax.group">
+ <field name="name">Propina</field>
</record>
<record id="tax_group_itbis_18" model="account.tax.group">
<field name="name">ITBIS 18%</field>
@@ -13,19 +31,19 @@
<field name="name">ITBIS 0.0015%</field>
</record>
<record id="tax_group_retencion_2" model="account.tax.group">
- <field name="name">Retencion 2%</field>
- </record>
- <record id="tax_group_retencion_54" model="account.tax.group">
- <field name="name">Retencion 5.4%</field>
+ <field name="name">ISR -2%</field>
</record>
<record id="tax_group_retencion_10" model="account.tax.group">
- <field name="name">Retencion 10%</field>
- </record>
- <record id="tax_group_retencion_18" model="account.tax.group">
- <field name="name">Retencion 18%</field>
+ <field name="name">ISR -10%</field>
</record>
<record id="tax_group_retencion_27" model="account.tax.group">
- <field name="name">Retencion 27%</field>
+ <field name="name">ISR -27%</field>
+ </record>
+ <record id="tax_group_retencion_54" model="account.tax.group">
+ <field name="name">ITBIS -30%</field>
+ </record>
+ <record id="tax_group_retencion_18" model="account.tax.group">
+ <field name="name">ITBIS -100%</field>
</record>
</data>
</odoo> \ No newline at end of file
diff --git a/addons/l10n_do/data/fiscal_position_template.xml b/addons/l10n_do/data/fiscal_position_template.xml
index 7179966d999..03900817ec6 100644
--- a/addons/l10n_do/data/fiscal_position_template.xml
+++ b/addons/l10n_do/data/fiscal_position_template.xml
@@ -5,41 +5,25 @@
<!-- Fiscal Position Templates -->
<!-- = = = = = = = = = = = = = = = -->
<!-- Principal Fiscal Position for Dominican Republic internally -->
- <record id="position_buyer_final" model="account.fiscal.position.template">
- <field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Consumidor Final</field>
- </record>
- <record id="position_buyer_moral" model="account.fiscal.position.template">
- <field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Crédito Fiscal</field>
- </record>
- <record id="position_provider_moral" model="account.fiscal.position.template">
- <field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Proveedor Fiscal</field>
- </record>
- <record id="position_construction_moral" model="account.fiscal.position.template">
+ <record id="position_person" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Proveedor Fiscal (Construcción)</field>
+ <field name="name">P. Física de Servicios</field>
</record>
- <record id="position_construction_person" model="account.fiscal.position.template">
+ <record id="position_service_moral" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Persona Física (Construcción)</field>
+ <field name="name">P. Jurídica de Servicios</field>
</record>
- <record id="position_person" model="account.fiscal.position.template">
+ <record id="position_security_moral" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Persona Física</field>
+ <field name="name">P. Jurídica de Vigilancia</field>
</record>
<record id="position_nonformal" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Proveedor Informal (Bienes)</field>
+ <field name="name">Proveedor Informal de Bienes</field>
</record>
<record id="position_exterior" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Proveedor del Exterior</field>
- </record>
- <record id="position_expenses" model="account.fiscal.position.template">
- <field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">Gastos Menores</field>
+ <field name="name">Servicios del Exterior</field>
</record>
<record id="position_gov" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
@@ -47,12 +31,20 @@
</record>
<record id="position_nonprofit" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
- <field name="name">No lucrativas</field>
+ <field name="name">No Lucrativa de Servicios</field>
</record>
<record id="position_especial" model="account.fiscal.position.template">
<field name="chart_template_id" ref="do_chart_template"/>
<field name="name">Regímenes Especiales</field>
</record>
+ <record id="position_restaurant" model="account.fiscal.position.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">Restaurantes</field>
+ </record>
+ <record id="position_restaurant_takeout" model="account.fiscal.position.template">
+ <field name="chart_template_id" ref="do_chart_template"/>
+ <field name="name">Para Llevar</field>
+ </record>
<!-- = = = = = = = = = = = = = = = -->
<!-- Fiscal Position Tax Templates -->
<!-- = = = = = = = = = = = = = = = -->
@@ -68,7 +60,7 @@
<field name="position_id" ref="position_nonformal"/>
<field name="tax_dest_id" ref="tax_group_nonformal"/>
</record>
- <!-- Persona Física>-->
+ <!-- Persona Física de Servicios>-->
<record id="fiscal_position_tax_9" model="account.fiscal.position.tax.template">
<field name="tax_src_id" ref="tax_18_purch"/>
<field name="position_id" ref="position_person"/>
@@ -83,38 +75,38 @@
<record id="fiscal_position_tax_1" model="account.fiscal.position.tax.template">
<field name="tax_src_id" ref="tax_18_sale"/>
<field name="position_id" ref="position_gov"/>
- <field name="tax_dest_id" ref="tax_0_sale"/>
+ <field name="tax_dest_id" ref="ret_5_income_gov"/>
</record>
<record id="fiscal_position_tax_2" model="account.fiscal.position.tax.template">
- <field name="tax_src_id" ref="tax_18_purch"/>
+ <field name="tax_src_id" ref="tax_18_sale_incl"/>
<field name="position_id" ref="position_gov"/>
- <field name="tax_dest_id" ref="tax_0_purch"/>
+ <field name="tax_dest_id" ref="ret_5_income_gov"/>
</record>
<!-- No Lucrativas -->
<record id="fiscal_position_tax_12" model="account.fiscal.position.tax.template">
<field name="tax_src_id" ref="tax_18_purch"/>
<field name="position_id" ref="position_nonprofit"/>
- <field name="tax_dest_id" ref="tax_0_purch"/>
+ <field name="tax_dest_id" ref="ret_100_tax_nonprofit"/>
</record>
<record id="fiscal_position_tax_13" model="account.fiscal.position.tax.template">
- <field name="tax_src_id" ref="tax_18_purch_serv"/>
+ <field name="tax_src_id" ref="tax_18_purch_incl"/>
<field name="position_id" ref="position_nonprofit"/>
<field name="tax_dest_id" ref="ret_100_tax_nonprofit"/>
</record>
- <!-- Proveedor Moral Construcción -->
+ <!-- Proveedor Moral de Seguridad -->
<record id="fiscal_position_tax_8" model="account.fiscal.position.tax.template">
<field name="tax_src_id" ref="tax_18_purch"/>
- <field name="position_id" ref="position_construction_moral"/>
- <field name="tax_dest_id" ref="tax_group_moral_construction"/>
+ <field name="position_id" ref="position_security_moral"/>
+ <field name="tax_dest_id" ref="ret_100_tax_security"/>
</record>
- <!-- Persona Física Construcción -->
+ <!-- Proveedor Moral de Servicio -->
<record id="fiscal_position_tax_7" model="account.fiscal.position.tax.template">
<field name="tax_src_id" ref="tax_18_purch"/>
- <field name="position_id" ref="position_construction_person"/>
- <field name="tax_dest_id" ref="tax_group_person_construction"/>
+ <field name="position_id" ref="position_service_moral"/>
+ <field name="tax_dest_id" ref="tax_group_moral_services"/>
</record>
<!-- Importación / Exportación -->
- <!-- Proveedo del Exterior -->
+ <!-- Proveedor del Exterior -->
<record id="fiscal_position_tax_5" model="account.fiscal.position.tax.template">
<field name="tax_src_id" ref="tax_18_purch_serv"/>
<field name="position_id" ref="position_exterior"/>
@@ -123,8 +115,54 @@
<record id="fiscal_position_tax_6" model="account.fiscal.position.tax.template">
<field name="tax_src_id" ref="tax_18_purch"/>
<field name="position_id" ref="position_exterior"/>
- <field name="tax_dest_id" ref="tax_0_purch"/>
+ <field name="tax_dest_id" ref="ret_27_income_remittance"/>
+ </record>
+ <!-- Restaurantes -->
+ <record id="fiscal_position_tax_14" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_18_purch"/>
+ <field name="position_id" ref="position_restaurant"/>
+ <field name="tax_dest_id" ref="tax_group_restaurant_purch"/>
+ </record>
+ <record id="fiscal_position_tax_15" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_18_purch_incl"/>
+ <field name="position_id" ref="position_restaurant"/>
+ <field name="tax_dest_id" ref="tax_group_restaurant_purch"/>
+ </record>
+ <record id="fiscal_position_tax_16" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_18_sale"/>
+ <field name="position_id" ref="position_restaurant"/>
+ <field name="tax_dest_id" ref="tax_group_restaurant_sale"/>
+ </record>
+ <record id="fiscal_position_tax_17" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_18_sale_incl"/>
+ <field name="position_id" ref="position_restaurant"/>
+ <field name="tax_dest_id" ref="tax_group_restaurant_sale"/>
+ </record>
+
+ <!-- Restaurantes Take-Out -->
+ <record id="fiscal_position_tax_18" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_group_restaurant_sale"/>
+ <field name="position_id" ref="position_restaurant_takeout"/>
+ <field name="tax_dest_id" ref="tax_18_sale"/>
+ </record>
+
+ <!-- Regímenes Especiales -->
+ <record id="fiscal_position_tax_19" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_18_sale"/>
+ <field name="position_id" ref="position_especial"/>
+ <field name="tax_dest_id" ref="tax_0_sale"/>
+ </record>
+ <record id="fiscal_position_tax_20" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_18_sale_incl"/>
+ <field name="position_id" ref="position_especial"/>
+ <field name="tax_dest_id" ref="tax_0_sale"/>
+ </record>
+ <record id="fiscal_position_tax_21" model="account.fiscal.position.tax.template">
+ <field name="tax_src_id" ref="tax_group_restaurant_sale"/>
+ <field name="position_id" ref="position_especial"/>
+ <field name="tax_dest_id" ref="tax_tip_sale"/>
</record>
+
<!-- = = = = = = = = = = = = = = = = = -->
<!-- Fiscal Position Accounts Template -->
<!-- = = = = = = = = = = = = = = = = = -->
diff --git a/addons/l10n_do/models/chart_template.py b/addons/l10n_do/models/chart_template.py
index d9f71e984af..73e99589873 100644
--- a/addons/l10n_do/models/chart_template.py
+++ b/addons/l10n_do/models/chart_template.py
@@ -11,8 +11,8 @@ class WizardMultiChartsAccounts(models.TransientModel):
def _get_default_bank_account_ids(self):
if self.env.user.company_id.country_id and self.env.user.company_id.country_id.code.upper() == 'DO':
return [
- {'acc_name': _('Cash'), 'account_type': 'cash'},
- {'acc_name': _('Caja Chica'), 'account_type': 'cash'},
- {'acc_name': _('Bank'), 'account_type': 'bank'}
- ]
+ {'acc_name': _('Cash'), 'account_type': 'cash'},
+ {'acc_name': _('Caja Chica'), 'account_type': 'cash'},
+ {'acc_name': _('Bank'), 'account_type': 'bank'}
+ ]
return super(WizardMultiChartsAccounts, self)._get_default_bank_account_ids()
diff --git a/addons/mail/static/src/less/composer.less b/addons/mail/static/src/less/composer.less
index e2fae8b106e..affd87da029 100644
--- a/addons/mail/static/src/less/composer.less
+++ b/addons/mail/static/src/less/composer.less
@@ -57,7 +57,7 @@
border: none;
}
.o_composer_button_full_composer {
- .o-position-absolute(0, 0);
+ .o-position-absolute(auto, 0);
}
@media (max-width: @screen-xs-max) {
.o_composer_button_send {
diff --git a/addons/mail/static/src/less/thread.less b/addons/mail/static/src/less/thread.less
index 81dee297011..8b2bc671d50 100644
--- a/addons/mail/static/src/less/thread.less
+++ b/addons/mail/static/src/less/thread.less
@@ -1,7 +1,7 @@
@mail-thread-avatar-size: 36px;
@mail-thread-icon-opacity: 0.6;
@mail-thread-side-date-opacity: 0.6;
-@mail-thread-note: @gray-lighter;
+@mail-thread-note: fade(@gray-lighter-dark, 50%);
.o_mail_thread, .o_mail_activity {
.o_thread_show_more {
@@ -49,7 +49,7 @@
&.o_mail_not_discussion {
background-color: @mail-thread-note;
- border-bottom: 1px solid @gray-lighter-dark;
+ border-bottom: 1px solid @gray-lighter-darker;
}
.o_thread_message_sidebar {
diff --git a/addons/note/views/note_views.xml b/addons/note/views/note_views.xml
index 29adc15b64e..d405dafb468 100644
--- a/addons/note/views/note_views.xml
+++ b/addons/note/views/note_views.xml
@@ -114,7 +114,7 @@
<!-- title -->
<field name="name"/>
<div class="oe_kanban_bottom_right">
- <div class="o_kanban_inline_block mt16 mr4">
+ <div class="o_kanban_inline_block mr4">
<field name="activity_ids" widget="kanban_activity" />
</div>
</div>
diff --git a/addons/payment/controllers/portal.py b/addons/payment/controllers/portal.py
index 7e023e01c7a..be70f46309e 100644
--- a/addons/payment/controllers/portal.py
+++ b/addons/payment/controllers/portal.py
@@ -89,6 +89,7 @@ class WebsitePayment(http.Controller):
'amount': float(amount),
'currency_id': currency_id,
'partner_id': partner_id,
+ 'type': 'form_save' if acquirer.save_token else 'form',
}
tx = request.env['payment.transaction'].sudo().create(values)
@@ -117,7 +118,8 @@ class WebsitePayment(http.Controller):
'amount': float(amount),
'currency_id': int(currency_id),
'partner_id': partner_id,
- 'payment_token_id': pm_id
+ 'payment_token_id': pm_id,
+ 'type': 'form_save' if token.acquirer_id.save_token else 'form',
}
tx = request.env['payment.transaction'].sudo().create(values)
diff --git a/addons/payment/static/src/js/payment_form.js b/addons/payment/static/src/js/payment_form.js
index 1e0d5e7a0c2..372e8ba233d 100644
--- a/addons/payment/static/src/js/payment_form.js
+++ b/addons/payment/static/src/js/payment_form.js
@@ -178,7 +178,7 @@ odoo.define('payment.payment_form', function (require) {
}).fail(function (message, data) {
self.displayError(
_t('Server Error'),
- _t("We are not able to redirect you to the payment form.<") +
+ _t("We are not able to redirect you to the payment form. ") +
data.data.message
);
});
@@ -221,7 +221,7 @@ odoo.define('payment.payment_form', function (require) {
var form_data = this.getFormData(inputs_form);
var ds = $('input[name="data_set"]', acquirer_form)[0];
var wrong_input = false;
-
+
inputs_form.toArray().forEach(function (element) {
//skip the check of non visible inputs
if ($(element).attr('type') == 'hidden') {
@@ -397,7 +397,7 @@ odoo.define('payment.payment_form', function (require) {
var acquirer_id = this.getAcquirerIdFromRadio(checked_radio);
// if we clicked on an add new payment radio, display its form
- if (this.isNewPaymentRadio(checked_radio)) {
+ if (this.isNewPaymentRadio(checked_radio)) {
this.$('#o_payment_add_token_acq_' + acquirer_id).removeClass('hidden');
}
else if (this.isFormPaymentRadio(checked_radio)) {
@@ -415,8 +415,14 @@ odoo.define('payment.payment_form', function (require) {
},
displayError: function (title, message) {
var $checkedRadio = this.$('input[type="radio"]:checked'),
- acquirerID = this.getAcquirerIdFromRadio($checkedRadio[0]),
+ acquirerID = this.getAcquirerIdFromRadio($checkedRadio[0]);
+ var $acquirerForm;
+ if (this.isNewPaymentRadio($checkedRadio[0])) {
$acquirerForm = this.$('#o_payment_add_token_acq_' + acquirerID);
+ }
+ else if (this.isFormPaymentRadio($checkedRadio[0])) {
+ $acquirerForm = this.$('#o_payment_form_acq_' + acquirerID);
+ }
if ($checkedRadio.length === 0) {
return new Dialog(null, {
diff --git a/addons/payment_authorize/models/payment.py b/addons/payment_authorize/models/payment.py
index b10f2824733..fe17ee4add9 100644
--- a/addons/payment_authorize/models/payment.py
+++ b/addons/payment_authorize/models/payment.py
@@ -11,7 +11,7 @@ import time
from odoo import _, api, fields, models
from odoo.addons.payment.models.payment_acquirer import ValidationError
from odoo.addons.payment_authorize.controllers.main import AuthorizeController
-from odoo.tools.float_utils import float_compare
+from odoo.tools.float_utils import float_compare, float_repr
from odoo.tools.safe_eval import safe_eval
_logger = logging.getLogger(__name__)
@@ -64,7 +64,7 @@ class PaymentAcquirerAuthorize(models.Model):
temp_authorize_tx_values = {
'x_login': self.authorize_login,
'x_trans_key': self.authorize_transaction_key,
- 'x_amount': str(values['amount']),
+ 'x_amount': float_repr(values['amount'], values['currency'].decimal_places if values['currency'] else 2),
'x_show_form': 'PAYMENT_FORM',
'x_type': 'AUTH_CAPTURE' if not self.capture_manually else 'AUTH_ONLY',
'x_method': 'CC',
diff --git a/addons/payment_authorize/tests/test_authorize.py b/addons/payment_authorize/tests/test_authorize.py
index 242fb20d265..3584cd38dc1 100644
--- a/addons/payment_authorize/tests/test_authorize.py
+++ b/addons/payment_authorize/tests/test_authorize.py
@@ -48,7 +48,7 @@ class AuthorizeForm(AuthorizeCommon):
form_values = {
'x_login': self.authorize.authorize_login,
'x_trans_key': self.authorize.authorize_transaction_key,
- 'x_amount': '320.0',
+ 'x_amount': '56.16',
'x_show_form': 'PAYMENT_FORM',
'x_type': 'AUTH_CAPTURE',
'x_method': 'CC',
@@ -84,7 +84,7 @@ class AuthorizeForm(AuthorizeCommon):
form_values['x_fp_hash'] = self._authorize_generate_hashing(form_values)
# render the button
- res = self.authorize.render('SO004', 320.0, self.currency_usd.id, values=self.buyer_values)
+ res = self.authorize.render('SO004', 56.16, self.currency_usd.id, values=self.buyer_values)
# check form result
tree = objectify.fromstring(res)
diff --git a/addons/payment_stripe/models/payment.py b/addons/payment_stripe/models/payment.py
index fc713d70390..9645a5e4288 100644
--- a/addons/payment_stripe/models/payment.py
+++ b/addons/payment_stripe/models/payment.py
@@ -130,7 +130,7 @@ class PaymentTransactionStripe(models.Model):
@api.multi
def stripe_s2s_do_transaction(self, **kwargs):
self.ensure_one()
- result = self._create_stripe_charge(acquirer_ref=self.payment_token_id.acquirer_ref)
+ result = self._create_stripe_charge(acquirer_ref=self.payment_token_id.acquirer_ref, email=self.partner_email)
return self._stripe_s2s_validate_tree(result)
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index 5b55e88896d..30baa7d4498 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -46,9 +46,11 @@ class PosOrder(models.Model):
}
def _payment_fields(self, ui_paymentline):
+ payment_date = ui_paymentline['name']
+ payment_date = fields.Date.context_today(self, fields.Datetime.from_string(payment_date))
return {
'amount': ui_paymentline['amount'] or 0.0,
- 'payment_date': ui_paymentline['name'],
+ 'payment_date': payment_date,
'statement_id': ui_paymentline['statement_id'],
'payment_name': ui_paymentline.get('note', False),
'journal': ui_paymentline['journal_id'],
@@ -413,14 +415,14 @@ class PosOrder(models.Model):
return True
def _get_pos_anglo_saxon_price_unit(self, product, partner_id, quantity):
- # In the SO part, the entries will be inverted by function compute_invoice_totals
- price_unit = - product._get_anglo_saxon_price_unit()
+ price_unit = product._get_anglo_saxon_price_unit()
if product._get_invoice_policy() == "delivery":
moves = self.filtered(lambda o: o.partner_id.id == partner_id).mapped('picking_id.move_lines').filtered(lambda m: m.product_id.id == product.id)
moves.sorted(lambda x: x.date)
- average_price_unit = product._compute_average_price(quantity, quantity, moves)
+ average_price_unit = product._compute_average_price(0, quantity, moves)
price_unit = average_price_unit or price_unit
- return price_unit
+ # In the SO part, the entries will be inverted by function compute_invoice_totals
+ return - price_unit
def _reconcile_payments(self):
for order in self:
@@ -811,7 +813,7 @@ class PosOrder(models.Model):
"""Create a new payment for the order"""
args = {
'amount': data['amount'],
- 'date': data.get('payment_date', fields.Date.today()),
+ 'date': data.get('payment_date', fields.Date.context_today(self)),
'name': self.name + ': ' + (data.get('payment_name', '') or ''),
'partner_id': self.env["res.partner"]._find_accounting_partner(self.partner_id).id or False,
}
diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js
index f59d6f81264..6a303b508a8 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -941,6 +941,7 @@ exports.PosModel = Backbone.Model.extend({
model: 'pos.order',
method: 'create_from_ui',
args: args,
+ kwargs: {context: session.user_context},
}, {
timeout: timeout,
shadow: !options.to_invoice
@@ -1385,7 +1386,8 @@ exports.Orderline = Backbone.Model.extend({
if (unit.rounding) {
this.quantity = round_pr(quant, unit.rounding);
var decimals = this.pos.dp['Product Unit of Measure'];
- this.quantityStr = field_utils.format.float(round_di(this.quantity, decimals), {digits: [69, decimals]});
+ this.quantity = round_di(this.quantity, decimals)
+ this.quantityStr = field_utils.format.float(this.quantity, {digits: [69, decimals]});
} else {
this.quantity = round_pr(quant, 1);
this.quantityStr = this.quantity.toFixed(0);
diff --git a/addons/portal/controllers/portal.py b/addons/portal/controllers/portal.py
index c12a10ebfaf..81ffa1c2c4f 100644
--- a/addons/portal/controllers/portal.py
+++ b/addons/portal/controllers/portal.py
@@ -6,8 +6,10 @@ import math
from werkzeug import urls
from odoo import fields as odoo_fields, tools, _
+from odoo.osv import expression
from odoo.exceptions import ValidationError
from odoo.http import Controller, request, route
+from odoo.addons.web.controllers.main import WebClient
# --------------------------------------------------
# Misc tools
diff --git a/addons/portal/models/__init__.py b/addons/portal/models/__init__.py
index 320a9e84f38..c6570a37f8c 100644
--- a/addons/portal/models/__init__.py
+++ b/addons/portal/models/__init__.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from . import ir_http
from . import mail_thread
from . import mail_message
from . import portal_mixin \ No newline at end of file
diff --git a/addons/portal/models/ir_http.py b/addons/portal/models/ir_http.py
new file mode 100644
index 00000000000..b1cf9f59a60
--- /dev/null
+++ b/addons/portal/models/ir_http.py
@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import api, fields, models
+from odoo.osv import expression
+
+
+class IrHttp(models.AbstractModel):
+ _inherit = 'ir.http'
+
+ @classmethod
+ def _get_translation_frontend_modules_domain(cls):
+ domain = super(IrHttp, cls)._get_translation_frontend_modules_domain()
+ return expression.OR([domain, [('name', '=', 'portal')]])
+
diff --git a/addons/portal/views/portal_templates.xml b/addons/portal/views/portal_templates.xml
index 64f24c95271..7004ad9fad3 100644
--- a/addons/portal/views/portal_templates.xml
+++ b/addons/portal/views/portal_templates.xml
@@ -10,6 +10,7 @@
is_website_user: <t t-esc="json.dumps(request.env.user._is_public())"/>,
user_id: <t t-esc="json.dumps(request.env.user.id)" />,
is_frontend: true,
+ translationURL: '/website/translations',
};
</script>
diff --git a/addons/pos_mercury/data/pos_mercury_demo.xml b/addons/pos_mercury/data/pos_mercury_demo.xml
index 5ff1a0d70e4..b242868f8df 100644
--- a/addons/pos_mercury/data/pos_mercury_demo.xml
+++ b/addons/pos_mercury/data/pos_mercury_demo.xml
@@ -5,8 +5,8 @@
<!-- This is a test account for testing with test cards and cannot be used in a live environment -->
<record id="pos_mercury_configuration" model="pos_mercury.configuration">
<field name="name">Mercury Demo</field>
- <field name="merchant_id">334160</field>
- <field name="merchant_pwd">81303DUR</field>
+ <field name="merchant_id">755847002</field>
+ <field name="merchant_pwd">xyz</field>
</record>
</data>
</odoo>
diff --git a/addons/pos_mercury/models/pos_mercury.py b/addons/pos_mercury/models/pos_mercury.py
index 65512565ba1..eca5ffae0e9 100644
--- a/addons/pos_mercury/models/pos_mercury.py
+++ b/addons/pos_mercury/models/pos_mercury.py
@@ -4,6 +4,7 @@
import logging
from odoo import models, fields, api, _
+from odoo.tools.float_utils import float_compare
_logger = logging.getLogger(__name__)
@@ -71,8 +72,9 @@ class PosOrder(models.Model):
statement_id = super(PosOrder, self).add_payment(data)
statement_lines = self.env['account.bank.statement.line'].search([('statement_id', '=', statement_id),
('pos_statement_id', '=', self.id),
- ('journal_id', '=', data['journal']),
- ('amount', '=', data['amount'])])
+ ('journal_id', '=', data['journal'])])
+ statement_lines = statement_lines.filtered(lambda line: float_compare(line.amount, data['amount'],
+ precision_rounding=line.journal_currency_id.rounding) == 0)
# we can get multiple statement_lines when there are >1 credit
# card payments with the same amount. In that case it doesn't
diff --git a/addons/pos_mercury/models/pos_mercury_transaction.py b/addons/pos_mercury/models/pos_mercury_transaction.py
index ade1f15c729..72faef7f207 100644
--- a/addons/pos_mercury/models/pos_mercury_transaction.py
+++ b/addons/pos_mercury/models/pos_mercury_transaction.py
@@ -61,11 +61,15 @@ class MercuryTransaction(models.Model):
'SOAPAction': 'http://www.mercurypay.com/CreditTransaction',
}
+ url = 'https://w1.mercurypay.com/ws/ws.asmx'
+ if self.env['ir.config_parameter'].sudo().get_param('pos_mercury.enable_test_env'):
+ url = 'https://w1.mercurycert.net/ws/ws.asmx'
+
try:
- r = requests.post('https://w1.mercurypay.com/ws/ws.asmx', data=xml_transaction, headers=headers, timeout=65)
+ r = requests.post(url, data=xml_transaction, headers=headers, timeout=65)
r.raise_for_status()
response = werkzeug.utils.unescape(r.content.decode())
- except:
+ except Exception:
response = "timeout"
return response
diff --git a/addons/project/models/project.py b/addons/project/models/project.py
index b561d5bcfcf..4ca2198b1fc 100644
--- a/addons/project/models/project.py
+++ b/addons/project/models/project.py
@@ -527,7 +527,7 @@ class Task(models.Model):
legend_done = fields.Char(related='stage_id.legend_done', string='Kanban Valid Explanation', readonly=True, related_sudo=False)
legend_normal = fields.Char(related='stage_id.legend_normal', string='Kanban Ongoing Explanation', readonly=True, related_sudo=False)
parent_id = fields.Many2one('project.task', string='Parent Task', index=True)
- child_ids = fields.One2many('project.task', 'parent_id', string="Sub-tasks")
+ child_ids = fields.One2many('project.task', 'parent_id', string="Sub-tasks", context={'active_test': False})
subtask_count = fields.Integer("Sub-task count", compute='_compute_subtask_count')
email_from = fields.Char(string='Email', help="These people will receive email.", index=True)
email_cc = fields.Char(string='Watchers Emails', help="""These email addresses will be added to the CC field of all inbound
diff --git a/addons/purchase/data/purchase_demo.xml b/addons/purchase/data/purchase_demo.xml
index 58f0049a3dc..a3d5d4e5e79 100644
--- a/addons/purchase/data/purchase_demo.xml
+++ b/addons/purchase/data/purchase_demo.xml
@@ -22,7 +22,7 @@
<field name="route_ids" eval="[(4,ref('route_warehouse0_buy'))]"></field>
</record>
</data>
-
+
<record id="purchase_order_1" model="purchase.order">
<field name="partner_id" ref="base.res_partner_1"/>
<field name="state">draft</field>
@@ -187,5 +187,11 @@
<record id="stock.stock_warehouse_shop0" model="stock.warehouse">
<field name="buy_to_resupply" eval="True"/>
</record>
+
+ <function model="stock.warehouse" name="write">
+ <value model="stock.warehouse" search="[('partner_id', '=', ref('stock.res_partner_company_1'))]"/>
+ <value eval="{'buy_to_resupply': True}"/>
+ </function>
+
</odoo>
diff --git a/addons/purchase/models/purchase.py b/addons/purchase/models/purchase.py
index f068dbf9af1..994142c7362 100644
--- a/addons/purchase/models/purchase.py
+++ b/addons/purchase/models/purchase.py
@@ -1050,11 +1050,11 @@ class ProcurementRule(models.Model):
def _prepare_purchase_order(self, product_id, product_qty, product_uom, origin, values, partner):
schedule_date = self._get_purchase_schedule_date(values)
purchase_date = self._get_purchase_order_date(product_id, product_qty, product_uom, values, partner, schedule_date)
- fpos = self.env['account.fiscal.position'].with_context(company_id=values['company_id'].id).get_fiscal_position(partner.id)
+ fpos = self.env['account.fiscal.position'].with_context(force_company=values['company_id'].id).get_fiscal_position(partner.id)
gpo = self.group_propagation_option
group = (gpo == 'fixed' and self.group_id.id) or \
- (gpo == 'propagate' and values['group_id'].id) or False
+ (gpo == 'propagate' and 'group_id' in values and values['group_id'].id) or False
return {
'partner_id': partner.id,
@@ -1079,7 +1079,7 @@ class ProcurementRule(models.Model):
domain = super(ProcurementRule, self)._make_po_get_domain(values, partner)
gpo = self.group_propagation_option
group = (gpo == 'fixed' and self.group_id) or \
- (gpo == 'propagate' and values['group_id']) or False
+ (gpo == 'propagate' and 'group_id' in values and values['group_id']) or False
domain += (
('partner_id', '=', partner.id),
diff --git a/addons/repair/views/repair_views.xml b/addons/repair/views/repair_views.xml
index c0842efbe28..b1eb662828b 100644
--- a/addons/repair/views/repair_views.xml
+++ b/addons/repair/views/repair_views.xml
@@ -149,7 +149,7 @@
</group>
</form>
<tree string="Fees" editable="bottom">
- <field name="product_id" domain="[('type','=','service')]"/>
+ <field name="product_id" domain="[('type','=','service')]" required="True"/>
<field name='name'/>
<field name="product_uom_qty" string="Quantity"/>
<field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
diff --git a/addons/sale/__manifest__.py b/addons/sale/__manifest__.py
index 5860dabd53c..15be2f95947 100644
--- a/addons/sale/__manifest__.py
+++ b/addons/sale/__manifest__.py
@@ -11,6 +11,8 @@ This module contains all the common features of Sales Management and eCommerce.
""",
'depends': ['sales_team', 'account', 'portal'],
'data': [
+ 'security/sale_security.xml',
+ 'security/ir.model.access.csv',
'data/ir_sequence_data.xml',
'data/sale_data.xml',
'report/sale_report.xml',
@@ -19,8 +21,6 @@ This module contains all the common features of Sales Management and eCommerce.
'report/sale_report_templates.xml',
'report/invoice_report_templates.xml',
'report/report_all_channels_sales_views.xml',
- 'security/sale_security.xml',
- 'security/ir.model.access.csv',
'wizard/sale_make_invoice_advance_views.xml',
'views/sale_views.xml',
'views/account_invoice_views.xml',
diff --git a/addons/sale/models/account_invoice.py b/addons/sale/models/account_invoice.py
index a03df305b16..0a2406a0968 100644
--- a/addons/sale/models/account_invoice.py
+++ b/addons/sale/models/account_invoice.py
@@ -39,6 +39,9 @@ class AccountInvoice(models.Model):
def _onchange_delivery_address(self):
addr = self.partner_id.address_get(['delivery'])
self.partner_shipping_id = addr and addr.get('delivery')
+ if self.env.context.get('type', 'out_invoice') == 'out_invoice':
+ company = self.company_id or self.env.user.company_id
+ self.comment = company.with_context(lang=self.partner_id.lang).sale_note
@api.multi
def action_invoice_paid(self):
diff --git a/addons/sale/report/sale_report.xml b/addons/sale/report/sale_report.xml
index 515d7634da2..9c9addca79b 100644
--- a/addons/sale/report/sale_report.xml
+++ b/addons/sale/report/sale_report.xml
@@ -16,6 +16,7 @@
string="PRO-FORMA Invoice"
model="sale.order"
report_type="qweb-pdf"
+ groups="sale.group_proforma_sales"
file="sale.report_saleorder_pro_forma"
name="sale.report_saleorder_pro_forma"
print_report_name="'PRO-FORMA - %s' % (object.name)"
diff --git a/addons/sale/report/sale_report_templates.xml b/addons/sale/report/sale_report_templates.xml
index 3352f75b048..8f7c66edc1a 100644
--- a/addons/sale/report/sale_report_templates.xml
+++ b/addons/sale/report/sale_report_templates.xml
@@ -60,6 +60,10 @@
<strong>Payment Terms:</strong>
<p t-field="doc.payment_term_id"/>
</div>
+ <div t-if="doc.validity_date and doc.state in ['draft', 'sent']" class="col-xs-3">
+ <strong>Expiration Date:</strong>
+ <p t-field="doc.validity_date"/>
+ </div>
</div>
<!-- Is there a discount on at least one line? -->
diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py
index 631c3eeeb3a..752a7a7c9fc 100644
--- a/addons/sale/wizard/sale_make_invoice_advance.py
+++ b/addons/sale/wizard/sale_make_invoice_advance.py
@@ -67,7 +67,7 @@ class SaleAdvancePaymentInv(models.TransientModel):
account_id = False
if self.product_id.id:
- account_id = self.product_id.property_account_income_id.id
+ account_id = self.product_id.property_account_income_id.id or self.product_id.categ_id.property_account_income_categ_id.id
if not account_id:
inc_acc = ir_property_obj.get('property_account_income_categ_id', 'product.category')
account_id = order.fiscal_position_id.map_account(inc_acc).id if inc_acc else False
diff --git a/addons/stock/models/stock_move_line.py b/addons/stock/models/stock_move_line.py
index 2ff3586a943..0837de9ebae 100644
--- a/addons/stock/models/stock_move_line.py
+++ b/addons/stock/models/stock_move_line.py
@@ -52,7 +52,6 @@ class StockMoveLine(models.Model):
reference = fields.Char(related='move_id.reference', store=True, related_sudo=False)
in_entire_package = fields.Boolean(compute='_compute_in_entire_package')
- @api.one
def _compute_location_description(self):
for operation, operation_sudo in izip(self, self.sudo()):
operation.from_loc = '%s%s' % (operation_sudo.location_id.name, operation.product_id and operation_sudo.package_id.name or '')
@@ -141,7 +140,7 @@ class StockMoveLine(models.Model):
help him. This onchange will warn him if he set `qty_done` to a non-supported value.
"""
res = {}
- if self.product_id.tracking == 'serial':
+ if self.qty_done and self.product_id.tracking == 'serial':
if float_compare(self.qty_done, 1.0, precision_rounding=self.move_id.product_id.uom_id.rounding) != 0:
message = _('You can only process 1.0 %s of products with unique serial number.') % self.product_id.uom_id.name
res['warning'] = {'title': _('Warning'), 'message': message}
diff --git a/addons/stock/models/stock_production_lot.py b/addons/stock/models/stock_production_lot.py
index 4fc1092839d..5a7a72074aa 100644
--- a/addons/stock/models/stock_production_lot.py
+++ b/addons/stock/models/stock_production_lot.py
@@ -37,6 +37,18 @@ class ProductionLot(models.Model):
raise UserError(_("You are not allowed to create a lot for this picking type"))
return super(ProductionLot, self).create(vals)
+ @api.multi
+ def write(self, vals):
+ if 'product_id' in vals:
+ move_lines = self.env['stock.move.line'].search([('lot_id', 'in', self.ids)])
+ if move_lines:
+ raise UserError(_(
+ 'You are not allowed to change the product linked to a serial or lot number ' +
+ 'if some stock moves have already been created with that number. ' +
+ 'This would lead to inconsistencies in your stock.'
+ ))
+ return super(ProductionLot, self).write(vals)
+
@api.one
def _product_qty(self):
# We only care for the quants in internal or transit locations.
diff --git a/addons/stock/report/report_location_barcode.xml b/addons/stock/report/report_location_barcode.xml
index 93aee57f27b..426f7037e28 100644
--- a/addons/stock/report/report_location_barcode.xml
+++ b/addons/stock/report/report_location_barcode.xml
@@ -9,8 +9,8 @@
</template>
<template id="report_location_barcode">
- <t t-call="web.basic_layout">
- <div t-foreach="[docs[x:x+4] for x in xrange(0, len(docs), 4)]" t-as="page_docs" class="page page_stock_location_barcodes">
+ <t t-call="web.html_container">
+ <div t-foreach="[docs[x:x+4] for x in xrange(0, len(docs), 4)]" t-as="page_docs" class="page article page_stock_location_barcodes">
<t t-foreach="page_docs" t-as="o">
<t t-if="o.barcode"><t t-set="content" t-value="o.barcode"/></t>
<t t-if="not o.barcode"><t t-set="content" t-value="o.name"/></t>
diff --git a/addons/stock/views/stock_move_line_views.xml b/addons/stock/views/stock_move_line_views.xml
index c0175c1380b..d392bafc072 100644
--- a/addons/stock/views/stock_move_line_views.xml
+++ b/addons/stock/views/stock_move_line_views.xml
@@ -25,6 +25,8 @@
<field name="state" widget="statusbar"/>
</header>
<sheet>
+ <field name="in_entire_package" invisible="1"/>
+ <field name="picking_id" invisible="1"/>
<group>
<group>
<field name="date"/>
@@ -44,7 +46,8 @@
<field name="qty_done"/>
<field name="product_uom_id" options="{'no_create': True}" string="Unit of Measure" groups="product.group_uom"/>
</div>
- <field name="lot_id" string="Lot/Serial Number" groups="stock.group_production_lot"/>
+ <field name="lot_id" attrs="{'readonly': [('in_entire_package', '=', True)]}" domain="[('product_id', '=', product_id)]" groups="stock.group_production_lot" context="{'default_product_id': product_id, 'active_picking_id': picking_id}"/>
+ <field name="lot_name" attrs="{'readonly': [('in_entire_package', '=', True)]}" groups="stock.group_production_lot"/>
<field name="package_id" string="Source Package" groups="product.group_stock_packaging"/>
<field name="result_package_id" string="Destination Package" groups="stock.group_tracking_lot"/>
<field name="owner_id" string="Owner" groups="stock.group_tracking_owner"/>
@@ -86,6 +89,7 @@
<field name="model">stock.move.line</field>
<field name="arch" type="xml">
<kanban class="o_kanban_mobile">
+ <field name="in_entire_package"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
@@ -93,6 +97,8 @@
<field name="picking_id"/>
<div class="row">
<div class="col-xs-6">
+ <field name="lot_id" invisible="not context.get('show_lots_m2o')" domain="[('product_id', '=', product_id)]" groups="stock.group_production_lot" context="{'default_product_id': product_id, 'active_picking_id': picking_id}"/>
+ <field name="lot_name" invisible="not context.get('show_lots_text')" groups="stock.group_production_lot"/>
<field name="qty_done" string="Quantity Done"/>
<field name="product_uom_id" string="Unit of Measure" groups="product.group_uom"/>
</div>
diff --git a/addons/stock/views/stock_move_views.xml b/addons/stock/views/stock_move_views.xml
index cd945d3bfe0..548593374e7 100644
--- a/addons/stock/views/stock_move_views.xml
+++ b/addons/stock/views/stock_move_views.xml
@@ -75,6 +75,7 @@
<field name="product_id"/>
<field name="priority"/>
<field name="state"/>
+ <field name="show_details_visible"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_global_click">
@@ -88,7 +89,11 @@
<field name="product_id"/>
</div>
<div class="o_kanban_record_bottom">
- <div class="oe_kanban_bottom_left"/>
+ <div class="oe_kanban_bottom_left">
+ <button name="action_show_details" string="Register lots, packs, location"
+ class="o_icon_button fa fa-list" type="object"
+ attrs="{'invisible': [('show_details_visible', '=', False)]}" options='{"warn": true}'/>
+ </div>
<div class="oe_kanban_bottom_right">
<span><field name="product_uom_qty"/></span>
</div>
diff --git a/addons/stock_account/data/stock_account_data.xml b/addons/stock_account/data/stock_account_data.xml
index 1a4a386eed6..c71fee32837 100644
--- a/addons/stock_account/data/stock_account_data.xml
+++ b/addons/stock_account/data/stock_account_data.xml
@@ -26,17 +26,6 @@
<field name="value">manual_periodic</field>
<field name="type">selection</field>
</record>
- <record id="action_stock_account_valuation_report" model="ir.actions.server">
- <field name="name">Stock Valuation Report</field>
- <field name="type">ir.actions.server</field>
- <field name="state">code</field>
- <field name="model_id" ref="product.model_product_product"></field>
- <field name="binding_model_id" ref="product.model_product_product"></field>
- <field name="code">
-env['stock.move']._run_fifo_vacuum()
-action = env.ref('stock_account.product_valuation_action').read()[0]
- </field>
- </record>
</data>
</odoo>
diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py
index a24f3b92726..10832aa8bde 100644
--- a/addons/stock_account/models/product.py
+++ b/addons/stock_account/models/product.py
@@ -63,7 +63,7 @@ class ProductTemplate(models.Model):
if self.property_cost_method == 'fifo' and self.cost_method in ['average', 'standard']:
# Cannot use the `stock_value` computed field as it's already invalidated when
# entering this method.
- valuation = sum([variant._sum_remaining_values() for variant in self.product_variant_ids])
+ valuation = sum([variant._sum_remaining_values()[0] for variant in self.product_variant_ids])
qty_available = self.with_context(company_owned=True).qty_available
if qty_available:
self.standard_price = valuation / qty_available
@@ -85,16 +85,8 @@ class ProductTemplate(models.Model):
@api.multi
def action_open_product_moves(self):
- self.ensure_one()
- action = self.env.ref('stock_account.stock_move_valuation_action').read()[0]
- action['domain'] = [('product_tmpl_id', '=', self.id)]
- action['context'] = {
- 'search_default_outgoing': True,
- 'search_default_incoming': True,
- 'search_default_done': True,
- 'is_avg': self.cost_method == 'average',
- }
- return action
+ # TODO: remove me in master
+ pass
@api.multi
def get_product_accounts(self, fiscal_pos=None):
@@ -111,6 +103,12 @@ class ProductProduct(models.Model):
stock_value = fields.Float(
'Value', compute='_compute_stock_value')
+ qty_at_date = fields.Float(
+ 'Quantity', compute='_compute_stock_value')
+ stock_fifo_real_time_aml_ids = fields.Many2many(
+ 'account.move.line', compute='_compute_stock_value')
+ stock_fifo_manual_move_ids = fields.Many2many(
+ 'stock.move', compute='_compute_stock_value')
@api.multi
def do_change_standard_price(self, new_price, account_id):
@@ -173,30 +171,100 @@ class ProductProduct(models.Model):
StockMove = self.env['stock.move']
domain = [('product_id', '=', self.id)] + StockMove._get_all_base_domain()
moves = StockMove.search(domain)
- return sum(moves.mapped('remaining_value'))
+ return sum(moves.mapped('remaining_value')), moves
@api.multi
- @api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'product_tmpl_id.cost_method')
+ @api.depends('stock_move_ids.product_qty', 'stock_move_ids.state', 'stock_move_ids.remaining_value', 'product_tmpl_id.cost_method', 'product_tmpl_id.standard_price', 'product_tmpl_id.property_valuation', 'product_tmpl_id.categ_id.property_valuation')
def _compute_stock_value(self):
+ StockMove = self.env['stock.move']
+ to_date = self.env.context.get('to_date')
+
+ self.env['account.move.line'].check_access_rights('read')
+ fifo_automated_values = {}
+ query = """SELECT aml.product_id, aml.account_id, sum(aml.debit) - sum(aml.credit), sum(quantity), array_agg(aml.id)
+ FROM account_move_line AS aml
+ WHERE aml.product_id IS NOT NULL AND aml.company_id=%%s %s
+ GROUP BY aml.product_id, aml.account_id"""
+ params = (self.env.user.company_id.id,)
+ if to_date:
+ query = query % ('AND aml.date <= %s',)
+ params = params + (to_date,)
+ else:
+ query = query % ('',)
+ self.env.cr.execute(query, params=params)
+
+ res = self.env.cr.fetchall()
+ for row in res:
+ fifo_automated_values[(row[0], row[1])] = (row[2], row[3], list(row[4]))
+
for product in self:
if product.cost_method in ['standard', 'average']:
- product.stock_value = product.standard_price * product.with_context(company_owned=True).qty_available
+ qty_available = product.with_context(company_owned=True).qty_available
+ price_used = product.standard_price
+ if to_date:
+ price_used = product.get_history_price(
+ self.env.user.company_id.id,
+ date=to_date,
+ )
+ product.stock_value = price_used * qty_available
+ product.qty_at_date = qty_available
elif product.cost_method == 'fifo':
- product.stock_value = product._sum_remaining_values()
-
- @api.multi
- def action_open_product_moves(self):
+ if to_date:
+ if product.product_tmpl_id.valuation == 'manual_periodic':
+ domain = [('product_id', '=', product.id), ('date', '<=', to_date)] + StockMove._get_all_base_domain()
+ moves = StockMove.search(domain)
+ product.stock_value = sum(moves.mapped('value'))
+ product.qty_at_date = product.with_context(company_owned=True).qty_available
+ product.stock_fifo_manual_move_ids = StockMove.browse(moves.ids)
+ elif product.product_tmpl_id.valuation == 'real_time':
+ valuation_account_id = product.categ_id.property_stock_valuation_account_id.id
+ value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, [])
+ product.stock_value = value
+ product.qty_at_date = quantity
+ product.stock_fifo_real_time_aml_ids = self.env['account.move.line'].browse(aml_ids)
+ else:
+ product.stock_value, moves = product._sum_remaining_values()
+ product.qty_at_date = product.with_context(company_owned=True).qty_available
+ if product.product_tmpl_id.valuation == 'manual_periodic':
+ product.stock_fifo_manual_move_ids = moves
+ elif product.product_tmpl_id.valuation == 'real_time':
+ valuation_account_id = product.categ_id.property_stock_valuation_account_id.id
+ value, quantity, aml_ids = fifo_automated_values.get((product.id, valuation_account_id)) or (0, 0, [])
+ product.stock_fifo_real_time_aml_ids = self.env['account.move.line'].browse(aml_ids)
+
+ def action_valuation_at_date_details(self):
+ """ Returns an action with either a list view of all the valued stock moves of `self` if the
+ valuation is set as manual or a list view of all the account move lines if the valuation is
+ set as automated.
+ """
self.ensure_one()
- action = self.env.ref('stock_account.stock_move_valuation_action').read()[0]
- action['domain'] = [('product_id', '=', self.id)]
- action['context'] = {
- 'search_default_outgoing': True,
- 'search_default_incoming': True,
- 'search_default_done': True,
- 'is_avg': self.cost_method == 'average',
+ to_date = self.env.context.get('to_date')
+ action = {
+ 'name': _('Valuation at date'),
+ 'type': 'ir.actions.act_window',
+ 'view_type': 'form',
+ 'view_mode': 'tree,form',
+ 'context': self.env.context,
}
+ if self.valuation == 'real_time':
+ action['res_model'] = 'account.move.line'
+ action['domain'] = [('id', 'in', self.with_context(to_date=to_date).stock_fifo_real_time_aml_ids.ids)]
+ tree_view_ref = self.env.ref('stock_account.view_stock_account_aml')
+ form_view_ref = self.env.ref('account.view_move_line_form')
+ action['views'] = [(tree_view_ref.id, 'tree'), (form_view_ref.id, 'form')]
+ else:
+ action['res_model'] = 'stock.move'
+ action['domain'] = [('id', 'in', self.with_context(to_date=to_date).stock_fifo_manual_move_ids.ids)]
+ tree_view_ref = self.env.ref('stock_account.view_move_tree_valuation_at_date')
+ form_view_ref = self.env.ref('stock.view_move_form')
+ action['views'] = [(tree_view_ref.id, 'tree'), (form_view_ref.id, 'form')]
return action
+ @api.multi
+ def action_open_product_moves(self):
+ #TODO: remove me in master
+ pass
+
@api.model
def _anglo_saxon_sale_move_lines(self, name, product, uom, qty, price_unit, currency=False, amount_currency=False, fiscal_position=False, account_analytic=False, analytic_tags=False):
"""Prepare dicts describing new journal COGS journal items for a product sale.
diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py
index a128f5a6942..c29215f2b79 100644
--- a/addons/stock_account/models/stock.py
+++ b/addons/stock_account/models/stock.py
@@ -71,37 +71,45 @@ class StockMoveLine(models.Model):
if move.product_id.valuation == 'real_time' and (move._is_in() or move._is_out()):
move.with_context(force_valuation_amount=correction_value)._account_entry_move()
return res
-
+
@api.multi
def write(self, vals):
+ """ When editing a done stock.move.line, we impact the valuation. Users may increase or
+ decrease the `qty_done` field. There are three cost method available: standard, average
+ and fifo. We implement the logic in a similar way for standard and average: increase
+ or decrease the original value with the standard or average price of today. In fifo, we
+ have a different logic wheter the move is incoming or outgoing. If the move is incoming, we
+ update the value and remaining_value/qty with the unit price of the move. If the move is
+ outgoing and the user increases qty_done, we call _run_fifo and it'll consume layer(s) in
+ the stack the same way a new outgoing move would have done. If the move is outoing and the
+ user decreases qty_done, we either increase the last receipt candidate if one is found or
+ we decrease the value with the last fifo price.
+ """
if 'qty_done' in vals:
- # We need to update the `value`, `remaining_value` and `remaining_qty` on the linked
- # stock move.
moves_to_update = {}
for move_line in self.filtered(lambda ml: ml.state == 'done' and (ml.move_id._is_in() or ml.move_id._is_out())):
moves_to_update[move_line.move_id] = vals['qty_done'] - move_line.qty_done
for move_id, qty_difference in moves_to_update.items():
- # more/less units are available, update `remaining_value` and
- # `remaining_qty` on the linked stock move.
- move_vals = {'remaining_qty': move_id.remaining_qty + qty_difference}
- new_remaining_value = 0
+ move_vals = {}
if move_id.product_id.cost_method in ['standard', 'average']:
correction_value = qty_difference * move_id.product_id.standard_price
- move_vals['value'] = move_id.value - correction_value
- move_vals.pop('remaining_qty')
+ if move_id._is_in():
+ move_vals['value'] = move_id.value + correction_value
+ elif move_id._is_out():
+ move_vals['value'] = move_id.value - correction_value
else:
- # FIFO handling
if move_id._is_in():
correction_value = qty_difference * move_id.price_unit
new_remaining_value = move_id.remaining_value + correction_value
+ move_vals['value'] = move_id.value + correction_value
+ move_vals['remaining_qty'] = move_id.remaining_qty + qty_difference
+ move_vals['remaining_value'] = move_id.remaining_value + correction_value
elif move_id._is_out() and qty_difference > 0:
- # send more, run fifo again
correction_value = self.env['stock.move']._run_fifo(move_id, quantity=qty_difference)
- new_remaining_value = move_id.remaining_value + correction_value
- move_vals.pop('remaining_qty')
+ # no need to adapt `remaining_qty` and `remaining_value` as `_run_fifo` took care of it
+ move_vals['value'] = move_id.value - correction_value
elif move_id._is_out() and qty_difference < 0:
- # fake return, find the last receipt and augment its qties
candidates_receipt = self.env['stock.move'].search(move_id._get_in_domain(), order='date, id desc', limit=1)
if candidates_receipt:
candidates_receipt.write({
@@ -111,15 +119,11 @@ class StockMoveLine(models.Model):
correction_value = qty_difference * candidates_receipt.price_unit
else:
correction_value = qty_difference * move_id.product_id.standard_price
- move_vals.pop('remaining_qty')
- if move_id._is_out():
- move_vals['remaining_value'] = new_remaining_value if new_remaining_value < 0 else 0
- else:
- move_vals['remaining_value'] = new_remaining_value
+ move_vals['value'] = move_id.value - correction_value
move_id.write(move_vals)
if move_id.product_id.valuation == 'real_time':
- move_id.with_context(force_valuation_amount=correction_value)._account_entry_move()
+ move_id.with_context(force_valuation_amount=correction_value, forced_quantity=qty_difference)._account_entry_move()
if qty_difference > 0:
move_id.product_price_update_before_done(forced_qty=qty_difference)
return super(StockMoveLine, self).write(vals)
@@ -210,13 +214,23 @@ class StockMove(models.Model):
@api.model
def _run_fifo(self, move, quantity=None):
+ """ Value `move` according to the FIFO rule, meaning we consume the
+ oldest receipt first. Candidates receipts are marked consumed or free
+ thanks to their `remaining_qty` and `remaining_value` fields.
+ By definition, `move` should be an outgoing stock move.
+
+ :param quantity: quantity to value instead of `move.product_qty`
+ :returns: valued amount in absolute
+ """
move.ensure_one()
- # Find back incoming stock moves (called candidates here) to value this move.
+
+ # Deal with possible move lines that do not impact the valuation.
valued_move_lines = move.move_line_ids.filtered(lambda ml: ml.location_id._should_be_valued() and not ml.location_dest_id._should_be_valued() and not ml.owner_id)
valued_quantity = 0
for valued_move_line in valued_move_lines:
valued_quantity += valued_move_line.product_uom_id._compute_quantity(valued_move_line.qty_done, move.product_id.uom_id)
+ # Find back incoming stock moves (called candidates here) to value this move.
qty_to_take_on_candidates = quantity or valued_quantity
candidates = move.product_id._get_fifo_candidates_in_move()
new_standard_price = 0
@@ -259,11 +273,12 @@ class StockMove(models.Model):
elif qty_to_take_on_candidates > 0:
last_fifo_price = new_standard_price or move.product_id.standard_price
negative_stock_value = last_fifo_price * -qty_to_take_on_candidates
+ tmp_value += abs(negative_stock_value)
vals = {
'remaining_qty': move.remaining_qty + -qty_to_take_on_candidates,
'remaining_value': move.remaining_value + negative_stock_value,
- 'value': -tmp_value + negative_stock_value,
- 'price_unit': (-tmp_value + negative_stock_value) / (move.product_qty or quantity),
+ 'value': -tmp_value,
+ 'price_unit': -1 * last_fifo_price,
}
move.write(vals)
return tmp_value
@@ -388,12 +403,14 @@ class StockMove(models.Model):
if not candidates:
continue
qty_to_take_on_candidates = abs(move.remaining_qty)
+ qty_taken_on_candidates = 0
tmp_value = 0
for candidate in candidates:
if candidate.remaining_qty <= qty_to_take_on_candidates:
qty_taken_on_candidate = candidate.remaining_qty
else:
qty_taken_on_candidate = qty_to_take_on_candidates
+ qty_taken_on_candidates += qty_taken_on_candidate
value_taken_on_candidate = qty_taken_on_candidate * candidate.price_unit
candidate_vals = {
@@ -407,27 +424,22 @@ class StockMove(models.Model):
if qty_to_take_on_candidates == 0:
break
- remaining_value_before_vacuum = move.remaining_value
- # If `remaining_qty` should be updated to 0, we wipe `remaining_value`. If it was set
- # it was only used to infer the correction entry anyway.
- new_remaining_qty = -qty_to_take_on_candidates
- new_remaining_value = 0 if not new_remaining_qty else move.remaining_value + tmp_value
+ # When working with `price_unit`, beware that out move are negative.
+ move_price_unit = move.price_unit if move._is_out() else -1 * move.price_unit
+ # Get the estimated value we will correct.
+ remaining_value_before_vacuum = qty_taken_on_candidates * move_price_unit
+ new_remaining_qty = move.remaining_qty + qty_taken_on_candidates
+ new_remaining_value = new_remaining_qty * abs(move.price_unit)
+
+ corrected_value = remaining_value_before_vacuum + tmp_value
move.write({
'remaining_value': new_remaining_value,
'remaining_qty': new_remaining_qty,
+ 'value': move.value - corrected_value,
})
if move.product_id.valuation == 'real_time':
- # If `move.remaining_value` is negative, it means that we initially valued this move at
- # an estimated price *and* posted an entry. `tmp_value` is the real value we took to
- # compensate and should always be positive, but if the remaining value is still negative
- # we have to take care to not overvalue by decreasing the correction entry by what's
- # already been posted.
- corrected_value = tmp_value
- if remaining_value_before_vacuum < 0:
- corrected_value += remaining_value_before_vacuum
-
# If `corrected_value` is 0, absolutely do *not* call `_account_entry_move`. We
# force the amount in the context, but in the case it is 0 it'll create an entry
# for the entire cost of the move. This case happens when the candidates moves
@@ -441,9 +453,9 @@ class StockMove(models.Model):
# The correction should behave as a return too. As `_account_entry_move`
# will post the natural values for an IN move (credit IN account, debit
# OUT one), we inverse the sign to create the correct entries.
- move.with_context(force_valuation_amount=-corrected_value)._account_entry_move()
+ move.with_context(force_valuation_amount=-corrected_value, forced_quantity=0)._account_entry_move()
else:
- move.with_context(force_valuation_amount=corrected_value)._account_entry_move()
+ move.with_context(force_valuation_amount=corrected_value, forced_quantity=0)._account_entry_move()
@api.model
def _run_fifo_vacuum(self):
@@ -502,6 +514,11 @@ class StockMove(models.Model):
else:
valuation_amount = cost
+ if self._context.get('forced_ref'):
+ ref = self._context['forced_ref']
+ else:
+ ref = self.picking_id.name
+
# the standard_price of the product may be in another decimal precision, or not compatible with the coinage of
# the company currency... so we need to use round() before creating the accounting entries.
debit_value = self.company_id.currency_id.round(valuation_amount)
@@ -528,7 +545,7 @@ class StockMove(models.Model):
'product_id': self.product_id.id,
'quantity': qty,
'product_uom_id': self.product_id.uom_id.id,
- 'ref': self.picking_id.name,
+ 'ref': ref,
'partner_id': partner_id,
'debit': debit_value if debit_value > 0 else 0,
'credit': -debit_value if debit_value < 0 else 0,
@@ -539,7 +556,7 @@ class StockMove(models.Model):
'product_id': self.product_id.id,
'quantity': qty,
'product_uom_id': self.product_id.uom_id.id,
- 'ref': self.picking_id.name,
+ 'ref': ref,
'partner_id': partner_id,
'credit': credit_value if credit_value > 0 else 0,
'debit': -credit_value if credit_value < 0 else 0,
@@ -559,7 +576,7 @@ class StockMove(models.Model):
'product_id': self.product_id.id,
'quantity': qty,
'product_uom_id': self.product_id.uom_id.id,
- 'ref': self.picking_id.name,
+ 'ref': ref,
'partner_id': partner_id,
'credit': diff_amount > 0 and diff_amount or 0,
'debit': diff_amount < 0 and -diff_amount or 0,
@@ -571,14 +588,25 @@ class StockMove(models.Model):
def _create_account_move_line(self, credit_account_id, debit_account_id, journal_id):
self.ensure_one()
AccountMove = self.env['account.move']
- move_lines = self._prepare_account_move_line(self.product_qty, abs(self.value), credit_account_id, debit_account_id)
+ quantity = self.env.context.get('forced_quantity', self.product_qty if self._is_in() else -1 * self.product_qty)
+
+ # Make an informative `ref` on the created account move to differentiate between classic
+ # movements, vacuum and edition of past moves.
+ ref = self.picking_id.name
+ if self.env.context.get('force_valuation_amount'):
+ if self.env.context.get('forced_quantity') == 0:
+ ref = 'Revaluation of %s (negative inventory)' % ref
+ elif self.env.context.get('forced_quantity') is not None:
+ ref = 'Correction of %s (modification of past move)' % ref
+
+ move_lines = self.with_context(forced_ref=ref)._prepare_account_move_line(quantity, abs(self.value), credit_account_id, debit_account_id)
if move_lines:
date = self._context.get('force_period_date', fields.Date.context_today(self))
new_account_move = AccountMove.create({
'journal_id': journal_id,
'line_ids': move_lines,
'date': date,
- 'ref': self.picking_id.name,
+ 'ref': ref,
'stock_move_id': self.id,
})
new_account_move.post()
diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py
index 29fa3d73761..50cc57885bb 100644
--- a/addons/stock_account/tests/test_stockvaluation.py
+++ b/addons/stock_account/tests/test_stockvaluation.py
@@ -1,7 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
+from datetime import timedelta
+
from odoo.exceptions import UserError
+from odoo.fields import Date
from odoo.tests.common import TransactionCase
@@ -115,6 +118,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 1)
self.assertEqual(move1_valuation_aml.debit, 100)
self.assertEqual(move1_valuation_aml.credit, 0)
+ self.assertEqual(move1_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move1_valuation_aml.quantity, 10)
+ self.assertEqual(move1_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
self.assertEqual(len(output_aml), 0)
@@ -159,6 +165,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 2)
self.assertEqual(move2_valuation_aml.debit, 80)
self.assertEqual(move2_valuation_aml.credit, 0)
+ self.assertEqual(move2_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move2_valuation_aml.quantity, 10)
+ self.assertEqual(move2_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
self.assertEqual(len(output_aml), 0)
@@ -207,6 +216,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 3)
self.assertEqual(move3_valuation_aml.debit, 0)
self.assertEqual(move3_valuation_aml.credit, 30)
+ self.assertEqual(move3_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move3_valuation_aml.quantity, -3)
+ self.assertEqual(move3_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
move3_output_aml = output_aml[-1]
@@ -243,7 +255,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move1.product_uom_qty, 12.0)
self.assertEqual(move1.price_unit, 10.0)
self.assertEqual(move1.remaining_qty, 9.0)
- self.assertEqual(move1.value, 100.0)
+ self.assertEqual(move1.value, 120.0) # move 1 is now 10@10 + 2@10
self.assertEqual(move1.remaining_value, 90.0)
# account values for move1
@@ -258,6 +270,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 4)
self.assertEqual(move1_correction_valuation_aml.debit, 20)
self.assertEqual(move1_correction_valuation_aml.credit, 0)
+ self.assertEqual(move1_correction_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move1_correction_valuation_aml.quantity, 2)
+ self.assertEqual(move1_correction_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
self.assertEqual(len(output_aml), 1)
@@ -311,6 +326,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 5)
self.assertEqual(move4_valuation_aml.debit, 0)
self.assertEqual(move4_valuation_aml.credit, 90)
+ self.assertEqual(move4_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move4_valuation_aml.quantity, -9)
+ self.assertEqual(move4_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
move4_output_aml = output_aml[-1]
@@ -326,7 +344,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move1.product_uom_qty, 12)
self.assertEqual(move1.price_unit, 10.0)
self.assertEqual(move1.remaining_qty, 0)
- self.assertEqual(move1.value, 100)
+ self.assertEqual(move1.value, 120)
self.assertEqual(move1.remaining_value, 0)
self.assertEqual(move2.product_uom_qty, 10.0)
self.assertEqual(move2.price_unit, 8.0)
@@ -373,6 +391,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 6)
self.assertEqual(move5_valuation_aml.debit, 0)
self.assertEqual(move5_valuation_aml.credit, 160)
+ self.assertEqual(move5_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move5_valuation_aml.quantity, -20)
+ self.assertEqual(move5_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
move5_output_aml = output_aml[-1]
@@ -388,7 +409,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move1.product_uom_qty, 12)
self.assertEqual(move1.price_unit, 10.0)
self.assertEqual(move1.remaining_qty, 0)
- self.assertEqual(move1.value, 100)
+ self.assertEqual(move1.value, 120)
self.assertEqual(move1.remaining_value, 0)
self.assertEqual(move2.product_uom_qty, 10.0)
self.assertEqual(move2.price_unit, 8.0)
@@ -445,6 +466,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 7)
self.assertEqual(move6_valuation_aml.debit, 120)
self.assertEqual(move6_valuation_aml.credit, 0)
+ self.assertEqual(move6_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move6_valuation_aml.quantity, 10)
+ self.assertEqual(move6_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
self.assertEqual(len(output_aml), 3)
@@ -457,7 +481,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move1.product_uom_qty, 12)
self.assertEqual(move1.price_unit, 10.0)
self.assertEqual(move1.remaining_qty, 0)
- self.assertEqual(move1.value, 100)
+ self.assertEqual(move1.value, 120)
self.assertEqual(move1.remaining_value, 0)
self.assertEqual(move2.product_uom_qty, 10.0)
self.assertEqual(move2.price_unit, 8.0)
@@ -495,6 +519,9 @@ class TestStockValuation(TransactionCase):
vacuum_valuation_aml = valuation_aml[-1]
self.assertEqual(len(valuation_aml), 8)
self.assertEqual(vacuum_valuation_aml.balance, -40)
+ self.assertEqual(vacuum_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(vacuum_valuation_aml.quantity, 0)
+ self.assertEqual(vacuum_valuation_aml.product_uom_id.id, self.uom_unit.id)
output_aml = self._get_stock_output_move_lines()
vacuum_output_aml = output_aml[-1]
@@ -505,7 +532,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move1.product_uom_qty, 12)
self.assertEqual(move1.price_unit, 10.0)
self.assertEqual(move1.remaining_qty, 0)
- self.assertEqual(move1.value, 100)
+ self.assertEqual(move1.value, 120)
self.assertEqual(move1.remaining_value, 0)
self.assertEqual(move2.product_uom_qty, 10.0)
self.assertEqual(move2.price_unit, 8.0)
@@ -522,7 +549,11 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move4.remaining_value, 0)
self.assertEqual(move5.product_uom_qty, 20.0)
self.assertEqual(move5.remaining_qty, 0.0)
- self.assertEqual(move5.value, -160.0)
+
+ # move5 sent 10@8 and 10@estimated price of 8
+ # the vacuum compensated the 10@8 by 12@10
+ # -(10*8 + 10@12) = -200
+ self.assertEqual(move5.value, -200.0)
self.assertEqual(move5.remaining_value, 0.0)
self.assertEqual(move6.product_uom_qty, 10)
self.assertEqual(move6.price_unit, 12.0)
@@ -553,7 +584,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move6.product_uom_qty, 8)
self.assertEqual(move6.price_unit, 12)
self.assertEqual(move6.remaining_qty, -2)
- self.assertEqual(move6.value, 120)
+ self.assertEqual(move6.value, 96) # move6 is now 8@12
self.assertEqual(move6.remaining_value, -24)
# account values for move1
@@ -566,6 +597,9 @@ class TestStockValuation(TransactionCase):
move6_correction_valuation_aml = valuation_aml[-1]
self.assertEqual(move6_correction_valuation_aml.debit, 0)
self.assertEqual(move6_correction_valuation_aml.credit, 24)
+ self.assertEqual(move6_correction_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move6_correction_valuation_aml.quantity, -2)
+ self.assertEqual(move6_correction_valuation_aml.product_uom_id.id, self.uom_unit.id)
# link between stock move and account move
self.assertEqual(len(move6.account_move_ids), 2)
@@ -607,6 +641,9 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 10)
self.assertEqual(move7_valuation_aml.debit, 60)
self.assertEqual(move7_valuation_aml.credit, 0)
+ self.assertEqual(move7_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move7_valuation_aml.quantity, 4)
+ self.assertEqual(move7_valuation_aml.product_uom_id.id, self.uom_unit.id)
# link between stock move and account move
self.assertEqual(len(move7.account_move_ids), 1)
@@ -629,12 +666,15 @@ class TestStockValuation(TransactionCase):
self.assertEqual(len(valuation_aml), 11)
self.assertEqual(move6_correction2_valuation_aml.debit, 0)
self.assertEqual(move6_correction2_valuation_aml.credit, 6)
+ self.assertEqual(move6_correction2_valuation_aml.product_id.id, self.product1.id)
+ self.assertEqual(move6_correction2_valuation_aml.quantity, 0)
+ self.assertEqual(move6_correction_valuation_aml.product_uom_id.id, self.uom_unit.id)
# stock_account values
self.assertEqual(move1.product_uom_qty, 12)
self.assertEqual(move1.price_unit, 10.0)
self.assertEqual(move1.remaining_qty, 0)
- self.assertEqual(move1.value, 100)
+ self.assertEqual(move1.value, 120)
self.assertEqual(move1.remaining_value, 0)
self.assertEqual(move2.product_uom_qty, 10.0)
self.assertEqual(move2.price_unit, 8.0)
@@ -651,12 +691,12 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move4.remaining_value, 0)
self.assertEqual(move5.product_uom_qty, 20.0)
self.assertEqual(move5.remaining_qty, 0.0)
- self.assertEqual(move5.value, -160.0)
+ self.assertEqual(move5.value, -200.0)
self.assertEqual(move5.remaining_value, 0.0)
self.assertEqual(move6.product_uom_qty, 8)
self.assertEqual(move6.price_unit, 12.0)
self.assertEqual(move6.remaining_qty, 0.0)
- self.assertEqual(move6.value, 120)
+ self.assertEqual(move6.value, 90)
self.assertEqual(move6.remaining_value, 0)
self.assertEqual(move7.product_uom_qty, 4.0)
self.assertEqual(move7.price_unit, 15.0)
@@ -681,14 +721,28 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# Ending
# ---------------------------------------------------------------------
+ # check on remaining_qty
self.assertEqual(self.product1.qty_available, 2)
+ # check on remaining_value
self.assertEqual(self.product1.stock_value, 30)
+ # check on accounting entries
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('debit')), 30)
self.assertEqual(sum(self._get_stock_input_move_lines().mapped('credit')), 380)
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 380)
self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 350)
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('debit')), 320)
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
+ moves = move1 + move2 + move3 + move4 + move5 + move6 + move7
+ # check on value
+ self.assertEqual(sum(moves.mapped('value')), 30)
+ # check on product_qty
+ qty = 0
+ for move in moves:
+ if move._is_in():
+ qty += move.product_qty
+ else:
+ qty -= move.product_qty
+ self.assertEqual(qty, 2)
def test_fifo_perpetual_2(self):
# http://accountingexplained.com/financial/inventories/fifo-method
@@ -1224,8 +1278,8 @@ class TestStockValuation(TransactionCase):
self.env['stock.move']._run_fifo_vacuum()
# stock values for move1 and move2
- self.assertEqual(move1.value, -400.0)
- self.assertEqual(move1.remaining_value, 200.0)
+ self.assertEqual(move1.value, -680.0) # 40@15 + 10@8
+ self.assertEqual(move1.remaining_value, -80.0)
self.assertEqual(move1.remaining_qty, -10.0)
self.assertEqual(move2.value, 600.0)
self.assertEqual(move2.remaining_value, 0.0)
@@ -1235,14 +1289,13 @@ class TestStockValuation(TransactionCase):
valuation_aml = self._get_stock_valuation_move_lines()
vacuum1_valuation_aml = valuation_aml[-1]
self.assertEqual(vacuum1_valuation_aml.debit, 0)
- # 200 was credited more in valuation (we initially credited 400 but the vacuum realized
- # that 600 was the right value)
- self.assertEqual(vacuum1_valuation_aml.credit, 200)
+ # 280 was credited more in valuation (we compensated 40 items here, so initially 40 were
+ # valued at 8 -> 320 in credit but now we actually sent 40@15 = 600, so the difference is
+ # 280 more credited)
+ self.assertEqual(vacuum1_valuation_aml.credit, 280)
output_aml = self._get_stock_output_move_lines()
vacuum1_output_aml = output_aml[-1]
- # 200 was debited more in output (we initially debited 400 but the vacuum realized
- # that 600 was the right value)
- self.assertEqual(vacuum1_output_aml.debit, 200)
+ self.assertEqual(vacuum1_output_aml.debit, 280)
self.assertEqual(vacuum1_output_aml.credit, 0)
self.assertTrue(set(move1.mapped('account_move_ids.line_ids').ids) == {move1_valuation_aml.id, move1_output_aml.id, vacuum1_valuation_aml.id, vacuum1_output_aml.id})
@@ -1290,7 +1343,7 @@ class TestStockValuation(TransactionCase):
self.env['stock.move']._run_fifo_vacuum()
# stock values for move1-3
- self.assertEqual(move1.value, -400.0)
+ self.assertEqual(move1.value, -850.0) # 40@15 + 10@25
self.assertEqual(move1.remaining_value, 0.0)
self.assertEqual(move1.remaining_qty, 0.0)
self.assertEqual(move2.value, 600.0)
@@ -1304,14 +1357,11 @@ class TestStockValuation(TransactionCase):
valuation_aml = self._get_stock_valuation_move_lines()
vacuum2_valuation_aml = valuation_aml[-1]
self.assertEqual(vacuum2_valuation_aml.debit, 0)
- # 250 was credited more in valuation (we initially credited 400+200 but the vacuum realized
- # that 850 was the right value)
- self.assertEqual(vacuum2_valuation_aml.credit, 250)
+ # there is still 10@8 to compensate with 10@25 -> 170 to credit more in the valuation account
+ self.assertEqual(vacuum2_valuation_aml.credit, 170)
output_aml = self._get_stock_output_move_lines()
vacuum2_output_aml = output_aml[-1]
- # 250 was debited more in output (we initially debited 400+200 but the vacuum realized
- # that 850 was the right value)
- self.assertEqual(vacuum2_output_aml.debit, 250)
+ self.assertEqual(vacuum2_output_aml.debit, 170)
self.assertEqual(vacuum2_output_aml.credit, 0)
self.assertTrue(set(move1.mapped('account_move_ids.line_ids').ids) == {move1_valuation_aml.id, move1_output_aml.id, vacuum1_valuation_aml.id, vacuum1_output_aml.id, vacuum2_valuation_aml.id, vacuum2_output_aml.id})
@@ -1655,6 +1705,18 @@ class TestStockValuation(TransactionCase):
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
def test_fifo_add_move_in_done_picking_1(self):
+ """ The flow is:
+
+ product2 std price = 20
+ IN01 10@10 product1
+ IN01 10@20 product2
+ IN01 correction 10@20 -> 11@20 (product2)
+ DO01 11 product2
+ DO02 1 product2
+ DO02 correction 1 -> 2 (negative stock)
+ IN03 2@30 product2
+ vacuum
+ """
self.product1.product_tmpl_id.cost_method = 'fifo'
# ---------------------------------------------------------------------
@@ -1725,16 +1787,21 @@ class TestStockValuation(TransactionCase):
self.assertEqual(self.product2.qty_available, 10)
self.assertEqual(self.product2.stock_value, 200)
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 300)
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 0)
+
# ---------------------------------------------------------------------
# Edit the previous stock move, receive 11
# ---------------------------------------------------------------------
move2.quantity_done = 11
- self.assertEqual(move2.value, 200.0)
+ self.assertEqual(move2.value, 220.0) # after correction, the move should be valued at 11@20
self.assertEqual(move2.remaining_qty, 11.0)
self.assertEqual(move2.price_unit, 20.0)
self.assertEqual(move2.remaining_value, 220.0)
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 320)
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 0)
# ---------------------------------------------------------------------
# Send 11 product 2
# ---------------------------------------------------------------------
@@ -1768,9 +1835,13 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move3.remaining_qty, 0.0)
self.assertEqual(move3.price_unit, -20.0)
self.assertEqual(move3.remaining_value, 0.0)
+ self.assertEqual(self.product2.qty_available, 0)
+
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 320)
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 220)
# ---------------------------------------------------------------------
- # Add one move of product 2
+ # Add one move of product 2, this'll make some negative stock.
# ---------------------------------------------------------------------
move4 = self.env['stock.move'].create({
'picking_id': delivery.id,
@@ -1794,12 +1865,18 @@ class TestStockValuation(TransactionCase):
self.assertEqual(move4.price_unit, -20.0)
self.assertEqual(move4.remaining_value, -20.0)
+ self.assertEqual(self.product2.qty_available, -1)
+
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 320)
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 240)
+
# ---------------------------------------------------------------------
# edit the created move, add 1
# ---------------------------------------------------------------------
move4.quantity_done = 2
- self.assertEqual(move4.value, -20.0)
+ self.assertEqual(self.product2.qty_available, -2)
+ self.assertEqual(move4.value, -40.0)
self.assertEqual(move4.remaining_qty, -2.0)
self.assertEqual(move4.price_unit, -20.0)
self.assertEqual(move4.remaining_value, -40.0)
@@ -1823,7 +1900,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
# receive 2 products 2 @ 30
# ---------------------------------------------------------------------
- move1 = self.env['stock.move'].create({
+ move5 = self.env['stock.move'].create({
'picking_id': receipt.id,
'name': '10 in',
'location_id': self.supplier_location.id,
@@ -1840,8 +1917,11 @@ class TestStockValuation(TransactionCase):
'qty_done': 2.0,
})]
})
- move1._action_confirm()
- move1._action_done()
+ move5._action_confirm()
+ move5._action_done()
+
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('debit')), 380)
+ self.assertEqual(sum(self._get_stock_valuation_move_lines().mapped('credit')), 260)
# ---------------------------------------------------------------------
# run vacuum
@@ -1858,6 +1938,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(self.product2.qty_available, 0)
self.assertEqual(self.product2.stock_value, 0)
self.assertEqual(move4.remaining_value, 0)
+ self.assertEqual(move4.value, -60) # after correction, the move is valued -(2*30)
def test_fifo_add_moveline_in_done_move_1(self):
self.product1.product_tmpl_id.cost_method = 'fifo'
@@ -1921,7 +2002,7 @@ class TestStockValuation(TransactionCase):
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
def test_fifo_edit_done_move1(self):
- """ Check that incrementing the done quantity will correctly re-run a fifo lookup.
+ """ Increase OUT done move while quantities are available.
"""
self.product1.product_tmpl_id.cost_method = 'fifo'
@@ -2059,6 +2140,9 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
move3.quantity_done = 14
self.assertEqual(move3.product_qty, 14)
+ # old value: -80 -(8@10)
+ # new value: -148 => -(10@10 + 4@12)
+ self.assertEqual(move3.value, -148)
# older move
self.assertEqual(move1.remaining_value, 0) # before, 20
@@ -2090,6 +2174,8 @@ class TestStockValuation(TransactionCase):
self.assertEqual(sum(self._get_stock_output_move_lines().mapped('credit')), 0)
def test_fifo_edit_done_move2(self):
+ """ Decrease, then increase OUT done move while quantities are available.
+ """
self.product1.product_tmpl_id.cost_method = 'fifo'
# ---------------------------------------------------------------------
@@ -2152,7 +2238,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
move2.quantity_done = 8
- self.assertEqual(move2.value, -100.0)
+ self.assertEqual(move2.value, -80.0) # the move actually sent 8@10
self.assertEqual(move2.remaining_qty, 0.0)
self.assertEqual(move2.remaining_value, 0.0)
@@ -2167,7 +2253,7 @@ class TestStockValuation(TransactionCase):
# ---------------------------------------------------------------------
move2.with_context(debug=True).quantity_done = 10
- self.assertEqual(move2.value, -100.0)
+ self.assertEqual(move2.value, -100.0) # the move actually sent 10@10
self.assertEqual(move2.remaining_qty, 0.0)
self.assertEqual(move2.remaining_value, 0.0)
@@ -3002,3 +3088,479 @@ class TestStockValuation(TransactionCase):
with self.assertRaises(UserError):
move2._action_done()
+ def test_at_date_standard_1(self):
+ self.product1.product_tmpl_id.cost_method = 'standard'
+
+ now = Date.from_string(Date.today())
+ date1 = now - timedelta(days=8)
+ date2 = now - timedelta(days=7)
+ date3 = now - timedelta(days=6)
+ date4 = now - timedelta(days=5)
+ date5 = now - timedelta(days=4)
+ date6 = now - timedelta(days=3)
+ date7 = now - timedelta(days=2)
+ date8 = now - timedelta(days=1)
+
+ # set the standard price to 10
+ self.product1.product_tmpl_id.standard_price = 10
+ self.env['product.price.history'].search([('product_id', '=', self.product1.id)], order='datetime desc, id DESC', limit=1).datetime = date1
+
+ # receive 10
+ move1 = self.env['stock.move'].create({
+ 'name': 'in 10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10,
+ })
+ move1._action_confirm()
+ move1._action_assign()
+ move1.move_line_ids.qty_done = 10
+ move1._action_done()
+ move1.date = date2
+
+ self.assertEqual(self.product1.qty_available, 10)
+ self.assertEqual(self.product1.stock_value, 100)
+
+ # receive 20
+ move2 = self.env['stock.move'].create({
+ 'name': 'in 10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 20,
+ })
+ move2._action_confirm()
+ move2._action_assign()
+ move2.move_line_ids.qty_done = 20
+ move2._action_done()
+ move2.date = date3
+
+ self.assertEqual(self.product1.qty_available, 30)
+ self.assertEqual(self.product1.stock_value, 300)
+
+ # send 15
+ move3 = self.env['stock.move'].create({
+ 'name': 'out 10',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 15,
+ })
+ move3._action_confirm()
+ move3._action_assign()
+ move3.move_line_ids.qty_done = 15
+ move3._action_done()
+ move3.date = date4
+
+ self.assertEqual(self.product1.qty_available, 15)
+ self.assertEqual(self.product1.stock_value, 150)
+
+ # set the standard price to 5
+ self.product1.product_tmpl_id.standard_price = 5
+ self.env['product.price.history'].search([('product_id', '=', self.product1.id)], order='datetime desc, id DESC', limit=1).datetime = date5
+
+ self.assertEqual(self.product1.qty_available, 15)
+ self.assertEqual(self.product1.stock_value, 75)
+
+ # send 20
+ move4 = self.env['stock.move'].create({
+ 'name': 'out 10',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 20,
+ })
+ move4._action_confirm()
+ move4._action_assign()
+ move4.move_line_ids.qty_done = 20
+ move4._action_done()
+ move4.date = date6
+
+ self.assertEqual(self.product1.qty_available, -5)
+ self.assertEqual(self.product1.stock_value, -25)
+
+ # set the standard price to 7.5
+ self.product1.product_tmpl_id.standard_price = 7.5
+ self.env['product.price.history'].search([('product_id', '=', self.product1.id)], order='datetime desc, id DESC', limit=1).datetime = date7
+
+ # receive 100
+ move5 = self.env['stock.move'].create({
+ 'name': 'in 10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 100,
+ })
+ move5._action_confirm()
+ move5._action_assign()
+ move5.move_line_ids.qty_done = 100
+ move5._action_done()
+ move5.date = date8
+
+ self.assertEqual(self.product1.qty_available, 95)
+ self.assertEqual(self.product1.stock_value, 712.5)
+
+ # Quantity at date
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_available, 0)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_available, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).qty_available, 30)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).qty_available, 15)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).qty_available, 15)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_available, -5)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date7)).qty_available, -5)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date8)).qty_available, 95)
+
+ # Valuation at date
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).stock_value, 100)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).stock_value, 300)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).stock_value, 150)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).stock_value, 75)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, -25)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date8)).stock_value, 712.5)
+
+ # edit the done quantity of move1, decrease it
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_available, 10)
+ move1.quantity_done = 5
+
+ # the quantity at date will reflect the change directly
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_available, 5)
+
+ # as when we decrease a quantity on a recreipt, we consider it as a out move with the price
+ # of today, the value will be decrease of 100 - (5*7.5)
+ self.assertEqual(move1.value, 62.5)
+
+ # the valuatin at date will take the qty at date * the standard price at date, that's why
+ # it is different.
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).stock_value, 50)
+
+ # edit move 4, send 15 instead of 20
+ # we now have +5 + 20 - 15 -20 = -10 * a standard price of 5
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, -50)
+ move4.quantity_done = 15
+
+ # -(20*5) + (5*7.5)
+ self.assertEqual(move4.value, -62.5)
+ # we now have +5 + 20 - 15 -15 = -5 * a standard price of 5
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, -25)
+
+ def test_at_date_fifo_1(self):
+ """ Make some operations at different dates, check that the results of the valuation at
+ date wizard are consistent. Afterwards, edit the done quantity of some operations. The
+ valuation at date results should take these changes into account.
+ """
+ self.product1.product_tmpl_id.cost_method = 'fifo'
+
+ now = Date.from_string(Date.today())
+ date1 = now - timedelta(days=8)
+ date2 = now - timedelta(days=7)
+ date3 = now - timedelta(days=6)
+ date4 = now - timedelta(days=5)
+ date5 = now - timedelta(days=4)
+ date6 = now - timedelta(days=3)
+
+ # receive 10@10
+ move1 = self.env['stock.move'].create({
+ 'name': 'in 10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10,
+ 'price_unit': 10,
+ })
+ move1._action_confirm()
+ move1._action_assign()
+ move1.move_line_ids.qty_done = 10
+ move1._action_done()
+ move1.date = date1
+ move1.account_move_ids.write({'date': date1})
+
+ self.assertEqual(self.product1.qty_available, 10)
+ self.assertEqual(self.product1.stock_value, 100)
+
+ # receive 10@12
+ move2 = self.env['stock.move'].create({
+ 'name': 'in 10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10,
+ 'price_unit': 12,
+ })
+ move2._action_confirm()
+ move2._action_assign()
+ move2.move_line_ids.qty_done = 10
+ move2._action_done()
+ move2.date = date2
+ move2.account_move_ids.write({'date': date2})
+
+ self.assertEqual(self.product1.qty_available, 20)
+ self.assertEqual(self.product1.stock_value, 220)
+
+ # send 15
+ move3 = self.env['stock.move'].create({
+ 'name': 'out 10',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 15,
+ })
+ move3._action_confirm()
+ move3._action_assign()
+ move3.move_line_ids.qty_done = 15
+ move3._action_done()
+ move3.date = date3
+ move3.account_move_ids.write({'date': date3})
+
+ self.assertEqual(self.product1.qty_available, 5)
+ self.assertEqual(self.product1.stock_value, 60)
+
+ # send 20
+ move4 = self.env['stock.move'].create({
+ 'name': 'out 10',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 20,
+ })
+ move4._action_confirm()
+ move4._action_assign()
+ move4.move_line_ids.qty_done = 20
+ move4._action_done()
+ move4.date = date4
+ move4.account_move_ids.write({'date': date4})
+
+ self.assertEqual(self.product1.qty_available, -15)
+ self.assertEqual(self.product1.stock_value, -180)
+
+ # receive 100@15
+ move5 = self.env['stock.move'].create({
+ 'name': 'in 10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 100,
+ 'price_unit': 15,
+ })
+ move5._action_confirm()
+ move5._action_assign()
+ move5.move_line_ids.qty_done = 100
+ move5._action_done()
+ move5.date = date5
+ move5.account_move_ids.write({'date': date5})
+
+ self.assertEqual(self.product1.qty_available, 85)
+ self.assertEqual(self.product1.stock_value, 1320)
+
+ # run the vacuum to compensate the negative stock move
+ self.env['stock.move']._run_fifo_vacuum()
+ move4.account_move_ids[0].write({'date': date6})
+
+ self.assertEqual(self.product1.qty_available, 85)
+ self.assertEqual(self.product1.stock_value, 1275)
+
+ # Edit the quantity done of move1, increase it.
+ move1.quantity_done = 20
+
+ # ---------------------------------------------------------------------
+ # ending: manual valuation
+ # ---------------------------------------------------------------------
+ self.product1.product_tmpl_id.valuation = 'manual_periodic'
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_at_date, 20)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).stock_value, 200)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 30)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).stock_value, 320)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).qty_at_date, 15)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).stock_value, 160)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).qty_at_date, -5)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).stock_value, -125)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).qty_at_date, 95)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).stock_value, 1375)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_at_date, 95)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, 1375)
+ self.assertEqual(self.product1.qty_at_date, 95)
+ self.assertEqual(self.product1.stock_value, 1375)
+
+ # ---------------------------------------------------------------------
+ # ending: perpetual valuation
+ # ---------------------------------------------------------------------
+ self.product1.product_tmpl_id.valuation = 'real_time'
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).stock_value, 100)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 20)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).stock_value, 220)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).qty_at_date, 5)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).stock_value, 60)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).qty_at_date, -15)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).stock_value, -180)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).qty_at_date, 85)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).stock_value, 1320)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_at_date, 85)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, 1275)
+ self.assertEqual(self.product1.qty_at_date, 95)
+ self.assertEqual(self.product1.stock_value, 1375)
+
+ def test_at_date_fifo_2(self):
+ self.product1.product_tmpl_id.cost_method = 'fifo'
+
+ now = Date.from_string(Date.today())
+ date1 = now - timedelta(days=8)
+ date2 = now - timedelta(days=7)
+ date3 = now - timedelta(days=6)
+ date4 = now - timedelta(days=5)
+ date5 = now - timedelta(days=4)
+ date6 = now - timedelta(days=3)
+
+ # receive 10@10
+ move1 = self.env['stock.move'].create({
+ 'name': 'in 10@10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10,
+ 'price_unit': 10,
+ })
+ move1._action_confirm()
+ move1._action_assign()
+ move1.move_line_ids.qty_done = 10
+ move1._action_done()
+ move1.date = date1
+ move1.account_move_ids.write({'date': date1})
+
+ self.assertEqual(self.product1.qty_available, 10)
+ self.assertEqual(self.product1.stock_value, 100)
+
+ # receive 10@15
+ move2 = self.env['stock.move'].create({
+ 'name': 'in 10@15',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10,
+ 'price_unit': 15,
+ })
+ move2._action_confirm()
+ move2._action_assign()
+ move2.move_line_ids.qty_done = 10
+ move2._action_done()
+ move2.date = date2
+ move2.account_move_ids.write({'date': date2})
+
+ self.assertEqual(self.product1.qty_available, 20)
+ self.assertEqual(self.product1.stock_value, 250)
+
+ # send 30
+ move3 = self.env['stock.move'].create({
+ 'name': 'out 30',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.customer_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 30,
+ })
+ move3._action_confirm()
+ move3._action_assign()
+ move3.move_line_ids.qty_done = 30
+ move3._action_done()
+ move3.date = date3
+ move3.account_move_ids.write({'date': date3})
+
+ self.assertEqual(self.product1.qty_available, -10)
+ self.assertEqual(self.product1.stock_value, -150)
+
+ # receive 10@20
+ move4 = self.env['stock.move'].create({
+ 'name': 'in 10@20',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10,
+ 'price_unit': 20,
+ })
+ move4._action_confirm()
+ move4._action_assign()
+ move4.move_line_ids.qty_done = 10
+ move4._action_done()
+ move4.date = date4
+ move4.account_move_ids.write({'date': date4})
+
+ self.assertEqual(self.product1.qty_available, 0)
+ self.assertEqual(self.product1.stock_value, 50)
+
+ # receive 10@10
+ move5 = self.env['stock.move'].create({
+ 'name': 'in 10@10',
+ 'location_id': self.supplier_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10,
+ 'price_unit': 10,
+ })
+ move5._action_confirm()
+ move5._action_assign()
+ move5.move_line_ids.qty_done = 10
+ move5._action_done()
+ move5.date = date5
+ move5.account_move_ids.write({'date': date5})
+
+ self.assertEqual(self.product1.qty_available, 10)
+ self.assertEqual(self.product1.stock_value, 150)
+
+ # run the vacuum to compensate the negative stock move
+ self.env['stock.move']._run_fifo_vacuum()
+ move3.account_move_ids[0].write({'date': date6})
+
+ self.assertEqual(self.product1.qty_available, 10)
+ self.assertEqual(self.product1.stock_value, 100)
+
+ # ---------------------------------------------------------------------
+ # ending: manual valuation
+ # ---------------------------------------------------------------------
+ self.product1.product_tmpl_id.valuation = 'manual_periodic'
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).stock_value, 100)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 20)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).stock_value, 250)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).qty_at_date, -10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).stock_value, -200)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).qty_at_date, 0)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).stock_value, 0)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).stock_value, 100)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, 100)
+ self.assertEqual(self.product1.qty_at_date, 10)
+ self.assertEqual(self.product1.stock_value, 100)
+
+ # ---------------------------------------------------------------------
+ # ending: perpetual valuation
+ # ---------------------------------------------------------------------
+ self.product1.product_tmpl_id.valuation = 'real_time'
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).stock_value, 100)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 20)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).stock_value, 250)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).qty_at_date, -10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date3)).stock_value, -150)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).qty_at_date, 0)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date4)).stock_value, 50)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date5)).stock_value, 150)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date6)).stock_value, 100)
+ self.assertEqual(self.product1.qty_at_date, 10)
+ self.assertEqual(self.product1.stock_value, 100)
diff --git a/addons/stock_account/views/product_views.xml b/addons/stock_account/views/product_views.xml
index 6b92f62cf4b..db9bd7f3735 100644
--- a/addons/stock_account/views/product_views.xml
+++ b/addons/stock_account/views/product_views.xml
@@ -86,27 +86,14 @@
</data>
</field>
</record>
-
- <record id="product_valuation_tree" model="ir.ui.view">
- <field name="name">product.valuation.tree</field>
- <field name="model">product.product</field>
- <field name="arch" type="xml">
- <tree>
- <field name="display_name" string="Product"/>
- <field name="qty_available" context="{'company_owned': True}" string="Quantity on Hand"/>
- <field name="uom_id" groups="product.group_uom"/>
- <field name="currency_id" invisible="1"/>
- <field name="stock_value" sum="Stock Valuation" widget="monetary" string="Total Value"/>
- </tree>
- </field>
- </record>
+
<record id="product_valuation_action" model="ir.actions.act_window">
<field name="name">Product Valuation</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.product</field>
<field name="view_mode">tree,form</field>
<field name="view_type">form</field>
- <field name="view_id" ref="product_valuation_tree"/>
+ <field name="view_id" ref="view_stock_product_tree2"/>
<field name="domain">[('type', '=', 'product'), ('qty_available', '!=', 0)]</field>
<field name="context">{}</field>
<field name="help" type="html">
@@ -117,68 +104,5 @@
</p>
</field>
</record>
-
- <record id="product_valuation_form_view" model="ir.ui.view">
- <field name="name">product.product</field>
- <field name="model">product.product</field>
- <field name="inherit_id" ref="stock.product_form_view_procurement_button"/>
- <field name="arch" type="xml">
- <xpath expr="//button[@name='action_view_stock_move_lines']" position="after">
- <button string="Inventory Valuation" type="object" name="action_open_product_moves" class="oe_stat_button" icon="fa-cubes" attrs="{'invisible': ['|', ('cost_method', '=', 'standard'), ('id', '=', False)]}"/>
- </xpath>
- </field>
- </record>
-
- <record id="product_template_valuation_form_view" model="ir.ui.view">
- <field name="name">product.template</field>
- <field name="model">product.template</field>
- <field name="inherit_id" ref="stock.product_template_form_view_procurement_button"/>
- <field name="arch" type="xml">
- <xpath expr="//button[@name='action_view_stock_move_lines']" position="after">
- <button string="Inventory Valuation" type="object" name="action_open_product_moves" class="oe_stat_button" icon="fa-cubes" attrs="{'invisible': [('cost_method', '=', 'standard')]}"/>
- </xpath>
- </field>
- </record>
-
- <!-- stock move valuation view -->
- <record id="view_move_tree_valuation" model="ir.ui.view">
- <field name="name">stock.move.tree.valuation</field>
- <field name="model">stock.move</field>
- <field eval="8" name="priority"/>
- <field name="arch" type="xml">
- <tree decoration-muted="state == 'cancel'" decoration-danger="(state not in ('cancel','done')) and date > current_date" string="Moves" create="0">
- <field name="name"/>
- <field name="picking_id" string="Reference"/>
- <field name="origin"/>
- <field name="picking_type_id" invisible="1"/>
- <field name="create_date" invisible="1" groups="base.group_no_one"/>
- <field name="product_id"/>
- <field name="location_id" groups="stock.group_stock_multi_locations"/>
- <field name="location_dest_id" groups="stock.group_stock_multi_locations"/>
- <field name="date" groups="base.group_no_one"/>
- <field name="state" invisible="1"/>
- <field name="product_uom_qty" string="Qty"/>
- <field name="product_uom" options="{'no_open': True, 'no_create': True}" string="Unit of Measure" groups="product.group_uom"/>
- <field name="price_unit"/>
- <field name="value" sum="Stock Valuation"/>
- <field name="remaining_qty" invisible="context.get('is_avg')"/>
- <field name="remaining_value" sum="Stock Valuation" invisible="context.get('is_avg')"/>
- </tree>
- </field>
- </record>
- <record id="stock_move_valuation_action" model="ir.actions.act_window">
- <field name="name">Stock Moves</field>
- <field name="res_model">stock.move</field>
- <field name="type">ir.actions.act_window</field>
- <field name="view_type">form</field>
- <field name="view_id" ref="view_move_tree_valuation"/>
- <field name="search_view_id" ref="stock.view_move_search"/>
- <field name="context">{'search_default_outgoing': 1, 'search_default_incoming': 1, 'search_default_done': 1, 'search_default_group_by_product': 1}</field>
- <field name="help" type="html">
- <p class="o_view_nocontent_smiling_face">
- Create a new stock movement
- </p>
- </field>
- </record>
- </data>
+ </data>
</odoo>
diff --git a/addons/stock_account/views/stock_account_views.xml b/addons/stock_account/views/stock_account_views.xml
index 70c1d04e9da..656d6ea7364 100644
--- a/addons/stock_account/views/stock_account_views.xml
+++ b/addons/stock_account/views/stock_account_views.xml
@@ -44,11 +44,87 @@
<field name="model">stock.return.picking</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='product_return_moves']/tree" position="inside">
- <field name="to_refund"/>
+ <field name="to_refund" widget="boolean_toggle"/>
</xpath>
</field>
</record>
- <menuitem id="menu_valuation" name="Inventory Valuation" parent="stock.menu_warehouse_report" sequence="110" action="stock_account.action_stock_account_valuation_report"/>
+ <!-- valuation wizard: current or at date -->
+ <record id="view_stock_quantity_history" model="ir.ui.view">
+ <field name="name">Valuation Report</field>
+ <field name="model">stock.quantity.history</field>
+ <field name="arch" type="xml">
+ <form string="Choose your date">
+ <group>
+ <group>
+ <field name="compute_at_date" widget="radio"/>
+ <field name="date" attrs="{'invisible': [('compute_at_date', '=', 0)]}"/>
+ </group>
+ </group>
+ <footer>
+ <button name="open_table" string="Retrieve the inventory valuation" type="object" class="btn-primary"/>
+ <button string="Cancel" class="btn-default" special="cancel" />
+ </footer>
+ </form>
+ </field>
+ </record>
+ <record id="view_stock_product_tree2" model="ir.ui.view">
+ <field name="name">product.stock.tree.2</field>
+ <field name="model">product.product</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="name"/>
+ <field name="qty_at_date"/>
+ <field name="uom_id" groups="product.group_uom"/>
+ <field name="currency_id" invisible="1"/>
+ <field name="stock_value" sum="Stock Valuation" widget="monetary"/>
+ <field name="cost_method" invisible="1"/>
+ <button name="action_valuation_at_date_details" type="object" icon="fa-info-circle" attrs="{'invisible': [('cost_method', '!=', 'fifo')]}" />
+ </tree>
+ </field>
+ </record>
+ <record id="action_stock_inventory_valuation" model="ir.actions.act_window">
+ <field name="name">Valuation Report</field>
+ <field name="res_model">stock.quantity.history</field>
+ <field name="view_type">form</field>
+ <field name="view_mode">form</field>
+ <field name="view_id" ref="stock_account.view_stock_quantity_history"/>
+ <field name="target">new</field>
+ <field name="context">{'default_compute_at_date': 0, 'valuation': True}</field>
+ </record>
+ <menuitem id="menu_valuation" name="Inventory Valuation" parent="stock.menu_warehouse_report" sequence="110" action="action_stock_inventory_valuation"/>
+
+ <!-- AML specialized tree view -->
+ <record id="view_stock_account_aml" model="ir.ui.view">
+ <field name="name">stock.account.aml</field>
+ <field name="model">account.move.line</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="date" />
+ <field name="ref" />
+ <field name="product_id" />
+ <field name="quantity" />
+ <field name="product_uom_id" groups="product.group_uom" />
+ <field name="balance" string="Value"/>
+ </tree>
+ </field>
+ </record>
+
+ <!-- stock move specialized tree view -->
+ <record id="view_move_tree_valuation_at_date" model="ir.ui.view">
+ <field name="name">stock.move.tree.valuation.at.date</field>
+ <field name="model">stock.move</field>
+ <field name="arch" type="xml">
+ <tree>
+ <field name="date" />
+ <field name="picking_id" string="Reference"/>
+ <field name="state" invisible="1"/>
+ <field name="product_id"/>
+ <field name="product_uom_qty" string="Quantity"/>
+ <field name="product_uom" options="{'no_open': True, 'no_create': True}" string="Unit of Measure" groups="product.group_uom"/>
+ <field name="value" sum="Stock Valuation"/>
+ </tree>
+ </field>
+ </record>
</data>
</odoo>
diff --git a/addons/stock_account/wizard/__init__.py b/addons/stock_account/wizard/__init__.py
index 3fbd834da9f..01b730d1fe4 100644
--- a/addons/stock_account/wizard/__init__.py
+++ b/addons/stock_account/wizard/__init__.py
@@ -2,4 +2,5 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import stock_change_standard_price
+from . import stock_quantity_history
diff --git a/addons/stock_account/wizard/stock_quantity_history.py b/addons/stock_account/wizard/stock_quantity_history.py
new file mode 100644
index 00000000000..6b244d13ac2
--- /dev/null
+++ b/addons/stock_account/wizard/stock_quantity_history.py
@@ -0,0 +1,32 @@
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import models, _
+
+
+class StockQuantityHistory(models.TransientModel):
+ _inherit = 'stock.quantity.history'
+
+ def open_table(self):
+ if not self.env.context.get('valuation'):
+ return super(StockQuantityHistory, self).open_table()
+
+ self.env['stock.move']._run_fifo_vacuum()
+
+ if self.compute_at_date:
+ tree_view_id = self.env.ref('stock_account.view_stock_product_tree2').id
+ form_view_id = self.env.ref('stock.product_form_view_procurement_button').id
+ # We pass `to_date` in the context so that `qty_available` will be computed across
+ # moves until date.
+ action = {
+ 'type': 'ir.actions.act_window',
+ 'views': [(tree_view_id, 'tree'), (form_view_id, 'form')],
+ 'view_mode': 'tree,form',
+ 'name': _('Products'),
+ 'res_model': 'product.product',
+ 'domain': "[('type', '=', 'product'), ('qty_available', '!=', 0)]",
+ 'context': dict(self.env.context, to_date=self.date),
+ }
+ return action
+ else:
+ return self.env.ref('stock_account.product_valuation_action').read()[0]
+
diff --git a/addons/stock_landed_costs/models/stock_landed_cost.py b/addons/stock_landed_costs/models/stock_landed_cost.py
index a4a73ef79c8..af58b84a0e7 100644
--- a/addons/stock_landed_costs/models/stock_landed_cost.py
+++ b/addons/stock_landed_costs/models/stock_landed_cost.py
@@ -91,11 +91,13 @@ class LandedCost(models.Model):
raise UserError(_('Cost and adjustments lines do not match. You should maybe recompute the landed costs.'))
for cost in self:
- move = self.env['account.move'].create({
+ move = self.env['account.move']
+ move_vals = {
'journal_id': cost.account_journal_id.id,
'date': cost.date,
- 'ref': cost.name
- })
+ 'ref': cost.name,
+ 'line_ids': [],
+ }
for line in cost.valuation_adjustment_lines.filtered(lambda line: line.move_id):
# Prorate the value at what's still in stock
cost_to_add = (line.move_id.remaining_qty / line.move_id.product_qty) * line.additional_landed_cost
@@ -103,6 +105,7 @@ class LandedCost(models.Model):
new_landed_cost_value = line.move_id.landed_cost_value + line.additional_landed_cost
line.move_id.write({
'landed_cost_value': new_landed_cost_value,
+ 'value': line.move_id.value + cost_to_add,
'remaining_value': line.move_id.remaining_value + cost_to_add,
'price_unit': (line.move_id.value + new_landed_cost_value) / line.move_id.product_qty,
})
@@ -113,9 +116,9 @@ class LandedCost(models.Model):
qty_out = line.move_id.product_qty - line.move_id.remaining_qty
elif line.move_id._is_out():
qty_out = line.move_id.product_qty
- line._create_accounting_entries(move, qty_out)
-
- move.assert_balanced()
+ move_vals['line_ids'] += line._create_accounting_entries(move, qty_out)
+
+ move = move.create(move_vals)
cost.write({'state': 'done', 'account_move_id': move.id})
move.post()
return True
@@ -315,13 +318,12 @@ class AdjustmentLines(models.Model):
Generate the account.move.line values to track the landed cost.
Afterwards, for the goods that are already out of stock, we should create the out moves
"""
- AccountMoveLine = self.env['account.move.line'].with_context(check_move_validity=False, recompute=False)
+ AccountMoveLine = []
base_line = {
'name': self.name,
- 'move_id': move.id,
'product_id': self.product_id.id,
- 'quantity': self.quantity,
+ 'quantity': 0,
}
debit_line = dict(base_line, account_id=debit_account_id)
credit_line = dict(base_line, account_id=credit_account_id)
@@ -333,18 +335,18 @@ class AdjustmentLines(models.Model):
# negative cost, reverse the entry
debit_line['credit'] = -diff
credit_line['debit'] = -diff
- AccountMoveLine.create(debit_line)
- AccountMoveLine.create(credit_line)
+ AccountMoveLine.append([0, 0, debit_line])
+ AccountMoveLine.append([0, 0, credit_line])
# Create account move lines for quants already out of stock
if qty_out > 0:
debit_line = dict(base_line,
name=(self.name + ": " + str(qty_out) + _(' already out')),
- quantity=qty_out,
+ quantity=0,
account_id=already_out_account_id)
credit_line = dict(base_line,
name=(self.name + ": " + str(qty_out) + _(' already out')),
- quantity=qty_out,
+ quantity=0,
account_id=debit_account_id)
diff = diff * qty_out / self.quantity
if diff > 0:
@@ -354,18 +356,18 @@ class AdjustmentLines(models.Model):
# negative cost, reverse the entry
debit_line['credit'] = -diff
credit_line['debit'] = -diff
- AccountMoveLine.create(debit_line)
- AccountMoveLine.create(credit_line)
+ AccountMoveLine.append([0, 0, debit_line])
+ AccountMoveLine.append([0, 0, credit_line])
# TDE FIXME: oh dear
if self.env.user.company_id.anglo_saxon_accounting:
debit_line = dict(base_line,
name=(self.name + ": " + str(qty_out) + _(' already out')),
- quantity=qty_out,
+ quantity=0,
account_id=credit_account_id)
credit_line = dict(base_line,
name=(self.name + ": " + str(qty_out) + _(' already out')),
- quantity=qty_out,
+ quantity=0,
account_id=already_out_account_id)
if diff > 0:
@@ -375,7 +377,7 @@ class AdjustmentLines(models.Model):
# negative cost, reverse the entry
debit_line['credit'] = -diff
credit_line['debit'] = -diff
- AccountMoveLine.create(debit_line)
- AccountMoveLine.create(credit_line)
+ AccountMoveLine.append([0, 0, debit_line])
+ AccountMoveLine.append([0, 0, credit_line])
- return True
+ return AccountMoveLine
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index 2fb0521ffb5..fbb6d0e7c6b 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -1028,6 +1028,21 @@ var FieldPhone = FieldEmail.extend({
},
/**
+ * Remove possibly present &shy; characters when saving number
+ *
+ * @override
+ * @private
+ */
+ _setValue: function (value, options) {
+ // NOT NEEDED AS OF SAAS-11.3
+ if (value) {
+ // remove possibly pasted &shy; characters
+ value = value.replace(/\u00AD/g, '');
+ }
+ return this._super(value, options);
+ },
+
+ /**
* Phone fields are clickable in readonly on small screens ~= on phones.
* This can be overriden by call-capable modules to display a clickable
* link in different situations, like always regardless of screen size,
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index 353da62706f..a977147460a 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -1292,12 +1292,27 @@ var FieldOne2Many = FieldX2Many.extend({
// we don't want interference with the components upstream.
ev.stopPropagation();
+ var self = this;
var id = ev.data.id;
- // trigger an empty 'UPDATE' operation when the user clicks on 'Save' in
- // the dialog, to notify the main record that a subrecord of this
- // relational field has changed (those changes will be already stored on
- // that subrecord, thanks to the 'Save').
- var onSaved = this._setValue.bind(this, { operation: 'UPDATE', id: id }, {});
+ var onSaved = function (record, hasChanged) {
+ if (!hasChanged) {
+ return;
+ }
+ if (_.some(self.value.data, {id: record.id})) {
+ // the record already exists in the relation, so trigger an
+ // empty 'UPDATE' operation when the user clicks on 'Save' in
+ // the dialog, to notify the main record that a subrecord of
+ // this relational field has changed (those changes will be
+ // already stored on that subrecord, thanks to the 'Save').
+ self._setValue({ operation: 'UPDATE', id: record.id });
+ } else {
+ // the record isn't in the relation yet, so add it ; this can
+ // happen if the user clicks on 'Save & New' in the dialog (the
+ // opened record will be updated, and other records will be
+ // created)
+ self._setValue({ operation: 'ADD', id: record.id });
+ }
+ };
this._openFormDialog({
id: id,
on_saved: onSaved,
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index 1007aa6c720..ff7ab5a43bb 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -102,6 +102,18 @@ var AbstractController = Widget.extend(ControlPanelMixin, {
}
return this._super.apply(this, arguments);
},
+ /**
+ * Called each time the controller is attached into the DOM.
+ */
+ on_attach_callback: function () {
+ this.renderer.on_attach_callback();
+ },
+ /**
+ * Called each time the controller is detached from the DOM.
+ */
+ on_detach_callback: function () {
+ this.renderer.on_detach_callback();
+ },
//--------------------------------------------------------------------------
// Public
diff --git a/addons/web/static/src/js/views/abstract_renderer.js b/addons/web/static/src/js/views/abstract_renderer.js
index 935fcc6643e..2394fb31a64 100644
--- a/addons/web/static/src/js/views/abstract_renderer.js
+++ b/addons/web/static/src/js/views/abstract_renderer.js
@@ -36,6 +36,14 @@ return Widget.extend({
this.$el.addClass(this.arch.attrs.class);
return $.when(this._render(), this._super());
},
+ /**
+ * Called each time the renderer is attached into the DOM.
+ */
+ on_attach_callback: function () {},
+ /**
+ * Called each time the renderer is detached from the DOM.
+ */
+ on_detach_callback: function () {},
//--------------------------------------------------------------------------
// Public
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index b17562348f7..de9001c328a 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -3167,6 +3167,9 @@ var BasicModel = AbstractModel.extend({
* @param {Object} [options]
* @param {string[]} [options.fieldNames] the fields to fetch for a record
* @param {boolean} [options.onlyGroups=false]
+ * @param {boolean} [options.keepEmptyGroups=false] if set, the groups not
+ * present in the read_group anymore (empty groups) will stay in the
+ * datapoint (used to mimic the kanban renderer behaviour for example)
* @returns {Deferred}
*/
_load: function (dataPoint, options) {
@@ -3319,9 +3322,29 @@ var BasicModel = AbstractModel.extend({
*/
_makeDefaultRecord: function (modelName, params) {
var self = this;
+
+ var determineExtraFields = function() {
+ // Fields that are present in the originating view, that need to be initialized
+ // Hence preventing their value to crash when getting back to the originating view
+ var parentRecord = self.localData[params.parentID];
+
+ var originView = parentRecord && parentRecord.fieldsInfo;
+ if (!originView || !originView[parentRecord.viewType])
+ return [];
+
+ var fieldsFromOrigin = _.filter(Object.keys(originView[parentRecord.viewType]),
+ function(fieldname) {
+ return params.fields[fieldname] !== undefined;
+ });
+
+ return fieldsFromOrigin;
+ }
+
var fieldNames = Object.keys(params.fieldsInfo[params.viewType]);
var fields_key = _.without(fieldNames, '__last_update');
+ var extraFields = determineExtraFields();
+
return this._rpc({
model: modelName,
method: 'default_get',
@@ -3339,7 +3362,7 @@ var BasicModel = AbstractModel.extend({
viewType: params.viewType,
});
- return self.applyDefaultValues(record.id, result)
+ return self.applyDefaultValues(record.id, result, {fieldNames: _.union(fieldNames, extraFields)})
.then(function () {
var def = $.Deferred();
self._performOnChange(record, fields_key).always(function () {
@@ -3603,6 +3626,8 @@ var BasicModel = AbstractModel.extend({
} else if (_.contains(['one2many', 'many2many'], fieldType)) {
var x2mCommands = commands[0][2][fieldName];
defs.push(self._processX2ManyCommands(r, fieldName, x2mCommands));
+ } else {
+ r._changes[fieldName] = self._parseServerValue(field, r._changes[fieldName]);
}
}
}
@@ -3801,6 +3826,16 @@ var BasicModel = AbstractModel.extend({
defs.push(self._load(newGroup, options));
}
});
+ if (options && options.keepEmptyGroups) {
+ // Find the groups that were available in a previous
+ // readGroup but are not there anymore.
+ // Note that these groups are put after existing groups so
+ // the order is not conserved. A sort *might* be useful.
+ var emptyGroupsIDs = _.difference(_.pluck(previousGroups, 'id'), list.data);
+ _.each(emptyGroupsIDs, function (groupID) {
+ list.data.push(groupID);
+ });
+ }
return $.when.apply($, defs).then(function () {
// generate the res_ids of the main list, being the concatenation
// of the fetched res_ids in each group
diff --git a/addons/web/static/src/js/views/calendar/calendar_model.js b/addons/web/static/src/js/views/calendar/calendar_model.js
index 6467e4695c6..92890766b34 100644
--- a/addons/web/static/src/js/views/calendar/calendar_model.js
+++ b/addons/web/static/src/js/views/calendar/calendar_model.js
@@ -253,7 +253,10 @@ return AbstractModel.extend({
* @param {Moment} start
*/
setDate: function (start) {
- this.data.start_date = this.data.end_date = this.data.target_date = this.data.highlight_date = start;
+ // keep highlight/target_date in localtime
+ this.data.highlight_date = this.data.target_date = start.clone();
+ // set dates in UTC with timezone applied manually
+ this.data.start_date = this.data.end_date = start;
this.data.start_date.utc().add(this.getSession().getTZOffset(this.data.start_date), 'minutes');
switch (this.data.scale) {
diff --git a/addons/web/static/src/js/views/form/form_controller.js b/addons/web/static/src/js/views/form/form_controller.js
index ea56c841c86..4c73fde121b 100644
--- a/addons/web/static/src/js/views/form/form_controller.js
+++ b/addons/web/static/src/js/views/form/form_controller.js
@@ -99,6 +99,7 @@ var FormController = BasicController.extend({
* @todo convert to new style
*/
on_attach_callback: function () {
+ this._super.apply(this, arguments);
this.autofocus();
},
/**
diff --git a/addons/web/static/src/js/views/graph/graph_renderer.js b/addons/web/static/src/js/views/graph/graph_renderer.js
index 8ce6ec14aba..1fbd6572a9a 100644
--- a/addons/web/static/src/js/views/graph/graph_renderer.js
+++ b/addons/web/static/src/js/views/graph/graph_renderer.js
@@ -42,6 +42,30 @@ return AbstractRenderer.extend({
nv.utils.offWindowResize(this.to_remove);
this._super();
},
+ /**
+ * The graph view uses the nv(d3) lib to render the graph. This lib requires
+ * that the rendering is done directly into the DOM (so that it can correctly
+ * compute positions). However, the views are always rendered in fragments,
+ * and appended to the DOM once ready (to prevent them from flickering). We
+ * here use the on_attach_callback hook, called when the widget is attached
+ * to the DOM, to perform the rendering. This ensures that the rendering is
+ * always done in the DOM.
+ *
+ * @override
+ */
+ on_attach_callback: function () {
+ this._super.apply(this, arguments);
+ this.isInDOM = true;
+ this._renderGraph();
+ },
+ /**
+ * @override
+ */
+ on_detach_callback: function () {
+ this._super.apply(this, arguments);
+ this.isInDOM = false;
+ },
+
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -50,10 +74,9 @@ return AbstractRenderer.extend({
* Render the chart.
*
* Note that This method is synchronous, but the actual rendering is done
- * asynchronously (in a setTimeout). The reason for that is that nvd3/d3
- * needs to be in the DOM to correctly render itself. So, we trick Odoo by
- * returning immediately, then wait a tiny interval before actually
- * displaying the data.
+ * asynchronously. The reason for that is that nvd3/d3 needs to be in the
+ * DOM to correctly render itself. So, we trick Odoo by returning
+ * immediately, then we render the chart when the widget is in the DOM.
*
* @override
* @private
@@ -76,21 +99,15 @@ return AbstractRenderer.extend({
description: _t("Try to add some records, or make sure that " +
"there is no active filter in the search bar."),
}));
- } else {
- var self = this;
- setTimeout(function () {
- self.$el.empty();
- var chart = self['_render' + _.str.capitalize(self.state.mode) + 'Chart']();
- if (chart && chart.tooltip.chartContainer) {
- self.to_remove = chart.update;
- nv.utils.onWindowResize(chart.update);
- chart.tooltip.chartContainer(self.el);
- }
- }, 0);
+ } else if (this.isInDOM) {
+ // only render the graph if the widget is already in the DOM (this
+ // happens typically after an update), otherwise, it will be
+ // rendered when the widget will be attached to the DOM (see
+ // 'on_attach_callback')
+ this._renderGraph();
}
return this._super.apply(this, arguments);
},
-
/**
* Helper function to set up data properly for the multiBarChart model in
* nvd3.
@@ -327,6 +344,21 @@ return AbstractRenderer.extend({
chart(svg);
return chart;
},
+ /**
+ * Renders the graph according to its type. This function must be called
+ * when the renderer is in the DOM (for nvd3 to render the graph correctly).
+ *
+ * @private
+ */
+ _renderGraph: function () {
+ this.$el.empty();
+ var chart = this['_render' + _.str.capitalize(this.state.mode) + 'Chart']();
+ if (chart && chart.tooltip.chartContainer) {
+ this.to_remove = chart.update;
+ nv.utils.onWindowResize(chart.update);
+ chart.tooltip.chartContainer(this.el);
+ }
+ },
});
});
diff --git a/addons/web/static/src/js/views/kanban/kanban_controller.js b/addons/web/static/src/js/views/kanban/kanban_controller.js
index 8a779becdea..9c227fba2ac 100644
--- a/addons/web/static/src/js/views/kanban/kanban_controller.js
+++ b/addons/web/static/src/js/views/kanban/kanban_controller.js
@@ -10,6 +10,7 @@ odoo.define('web.KanbanController', function (require) {
var BasicController = require('web.BasicController');
var Context = require('web.Context');
var core = require('web.core');
+var Domain = require('web.Domain');
var view_dialogs = require('web.view_dialogs');
var _t = core._t;
@@ -189,10 +190,57 @@ var KanbanController = BasicController.extend({
resIDs: record.res_ids,
},
on_closed: function () {
+ var recordModel = self.model.localData[record.id];
+ var group = self.model.localData[recordModel.parentID];
+ var parent = self.model.localData[group.parentID];
+
self.model.reload(record.id).then(function (db_id) {
var data = self.model.get(db_id);
var kanban_record = event.target;
kanban_record.update(data);
+
+ // Check if we still need to display the record. Some fields of the domain are
+ // not guaranteed to be in data. This is for example the case if the action
+ // contains a domain on a field which is not in the Kanban view. Therefore,
+ // we need to handle multiple cases based on 3 variables:
+ // domInData: all domain fields are in the data
+ // activeInDomain: 'active' is already in the domain
+ // activeInData: 'active' is available in the data
+
+ var domain = (parent ? parent.domain : group.domain) || [];
+ var domInData = _.every(domain, function (d) {
+ return d[0] in data.data;
+ });
+ var activeInDomain = _.pluck(domain, 0).indexOf('active') !== -1;
+ var activeInData = 'active' in data.data;
+
+ // Case # | domInData | activeInDomain | activeInData
+ // 1 | true | true | true => no domain change
+ // 2 | true | true | false => not possible
+ // 3 | true | false | true => add active in domain
+ // 4 | true | false | false => no domain change
+ // 5 | false | true | true => no evaluation
+ // 6 | false | true | false => no evaluation
+ // 7 | false | false | true => replace domain
+ // 8 | false | false | false => no evaluation
+
+ // There are 3 cases which cannot be evaluated since we don't have all the
+ // necessary information. The complete solution would be to perform a RPC in
+ // these cases, but this is out of scope. A simpler one is to do a try / catch.
+
+ if (domInData && !activeInDomain && activeInData) {
+ domain = domain.concat([['active', '=', true]]);
+ } else if (!domInData && !activeInDomain && activeInData) {
+ domain = [['active', '=', true]];
+ }
+ try {
+ var visible = new Domain(domain).compute(data.evalContext);
+ } catch (e) {
+ return;
+ }
+ if (!visible) {
+ kanban_record.destroy();
+ }
});
},
});
diff --git a/addons/web/static/src/js/views/kanban/kanban_model.js b/addons/web/static/src/js/views/kanban/kanban_model.js
index 15d6284cfad..411d4cc7b14 100644
--- a/addons/web/static/src/js/views/kanban/kanban_model.js
+++ b/addons/web/static/src/js/views/kanban/kanban_model.js
@@ -419,7 +419,10 @@ var KanbanModel = BasicModel.extend({
while (element) {
if (element.progressBar) {
return def.then(function (data) {
- return self._load(element, {onlyGroups: true}).then(function () {
+ return self._load(element, {
+ keepEmptyGroups: true,
+ onlyGroups: true,
+ }).then(function () {
return data;
});
});
diff --git a/addons/web/static/src/less/datepicker.less b/addons/web/static/src/less/datepicker.less
index 99c909efacc..fdf3a585b57 100644
--- a/addons/web/static/src/less/datepicker.less
+++ b/addons/web/static/src/less/datepicker.less
@@ -17,11 +17,12 @@
.o_datepicker_input {
width: 100%;
+ cursor: pointer;
}
.o_datepicker_button {
.o-position-absolute(2px, 4px);
- cursor: pointer;
+ pointer-events: none; // let click events go through the underlying input
&:after {
.o-caret-down;
}
diff --git a/addons/web/static/src/less/fields.less b/addons/web/static/src/less/fields.less
index ee9f1d9556a..ff6fe9eb20b 100644
--- a/addons/web/static/src/less/fields.less
+++ b/addons/web/static/src/less/fields.less
@@ -185,7 +185,7 @@
display: inline-block;
padding: 0;
margin: 0;
- vertical-align: middle;
+ vertical-align: baseline;
> .o_priority_star {
display: inline-block;
font-size: 1.35em;
diff --git a/addons/web/static/src/less/form_view.less b/addons/web/static/src/less/form_view.less
index 60a3671caa2..c3cbe2e3494 100644
--- a/addons/web/static/src/less/form_view.less
+++ b/addons/web/static/src/less/form_view.less
@@ -248,6 +248,10 @@
border-left-color: @gray-lighter;
}
}
+
+ .caret {
+ margin-top: -2px;
+ }
}
.o-status-more {
diff --git a/addons/web/static/src/less/kanban_column_progressbar.less b/addons/web/static/src/less/kanban_column_progressbar.less
index 86fe0853de2..f4cffd6c097 100644
--- a/addons/web/static/src/less/kanban_column_progressbar.less
+++ b/addons/web/static/src/less/kanban_column_progressbar.less
@@ -91,6 +91,7 @@
margin-left: 3%;
color: @headings-color;
text-align: right;
+ white-space: nowrap;
.o-transform-origin(right, center);
&.o_kanban_grow {
diff --git a/addons/web/static/src/less/kanban_dashboard.less b/addons/web/static/src/less/kanban_dashboard.less
index adf67f31bf0..947b78739f7 100644
--- a/addons/web/static/src/less/kanban_dashboard.less
+++ b/addons/web/static/src/less/kanban_dashboard.less
@@ -223,6 +223,7 @@
}
.o_favorite {
+ top: 3px;
left: 0;
right: auto;
}
diff --git a/addons/web/static/src/less/list_view.less b/addons/web/static/src/less/list_view.less
index c6d81293fbf..73bd50e1966 100644
--- a/addons/web/static/src/less/list_view.less
+++ b/addons/web/static/src/less/list_view.less
@@ -37,12 +37,14 @@
.user-select(none); // Prevent unwanted selection while sorting
&::after {
- margin-left: 6px;
- position: absolute;
font-family: FontAwesome;
content: "\f0d7";
opacity: 0;
}
+ &:not(:empty)::after {
+ margin-left: 6px;
+ position: absolute;
+ }
&.o-sort-up {
cursor: n-resize;
&::after {
diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js
index e395d1a0d7e..f321db1d172 100644
--- a/addons/web/static/tests/fields/basic_fields_tests.js
+++ b/addons/web/static/tests/fields/basic_fields_tests.js
@@ -3080,7 +3080,7 @@ QUnit.module('basic_fields', {
QUnit.module('PhoneWidget');
QUnit.test('phone field in form view on extra small screens', function (assert) {
- assert.expect(7);
+ assert.expect(8);
var form = createView({
View: FormView,
@@ -3127,6 +3127,15 @@ QUnit.module('basic_fields', {
assert.strictEqual($phoneLink.attr('href'), 'tel:new',
"should still have proper tel prefix");
+ // NOT NEEDED AS OF SAAS-11.3
+ // save phone with &shy; and verify it is removed
+ form.$buttons.find('.o_form_button_edit').click();
+ form.$('input[type="text"].o_field_widget').val('h\u00ADi').trigger('input');
+ form.$buttons.find('.o_form_button_save').click();
+ $phoneLink = form.$('a.o_form_uri.o_field_widget');
+ assert.strictEqual($phoneLink.attr('href'), 'tel:hi',
+ "U+00AD should have been removed");
+
form.destroy();
});
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index b755dc3440c..64ffc31096c 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -4246,7 +4246,6 @@ QUnit.module('relational_fields', {
form.destroy();
});
-
QUnit.test('one2many list (non editable): edition', function (assert) {
assert.expect(12);
@@ -5115,6 +5114,32 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('one2many and default_get (with date)', function (assert) {
+ assert.expect(1);
+
+ this.data.partner.fields.p.default = [
+ [0, false, {date: '2017-10-08'}],
+ ];
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch:'<form string="Partners">' +
+ '<field name="p">' +
+ '<tree>' +
+ '<field name="date"/>' +
+ '</tree>' +
+ '</field>' +
+ '</form>',
+ });
+
+ assert.strictEqual(form.$('.o_data_cell').text(), '10/08/2017',
+ "should correctly display the date");
+
+ form.destroy();
+ });
+
QUnit.test('one2many and onchange (with integer)', function (assert) {
assert.expect(4);
@@ -8780,6 +8805,53 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('add a line, edit it and "Save & New"', function (assert) {
+ assert.expect(5);
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<field name="p">' +
+ '<tree><field name="display_name"/></tree>' +
+ '<form><field name="display_name"/></form>' +
+ '</field>' +
+ '</form>',
+ });
+
+ assert.strictEqual(form.$('.o_data_row').length, 0,
+ "there should be no record in the relation");
+
+ // add a new record
+ form.$('.o_field_x2many_list_row_add a').click();
+ $('.modal .o_field_widget').val('new record').trigger('input');
+ $('.modal .modal-footer .btn-primary:first').click(); // Save & Close
+
+ assert.strictEqual(form.$('.o_data_row .o_data_cell').text(), 'new record',
+ "should display the new record");
+
+ // reopen freshly added record and edit it
+ form.$('.o_data_row .o_data_cell').click();
+ $('.modal .o_field_widget').val('new record edited').trigger('input');
+
+ // save it, and choose to directly create another record
+ $('.modal .modal-footer .btn-primary:nth(1)').click(); // Save & New
+
+ assert.strictEqual($('.modal').length, 1,
+ "the model should still be open");
+ assert.strictEqual($('.modal .o_field_widget').text(), '',
+ "should have cleared the input");
+
+ $('.modal .o_field_widget').val('another new record').trigger('input');
+ $('.modal .modal-footer .btn-primary:first').click(); // Save & Close
+
+ assert.strictEqual(form.$('.o_data_row .o_data_cell').text(),
+ 'new record editedanother new record', "should display the two records");
+
+ form.destroy();
+ });
+
QUnit.module('FieldMany2Many');
QUnit.test('many2many kanban: edition', function (assert) {
@@ -11304,6 +11376,78 @@ QUnit.module('relational_fields', {
form.destroy();
});
+ QUnit.test('one2many with extra field from server not in form', function (assert) {
+ assert.expect(6);
+
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<field name="p" >' +
+ '<tree>' +
+ '<field name="datetime"/>' +
+ '<field name="display_name"/>' +
+ '</tree>' +
+ '</field>' +
+ '</form>',
+ res_id: 1,
+ archs: {
+ 'partner,false,form': '<form>' +
+ '<field name="display_name"/>' +
+ '</form>'},
+ mockRPC: function(route, args) {
+ if (route === '/web/dataset/call_kw/partner/write') {
+ args.args[1].p[0][2].datetime = '2018-04-05 12:00:00';
+ }
+ return this._super.apply(this, arguments);
+ }
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+
+ var x2mList = form.$('.o_field_x2many_list[name=p]');
+
+ // Add a record in the list
+ x2mList.find('.o_field_x2many_list_row_add a').click();
+
+ var modal = $('.modal-dialog.modal-lg');
+
+ var nameInput = modal.find('input.o_input[name=display_name]');
+ nameInput.val('michelangelo').trigger('input');
+
+ // Save the record in the modal (though it is still virtual)
+ modal.find('.btn-primary').first().click();
+
+ assert.equal(x2mList.find('.o_data_row').length, 1,
+ 'There should be 1 records in the x2m list');
+
+ var newlyAdded = x2mList.find('.o_data_row').eq(0);
+
+ assert.equal(newlyAdded.find('.o_data_cell').first().text(), '',
+ 'The create_date field should be empty');
+ assert.equal(newlyAdded.find('.o_data_cell').eq(1).text(), 'michelangelo',
+ 'The display name field should have the right value');
+
+ // Save the whole thing
+ form.$buttons.find('.o_form_button_save').click();
+
+ x2mList = form.$('.o_field_x2many_list[name=p]');
+
+ // Redo asserts in RO mode after saving
+ assert.equal(x2mList.find('.o_data_row').length, 1,
+ 'There should be 1 records in the x2m list');
+
+ newlyAdded = x2mList.find('.o_data_row').eq(0);
+
+ assert.equal(newlyAdded.find('.o_data_cell').first().text(), '04/05/2018 12:00:00',
+ 'The create_date field should have the right value');
+ assert.equal(newlyAdded.find('.o_data_cell').eq(1).text(), 'michelangelo',
+ 'The display name field should have the right value');
+
+ form.destroy();
+ });
+
QUnit.test('one2many invisible depends on parent field', function (assert) {
assert.expect(4);
diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js
index b073bc988dd..7430c6b994b 100644
--- a/addons/web/static/tests/views/calendar_tests.js
+++ b/addons/web/static/tests/views/calendar_tests.js
@@ -1824,6 +1824,41 @@ QUnit.module('Views', {
assert.ok(!$groupBy.is(':visible'), 'groupby menu should not be visible');
actionManager.destroy();
});
+
+ QUnit.test('timezone does not affect current day', function (assert) {
+ assert.expect(2);
+
+ var calendar = createView({
+ View: CalendarView,
+ model: 'event',
+ data: this.data,
+ arch:
+ '<calendar date_start="start_date">'+
+ '<field name="name"/>'+
+ '</calendar>',
+ archs: archs,
+ viewOptions: {
+ initialDate: initialDate,
+ },
+ session: {
+ getTZOffset: function () {
+ return -2400; // 40 hours timezone
+ },
+ },
+
+ });
+
+ var $sidebar = calendar.$('.o_calendar_sidebar');
+
+ assert.strictEqual($sidebar.find('.ui-datepicker-current-day').text(), "12", "should highlight the target day");
+
+ // go to previous day
+ $sidebar.find('.ui-datepicker-current-day').prev().click();
+
+ assert.strictEqual($sidebar.find('.ui-datepicker-current-day').text(), "11", "should highlight the selected day");
+
+ calendar.destroy();
+ });
});
});
diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js
index b26cc8a3bd5..7aed9cad8f9 100644
--- a/addons/web/static/tests/views/kanban_tests.js
+++ b/addons/web/static/tests/views/kanban_tests.js
@@ -2511,6 +2511,73 @@ QUnit.module('Views', {
kanban.destroy();
});
+ QUnit.test('button executes action and check domain', function (assert) {
+ assert.expect(2);
+
+ var data = this.data;
+ data.partner.fields.active = {string: "Active", type: "boolean", default: true};
+ for (var k in this.data.partner.records) {
+ data.partner.records[k].active = true;
+ }
+
+ var kanban = createView({
+ View: KanbanView,
+ model: "partner",
+ data: data,
+ arch:
+ '<kanban>' +
+ '<templates><div t-name="kanban-box">' +
+ '<field name="foo"/>' +
+ '<field name="active"/>' +
+ '<button type="object" name="a1" />' +
+ '<button type="object" name="toggle_active" />' +
+ '</div></templates>' +
+ '</kanban>',
+ });
+
+ testUtils.intercept(kanban, 'execute_action', function (event) {
+ data.partner.records[0].active = false;
+ event.data.on_closed();
+ });
+
+ assert.strictEqual(kanban.$('.o_kanban_record:contains(yop)').length, 1, "should display 'yop' record");
+ kanban.$('.o_kanban_record:contains(yop) button[data-name="toggle_active"]').click();
+ assert.strictEqual(kanban.$('.o_kanban_record:contains(yop)').length, 0, "should remove 'yop' record from the view");
+
+ kanban.destroy();
+ });
+
+ QUnit.test('button executes action with domain field not in view', function (assert) {
+ assert.expect(1);
+
+ var kanban = createView({
+ View: KanbanView,
+ model: "partner",
+ data: this.data,
+ domain: [['bar', '=', true]],
+ arch:
+ '<kanban>' +
+ '<templates><div t-name="kanban-box">' +
+ '<field name="foo"/>' +
+ '<button type="object" name="a1" />' +
+ '<button type="object" name="toggle_action" />' +
+ '</div></templates>' +
+ '</kanban>',
+ });
+
+ testUtils.intercept(kanban, 'execute_action', function (event) {
+ event.data.on_closed();
+ });
+
+ try {
+ kanban.$('.o_kanban_record:contains(yop) button[data-name="toggle_action"]').click();
+ assert.strictEqual(true, true, 'Everything went fine');
+ } catch (e) {
+ assert.strictEqual(true, false, 'Error triggered at action execution');
+ }
+ kanban.destroy();
+ });
+
QUnit.test('rendering date and datetime', function (assert) {
assert.expect(2);
@@ -3150,6 +3217,51 @@ QUnit.module('Views', {
kanban.destroy();
});
+ QUnit.test('drag & drop records grouped by m2o with progressbar', function (assert) {
+ assert.expect(4);
+
+ this.data.partner.records[0].product_id = false;
+
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch:
+ '<kanban>' +
+ '<progressbar field="foo" colors=\'{"yop": "success", "gnap": "warning", "blip": "danger"}\'/>' +
+ '<templates><t t-name="kanban-box">' +
+ '<div>' +
+ '<field name="int_field"/>' +
+ '</div>' +
+ '</t></templates>' +
+ '</kanban>',
+ groupBy: ['product_id'],
+ mockRPC: function (route, args) {
+ if (route === '/web/dataset/resequence') {
+ return $.when(true);
+ }
+ return this._super(route, args);
+ },
+ });
+
+ assert.strictEqual(kanban.$('.o_kanban_group:eq(0) .o_kanban_counter_side').text(), "1",
+ "counter should contain the correct value");
+
+ testUtils.dragAndDrop(kanban.$('.o_kanban_group:eq(0) .o_kanban_record:eq(0)'), kanban.$('.o_kanban_group:eq(1)'));
+ assert.strictEqual(kanban.$('.o_kanban_group:eq(0) .o_kanban_counter_side').text(), "0",
+ "counter should contain the correct value");
+
+ testUtils.dragAndDrop(kanban.$('.o_kanban_group:eq(1) .o_kanban_record:eq(2)'), kanban.$('.o_kanban_group:eq(0)'));
+ assert.strictEqual(kanban.$('.o_kanban_group:eq(0) .o_kanban_counter_side').text(), "1",
+ "counter should contain the correct value");
+
+ testUtils.dragAndDrop(kanban.$('.o_kanban_group:eq(0) .o_kanban_record:eq(0)'), kanban.$('.o_kanban_group:eq(1)'));
+ assert.strictEqual(kanban.$('.o_kanban_group:eq(0) .o_kanban_counter_side').text(), "0",
+ "counter should contain the correct value");
+
+ kanban.destroy();
+ });
+
QUnit.test('progress bar subgroup count recompute', function(assert) {
assert.expect(2);
diff --git a/addons/web_editor/models/ir_http.py b/addons/web_editor/models/ir_http.py
index d6e2b2d5ee6..aaf0f67cefb 100644
--- a/addons/web_editor/models/ir_http.py
+++ b/addons/web_editor/models/ir_http.py
@@ -3,6 +3,7 @@
from odoo import models
from odoo.http import request
+from odoo.osv import expression
class IrHttp(models.AbstractModel):
@@ -19,3 +20,8 @@ class IrHttp(models.AbstractModel):
context['translatable'] = True
request.context = context
return super(IrHttp, cls)._dispatch()
+
+ @classmethod
+ def _get_translation_frontend_modules_domain(cls):
+ domain = super(IrHttp, cls)._get_translation_frontend_modules_domain()
+ return expression.OR([domain, [('name', '=', 'web_editor')]])
diff --git a/addons/web_editor/static/src/js/editor/summernote.js b/addons/web_editor/static/src/js/editor/summernote.js
index 58710987a51..dc97da37365 100644
--- a/addons/web_editor/static/src/js/editor/summernote.js
+++ b/addons/web_editor/static/src/js/editor/summernote.js
@@ -1800,12 +1800,17 @@ $.summernote.pluginEvents.indent = function (event, editor, layoutInfo, outdent)
var $dom = $(ancestor);
if (!dom.isList(ancestor)) {
+ // to indent a selection, we indent the child nodes of the common
+ // ancestor that contains this selection
$dom = $(dom.node(ancestor)).children();
}
- if (!$dom.length) {
- $dom = $(dom.ancestor(r.sc, dom.isList) || dom.ancestor(r.sc, dom.isCell));
+ if (!$dom.not('br').length) {
+ // if selection is inside a list, we indent its list items
+ $dom = $(dom.ancestor(r.sc, dom.isList));
if (!$dom.length) {
- $dom = $(r.sc).closest(options.styleTags.join(','));
+ // if the selection is contained in a single HTML node, we indent
+ // the first ancestor 'content block' (P, H1, PRE, ...) or TD
+ $dom = $(r.sc).closest(options.styleTags.join(',')+',td');
}
}
diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py
index 425859decd9..62d862afe35 100644
--- a/addons/website/controllers/main.py
+++ b/addons/website/controllers/main.py
@@ -295,17 +295,6 @@ class Website(Home):
modules.button_immediate_upgrade()
return request.redirect(redirect)
- @http.route('/website/translations', type='json', auth="public", website=True)
- def get_website_translations(self, lang, mods=None):
- Modules = request.env['ir.module.module'].sudo()
- modules = Modules.search([
- '|', ('name', 'ilike', 'website'), ('name', '=', 'web_editor'),
- ('state', '=', 'installed')
- ]).mapped('name')
- if mods:
- modules += mods
- return WebClient().translations(mods=modules, lang=lang)
-
@http.route(['/website/publish'], type='json', auth="public", website=True)
def publish(self, id, object):
Model = request.env[object]
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index ba58f790597..0e5443ad79e 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -17,7 +17,7 @@ from odoo.http import request
from odoo.tools import config
from odoo.exceptions import QWebException
from odoo.tools.safe_eval import safe_eval
-from odoo.osv.expression import FALSE_DOMAIN
+from odoo.osv.expression import FALSE_DOMAIN, OR
from odoo.addons.http_routing.models.ir_http import ModelConverter, _guess_mimetype
from odoo.addons.portal.controllers.portal import _build_url_w_params
@@ -105,6 +105,11 @@ class Http(models.AbstractModel):
return super(Http, cls)._get_default_lang()
@classmethod
+ def _get_translation_frontend_modules_domain(cls):
+ domain = super(Http, cls)._get_translation_frontend_modules_domain()
+ return OR([domain, [('name', 'ilike', 'website')]])
+
+ @classmethod
def _serve_page(cls):
req_page = request.httprequest.path
diff --git a/addons/website_event_sale/static/src/js/website.tour.event_sale.js b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
index fef2c038777..b291d340aa7 100644
--- a/addons/website_event_sale/static/src/js/website.tour.event_sale.js
+++ b/addons/website_event_sale/static/src/js/website.tour.event_sale.js
@@ -92,6 +92,7 @@ tour.register('event_buy_tickets', {
{
content: "Last step",
trigger: '.oe_website_sale:contains("Thank you for your order")',
+ timeout: 30000,
}
]
);
diff --git a/addons/website_form/static/src/js/website_form.js b/addons/website_form/static/src/js/website_form.js
index 5318a84067d..512c7a0269c 100644
--- a/addons/website_form/static/src/js/website_form.js
+++ b/addons/website_form/static/src/js/website_form.js
@@ -20,7 +20,11 @@ odoo.define('website_form.animation', function (require) {
return $.when(this._super.apply(this, arguments), def);
},
- start: function () {
+ start: function (editable_mode) {
+ if (editable_mode) {
+ this.stop();
+ return;
+ }
var self = this;
this.templates_loaded = ajax.loadXML('/website_form/static/src/xml/website_form.xml', qweb);
this.$target.find('.o_website_form_send').on('click',function (e) {self.send(e);});
diff --git a/addons/website_quote/report/sale_order_templates.xml b/addons/website_quote/report/sale_order_templates.xml
index 308df119a16..ad67e5e9439 100644
--- a/addons/website_quote/report/sale_order_templates.xml
+++ b/addons/website_quote/report/sale_order_templates.xml
@@ -1,12 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_saleorder_validity_date" inherit_id="sale.report_saleorder_document">
- <xpath expr="//div[hasclass('page')]/div[@id='informations']" position="inside">
- <div t-if="doc.validity_date and doc.state in ['draft', 'sent']" class="col-xs-3">
- <strong>Expiration Date:</strong>
- <p t-field="doc.validity_date"/>
- </div>
- </xpath>
<xpath expr="//div[hasclass('page')]/p[@id='fiscal_position_remark']" position="after">
<div t-if="doc.options and doc.state in ['draft', 'sent']" style="page-break-before:always;">
<h2>
diff --git a/addons/website_sale/models/res_config_settings.py b/addons/website_sale/models/res_config_settings.py
index ab48523b662..197ac1dbf0d 100644
--- a/addons/website_sale/models/res_config_settings.py
+++ b/addons/website_sale/models/res_config_settings.py
@@ -31,7 +31,7 @@ class ResConfigSettings(models.TransientModel):
], string="Shipping Management")
group_website_multiimage = fields.Boolean(string='Multi-Images', implied_group='website_sale.group_website_multi_image', group='base.group_portal,base.group_user,base.group_public')
- group_delivery_invoice_address = fields.Boolean(string="Shipping Address", implied_group='sale.group_delivery_invoice_address')
+ group_delivery_invoice_address = fields.Boolean(string="Shipping Address", implied_group='sale.group_delivery_invoice_address', group='base.group_portal,base.group_user,base.group_public')
module_website_sale_options = fields.Boolean("Optional Products")
module_website_sale_digital = fields.Boolean("Digital Content")
diff --git a/addons/website_sale/static/src/js/website_sale_tour_buy.js b/addons/website_sale/static/src/js/website_sale_tour_buy.js
index 10ff83552ed..47921e71547 100644
--- a/addons/website_sale/static/src/js/website_sale_tour_buy.js
+++ b/addons/website_sale/static/src/js/website_sale_tour_buy.js
@@ -82,6 +82,7 @@ tour.register('shop_buy_product', {
{
content: "finish",
trigger: '.oe_website_sale:contains("Thank you for your order")',
+ timeout: 30000,
}
]
);
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index e9f22845bda..770ee2a9c4e 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -443,7 +443,7 @@
<li t-if="variant_img" data-target="#o-carousel-product" data-slide-to="0" class="active">
<img class="img img-responsive js_variant_img_small" t-attf-src="/website/image/product.product/{{product.product_variant_id.id}}/image/90x90" t-att-alt="product.name"/>
</li>
- <li data-target="#o-carousel-product" t-att-data-slide-to="1 if variant_img else 0" t-att-class="'' if variant_img else 'active'">
+ <li data-target="#o-carousel-product" t-att-data-slide-to="1 if variant_img else '0'" t-att-class="'' if variant_img else 'active'">
<img class="img img-responsive" t-attf-src="/website/image/product.template/{{product.id}}/image/90x90" t-att-alt="product.name"/>
</li>
<t t-if="len(image_ids)" t-foreach="image_ids" t-as="pimg">
diff --git a/addons/website_sale_wishlist/controllers/main.py b/addons/website_sale_wishlist/controllers/main.py
index e9ebff51ad0..c9fd9a6b25e 100644
--- a/addons/website_sale_wishlist/controllers/main.py
+++ b/addons/website_sale_wishlist/controllers/main.py
@@ -39,3 +39,8 @@ class WebsiteSaleWishlist(WebsiteSale):
return request.redirect("/shop")
return request.render("website_sale_wishlist.product_wishlist", dict(wishes=values))
+
+ @http.route(['/shop/wishlist/remove/<model("product.wishlist"):wish>'], type='json', auth="public", website=True)
+ def rm_from_wishlist(self, wish, **kw):
+ wish.active = False
+ return True
diff --git a/addons/website_sale_wishlist/static/src/js/website_sale_tour_wishlist.js b/addons/website_sale_wishlist/static/src/js/website_sale_tour_wishlist.js
new file mode 100644
index 00000000000..c3e6c9349d8
--- /dev/null
+++ b/addons/website_sale_wishlist/static/src/js/website_sale_tour_wishlist.js
@@ -0,0 +1,130 @@
+odoo.define('website_sale_wishlist.tour', function (require) {
+'use strict';
+
+var tour = require("web_tour.tour");
+var base = require("web_editor.base");
+
+tour.register('shop_wishlist', {
+ test: true,
+ url: '/shop',
+ wait_for: base.ready(),
+},
+ [
+ {
+ content: "click on add to wishlist",
+ trigger: '.o_add_wishlist',
+ },
+ {
+ content: "go to wishlist",
+ extra_trigger: ".label:contains(1)",
+ trigger: 'a[href="/shop/wishlist"]',
+ },
+ {
+ content: "remove first item in whishlist",
+ trigger: 'a.o_wish_rm:first',
+ },
+ {
+ content: "go back to the store",
+ trigger: "a[href='/shop']"
+ },
+ {
+ content: "click on add to wishlist",
+ trigger: '.o_add_wishlist',
+ },
+ {
+ content: "check value of wishlist and go to login",
+ extra_trigger: ".my_wish_quantity:contains(1)",
+ trigger: 'a[href="/web/login"]',
+ },
+ {
+ content: "submit login",
+ trigger: ".oe_login_form",
+ run: function (){
+ $('.oe_login_form input[name="login"]').val("admin");
+ $('.oe_login_form input[name="password"]').val("admin");
+ $('.oe_login_form input[name="redirect"]').val("/shop");
+ $('.oe_login_form').submit();
+ },
+ },
+ {
+ content: "check that logged in and search for ipad",
+ extra_trigger: 'li span:contains(Administrator)',
+ trigger: 'form input[name="search"]',
+ run: "text ipad retina",
+ },
+ {
+ content: "submit search",
+ trigger: 'form:has(input[name="search"]) .oe_search_button',
+ },
+ {
+ content: "click on ipad",
+ trigger: '.oe_product_cart a:contains("iPad Retina Display")',
+ },
+ {
+ content: "select ipad 32GB",
+ extra_trigger: '#product_detail',
+ trigger: 'label:contains(32 GB) input',
+ },
+ {
+ content: "click on add to wishlist",
+ trigger: '#product_detail .o_add_wishlist_dyn',
+ },
+ {
+ content: "check that wishlist contains 2 items and go to wishlist",
+ extra_trigger: ".label:contains(2)",
+ trigger: 'a[href="/shop/wishlist"]',
+ },
+ {
+ content: "remove Ipad",
+ trigger: 'tr:contains("iPad Retina Display") a.o_wish_rm:first',
+ },
+ {
+ content: "check that wishlist contains 1 item",
+ trigger: ".my_wish_quantity:contains(1)",
+ run: function() {},
+ },
+ {
+ content: "check B2B wishlist mode",
+ trigger: "input#b2b_wish",
+ },
+ {
+ content: "add item to cart",
+ trigger: 'a.o_wish_add:first',
+ },
+ {
+ content: "check that cart contains 1 item",
+ trigger: ".my_cart_quantity:contains(1)",
+ run: function() {},
+ },
+ {
+ content: "check that wishlist contains 1 item",
+ trigger: ".my_wish_quantity:contains(1)",
+ run: function() {},
+ },
+ {
+ content: "remove B2B wishlist mode",
+ trigger: "input#b2b_wish",
+ },
+ {
+ content: "add last item to cart",
+ trigger: 'a.o_wish_add:first',
+ },
+ {
+ content: "check that user is redirect - wishlist is empty",
+ trigger: "h2:contains('Shopping Cart')",
+ run: function() {},
+ },
+ {
+ content: "check that cart contains 2 items",
+ trigger: ".my_cart_quantity:contains(2)",
+ run: function() {},
+ },
+ {
+ content: "check that wishlist is empty and no more visible",
+ trigger: ":not(:has(.my_wish_quantity:visible))",
+ run: function() {},
+ },
+ ]
+);
+
+});
diff --git a/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js b/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js
index 34ed9c47957..3eb511140a3 100644
--- a/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js
+++ b/addons/website_sale_wishlist/static/src/js/website_sale_wishlist.js
@@ -3,11 +3,9 @@ odoo.define('website_sale_wishlist.wishlist', function (require) {
require('web.dom_ready');
var ajax = require('web.ajax');
-var rpc = require('web.rpc');
var Widget = require('web.Widget');
var base = require('web_editor.base');
var website_sale_utils = require('website_sale.utils');
-var weContext = require('web_editor.context');
if(!$('.oe_website_sale').length) {
return $.Deferred().reject("DOM doesn't contain '.oe_website_sale'");
@@ -71,7 +69,7 @@ var ProductWishlist = Widget.extend({
});
},
- add_new_products:function($el, e){
+ add_new_products: function($el, e){
var self = this;
var product_id = parseInt($el.data('product-product-id'), 10);
if (!product_id && e.currentTarget.classList.contains('o_add_wishlist_dyn')) {
@@ -112,14 +110,9 @@ var ProductWishlist = Widget.extend({
var product = tr.data('product-id');
var self = this;
- rpc.query({
- model: 'product.wishlist',
- method: 'write',
- args: [[wish], { active: false }, weContext.getExtra()],
- })
- .then(function(){
- $(tr).hide();
- });
+ ajax.jsonRpc('/shop/wishlist/remove/' + wish).done(function () {
+ $(tr).hide();
+ });
this.wishlist_product_ids = _.without(this.wishlist_product_ids, product);
if (this.wishlist_product_ids.length === 0) {
diff --git a/addons/website_sale_wishlist/tests/__init__.py b/addons/website_sale_wishlist/tests/__init__.py
new file mode 100644
index 00000000000..c19627a953b
--- /dev/null
+++ b/addons/website_sale_wishlist/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_wishlist_process
diff --git a/addons/website_sale_wishlist/tests/test_wishlist_process.py b/addons/website_sale_wishlist/tests/test_wishlist_process.py
new file mode 100644
index 00000000000..26b13dd0957
--- /dev/null
+++ b/addons/website_sale_wishlist/tests/test_wishlist_process.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+import odoo.tests
+
+
+@odoo.tests.common.at_install(False)
+@odoo.tests.common.post_install(True)
+class TestUi(odoo.tests.HttpCase):
+ def test_01_wishlist_tour(self):
+ self.phantom_js("/", "odoo.__DEBUG__.services['web_tour.tour'].run('shop_wishlist')", "odoo.__DEBUG__.services['web_tour.tour'].tours.shop_wishlist.ready")
diff --git a/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml b/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml
index 4fcb14d7d31..1d306318534 100644
--- a/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml
+++ b/addons/website_sale_wishlist/views/website_sale_wishlist_template.xml
@@ -5,6 +5,7 @@
<xpath expr="." position="inside">
<link type="text/less" rel='stylesheet' href='/website_sale_wishlist/static/src/less/website_sale_wishlist.less'/>
<script type="text/javascript" src="/website_sale_wishlist/static/src/js/website_sale_wishlist.js"></script>
+ <script type="text/javascript" src="/website_sale_wishlist/static/src/js/website_sale_tour_wishlist.js"></script>
</xpath>
</template>
diff --git a/doc/_extensions/odoo_ext/switcher.py b/doc/_extensions/odoo_ext/switcher.py
index 51fb604929c..8571d124259 100644
--- a/doc/_extensions/odoo_ext/switcher.py
+++ b/doc/_extensions/odoo_ext/switcher.py
@@ -1,7 +1,8 @@
from docutils import nodes, utils
from docutils.parsers.rst import Directive
-from pygments.lexers import get_lexer_by_name
+from pygments.lexers import get_lexer_by_name, PythonLexer
+PythonLexer.name = 'Python 2'
def setup(app):
app.add_directive('switcher', SwitcherDirective)
diff --git a/doc/cla/corporate/iterativo.md b/doc/cla/corporate/iterativo.md
index 83075996389..81659d8a50d 100644
--- a/doc/cla/corporate/iterativo.md
+++ b/doc/cla/corporate/iterativo.md
@@ -12,4 +12,6 @@ Edser G. Solís edser@iterativo.do https://github.com/edsersolis
List of contributors:
-Gustavo A. Valverde gustavo@iterativo.do https://github.com/gustavovalverde
+ Gustavo A. Valverde gustavo@iterativo.do https://github.com/gustavovalverde
+ Edser G. Solís edser@iterativo.do https://github.com/edsersolis
+ José López joselopezg8@gmail.com https://github.com/jlopezg \ No newline at end of file
diff --git a/doc/cla/individual/eternalharvest.md b/doc/cla/individual/eternalharvest.md
new file mode 100644
index 00000000000..4ce2219f4cb
--- /dev/null
+++ b/doc/cla/individual/eternalharvest.md
@@ -0,0 +1,11 @@
+Japan, 2018-04-05
+
+I hereby agree to the terms of the Odoo Individual Contributor License
+Agreement v1.0.
+
+I declare that I am authorized and able to make this agreement and sign this
+declaration.
+
+Signed,
+
+Takuya Sawada <takuya@tuntunkun.com> https://github.com/eternalharvest
diff --git a/doc/cla/individual/kirca.md b/doc/cla/individual/kirca.md
index be2dea9c302..a53fcad358d 100644
--- a/doc/cla/individual/kirca.md
+++ b/doc/cla/individual/kirca.md
@@ -9,3 +9,4 @@ declaration.
Signed,
Kiril Vangelovski kiril@hacbee.com https://github.com/kirca
+Kiril Vangelovski kiril@lambda-is.com https://github.com/kirca
diff --git a/doc/howtos/backend.rst b/doc/howtos/backend.rst
index ddc41dca404..933309ad190 100644
--- a/doc/howtos/backend.rst
+++ b/doc/howtos/backend.rst
@@ -1709,12 +1709,19 @@ JSON-RPC Library
----------------
The following example is a Python 3 program that interacts with an Odoo server
-with the standard Python libraries ``urllib.request`` and ``json``::
+with the standard Python libraries ``urllib.request`` and ``json``. This
+example assumes the **Productivity** app (``note``) is installed::
import json
import random
import urllib.request
+ HOST = 'localhost'
+ PORT = 8069
+ DB = 'openacademy'
+ USER = 'admin'
+ PASS = 'admin'
+
def json_rpc(url, method, params):
data = {
"jsonrpc": "2.0",
@@ -1725,7 +1732,7 @@ with the standard Python libraries ``urllib.request`` and ``json``::
req = urllib.request.Request(url=url, data=json.dumps(data).encode(), headers={
"Content-Type":"application/json",
})
- reply = json.load(urllib.request.urlopen(req))
+ reply = json.loads(urllib.request.urlopen(req).read().decode('UTF-8'))
if reply.get("error"):
raise Exception(reply["error"])
return reply["result"]
diff --git a/doc/howtos/profilecode.rst b/doc/howtos/profilecode.rst
index 34591fcf274..840181ae43b 100644
--- a/doc/howtos/profilecode.rst
+++ b/doc/howtos/profilecode.rst
@@ -5,18 +5,19 @@ Profiling Odoo code
.. warning::
This tutorial requires :ref:`having installed Odoo <setup/install>`
- and :ref:`writing Odoo code <backend>`
+ and :doc:`writing Odoo code <backend>`
-Graph a method Up to 10.0
-=========================
+Graph a method
+==============
Odoo embeds a profiler of code. This embeded profiler output can be used to
-generate a graph of calls triggered by the method, percentage of time taken in
-the method itself as well as time taken in method and it's sub-called methods.
+generate a graph of calls triggered by the method, number of queries, percentage
+of time taken in the method itself as well as time taken in method and it's
+sub-called methods.
.. code:: python
- from openerp.tools.misc import profile
+ from odoo.tools.profiler import profile
[...]
@profile('/temp/prof.profile')
@api.multi
@@ -36,6 +37,44 @@ A tool called *xdot* will display the resulting graph:
xdot /temp/prof.xdot
+The profiler can be also used without saving data in a file.
+
+.. code:: python
+
+ @profile
+ @api.model
+ def mymethod(...):
+
+The statistics will be displayed into the logs once the method to be analysed is
+completely reviewed.
+
+.. code:: bash
+
+ 2018-03-28 06:18:23,196 22878 INFO openerp odoo.tools.profiler:
+ calls queries ms
+ project.task ------------------------ /home/odoo/src/odoo/addons/project/models/project.py, 638
+
+ 1 0 0.02 @profile
+ @api.model
+ def create(self, vals):
+ # context: no_log, because subtype already handle this
+ 1 0 0.01 context = dict(self.env.context, mail_create_nolog=True)
+
+ # for default stage
+ 1 0 0.01 if vals.get('project_id') and not context.get('default_project_id'):
+ context['default_project_id'] = vals.get('project_id')
+ # user_id change: update date_assign
+ 1 0 0.01 if vals.get('user_id'):
+ vals['date_assign'] = fields.Datetime.now()
+ # Stage change: Update date_end if folded stage
+ 1 0 0.0 if vals.get('stage_id'):
+ vals.update(self.update_date_end(vals['stage_id']))
+ 1 108 631.8 task = super(Task, self.with_context(context)).create(vals)
+ 1 0 0.01 return task
+
+ Total:
+ 1 108 631.85
+
Dump stack
==========
@@ -56,6 +95,7 @@ Install pyflame and flamegraph
.. code:: bash
+ # These instructions are given for Debian/Ubuntu distributions
sudo apt install autoconf automake autotools-dev g++ pkg-config python-dev python3-dev libtool make
git clone https://github.com/uber/pyflame.git
git clone https://github.com/brendangregg/FlameGraph.git
diff --git a/odoo/addons/base/data/res_country_data.xml b/odoo/addons/base/data/res_country_data.xml
index fdbb6fff9f2..db41e2370ce 100644
--- a/odoo/addons/base/data/res_country_data.xml
+++ b/odoo/addons/base/data/res_country_data.xml
@@ -1399,7 +1399,7 @@
<field name="name">Sudan</field>
<field name="code">sd</field>
<field file="base/static/img/country_flags/sd.png" name="image" type="base64" />
- <field name="currency_id" ref="SDD" />
+ <field name="currency_id" ref="SDG" />
<field eval="249" name="phone_code" />
</record>
<record id="se" model="res.country">
diff --git a/odoo/addons/base/data/res_currency_data.xml b/odoo/addons/base/data/res_currency_data.xml
index 6e2d8cf5dc8..d9c56dfe558 100644
--- a/odoo/addons/base/data/res_currency_data.xml
+++ b/odoo/addons/base/data/res_currency_data.xml
@@ -1292,6 +1292,7 @@
<field name="currency_subunit_label">Cents</field>
</record>
+ <!-- no longer in use since 2007 -->
<record id="SDD" model="res.currency">
<field name="name">SDD</field>
<field name="symbol">£Sd</field>
@@ -1301,6 +1302,13 @@
<field name="currency_subunit_label">Fils</field>
</record>
+ <record id="SDG" model="res.currency">
+ <field name="name">SDG</field>
+ <field name="symbol">ج.س.</field>
+ <field name="rounding">0.01</field>
+ <field name="active" eval="False"/>
+ </record>
+
<record id="LKR" model="res.currency">
<field name="name">LKR</field>
<field name="symbol">Rs</field>
diff --git a/odoo/addons/base/data/res_currency_rate_demo.xml b/odoo/addons/base/data/res_currency_rate_demo.xml
index 220e7849668..99fcdcf05f7 100644
--- a/odoo/addons/base/data/res_currency_rate_demo.xml
+++ b/odoo/addons/base/data/res_currency_rate_demo.xml
@@ -871,6 +871,12 @@
<field name="rate">544.44</field>
</record>
+ <record forcecreate="0" id="rateSDG" model="res.currency.rate">
+ <field name="currency_id" ref="SDG" />
+ <field name="name">2010-01-01</field>
+ <field name="rate">3.1999</field>
+ </record>
+
<record forcecreate="0" id="rateLKR" model="res.currency.rate">
<field name="currency_id" ref="LKR" />
<field name="name">2010-01-01</field>
diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py
index 073eedfb535..a330b7d3dd3 100644
--- a/odoo/addons/base/models/ir_module.py
+++ b/odoo/addons/base/models/ir_module.py
@@ -676,7 +676,7 @@ class Module(models.Model):
res = [0, 0] # [update, add]
default_version = modules.adapt_version('1.0')
- known_mods = self.search([])
+ known_mods = self.with_context(lang=None).search([])
known_mods_names = {mod.name: mod for mod in known_mods}
# iterate through detected modules and update/create them in db
diff --git a/odoo/addons/base/models/res_currency.py b/odoo/addons/base/models/res_currency.py
index 54b4d106120..509bb548ecc 100644
--- a/odoo/addons/base/models/res_currency.py
+++ b/odoo/addons/base/models/res_currency.py
@@ -101,17 +101,20 @@ class Currency(models.Model):
logging.getLogger(__name__).warning("The library 'num2words' is missing, cannot render textual amounts.")
return ""
- fractional_value, integer_value = math.modf(amount)
- fractional_amount = round(abs(fractional_value), self.decimal_places) * (math.pow(10, self.decimal_places))
+ formatted = "%.{0}f".format(self.decimal_places) % amount
+ parts = formatted.partition('.')
+ integer_value = int(parts[0])
+ fractional_value = int(parts[2] or 0)
+
lang_code = self.env.context.get('lang') or self.env.user.lang
lang = self.env['res.lang'].search([('code', '=', lang_code)])
amount_words = tools.ustr('{amt_value} {amt_word}').format(
- amt_value=_num2words(int(integer_value), lang=lang.iso_code),
+ amt_value=_num2words(integer_value, lang=lang.iso_code),
amt_word=self.currency_unit_label,
)
- if not self.is_zero(fractional_value):
+ if not self.is_zero(amount - integer_value):
amount_words += ' ' + _('and') + tools.ustr(' {amt_value} {amt_word}').format(
- amt_value=_num2words(int(fractional_amount), lang=lang.iso_code),
+ amt_value=_num2words(fractional_value, lang=lang.iso_code),
amt_word=self.currency_subunit_label,
)
return amount_words
diff --git a/odoo/addons/base/tests/test_float.py b/odoo/addons/base/tests/test_float.py
index 6e42f8adf1d..a5f91982303 100644
--- a/odoo/addons/base/tests/test_float.py
+++ b/odoo/addons/base/tests/test_float.py
@@ -206,3 +206,12 @@ class TestFloatPrecision(TransactionCase):
with self.assertRaises(AssertionError):
float_round(0.01, precision_digits=3, precision_rounding=0.01)
+
+ def test_amount_to_text_10(self):
+ """ verify that amount_to_text works as expected """
+ currency = self.env.ref('base.EUR')
+
+ amount_target = currency.amount_to_text(0.29)
+ amount_test = currency.amount_to_text(0.28)
+ self.assertNotEqual(amount_test, amount_target,
+ "Amount in text should not depend on float representation")
diff --git a/odoo/http.py b/odoo/http.py
index cb2bd2b4368..e06f345964d 100644
--- a/odoo/http.py
+++ b/odoo/http.py
@@ -603,7 +603,7 @@ class JsonRequest(WebRequest):
request = self.session.pop('jsonp_request_%s' % (request_id,), '{}')
else:
# regular jsonrpc2
- request = self.httprequest.stream.read().decode(self.httprequest.charset)
+ request = self.httprequest.get_data().decode(self.httprequest.charset)
# Read POST content or POST Form Data named "request"
try:
diff --git a/odoo/models.py b/odoo/models.py
index bcb0036c8df..e64099a99ae 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -651,6 +651,12 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# create missing xml ids
missing = self.filtered(lambda r: r.id not in xids)
+ if not missing:
+ return (
+ (record, '%s.%s' % xids[record.id])
+ for record in self
+ )
+
xids.update(
(r.id, (modname, '%s_%s_%s' % (
r._table,
@@ -659,6 +665,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
)))
for r in missing
)
+ fields = ['module', 'model', 'name', 'res_id']
cr.copy_from(io.StringIO(
u'\n'.join(
u"%s\t%s\t%s\t%d" % (
@@ -670,10 +677,9 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
for record in missing
)),
table='ir_model_data',
- columns=['module', 'model', 'name', 'res_id'],
+ columns=fields,
)
-
- self.invalidate_cache()
+ self.env['ir.model.data'].invalidate_cache(fnames=fields)
return (
(record, '%s.%s' % xids[record.id])
@@ -681,10 +687,12 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
)
@api.multi
- def _export_rows(self, fields):
+ def _export_rows(self, fields, batch_invalidate=True):
""" Export fields of the records in ``self``.
:param fields: list of lists of fields to traverse
+ :param batch_invalidate:
+ whether to clear the cache for the top-level object every so often (avoids huge memory consumption when exporting large numbers of records)
:return: list of lists of corresponding values
"""
import_compatible = self.env.context.get('import_compat', True)
@@ -700,6 +708,8 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
for rec in sub:
yield rec
rs.invalidate_cache(ids=sub.ids)
+ if not batch_invalidate:
+ splittor = lambda rs: rs
# both _ensure_xml_id and the splitter want to work on recordsets but
# neither returns one, so can't really be composed...
@@ -750,7 +760,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# 'display_name' where no subfield is exported
fields2 = [(p[1:] or ['display_name'] if p and p[0] == name else [])
for p in fields]
- lines2 = value._export_rows(fields2)
+ lines2 = value._export_rows(fields2, batch_invalidate=False)
if lines2:
# merge first line with record's main line
for j, val in enumerate(lines2[0]):
diff --git a/odoo/tools/config.py b/odoo/tools/config.py
index ec7cc0c0cb1..ddda566b68b 100644
--- a/odoo/tools/config.py
+++ b/odoo/tools/config.py
@@ -274,7 +274,7 @@ class configmanager(object):
type="int")
group.add_option("--unaccent", dest="unaccent", my_default=False, action="store_true",
help="Use the unaccent function provided by the database when available.")
- group.add_option("--geoip-db", dest="geoip_database", my_default='/usr/share/GeoIP/GeoLiteCity.dat',
+ group.add_option("--geoip-db", dest="geoip_database", my_default='/usr/share/GeoIP/GeoLite2-City.mmdb',
help="Absolute path to the GeoIP database file.")
parser.add_option_group(group)