跳转至内容
  • 版块
  • 标签
  • 热门
  • 用户
  • 群组
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(Flatly)
  • 不使用皮肤
折叠

Odoo 中文社区

  1. 主页
  2. 版块
  3. Odoo 开发与实施交流
  4. 关于 sale.py 中 _amount_all 几天折腾的结果

关于 sale.py 中 _amount_all 几天折腾的结果

已定时 已固定 已锁定 已移动 Odoo 开发与实施交流
5 帖子 3 发布者 3.7k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • C 离线
    C 离线
    ccdos
    写于 最后由 编辑
    #1

    在写个模块,是动态计算生成  sale_order 的 order_line  的,写好后没一时发现什么问题。

    后来又完成了 从老系统 直接导入的功能后, 就导入了一个 1000 多行的订单 进行测试,

    结果发现有严重的性能问题,计算过程长达几小时。

    查了很久,一步步跟踪后,发现时间耗在
    sale.py 中 _amount_all 中。

    这是 amount_untaxed,amount_tax,amount_total 三个 function 字段的 计算函数。

    原因是这样的。
    我是逐行生成 sale.order.line 的,

     order_lines_id = order_lines_obj.create(cr, uid, order_lines_values, context=context)
    



    OE 会在你每create 一行的时候,就调用 _amount_all,进行计算,这函数还要计算 税 等等 东西,耗时挺长,且随着  sale.order.line 行数的增多,性能急剧下降。这样 几个 循环一套, 造成了 计算几小时也不能完成的结果。


    显然,理想的方式 是 当 create  sale.order.line 的时候,不要立即 进行  _amount_all 的计算。

    问题发到 群里 请教后,
    给出了几种方案:

    1. 我自己提出的暴力方案,添加一个 全局变量设置, 开始计算前,设置一下,然后在  _amount_all 判断状态,不要计算的话,直接返回
    2. buke 提出的  @bzrcache ,对计算结果进行缓存,避免重复计算
    3. 总监提出的 试试 不要 每行 create,试试在  sale.order 对象上面 write    (0, 0,order_lines_values)这样的方式一次写入



    显然,总监的方案 最吸引人了,尝试后发现,虽然语句上是在 sale.order 一次写入了,但是 实际上 OE 会对 每一个  (0, 0,order_lines_values)调用一次 sale.order.line 的create 的。我测试了两行, _amount_all 被调用了两次, 然后 我犯了最大的错误, 就是 想当然地以为 依旧是逐行调用  _amount_all , 跟现有状况无差别。于是 放弃。

    于是,开始我自己 流氓方案,加了全局变量,这里就不多说了,总之,初步解决了问题,性能从几小时 提高到了二十几分钟。方案当然不太理想了,因为要直接 改 sale.py ,试着改成了模块,折腾了2天,决定这是 最后的解决方案。

    下面又尝试了 buke 的,@bzrcache,  python基础差,bzrcache 的代码虽不多,也没完全看懂和理解, 就是照着bzrerp 依样画葫芦抄了一遍。很不幸报错了,因为也要改 sale.py ,又没读懂,心里有点 抗拒这个方案了。



    又回到 最早 总监的方案里,
    前面测试说了, 插入 两行,调用了两次 _amount_all , 想当然地认为,插入n行 就是调用 n次。

    结果这是个错误,进一步测试发现, 插入n次,调用  _amount_all  依旧是2次而已


    这就是我要的结果

    &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sale_order_obj.write(cr,uid,[order_id],{&#039;order_line&#039;:order_lines,&#039;sale_order_contract_details&#039;:contract_details},context)<br />
    


    这里面的 order_lines 会比较大,我写到文件里看了一下, 订单大的时候(2000行)大约有10M。


    这里面还有一个插曲,因为考虑到 多次计算的问题,第二次计算时,要求先清除上一次的结果,
    原先我是调用 unlike 删除的,后面 觉得 既然 写入能用  (0, 0,order_lines_values),删除应该也用  (2,contract_details_id) ,结果再次进入噩梦中,OE 会为 每一个 (2,contract_details_id) 调用一次 unlike,并且还会逐个调用一次  _amount_all 。
    好在 这时 我一看就知道问题了。
    改回这样

    order_lines_obj.unlink(cr, uid, delete_order_lines_ids, context=None)<br />
    


    并且 不是每行调用一次, 而是 先 把要删除的 id 全部合并到一个 list 中,最后 调用一次。



    这算是我一次“优化”的过程吧,反反复复 有一周了,又学到不少东西

    谢谢 buke、总监、jeff、joshua ,谢谢 cctv

    1 条回复 最后回复
    0
    • mrshellyM 离线
      mrshellyM 离线
      mrshelly
      写于 最后由 编辑
      #2

      嗯. 那就是删除 与添加分开做 就OK了.

      删除也是将 [(2, ID1), (2,ID2)....] 组合后 write 一次? 然后  添加是 [(0,0,{...}),(0,0,{...}),...] 这样组合后 write 一次吧?

      1 条回复 最后回复
      0
      • C 离线
        C 离线
        ccdos
        写于 最后由 编辑
        #3

        删除也是将 [(2, ID1), (2,ID2)....] 组合后 write 一次?~

        ~~~~~~~~ 删除这样做以后,反而真正变成了, 一个个  删除
        要把 id1,id2 组合成 ids 然后 调用 unlike,

        而添加则反之, 要 [(0,0,{...}),(0,0,{...}),...] 这样组合后 write 一次

        1 条回复 最后回复
        0
        • wjfonhandW 离线
          wjfonhandW 离线
          wjfonhand
          写于 最后由 编辑
          #4

          总监威武,ccdos进步神速,buke奇招迭出,我看看热闹,少看cctv多向诸位学习!

          GoodERP -- Odoo China fork

          1 条回复 最后回复
          0

          • 登录

          • 没有帐号? 注册

          • 登录或注册以进行搜索。
          • 第一个帖子
            最后一个帖子
          0
          • 版块
          • 标签
          • 热门
          • 用户
          • 群组