[PATCH] Upstream patch - 03122021

This commit is contained in:
Parthiv Patel committed 2021-12-03 09:40:42 +00:00
1 parent 4f2062025b
commit 0afd89c0bb
23 files changed
+141 -33

No files matched your search

+2 -2
View File
@@ -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),
]
+3 -3
View File
@@ -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)
+1 -1
View File
@@ -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 {
+15 -5
View File
@@ -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
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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
+5 -1
View File
@@ -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
View File
@@ -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);
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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'));
}
}
}