[PATCH] Upstream patch - 19032023

This commit is contained in:
Parthiv Patel committed 2023-03-19 08:34:17 +00:00
1 parent 63dca856d9
commit 90effe3bad
9 files changed
+183 -13

No files matched your search

@@ -610,18 +610,37 @@ class AccountReconcileModel(models.Model):
"""
self.ensure_one()
# On big databases, it is possible that some setups will create huge queries when trying to apply reconciliation models.
# In such cases, this query might take a very long time to run, essentially eating up all the available CPU, and proof
# impossible to kill, because of the type of operations ran by SQL. To alleviate that, we introduce the config parameter below,
# which essentially allows cutting the list of statement lines to match into slices, and running the matching in multiple queries.
# This way, we avoid server overload, giving the ability to kill the process if takes too long.
slice_size = len(st_lines_with_partner)
slice_size_param = self.env['ir.config_parameter'].sudo().get_param('account.reconcile_model_forced_slice_size')
if slice_size_param:
converted_param = int(slice_size_param)
if converted_param > 0:
slice_size = converted_param
treatment_slices = []
slice_start = 0
while slice_start < len(st_lines_with_partner):
slice_end = slice_start + slice_size
treatment_slices.append(st_lines_with_partner[slice_start:slice_end])
slice_start = slice_end
treatment_map = {
'invoice_matching': lambda x: x._get_invoice_matching_query(st_lines_with_partner, excluded_ids),
'writeoff_suggestion': lambda x: x._get_writeoff_suggestion_query(st_lines_with_partner, excluded_ids),
'invoice_matching': lambda rec_model, slice: rec_model._get_invoice_matching_query(slice, excluded_ids),
'writeoff_suggestion': lambda rec_model, slice: rec_model._get_writeoff_suggestion_query(slice, excluded_ids),
}
query_generator = treatment_map[self.rule_type]
query, params = query_generator(self)
self._cr.execute(query, params)
rslt = defaultdict(lambda: [])
for candidate_dict in self._cr.dictfetchall():
rslt[candidate_dict['id']].append(candidate_dict)
for treatment_slice in treatment_slices:
query_generator = treatment_map[self.rule_type]
query, params = query_generator(self, treatment_slice)
self._cr.execute(query, params)
for candidate_dict in self._cr.dictfetchall():
rslt[candidate_dict['id']].append(candidate_dict)
return rslt
+6 -2
View File
@@ -578,7 +578,9 @@ class MrpProduction(models.Model):
if not self.product_id:
self.bom_id = False
elif not self.bom_id or self.bom_id.product_tmpl_id != self.product_tmpl_id or (self.bom_id.product_id and self.bom_id.product_id != self.product_id):
bom = self.env['mrp.bom']._bom_find(product=self.product_id, picking_type=self.picking_type_id, company_id=self.company_id.id, bom_type='normal')
picking_type_id = self._context.get('default_picking_type_id')
picking_type = picking_type_id and self.env['stock.picking.type'].browse(picking_type_id)
bom = self.env['mrp.bom']._bom_find(product=self.product_id, picking_type=picking_type, company_id=self.company_id.id, bom_type='normal')
if bom:
self.bom_id = bom.id
self.product_qty = self.bom_id.product_qty
@@ -606,7 +608,9 @@ class MrpProduction(models.Model):
self.product_uom_id = self.bom_id and self.bom_id.product_uom_id.id or self.product_id.uom_id.id
self.move_raw_ids = [(2, move.id) for move in self.move_raw_ids.filtered(lambda m: m.bom_line_id)]
self.move_finished_ids = [(2, move.id) for move in self.move_finished_ids]
self.picking_type_id = self.bom_id.picking_type_id or self.picking_type_id
picking_type_id = self._context.get('default_picking_type_id')
picking_type = picking_type_id and self.env['stock.picking.type'].browse(picking_type_id)
self.picking_type_id = picking_type or self.bom_id.picking_type_id or self.picking_type_id
@api.onchange('date_planned_start', 'product_id')
def _onchange_date_planned_start(self):
+62
View File
@@ -2506,3 +2506,65 @@ class TestMrpOrder(TestMrpCommon):
raw.product_uom_qty = 1.25
self.assertEqual(mo.move_raw_ids.quantity_done, 1.25)
def test_onchange_bom_ids_and_picking_type(self):
warehouse01 = self.env['stock.warehouse'].search([('company_id', '=', self.env.company.id)], limit=1)
warehouse02, warehouse03 = self.env['stock.warehouse'].create([
{'name': 'Second Warehouse', 'code': 'WH02'},
{'name': 'Third Warehouse', 'code': 'WH03'},
])
finished_product = self.env['product.product'].create({'name': 'finished product'})
bom_wh01, bom_wh02 = self.env['mrp.bom'].create([{
'product_id': finished_product.id,
'product_tmpl_id': finished_product.product_tmpl_id.id,
'product_uom_id': self.uom_unit.id,
'product_qty': 1.0,
'bom_line_ids': [(0, 0, {'product_id': self.product_0.id, 'product_qty': 1})],
'picking_type_id': wh.manu_type_id.id,
'sequence': wh.id,
} for wh in [warehouse01, warehouse02]])
# Prioritize BoM of WH02
bom_wh01.sequence = bom_wh02.sequence + 1
mo_form = Form(self.env['mrp.production'])
mo_form.product_id = finished_product
self.assertEqual(mo_form.bom_id, bom_wh02, 'Should select the first BoM in the list, whatever the picking type is')
self.assertEqual(mo_form.picking_type_id, warehouse02.manu_type_id)
mo_form.bom_id = bom_wh01
self.assertEqual(mo_form.picking_type_id, warehouse01.manu_type_id, 'Should be adapted because of the found BoM')
mo_form.bom_id = bom_wh02
self.assertEqual(mo_form.picking_type_id, warehouse02.manu_type_id, 'Should be adapted because of the found BoM')
mo_form.picking_type_id = warehouse01.manu_type_id
self.assertEqual(mo_form.bom_id, bom_wh02, 'Should not change')
self.assertEqual(mo_form.picking_type_id, warehouse01.manu_type_id, 'Should not change')
mo_form.picking_type_id = warehouse03.manu_type_id
mo_form.bom_id = bom_wh01
self.assertEqual(mo_form.picking_type_id, warehouse01.manu_type_id, 'Should be adapted because of the found BoM '
'(the selected picking type should be ignored)')
mo_form = Form(self.env['mrp.production'].with_context(default_picking_type_id=warehouse03.manu_type_id.id))
mo_form.product_id = finished_product
self.assertFalse(mo_form.bom_id, 'Should not find any BoM, because of the defined picking type')
self.assertEqual(mo_form.picking_type_id, warehouse03.manu_type_id)
mo_form = Form(self.env['mrp.production'].with_context(default_picking_type_id=warehouse01.manu_type_id.id))
mo_form.product_id = finished_product
self.assertEqual(mo_form.bom_id, bom_wh01, 'Should select the BoM that matches the default picking type')
self.assertEqual(mo_form.picking_type_id, warehouse01.manu_type_id, 'Should be the default one')
mo_form.bom_id = bom_wh02
self.assertEqual(mo_form.picking_type_id, warehouse01.manu_type_id, 'Should not change, because of default value')
mo_form.picking_type_id = warehouse02.manu_type_id
self.assertEqual(mo_form.bom_id, bom_wh02, 'Should not change')
self.assertEqual(mo_form.picking_type_id, warehouse02.manu_type_id, 'Should not change')
mo_form.picking_type_id = warehouse02.manu_type_id
mo_form.bom_id = bom_wh02
self.assertEqual(mo_form.picking_type_id, warehouse01.manu_type_id, 'Should be adapted because of the default value')
@@ -1082,6 +1082,36 @@ class TestSaleStock(TestSaleCommon, ValuationReconciliationTestCommon):
self.assertEqual(so.order_line[1].qty_delivered, 1)
self.assertEqual(so.order_line[1].product_uom.id, uom_km_id)
def test_multiple_returns(self):
# Creates a sale order for 10 products.
sale_order = self._get_new_sale_order()
# Valids the sale order, then valids the delivery.
sale_order.action_confirm()
picking = sale_order.picking_ids
picking.move_lines.write({'quantity_done': 10})
picking.button_validate()
# Creates a return from the delivery picking.
return_picking_form = Form(self.env['stock.return.picking']
.with_context(active_ids=picking.ids, active_id=picking.id,
active_model='stock.picking'))
return_wizard = return_picking_form.save()
# Check that the correct quantity is set on the retrun
self.assertEqual(return_wizard.product_return_moves.quantity, 10)
return_wizard.product_return_moves.quantity = 2
# Valids the return picking.
res = return_wizard.create_returns()
return_picking = self.env['stock.picking'].browse(res['res_id'])
return_picking.move_lines.write({'quantity_done': 2})
return_picking.button_validate()
# Creates a second return from the delivery picking.
return_picking_form = Form(self.env['stock.return.picking']
.with_context(active_ids=picking.ids, active_id=picking.id,
active_model='stock.picking'))
return_wizard = return_picking_form.save()
# Check that the remaining quantity is set on the retrun
self.assertEqual(return_wizard.product_return_moves.quantity, 8)
class TestSaleStockOnly(SavepointCase):
+1 -1
View File
@@ -79,7 +79,7 @@ class ReturnPicking(models.TransientModel):
def _prepare_stock_return_picking_line_vals_from_move(self, stock_move):
quantity = stock_move.product_qty
for move in stock_move.move_dest_ids:
if move.origin_returned_move_id and move.origin_returned_move_id != stock_move:
if not move.origin_returned_move_id or move.origin_returned_move_id != stock_move:
continue
if move.state in ('partially_available', 'assigned'):
quantity -= sum(move.move_line_ids.mapped('product_qty'))
@@ -931,7 +931,7 @@ var SnippetEditor = Widget.extend({
ev.preventDefault();
ev.stopPropagation();
this.trigger_up('request_history_undo_record', {$target: this.$target});
this.removeSnippet();
this.trigger_up('snippet_edition_request', {exec: this.removeSnippet.bind(this)});
},
/**
* @private
@@ -0,0 +1,35 @@
flectra.define("website.tour.snippet_image_gallery", function (require) {
"use strict";
const tour = require("web_tour.tour");
const wTourUtils = require("website.tour_utils");
tour.register("snippet_image_gallery", {
test: true,
url: "/",
}, [
wTourUtils.clickOnEdit(),
wTourUtils.dragNDrop({
id: "s_image_gallery",
name: "Image Gallery",
}), {
content: "Click on the first new image",
trigger: ".o_select_media_dialog img[title='s_default_image.jpg']",
}, {
content: "Click on the second new image",
trigger: ".o_select_media_dialog img[title='s_default_image2.jpg']",
}, {
content: "Click on Add",
trigger: "button:has(span:contains('Add'))",
}, {
content: "Click on the image of the Image Gallery snippet",
trigger: ".s_image_gallery .carousel-item.active img",
}, {
content: "Click on Remove Block",
trigger: ".o_we_customize_panel we-title:has(span:contains('Image Gallery')) we-button[title='Remove Block']",
}, {
content: "Check that the Image Gallery snippet has been removed",
trigger: "#wrap:not(:has(.s_image_gallery))",
run: () => null,
}]);
});
+19
View File
@@ -3,6 +3,8 @@
import flectra
import flectra.tests
from flectra.tests.common import HOST
from flectra.tools import config
@flectra.tests.common.tagged('post_install', '-at_install', 'website_snippets')
@@ -13,3 +15,20 @@ class TestSnippets(flectra.tests.HttpCase):
def test_02_countdown_preview(self):
self.start_tour("/?enable_editor=1", "snippet_countdown", login='admin')
def test_03_snippet_image_gallery(self):
IrAttachment = self.env['ir.attachment']
base = "http://%s:%s" % (HOST, config['http_port'])
IrAttachment.create({
'public': True,
'name': 's_default_image.jpg',
'type': 'url',
'url': base + '/web/image/website.s_banner_default_image.jpg',
})
IrAttachment.create({
'public': True,
'name': 's_default_image2.jpg',
'type': 'url',
'url': base + '/web/image/website.s_banner_default_image.jpg',
})
self.start_tour("/", "snippet_image_gallery", login='admin')
+1
View File
@@ -34,6 +34,7 @@
<script type="text/javascript" src="/website/static/tests/tours/website_style_edition.js"/>
<script type="text/javascript" src="/website/static/tests/tours/snippet_empty_parent_autoremove.js"/>
<script type="text/javascript" src="/website/static/tests/tours/snippet_countdown.js"/>
<script type="text/javascript" src="/website/static/tests/tours/snippet_image_gallery.js"/>
</xpath>
</template>