# -*- coding: utf-8 -*- ############################################################################## # # Authors: Laetitia Gangloff # Copyright (c) 2015 Acsone SA/NV (http://www.acsone.eu) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # ############################################################################## from openerp import api, fields, models import openerp.addons.decimal_precision as dp class PurchaseOrder(models.Model): _inherit = "purchase.order" @api.cr_uid_context def _prepare_order_line_move(self, cr, uid, order, order_line, picking_id, group_id, context=None): """ Set product_packaging on stock move """ result = super(PurchaseOrder, self)._prepare_order_line_move( cr, uid, order, order_line, picking_id, group_id, context=context) if order_line.packaging_id: for res in result: res['product_packaging'] = order_line.packaging_id.id return result class PurchaseOrderLine(models.Model): _inherit = "purchase.order.line" @api.model def _default_product_purchase_uom_id(self): return self.env.ref('product.product_uom_unit') product_tmpl_id = fields.Many2one(related='product_id.product_tmpl_id', comodel_name='product.template') packaging_id = fields.Many2one('product.packaging', 'Packaging') product_purchase_qty = fields.Float( 'Purchase quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True, default=lambda *a: 1.0) product_purchase_uom_id = fields.Many2one( 'product.uom', 'Purchase Unit of Measure', required=True, default=_default_product_purchase_uom_id) product_qty = fields.Float( compute="_compute_product_qty", string='Quantity', inverse='_inverse_product_qty',) @api.one @api.depends('product_purchase_uom_id', 'product_purchase_qty') def _compute_product_qty(self): """ Compute the total quantity """ uom_obj = self.env['product.uom'] to_uom = uom_obj.search( [('category_id', '=', self.product_purchase_uom_id.category_id.id), ('uom_type', '=', 'reference')], limit=1) self.product_qty = uom_obj._compute_qty( self.product_purchase_uom_id.id, self.product_purchase_qty, to_uom.id) @api.one def _inverse_product_qty(self): """ If product_quantity is set compute the purchase_qty """ if self.product_id and self.order_id.partner_id: for supplier in self.product_id.seller_ids: if (supplier.name.id == self.order_id.partner_id.id): product_purchase_uom = supplier.min_qty_uom_id uom_obj = self.env['product.uom'] from_uom = uom_obj.search( [('category_id', '=', product_purchase_uom.category_id.id), ('uom_type', '=', 'reference')], limit=1) self.product_purchase_qty = uom_obj._compute_qty( from_uom.id, self.product_qty, product_purchase_uom.id,) self.product_purchase_uom_id = product_purchase_uom.id break else: self.product_purchase_qty = self.product_qty @api.onchange("packaging_id") def _onchange_packaging_id(self): if self.packaging_id: self.product_uom = self.packaging_id.uom_id @api.cr_uid_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, state='draft', context=None): """ set domain on product_purchase_uom_id and packaging_id if there is no qty (first pass), set the first packagigng, purchase_uom and purchase_qty """ product_product = self.pool['product.product'] product_purchase_qty = 0 product_purchase_uom_id = False category_product_purchase_uom_id = False packaging_id = False new_uom_id = False domain = {} if product_id and partner_id: product = product_product.browse(cr, uid, product_id, context=context) first = True packaging_ids = [] po_uom_ids = [] domain['packaging_id'] = [('id', 'in', packaging_ids)] domain['product_purchase_uom_id'] = [('id', 'in', po_uom_ids)] for supplier in product.seller_ids: if (supplier.name.id == partner_id): if first: product_purchase_qty = supplier.min_qty product_purchase_uom_id = supplier.min_qty_uom_id.id category_product_purchase_uom_id = \ supplier.min_qty_uom_id.category_id.id new_uom_id = supplier.product_uom.id if supplier.packaging_id: packaging_id = supplier.packaging_id.id first = False po_uom_ids.append(supplier.min_qty_uom_id.id) if supplier.packaging_id: packaging_ids.append(supplier.packaging_id.id) uom_id = new_uom_id if not qty else uom_id res = super(PurchaseOrderLine, 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, state=state, context=context) if product_id and partner_id and not qty \ and category_product_purchase_uom_id: res['value']['product_purchase_qty'] = product_purchase_qty res['value']['product_purchase_uom_id'] = product_purchase_uom_id uom_obj = self.pool['product.uom'] to_uom_id = uom_obj.search( cr, uid, [('category_id', '=', category_product_purchase_uom_id), ('uom_type', '=', 'reference')], limit=1, context=context)[0] res['value']['product_qty'] = uom_obj._compute_qty( cr, uid, product_purchase_uom_id, product_purchase_qty, to_uom_id) res['value']['packaging_id'] = packaging_id if domain: if res.get('domain'): res['domain'].update(domain) else: res['domain'] = domain return res @api.model def update_vals(self, vals): """ When packaging_id is set, uom_id is readonly, so we need to reset the uom value in the vals dict """ if vals.get('packaging_id'): vals['product_uom'] = self.env['product.packaging'].browse( vals['packaging_id']).uom_id.id return vals @api.model @api.returns('self', lambda rec: rec.id) def create(self, vals): if 'product_qty' not in vals and 'product_purchase_qty' in vals: # compute product_qty to avoid inverse computation and reset to 1 uom_obj = self.env['product.uom'] product_purchase_uom = uom_obj.browse( vals['product_purchase_uom_id']) to_uom = uom_obj.search( [('category_id', '=', product_purchase_uom.category_id.id), ('uom_type', '=', 'reference')], limit=1) vals['product_qty'] = uom_obj._compute_qty( vals['product_purchase_uom_id'], vals['product_purchase_qty'], to_uom.id) return super(PurchaseOrderLine, self).create(self.update_vals(vals)) @api.multi def write(self, vals): return super(PurchaseOrderLine, self).write(self.update_vals(vals)) class ProcurementOrder(models.Model): _inherit = 'procurement.order' @api.model def _get_po_line_values_from_proc(self, procurement, partner, company, schedule_date): """ add packaging and update product_uom/quantity if necessary """ res = super(ProcurementOrder, self)._get_po_line_values_from_proc( procurement, partner, company, schedule_date) uom_obj = self.env['product.uom'] for supplier in procurement.product_id.seller_ids: if (supplier.name.id == partner.id): if supplier.packaging_id: res['packaging_id'] = supplier.packaging_id.id new_uom_id = supplier.product_uom.id if new_uom_id != res['product_uom']: res['product_uom'] = new_uom_id qty = uom_obj._compute_qty(procurement.product_uom.id, procurement.product_qty, new_uom_id) res['product_qty'] = max(qty, supplier.qty) pricelist = partner.property_product_pricelist_purchase res['price_unit'] = pricelist.with_context( uom=new_uom_id).price_get( procurement.product_id.id, qty, partner=partner.id)[pricelist.id] break return res