From a2ad095f6140d9a42bd59c98d0fc4672529b228a Mon Sep 17 00:00:00 2001 From: sebastien beau Date: Wed, 11 Jul 2012 02:23:33 +0200 Subject: [PATCH 1/5] [REF] product: refactor move function field on variant in order to allow to move the seller_ids from the template to the variant easily bzr revid: sebastien.beau@akretion.com.br-20120711002333-frtn37s96ovjahkp --- addons/product/product.py | 68 ++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/addons/product/product.py b/addons/product/product.py index a81074aa56e..091c76db44b 100644 --- a/addons/product/product.py +++ b/addons/product/product.py @@ -258,32 +258,6 @@ class product_template(osv.osv): _name = "product.template" _description = "Product Template" - def _get_main_product_supplier(self, cr, uid, product, context=None): - """Determines the main (best) product supplier for ``product``, - returning the corresponding ``supplierinfo`` record, or False - if none were found. The default strategy is to select the - supplier with the highest priority (i.e. smallest sequence). - - :param browse_record product: product to supply - :rtype: product.supplierinfo browse_record or False - """ - sellers = [(seller_info.sequence, seller_info) - for seller_info in product.seller_ids or [] - if seller_info and isinstance(seller_info.sequence, (int, long))] - return sellers and sellers[0][1] or False - - def _calc_seller(self, cr, uid, ids, fields, arg, context=None): - result = {} - for product in self.browse(cr, uid, ids, context=context): - main_supplier = self._get_main_product_supplier(cr, uid, product, context=context) - result[product.id] = { - 'seller_info_id': main_supplier and main_supplier.id or False, - 'seller_delay': main_supplier and main_supplier.delay or 1, - 'seller_qty': main_supplier and main_supplier.qty or 0.0, - 'seller_id': main_supplier and main_supplier.name.id or False - } - return result - _columns = { 'name': fields.char('Name', size=128, required=True, translate=True, select=True), 'product_manager': fields.many2one('res.users','Product Manager',help="This is use as task responsible"), @@ -320,11 +294,7 @@ class product_template(osv.osv): help='Coefficient to convert Unit of Measure to UOS\n' ' uos = uom * coeff'), 'mes_type': fields.selection((('fixed', 'Fixed'), ('variable', 'Variable')), 'Measure Type', required=True), - 'seller_info_id': fields.function(_calc_seller, type='many2one', relation="product.supplierinfo", multi="seller_info"), - 'seller_delay': fields.function(_calc_seller, type='integer', string='Supplier Lead Time', multi="seller_info", help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."), - 'seller_qty': fields.function(_calc_seller, type='float', string='Supplier Quantity', multi="seller_info", help="This is minimum quantity to purchase from Main Supplier."), - 'seller_id': fields.function(_calc_seller, type='many2one', relation="res.partner", string='Main Supplier', help="Main Supplier who has highest priority in Supplier List.", multi="seller_info"), - 'seller_ids': fields.one2many('product.supplierinfo', 'product_id', 'Partners'), + 'seller_ids': fields.one2many('product.supplierinfo', 'product_template_id', 'Partners'), 'loc_rack': fields.char('Rack', size=16), 'loc_row': fields.char('Row', size=16), 'loc_case': fields.char('Case', size=16), @@ -491,6 +461,34 @@ class product_product(osv.osv): res[p.id] = (data['code'] and ('['+data['code']+'] ') or '') + \ (data['name'] or '') + (data['variants'] and (' - '+data['variants']) or '') return res + + + def _get_main_product_supplier(self, cr, uid, product, context=None): + """Determines the main (best) product supplier for ``product``, + returning the corresponding ``supplierinfo`` record, or False + if none were found. The default strategy is to select the + supplier with the highest priority (i.e. smallest sequence). + + :param browse_record product: product to supply + :rtype: product.supplierinfo browse_record or False + """ + sellers = [(seller_info.sequence, seller_info) + for seller_info in product.seller_ids or [] + if seller_info and isinstance(seller_info.sequence, (int, long))] + return sellers and sellers[0][1] or False + + def _calc_seller(self, cr, uid, ids, fields, arg, context=None): + result = {} + for product in self.browse(cr, uid, ids, context=context): + main_supplier = self._get_main_product_supplier(cr, uid, product, context=context) + result[product.id] = { + 'seller_info_id': main_supplier and main_supplier.id or False, + 'seller_delay': main_supplier and main_supplier.delay or 1, + 'seller_qty': main_supplier and main_supplier.qty or 0.0, + 'seller_id': main_supplier and main_supplier.name.id or False + } + return result + _defaults = { 'active': lambda *a: 1, @@ -526,6 +524,10 @@ class product_product(osv.osv): 'name_template': fields.related('product_tmpl_id', 'name', string="Name", type='char', size=128, store=True, select=True), 'color': fields.integer('Color Index'), 'product_image': fields.binary('Image'), + 'seller_info_id': fields.function(_calc_seller, type='many2one', relation="product.supplierinfo", multi="seller_info"), + 'seller_delay': fields.function(_calc_seller, type='integer', string='Supplier Lead Time', multi="seller_info", help="This is the average delay in days between the purchase order confirmation and the reception of goods for this product and for the default supplier. It is used by the scheduler to order requests based on reordering delays."), + 'seller_qty': fields.function(_calc_seller, type='float', string='Supplier Quantity', multi="seller_info", help="This is minimum quantity to purchase from Main Supplier."), + 'seller_id': fields.function(_calc_seller, type='many2one', relation="res.partner", string='Main Supplier', help="Main Supplier who has highest priority in Supplier List.", multi="seller_info"), } def create(self, cr, uid, vals, context=None): @@ -783,10 +785,10 @@ class product_supplierinfo(osv.osv): 'product_name': fields.char('Supplier Product Name', size=128, help="This supplier's product name will be used when printing a request for quotation. Keep empty to use the internal one."), 'product_code': fields.char('Supplier Product Code', size=64, help="This supplier's product code will be used when printing a request for quotation. Keep empty to use the internal one."), 'sequence' : fields.integer('Sequence', help="Assigns the priority to the list of product supplier."), - 'product_uom': fields.related('product_id', 'uom_po_id', type='many2one', relation='product.uom', string="Supplier Unit of Measure", readonly="1", help="This comes from the product form."), + 'product_uom': fields.related('product_template_id', 'uom_po_id', type='many2one', relation='product.uom', string="Supplier Unit of Measure", readonly="1", help="This comes from the product form."), 'min_qty': fields.float('Minimal Quantity', required=True, help="The minimal quantity to purchase to this supplier, expressed in the supplier Product Unit of Measure if not empty, in the default unit of measure of the product otherwise."), 'qty': fields.function(_calc_qty, store=True, type='float', string='Quantity', multi="qty", help="This is a quantity which is converted into Default Unit of Measure."), - 'product_id' : fields.many2one('product.template', 'Product', required=True, ondelete='cascade', select=True), + 'product_template_id' : fields.many2one('product.template', 'Product Template', required=True, ondelete='cascade', select=True), 'delay' : fields.integer('Delivery Lead Time', required=True, help="Lead time in days between the confirmation of the purchase order and the reception of the products in your warehouse. Used by the scheduler for automatic computation of the purchase order planning."), 'pricelist_ids': fields.one2many('pricelist.partnerinfo', 'suppinfo_id', 'Supplier Pricelist'), 'company_id':fields.many2one('res.company','Company',select=1), From ef50bf061bbd0df7c70259d9736dce5b11c6f612 Mon Sep 17 00:00:00 2001 From: sebastien beau Date: Wed, 11 Jul 2012 01:49:48 +0200 Subject: [PATCH 2/5] [FIX] purchase : fix due to refactor done on product module bzr revid: sebastien.beau@akretion.com.br-20120710234948-p87xrwwfbk4r6lc4 --- addons/purchase/purchase.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index e74ca83a92b..9f4c57babf9 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -917,15 +917,15 @@ class purchase_order_line(osv.osv): qty = qty or 1.0 supplierinfo = False - supplierinfo_ids = product_supplierinfo.search(cr, uid, [('name','=',partner_id),('product_id','=',product.id)]) - if supplierinfo_ids: - supplierinfo = product_supplierinfo.browse(cr, uid, supplierinfo_ids[0], context=context) - 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 + for supplier in product.seller_ids: + if supplier.name.id == partner_id: + supplierinfo = supplier + 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 dt = self._get_date_planned(cr, uid, supplierinfo, date_order, context=context).strftime(DEFAULT_SERVER_DATETIME_FORMAT) From 7f28916d734eb9dc2522ca6a478dbe5a027414f1 Mon Sep 17 00:00:00 2001 From: sebastien beau Date: Wed, 11 Jul 2012 02:28:17 +0200 Subject: [PATCH 3/5] [FIX] purchase : manual or automatic purchase should have the same description for line always the partner_ref bzr revid: sebastien.beau@akretion.com.br-20120711002817-pupfagnty0so015e --- addons/purchase/purchase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 9f4c57babf9..3f351d3fc8f 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -895,7 +895,7 @@ class purchase_order_line(osv.osv): 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}) + res['value'].update({'name': product.partner_ref, 'notes': notes or product.description_purchase}) # - set a domain on product_uom res['domain'] = {'product_uom': [('category_id','=',product.uom_id.category_id.id)]} From 6cc7bfc593b2db8ac4b9ce4e4b31805b6b50df19 Mon Sep 17 00:00:00 2001 From: sebastien beau Date: Wed, 11 Jul 2012 10:39:42 +0200 Subject: [PATCH 4/5] [FIX] product : fix demo data due to refactor done before bzr revid: sebastien.beau@akretion.com.br-20120711083942-7lgvt13cr3apdrjk --- addons/product/product_demo.xml | 56 ++++++++++++++++----------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/addons/product/product_demo.xml b/addons/product/product_demo.xml index a331d5c8b6b..3bd67ca7e61 100644 --- a/addons/product/product_demo.xml +++ b/addons/product/product_demo.xml @@ -693,112 +693,112 @@ 10 1 - + 5 10 1 - + 5 1 1 - + 1 1 1 - + 1 1 1 - + 2 1 1 - + 2 1 1 - + 2 1 1 - + 1 1 1 - + 1 1 1 - + 1 1 1 - + 1 1 1 - + 1 1 1 - + 1 1 1 - + 5 1 1 - + 5 1 1 - + 5 @@ -806,7 +806,7 @@ 10 1 5 - + 5 @@ -814,7 +814,7 @@ 10 1 5 - + 5 @@ -822,7 +822,7 @@ 10 1 5 - + 5 @@ -831,7 +831,7 @@ --> - + 5 1 @@ -839,7 +839,7 @@ - + 5 1 @@ -847,7 +847,7 @@ - + 5 1 @@ -855,7 +855,7 @@ - + 5 1 @@ -863,7 +863,7 @@ - + 5 1 @@ -871,7 +871,7 @@ - + 5 1 @@ -879,7 +879,7 @@ - + 2 1 @@ -887,7 +887,7 @@ - + 5 1 @@ -895,7 +895,7 @@ - + 5 1 From fc0e0b056339ad8750d07e5e13838a6ff9a4c397 Mon Sep 17 00:00:00 2001 From: sebastien beau Date: Wed, 11 Jul 2012 11:43:51 +0200 Subject: [PATCH 5/5] [FIX] mrp fix demo data due to previous refactor bzr revid: sebastien.beau@akretion.com.br-20120711094351-nn21w9odo13k14t0 --- addons/mrp/mrp_demo.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/mrp/mrp_demo.xml b/addons/mrp/mrp_demo.xml index 68fe21ea16c..a008b2a1dee 100644 --- a/addons/mrp/mrp_demo.xml +++ b/addons/mrp/mrp_demo.xml @@ -930,7 +930,7 @@ - + 1.0 @@ -945,7 +945,7 @@ - + 2.0 @@ -960,7 +960,7 @@ - + 2.0 @@ -1050,7 +1050,7 @@ - + 300.0 @@ -1065,7 +1065,7 @@ - + 100.0