Merge lp:~unifield-team/unifield-server/us-1160 into lp:unifield-server
- us-1160
- Merge into trunk
Proposed by
jftempo
Status: | Merged |
---|---|
Merged at revision: | 3762 |
Proposed branch: | lp:~unifield-team/unifield-server/us-1160 |
Merge into: | lp:unifield-server |
Diff against target: |
856 lines (+384/-29) 18 files modified
bin/addons/msf_custom_settings/view/purchase_view.xml (+1/-1) bin/addons/msf_doc_import/view/purchase_order_import_line_view.xml (+2/-0) bin/addons/msf_partner/partner.py (+8/-0) bin/addons/partner_modification/partner_modification_view.xml (+1/-0) bin/addons/purchase_override/purchase.py (+2/-0) bin/addons/purchase_override/purchase_view.xml (+1/-0) bin/addons/sale_override/sale.py (+12/-0) bin/addons/sourcing/__init__.py (+1/-0) bin/addons/sourcing/__openerp__.py (+1/-0) bin/addons/sourcing/procurement_order.py (+14/-0) bin/addons/sourcing/purchase_order.py (+5/-0) bin/addons/sourcing/related_sourcing.py (+68/-0) bin/addons/sourcing/related_sourcing_view.xml (+30/-0) bin/addons/sourcing/res_partner.py (+3/-0) bin/addons/sourcing/sale_order_line.py (+107/-7) bin/addons/sourcing/sourcing_view.xml (+28/-2) bin/addons/sourcing/wizard/multiple_sourcing.py (+89/-11) bin/addons/sourcing/wizard/multiple_sourcing_view.xml (+11/-8) |
To merge this branch: | bzr merge lp:~unifield-team/unifield-server/us-1160 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
UniField Reviewer Team | Pending | ||
Review via email: mp+292800@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'bin/addons/msf_custom_settings/view/purchase_view.xml' |
2 | --- bin/addons/msf_custom_settings/view/purchase_view.xml 2016-03-14 10:56:12 +0000 |
3 | +++ bin/addons/msf_custom_settings/view/purchase_view.xml 2016-05-18 10:13:49 +0000 |
4 | @@ -34,7 +34,7 @@ |
5 | <field name="po_from_fo" invisible="1" /> |
6 | <field name="canceled_end" invisible="1" /> |
7 | <field name="partner_id" on_change="onchange_partner_id(partner_id,date_order,est_transport_lead_time,context)" context="{'search_default_supplier':1}" |
8 | - domain="[('supplier', '=', True), ('id', '!=', company_id), ('check_partner_po', '=', {'order_type':order_type, 'partner_id': partner_id}), ('check_partner_rfq', '=', tender_id), ('partner_not_int', 'in', {'type':'po', 'ids':[active_id]})]" |
9 | + domain="[('supplier', '=', True), ('id', '!=', company_id), ('check_partner_po', '=', {'order_type':order_type, 'partner_id': partner_id, 'split_po': related_sourcing_id}), ('check_partner_rfq', '=', tender_id), ('partner_not_int', 'in', {'type':'po', 'ids':[active_id]})]" |
10 | attrs="{'readonly': [('state', 'in', ['sourced', 'split', 'rfq_sent', 'rfq_updated', 'done', 'cancel', 'confirmed', 'confirmed_wait', 'approved', 'except_picking', 'except_invoice'])]}" /> |
11 | <field name="partner_type" /> |
12 | <field name="partner_address_id" attrs="{'readonly': [('state', 'in', ['sourced', 'split', 'rfq_sent', 'rfq_updated', 'done', 'cancel', 'confirmed_wait', 'approved', 'except_picking', 'except_invoice'])]}"/> |
13 | |
14 | === modified file 'bin/addons/msf_doc_import/view/purchase_order_import_line_view.xml' |
15 | --- bin/addons/msf_doc_import/view/purchase_order_import_line_view.xml 2016-04-12 12:42:49 +0000 |
16 | +++ bin/addons/msf_doc_import/view/purchase_order_import_line_view.xml 2016-05-18 10:13:49 +0000 |
17 | @@ -31,6 +31,8 @@ |
18 | <field name="import_in_progress" readonly="1" invisible="0" /> |
19 | </xpath> |
20 | <xpath expr="/form/notebook/page[@string='Notes']/field[@name='project_ref']" position="after"> |
21 | + <separator colspan="4" string="Sourcing group" /> |
22 | + <field name="related_sourcing_id" readonly="True" /> |
23 | <separator colspan="4" string="Import filenames" /> |
24 | <field name="import_filenames" mode="tree" readonly="1" nolabel="1" colspan="4"> |
25 | <tree string="Imported filenames"> |
26 | |
27 | === modified file 'bin/addons/msf_partner/partner.py' |
28 | --- bin/addons/msf_partner/partner.py 2016-01-04 13:16:43 +0000 |
29 | +++ bin/addons/msf_partner/partner.py 2016-05-18 10:13:49 +0000 |
30 | @@ -192,6 +192,13 @@ |
31 | _columns = { |
32 | 'manufacturer': fields.boolean(string='Manufacturer', help='Check this box if the partner is a manufacturer'), |
33 | 'partner_type': fields.selection(PARTNER_TYPE, string='Partner type', required=True), |
34 | + 'split_po': fields.selection( |
35 | + selection=[ |
36 | + ('yes', 'Yes'), |
37 | + ('no', 'No'), |
38 | + ], |
39 | + string='Split PO ?', |
40 | + ), |
41 | 'in_product': fields.function(_set_in_product, fnct_search=search_in_product, string='In product', type="boolean", readonly=True, method=True, multi='in_product'), |
42 | 'min_qty': fields.function(_set_in_product, string='Min. Qty', type='char', readonly=True, method=True, multi='in_product'), |
43 | 'delay': fields.function(_set_in_product, string='Delivery Lead time', type='char', readonly=True, method=True, multi='in_product'), |
44 | @@ -247,6 +254,7 @@ |
45 | 'manufacturer': lambda *a: False, |
46 | 'transporter': lambda *a: False, |
47 | 'partner_type': lambda *a: 'external', |
48 | + 'split_po': lambda *a: False, |
49 | 'vat_ok': lambda obj, cr, uid, c: obj.pool.get('unifield.setup.configuration').get_config(cr, uid).vat_ok, |
50 | } |
51 | |
52 | |
53 | === modified file 'bin/addons/partner_modification/partner_modification_view.xml' |
54 | --- bin/addons/partner_modification/partner_modification_view.xml 2012-09-12 14:01:30 +0000 |
55 | +++ bin/addons/partner_modification/partner_modification_view.xml 2016-05-18 10:13:49 +0000 |
56 | @@ -31,6 +31,7 @@ |
57 | <field name="lang" position="after"> |
58 | <field name="zone" /> |
59 | <field name="po_by_project" attrs="{'invisible': [('supplier', '=', False)], 'required': [('supplier', '!=', False)]}" /> |
60 | + <field name="split_po" attrs="{'invisible': [('partner_type', '!=', 'esc')], 'required': [('partner_type', '=', 'esc')]}" /> |
61 | </field> |
62 | <field name="user_id" position="replace"></field> |
63 | <!-- <field name="leadtime" position="replace"></field> --> |
64 | |
65 | === modified file 'bin/addons/purchase_override/purchase.py' |
66 | --- bin/addons/purchase_override/purchase.py 2016-05-12 12:09:25 +0000 |
67 | +++ bin/addons/purchase_override/purchase.py 2016-05-18 10:13:49 +0000 |
68 | @@ -168,6 +168,8 @@ |
69 | |
70 | if not 'date_confirm' in default: |
71 | default['date_confirm'] = False |
72 | + if not default.get('related_sourcing_id', False): |
73 | + default['related_sourcing_id'] = False |
74 | |
75 | return super(purchase_order, self).copy(cr, uid, p_id, default, context=context) |
76 | |
77 | |
78 | === modified file 'bin/addons/purchase_override/purchase_view.xml' |
79 | --- bin/addons/purchase_override/purchase_view.xml 2015-12-07 15:40:55 +0000 |
80 | +++ bin/addons/purchase_override/purchase_view.xml 2016-05-18 10:13:49 +0000 |
81 | @@ -379,6 +379,7 @@ |
82 | <html colspan="4"> |
83 | <p>All information of the PO template will be written in the new PO,</p> |
84 | <p>except the Delivery Requested date which will be the earliest date of all POs.</p> |
85 | + <p>Any sourcing group will be lost.</p> |
86 | </html> |
87 | <newline /> |
88 | <group colspan="4" col="4" attrs="{'invisible': [('unmatched_categ', '=', False)]}"> |
89 | |
90 | === modified file 'bin/addons/sale_override/sale.py' |
91 | --- bin/addons/sale_override/sale.py 2016-04-25 09:24:04 +0000 |
92 | +++ bin/addons/sale_override/sale.py 2016-05-18 10:13:49 +0000 |
93 | @@ -2277,6 +2277,17 @@ |
94 | |
95 | return True |
96 | |
97 | + def _get_related_sourcing_id(self, line): |
98 | + """ |
99 | + Return the ID of the related.sourcing document if any |
100 | + :param line: browse_record of FO/IR line |
101 | + :return: ID of a related.sourcing record or False |
102 | + """ |
103 | + if line.related_sourcing_ok and line.related_sourcing_id: |
104 | + return line.related_sourcing_id.id |
105 | + |
106 | + return False |
107 | + |
108 | def _get_procurement_order_data(self, line, order, rts_date, context=None): |
109 | """ |
110 | Get data for the procurement order creation according to |
111 | @@ -2315,6 +2326,7 @@ |
112 | 'company_id': order.company_id.id, |
113 | 'supplier': line.supplier and line.supplier.id or False, |
114 | 'po_cft': line.po_cft or False, |
115 | + 'related_sourcing_id': self._get_related_sourcing_id(line), |
116 | 'date_planned': rts_date, |
117 | 'from_yml_test': order.from_yml_test, |
118 | 'so_back_update_dest_po_id_procurement_order': line.so_back_update_dest_po_id_sale_order_line.id, |
119 | |
120 | === modified file 'bin/addons/sourcing/__init__.py' |
121 | --- bin/addons/sourcing/__init__.py 2016-03-15 09:50:06 +0000 |
122 | +++ bin/addons/sourcing/__init__.py 2016-05-18 10:13:49 +0000 |
123 | @@ -19,6 +19,7 @@ |
124 | # |
125 | ############################################################################## |
126 | |
127 | +import related_sourcing |
128 | import sale_order_line |
129 | import wizard |
130 | |
131 | |
132 | === modified file 'bin/addons/sourcing/__openerp__.py' |
133 | --- bin/addons/sourcing/__openerp__.py 2014-03-14 08:17:52 +0000 |
134 | +++ bin/addons/sourcing/__openerp__.py 2016-05-18 10:13:49 +0000 |
135 | @@ -50,6 +50,7 @@ |
136 | ], |
137 | 'update_xml': [ |
138 | 'sourcing_view.xml', |
139 | + 'related_sourcing_view.xml', |
140 | 'wizard/multiple_sourcing_view.xml', |
141 | ], |
142 | 'installable': True, |
143 | |
144 | === modified file 'bin/addons/sourcing/procurement_order.py' |
145 | --- bin/addons/sourcing/procurement_order.py 2016-04-25 09:24:04 +0000 |
146 | +++ bin/addons/sourcing/procurement_order.py 2016-05-18 10:13:49 +0000 |
147 | @@ -68,6 +68,10 @@ |
148 | _columns = { |
149 | 'supplier': fields.many2one('res.partner', 'Supplier'), |
150 | 'po_cft': fields.selection(_SELECTION_PO_CFT, string="PO/CFT"), |
151 | + 'related_sourcing_id': fields.many2one( |
152 | + 'related.sourcing', |
153 | + string='Group', |
154 | + ), |
155 | 'unique_rule_type': fields.char( |
156 | size=128, |
157 | string='Unique Replenishment rule type', |
158 | @@ -86,6 +90,9 @@ |
159 | if not default_values.get('from_splitted_po_line'): |
160 | default_values['from_splitted_po_line'] = False |
161 | |
162 | + if not default_values.get('related_sourcing_id'): |
163 | + default_values['related_sourcing_id'] = False |
164 | + |
165 | return super(procurement_order, self).copy_data(cr, uid, copy_id, default_values, context=context) |
166 | |
167 | def po_line_values_hook(self, cr, uid, ids, context=None, *args, **kwargs): |
168 | @@ -206,6 +213,13 @@ |
169 | else: |
170 | purchase_domain.append(('order_type', '!=', 'direct')) |
171 | |
172 | + if procurement.related_sourcing_id: |
173 | + purchase_domain.append(('related_sourcing_id', '=', procurement.related_sourcing_id.id)) |
174 | + values['related_sourcing_id'] = procurement.related_sourcing_id.id |
175 | + else: |
176 | + purchase_domain.append(('related_sourcing_id', '=', False)) |
177 | + values['related_sourcing_id'] = False |
178 | + |
179 | if procurement.tender_line_id and procurement.tender_line_id.purchase_order_line_id: |
180 | purchase_domain.append(('pricelist_id', '=', procurement.tender_line_id.purchase_order_line_id.order_id.pricelist_id.id)) |
181 | elif procurement.rfq_id: |
182 | |
183 | === modified file 'bin/addons/sourcing/purchase_order.py' |
184 | --- bin/addons/sourcing/purchase_order.py 2014-10-02 20:13:13 +0000 |
185 | +++ bin/addons/sourcing/purchase_order.py 2016-05-18 10:13:49 +0000 |
186 | @@ -51,6 +51,11 @@ |
187 | string='PO from replenishment rules', |
188 | readonly=True, |
189 | ), |
190 | + 'related_sourcing_id': fields.many2one( |
191 | + 'related.sourcing', |
192 | + string='Sourcing group', |
193 | + readonly=True, |
194 | + ), |
195 | } |
196 | |
197 | _defaults = { |
198 | |
199 | === added file 'bin/addons/sourcing/related_sourcing.py' |
200 | --- bin/addons/sourcing/related_sourcing.py 1970-01-01 00:00:00 +0000 |
201 | +++ bin/addons/sourcing/related_sourcing.py 2016-05-18 10:13:49 +0000 |
202 | @@ -0,0 +1,68 @@ |
203 | +# -*- coding: utf-8 -*- |
204 | +############################################################################## |
205 | +# |
206 | +# OpenERP, Open Source Management Solution |
207 | +# Copyright (C) 2014 TeMPO Consulting, MSF |
208 | +# |
209 | +# This program is free software: you can redistribute it and/or modify |
210 | +# it under the terms of the GNU Affero General Public License as |
211 | +# published by the Free Software Foundation, either version 3 of the |
212 | +# License, or (at your option) any later version. |
213 | +# |
214 | +# This program is distributed in the hope that it will be useful, |
215 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
216 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
217 | +# GNU Affero General Public License for more details. |
218 | +# |
219 | +# You should have received a copy of the GNU Affero General Public License |
220 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
221 | +# |
222 | +############################################################################## |
223 | + |
224 | +from osv import fields |
225 | +from osv import osv |
226 | + |
227 | +import string |
228 | + |
229 | + |
230 | +class related_sourcing(osv.osv): |
231 | + """ |
232 | + This object is used to link sourcing lines on a same PO to the same |
233 | + supplier. If most sourcing lines are sourced to the same supplier but |
234 | + have different related.sourcing, one PO per related.sourcing will be |
235 | + created with all lines linked to this related.sourcing. |
236 | + """ |
237 | + _name = 'related.sourcing' |
238 | + _description = 'Sourcing group' |
239 | + |
240 | + _columns = { |
241 | + 'name': fields.char( |
242 | + size=128, |
243 | + string='Name', |
244 | + required=True, |
245 | + ), |
246 | + 'description': fields.text( |
247 | + string='Description', |
248 | + ), |
249 | + } |
250 | + |
251 | + def create(self, cr, uid, vals, context=None): |
252 | + """ |
253 | + Format the name value |
254 | + """ |
255 | + vals['name'] = filter(str.isalnum, vals.get('name', '')).upper() |
256 | + return super(related_sourcing, self).\ |
257 | + create(cr, uid, vals, context=context) |
258 | + |
259 | + def write(self, cr, uid, ids, vals, context=None): |
260 | + """ |
261 | + Format the name value |
262 | + """ |
263 | + vals['name'] = filter(str.isalnum, vals.get('name', '')).upper() |
264 | + return super(related_sourcing, self).\ |
265 | + write(cr, uid, ids, vals, context=context) |
266 | + |
267 | +related_sourcing() |
268 | + |
269 | + |
270 | +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: |
271 | |
272 | === added file 'bin/addons/sourcing/related_sourcing_view.xml' |
273 | --- bin/addons/sourcing/related_sourcing_view.xml 1970-01-01 00:00:00 +0000 |
274 | +++ bin/addons/sourcing/related_sourcing_view.xml 2016-05-18 10:13:49 +0000 |
275 | @@ -0,0 +1,30 @@ |
276 | +<?xml version="1.0" encoding="utf-8"?> |
277 | +<openerp> |
278 | + <data> |
279 | + |
280 | + <record id="related_sourcing_tree_view" model="ir.ui.view"> |
281 | + <field name="name">related.sourcing.tree.view</field> |
282 | + <field name="model">related.sourcing</field> |
283 | + <field name="type">tree</field> |
284 | + <field name="arch" type="xml"> |
285 | + <tree string="Sourcing groups" editable="top"> |
286 | + <field name="name" /> |
287 | + <field name="description" /> |
288 | + </tree> |
289 | + </field> |
290 | + </record> |
291 | + |
292 | + <record id="related_sourcing_action" model="ir.actions.act_window"> |
293 | + <field name="name">Sourcing groups</field> |
294 | + <field name="res_model">related.sourcing</field> |
295 | + <field name="view_type">form</field> |
296 | + <field name="view_mode">tree,form</field> |
297 | + </record> |
298 | + |
299 | + <menuitem |
300 | + id="related_sourcing_menu" |
301 | + action="related_sourcing_action" |
302 | + parent="base.menu_sale_config_sales" /> |
303 | + |
304 | + </data> |
305 | +</openerp> |
306 | |
307 | === modified file 'bin/addons/sourcing/res_partner.py' |
308 | --- bin/addons/sourcing/res_partner.py 2014-03-10 14:11:36 +0000 |
309 | +++ bin/addons/sourcing/res_partner.py 2016-05-18 10:13:49 +0000 |
310 | @@ -151,6 +151,9 @@ |
311 | or not isinstance(arg[2]['partner_id'], (int, long)): |
312 | raise osv.except_osv(_('Error'), _('Filter check_partner_po different than (arg[0], =, %s) not implemented.') % arg[2]) |
313 | order_type = arg[2]['order_type'] |
314 | + split_po = arg[2]['split_po'] |
315 | + if split_po: |
316 | + newargs.append(('split_po', '=', 'yes')) |
317 | # Added by UF-1660 to filter partners |
318 | # do nothing on partner_type for loan |
319 | p_list = [] |
320 | |
321 | === modified file 'bin/addons/sourcing/sale_order_line.py' |
322 | --- bin/addons/sourcing/sale_order_line.py 2016-04-25 09:24:04 +0000 |
323 | +++ bin/addons/sourcing/sale_order_line.py 2016-05-18 10:13:49 +0000 |
324 | @@ -77,17 +77,49 @@ |
325 | |
326 | return True |
327 | |
328 | + def _get_supplier(self, cr, uid, ids, context=None): |
329 | + """ |
330 | + Returns a list of sale.order.line ID to update |
331 | + :param cr: Cursor to the database |
332 | + :param uid: ID of the res.users that calls this method |
333 | + :param ids: List of ID of res.partner |
334 | + :param context: Context of the call |
335 | + :return: List of sale.order.line ID to update |
336 | + """ |
337 | + return self.pool.get('sale.order.line').search(cr, uid, [ |
338 | + ('supplier', 'in', ids), |
339 | + ('state', '=', 'draft'), |
340 | + ], context=context) |
341 | + |
342 | + def _check_related_sourcing_ok(self, cr, uid, supplier=False, l_type='make_to_order', context=None): |
343 | + """ |
344 | + Return True if the supplier allows split PO. |
345 | + :param cr: Cursor to the database |
346 | + :param uid: ID of the res.users that calls this method |
347 | + :param supplier: ID of the res.partner selected as supplier for the sale.order.line |
348 | + :param l_type: Procurement method selected for the sale.order.line |
349 | + :param context: Context of the call |
350 | + :return: True or False |
351 | + """ |
352 | + if not supplier: |
353 | + return False |
354 | + |
355 | + sup_rec = self.pool.get('res.partner').\ |
356 | + read(cr, uid, [supplier], ['partner_type', 'split_po'], context=context)[0] |
357 | + |
358 | + return l_type == 'make_to_order' and sup_rec['partner_type'] == 'esc' and sup_rec['split_po'] == 'yes' |
359 | + |
360 | """ |
361 | Methods to get fields.function values |
362 | """ |
363 | - def _get_fake(self, cr, uid, ids, field_name, args, context=None): |
364 | + def _get_fake(self, cr, uid, idsrelated_sourcing_ok, field_name, args, context=None): |
365 | """ |
366 | Returns False for each ID. |
367 | |
368 | :param cr: Cursor to the database |
369 | :param uid: ID of the user that runs the method |
370 | :param ids: List of ID of field order lines to re-compute |
371 | - :param field_name: A field or a list of fields to be computed |
372 | + :param field_name: A fOield or a list of fields to be computed |
373 | :param args: Some other arguments |
374 | :param context: Context of the call |
375 | |
376 | @@ -152,6 +184,7 @@ |
377 | uid, |
378 | [line.id], |
379 | line.supplier.id, |
380 | + line.type, |
381 | context=context) |
382 | res = get_delay.get('value', {}).get('estimated_delivery_date', False) |
383 | |
384 | @@ -404,6 +437,30 @@ |
385 | ('sale_order_state', '=', 'validated'), |
386 | ] |
387 | |
388 | + def _get_related_sourcing_ok(self, cr, uid, ids, field_name, args, context=None): |
389 | + """ |
390 | + Return True or False to determine if the user could select a sourcing group on the OST for the line |
391 | + :param cr: Cursor to the database |
392 | + :param uid: ID of the res.users that calls this method |
393 | + :param ids: List of ID of sale.order.line to compute |
394 | + :param field_name: Name of the fields to compute |
395 | + :param args: Extra parameters |
396 | + :param context: Context of the call |
397 | + :return: True or False |
398 | + """ |
399 | + if context is None: |
400 | + context = {} |
401 | + |
402 | + if isinstance(ids, (int, long)): |
403 | + ids = [ids] |
404 | + |
405 | + res = {} |
406 | + |
407 | + for line in self.browse(cr, uid, ids, context=context): |
408 | + res[line.id] = self._check_related_sourcing_ok(cr, uid, line.supplier.id, line.type, context=context) |
409 | + |
410 | + return res |
411 | + |
412 | _columns = { |
413 | 'customer': fields.related( |
414 | 'order_id', |
415 | @@ -419,6 +476,10 @@ |
416 | 'res.partner', |
417 | 'Supplier', |
418 | ), |
419 | + 'related_sourcing_id': fields.many2one( |
420 | + 'related.sourcing', |
421 | + string='Group', |
422 | + ), |
423 | 'location_id': fields.many2one( |
424 | 'stock.location', |
425 | string='Location', |
426 | @@ -517,7 +578,18 @@ |
427 | method=True, |
428 | type='boolean', |
429 | string='Order in progress', |
430 | - multi='line_info'), |
431 | + multi='line_info', |
432 | + ), |
433 | + 'related_sourcing_ok': fields.function( |
434 | + _get_related_sourcing_ok, |
435 | + method=True, |
436 | + type='boolean', |
437 | + string='Related sourcing OK', |
438 | + store={ |
439 | + 'sale.order.line': (lambda obj, cr, uid, ids, c={}: ids, ['supplier', 'type'], 10), |
440 | + 'res.partner': (_get_supplier, ['partner_type', 'split_po'], 20), |
441 | + }, |
442 | + ), |
443 | # UTP-965 : Select a source stock location for line in make to stock |
444 | 'real_stock': fields.function( |
445 | _getVirtualStock, |
446 | @@ -994,6 +1066,13 @@ |
447 | if vals.get('type', False) == 'make_to_order': |
448 | vals['location_id'] = False |
449 | |
450 | + if vals.get('type') == 'make_to_stock': |
451 | + vals['related_sourcing_id'] = False |
452 | + elif vals.get('supplier'): |
453 | + related_sourcing_ok = self._check_related_sourcing_ok(cr, uid, vals.get('supplier'), vals.get('type'), context=context) |
454 | + if not related_sourcing_ok: |
455 | + vals['related_sourcing_id'] = False |
456 | + |
457 | # UFTP-139: if make_to_stock and no location, put Stock as location |
458 | if ids and 'type' in vals and vals.get('type', False) == 'make_to_stock' and not vals.get('location_id', False): |
459 | # Define Stock as location_id for each line without location_id |
460 | @@ -1518,7 +1597,7 @@ |
461 | |
462 | return res |
463 | |
464 | - def onChangeType(self, cr, uid, line_id, l_type, location_id=False, context=None): |
465 | + def onChangeType(self, cr, uid, line_id, l_type, location_id=False, supplier=False, context=None): |
466 | """ |
467 | When the method of procurement is changed, check if the new |
468 | values are compatible with the other values of the line and of the order. |
469 | @@ -1528,6 +1607,7 @@ |
470 | :param line_id: ID of the line to check |
471 | :param l_type: Value of the procurement method |
472 | :param location_id: ID of the stock location of the line |
473 | + :param supplier: Id of the res.partner selected as partner for the line |
474 | :param context: Context of the change |
475 | |
476 | :return A dictionary with the new values |
477 | @@ -1562,7 +1642,11 @@ |
478 | if wh_ids: |
479 | value['location_id'] = wh_obj.browse(cr, uid, wh_ids[0], context=context).lot_stock_id.id |
480 | |
481 | - value['po_cft'] = False |
482 | + value.update({ |
483 | + 'po_cft': False, |
484 | + 'related_sourcing_ok': False, |
485 | + 'related_sourcing_id': False, |
486 | + }) |
487 | |
488 | res = {'value': value, 'warning': message} |
489 | if line_id: |
490 | @@ -1585,10 +1669,15 @@ |
491 | |
492 | if error: |
493 | return res |
494 | + else: |
495 | + related_sourcing_ok = self._check_related_sourcing_ok(cr, uid, supplier, l_type, context=context) |
496 | + value['related_sourcing_ok'] = related_sourcing_ok |
497 | + if not related_sourcing_ok: |
498 | + value['related_sourcing_id'] = False |
499 | |
500 | return {'value': value, 'warning': message} |
501 | |
502 | - def onChangeSupplier(self, cr, uid, line_id, supplier, context=None): |
503 | + def onChangeSupplier(self, cr, uid, line_id, supplier, l_type, context=None): |
504 | """ |
505 | When the supplier is changed, check if the new values are compatible |
506 | with the other values of the line and of the order. |
507 | @@ -1597,6 +1686,7 @@ |
508 | :param uid: ID of the user that runs the method |
509 | :param line_id: ID of the line to check |
510 | :param supplier: ID of the current or new choosen supplier |
511 | + :param l_type: Mode of procurement for the line |
512 | :param context: Context of the change |
513 | |
514 | :return A dictionary with the new values |
515 | @@ -1618,6 +1708,10 @@ |
516 | } |
517 | |
518 | if not supplier: |
519 | + result['value'].update({ |
520 | + 'related_sourcing_id': False, |
521 | + 'related_sourcing_ok': False, |
522 | + }) |
523 | sl = self.browse(cr, uid, line_id, context=context) |
524 | if not sl.product_id and sl.order_id.procurement_request and sl.type == 'make_to_order': |
525 | result['domain']['supplier'] = [('partner_type', 'in', ['internal', 'section', 'intermission'])] |
526 | @@ -1638,7 +1732,13 @@ |
527 | |
528 | estDeliveryDate = date.today() + relativedelta(days=int(delay)) |
529 | |
530 | - result['value']['estimated_delivery_date'] = estDeliveryDate.strftime('%Y-%m-%d') |
531 | + related_sourcing_ok = self._check_related_sourcing_ok(cr, uid, supplier, l_type, context=context) |
532 | + result['value'].update({ |
533 | + 'estimated_delivery_date': estDeliveryDate.strftime('%Y-%m-%d'), |
534 | + 'related_sourcing_ok': related_sourcing_ok, |
535 | + }) |
536 | + if not related_sourcing_ok: |
537 | + result['value']['related_sourcing_id'] = False |
538 | |
539 | value = result['value'] |
540 | partner_id = 'supplier' in value and value['supplier'] or supplier |
541 | |
542 | === modified file 'bin/addons/sourcing/sourcing_view.xml' |
543 | --- bin/addons/sourcing/sourcing_view.xml 2016-03-15 09:50:06 +0000 |
544 | +++ bin/addons/sourcing/sourcing_view.xml 2016-05-18 10:13:49 +0000 |
545 | @@ -93,11 +93,14 @@ |
546 | <button name="open_split_wizard" type="object" string="Split line" icon="terp-stock_effects-object-colorize" |
547 | attrs="{'invisible': [('display_confirm_button', '=', False)]}" /> |
548 | <field name="rts" readonly="True" /> |
549 | - <field name="type" string="Proc. Method" on_change="onChangeType(type, location_id)" |
550 | + <field name="type" string="Proc. Method" on_change="onChangeType(type, location_id, supplier)" |
551 | attrs="{'readonly': ['|', ('state', '!=', 'draft'), ('loan_type', '=', True)]}" /> |
552 | <field name="po_cft" |
553 | on_change="onChangePoCft(po_cft, order_id, supplier)" |
554 | attrs="{'readonly': ['|', ('type', '=', 'make_to_stock'), ('state', '!=', 'draft')], 'required': [('type', '=', 'make_to_order')]}" /> |
555 | + <field name="related_sourcing_ok" invisible="1" /> |
556 | + <field name="related_sourcing_id" |
557 | + attrs="{'readonly': ['|', '|', '|', ('supplier', '=', False), ('related_sourcing_ok', '=', False), ('state', '!=', 'draft'), ('po_cft', 'not in', ['po', 'dpo'])]}" /> |
558 | <field name="location_id" |
559 | widget="selection" |
560 | on_change="onChangeLocation(location_id, product_id, rts, order_id)" |
561 | @@ -113,7 +116,7 @@ |
562 | domain="[('id', '!=', company_id), ('available_for_dpo', '=', po_cft),('check_partner', '=', order_id)]" |
563 | context="{'product_id': product_id, 'choose_supplier': True, 'uom': product_uom, 'product_qty': product_uom_qty}" |
564 | attrs="{'readonly': ['|', ('po_cft', '=', 'cft'), '|', ('type', '=', 'make_to_stock'), ('state', '!=', 'draft')]}" |
565 | - on_change="onChangeSupplier(supplier)" /> |
566 | + on_change="onChangeSupplier(supplier, type)" /> |
567 | <field name="customer" invisible="1" /> |
568 | <field name="estimated_delivery_date" /> |
569 | <button name="confirmLine" string="Source Line" icon="gtk-go-forward" type="object" attrs="{'invisible':[('display_confirm_button', '=', False)]}" /> |
570 | @@ -221,6 +224,29 @@ |
571 | action="action_po_automation_config" |
572 | parent="base.menu_sale_config_sales" |
573 | name="PO Automation" /> |
574 | + |
575 | + <!-- Related sourcing group --> |
576 | + <record id="related_sourcing_search_view" model="ir.ui.view"> |
577 | + <field name="name">related.sourcing.search.view</field> |
578 | + <field name="model">related.sourcing</field> |
579 | + <field name="type">form</field> |
580 | + <field name="arch" type="xml"> |
581 | + <search string="Related sourcing group"> |
582 | + <field name="name" /> |
583 | + </search> |
584 | + </field> |
585 | + </record> |
586 | + |
587 | + <record id="related_sourcing_form_view" model="ir.ui.view"> |
588 | + <field name="name">related.sourcing.form.view</field> |
589 | + <field name="model">related.sourcing</field> |
590 | + <field name="type">form</field> |
591 | + <field name="arch" type="xml"> |
592 | + <form string="Related sourcing group"> |
593 | + <field name="name" /> |
594 | + </form> |
595 | + </field> |
596 | + </record> |
597 | |
598 | </data> |
599 | </openerp> |
600 | |
601 | === modified file 'bin/addons/sourcing/wizard/multiple_sourcing.py' |
602 | --- bin/addons/sourcing/wizard/multiple_sourcing.py 2016-03-17 10:38:35 +0000 |
603 | +++ bin/addons/sourcing/wizard/multiple_sourcing.py 2016-05-18 10:13:49 +0000 |
604 | @@ -54,6 +54,10 @@ |
605 | _SELECTION_PO_CFT, |
606 | string='PO/CFT', |
607 | ), |
608 | + 'related_sourcing_id': fields.many2one( |
609 | + 'related.sourcing', |
610 | + string='Group', |
611 | + ), |
612 | 'location_id': fields.many2one( |
613 | 'stock.location', |
614 | string='Location', |
615 | @@ -71,6 +75,9 @@ |
616 | string='Error', |
617 | help="If there is line without need sourcing on selected lines", |
618 | ), |
619 | + 'related_sourcing_ok': fields.boolean( |
620 | + string='Related sourcing OK', |
621 | + ), |
622 | } |
623 | |
624 | def default_get(self, cr, uid, fields_list, context=None): |
625 | @@ -101,13 +108,17 @@ |
626 | 'run_scheduler': po_auto_cfg_obj.get_po_automation(cr, uid, context=context), |
627 | 'type': 'make_to_stock', |
628 | 'po_cft': False, |
629 | + 'related_sourcing_ok': False, |
630 | }) |
631 | |
632 | # Check if all lines are with the same type, then set that type, otherwise set make_to_order |
633 | # Ignore all lines which have already been sourced, if there are some already sourced lines, a message |
634 | # will be displayed at the top of the wizard |
635 | - loc = -1 # first location flag |
636 | - supplier = -1 # first location flag |
637 | + res['type'] = 'make_to_stock' |
638 | + res['po_cft'] = False |
639 | + loc = -1 # first location flag |
640 | + supplier = -1 # first location flag |
641 | + group = None |
642 | for line in sol_obj.browse(cr, uid, active_ids, context=context): |
643 | if line.state == 'draft' and line.sale_order_state == 'validated': |
644 | res['line_ids'].append(line.id) |
645 | @@ -127,10 +138,20 @@ |
646 | supplier = temp |
647 | elif supplier != temp: |
648 | supplier = False |
649 | + |
650 | + if not line.related_sourcing_ok or not line.related_sourcing_id: |
651 | + group = False |
652 | + else: |
653 | + temp = line.related_sourcing_id.id |
654 | + if group is None: |
655 | + group = temp |
656 | + elif group != temp: |
657 | + group = False |
658 | + |
659 | else: |
660 | - # UTP-1021: Calculate the location to set into the wizard view if all lines |
661 | - # are sourced from the same location |
662 | - supplier = False # if source from stock, always set False to partner |
663 | + # UTP-1021: Calculate the location to set into the wizard view if all lines are sourced from the same location |
664 | + supplier = False # if source from stock, always set False to partner |
665 | + group = False |
666 | temploc = line.location_id.id |
667 | if loc == -1: # first location |
668 | loc = temploc |
669 | @@ -142,6 +163,10 @@ |
670 | res['location_id'] = loc |
671 | if supplier != -1: |
672 | res['supplier_id'] = supplier |
673 | + if group is not None: |
674 | + res['related_sourcing_id'] = group |
675 | + |
676 | + res['related_sourcing_ok'] = sol_obj._check_related_sourcing_ok(cr, uid, supplier, res['type'], context=context) |
677 | |
678 | if not res['line_ids']: |
679 | raise osv.except_osv( |
680 | @@ -153,6 +178,18 @@ |
681 | |
682 | return res |
683 | |
684 | + def _get_related_sourcing_id(self, wiz): |
685 | + """ |
686 | + Return the ID of a related.sourcing record or False |
687 | + :param wiz: browse_record of multiple.sourcing.wizard |
688 | + :return: ID of a related.sourcing record or False |
689 | + """ |
690 | + if wiz.related_sourcing_id and wiz.supplier_id and wiz.supplier_id.partner_type == 'esc' \ |
691 | + and wiz.supplier_id.split_po == 'yes': |
692 | + return wiz.related_sourcing_id.id |
693 | + |
694 | + return False |
695 | + |
696 | def save_lines(self, cr, uid, ids, context=None): |
697 | """ |
698 | Set values defined on the wizard to the lines of the wizard. |
699 | @@ -195,6 +232,7 @@ |
700 | 'type': wiz.type, |
701 | 'po_cft': wiz.po_cft, |
702 | 'supplier': wiz.supplier_id and wiz.supplier_id.id or False, |
703 | + 'related_sourcing_id': self._get_related_sourcing_id(wiz), |
704 | 'location_id': wiz.location_id.id and wiz.location_id.id or False, |
705 | }, context=context) |
706 | except osv.except_osv, e: |
707 | @@ -272,13 +310,14 @@ |
708 | |
709 | return {'type': 'ir.actions.act_window_close'} |
710 | |
711 | - def change_type(self, cr, uid, ids, l_type, context=None): |
712 | + def change_type(self, cr, uid, ids, l_type, supplier, context=None): |
713 | """ |
714 | Unset the other fields if the type is 'from stock' |
715 | :param cr: Cursor to the database |
716 | :param uid: ID of the res.users that calls the method |
717 | :param ids: List of ID of multiple.sourcing.wizard on which field values has to be changed |
718 | :param l_type: Value of the field 'type' |
719 | + :param supplier: Value of the field 'supplier' |
720 | :param context: Context of the call |
721 | :return: A dictionary that contains the field names to change as keys and the value for these fields as values. |
722 | """ |
723 | @@ -289,9 +328,21 @@ |
724 | context = {} |
725 | |
726 | if l_type == 'make_to_order': |
727 | - return {'value': {'location_id': False}} |
728 | + return { |
729 | + 'value': { |
730 | + 'location_id': False, |
731 | + 'related_sourcing_ok': sol_obj._check_related_sourcing_ok(cr, uid, supplier, l_type, context=context) |
732 | + }, |
733 | + } |
734 | |
735 | - res = {'value': {'po_cft': False, 'supplier_id': False}} |
736 | + res = { |
737 | + 'value': { |
738 | + 'po_cft': False, |
739 | + 'supplier_id': False, |
740 | + 'related_sourcing_ok': False, |
741 | + 'related_sourcing_id': False, |
742 | + }, |
743 | + } |
744 | if not context or not context[0] or not context[0][2]: |
745 | return res |
746 | |
747 | @@ -313,9 +364,24 @@ |
748 | all_line_empty = False |
749 | |
750 | if all_line_empty: # by default, and if all lines has no location, then set by default Stock |
751 | - return {'value': {'po_cft': False, 'supplier_id': False, 'location_id': stock_loc}} |
752 | + return { |
753 | + 'value': { |
754 | + 'po_cft': False, |
755 | + 'supplier_id': False, |
756 | + 'location_id': stock_loc, |
757 | + 'related_sourcing_ok': False, |
758 | + 'related_sourcing_id': False, |
759 | + }, |
760 | + } |
761 | |
762 | - return {'value': {'po_cft': False, 'supplier_id': False}} |
763 | + return { |
764 | + 'value': { |
765 | + 'po_cft': False, |
766 | + 'supplier_id': False, |
767 | + 'related_sourcing_ok': False, |
768 | + 'related_sourcing_id': False, |
769 | + }, |
770 | + } |
771 | |
772 | def change_po_cft(self, cr, uid, ids, po_cft, context=None): |
773 | """ |
774 | @@ -332,23 +398,27 @@ |
775 | |
776 | return {} |
777 | |
778 | - def change_supplier(self, cr, uid, ids, supplier, context=None): |
779 | + def change_supplier(self, cr, uid, ids, supplier, l_type, context=None): |
780 | """ |
781 | Check if the partner has an address. |
782 | :param cr: Cursor to the database |
783 | :param uid: ID of the res.users that calls the method |
784 | :param ids: List of ID of multiple.sourcing.wizard on which field values has to be changed |
785 | :param supplier: Value of the field 'supplier_id' |
786 | + :param l_type: Value of the field 'type' |
787 | :param context: Context of the call |
788 | :return: A dictionary that contains the field names to change as keys and the value for these fields as values. |
789 | """ |
790 | partner_obj = self.pool.get('res.partner') |
791 | + sol_obj = self.pool.get('sale.order.line') |
792 | |
793 | if context is None: |
794 | context = {} |
795 | |
796 | result = {} |
797 | + related_sourcing_ok = False |
798 | if supplier: |
799 | + related_sourcing_ok = sol_obj._check_related_sourcing_ok(cr, uid, supplier, l_type, context=context) |
800 | partner = partner_obj.browse(cr, uid, supplier, context) |
801 | # Check if the partner has addresses |
802 | if not partner.address: |
803 | @@ -356,6 +426,14 @@ |
804 | 'title': _('Warning'), |
805 | 'message': _('The chosen partner has no address. Please define an address before continuing.'), |
806 | } |
807 | + |
808 | + result['value'] = { |
809 | + 'related_sourcing_ok': related_sourcing_ok, |
810 | + } |
811 | + |
812 | + if not related_sourcing_ok: |
813 | + result['value']['related_sourcing_id'] = False |
814 | + |
815 | return result |
816 | |
817 | def change_location(self, cr, uid, ids, location_id, line_ids, context=None): |
818 | |
819 | === modified file 'bin/addons/sourcing/wizard/multiple_sourcing_view.xml' |
820 | --- bin/addons/sourcing/wizard/multiple_sourcing_view.xml 2016-03-01 14:43:23 +0000 |
821 | +++ bin/addons/sourcing/wizard/multiple_sourcing_view.xml 2016-05-18 10:13:49 +0000 |
822 | @@ -18,7 +18,7 @@ |
823 | <field name="line_ids" nolabel="1" colspan="4" /> |
824 | <separator colspan="4" string="Procurement method" /> |
825 | <field name="type" |
826 | - on_change="change_type(type)"/> |
827 | + on_change="change_type(type, supplier)"/> |
828 | <field name="po_cft" attrs="{'readonly': [('type', '=', 'make_to_stock')]}" |
829 | on_change="change_po_cft(po_cft)"/> |
830 | <field name="run_scheduler" /> |
831 | @@ -26,15 +26,18 @@ |
832 | <field name="supplier_id" |
833 | domain="[('id', '!=', company_id), ('available_for_dpo', '=', po_cft), ('line_contains_fo', '=', line_ids)]" |
834 | attrs="{'readonly': ['|', ('po_cft', '=', 'cft'), ('type', '=', 'make_to_stock')]}" |
835 | - on_change="change_supplier(supplier_id)" |
836 | + on_change="change_supplier(supplier_id, type)" |
837 | /> |
838 | + |
839 | <field name="location_id" |
840 | - domain="[('usage', '=', 'internal'), ('quarantine_location', '=', False), |
841 | - ('scrap_location', '=', False), ('destruction_location', '=', False), |
842 | - ('output_ok', '=', False), ('input_ok', '=', False)]" |
843 | - attrs="{'readonly': [('type', '!=', 'make_to_stock')]}" |
844 | - on_change="change_location(location_id, line_ids)" |
845 | - /> |
846 | + domain="[('usage', '=', 'internal'), ('quarantine_location', '=', False), |
847 | + ('scrap_location', '=', False), ('destruction_location', '=', False), |
848 | + ('output_ok', '=', False), ('input_ok', '=', False)]" |
849 | + attrs="{'readonly': [('type', '!=', 'make_to_stock')]}" |
850 | + on_change="change_location(location_id, line_ids)" /> |
851 | + <field name="related_sourcing_ok" invisible="1" /> |
852 | + <field name="related_sourcing_id" |
853 | + attrs="{'readonly': ['|', '|', '|', ('supplier_id', '=', False), ('related_sourcing_ok', '=', False), ('type', '!=', 'make_to_order'), ('po_cft', 'not in', ['po', 'dpo'])]}" /> |
854 | </group> |
855 | <separator colspan="4" string="Actions" /> |
856 | <button special="cancel" string="Cancel" icon="gtk-cancel" help="Close the wizard" /> |