Odoo中文社区可以通过以下三个域名访问:shine-it.net , odoocn.org,odoo.net.cn

原论坛用户的基本信息和发帖这里都予以保留,请注意:原论坛用户无需重新注册新用户,但是您的密码需要重置

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

按库存采购的货品,设定了供应商和再订货规则,运行排程会不断重复产生询价单,何故



  • 按库存采购的货品,设定了供应商和再订货规则,运行排程会不断重复产生询价单,何故<br />货品资料:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5063;image[/img]<br />按库存采购的材料,设置了补货供应商:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5065;image[/img]<br />再订购规则:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5067;image[/img]<br />货品当前库存为0;<br />第一次运行仓库-计划-运行排程:<br />产生询价单然后确认订单如下:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5061;image[/img]<br />当我再次运行仓库-计划-运行排程时:<br />需求没有任何增加,结果又产生询价单了,这次数量变成了50,我再次确认订单;<br />再运行,询价单数量变成了100,怎么会这样呢?<br />按照我的理解:前面采购单已经确认,预测数量已经变成了25,再次运行 排程,因为25已经高于最小数量10,就不应该再产生询价单了,这是哪里错了呢,请各位前辈指点一下,非常感谢!



  • 按库存采购的货品,设定了供应商和再订货规则,运行排程会不断重复产生询价单,何故<br />货品资料:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5063;image[/img]<br />按库存采购的材料,设置了补货供应商:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5065;image[/img]<br />再订购规则:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5067;image[/img]<br />货品当前库存为0;<br />第一次运行仓库-计划-运行排程:<br />产生询价单然后确认订单如下:<br />[img]http://shine-it.net/index.php?action=dlattach;topic=17612.0;attach=5061;image[/img]<br />当我再次运行仓库-计划-运行排程时:<br />需求没有任何增加,结果又产生询价单了,这次数量变成了50,我再次确认订单;<br />再运行,询价单数量变成了100,怎么会这样呢?<br />按照我的理解:前面采购单已经确认,预测数量已经变成了25,再次运行 排程,因为25已经高于最小数量10,就不应该再产生询价单了,这是哪里错了呢,请各位前辈指点一下,非常感谢!



  • 你之前的询价单 确认了么?收货了么?<br />如果 产品 库存数量 低于 你设的 再订购 规则 中的 最小数量,<br />你 跑 mrp(排程) 就会重复生成 作为 草稿的 采购询价单 。<br /><br />如果 产品的 在手 库存 数量 大于 触发条件 ,应该就不会 生成 询价单了。



  • 恭喜你,又碰到了odoo给你预留的一个坑位。如果我没估计错,你的仓库是[b]两步入库[/b](因为我是三步入库,第二次的运行结果是75并非50)。<br /><br />其实你的理解并没错,按道理讲你已经生成了25个的采购单,再次运行MRP运算不应该生成后续的询价单,但是理想很美好,现实很骨感。<br /><br />我们来看看这个错误是如何发生的:<br /><br />[code]<br />for key in product_dict.keys():<br />                ctx = context.copy()<br />                ctx.update({'location': ops_dict[key][0].location_id.id})<br />                prod_qty = product_obj._product_available(cr, uid, [x.id for x in product_dict[key]],<br />                                                          context=ctx)<br />                subtract_qty = orderpoint_obj.subtract_procurements_from_orderpoints(cr, uid, [x.id for x in ops_dict[key]], context=context)<br />                for op in ops_dict[key]:<br />                    try:<br />                        prods = prod_qty[op.product_id.id]['virtual_available']<br />                        if prods is None:<br />                            continue<br />                        if float_compare(prods, op.product_min_qty, precision_rounding=op.product_uom.rounding) <= 0:<br />                            qty = max(op.product_min_qty, op.product_max_qty) - prods<br />                            reste = op.qty_multiple > 0 and qty % op.qty_multiple or 0.0<br />                            if float_compare(reste, 0.0, precision_rounding=op.product_uom.rounding) > 0:<br />                                qty += op.qty_multiple - reste<br /><br />                            if float_compare(qty, 0.0, precision_rounding=op.product_uom.rounding) < 0:<br />                                continue<br /><br />                            qty -= subtract_qty[op.id]<br /><br />                            qty_rounded = float_round(qty, precision_rounding=op.product_uom.rounding)<br />                            if qty_rounded > 0:<br />                                proc_id = procurement_obj.create(cr, uid,<br />                                                                self._prepare_orderpoint_procurement(cr, uid, op, qty_rounded, context=context),<br />                                                                context=context)<br />                                tot_procs.append(proc_id)<br />                            if use_new_cursor:<br />                                cr.commit()<br />                    except OperationalError:<br />[/code]<br />由以上代码可以看出,Odoo官方其实是已经将预先采购但并未实际入库的数量扣除了,所以这里你入没入库实际并不影响它的运算结果。<br /><br />但作怪的究竟是谁呢?经过一番print之后,找到始作俑者:<br />[code] qty -= subtract_qty[op.id][/code]<br /><br />进而,按图索骥,找到最终的罪魁祸首——<br />orderpoint对象的subtract_procurements_from_orderpoints方法:<br />[code]<br />def subtract_procurements_from_orderpoints(self, cr, uid, orderpoint_ids, context=None):<br />        '''This function returns quantity of product that needs to be deducted from the orderpoint computed quantity because there's already a procurement created with aim to fulfill it.<br />        '''<br /><br />        cr.execute("""select op.id, p.id, p.product_uom, p.product_qty, pt.uom_id, sm.product_qty from procurement_order as p left join stock_move as sm ON sm.procurement_id = p.id,<br />                                    stock_warehouse_orderpoint op, product_product pp, product_template pt<br />                                WHERE p.orderpoint_id = op.id AND p.state not in ('done', 'cancel') AND (sm.state IS NULL OR sm.state not in ('draft'))<br />                                AND pp.id = p.product_id AND pp.product_tmpl_id = pt.id<br />                                AND op.id IN %s<br />                                ORDER BY op.id, p.id<br />                    """, (tuple(orderpoint_ids),))<br />        results = cr.fetchall()<br />        current_proc = False<br />        current_op = False<br />        uom_obj = self.pool.get("product.uom")<br />        op_qty = 0<br />        res = dict.fromkeys(orderpoint_ids, 0.0)<br />        for move_result in results:<br />            op = move_result[0]<br />            if current_op != op:<br />                if current_op:<br />                    res[current_op] = op_qty<br />                current_op = op<br />                op_qty = 0<br />            proc = move_result[1]<br />            if proc != current_proc:<br />                op_qty += uom_obj._compute_qty(cr, uid, move_result[2], move_result[3], move_result[4], round=False)<br />                current_proc = proc<br />            if move_result[5]: #If a move is associated (is move qty)<br />                op_qty -= move_result[5]<br />        if current_op:<br />            res[current_op] = op_qty<br />        return res<br />[/code]<br /><br />这段代码的问题在什么地方呢?<br />在于联表查询stock_move的时候并没有判断move的源库位和目的库位。<br />针对你这里的问题,按我估计,你是两步入库,第一步供应商到input 数量25,第二步 input到stock 25。根据上面的代码,第一次循环走前2个if 到第三个if的时候<br />相互抵消,op_qty数量为0。第二次循环 不走前两个if 直接第三个if 结果为-25.<br />回到_procure_orderpoint_confirm 方法 ,因此会创建一个 (25 -= -25 )50的询价单。<br /><br />第三次运行MRP运算,你确认了50的询价单 ,因而符合的stock move有4个 分别为25,25,50,50.<br />因此 会创建一个(25-=-75) 100的询价单。<br /><br />依次可类推,第四次运算的结果应该为 200.<br /><br />WTF!!(ノಠ益ಠ)ノ彡┻━┻!!<br /><br />多大一坑啊!!!!<br /><br />好了,认识了这个坑就该知道怎么修补这个坑了吧~~<br /><br /><br />什么?不知道如何修补? <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />...........................<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />那还玩什么odoo啊。。。。。。。。<br /><br /><br />【原创,禁止转载】<br /><br />--------------------------------------------------更新----------------------------------------------------<br /><br />细心的同学可能已经发现了 按上面说的 <br />[code]prods = prod_qty[op.product_id.id]['virtual_available'][/code]<br />当第一次的25入库以后,预计数量应该为25才对,但从结果上看,显然预计数量仍然为0 。<br /><br />oh,no!又是灵异事件么?<br /><br />经查,odoo关于预测数量的算法是这样的,预测数量 = 入库数量 - 出库数量 (当前库位)<br /><br />而楼主的问题,在于 预测数量始终为0 才导致的 每运行一次都出一次询价单。。。。。。<br /><br />所以,饶了一圈又回到了原点。<br /><br />解决楼主问题的方法非常简单,不要把订购点设置到input库位上!!!!!!!!!!!!<br /><br />为什么?<br /><br />两次入库的前提下,每确定一张采购单,系统会自动生成 供应商到 input的 move 和 input 到 stock的move <br /><br />这一进一出,预测数量不为0 才怪! 同理, 三步入库把 订购点设置到qc库位的,也是傻*一个。<br /><br />╮(╯▽╰)╭



  • [quote author=KevinKong link=topic=17612.msg32268#msg32268 date=1463560230]<br />如果我没估计错,你的仓库是[b]两步入库[/b](因为我是三步入库,第二次的运行结果是75并非50)。<br /><br /><br /><br />WTF!!(ノಠ益ಠ)ノ彡┻━┻!!<br /><br />多大一坑啊!!!!<br /><br />好了,认识了这个坑就该知道怎么修补这个坑了吧~~<br /><br /><br />什么?不知道如何修补? <br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />...........................<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />那还玩什么odoo啊。。。。。。。。<br /><br /><br />【原创,禁止转载】<br /><br />--------------------------------------------------更新----------------------------------------------------<br /><br /><br /><br /><br /><br />解决楼主问题的方法非常简单,[b]不要把订购点设置到input库位上[/b]!!!!!!!!!!!!<br /><br /><br /><br />╮(╯▽╰)╭<br />[/quote]<br /><br />兄台真神人也,我的系统设置被你一一言中,我的仓库真的真的是[b]两步入库[/b],更神奇的是,我的产品订购点刚好就设置在input库位上,小生佩服的五体投地,非常非常非常感谢,[b]高手在民间[/b]呀!!!



  • 再订购规则本就应该设置在库存库位上吧<br /><br />小孔可不是民间的,科班出身,知名公司就职,odoo资深哪


登录后回复
 

与 Odoo 中文社区 的连接断开,我们正在尝试重连,请耐心等待