[REF] product: do not use selected_seller_id

The function field selected_seller_id is removed  and must be replaced
by a direct call to method `_select_seller`. This is more conventional
than the previous 'browse with context' way of doing.
This commit is contained in:
Nicolas Martinelli
2015-09-25 11:34:01 +02:00
parent b65c67a259
commit 9577f4e419
6 changed files with 119 additions and 150 deletions
+22 -22
View File
@@ -904,28 +904,29 @@ class product_product(osv.osv):
result[product.id] = price_extra
return result
def _select_seller(self, cr, uid, ids, name, arg, context=None):
def _select_seller(self, cr, uid, product_id, partner_id=False, quantity=0.0, date=time.strftime(DEFAULT_SERVER_DATE_FORMAT), uom_id=False, context=None):
if context is None:
context = {}
res = {}
partner = context.get('partner_id')
minimal_quantity = context.get('quantity', 0.0)
date = context.get('date', time.strftime(DEFAULT_SERVER_DATE_FORMAT))
for product in self.browse(cr, uid, ids, context=context):
res[product.id] = False
for seller in product.seller_ids:
if seller.date_start and seller.date_start > date:
continue
if seller.date_end and seller.date_end < date:
continue
if partner and seller.name.id != partner:
continue
if minimal_quantity and minimal_quantity < seller.qty:
continue
if seller.product_id and seller.product_id != product:
continue
res[product.id] = seller
break
res = self.pool.get('product.supplierinfo').browse(cr, uid, [])
for seller in product_id.seller_ids:
# Set quantity in UoM of seller
quantity_uom_seller = quantity
if quantity_uom_seller and uom_id and uom_id != seller.product_uom:
quantity_uom_seller = uom_id._compute_qty_obj(uom_id, quantity_uom_seller, seller.product_uom)
if seller.date_start and seller.date_start > date:
continue
if seller.date_end and seller.date_end < date:
continue
if partner_id and seller.name != partner_id:
continue
if quantity_uom_seller and quantity_uom_seller < seller.qty:
continue
if seller.product_id and seller.product_id != product_id:
continue
res |= seller
break
return res
_columns = {
@@ -964,7 +965,6 @@ class product_product(osv.osv):
groups="base.group_user", string="Cost"),
'volume': fields.float('Volume', help="The volume in m3."),
'weight': fields.float('Gross Weight', digits_compute=dp.get_precision('Stock Weight'), help="The weight of the contents in Kg, not including any packaging, etc."),
'selected_seller_id': fields.function(_select_seller, type='many2one', relation='product.supplierinfo', string='Selected Seller', help='Technical field that selects a seller based on priority (sequence) and an optional partner and/or a minimal quantity in the context'),
}
_defaults = {
@@ -1236,7 +1236,7 @@ class product_supplierinfo(osv.osv):
'product_tmpl_id': fields.many2one('product.template', 'Product Template', ondelete='cascade', select=True, oldname='product_id'),
'delay': fields.integer('Delivery Lead Time', required=True, help="Lead time in days between the confirmation of the purchase order and the receipt of the products in your warehouse. Used by the scheduler for automatic computation of the purchase order planning."),
'company_id': fields.many2one('res.company', string='Company', select=1),
'product_id': fields.many2one('product.product', string='Product Variant'),
'product_id': fields.many2one('product.product', string='Product Variant', help="When this field is filled in, the vendor data will only apply to the variant."),
}
_defaults = {
'min_qty': 0.0,
+4 -4
View File
@@ -51,17 +51,17 @@
-
!python {model: product.product}: |
from openerp.tools import float_compare
context.update({'quantity':1, 'date': False, 'partner_id': ref('base.res_partner_4')})
product = self.browse(cr, uid, ref("product_product_6"), context=context)
assert float_compare(product.selected_seller_id.price, 790, precision_digits=2) == 0, "Wrong cost price: LCD Monitor."
partner = self.pool.get('res.partner').browse(cr, uid, ref('base.res_partner_4'), context=context)
assert float_compare(product._select_seller(product, partner_id=partner, quantity=1.0).price, 790, precision_digits=2) == 0, "Wrong cost price: LCD Monitor."
-
I check cost price of LCD Monitor if more than 3 Unit.
-
!python {model: product.product}: |
from openerp.tools import float_compare
context.update({'quantity':3})
product = self.browse(cr, uid, ref("product_product_6"), context=context)
assert float_compare(product.selected_seller_id.price, 785, precision_digits=2) == 0, "Wrong cost price: LCD Monitor if more than 3 Unit."
partner = self.pool.get('res.partner').browse(cr, uid, ref('base.res_partner_4'), context=context)
assert float_compare(product._select_seller(product, partner_id=partner, quantity=3.0).price, 785, precision_digits=2) == 0, "Wrong cost price: LCD Monitor if more than 3 Unit."
-
I print the sale prices report.
-
+63 -109
View File
@@ -531,7 +531,7 @@ class PurchaseOrderLine(models.Model):
return super(PurchaseOrderLine, self).unlink()
@api.model
def _get_date_planned(self, product, po=False):
def _get_date_planned(self, seller, po=False):
"""Return the datetime value to use as Schedule Date (``date_planned``) for
PO Lines that correspond to the given product.seller_ids,
when ordered at `date_order_str`.
@@ -543,15 +543,11 @@ class PurchaseOrderLine(models.Model):
:rtype: datetime
:return: desired Schedule Date for the PO line
"""
supplier_delay = int(product.selected_seller_id.delay) if product else 0
if po:
date_order = po.date_order
else:
date_order = self.order_id.date_order
date_order = po.date_order if po else self.order_id.date_order
if date_order:
return datetime.strptime(date_order, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=supplier_delay)
return datetime.strptime(date_order, DEFAULT_SERVER_DATETIME_FORMAT) + relativedelta(days=seller.delay if seller else 0)
else:
return datetime.today() + relativedelta(days=supplier_delay)
return datetime.today() + relativedelta(days=seller.delay if seller else 0)
@api.onchange('product_id', 'product_qty', 'product_uom')
def onchange_product_id(self):
@@ -563,18 +559,27 @@ class PurchaseOrderLine(models.Model):
self.product_uom = self.product_id.uom_po_id
result['domain'] = {'product_uom': [('category_id', '=', self.product_id.uom_id.category_id.id)]}
res = self._get_name_price_quantity_date(
seller = self.product_id._select_seller(
self.product_id,
self.partner_id,
self.order_id.date_order and self.order_id.date_order[:10],
self.product_qty,
self.product_uom,
self.order_id.currency_id)
partner_id=self.partner_id,
quantity=self.product_qty,
date=self.order_id.date_order and self.order_id.date_order[:10],
uom_id=self.product_uom)
self.name = res['name']
self.product_qty = res['quantity'] if not res['quantity'] else max(self.product_qty, res['quantity'])
self.price_unit = res['price_unit']
self.date_planned = res['date_planned']
price_unit = seller.price if seller else 0.0
if price_unit and seller and self.order_id.currency_id and seller.currency_id != self.order_id.currency_id:
price_unit = seller.currency_id.compute(price_unit, self.order_id.currency_id)
self.price_unit = price_unit
self.date_planned = self._get_date_planned(seller).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
product_lang = self.product_id.with_context({
'lang': self.partner_id.lang,
'partner_id': self.partner_id.id,
})
self.name = product_lang.display_name
if product_lang.description_purchase:
self.name += '\n' + product_lang.description_purchase
taxes = self.product_id.supplier_taxes_id
fpos = self.order_id.fiscal_position_id
@@ -591,67 +596,6 @@ class PurchaseOrderLine(models.Model):
return result
@api.model
def _get_name_price_quantity_date(self, product_id, partner_id, date, quantity, product_uom, currency_id, order_id=False):
"""Return the name of the product, the seller quantity, the unit price and
the date planned of a given product.
:param browse_record product_id: product.product, for which we want to
get the information
:param browse_record partner_id: res.partner, supplier of the product
:param str date: order date
:param float quantity: quantity of product in product_uom UoM
:param browse_record product_uom: product.uom, product_uom UoM in which is
expressed the quantity
:param browse_record currency_id: res.currency, currency in which we want the price
:param browse_record | False order_id: purchase.order, purchase order in case we
try to get the data for a PO line not yet attached to a PO.
:rtype: dict
:return: name, seller quantity, seller price, date planned
"""
# This is useful in case partner is not registered supplier
if not product_id or not partner_id or not product_uom or not currency_id:
return {
'name': False,
'quantity': 0.0,
'price_unit': 0.0,
'date_planned': False,
}
# The first browse is used to know the uom_id and the currency_id for the given vendor
product = product_id.with_context({'partner_id': partner_id.id})
seller_currency_id = product.selected_seller_id.currency_id if product.selected_seller_id else partner_id.currency_id
seller_product_uom = product.selected_seller_id.product_uom if product.selected_seller_id else product_id.uom_id
# Switch quantity to uom_id
quantity_seller_uom_id = quantity
if quantity_seller_uom_id and seller_product_uom != product_uom:
quantity_seller_uom_id = product_uom._compute_qty_obj(product_uom, quantity_seller_uom_id, seller_product_uom)
product = product_id.with_context({
'lang': partner_id.lang,
'partner_id': partner_id.id,
'date': date,
'quantity': quantity_seller_uom_id,
})
price_unit = product.selected_seller_id.price
if price_unit and seller_currency_id != currency_id:
price_unit = seller_currency_id.compute(price_unit, currency_id)
date_planned = self._get_date_planned(product, po=order_id).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
name = product.display_name
if product.description_purchase:
name += '\n' + product.description_purchase
return {
'name': name,
'quantity': quantity,
'price_unit': price_unit,
'date_planned': date_planned,
}
class ProcurementRule(models.Model):
_inherit = 'procurement.rule'
@@ -684,16 +628,16 @@ class ProcurementOrder(models.Model):
precision = self.env['decimal.precision'].precision_get('Product Unit of Measure')
if not float_is_zero(product_qty, precision_digits=precision):
res = self.env['purchase.order.line']._get_name_price_quantity_date(
seller = procurement.product_id._select_seller(
procurement.product_id,
procurement.purchase_line_id.partner_id,
procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id.date_order[:10],
product_qty,
procurement.product_uom,
procurement.purchase_line_id.order_id.currency_id)
partner_id=procurement.purchase_line_id.partner_id,
quantity=product_qty,
date=procurement.purchase_line_id.order_id.date_order and procurement.purchase_line_id.order_id.date_order[:10],
uom_id=procurement.product_uom)
product_qty = res['quantity']
price_unit = res['price_unit']
price_unit = seller.price if seller else 0.0
if price_unit and seller and procurement.purchase_line_id.order_id.currency_id and seller.currency_id != procurement.purchase_line_id.order_id.currency_id:
price_unit = seller.currency_id.compute(price_unit, procurement.purchase_line_id.order_id.currency_id)
procurement.purchase_line_id.product_qty = product_qty
procurement.purchase_line_id.price_unit = price_unit
@@ -736,7 +680,7 @@ class ProcurementOrder(models.Model):
@api.v8
def _get_purchase_order_date(self, schedule_date):
self.ensure_one()
seller_delay = int(self.product_id.selected_seller_id.delay)
seller_delay = int(self.product_id._select_seller(self.product_id).delay)
return schedule_date - relativedelta(days=seller_delay)
@api.v7
@@ -750,26 +694,33 @@ class ProcurementOrder(models.Model):
:rtype: datetime
:return: the desired Order Date for the PO
"""
seller_delay = int(procurement.product_id.selected_seller_id.delay)
seller_delay = int(procurement.product_id._select_seller(procurement.product_id).delay)
return schedule_date - relativedelta(days=seller_delay)
@api.multi
def _prepare_purchase_order_line(self, po, supplier):
self.ensure_one()
res = self.env['purchase.order.line']._get_name_price_quantity_date(
seller = self.product_id._select_seller(
self.product_id,
supplier.name,
po.date_order and po.date_order[:10],
self.product_qty,
self.product_uom,
po.currency_id,
order_id=po)
partner_id=supplier.name,
quantity=self.product_qty,
date=po.date_order and po.date_order[:10],
uom_id=self.product_uom)
name = res['name']
product_qty = res['quantity']
price_unit = res['price_unit']
date_planned = res['date_planned']
price_unit = seller.price if seller else 0.0
if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id:
price_unit = seller.currency_id.compute(price_unit, po.currency_id)
product_lang = self.product_id.with_context({
'lang': supplier.name.lang,
'partner_id': supplier.name.id,
})
name = product_lang.display_name
if product_lang.description_purchase:
name += '\n' + product_lang.description_purchase
date_planned = self.env['purchase.order.line']._get_date_planned(seller, po=po).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
taxes = self.product_id.supplier_taxes_id
fpos = po.fiscal_position_id
@@ -777,7 +728,7 @@ class ProcurementOrder(models.Model):
return {
'name': name,
'product_qty': product_qty,
'product_qty': self.product_qty,
'product_id': self.product_id.id,
'product_uom': self.product_uom.id,
'price_unit': price_unit,
@@ -844,17 +795,20 @@ class ProcurementOrder(models.Model):
po_line = False
for line in po.order_line:
if line.product_id == procurement.product_id and line.product_uom == procurement.product_uom:
res = self.env['purchase.order.line']._get_name_price_quantity_date(
seller = self.product_id._select_seller(
self.product_id,
partner,
po.date_order and po.date_order[:10],
line.product_qty + procurement.product_qty,
self.product_uom,
po.currency_id)
partner_id=partner,
quantity=line.product_qty + procurement.product_qty,
date=po.date_order and po.date_order[:10],
uom_id=self.product_uom)
price_unit = seller.price if seller else 0.0
if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id:
price_unit = seller.currency_id.compute(price_unit, po.currency_id)
po_line = line.write({
'product_qty': res['quantity'],
'price_unit': res['price_unit'],
'product_qty': line.product_qty + procurement.product_qty,
'price_unit': price_unit,
'procurement_ids': [(4, procurement.id)]
})
if not po_line:
+6 -2
View File
@@ -62,8 +62,12 @@ class TestPurchaseOrder(AccountingTestCase):
self.assertEqual(self.po.invoice_status, 'to invoice', 'Purchase: PO invoice_status should be "Waiting Invoices"')
self.assertTrue(self.product_id_2.seller_ids.filtered(lambda r: r.name == self.partner_id), 'Purchase: the partner should be in the list of the product suppliers')
res = self.PurchaseOrderLine._get_name_price_quantity_date(self.product_id_2, self.partner_id, self.po.date_planned, 2.0, self.product_id_2.uom_po_id, self.po.currency_id)
self.assertEqual(res['price_unit'], 250.0, 'Purchase: the price of the product for the suppleir should be 250.0.')
seller = self.product_id_2._select_seller(self.product_id_2, partner_id=self.partner_id, quantity=2.0, date=self.po.date_planned, uom_id=self.product_id_2.uom_po_id)
price_unit = seller.price if seller else 0.0
if price_unit and seller and self.po.currency_id and seller.currency_id != self.po.currency_id:
price_unit = seller.currency_id.compute(price_unit, self.po.currency_id)
self.assertEqual(price_unit, 250.0, 'Purchase: the price of the product for the supplier should be 250.0.')
self.assertEqual(self.po.picking_count, 1, 'Purchase: one picking should be created"')
self.picking = self.po.picking_ids[0]
@@ -147,24 +147,35 @@ class purchase_requisition(osv.osv):
taxes_id = fpos.map_tax(taxes) if fpos else []
po = po_obj.browse(cr, uid, [purchase_id], context=context)
res = po_line_obj._get_name_price_quantity_date(cr, uid,
seller = requisition_line.product_id._select_seller(
requisition_line.product_id,
supplier,
date_order and date_order[:10],
qty,
product.uom_po_id,
po.currency_id,
order_id=po,
context=context)
partner_id=supplier,
quantity=qty,
date=date_order and date_order[:10],
uom_id=product.uom_po_id)
price_unit = seller.price if seller else 0.0
if price_unit and seller and po.currency_id and seller.currency_id != po.currency_id:
price_unit = seller.currency_id.compute(price_unit, po.currency_id)
date_planned = po_line_obj._get_date_planned(cr, uid, seller, po=po, context=context).strftime(DEFAULT_SERVER_DATETIME_FORMAT)
product_lang = requisition_line.product_id.with_context({
'lang': supplier.lang,
'partner_id': supplier.id,
})
name = product_lang.display_name
if product_lang.description_purchase:
name += '\n' + product_lang.description_purchase
vals = {
'name': res['name'],
'name': name,
'order_id': purchase_id,
'product_qty': res['quantity'],
'product_qty': qty,
'product_id': product.id,
'product_uom': default_uom_po_id,
'price_unit': res['price_unit'],
'date_planned': res['date_planned'],
'price_unit': price_unit,
'date_planned': date_planned,
'taxes_id': [(6, 0, taxes_id)],
'account_analytic_id': requisition_line.account_analytic_id.id,
}
+1 -1
View File
@@ -425,7 +425,7 @@ class procurement_order(osv.osv):
days = orderpoint.lead_days or 0.0
if orderpoint.lead_type=='purchase':
# These days will be substracted when creating the PO
days += orderpoint.product_id.selected_seller_id.delay or 0.0
days += orderpoint.product_id._select_seller(orderpoint.product_id).delay or 0.0
date_planned = start_date + relativedelta(days=days)
return date_planned.strftime(DEFAULT_SERVER_DATE_FORMAT)