Odoo commit 每日一读/10-a9a189

今天我们来谈谈a9a189这个commit。这个提交是对product.py中的select_seller函数的改进。

为什么要提交这个commit

product的select_seller()函数中的date获取方式由于时区的 差异会存在日期的延迟。需求质量在计量单位不一致下进行转换后产生的浮点数近似值会影响判断。

改进方法

  • 对于日期:date的获取方式通过context_today()方法来获取对应时区的日期 (field.py中的函数)

    @staticmethod
    def context_today(record, timestamp=None):
    today = timestamp or datetime.now()
    context_today = None
    # 获取odoo中的时区
    tz_name = record._context.get('tz') or record.env.user.tz
    if tz_name:
        try:
            today_utc = pytz.timezone('UTC').localize(today, is_dst=False)  # UTC = no DST
            context_today = today_utc.astimezone(pytz.timezone(tz_name))
        except Exception:
            _logger.debug("failed to compute context/client-specific today date, using UTC value for `today`",
                          exc_info=True)
    return (context_today or today).strftime(DATE_FORMAT)
  • 对于计量单位转换:首先获取计量标准的精度, 再通过float_compare方法对计量标准转换后的数值进行更为精确的比较。(float_utils.py中的函数)

    def float_compare(value1, value2, precision_digits=None, precision_rounding=None):
    rounding_factor = _float_check_precision(precision_digits=precision_digits,
                                             precision_rounding=precision_rounding)
    value1 = float_round(value1, precision_rounding=rounding_factor)
    value2 = float_round(value2, precision_rounding=rounding_factor)
    delta = value1 - value2
    if float_is_zero(delta, precision_rounding=rounding_factor): return 0
    return -1 if delta < 0.0 else 1

    本次提交中,使用了odoo中本身已有的contaxt_todayfloat_compare方法对selector_seller中的逻辑判断数值进行了更为精确的获取.

原始提交信息

commit a9a1895b31e2b9c269a422c13f2bca0e97e90234
Author:     Graeme Gellatly <[email protected]>
AuthorDate: Wed Dec 6 15:12:51 2017 +0100
Commit:     Martin Trigaux <[email protected]>
CommitDate: Wed Dec 6 15:54:24 2017 +0100

    [FIX] product: correct seller selection

    Choose the date in the user's tz
    Compare the quantities using float_compare to avoid rounding issues during UoM
    conversions

    Closes #21359
---
 addons/product/models/product.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/addons/product/models/product.py b/addons/product/models/product.py
index 62347b4cd06..5ac510b84ff 100644
--- a/addons/product/models/product.py
+++ b/addons/product/models/product.py
@@ -9,7 +9,7 @@ from odoo.osv import expression

 from odoo.addons import decimal_precision as dp

-from odoo.tools import pycompat
+from odoo.tools import float_compare, pycompat


 class ProductCategory(models.Model):
@@ -468,7 +468,9 @@ class ProductProduct(models.Model):
     def _select_seller(self, partner_id=False, quantity=0.0, date=None, uom_id=False):
         self.ensure_one()
         if date is None:
-            date = fields.Date.today()
+            date = fields.Date.context_today(self)
+        precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
+
         res = self.env['product.supplierinfo']
         for seller in self.seller_ids:
             # Set quantity in UoM of seller
@@ -482,7 +484,7 @@ class ProductProduct(models.Model):
                 continue
             if partner_id and seller.name not in [partner_id, partner_id.parent_id]:
                 continue
-            if quantity_uom_seller < seller.min_qty:
+            if float_compare(quantity_uom_seller, seller.min_qty, precision_digits=precision) == -1:
                 continue
             if seller.product_id and seller.product_id != self:
                 continue