[IMP] Add test purchase order other company to tests, add price_unit_out for generati...
authorJosse Colpaert <jco@openerp.com>
Tue, 7 May 2013 14:04:43 +0000 (16:04 +0200)
committerJosse Colpaert <jco@openerp.com>
Tue, 7 May 2013 14:04:43 +0000 (16:04 +0200)
bzr revid: jco@openerp.com-20130507140443-6z4wzpnac62911ku

addons/stock/product.py
addons/stock/stock.py
addons/stock/stock_demo.xml
addons/stock_fifo_lifo/stock_fifo_lifo.py
addons/stock_fifo_lifo/test/fifolifo_price.yml

index 348aea5..9f3109b 100644 (file)
@@ -216,7 +216,10 @@ class product_product(osv.osv):
             if type(context['location']) == type(1):
                 location_ids = [context['location']]
             elif type(context['location']) in (type(''), type(u'')):
-                location_ids = location_obj.search(cr, uid, [('name','ilike',context['location'])], context=context)
+                if context.get('force_company', False):
+                    location_ids = location_obj.search(cr, uid, [('name','ilike',context['location']), ('company_id', '=', context['force_company'])], context=context)
+                else:
+                    location_ids = location_obj.search(cr, uid, [('name','ilike',context['location'])], context=context)
             else:
                 location_ids = context['location']
         else:
@@ -225,13 +228,19 @@ class product_product(osv.osv):
             if not wids:
                 return False
             for w in warehouse_obj.browse(cr, uid, wids, context=context):
-                location_ids.append(w.lot_stock_id.id)
+                if not context.get('force_company', False) or w.lot_stock_id.company_id == context['force_company']:
+                    location_ids.append(w.lot_stock_id.id)
 
         # build the list of ids of children of the location given by id
         if context.get('compute_child',True):
-            child_location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', location_ids)])
+            if context.get('force_company', False):
+                child_location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', location_ids), ('company_id', '=', context['force_company'])])
+            else:
+                child_location_ids = location_obj.search(cr, uid, [('location_id', 'child_of', location_ids)])
             location_ids = child_location_ids or location_ids
-            
+        
+        
+        
         return location_ids
 
 
@@ -299,12 +308,6 @@ class product_product(osv.osv):
         if where_add:
             where += where_add
 
-        #It depends on the company of the user OR by using force_company in context
-        user = self.pool.get("res.users").browse(cr, uid, uid, context=context)
-        if context.get("force_company", False):
-            where.append(context['force_company'])
-        else:
-            where.append(user.company_id.id)
 
         prodlot_id = context.get('prodlot_id', False)
         prodlot_clause = ''
@@ -322,7 +325,6 @@ class product_product(osv.osv):
                 'and location_dest_id IN %s '\
                 'and product_id IN %s '\
                 'and state IN %s ' + (date_str and 'and '+date_str+' ' or '') +' '\
-                'and company_id = %s '\
                 + prodlot_clause + 
                 'group by product_id,product_uom',tuple(where))
             results = cr.fetchall()
@@ -335,7 +337,6 @@ class product_product(osv.osv):
                 'and location_dest_id NOT IN %s '\
                 'and product_id  IN %s '\
                 'and state in %s ' + (date_str and 'and '+date_str+' ' or '') + ' '\
-                'and company_id = %s '\
                 + prodlot_clause + 
                 'group by product_id,product_uom',tuple(where))
             results2 = cr.fetchall()
index 853c37c..19b900a 100644 (file)
@@ -2293,6 +2293,9 @@ class stock_move(osv.osv):
         return reference_amount, reference_currency_id
 
 
