#In case no product_qty is given, take the remaining qty to produce for the given production
if not product_qty:
- product_qty = uom_obj._compute_qty(cr, uid, production.uom_id.id, production.product_qty, production.product_id.uom_id.id) - produced_qty
+ product_qty = uom_obj._compute_qty(cr, uid, production.product_uom.id, production.product_qty, production.product_id.uom_id.id) - produced_qty
+ production_qty = uom_obj._compute_qty(cr, uid, production.product_uom.id, production.product_qty, production.product_id.uom_id.id)
scheduled_qty = {}
for scheduled in production.product_lines:
dicts[product_id] = {}
# total qty of consumed product we need after this consumption
- if product_qty + produced_qty <= production.product_qty:
- total_consume = ((product_qty + produced_qty) * sched_product_qty / production.product_qty)
+ if product_qty + produced_qty <= production_qty:
+ total_consume = ((product_qty + produced_qty) * sched_product_qty / production_qty)
else:
total_consume = sched_product_qty
qty = total_consume - consumed_qty
from openerp.osv import osv
from openerp.tools.translate import _
from openerp import SUPERUSER_ID
-from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
+from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, float_compare
class StockMove(osv.osv):
_inherit = 'stock.move'
if move_qty <= 0:
raise osv.except_osv(_('Error!'), _('Cannot consume a move with negative or zero quantity.'))
quantity_rest = move_qty - product_qty
- if quantity_rest > 0:
+ # Compare with numbers of move uom as we want to avoid a split with 0 qty
+ quantity_rest_uom = move.product_uom_qty - self.pool.get("product.uom")._compute_qty_obj(cr, uid, move.product_id.uom_id, product_qty, move.product_uom)
+ if float_compare(quantity_rest_uom, 0, precision_rounding=move.product_uom.rounding) != 0:
new_mov = self.split(cr, uid, move, quantity_rest, context=context)
res.append(new_mov)
vals = {'restrict_lot_id': restrict_lot_id,
which the user can still adapt
"""
prod_obj = self.pool.get("mrp.production")
+ uom_obj = self.pool.get("product.uom")
production = prod_obj.browse(cr, uid, context['active_id'], context=context)
consume_lines = []
new_consume_lines = []
if product_qty > 0.0:
- consume_lines = prod_obj._calculate_qty(cr, uid, production, product_qty=product_qty, context=context)
+ product_uom_qty = uom_obj._compute_qty(cr, uid, production.product_uom.id, product_qty, production.product_id.uom_id.id)
+ consume_lines = prod_obj._calculate_qty(cr, uid, production, product_qty=product_uom_qty, context=context)
for consume in consume_lines:
new_consume_lines.append([0, False, consume])
for move in prod.move_created_ids2:
if move.product_id == prod.product_id:
if not move.scrapped:
- done += move.product_qty
- return (prod.product_qty - done) or prod.product_qty
+ done += move.product_uom_qty # As uom of produced products and production order should correspond
+ return prod.product_qty - done
def _get_product_id(self, cr, uid, context=None):
""" To obtain product id
Bill of Materials for 1 SHE100 Unit
-+-------------+----------+------------
-| Product Code| Quantity | UoM |
-+====================================+
-|SIDEPAN | 2 | PCE |
-+-------------+----------+-----------+
-|LIN040 | 1 | M |
-+-------------+----------+-----------+
-|WOOD010 | 0.249| M |
-+-------------+----------+-----------+
-|METC000 | 12| PCE |
-+-------------+----------+-----------+
++--------------+----------+-----------+
+| Product Code | Quantity | UoM |
++==============+==========+===========+
+| SIDEPAN | 2 | PCE |
++--------------+----------+-----------+
+| LIN040 | 1 | M |
++--------------+----------+-----------+
+| WOOD010 | 0.249 | M |
++--------------+----------+-----------+
+| METC000 | 12 | PCE |
++--------------+----------+-----------+
Bill of Materials for 2 SIDEPAN Units
-+-------------+----------+------------
-| Product Code| Quantity | UoM |
-+====================================+
-| WOOD002 | 0.17| M |
-+-------------+----------+------------
++--------------+----------+-----------+
+| Product Code | Quantity | UoM |
++==============+==========+===========+
+| WOOD002 | 0.17 | M |
++--------------+----------+-----------+
The SIDEPAN is made from an order using the workflow shown. The WOOD002 is purchased on order and the other products are all found in stock. An order for the product SHE100 will then generate two production orders (SHE100 and SIDEPAN) then produce two purchase orders for the product WOOD002. Product WOOD002 is used in the production of both SHE100 and SIDEPAN. Set the lead times on the product forms to the following:
-+-------------+-------------------+------------------------+---------------------+
-|Product Code |Customer Lead Time |Manufacturing Lead Time |Supplier Lead Time |
-+================================================================================+
-|SHE100 | 30 days | 5 days | |
-+-------------+-------------------+------------------------+---------------------+
-|SIDEPAN | | 10 days | |
-+-------------+-------------------+------------------------+---------------------+
-|WOOD002 | | | 5 days |
-+-------------+-------------------+------------------------+---------------------+
++--------------+--------------------+-------------------------+--------------------+
+| Product Code | Customer Lead Time | Manufacturing Lead Time | Supplier Lead Time |
++=============+=====================+=========================+====================+
+| SHE100 | 30 days | 5 days | |
++--------------+--------------------+-------------------------+--------------------+
+| SIDEPAN | | 10 days | |
++--------------+--------------------+-------------------------+--------------------+
+| WOOD002 | | | 5 days |
++--------------+--------------------+-------------------------+--------------------+
A customer order placed on the 1st January will set up the following operations and lead times: