Merge branch 'master-upstream-patch-14122022' into 'master'

[PATCH] Upstream patch - 14122022

See merge request flectra-hq/flectra!876
This commit is contained in:
Parthiv Patel
2022-12-14 09:48:34 +00:00
5 changed files with 117 additions and 31 deletions
+42 -18
View File
@@ -2,6 +2,7 @@
# Part of Odoo, Flectra. See LICENSE file for full copyright and licensing details.
import json
from collections import defaultdict
from flectra import models, fields, api, _
from flectra.exceptions import UserError
@@ -13,21 +14,31 @@ class StockQuantPackage(models.Model):
@api.depends('quant_ids')
def _compute_weight(self):
if self.env.context.get('picking_id'):
package_weights = defaultdict(float)
# Ordering by qty_done prevents the default ordering by groupby fields that can inject multiple Left Joins in the resulting query.
res_groups = self.env['stock.move.line'].read_group(
[('result_package_id', 'in', self.ids), ('product_id', '!=', False), ('picking_id', '=', self.env.context['picking_id'])],
['id:count'],
['result_package_id', 'product_id', 'product_uom_id', 'qty_done'],
lazy=False, orderby='qty_done asc'
)
for res_group in res_groups:
product_id = self.env['product.product'].browse(res_group['product_id'][0])
product_uom_id = self.env['uom.uom'].browse(res_group['product_uom_id'][0])
package_weights[res_group['result_package_id'][0]] += (
res_group['__count']
* product_uom_id._compute_quantity(res_group['qty_done'], product_id.uom_id)
* product_id.weight
)
for package in self:
weight = 0.0
if self.env.context.get('picking_id'):
# TODO: potential bottleneck: N packages = N queries, use groupby ?
current_picking_move_line_ids = self.env['stock.move.line'].search([
('result_package_id', '=', package.id),
('picking_id', '=', self.env.context['picking_id'])
])
for ml in current_picking_move_line_ids:
weight += ml.product_uom_id._compute_quantity(
ml.qty_done, ml.product_id.uom_id) * ml.product_id.weight
package.weight = package_weights[package.id]
else:
weight = 0.0
for quant in package.quant_ids:
weight += quant.quantity * quant.product_id.weight
package.weight = weight
package.weight = weight
def _get_default_weight_uom(self):
return self.env['product.template']._get_weight_uom_name_from_ir_config_parameter()
@@ -49,19 +60,32 @@ class StockPicking(models.Model):
def _compute_packages(self):
for package in self:
packs = set()
for move_line in package.move_line_ids:
if move_line.result_package_id:
packs.add(move_line.result_package_id.id)
if self.env['stock.move.line'].search_count([('picking_id', '=', package.id), ('result_package_id', '!=', False)]):
for move_line in package.move_line_ids:
if move_line.result_package_id:
packs.add(move_line.result_package_id.id)
package.package_ids = list(packs)
@api.depends('move_line_ids', 'move_line_ids.result_package_id', 'move_line_ids.product_uom_id', 'move_line_ids.qty_done')
def _compute_bulk_weight(self):
picking_weights = defaultdict(float)
# Ordering by qty_done prevents the default ordering by groupby fields that can inject multiple Left Joins in the resulting query.
res_groups = self.env['stock.move.line'].read_group(
[('picking_id', 'in', self.ids), ('product_id', '!=', False), ('result_package_id', '=', False)],
['id:count'],
['picking_id', 'product_id', 'product_uom_id', 'qty_done'],
lazy=False, orderby='qty_done asc'
)
for res_group in res_groups:
product_id = self.env['product.product'].browse(res_group['product_id'][0])
product_uom_id = self.env['uom.uom'].browse(res_group['product_uom_id'][0])
picking_weights[res_group['picking_id'][0]] += (
res_group['__count']
* product_uom_id._compute_quantity(res_group['qty_done'], product_id.uom_id)
* product_id.weight
)
for picking in self:
weight = 0.0
for move_line in picking.move_line_ids:
if move_line.product_id and not move_line.result_package_id:
weight += move_line.product_uom_id._compute_quantity(move_line.qty_done, move_line.product_id.uom_id) * move_line.product_id.weight
picking.weight_bulk = weight
picking.weight_bulk = picking_weights[picking.id]
@api.depends('move_line_ids.result_package_id', 'move_line_ids.result_package_id.shipping_weight', 'weight_bulk')
def _compute_shipping_weight(self):
+1 -1
View File
@@ -110,7 +110,7 @@ class PaymentAcquirer(models.Model):
help="Capture the amount from Flectra, when the delivery is completed.")
journal_id = fields.Many2one(
'account.journal', 'Payment Journal', domain="[('type', 'in', ['bank', 'cash']), ('company_id', '=', company_id)]",
help="""Journal where the successful transactions will be posted""")
help="""Journal where the successful transactions will be posted""", ondelete='restrict')
check_validity = fields.Boolean(string="Verify Card Validity",
help="""Trigger a transaction of 1 currency unit and its refund to check the validity of new credit cards entered in the customer portal.
Without this check, the validity will be verified at the very first transaction.""")
@@ -8,8 +8,6 @@ from calendar import monthrange
from dateutil.relativedelta import relativedelta
from dateutil.rrule import rrule, rruleset, DAILY, WEEKLY, MONTHLY, YEARLY, MO, TU, WE, TH, FR, SA, SU
import math
MONTHS = {
'january': 31,
'february': 28,
@@ -140,8 +138,9 @@ class ProjectTaskRecurrence(models.Model):
@api.constrains('repeat_unit', 'repeat_on_month', 'repeat_day', 'repeat_type', 'repeat_until')
def _check_repeat_until_month(self):
if self.filtered(lambda r: r.repeat_type == 'until' and r.repeat_unit == 'month' and r.repeat_until and r.repeat_on_month == 'date' and int(r.repeat_day) > r.repeat_until.day):
raise ValidationError('The end date should be after the day of the month')
if self.filtered(lambda r: r.repeat_type == 'until' and r.repeat_unit == 'month' and r.repeat_until and r.repeat_on_month == 'date'
and int(r.repeat_day) > r.repeat_until.day and monthrange(r.repeat_until.year, r.repeat_until.month)[1] != r.repeat_until.day):
raise ValidationError('The end date should be after the day of the month or the last day of the month')
@api.model
def _get_recurring_fields(self):
@@ -179,16 +178,16 @@ class ProjectTaskRecurrence(models.Model):
rrule_kwargs['freq'] = MONTHLY
if repeat_on_month == 'date':
start = date_start - relativedelta(days=1)
if repeat_type == 'until' and repeat_until > date_start:
delta = relativedelta(repeat_until, date_start)
count = math.floor((delta.years * 12 + delta.months) / repeat_interval)
for i in range(count):
start = start.replace(day=min(repeat_day, monthrange(start.year, start.month)[1]))
if start < date_start:
# Ensure the next recurrence is in the future
start += relativedelta(months=repeat_interval)
start = start.replace(day=min(repeat_day, monthrange(start.year, start.month)[1]))
if i == 0 and start < date_start:
# Ensure the next recurrence is in the future
start += relativedelta(months=repeat_interval)
can_generate_date = (lambda: start <= repeat_until) if repeat_type == 'until' else (lambda: len(dates) < count)
while can_generate_date():
dates.append(start)
start += relativedelta(months=repeat_interval)
start = start.replace(day=min(repeat_day, monthrange(start.year, start.month)[1]))
return dates
elif repeat_unit == 'year':
rrule_kwargs['freq'] = YEARLY
@@ -455,6 +455,69 @@ class TestProjectrecurrence(SavepointCase):
self.assertEqual(dates[0], datetime(2020, 7, 3))
self.assertEqual(dates[1], datetime(2021, 1, 3))
# Should generate a date at the last day of the current month
dates = self.env['project.task.recurrence']._get_next_recurring_dates(
date_start=date(2022, 2, 26),
repeat_interval=1,
repeat_unit='month',
repeat_type='until',
repeat_until=date(2022, 2, 28),
repeat_on_month='date',
repeat_on_year=False,
weekdays=False,
repeat_day=31,
repeat_week=False,
repeat_month=False,
count=5)
self.assertEqual(len(dates), 1)
self.assertEqual(dates[0], date(2022, 2, 28))
dates = self.env['project.task.recurrence']._get_next_recurring_dates(
date_start=date(2022, 11, 26),
repeat_interval=3,
repeat_unit='month',
repeat_type='until',
repeat_until=date(2024, 2, 29),
repeat_on_month='date',
repeat_on_year=False,
weekdays=False,
repeat_day=25,
repeat_week=False,
repeat_month=False,
count=5)
self.assertEqual(len(dates), 5)
self.assertEqual(dates[0], date(2023, 2, 25))
self.assertEqual(dates[1], date(2023, 5, 25))
self.assertEqual(dates[2], date(2023, 8, 25))
self.assertEqual(dates[3], date(2023, 11, 25))
self.assertEqual(dates[4], date(2024, 2, 25))
# Use the exact same parameters than the previous test but with a repeat_day that is not passed yet
# So we generate an additional date in the current month
dates = self.env['project.task.recurrence']._get_next_recurring_dates(
date_start=date(2022, 11, 26),
repeat_interval=3,
repeat_unit='month',
repeat_type='until',
repeat_until=date(2024, 2, 29),
repeat_on_month='date',
repeat_on_year=False,
weekdays=False,
repeat_day=31,
repeat_week=False,
repeat_month=False,
count=5)
self.assertEqual(len(dates), 6)
self.assertEqual(dates[0], date(2022, 11, 30))
self.assertEqual(dates[1], date(2023, 2, 28))
self.assertEqual(dates[2], date(2023, 5, 31))
self.assertEqual(dates[3], date(2023, 8, 31))
self.assertEqual(dates[4], date(2023, 11, 30))
self.assertEqual(dates[5], date(2024, 2, 29))
def test_recurrence_next_dates_year(self):
dates = self.env['project.task.recurrence']._get_next_recurring_dates(
date_start=date(2020, 12, 1),
+1 -1
View File
@@ -184,7 +184,7 @@ class MrpStockReport(models.TransientModel):
lines = self._get_move_lines(move_line, line_id=line_id)
for line in lines:
unfoldable = False
if line.consume_line_ids or ( line.lot_id and self._get_move_lines(line) and model != "stock.production.lot"):
if line.consume_line_ids or (model != "stock.production.lot" and line.lot_id and self._get_move_lines(line)):
unfoldable = True
final_vals += self._make_dict_move(level, parent_id=line_id, move_line=line, unfoldable=unfoldable)
return final_vals