[FIX] mrp: fix YAML test to perform proper float comparisons
[odoo/odoo.git] / addons / mrp / test / order_process.yml
1 -
2   I compute the production order.
3 -
4   !python {model: mrp.production}: |
5     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"), context=context)
6     order.action_compute(context=context)
7 -
8   I check production lines after compute.
9 -
10   !python {model: mrp.production}: |
11     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"), context=context)
12     assert len(order.product_lines) == 5, "Production lines are not generated proper."
13     factor = 12.0*5.0
14     sidepanel = False
15     woodlintelm = False
16     woodmm0 = False
17     woodmm10 = False
18     metalcleats = False
19     for line in order.product_lines:
20         if line.product_id.id == ref('product.product_product_sidepanel0'):                         #SIDEPAN     2          PCE
21             assert not sidepanel, "Production line is already generated for SIDEPAN."
22             assert line.product_qty == (2.0*factor), "Qty is not correspond."
23             assert line.product_uom.id == ref('product.product_uom_unit'), "UOM is not correspond"
24             sidepanel = True
25         elif line.product_id.id == ref('product.product_product_woodlintelm0'):                     #LIN40           4*0.25 Meter       
26             assert not woodlintelm, "Production line is already generated for LIN40."            
27             assert line.product_qty == (4*0.25*factor), "Qty is not correspond."
28             assert line.product_uom.id == ref('product.product_uom_meter'), "UOM is not correspond"
29             woodlintelm = True
30         elif line.product_id.id == ref('product.product_product_woodmm0'):                          #WOOD002     0.25       m
31             assert not woodmm0, "Production line is already generated for WOOD002."
32             assert line.product_qty == (0.25*factor), "Qty is not correspond."
33             assert line.product_uom.id == ref('product.product_uom_meter'), "UOM is not correspond"
34             woodmm0 = True
35         elif line.product_id.id == ref('product.product_product_metalcleats0'):                     #METC000      4*3      PCE  
36             assert not metalcleats, "Production line is already generated for METC000."
37             assert line.product_qty == (4*3*factor), "Qty is not correspond."
38             assert line.product_uom.id == ref('product.product_uom_unit'), "UOM is not correspond"
39             metalcleats = True
40         elif line.product_id.id == ref('product.product_product_woodmm10'):                         #WOOD010     0.083*3        m
41             assert not woodmm10, "Production line is already generated for WOOD010."
42             assert line.product_qty == (0.083*3*factor), "Qty is not correspond."
43             assert line.product_uom.id == ref('product.product_uom_meter'), "UOM is not correspond"
44             woodmm10 = True
45         else:
46             raise AssertionError('unknown order line: %s' % line)
47     assert sidepanel, "Production line is not generated for SIDEPAN."
48     assert woodlintelm, "Production line is not generated for LIN40."
49     assert woodmm0, "Production line is not generated for WOOD002."
50     assert metalcleats, "Production line is not generated for METC000."
51     assert woodmm10, "Production line is not generated for WOOD010."
52
53 -
54   Now I check workcenter lines.
55 -
56   !python {model: mrp.production}: |
57     from tools import float_compare
58     def assert_equals(value1, value2, msg, float_compare=float_compare):
59         assert float_compare(value1, value2, precision_digits=2) == 0, msg
60     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"), context=context)
61     assert len(order.workcenter_lines), "Workcenter lines are not generated proper."
62     for line in order.workcenter_lines:
63         wc = line.workcenter_id
64         hours = ((wc.time_start or 0.0)+(wc.time_stop or 0.0)+line.cycle*(wc.time_cycle or 0.0)) * (wc.time_efficiency or 1.0)
65         factor = 5*12
66         d, m = divmod(factor, wc.capacity_per_cycle)
67         cycle = (d + (m and 1.0 or 0.0))
68         if line.name == "Short time assembly - Assembly Section":
69             assert_equals(line.cycle, (4*cycle), "Computed cycles mismatch: %s" % (line.name))
70             assert_equals(line.hour, (2*cycle*4 + hours), "Computed hours mismatch: %s"% (line.name))
71         elif line.name == "Short time assembly - Rear Panel SHE100":
72             assert_equals(line.cycle, (1*cycle), "Computed cycles mismatch: %s" % (line.name))
73             assert_equals(line.hour, (2*cycle + hours), "Computed hours mismatch: %s"% (line.name))
74         elif line.name == "long time assembly - Shelf of 100cm":
75             assert_equals(line.cycle, (2*cycle), "Computed cycles mismatch: %s" % (line.name))
76             assert_equals(line.hour, (5*cycle + hours), "Computed hours mismatch: %s"% (line.name))
77         elif line.name == "Testing - Shelf of 100cm":
78             assert_equals(line.cycle, (1*cycle), "Computed cycles mismatch: %s" % (line.name))
79             assert_equals(line.hour, (1*cycle + hours), "Computed hours mismatch: %s"% (line.name))
80         elif line.name == "Packing - Shelf of 100cm":
81             assert_equals(line.cycle, (1*cycle), "Computed cycles mismatch: %s" % (line.name))
82             assert_equals(line.hour, (0.5*cycle + hours), "Computed hours mismatch: %s"% (line.name))
83         else:
84             raise AssertionError('unknown workcenter line: %s' % line)
85 -
86   I confirm the Production Order.
87 -
88   !workflow {model: mrp.production, action: button_confirm, ref: mrp_production_shelf100cm}
89 -
90   I check details of Produce Move of Production Order to trace Final Product.
91 -
92   !python {model: mrp.production}: |
93     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
94     assert order.state == 'confirmed', "Production order should be confirmed."
95     assert order.move_created_ids, "Trace Record is not created for Final Product."
96     move = order.move_created_ids[0]
97     source_location_id = order.product_id.product_tmpl_id.property_stock_production.id
98     assert move.date == order.date_planned, "Planned date is not correspond."
99     assert move.product_id.id == order.product_id.id, "Product is not correspond."
100     assert move.product_uom.id == order.product_uom.id, "UOM is not correspond."
101     assert move.product_qty == order.product_qty, "Qty is not correspond."
102     assert move.product_uos_qty == order.product_uos and order.product_uos_qty or order.product_qty, "UOS qty is not correspond."
103     if order.product_uos:
104         assert move.product_uos.id == order.product_uos.id, "UOS is not correspond."
105     assert move.location_id.id == source_location_id, "Source Location is not correspond."
106     assert move.location_dest_id.id == order.location_dest_id.id, "Destination Location is not correspond."
107     routing_loc = None
108     if order.bom_id.routing_id and order.bom_id.routing_id.location_id:
109         routing_loc = order.bom_id.routing_id.location_id.id
110     date_planned = order.date_planned    
111     for move_line in order.move_lines:
112         for order_line in order.product_lines:
113             if move_line.product_id.type not in ('product', 'consu'):
114                 continue
115             if move_line.product_id.id == order_line.product_id.id:
116                 assert move_line.date == date_planned, "Planned date is not correspond in 'To consume line'."
117                 assert move_line.product_qty == order_line.product_qty, "Qty is not correspond in 'To consume line'."
118                 assert move_line.product_uom.id == order_line.product_uom.id, "UOM is not correspond in 'To consume line'."
119                 assert move_line.product_uos_qty == order_line.product_uos and order_line.product_uos_qty or order_line.product_qty, "UOS qty is not correspond in 'To consume line'."
120                 if order_line.product_uos:
121                     assert move_line.product_uos.id == order_line.product_uos.id, "UOS is not correspond in 'To consume line'."
122                 assert move_line.location_id.id == routing_loc or order.location_src_id.id, "Source location is not correspond in 'To consume line'."
123                 assert move_line.location_dest_id.id == source_location_id, "Destination Location is not correspond in 'To consume line'."
124
125 -
126   I check details of an Internal Shipment after confirmed production order to bring components in Raw Materials Location.
127 -
128   !python {model: mrp.production}: |
129     procurement = self.pool.get('procurement.order')
130     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
131     assert order.picking_id, 'Internal Shipment should be created!'
132     
133     routing_loc = None
134     pick_type = 'internal'
135     address_id = False
136     if order.bom_id.routing_id and order.bom_id.routing_id.location_id:
137         routing_loc = order.bom_id.routing_id.location_id
138         if routing_loc.usage <> 'internal':
139             pick_type = 'out'
140         address_id = routing_loc.address_id and routing_loc.address_id.id or False
141         routing_loc = routing_loc.id
142     assert order.picking_id.type == pick_type, "Shipment should be Internal."
143     assert order.picking_id.address_id.id ==  address_id, "Shipment Address is not correspond with Adderss of Routing Location."
144     date_planned = order.date_planned
145     for move_line in order.picking_id.move_lines:
146         for order_line in order.product_lines:
147             if move_line.product_id.type not in ('product', 'consu'):
148                 continue
149             if move_line.product_id.id == order_line.product_id.id:
150                 assert move_line.date == date_planned, "Planned date is not correspond."
151                 assert move_line.product_qty == order_line.product_qty, "Qty is not correspond."
152                 assert move_line.product_uom.id == order_line.product_uom.id, "UOM is not correspond."
153                 assert move_line.product_uos_qty == order_line.product_uos and order_line.product_uos_qty or order_line.product_qty, "UOS qty is not correspond."
154                 if order_line.product_uos:
155                     assert move_line.product_uos.id == order_line.product_uos.id, "UOS is not correspond."
156                 assert move_line.location_id.id == order.location_src_id.id, "Source location is not correspond."
157                 assert move_line.location_dest_id.id == routing_loc or order.location_src_id.id, "Destination Location is not correspond."
158                 procurement_ids = procurement.search(cr, uid, [('move_id','=',move_line.id)])
159                 assert procurement_ids, "Procurement should be created for shipment line of raw materials."
160                 shipment_procurement = procurement.browse(cr, uid, procurement_ids[0], context=context)
161                 assert shipment_procurement.date_planned == date_planned, "Planned date is not correspond in procurement."
162                 assert shipment_procurement.product_id.id == order_line.product_id.id, "Product is not correspond in procurement."
163                 assert shipment_procurement.product_qty == order_line.product_qty, "Qty is not correspond in procurement."
164                 assert shipment_procurement.product_uom.id == order_line.product_uom.id, "UOM is not correspond in procurement."
165                 assert shipment_procurement.product_uos_qty == order_line.product_uos and order_line.product_uos_qty or order_line.product_qty, "UOS qty is not correspond in procurement."
166                 if order_line.product_uos:
167                     assert shipment_procurement.product_uos.id == order_line.product_uos.id, "UOS is not correspond in procurement."
168                 assert shipment_procurement.location_id.id == order.location_src_id.id, "Location is not correspond in procurement."
169                 assert shipment_procurement.procure_method == order_line.product_id.procure_method, "Procure method is not correspond in procurement."
170    
171 -
172   I change production qty with 3 Dozen Shelf 100cm.
173 -
174   !python {model: change.production.qty}: |
175     context.update({'active_id': ref('mrp_production_shelf100cm')})
176 -
177   !record {model: change.production.qty, id: mrp_production_qty}:
178     product_qty: 3.0
179 -
180   !python {model: change.production.qty}: |
181     self.change_prod_qty(cr, uid, [ref("mrp_production_qty")], context=context)
182 -
183   I check qty after changed in production order.
184 -
185   !python {model: mrp.production}: |
186     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
187     assert order.product_qty == 3, "Qty is not changed in order."
188     move = order.move_created_ids[0]
189     assert move.product_qty == order.product_qty, "Qty is not changed in move line."
190 -  
191   I run scheduler.
192 -
193   !python {model: procurement.order}: |
194     self.run_scheduler(cr, uid)
195 -
196   The production order is Waiting Goods, I forcefully done internal shipment.
197 -
198   !python {model: mrp.production}: |
199     self.force_production(cr, uid, [ref("mrp_production_shelf100cm")])
200 -
201   I check that production order in ready state after forcefully done internal shipment.
202 -
203   !python {model: mrp.production}: |
204     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
205     assert order.state == 'ready', 'Production order should be in Ready State.'
206     assert order.picking_id.state == 'done', 'Internal shipment should be done.'
207 -
208   Now I start production.
209 -
210   !workflow {model: mrp.production, action: button_produce, ref: mrp_production_shelf100cm}
211 -
212   I check that production order in production state after start production.
213 -
214   !python {model: mrp.production}: |
215     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
216     assert order.state == 'in_production', 'Production order should be in production State.'
217 -
218   I consume raw materials and put one material in scrap location due to waste it.
219 -
220   !python {model: mrp.production}: |
221     scrap_location_ids = self.pool.get('stock.location').search(cr, uid, [('scrap_location','=',True)])
222     scrap_location_id = scrap_location_ids[0]
223     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
224     for move in order.move_lines:
225         move.action_consume(move.product_qty)
226         if move.product_id.id == ref("product.product_product_metalcleats0"): 
227             move.action_scrap(5.0, scrap_location_id)
228 -
229   I produce product.
230 -
231   !python {model: mrp.product.produce}: |
232     context.update({'active_id': ref('mrp_production_shelf100cm')})
233 -
234   !record {model: mrp.product.produce, id: mrp_product_produce1}:
235     mode: 'consume_produce'
236 -
237   !python {model: mrp.product.produce}: |
238     self.do_produce(cr, uid, [ref('mrp_product_produce1')], context=context)
239 -
240   I check production order after produced.
241 -
242   !python {model: mrp.production}: |
243     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
244     assert order.state == 'done', "Production order should be closed."
245
246   I check Total Costs at End of Production. 
247 -
248   !python {model: mrp.production}: |
249     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
250     account_analytic_line = self.pool.get('account.analytic.line')
251     def rounding(f, r):
252         import math
253         if not r:
254             return f
255         return math.ceil(f / r) * r
256
257     for wc_line in order.workcenter_lines:
258         wc = wc_line.workcenter_id
259         accounts = [wc.costs_hour_account_id, wc.costs_cycle_account_id]
260         cost_per_cyle = wc_line.cycle * wc.costs_cycle
261         cost_per_hours = wc_line.hour * wc.costs_hour
262         if accounts and wc.costs_journal_id and wc.costs_general_account_id and (cost_per_cyle or cost_per_hours):
263             line_ids = account_analytic_line.search(cr, uid, [('name','ilike',wc_line.name)])
264             assert line_ids, 'Costs lines are not generated.'
265             for line in account_analytic_line.browse(cr, uid, line_ids, context=context):
266                 if wc.costs_hour_account_id and line.account_id.id == wc.costs_hour_account_id.id:
267                     assert rounding(line.unit_amount, 3) == rounding(wc_line.hour, 3), "Cost Unit Amount is not correspond."
268                     assert rounding(line.amount, 3) == rounding(cost_per_hours, 3), "Cost amount is not correspond."
269                 elif wc.costs_cycle_account_id and line.account_id.id == wc.costs_cycle_account_id.id:
270                     assert rounding(line.unit_amount, 3) == rounding(wc_line.cycle, 3), "Cost Unit Amount is not correspond."
271                     assert rounding(line.amount, 3) == rounding(cost_per_cyle, 3), "Cost Amount is not correspond."
272                 else:
273                     raise AssertionError('unknown cost line: %s' % line)
274                 assert line.general_account_id.id == wc.costs_general_account_id.id, "General Account is not correspond."
275                 assert line.journal_id.id == wc.costs_journal_id.id, "Account Journal is not correspond."
276                 assert line.product_id.id == wc.product_id.id, "Product is not correspond."
277                 assert line.product_uom_id.id == wc.product_id.uom_id.id, "UOM is not correspond."
278             
279 -
280   I print a "BOM Structure".
281 -
282   !python {model: mrp.production}: |
283     import netsvc, tools, os
284     order = self.browse(cr, uid, ref("mrp_production_shelf100cm"))
285     (data, format) = netsvc.LocalService('report.bom.structure').create(cr, uid, [order.bom_id.id], {}, {})
286     if tools.config['test_report_directory']:
287         file(os.path.join(tools.config['test_report_directory'], 'mrp-bom_structure_report.'+format), 'wb+').write(data)
288
289 -
290   I print "Production Order".
291 -
292   !python {model: mrp.production}: |
293     import netsvc, tools, os
294     (data, format) = netsvc.LocalService('report.mrp.production.order').create(cr, uid, [ref("mrp_production_shelf100cm")], {}, {})
295     if tools.config['test_report_directory']:
296         file(os.path.join(tools.config['test_report_directory'], 'mrp-production_order_report.'+format), 'wb+').write(data)
297
298 -
299   I print  "Work Center Load Report".
300 -
301   !python {model: mrp.workcenter}: |
302     ctx = context.copy()
303     ctx.update({'model': 'mrp.workcenter','active_ids': [ref('mrp_workcenter_0'),ref('mrp_workcenter_1')]})
304     data_dict = {'time_unit': 'day', 'measure_unit': 'hours'}
305     from tools import test_reports
306     test_reports.try_report_action(cr, uid, 'action_mrp_workcenter_load_wizard',wiz_data=data_dict, context=ctx, our_module='mrp')
307