Merge lp:~openerp-dev/openobject-addons/trunk-wms-mrpclean-jco into lp:~openerp-dev/openobject-addons/trunk-wms

Proposed by Josse Colpaert (OpenERP)
Status: Merged
Merged at revision: 9695
Proposed branch: lp:~openerp-dev/openobject-addons/trunk-wms-mrpclean-jco
Merge into: lp:~openerp-dev/openobject-addons/trunk-wms
Diff against target: 296 lines (+46/-50)
10 files modified
mrp/mrp.py (+12/-32)
mrp/mrp_view.xml (+5/-7)
mrp/stock.py (+1/-1)
mrp_operations/mrp_operations.py (+1/-1)
purchase/stock.py (+1/-1)
sale_mrp/test/cancellation_propagated.yml (+7/-2)
sale_mrp/test/sale_mrp.yml (+3/-3)
stock/procurement.py (+1/-2)
stock/stock.py (+9/-0)
stock_dropshipping/test/cancellation_propagated.yml (+6/-1)
To merge this branch: bzr merge lp:~openerp-dev/openobject-addons/trunk-wms-mrpclean-jco
Reviewer Review Type Date Requested Status
qdp (OpenERP) Approve
Review via email: mp+217020@code.launchpad.net

Description of the change

Propagation of stock move cancelling (forward), cancels procurements in between when possible. The cancelling mrp/purchase order does not cancel entire chain. Backward cancelling of procurements should not check propagate on rule, but should depend on move cancellation only. (if move is propagate and cancelled, cancel procurement before)

To post a comment you must log in.
Revision history for this message
qdp (OpenERP) (qdp) wrote :

line 246 === modified file 'stock/stock.py'

i don't think it's gonna work, i need to test more: it seems that if i cancel the move stock -> customer in a MTO it will also set the procurement in customer in cancelled instead of exception because move.procurement_id link to the procurement that _created_ the move, not the one _created by_ the move.

Revision history for this message
qdp (OpenERP) (qdp) wrote :

otherwise, i just need to adapt the code first to create procurement if a service product has been set on a bom before removing entirely the function _make_production_line_procurement()

Revision history for this message
qdp (OpenERP) (qdp) wrote :

sorry, my bad: it was correct. :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'mrp/mrp.py'
2--- mrp/mrp.py 2014-04-23 15:05:03 +0000
3+++ mrp/mrp.py 2014-04-24 10:15:52 +0000
4@@ -493,7 +493,7 @@
5 'workcenter_lines': fields.one2many('mrp.production.workcenter.line', 'production_id', 'Work Centers Utilisation',
6 readonly=True, states={'draft': [('readonly', False)]}),
7 'state': fields.selection(
8- [('draft', 'New'), ('cancel', 'Cancelled'), ('picking_except', 'Picking Exception'), ('confirmed', 'Awaiting Raw Materials'),
9+ [('draft', 'New'), ('cancel', 'Cancelled'), ('confirmed', 'Awaiting Raw Materials'),
10 ('ready', 'Ready to Produce'), ('in_production', 'Production Started'), ('done', 'Done')],
11 string='Status', readonly=True,
12 track_visibility='onchange',
13@@ -614,12 +614,6 @@
14 }
15 return {'value': result}
16
17- def action_picking_except(self, cr, uid, ids):
18- """ Changes the state to Exception.
19- @return: True
20- """
21- self.write(cr, uid, ids, {'state': 'picking_except'})
22- return True
23
24 def _action_compute_lines(self, cr, uid, ids, properties=None, context=None):
25 """ Compute product_lines and workcenter_lines from BoM structure
26@@ -685,6 +679,11 @@
27 move_obj.action_cancel(cr, uid, [x.id for x in production.move_created_ids])
28 move_obj.action_cancel(cr, uid, [x.id for x in production.move_lines])
29 self.write(cr, uid, ids, {'state': 'cancel'})
30+ # Put related procurements in exception
31+ proc_obj = self.pool.get("procurement.order")
32+ procs = proc_obj.search(cr, uid, [('production_id', 'in', ids)], context=context)
33+ if procs:
34+ proc_obj.write(cr, uid, procs, {'state': 'exception'}, context=context)
35 return True
36
37 def action_ready(self, cr, uid, ids, context=None):
38@@ -697,8 +696,6 @@
39 for production in self.browse(cr, uid, ids, context=context):
40 if not production.move_created_ids:
41 self._make_production_produce_line(cr, uid, production, context=context)
42- for scheduled in production.product_lines:
43- self._make_production_line_procurement(cr, uid, scheduled, False, context=context)
44
45 if production.move_prod_id and production.move_prod_id.location_id.id != production.location_dest_id.id:
46 move_obj.write(cr, uid, [production.move_prod_id.id],
47@@ -712,6 +709,10 @@
48 for production in self.browse(cr, uid, ids):
49 self._costs_generate(cr, uid, production)
50 write_res = self.write(cr, uid, ids, {'state': 'done', 'date_finished': time.strftime('%Y-%m-%d %H:%M:%S')})
51+ # Check related procurements
52+ proc_obj = self.pool.get("procurement.order")
53+ procs = proc_obj.search(cr, uid, [('production_id', 'in', ids)], context=context)
54+ proc_obj.check(cr, uid, procs, context=context)
55 return write_res
56
57 def test_production_done(self, cr, uid, ids):
58@@ -965,29 +966,8 @@
59 if production.ready_production:
60 res = True
61 return res
62-
63- def _make_production_line_procurement(self, cr, uid, production_line, shipment_move_id, context=None):
64- procurement_order = self.pool.get('procurement.order')
65- production = production_line.production_id
66- location_id = production.location_src_id.id
67- date_planned = production.date_planned
68- procurement_name = (production.origin or '').split(':')[0] + ':' + production.name
69- procurement_id = procurement_order.create(cr, uid, {
70- 'name': procurement_name,
71- 'origin': procurement_name,
72- 'date_planned': date_planned,
73- 'product_id': production_line.product_id.id,
74- 'product_qty': production_line.product_qty,
75- 'product_uom': production_line.product_uom.id,
76- 'product_uos_qty': production_line.product_uos and production_line.product_qty or False,
77- 'product_uos': production_line.product_uos and production_line.product_uos.id or False,
78- 'location_id': location_id,
79- 'move_id': shipment_move_id,
80- 'company_id': production.company_id.id,
81- })
82- procurement_order.signal_button_confirm(cr, uid, [procurement_id])
83- return procurement_id
84-
85+
86+
87 def _make_production_produce_line(self, cr, uid, production, context=None):
88 stock_move = self.pool.get('stock.move')
89 source_location_id = production.product_id.property_stock_production.id
90
91=== modified file 'mrp/mrp_view.xml'
92--- mrp/mrp_view.xml 2014-04-22 09:28:15 +0000
93+++ mrp/mrp_view.xml 2014-04-24 10:15:52 +0000
94@@ -674,12 +674,10 @@
95 <button name="button_confirm" states="draft" string="Confirm Production" class="oe_highlight"/>
96 <button name="%(act_mrp_product_produce)d" states="ready,in_production" string="Produce" type="action" class="oe_highlight"/>
97 <button name="force_production" states="confirmed" string="Force Reservation" type="object"/>
98- <button name="force_production" states="picking_except" string="Force Reservation" type="object"/>
99 <button name="button_produce" states="ready" string="Mark as Started"/>
100- <button name="button_recreate" states="picking_except" string="Recreate Picking"/>
101- <button name="button_cancel" states="draft,ready,in_production,picking_except" string="Cancel Production"/>
102+ <button name="button_cancel" states="draft,ready,in_production" string="Cancel Production"/>
103 <button name="action_cancel" type="object" states="confirmed" string="Cancel Production"/>
104- <field name="state" widget="statusbar" statusbar_visible="draft,ready,in_production,done" statusbar_colors='{"picking_except":"red","confirmed":"blue"}'/>
105+ <field name="state" widget="statusbar" statusbar_visible="draft,ready,in_production,done" statusbar_colors='{"confirmed":"blue"}'/>
106 </header>
107 <sheet>
108 <div class="oe_title">
109@@ -720,7 +718,7 @@
110 <group>
111 <group string="Products to Consume">
112 <field name="move_lines" nolabel="1" options="{'reload_on_button': true}">
113- <tree colors="blue:state == 'draft';black:state in ('ready','assigned','in_production');gray:state in ('cancel','done');red:state in ('confirmed','picking_except','waiting')" string="Products to Consume">
114+ <tree colors="blue:state == 'draft';black:state in ('ready','assigned','in_production');gray:state in ('cancel','done');red:state in ('confirmed','waiting')" string="Products to Consume">
115 <field name="product_id"/>
116 <field name="product_qty" string="Quantity"/>
117 <field name="product_uom" string="Unit of Measure" groups="product.group_uom"/>
118@@ -739,7 +737,7 @@
119 </group>
120 <group string="Consumed Products">
121 <field name="move_lines2" nolabel="1" options="{'reload_on_button': true}">
122- <tree colors="red:scrapped==True;blue:state == 'draft';black:state in('picking_except','confirmed','ready','in_production');gray:state == 'cancel' " string="Consumed Products" editable="bottom">
123+ <tree colors="red:scrapped==True;blue:state == 'draft';black:state in ('confirmed','ready','in_production');gray:state == 'cancel' " string="Consumed Products" editable="bottom">
124 <field name="product_id" readonly="1"/>
125 <field name="restrict_lot_id" context="{'product_id': product_id}" groups="stock.group_tracking_lot"/>
126 <field name="product_qty" readonly="1"/>
127@@ -766,7 +764,7 @@
128 </group>
129 <group string="Produced Products">
130 <field name="move_created_ids2" nolabel="1" options="{'reload_on_button': true}">
131- <tree colors="red:scrapped==True;blue:state == 'draft';black:state in('picking_except','confirmed','ready','in_production');gray:state in('cancel','done') " string="Finished Products">
132+ <tree colors="red:scrapped==True;blue:state == 'draft';black:state in('confirmed','ready','in_production');gray:state in('cancel','done') " string="Finished Products">
133 <field name="product_id" readonly="1"/>
134 <field name="product_qty" readonly="1"/>
135 <field name="restrict_lot_id" groups="stock.group_tracking_lot"/>
136
137=== modified file 'mrp/stock.py'
138--- mrp/stock.py 2014-02-14 15:03:30 +0000
139+++ mrp/stock.py 2014-04-24 10:15:52 +0000
140@@ -227,7 +227,7 @@
141 'route_id': manufacture_route_id,
142 'action': 'manufacture',
143 'picking_type_id': warehouse.int_type_id.id,
144- 'procure_method': 'make_to_order',
145+ 'propagate': False,
146 'warehouse_id': warehouse.id,
147 }
148
149
150=== modified file 'mrp_operations/mrp_operations.py'
151--- mrp_operations/mrp_operations.py 2014-04-03 09:38:33 +0000
152+++ mrp_operations/mrp_operations.py 2014-04-24 10:15:52 +0000
153@@ -97,7 +97,7 @@
154 'delay': fields.float('Working Hours',help="The elapsed time between operation start and stop in this Work Center",readonly=True),
155 'production_state':fields.related('production_id','state',
156 type='selection',
157- selection=[('draft','Draft'),('picking_except', 'Picking Exception'),('confirmed','Waiting Goods'),('ready','Ready to Produce'),('in_production','In Production'),('cancel','Canceled'),('done','Done')],
158+ selection=[('draft','Draft'),('confirmed','Waiting Goods'),('ready','Ready to Produce'),('in_production','In Production'),('cancel','Canceled'),('done','Done')],
159 string='Production Status', readonly=True),
160 'product':fields.related('production_id','product_id',type='many2one',relation='product.product',string='Product',
161 readonly=True),
162
163=== modified file 'purchase/stock.py'
164--- purchase/stock.py 2014-04-16 15:05:51 +0000
165+++ purchase/stock.py 2014-04-24 10:15:52 +0000
166@@ -116,7 +116,7 @@
167 'route_id': buy_route_id,
168 'action': 'buy',
169 'picking_type_id': warehouse.in_type_id.id,
170- 'procure_method': 'make_to_order',
171+ 'propagate': False,
172 'warehouse_id': warehouse.id,
173 }
174
175
176=== modified file 'sale_mrp/test/cancellation_propagated.yml'
177--- sale_mrp/test/cancellation_propagated.yml 2013-10-29 19:27:02 +0000
178+++ sale_mrp/test/cancellation_propagated.yml 2014-04-24 10:15:52 +0000
179@@ -51,12 +51,17 @@
180 Confirm sales order
181 -
182 !workflow {model: sale.order, action: order_confirm, ref: sale_order_product_manu}
183+-
184+ I run scheduler.
185+-
186+ !python {model: procurement.order}: |
187+ self.run_scheduler(cr, uid)
188 -
189 Check the propagation when we cancel the main procurement
190 * Retrieve related procurements and check that there are all running
191 * Check that the purchase order has been well created
192 * Cancel the main procurement
193- * Check that all procurements related and the purchase order has been well cancelled
194+ * Check that all procurements related and the purchase order has been well cancelled
195 -
196 !python {model: procurement.order}: |
197 # Retrieve related procu
198@@ -65,7 +70,7 @@
199 assert len(procu_ids)>0, 'No procurements are found for sale order "%s" (with id : %d)' %(so.name, so.id)
200
201 # Check that all procurements are running
202- for procu in self.browse(cr, uid, procu_ids, context=context):
203+ for procu in self.browse(cr, uid, procu_ids, context=context):
204 assert procu.state == u'running', 'Procurement with id %d should be "running" but is with a state : %s!' %(procu.id, procu.state)
205
206 # Check that one production order exist
207
208=== modified file 'sale_mrp/test/sale_mrp.yml'
209--- sale_mrp/test/sale_mrp.yml 2014-02-11 09:44:44 +0000
210+++ sale_mrp/test/sale_mrp.yml 2014-04-24 10:15:52 +0000
211@@ -100,7 +100,7 @@
212 !python {model: procurement.order}: |
213 sale_order_obj = self.pool.get('sale.order')
214 so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
215- proc_ids = self.search(cr, uid, [('origin','=',so.name)])
216+ proc_ids = self.search(cr, uid, [('origin','like',so.name)])
217 self.run(cr, uid, proc_ids)
218 -
219 I verify that a procurement state is "running"
220@@ -108,8 +108,8 @@
221 !python {model: procurement.order}: |
222 sale_order_obj = self.pool.get('sale.order')
223 so = sale_order_obj.browse(cr, uid, ref("sale_order_so0"))
224- proc_ids = self.search(cr, uid, [('origin','like',so.name), ('state','=','running')])
225- # Check that all procurement are running
226+ proc_ids = self.search(cr, uid, [('origin','like',so.name)])
227+ # Check that all procurement are running
228 for procu in self.browse(cr,uid,proc_ids,context=context):
229 assert procu.state == u'running', 'Procurement with id %d should be with a state "running" but is with a state : %s!' %(procu.id,procu.state)
230 -
231
232=== modified file 'stock/procurement.py'
233--- stock/procurement.py 2014-04-23 15:55:57 +0000
234+++ stock/procurement.py 2014-04-24 10:15:52 +0000
235@@ -99,8 +99,7 @@
236 #set the context for the propagation of the procurement cancelation
237 ctx['cancel_procurement'] = True
238 for procurement in self.browse(cr, uid, to_cancel_ids, context=ctx):
239- if procurement.rule_id and procurement.rule_id.propagate:
240- self.propagate_cancel(cr, uid, procurement, context=ctx)
241+ self.propagate_cancel(cr, uid, procurement, context=ctx)
242 return super(procurement_order, self).cancel(cr, uid, to_cancel_ids, context=ctx)
243
244 def _find_parent_locations(self, cr, uid, procurement, context=None):
245
246=== modified file 'stock/stock.py'
247--- stock/stock.py 2014-04-23 15:55:57 +0000
248+++ stock/stock.py 2014-04-24 10:15:52 +0000
249@@ -2144,6 +2144,14 @@
250 #cancel chained moves
251 if move.propagate:
252 self.action_cancel(cr, uid, [move.move_dest_id.id], context=context)
253+ # If we have a long chain of moves to be cancelled, it is easier for the user to handle
254+ # only the last procurement which will go into exception, instead of all procurements
255+ # along the chain going into exception. We need to check if there are no split moves not cancelled however
256+ if move.procurement_id:
257+ proc = move.procurement_id
258+ if all([x.state == 'cancel' for x in proc.move_ids if x.id != move.id]):
259+ procurement_obj.write(cr, uid, [proc.id], {'state': 'cancel'})
260+
261 elif move.move_dest_id.state == 'waiting':
262 self.write(cr, uid, [move.move_dest_id.id], {'state': 'confirmed'}, context=context)
263 return self.write(cr, uid, ids, {'state': 'cancel', 'move_dest_id': False}, context=context)
264@@ -2360,6 +2368,7 @@
265 'restrict_lot_id': restrict_lot_id,
266 'restrict_partner_id': restrict_partner_id,
267 'split_from': move.id,
268+ 'move_dest_id': move.move_dest_id.id,
269 }
270 if context.get('source_location_id'):
271 defaults['location_id'] = context['source_location_id']
272
273=== modified file 'stock_dropshipping/test/cancellation_propagated.yml'
274--- stock_dropshipping/test/cancellation_propagated.yml 2013-10-29 19:27:02 +0000
275+++ stock_dropshipping/test/cancellation_propagated.yml 2014-04-24 10:15:52 +0000
276@@ -40,6 +40,11 @@
277 Confirm the sale order
278 -
279 !workflow {model: sale.order, action: order_confirm, ref: sale_order_product_mto}
280+-
281+ I run scheduler.
282+-
283+ !python {model: procurement.order}: |
284+ self.run_scheduler(cr, uid)
285 -
286 Check the propagation when we cancel the main procurement
287 * Retrieve related procurements and check that there are all running
288@@ -64,7 +69,7 @@
289 # Cancel the main procurement
290 main_procu_id = self.search(cr, uid, [('origin', '=', so.name)])
291 assert len(main_procu_id) == 1, 'Main procurement not identified !'
292- self.cancel(cr, uid, main_procu_id, context=context)
293+ self.cancel(cr, uid, main_procu_id, context=context)
294 assert self.browse(cr, uid, main_procu_id[0]).state == u'cancel', 'Main procurement should be cancelled !'
295
296 # Check that all procurements related are cancelled