Merge lp:~camptocamp/openerp-humanitarian-ngo/add-bid_selected_state_on_po-nbi into lp:openerp-humanitarian-ngo/purchase-wkfl

Proposed by Nicolas Bessi - Camptocamp
Status: Merged
Approved by: Yannick Vaucher @ Camptocamp
Approved revision: 79
Merged at revision: 73
Proposed branch: lp:~camptocamp/openerp-humanitarian-ngo/add-bid_selected_state_on_po-nbi
Merge into: lp:openerp-humanitarian-ngo/purchase-wkfl
Diff against target: 253 lines (+96/-25)
6 files modified
purchase_extended/model/purchase_order.py (+8/-2)
purchase_extended/test/process/bid2order.yml (+8/-3)
purchase_extended/workflow/purchase_order.xml (+14/-0)
purchase_requisition_extended/model/purchase_order.py (+2/-0)
purchase_requisition_extended/model/purchase_requisition.py (+63/-20)
purchase_requisition_extended/view/purchase_requisition.xml (+1/-0)
To merge this branch: bzr merge lp:~camptocamp/openerp-humanitarian-ngo/add-bid_selected_state_on_po-nbi
Reviewer Review Type Date Requested Status
Yannick Vaucher @ Camptocamp code review, no tests Approve
Romain Deheele - Camptocamp (community) code review Approve
Joël Grand-Guillaume @ camptocamp code review + test Approve
Review via email: mp+200799@code.launchpad.net

Commit message

[ADD] a bid selected state on PO
[FIX] confirmation of cost estimate. PO in state bid will be cancel too

Description of the change

Add a bid selected state on PO
Fix confirmation of cost estimate. PO in state bid will be cancel too

To post a comment you must log in.
Revision history for this message
Nicolas Bessi - Camptocamp (nbessi-c2c-deactivatedaccount) wrote :

Add a bid selected state on PO
Fix confirmation of cost estimate. PO in state bid will be cancel too

74. By Nicolas Bessi <email address hidden>

[FIX] on change product line on po line to allows manual creation of purchase order

75. By Nicolas Bessi <email address hidden>

[FIX] test do not use draftbid state but sent state as we can not send context to the server

76. By Joël Grand-Guillaume @ camptocamp

[ADD] The pricelist on the requisition and bid creation process

77. By Joël Grand-Guillaume @ camptocamp

[IMP] Add a pricelist in tendering process

78. By Nicolas Bessi - Camptocamp

[MRG] from head

Revision history for this message
Joël Grand-Guillaume @ camptocamp (jgrandguillaume-c2c) wrote :

LGTM, Thanks !

review: Approve (code review + test)
Revision history for this message
Romain Deheele - Camptocamp (romaindeheele) wrote :

LGTM,

Romain

review: Approve (code review)
79. By Yannick Vaucher @ Camptocamp

[IMP] assign single dict value using key instead of using update

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote :

LGTM

