summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/account/models/account_invoice.py8
-rw-r--r--addons/account/report/account_aged_partner_balance.py2
-rw-r--r--addons/account/static/src/scss/account_reconciliation.scss6
-rw-r--r--addons/account/wizard/account_invoice_send_views.xml1
-rw-r--r--addons/account_payment/controllers/payment.py4
-rw-r--r--addons/crm/models/crm_lead.py4
-rw-r--r--addons/crm/tests/test_new_lead_notification.py92
-rw-r--r--addons/event_sale/models/sale_order.py10
-rw-r--r--addons/event_sale/wizard/event_edit_registration.xml2
-rw-r--r--addons/hr_holidays/models/hr_leave.py2
-rw-r--r--addons/hr_holidays/models/hr_leave_type.py25
-rw-r--r--addons/hr_org_chart/static/src/xml/hr_org_chart.xml1
-rw-r--r--addons/hr_timesheet/views/project_views.xml46
-rwxr-xr-xaddons/hw_drivers/controllers/driver.py34
-rw-r--r--addons/hw_posbox_homepage/controllers/main.py14
-rw-r--r--addons/hw_posbox_homepage/views/homepage.html3
-rw-r--r--addons/im_livechat/models/mail_channel.py7
-rw-r--r--addons/l10n_be/i18n_extra/l10n_be.pot527
-rw-r--r--addons/l10n_be/i18n_extra/nl.po77
-rw-r--r--addons/l10n_be_invoice_bba/data/mail_template_data.xml2
-rw-r--r--addons/mail/models/mail_channel.py9
-rw-r--r--addons/mail/static/src/js/utils.js2
-rw-r--r--addons/mass_mailing/static/src/scss/mass_mailing.scss6
-rw-r--r--addons/mass_mailing/views/unsubscribe_templates.xml4
-rw-r--r--addons/mass_mailing_crm/data/mass_mailing_demo.xml2
-rw-r--r--addons/mrp/models/mrp_production.py5
-rw-r--r--addons/mrp/models/stock_move.py18
-rw-r--r--addons/mrp/report/mrp_production_templates.xml57
-rw-r--r--addons/mrp/report/mrp_report_views_main.xml9
-rw-r--r--addons/mrp/tests/test_order.py47
-rw-r--r--addons/mrp/wizard/change_production_qty.py4
-rw-r--r--addons/payment/models/payment_acquirer.py2
-rw-r--r--addons/payment/wizards/payment_acquirer_onboarding_wizard.py3
-rw-r--r--addons/point_of_sale/models/pos_order.py16
-rw-r--r--addons/point_of_sale/static/src/js/chrome.js2
-rwxr-xr-xaddons/point_of_sale/tools/posbox/configuration/posbox_update.sh7
-rwxr-xr-xaddons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh4
-rw-r--r--addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cups-files.conf93
-rw-r--r--addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cupsd.conf188
-rw-r--r--addons/point_of_sale/tools/posbox/overwrite_after_init/etc/nginx/sites-enabled/default10
-rw-r--r--addons/point_of_sale/tools/posbox/overwrite_after_init/var/www/iot.jpgbin0 -> 5444 bytes
-rwxr-xr-xaddons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh66
-rwxr-xr-xaddons/point_of_sale/tools/posbox/posbox_create_image.sh2
-rw-r--r--addons/product/models/product.py4
-rw-r--r--addons/product/views/product_views.xml2
-rw-r--r--addons/purchase/models/res_partner.py35
-rw-r--r--addons/purchase/report/purchase_bill.py2
-rw-r--r--addons/purchase/views/purchase_views.xml1
-rw-r--r--addons/sale/models/sale.py15
-rw-r--r--addons/sale/views/sale_views.xml2
-rw-r--r--addons/sale_management/models/sale_order.py15
-rw-r--r--addons/snailmail/static/src/scss/snailmail_external_layout_asset.scss3
-rw-r--r--addons/stock_account/models/product.py11
-rw-r--r--addons/stock_account/views/stock_account_views.xml3
-rw-r--r--addons/survey/controllers/main.py4
-rw-r--r--addons/web/static/src/js/chrome/abstract_web_client.js4
-rw-r--r--addons/web/static/src/js/chrome/apps_menu.js3
-rw-r--r--addons/web/static/src/js/fields/special_fields.js3
-rw-r--r--addons/web/static/src/js/services/crash_manager.js35
-rw-r--r--addons/web/static/src/js/views/basic/basic_controller.js12
-rw-r--r--addons/web/static/src/js/views/field_manager_mixin.js6
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_controller.js29
-rw-r--r--addons/web/static/src/js/views/pivot/pivot_model.js35
-rw-r--r--addons/web/static/tests/fields/relational_fields_tests.js97
-rw-r--r--addons/web/static/tests/views/form_tests.js63
-rw-r--r--addons/web/static/tests/views/kanban_tests.js61
-rw-r--r--addons/web/static/tests/views/pivot_tests.js74
-rw-r--r--addons/web_editor/controllers/main.py12
-rw-r--r--addons/web_tour/__manifest__.py2
-rw-r--r--addons/web_tour/static/src/js/tip.js1
-rw-r--r--addons/web_tour/static/src/js/tour_manager.js27
-rw-r--r--addons/web_tour/static/src/js/tour_service.js26
-rw-r--r--addons/website/models/ir_ui_view.py51
-rw-r--r--addons/website/models/website.py2
-rw-r--r--addons/website/static/src/js/menu/new_content.js2
-rw-r--r--addons/website/static/src/scss/website.edit_mode.scss2
-rw-r--r--addons/website/static/src/xml/website.editor.xml2
-rw-r--r--addons/website/tests/test_views.py98
-rw-r--r--addons/website_forum/views/forum.xml13
-rw-r--r--addons/website_sale/controllers/main.py2
-rw-r--r--addons/website_sale/static/src/js/website_sale_tour_buy.js2
-rw-r--r--addons/website_sale_comparison/controllers/main.py7
-rw-r--r--addons/website_sale_wishlist/static/src/js/website_sale_tour_wishlist.js11
-rw-r--r--addons/website_slides/views/website_slides_embed_templates.xml2
-rw-r--r--doc/cla/corporate/merchise.md1
-rw-r--r--doc/cla/individual/dipsshah42.md9
-rw-r--r--doc/cla/individual/ehansejoerg.md11
-rw-r--r--doc/cla/individual/i-vyshnevska.md9
-rw-r--r--doc/cla/individual/stanisljevic.md11
-rw-r--r--odoo/addons/base/models/ir_actions.py2
-rw-r--r--odoo/addons/base/models/ir_module.py3
-rw-r--r--odoo/addons/base/models/res_partner.py4
-rw-r--r--odoo/addons/base/wizard/base_partner_merge.py8
-rw-r--r--odoo/addons/test_main_flows/static/src/js/tour.js17
-rw-r--r--odoo/addons/test_new_api/ir.model.access.csv1
-rw-r--r--odoo/addons/test_new_api/models.py7
-rw-r--r--odoo/addons/test_new_api/tests/test_one2many.py19
-rw-r--r--odoo/models.py16
-rw-r--r--odoo/modules/module.py6
-rw-r--r--odoo/tests/common.py10
100 files changed, 1640 insertions, 698 deletions
diff --git a/addons/account/models/account_invoice.py b/addons/account/models/account_invoice.py
index 50760c25ff9..accec89538a 100644
--- a/addons/account/models/account_invoice.py
+++ b/addons/account/models/account_invoice.py
@@ -772,12 +772,12 @@ class AccountInvoice(models.Model):
msg = _('Cannot find a chart of accounts for this company, You should configure it. \nPlease go to Account Configuration.')
raise RedirectWarning(msg, action.id, _('Go to the configuration panel'))
- if type in ('out_invoice', 'out_refund'):
- account_id = rec_account.id
- payment_term_id = p.property_payment_term_id.id
- else:
+ if type in ('in_invoice', 'in_refund'):
account_id = pay_account.id
payment_term_id = p.property_supplier_payment_term_id.id
+ else:
+ account_id = rec_account.id
+ payment_term_id = p.property_payment_term_id.id
delivery_partner_id = self.get_delivery_partner_id()
fiscal_position = self.env['account.fiscal.position'].get_fiscal_position(self.partner_id.id, delivery_id=delivery_partner_id)
diff --git a/addons/account/report/account_aged_partner_balance.py b/addons/account/report/account_aged_partner_balance.py
index 6df0ffb1274..bc660b494b3 100644
--- a/addons/account/report/account_aged_partner_balance.py
+++ b/addons/account/report/account_aged_partner_balance.py
@@ -28,7 +28,7 @@ class ReportAgedPartnerBalance(models.AbstractModel):
ctx = self._context
periods = {}
date_from = fields.Date.from_string(date_from)
- start = date_from - relativedelta(days=1)
+ start = date_from
for i in range(5)[::-1]:
stop = start - relativedelta(days=period_length)
period_name = str((5-(i+1)) * period_length + 1) + '-' + str((5-i) * period_length)
diff --git a/addons/account/static/src/scss/account_reconciliation.scss b/addons/account/static/src/scss/account_reconciliation.scss
index 0eda5d43fc0..1d94d0cbcb7 100644
--- a/addons/account/static/src/scss/account_reconciliation.scss
+++ b/addons/account/static/src/scss/account_reconciliation.scss
@@ -292,6 +292,10 @@
overflow: auto;
border: 1px solid #ddd;
border-radius: 0 0 5px 5px;
+ > div.quick_add > .o_reconcile_models {
+ max-height: 54px;
+ overflow: auto;
+ }
}
.quick_add {
margin-bottom: 7px;
@@ -360,4 +364,4 @@
}
}
}
-} \ No newline at end of file
+}
diff --git a/addons/account/wizard/account_invoice_send_views.xml b/addons/account/wizard/account_invoice_send_views.xml
index 90ecfadf793..6052c1438d9 100644
--- a/addons/account/wizard/account_invoice_send_views.xml
+++ b/addons/account/wizard/account_invoice_send_views.xml
@@ -83,7 +83,6 @@
view_type="form"
context="{
'default_template_id': ref('account.email_template_edi_invoice'),
- 'default_is_print': False,
'mark_invoice_as_sent': True,
}"
groups="account.group_account_invoice"/>
diff --git a/addons/account_payment/controllers/payment.py b/addons/account_payment/controllers/payment.py
index 496a158563e..8ac01bd398d 100644
--- a/addons/account_payment/controllers/payment.py
+++ b/addons/account_payment/controllers/payment.py
@@ -77,11 +77,11 @@ class PaymentPortal(http.Controller):
vals = {
'payment_token_id': token.id,
'type': 'server2server',
- 'return_url': success_url,
+ 'return_url': _build_url_w_params(success_url, params),
}
tx = invoice_sudo._create_payment_transaction(vals)
PaymentProcessing.add_payment_transaction(tx)
params['success'] = 'pay_invoice'
- return request.redirect(_build_url_w_params(success_url, params))
+ return request.redirect('/payment/process')
diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py
index a3c20bd00de..a5d7dae73a6 100644
--- a/addons/crm/models/crm_lead.py
+++ b/addons/crm/models/crm_lead.py
@@ -1205,6 +1205,10 @@ class Lead(models.Model):
if msg_dict.get('priority') in dict(crm_stage.AVAILABLE_PRIORITIES):
defaults['priority'] = msg_dict.get('priority')
defaults.update(custom_values)
+
+ # assign right company
+ if 'company_id' not in defaults and 'team_id' in defaults:
+ defaults['company_id'] = self.env['crm.team'].browse(defaults['team_id']).company_id.id
return super(Lead, self).message_new(msg_dict, custom_values=defaults)
def _message_post_after_hook(self, message, *args, **kwargs):
diff --git a/addons/crm/tests/test_new_lead_notification.py b/addons/crm/tests/test_new_lead_notification.py
index dedcd02449a..16228fcc55c 100644
--- a/addons/crm/tests/test_new_lead_notification.py
+++ b/addons/crm/tests/test_new_lead_notification.py
@@ -41,3 +41,95 @@ class NewLeadNotification(TestCrmCases):
# The user should have a new unread message
lead_user = lead.sudo(self.crm_salesman)
self.assertTrue(lead_user.message_needaction)
+
+ def test_new_lead_from_email_multicompany(self):
+ company0 = self.env.user.company_id
+ company1 = self.env['res.company'].create({'name': 'new_company'})
+
+ self.env.user.write({
+ 'company_ids': [(4, company0.id, False), (4, company1.id, False)],
+ })
+
+ crm_team_model = self.env['ir.model'].search([('model', '=', 'crm.team')])
+ crm_lead_model = self.env['ir.model'].search([('model', '=', 'crm.lead')])
+ self.env["ir.config_parameter"].sudo().set_param("mail.catchall.domain", 'aqualung.com')
+
+ crm_team0 = self.env['crm.team'].create({
+ 'name': 'crm team 0',
+ 'company_id': company0.id,
+ })
+ crm_team1 = self.env['crm.team'].create({
+ 'name': 'crm team 1',
+ 'company_id': company1.id,
+ })
+
+ mail_alias0 = self.env['mail.alias'].create({
+ 'alias_name': 'sale_team_0',
+ 'alias_model_id': crm_lead_model.id,
+ 'alias_parent_model_id': crm_team_model.id,
+ 'alias_parent_thread_id': crm_team0.id,
+ 'alias_defaults': "{'type': 'opportunity', 'team_id': %s}" % crm_team0.id,
+ })
+ mail_alias1 = self.env['mail.alias'].create({
+ 'alias_name': 'sale_team_1',
+ 'alias_model_id': crm_lead_model.id,
+ 'alias_parent_model_id': crm_team_model.id,
+ 'alias_parent_thread_id': crm_team1.id,
+ 'alias_defaults': "{'type': 'opportunity', 'team_id': %s}" % crm_team1.id,
+ })
+
+ crm_team0.write({'alias_id': mail_alias0.id})
+ crm_team1.write({'alias_id': mail_alias1.id})
+
+ new_message0 = """MIME-Version: 1.0
+Date: Thu, 27 Dec 2018 16:27:45 +0100
+Message-ID: blablabla0
+Subject: sale team 0 in company 0
+From: A client <client_a@someprovider.com>
+To: sale_team_0@aqualung.com
+Content-Type: multipart/alternative; boundary="000000000000a47519057e029630"
+
+--000000000000a47519057e029630
+Content-Type: text/plain; charset="UTF-8"
+
+
+--000000000000a47519057e029630
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+<div>A good message</div>
+
+--000000000000a47519057e029630--
+"""
+
+ new_message1 = """MIME-Version: 1.0
+Date: Thu, 27 Dec 2018 16:27:45 +0100
+Message-ID: blablabla1
+Subject: sale team 1 in company 1
+From: B client <client_b@someprovider.com>
+To: sale_team_1@aqualung.com
+Content-Type: multipart/alternative; boundary="000000000000a47519057e029630"
+
+--000000000000a47519057e029630
+Content-Type: text/plain; charset="UTF-8"
+
+
+--000000000000a47519057e029630
+Content-Type: text/html; charset="UTF-8"
+Content-Transfer-Encoding: quoted-printable
+
+<div>A good message bis</div>
+
+--000000000000a47519057e029630--
+"""
+ crm_lead0_id = self.env['mail.thread'].message_process('crm.lead', new_message0)
+ crm_lead1_id = self.env['mail.thread'].message_process('crm.lead', new_message1)
+
+ crm_lead0 = self.env['crm.lead'].browse(crm_lead0_id)
+ crm_lead1 = self.env['crm.lead'].browse(crm_lead1_id)
+
+ self.assertEqual(crm_lead0.team_id, crm_team0)
+ self.assertEqual(crm_lead1.team_id, crm_team1)
+
+ self.assertEqual(crm_lead0.company_id, company0)
+ self.assertEqual(crm_lead1.company_id, company1)
diff --git a/addons/event_sale/models/sale_order.py b/addons/event_sale/models/sale_order.py
index b749f615293..1b15093de03 100644
--- a/addons/event_sale/models/sale_order.py
+++ b/addons/event_sale/models/sale_order.py
@@ -12,8 +12,16 @@ class SaleOrder(models.Model):
for so in self:
# confirm registration if it was free (otherwise it will be confirmed once invoice fully paid)
so.order_line._update_registrations(confirm=so.amount_total == 0, cancel_to_draft=False)
+ return res
+
+ @api.multi
+ def action_confirm(self):
+ res = super(SaleOrder, self).action_confirm()
+ for so in self:
if any(so.order_line.filtered(lambda line: line.event_id)):
- return self.env['ir.actions.act_window'].with_context(default_sale_order_id=so.id).for_xml_id('event_sale', 'action_sale_order_event_registration')
+ return self.env['ir.actions.act_window'] \
+ .with_context(default_sale_order_id=so.id) \
+ .for_xml_id('event_sale', 'action_sale_order_event_registration')
return res
diff --git a/addons/event_sale/wizard/event_edit_registration.xml b/addons/event_sale/wizard/event_edit_registration.xml
index 92a69107ba7..25422c2947a 100644
--- a/addons/event_sale/wizard/event_edit_registration.xml
+++ b/addons/event_sale/wizard/event_edit_registration.xml
@@ -12,7 +12,7 @@
<tree string="Registration" editable="top" create="false" delete="false">
<field name="event_id" readonly='1' force_save="1"/>
<field name="registration_id" readonly='1' force_save="1"/>
- <field name="event_ticket_id" domain="[('event_id', '=', event_id)]" readonly='1'/>
+ <field name="event_ticket_id" domain="[('event_id', '=', event_id)]" readonly='1' force_save="1"/>
<field name="name"/>
<field name="email"/>
<field name="phone"/>
diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py
index 24062454dca..37e12bd0c86 100644
--- a/addons/hr_holidays/models/hr_leave.py
+++ b/addons/hr_holidays/models/hr_leave.py
@@ -427,7 +427,7 @@ class HolidaysRequest(models.Model):
employee = self.env['hr.employee'].browse(employee_id)
return employee.get_work_days_data(date_from, date_to)['days']
- return self.env.user.company_id.resource_calendar_id.get_work_hours_count() / HOURS_PER_DAY
+ return self.env.user.company_id.resource_calendar_id.get_work_hours_count(date_from, date_to) / HOURS_PER_DAY
####################################################
# ORM Overrides methods
diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py
index c542ea14909..a0e9ba65e8d 100644
--- a/addons/hr_holidays/models/hr_leave_type.py
+++ b/addons/hr_holidays/models/hr_leave_type.py
@@ -8,6 +8,7 @@ import logging
from odoo import api, fields, models
from odoo.exceptions import ValidationError
+from odoo.osv import expression
from odoo.tools.translate import _
from odoo.tools.float_utils import float_round
@@ -207,9 +208,18 @@ class HolidaysType(models.Model):
@api.multi
def _compute_group_days_allocation(self):
+ domain = [
+ ('holiday_status_id', 'in', self.ids),
+ ('holiday_type', '!=', 'employee'),
+ ('state', '=', 'validate'),
+ ]
+ domain2 = [
+ '|',
+ ('date_from', '>=', fields.Datetime.to_string(datetime.datetime.now().replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0))),
+ ('date_from', '=', False),
+ ]
grouped_res = self.env['hr.leave.allocation'].read_group(
- [('holiday_status_id', 'in', self.ids), ('holiday_type', '!=', 'employee'), ('state', '=', 'validate'),
- ('date_from', '>=', fields.Datetime.to_string(datetime.datetime.now().replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)))],
+ expression.AND([domain, domain2]),
['holiday_status_id', 'number_of_days'],
['holiday_status_id'],
)
@@ -270,11 +280,16 @@ class HolidaysType(models.Model):
def action_see_days_allocated(self):
self.ensure_one()
action = self.env.ref('hr_holidays.hr_leave_allocation_action_all').read()[0]
- action['domain'] = [
+ domain = [
+ ('holiday_status_id', 'in', self.ids),
('holiday_type', '!=', 'employee'),
- ('holiday_status_id', '=', self.ids[0]),
- ('date_from', '>=', fields.Datetime.to_string(datetime.datetime.now().replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)))
]
+ domain2 = [
+ '|',
+ ('date_from', '>=', fields.Datetime.to_string(datetime.datetime.now().replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0))),
+ ('date_from', '=', False),
+ ]
+ action['domain'] = expression.AND([domain, domain2])
action['context'] = {
'default_holiday_type': 'department',
'default_holiday_status_id': self.ids[0],
diff --git a/addons/hr_org_chart/static/src/xml/hr_org_chart.xml b/addons/hr_org_chart/static/src/xml/hr_org_chart.xml
index fa5db5f32a8..893e0394f90 100644
--- a/addons/hr_org_chart/static/src/xml/hr_org_chart.xml
+++ b/addons/hr_org_chart/static/src/xml/hr_org_chart.xml
@@ -104,6 +104,7 @@
<div class="o_media_left">
<a href="#"
t-att-data-employee-id="self.id"
+ t-att-data-employee-name="self.name"
class="o_org_chart_show_more text-center o_employee_sub_redirect">&#8230;</a>
</div>
</div>
diff --git a/addons/hr_timesheet/views/project_views.xml b/addons/hr_timesheet/views/project_views.xml
index 5c51e6eb4d5..3296f9c891a 100644
--- a/addons/hr_timesheet/views/project_views.xml
+++ b/addons/hr_timesheet/views/project_views.xml
@@ -81,7 +81,7 @@
You can not log timesheets on this project since is linked to an inactive analytic account. Please change it, or reactivate the current one to timesheet on the project.
</div>
</group>
- <field name="timesheet_ids" attrs="{'invisible': [('analytic_account_active', '=', False)]}" context="{'default_project_id': project_id, 'default_name':''}">
+ <field name="timesheet_ids" mode="tree,kanban" attrs="{'invisible': [('analytic_account_active', '=', False)]}" context="{'default_project_id': project_id, 'default_name':''}">
<tree editable="bottom" string="Timesheet Activities" default_order="date">
<field name="date"/>
<field name="user_id" invisible="1"/>
@@ -90,6 +90,50 @@
<field name="unit_amount" widget="timesheet_uom"/>
<field name="project_id" invisible="1"/>
</tree>
+ <kanban class="o_kanban_mobile">
+ <field name="date"/>
+ <field name="user_id"/>
+ <field name="employee_id"/>
+ <field name="name"/>
+ <field name="unit_amount"/>
+ <field name="project_id"/>
+ <templates>
+ <t t-name="kanban-box">
+ <div t-attf-class="oe_kanban_card oe_kanban_global_click">
+ <div class="row">
+ <div class="col-xs-6">
+ <strong><span><t t-esc="record.employee_id.value"/></span></strong>
+ </div>
+ <div class="col-xs-6 pull-right text-right">
+ <strong><t t-esc="record.date.value"/></strong>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-xs-6 text-muted">
+ <span><t t-esc="record.name.value"/></span>
+ </div>
+ <div class="col-xs-6">
+ <span class="pull-right text-right">
+ <field name="unit_amount" widget="float_time"/>
+ </span>
+ </div>
+ </div>
+ </div>
+ </t>
+ </templates>
+ </kanban>
+ <form string="Timesheet Activities">
+ <sheet>
+ <group>
+ <field name="date"/>
+ <field name="user_id" invisible="1"/>
+ <field name="employee_id" required="1"/>
+ <field name="name"/>
+ <field name="unit_amount" string="Duration" widget="float_time"/>
+ <field name="project_id" invisible="1"/>
+ </group>
+ </sheet>
+ </form>
</field>
<group attrs="{'invisible': [('analytic_account_active', '=', False)]}">
<group class="oe_subtotal_footer oe_right" name="project_hours">
diff --git a/addons/hw_drivers/controllers/driver.py b/addons/hw_drivers/controllers/driver.py
index 7e2a775e4b7..3772dfa32f9 100755
--- a/addons/hw_drivers/controllers/driver.py
+++ b/addons/hw_drivers/controllers/driver.py
@@ -344,15 +344,19 @@ def send_iot_box_device(send_printer):
printerList = {}
if send_printer:
printers = subprocess.check_output("sudo lpinfo -lv", shell=True).decode('utf-8').split('Device')
+ printers_installed = ''
+ try:
+ printers_installed = subprocess.check_output("sudo lpstat -a", shell=True).decode('utf-8')
+ except:
+ pass
for printer in printers:
printerTab = printer.split('\n')
- if printer and printerTab[4].split('=')[1] != ' ':
+ if printer and printerTab[4].split('=')[1] != ' ' or 'lpd://' in printerTab[0]:
device_connection = printerTab[1].split('= ')[1]
model = ''
for device_id in printerTab[4].split('= ')[1].split(';'):
if any(x in device_id for x in ['MDL','MODEL']):
model = device_id.split(':')[1]
- name = printerTab[2].split('= ')[1]
serial = re.sub('[^a-zA-Z0-9 ]+', '', model).replace(' ','_')
identifier = ''
if device_connection == 'direct':
@@ -361,6 +365,9 @@ def send_iot_box_device(send_printer):
socketIP = printerTab[0].split('://')[1]
macprinter = subprocess.check_output("arp -a " + socketIP + " |awk NR==1'{print $4}'", shell=True).decode('utf-8').split('\n')[0]
identifier = macprinter # macPRINTER
+ elif device_connection == 'network' and 'lpd' in printerTab[0]:
+ identifier = re.sub('[^a-zA-Z0-9 ]+', '', printerTab[0].split('://')[1])
+ model = printerTab[2].split('= ')[1]
elif device_connection == 'network' and 'dnssd' in printerTab[0]:
hostname_printer = subprocess.check_output("ippfind -n \"" + model + "\" | awk \'{split($0,a,\"/\"); print a[3]}\' | awk \'{split($0,b,\":\"); print b[1]}\'", shell=True).decode('utf-8').split('\n')[0]
if hostname_printer:
@@ -375,15 +382,16 @@ def send_iot_box_device(send_printer):
'type': 'printer'
}
- # install these printers
- try:
- ppd = subprocess.check_output("sudo lpinfo -m |grep '" + model + "'", shell=True).decode('utf-8').split('\n')
- if len(ppd) > 2:
+ if identifier not in printers_installed:
+ # install these printers
+ try:
+ ppd = subprocess.check_output("sudo lpinfo -m |grep '" + model + "'", shell=True).decode('utf-8').split('\n')
+ if len(ppd) > 2:
+ subprocess.call("sudo lpadmin -p '" + identifier + "' -E -v '" + printerTab[0].split('= ')[1] + "'", shell=True)
+ else:
+ subprocess.call("sudo lpadmin -p '" + identifier + "' -E -v '" + printerTab[0].split('= ')[1] + "' -m '" + ppd[0].split(' ')[0] + "'", shell=True)
+ except:
subprocess.call("sudo lpadmin -p '" + identifier + "' -E -v '" + printerTab[0].split('= ')[1] + "'", shell=True)
- else:
- subprocess.call("sudo lpadmin -p '" + identifier + "' -E -v '" + printerTab[0].split('= ')[1] + "' -m '" + ppd[0].split(' ')[0] + "'", shell=True)
- except:
- subprocess.call("sudo lpadmin -p '" + identifier + "' -E -v '" + printerTab[0].split('= ')[1] + "'", shell=True)
subprocess.call('> /tmp/printers', shell=True)
for printer in printerList:
subprocess.call('echo "' + printerList[printer]['name'] + '" >> /tmp/printers', shell=True)
@@ -409,14 +417,16 @@ def send_iot_box_device(send_printer):
data['devices'] = devicesList
data_json = json.dumps(data).encode('utf8')
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
- http = urllib3.PoolManager()
+ urllib3.disable_warnings()
+ http = urllib3.PoolManager(cert_reqs='CERT_NONE')
req = False
try:
req = http.request('POST',
url,
body=data_json,
headers=headers)
- except:
+ except Exception as e:
_logger.warning('Could not reach configured server')
+ _logger.error('A error encountered : %s ' % e)
diff --git a/addons/hw_posbox_homepage/controllers/main.py b/addons/hw_posbox_homepage/controllers/main.py
index 3a21ba8cdae..f3de5a0d138 100644
--- a/addons/hw_posbox_homepage/controllers/main.py
+++ b/addons/hw_posbox_homepage/controllers/main.py
@@ -119,12 +119,15 @@ class IoTboxHomepage(odoo.addons.web.controllers.main.Home):
f = open('/tmp/devices', 'r')
for line in f:
url = 'http://' + self.get_ip_iotbox() + ':8069/hw_drivers/driverdetails/' + line.split('|')[0]
- http = urllib3.PoolManager()
+ urllib3.disable_warnings()
+ http = urllib3.PoolManager(cert_reqs='CERT_NONE')
value = ''
try:
req = http.request('GET', url)
- except:
+ except Exception as e:
req = ''
+ _logger.warning('Could not reach configured server')
+ _logger.error('A error encountered : %s ' % e)
if req:
value = req.data.decode('utf-8')
@@ -193,15 +196,18 @@ class IoTboxHomepage(odoo.addons.web.controllers.main.Home):
#response = requests.get(url, auth=(username, db_uuid.split('\n')[0]), stream=True)
server = self.get_server_status()
if server:
- pm = urllib3.PoolManager()
+ urllib3.disable_warnings()
+ pm = urllib3.PoolManager(cert_reqs='CERT_NONE')
resp = False
server = server + '/iot/get_drivers'
try:
resp = pm.request('POST',
server,
fields={'mac': mac})
- except:
+ except Exception as e:
+ req = ''
_logger.warning('Could not reach configured server')
+ _logger.error('A error encountered : %s ' % e)
if resp and resp.data:
zip_file = zipfile.ZipFile(io.BytesIO(resp.data))
zip_file.extractall("/home/pi/odoo/addons/hw_drivers/drivers")
diff --git a/addons/hw_posbox_homepage/views/homepage.html b/addons/hw_posbox_homepage/views/homepage.html
index e952e5620f4..71c0f26c565 100644
--- a/addons/hw_posbox_homepage/views/homepage.html
+++ b/addons/hw_posbox_homepage/views/homepage.html
@@ -90,7 +90,7 @@
</tr>
<tr>
<td class="heading">Version</td>
- <td>V18.10 <a class="btn btn-sm float-right" href='/hw_proxy/upgrade/'>update</a></td>
+ <td>V18.12 <a class="btn btn-sm float-right" href='/hw_proxy/upgrade/'>update</a></td>
</tr>
<tr>
<td class="heading">IP Address</td>
@@ -136,5 +136,6 @@
<div style="margin: 20px auto 10px auto;" class="text-center">
<a class="btn" href='/point_of_sale/display'>POS Display</a>
<a class="btn" style="margin-left: 10px;" href='/remote_connect'>Remote Debug</a>
+ <a target="_blank" class="btn" style="margin-left: 10px;" href="http://{{ ip }}:631">Printers server</a>
</div>
{% endblock %}
diff --git a/addons/im_livechat/models/mail_channel.py b/addons/im_livechat/models/mail_channel.py
index bb38a314fb0..8b81501db20 100644
--- a/addons/im_livechat/models/mail_channel.py
+++ b/addons/im_livechat/models/mail_channel.py
@@ -42,6 +42,13 @@ class MailChannel(models.Model):
'Livechat Operator ID is required for a channel of type livechat.')]
@api.multi
+ def _compute_is_chat(self):
+ super(MailChannel, self)._compute_is_chat()
+ for record in self:
+ if record.channel_type == 'livechat':
+ record.is_chat = True
+
+ @api.multi
def _channel_message_notifications(self, message):
""" When a anonymous user create a mail.channel, the operator is not notify (to avoid massive polling when
clicking on livechat button). So when the anonymous person is sending its FIRST message, the channel header
diff --git a/addons/l10n_be/i18n_extra/l10n_be.pot b/addons/l10n_be/i18n_extra/l10n_be.pot
index 0697b138641..cf3158c7467 100644
--- a/addons/l10n_be/i18n_extra/l10n_be.pot
+++ b/addons/l10n_be/i18n_extra/l10n_be.pot
@@ -4,10 +4,10 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 11.0alpha1\n"
+"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-03-06 12:52+0000\n"
-"PO-Revision-Date: 2017-03-06 12:52+0000\n"
+"POT-Creation-Date: 2019-01-17 08:59+0000\n"
+"PO-Revision-Date: 2019-01-17 08:59+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -16,950 +16,779 @@ msgstr ""
"Plural-Forms: \n"
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-00
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-00
msgid "0% Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-00-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-00-G
msgid "0% Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-00-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-00-CC
msgid "0% Cocont."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-00-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-00-CC
msgid "0% Cocont. - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-00-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-00-CC
msgid "0% Cocont. M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-00-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-00-CC
msgid "0% Cocont. S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-00-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-00-EU
msgid "0% EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-00-EU-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-00-EU-G
msgid "0% EU - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-00-EU
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-00-EU-L
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-00-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-00-EU-L
msgid "0% EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-00-EU-S
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-00-EU-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-00-EU-S
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-00-EU-S
msgid "0% EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-00-EU-T
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-00-EU-T
msgid "0% EU T."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-00
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-00
msgid "0% M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-00-ROW
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-00-ROW
msgid "0% Non EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-00-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-00-ROW-CC
msgid "0% Non EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-00-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-00-ROW-CC
msgid "0% Non EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-00-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-00-ROW-CC
msgid "0% Non EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-00-S
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-00-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-00-S
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-00-S
msgid "0% S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-12-L
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-12-L
msgid "12%"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12
msgid "12% Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-G
msgid "12% Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-CC
msgid "12% Cocont. - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-CC-C1
msgid "12% Cocont. Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-CC-C1
msgid "12% Cocont. Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-CC-C1
msgid "12% Cocont. Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-CC
msgid "12% Cocont. M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-CC-C2
msgid "12% Cocont. Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-CC-C2
msgid "12% Cocont. Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-CC-C2
msgid "12% Cocont. Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-CC
msgid "12% Cocont. S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-EU
msgid "12% EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-EU-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-EU-G
msgid "12% EU - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-EU-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-EU-C1
msgid "12% EU Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-EU-G-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-EU-G-C1
msgid "12% EU Déductible - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-EU-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-EU-C1
msgid "12% EU Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-EU-S-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-EU-S-C1
msgid "12% EU Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-EU
msgid "12% EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-EU-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-EU-C2
msgid "12% EU Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-EU-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-EU-C2
msgid "12% EU Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-EU-S-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-EU-S-C2
msgid "12% EU Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-EU-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-EU-S
msgid "12% EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12
msgid "12% M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-ROW-CC
msgid "12% Non EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-ROW-CC-C1
msgid "12% Non EU Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-ROW-CC-C1
msgid "12% Non EU Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-ROW-CC-C1
msgid "12% Non EU Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-ROW-CC
msgid "12% Non EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-12-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-12-ROW-CC-C2
msgid "12% Non EU Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-12-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-12-ROW-CC-C2
msgid "12% Non EU Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-ROW-CC-C2
msgid "12% Non EU Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-ROW-CC
msgid "12% Non EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-S
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-12-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-S
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-12-S
msgid "12% S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-21-L
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-21-L
msgid "21%"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21
msgid "21% Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-G
msgid "21% Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-CC
msgid "21% Cocont .S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-CC
msgid "21% Cocont. - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-CC-C1
msgid "21% Cocont. Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-CC-C1
msgid "21% Cocont. Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-CC-C1
msgid "21% Cocont. Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-CC
msgid "21% Cocont. M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-CC-C2
msgid "21% Cocont. Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-CC-C2
msgid "21% Cocont. Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-CC-C2
msgid "21% Cocont. Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-EU
msgid "21% EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-EU-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-EU-G
msgid "21% EU - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-EU-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-EU-C1
msgid "21% EU Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-EU-G-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-EU-G-C1
msgid "21% EU Déductible - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-EU-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-EU-C1
msgid "21% EU Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-EU-S-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-EU-S-C1
msgid "21% EU Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-EU
msgid "21% EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-EU-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-EU-C2
msgid "21% EU Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-EU-G-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-EU-G-C2
msgid "21% EU Récupérable - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-EU-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-EU-C2
msgid "21% EU Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-EU-S-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-EU-S-C2
msgid "21% EU Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-EU-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-EU-S
msgid "21% EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21
msgid "21% M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-ROW-CC
msgid "21% Non EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-ROW-CC-C1
msgid "21% Non EU Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-ROW-CC-C1
msgid "21% Non EU Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-ROW-CC-C1
msgid "21% Non EU Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-ROW-CC
msgid "21% Non EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-21-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-21-ROW-CC-C2
msgid "21% Non EU Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-21-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-21-ROW-CC-C2
msgid "21% Non EU Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-ROW-CC-C2
msgid "21% Non EU Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-ROW-CC
msgid "21% Non EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-21-S
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-21-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-21-S
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-21-S
msgid "21% S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_TVA-21-inclus-dans-prix
#: model:account.tax.template,name:l10n_be.attn_TVA-21-inclus-dans-prix
msgid "21% S. TTC"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-CAR-EXC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-CAR-EXC-C2
msgid "50% Déductible - Frais de voiture (Prix Excl.)"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-CAR-EXC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-CAR-EXC-C1
msgid "50% Non Déductible - Frais de voiture"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-CAR-EXC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-CAR-EXC
msgid "50% Non Déductible - Frais de voiture (Prix Excl.)"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06
msgid "6% Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-G
msgid "6% Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-CC
msgid "6% Cocont. - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-CC-C1
msgid "6% Cocont. Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-CC-C1
msgid "6% Cocont. Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-CC-C1
msgid "6% Cocont. Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-CC
msgid "6% Cocont. M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-CC-C2
msgid "6% Cocont. Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-CC-C2
msgid "6% Cocont. Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-CC-C2
msgid "6% Cocont. Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-CC
msgid "6% Cocont. S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-EU
msgid "6% EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-EU-G
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-EU-G
msgid "6% EU - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-EU-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-EU-C1
msgid "6% EU Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-EU-G-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-EU-G-C1
msgid "6% EU Déductible - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-EU-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-EU-C1
msgid "6% EU Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-EU-S-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-EU-S-C1
msgid "6% EU Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-EU
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-EU
msgid "6% EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-EU-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-EU-C2
msgid "6% EU Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-EU-G-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-EU-G-C2
msgid "6% EU Récupérable - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-EU-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-EU-C2
msgid "6% EU Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-EU-S-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-EU-S-C2
msgid "6% EU Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-EU-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-EU-S
msgid "6% EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06
msgid "6% M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-ROW-CC
msgid "6% Non EU - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-ROW-CC-C1
msgid "6% Non EU Déductible - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-ROW-CC-C1
msgid "6% Non EU Déductible M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-ROW-CC-C1
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-ROW-CC-C1
msgid "6% Non EU Déductible S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-ROW-CC
msgid "6% Non EU M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V83-06-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V83-06-ROW-CC-C2
msgid "6% Non EU Récupérable - Biens d'investissement"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V81-06-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V81-06-ROW-CC-C2
msgid "6% Non EU Récupérable M."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-ROW-CC-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-ROW-CC-C2
msgid "6% Non EU Récupérable S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-ROW-CC
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-ROW-CC
msgid "6% Non EU S."
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-06-S
-#: model:account.tax,name:l10n_be.1_attn_VAT-OUT-06-S
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-06-S
#: model:account.tax.template,name:l10n_be.attn_VAT-OUT-06-S
msgid "6% S."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a601
#: model:account.account.template,name:l10n_be.a601
msgid "Achats de fournitures"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a604
#: model:account.account.template,name:l10n_be.a604
msgid "Achats de marchandises"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a600
#: model:account.account.template,name:l10n_be.a600
msgid "Achats de matières premières"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a602
#: model:account.account.template,name:l10n_be.a602
msgid "Achats de services, travaux et études"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a446
#: model:account.account.template,name:l10n_be.a446
msgid "Acomptes reçus"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a176
#: model:account.account.template,name:l10n_be.a176
msgid "Acomptes reçus sur commandes"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a406
#: model:account.account.template,name:l10n_be.a406
msgid "Acomptes versés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a360
#: model:account.account.template,name:l10n_be.a360
msgid "Acomptes versés sur achats pour stocks"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4550
#: model:account.account.template,name:l10n_be.a4550
msgid "Administrateurs, gérants et commissaires"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2119
#: model:account.account.template,name:l10n_be.a2119
msgid "Amortissements sur concessions, brevets, etc..."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2690
#: model:account.account.template,name:l10n_be.a2690
msgid "Amortissements sur frais d'aménagement des locaux pris en location"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2009
#: model:account.account.template,name:l10n_be.a2009
msgid "Amortissements sur frais de constitution et d'augmentation de capital"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2109
#: model:account.account.template,name:l10n_be.a2109
msgid "Amortissements sur frais de recherche et de mise au point"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24190
#: model:account.account.template,name:l10n_be.a24190
msgid "Amortissements sur matériel automobile"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24090
#: model:account.account.template,name:l10n_be.a24090
msgid "Amortissements sur mobilier"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2529
#: model:account.account.template,name:l10n_be.a2529
msgid "Amortissements sur mobilier et matériel roulant en leasing"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a614
#: model:account.account.template,name:l10n_be.a614
msgid "Annonces, publicité, propagande et documentation"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a3100
#: model:account.account.template,name:l10n_be.a3100
msgid "Approvisionements et fournitures"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4160
#: model:account.account.template,name:l10n_be.a4160
msgid "Associés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a45932
#: model:account.account.template,name:l10n_be.a45932
msgid "Assurance groupe "
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a45930
#: model:account.account.template,name:l10n_be.a45930
msgid "Assurance loi"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a45931
#: model:account.account.template,name:l10n_be.a45931
msgid "Assurance salaire garanti "
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a45933
#: model:account.account.template,name:l10n_be.a45933
msgid "Assurances individuelles"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a41671
#: model:account.account.template,name:l10n_be.a41671
msgid "Autres créances"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a174
-#: model:account.account,name:l10n_be.1_a424
#: model:account.account.template,name:l10n_be.a174
#: model:account.account.template,name:l10n_be.a424
msgid "Autres emprunts"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4125
#: model:account.account.template,name:l10n_be.a4125
msgid "Autres impôts belges"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a49102
-#: model:account.account,name:l10n_be.1_a740
#: model:account.account.template,name:l10n_be.a49102
#: model:account.account.template,name:l10n_be.a740
msgid "Autres produits d'exploitation"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4538
#: model:account.account.template,name:l10n_be.a4538
msgid "Autres précomptes retenus"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4161
#: model:account.account.template,name:l10n_be.a4161
msgid "Avances et prêts au personnel"
msgstr ""
#. module: l10n_be
-#: model:account.chart.template,name:l10n_be.l10nbe_chart_template
-msgid "Belgian PCMN"
-msgstr ""
-
-#. module: l10n_be
-#: model:ir.ui.menu,name:l10n_be.account_reports_be_statements_menu
-msgid "Belgium Statements"
-msgstr ""
-
-#. module: l10n_be
#: model:account.account.tag,name:l10n_be.tax_tag_81_not_deductible
msgid "Belgium VAT Form: Tax not deductible (grid 81)"
msgstr ""
@@ -1130,854 +959,707 @@ msgid "Belgium VAT Form: grid 88"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a140
#: model:account.account.template,name:l10n_be.a140
msgid "Bénéfice reporté"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a790
#: model:account.account.template,name:l10n_be.a790
msgid "Bénéfice reporté de l'exercice précédent"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a693
#: model:account.account.template,name:l10n_be.a693
msgid "Bénéfice à reporter"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4594
#: model:account.account.template,name:l10n_be.a4594
msgid "Caisse d'assurances sociales pour travailleurs indépendants"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24105
#: model:account.account.template,name:l10n_be.a24105
msgid "Camions"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a1000
#: model:account.account.template,name:l10n_be.a1000
msgid "Capital"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a418
#: model:account.account.template,name:l10n_be.a418
msgid "Cautionnements versés en numéraires"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6600
#: model:account.account.template,name:l10n_be.a6600
msgid "Charges exceptionelles"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6101
#: model:account.account.template,name:l10n_be.a6101
msgid "Charges locatives"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a492
#: model:account.account.template,name:l10n_be.a492
msgid "Charges à imputer"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a490
#: model:account.account.template,name:l10n_be.a490
msgid "Charges à reporter"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a540
#: model:account.account.template,name:l10n_be.a540
msgid "Chèques à encaisser"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4000
#: model:account.account.template,name:l10n_be.a4000
msgid "Clients"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a370
#: model:account.account.template,name:l10n_be.a370
msgid "Commandes en cours d'exécution"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a49101
#: model:account.account.template,name:l10n_be.a49101
msgid "Commissions à obtenir"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a448
#: model:account.account.template,name:l10n_be.a448
msgid "Compensations fournisseurs"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4112
-#: model:account.account,name:l10n_be.1_a4512
#: model:account.account.template,name:l10n_be.a4112
#: model:account.account.template,name:l10n_be.a4512
msgid "Compte courant administration T.V.A."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4163
#: model:account.account.template,name:l10n_be.a4163
msgid "Compte courant des administrateurs et gérants"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4162
#: model:account.account.template,name:l10n_be.a4162
msgid "Compte courant des associés en S.P.R.L."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4990
#: model:account.account.template,name:l10n_be.a4990
msgid "Compte d'attente"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2110
#: model:account.account.template,name:l10n_be.a2110
msgid "Concessions, brevets, licences, savoir-faire, marques, etc..."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2501
#: model:account.account.template,name:l10n_be.a2501
msgid "Constructions"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a621
#: model:account.account.template,name:l10n_be.a621
msgid "Cotisations patronales d'assurances sociales"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a29000
#: model:account.account.template,name:l10n_be.a29000
msgid "Créances commerciales"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a407
-#: model:account.account,name:l10n_be.1_a417
#: model:account.account.template,name:l10n_be.a407
#: model:account.account.template,name:l10n_be.a417
msgid "Créances douteuses"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4164
#: model:account.account.template,name:l10n_be.a4164
msgid "Créances sur sociétés apparentées"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a1720
#: model:account.account.template,name:l10n_be.a1720
msgid "Dettes de location-financement de biens immobiliers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a1721
#: model:account.account.template,name:l10n_be.a1721
msgid "Dettes de location-financement de biens mobiliers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a17300
#: model:account.account.template,name:l10n_be.a17300
msgid "Dettes en compte \\ Banque A"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4597
#: model:account.account.template,name:l10n_be.a4597
msgid "Dettes et provisions sociales diverses"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4500
#: model:account.account.template,name:l10n_be.a4500
msgid "Dettes fiscales estimées"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a1722
#: model:account.account.template,name:l10n_be.a1722
msgid "Dettes sur droits réels sur immeubles"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a654
-#: model:account.account,name:l10n_be.1_a754
#: model:account.account.template,name:l10n_be.a654
#: model:account.account.template,name:l10n_be.a754
msgid "Différences de change"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4551
-#: model:account.account,name:l10n_be.1_a4560
#: model:account.account.template,name:l10n_be.a4551
#: model:account.account.template,name:l10n_be.a4560
msgid "Direction"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6302
#: model:account.account.template,name:l10n_be.a6302
msgid "Dotations aux amortissements sur immobilisations corporelles"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6301
#: model:account.account.template,name:l10n_be.a6301
msgid "Dotations aux amortissements sur immobilisations incorporelles"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a755
#: model:account.account.template,name:l10n_be.a755
msgid "Ecarts de conversion des devises"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a175111
#: model:account.account.template,name:l10n_be.a175111
msgid "Effets à payer \\ Fournisseurs C.E.E."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a175110
#: model:account.account.template,name:l10n_be.a175110
msgid "Effets à payer \\ Fournisseurs belges"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a175112
#: model:account.account.template,name:l10n_be.a175112
msgid "Effets à payer \\ Fournisseurs importation"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4166
#: model:account.account.template,name:l10n_be.a4166
msgid "Emballages et matériel à rendre"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4552
-#: model:account.account,name:l10n_be.1_a4561
#: model:account.account.template,name:l10n_be.a4552
#: model:account.account.template,name:l10n_be.a4561
msgid "Employés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a3200
#: model:account.account.template,name:l10n_be.a3200
msgid "En cours de fabrication"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a611
#: model:account.account.template,name:l10n_be.a611
msgid "Entretien et réparation"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a653
#: model:account.account.template,name:l10n_be.a653
msgid "Escomptes clients"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a757
#: model:account.account.template,name:l10n_be.a757
msgid "Escomptes obtenus"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4230
#: model:account.account.template,name:l10n_be.a4230
msgid "Etablissements de crédit"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a430
#: model:account.account.template,name:l10n_be.a430
msgid "Etablissements de crédit. Emprunts en compte à terme fixe"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a444
#: model:account.account.template,name:l10n_be.a444
msgid "Factures à recevoir"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4220
#: model:account.account.template,name:l10n_be.a4220
msgid "Financement de biens immobiliers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4221
#: model:account.account.template,name:l10n_be.a4221
msgid "Financement de biens mobiliers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a440
#: model:account.account.template,name:l10n_be.a440
msgid "Fournisseurs"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a612
#: model:account.account.template,name:l10n_be.a612
msgid "Fournitures"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a260
#: model:account.account.template,name:l10n_be.a260
msgid "Frais d'aménagements de locaux pris en location"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a656
#: model:account.account.template,name:l10n_be.a656
msgid "Frais de banques, de chèques postaux"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2000
#: model:account.account.template,name:l10n_be.a2000
msgid "Frais de constitution et d'augmentation de capital"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2100
#: model:account.account.template,name:l10n_be.a2100
msgid "Frais de recherche et de mise au point"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a3500
#: model:account.account.template,name:l10n_be.a3500
msgid "Immeubles destinés à la vente"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2800
#: model:account.account.template,name:l10n_be.a2800
msgid "Immobilisations Financières"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4120
#: model:account.account.template,name:l10n_be.a4120
msgid "Impôts belges sur le résultat"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6700
#: model:account.account.template,name:l10n_be.a6700
msgid "Impôts et précomptes dus ou versés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4128
#: model:account.account.template,name:l10n_be.a4128
msgid "Impôts étrangers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6100
+#: model:account.account.template,name:l10n_be.l10nbe_chart_template_liquidity_transfer
+msgid "Liquidity Transfer"
+msgstr ""
+
+#. module: l10n_be
#: model:account.account.template,name:l10n_be.a6100
msgid "Loyers divers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a3400
#: model:account.account.template,name:l10n_be.a3400
msgid "Marchandises"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a300
#: model:account.account.template,name:l10n_be.a300
msgid "Matières premières"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24011
#: model:account.account.template,name:l10n_be.a24011
msgid "Matériel de bureau de bâtiments administratifs et commerciaux"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24010
#: model:account.account.template,name:l10n_be.a24010
msgid "Matériel de bureau de bâtiments industriels"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2521
#: model:account.account.template,name:l10n_be.a2521
msgid "Matériel roulant"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2520
#: model:account.account.template,name:l10n_be.a2520
msgid "Mobilier"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24001
#: model:account.account.template,name:l10n_be.a24001
msgid "Mobilier des bâtiments administratifs et commerciaux"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24000
#: model:account.account.template,name:l10n_be.a24000
msgid "Mobilier des bâtiments industriels"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a151
#: model:account.account.template,name:l10n_be.a151
msgid "Montants transférés aux résultats"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4541
#: model:account.account.template,name:l10n_be.a4541
msgid "ONSS. 1er trimestre"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4542
#: model:account.account.template,name:l10n_be.a4542
msgid "ONSS. 2ème trimestre"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4543
#: model:account.account.template,name:l10n_be.a4543
msgid "ONSS. 3ème trimestre"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4544
#: model:account.account.template,name:l10n_be.a4544
msgid "ONSS. 4ème trimestre"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4540
#: model:account.account.template,name:l10n_be.a4540
msgid "ONSS. Arriérés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4553
-#: model:account.account,name:l10n_be.1_a4562
#: model:account.account.template,name:l10n_be.a4553
#: model:account.account.template,name:l10n_be.a4562
msgid "Ouvriers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a141
#: model:account.account.template,name:l10n_be.a141
msgid "Perte reportée"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a690
#: model:account.account.template,name:l10n_be.a690
msgid "Perte reportée de l'exercice précédent"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a793
#: model:account.account.template,name:l10n_be.a793
msgid "Perte à reporter"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2118
#: model:account.account.template,name:l10n_be.a2118
msgid "Plus-values actées sur concessions, brevets, etc..."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2108
#: model:account.account.template,name:l10n_be.a2108
msgid "Plus-values actées sur frais de recherche et de mise au point"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2528
#: model:account.account.template,name:l10n_be.a2528
msgid "Plus-values actées sur mobilier et matériel roulant en leasing"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a752
#: model:account.account.template,name:l10n_be.a752
msgid "Plus-values sur réalisations d'actifs circulants"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7051
#: model:account.account.template,name:l10n_be.a7051
msgid "Prestations de services dans les pays membres de la C.E.E."
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7050
#: model:account.account.template,name:l10n_be.a7050
msgid "Prestations de services en Belgique"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7052
#: model:account.account.template,name:l10n_be.a7052
msgid "Prestations de services en vue de l'exportation"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a11
#: model:account.account.template,name:l10n_be.a11
msgid "Primes d'émission"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4930
#: model:account.account.template,name:l10n_be.a4930
msgid "Produits d'exploitation à reporter"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a751
#: model:account.account.template,name:l10n_be.a751
msgid "Produits des actifs circulants"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a756
#: model:account.account.template,name:l10n_be.a756
msgid "Produits des autres créances"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7600
#: model:account.account.template,name:l10n_be.a7600
msgid "Produits exceptionnels"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a3300
#: model:account.account.template,name:l10n_be.a3300
msgid "Produits finis"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a404
-#: model:account.account,name:l10n_be.1_a414
#: model:account.account.template,name:l10n_be.a404
#: model:account.account.template,name:l10n_be.a414
msgid "Produits à recevoir"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4590
#: model:account.account.template,name:l10n_be.a4590
msgid "Provision pour gratifications de fin d'année"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a1600
#: model:account.account.template,name:l10n_be.a1600
msgid "Provisions pour risques et charges"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4533
#: model:account.account.template,name:l10n_be.a4533
msgid "Précompte mobilier retenu sur intérêts payés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4530
#: model:account.account.template,name:l10n_be.a4530
msgid "Précompte professionnel retenu sur rémunérations"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a791
#: model:account.account.template,name:l10n_be.a791
msgid "Prélèvement sur le capital et les primes d'émission"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a780
#: model:account.account.template,name:l10n_be.a780
msgid "Prélèvements sur les impôts différés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a789
#: model:account.account.template,name:l10n_be.a789
msgid "Prélèvements sur les réserves immunisées"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a706
#: model:account.account.template,name:l10n_be.a706
msgid "Pénalités et dédits obtenus par l'entreprise"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4168
#: model:account.account.template,name:l10n_be.a4168
msgid "Rabais, ristournes, remises à obtenir et autres avoirs non encore reçus"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7500
#: model:account.account.template,name:l10n_be.a7500
msgid "Revenus des actions"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7502
#: model:account.account.template,name:l10n_be.a7502
msgid "Revenus des créances à plus d'un an"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7501
#: model:account.account.template,name:l10n_be.a7501
msgid "Revenus des obligations"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a49100
#: model:account.account.template,name:l10n_be.a49100
msgid "Ristournes, rabais à obtenir"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a329
-#: model:account.account,name:l10n_be.1_a419
#: model:account.account.template,name:l10n_be.a329
#: model:account.account.template,name:l10n_be.a419
msgid "Réductions de valeur actées"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6320
#: model:account.account.template,name:l10n_be.a6320
msgid "Réductions de valeur sur commandes en cours d'exécution"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6310
#: model:account.account.template,name:l10n_be.a6310
msgid "Réductions de valeur sur stocks"
msgstr ""
#. module: l10n_be
-#: model:account.fiscal.position,name:l10n_be.1_fiscal_position_template_4
#: model:account.fiscal.position.template,name:l10n_be.fiscal_position_template_4
msgid "Régime Cocontractant"
msgstr ""
#. module: l10n_be
-#: model:account.fiscal.position,name:l10n_be.1_fiscal_position_template_2
#: model:account.fiscal.position.template,name:l10n_be.fiscal_position_template_2
msgid "Régime Extra-Communautaire"
msgstr ""
#. module: l10n_be
-#: model:account.fiscal.position,name:l10n_be.1_fiscal_position_template_3
#: model:account.fiscal.position.template,name:l10n_be.fiscal_position_template_3
msgid "Régime Intra-Communautaire"
msgstr ""
#. module: l10n_be
-#: model:account.fiscal.position,name:l10n_be.1_fiscal_position_template_1
#: model:account.fiscal.position.template,name:l10n_be.fiscal_position_template_1
msgid "Régime National"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V61
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V61
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V61
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V61
msgid "Régularisation en faveur de l'état"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V62
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V62
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V62
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V62
msgid "Régularisation en faveur du déclarant"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7710
#: model:account.account.template,name:l10n_be.a7710
msgid "Régularisations d'impôts dus ou versés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7711
#: model:account.account.template,name:l10n_be.a7711
msgid "Régularisations d'impôts estimés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6200
#: model:account.account.template,name:l10n_be.a6200
msgid "Rémunérations: Administrateurs ou gérants"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6204
#: model:account.account.template,name:l10n_be.a6204
msgid "Rémunérations: Autres membres du personnel"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6202
#: model:account.account.template,name:l10n_be.a6202
msgid "Rémunérations: Employés"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6203
#: model:account.account.template,name:l10n_be.a6203
msgid "Rémunérations: Ouvriers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a6201
#: model:account.account.template,name:l10n_be.a6201
msgid "Rémunérations: Personnel de direction"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a130
#: model:account.account.template,name:l10n_be.a130
msgid "Réserve légale"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a132
#: model:account.account.template,name:l10n_be.a132
msgid "Réserves immunisées"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a613
#: model:account.account.template,name:l10n_be.a613
msgid "Rétributions de tiers"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a603
#: model:account.account.template,name:l10n_be.a603
msgid "Sous-traitances générales"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a753
#: model:account.account.template,name:l10n_be.a753
msgid "Subsides en capital et en intérêts"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a150
#: model:account.account.template,name:l10n_be.a150
msgid "Subsides obtenus"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a41670
#: model:account.account.template,name:l10n_be.a41670
msgid "Subsides à recevoir"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a411059
#: model:account.account.template,name:l10n_be.a411059
msgid "T.V.A Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a64012
#: model:account.account.template,name:l10n_be.a64012
msgid "T.V.A. non déductible"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a451054
#: model:account.account.template,name:l10n_be.a451054
msgid "T.V.A. à payer"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a451056
#: model:account.account.template,name:l10n_be.a451056
msgid "T.V.A. à payer - Cocontractant"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a451057
#: model:account.account.template,name:l10n_be.a451057
msgid "T.V.A. à payer - Import"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a451055
#: model:account.account.template,name:l10n_be.a451055
msgid "T.V.A. à payer - Intra-communautaire"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-00
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-00-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-00-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-00
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-00-L
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-00-S
+#: model:account.tax.group,name:l10n_be.tax_group_tva_0
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-00
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-S
@@ -1988,10 +1670,6 @@ msgid "TVA 0%"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-00-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-00-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-00-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-00-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-00-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-00-CC
@@ -2000,13 +1678,6 @@ msgid "TVA 0% Cocont."
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-00-EU
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-00-EU-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-00-EU-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-00-EU
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-00-EU-L
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-00-EU-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-00-EU-T
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-00-EU
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-EU-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-EU-S
@@ -2018,10 +1689,11 @@ msgid "TVA 0% EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-00-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-00-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-00-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-00-ROW
+#: model:account.tax.group,name:l10n_be.tax_group_tva_0_eu
+msgid "TVA 0% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-00-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-00-ROW-CC
@@ -2030,12 +1702,7 @@ msgid "TVA 0% Non EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-12-L
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-12-S
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-S
@@ -2046,9 +1713,7 @@ msgid "TVA 12%"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-CC
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12_cocont
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-CC
@@ -2056,9 +1721,6 @@ msgid "TVA 12% Cocont."
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-CC-C1
@@ -2066,9 +1728,6 @@ msgid "TVA 12% Cocont. Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-CC-C2
@@ -2076,10 +1735,6 @@ msgid "TVA 12% Cocont. Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-EU
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-EU-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-EU-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-EU
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-EU
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-EU-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-EU-S
@@ -2088,10 +1743,6 @@ msgid "TVA 12% EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-EU-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-EU-G-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-EU-S-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-EU-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-EU-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-EU-G-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-EU-S-C1
@@ -2100,10 +1751,6 @@ msgid "TVA 12% EU Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-EU-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-EU-G-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-EU-S-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-EU-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-EU-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-EU-G-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-EU-S-C2
@@ -2112,15 +1759,16 @@ msgid "TVA 12% EU Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,name:l10n_be.1_attn_VAT-IN-V82-12-EU-G-C2
#: model:account.tax.template,name:l10n_be.attn_VAT-IN-V82-12-EU-G-C2
msgid "TVA 12% EU Récupérable - Biens divers"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-ROW-CC
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12_eu
+msgid "TVA 12% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-ROW-CC
@@ -2128,9 +1776,6 @@ msgid "TVA 12% Non EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-ROW-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-ROW-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-ROW-CC-C1
@@ -2138,9 +1783,6 @@ msgid "TVA 12% Non EU Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-12-ROW-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-12-ROW-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-12-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-ROW-CC-C2
@@ -2148,12 +1790,12 @@ msgid "TVA 12% Non EU Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-21-L
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-21-S
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12_non_eu
+msgid "TVA 12% Non EU."
+msgstr ""
+
+#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-S
@@ -2164,9 +1806,7 @@ msgid "TVA 21%"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-CC
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_cocont
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-CC
@@ -2174,9 +1814,6 @@ msgid "TVA 21% Cocont."
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-CC-C1
@@ -2184,9 +1821,6 @@ msgid "TVA 21% Cocont. Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-CC-C2
@@ -2194,10 +1828,6 @@ msgid "TVA 21% Cocont. Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-EU
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-EU-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-EU-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-EU
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-EU
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-EU-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-EU-S
@@ -2206,10 +1836,6 @@ msgid "TVA 21% EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-EU-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-EU-G-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-EU-S-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-EU-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-EU-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-EU-G-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-EU-S-C1
@@ -2218,10 +1844,6 @@ msgid "TVA 21% EU Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-EU-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-EU-G-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-EU-S-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-EU-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-EU-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-EU-G-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-EU-S-C2
@@ -2230,9 +1852,11 @@ msgid "TVA 21% EU Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-ROW-CC
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_eu
+msgid "TVA 21% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-ROW-CC
@@ -2240,9 +1864,6 @@ msgid "TVA 21% Non EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-ROW-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-ROW-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-ROW-CC-C1
@@ -2250,9 +1871,6 @@ msgid "TVA 21% Non EU Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-21-ROW-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-21-ROW-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-21-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-ROW-CC-C2
@@ -2260,30 +1878,32 @@ msgid "TVA 21% Non EU Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_TVA-21-inclus-dans-prix
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_non_eu
+msgid "TVA 21% Non EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_TVA-21-inclus-dans-prix
msgid "TVA 21% TTC"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-CAR-EXC-C2
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_50_deductible
+msgid "TVA 21%, 50% Deductible."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-CAR-EXC-C2
msgid "TVA 50% Déductible - Frais de voiture (Prix Excl.)"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-CAR-EXC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-CAR-EXC
msgid "TVA 50% Non Déductible - Frais de voiture (Prix Excl.)"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-06-L
-#: model:account.tax,description:l10n_be.1_attn_VAT-OUT-06-S
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-S
@@ -2294,9 +1914,7 @@ msgid "TVA 6%"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-CC
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6_cocont
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-CC
@@ -2304,9 +1922,6 @@ msgid "TVA 6% Cocont."
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-CC-C1
@@ -2314,9 +1929,6 @@ msgid "TVA 6% Cocont. Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-CC-C2
@@ -2324,10 +1936,6 @@ msgid "TVA 6% Cocont. Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-EU
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-EU-G
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-EU-S
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-EU
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-EU
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-EU-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-EU-S
@@ -2336,10 +1944,6 @@ msgid "TVA 6% EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-EU-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-EU-G-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-EU-S-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-EU-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-EU-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-EU-G-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-EU-S-C1
@@ -2348,10 +1952,6 @@ msgid "TVA 6% EU Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-EU-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-EU-G-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-EU-S-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-EU-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-EU-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-EU-G-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-EU-S-C2
@@ -2360,9 +1960,11 @@ msgid "TVA 6% EU Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-ROW-CC
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-ROW-CC
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6_eu
+msgid "TVA 6% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-ROW-CC
@@ -2370,9 +1972,6 @@ msgid "TVA 6% Non EU"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-ROW-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-ROW-CC-C1
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-ROW-CC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-ROW-CC-C1
@@ -2380,9 +1979,6 @@ msgid "TVA 6% Non EU Déductible"
msgstr ""
#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V81-06-ROW-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-06-ROW-CC-C2
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V83-06-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-ROW-CC-C2
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-ROW-CC-C2
@@ -2390,74 +1986,61 @@ msgid "TVA 6% Non EU Récupérable"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a4118
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6_non_eu
+msgid "TVA 6% Non EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.account.template,name:l10n_be.a4118
msgid "Taxe d'égalisation due"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a64000
#: model:account.account.template,name:l10n_be.a64000
msgid "Taxes sur autos et camions"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a2500
#: model:account.account.template,name:l10n_be.a2500
msgid "Terrains"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_trans
-#: model:account.account.template,name:l10n_be.trans
-msgid "Transferts"
-msgstr ""
-
-#. module: l10n_be
-#: model:account.tax,description:l10n_be.1_attn_VAT-IN-V82-CAR-EXC-C1
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-CAR-EXC-C1
msgid "VAT 50% Non Déductible - Frais de voiture"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7001
#: model:account.account.template,name:l10n_be.a7001
msgid "Ventes dans les pays membres de la C.E.E. (marchandises)"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7011
#: model:account.account.template,name:l10n_be.a7011
msgid "Ventes dans les pays membres de la C.E.E. (produits finis)"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7000
#: model:account.account.template,name:l10n_be.a7000
msgid "Ventes en Belgique (marchandises)"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7010
#: model:account.account.template,name:l10n_be.a7010
msgid "Ventes en Belgique (produits finis)"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7002
#: model:account.account.template,name:l10n_be.a7002
msgid "Ventes à l'exportation (marchandises)"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a7012
#: model:account.account.template,name:l10n_be.a7012
msgid "Ventes à l'exportation (produits finis)"
msgstr ""
#. module: l10n_be
-#: model:account.account,name:l10n_be.1_a24100
#: model:account.account.template,name:l10n_be.a24100
msgid "Voitures"
msgstr ""
-
diff --git a/addons/l10n_be/i18n_extra/nl.po b/addons/l10n_be/i18n_extra/nl.po
index 2a4b067ee33..f031378df09 100644
--- a/addons/l10n_be/i18n_extra/nl.po
+++ b/addons/l10n_be/i18n_extra/nl.po
@@ -4,9 +4,9 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 9.0\n"
+"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-03-06 12:52+0000\n"
+"POT-Creation-Date: 2019-01-17 08:59+0000\n"
"PO-Revision-Date: 2017-03-15 14:20+0100\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -791,16 +791,6 @@ msgid "Avances et prêts au personnel"
msgstr "Voorschotten en leningen aan het personeel"
#. module: l10n_be
-#: model:account.chart.template,name:l10n_be.l10nbe_chart_template
-msgid "Belgian PCMN"
-msgstr "Belgische PCMN"
-
-#. module: l10n_be
-#: model:ir.ui.menu,name:l10n_be.account_reports_be_statements_menu
-msgid "Belgium Statements"
-msgstr ""
-
-#. module: l10n_be
#: model:account.account.tag,name:l10n_be.tax_tag_81_not_deductible
msgid "Belgium VAT Form: Tax not deductible (grid 81)"
msgstr ""
@@ -1286,6 +1276,11 @@ msgid "Impôts étrangers"
msgstr "Buitenlandse belastingen"
#. module: l10n_be
+#: model:account.account.template,name:l10n_be.l10nbe_chart_template_liquidity_transfer
+msgid "Liquidity Transfer"
+msgstr ""
+
+#. module: l10n_be
#: model:account.account.template,name:l10n_be.a6100
msgid "Loyers divers"
msgstr "Diverse huren"
@@ -1303,7 +1298,8 @@ msgstr "Grondstoffen"
#. module: l10n_be
#: model:account.account.template,name:l10n_be.a24011
msgid "Matériel de bureau de bâtiments administratifs et commerciaux"
-msgstr "Kantooruitrusting voor gebouwen met adminestratieve en commerciële functie"
+msgstr ""
+"Kantooruitrusting voor gebouwen met adminestratieve en commerciële functie"
#. module: l10n_be
#: model:account.account.template,name:l10n_be.a24010
@@ -1583,7 +1579,8 @@ msgstr "Bezoldigingen: Bestuurders of zaakvoerders"
#. module: l10n_be
#: model:account.account.template,name:l10n_be.a6204
msgid "Rémunérations: Autres membres du personnel"
-msgstr "Bezoldigingen: Andere personeelsleden, verbonden met een arbeidsovereenkomst"
+msgstr ""
+"Bezoldigingen: Andere personeelsleden, verbonden met een arbeidsovereenkomst"
#. module: l10n_be
#: model:account.account.template,name:l10n_be.a6202
@@ -1666,6 +1663,7 @@ msgid "T.V.A. à payer - Intra-communautaire"
msgstr "Te betalen BTW - Intracommunautair"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_0
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-00
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-S
@@ -1695,6 +1693,11 @@ msgid "TVA 0% EU"
msgstr "BTW 0% EU"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_0_eu
+msgid "TVA 0% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-00-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-00-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-00-ROW-CC
@@ -1703,6 +1706,7 @@ msgid "TVA 0% Non EU"
msgstr "BTW 0% Non EU"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-S
@@ -1713,6 +1717,7 @@ msgid "TVA 12%"
msgstr "BTW 12%"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12_cocont
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-CC
@@ -1763,6 +1768,11 @@ msgid "TVA 12% EU Récupérable - Biens divers"
msgstr "BTW 12% EU Verhaalbaar - Diverse goederen"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12_eu
+msgid "TVA 12% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-12-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-12-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-12-ROW-CC
@@ -1784,6 +1794,12 @@ msgid "TVA 12% Non EU Récupérable"
msgstr "BTW 12% Niet EU Verhaalbaar"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_12_non_eu
+msgid "TVA 12% Non EU."
+msgstr ""
+
+#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-S
@@ -1794,6 +1810,7 @@ msgid "TVA 21%"
msgstr "BTW 21%"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_cocont
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-CC
@@ -1839,6 +1856,11 @@ msgid "TVA 21% EU Récupérable"
msgstr "BTW 21% EU Verhaalbaar"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_eu
+msgid "TVA 21% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-21-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-21-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-21-ROW-CC
@@ -1860,11 +1882,21 @@ msgid "TVA 21% Non EU Récupérable"
msgstr "BTW 21% Niet EU Verhaalbaar"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_non_eu
+msgid "TVA 21% Non EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_TVA-21-inclus-dans-prix
msgid "TVA 21% TTC"
msgstr "VAT 21% (inclusief BTW)"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_21_50_deductible
+msgid "TVA 21%, 50% Deductible."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-CAR-EXC-C2
msgid "TVA 50% Déductible - Frais de voiture (Prix Excl.)"
msgstr "BTW 5°% Aftrekbaar - Auto kosten (Prijs Excl.)"
@@ -1875,6 +1907,7 @@ msgid "TVA 50% Non Déductible - Frais de voiture (Prix Excl.)"
msgstr "BTW 50% Niet Aftrekbaar - Auto kosten (Prijs Excl.)"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-G
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-S
@@ -1885,6 +1918,7 @@ msgid "TVA 6%"
msgstr "BTW 6%"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6_cocont
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-CC
@@ -1930,6 +1964,11 @@ msgid "TVA 6% EU Récupérable"
msgstr "BTW 6% EU Verhaalbaar"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6_eu
+msgid "TVA 6% EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V81-06-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-06-ROW-CC
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V83-06-ROW-CC
@@ -1951,6 +1990,11 @@ msgid "TVA 6% Non EU Récupérable"
msgstr "BTW 6% Niet EU Verhaalbaar"
#. module: l10n_be
+#: model:account.tax.group,name:l10n_be.tax_group_tva_6_non_eu
+msgid "TVA 6% Non EU."
+msgstr ""
+
+#. module: l10n_be
#: model:account.account.template,name:l10n_be.a4118
msgid "Taxe d'égalisation due"
msgstr "Verschuldigde egalisatiebelasting"
@@ -1966,11 +2010,6 @@ msgid "Terrains"
msgstr "Terreinen"
#. module: l10n_be
-#: model:account.account.template,name:l10n_be.trans
-msgid "Transferts"
-msgstr "Transferten"
-
-#. module: l10n_be
#: model:account.tax.template,description:l10n_be.attn_VAT-IN-V82-CAR-EXC-C1
msgid "VAT 50% Non Déductible - Frais de voiture"
msgstr "BTW 50% Niet Aftrekbaar - Auto kosten"
diff --git a/addons/l10n_be_invoice_bba/data/mail_template_data.xml b/addons/l10n_be_invoice_bba/data/mail_template_data.xml
index e12f7745b91..5e6bfecdfb7 100644
--- a/addons/l10n_be_invoice_bba/data/mail_template_data.xml
+++ b/addons/l10n_be_invoice_bba/data/mail_template_data.xml
@@ -25,7 +25,7 @@
This invoice is already paid.
% else:
Please remit payment at your earliest convenience.
- % if object.reference_type == 'bba' and object.reference:
+ % if object.invoice_reference_type=='structured' and object.reference:
Please use the following communication for your payment: <strong>${object.reference}</strong>.
% endif
<br /><br />
diff --git a/addons/mail/models/mail_channel.py b/addons/mail/models/mail_channel.py
index 99996615094..2b5bfe2a2db 100644
--- a/addons/mail/models/mail_channel.py
+++ b/addons/mail/models/mail_channel.py
@@ -78,6 +78,7 @@ class Channel(models.Model):
('chat', 'Chat Discussion'),
('channel', 'Channel')],
'Channel Type', default='channel')
+ is_chat = fields.Boolean(string='Is a chat', compute='_compute_is_chat', default=False)
description = fields.Text('Description')
uuid = fields.Char('UUID', size=50, index=True, default=lambda self: str(uuid4()), copy=False)
email_send = fields.Boolean('Send messages by email', default=False)
@@ -178,6 +179,12 @@ class Channel(models.Model):
for record in self:
record.is_member = record in membership_ids
+ @api.multi
+ def _compute_is_chat(self):
+ for record in self:
+ if record.channel_type == 'chat':
+ record.is_chat = True
+
@api.onchange('public')
def _onchange_public(self):
if self.public == 'public':
@@ -384,7 +391,7 @@ class Channel(models.Model):
if moderation_status == 'rejected':
return self.env['mail.message']
- self.filtered(lambda channel: channel.channel_type == 'chat').mapped('channel_last_seen_partner_ids').write({'is_pinned': True})
+ self.filtered(lambda channel: channel.is_chat).mapped('channel_last_seen_partner_ids').write({'is_pinned': True})
message = super(Channel, self.with_context(mail_create_nosubscribe=True)).message_post(message_type=message_type, moderation_status=moderation_status, **kwargs)
diff --git a/addons/mail/static/src/js/utils.js b/addons/mail/static/src/js/utils.js
index 4749ba11b20..740be8eb54d 100644
--- a/addons/mail/static/src/js/utils.js
+++ b/addons/mail/static/src/js/utils.js
@@ -22,7 +22,7 @@ function _parseAndTransform(nodes, transformFunction) {
// Suggested URL Javascript regex of http://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url
// Adapted to make http(s):// not required if (and only if) www. is given. So `should.notmatch` does not match.
-var urlRegexp = /\b(?:https?:\/\/\d{1,3}(?:\.\d{1,3}){3}|(?:https?:\/\/|(?:www\.))[-a-z0-9@:%._+~#=]{2,256}\.[a-z]{2,13})\b(?:[-a-z0-9@:%_+.~#?&'$//=]*)/gi;
+var urlRegexp = /\b(?:https?:\/\/\d{1,3}(?:\.\d{1,3}){3}|(?:https?:\/\/|(?:www\.))[-a-z0-9@:%._+~#=]{2,256}\.[a-z]{2,13})\b(?:[-a-z0-9@:%_+.~#?&'$//=;]*)/gi;
function linkify(text, attrs) {
attrs = attrs || {};
if (attrs.target === undefined) {
diff --git a/addons/mass_mailing/static/src/scss/mass_mailing.scss b/addons/mass_mailing/static/src/scss/mass_mailing.scss
index e13cea29676..873e1b9dea0 100644
--- a/addons/mass_mailing/static/src/scss/mass_mailing.scss
+++ b/addons/mass_mailing/static/src/scss/mass_mailing.scss
@@ -18,3 +18,9 @@
.o_white_body {
background-color: white;
}
+
+.o_mass_mailing_unsubscribed {
+ margin-left: 20px;
+ color: #005326;
+ font-size: 90%;
+}
diff --git a/addons/mass_mailing/views/unsubscribe_templates.xml b/addons/mass_mailing/views/unsubscribe_templates.xml
index 621119c35b6..dfad695abf6 100644
--- a/addons/mass_mailing/views/unsubscribe_templates.xml
+++ b/addons/mass_mailing/views/unsubscribe_templates.xml
@@ -32,6 +32,10 @@
<input type="checkbox" class="mail_list_checkbox" name="contact_ids"
t-att-value="list_id['id']" t-att-checked="None if list_id['id'] in opt_out_list_ids else 'checked'"/>
<t t-esc="list_id.name"/>
+ <span t-if="list_id['id'] in opt_out_list_ids"
+ class="o_mass_mailing_unsubscribed">
+ Unsubscribed
+ </span>
</li>
</t>
</t>
diff --git a/addons/mass_mailing_crm/data/mass_mailing_demo.xml b/addons/mass_mailing_crm/data/mass_mailing_demo.xml
index 669f318341f..27d36357554 100644
--- a/addons/mass_mailing_crm/data/mass_mailing_demo.xml
+++ b/addons/mass_mailing_crm/data/mass_mailing_demo.xml
@@ -57,7 +57,7 @@
${object.company_id.email}
</a>
% endif
- ${object.company_id.website}
+ % if object.company_id.website
|
<a href="'%s' % object.company_id.website" style="text-decoration:none; color: #999999;">
${object.company_id.website}
diff --git a/addons/mrp/models/mrp_production.py b/addons/mrp/models/mrp_production.py
index 10ac3e19112..6310ffd8b82 100644
--- a/addons/mrp/models/mrp_production.py
+++ b/addons/mrp/models/mrp_production.py
@@ -540,7 +540,10 @@ class MrpProduction(models.Model):
if move:
old_qty = move[0].product_uom_qty
if quantity > 0:
- move[0].write({'product_uom_qty': quantity})
+ move[0]._decrease_reserved_quanity(quantity)
+ move[0].with_context(do_not_unreserve=True).write({'product_uom_qty': quantity})
+ move[0]._recompute_state()
+ move[0]._action_assign()
move.unit_factor = quantity / move.raw_material_production_id.product_qty
elif quantity < 0: # Do not remove 0 lines
if move[0].quantity_done > 0:
diff --git a/addons/mrp/models/stock_move.py b/addons/mrp/models/stock_move.py
index 096074b8157..ac20a46338e 100644
--- a/addons/mrp/models/stock_move.py
+++ b/addons/mrp/models/stock_move.py
@@ -188,6 +188,24 @@ class StockMove(models.Model):
self.sudo().unlink()
return processed_moves
+ def _decrease_reserved_quanity(self, quantity):
+ """ Decrease the reservation on move lines but keeps the
+ all other data.
+ """
+ move_line_to_unlink = self.env['stock.move.line']
+ for move in self:
+ reserved_quantity = quantity
+ for move_line in self.move_line_ids:
+ if move_line.product_uom_qty > reserved_quantity:
+ move_line.product_uom_qty = reserved_quantity
+ else:
+ move_line.product_uom_qty = 0
+ reserved_quantity -= move_line.product_uom_qty
+ if not move_line.product_uom_qty and not move_line.qty_done:
+ move_line_to_unlink |= move_line
+ move_line_to_unlink.unlink()
+ return True
+
def _prepare_phantom_move_values(self, bom_line, product_qty, quantity_done):
return {
'picking_id': self.picking_id.id if self.picking_id else False,
diff --git a/addons/mrp/report/mrp_production_templates.xml b/addons/mrp/report/mrp_production_templates.xml
index cbb042ff445..531b516f0da 100644
--- a/addons/mrp/report/mrp_production_templates.xml
+++ b/addons/mrp/report/mrp_production_templates.xml
@@ -7,9 +7,14 @@
<div class="page">
<div class="oe_structure"/>
<div class="row">
- <div class="col-12">
+ <div class="col-7">
<h2><span t-field="o.name"/></h2>
</div>
+ <div class="col-5">
+ <span class="text-right">
+ <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('Code128', o.name, 600, 100)" style="width:350px;height:60px"/>
+ </span>
+ </div>
</div>
<div class="row mt32 mb32">
<div class="col-3" t-if="o.origin">
@@ -142,6 +147,56 @@
</t>
</template>
+<template id="label_production_view_pdf">
+ <t t-call="web.basic_layout">
+ <t t-foreach="docs" t-as="o">
+ <div class="page">
+ <table class="table table-condensed" style="border-bottom: 0px solid white !important;width: 3in;" t-if="o.move_finished_ids">
+ <t t-set="lines" t-value="o.move_finished_ids"/>
+ <t t-foreach="lines" t-as="line">
+ <t t-set="move_lines" t-value="line.move_line_ids.filtered(lambda x: x.state != 'done' and x.product_qty)"/>
+ <t t-if="o.state == 'done'">
+ <t t-set="move_lines" t-value="line.move_line_ids.filtered(lambda x: x.state == 'done' and x.qty_done)"/>
+ </t>
+ <t t-foreach="move_lines" t-as="ml">
+ <tr>
+ <th style="text-align: left;">
+ <span t-field="line.product_id"/>
+ </th>
+ </tr>
+ <tr>
+ <td>
+ Quantity:
+ <span t-esc="ml.product_uom_qty" t-if="ml.state !='done'"/>
+ <span t-esc="ml.qty_done" t-if="ml.state =='done'"/>
+ <span t-field="ml.product_uom_id" groups="uom.group_uom"/>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: center; vertical-align: middle;" class="col-5">
+ <t t-if="ml.lot_id">
+ <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('Code128', ml.lot_id.name, 600, 100)" style="width:100%;height:35px" alt="Barcode"/>
+ <span t-field="ml.lot_id.name"/>
+ </t>
+ </td>
+ </tr>
+ <tr>
+ <td style="text-align: center; vertical-align: middle;" class="col-5">
+ <t t-if="line.product_id.barcode and not ml.lot_id">
+ <img t-att-src="'/report/barcode/?type=%s&amp;value=%s&amp;width=%s&amp;height=%s' % ('Code128', line.product_id.barcode, 600, 100)" style="width:100%;height:20%;" alt="Barcode"/>
+ <span t-field="line.product_id.barcode"/>
+ </t>
+ </td>
+ </tr>
+ </t>
+ </t>
+ </table>
+ <div class="oe_structure"/>
+ </div>
+ </t>
+ </t>
+</template>
+
<template id="production_message">
<t t-if="move.move_id.raw_material_production_id">
<t t-set="message">Consumed</t>
diff --git a/addons/mrp/report/mrp_report_views_main.xml b/addons/mrp/report/mrp_report_views_main.xml
index c78c6de4fa3..5805bea5820 100644
--- a/addons/mrp/report/mrp_report_views_main.xml
+++ b/addons/mrp/report/mrp_report_views_main.xml
@@ -19,5 +19,14 @@
report_type="qweb-pdf"
print_report_name="'Bom Structure - %s' % object.display_name"
/>
+ <report
+ string="Finished Product Label (PDF)"
+ id="action_report_finished_product"
+ model="mrp.production"
+ name="mrp.label_production_view_pdf"
+ file="mrp.label_production_view_pdf"
+ report_type="qweb-pdf"
+ print_report_name="'Finished products - %s' % object.name"
+ />
</data>
</odoo>
diff --git a/addons/mrp/tests/test_order.py b/addons/mrp/tests/test_order.py
index 8b2c4dd6c46..ac4ec19b748 100644
--- a/addons/mrp/tests/test_order.py
+++ b/addons/mrp/tests/test_order.py
@@ -629,6 +629,53 @@ class TestMrpOrder(TestMrpCommon):
mo.button_mark_done()
self.assertEqual(mo.state, 'done', "Production order should be in done state.")
+ def test_product_produce_5(self):
+ """ Build 5 final products with different consumed lots,
+ then edit the finished quantity and update the Manufacturing
+ order quantity. Then check if the produced quantity do not
+ change and it is possible to close the MO.
+ """
+ self.stock_location = self.env.ref('stock.stock_location_stock')
+ mo, bom, p_final, p1, p2 = self.generate_mo(tracking_base_1='lot')
+ self.assertEqual(len(mo), 1, 'MO should have been created')
+
+ lot_1 = self.env['stock.production.lot'].create({
+ 'name': 'lot1',
+ 'product_id': p1.id,
+ })
+ lot_2 = self.env['stock.production.lot'].create({
+ 'name': 'lot2',
+ 'product_id': p1.id,
+ })
+
+ self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 10, lot_id=lot_1)
+ self.env['stock.quant']._update_available_quantity(p1, self.stock_location, 10, lot_id=lot_2)
+
+ self.env['stock.quant']._update_available_quantity(p2, self.stock_location, 5)
+ mo.action_assign()
+
+ produce_wizard = self.env['mrp.product.produce'].with_context({
+ 'active_id': mo.id,
+ 'active_ids': [mo.id],
+ }).create({
+ 'product_qty': 5.0,
+ })
+ produce_wizard._onchange_product_qty()
+
+ for produce_line in produce_wizard.produce_line_ids:
+ produce_line.qty_done = produce_line.qty_to_consume
+ produce_wizard.do_produce()
+
+ mo.move_finished_ids.move_line_ids.qty_done -= 1
+ update_quantity_wizard = self.env['change.production.qty'].create({
+ 'mo_id': mo.id,
+ 'product_qty': 4,
+ })
+ update_quantity_wizard.change_prod_qty()
+
+ self.assertEqual(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).quantity_done, 20, 'Update the produce quantity should not impact already produced quantity.')
+ mo.button_mark_done()
+
def test_product_produce_uom(self):
plastic_laminate = self.env.ref('mrp.product_product_plastic_laminate')
bom = self.env.ref('mrp.mrp_bom_plastic_laminate')
diff --git a/addons/mrp/wizard/change_production_qty.py b/addons/mrp/wizard/change_production_qty.py
index 6cda5d64f9b..b92616c9a50 100644
--- a/addons/mrp/wizard/change_production_qty.py
+++ b/addons/mrp/wizard/change_production_qty.py
@@ -53,7 +53,6 @@ class ChangeProductionQty(models.TransientModel):
factor = production.product_uom_id._compute_quantity(production.product_qty - qty_produced, production.bom_id.product_uom_id) / production.bom_id.product_qty
boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id)
documents = {}
- done_quantities = {move: move.quantity_done for move in production.move_raw_ids}
for line, line_data in lines:
move, old_qty, new_qty = production._update_raw_move(line, line_data)
iterate_key = production._get_document_iterate_key(move)
@@ -73,9 +72,6 @@ class ChangeProductionQty(models.TransientModel):
production._log_downside_manufactured_quantity(finished_moves_modification)
moves = production.move_raw_ids.filtered(lambda x: x.state not in ('done', 'cancel'))
moves._action_assign()
- for move in production.move_raw_ids:
- if move.quantity_done != done_quantities[move]:
- move._set_quantity_done(done_quantities[move])
for wo in production.workorder_ids:
operation = wo.operation_id
if operation_bom_qty.get(operation.id):
diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py
index afed11da38e..209c4556d7b 100644
--- a/addons/payment/models/payment_acquirer.py
+++ b/addons/payment/models/payment_acquirer.py
@@ -324,7 +324,7 @@ class PaymentAcquirer(models.Model):
'acquirers': acquirers,
'pms': self.env['payment.token'].search([
('partner_id', '=', partner.id),
- ('acquirer_id', 'in', acquirers.filtered(lambda acq: acq.payment_flow == 's2s').ids)]),
+ ('acquirer_id', 'in', acquirers.ids)]),
}
@api.multi
diff --git a/addons/payment/wizards/payment_acquirer_onboarding_wizard.py b/addons/payment/wizards/payment_acquirer_onboarding_wizard.py
index b53b25130c6..1b23489460c 100644
--- a/addons/payment/wizards/payment_acquirer_onboarding_wizard.py
+++ b/addons/payment/wizards/payment_acquirer_onboarding_wizard.py
@@ -114,12 +114,14 @@ class PaymentWizard(models.TransientModel):
'paypal_seller_account': self.paypal_seller_account,
'paypal_pdt_token': self.paypal_pdt_token,
'website_published': True,
+ 'environment': 'prod',
})
if self.payment_method == 'stripe':
new_env.ref('payment.payment_acquirer_stripe').write({
'stripe_secret_key': self.stripe_secret_key,
'stripe_publishable_key': self.stripe_publishable_key,
'website_published': True,
+ 'environment': 'prod',
})
if self.payment_method == 'manual':
manual_acquirer = self._get_manual_payment_acquirer(new_env)
@@ -131,6 +133,7 @@ class PaymentWizard(models.TransientModel):
manual_acquirer.name = self.manual_name
manual_acquirer.post_msg = self.manual_post_msg
manual_acquirer.website_published = True
+ manual_acquirer.environment = 'prod'
journal = manual_acquirer.journal_id
if journal:
diff --git a/addons/point_of_sale/models/pos_order.py b/addons/point_of_sale/models/pos_order.py
index a4919e7c17f..b9543ca8453 100644
--- a/addons/point_of_sale/models/pos_order.py
+++ b/addons/point_of_sale/models/pos_order.py
@@ -572,14 +572,22 @@ class PosOrder(models.Model):
states={'draft': [('readonly', False)]},
)
- @api.onchange('statement_ids', 'lines', 'lines')
+ @api.onchange('statement_ids', 'lines')
def _onchange_amount_all(self):
+ amounts = {order_id: {'paid': 0, 'return': 0, 'untaxed': 0} for order_id in self.ids}
+ for order in self.env['account.bank.statement.line'].read_group([('pos_statement_id', 'in', self.ids)], ['pos_statement_id', 'amount'], ['pos_statement_id']):
+ amounts[order['pos_statement_id'][0]]['paid'] = order['amount']
+ for order in self.env['account.bank.statement.line'].read_group(['&', ('pos_statement_id', 'in', self.ids), ('amount', '<', 0)], ['pos_statement_id', 'amount'], ['pos_statement_id']):
+ amounts[order['pos_statement_id'][0]]['return'] = order['amount']
+ for order in self.env['pos.order.line'].read_group([('order_id', 'in', self.ids)], ['order_id', 'price_subtotal'], ['order_id']):
+ amounts[order['order_id'][0]]['untaxed'] = order['price_subtotal']
+
for order in self:
currency = order.pricelist_id.currency_id
- order.amount_paid = sum(payment.amount for payment in order.statement_ids)
- order.amount_return = sum(payment.amount < 0 and payment.amount or 0 for payment in order.statement_ids)
+ order.amount_paid = amounts[order.id]['paid']
+ order.amount_return = amounts[order.id]['return']
order.amount_tax = currency.round(sum(self._amount_line_tax(line, order.fiscal_position_id) for line in order.lines))
- amount_untaxed = currency.round(sum(line.price_subtotal for line in order.lines))
+ amount_untaxed = currency.round(amounts[order.id]['untaxed'])
order.amount_total = order.amount_tax + amount_untaxed
@api.onchange('partner_id')
diff --git a/addons/point_of_sale/static/src/js/chrome.js b/addons/point_of_sale/static/src/js/chrome.js
index d0d74c272f2..026682d5135 100644
--- a/addons/point_of_sale/static/src/js/chrome.js
+++ b/addons/point_of_sale/static/src/js/chrome.js
@@ -723,7 +723,7 @@ var Chrome = PosBaseWidget.extend(AbstractAction.prototype, {
body = 'The Point of Sale could not be loaded due to a network problem.\n Please check your internet connection.';
}else if(err.message === 'TLSError'){
title = 'Https connection to IoT Box failed';
- body = 'Make sure you are using IoT Box v18.10 or higher.\n\n Navigate to ' + err.url + ' to accept the certificate of your IoT Box.';
+ body = 'Make sure you are using IoT Box v18.12 or higher.\n\n Navigate to ' + err.url + ' to accept the certificate of your IoT Box.';
}else if(err.code === 200){
title = err.data.message;
body = err.data.debug;
diff --git a/addons/point_of_sale/tools/posbox/configuration/posbox_update.sh b/addons/point_of_sale/tools/posbox/configuration/posbox_update.sh
index e994a60461f..8629d1a629a 100755
--- a/addons/point_of_sale/tools/posbox/configuration/posbox_update.sh
+++ b/addons/point_of_sale/tools/posbox/configuration/posbox_update.sh
@@ -1,6 +1,11 @@
#!/usr/bin/env bash
sudo mount -o remount,rw /
-sudo git --work-tree=/home/pi/odoo/ --git-dir=/home/pi/odoo/.git pull
+
+cd /home/pi/odoo
+localbranch=$(git symbolic-ref -q --short HEAD)
+localremote=$(git config branch.$localbranch.remote)
+git fetch "${localremote}" "${localbranch}" --depth=1
+git reset "${localremote}"/"${localbranch}" --hard
sudo mount -o remount,ro /
(sleep 5 && sudo reboot) &
diff --git a/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh b/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh
index c9fc6c0da92..01470fff3c6 100755
--- a/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh
+++ b/addons/point_of_sale/tools/posbox/configuration/setup_ramdisks.sh
@@ -22,3 +22,7 @@ create_ramdisk "/tmp" "64M"
# bind mount / so that we can get to the real /var and /etc
mount --bind / /root_bypass_ramdisks
+
+# allow to cups server to save configuration file of printers
+mount --bind /root_bypass_ramdisks/etc/cups /root_bypass_ramdisks/etc/cups
+mount -o remount,rw /root_bypass_ramdisks/etc/cups /root_bypass_ramdisks/etc/cups
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cups-files.conf b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cups-files.conf
new file mode 100644
index 00000000000..31864e16705
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cups-files.conf
@@ -0,0 +1,93 @@
+#
+# File/directory/user/group configuration file for the CUPS scheduler.
+# See "man cups-files.conf" for a complete description of this file.
+#
+
+# List of events that are considered fatal errors for the scheduler...
+#FatalErrors config
+
+# Do we call fsync() after writing configuration or status files?
+#SyncOnClose Yes
+
+# Default user and group for filters/backends/helper programs; this cannot be
+# any user or group that resolves to ID 0 for security reasons...
+#User lp
+#Group lp
+
+# Administrator user group, used to match @SYSTEM in cupsd.conf policy rules...
+# This cannot contain the Group value for security reasons...
+SystemGroup lpadmin pi
+
+
+# User that is substituted for unauthenticated (remote) root accesses...
+#RemoteRoot remroot
+
+# Do we allow file: device URIs other than to /dev/null?
+#FileDevice No
+
+# Permissions for configuration and log files...
+#ConfigFilePerm 0640
+#LogFilePerm 00640
+
+# Location of the file logging all access to the scheduler; may be the name
+# "syslog". If not an absolute path, the value of ServerRoot is used as the
+# root directory. Also see the "AccessLogLevel" directive in cupsd.conf.
+AccessLog /var/log/cups/access_log
+
+# Location of cache files used by the scheduler...
+#CacheDir /var/cache/cups
+
+# Location of data files used by the scheduler...
+#DataDir /usr/share/cups
+
+# Location of the static web content served by the scheduler...
+#DocumentRoot /usr/share/cups/doc-root
+
+# Location of the file logging all messages produced by the scheduler and any
+# helper programs; may be the name "syslog". If not an absolute path, the value
+# of ServerRoot is used as the root directory. Also see the "LogLevel"
+# directive in cupsd.conf.
+ErrorLog /var/log/cups/error_log
+
+# Location of fonts used by older print filters...
+#FontPath /usr/share/cups/fonts
+
+# Location of LPD configuration
+#LPDConfigFile
+
+# Location of the file logging all pages printed by the scheduler and any
+# helper programs; may be the name "syslog". If not an absolute path, the value
+# of ServerRoot is used as the root directory. Also see the "PageLogFormat"
+# directive in cupsd.conf.
+PageLog /var/log/cups/page_log
+
+# Location of the file listing all of the local printers...
+#Printcap /run/cups/printcap
+
+# Format of the Printcap file...
+#PrintcapFormat bsd
+#PrintcapFormat plist
+#PrintcapFormat solaris
+
+# Location of all spool files...
+#RequestRoot /var/spool/cups
+
+# Location of helper programs...
+#ServerBin /usr/lib/cups
+
+# SSL/TLS keychain for the scheduler...
+#ServerKeychain ssl
+
+# Location of other configuration files...
+ServerRoot /root_bypass_ramdisks/etc/cups
+
+# Location of Samba configuration file...
+#SMBConfigFile
+
+# Location of scheduler state files...
+#StateDir /run/cups
+
+# Location of scheduler/helper temporary files. This directory is emptied on
+# scheduler startup and cannot be one of the standard (public) temporary
+# directory locations for security reasons...
+#TempDir /var/spool/cups/tmp
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cupsd.conf b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cupsd.conf
new file mode 100644
index 00000000000..ee6cbbf93d4
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/cups/cupsd.conf
@@ -0,0 +1,188 @@
+#
+# Configuration file for the CUPS scheduler. See "man cupsd.conf" for a
+# complete description of this file.
+#
+
+# Log general information in error_log - change "warn" to "debug"
+# for troubleshooting...
+LogLevel warn
+PageLogFormat
+
+# Deactivate CUPS' internal logrotating, as we provide a better one, especially
+# LogLevel debug2 gets usable now
+MaxLogSize 0
+
+# Only listen for connections from the local machine.
+Listen 0.0.0.0:631
+Listen /run/cups/cups.sock
+
+# Show shared printers on the local network.
+Browsing On
+BrowseLocalProtocols dnssd
+
+# Default authentication type, when authentication is required...
+DefaultAuthType Basic
+
+# Web interface setting...
+WebInterface Yes
+
+# Restrict access to the server...
+<Location />
+ Order allow,deny
+ Allow all
+</Location>
+
+# Restrict access to the admin pages...
+<Location /admin>
+ Order allow,deny
+ Allow all
+</Location>
+
+# Restrict access to configuration files...
+<Location /admin/conf>
+ AuthType Default
+ Require user @SYSTEM
+ Order allow
+</Location>
+
+# Restrict access to log files...
+<Location /admin/log>
+ AuthType Default
+ Require user @SYSTEM
+ Order allow
+</Location>
+
+# Set the default printer/job policies...
+<Policy default>
+ # Job/subscription privacy...
+ JobPrivateAccess default
+ JobPrivateValues default
+ SubscriptionPrivateAccess default
+ SubscriptionPrivateValues default
+
+ # Job-related operations must be done by the owner or an administrator...
+ <Limit Create-Job Print-Job Print-URI Validate-Job>
+ Order deny,allow
+ </Limit>
+
+ <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
+ Require user @OWNER @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # All administration operations require an administrator to authenticate...
+ <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default CUPS-Get-Devices>
+ AuthType Default
+ Require user @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # All printer operations require a printer operator to authenticate...
+ <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
+ AuthType Default
+ Require user @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # Only the owner or an administrator can cancel or authenticate a job...
+ <Limit Cancel-Job CUPS-Authenticate-Job>
+ Require user @OWNER @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ <Limit All>
+ Order deny,allow
+ </Limit>
+</Policy>
+
+# Set the authenticated printer/job policies...
+<Policy authenticated>
+ # Job/subscription privacy...
+ JobPrivateAccess default
+ JobPrivateValues default
+ SubscriptionPrivateAccess default
+ SubscriptionPrivateValues default
+
+ # Job-related operations must be done by the owner or an administrator...
+ <Limit Create-Job Print-Job Print-URI Validate-Job>
+ AuthType Default
+ Order deny,allow
+ </Limit>
+
+ <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
+ AuthType Default
+ Require user @OWNER @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # All administration operations require an administrator to authenticate...
+ <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>
+ AuthType Default
+ Require user @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # All printer operations require a printer operator to authenticate...
+ <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
+ AuthType Default
+ Require user @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # Only the owner or an administrator can cancel or authenticate a job...
+ <Limit Cancel-Job CUPS-Authenticate-Job>
+ AuthType Default
+ Require user @OWNER @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ <Limit All>
+ Order deny,allow
+ </Limit>
+</Policy>
+
+# Set the kerberized printer/job policies...
+<Policy kerberos>
+ # Job/subscription privacy...
+ JobPrivateAccess default
+ JobPrivateValues default
+ SubscriptionPrivateAccess default
+ SubscriptionPrivateValues default
+
+ # Job-related operations must be done by the owner or an administrator...
+ <Limit Create-Job Print-Job Print-URI Validate-Job>
+ AuthType Negotiate
+ Order deny,allow
+ </Limit>
+
+ <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
+ AuthType Negotiate
+ Require user @OWNER @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # All administration operations require an administrator to authenticate...
+ <Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>
+ AuthType Default
+ Require user @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # All printer operations require a printer operator to authenticate...
+ <Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
+ AuthType Default
+ Require user @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ # Only the owner or an administrator can cancel or authenticate a job...
+ <Limit Cancel-Job CUPS-Authenticate-Job>
+ AuthType Negotiate
+ Require user @OWNER @SYSTEM
+ Order deny,allow
+ </Limit>
+
+ <Limit All>
+ Order deny,allow
+ </Limit>
+</Policy> \ No newline at end of file
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/nginx/sites-enabled/default b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/nginx/sites-enabled/default
index b85a093785a..cd95a43753a 100644
--- a/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/nginx/sites-enabled/default
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/etc/nginx/sites-enabled/default
@@ -76,16 +76,16 @@ server {
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
-#server {
-# listen 80;
+server {
+ listen 80;
# listen [::]:80;
#
# server_name example.com;
#
-# root /var/www/example.com;
-# index index.html;
+ root /var/www/;
+ index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
-#}
+}
diff --git a/addons/point_of_sale/tools/posbox/overwrite_after_init/var/www/iot.jpg b/addons/point_of_sale/tools/posbox/overwrite_after_init/var/www/iot.jpg
new file mode 100644
index 00000000000..863710d5ade
--- /dev/null
+++ b/addons/point_of_sale/tools/posbox/overwrite_after_init/var/www/iot.jpg
Binary files differ
diff --git a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh
index 254c8def2b0..85c1933f096 100755
--- a/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh
+++ b/addons/point_of_sale/tools/posbox/overwrite_before_init/etc/init_posbox_image.sh
@@ -21,7 +21,70 @@ apt-get update && apt-get -y upgrade
# Do not be too fast to upgrade to more recent firmware and kernel than 4.38
# Firmware 4.44 seems to prevent the LED mechanism from working
-PKGS_TO_INSTALL="fswebcam python3-urllib3 cups printer-driver-all cups-ipp-utils adduser postgresql python3 python3-dateutil python3-decorator python3-docutils python3-feedparser python3-pil python3-jinja2 python3-ldap3 python3-lxml python3-mako python3-mock python3-openid python3-psutil python3-psycopg2 python3-babel python3-pydot python3-pyparsing python3-pypdf2 python3-reportlab python3-requests python3-simplejson python3-tz python3-vatnumber python3-werkzeug python3-serial python3-pip python3-dev localepurge vim mc mg screen iw hostapd git rsync console-data lightdm xserver-xorg-video-fbdev xserver-xorg-input-evdev iceweasel xdotool unclutter x11-utils openbox python3-netifaces rpi-update python3-passlib python3-libsass python3-qrcode python3-html2text python3-unittest2 python3-simplejson nginx-full dnsmasq"
+PKGS_TO_INSTALL="
+ fswebcam \
+ nginx-full \
+ dnsmasq \
+ cups \
+ printer-driver-all \
+ cups-ipp-utils \
+ localepurge \
+ vim \
+ mc \
+ mg \
+ screen \
+ iw \
+ hostapd \
+ git \
+ rsync \
+ console-data \
+ lightdm \
+ xserver-xorg-video-fbdev \
+ xserver-xorg-input-evdev \
+ iceweasel \
+ xdotool \
+ unclutter \
+ x11-utils \
+ openbox \
+ rpi-update \
+ adduser \
+ postgresql \
+ python3 \
+ python3-urllib3 \
+ python3-dateutil \
+ python3-decorator \
+ python3-docutils \
+ python3-feedparser \
+ python3-pil \
+ python3-jinja2 \
+ python3-ldap3 \
+ python3-lxml \
+ python3-mako \
+ python3-mock \
+ python3-openid \
+ python3-psutil \
+ python3-psycopg2 \
+ python3-babel \
+ python3-pydot \
+ python3-pyparsing \
+ python3-pypdf2 \
+ python3-reportlab \
+ python3-requests \
+ python3-simplejson \
+ python3-tz \
+ python3-vatnumber \
+ python3-werkzeug \
+ python3-serial \
+ python3-pip \
+ python3-dev \
+ python3-netifaces \
+ python3-passlib \
+ python3-libsass \
+ python3-qrcode \
+ python3-html2text \
+ python3-unittest2 \
+ python3-simplejson"
+
echo "Acquire::Retries "16";" > /etc/apt/apt.conf.d/99acquire-retries
# KEEP OWN CONFIG FILES DURING PACKAGE CONFIGURATION
# http://serverfault.com/questions/259226/automatically-keep-current-version-of-config-files-when-apt-get-install
@@ -84,6 +147,7 @@ fi
if [ $SYSTEMD -eq 1 ]; then
systemctl set-default graphical.target
ln -fs /etc/systemd/system/autologin@.service /etc/systemd/system/getty.target.wants/getty@tty1.service
+ rm /etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service
else
update-rc.d lightdm enable 2
fi
diff --git a/addons/point_of_sale/tools/posbox/posbox_create_image.sh b/addons/point_of_sale/tools/posbox/posbox_create_image.sh
index 946d2cefbde..0c517da73d7 100755
--- a/addons/point_of_sale/tools/posbox/posbox_create_image.sh
+++ b/addons/point_of_sale/tools/posbox/posbox_create_image.sh
@@ -29,7 +29,7 @@ __base="$(basename ${__file} .sh)"
MOUNT_POINT="${__dir}/root_mount"
OVERWRITE_FILES_BEFORE_INIT_DIR="${__dir}/overwrite_before_init"
OVERWRITE_FILES_AFTER_INIT_DIR="${__dir}/overwrite_after_init"
-VERSION=saas-11.5
+VERSION=12.0
REPO=https://github.com/odoo/odoo.git
if [ ! -f kernel-qemu ] || ! file_exists *raspbian*.img ; then
diff --git a/addons/product/models/product.py b/addons/product/models/product.py
index 7b8a60a9787..ef770c8ac38 100644
--- a/addons/product/models/product.py
+++ b/addons/product/models/product.py
@@ -414,7 +414,7 @@ class ProductProduct(models.Model):
# Prefetch the fields used by the `name_get`, so `browse` doesn't fetch other fields
# Use `load=False` to not call `name_get` for the `product_tmpl_id`
- self.sudo().read(['name', 'default_code', 'product_tmpl_id', 'attribute_value_ids'], load=False)
+ self.sudo().read(['name', 'default_code', 'product_tmpl_id', 'attribute_value_ids', 'attribute_line_ids'], load=False)
product_template_ids = self.sudo().mapped('product_tmpl_id').ids
@@ -431,7 +431,7 @@ class ProductProduct(models.Model):
supplier_info_by_template.setdefault(r.product_tmpl_id, []).append(r)
for product in self.sudo():
# display only the attributes with multiple possible values on the template
- variable_attributes = product.attribute_value_ids.filtered(lambda v: len(v.attribute_id.value_ids) > 1).mapped('attribute_id')
+ variable_attributes = product.attribute_line_ids.filtered(lambda l: len(l.value_ids) > 1).mapped('attribute_id')
variant = product.attribute_value_ids._variant_name(variable_attributes)
name = variant and "%s (%s)" % (product.name, variant) or product.name
diff --git a/addons/product/views/product_views.xml b/addons/product/views/product_views.xml
index 3d2a4306f66..12159290405 100644
--- a/addons/product/views/product_views.xml
+++ b/addons/product/views/product_views.xml
@@ -310,7 +310,7 @@
<label for="weight"/>
<div class="o_row">
<field name="weight"/>
- <span>kg</span>
+ <span><field name="weight_uom_name"/></span>
</div>
</group>
<group name="packaging" string="Packaging" groups="product.group_stock_packaging">
diff --git a/addons/purchase/models/res_partner.py b/addons/purchase/models/res_partner.py
index 75b849af619..32007e09ab4 100644
--- a/addons/purchase/models/res_partner.py
+++ b/addons/purchase/models/res_partner.py
@@ -11,15 +11,38 @@ class res_partner(models.Model):
@api.multi
def _compute_purchase_order_count(self):
- PurchaseOrder = self.env['purchase.order']
- for partner in self:
- partner.purchase_order_count = PurchaseOrder.search_count([('partner_id', 'child_of', partner.id)])
+ # retrieve all children partners and prefetch 'parent_id' on them
+ all_partners = self.search([('id', 'child_of', self.ids)])
+ all_partners.read(['parent_id'])
+
+ purchase_order_groups = self.env['purchase.order'].read_group(
+ domain=[('partner_id', 'in', all_partners.ids)],
+ fields=['partner_id'], groupby=['partner_id']
+ )
+ for group in purchase_order_groups:
+ partner = self.browse(group['partner_id'][0])
+ while partner:
+ if partner in self:
+ partner.purchase_order_count += group['partner_id_count']
+ partner = partner.parent_id
@api.multi
def _compute_supplier_invoice_count(self):
- Invoice = self.env['account.invoice']
- for partner in self:
- partner.supplier_invoice_count = Invoice.search_count([('partner_id', 'child_of', partner.id), ('type', 'in', ('in_invoice', 'in_refund'))])
+ # retrieve all children partners and prefetch 'parent_id' on them
+ all_partners = self.search([('id', 'child_of', self.ids), ('type', 'in', ('in_invoice', 'in_refund')])
+ all_partners.read(['parent_id'])
+
+ supplier_invoice_groups = self.env['account.invoice'].read_group(
+ domain=[('partner_id', 'in', all_partners.ids),
+ ('type', '=', 'in_invoice')],
+ fields=['partner_id'], groupby=['partner_id']
+ )
+ for group in supplier_invoice_groups:
+ partner = self.browse(group['partner_id'][0])
+ while partner:
+ if partner in self:
+ partner.supplier_invoice_count += group['partner_id_count']
+ partner = partner.parent_id
@api.model
def _commercial_fields(self):
diff --git a/addons/purchase/report/purchase_bill.py b/addons/purchase/report/purchase_bill.py
index f9af76ca424..a16ff44b60c 100644
--- a/addons/purchase/report/purchase_bill.py
+++ b/addons/purchase/report/purchase_bill.py
@@ -8,7 +8,7 @@ class PurchaseBillUnion(models.Model):
_name = 'purchase.bill.union'
_auto = False
_description = 'Purchases & Bills Union'
- _order = "purchase_order_id desc, vendor_bill_id desc"
+ _order = "date desc, name desc"
name = fields.Char(string='Reference', readonly=True)
reference = fields.Char(string='Source', readonly=True)
diff --git a/addons/purchase/views/purchase_views.xml b/addons/purchase/views/purchase_views.xml
index 9c1f9d409c4..e4d9fcd309e 100644
--- a/addons/purchase/views/purchase_views.xml
+++ b/addons/purchase/views/purchase_views.xml
@@ -220,6 +220,7 @@
<field name="taxes_id" widget="many2many_tags" domain="[('type_tax_use', '=', 'purchase')]" options="{'no_create': True}"/>
<field name="date_planned" widget="date"/>
<field name="account_analytic_id" colspan="2" groups="analytic.group_analytic_accounting"/>
+ <field name="analytic_tag_ids" groups="analytic.group_analytic_accounting" widget="many2many_tags" options="{'color_field': 'color'}"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
</group>
</group>
diff --git a/addons/sale/models/sale.py b/addons/sale/models/sale.py
index 5ab5355ac24..04391491a4d 100644
--- a/addons/sale/models/sale.py
+++ b/addons/sale/models/sale.py
@@ -863,21 +863,6 @@ class SaleOrder(models.Model):
self.ensure_one()
return '%s %s' % (self.type_name, self.name)
- @api.multi
- def get_access_action(self, access_uid=None):
- """ Instead of the classic form view, redirect to the online quote if it exists. """
- self.ensure_one()
- user = access_uid and self.env['res.users'].sudo().browse(access_uid) or self.env.user
-
- if not self.sale_order_template_id or (not user.share and not self.env.context.get('force_website')):
- return super(SaleOrder, self).get_access_action(access_uid)
- return {
- 'type': 'ir.actions.act_url',
- 'url': self.get_portal_url(),
- 'target': 'self',
- 'res_id': self.id,
- }
-
def _get_share_url(self, redirect=False, signup_partner=False, pid=None):
self.ensure_one()
if self.state not in ['sale', 'done']:
diff --git a/addons/sale/views/sale_views.xml b/addons/sale/views/sale_views.xml
index 582c23404bf..ade6a2e3f52 100644
--- a/addons/sale/views/sale_views.xml
+++ b/addons/sale/views/sale_views.xml
@@ -313,6 +313,7 @@
<field name="qty_to_invoice" invisible="1"/>
<field name="qty_delivered_manual" invisible="1"/>
<field name="qty_delivered_method" invisible="1"/>
+ <field name="price_total" invisible="1"/>
<field name="price_subtotal" invisible="1"/>
<label for="product_uom_qty" string="Ordered Quantity"/>
<div>
@@ -479,6 +480,7 @@
<field name="product_uom_qty"/>
<field name="product_uom" groups="uom.group_uom"/>
<field name="price_subtotal"/>
+ <field name="price_total" invisible="1"/>
<field name="price_unit"/>
<field name="display_type"/>
<templates>
diff --git a/addons/sale_management/models/sale_order.py b/addons/sale_management/models/sale_order.py
index bc32d716dab..afa13aed50d 100644
--- a/addons/sale_management/models/sale_order.py
+++ b/addons/sale_management/models/sale_order.py
@@ -114,6 +114,21 @@ class SaleOrder(models.Model):
self.sale_order_template_id.mail_template_id.send_mail(order.id)
return res
+ @api.multi
+ def get_access_action(self, access_uid=None):
+ """ Instead of the classic form view, redirect to the online quote if it exists. """
+ self.ensure_one()
+ user = access_uid and self.env['res.users'].sudo().browse(access_uid) or self.env.user
+
+ if not self.sale_order_template_id or (not user.share and not self.env.context.get('force_website')):
+ return super(SaleOrder, self).get_access_action(access_uid)
+ return {
+ 'type': 'ir.actions.act_url',
+ 'url': self.get_portal_url(),
+ 'target': 'self',
+ 'res_id': self.id,
+ }
+
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
diff --git a/addons/snailmail/static/src/scss/snailmail_external_layout_asset.scss b/addons/snailmail/static/src/scss/snailmail_external_layout_asset.scss
index 340c17dda25..ae60f3d4458 100644
--- a/addons/snailmail/static/src/scss/snailmail_external_layout_asset.scss
+++ b/addons/snailmail/static/src/scss/snailmail_external_layout_asset.scss
@@ -14,6 +14,9 @@
padding-left: 10mm;
}
}
+.o_background_footer {
+ padding-left: 8mm;
+}
.article>.page {
> h1, > h2, > h3 {
width: 50%;
diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py
index 3ecccb65beb..8e4bde1a2e2 100644
--- a/addons/stock_account/models/product.py
+++ b/addons/stock_account/models/product.py
@@ -50,6 +50,7 @@ class ProductTemplate(models.Model):
class ProductProduct(models.Model):
_inherit = 'product.product'
+ stock_value_currency_id = fields.Many2one('res.currency', compute='_compute_stock_value_currency')
stock_value = fields.Float(
'Value', compute='_compute_stock_value')
qty_at_date = fields.Float(
@@ -126,6 +127,12 @@ class ProductProduct(models.Model):
return sum(moves.mapped('remaining_value')), moves
@api.multi
+ def _compute_stock_value_currency(self):
+ currency_id = self.env.user.company_id.currency_id
+ for product in self:
+ product.stock_value_currency_id = currency_id
+
+ @api.multi
@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.categ_id.property_valuation')
def _compute_stock_value(self):
StockMove = self.env['stock.move']
@@ -191,12 +198,14 @@ class ProductProduct(models.Model):
"""
self.ensure_one()
to_date = self.env.context.get('to_date')
+ ctx = self.env.context.copy()
+ ctx.pop('group_by', None)
action = {
'name': _('Valuation at date'),
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'tree,form',
- 'context': self.env.context,
+ 'context': ctx,
}
if self.valuation == 'real_time':
action['res_model'] = 'account.move.line'
diff --git a/addons/stock_account/views/stock_account_views.xml b/addons/stock_account/views/stock_account_views.xml
index fd6ed2c27a5..a9dbf024f2e 100644
--- a/addons/stock_account/views/stock_account_views.xml
+++ b/addons/stock_account/views/stock_account_views.xml
@@ -77,7 +77,8 @@
<field name="qty_at_date"/>
<field name="uom_id" groups="uom.group_uom"/>
<field name="currency_id" invisible="1"/>
- <field name="stock_value" sum="Stock Valuation" widget="monetary"/>
+ <field name="stock_value_currency_id" invisible="1"/>
+ <field name="stock_value" sum="Stock Valuation" widget="monetary" options="{'currency_field': 'stock_value_currency_id'}"/>
<field name="cost_method" invisible="1"/>
<button name="action_valuation_at_date_details" type="object" icon="fa-info-circle" aria-label="Valuation" title="Valuation" attrs="{'invisible': [('cost_method', '!=', 'fifo')]}" />
</tree>
diff --git a/addons/survey/controllers/main.py b/addons/survey/controllers/main.py
index 80ee03d0dcf..2d7d1b49df5 100644
--- a/addons/survey/controllers/main.py
+++ b/addons/survey/controllers/main.py
@@ -254,6 +254,10 @@ class Survey(http.Controller):
def print_survey(self, survey, token=None, **post):
'''Display an survey in printable view; if <token> is set, it will
grab the answers of the user_input_id that has <token>.'''
+
+ if survey.auth_required and request.env.user == request.website.user_id:
+ return request.render("survey.auth_required", {'survey': survey, 'token': token})
+
return request.render('survey.survey_print',
{'survey': survey,
'token': token,
diff --git a/addons/web/static/src/js/chrome/abstract_web_client.js b/addons/web/static/src/js/chrome/abstract_web_client.js
index ea8fdc24a18..7082f26e69d 100644
--- a/addons/web/static/src/js/chrome/abstract_web_client.js
+++ b/addons/web/static/src/js/chrome/abstract_web_client.js
@@ -205,6 +205,10 @@ var AbstractWebClient = Widget.extend(ServiceProviderMixin, KeyboardNavigationMi
});
}
} else {
+ // ignore Chrome video internal error: https://crbug.com/809574
+ if (!error && message === 'ResizeObserver loop limit exceeded') {
+ return;
+ }
var traceback = error ? error.stack : '';
crash_manager.show_error({
type: _t("Odoo Client Error"),
diff --git a/addons/web/static/src/js/chrome/apps_menu.js b/addons/web/static/src/js/chrome/apps_menu.js
index f6535ed764c..eb7faaa971b 100644
--- a/addons/web/static/src/js/chrome/apps_menu.js
+++ b/addons/web/static/src/js/chrome/apps_menu.js
@@ -41,6 +41,9 @@ var AppsMenu = Widget.extend({
* Open the first app in the list of apps
*/
openFirstApp: function () {
+ if (!this._apps.length) {
+ return
+ }
var firstApp = this._apps[0];
this._openApp(firstApp);
},
diff --git a/addons/web/static/src/js/fields/special_fields.js b/addons/web/static/src/js/fields/special_fields.js
index 5057b9de33f..e9dcbc592a3 100644
--- a/addons/web/static/src/js/fields/special_fields.js
+++ b/addons/web/static/src/js/fields/special_fields.js
@@ -122,7 +122,8 @@ var FieldTimezoneMismatch = FieldSelection.extend({
});
var FieldReportLayout = relational_fields.FieldMany2One.extend({
- supportedFieldTypes: ['many2one', 'selection'],
+ // this widget is not generic, so we disable its studio use
+ // supportedFieldTypes: ['many2one', 'selection'],
events: _.extend({}, relational_fields.FieldMany2One.prototype.events, {
'click img': '_onImgClicked',
}),
diff --git a/addons/web/static/src/js/services/crash_manager.js b/addons/web/static/src/js/services/crash_manager.js
index e1da816c8e5..31aa178dc1b 100644
--- a/addons/web/static/src/js/services/crash_manager.js
+++ b/addons/web/static/src/js/services/crash_manager.js
@@ -22,6 +22,7 @@ var map_title ={
var CrashManager = core.Class.extend({
init: function() {
this.active = true;
+ this.isConnected = true;
},
enable: function () {
this.active = true;
@@ -29,8 +30,29 @@ var CrashManager = core.Class.extend({
disable: function () {
this.active = false;
},
- rpc_error: function(error) {
+ handleLostConnection: function () {
var self = this;
+ if (!this.isConnected) {
+ // already handled, nothing to do. This can happen when several
+ // rpcs are done in parallel and fail because of a lost connection.
+ return;
+ }
+ this.isConnected = false;
+ var delay = 2000;
+ core.bus.trigger('connection_lost');
+
+ setTimeout(function checkConnection() {
+ ajax.jsonRpc('/web/webclient/version_info', 'call', {}, {shadow:true}).then(function () {
+ core.bus.trigger('connection_restored');
+ self.isConnected = true;
+ }).fail(function () {
+ // exponential backoff, with some jitter
+ delay = (delay * 1.5) + 500*Math.random();
+ setTimeout(checkConnection, delay);
+ });
+ }, delay);
+ },
+ rpc_error: function(error) {
if (!this.active) {
return;
}
@@ -38,16 +60,7 @@ var CrashManager = core.Class.extend({
return;
}
if (error.code === -32098) {
- core.bus.trigger('connection_lost');
- this.connection_lost = true;
- var timeinterval = setInterval(function() {
- var options = {shadow: true};
- ajax.jsonRpc('/web/webclient/version_info', 'call', {}, options).then(function () {
- clearInterval(timeinterval);
- core.bus.trigger('connection_restored');
- self.connection_lost = false;
- });
- }, 2000);
+ this.handleLostConnection();
return;
}
var handler = core.crash_registry.get(error.data.name, true);
diff --git a/addons/web/static/src/js/views/basic/basic_controller.js b/addons/web/static/src/js/views/basic/basic_controller.js
index 7f578da077d..f26a9cbe737 100644
--- a/addons/web/static/src/js/views/basic/basic_controller.js
+++ b/addons/web/static/src/js/views/basic/basic_controller.js
@@ -38,6 +38,10 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
FieldManagerMixin.init.call(this, this.model);
this.mode = params.mode || 'readonly';
this.handle = this.initialState.id;
+ // savingDef is used to ensure that we always wait for pending save
+ // operations to complete before checking if there are changes to
+ // discard when discardChanges is called
+ this.savingDef = $.when();
},
/**
* @override
@@ -102,14 +106,15 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
return true;
},
/**
- * Waits for the mutex to be unlocked and then calls _.discardChanges.
+ * Waits for the mutex to be unlocked and for changes to be saved, then
+ * calls _.discardChanges.
* This ensures that the confirm dialog isn't displayed directly if there is
* a pending 'write' rpc.
*
* @see _.discardChanges
*/
discardChanges: function (recordID, options) {
- return this.mutex.exec(function () {})
+ return $.when(this.mutex.getUnlockedDef(), this.savingDef)
.then(this._discardChanges.bind(this, recordID || this.handle, options));
},
/**
@@ -183,11 +188,12 @@ var BasicController = AbstractController.extend(FieldManagerMixin, {
// mutex-protected as commitChanges function of x2m has to be aware of
// all final changes made to a row.
var self = this;
- return this.mutex.getUnlockedDef().then(function () {
+ this.savingDef = this.mutex.getUnlockedDef().then(function () {
return self.renderer.commitChanges(recordID || self.handle).then(function () {
return self.mutex.exec(self._saveRecord.bind(self, recordID, options));
});
});
+ return this.savingDef;
},
/**
* @override
diff --git a/addons/web/static/src/js/views/field_manager_mixin.js b/addons/web/static/src/js/views/field_manager_mixin.js
index 343730cc7a4..bc61e92a89a 100644
--- a/addons/web/static/src/js/views/field_manager_mixin.js
+++ b/addons/web/static/src/js/views/field_manager_mixin.js
@@ -130,8 +130,10 @@ var FieldManagerMixin = {
if ('offset' in data) {
params.offset = data.offset;
}
- this.model.reload(data.id, params).then(function (db_id) {
- data.on_success(self.model.get(db_id));
+ this.mutex.exec(function () {
+ return self.model.reload(data.id, params).then(function (db_id) {
+ data.on_success(self.model.get(db_id));
+ });
});
},
/**
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 2383a0ac730..8c43857277c 100644
--- a/addons/web/static/src/js/views/kanban/kanban_controller.js
+++ b/addons/web/static/src/js/views/kanban/kanban_controller.js
@@ -210,15 +210,17 @@ var KanbanController = BasicController.extend({
*/
_onAddColumn: function (ev) {
var self = this;
- this.model.createGroup(ev.data.value, this.handle).then(function () {
- var state = self.model.get(self.handle, {raw: true});
- var ids = _.pluck(state.data, 'res_id').filter(_.isNumber);
- return self._resequenceColumns(ids);
- }).then(function () {
- return self.update({}, {reload: false});
- }).then(function () {
- self._updateButtons();
- self.renderer.quickCreateToggleFold();
+ this.mutex.exec(function () {
+ return self.model.createGroup(ev.data.value, this.handle).then(function () {
+ var state = self.model.get(self.handle, {raw: true});
+ var ids = _.pluck(state.data, 'res_id').filter(_.isNumber);
+ return self._resequenceColumns(ids);
+ }).then(function () {
+ return self.update({}, {reload: false});
+ }).then(function () {
+ self._updateButtons();
+ self.renderer.quickCreateToggleFold();
+ });
});
},
/**
@@ -271,11 +273,16 @@ var KanbanController = BasicController.extend({
* @private
*/
_onButtonNew: function () {
+ var self = this;
var state = this.model.get(this.handle, {raw: true});
var quickCreateEnabled = this.quickCreateEnabled && viewUtils.isQuickCreateEnabled(state);
if (this.on_create === 'quick_create' && quickCreateEnabled && state.data.length) {
- // Activate the quick create in the first column
- this.renderer.addQuickCreate();
+ // activate the quick create in the first column when the mutex is
+ // unlocked, to ensure that there is no pending re-rendering that
+ // would remove it (e.g. if we are currently adding a new column)
+ this.mutex.getUnlockedDef().then(function () {
+ self.renderer.addQuickCreate();
+ });
} else if (this.on_create && this.on_create !== 'quick_create') {
// Execute the given action
this.do_action(this.on_create, {
diff --git a/addons/web/static/src/js/views/pivot/pivot_model.js b/addons/web/static/src/js/views/pivot/pivot_model.js
index 5a6423fbe34..607cf2d7b2f 100644
--- a/addons/web/static/src/js/views/pivot/pivot_model.js
+++ b/addons/web/static/src/js/views/pivot/pivot_model.js
@@ -321,7 +321,7 @@ var PivotModel = AbstractModel.extend({
};
}
return {
- colGroupBys: this.data.main_col.groupbys,
+ colGroupBys: this.data.main_col.root.groupbys,
context: this.data.context,
domain: this.data.domain,
compare: this.data.compare,
@@ -331,7 +331,7 @@ var PivotModel = AbstractModel.extend({
mainColWidth: this.data.main_col.width,
measures: this.data.measures,
rows: !isRaw && this._computeRows(),
- rowGroupBys: this.data.main_row.groupbys,
+ rowGroupBys: this.data.main_row.root.groupbys,
sortedColumn: this.data.sorted_column,
};
},
@@ -432,22 +432,19 @@ var PivotModel = AbstractModel.extend({
return this._loadData();
}
- var old_row_root = this.data.main_row.root;
- var old_col_root = this.data.main_col.root;
+ var old_row = this.data.main_row;
+ var old_col = this.data.main_col;
return this._loadData().then(function () {
- var new_groupby_length;
if (!('groupBy' in params) && !('pivot_row_groupby' in (params.context || {}))) {
// we only update the row groupbys according to the old groupbys
// if we don't have the key 'groupBy' in params. In that case,
// we want to have the full open state for the groupbys.
- self._updateTree(old_row_root, self.data.main_row.root);
- new_groupby_length = self._getHeaderDepth(self.data.main_row.root) - 1;
- self.data.main_row.groupbys = old_row_root.groupbys.slice(0, new_groupby_length);
+ self._updateTree(old_row.root, self.data.main_row.root);
+ self._updateMainGroupBys(old_row, self.data.main_row);
}
- self._updateTree(old_col_root, self.data.main_col.root);
- new_groupby_length = self._getHeaderDepth(self.data.main_col.root) - 1;
- self.data.main_row.groupbys = old_row_root.groupbys.slice(0, new_groupby_length);
+ self._updateTree(old_col.root, self.data.main_col.root);
+ self._updateMainGroupBys(old_col, self.data.main_col);
});
},
/**
@@ -1052,9 +1049,6 @@ var PivotModel = AbstractModel.extend({
}
}
- this.data.main_row.groupbys = rowGroupBys;
- this.data.main_col.groupbys = colGroupBys;
-
main_row_header.other_root = main_col_header;
main_col_header.other_root = main_row_header;
@@ -1124,6 +1118,19 @@ var PivotModel = AbstractModel.extend({
}
},
/**
+ * Updates the groupBys that the main[row | col] holds
+ *
+ * @private
+ * @param {Object} old: The main abstract header before reload
+ * @param {Object} main: The main abstract header after reload
+ *
+ */
+ _updateMainGroupBys: function (old, main) {
+ var new_groupby_length = this._getHeaderDepth(main.root) - 1;
+ var new_groupby_list = old.root.groupbys.slice(0, new_groupby_length);
+ main.root.groupbys = new_groupby_list;
+ },
+ /**
* @param {Object} old_tree
* @param {Object} new_tree
*/
diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js
index 15999ca952e..21dcef78978 100644
--- a/addons/web/static/tests/fields/relational_fields_tests.js
+++ b/addons/web/static/tests/fields/relational_fields_tests.js
@@ -150,6 +150,61 @@ QUnit.module('relational_fields', {
}
}, function () {
+ QUnit.test('search more pager is reset when doing a new search', function (assert) {
+ assert.expect(6);
+ for(var i = 10; i < 180; i++) {
+ this.data.partner.records.push({
+ id: i,
+ display_name: "Partner " + i,
+ });
+ }
+
+ function stringToEvent ($element, string) {
+ for (var i = 0; i < string.length; i++) {
+ var keyAscii = string.charCodeAt(i);
+ $element.val($element.val()+string[i]);
+ $element.trigger($.Event('keyup', {which: keyAscii, keyCode:keyAscii}));
+ }
+ $element.trigger($.Event('keyup', {which: $.ui.keyCode.ENTER, keyCode:$.ui.keyCode.ENTER}));
+ }
+
+ this.data.partner.fields.datetime.searchable = true;
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<sheet>' +
+ '<group>' +
+ '<field name="trululu"/>' +
+ '</group>' +
+ '</sheet>' +
+ '</form>',
+ archs: {
+ 'partner,false,list': '<tree><field name="display_name"/></tree>',
+ 'partner,false,search': '<search><field name="datetime"/><field name="display_name"/></search>',
+ },
+ res_id: 1,
+ });
+
+ form.$buttons.find('.o_form_button_edit').click();
+ var $dropdown = form.$('.o_field_many2one input').autocomplete('widget');
+ form.$('.o_field_many2one input').click();
+ $dropdown.find('.o_m2o_dropdown_option:contains(Search)').mouseenter().click();
+ $('.modal .o_pager_next').click();
+
+ assert.strictEqual($('.o_pager_limit').text(), "1173", "there should be 173 records");
+ assert.strictEqual($('.o_pager_value').text(), "181-160", "should display the second page");
+ assert.strictEqual($('tr.o_data_row').length, 80, "should display 80 record");
+
+ stringToEvent($('.modal .o_searchview_input'), 'first');
+
+ assert.strictEqual($('.o_pager_limit').text(), "11", "there should be 1 record");
+ assert.strictEqual($('.o_pager_value').text(), "11-1", "should display the first page");
+ assert.strictEqual($('tr.o_data_row').length, 1, "should display 1 record");
+ form.destroy();
+ });
+
QUnit.test('x2many default_order multiple fields', function (assert) {
assert.expect(7);
@@ -446,6 +501,48 @@ QUnit.module('relational_fields', {
form.destroy();
});
+
+ form.destroy();
+ });
+
+ QUnit.test('quickly switch between pages in one2many list', function (assert) {
+ assert.expect(2);
+
+ this.data.partner.records[0].turtles = [1, 2, 3];
+
+ var readDefs = [$.when(), $.Deferred(), $.Deferred()];
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form string="Partners">' +
+ '<field name="turtles">' +
+ '<tree limit="1">' +
+ '<field name="display_name"/>' +
+ '</tree>' +
+ '</field>' +
+ '</form>',
+ mockRPC: function (route, args) {
+ var result = this._super.apply(this, arguments);
+ if (args.method === 'read') {
+ var recordID = args.args[0][0];
+ return $.when(readDefs[recordID - 1]).then(_.constant(result));
+ }
+ return result;
+ },
+ res_id: 1,
+ });
+
+ form.$('.o_field_widget[name=turtles] .o_pager_next').click();
+ form.$('.o_field_widget[name=turtles] .o_pager_next').click();
+
+ readDefs[1].resolve();
+
+ assert.strictEqual(form.$('.o_field_widget[name=turtles] .o_data_cell').text(), 'donatello');
+
+ readDefs[2].resolve();
+
+ assert.strictEqual(form.$('.o_field_widget[name=turtles] .o_data_cell').text(), 'raphael');
QUnit.test('many2many read, field context is properly sent', function (assert) {
assert.expect(4);
diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js
index e1cb3277dba..f70c21de765 100644
--- a/addons/web/static/tests/views/form_tests.js
+++ b/addons/web/static/tests/views/form_tests.js
@@ -7189,6 +7189,69 @@ QUnit.module('Views', {
form.destroy();
});
+ QUnit.test('call canBeRemoved while saving', function (assert) {
+ assert.expect(10);
+
+ this.data.partner.onchanges = {
+ foo: function (obj) {
+ obj.display_name = obj.foo === 'trigger onchange' ? 'changed' : 'default';
+ },
+ };
+
+ var onchangeDef;
+ var createDef = $.Deferred();
+ var form = createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: '<form><field name="display_name"/><field name="foo"/></form>',
+ mockRPC: function (route, args) {
+ var result = this._super.apply(this, arguments);
+ if (args.method === 'onchange') {
+ return $.when(onchangeDef).then(_.constant(result));
+ }
+ if (args.method === 'create') {
+ return $.when(createDef).then(_.constant(result));
+ }
+ return result;
+ },
+ });
+
+ // edit foo to trigger a delayed onchange
+ onchangeDef = $.Deferred();
+ testUtils.fields.editInput(form.$('.o_field_widget[name=foo]'), 'trigger onchange');
+
+ assert.strictEqual(form.$('.o_field_widget[name=display_name]').val(), 'default');
+
+ // save (will wait for the onchange to return), and will be delayed as well
+ testUtils.dom.click(form.$buttons.find('.o_form_button_save'));
+
+ assert.hasClass(form.$('.o_form_view'), 'o_form_editable');
+ assert.strictEqual(form.$('.o_field_widget[name=display_name]').val(), 'default');
+
+ // simulate a click on the breadcrumbs to leave the form view
+ form.canBeRemoved();
+
+ assert.hasClass(form.$('.o_form_view'), 'o_form_editable');
+ assert.strictEqual(form.$('.o_field_widget[name=display_name]').val(), 'default');
+
+ // unlock the onchange
+ onchangeDef.resolve();
+
+ assert.hasClass(form.$('.o_form_view'), 'o_form_editable');
+ assert.strictEqual(form.$('.o_field_widget[name=display_name]').val(), 'changed');
+
+ // unlock the create
+ createDef.resolve();
+
+ assert.hasClass(form.$('.o_form_view'), 'o_form_readonly');
+ assert.strictEqual(form.$('.o_field_widget[name=display_name]').text(), 'changed');
+ assert.containsNone(document.body, '.modal',
+ "should not display the 'Changes will be discarded' dialog");
+
+ form.destroy();
+ });
+
QUnit.module('FormViewTABMainButtons');
QUnit.test('using tab in an empty required string field should not move to the next field',function(assert) {
diff --git a/addons/web/static/tests/views/kanban_tests.js b/addons/web/static/tests/views/kanban_tests.js
index 86538ab5eb0..47af910083d 100644
--- a/addons/web/static/tests/views/kanban_tests.js
+++ b/addons/web/static/tests/views/kanban_tests.js
@@ -2110,6 +2110,67 @@ QUnit.module('Views', {
kanban.destroy();
});
+ QUnit.test('quick create record while adding a new column', function (assert) {
+ assert.expect(10);
+
+ var def = $.Deferred();
+ var kanban = createView({
+ View: KanbanView,
+ model: 'partner',
+ data: this.data,
+ arch: '<kanban on_create="quick_create">' +
+ '<templates><t t-name="kanban-box">' +
+ '<div><field name="foo"/></div>' +
+ '</t></templates>' +
+ '</kanban>',
+ groupBy: ['product_id'],
+ mockRPC: function (route, args) {
+ var result = this._super.apply(this, arguments);
+ if (args.method === 'name_create' && args.model === 'product') {
+ return def.then(_.constant(result));
+ }
+ return result;
+ },
+ });
+
+ assert.containsN(kanban, '.o_kanban_group', 2);
+ assert.containsN(kanban, '.o_kanban_group:first .o_kanban_record', 2);
+
+ // add a new column
+ assert.containsOnce(kanban, '.o_column_quick_create');
+ assert.isNotVisible(kanban.$('.o_column_quick_create input'));
+
+ testUtils.dom.click(kanban.$('.o_quick_create_folded'));
+
+ assert.isVisible(kanban.$('.o_column_quick_create input'));
+
+ testUtils.fields.editInput(kanban.$('.o_column_quick_create input'), 'new column');
+ testUtils.dom.click(kanban.$('.o_column_quick_create button.o_kanban_add'));
+
+ assert.containsN(kanban, '.o_kanban_group', 2);
+
+ // click to add a new record
+ testUtils.dom.click(kanban.$buttons.find('.o-kanban-button-new'));
+
+ // should wait for the column to be created (and view to be re-rendered
+ // before opening the quick create
+ assert.containsNone(kanban, '.o_kanban_quick_create');
+
+ // unlock column creation
+ def.resolve();
+
+ assert.containsN(kanban, '.o_kanban_group', 3);
+ assert.containsOnce(kanban, '.o_kanban_quick_create');
+
+ // quick create record in first column
+ testUtils.fields.editInput(kanban.$('.o_kanban_quick_create input'), 'new record');
+ testUtils.dom.click(kanban.$('.o_kanban_quick_create .o_kanban_add'));
+
+ assert.containsN(kanban, '.o_kanban_group:first .o_kanban_record', 3);
+
+ kanban.destroy();
+ });
+
QUnit.test('many2many_tags in kanban views', function (assert) {
assert.expect(12);
diff --git a/addons/web/static/tests/views/pivot_tests.js b/addons/web/static/tests/views/pivot_tests.js
index 930fadbbb7b..6263d34bfb3 100644
--- a/addons/web/static/tests/views/pivot_tests.js
+++ b/addons/web/static/tests/views/pivot_tests.js
@@ -923,6 +923,80 @@ QUnit.module('Views', {
pivot.destroy();
});
+ QUnit.test('correctly remove pivot_ keys from the context', function (assert) {
+ assert.expect(5);
+
+ this.data.partner.fields.amount = {string: "Amount", type: "float"};
+
+ // Equivalent to loading with default filter
+ var pivot = createView({
+ View: PivotView,
+ model: "partner",
+ data: this.data,
+ arch: '<pivot>' +
+ '<field name="date" interval="day" type="col"/>' +
+ '<field name="amount" type="measure"/>' +
+ '</pivot>',
+ viewOptions: {
+ context: {
+ pivot_measures: ['foo'],
+ pivot_column_groupby: ['customer'],
+ pivot_row_groupby: ['product_id'],
+ },
+ },
+ });
+
+ // Equivalent to unload the filter
+ var reloadParams = {
+ context: {},
+ };
+ pivot.reload(reloadParams);
+
+ assert.deepEqual(pivot.getContext(), {
+ pivot_column_groupby: ['customer'],
+ pivot_measures: ['foo'],
+ pivot_row_groupby: ['product_id'],
+ }, "context should be correct");
+
+ // Let's get rid of the rows groupBy
+ pivot.$('tbody .o_pivot_header_cell_opened').click();
+
+ assert.deepEqual(pivot.getContext(), {
+ pivot_column_groupby: ['customer'],
+ pivot_measures: ['foo'],
+ pivot_row_groupby: [],
+ }, "context should be correct");
+
+ // And now, get rid of the col groupby
+ pivot.$('thead .o_pivot_header_cell_opened').click();
+
+ assert.deepEqual(pivot.getContext(), {
+ pivot_column_groupby: [],
+ pivot_measures: ['foo'],
+ pivot_row_groupby: [],
+ }, "context should be correct");
+
+ pivot.$('tbody .o_pivot_header_cell_closed').click();
+ pivot.$('.o_pivot_field_menu li[data-field=product_id] a').click();
+
+ assert.deepEqual(pivot.getContext(), {
+ pivot_column_groupby: [],
+ pivot_measures: ['foo'],
+ pivot_row_groupby: ['product_id'],
+ }, "context should be correct");
+
+ pivot.$('thead .o_pivot_header_cell_closed').click();
+ pivot.$('.o_pivot_field_menu li[data-field=customer] a').click();
+
+ assert.deepEqual(pivot.getContext(), {
+ pivot_column_groupby: ['customer'],
+ pivot_measures: ['foo'],
+ pivot_row_groupby: ['product_id'],
+ }, "context should be correct");
+
+ pivot.destroy();
+ });
+
QUnit.test('correctly uses pivot_ keys from the context', function (assert) {
assert.expect(7);
diff --git a/addons/web_editor/controllers/main.py b/addons/web_editor/controllers/main.py
index 1b3f03966f3..40cf2aba5ef 100644
--- a/addons/web_editor/controllers/main.py
+++ b/addons/web_editor/controllers/main.py
@@ -416,7 +416,17 @@ class Web_Editor(http.Controller):
# Create a view to extend the template which adds the original file to link the new modified version instead
IrUiView = request.env["ir.ui.view"]
- view_to_xpath = IrUiView.get_related_views(bundle_xmlid, bundles=True).filtered(lambda v: v.arch.find(url) >= 0)
+
+ def views_linking_url(view):
+ """
+ Returns whether the view arch has some html link tag linked to the url.
+
+ (note: searching for the URL string is not enough as it could appear in a comment or an xpath expression.)
+ """
+ return bool(etree.XML(view.arch).xpath("link[@href='{}']".format(url)))
+
+ view_to_xpath = IrUiView.get_related_views(bundle_xmlid, bundles=True).filtered(views_linking_url)
+
new_view = {
'name': custom_url,
'key': 'web_editor.scss_%s' % str(uuid.uuid4())[:6],
diff --git a/addons/web_tour/__manifest__.py b/addons/web_tour/__manifest__.py
index 80f44db9165..5ff9710e855 100644
--- a/addons/web_tour/__manifest__.py
+++ b/addons/web_tour/__manifest__.py
@@ -21,7 +21,7 @@ Odoo Web tours.
'data/web_tour_demo.xml',
],
'qweb': [
- "static/src/xml/*.xml",
+ "static/src/xml/debug_manager.xml",
],
'auto_install': True
}
diff --git a/addons/web_tour/static/src/js/tip.js b/addons/web_tour/static/src/js/tip.js
index 971af4e7c7f..8b3a8d04566 100644
--- a/addons/web_tour/static/src/js/tip.js
+++ b/addons/web_tour/static/src/js/tip.js
@@ -8,6 +8,7 @@ var _t = core._t;
var Tip = Widget.extend({
template: "Tip",
+ xmlDependencies: ['/web_tour/static/src/xml/tip.xml'],
events: {
click: '_onTipClicked',
mouseenter: "_to_info_mode",
diff --git a/addons/web_tour/static/src/js/tour_manager.js b/addons/web_tour/static/src/js/tour_manager.js
index 7b787e3f059..f0521441a9e 100644
--- a/addons/web_tour/static/src/js/tour_manager.js
+++ b/addons/web_tour/static/src/js/tour_manager.js
@@ -32,7 +32,7 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
this.tours = {};
this.consumed_tours = consumed_tours || [];
this.running_tour = local_storage.getItem(get_running_key());
- this.running_step_delay = parseInt(local_storage.getItem(get_running_delay_key()), 10) || 10;
+ this.running_step_delay = parseInt(local_storage.getItem(get_running_delay_key()), 10) || 0;
this.edition = (_.last(session.server_version_info) === 'e') ? 'enterprise' : 'community';
this._log = [];
console.log('Tour Manager is ready. running_tour=' + this.running_tour);
@@ -171,7 +171,10 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
if (this.running_tour && this.running_tour_timeout === undefined) {
this._set_running_tour_timeout(this.running_tour, this.active_tooltips[this.running_tour]);
}
- this._check_for_tooltip(this.active_tooltips[tour_name], tour_name);
+ var self = this;
+ setTimeout(function () {
+ self._check_for_tooltip(self.active_tooltips[tour_name], tour_name);
+ });
} else {
for (var tourName in this.active_tooltips) {
var tip = this.active_tooltips[tourName];
@@ -371,11 +374,23 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
},
_to_next_running_step: function (tip, tour_name) {
if (this.running_tour !== tour_name) return;
+ var self = this;
this._stop_running_tour_timeout();
+ if (this.running_step_delay) {
+ // warning: due to the delay, it may happen that the $anchor isn't
+ // in the DOM anymore when exec is called, either because:
+ // - it has been removed from the DOM meanwhile and the tip's
+ // selector doesn't match anything anymore
+ // - it has been re-rendered and thus the selector still has a match
+ // in the DOM, but executing the step with that $anchor won't work
+ _.delay(exec, this.running_step_delay);
+ } else {
+ exec();
+ }
- var action_helper = new RunningTourActionHelper(tip.widget);
- _.delay((function () {
- do_before_unload(this._consume_tip.bind(this, tip, tour_name));
+ function exec() {
+ var action_helper = new RunningTourActionHelper(tip.widget);
+ do_before_unload(self._consume_tip.bind(self, tip, tour_name));
if (typeof tip.run === "function") {
tip.run.call(tip.widget, action_helper);
@@ -385,7 +400,7 @@ return core.Class.extend(mixins.EventDispatcherMixin, ServicesMixin, {
} else {
action_helper.auto();
}
- }).bind(this), this.running_step_delay);
+ }
},
/**
diff --git a/addons/web_tour/static/src/js/tour_service.js b/addons/web_tour/static/src/js/tour_service.js
index 75e2b4daa8d..b0507d22e43 100644
--- a/addons/web_tour/static/src/js/tour_service.js
+++ b/addons/web_tour/static/src/js/tour_service.js
@@ -61,12 +61,8 @@ return session.is_bound.then(function () {
}, 500);
var observer = new MutationObserver(check_tooltip);
var start_service = (function () {
- var load_def;
return function (observe) {
- if (load_def === undefined && observe && session.is_frontend) {
- load_def = ajax.loadXML('/web_tour/static/src/xml/tip.xml', QWeb);
- }
var def = $.Deferred();
$(function () {
@@ -74,18 +70,16 @@ return session.is_bound.then(function () {
* Once the DOM is ready, we still have to wait all the modules are loaded before completing the tours
* registration and starting listening for DOM mutations.
*/
- $.when(load_def).then(function () {
- _.defer(function () {
- tour_manager._register_all(observe);
- if (observe) {
- observer.observe(document.body, {
- attributes: true,
- childList: true,
- subtree: true,
- });
- }
- def.resolve();
- });
+ _.defer(function () {
+ tour_manager._register_all(observe);
+ if (observe) {
+ observer.observe(document.body, {
+ attributes: true,
+ childList: true,
+ subtree: true,
+ });
+ }
+ def.resolve();
});
});
return def;
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index d37852ae0de..a94397e77ba 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -74,7 +74,7 @@ class View(models.Model):
view._create_website_specific_pages_for_view(website_specific_view,
view.env['website'].browse(current_website_id))
- for inherit_child in view.inherit_children_ids.filter_duplicate():
+ for inherit_child in view.inherit_children_ids.filter_duplicate().sorted(key=lambda v: (v.priority, v.id)):
if inherit_child.website_id.id == current_website_id:
# In the case the child was already specific to the current
# website, we cannot just reattach it to the new specific
@@ -93,6 +93,55 @@ class View(models.Model):
return True
@api.multi
+ def _get_specific_views(self):
+ """ Given a view, return a record set containing all the specific views
+ for that view's key.
+ If the given view is already specific, it will also return itself.
+ """
+ self.ensure_one()
+ domain = [('key', '=', self.key), ('website_id', '!=', False)]
+ return self.with_context(active_test=False).search(domain)
+
+ def _load_records_write(self, values):
+ """ During module update, when updating a generic view, we should also
+ update its specific views (COW'd).
+ Note that we will only update unmodified fields. That will mimic the
+ noupdate behavior on views having an ir.model.data.
+ """
+ if self.type == 'qweb' and not self.website_id:
+ # Update also specific views
+ for cow_view in self._get_specific_views():
+ authorized_vals = {}
+ for key in values:
+ if cow_view[key] == self[key]:
+ authorized_vals[key] = values[key]
+ cow_view.write(authorized_vals)
+ super(View, self)._load_records_write(values)
+
+ def _load_records_create(self, values):
+ """ During module install, when creating a generic child view, we should
+ also create that view under specific view trees (COW'd).
+ Top level view (no inherit_id) do not need that behavior as they
+ will be shared between websites since there is no specific yet.
+ """
+ records = super(View, self)._load_records_create(values)
+ for record in records:
+ if record.type == 'qweb' and record.inherit_id and not record.website_id and not record.inherit_id.website_id:
+ specific_parent_views = record.with_context(active_test=False).search([
+ ('key', '=', record.inherit_id.key),
+ ('website_id', '!=', None),
+ ])
+ for specific_parent_view in specific_parent_views:
+ record.copy({
+ # Set key to avoid copy() to generate an unique key as
+ # we want the specific view to have the same key
+ 'key': record.key,
+ 'inherit_id': specific_parent_view.id,
+ 'website_id': specific_parent_view.website_id.id,
+ })
+ return records
+
+ @api.multi
def unlink(self):
'''This implements COU (copy-on-unlink). When deleting a generic page
website-specific pages will be created so only the current
diff --git a/addons/website/models/website.py b/addons/website/models/website.py
index 4aea35aa481..24099bef72d 100644
--- a/addons/website/models/website.py
+++ b/addons/website/models/website.py
@@ -1253,7 +1253,7 @@ class WebsiteRedirect(models.Model):
_order = "sequence, id"
_rec_name = 'url_from'
- redirect_type = fields.Selection([('301', 'Moved permanently (301)'), ('302', 'Moved temporarily (302)')], string='Redirection Type', required=True, oldname='type')
+ redirect_type = fields.Selection([('301', 'Moved permanently (301)'), ('302', 'Moved temporarily (302)')], string='Redirection Type', required=True, default='301)
url_from = fields.Char('Redirect From', required=True)
url_to = fields.Char('Redirect To', required=True)
website_id = fields.Many2one('website', 'Website')
diff --git a/addons/website/static/src/js/menu/new_content.js b/addons/website/static/src/js/menu/new_content.js
index 490e4f75516..2b4d1177a08 100644
--- a/addons/website/static/src/js/menu/new_content.js
+++ b/addons/website/static/src/js/menu/new_content.js
@@ -81,7 +81,7 @@ var NewContentMenu = websiteNavbarData.WebsiteNavbarActionWidget.extend({
var $group = this.$dialog.find('div.form-group');
$group.removeClass('mb0');
- var $add = $('<div/>', {'class': 'form-group mb0'})
+ var $add = $('<div/>', {'class': 'form-group mb0 row'})
.append($('<span/>', {'class': 'offset-md-3 col-md-9 text-left'})
.append(qweb.render('web_editor.components.switch', {id: 'switch_addTo_menu', label: _t("Add to menu")})));
$add.find('input').prop('checked', true);
diff --git a/addons/website/static/src/scss/website.edit_mode.scss b/addons/website/static/src/scss/website.edit_mode.scss
index de6f5d4c1a4..85ee8dc8fd4 100644
--- a/addons/website/static/src/scss/website.edit_mode.scss
+++ b/addons/website/static/src/scss/website.edit_mode.scss
@@ -176,8 +176,6 @@
font-family: Roboto, $font-family-sans-serif;
.o_tooltip_container {
- display: inline-flex;
- align-items: center;
transition: opacity 1s linear;
> .o_tooltip {
diff --git a/addons/website/static/src/xml/website.editor.xml b/addons/website/static/src/xml/website.editor.xml
index 5018d28d1d9..292f624e403 100644
--- a/addons/website/static/src/xml/website.editor.xml
+++ b/addons/website/static/src/xml/website.editor.xml
@@ -3,7 +3,7 @@
<div t-name="website.homepage_editor_welcome_message" class="container text-center o_homepage_editor_welcome_message">
<h2 class="mt0">Welcome to your <b>Homepage</b>!</h2>
<p class="lead d-none d-md-block">Let's start designing.</p>
- <div class="o_tooltip_container d-none d-md-block fade">Follow all the <div class="o_tooltip bottom"/> signs to get your website ready in no time.</div>
+ <div class="o_tooltip_container d-none d-md-inline-flex fade">Follow all the <div class="o_tooltip bottom"/> signs to get your website ready in no time.</div>
</div>
<div t-name="website.leaving_current_page_edition">
<p>What do you want to do?</p>
diff --git a/addons/website/tests/test_views.py b/addons/website/tests/test_views.py
index 132472de2c0..9ece6cf4c3d 100644
--- a/addons/website/tests/test_views.py
+++ b/addons/website/tests/test_views.py
@@ -622,6 +622,104 @@ class TestCowViewSaving(common.TransactionCase):
views = View.with_context(website_id=1).get_related_views('B')
self.assertEqual(views.mapped('key'), ['B', 'I', 'II'], "Should only return the specific tree")
+ def test_cow_inherit_children_order(self):
+ """ COW method should loop on inherit_children_ids in correct order
+ when copying them on the new specific tree.
+ Correct order is the same as the one when applying view arch:
+ PRIORITY, ID
+ And not the default one from ir.ui.view (NAME, PRIORIRTY, ID).
+ """
+ self.inherit_view.copy({
+ 'name': 'alphabetically before "Extension"',
+ 'key': '_test.alphabetically_first',
+ 'arch': '<div position="replace"><p>COMPARE</p></div>',
+ })
+ # Next line should not crash, COW loop on inherit_children_ids should be sorted correctly
+ self.base_view.with_context(website_id=1).write({'name': 'Product (W1)'})
+
+ def test_module_new_inherit_view_on_parent_already_forked(self):
+ """ If a generic parent view is copied (COW) and that another module
+ creates a child view for that generic parent, all the COW views
+ should also get a copy of that new child view.
+
+ Typically, a parent view (website_sale.product) is copied (COW)
+ and then wishlist module is installed.
+ Wishlist views inhering from website_sale.product are added to the
+ generic `website_sale.product`. But it should also be added to the
+ COW `website_sale.product` to activate the module views for that
+ website.
+ """
+ Website = self.env['website']
+ View = self.env['ir.ui.view']
+
+ # Simulate website_sale product view
+ self.base_view.write({'name': 'Product', 'key': '_website_sale.product'})
+ # Trigger cow on website_sale hierarchy for website 1
+ self.base_view.with_context(website_id=1).write({'name': 'Product (W1)'})
+
+ # Simulate website_sale_comparison install
+ View._load_records([dict(xml_id='_website_sale_comparison.product_add_to_compare', values={
+ 'name': 'Add to comparison in product page',
+ 'mode': 'extension',
+ 'inherit_id': self.base_view.id,
+ 'arch': '<div position="replace"><p>COMPARE</p></div>',
+ 'key': '_website_sale_comparison.product_add_to_compare',
+ })])
+
+ specific_view = Website.with_context(load_all_views=True, website_id=1).viewref('_website_sale.product')
+ specific_view_arch = specific_view.read_combined(['arch'])['arch']
+ self.assertEqual(specific_view.website_id.id, 1, "Ensure we got specific view to perform the checks against")
+ self.assertEqual(specific_view_arch, '<p>COMPARE</p>', "When a module creates an inherited view (on a generic tree), it should also create that view in the specific COW'd tree.")
+
+ # Simulate website_sale_comparison update
+ View._load_records([dict(xml_id='_website_sale_comparison.product_add_to_compare', values={
+ 'arch': '<div position="replace"><p>COMPARE EDITED</p></div>',
+ })])
+
+ specific_view_arch = Website.with_context(load_all_views=True, website_id=1).viewref('_website_sale.product').read_combined(['arch'])['arch']
+ self.assertEqual(specific_view_arch, '<p>COMPARE EDITED</p>', "When a module updates an inherited view (on a generic tree), it should also update the copies of that view (COW).")
+
+ # Test fields that should not be COW'd
+ random_view_id = View.search([], limit=1).id
+ View._load_records([dict(xml_id='_website_sale_comparison.product_add_to_compare', values={
+ 'website_id': None,
+ 'inherit_id': random_view_id,
+ })])
+
+ w1_specific_child_view = Website.with_context(load_all_views=True, website_id=1).viewref('_website_sale_comparison.product_add_to_compare')
+ generic_child_view = Website.with_context(load_all_views=True).viewref('_website_sale_comparison.product_add_to_compare')
+ self.assertEqual(w1_specific_child_view.website_id.id, 1, "website_id is a prohibited field when COWing views during _load_records")
+ self.assertEqual(w1_specific_child_view.inherit_id.id != random_view_id, True, "inherit_id is a prohibited field when COWing views during _load_records")
+ self.assertEqual(generic_child_view.inherit_id.id, random_view_id, "prohibited fields only concerned write on COW'd view. Generic should still considere these fields")
+
+ # Set back the generic view as parent for the rest of the test
+ generic_child_view.inherit_id = self.base_view
+
+ # Don't update fields from COW'd view if these fields have been modified from original view
+ new_website = Website.create({'name': 'New Website'})
+ self.base_view.with_context(website_id=new_website.id).write({'name': 'Product (new_website)'})
+ new_website_specific_child_view = Website.with_context(load_all_views=True, website_id=new_website.id).viewref('_website_sale_comparison.product_add_to_compare')
+ new_website_specific_child_view.priority = 6
+ View._load_records([dict(xml_id='_website_sale_comparison.product_add_to_compare', values={
+ 'priority': 3,
+ })])
+ self.assertEqual(generic_child_view.priority, 3, "XML update should be written on the Generic View")
+ self.assertEqual(w1_specific_child_view.priority, 3, "XML update should be written on the specific view if the fields have not been modified on that specific view")
+ self.assertEqual(new_website_specific_child_view.priority, 6, "XML update should NOT be written on the specific view if the fields have been modified on that specific view")
+
+ # Simulate website_sale update on top level view
+ self.env['ir.model.data'].create({
+ 'module': '_website_sale',
+ 'name': 'product',
+ 'model': self.base_view._name,
+ 'res_id': self.base_view.id,
+ })
+ View._load_records([dict(xml_id='_website_sale.product', values={
+ 'website_meta_title': 'A bug got fixed by updating this field',
+ })])
+ all_title_updated = specific_view.website_meta_title == self.base_view.website_meta_title == "A bug got fixed by updating this field"
+ self.assertEqual(all_title_updated, True, "Update on top level generic views should also be applied on specific views")
+
class Crawler(HttpCase):
def setUp(self):
diff --git a/addons/website_forum/views/forum.xml b/addons/website_forum/views/forum.xml
index 6a168613cdc..fe9188af31e 100644
--- a/addons/website_forum/views/forum.xml
+++ b/addons/website_forum/views/forum.xml
@@ -8,6 +8,19 @@
<menuitem name="Forum" id="menu_website_forum_global"
parent="website.menu_website_global_configuration" sequence="170" groups="website.group_website_designer"/>
+ <record id="badge_form_view_forum" model="ir.ui.view">
+ <field name="name">forum.badge_form_view</field>
+ <field name="model">gamification.badge</field>
+ <field name="inherit_id" ref="gamification.badge_form_view"/>
+ <field name="arch" type="xml">
+ <field name="challenge_ids" position="after">
+ <group>
+ <field name="level" />
+ </group>
+ </field>
+ </field>
+ </record>
+
<!-- FORUM VIEWS -->
<record id="view_forum_forum_list" model="ir.ui.view">
<field name="name">forum.forum.list</field>
diff --git a/addons/website_sale/controllers/main.py b/addons/website_sale/controllers/main.py
index 0b5ed81a6e5..4f0f84cebf6 100644
--- a/addons/website_sale/controllers/main.py
+++ b/addons/website_sale/controllers/main.py
@@ -568,7 +568,7 @@ class WebsiteSale(ProductConfiguratorController):
except ValidationError:
error["vat"] = 'error'
- if [err for err in error.items() if err == 'missing']:
+ if [err for err in error.values() if err == 'missing']:
error_message.append(_('Some required fields are empty.'))
return error, error_message
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 1797a59ea9b..87ae9564b65 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
@@ -21,7 +21,7 @@ tour.register('shop_buy_product', {
},
{
content: "select conference chair",
- trigger: '.oe_product_cart a:contains("Conference Chair")',
+ trigger: '.oe_product_cart:first a:contains("Conference Chair")',
},
{
content: "select Conference Chair Aluminium",
diff --git a/addons/website_sale_comparison/controllers/main.py b/addons/website_sale_comparison/controllers/main.py
index d58c6c5a0dc..9b833777b7b 100644
--- a/addons/website_sale_comparison/controllers/main.py
+++ b/addons/website_sale_comparison/controllers/main.py
@@ -3,6 +3,7 @@ from odoo import http, _
from odoo.http import request
from odoo.addons.website_sale.controllers.main import WebsiteSale
import json
+from collections import OrderedDict
class WebsiteSaleProductComparison(WebsiteSale):
@@ -24,12 +25,12 @@ class WebsiteSaleProductComparison(WebsiteSale):
att_name = var.attribute_id.name
if not product.attribute_value_ids: # create_variant = False
continue
- res.setdefault(cat_name, {}).setdefault(att_name, [' - '] * len(products))
+ res.setdefault(cat_name, OrderedDict()).setdefault(att_name, [' - '] * len(products))
val = product.attribute_value_ids.filtered(lambda x: x.attribute_id == var.attribute_id)
if val:
res[cat_name][att_name][num] = val[0].name
values['specs'] = res
- values['compute_currency'] = self._get_compute_currency_and_context(products[:1])[0]
+ values['compute_currency'] = self._get_compute_currency_and_context(products[:1].product_tmpl_id)[0]
return request.render("website_sale_comparison.product_compare", values)
@http.route(['/shop/get_product_data'], type='json', auth="public", website=True)
@@ -37,7 +38,7 @@ class WebsiteSaleProductComparison(WebsiteSale):
ret = {}
pricelist_context, pricelist = self._get_pricelist_context()
prods = request.env['product.product'].with_context(pricelist_context, display_default_code=False).search([('id', 'in', product_ids)])
- compute_currency = self._get_compute_currency(pricelist, prods[:1])
+ compute_currency = self._get_compute_currency(pricelist, prods[:1].product_tmpl_id)
if cookies is not None:
ret['cookies'] = json.dumps(request.env['product.product'].search([('id', 'in', list(set(product_ids + cookies)))]).ids)
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
index b03e0108fb2..8089d8fb3e7 100644
--- 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
@@ -47,14 +47,9 @@ tour.register('shop_wishlist', {
},
},
{
- content: "check that logged in and search for Customizable Desk",
- extra_trigger: "li span:contains('Mitchell Admin')",
- trigger: 'form input[name="search"]',
- run: "text Customizable Desk",
- },
- {
- content: "submit search",
- trigger: 'form:has(input[name="search"]) .oe_search_button',
+ content: "check that logged in",
+ trigger: "li span:contains('Mitchell Admin')",
+ run: function () {},
},
{
content: "click on Customizable Desk",
diff --git a/addons/website_slides/views/website_slides_embed_templates.xml b/addons/website_slides/views/website_slides_embed_templates.xml
index 55f63c1d3e1..c37facd252e 100644
--- a/addons/website_slides/views/website_slides_embed_templates.xml
+++ b/addons/website_slides/views/website_slides_embed_templates.xml
@@ -113,7 +113,7 @@
</a>
</div>
<div class="col-auto text-right ml-auto mt-2 mb-2">
- <a t-if="slide.download_security and not is_embedded" target="_top" t-attf-href="/slides/slide/#{slug(slide)}/download" title="Download" id="download">
+ <a t-if="slide.download_security != 'none' and not is_embedded" target="_top" t-attf-href="/slides/slide/#{slug(slide)}/download" title="Download" id="download">
<i class="fa fa-download fa-2x" role="img" aria-label="Download"></i>
</a>
<span id="fullscreen" title="View fullscreen" role="img" aria-label="Fullscreen">
diff --git a/doc/cla/corporate/merchise.md b/doc/cla/corporate/merchise.md
index e4cbd3c3f95..64d5b277ccd 100644
--- a/doc/cla/corporate/merchise.md
+++ b/doc/cla/corporate/merchise.md
@@ -21,3 +21,4 @@ Medardo Rodríguez med@merchise.org https://github.com/med-merchise
Abel Firvida firvida@merchise.org
Abel Firvida abel@merchise.org
Mónica Díaz Pena monicadp@merchise.org https://github.com/mdpena
+Larisa González larisa@merchise.org
diff --git a/doc/cla/individual/dipsshah42.md b/doc/cla/individual/dipsshah42.md
new file mode 100644
index 00000000000..d6a647178ae
--- /dev/null
+++ b/doc/cla/individual/dipsshah42.md
@@ -0,0 +1,9 @@
+India, 2019-01-11
+
+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,
+
+Dipak Shah dipssah@gmail.com https://github.com/dipsshah42
diff --git a/doc/cla/individual/ehansejoerg.md b/doc/cla/individual/ehansejoerg.md
new file mode 100644
index 00000000000..f4be23d6c5c
--- /dev/null
+++ b/doc/cla/individual/ehansejoerg.md
@@ -0,0 +1,11 @@
+Germany, 10.01.2019
+
+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,
+
+Jörg Ricardo Schumacher eHanseJoerg@users.noreply.github.com https://github.com/eHanseJoerg
diff --git a/doc/cla/individual/i-vyshnevska.md b/doc/cla/individual/i-vyshnevska.md
new file mode 100644
index 00000000000..0df4e78944d
--- /dev/null
+++ b/doc/cla/individual/i-vyshnevska.md
@@ -0,0 +1,9 @@
+Ukraine, 2019-01-09
+
+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,
+
+Vyshnevska Iryna i.vyshnevska@mobilunity.com https://github.com/i-vyshnevska/ \ No newline at end of file
diff --git a/doc/cla/individual/stanisljevic.md b/doc/cla/individual/stanisljevic.md
new file mode 100644
index 00000000000..16d61d63d19
--- /dev/null
+++ b/doc/cla/individual/stanisljevic.md
@@ -0,0 +1,11 @@
+Bosnia and Herzegovina, 2019-01-12
+
+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,
+
+Sasa Stanisljevic mcse.sasa@gmail.com https://github.com/stanisljevic
diff --git a/odoo/addons/base/models/ir_actions.py b/odoo/addons/base/models/ir_actions.py
index 2b9f88104f1..80c61aab9d7 100644
--- a/odoo/addons/base/models/ir_actions.py
+++ b/odoo/addons/base/models/ir_actions.py
@@ -397,7 +397,7 @@ class IrActionsServer(models.Model):
# Create
crud_model_id = fields.Many2one('ir.model', string='Create/Write Target Model',
oldname='srcmodel_id', help="Model for record creation / update. Set this field only to specify a different model than the base model.")
- crud_model_name = fields.Char(related='crud_model_id.name', readonly=True)
+ crud_model_name = fields.Char(related='crud_model_id.model', string='Target Model', readonly=True)
link_field_id = fields.Many2one('ir.model.fields', string='Link using field',
help="Provide the field used to link the newly created record "
"on the record on used by the server action.")
diff --git a/odoo/addons/base/models/ir_module.py b/odoo/addons/base/models/ir_module.py
index e673ac016dd..0e5fd313ab9 100644
--- a/odoo/addons/base/models/ir_module.py
+++ b/odoo/addons/base/models/ir_module.py
@@ -457,7 +457,8 @@ class Module(models.Model):
modules_to_remove = self.mapped('name')
self.env['ir.model.data']._module_data_uninstall(modules_to_remove)
self._remove_copied_views()
- self.write({'state': 'uninstalled', 'latest_version': False})
+ # we deactivate prefetching to not try to read a column that has been deleted
+ self.with_context(prefetch_fields=False).write({'state': 'uninstalled', 'latest_version': False})
return True
@api.multi
diff --git a/odoo/addons/base/models/res_partner.py b/odoo/addons/base/models/res_partner.py
index 8f1bb377c99..d8b949c2fc2 100644
--- a/odoo/addons/base/models/res_partner.py
+++ b/odoo/addons/base/models/res_partner.py
@@ -257,10 +257,10 @@ class Partner(models.Model):
for partner in self:
partner.tz_offset = datetime.datetime.now(pytz.timezone(partner.tz or 'GMT')).strftime('%z')
- @api.depends('user_ids.share')
+ @api.depends('user_ids.share', 'user_ids.active')
def _compute_partner_share(self):
for partner in self:
- partner.partner_share = not partner.user_ids or any(user.share for user in partner.user_ids)
+ partner.partner_share = not partner.user_ids or not any(not user.share for user in partner.user_ids)
@api.depends(lambda self: self._display_address_depends())
def _compute_contact_address(self):
diff --git a/odoo/addons/base/wizard/base_partner_merge.py b/odoo/addons/base/wizard/base_partner_merge.py
index cce25eed51f..7a8323f67e1 100644
--- a/odoo/addons/base/wizard/base_partner_merge.py
+++ b/odoo/addons/base/wizard/base_partner_merge.py
@@ -129,14 +129,14 @@ class MergePartnerAutomatic(models.TransientModel):
# unique key treated
query = """
UPDATE "%(table)s" as ___tu
- SET %(column)s = %%s
+ SET "%(column)s" = %%s
WHERE
- %(column)s = %%s AND
+ "%(column)s" = %%s AND
NOT EXISTS (
SELECT 1
FROM "%(table)s" as ___tw
WHERE
- %(column)s = %%s AND
+ "%(column)s" = %%s AND
___tu.%(value)s = ___tw.%(value)s
)""" % query_dic
for partner in src_partners:
@@ -144,7 +144,7 @@ class MergePartnerAutomatic(models.TransientModel):
else:
try:
with mute_logger('odoo.sql_db'), self._cr.savepoint():
- query = 'UPDATE "%(table)s" SET %(column)s = %%s WHERE %(column)s IN %%s' % query_dic
+ query = 'UPDATE "%(table)s" SET "%(column)s" = %%s WHERE "%(column)s" IN %%s' % query_dic
self._cr.execute(query, (dst_partner.id, tuple(src_partners.ids),))
# handle the recursivity with parent relation
diff --git a/odoo/addons/test_main_flows/static/src/js/tour.js b/odoo/addons/test_main_flows/static/src/js/tour.js
index 1e65a2b2e58..af051f956e1 100644
--- a/odoo/addons/test_main_flows/static/src/js/tour.js
+++ b/odoo/addons/test_main_flows/static/src/js/tour.js
@@ -211,7 +211,6 @@ tour.register('main_flow_tour', {
position: 'bottom',
}, {
trigger: ".breadcrumb-item:first",
- extra_trigger: ".o_form_readonly", // FIXME: this is required due to an issue in tour_manager (see [*])
content: _t("Use the breadcrumbs to <b>go back to products</b>."),
position: "bottom"
}, {
@@ -542,12 +541,10 @@ tour.register('main_flow_tour', {
trigger: ".o_menu_sections a[data-menu-xmlid='mrp.menu_mrp_manufacturing']",
content: _t('Click on Operations menuitem'),
position: 'bottom',
- edition: 'enterprise',
}, {
trigger: ".o_menu_sections a[data-menu-xmlid='mrp.menu_mrp_production_action']",
content: _t('Open manufacturing orders'),
position: 'bottom',
- edition: 'enterprise',
}, {
trigger: '.o_data_row:has(.o_data_cell:contains("the_flow.product")):first',
content: _t('Select the generated manufacturing order'),
@@ -755,7 +752,6 @@ tour.register('main_flow_tour', {
}, {
edition: "enterprise",
trigger: ".o_selected_row .o_field_widget[name=name]",
- extra_trigger: ".o_selected_row .o_field_widget[name=partner_id] .o_external_button", // FIXME: this is required due to an issue in tour_manager (see [*])
content: _t('Let\'s enter a name.'),
position: "bottom",
run: "text the_flow.statement.line",
@@ -781,16 +777,3 @@ tour.register('main_flow_tour', {
position: "bottom",
}]);
});
-
-/*
- * [*] FIXME: issue in tour_manager:
- * The JQuery element of a step is registered as soon as its trigger and
- * extra_trigger elements are visible in the DOM, but it's action is delayed
- * to handle the 'running_step_delay' option (0 by default, but even with 0,
- * the action is executed after finishing the current execution block, which
- * may produce a re-rendering of the part of the DOM containing the element).
- * When this happens, the action is executed on an jquery element not present
- * in the DOM anymore.
- * To avoid this, we add an 'extra_trigger' to wait for the updated jquery
- * element before activating the step (and thus registering the JQuery element).
- */
diff --git a/odoo/addons/test_new_api/ir.model.access.csv b/odoo/addons/test_new_api/ir.model.access.csv
index 77c881dcc4d..77e0b8e165b 100644
--- a/odoo/addons/test_new_api/ir.model.access.csv
+++ b/odoo/addons/test_new_api/ir.model.access.csv
@@ -26,3 +26,4 @@ access_test_new_api_monetary_base,access_test_new_api_monetary_base,model_test_n
access_test_new_api_monetary_related,access_test_new_api_monetary_related,model_test_new_api_monetary_related,,1,1,1,1
access_test_new_api_monetary_custom,access_test_new_api_monetary_custom,model_test_new_api_monetary_custom,,1,1,1,1
access_test_new_api_monetary_inherits,access_test_new_api_monetary_inherits,model_test_new_api_monetary_inherits,,1,1,1,1
+access_test_new_api_field_with_caps,access_test_new_api_field_with_caps,model_test_new_api_field_with_caps,,1,1,1,1
diff --git a/odoo/addons/test_new_api/models.py b/odoo/addons/test_new_api/models.py
index 90edf910944..6bd198006ee 100644
--- a/odoo/addons/test_new_api/models.py
+++ b/odoo/addons/test_new_api/models.py
@@ -504,3 +504,10 @@ class MonetaryInherits(models.Model):
monetary_id = fields.Many2one('test_new_api.monetary_base', required=True, ondelete='cascade')
currency_id = fields.Many2one('res.currency')
+
+
+class FieldWithCaps(models.Model):
+ _name = 'test_new_api.field_with_caps'
+ _description = 'Model with field defined with capital letters'
+
+ pArTneR_321_id = fields.Many2one('res.partner')
diff --git a/odoo/addons/test_new_api/tests/test_one2many.py b/odoo/addons/test_new_api/tests/test_one2many.py
index 8531396fe48..62de71c07fc 100644
--- a/odoo/addons/test_new_api/tests/test_one2many.py
+++ b/odoo/addons/test_new_api/tests/test_one2many.py
@@ -130,3 +130,22 @@ class One2manyCase(TransactionCase):
res_movies_not_of_edition_name = self.Movie.search([('editions', '!=', one_movie_edition.name)])
self.assertItemsEqual(t(res_movies_not_of_edition_name), t(movies.filtered(lambda r: one_movie_edition not in r.editions)))
+
+ def test_merge_partner(self):
+ model = self.env['test_new_api.field_with_caps']
+ partner = self.env['res.partner']
+
+ p1 = partner.create({'name': 'test1'})
+ p2 = partner.create({'name': 'test2'})
+
+ model1 = model.create({'pArTneR_321_id': p1.id})
+ model2 = model.create({'pArTneR_321_id': p2.id})
+
+ self.env['base.partner.merge.automatic.wizard']._merge((p1 + p2).ids, p1)
+
+ self.assertFalse(p2.exists())
+ self.assertTrue(p1.exists())
+
+ self.assertEqual(model1.pArTneR_321_id, p1)
+ self.assertTrue(model2.exists())
+ self.assertEqual(model2.pArTneR_321_id, p1)
diff --git a/odoo/models.py b/odoo/models.py
index eca249f6200..9104406195b 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -2778,14 +2778,16 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# retrieve results from records; this takes values from the cache and
# computes remaining fields
+ self = self.with_prefetch(self._prefetch.copy())
data = {record: {'id': record.id} for record in self}
missing = set()
use_name_get = (load == '_classic_read')
for name in (stored + inherited + computed):
convert = self._fields[name].convert_to_read
- # read every field with prefetching limited to self; this avoids
+ # restrict the prefetching of self's model to self; this avoids
# computing fields on a larger recordset than self
- for record in self.with_prefetch():
+ self._prefetch[self._name] = set(self._ids)
+ for record in self:
try:
data[record][name] = convert(record[name], record, use_name_get)
except MissingError:
@@ -3738,6 +3740,12 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
modified_ids = {row[0] for row in cr.fetchall()}
self.browse(modified_ids).modified(['parent_path'])
+ def _load_records_write(self, values):
+ self.write(values)
+
+ def _load_records_create(self, values):
+ return self.create(values)
+
def _load_records(self, data_list, update=False):
""" Create or update records of this model, and assign XMLIDs.
@@ -3795,7 +3803,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
# update existing records
for data in to_update:
- data['record'].write(data['values'])
+ data['record']._load_records_write(data['values'])
# determine existing parents for new records
for parent_model, parent_field in self._inherits.items():
@@ -3822,7 +3830,7 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
_logger.warning("Creating record %s in module %s.", data['xml_id'], module)
# create records
- records = self.create([data['values'] for data in to_create])
+ records = self._load_records_create([data['values'] for data in to_create])
for data, record in zip(to_create, records):
data['record'] = record
diff --git a/odoo/modules/module.py b/odoo/modules/module.py
index c94df025f9b..378812f1036 100644
--- a/odoo/modules/module.py
+++ b/odoo/modules/module.py
@@ -128,17 +128,17 @@ def initialize_sys_path():
global ad_paths
global hooked
- dd = tools.config.addons_data_dir
+ dd = os.path.normcase(tools.config.addons_data_dir)
if os.access(dd, os.R_OK) and dd not in ad_paths:
ad_paths.append(dd)
for ad in tools.config['addons_path'].split(','):
- ad = os.path.abspath(tools.ustr(ad.strip()))
+ ad = os.path.normcase(os.path.abspath(tools.ustr(ad.strip())))
if ad not in ad_paths:
ad_paths.append(ad)
# add base module path
- base_path = os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons'))
+ base_path = os.path.normcase(os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'addons')))
if base_path not in ad_paths and os.path.isdir(base_path):
ad_paths.append(base_path)
diff --git a/odoo/tests/common.py b/odoo/tests/common.py
index 9a03f589200..51660dca0a8 100644
--- a/odoo/tests/common.py
+++ b/odoo/tests/common.py
@@ -529,6 +529,7 @@ class ChromeBrowser():
'--user-data-dir': self.user_data_dir,
'--disable-translate': '',
'--window-size': self.window_size,
+ '--remote-debugging-address': HOST,
'--remote-debugging-port': str(self.devtools_port),
'--no-sandbox': '',
}
@@ -571,7 +572,7 @@ class ChromeBrowser():
command = os.path.join('json', command).strip('/')
while timeout > 0:
try:
- url = werkzeug.urls.url_join('http://127.0.0.1:%s/' % self.devtools_port, command)
+ url = werkzeug.urls.url_join('http://%s:%s/' % (HOST, self.devtools_port), command)
self._logger.info('Url : %s', url)
r = requests.get(url, timeout=3)
if r.ok:
@@ -881,7 +882,7 @@ class HttpCase(TransactionCase):
odoo.http.root.session_store.save(session)
if self.browser:
self._logger.info('Setting session cookie in browser')
- self.browser.set_cookie('session_id', self.session_id, '/', '127.0.0.1')
+ self.browser.set_cookie('session_id', self.session_id, '/', HOST)
def browser_js(self, url_path, code, ready='', login=None, timeout=60, **kw):
""" Test js code running in the browser
@@ -905,7 +906,10 @@ class HttpCase(TransactionCase):
try:
self.authenticate(login, login)
- url = "http://%s:%s%s" % (HOST, PORT, url_path or '/')
+ base_url = "http://%s:%s" % (HOST, PORT)
+ ICP = self.env['ir.config_parameter']
+ ICP.set_param('web.base.url', base_url)
+ url = "%s%s" % (base_url, url_path or '/')
self._logger.info('Open "%s" in browser', url)
if odoo.tools.config['logfile']: