Merge lp:~unifield-team/unifield-server/us-1160 into lp:unifield-server

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
Reviewer Review Type Date Requested Status
UniField Reviewer Team Pending
Review via email: mp+292800@code.launchpad.net
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" />

Subscribers

People subscribed via source and target branches

to all changes: