diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 54fb2267368..bb748d68329 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -700,97 +700,89 @@ class purchase_order_line(osv.osv): #TOFIX: # - name of method should "onchange_product_id" # - docstring - # - merge 'product_uom_change' method - # - split into small internal methods for clearity - def product_id_change(self, cr, uid, ids, pricelist, product, qty, uom, - partner_id, date_order=False, fiscal_position=False, date_planned=False, - name=False, price_unit=False, notes=False, context={}): - if not pricelist: + # - split into small internal methods for clearity + def product_id_change(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id, + partner_id, date_order=False, fiscal_position_id=False, date_planned=False, + name=False, price_unit=False, notes=False, context=None): + if context is None: + context = {} + + res = {'price_unit': price_unit or 0.0, 'name': name or '', 'notes': notes or'', 'product_uom' : uom_id or False} + uom_change = context.get('uom_change', False) + + if not pricelist_id: raise osv.except_osv(_('No Pricelist !'), _('You have to select a pricelist or a supplier in the purchase form !\nPlease set one before choosing a product.')) - if not partner_id: + if not partner_id: raise osv.except_osv(_('No Partner!'), _('You have to select a partner in the purchase form !\nPlease set one partner before choosing a product.')) - if not product: - return {'value': {'price_unit': price_unit or 0.0, 'name': name or '', - 'notes': notes or'', 'product_uom' : uom or False}, 'domain':{'product_uom':[]}} - res = {} - prod= self.pool.get('product.product').browse(cr, uid, product) + if not product_id: + return {'value': res} + + product_uom_pool = self.pool.get('product.uom') - lang=False - if partner_id: - lang=self.pool.get('res.partner').read(cr, uid, partner_id, ['lang'])['lang'] - context={'lang':lang} + product_supplierinfo = self.pool.get('product.supplierinfo') + res_partner = self.pool.get('res.partner') + product_product = self.pool.get('product.product') + account_fiscal_position = self.pool.get('account.fiscal.position') + account_tax = self.pool.get('account.tax') + + # set supplier langauage in context + lang = res_partner.browse(cr, uid, partner_id).lang + if lang: + context['lang'] = lang context['partner_id'] = partner_id - prod = self.pool.get('product.product').browse(cr, uid, product, context=context) - prod_uom_po = prod.uom_po_id.id - if not uom: - uom = prod_uom_po + product = product_product.browse(cr, uid, product_id, context=context) + domain = {'product_uom':[('category_id','=',product.uom_id.category_id.id)]} + res['domain'] = domain + + if uom_change and not uom_id: + return {'value': res} + + product_uom_po_id = product.uom_po_id.id + if not uom_id: + uom_id = product_uom_po_id + + # checking UOM category + if product.uom_id.category_id.id != product_uom_pool.browse(cr, uid, uom_id).category_id.id: + res.update({'warning': {'title': _('Warning'), 'message': _('Selected UOM does not have same category of default UOM')}}) + uom_id = product_uom_po_id + if not date_order: date_order = time.strftime('%Y-%m-%d') + qty = qty or 1.0 seller_delay = 0 - if uom: - uom1_cat = prod.uom_id.category_id.id - uom2_cat = product_uom_pool.browse(cr, uid, uom).category_id.id - if uom1_cat != uom2_cat: - uom = False - - prod_name = self.pool.get('product.product').name_get(cr, uid, [prod.id], context=context)[0][1] - res = {} - for s in prod.seller_ids: - if s.name.id == partner_id: - seller_delay = s.delay - if s.product_uom: - temp_qty = product_uom_pool._compute_qty(cr, uid, s.product_uom.id, s.min_qty, to_uom_id=prod.uom_id.id) - uom = s.product_uom.id #prod_uom_po - temp_qty = s.min_qty # supplier _qty assigned to temp - if qty < temp_qty: # If the supplier quantity is greater than entered from user, set minimal. - qty = temp_qty - res.update({'warning': {'title': _('Warning'), 'message': _('The selected supplier has a minimal quantity set to %s, you should not purchase less.') % qty}}) - qty_in_product_uom = product_uom_pool._compute_qty(cr, uid, uom, qty, to_uom_id=prod.uom_id.id) - price = self.pool.get('product.pricelist').price_get(cr,uid,[pricelist], - product, qty_in_product_uom or 1.0, partner_id, { - 'uom': uom, + + supplierinfo_ids = product_supplierinfo.search(cr, uid, [('name','=',partner_id),('product_id','=',product.id)]) + for supplierinfo in product_supplierinfo.browse(cr, uid, supplierinfo_ids, context=context): + seller_delay = supplierinfo.delay + if supplierinfo.product_uom.id != uom_id: + res.update({'warning': {'title': _('Warning'), 'message': _('The selected supplier only sells this product by %s') % supplierinfo.product_uom.name }}) + min_qty = product_uom_pool._compute_qty(cr, uid, supplierinfo.product_uom.id, supplierinfo.min_qty, to_uom_id=uom_id) + if qty < min_qty: # If the supplier quantity is greater than entered from user, set minimal. + res.update({'warning': {'title': _('Warning'), 'message': _('The selected supplier has a minimal quantity set to %s %s, you should not purchase less.') % (supplierinfo.min_qty, supplierinfo.product_uom.name)}}) + qty = min_qty + + price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist_id], + product.id, qty or 1.0, partner_id, { + 'uom': uom_id, 'date': date_order, - })[pricelist] + })[pricelist_id] dt = (datetime.now() + relativedelta(days=int(seller_delay) or 0.0)).strftime('%Y-%m-%d %H:%M:%S') - res.update({'value': {'price_unit': price, 'name': prod_name, - 'taxes_id':map(lambda x: x.id, prod.supplier_taxes_id), - 'date_planned': date_planned or dt,'notes': notes or prod.description_purchase, + res.update({'value': {'price_unit': price, 'name': product.name, + 'taxes_id':map(lambda x: x.id, product.supplier_taxes_id), + 'date_planned': date_planned or dt,'notes': notes or product.description_purchase, 'product_qty': qty, - 'product_uom': prod.uom_id.id}}) - domain = {} + 'product_uom': uom_id}}) - taxes = self.pool.get('account.tax').browse(cr, uid,map(lambda x: x.id, prod.supplier_taxes_id)) - fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False - res['value']['taxes_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, taxes) - res2 = self.pool.get('product.uom').read(cr, uid, [prod.uom_id.id], ['category_id']) - res3 = prod.uom_id.category_id.id - domain = {'product_uom':[('category_id','=',res2[0]['category_id'][0])]} - if res2[0]['category_id'][0] != res3: - raise osv.except_osv(_('Wrong Product UOM !'), _('You have to select a product UOM in the same category than the purchase UOM of the product')) - - res['domain'] = domain + taxes = account_tax.browse(cr, uid, map(lambda x: x.id, product.supplier_taxes_id)) + fpos = fiscal_position_id and account_fiscal_position.browse(cr, uid, fiscal_position_id, context=context) or False + res['value']['taxes_id'] = account_fiscal_position.map_tax(cr, uid, fpos, taxes) return res - #TOFIX: - # - merge into 'product_id_change' method - def product_uom_change(self, cr, uid, ids, pricelist, product, qty, uom, - partner_id, date_order=False, fiscal_position=False, date_planned=False, - name=False, price_unit=False, notes=False, context={}): - res = self.product_id_change(cr, uid, ids, pricelist, product, qty, uom, - partner_id, date_order=date_order, fiscal_position=fiscal_position, date_planned=date_planned, - name=name, price_unit=price_unit, notes=notes, context=context) - if 'product_uom' in res['value']: - if uom and (uom != res['value']['product_uom']) and res['value']['product_uom']: - seller_uom_name = self.pool.get('product.uom').read(cr, uid, [res['value']['product_uom']], ['name'])[0]['name'] - res.update({'warning': {'title': _('Warning'), 'message': _('The selected supplier only sells this product by %s') % seller_uom_name }}) - del res['value']['product_uom'] - if not uom: - res['value']['price_unit'] = 0.0 - return res + product_uom_change = product_id_change def action_confirm(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'confirmed'}, context=context) diff --git a/addons/purchase/purchase_order_demo.yml b/addons/purchase/purchase_order_demo.yml index abfaa102033..4ff5b377662 100644 --- a/addons/purchase/purchase_order_demo.yml +++ b/addons/purchase/purchase_order_demo.yml @@ -74,3 +74,12 @@ - product_id: product.product_product_1 product_qty: 15 +- + !record {model: product.product, id: stock.product_icecream}: + uom_id: product.product_uom_gram +- + !record {model: purchase.order, id: order_purchase_icecream}: + partner_id: base.res_partner_asus + order_line: + - product_id: stock.product_icecream + diff --git a/addons/purchase/purchase_view.xml b/addons/purchase/purchase_view.xml index 1516ea729c0..14f5354f970 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -361,7 +361,7 @@ - + diff --git a/addons/stock/stock_demo.yml b/addons/stock/stock_demo.yml index 99cde47b843..4a1cb831b41 100644 --- a/addons/stock/stock_demo.yml +++ b/addons/stock/stock_demo.yml @@ -42,8 +42,10 @@ uom_po_id: product.product_uom_kgm procure_method: make_to_stock property_stock_inventory: location_opening - property_stock_account_input: location_refrigerator - property_stock_account_output: location_delivery_counter + valuation: real_time + cost_method: average + property_stock_account_input: account.o_expense + property_stock_account_output: account.o_income description: Ice cream can be mass-produced and thus is widely available in developed parts of the world. Ice cream can be purchased in large cartons (vats and squrounds) from supermarkets and grocery stores, in smaller quantities from ice cream shops, convenience stores, and milk bars, and in individual servings from small carts or vans at public events. - diff --git a/addons/stock/test/shipment.yml b/addons/stock/test/shipment.yml index dad6edd78a5..6482668bfae 100644 --- a/addons/stock/test/shipment.yml +++ b/addons/stock/test/shipment.yml @@ -149,6 +149,23 @@ assert move.prodlot_id.name in ['incoming_lot0', 'incoming_lot1', 'incoming_lot2', 'incoming_lot3'], "lot is not correspond." assert move.product_qty == 10, "qty is not correspond per production lot." context.update({'active_model':'stock.move', 'active_id':move_ids[0],'active_ids': move_ids}) +- + I check the stock valuation account entries. +- + !python {model: account.move}: | + incomming_shipment = self.pool.get('stock.picking').browse(cr, uid, ref('incomming_shipment'), context=context) + account_move_ids = self.search(cr, uid, [('ref','=',incomming_shipment.name)]) + assert len(account_move_ids), "account move should be created." + account_move = self.browse(cr, uid, account_move_ids[0], context=context) + assert len(account_move.line_id) == len(incomming_shipment.move_lines) + 1, 'accuont entries are not correspond.' + for account_move_line in account_move.line_id: + for stock_move in incomming_shipment.move_lines: + if account_move_line.account_id.id == stock_move.product_id.property_stock_account_input.id: + assert account_move_line.credit == 800.0, "Credit amount is not correspond." + assert account_move_line.debit == 0.0, "Debit amount is not correspond." + else: + assert account_move_line.credit == 0.0, "Credit amount is not correspond." + assert account_move_line.debit == 800.0, "Debit amount is not correspond." - I consume 1 kgm ice-cream from each incoming lots into internal production. -