stock.move.group renamed to procurement.group
authorFabien Pinckaers <fp@tinyerp.com>
Sat, 29 Jun 2013 09:13:28 +0000 (11:13 +0200)
committerFabien Pinckaers <fp@tinyerp.com>
Sat, 29 Jun 2013 09:13:28 +0000 (11:13 +0200)
procurement module (where stock.move.group was defined) does not depend on the stock module
the same grouping system could be used for services too

procurement.group
removed sequence_id field
put a default values on the name field, using a defined sequence
renamed "Move Group" into "Procurement Requisition"

procurement object:
location_id should not come from the customer property but should be stored on the procurement (set by the sale order, using the customer property)

bzr revid: fp@tinyerp.com-20130629091328-5gc39647aa2pymlf

addons/procurement/procurement.py
addons/procurement/procurement_data.xml
addons/product/product.py
addons/product_expiry/product_expiry_demo.xml
addons/purchase/res_config.py
addons/purchase/stock.py
addons/sale_stock/sale_stock.py
addons/stock_location_sale/stock_location_sale.py

index 5202eb4..225c161 100644 (file)
@@ -65,7 +65,7 @@ class StockMove(osv.osv):
     _inherit = 'stock.move'
     _columns= {
         'procurements': fields.one2many('procurement.order', 'move_id', 'Procurements'),
-        'group_id':fields.many2one('stock.move.group', 'Move Group'), 
+        'group_id':fields.many2one('procurement.group', 'Move Group'), 
     }
 
     def copy_data(self, cr, uid, id, default=None, context=None):
@@ -75,25 +75,38 @@ class StockMove(osv.osv):
         return super(StockMove, self).copy_data(cr, uid, id, default, context=context)
 
 
-class move_group(osv.osv):
+class procurement_group(osv.osv):
     '''
-    The procurement requirement class is used to group procurement orders. 
-    The goal is that when you have one delivery order of several products
-    and the products are pulled from the same or several location(s), to keep having
-    the moves grouped into pickings.  
-    
-    As the pulled moves are created by the procurement orders who are created by moves/SO/..., 
-    the procurement requisition will bundle these procurement orders according to the same original picking
-    
-    Suppose you have 4 lines on a picking from Output where 2 lines will need to come from Input and 2 lines coming from Stock -> Output
-    As the four procurement orders will have the same group ids from the SO, the move from input will have a stock.picking with 2 grouped lines
-    and the move from stock will have 2 grouped lines also.  
+    The procurement requirement class is used to group products together
+    when computing procurements. (tasks, physical products, ...)
+
+    The goal is that when you have one sale order of several products
+    and the products are pulled from the same or several location(s), to keep
+    having the moves grouped into pickings that represent the sale order.
+
+    Used in: sales order (to group delivery order lines like the so), pull/push
+    rules (to pack like the delivery order), on orderpoints (e.g. for wave picking
+    all the similar products together).
+
+    Grouping is made only if the source and the destination is the same.
+    Suppose you have 4 lines on a picking from Output where 2 lines will need
+    to come from Input (crossdock) and 2 lines coming from Stock -> Output As
+    the four procurement orders will have the same group ids from the SO, the
+    move from input will have a stock.picking with 2 grouped lines and the move
+    from stock will have 2 grouped lines also.
+
+    The name is usually the name of the original document (sale order) or a
+    sequence computed if created manually.
     '''
-    _name = 'stock.move.group'
+    _name = 'procurement.group'
+    _description = 'Procurement Requisition'
+    _order = "id desc"
     _columns = {
-        'name': fields.char('Name'), 
-        'sequence_id': fields.many2one('ir.sequence', 'Group Sequence', help="Move group sequence"), 
-        }
+        'name': fields.char('Reference'), 
+    }
+    _defaults = {
+        'name': lambda self,cr,uid,c: self.pool.get('ir.sequence').get(cr,uid,'procurement.group') or ''
+    }
 
 
 
@@ -140,7 +153,7 @@ class procurement_order(osv.osv):
             \nAfter confirming the status is set to \'Running\'.\n If any exception arises in the order then the status is set to \'Exception\'.\n Once the exception is removed the status becomes \'Ready\'.\n It is in \'Waiting\'. status when the procurement is waiting for another one to finish.'),
         'note': fields.text('Note'),
         'company_id': fields.many2one('res.company','Company',required=True),
