mirror of
https://gitlab.com/flectra-hq/flectra.git
synced 2026-10-25 07:27:39 -05:00
[PATCH] Upstream patch - 03122021
This commit is contained in:
1 parent
4f2062025b
commit
0afd89c0bb
23 files changed
+141
-33
No files matched your search
@@ -689,7 +689,7 @@ class AccountJournal(models.Model):
|
||||
domain = (domain or []) + [
|
||||
('account_id', 'in', tuple(self.default_account_id.ids)),
|
||||
('display_type', 'not in', ('line_section', 'line_note')),
|
||||
('move_id.state', '!=', 'cancel'),
|
||||
('parent_state', '!=', 'cancel'),
|
||||
]
|
||||
query = self.env['account.move.line']._where_calc(domain)
|
||||
tables, where_clause, where_params = query.get_sql()
|
||||
@@ -734,7 +734,7 @@ class AccountJournal(models.Model):
|
||||
domain = (domain or []) + [
|
||||
('account_id', 'in', tuple(accounts.ids)),
|
||||
('display_type', 'not in', ('line_section', 'line_note')),
|
||||
('move_id.state', '!=', 'cancel'),
|
||||
('parent_state', '!=', 'cancel'),
|
||||
('reconciled', '=', False),
|
||||
('journal_id', '=', self.id),
|
||||
]
|
||||
|
||||
@@ -1514,7 +1514,7 @@ class AccountMove(models.Model):
|
||||
|
||||
domain = [
|
||||
('account_id', 'in', pay_term_lines.account_id.ids),
|
||||
('move_id.state', '=', 'posted'),
|
||||
('parent_state', '=', 'posted'),
|
||||
('partner_id', '=', move.commercial_partner_id.id),
|
||||
('reconciled', '=', False),
|
||||
'|', ('amount_residual', '!=', 0.0), ('amount_residual_currency', '!=', 0.0),
|
||||
@@ -5044,7 +5044,7 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
state = context.get('state')
|
||||
if state and state.lower() != 'all':
|
||||
domain += [('move_id.state', '=', state)]
|
||||
domain += [('parent_state', '=', state)]
|
||||
|
||||
if context.get('company_id'):
|
||||
domain += [('company_id', '=', context['company_id'])]
|
||||
@@ -5079,7 +5079,7 @@ class AccountMoveLine(models.Model):
|
||||
tables = ''
|
||||
if domain:
|
||||
domain.append(('display_type', 'not in', ('line_section', 'line_note')))
|
||||
domain.append(('move_id.state', '!=', 'cancel'))
|
||||
domain.append(('parent_state', '!=', 'cancel'))
|
||||
|
||||
query = self._where_calc(domain)
|
||||
|
||||
|
||||
@@ -340,7 +340,7 @@ class AccountPayment(models.Model):
|
||||
else:
|
||||
bank_partner = pay.partner_id
|
||||
|
||||
available_partner_bank_accounts = bank_partner.bank_ids.filtered(lambda x: x.company_id in (False, pay.company_id))
|
||||
available_partner_bank_accounts = bank_partner.bank_ids.filtered(lambda x: x.company_id.id in (False, pay.company_id.id))
|
||||
if available_partner_bank_accounts:
|
||||
if pay.partner_bank_id not in available_partner_bank_accounts:
|
||||
pay.partner_bank_id = available_partner_bank_accounts[0]._origin
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from lxml import etree
|
||||
|
||||
from flectra import models, fields, api, _
|
||||
from flectra.exceptions import UserError
|
||||
@@ -276,7 +277,7 @@ class AccountPaymentRegister(models.TransientModel):
|
||||
batches = wizard._get_batches()
|
||||
bank_partners = batches[0]['lines'].move_id.bank_partner_id
|
||||
wizard.available_partner_bank_ids = bank_partners.bank_ids\
|
||||
.filtered(lambda x: x.company_id in (False, wizard.company_id))._origin
|
||||
.filtered(lambda x: x.company_id.id in (False, wizard.company_id.id))._origin
|
||||
else:
|
||||
wizard.available_partner_bank_ids = False
|
||||
|
||||
@@ -361,7 +362,28 @@ class AccountPaymentRegister(models.TransientModel):
|
||||
# -------------------------------------------------------------------------
|
||||
# LOW-LEVEL METHODS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@api.model
|
||||
def fields_view_get(self, view_id=None, view_type='form', toolbar=False, submenu=False):
|
||||
# OVERRIDE to add the 'available_partner_bank_ids' field dynamically inside the view.
|
||||
# TO BE REMOVED IN MASTER
|
||||
res = super().fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
|
||||
if view_type == 'form':
|
||||
form_view = self.env.ref('account.view_account_payment_register_form')
|
||||
tree = etree.fromstring(res['arch'])
|
||||
if res.get('view_id') == form_view.id and len(tree.xpath("//field[@name='available_partner_bank_ids']")) == 0:
|
||||
# Don't force people to update the account module.
|
||||
arch_tree = etree.fromstring(form_view.arch)
|
||||
if arch_tree.tag == 'form':
|
||||
arch_tree.insert(0, etree.Element('field', attrib={
|
||||
'name': 'available_partner_bank_ids',
|
||||
'invisible': '1',
|
||||
}))
|
||||
form_view.arch = etree.tostring(arch_tree, encoding='unicode')
|
||||
return super().fields_view_get(view_id=view_id, view_type=view_type, toolbar=toolbar, submenu=submenu)
|
||||
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
# OVERRIDE
|
||||
|
||||
@@ -296,7 +296,7 @@ class AccountEdiFormat(models.Model):
|
||||
"""
|
||||
# TO OVERRIDE
|
||||
self.ensure_one()
|
||||
if self._is_embedding_to_invoice_pdf_needed():
|
||||
if self._is_embedding_to_invoice_pdf_needed() and edi_document.attachment_id:
|
||||
pdf_writer.embed_flectra_attachment(edi_document.attachment_id)
|
||||
|
||||
####################################################
|
||||
|
||||
@@ -54,7 +54,9 @@ class AccountEdiFormat(models.Model):
|
||||
def _prepare_invoice_report(self, pdf_writer, edi_document):
|
||||
self.ensure_one()
|
||||
if self.code != 'facturx_1_0_05':
|
||||
super()._prepare_invoice_report(pdf_writer, edi_document)
|
||||
return super()._prepare_invoice_report(pdf_writer, edi_document)
|
||||
if not edi_document.attachment_id:
|
||||
return
|
||||
|
||||
pdf_writer.embed_flectra_attachment(edi_document.attachment_id)
|
||||
if not pdf_writer.is_pdfa and str2bool(self.env['ir.config_parameter'].sudo().get_param('edi.use_pdfa', 'False')):
|
||||
|
||||
@@ -15,8 +15,8 @@ class AccountPaymentRegister(models.TransientModel):
|
||||
# OVERRIDE to set the bank account defined on the employee
|
||||
res = super()._get_line_batch_key(line)
|
||||
expense_sheet = self.env['hr.expense.sheet'].search([('payment_mode', '=', 'own_account'), ('account_move_id', 'in', line.move_id.ids)])
|
||||
if expense_sheet.employee_id.bank_account_id and not line.move_id.partner_bank_id:
|
||||
res['partner_bank_id'] = expense_sheet.employee_id.bank_account_id.id
|
||||
if expense_sheet and not line.move_id.partner_bank_id:
|
||||
res['partner_bank_id'] = expense_sheet.employee_id.bank_account_id.id or line.partner_id.bank_ids and line.partner_id.bank_ids.ids[0]
|
||||
return res
|
||||
|
||||
def _create_payments(self):
|
||||
|
||||
@@ -306,3 +306,20 @@ class TestTimesheet(TestCommonTimesheet):
|
||||
self.task1.write({'partner_id': partner2})
|
||||
|
||||
self.assertEqual(timesheet_entry.partner_id, partner2, "The timesheet entry's partner should still be equal to the task's partner/customer, after the change")
|
||||
|
||||
def test_add_time_from_wizard(self):
|
||||
config = self.env["res.config.settings"].create({
|
||||
"timesheet_min_duration": 60,
|
||||
"timesheet_rounding": 15,
|
||||
})
|
||||
config.execute()
|
||||
wizard_min = self.env['project.task.create.timesheet'].create({
|
||||
'time_spent': 0.7,
|
||||
'task_id': self.task1.id,
|
||||
})
|
||||
wizard_round = self.env['project.task.create.timesheet'].create({
|
||||
'time_spent': 1.15,
|
||||
'task_id': self.task1.id,
|
||||
})
|
||||
self.assertEqual(wizard_min.save_timesheet().unit_amount, 1, "The timesheet's duration should be 1h (Minimum Duration = 60').")
|
||||
self.assertEqual(wizard_round.save_timesheet().unit_amount, 1.25, "The timesheet's duration should be 1h15 (Rounding = 15').")
|
||||
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from math import ceil
|
||||
from flectra import api, fields, models
|
||||
from datetime import datetime
|
||||
|
||||
@@ -20,13 +21,18 @@ class ProjectTaskCreateTimesheet(models.TransientModel):
|
||||
)
|
||||
|
||||
def save_timesheet(self):
|
||||
minimum_duration = int(self.env['ir.config_parameter'].sudo().get_param('hr_timesheet.timesheet_min_duration', 0))
|
||||
rounding = int(self.env['ir.config_parameter'].sudo().get_param('hr_timesheet.timesheet_rounding', 0))
|
||||
minutes_spent = max(minimum_duration, self.time_spent * 60)
|
||||
if rounding and ceil(minutes_spent % rounding) != 0:
|
||||
minutes_spent = ceil(minutes_spent / rounding) * rounding
|
||||
|
||||
values = {
|
||||
'task_id': self.task_id.id,
|
||||
'project_id': self.task_id.project_id.id,
|
||||
'date': fields.Date.context_today(self),
|
||||
'name': self.description,
|
||||
'user_id': self.env.uid,
|
||||
'unit_amount': self.time_spent,
|
||||
'unit_amount': minutes_spent / 60,
|
||||
}
|
||||
self.task_id.user_timer_id.unlink()
|
||||
return self.env['account.analytic.line'].create(values)
|
||||
@@ -177,6 +177,10 @@ body {
|
||||
}
|
||||
@mixin title {
|
||||
@include font;
|
||||
font-weight: bold;
|
||||
}
|
||||
.title {
|
||||
@include title;
|
||||
}
|
||||
|
||||
.swissqr_text {
|
||||
|
||||
@@ -1678,6 +1678,7 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'plus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_08_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
@@ -1699,7 +1700,8 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'minus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_08_taxe')],
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_08_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
(0,0, {
|
||||
@@ -1731,6 +1733,7 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'plus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_10_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
@@ -1752,7 +1755,8 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'minus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_10_taxe')],
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_10_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
(0,0, {
|
||||
@@ -1784,6 +1788,7 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'plus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_9B_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
@@ -1805,7 +1810,8 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'minus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_9B_taxe')],
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_9B_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
(0,0, {
|
||||
@@ -1837,6 +1843,7 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'plus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_09_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
@@ -1858,7 +1865,8 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'minus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_09_taxe')],
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_09_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
(0,0, {
|
||||
@@ -1890,6 +1898,7 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'plus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_11_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
@@ -1911,7 +1920,8 @@
|
||||
'factor_percent': 100,
|
||||
'repartition_type': 'tax',
|
||||
'minus_report_line_ids': [ref('l10n_fr.tax_report_17'),
|
||||
ref('l10n_fr.tax_report_11_taxe')],
|
||||
ref('l10n_fr.tax_report_20'),
|
||||
ref('l10n_fr.tax_report_11_taxe')],
|
||||
'account_id': ref('pcg_44566'),
|
||||
}),
|
||||
(0,0, {
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import stock_picking
|
||||
from . import stock_move
|
||||
@@ -0,0 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from flectra import models
|
||||
|
||||
|
||||
class StockMove(models.Model):
|
||||
_inherit = 'stock.move'
|
||||
|
||||
def _should_force_price_unit(self):
|
||||
self.ensure_one()
|
||||
return self.is_subcontract or super()._should_force_price_unit()
|
||||
@@ -64,6 +64,20 @@ class TestAccountSubcontractingFlows(TestMrpSubcontractingCommon):
|
||||
self.assertEqual(picking_receipt.move_lines.stock_valuation_layer_ids.value, 0)
|
||||
self.assertEqual(picking_receipt.move_lines.product_id.value_svl, 60)
|
||||
|
||||
# Do the same without any additionnal cost
|
||||
picking_receipt = picking_receipt.copy()
|
||||
picking_receipt.move_lines.price_unit = 0
|
||||
|
||||
picking_receipt.action_confirm()
|
||||
picking_receipt.move_lines.quantity_done = 1.0
|
||||
picking_receipt._action_done()
|
||||
|
||||
mo = picking_receipt._get_subcontracted_productions()
|
||||
# In this case, since there isn't any additionnal cost, the total cost of the subcontracting
|
||||
# is the sum of the components' costs: 10 + 20 = 30
|
||||
self.assertEqual(mo.move_finished_ids.stock_valuation_layer_ids.value, 30)
|
||||
self.assertEqual(picking_receipt.move_lines.product_id.value_svl, 90)
|
||||
|
||||
def test_subcontracting_account_backorder(self):
|
||||
""" This test uses tracked (serial and lot) component and tracked (serial) finished product
|
||||
The original subcontracting production order will be split into 4 backorders. This test
|
||||
|
||||
@@ -1557,7 +1557,7 @@ exports.Product = Backbone.Model.extend({
|
||||
// ORM. After that they are added in this order to the pricelists.
|
||||
get_price: function(pricelist, quantity, price_extra){
|
||||
var self = this;
|
||||
var date = moment().startOf('day');
|
||||
var date = moment();
|
||||
|
||||
// In case of nested pricelists, it is necessary that all pricelists are made available in
|
||||
// the POS. Display a basic alert to the user in this case.
|
||||
|
||||
@@ -193,7 +193,7 @@ class RatingMixin(models.AbstractModel):
|
||||
if hasattr(self, 'message_post'):
|
||||
feedback = tools.plaintext2html(feedback or '')
|
||||
self.message_post(
|
||||
body="<img src='/rating/static/src/img/rating_%s.png' alt=':%s/10' style='width:18px;height:18px;float:left;margin-right: 5px;'/>%s"
|
||||
body="<img src='/rating/static/src/img/rating_%s.png' alt=':%s/5' style='width:18px;height:18px;float:left;margin-right: 5px;'/>%s"
|
||||
% (rate, rate, feedback),
|
||||
subtype_xmlid=subtype_xmlid or "mail.mt_comment",
|
||||
author_id=rating.partner_id and rating.partner_id.id or None # None will set the default author in mail_thread.py
|
||||
|
||||
@@ -28,6 +28,10 @@ class StockMove(models.Model):
|
||||
action_data['domain'] = [('id', 'in', self.account_move_ids.ids)]
|
||||
return action_data
|
||||
|
||||
def _should_force_price_unit(self):
|
||||
self.ensure_one()
|
||||
return False
|
||||
|
||||
def _get_price_unit(self):
|
||||
""" Returns the unit price to value this stock move """
|
||||
self.ensure_one()
|
||||
@@ -36,7 +40,7 @@ class StockMove(models.Model):
|
||||
# If the move is a return, use the original move's price unit.
|
||||
if self.origin_returned_move_id and self.origin_returned_move_id.sudo().stock_valuation_layer_ids:
|
||||
price_unit = self.origin_returned_move_id.sudo().stock_valuation_layer_ids[-1].unit_cost
|
||||
return not float_is_zero(price_unit, precision) and price_unit or self.product_id.standard_price
|
||||
return price_unit if not float_is_zero(price_unit, precision) or self._should_force_price_unit() else self.product_id.standard_price
|
||||
|
||||
@api.model
|
||||
def _get_valued_types(self):
|
||||
|
||||
+4
-1
@@ -153,7 +153,10 @@ $.fn.extend({
|
||||
}
|
||||
const scrollableEl = isScrollElement ? el : $(el).parent().closestScrollable()[0];
|
||||
const style = window.getComputedStyle(el);
|
||||
const newValue = parseInt(style[cssProperty]) + scrollableEl.offsetWidth - scrollableEl.clientWidth;
|
||||
const borderLeftWidth = parseInt(style.borderLeftWidth.replace('px', ''));
|
||||
const borderRightWidth = parseInt(style.borderRightWidth.replace('px', ''));
|
||||
const bordersWidth = borderLeftWidth + borderRightWidth;
|
||||
const newValue = parseInt(style[cssProperty]) + scrollableEl.offsetWidth - scrollableEl.clientWidth - bordersWidth;
|
||||
el.style.setProperty(cssProperty, `${newValue}px`, 'important');
|
||||
}
|
||||
},
|
||||
|
||||
@@ -43,7 +43,7 @@ var ReportAction = AbstractAction.extend({
|
||||
$buttons: this.$buttons,
|
||||
};
|
||||
return Promise.all([this._super.apply(this, arguments), session.is_bound]).then(async function () {
|
||||
var web_base_url = session['web.base.url'];
|
||||
var web_base_url = window.origin;
|
||||
var trusted_host = utils.get_host_from_url(web_base_url);
|
||||
var trusted_protocol = utils.get_protocol_from_url(web_base_url);
|
||||
self.trusted_origin = utils.build_origin(trusted_protocol, trusted_host);
|
||||
|
||||
@@ -13,7 +13,7 @@ $(document.body)
|
||||
.addClass('container-fluid')
|
||||
.removeClass('container');
|
||||
|
||||
var web_base_url = $('html').attr('web-base-url');
|
||||
var web_base_url = window.origin;
|
||||
var trusted_host = utils.get_host_from_url(web_base_url);
|
||||
var trusted_protocol = utils.get_protocol_from_url(web_base_url);
|
||||
var trusted_origin = utils.build_origin(trusted_protocol, trusted_host);
|
||||
|
||||
@@ -1316,11 +1316,16 @@ var SnippetsMenu = Widget.extend({
|
||||
_activateInsertionZones: function ($selectorSiblings, $selectorChildren) {
|
||||
var self = this;
|
||||
|
||||
// If a modal is open, the drop zones must be created only in this modal
|
||||
const $openModal = self.getEditableArea().find('.modal:visible');
|
||||
if ($openModal.length) {
|
||||
$selectorSiblings = $openModal.find($selectorSiblings);
|
||||
$selectorChildren = $openModal.find($selectorChildren);
|
||||
// If a modal or a dropdown is open, the drop zones must be created
|
||||
// only in this element.
|
||||
const $editableArea = self.getEditableArea();
|
||||
let $open = $editableArea.find('.modal:visible');
|
||||
if (!$open.length) {
|
||||
$open = $editableArea.find('.dropdown-menu.show').addBack('.dropdown-menu.show').parent();
|
||||
}
|
||||
if ($open.length) {
|
||||
$selectorSiblings = $open.find($selectorSiblings);
|
||||
$selectorChildren = $open.find($selectorChildren);
|
||||
}
|
||||
|
||||
// Check if the drop zone should be horizontal or vertical
|
||||
|
||||
@@ -1004,7 +1004,7 @@ header {
|
||||
}
|
||||
}
|
||||
|
||||
.o_connected_user:not(.editor_has_snippets) header & {
|
||||
.o_connected_user:not(.editor_has_snippets):not(.o_fullscreen) header & {
|
||||
top: -$o-navbar-height;
|
||||
padding-top: $o-navbar-height;
|
||||
}
|
||||
@@ -1098,7 +1098,7 @@ header {
|
||||
}
|
||||
}
|
||||
}
|
||||
body.o_connected_user {
|
||||
body.o_connected_user:not(.o_fullscreen) {
|
||||
&:not(.editor_has_snippets) #wrapwrap > header {
|
||||
top: $o-navbar-height;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,18 @@
|
||||
* in its own file in master.
|
||||
*/
|
||||
|
||||
.editor_has_snippets {
|
||||
.editor_has_snippets:not(.o_fullscreen) {
|
||||
.o_livechat_button, .o_thread_window {
|
||||
// TODO add this in an edit-mode only file in master (in 14.0 that asset
|
||||
// would be website.assets_wysiwyg...)
|
||||
right: $o-we-sidebar-width !important;
|
||||
}
|
||||
}
|
||||
|
||||
@if o-website-value('header-template') == 'sidebar' and $-hamburger-right {
|
||||
@include media-breakpoint-up(lg) {
|
||||
.o_livechat_button, .o_thread_window {
|
||||
transform: translate(- o-website-value('sidebar-width'));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user