diff --git a/addons/account/models/partner.py b/addons/account/models/partner.py index a1fa22a824c410f93baf5acb332e168778c44bab..40b1cd90ff54b51f1c910f00a00ee331c1c6bedb 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 b41576149667f22f9dcc616ec646b41af14947e3..bc325f129bd8328bca4afea3eeed222fbf3e883a 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 d498bb62afb2a13e00f32dba4a498864a2830f50..2f188b1abab44a9bc79fc4fc04947e1d11c18097 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 3d4ed0a9e9a6a0bb6671b4a1dbe5132f18555e7c..dba164388b90e3c39802d9a59890f998f8f34d1f 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 3bb25d93e730ffb3fe846541d403adb526c61ef3..3b29938007cf9f5d6e66781bb748bf0cec400e35 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 e2a5e6dbea985f100d10528b4db2773b7e5927fb..2916a512b51f696292c86d1d12e4d600c095b353 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 ff59aff918a3891c1f378f1df7d36f58b6b8e659..70ac02fefefe9371a7b50e4c12d77b2b6aaba3e1 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 11b81a6373a04569d8dede54b9993aa1de775e2e..a2dc616ee2c7e060997976f7f274a3ed7ab6bf14 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 4130b1d03478d4098bedcbe0f7a582d78a546085..f882bf7f5571665b74fff5c5572919d4a261afb8 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 55f3300da9157eec0b102960380a80f955ad1f80..df2d18a3feb1eaf7f8f5c154b7399a283ea36b1a 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 2e56eb39685ee8e318acaaf6dc5b5bfa11acb96d..5793908c02bc03ddf5b6f32070eceabb79b85925 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 0a1264dc589869eabf93d3107d0d5a43c0b7168b..6eaeae518b1caf38ef86cce6c9f57398c6a8caea 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 a7874c34c69b9012e98395d7226d41b99ef10a3b..c5c7d19a1b7bcab1914d4bba79b0c5056c86f8c9 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 30bb3c9dff27df67c88ecf7d4232bee5dfdd1071..fa2ce2b944b4f42b353151cc8a4099fa47f5eae6 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 e6d0f0905cffa9cbd72d8022b2106bfe605c63cc..fea714a5d7a26ccec303de1d6e7829a6db26ba5a 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 dc5e6b693d19dcacd224b7ab27b26f75e66cb7b2..7d34c7c054abd3105d5bb41fe9674111e1c27c16 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 0000000000000000000000000000000000000000..5d4b25db9c00182450a7328f8348aa3ad4ba706e --- /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 0000000000000000000000000000000000000000..206aff1d639d30d172a008297575bf78e9e9bda7 --- /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 0000000000000000000000000000000000000000..1f9b0e2272453753afe131450670ca9d136ec9aa --- /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 4011f4987d706681942ae40bb11fccc61a21aa0c..5a9343e03fffee113f5c972244728200121f6bbd 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 e2ef5e99a2954de637f49f57be9723826b18a07b..a2933bac8567b0aec2f85381b82bf5e47e5589e5 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 similarity index 81% rename from addons/l10n_ch/i18n_extra/de_CH.po rename to addons/l10n_ch/i18n_extra/de.po index 0f9c0b787265ee8068928deccc811f790c2b44e9..dfe1938442035962998365fe563ff74ffa60c40e 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 c24b83d6e1d2c6703d6c6fc0545338e3818eccdb..edc22fcd98892a0ed4c72b0b7643bca95279f387 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 135eb7f24c8e7a3091ea0fc539f698f4d7e7ac5f..61bc5d5d2a768d4da01f65ea759ba63bd446b137 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 db5bf0864acb59c5438aabe47009a00654cdcaf7..70826b6bbf5311da99cc6eadfd07469015247c8f 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 696cae7b228f6b4fafe9d82a56ef431f93378519..d616459cf6b91d1ed2964c73a5faaf52b354ec74 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 698a011b518183caab3c708a0dcdbeb47f4ad723..462fb38760db750b8a5aae50a837427da2b6b38f 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 7179966d999350c7c90ada13184b959f33a65147..03900817ec6473550702ad100c43bde56b3ca610 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 d9f71e984afc23fb9315bc642bbba22182294a6e..73e9958987338fa69f58cfb7d68008d17139d0c2 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 e2fae8b106e1a5d1dc34dabf53381676e242a3fd..affd87da0292956a4b5af8aa0d2793c04302c8e5 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 81dee297011b9f29c7af74b56fd5253b2f2b64fc..8b2bc671d50ed1d4a1b9c925897b98e86c658250 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 29adc15b64e741e4948a302879aa2dfd5a711efa..d405dafb4683247c372f785bb35fb6a10c06092c 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 7e023e01c7a97684a268e3af2c44f495ac203637..be70f46309e35b8665190cee9c9a09705784b2bd 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 1e0d5e7a0c255bfbf29b85527e4d136ef3883c63..372e8ba233d9f3ed4824ab199a1812e4f404d5d4 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 b10f2824733283ff05812b2a763795fdd6f1b966..fe17ee4add937e6485983722b7e9a760b07f7175 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 242fb20d265707845d3ea77101fd9ed76c00bd9b..3584cd38dc1d19d47775b6b804e62323f23c701a 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 fc713d703903fbe950a66b0fa15a977790140edf..9645a5e42886082b21d53c329d9605d141f2c894 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 5b55e88896dd6dcc47f111d2ea2b47b703c638ce..30baa7d4498a199844474f72e0bd72a3ad9fae34 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 f59d6f812644826d870946369a9413947c36fa7b..6a303b508a8174b36359e1013664c934cde6e196 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 c12a10ebfafd28f035f8580ea171ea059eff6f63..81ffa1c2c4fa79627a9e9c29f34b7fcaf6e015f7 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 320a9e84f38f791eb5b44f793fe5966587a909c0..c6570a37f8c33652f04f22e3b00e8a5f19b0d303 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 0000000000000000000000000000000000000000..b1cf9f59a60bc3a20319abf06c6f74990bed9af2 --- /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 64f24c95271504d73b9acc202527b123edc26365..7004ad9fad37eb5906dc3abd11bf92875983d8ff 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 5ff1a0d70e434deb43e1a36035ec673a43397bfc..b242868f8df89ba78cdd062513e2eb05a0dbbef9 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 65512565ba16c986c68cee2f7f1cb9581f40ba5d..eca5ffae0e9a8ce9aa16d8f1d01f3f0ccc6a6292 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 ade1f15c7290a2f41a3300accb49e8954a8b7667..72faef7f2079373a4431bf49f5def09786af2686 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 b561d5bcfcfdc5c2c2f69ce2029afcc59acc25bc..4ca2198b1fc0b20101d723f85820c49b59fdd659 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 58f0049a3dcd6c2b6fc72677f0a2e014de4c2490..a3d5d4e5e798ca76c3751e8fedcb033d7e19aa87 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 f068dbf9af13da3adb35c8aecc9afea8a306715f..994142c736207d87745debfd3b6db6c8a851a8ca 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 c0842efbe288bf1069b39efe6dfcec370585344b..b1eb662828b04e5df5e8846077945b025847be6f 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 5860dabd53c1abe4957b65b15cd6fb747873151f..15be2f959475f7e9d7199f03a6b55aac83ec4907 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 a03df305b166308ff5d9e249372ed005521aed7d..0a2406a096847bf3e22aa6e59fd9d7c76ed5a2aa 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 515d7634da2f1a68ca69d5b2915b0235a1058928..9c9addca79b7c477d8a5c76e16ee6e8581125540 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 3352f75b048f48af24a9be36c152122f6a7d5978..8f7c66edc1af907ce4be8cc7cb162ed9e339f6e4 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 631c3eeeb3a26facd3f6e8f68cd8bb6854b9b6f0..752a7a7c9fcd4a1bb9109cb0ae608bdbf2148929 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 2ff3586a943e7fc352c4718133976783d27354f9..0837de9ebae67be1ffd120f43801322635d69b26 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 4fc1092839d3e0910ee08d68d5de24bcfecc34c0..5a7a72074aabf9c3960e4b35b1818ed564f39e6b 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 93aee57f27b3669d7ed72e631659c18337714618..426f7037e285d03199890d2fb55dba9b9bbbfcbd 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 c0175c1380b00c38640aaed3b616de702005e8e9..d392bafc072b28f8d667a4341fdffd09155932fb 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 cd945d3bfe08603967dde69dbda31f5f0fda3216..548593374e75f9a368d1d15de60763f15ac2697a 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 1a4a386eed64cd732959c97dec640b43980c88c2..c71fee328379b243d01294f350ed47b703feac8f 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 a24f3b92726240f47d5edb721f7b47915a3caa7f..10832aa8bde25087c72a0829b40884a49a3c72af 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 a128f5a6942421d55c5be2f3be21db4731406d17..c29215f2b79e5060e216e4df03870fead07c7899 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 29fa3d737617317ceaa28f35cddf14541b07e9a3..50cc57885bbaea070f9fc23c0e538785ce75045e 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 6b92f62cf4bfad08f2922f255f4624b6adca5f73..db9bd7f373550bfc42ffbf025bf1138accaa4ebd 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 70c1d04e9da20d57dc8d71236a1e5ab619196a66..656d6ea7364f6cfa125292eab41ce8075dea84a4 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 3fbd834da9fd2e85ef2a0e0f85b59e6eb3d4237c..01b730d1fe403d1de293c29c745bdf797824611a 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 0000000000000000000000000000000000000000..6b244d13ac225c06cb69966a591b67b8c3834690 --- /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 a4a73ef79c8e0175182bb5ac9f20e0b0e5b4ffcc..af58b84a0e77bd9bd962d89b08b9ff35dec6f014 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 2fb0521ffb59db4b106038e58381bb1983f81838..fbb6d0e7c6b417336020d7d61df6f3b0466587ac 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1027,6 +1027,21 @@ var FieldPhone = FieldEmail.extend({ this.$el.removeClass('o_text_overflow'); }, + /** + * Remove possibly present ­ characters when saving number + * + * @override + * @private + */ + _setValue: function (value, options) { + // NOT NEEDED AS OF SAAS-11.3 + if (value) { + // remove possibly pasted ­ 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 diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 353da62706f9a49778e6f601459947b3a43cfbaa..a977147460ae2e572e5db4663c9d363c81d897a2 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 1007aa6c720affe12cb8ad18d402d179462d9a78..ff7ab5a43bb4c18ebc845009ba83ae27545b91c0 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 935fcc6643edf750ba62f6f66d421d220b9e50ab..2394fb31a64ed6d1532f3adb887485dd591e5dbc 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 b17562348f7d6b02b766cf71113d48dd309978d8..de9001c328a1408a718316b8b4c3698405f0e8b7 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 6467e4695c6cc2e514b842acdc4e1d22e9efecfa..92890766b346284192140845eb461c16231d737f 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 ea56c841c861de7aea8f489b2f9186d12a0b72dd..4c73fde121ba5bc38bd0261d9b207bb3f3188bd6 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 8ce6ec14aba25c5bcf6c1b0435663e8ea452ed0c..1fbd6572a9a8e5defea55ba1efffb8bcf8e8a9f7 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 8a779becdea9ec522ab5e506f2b59e55675282c7..9c227fba2ac5efda650562c8591d264fd89d973b 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 15d6284cfad7915ee8c130e1779666861ea7b694..411d4cc7b146ce553079650620bcca088797ed56 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 99c909efaccbd9657ef46302ccde1f1c0039e6b7..fdf3a585b57b3dbfba99278e1312e7b97a32ecee 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 ee9f1d9556ae5ff342f90102111f9eb52213ea7b..ff6fe9eb20bfea016d0c928ba41d17217fe893c3 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 60a3671caa26cfd83e450ab33e343ebc5143af79..c3cbe2e34948493112ec108f164cdbf687b99637 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 86fe0853de2eac581700d01f2303a38ff7c67d4b..f4cffd6c097357fd81a831536edcd72d4f10c06b 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 adf67f31bf0cdf8de408984e0205e7542a16e92a..947b78739f7ae17953b5d7e06c432214e4bd0cda 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 c6d81293fbf8048b8336569af7d2a6ddb77e69fc..73bd50e1966f57253e7e31fe78377a7b796b5975 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 e395d1a0d7ebb0d21e473b646220d151f841b9e7..f321db1d17263de028a073ece9634594beb6b6b2 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 ­ 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 b755dc3440c852839c92fcd5a8d4a92fd1d41543..64ffc31096cb5e7f7ff92603eadffeea8a23090a 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 b073bc988dd10f701afb4ffa682dc836e28cfe30..7430c6b994b11aa3d79ca10eb7889fdf4975c08e 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 b26cc8a3bd5970ab0901d5a977f53c4dd60639fa..7aed9cad8f9c9e73084a4a62143e8eaf9cb74d1f 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 d6e2b2d5ee6436b62a61874208c5765b12a44a44..aaf0f67cefbca2d612204d2df7e3fc2a48364731 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 58710987a518e3eecef61a20858e5aeccfaaf260..dc97da3736562679e73efd748209d145580d260f 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 425859decd912b1ec21b75aad3e7e295b21db0b0..62d862afe35a6ca90cd9b397fd075eec67eea76e 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 ba58f7905973effe7c27000e3ed747903c5fdff3..0e5443ad79e117f2c10a903e6537f304ffb17552 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 @@ -104,6 +104,11 @@ class Http(models.AbstractModel): return request.website.default_lang_id 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 fef2c038777df316f282801f81aa8b8c461c9b56..b291d340aa78ac3078a35ebcfbbb852b30f53cde 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 5318a84067dd03c7648b4a17d1696b61dc38ddc6..512c7a0269c1081eb2788df60b15edb9d6ec674d 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 308df119a160695401e05df5364894981599db19..ad67e5e9439a05d6739503bfae961156726ce16b 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 ab48523b6629eee77d62b2302dfbcd006c6cadc1..197ac1dbf0d3b96dbb335d97bab62792cd03b4dd 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 10ff83552ed666f9cefbf54ee976e9ab38214c11..47921e7154775f88c2d60f5dea8f349533575500 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 e9f22845bda9c5f10297fe27c72ad653fcab02d9..770ee2a9c4eb74298b111c32e02a2c7e9aa2dbc4 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 e9ebff51ad0868d5eb1fd8a33bea93612266f15b..c9fd9a6b25e71a55908714f7e9702ac332e599df 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 0000000000000000000000000000000000000000..c3e6c9349d831295c88d4f09623f0bf84e90435f --- /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 34ed9c479570bdeab5502ffd33ad82589abe79e3..3eb511140a3ec706d0d59a59cb09e3148697057e 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 0000000000000000000000000000000000000000..c19627a953b89254026896657eb3ad1f4eb025c2 --- /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 0000000000000000000000000000000000000000..26b13dd0957e0d9febd84d31c19612a0d032eaa4 --- /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 4fcb14d7d31c1c343ba86ec0d08da263b1c90a29..1d306318534decd679bd73d63047ec3e09aa5d16 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 51fb604929c8beca300ea9515ed4b6cb9ac51c17..8571d12425950fb2ed5a54f94cae5b17cdb63536 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 8307599638927288ccac5bdd09a6383abc9db39e..81659d8a50db8b593bce9a1f76ed8b0a27122e65 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 0000000000000000000000000000000000000000..4ce2219f4cb3d11c5ba2eb80df2687b12086b99b --- /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 be2dea9c3029fa3f1f69b23a706ebef8b1b03cc9..a53fcad358d4dcdc4dfd0850fe720467c6259229 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 ddc41dca404c7e103f3d07a85db9e67f4c7055ef..933309ad1902ec57a1558d46c5fa957f228d475a 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 34591fcf2746e15748b27e6cc60886067fcbf69d..840181ae43b18aeb4d2e69a1205842fba775181f 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 fdbb6fff9f2f8e9a83fc3777722b5a427f4f8790..db41e2370cedaafb49af2e2e3c8a4f6659631d84 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 6e2d8cf5dc8ef4c64f719a7c5c9deb297a06638f..d9c56dfe558bec0642a1ea9ed53eca63af41e746 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 220e78496685bd76a643de34c057519c68759359..99fcdcf05f702c545e5e627ef6f1ee7483356648 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 073eedfb53569b894b7303a3f8ff647abbb0cd03..a330b7d3dd3d0733ec0141bca4cb7f23d9e3da24 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 54b4d106120c27ef07f8049d1c43879c21ee318b..509bb548ecc44ab7db54039a3fc66164d6ff8486 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 6e42f8adf1dde55b7585ffe470d8eb8e5e27d5ae..a5f9198230396e3d2afa671331c73d6d09319c04 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 cb2bd2b436865738ff99aceb2ed06de755786d11..e06f345964d8258acbd04c659eb3eb60f234e277 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 bcb0036c8dfa5ef3eb9fc7c81e0f44a862589722..e64099a99aeda9c713c0b154fda83719f26b56f6 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 ec7cc0c0cb1b7f3bd7bcf64ca0ab298d47ba4bce..ddda566b68b77e0ce6f09b4371caea9d072cee7c 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)