mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2026-08-17 16:54:42 -05:00
[PATCH] Upstream patch - 02072023
This commit is contained in:
@@ -52,8 +52,8 @@ class PortalAccount(CustomerPortal):
|
||||
|
||||
searchbar_filters = {
|
||||
'all': {'label': _('All'), 'domain': []},
|
||||
'invoices': {'label': _('Invoices'), 'domain': [('move_type', '=', ('out_invoice', 'out_refund'))]},
|
||||
'bills': {'label': _('Bills'), 'domain': [('move_type', '=', ('in_invoice', 'in_refund'))]},
|
||||
'invoices': {'label': _('Invoices'), 'domain': [('move_type', 'in', ('out_invoice', 'out_refund'))]},
|
||||
'bills': {'label': _('Bills'), 'domain': [('move_type', 'in', ('in_invoice', 'in_refund'))]},
|
||||
}
|
||||
# default filter by value
|
||||
if not filterby:
|
||||
|
||||
@@ -495,7 +495,8 @@ class AccountPartialReconcile(models.Model):
|
||||
partial = partial_values['partial']
|
||||
|
||||
# Init the journal entry.
|
||||
move_date = partial.max_date if partial.max_date > (move.company_id.period_lock_date or date.min) else today
|
||||
lock_date = move.company_id._get_user_fiscal_lock_date()
|
||||
move_date = partial.max_date if partial.max_date > (lock_date or date.min) else today
|
||||
move_vals = {
|
||||
'move_type': 'entry',
|
||||
'date': move_date,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from collections import defaultdict
|
||||
|
||||
from flectra.exceptions import AccessError
|
||||
from flectra import api, fields, models, _
|
||||
@@ -43,15 +44,18 @@ def update_taxes_from_templates(cr, chart_template_xmlid):
|
||||
This method is mainly used as a local upgrade script.
|
||||
Returns a list of tuple (template_id, tax_id) of newly created records.
|
||||
"""
|
||||
def _create_tax_from_template(company, template, old_tax=None):
|
||||
""" Create a new tax from template with template xmlid, if there was already an old tax with that xmlid we
|
||||
def _create_taxes_from_template(company, template2tax_mapping):
|
||||
""" Create a new taxes from templates. If an old tax already used the same xmlid, we
|
||||
remove the xmlid from it but don't modify anything else.
|
||||
:param company: the company of the tax to instantiate
|
||||
:param template2tax_mapping: a list of tuples (template, existing_tax) where existing_tax can be None
|
||||
:return: a list of tuples of ids (template.id, newly_created_tax.id)
|
||||
"""
|
||||
def _remove_xml_id(xml_id):
|
||||
module, name = xml_id.split('.', 1)
|
||||
env['ir.model.data'].search([('module', '=', module), ('name', '=', name)]).unlink()
|
||||
|
||||
def _avoid_name_conflict():
|
||||
def _avoid_name_conflict(company, template):
|
||||
conflict_taxes = env['account.tax'].search([
|
||||
('name', '=', template.name), ('company_id', '=', company.id),
|
||||
('type_tax_use', '=', template.type_tax_use), ('tax_scope', '=', template.tax_scope)
|
||||
@@ -60,48 +64,61 @@ def update_taxes_from_templates(cr, chart_template_xmlid):
|
||||
for index, conflict_taxes in enumerate(conflict_taxes):
|
||||
conflict_taxes.name = f"[old{index if index > 0 else ''}] {conflict_taxes.name}"
|
||||
|
||||
template_vals = template._get_tax_vals_complete(company)
|
||||
chart_template = env['account.chart.template'].with_context(default_company_id=company.id)
|
||||
if old_tax:
|
||||
xml_id = old_tax.get_xml_id().get(old_tax.id)
|
||||
if xml_id:
|
||||
_remove_xml_id(xml_id)
|
||||
_avoid_name_conflict()
|
||||
return chart_template.create_record_with_xmlid(company, template, 'account.tax', template_vals)
|
||||
templates_to_create = env['account.tax.template'].with_context(active_test=False)
|
||||
for template, old_tax in template2tax_mapping:
|
||||
if old_tax:
|
||||
xml_id = old_tax.get_external_id().get(old_tax.id)
|
||||
if xml_id:
|
||||
_remove_xml_id(xml_id)
|
||||
_avoid_name_conflict(company, template)
|
||||
templates_to_create += template
|
||||
new_template2tax_company = templates_to_create._generate_tax(company, accounts_exist=True)['tax_template_to_tax']
|
||||
return [(env['account.tax.template'].browse(template_id), env['account.tax'].browse(tax_id))
|
||||
for template_id, tax_id in new_template2tax_company.items()]
|
||||
|
||||
def _update_tax_from_template(template, tax):
|
||||
""" Update the tax's tags (and only tags!) based on template values. """
|
||||
tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
|
||||
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
|
||||
for tax_line, template_line in zip(tax_rep_lines, template_rep_lines):
|
||||
tags_to_add = template_line._get_tags_to_add()
|
||||
tags_to_unlink = tax_line.tag_ids
|
||||
if tags_to_add != tags_to_unlink:
|
||||
tax_line.write({'tag_ids': [(6, 0, tags_to_add.ids)]})
|
||||
_cleanup_tags(tags_to_unlink)
|
||||
def _update_taxes_from_template(template2tax_mapping):
|
||||
""" Update the taxes' tags (and only tags!) based on their corresponding template values.
|
||||
:param template2tax_mapping: a list of tuples (template, existing_taxes)
|
||||
"""
|
||||
for template, existing_tax in template2tax_mapping:
|
||||
tax_rep_lines = existing_tax.invoice_repartition_line_ids + existing_tax.refund_repartition_line_ids
|
||||
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
|
||||
for tax_line, template_line in zip(tax_rep_lines, template_rep_lines):
|
||||
tags_to_add = template_line._get_tags_to_add()
|
||||
tags_to_unlink = tax_line.tag_ids
|
||||
if tags_to_add != tags_to_unlink:
|
||||
tax_line.write({'tag_ids': [(6, 0, tags_to_add.ids)]})
|
||||
_cleanup_tags(tags_to_unlink)
|
||||
|
||||
def _get_template_to_real_xmlid_mapping(company, model):
|
||||
def _get_template_to_real_xmlid_mapping(model, templates):
|
||||
""" This function uses ir_model_data to return a mapping between the templates and the data, using their xmlid
|
||||
:returns: {
|
||||
account.tax.template.id: account.tax.id
|
||||
}
|
||||
company_id: { model.template.id1: model.id1, model.template.id2: model.id2 },
|
||||
...
|
||||
}
|
||||
"""
|
||||
template_xmlids = [xmlid.split('.', 1)[1] for xmlid in templates.get_external_id().values()]
|
||||
res = defaultdict(dict)
|
||||
if not template_xmlids:
|
||||
return res
|
||||
env['ir.model.data'].flush()
|
||||
env.cr.execute(
|
||||
"""
|
||||
SELECT template.res_id AS template_res_id,
|
||||
data.res_id AS data_res_id
|
||||
SELECT substr(data.name, 0, strpos(data.name, '_'))::INTEGER AS data_company_id,
|
||||
template.res_id AS template_res_id,
|
||||
data.res_id AS data_res_id
|
||||
FROM ir_model_data data
|
||||
JOIN ir_model_data template
|
||||
ON template.name = substr(data.name, strpos(data.name, '_') + 1)
|
||||
WHERE data.model = %s
|
||||
AND data.name LIKE %s
|
||||
AND template.name IN %s
|
||||
-- tax.name is of the form: {company_id}_{account.tax.template.name}
|
||||
""",
|
||||
[model, r"%s\_%%" % company.id],
|
||||
[model, tuple(template_xmlids)],
|
||||
)
|
||||
tuples = env.cr.fetchall()
|
||||
return dict(tuples)
|
||||
for company_id, template_id, model_id in env.cr.fetchall():
|
||||
res[company_id][template_id] = model_id
|
||||
return res
|
||||
|
||||
def _is_tax_and_template_same(template, tax):
|
||||
""" This function compares account.tax and account.tax.template repartition lines.
|
||||
@@ -110,17 +127,23 @@ def update_taxes_from_templates(cr, chart_template_xmlid):
|
||||
- amount
|
||||
- repartition lines percentages in the same order
|
||||
"""
|
||||
tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
|
||||
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
|
||||
return (
|
||||
tax.amount_type == template.amount_type
|
||||
and tax.amount == template.amount
|
||||
and len(tax_rep_lines) == len(template_rep_lines)
|
||||
and all(
|
||||
rep_line_tax.factor_percent == rep_line_template.factor_percent
|
||||
for rep_line_tax, rep_line_template in zip(tax_rep_lines, template_rep_lines)
|
||||
)
|
||||
)
|
||||
if tax.children_tax_ids:
|
||||
# if the tax has children taxes we don't do checks on rep. lines nor amount
|
||||
return tax.amount_type == template.amount_type
|
||||
else:
|
||||
tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
|
||||
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
|
||||
return (
|
||||
tax.amount_type == template.amount_type
|
||||
and tax.amount == template.amount
|
||||
and (
|
||||
len(tax_rep_lines) == len(template_rep_lines)
|
||||
and all(
|
||||
rep_line_tax.factor_percent == rep_line_template.factor_percent
|
||||
for rep_line_tax, rep_line_template in zip(tax_rep_lines, template_rep_lines)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
def _cleanup_tags(tags):
|
||||
""" Checks if the tags are still used in taxes or move lines. If not we delete it. """
|
||||
@@ -131,27 +154,33 @@ def update_taxes_from_templates(cr, chart_template_xmlid):
|
||||
if not (aml_using_tag or tax_using_tag or report_line_using_tag):
|
||||
tag.unlink()
|
||||
|
||||
def _update_fiscal_positions_from_templates(company, chart_template_id, new_taxes_template):
|
||||
chart_template = env['account.chart.template'].browse(chart_template_id)
|
||||
positions = env['account.fiscal.position.template'].search([('chart_template_id', '=', chart_template_id)])
|
||||
tax_template_ref = _get_template_to_real_xmlid_mapping(company, 'account.tax')
|
||||
fp_template_ref = _get_template_to_real_xmlid_mapping(company, 'account.fiscal.position')
|
||||
def _update_fiscal_positions_from_templates(chart_template, new_tax_template_by_company, all_tax_templates):
|
||||
fp_templates = env['account.fiscal.position.template'].search([('chart_template_id', '=', chart_template.id)])
|
||||
template2tax = _get_template_to_real_xmlid_mapping('account.tax', all_tax_templates)
|
||||
template2fp = _get_template_to_real_xmlid_mapping('account.fiscal.position', fp_templates)
|
||||
|
||||
tax_template_vals = []
|
||||
for position_template in positions:
|
||||
fp = env['account.fiscal.position'].browse(fp_template_ref.get(position_template.id))
|
||||
if not fp:
|
||||
continue
|
||||
for position_tax in position_template.tax_ids:
|
||||
position_tax_template_exist = fp.tax_ids.filtered_domain([('tax_src_id', '=', tax_template_ref[position_tax.tax_src_id.id]),
|
||||
('tax_dest_id', '=', position_tax.tax_dest_id and tax_template_ref[position_tax.tax_dest_id.id] or False)])
|
||||
if not position_tax_template_exist and (position_tax.tax_src_id in new_taxes_template or position_tax.tax_dest_id in new_taxes_template):
|
||||
tax_template_vals.append((position_tax, {
|
||||
'tax_src_id': tax_template_ref[position_tax.tax_src_id.id],
|
||||
'tax_dest_id': position_tax.tax_dest_id and tax_template_ref[position_tax.tax_dest_id.id] or False,
|
||||
'position_id': fp.id,
|
||||
}))
|
||||
chart_template._create_records_with_xmlid('account.fiscal.position.tax', tax_template_vals, company)
|
||||
for company_id in new_tax_template_by_company:
|
||||
fp_tax_template_vals = []
|
||||
template2fp_company = template2fp.get(company_id)
|
||||
for position_template in fp_templates:
|
||||
fp = env['account.fiscal.position'].browse(template2fp_company.get(position_template.id)) if template2fp_company else None
|
||||
if not fp:
|
||||
continue
|
||||
for position_tax in position_template.tax_ids:
|
||||
position_tax_template_exist = fp.tax_ids.filtered(
|
||||
lambda tax_fp: tax_fp.tax_src_id.id == template2tax.get(company_id).get(position_tax.tax_src_id.id)
|
||||
and tax_fp.tax_dest_id.id == (position_tax.tax_dest_id and template2tax.get(company_id).get(position_tax.tax_dest_id.id) or False)
|
||||
)
|
||||
if not position_tax_template_exist and (
|
||||
position_tax.tax_src_id in new_tax_template_by_company[company_id]
|
||||
or position_tax.tax_dest_id in new_tax_template_by_company[company_id]
|
||||
):
|
||||
fp_tax_template_vals.append((position_tax, {
|
||||
'tax_src_id': template2tax.get(company_id).get(position_tax.tax_src_id.id),
|
||||
'tax_dest_id': position_tax.tax_dest_id and template2tax.get(company_id).get(position_tax.tax_dest_id.id) or False,
|
||||
'position_id': fp.id,
|
||||
}))
|
||||
chart_template._create_records_with_xmlid('account.fiscal.position.tax', fp_tax_template_vals, env['res.company'].browse(company_id))
|
||||
|
||||
def _process_taxes_translations(chart_template, new_template_x_taxes):
|
||||
"""
|
||||
@@ -191,25 +220,30 @@ def update_taxes_from_templates(cr, chart_template_xmlid):
|
||||
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
chart_template = env.ref(chart_template_xmlid)
|
||||
companies = env['res.company'].search(['|', ('chart_template_id', '=', chart_template.id), ('chart_template_id', 'child_of', chart_template.id)])
|
||||
outdated_taxes = []
|
||||
new_taxes_template = []
|
||||
new_template2tax = []
|
||||
companies = env['res.company'].search([('chart_template_id', 'child_of', chart_template.id)])
|
||||
templates = env['account.tax.template'].with_context(active_test=False).search([('chart_template_id', '=', chart_template.id)])
|
||||
template2tax = _get_template_to_real_xmlid_mapping('account.tax', templates)
|
||||
outdated_taxes = env['account.tax']
|
||||
new_tax_template_by_company = defaultdict(env['account.tax.template'].browse) # only contains completely new taxes (not previous taxe had the xmlid)
|
||||
new_template2tax = [] # contains all created taxes
|
||||
for company in companies:
|
||||
template_to_tax = _get_template_to_real_xmlid_mapping(company, 'account.tax')
|
||||
templates = env['account.tax.template'].with_context(active_test=False).search([('chart_template_id', '=', chart_template.id)])
|
||||
templates_to_tax_create = []
|
||||
templates_to_tax_update = []
|
||||
template2oldtax_company = template2tax.get(company.id)
|
||||
for template in templates:
|
||||
tax = env['account.tax'].browse(template_to_tax.get(template.id))
|
||||
tax = env['account.tax'].browse(template2oldtax_company.get(template.id)) if template2oldtax_company else None
|
||||
if not tax or not _is_tax_and_template_same(template, tax):
|
||||
new_tax_id = _create_tax_from_template(company, template, old_tax=tax)
|
||||
new_template2tax.append((template.id, new_tax_id))
|
||||
templates_to_tax_create.append((template, tax))
|
||||
if tax:
|
||||
outdated_taxes.append(tax)
|
||||
outdated_taxes += tax
|
||||
else:
|
||||
new_taxes_template.append(template)
|
||||
# we only want to update fiscal position if there is no previous tax with the mapping
|
||||
new_tax_template_by_company[company.id] += template
|
||||
else:
|
||||
_update_tax_from_template(template, tax)
|
||||
_update_fiscal_positions_from_templates(company, chart_template.id, new_taxes_template)
|
||||
templates_to_tax_update.append((template, tax))
|
||||
new_template2tax += _create_taxes_from_template(company, templates_to_tax_create)
|
||||
_update_taxes_from_template(templates_to_tax_update)
|
||||
_update_fiscal_positions_from_templates(chart_template, new_tax_template_by_company, templates)
|
||||
if outdated_taxes:
|
||||
_notify_accountant_managers(outdated_taxes)
|
||||
if hasattr(chart_template, 'spoken_languages') and chart_template.spoken_languages:
|
||||
@@ -1120,17 +1154,15 @@ class AccountTaxTemplate(models.Model):
|
||||
val['tax_group_id'] = self.tax_group_id.id
|
||||
return val
|
||||
|
||||
def _get_tax_vals_complete(self, company):
|
||||
def _get_tax_vals_complete(self, company, tax_template_to_tax):
|
||||
"""
|
||||
Returns a dict of values to be used to create the tax corresponding to the template, assuming the
|
||||
account.account objects were already created.
|
||||
It differs from function _get_tax_vals because here, we replace the references to account.template by their
|
||||
corresponding account.account ids ('cash_basis_transition_account_id' and 'account_id' in the invoice and
|
||||
refund repartition lines)
|
||||
(Used by upgrade/migrations/util/accounting)
|
||||
"""
|
||||
vals = self._get_tax_vals(company, {})
|
||||
vals.pop("children_tax_ids", None)
|
||||
vals = self._get_tax_vals(company, tax_template_to_tax)
|
||||
|
||||
if self.cash_basis_transition_account_id.code:
|
||||
cash_basis_account_id = self.env['account.account'].search([
|
||||
@@ -1146,7 +1178,7 @@ class AccountTaxTemplate(models.Model):
|
||||
})
|
||||
return vals
|
||||
|
||||
def _generate_tax(self, company):
|
||||
def _generate_tax(self, company, accounts_exist=False):
|
||||
""" This method generate taxes from templates.
|
||||
|
||||
:param company: the company for which the taxes should be created from templates in self
|
||||
@@ -1170,7 +1202,10 @@ class AccountTaxTemplate(models.Model):
|
||||
tax_template_vals = []
|
||||
for template in templates:
|
||||
if all(child.id in tax_template_to_tax for child in template.children_tax_ids):
|
||||
vals = template._get_tax_vals(company, tax_template_to_tax)
|
||||
if accounts_exist:
|
||||
vals = template._get_tax_vals_complete(company, tax_template_to_tax)
|
||||
else:
|
||||
vals = template._get_tax_vals(company, tax_template_to_tax)
|
||||
tax_template_vals.append((template, vals))
|
||||
else:
|
||||
# defer the creation of this tax to the next batch
|
||||
|
||||
@@ -3538,3 +3538,56 @@ class TestAccountMoveOutInvoiceOnchanges(AccountTestInvoicingCommon):
|
||||
|
||||
# Date of the reversal of the exchange move should be the last day of the month/year of the payment depending on the sequence format
|
||||
self.assertEqual(exchange_move_reversal.date, fields.Date.to_date(expected_date))
|
||||
|
||||
@freeze_time('2023-05-01')
|
||||
def test_caba_with_different_lock_dates(self):
|
||||
"""
|
||||
Test the date of the CABA move when reconciling a payment with an invoice
|
||||
with date before fiscalyear_period but after period_lock_date when
|
||||
having accountant rights.
|
||||
"""
|
||||
self.env.company.tax_exigibility = True
|
||||
|
||||
tax_waiting_account = self.env['account.account'].create({
|
||||
'name': 'TAX_WAIT',
|
||||
'code': 'TWAIT',
|
||||
'user_type_id': self.env.ref('account.data_account_type_current_liabilities').id,
|
||||
'reconcile': True,
|
||||
})
|
||||
tax = self.env['account.tax'].create({
|
||||
'name': 'cash basis 10%',
|
||||
'type_tax_use': 'sale',
|
||||
'amount': 10,
|
||||
'tax_exigibility': 'on_payment',
|
||||
'cash_basis_transition_account_id': tax_waiting_account.id,
|
||||
})
|
||||
|
||||
self.env['account.move'].search([('state', '=', 'draft')]).unlink()
|
||||
|
||||
self.env.company.fiscalyear_lock_date = fields.Date.from_string('2023-01-01')
|
||||
self.env.company.period_lock_date = fields.Date.from_string('2023-02-01')
|
||||
|
||||
if not self.env.user.user_has_groups('account.group_account_manager'):
|
||||
self.env.user.groups_id = [(4, [self.env.ref('account.group_account_manager').id], 0)]
|
||||
|
||||
invoice = self.init_invoice(move_type='out_invoice', products=self.product_a, invoice_date='2023-01-02', taxes=tax)
|
||||
|
||||
payment = self.env['account.payment'].create({
|
||||
'partner_id': self.partner_a.id,
|
||||
'payment_type': 'inbound',
|
||||
'partner_type': 'customer',
|
||||
'date': '2023-01-30',
|
||||
'amount': invoice.amount_total,
|
||||
})
|
||||
|
||||
(invoice + payment.move_id).action_post()
|
||||
|
||||
(invoice + payment.move_id).line_ids\
|
||||
.filtered(lambda x: x.account_internal_type in ('receivable', 'payable'))\
|
||||
.reconcile()
|
||||
|
||||
caba_move = self.env['account.move'].search([('tax_cash_basis_move_id', '=', invoice.id)])
|
||||
|
||||
self.assertRecordValues(caba_move, [{
|
||||
'date': fields.Date.from_string('2023-01-30'),
|
||||
}])
|
||||
|
||||
@@ -15,19 +15,48 @@ class TestChartTemplate(SavepointCase):
|
||||
"""
|
||||
super().setUpClass()
|
||||
|
||||
be_country_id = cls.env.ref('base.be').id
|
||||
us_country_id = cls.env.ref('base.us').id
|
||||
cls.company = cls.env['res.company'].create({
|
||||
'name': 'TestCompany1',
|
||||
'country_id': be_country_id,
|
||||
'account_tax_fiscal_country_id': be_country_id,
|
||||
'country_id': us_country_id,
|
||||
'account_tax_fiscal_country_id': us_country_id,
|
||||
})
|
||||
|
||||
cls.chart_template = cls.env.ref('l10n_generic_coa.configurable_chart_template', raise_if_not_found=False)
|
||||
if not cls.chart_template:
|
||||
cls.skipTest(cls, "Accounting Tests skipped because the generic chart of accounts was not found")
|
||||
cls.chart_template_xmlid = 'l10n_test.test_chart_template_xmlid'
|
||||
cls.chart_template = cls.env['account.chart.template']._load_records([{
|
||||
'xml_id': cls.chart_template_xmlid,
|
||||
'values': {
|
||||
'name': 'Test Chart Template US',
|
||||
'currency_id': cls.env.ref('base.USD').id,
|
||||
'bank_account_code_prefix': 1000,
|
||||
'cash_account_code_prefix': 2000,
|
||||
'transfer_account_code_prefix': 3000,
|
||||
}
|
||||
}])
|
||||
account_templates = cls.env['account.account.template']._load_records([{
|
||||
'xml_id': 'account.test_account_income_template',
|
||||
'values':
|
||||
{
|
||||
'name': 'property_income_account',
|
||||
'code': '222221',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_revenue').id,
|
||||
'chart_template_id': cls.chart_template.id,
|
||||
}
|
||||
}, {
|
||||
'xml_id': 'account.test_account_expense_template',
|
||||
'values':
|
||||
{
|
||||
'name': 'property_expense_account',
|
||||
'code': '222222',
|
||||
'user_type_id': cls.env.ref('account.data_account_type_expenses').id,
|
||||
'chart_template_id': cls.chart_template.id,
|
||||
}
|
||||
}])
|
||||
cls.chart_template.property_account_income_categ_id = account_templates[0].id
|
||||
cls.chart_template.property_account_expense_categ_id = account_templates[1].id
|
||||
|
||||
cls.fiscal_position_template = cls._create_fiscal_position_template('account.test_fiscal_position_template',
|
||||
'BE fiscal position test', be_country_id)
|
||||
'US fiscal position test', us_country_id)
|
||||
cls.tax_template_1 = cls._create_tax_template('account.test_tax_template_1', 'Tax name 1', 1, 'tag_name_1')
|
||||
cls.tax_template_2 = cls._create_tax_template('account.test_tax_template_2', 'Tax name 2', 2, 'tag_name_2')
|
||||
cls.fiscal_position_tax_template_1 = cls._create_fiscal_position_tax_template(
|
||||
@@ -48,19 +77,48 @@ class TestChartTemplate(SavepointCase):
|
||||
return cls._create_tax_template(template_name, name, amount, tag_name=None)
|
||||
|
||||
@classmethod
|
||||
def _create_tax_template(cls, tax_template_xmlid, name, amount, tag_name=None):
|
||||
def _create_group_tax_template(cls, tax_template_xmlid, name, chart_template_id=None, active=True):
|
||||
children_1 = cls._create_tax_template(f'{tax_template_xmlid}_children1', f'{name}_children_1', 10,
|
||||
active=active)
|
||||
children_2 = cls._create_tax_template(f'{tax_template_xmlid}_children2', f'{name}_children_2', 15,
|
||||
active=active)
|
||||
return cls.env['account.tax.template']._load_records([{
|
||||
'xml_id': tax_template_xmlid,
|
||||
'values': {
|
||||
'name': name,
|
||||
'amount_type': 'group',
|
||||
'type_tax_use': 'none',
|
||||
'active': active,
|
||||
'chart_template_id': chart_template_id if chart_template_id else cls.chart_template.id,
|
||||
'children_tax_ids': [(6, 0, (children_1 + children_2).ids)],
|
||||
},
|
||||
}])
|
||||
|
||||
@classmethod
|
||||
def _create_tax_template(cls, tax_template_xmlid, name, amount, tag_name=None, account_data=None, active=True):
|
||||
if tag_name:
|
||||
tag = cls.env['account.account.tag'].create({
|
||||
'name': tag_name,
|
||||
'applicability': 'taxes',
|
||||
'country_id': cls.company.account_tax_fiscal_country_id.id,
|
||||
})
|
||||
if account_data:
|
||||
account_vals = {
|
||||
'name': account_data['name'],
|
||||
'code': account_data['code'],
|
||||
'user_type_id': cls.env.ref('account.data_account_type_current_liabilities').id,
|
||||
}
|
||||
# We have to instantiate both the template and the record since we suppose accounts are already created.
|
||||
account_template = cls.env['account.account.template'].create(account_vals)
|
||||
account_vals.update({'company_id': cls.company.id})
|
||||
cls.env['account.account'].create(account_vals)
|
||||
return cls.env['account.tax.template']._load_records([{
|
||||
'xml_id': tax_template_xmlid,
|
||||
'values': {
|
||||
'name': name,
|
||||
'amount': amount,
|
||||
'type_tax_use': 'none',
|
||||
'active': active,
|
||||
'chart_template_id': cls.chart_template.id,
|
||||
'invoice_repartition_line_ids': [
|
||||
(0, 0, {
|
||||
@@ -70,6 +128,7 @@ class TestChartTemplate(SavepointCase):
|
||||
}),
|
||||
(0, 0, {
|
||||
'factor_percent': 100,
|
||||
'account_id': account_template.id if account_data else None,
|
||||
'repartition_type': 'tax',
|
||||
}),
|
||||
],
|
||||
@@ -81,6 +140,7 @@ class TestChartTemplate(SavepointCase):
|
||||
}),
|
||||
(0, 0, {
|
||||
'factor_percent': 100,
|
||||
'account_id': account_template.id if account_data else None,
|
||||
'repartition_type': 'tax',
|
||||
}),
|
||||
],
|
||||
@@ -115,7 +175,7 @@ class TestChartTemplate(SavepointCase):
|
||||
creates this new tax and fiscal position line when updating
|
||||
"""
|
||||
tax_template_3 = self._create_tax_template('account.test_tax_3_template', 'Tax name 3', 3, 'tag_name_3')
|
||||
tax_template_4 = self._create_tax_template('account.test_tax_4_template', 'Tax name 4', 4)
|
||||
tax_template_4 = self._create_tax_template('account.test_tax_4_template', 'Tax name 4', 4, account_data={'name': 'account_name_4', 'code': 'TACT'})
|
||||
self._create_fiscal_position_tax_template(self.fiscal_position_template, 'account.test_fiscal_position_tax_template', tax_template_3, tax_template_4)
|
||||
update_taxes_from_templates(self.env.cr, self.chart_template_xmlid)
|
||||
|
||||
@@ -128,6 +188,7 @@ class TestChartTemplate(SavepointCase):
|
||||
{'name': 'Tax name 4', 'amount': 4},
|
||||
])
|
||||
self.assertEqual(taxes.invoice_repartition_line_ids.tag_ids.name, 'tag_name_3')
|
||||
self.assertEqual(taxes.invoice_repartition_line_ids.account_id.name, 'account_name_4')
|
||||
self.assertRecordValues(self.fiscal_position.tax_ids.tax_src_id, [
|
||||
{'name': 'Tax name 1'},
|
||||
{'name': 'Tax name 3'},
|
||||
@@ -265,3 +326,47 @@ class TestChartTemplate(SavepointCase):
|
||||
('partner_ids', 'in', normal_user.partner_id.ids),
|
||||
('body', 'like', f"%{self.tax_template_1.name}%"), # we look for taxes' name that have been sent in the message's body
|
||||
]), 0)
|
||||
|
||||
def test_update_taxes_children_tax_ids(self):
|
||||
""" Ensures children_tax_ids are correctly generated when updating taxes with
|
||||
amount_type='group'.
|
||||
"""
|
||||
group_tax_name = 'Group Tax name 1 TEST'
|
||||
self._create_group_tax_template('account.test_group_tax_test_template', group_tax_name,
|
||||
chart_template_id=self.chart_template.id)
|
||||
update_taxes_from_templates(self.env.cr, self.chart_template_xmlid)
|
||||
|
||||
parent_tax = self.env['account.tax'].search([
|
||||
('company_id', '=', self.company.id),
|
||||
('name', '=', group_tax_name),
|
||||
])
|
||||
children_taxes = self.env['account.tax'].search([
|
||||
('company_id', '=', self.company.id),
|
||||
('name', 'like', f'{group_tax_name}_%'),
|
||||
])
|
||||
self.assertEqual(len(parent_tax), 1, "The parent tax should have been created.")
|
||||
self.assertEqual(len(children_taxes), 2, "Two children should have been created.")
|
||||
self.assertEqual(parent_tax.children_tax_ids.ids, children_taxes.ids,
|
||||
"The parent and its children taxes should be linked together.")
|
||||
|
||||
def test_update_taxes_children_tax_ids_inactive(self):
|
||||
""" Ensure tax templates are correctly generated when updating taxes with children taxes,
|
||||
even if templates are inactive.
|
||||
"""
|
||||
group_tax_name = 'Group Tax name 1 inactive TEST'
|
||||
self._create_group_tax_template('account.test_group_tax_test_template_inactive', group_tax_name,
|
||||
chart_template_id=self.chart_template.id, active=False)
|
||||
update_taxes_from_templates(self.env.cr, self.chart_template_xmlid)
|
||||
|
||||
parent_tax = self.env['account.tax'].with_context(active_test=False).search([
|
||||
('company_id', '=', self.company.id),
|
||||
('name', '=', group_tax_name),
|
||||
])
|
||||
children_taxes = self.env['account.tax'].with_context(active_test=False).search([
|
||||
('company_id', '=', self.company.id),
|
||||
('name', 'like', f'{group_tax_name}_%'),
|
||||
])
|
||||
self.assertEqual(len(parent_tax), 1, "The parent tax should have been created, even if it is inactive.")
|
||||
self.assertFalse(parent_tax.active, "The parent tax should be inactive.")
|
||||
self.assertEqual(len(children_taxes), 2, "Two children should have been created, even if they are inactive.")
|
||||
self.assertEqual(children_taxes.mapped('active'), [False] * 2, "Children taxes should be inactive.")
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from flectra import models, fields, api
|
||||
from flectra import models, fields, _
|
||||
from flectra.tools.safe_eval import safe_eval
|
||||
from flectra.exceptions import UserError
|
||||
|
||||
|
||||
class AccountTaxPython(models.Model):
|
||||
@@ -35,7 +36,10 @@ class AccountTaxPython(models.Model):
|
||||
if self.amount_type == 'code':
|
||||
company = self.env.company
|
||||
localdict = {'base_amount': base_amount, 'price_unit':price_unit, 'quantity': quantity, 'product':product, 'partner':partner, 'company': company}
|
||||
safe_eval(self.python_compute, localdict, mode="exec", nocopy=True)
|
||||
try:
|
||||
safe_eval(self.python_compute, localdict, mode="exec", nocopy=True)
|
||||
except Exception as e:
|
||||
raise UserError(_("You entered invalid code %r in %r taxes\n\nError : %s") % (self.python_compute, self.name, e)) from e
|
||||
return localdict['result']
|
||||
return super(AccountTaxPython, self)._compute_amount(base_amount, price_unit, quantity, product, partner)
|
||||
|
||||
@@ -47,7 +51,10 @@ class AccountTaxPython(models.Model):
|
||||
for tax in self.filtered(lambda r: r.amount_type == 'code'):
|
||||
localdict = self._context.get('tax_computation_context', {})
|
||||
localdict.update({'price_unit': price_unit, 'quantity': quantity, 'product': product, 'partner': partner, 'company': company})
|
||||
safe_eval(tax.python_applicable, localdict, mode="exec", nocopy=True)
|
||||
try:
|
||||
safe_eval(tax.python_applicable, localdict, mode="exec", nocopy=True)
|
||||
except Exception as e:
|
||||
raise UserError(_("You entered invalid code %r in %r taxes\n\nError : %s") % (tax.python_applicable, tax.name, e)) from e
|
||||
if localdict.get('result', False):
|
||||
taxes += tax
|
||||
return super(AccountTaxPython, taxes).compute_all(price_unit, currency, quantity, product, partner, is_refund=is_refund, handle_price_include=handle_price_include)
|
||||
|
||||
@@ -178,9 +178,9 @@ var BarcodeParser = Class.extend({
|
||||
match.base_code = base_code.join('')
|
||||
}
|
||||
|
||||
if (base_pattern[0] !== '^') {
|
||||
base_pattern = "^" + base_pattern;
|
||||
}
|
||||
base_pattern = base_pattern.split('|')
|
||||
.map(part => part.startsWith('^') ? part : '^' + part)
|
||||
.join('|');
|
||||
match.match = match.base_code.match(base_pattern);
|
||||
|
||||
return match;
|
||||
|
||||
@@ -424,7 +424,7 @@ Or send your receipts at <a href="mailto:%(email)s?subject=Lunch%%20with%%20cust
|
||||
move_line_name = expense.employee_id.name + ': ' + expense.name.split('\n')[0][:64]
|
||||
account_src = expense._get_expense_account_source()
|
||||
account_dst = expense._get_expense_account_destination()
|
||||
account_date = expense.sheet_id.accounting_date or expense.date or fields.Date.context_today(expense)
|
||||
account_date = expense.date or expense.sheet_id.accounting_date or fields.Date.context_today(expense)
|
||||
|
||||
company_currency = expense.company_id.currency_id
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ class TestExpenses(TestExpenseCommon):
|
||||
# Receivable line (foreign currency):
|
||||
{
|
||||
'debit': 0.0,
|
||||
'credit': 862.5,
|
||||
'credit': 575.0,
|
||||
'amount_currency': -1725.0,
|
||||
'account_id': self.company_data['default_account_payable'].id,
|
||||
'product_id': False,
|
||||
@@ -81,7 +81,7 @@ class TestExpenses(TestExpenseCommon):
|
||||
},
|
||||
# Tax line (foreign currency):
|
||||
{
|
||||
'debit': 112.5,
|
||||
'debit': 75.0,
|
||||
'credit': 0.0,
|
||||
'amount_currency': 225.0,
|
||||
'account_id': self.company_data['default_account_tax_purchase'].id,
|
||||
@@ -103,7 +103,7 @@ class TestExpenses(TestExpenseCommon):
|
||||
},
|
||||
# Product line (foreign currency):
|
||||
{
|
||||
'debit': 750.0,
|
||||
'debit': 500.0,
|
||||
'credit': 0.0,
|
||||
'amount_currency': 1500.0,
|
||||
'account_id': self.company_data['default_account_expense'].id,
|
||||
@@ -134,7 +134,7 @@ class TestExpenses(TestExpenseCommon):
|
||||
'currency_id': self.company_data['currency'].id,
|
||||
},
|
||||
{
|
||||
'amount': -750.0,
|
||||
'amount': -500.0,
|
||||
'date': fields.Date.from_string('2017-01-01'),
|
||||
'account_id': self.analytic_account_2.id,
|
||||
'currency_id': self.company_data['currency'].id,
|
||||
|
||||
@@ -93,3 +93,5 @@ class ResCompany(models.Model):
|
||||
'printing_date': format_date(self.env, Date.to_string( Date.today())),
|
||||
'corrupted_orders': corrupted_orders or 'None'
|
||||
}
|
||||
else:
|
||||
raise UserError(_('Accounting is not unalterable for the company %s. This mechanism is designed for companies where accounting is unalterable.') % self.env.company.name)
|
||||
|
||||
@@ -10,10 +10,8 @@ class ReportPosHashIntegrity(models.AbstractModel):
|
||||
|
||||
@api.model
|
||||
def _get_report_values(self, docids, data=None):
|
||||
if data:
|
||||
data.update(self.env.company._check_pos_hash_integrity())
|
||||
else:
|
||||
data = self.env.company._check_hash_pos_integrity()
|
||||
data = data or {}
|
||||
data.update(self.env.company._check_pos_hash_integrity() or {})
|
||||
return {
|
||||
'doc_ids' : docids,
|
||||
'doc_model' : self.env['res.company'],
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<t t-foreach="ddt_dict" t-as="picking">
|
||||
<DatiDDT>
|
||||
<NumeroDDT t-esc="format_alphanumeric(picking.l10n_it_ddt_number[-20:])"/>
|
||||
<DataDDT t-esc="format_date(picking.date)"/>
|
||||
<DataDDT t-esc="format_date(picking.date_done)"/>
|
||||
<t t-if="len(ddt_dict) > 1">
|
||||
<t t-foreach="ddt_dict[picking]" t-as="line_ref">
|
||||
<RiferimentoNumeroLinea t-esc="line_ref"/>
|
||||
|
||||
@@ -48,6 +48,10 @@
|
||||
margin-right: $o-mail-discuss-sidebar-scrollbar-width;
|
||||
}
|
||||
|
||||
.o_DiscussSidebar_newChannelAutocompleteSuggestions {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.o_DiscussSidebar_quickSearch {
|
||||
border-radius: 10px;
|
||||
margin: 0 $o-mail-discuss-sidebar-scrollbar-width 10px;
|
||||
|
||||
@@ -130,6 +130,12 @@ class MicrosoftSync(models.AbstractModel):
|
||||
if with_uid
|
||||
else [('microsoft_id', '=', False)]
|
||||
)
|
||||
elif operator == '!=' and not value:
|
||||
return (
|
||||
[('microsoft_id', 'ilike', f'{IDS_SEPARATOR}_')]
|
||||
if with_uid
|
||||
else [('microsoft_id', '!=', False)]
|
||||
)
|
||||
return (
|
||||
['|'] * (len(value) - 1) + [_domain(v) for v in value]
|
||||
if operator.lower() == 'in'
|
||||
|
||||
@@ -288,3 +288,17 @@ class TestMicrosoftEvent(TestCommon):
|
||||
|
||||
# assert
|
||||
self.assertEqual(len(matched._events), 0)
|
||||
|
||||
def test_search_set_ms_universal_event_id(self):
|
||||
not_synced_events = self.env['calendar.event'].search([('ms_universal_event_id', '=', False)])
|
||||
synced_events = self.env['calendar.event'].search([('ms_universal_event_id', '!=', False)])
|
||||
|
||||
self.assertIn(self.simple_event, synced_events)
|
||||
self.assertNotIn(self.simple_event, not_synced_events)
|
||||
|
||||
self.simple_event.ms_universal_event_id = ''
|
||||
not_synced_events = self.env['calendar.event'].search([('ms_universal_event_id', '=', False)])
|
||||
synced_events = self.env['calendar.event'].search([('ms_universal_event_id', '!=', False)])
|
||||
|
||||
self.assertNotIn(self.simple_event, synced_events)
|
||||
self.assertIn(self.simple_event, not_synced_events)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
flectra.define('point_of_sale.tour.BarcodeScanning', function (require) {
|
||||
'use strict';
|
||||
|
||||
const { ProductScreen } = require('point_of_sale.tour.ProductScreenTourMethods');
|
||||
const { getSteps, startSteps } = require('point_of_sale.tour.utils');
|
||||
const Tour = require('web_tour.tour');
|
||||
|
||||
startSteps();
|
||||
|
||||
|
||||
// Add a product with its barcode
|
||||
ProductScreen.do.scan_barcode("0123456789");
|
||||
ProductScreen.check.selectedOrderlineHas('Monitor Stand');
|
||||
ProductScreen.do.scan_barcode("0123456789");
|
||||
ProductScreen.check.selectedOrderlineHas('Monitor Stand', 2);
|
||||
|
||||
// Test "Prices product" EAN-13 `23.....{NNNDD}` barcode pattern
|
||||
ProductScreen.do.scan_ean13_barcode("2305000000004");
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', 1, "0.00");
|
||||
ProductScreen.do.scan_ean13_barcode("2305000123454");
|
||||
ProductScreen.check.selectedOrderlineHas('Magnetic Board', 1, "123.45");
|
||||
|
||||
// Test "Weighted product" EAN-13 `21.....{NNDDD}` barcode pattern
|
||||
ProductScreen.do.scan_ean13_barcode("2100005000000");
|
||||
ProductScreen.check.selectedOrderlineHas('Wall Shelf Unit', 0, "0.00");
|
||||
ProductScreen.do.scan_ean13_barcode("2100005080000");
|
||||
ProductScreen.check.selectedOrderlineHas('Wall Shelf Unit', 8);
|
||||
|
||||
|
||||
Tour.register('BarcodeScanningTour', { test: true, url: '/pos/ui' }, getSteps());
|
||||
});
|
||||
@@ -146,6 +146,34 @@ flectra.define('point_of_sale.tour.ProductScreenTourMethods', function (require)
|
||||
},
|
||||
];
|
||||
}
|
||||
scan_barcode(barcode) {
|
||||
return [
|
||||
{
|
||||
content: `input barcode '${barcode}'`,
|
||||
trigger: "input.ean",
|
||||
run: `text ${barcode}`,
|
||||
},
|
||||
{
|
||||
content: `button scan barcode '${barcode}'`,
|
||||
trigger: "li.barcode",
|
||||
run: 'click',
|
||||
}
|
||||
];
|
||||
}
|
||||
scan_ean13_barcode(barcode) {
|
||||
return [
|
||||
{
|
||||
content: `input barcode '${barcode}'`,
|
||||
trigger: "input.ean",
|
||||
run: `text ${barcode}`,
|
||||
},
|
||||
{
|
||||
content: `button scan EAN-13 barcode '${barcode}'`,
|
||||
trigger: "li.custom_ean",
|
||||
run: 'click',
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
class Check {
|
||||
|
||||
@@ -70,6 +70,7 @@ class TestPointOfSaleHttpCommon(flectra.tests.HttpCase):
|
||||
'available_in_pos': True,
|
||||
'list_price': 1.98,
|
||||
'taxes_id': False,
|
||||
'barcode': '2100005000000',
|
||||
})
|
||||
small_shelf = env['product.product'].create({
|
||||
'name': 'Small Shelf',
|
||||
@@ -82,12 +83,14 @@ class TestPointOfSaleHttpCommon(flectra.tests.HttpCase):
|
||||
'available_in_pos': True,
|
||||
'list_price': 1.98,
|
||||
'taxes_id': False,
|
||||
'barcode': '2305000000004',
|
||||
})
|
||||
monitor_stand = env['product.product'].create({
|
||||
'name': 'Monitor Stand',
|
||||
'available_in_pos': True,
|
||||
'list_price': 3.19,
|
||||
'taxes_id': False,
|
||||
'barcode': '0123456789', # No pattern in barcode nomenclature
|
||||
})
|
||||
desk_pad = env['product.product'].create({
|
||||
'name': 'Desk Pad',
|
||||
@@ -659,3 +662,12 @@ class TestUi(TestPointOfSaleHttpCommon):
|
||||
|
||||
self.main_pos_config.open_session_cb(check_coa=False)
|
||||
self.start_tour("/pos/ui?config_id=%d" % self.main_pos_config.id, 'ReceiptScreenDiscountWithPricelistTour', login="admin")
|
||||
|
||||
def test_07_pos_barcodes_scan(self):
|
||||
barcode_rule = self.env.ref("point_of_sale.barcode_rule_client")
|
||||
barcode_rule.pattern = barcode_rule.pattern + "|234"
|
||||
# should in theory be changed in the JS code to `|^234`
|
||||
# If not, it will fail as it will mistakenly match with the product barcode "0123456789"
|
||||
|
||||
self.main_pos_config.open_session_cb(check_coa=False)
|
||||
self.start_tour("/pos/ui?debug=1&config_id=%d" % self.main_pos_config.id, 'BarcodeScanningTour', login="admin")
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<script type="text/javascript" src="/point_of_sale/static/tests/tours/ReceiptScreen.tour.js"></script>
|
||||
<script type="text/javascript" src="/point_of_sale/static/tests/tours/Chrome.tour.js"></script>
|
||||
<script type="text/javascript" src="/point_of_sale/static/tests/tours/TicketScreen.tour.js"></script>
|
||||
<script type="text/javascript" src="/point_of_sale/static/tests/tours/BarcodeScanning.tour.js"></script>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class StockMove(models.Model):
|
||||
layers = self.origin_returned_move_id.sudo().stock_valuation_layer_ids
|
||||
# dropshipping create additional positive svl to make sure there is no impact on the stock valuation
|
||||
# We need to remove them from the computation of the price unit.
|
||||
if self.origin_returned_move_id._is_dropshipped():
|
||||
if self.origin_returned_move_id._is_dropshipped() or self.origin_returned_move_id._is_dropshipped_returned():
|
||||
layers = layers.filtered(lambda l: float_compare(l.value, 0, precision_rounding=l.product_id.uom_id.rounding) <= 0)
|
||||
layers |= layers.stock_valuation_layer_ids
|
||||
quantity = sum(layers.mapped("quantity"))
|
||||
|
||||
@@ -324,3 +324,16 @@ class TestStockValuation(ValuationReconciliationTestCommon):
|
||||
|
||||
self.assertTrue(8 in return_pick.move_lines.stock_valuation_layer_ids.mapped('value'))
|
||||
self.assertTrue(-8 in return_pick.move_lines.stock_valuation_layer_ids.mapped('value'))
|
||||
|
||||
# return again to have a new dropship picking from a dropship return
|
||||
stock_return_picking_form_2 = Form(self.env['stock.return.picking']
|
||||
.with_context(active_ids=return_pick.ids, active_id=return_pick.ids[0],
|
||||
active_model='stock.picking'))
|
||||
stock_return_picking_2 = stock_return_picking_form_2.save()
|
||||
stock_return_picking_action_2 = stock_return_picking_2.create_returns()
|
||||
return_pick_2 = self.env['stock.picking'].browse(stock_return_picking_action_2['res_id'])
|
||||
return_pick_2.move_lines[0].move_line_ids[0].qty_done = 1.0
|
||||
return_pick_2._action_done()
|
||||
|
||||
self.assertTrue(8 in return_pick_2.move_lines.stock_valuation_layer_ids.mapped('value'))
|
||||
self.assertTrue(-8 in return_pick_2.move_lines.stock_valuation_layer_ids.mapped('value'))
|
||||
|
||||
+5
-1
@@ -159,11 +159,15 @@ $.fn.extend({
|
||||
compensateScrollbar(add = true, isScrollElement = true, cssProperty = 'padding-right') {
|
||||
for (const el of this) {
|
||||
// Compensate scrollbar
|
||||
const scrollableEl = isScrollElement ? el : $(el).parent().closestScrollable()[0];
|
||||
const isRTL = scrollableEl.matches(".o_rtl");
|
||||
if (isRTL) {
|
||||
cssProperty = cssProperty.replace("right", "left");
|
||||
}
|
||||
el.style.removeProperty(cssProperty);
|
||||
if (!add) {
|
||||
return;
|
||||
}
|
||||
const scrollableEl = isScrollElement ? el : $(el).parent().closestScrollable()[0];
|
||||
const style = window.getComputedStyle(el);
|
||||
const borderLeftWidth = parseInt(style.borderLeftWidth.replace('px', ''));
|
||||
const borderRightWidth = parseInt(style.borderRightWidth.replace('px', ''));
|
||||
|
||||
@@ -46,6 +46,13 @@ publicWidget.registry.Channel = publicWidget.Widget.extend({
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
destroy: function () {
|
||||
this.el.classList.add('d-none');
|
||||
this._super(...arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
|
||||
@@ -15,12 +15,6 @@ options.registry.Channel = options.Class.extend({
|
||||
await this._super(...arguments);
|
||||
this.publicChannels = await this._getPublicChannels();
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
cleanForSave: function () {
|
||||
this.$target.addClass('d-none');
|
||||
},
|
||||
/**
|
||||
* If we have already created channels => select the first one
|
||||
* else => modal prompt (create a new channel)
|
||||
|
||||
Reference in New Issue
Block a user