[PATCH] Upstream patch - 16022023

This commit is contained in:
Parthiv Patel
2023-02-16 08:34:17 +00:00
parent 0d6c5135b1
commit d8fef7a66d
16 changed files with 108 additions and 13 deletions

View File

@@ -261,7 +261,7 @@ class AccountMove(models.Model):
# ==== Reverse feature fields ====
reversed_entry_id = fields.Many2one('account.move', string="Reversal of", readonly=True, copy=False,
check_company=True)
check_company=True, index=True)
reversal_move_id = fields.One2many('account.move', 'reversed_entry_id')
# =========================================================

View File

@@ -135,7 +135,9 @@ def update_taxes_from_templates(cr, chart_template_xmlid):
if not fp:
continue
for position_tax in position_template.tax_ids:
if position_tax.tax_src_id in new_taxes_template or position_tax.tax_dest_id in new_taxes_template:
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,

View File

@@ -469,6 +469,9 @@ class ResCompany(models.Model):
"""Checks that all posted moves have still the same data as when they were posted
and raises an error with the result.
"""
if not self.env.user.has_group('account.group_account_user'):
raise UserError(_('Please contact your accountant to print the Hash integrity result.'))
def build_move_info(move):
return(move.name, move.inalterable_hash, fields.Date.to_string(move.date))
@@ -496,8 +499,11 @@ class ResCompany(models.Model):
results_by_journal['results'].append(rslt)
continue
all_moves_count = self.env['account.move'].search_count([('state', '=', 'posted'), ('journal_id', '=', journal.id)])
moves = self.env['account.move'].search([('state', '=', 'posted'), ('journal_id', '=', journal.id),
# We need the `sudo()` to ensure that all the moves are searched, no matter the user's access rights.
# This is required in order to generate consistent hashs.
# It is not an issue, since the data is only used to compute a hash and not to return the actual values.
all_moves_count = self.env['account.move'].sudo().search_count([('state', '=', 'posted'), ('journal_id', '=', journal.id)])
moves = self.env['account.move'].sudo().search([('state', '=', 'posted'), ('journal_id', '=', journal.id),
('secure_sequence_number', '!=', 0)], order="secure_sequence_number ASC")
if not moves:
rslt.update({

View File

@@ -230,6 +230,7 @@ class HrEmployeePrivate(models.Model):
vals.update(self._sync_user(user, vals.get('image_1920') == self._default_image()))
vals['name'] = vals.get('name', user.name)
employee = super(HrEmployeePrivate, self).create(vals)
employee.message_subscribe(employee.address_home_id.ids)
url = '/web#%s' % url_encode({
'action': 'hr.plan_wizard_action',
'active_id': employee.id,
@@ -248,6 +249,8 @@ class HrEmployeePrivate(models.Model):
account_id = vals.get('bank_account_id') or self.bank_account_id.id
if account_id:
self.env['res.partner.bank'].browse(account_id).partner_id = vals['address_home_id']
self.message_unsubscribe(self.address_home_id.ids)
self.message_subscribe([vals['address_home_id']])
if vals.get('user_id'):
# Update the profile pictures with user, except if provided
vals.update(self._sync_user(self.env['res.users'].browse(vals['user_id']), bool(vals.get('image_1920'))))

View File

@@ -7,6 +7,7 @@ class AccountMove(models.Model):
l10n_de_template_data = fields.Binary(compute='_compute_l10n_de_template_data')
l10n_de_document_title = fields.Char(compute='_compute_l10n_de_document_title')
l10n_de_addresses = fields.Binary(compute='_compute_l10n_de_addresses')
def _compute_l10n_de_template_data(self):
for record in self:
@@ -38,3 +39,14 @@ class AccountMove(models.Model):
record.l10n_de_document_title = _('Vendor Credit Note')
elif record.move_type == 'in_invoice':
record.l10n_de_document_title = _('Vendor Bill')
def _compute_l10n_de_addresses(self):
for record in self:
record.l10n_de_addresses = data = []
if record.partner_shipping_id == record.partner_id:
data.append((_("Invoicing and Shipping Address:"), record.partner_shipping_id))
elif record.move_type in ("in_invoice", "in_refund"):
data.append((_("Invoicing and Shipping Address:"), record.partner_id))
else:
data.append((_("Shipping Address:"), record.partner_shipping_id))
data.append((_("Invoicing Address:"), record.partner_id))

View File

@@ -3841,6 +3841,16 @@
<field name="tax_src_id" ref="l10n_es.account_tax_template_p_iva4_bc"/>
<field name="tax_dest_id" ref="l10n_es.account_tax_template_p_irpf2"/>
</record>
<record id="fptt_reagyp_a_4b_3" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fp_reagyp_a"/>
<field name="tax_src_id" ref="account_tax_template_p_iva0_s_bc"/>
<field name="tax_dest_id" ref="account_tax_template_p_iva12_agr"/>
</record>
<record id="fptt_reagyp_a_4b_4" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fp_reagyp_a"/>
<field name="tax_src_id" ref="account_tax_template_p_iva0_s_bc"/>
<field name="tax_dest_id" ref="account_tax_template_p_irpf2"/>
</record>
<record id="fptt_reagyp_gp_4b_1" model="account.fiscal.position.tax.template">
<field name="position_id" ref="fp_reagyp_gp"/>
<field name="tax_src_id" ref="l10n_es.account_tax_template_p_iva4_bc"/>

View File

@@ -19,7 +19,7 @@
<!-- Don't put move_id here to avoid that the framework send falsy move_id -->
<field name="id" invisible="1"/>
<field name="product_id" required="1"/>
<field name="lot_id"
<field name="lot_id" groups="stock.group_production_lot"
attrs="{'invisible': [('tracking', 'not in', ('serial', 'lot'))], 'required': [('tracking', 'in', ('serial', 'lot'))]}"
context="{'default_product_id': product_id, 'default_company_id': company_id}"/>
<field name="product_uom_qty" readonly="1" force_save="1"/>
@@ -67,7 +67,7 @@
<field name="location_dest_id" invisible="1"/>
<field name="product_id" readonly="1" force_save="1"/>
<field name="qty_done"/>
<field name="lot_id" attrs="{'column_invisible':[('parent.has_tracking', 'not in', ('serial', 'lot'))], 'required': [('tracking', 'in', ('serial', 'lot'))]}" context="{'default_product_id': product_id, 'default_company_id': company_id}"/>
<field name="lot_id" attrs="{'column_invisible':[('parent.has_tracking', 'not in', ('serial', 'lot'))], 'required': [('tracking', 'in', ('serial', 'lot'))]}" context="{'default_product_id': product_id, 'default_company_id': company_id}" groups="stock.group_production_lot"/>
</tree>
</field>
</sheet>

View File

@@ -84,8 +84,8 @@ class AuthorizeAPI():
'paymentProfiles': {
'customerType': 'business' if partner.is_company else 'individual',
'billTo': {
'firstName': '' if partner.is_company else _partner_split_name(partner.name)[0],
'lastName': _partner_split_name(partner.name)[1],
'firstName': '' if partner.is_company else _partner_split_name(partner.name)[0][:50],
'lastName': partner.name[:50] if partner.is_company else _partner_split_name(partner.name)[1][:50],
'address': (partner.street or '' + (partner.street2 if partner.street2 else '')) or None,
'city': partner.city,
'state': partner.state_id.name or None,

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from . import test_phonenumbers
from . import test_phonenumbers_patch

View File

@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
from flectra.addons.phone_validation.tools import phone_validation
from flectra.exceptions import UserError
from flectra.tests import tagged
from flectra.tests.common import BaseCase
@tagged('phone_validation')
class TestPhonenumbers(BaseCase):
def test_country_code_falsy(self):
self.assertEqual(
phone_validation.phone_format('0456998877', 'BE', '32', force_format='E164'),
'+32456998877'
)
# no country code -> UserError, no internal traceback
with self.assertRaises(UserError):
self.assertEqual(
phone_validation.phone_format('0456998877', None, '32', force_format='E164'),
'+32456998877'
)

View File

@@ -15,7 +15,7 @@ try:
def phone_parse(number, country_code):
try:
phone_nbr = phonenumbers.parse(number, region=country_code, keep_raw_input=True)
phone_nbr = phonenumbers.parse(number, region=country_code or None, keep_raw_input=True)
except phonenumbers.phonenumberutil.NumberParseException as e:
raise UserError(_('Unable to parse %(phone)s: %(error)s', phone=number, error=str(e)))

View File

@@ -106,6 +106,13 @@ flectra.define('point_of_sale.ReceiptScreen', function (require) {
const orderName = order.get_name();
const orderClient = { email: this.orderUiState.inputEmail, name: client ? client.name : this.orderUiState.inputEmail };
const order_server_id = this.env.pos.validated_orders_name_server_id_map[orderName];
if (!order_server_id) {
this.showPopup('ErrorPopup', {
title: 'Unsynced order',
body: 'This order is not yet synced to server. Make sure it is synced then try again.',
});
return Promise.reject();
}
await this.rpc({
model: 'pos.order',
method: 'action_receipt_to_customer',

View File

@@ -637,7 +637,7 @@ class Task(models.Model):
allow_subtasks = fields.Boolean(string="Allow Sub-tasks", related="project_id.allow_subtasks", readonly=True)
subtask_count = fields.Integer("Sub-task count", compute='_compute_subtask_count')
email_from = fields.Char(string='Email From', help="These people will receive email.", index=True,
compute='_compute_email_from', store="True", readonly=False)
compute='_compute_email_from', store="True", readonly=False, copy=False)
allowed_user_ids = fields.Many2many('res.users', string="Visible to", groups='project.group_project_manager', compute='_compute_allowed_user_ids', store=True, readonly=False, copy=False)
project_privacy_visibility = fields.Selection(related='project_id.privacy_visibility', string="Project Visibility")
# Computed field about working time elapsed between record creation and assignation/closing.

View File

@@ -2162,6 +2162,20 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon):
invoice = so._create_invoices()
invoice.action_post()
# Receive one @100
in_moves = self.env['stock.move'].create({
'name': 'IN move @100',
'product_id': self.component_a.id,
'location_id': self.env.ref('stock.stock_location_suppliers').id,
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
'product_uom': self.component_a.uom_id.id,
'product_uom_qty': 1,
'price_unit': 100,
})
in_moves._action_confirm()
in_moves.quantity_done = 1
in_moves._action_done()
# Return the second picking (i.e. one component @20)
ctx = {'active_id': pickings[1].id, 'active_model': 'stock.picking'}
return_wizard = Form(self.env['stock.return.picking'].with_context(ctx)).save()
@@ -2259,6 +2273,20 @@ class TestSaleMrpFlow(ValuationReconciliationTestCommon):
invoice = so._create_invoices()
invoice.action_post()
# Receive one @100
in_moves = self.env['stock.move'].create({
'name': 'IN move @100',
'product_id': self.component_a.id,
'location_id': self.env.ref('stock.stock_location_suppliers').id,
'location_dest_id': self.company_data['default_warehouse'].lot_stock_id.id,
'product_uom': self.component_a.uom_id.id,
'product_uom_qty': 1,
'price_unit': 100,
})
in_moves._action_confirm()
in_moves.quantity_done = 1
in_moves._action_done()
# Return the second picking (i.e. one component @20)
ctx = {'active_id': pickings[1].id, 'active_model': 'stock.picking'}
return_wizard = Form(self.env['stock.return.picking'].with_context(ctx)).save()

View File

@@ -201,7 +201,7 @@ class Website(Home):
sitemaps.unlink()
pages = 0
locs = request.website.with_user(request.website.user_id)._enumerate_pages()
locs = request.website.with_context(_filter_duplicate_pages=True).with_user(request.website.user_id)._enumerate_pages()
while True:
values = {
'locs': islice(locs, 0, LOC_PER_SITEMAP),
@@ -264,7 +264,7 @@ class Website(Home):
current_website = request.website
matching_pages = []
for page in current_website.search_pages(needle, limit=int(limit)):
for page in current_website.with_context(_filter_duplicate_pages=True).search_pages(needle, limit=int(limit)):
matching_pages.append({
'value': page['loc'],
'label': 'name' in page and '%s (%s)' % (page['loc'], page['name']) or page['loc'],
@@ -272,7 +272,7 @@ class Website(Home):
matching_urls = set(map(lambda match: match['value'], matching_pages))
matching_last_modified = []
last_modified_pages = current_website._get_website_pages(order='write_date desc', limit=5)
last_modified_pages = current_website.with_context(_filter_duplicate_pages=True)._get_website_pages(order='write_date desc', limit=5)
for url, name in last_modified_pages.mapped(lambda p: (p.url, p.name)):
if needle.lower() in name.lower() or needle.lower() in url.lower() and url not in matching_urls:
matching_last_modified.append({

View File

@@ -892,6 +892,9 @@ class Website(models.Model):
domain = []
domain += self.get_current_website().website_domain()
pages = self.env['website.page'].sudo().search(domain, order=order, limit=limit)
# TODO In 16.0 remove condition on _filter_duplicate_pages.
if self.env.context.get('_filter_duplicate_pages'):
pages = pages.filtered(pages._is_most_specific_page)
return pages
def search_pages(self, needle=None, limit=None):