diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 6dd6db4085a..e91071a8e3f 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -697,100 +697,97 @@ class purchase_order_line(osv.osv): default.update({'state':'draft', 'move_ids':[],'invoiced':0,'invoice_lines':[]}) return super(purchase_order_line, self).copy_data(cr, uid, id, default, context) - #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: + def onchange_product_uom(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): + """ + onchange handler of product_uom. + """ + if not uom_id: + return {'value': {'price_unit': price_unit or 0.0, 'name': name or '', 'notes': notes or'', 'product_uom' : uom_id or False}} + return self.onchange_product_id(cr, uid, ids, pricelist_id, product_id, qty, uom_id, + partner_id, date_order=date_order, fiscal_position_id=fiscal_position_id, date_planned=date_planned, + name=name, price_unit=price_unit, notes=notes, context=context) + + def onchange_product_id(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): + """ + onchange handler of product_id. + """ + if context is None: + context = {} + + res = {'value': {'price_unit': price_unit or 0.0, 'name': name or '', 'notes': notes or '', 'product_uom' : uom_id or False}} + if not product_id: + return res + + product_product = self.pool.get('product.product') + product_uom = self.pool.get('product.uom') + res_partner = self.pool.get('res.partner') + product_supplierinfo = self.pool.get('product.supplierinfo') + product_pricelist = self.pool.get('product.pricelist') + account_fiscal_position = self.pool.get('account.fiscal.position') + account_tax = self.pool.get('account.tax') + + # - check for the presence of partner_id and pricelist_id + 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) - 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'] + # - determine name and notes based on product in partner lang. + lang = res_partner.browse(cr, uid, partner_id).lang context_partner = {'lang': lang, 'partner_id': partner_id} + product = product_product.browse(cr, uid, product_id, context=context_partner) + res['value'].update({'name': product.name, 'notes': notes or product.description_purchase}) + + # - set a domain on product_uom + res['domain'] = {'product_uom': [('category_id','=',product.uom_id.category_id.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 + # - check that uom and product uom belong to the same category + product_uom_po_id = product.uom_po_id.id + if not uom_id: + uom_id = product_uom_po_id + + if product.uom_id.category_id.id != product_uom.browse(cr, uid, uom_id, context=context).category_id.id: + res['warning'] = {'title': _('Warning'), 'message': _('Selected UOM does not belong to the same category as the product UOM')} + uom_id = product_uom_po_id + + res['value'].update({'product_uom': uom_id}) + + # - determine product_qty and date_planned based on seller info 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 + 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['warning'] = {'title': _('Warning'), 'message': _('The selected supplier only sells this product by %s') % supplierinfo.product_uom.name } + min_qty = product_uom._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['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 - prod_name = self.pool.get('product.product').name_get(cr, uid, [prod.id], context=context_partner)[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, - 'date': date_order, - })[pricelist] - dt = (datetime.now() + relativedelta(days=int(seller_delay) or 0.0)).strftime('%Y-%m-%d %H:%M:%S') + dt = (datetime.strptime(date_order, '%Y-%m-%d') + relativedelta(days=int(seller_delay) or 0.0)).strftime('%Y-%m-%d %H:%M:%S') + res['value'].update({'date_planned': date_planned or dt, 'product_qty': qty}) + # - determine price_unit and taxes_id + price = product_pricelist.price_get(cr, uid, [pricelist_id], + product.id, qty or 1.0, partner_id, {'uom': uom_id, 'date': date_order})[pricelist_id] + + 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 + taxes_ids = account_fiscal_position.map_tax(cr, uid, fpos, taxes) + res['value'].update({'price_unit': price, 'taxes_id': taxes_ids}) - 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, - 'product_qty': qty, - 'product_uom': prod.uom_id.id}}) - domain = {} - - 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 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_id_change = onchange_product_id + product_uom_change = onchange_product_uom 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 736d1cf87d7..ec53ae76a7a 100644 --- a/addons/purchase/purchase_view.xml +++ b/addons/purchase/purchase_view.xml @@ -359,9 +359,9 @@