-        'group_id':fields.many2one('stock.move.group', 'Move Group'), 
+        'group_id':fields.many2one('procurement.group', 'Procurement Requisition'), 
     }
     _defaults = {
         'state': 'draft',
@@ -329,8 +342,6 @@ class procurement_order(osv.osv):
         @return: True
         """
         move_obj = self.pool.get('stock.move')
-        mod_obj = self.pool.get('ir.model.data')
-        location_model, location_id = mod_obj.get_object_reference(cr, uid, 'stock', 'stock_location_customers')
         for procurement in self.browse(cr, uid, ids, context=context):
             if procurement.product_qty <= 0.00:
                 raise osv.except_osv(_('Data Insufficient!'),
@@ -338,7 +349,7 @@ class procurement_order(osv.osv):
             if procurement.product_id.type in ('product', 'consu'):
                 if not procurement.move_id:
                     source = procurement.location_id.id
-                    if procurement.procure_method == 'make_to_order':#and source != location_id: Last statement is not good
+                    if procurement.procure_method == 'make_to_order':
                         source = procurement.product_id.property_stock_procurement.id
                     id = move_obj.create(cr, uid, {
                         'name': procurement.name,
@@ -354,8 +365,7 @@ class procurement_order(osv.osv):
                     })
                     move_obj.action_confirm(cr, uid, [id], context=context)
                     self.write(cr, uid, [procurement.id], {'move_id': id, 'close_move': 1})
-                self.write(cr, uid, [procurement.id], {'state': 'confirmed', 'message': ''})
-
+        self.write(cr, uid, ids, {'state': 'confirmed', 'message': ''})
         return True
 
     def action_move_assigned(self, cr, uid, ids, context=None):
index 6a83d52..872e5fd 100644 (file)
             <field eval="'run_scheduler'" name="function"/>
             <field eval="'(False,)'" name="args"/>
         </record>
+
+        <record id="sequence_proc_group_type" model="ir.sequence.type">
+            <field name="name">Procurement Group</field>
+            <field name="code">procurement.group</field>
+        </record>
+        
+        <record id="sequence_proc_group" model="ir.sequence">
+            <field name="name">Procurement Group</field>
+            <field name="code">procurement.group</field>
+            <field name="prefix">PG/</field>
+            <field name="padding">6</field>
+            <field name="number_next">1</field>
+            <field name="number_increment">1</field>
+        </record>
         
         <record id="sequence_mrp_op_type" model="ir.sequence.type">
             <field name="name">Stock orderpoint</field>
@@ -29,4 +43,4 @@
             <field name="number_increment">1</field>
         </record>
     </data>
-</openerp>
\ No newline at end of file
+</openerp>
index 99de24c..5ee41a0 100644 (file)
@@ -177,10 +177,9 @@ class product_uom(osv.osv):
                 return qty
         amount = qty / from_unit.factor
         if to_unit:
+            amount = amount * to_unit.factor
             if round:
-                amount = rounding(amount * to_unit.factor, to_unit.rounding)
-            else:
-                amount = amount * to_unit.factor
+                amount = rounding(amount, to_unit.rounding)
         return amount
 
     def _compute_price(self, cr, uid, from_uom_id, price, to_uom_id=False):
index 85539d1..b644671 100644 (file)
@@ -34,7 +34,7 @@
         <record id="product_product_from" model="product.product">
             <field name="supply_method">buy</field>
             <field name="list_price">8.0</field>
-<!--            <field name="standard_price">6.0</field>--> <!-- TODO: why this change? -->
+            <field name="standard_price">6.0</field>
             <field name="uom_id" ref="product.product_uom_unit"/>
             <field name="uom_po_id" ref="product.product_uom_unit"/>
             <field name="uos_id" ref="product.product_uom_kgm" />
index 33858fc..ffbbbfd 100644 (file)
@@ -39,7 +39,7 @@ class purchase_config_settings(osv.osv_memory):
         'group_uom':fields.boolean("Manage different units of measure for products",
             implied_group='product.group_uom',
             help="""Allows you to select and maintain different units of measure for products."""),
-        'group_costing_method':fields.boolean("Compute product cost price based on average/FIFO/LIFO cost",
+        'group_costing_method':fields.boolean("The default costing method applied to all products",
             implied_group='product.group_costing_method',
             help="""Allows you to compute product cost price based on average cost."""),
         'module_warning': fields.boolean("Alerts by products or supplier",
index a5c7376..794ff22 100644 (file)
@@ -125,10 +125,9 @@ class stock_partial_picking(osv.osv_memory):
     _inherit = 'stock.partial.picking'
 
     # Overridden to inject the purchase price as true 'cost price' when processing
-    # incoming pickings.
+    # incoming pickings. The price is always stored in the company currency.
     def _product_cost_for_average_update(self, cr, uid, move):
         if move.picking_id.purchase_id:
-            #always write the cost price of products in the company currency, for easiness in further computation
             currency_obj = self.pool.get("res.currency")
             new_price = currency_obj.compute(cr, uid, move.picking_id.purchase_id.pricelist_id.currency_id.id, move.company_id.currency_id.id, 
                                                  move.purchase_line_id.price_unit, round=False)
index e282e63..c6fac18 100644 (file)
@@ -27,16 +27,6 @@ from openerp.tools.translate import _
 import pytz
 from openerp import SUPERUSER_ID
 
-
-#COULD BE INTERESTING WHEN PROCUREMENT TO CUSTOMER AND PULL RULE
-class procurement_order(osv.osv):
-    _inherit = 'procurement.order'
-    _columns = {
-        'sale_line_id': fields.many2one('sale.order.line', 'Sale order line'), 
-        }
-
-
-
 class sale_order(osv.osv):
     _inherit = "sale.order"
     
@@ -308,7 +298,6 @@ class sale_order(osv.osv):
     def _prepare_order_line_procurement(self, cr, uid, order, line, move_id, date_planned, group_id = False, context=None):
         mod_obj = self.pool.get('ir.model.data')
         location_model, location_id = mod_obj.get_object_reference(cr, uid, 'stock', 'stock_location_customers')
-        output_id = order.warehouse_id.lot_output_id.id
         return {
             'name': line.name,
             'origin': order.name,
@@ -320,80 +309,13 @@ class sale_order(osv.osv):
                     or line.product_uom_qty,
             'product_uos': (line.product_uos and line.product_uos.id)\
                     or line.product_uom.id,
-            'location_id': order.warehouse_id.lot_stock_id.id, #TODO Procurement should be generated towards customers instead
+            'location_id': location_id,
             'procure_method': line.type,
             'move_id': move_id,
             'company_id': order.company_id.id,
             'note': line.name,
             'group_id': group_id, 
         }
-    def _prepare_order_line_move(self, cr, uid, order, line, picking_id, date_planned, group_id = False, context=None):
-        location_id = order.warehouse_id.lot_stock_id.id
-        output_id = order.warehouse_id.lot_output_id.id
-        #mod_obj = self.pool.get('ir.model.data')
-        #location_model, location_id = mod_obj.get_object_reference(cr, uid, 'stock', 'stock_location_customers')
-        return {
-            'name': line.name,
-            'picking_id': picking_id,
-            'product_id': line.product_id.id,
-            'date': date_planned,
-            'date_expected': date_planned,
-            'product_qty': line.product_uom_qty,
-            'product_uom': line.product_uom.id,
-            'product_uos_qty': (line.product_uos and line.product_uos_qty) or line.product_uom_qty,
-            'product_uos': (line.product_uos and line.product_uos.id)\
-                    or line.product_uom.id,
-            'product_packaging': line.product_packaging.id,
-            'partner_id': line.address_allotment_id.id or order.partner_shipping_id.id,
-            'location_id': location_id,
-            'location_dest_id': output_id, 
-            'sale_line_id': line.id,
-            'tracking_id': False,
-            'state': 'draft',
-            #'state': 'waiting',
-            'company_id': order.company_id.id,
-            'price_unit': line.product_id.standard_price or 0.0, 
-            'group_id': group_id, 
-        }
-    def _prepare_order_picking(self, cr, uid, order, context=None):
-        pick_name = self.pool.get('ir.sequence').get(cr, uid, 'stock.picking.out')
-        return {
-            'name': pick_name,
-            'origin': order.name,
-            'date': self.date_to_datetime(cr, uid, order.date_order, context),
-            'type': 'out',
-            'state': 'auto',
-            'move_type': order.picking_policy,
-            'sale_id': order.id,
-            'partner_id': order.partner_shipping_id.id,
-            'note': order.note,
-            'invoice_state': (order.order_policy=='picking' and '2binvoiced') or 'none',
-            'company_id': order.company_id.id,
-        }
-
-    def ship_recreate(self, cr, uid, order, line, move_id, proc_id):
-        # FIXME: deals with potentially cancelled shipments, seems broken (specially if shipment has production lot)
-        """
-        Define ship_recreate for process after shipping exception
-        param order: sales order to which the order lines belong
-        param line: sales order line records to procure
-        param move_id: the ID of stock move
-        param proc_id: the ID of procurement
-        """
-        move_obj = self.pool.get('stock.move')
-        if order.state == 'shipping_except':
-            for pick in order.picking_ids:
-                for move in pick.move_lines:
-                    if move.state == 'cancel':
-                        mov_ids = move_obj.search(cr, uid, [('state', '=', 'cancel'),('sale_line_id', '=', line.id),('picking_id', '=', pick.id)])
-                        if mov_ids:
-                            for mov in move_obj.browse(cr, uid, mov_ids):
-                                # FIXME: the following seems broken: what if move_id doesn't exist? What if there are several mov_ids? Shouldn't that be a sum?
-                                move_obj.write(cr, uid, [move_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
-                                self.pool.get('procurement.order').write(cr, uid, [proc_id], {'product_qty': mov.product_qty, 'product_uos_qty': mov.product_uos_qty})
-        return True
 
     def _get_date_planned(self, cr, uid, order, line, start_date, context=None):
         start_date = self.date_to_datetime(cr, uid, start_date, context)
@@ -401,7 +323,6 @@ class sale_order(osv.osv):
         date_planned = (date_planned - timedelta(days=order.company_id.security_lead)).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
         return date_planned
 
-
     def _create_pickings_and_procurements(self, cr, uid, order, order_lines, picking_id=False, context=None):
         """Create the required procurements to supply sales order lines, also connecting
         the procurements to appropriate stock moves in order to bring the goods to the
@@ -421,14 +342,12 @@ class sale_order(osv.osv):
                                will be added. A new picking will be created if ommitted.
         :return: True
         """
-        print "CREATE OLD PICKINGS AND PROCUREMENTS"
         move_obj = self.pool.get('stock.move')
         picking_obj = self.pool.get('stock.picking')
         procurement_obj = self.pool.get('procurement.order')
         proc_ids = []
 
-        #Create group
-        group_id = self.pool.get("stock.move.group").create(cr, uid, {'name': order.name}, context=context)
+        group_id = self.pool.get("procurement.group").create(cr, uid, {'name': order.name}, context=context)
 
         for line in order_lines:
             if line.state == 'done':
@@ -437,23 +356,10 @@ class sale_order(osv.osv):
             date_planned = self._get_date_planned(cr, uid, order, line, order.date_order, context=context)
 
             if line.product_id:
-                if line.product_id.type in ('product', 'consu'):
-                    if not picking_id:
-                        picking_id = picking_obj.create(cr, uid, self._prepare_order_picking(cr, uid, order, context=context))
-                    move_id = move_obj.create(cr, uid, self._prepare_order_line_move(cr, uid, order, line, picking_id, date_planned, group_id=group_id, context=context))
-                else:
-                    # a service has no stock move
-                    move_id = False
-
-            #TODO Need to do something instead of warehouse
-            if line.product_id:
                 proc_id = procurement_obj.create(cr, uid, self._prepare_order_line_procurement(cr, uid, order, line, move_id, date_planned, group_id = group_id, context=context))
                 proc_ids.append(proc_id)
                 line.write({'procurement_id': proc_id})
-                self.ship_recreate(cr, uid, order, line, move_id, proc_id)
 
-        if picking_id:
-            picking_obj.signal_button_confirm(cr, uid, [picking_id])
         procurement_obj.signal_button_confirm(cr, uid, proc_ids)
 
         val = {}
index 4b06962..eed8b32 100644 (file)
@@ -65,7 +65,7 @@ class sale_order(osv.osv):
         proc_ids = []
 
         #Create group
-        group_id = self.pool.get("stock.move.group").create(cr, uid, {'name': order.name}, context=context)
+        group_id = self.pool.get("procurement.group").create(cr, uid, {'name': order.name}, context=context)
 
         for line in order_lines:
             if line.state == 'done':
@@ -130,4 +130,4 @@ class sale_order(osv.osv):
             'note': line.name,
             'group_id': group_id,
             'state': 'draft',  
-        }
\ No newline at end of file
+        }