From 5d6379bc62ad140e713adeb569b7e5d50167f101 Mon Sep 17 00:00:00 2001 From: Cedric Snauwaert Date: Fri, 31 May 2013 09:38:56 +0200 Subject: [PATCH] [FIX]purchase_requisition: working generate_po button and add groups in view for advance bidding mode bzr revid: csn@openerp.com-20130531073856-v6p416dm50qwzf8x --- addons/purchase/purchase.py | 18 ++++- addons/purchase/purchase_workflow.xml | 4 +- .../purchase_requisition.py | 67 ++++++++++++++++--- .../purchase_requisition_view.xml | 8 ++- .../static/src/js/web_addons.js | 2 +- 5 files changed, 84 insertions(+), 15 deletions(-) diff --git a/addons/purchase/purchase.py b/addons/purchase/purchase.py index 407557a0e7c..81809d2e451 100644 --- a/addons/purchase/purchase.py +++ b/addons/purchase/purchase.py @@ -271,6 +271,13 @@ class purchase_order(osv.osv): return super(purchase_order, self).unlink(cr, uid, unlink_ids, context=context) + def set_order_line_status(self, cr, uid, ids, status, context=None): + line = self.pool.get('purchase.order.line') + for order in self.browse(cr, uid, ids, context=context): + for order_line in order.order_line: + line.write(cr, uid, order_line.id, {'state': status}, context=context) + return True + def button_dummy(self, cr, uid, ids, context=None): return True @@ -500,12 +507,17 @@ class purchase_order(osv.osv): return False self.write(cr, uid, ids, {'state':'draft','shipped':0}) wf_service = netsvc.LocalService("workflow") + self.set_order_line_status(cr, uid, ids, 'draft', context=context) for p_id in ids: # Deleting the existing instance of workflow for PO wf_service.trg_delete(uid, 'purchase.order', p_id, cr) wf_service.trg_create(uid, 'purchase.order', p_id, cr) return True + def wkf_po_done(self, cr, uid, ids, context=None): + self.write(cr, uid, ids, {'state': 'done'}, context=context) + self.set_order_line_status(cr, uid, ids, 'done', context=context) + def action_invoice_create(self, cr, uid, ids, context=None): """Generates invoice for given ids of purchase orders and links that invoice ID to purchase order. :param ids: list of ids of purchase orders. @@ -583,6 +595,10 @@ class purchase_order(osv.osv): return True return False + def wkf_action_cancel(self, cr, uid, ids, context=None): + self.write(cr,uid,ids,{'state':'cancel'}) + self.set_order_line_status(cr, uid, ids, 'cancel', context=context) + def action_cancel(self, cr, uid, ids, context=None): wf_service = netsvc.LocalService("workflow") for purchase in self.browse(cr, uid, ids, context=context): @@ -601,7 +617,7 @@ class purchase_order(osv.osv): if inv: wf_service.trg_validate(uid, 'account.invoice', inv.id, 'invoice_cancel', cr) self.write(cr,uid,ids,{'state':'cancel'}) - + self.set_order_line_status(cr, uid, ids, 'cancel', context=context) for (id, name) in self.name_get(cr, uid, ids): wf_service.trg_validate(uid, 'purchase.order', id, 'purchase_cancel', cr) return True diff --git a/addons/purchase/purchase_workflow.xml b/addons/purchase/purchase_workflow.xml index d4713044df7..2b79f903f89 100644 --- a/addons/purchase/purchase_workflow.xml +++ b/addons/purchase/purchase_workflow.xml @@ -37,7 +37,7 @@ cancel function True - write({'state':'cancel'}) + wkf_action_cancel() @@ -93,7 +93,7 @@ done - write({'state':'done'}) + wkf_po_done() function True AND diff --git a/addons/purchase_requisition/purchase_requisition.py b/addons/purchase_requisition/purchase_requisition.py index e889f0dd411..71681c251b2 100644 --- a/addons/purchase_requisition/purchase_requisition.py +++ b/addons/purchase_requisition/purchase_requisition.py @@ -57,8 +57,9 @@ class purchase_requisition(osv.osv): 'po_line_ids': fields.function(_get_po_line, method=True, type='one2many', relation='purchase.order.line', string='Products by supplier'), 'line_ids' : fields.one2many('purchase.requisition.line','requisition_id','Products to Purchase',states={'done': [('readonly', True)]}), 'warehouse_id': fields.many2one('stock.warehouse', 'Warehouse'), - 'state': fields.selection([('draft','New'),('in_progress','Sent to Suppliers'),('open','Choose Lines'),('cancel','Cancelled'),('done','PO Created')], - 'Status', track_visibility='onchange', required=True) + 'state': fields.selection([('draft','New'),('in_progress','Sent to Suppliers'),('open','Choosing Lines'),('done','PO Created'),('cancel','Cancelled')], + 'Status', track_visibility='onchange', required=True), + 'multiple_rfq_per_supplier': fields.boolean('Multiple RFQ per supplier'), } _defaults = { 'date_start': lambda *args: time.strftime('%Y-%m-%d %H:%M:%S'), @@ -97,7 +98,6 @@ class purchase_requisition(osv.osv): return self.write(cr, uid, ids, {'state': 'draft'}) def tender_done(self, cr, uid, ids, context=None): - self.generate_po(cr, uid, ids, context=context) return self.write(cr, uid, ids, {'state':'done', 'date_end':time.strftime('%Y-%m-%d %H:%M:%S')}, context=context) def _planned_date(self, requisition, delay=0.0): @@ -166,7 +166,7 @@ class purchase_requisition(osv.osv): supplier_pricelist = supplier.property_product_pricelist_purchase or False res = {} for requisition in self.browse(cr, uid, ids, context=context): - if supplier.id in filter(lambda x: x, [rfq.state <> 'cancel' and rfq.partner_id.id or None for rfq in requisition.purchase_ids]): + if not requisition.multiple_rfq_per_supplier and supplier.id in filter(lambda x: x, [rfq.state <> 'cancel' and rfq.partner_id.id or None for rfq in requisition.purchase_ids]): raise osv.except_osv(_('Warning!'), _('You have already one %s purchase order for this partner, you must cancel this purchase order to create a new quotation.') % rfq.state) location_id = requisition.warehouse_id.lot_input_id.id purchase_id = purchase_order.create(cr, uid, { @@ -199,6 +199,18 @@ class purchase_requisition(osv.osv): return res + def check_valid_quotation(self, cr, uid, quotation, context=None): + """ + Check if a quotation has all his order lines bid in order to confirm it if its the case + return True if all order line have been selected during bidding process, else return False + + args : 'quotation' must be a browse record + """ + for line in quotation.order_line: + if line.state != 'confirmed' or line.product_qty != line.quantity_bid: + return False + return True + def generate_po(self, cr, uid, id, context=None): """ Generate all purchase order based on selected lines, should only be called on one tender at a time @@ -210,6 +222,23 @@ class purchase_requisition(osv.osv): tender = self.browse(cr, uid, id, context=context)[0] if tender.state == 'done': raise osv.except_osv(_('Warning!'), _('You have already generate the purchase order(s).')) + + confirm = False + #check that we have at least confirm one line + for po_line in tender.po_line_ids: + if po_line.state == 'confirmed': + confirm = True + break + if not confirm: + raise osv.except_osv(_('Warning!'), _('You have no line selected for buying.')) + + #check for complete RFQ + for quotation in tender.purchase_ids: + if (self.check_valid_quotation(cr, uid, quotation, context=context)): + #use workflow to set PO state to confirm + wf_service.trg_validate(uid, 'purchase.order', quotation.id, 'purchase_confirm', cr) + + #get other confirmed lines per supplier for po_line in tender.po_line_ids: #only take into account confirmed line that does not belong to already confirmed purchase order if po_line.state == 'confirmed' and po_line.order_id.state in ['draft', 'sent', 'bid', 'cancel']: @@ -236,6 +265,10 @@ class purchase_requisition(osv.osv): for quotation in tender.purchase_ids: if quotation.state in ['draft', 'sent', 'bid']: wf_service.trg_validate(uid, 'purchase.order', quotation.id, 'purchase_cancel', cr) + + #set tender to state done + self.tender_done(cr, uid, id, context=context) + return True class purchase_requisition_line(osv.osv): @@ -273,8 +306,23 @@ purchase_requisition_line() class purchase_order(osv.osv): _inherit = "purchase.order" + + def _belong_to_bid_group(self, cr, uid, ids, field_names, arg=None, context=None): + belong = False + group_bid_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'purchase', 'group_advance_bidding')[1] + user = self.pool.get('res.users').browse(cr, uid, uid, context=context) + for group in user.groups_id: + if group.id == group_bid_id: + belong = True + result = {} + if not ids: return result + for id in ids: + result.setdefault(id, belong) + return result + _columns = { - 'requisition_id' : fields.many2one('purchase.requisition','Purchase Requisition') + 'requisition_id' : fields.many2one('purchase.requisition','Purchase Requisition'), + 'advance_bidding_group': fields.function(_belong_to_bid_group, method=True, type='boolean', string="Belong to advance bidding group"), } def wkf_confirm_order(self, cr, uid, ids, context=None): @@ -297,7 +345,6 @@ purchase_order() class purchase_order_line(osv.osv): _inherit = 'purchase.order.line' - #TODO add field function to get same value as product_qty wherever quantity_bid is zero, with an inverse fct to write on quantity_bid _columns= { 'quantity_bid': fields.float('Quantity Bid', digits_compute=dp.get_precision('Product Unit of Measure')), } @@ -312,8 +359,12 @@ class purchase_order_line(osv.osv): self.write(cr, uid, ids, {'quantity_bid': element.product_qty}, context=context) return True - def generate_po(self, cr, uid, id, context=None): - print '-----------------------------------------' + def generate_po(self, cr, uid, active_id, context=None): + #call generate_po from tender with active_id + self.pool.get('purchase.requisition').generate_po(cr, uid, [active_id], context=context) + res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'purchase_requisition','action_purchase_requisition', context=context) + return res + class product_product(osv.osv): _inherit = 'product.product' diff --git a/addons/purchase_requisition/purchase_requisition_view.xml b/addons/purchase_requisition/purchase_requisition_view.xml index 9541f655c85..28ac0b66746 100644 --- a/addons/purchase_requisition/purchase_requisition_view.xml +++ b/addons/purchase_requisition/purchase_requisition_view.xml @@ -31,16 +31,17 @@