From 6073024f8df7dcea4114a90ce875bd690067b1f0 Mon Sep 17 00:00:00 2001 From: Parthiv Patel Date: Mon, 28 Mar 2022 08:35:30 +0000 Subject: [PATCH] [PATCH] Upstream patch - 28032022 --- addons/account/models/account_move.py | 1 + .../models/account_edi_proxy_user.py | 2 +- addons/coupon/models/coupon.py | 3 +- addons/hr/security/hr_security.xml | 2 +- .../models/account_edi_format.py | 19 ++++- .../data/account_tax_template_data.xml | 16 ++-- addons/mrp/models/mrp_document.py | 8 ++ addons/point_of_sale/static/src/js/models.js | 2 +- addons/survey/controllers/main.py | 2 +- .../web/static/src/js/fields/basic_fields.js | 16 ++++ .../static/tests/fields/basic_fields_tests.js | 75 +++++++++++++++++++ 11 files changed, 130 insertions(+), 16 deletions(-) diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 1446c38c11..0b2e8fd187 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -5089,6 +5089,7 @@ class AccountMoveLine(models.Model): # Force the values of the move line in the context to avoid issues ctx = dict(self.env.context) ctx.pop('active_id', None) + ctx.pop('default_journal_id', None) ctx['active_ids'] = self.ids ctx['active_model'] = 'account.move.line' action['context'] = ctx diff --git a/addons/account_edi_proxy_client/models/account_edi_proxy_user.py b/addons/account_edi_proxy_client/models/account_edi_proxy_user.py index c3e5e242b1..cb6b852e94 100644 --- a/addons/account_edi_proxy_client/models/account_edi_proxy_user.py +++ b/addons/account_edi_proxy_client/models/account_edi_proxy_user.py @@ -19,7 +19,7 @@ _logger = logging.getLogger(__name__) DEFAULT_SERVER_URL = 'https://l10n-it-edi.api.flectrahq.com' -DEFAULT_TEST_SERVER_URL = 'https://iap-services-test-saas12-test-13-test-14-test-15.test.flectrahq.com' +DEFAULT_TEST_SERVER_URL = 'https://iap-services-test.flectrahq.com' TIMEOUT = 30 diff --git a/addons/coupon/models/coupon.py b/addons/coupon/models/coupon.py index f81e330f1f..b1fc5c7d52 100644 --- a/addons/coupon/models/coupon.py +++ b/addons/coupon/models/coupon.py @@ -5,6 +5,7 @@ from dateutil.relativedelta import relativedelta from flectra import api, fields, models, _ +from uuid import uuid4 class Coupon(models.Model): _name = 'coupon.coupon' @@ -22,7 +23,7 @@ class Coupon(models.Model): Generate 8 bytes (64 bits) barcodes as 16 bytes barcodes are not compatible with all scanners. """ - return str(random.getrandbits(64)) + return str(uuid4())[:22] code = fields.Char(default=_generate_code, required=True, readonly=True) expiration_date = fields.Date('Expiration Date', compute='_compute_expiration_date') diff --git a/addons/hr/security/hr_security.xml b/addons/hr/security/hr_security.xml index 89f0c595b1..9e3c9f720d 100644 --- a/addons/hr/security/hr_security.xml +++ b/addons/hr/security/hr_security.xml @@ -41,7 +41,7 @@ Employee multi company rule - ['|',('company_id','=',False),('company_id', 'in', company_ids)] + ['|','|',('user_id', '=', user.id),('company_id', '=',False),('company_id', 'in', company_ids)] diff --git a/addons/l10n_it_edi_sdicoop/models/account_edi_format.py b/addons/l10n_it_edi_sdicoop/models/account_edi_format.py index 0d1c31af5d..d3a76e8966 100644 --- a/addons/l10n_it_edi_sdicoop/models/account_edi_format.py +++ b/addons/l10n_it_edi_sdicoop/models/account_edi_format.py @@ -237,9 +237,22 @@ class AccountEdiFormat(models.Model): else: to_return[invoice] = {'attachment': invoice.l10n_it_edi_attachment_id, 'success': True} elif state == 'notificaScarto': - errors = [element.find('Descrizione').text for element in response_tree.xpath('//Errore')] - to_return[invoice] = {'error': self._format_error_message(_('The invoice has been refused by the Exchange System'), errors), 'blocking_level': 'error'} - invoice.l10n_it_edi_transaction = False + elements = response_tree.xpath('//Errore') + error_codes = [element.find('Codice').text for element in elements] + errors = [element.find('Descrizione').text for element in elements] + # Duplicated invoice + if '00404' in error_codes: + idx = error_codes.index('00404') + invoice.message_post(body=_( + 'This invoice number had already been submitted to the SdI, so it is' + ' set as Sent. Please verify that the system is correctly configured,' + ' because the correct flow does not need to send the same invoice' + ' twice for any reason.\n' + ' Original message from the SDI: %s', errors[idx])) + to_return[invoice] = {'attachment': invoice.l10n_it_edi_attachment_id, 'success': True} + else: + to_return[invoice] = {'error': self._format_error_message(_('The invoice has been refused by the Exchange System'), errors), 'blocking_level': 'error'} + invoice.l10n_it_edi_transaction = False elif state == 'notificaMancataConsegna': if invoice._is_commercial_partner_pa(): to_return[invoice] = {'error': _( diff --git a/addons/l10n_jp/data/account_tax_template_data.xml b/addons/l10n_jp/data/account_tax_template_data.xml index 7e88ef6c6f..7f220dac87 100644 --- a/addons/l10n_jp/data/account_tax_template_data.xml +++ b/addons/l10n_jp/data/account_tax_template_data.xml @@ -240,7 +240,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'plus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_8')], }), ]"/> @@ -253,7 +253,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'minus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_8')], }), ]"/> @@ -278,7 +278,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'plus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_10')], }), ]"/> @@ -291,7 +291,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'minus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_10')], }), ]"/> @@ -316,7 +316,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'plus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_8')], }), ]"/> @@ -329,7 +329,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'minus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_8')], }), ]"/> @@ -354,7 +354,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'plus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_10')], }), ]"/> @@ -367,7 +367,7 @@ (0,0, { 'factor_percent': 100, 'repartition_type': 'tax', - 'account_id': ref('A11807'), + 'account_id': ref('A11809'), 'minus_report_line_ids': [ref('l10n_jp.tax_report_to_pay_temp_pmt_susp_cons_10')], }), ]"/> diff --git a/addons/mrp/models/mrp_document.py b/addons/mrp/models/mrp_document.py index b2722686e3..4a4646d298 100644 --- a/addons/mrp/models/mrp_document.py +++ b/addons/mrp/models/mrp_document.py @@ -15,6 +15,14 @@ class MrpDocument(models.Model): } _order = "priority desc, id desc" + def copy(self, default=None): + ir_default = default + if ir_default: + ir_fields = list(self.env['ir.attachment']._fields) + ir_default = {field : default[field] for field in default.keys() if field in ir_fields} + new_attach = self.ir_attachment_id.copy(ir_default) + return super().copy(dict(default, ir_attachment_id=new_attach.id)) + ir_attachment_id = fields.Many2one('ir.attachment', string='Related attachment', required=True, ondelete='cascade') active = fields.Boolean('Active', default=True) priority = fields.Selection([ diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 67ff5a187b..e7ce210405 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -792,7 +792,7 @@ exports.PosModel = Backbone.Model.extend({ } for (var i = 0; i < jsons.length; i++) { var json = jsons[i]; - if (json.pos_session_id !== this.pos_session.id && json.lines.length > 0) { + if (json.pos_session_id !== this.pos_session.id && (json.lines.length > 0 || json.statement_ids.length > 0)) { orders.push(new exports.Order({},{ pos: this, json: json, diff --git a/addons/survey/controllers/main.py b/addons/survey/controllers/main.py index 8e56ec0b6a..23cd062a29 100644 --- a/addons/survey/controllers/main.py +++ b/addons/survey/controllers/main.py @@ -84,7 +84,7 @@ class Survey(http.Controller): return 'survey_void' if answer_sudo and check_partner: - if request.env.user._is_public() and answer_sudo.partner_id: + if request.env.user._is_public() and answer_sudo.partner_id and not answer_token: # answers from public user should not have any partner_id; this indicates probably a cookie issue return 'answer_wrong_user' if not request.env.user._is_public() and answer_sudo.partner_id != request.env.user.partner_id: diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index be76b50c51..363f46e634 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -1926,10 +1926,18 @@ var FieldBinaryImage = AbstractFieldBinary.extend({ if (width) { $img.attr('width', width); $img.css('max-width', width + 'px'); + if (!height) { + $img.css('height', 'auto'); + $img.css('max-height', '100%'); + } } if (height) { $img.attr('height', height); $img.css('max-height', height + 'px'); + if (!width) { + $img.css('width', 'auto'); + $img.css('max-width', '100%'); + } } this.$('> img').remove(); this.$el.prepend($img); @@ -2028,10 +2036,18 @@ var CharImageUrl = AbstractField.extend({ if (width) { $img.attr('width', width); $img.css('max-width', width + 'px'); + if (!height) { + $img.css('height', 'auto'); + $img.css('max-height', '100%'); + } } if (height) { $img.attr('height', height); $img.css('max-height', height + 'px'); + if (!width) { + $img.css('width', 'auto'); + $img.css('max-width', '100%'); + } } this.$('> img').remove(); this.$el.prepend($img); diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 4a59b3e5aa..7e667d5b9a 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -2740,6 +2740,48 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('image fields are correctly rendered with one dimension set', async function (assert) { + assert.expect(6); + + this.data.partner.fields.picture = { string: 'Picture', type: 'binary' }; + this.data.partner.records[0].__last_update = '2017-02-08 10:00:00'; + this.data.partner.records[0].document = 'myimage1'; + this.data.partner.records[0].picture = 'myimage2'; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + ' ' + + ' ' + + '', + res_id: 1, + mockRPC: function (route, args) { + if (route.startsWith('data:image/png;base64,myimage')) { + return Promise.resolve('wow'); + } + return this._super.apply(this, arguments); + }, + }); + + assert.containsOnce(form, 'div[name="document"] > img', "the widget should contain an image"); + assert.hasAttrValue(form.$('div[name="document"] > img'), 'width', "180", + "the image should correctly set its attributes"); + const image1Style = form.$('div[name="document"] > img').attr('style'); + assert.ok(['max-width: 180px', 'height: auto', 'max-height: 100%'].every(e => image1Style.includes(e)), + "the image should correctly set its style"); + + assert.containsOnce(form, 'div[name="picture"] > img', "the widget should contain an image"); + assert.hasAttrValue(form.$('div[name="picture"] > img'), 'height', "270", + "the image should correctly set its attributes"); + const image2Style = form.$('div[name="picture"] > img').attr('style'); + assert.ok(['max-height: 270px', 'width: auto', 'max-width: 100%'].every(e => image2Style.includes(e)), + "the image should correctly set its style"); + + form.destroy(); + }); + QUnit.test('image fields are correctly replaced when given an incorrect value', async function (assert) { assert.expect(7); @@ -2976,6 +3018,39 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('image fields are correctly rendered with one dimension set', async function (assert) { + assert.expect(6); + + this.data.partner.fields.tortue = {string: "Tortue", type: "char", default: "a"}; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + ' ' + + ' ' + + '', + res_id: 6, + }); + + assert.containsOnce(form, 'div[name="foo"] > img', "the widget should contain an image"); + assert.hasAttrValue(form.$('div[name="foo"] > img'), 'width', "180", + "the image should correctly set its attributes"); + const image1Style = form.$('div[name="foo"] > img').attr('style'); + assert.ok(['max-width: 180px', 'height: auto', 'max-height: 100%'].every(e => image1Style.includes(e)), + "the image should correctly set its style"); + + assert.containsOnce(form, 'div[name="tortue"] > img', "the widget should contain an image"); + assert.hasAttrValue(form.$('div[name="tortue"] > img'), 'height', "270", + "the image should correctly set its attributes"); + const image2Style = form.$('div[name="tortue"] > img').attr('style'); + assert.ok(['max-height: 270px', 'width: auto', 'max-width: 100%'].every(e => image2Style.includes(e)), + "the image should correctly set its style"); + + form.destroy(); + }); + QUnit.test('image_url widget in subviews are loaded correctly', async function (assert) { assert.expect(6);