+        
+
+
     def _create_product_valuation_moves(self, cr, uid, move, context=None):
         """
         Generate the appropriate accounting moves if the product being moves is subject
@@ -2316,9 +2319,9 @@ class stock_move(osv.osv):
                 reference_amount, reference_currency_id = self._get_reference_accounting_values_for_valuation(cr, uid, move, src_company_ctx)
                 #returning goods to supplier
                 if move.location_dest_id.usage == 'supplier':
-                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_valuation, acc_src, reference_amount, reference_currency_id, context))]
+                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_valuation, acc_src, reference_amount, reference_currency_id, 'out', context=context))]
                 else:
-                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_valuation, acc_dest, reference_amount, reference_currency_id, context))]
+                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_valuation, acc_dest, reference_amount, reference_currency_id, 'out', context=context))]
 
             # Incoming moves (or cross-company input part)
             if move.location_dest_id.company_id \
@@ -2328,9 +2331,9 @@ class stock_move(osv.osv):
                 reference_amount, reference_currency_id = self._get_reference_accounting_values_for_valuation(cr, uid, move, src_company_ctx)
                 #goods return from customer
                 if move.location_id.usage == 'customer':
-                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_dest, acc_valuation, reference_amount, reference_currency_id, context))]
+                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_dest, acc_valuation, reference_amount, reference_currency_id, 'in', context=context))]
                 else:
-                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_src, acc_valuation, reference_amount, reference_currency_id, context))]
+                    account_moves += [(journal_id, self._create_account_move_line(cr, uid, move, acc_src, acc_valuation, reference_amount, reference_currency_id, 'in', context=context))]
             move_obj = self.pool.get('account.move')
             for j_id, move_lines in account_moves:
                 move_obj.create(cr, uid,
@@ -2394,55 +2397,70 @@ class stock_move(osv.osv):
 
         return True
 
-    def _create_account_move_line(self, cr, uid, move, src_account_id, dest_account_id, reference_amount, reference_currency_id, context=None):
+    def _create_account_move_line(self, cr, uid, move, src_account_id, dest_account_id, reference_amount, reference_currency_id, type='', context=None):
         """
         Generate the account.move.line values to post to track the stock valuation difference due to the
         processing of the given stock move.
         """
-        # prepare default values considering that the destination accounts have the reference_currency_id as their main currency
-        partner_id = (move.picking_id.partner_id and self.pool.get('res.partner')._find_accounting_partner(move.picking_id.partner_id).id) or False
-        debit_line_vals = {
-                    'name': move.name,
-                    'product_id': move.product_id and move.product_id.id or False,
-                    'quantity': move.product_qty,
-                    'ref': move.picking_id and move.picking_id.name or False,
-                    'date': time.strftime('%Y-%m-%d'),
-                    'partner_id': partner_id,
-                    'debit': reference_amount,
-                    'account_id': dest_account_id,
-        }
-        credit_line_vals = {
-                    'name': move.name,
-                    'product_id': move.product_id and move.product_id.id or False,
-                    'quantity': move.product_qty,
-                    'ref': move.picking_id and move.picking_id.name or False,
-                    'date': time.strftime('%Y-%m-%d'),
-                    'partner_id': partner_id,
-                    'credit': reference_amount,
-                    'account_id': src_account_id,
-        }
+        move_list = []
+        # Consists of access rights 
+        # TODO Check if currency is not needed
+        if type == 'out' and move.product_id.cost_method in ['fifo', 'lifo']:
+            match_obj = self.pool.get("stock.move.matching")
+            matches = match_obj.search(cr, uid, [('move_out_id','=', move.id)], context=context)
+            for match in match_obj.browse(cr, uid, matches, context=context):
+                move_in = match.move_in_id
+                move_list += [(match.qty, match.qty * match.price_unit_out)]
+        else:
+            move_list = [(move.product_qty, reference_amount)]
+            
+        res = []
+        for item in move_list:
+            # prepare default values considering that the destination accounts have the reference_currency_id as their main currency
+            partner_id = (move.picking_id.partner_id and self.pool.get('res.partner')._find_accounting_partner(move.picking_id.partner_id).id) or False
+            debit_line_vals = {
+                        'name': move.name,
+                        'product_id': move.product_id and move.product_id.id or False,
+                        'quantity': item[0],
+                        'ref': move.picking_id and move.picking_id.name or False,
+                        'date': time.strftime('%Y-%m-%d'),
+                        'partner_id': partner_id,
+                        'debit': item[1],
+                        'account_id': dest_account_id,
+            }
+            credit_line_vals = {
+                        'name': move.name,
+                        'product_id': move.product_id and move.product_id.id or False,
+                        'quantity': item[0],
+                        'ref': move.picking_id and move.picking_id.name or False,
+                        'date': time.strftime('%Y-%m-%d'),
+                        'partner_id': partner_id,
+                        'credit': item[1],
+                        'account_id': src_account_id,
+            }
 
-        # if we are posting to accounts in a different currency, provide correct values in both currencies correctly
-        # when compatible with the optional secondary currency on the account.
-        # Financial Accounts only accept amounts in secondary currencies if there's no secondary currency on the account
-        # or if it's the same as that of the secondary amount being posted.
-        account_obj = self.pool.get('account.account')
-        src_acct, dest_acct = account_obj.browse(cr, uid, [src_account_id, dest_account_id], context=context)
-        src_main_currency_id = src_acct.company_id.currency_id.id
-        dest_main_currency_id = dest_acct.company_id.currency_id.id
-        cur_obj = self.pool.get('res.currency')
-        if reference_currency_id != src_main_currency_id:
-            # fix credit line:
-            credit_line_vals['credit'] = cur_obj.compute(cr, uid, reference_currency_id, src_main_currency_id, reference_amount, context=context)
-            if (not src_acct.currency_id) or src_acct.currency_id.id == reference_currency_id:
-                credit_line_vals.update(currency_id=reference_currency_id, amount_currency=-reference_amount)
-        if reference_currency_id != dest_main_currency_id:
-            # fix debit line:
-            debit_line_vals['debit'] = cur_obj.compute(cr, uid, reference_currency_id, dest_main_currency_id, reference_amount, context=context)
-            if (not dest_acct.currency_id) or dest_acct.currency_id.id == reference_currency_id:
-                debit_line_vals.update(currency_id=reference_currency_id, amount_currency=reference_amount)
-
-        return [(0, 0, debit_line_vals), (0, 0, credit_line_vals)]
+            # if we are posting to accounts in a different currency, provide correct values in both currencies correctly
+            # when compatible with the optional secondary currency on the account.
+            # Financial Accounts only accept amounts in secondary currencies if there's no secondary currency on the account
+            # or if it's the same as that of the secondary amount being posted.
+            #TODO -> might need to be changed still for fifolifo
+            account_obj = self.pool.get('account.account')
+            src_acct, dest_acct = account_obj.browse(cr, uid, [src_account_id, dest_account_id], context=context)
+            src_main_currency_id = src_acct.company_id.currency_id.id
+            dest_main_currency_id = dest_acct.company_id.currency_id.id
+            cur_obj = self.pool.get('res.currency')
+            if reference_currency_id != src_main_currency_id:
+                # fix credit line:
+                credit_line_vals['credit'] = cur_obj.compute(cr, uid, reference_currency_id, src_main_currency_id, reference_amount, context=context)
+                if (not src_acct.currency_id) or src_acct.currency_id.id == reference_currency_id:
+                    credit_line_vals.update(currency_id=reference_currency_id, amount_currency=-reference_amount)
+            if reference_currency_id != dest_main_currency_id:
+                # fix debit line:
+                debit_line_vals['debit'] = cur_obj.compute(cr, uid, reference_currency_id, dest_main_currency_id, reference_amount, context=context)
+                if (not dest_acct.currency_id) or dest_acct.currency_id.id == reference_currency_id:
+                    debit_line_vals.update(currency_id=reference_currency_id, amount_currency=reference_amount)
+            res += [(0, 0, debit_line_vals), (0, 0, credit_line_vals)]
+        return res
 
     def unlink(self, cr, uid, ids, context=None):
         if context is None:
@@ -2666,7 +2684,7 @@ class stock_move(osv.osv):
             if avg_in_update or avg_out_update:
                 
                 # If no price from picking, use cost price from product
-                if product_price == 0:
+                if product_price == 0.0:
                     product_price = product.price_get('standard_price', context=ctx)[product.id]
                 
                 move_currency_id = move.company_id.currency_id.id
index eb5a6c4..4f8b2b4 100644 (file)
         <record id="stock_location_intermediatelocation0" model="stock.location">
             <field name="partner_id" ref="base.main_partner"/>
             <field name="location_id" ref="stock.stock_location_locations_partner"/>
-            <field name="usage">procurement</field>
+            <field name="usage">transit</field>
             <field name="name">Internal Shippings</field>
         </record>
 
index 74aed07..289c2e0 100644 (file)
@@ -141,31 +141,35 @@ class stock_move(osv.osv):
                 ctx['force_company'] = company_id
                 product = product_obj.browse(cr, uid, move.product_id.id, context=ctx)
             cost_method = product.cost_method
-            
+            uom_id = product.uom_id.id
             if move.picking_id.type == 'out' and cost_method in ['fifo', 'lifo']:
+                #This price has to be put as the new standard price for the product, but needs to be converted to product UoM and currency
+                #convert uom of qty
+
+                product_uom_qty = uom_obj._compute_qty(cr, uid, product_uom, product_qty, uom_id)
+
                 #get_stock_matchings will convert to currency and UoM of this stock move
                 tuples = product_obj.get_stock_matchings_fifolifo(cr, uid, [product.id], product_qty, cost_method == 'fifo', 
-                                                                  product_uom, move.company_id.currency_id.id, context=context) #Always move of the company
+                                                                  product_uom, move.company_id.currency_id.id, context=context) #Always currency of the company
                 price_amount = 0.0
                 amount = 0.0
                 move_currency_id = move.company_id.currency_id.id
                 ctx['currency_id'] = move_currency_id
                 for match in tuples: 
                     matchvals = {'move_in_id': match[0], 'qty': match[1], 
-                                 'move_out_id': move.id}
+                                 'move_out_id': move.id, 'price_unit_out': match[2]}
                     match_id = matching_obj.create(cr, uid, matchvals, context=context)
                     move_in = self.browse(cr, uid, match[0], context=context)
                     #Reduce remaining quantity
                     self.write(cr, uid, match[0], { 'qty_remaining': move_in.qty_remaining - match[3]}, context=context)
                     price_amount += match[1] * match[2]
                     amount += match[1]
-                self.write(cr, uid, move.id, {'price_unit': price_amount / amount}, context=context)
-                print price_amount
-                print amount
-                #This price has to be put as the new standard price for the product, but needs to be converted to product UoM and currency
-                #convert uom of qty
-                uom_id = product.uom_id.id
-                product_qty = uom_obj._compute_qty(cr, uid, product_uom, amount, uom_id)
+                if product.qty_available >= product_uom_qty:
+                    self.write(cr, uid, move.id, {'price_unit': price_amount / amount}, context=context)
+                else:
+                    self.write(cr, uid, move.id, {'price_unit': price_amount / amount}, context=context)
+                
+
                 #convert price, no need of UoM conversion as it is the total price
                 currency_id = move.company_id.currency_id.id
                 currency_from = move.price_currency_id
@@ -175,16 +179,23 @@ class stock_move(osv.osv):
                 else:
                     new_price = price_amount
                 #new_price does not depend on qty as it is the total amount => no conversion needed for uom 
-                product_obj.write(cr, uid, product.id, {'standard_price': new_price / product_qty}, context=ctx)
-            # When the move is products returned to supplier or return products from customer
-            # then the price should be the price from the original move
+                product_obj.write(cr, uid, product.id, {'standard_price': new_price / product_uom_qty}, context=ctx)
+            # When the move is products returned to supplier or return products from customer, 
+            # it should be treated as a normal in or out, so for every in
             elif cost_method in ['fifo', 'lifo']:  
                 #The currency in the stock move should be the currency of the company
-                if product_currency != move.company_id.currency_id.id:
-                    new_price = currency_obj.compute(cr, uid, product_currency, move.company_id.currency_id.id, 
-                                                 product_price, round=False)
-                else:
-                    new_price = product_price
+                if product_price > 0.0:
+                    if product_currency != move.company_id.currency_id.id:
+                        new_price = currency_obj.compute(cr, uid, product_currency, move.company_id.currency_id.id, 
+                                                     product_price, round=False)
+                    else:
+                        new_price = product_price
+                else: 
+                    if product_uom != uom_id:
+                        new_price = uom_obj._compute_price(cr, uid, uom_id, new_price,
+                            product_uom)
+                    else:
+                        new_price = product.standard_price
                 self.write(cr, uid, [move.id],
                             {'price_unit': new_price,
                              'price_currency_id': move.company_id.currency_id.id})
@@ -196,7 +207,8 @@ class stock_move_matching(osv.osv):
     _columns = {
         'move_in_id': fields.many2one('stock.move', 'Stock move in', required=True),
         'move_out_id': fields.many2one('stock.move', 'Stock move out', required=True),
-        'qty': fields.integer('Quantity', required=True), 
+        'qty': fields.float('Quantity', required=True), 
         'price_unit':fields.related('move_in_id', 'price_unit', string="Unit price", type="float"),
+        'price_unit_out': fields.float('Unit price out') 
     }
 
index 98c6484..4ad2754 100644 (file)
     partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
     self.do_partial(cr, uid, [partial_id])
 - 
+  A purchase order towards the Chicago shop
+- 
+  !record {model: purchase.order, id: purchase_order_fifo_comp}:
+    partner_id: base.res_partner_3
+    company_id: stock.res_company_1
+    location_id: stock.stock_location_shop0
+    pricelist_id: 1
+    order_line:
+      - product_id: product_fifo_icecream
+        product_qty: 35.0
+        product_uom: product.product_uom_categ_kgm
+        price_unit: 50.0
+        name: 'FIFO Ice Cream'
+- 
+  I confirm the Chicago Shop company's purchase order'
+- 
+  !workflow {model: purchase.order, action: purchase_confirm, ref: purchase_order_fifo_comp}
+- 
+  I receive the Chicago Shop company's purchase order'
+- 
+  !python {model: stock.partial.picking}: |
+    pick_ids = self.pool.get('purchase.order').browse(cr, uid, ref("purchase_order_fifo_comp")).picking_ids
+    partial_id = self.create(cr, uid, {}, context={'active_model': 'stock.picking','active_ids': [pick_ids[0].id]})
+    self.do_partial(cr, uid, [partial_id])
+- 
   Check the standard price should not have changed
 - 
   !python {model: product.product}: |
   !python {model: product.product}: |
     print self.browse(cr, uid, ref("product_fifo_icecream")).standard_price
     print self.browse(cr, uid, ref("product_fifo_icecream")).qty_available
+    print self.browse(cr, uid, ref("product_fifo_icecream"), context={'force_company': 1}).qty_available
     list = self.pool.get("stock.move").search(cr, uid, [('product_id','=', ref("product_fifo_icecream"))])
     for move in self.pool.get("stock.move").browse(cr, uid, list):
       print move.price_unit, move.product_qty, move.qty_remaining, move.type, move.date
\ No newline at end of file