[PATCH] Upstream patch - 08112022

This commit is contained in:
Parthiv Patel committed 2022-11-08 08:35:07 +00:00
1 parent a610488738
commit 83f1d94de1
19 files changed
+119 -25

No files matched your search

+11 -3
View File
@@ -293,7 +293,7 @@ class AccountMove(models.Model):
invoice_incoterm_id = fields.Many2one('account.incoterms', string='Incoterm',
default=_get_default_invoice_incoterm,
help='International Commercial Terms are a series of predefined commercial terms used in international transactions.')
display_qr_code = fields.Boolean(string="Display QR-code", related='company_id.qr_code')
display_qr_code = fields.Boolean(string="Display QR-code", compute='_compute_display_qr_code')
qr_code_method = fields.Selection(string="Payment QR-code", copy=False,
selection=lambda self: self.env['res.partner.bank'].get_available_qr_methods_in_sequence(),
help="Type of QR-code to be generated for the payment of this invoice, when printing it. If left blank, the first available and usable method will be used.")
@@ -2999,6 +2999,14 @@ class AccountMove(models.Model):
for move in self:
move.has_reconciled_entries = len(move.line_ids._reconciled_lines()) > 1
@api.depends('company_id')
def _compute_display_qr_code(self):
for record in self:
record.display_qr_code = (
record.move_type in ('out_invoice', 'out_receipt')
and record.company_id.qr_code
)
def action_view_reverse_entry(self):
self.ensure_one()
@@ -3074,8 +3082,8 @@ class AccountMove(models.Model):
"""
self.ensure_one()
if not self.is_invoice():
raise UserError(_("QR-codes can only be generated for invoice entries."))
if not self.display_qr_code:
return None
qr_code_method = self.qr_code_method
if qr_code_method:
+1 -1
View File
@@ -996,7 +996,7 @@
sum="Total Credit"
attrs="{'invisible': [('display_type', 'in', ('line_section', 'line_note'))]}"/>
<field name="tax_fiscal_country_id" invisible="1"/>
<field name="tax_tag_ids" widget="many2many_tags" string="Tax Grids" optional="show" domain="[('country_id', '=', tax_fiscal_country_id), ('applicability', '=', 'taxes')]"/>
<field name="tax_tag_ids" widget="many2many_tags" string="Tax Grids" optional="show" domain="[('country_id', '=', tax_fiscal_country_id), ('applicability', '=', 'taxes')]" options="{'no_create': True}"/>
<!-- Buttons -->
<button name="action_automatic_entry"
@@ -393,7 +393,7 @@ class AccountPaymentRegister(models.TransientModel):
wizard.amount = wizard.source_amount
else:
# Foreign currency on payment different than the one set on the journal entries.
amount_payment_currency = wizard.company_id.currency_id._convert(wizard.source_amount, wizard.currency_id, wizard.company_id, wizard.payment_date)
amount_payment_currency = wizard.company_id.currency_id._convert(wizard.source_amount, wizard.currency_id, wizard.company_id, wizard.payment_date or fields.Date.today())
wizard.amount = amount_payment_currency
@api.depends('amount')
@@ -407,7 +407,7 @@ class AccountPaymentRegister(models.TransientModel):
wizard.payment_difference = wizard.source_amount - wizard.amount
else:
# Foreign currency on payment different than the one set on the journal entries.
amount_payment_currency = wizard.company_id.currency_id._convert(wizard.source_amount, wizard.currency_id, wizard.company_id, wizard.payment_date)
amount_payment_currency = wizard.company_id.currency_id._convert(wizard.source_amount, wizard.currency_id, wizard.company_id, wizard.payment_date or fields.Date.today())
wizard.payment_difference = amount_payment_currency - wizard.amount
# -------------------------------------------------------------------------
+1
View File
@@ -60,6 +60,7 @@ _ref_vat = {
'nl': 'NL123456782B90',
'no': 'NO123456785',
'pe': '10XXXXXXXXY or 20XXXXXXXXY or 15XXXXXXXXY or 16XXXXXXXXY or 17XXXXXXXXY',
'ph': '123-456-789-01234',
'pl': 'PL1234567883',
'pt': 'PT123456789',
'ro': 'RO1234567897',
+1
View File
@@ -474,6 +474,7 @@ class Meeting(models.Model):
for attendee in meeting.attendee_ids:
attendee_add = event.add('attendee')
attendee_add.value = u'MAILTO:' + (attendee.email or u'')
event.add('organizer').value = u'MAILTO:' + (meeting.user_id.email or u'')
result[meeting.id] = cal.serialize().encode('utf-8')
return result
+1 -1
View File
@@ -4,7 +4,7 @@
<record id="sms_template_data_calendar_reminder" model="sms.template">
<field name="name">Calendar Event: Reminder</field>
<field name="model_id" ref="calendar.model_calendar_event"/>
<field name="body">Event reminder: ${object.name}, ${object.display_time}</field>
<field name="body">Event reminder: ${object.name}, ${object.get_display_time_tz(object.partner_id.tz)}</field>
</record>
</data>
</flectra>
@@ -166,7 +166,7 @@
<ImponibileImporto t-esc="format_monetary(tax_dict['base_amount'] if currency.name == 'EUR' else tax_dict['base_amount_currency'], currency)"/>
<Imposta t-esc="format_monetary(tax_dict['tax_amount'] if currency.name == 'EUR' else tax_dict['base_amount_currency'], currency)"/>
<EsigibilitaIVA t-if="not has_exoneration or kind_exoneration == 'N6'" t-esc="tax.l10n_it_vat_due_date"/>
<RiferimentoNormativo t-if="has_exoneration" t-esc="format_alphanumeric(tax.l10n_it_law_reference[:100])"/>
<RiferimentoNormativo t-if="tax.l10n_it_law_reference" t-esc="format_alphanumeric(tax.l10n_it_law_reference[:100])"/>
</DatiRiepilogo>
</t>
</DatiBeniServizi>
+1 -1
View File
@@ -26,7 +26,7 @@
<field name="l10n_it_vat_due_date"/>
<field name="l10n_it_has_exoneration" readonly="False"/>
<field name="l10n_it_kind_exoneration" attrs="{'invisible': [('l10n_it_has_exoneration', '=', False)]}"/>
<field name="l10n_it_law_reference" attrs="{'invisible': [('l10n_it_has_exoneration', '=', False)]}"/>
<field name="l10n_it_law_reference"/>
</group>
</xpath>
</data>
@@ -20,7 +20,7 @@
<Anagrafica>
<Denominazione>Alessi</Denominazione>
</Anagrafica>
<RegimeFiscale>RF01</RegimeFiscale>
<RegimeFiscale>RF18</RegimeFiscale>
</DatiAnagrafici>
<Sede>
<Indirizzo>Avenue Test rue </Indirizzo>
+1 -1
View File
@@ -435,7 +435,7 @@ class StockMove(models.Model):
def _update_quantity_done(self, mo):
self.ensure_one()
new_qty = mo.product_uom_id._compute_quantity((mo.qty_producing - mo.qty_produced) * self.unit_factor, mo.product_uom_id, rounding_method='HALF-UP')
new_qty = float_round((mo.qty_producing - mo.qty_produced) * self.unit_factor, precision_rounding=self.product_uom.rounding)
if not self.is_quantity_done_editable:
self.move_line_ids.filtered(lambda ml: ml.state not in ('done', 'cancel')).qty_done = 0
self.move_line_ids = self._set_quantity_done_prepare_vals(new_qty)
+24
View File
@@ -2395,3 +2395,27 @@ class TestMrpOrder(TestMrpCommon):
('raw_material_production_id', '=', mo_backorder.id)])
self.assertEqual(sum(move_prod_1_bo.mapped('product_uom_qty')), 60.0)
self.assertEqual(sum(move_prod_2_bo.mapped('product_uom_qty')), 40.0)
def test_update_qty_to_consume_of_component(self):
"""
The UoM of the finished product has a rounding precision equal to 1.0
and the UoM of the component has a decimal one. When the producing qty
is set, an onchange autocomplete the consumed quantity of the component.
Then, when updating the 'to consume' quantity of the components, their
consumed quantity is updated again. The test ensures that this update
respects the rounding precisions
"""
self.uom_dozen.rounding = 1
self.bom_4.product_uom_id = self.uom_dozen
mo_form = Form(self.env['mrp.production'])
mo_form.bom_id = self.bom_4
mo = mo_form.save()
mo.action_confirm()
with Form(mo) as mo_form:
mo_form.qty_producing = 1
with mo_form.move_raw_ids.edit(0) as raw:
raw.product_uom_qty = 1.25
self.assertEqual(mo.move_raw_ids.quantity_done, 1.25)
+4
View File
@@ -393,6 +393,10 @@ class SaleOrder(models.Model):
def update_line(order, lines, values):
'''Update the lines and return them if they should be deleted'''
lines_to_remove = self.env['sale.order.line']
# move global coupons to the end of the SO
if program.discount_apply_on == 'on_order':
values['sequence'] = max(order.order_line.mapped('sequence')) + 1
# Check commit 6bb42904a03 for next if/else
# Remove reward line if price or qty equal to 0
if values['product_uom_qty'] and values['price_unit']:
@@ -52,3 +52,38 @@ class TestSaleInvoicing(TestSaleCouponCommon):
self.assertEqual(order.order_line, invoiceable_lines)
account_move = order._create_invoices()
self.assertEqual(len(account_move.invoice_line_ids), 2)
def test_coupon_on_order_sequence(self):
# discount_coupon_program
self.env['coupon.program'].create({
'name': '10% Discount', # Default behavior
'program_type': 'coupon_program',
'reward_type': 'discount',
'discount_apply_on': 'on_order',
'promo_code_usage': 'no_code_needed',
})
order = self.empty_order
# orderline1
self.env['sale.order.line'].create({
'product_id': self.env.ref('product.product_product_6').id,
'name': 'largeCabinet',
'product_uom_qty': 1.0,
'order_id': order.id,
})
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line), 2, 'Coupon correctly applied')
# orderline2
self.env['sale.order.line'].create({
'product_id': self.env.ref('product.product_product_11').id,
'name': 'conferenceChair',
'product_uom_qty': 1.0,
'order_id': order.id,
})
order.recompute_coupon_lines()
self.assertEqual(len(order.order_line), 3, 'Coupon correctly applied')
self.assertTrue(order.order_line.sorted(lambda x: x.sequence)[-1].is_reward_line, 'Global coupons appear on the last line')
+6 -3
View File
@@ -13,7 +13,7 @@ from reportlab.pdfgen.canvas import Canvas
from flectra import fields, models, api, _
from flectra.addons.iap.tools import iap_tools
from flectra.exceptions import AccessError
from flectra.exceptions import AccessError, UserError
from flectra.tools.safe_eval import safe_eval
DEFAULT_ENDPOINT = 'https://iap-snailmail.flectrahq.com'
@@ -140,7 +140,10 @@ class SnailmailLetter(models.Model):
else:
report_name = 'Document'
filename = "%s.%s" % (report_name, "pdf")
pdf_bin, _ = report.with_context(snailmail_layout=not self.cover)._render_qweb_pdf(self.res_id)
paperformat = report.get_paperformat()
if (paperformat.format == 'custom' and paperformat.page_width != 210 and paperformat.page_height != 297) or paperformat.format != 'A4':
raise UserError(_("Please use an A4 Paper format."))
pdf_bin, unused_filetype = report.with_context(snailmail_layout=not self.cover, lang='en_US').render_qweb_pdf(self.res_id)
if self.cover:
pdf_bin = self._append_cover_page(pdf_bin)
attachment = self.env['ir.attachment'].create({
@@ -426,7 +429,7 @@ class SnailmailLetter(models.Model):
return all(record[key] for key in required_keys)
def _append_cover_page(self, invoice_bin: bytes):
address = self.partner_id.with_context(show_address=True)._get_name().replace('\n', '<br/>')
address = self.partner_id.with_context(show_address=True, lang='en_US')._get_name().replace('\n', '<br/>')
address_x = 118 * mm
address_y = 60 * mm
frame_width = 85.5 * mm
+2 -2
View File
@@ -272,11 +272,11 @@ class StockMove(models.Model):
for svl in stock_valuation_layers:
if not svl.product_id.valuation == 'real_time':
if not svl.with_company(svl.company_id).product_id.valuation == 'real_time':
continue
if svl.currency_id.is_zero(svl.value):
continue
svl.stock_move_id._account_entry_move(svl.quantity, svl.description, svl.id, svl.value)
svl.stock_move_id.with_company(svl.company_id)._account_entry_move(svl.quantity, svl.description, svl.id, svl.value)
stock_valuation_layers._check_company()
+16 -5
View File
@@ -97,11 +97,22 @@ function _genericJsonRpc (fct_name, params, settings, fct) {
});
// FIXME: jsonp?
promise.abort = function () {
rejection({
message: "XmlHttpRequestError abort",
event: $.Event('abort')
});
/**
* @param {Boolean} rejectError Returns an error if true. Allows you to cancel
* ignored rpc's in order to unblock the ui and not display an error.
*/
promise.abort = function (rejectError = true) {
if (rejectError) {
rejection({
message: "XmlHttpRequestError abort",
event: $.Event('abort')
});
}
if (!shadow) {
core.bus.trigger('rpc_response');
}
if (xhr.abort) {
xhr.abort();
}
@@ -576,7 +576,10 @@ var FieldMany2One = AbstractField.extend({
domain.push(['id', 'not in', blackListedIds]);
}
const nameSearch = this._rpc({
if (this.lastNameSearch) {
this.lastNameSearch.abort(false)
}
this.lastNameSearch = this._rpc({
model: this.field.relation,
method: "name_search",
kwargs: {
@@ -587,7 +590,7 @@ var FieldMany2One = AbstractField.extend({
context,
}
});
const results = await this.orderer.add(nameSearch);
const results = await this.orderer.add(this.lastNameSearch);
// Format results to fit the options dropdown
let values = results.map((result) => {
@@ -51,6 +51,8 @@
}
}
.calendar-time {
/*rtl:ignore*/
direction:ltr;
select {
&.hourselect, &.minuteselect, &.secondselect, &.ampmselect {
display: initial;
@@ -151,8 +151,10 @@ var MockServer = Class.extend({
if (abort) {
abort = abort.bind(def);
} else {
abort = function () {
throw new Error("Can't abort this request");
abort = function (rejectError = true) {
if (rejectError) {
throw new ConnectionAbortedError("XmlHttpRequestError abort");
}
};
}