review: Approve (code review, no tests)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'purchase_extended/model/purchase_order.py'
2--- purchase_extended/model/purchase_order.py 2013-11-13 08:49:37 +0000
3+++ purchase_extended/model/purchase_order.py 2014-02-06 13:54:03 +0000
4@@ -14,6 +14,7 @@
5 ('sent', 'RFQ Sent'),
6 ('draftbid', 'Draft Bid'), # added
7 ('bid', 'Bid Encoded'), # Bid Received renamed into Bid Encoded
8+ ('bid_selected', 'Bid selected'), # added
9 ('draftpo', 'Draft PO'), # added
10 ('confirmed', 'Waiting Approval'),
11 ('approved', 'Purchase Confirmed'),
12@@ -236,17 +237,22 @@
13 value['value']['dest_address_id'] = dest_id
14 return value
15
16+ def po_tender_requisition_selected(self, cr, uid, ids, context=None):
17+ """Workflow function that write state 'bid selected'"""
18+ return self.write(cr, uid, ids, {'state': 'bid_selected'},
19+ context=context)
20+
21
22 class purchase_order_line(orm.Model):
23 _inherit = 'purchase.order.line'
24
25 def onchange_product_id(self, cr, uid, ids, pricelist_id, product_id, qty, uom_id,
26 partner_id, date_order=False, fiscal_position_id=False, date_planned=False,
27- name=False, price_unit=False, context=None, state='draft', type='rfq', **kwargs):
28+ name=False, price_unit=False, context=None, state='draftpo', type='purchase', **kwargs):
29 res = super(purchase_order_line, self).onchange_product_id(cr, uid, ids,
30 pricelist_id, product_id, qty, uom_id, partner_id, date_order,
31 fiscal_position_id, date_planned, name, price_unit, context)
32- if state == 'draft' and type == 'bid':
33+ if state == 'draft' and type == 'rfq':
34 res['value'].update({'price_unit': 0})
35 elif state in ('sent', 'draftbid', 'bid'):
36 if 'price_unit' in res['value']:
37
38=== modified file 'purchase_extended/test/process/bid2order.yml'
39--- purchase_extended/test/process/bid2order.yml 2013-11-01 11:44:19 +0000
40+++ purchase_extended/test/process/bid2order.yml 2014-02-06 13:54:03 +0000
41@@ -22,11 +22,16 @@
42 date_planned: '2013-08-30'
43 price_unit: 52.53
44 -
45- Type must be 'bid' and the total untaxed amount of the RFQ must be computed.
46+ I print the RFQ.
47+-
48+ !python {model: purchase.order}: |
49+ self.print_quotation(cr, uid, [ref("purchase_order_ext_bid2order1")])
50+-
51+ Type must be 'rfq' and the total untaxed amount of the RFQ must be computed.
52 -
53 !assert {model: purchase.order, id: purchase_order_ext_bid2order1, string: The amount of RFQ is not correctly computed}:
54- - type == 'bid'
55- - state == 'draftbid'
56+ - type == 'rfq'
57+ - state == 'sent'
58 - round(sum([l.price_subtotal for l in order_line]), 2) == round(amount_untaxed, 2)
59 -
60 I run the 'Bid encoded' wizard. I fill the date.
61
62=== modified file 'purchase_extended/workflow/purchase_order.xml'
63--- purchase_extended/workflow/purchase_order.xml 2013-08-07 12:39:30 +0000
64+++ purchase_extended/workflow/purchase_order.xml 2014-02-06 13:54:03 +0000
65@@ -55,6 +55,20 @@
66 <field name="signal">purchase_cancel</field>
67 </record>
68
69+ <record id="act_po_requisition_selected" model="workflow.activity">
70+ <field name="wkf_id" ref="purchase.purchase_order"/>
71+ <field name="name">Bid selected</field>
72+ <field name="kind">function</field>
73+ <field name="action">po_tender_requisition_selected()</field>
74+ <field name="flow_stop">True</field>
75+ </record>
76+ <record id="trans_po_requisition_selected" model="workflow.transition">
77+ <field name="act_from" ref="purchase.act_bid"/>
78+ <field name="act_to" ref="act_po_requisition_selected"/>
79+ <field name="signal">select_requisition</field>
80+ </record>
81+
82+
83 <!-- Rename some activities to make the workflow clear -->
84 <record id="purchase.act_draft" model="workflow.activity">
85 <field name="name">draft RFQ</field>
86
87=== modified file 'purchase_requisition_extended/model/purchase_order.py'
88--- purchase_requisition_extended/model/purchase_order.py 2014-02-06 09:49:41 +0000
89+++ purchase_requisition_extended/model/purchase_order.py 2014-02-06 13:54:03 +0000
90@@ -62,6 +62,8 @@
91 'incoterm_address': requisition.req_incoterm_address,
92 'transport_mode_id': requisition.req_transport_mode_id,
93 })
94+ if requisition.pricelist_id:
95+ values.update({'pricelist_id': requisition.pricelist_id.id})
96 return values
97
98 def copy(self, cr, uid, id, default=None, context=None):
99
100=== modified file 'purchase_requisition_extended/model/purchase_requisition.py'
101--- purchase_requisition_extended/model/purchase_requisition.py 2013-11-01 11:44:19 +0000
102+++ purchase_requisition_extended/model/purchase_requisition.py 2014-02-06 13:54:03 +0000
103@@ -25,15 +25,33 @@
104 domain=[('type', 'in', ('rfq', 'bid'))]),
105 # new
106 'req_validity': fields.date("Requested Bid's End of Validity",
107- help="Default value requested to "
108- "the supplier."),
109+ help="Requested validity period requested to the bidder, "
110+ "i.e. please send bids that stay valid until that "
111+ "date.\n The bidder is allowed to send a bid with "
112+ "another validity end date that gets encoded in the "
113+ "bid."),
114 'bid_tendering_mode': fields.selection([('open', 'Open'),
115 ('restricted', 'Restricted')],
116 'Call for Bids Mode'),
117+ help="- Restricted : you select yourself the "
118+ "bidders and generate a RFQ for each of "
119+ "those. \n"
120+ "- Open : anybody can bid (you have to "
121+ "advertise the call for bids) and you "
122+ "directly encode the bids you received. "
123+ "You are still able to generate RFQ if "
124+ "you want to contact usual bidders."),
125 'bid_receipt_mode': fields.selection([('open', 'Open'),
126 ('sealed', 'Sealed')],
127 'Bid Receipt Mode',
128 required=True),
129+ help="- Open : The bids can be opened when "
130+ "received and encoded. \n"
131+ "- Closed : The bids can be marked as "
132+ "received but they have to be opened \n"
133+ "all at the same time after an opening "
134+ "ceremony (probably specific to public "
135+ "sector)."),
136 'consignee_id': fields.many2one('res.partner',
137 'Consignee',
138 help="Person responsible of delivery"),
139@@ -55,6 +73,13 @@
140 'account.payment.term',
141 'Requested Payment Term',
142 help="Default value requested to the supplier."),
143+ 'pricelist_id': fields.many2one('product.pricelist',
144+ 'Pricelist',
145+ help="If set that pricelist will be used to generate the RFQ."
146+ "Mostely used to ask a requisition in a given currency."),
147+ 'date_end': fields.datetime('Bid Submission Deadline',
148+ help="All bids received after that date won't be valid "
149+ " (probably specific to public sector)."),
150 }
151 _defaults = {
152 'bid_receipt_mode': 'open',
153@@ -83,6 +108,8 @@
154 'incoterm_id': requisition.req_incoterm_id.id,
155 'incoterm_address': requisition.req_incoterm_address,
156 })
157+ if requisition.pricelist_id:
158+ values['pricelist_id'] = requisition.pricelist_id.id
159 return values
160
161 def _prepare_purchase_order_line(self, cr, uid, requisition,
162@@ -142,18 +169,34 @@
163 context=context)
164 return super(PurchaseRequisition, self).generate_po(cr, uid, [ids], context=context)
165
166+ def quotation_selected(self, cr, uid, quotation, context=None):
167+ """Predicate that checks if a quotation has at least one line chosen
168+ :param quotation: record of 'purchase.order'
169+
170+ :returns: True if one line has been chosen
171+
172+ """
173+ # This topic is subject to changes
174+ return quotation.bid_partial
175+
176 def cancel_quotation(self, cr, uid, tender, context=None):
177 """
178 Called from generate_po. Cancel only draft and sent rfq
179 """
180 po = self.pool.get('purchase.order')
181 wf_service = netsvc.LocalService("workflow")
182+ tender.refresh()
183 for quotation in tender.purchase_ids:
184- if quotation.state in ['draft', 'sent']:
185- wf_service.trg_validate(uid, 'purchase.order', quotation.id, 'purchase_cancel', cr)
186- po.message_post(cr, uid, [quotation.id],
187- body=_('Canceled by the call for bids associated to this request for quotation.'),
188- context=context)
189+ if quotation.state in ['draft', 'sent', 'bid']:
190+ if self.quotation_selected(cr, uid, quotation, context=context):
191+ wf_service.trg_validate(uid, 'purchase.order', quotation.id,
192+ 'select_requisition', cr)
193+ else:
194+ wf_service.trg_validate(uid, 'purchase.order', quotation.id, 'purchase_cancel', cr)
195+ po.message_post(cr, uid, [quotation.id],
196+ body=_('Canceled by the call for bids associated'
197+ ' to this request for quotation.'),
198+ context=context)
199
200 return True
201
202@@ -226,19 +269,6 @@
203 res['domain'] = expression.AND([eval(res.get('domain', [])), [('requisition_id', 'in', ids)]])
204 return res
205
206- def open_product_line(self, cr, uid, ids, context=None):
207- """ Filter to show only lines from bids received. Group by requisition line instead of product for unicity
208- """
209- res = super(PurchaseRequisition, self).open_product_line(cr, uid, ids, context=context)
210- ctx = res.setdefault('context', {})
211- if 'search_default_groupby_product' in ctx:
212- del ctx['search_default_groupby_product']
213- if 'search_default_hide_cancelled' in ctx:
214- del ctx['search_default_hide_cancelled']
215- ctx['search_default_groupby_requisitionline'] = True
216- ctx['search_default_showbids'] = True
217- return res
218-
219 def close_callforbids(self, cr, uid, ids, context=None):
220 """
221 Check all quantities have been sourced
222@@ -289,6 +319,19 @@
223 'context': ctx,
224 }
225
226+ def open_product_line(self, cr, uid, ids, context=None):
227+ """ Filter to show only lines from bids received. Group by requisition line instead of product for unicity
228+ """
229+ res = super(PurchaseRequisition, self).open_product_line(cr, uid, ids, context=context)
230+ ctx = res.setdefault('context', {})
231+ if 'search_default_groupby_product' in ctx:
232+ del ctx['search_default_groupby_product']
233+ if 'search_default_hide_cancelled' in ctx:
234+ del ctx['search_default_hide_cancelled']
235+ ctx['search_default_groupby_requisitionline'] = True
236+ ctx['search_default_showbids'] = True
237+ return res
238+
239 def close_callforbids_ok(self, cr, uid, ids, context=None):
240 wf_service = netsvc.LocalService("workflow")
241 for id in ids:
242
243=== modified file 'purchase_requisition_extended/view/purchase_requisition.xml'
244--- purchase_requisition_extended/view/purchase_requisition.xml 2013-08-08 09:31:25 +0000
245+++ purchase_requisition_extended/view/purchase_requisition.xml 2014-02-06 13:54:03 +0000
246@@ -21,6 +21,7 @@
247 </xpath>
248 <xpath expr="//field[@name='user_id']" position="after">
249 <field name="bid_tendering_mode" attrs="{'readonly': [('state','not in',('draft'))]}" required="1"/>
250+ <field name="pricelist_id" attrs="{'readonly': [('state','not in',('draft'))]}"/>
251 </xpath>
252 <separator string="Requests for Quotation" position="attributes">
253 <attribute name="string">Requests for Quotation / Bids</attribute>

Subscribers

People subscribed via source and target branches