Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1202)

Delta Between Two Patch Sets: production.py

Issue 4306055: New production module (Closed)
Left Patch Set: Fix order of import Created 13 years, 1 month ago
Right Patch Set: To be sure Created 12 years, 11 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « product.xml ('k') | production.xml » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #This file is part of Tryton. The COPYRIGHT file at the top level of 1 #This file is part of Tryton. The COPYRIGHT file at the top level of
2 #this repository contains the full copyright notices and license terms. 2 #this repository contains the full copyright notices and license terms.
3 from trytond.model import ModelView, ModelSQL, fields 3 from decimal import Decimal
4 from trytond.pyson import Eval, Bool 4
5 from trytond.model import ModelView, ModelSQL, Workflow, fields
6 from trytond.wizard import Wizard, StateTransition, StateView, Button
7 from trytond.pyson import Eval, Bool, If, Id
5 from trytond.pool import Pool 8 from trytond.pool import Pool
6 from trytond.transaction import Transaction 9 from trytond.transaction import Transaction
7 10
8 BOM_CHANGES = ['bom', 'product', 'quantity', 'uom', 'warehouse', 'location', 11 BOM_CHANGES = ['bom', 'product', 'quantity', 'uom', 'warehouse', 'location',
9 'company', 'inputs', 'outputs'] 12 'company', 'inputs', 'outputs']
10 13
11 14
12 class Production(ModelSQL, ModelView): 15 class Production(Workflow, ModelSQL, ModelView):
13 "Production" 16 "Production"
14 _name = 'production' 17 _name = 'production'
15 _description = __doc__ 18 _description = __doc__
16 _rec_name = 'code' 19 _rec_name = 'code'
17 20
18 code = fields.Char('Code', select=True, readonly=True) 21 code = fields.Char('Code', select=True, readonly=True)
19 reference = fields.Char('Reference', select=1, 22 reference = fields.Char('Reference', select=1,
20 states={ 23 states={
21 'readonly': ~Eval('state').in_(['request', 'draft']), 24 'readonly': ~Eval('state').in_(['request', 'draft']),
22 }, 25 },
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 on_change_with=['uom']), 'get_unit_digits') 91 on_change_with=['uom']), 'get_unit_digits')
89 quantity = fields.Float('Quantity', 92 quantity = fields.Float('Quantity',
90 digits=(16, Eval('unit_digits', 2)), 93 digits=(16, Eval('unit_digits', 2)),
91 states={ 94 states={
92 'readonly': ~Eval('state').in_(['request', 'draft']), 95 'readonly': ~Eval('state').in_(['request', 'draft']),
93 'required': Bool(Eval('bom')), 96 'required': Bool(Eval('bom')),
94 'invisible': ~Eval('bom'), 97 'invisible': ~Eval('bom'),
95 }, 98 },
96 on_change=BOM_CHANGES, 99 on_change=BOM_CHANGES,
97 depends=['unit_digits']) 100 depends=['unit_digits'])
101 cost = fields.Function(fields.Numeric('Cost', digits=(16, 4),
102 readonly=True, on_change_with=['inputs']), 'get_cost')
98 inputs = fields.One2Many('stock.move', 'production_input', 'Inputs', 103 inputs = fields.One2Many('stock.move', 'production_input', 'Inputs',
99 domain=[ 104 domain=[
100 ('from_location', 'child_of', [Eval('warehouse')], 'parent'), 105 ('from_location', 'child_of', [Eval('warehouse')], 'parent'),
101 ('to_location', '=', Eval('location')), 106 ('to_location', '=', Eval('location')),
102 ], 107 ],
108 states={
109 'readonly': (~Eval('state').in_(['request', 'draft', 'waiting'])
110 | ~Eval('location')),
111 },
103 depends=['warehouse', 'location']) 112 depends=['warehouse', 'location'])
104 outputs = fields.One2Many('stock.move', 'production_output', 'Outputs', 113 outputs = fields.One2Many('stock.move', 'production_output', 'Outputs',
105 domain=[ 114 domain=[
106 ('from_location', '=', Eval('location')), 115 ('from_location', '=', Eval('location')),
107 ('to_location', 'child_of', [Eval('warehouse')], 'parent'), 116 ('to_location', 'child_of', [Eval('warehouse')], 'parent'),
108 ], 117 ],
118 states={
119 'readonly': (Eval('state').in_(['done', 'cancel'])
120 | ~Eval('location')),
121 },
109 depends=['warehouse', 'location']) 122 depends=['warehouse', 'location'])
110 state = fields.Selection([ 123 state = fields.Selection([
111 ('request', 'Request'), 124 ('request', 'Request'),
112 ('draft', 'Draft'), 125 ('draft', 'Draft'),
126 ('waiting', 'Waiting'),
113 ('assigned', 'Assigned'), 127 ('assigned', 'Assigned'),
114 ('running', 'Running'), 128 ('running', 'Running'),
115 ('done', 'Done'), 129 ('done', 'Done'),
116 ('cancel', 'Canceled'), 130 ('cancel', 'Canceled'),
117 ], 'State', readonly=True) 131 ], 'State', readonly=True)
118 132
133 def __init__(self):
134 super(Production, self).__init__()
135 self._constraints += [
136 ('check_cost', 'missing_cost'),
137 ]
138 self._error_messages.update({
139 'missing_cost': 'It misses some cost on the outputs!',
140 })
141 self._transitions |= set((
142 ('request', 'draft'),
143 ('draft', 'waiting'),
144 ('waiting', 'assigned'),
145 ('assigned', 'running'),
146 ('running', 'done'),
147 ('running', 'waiting'),
148 ('assigned', 'waiting'),
149 ('waiting', 'waiting'),
150 ('waiting', 'draft'),
151 ('request', 'cancel'),
152 ('draft', 'cancel'),
153 ('waiting', 'cancel'),
154 ('assigned', 'cancel'),
155 ('cancel', 'draft'),
156 ))
157 self._buttons.update({
158 'cancel': {
159 'invisible': ~Eval('state').in_(['request', 'draft',
160 'assigned']),
161 },
162 'draft': {
163 'invisible': ~Eval('state').in_(['request', 'waiting',
164 'cancel']),
165 'icon': If(Eval('state') == 'cancel',
166 'tryton-clear',
167 If(Eval('state') == 'request',
168 'tryton-go-next',
169 'tryton-go-previous')),
170 },
171 'wait': {
172 'invisible': ~Eval('state').in_(['draft', 'assigned',
173 'waiting', 'running']),
174 'icon': If(Eval('state').in_(['assigned', 'running']),
175 'tryton-go-previous',
176 If(Eval('state') == 'waiting',
177 'tryton-clear',
178 'tryton-go-next')),
179 },
180 'run': {
181 'invisible': Eval('state') != 'assigned',
182 },
183 'done': {
184 'invisible': Eval('state') != 'running',
185 },
186 'assign_try': {},
187 'assign_force': {},
188 })
189
119 def default_state(self): 190 def default_state(self):
120 return 'draft' 191 return 'draft'
121 192
122 def default_warehouse(self): 193 def default_warehouse(self):
123 location_obj = Pool().get('stock.location') 194 location_obj = Pool().get('stock.location')
124 location_ids = location_obj.search(self.warehouse.domain) 195 location_ids = location_obj.search(self.warehouse.domain)
125 if len(location_ids) == 1: 196 if len(location_ids) == 1:
126 return location_ids[0] 197 return location_ids[0]
127 return False
128 198
129 def default_location(self): 199 def default_location(self):
130 location_obj = Pool().get('stock.location') 200 location_obj = Pool().get('stock.location')
131 warehouse_id = self.default_warehouse() 201 warehouse_id = self.default_warehouse()
132 if warehouse_id: 202 if warehouse_id:
133 warehouse = location_obj.browse(warehouse_id) 203 warehouse = location_obj.browse(warehouse_id)
134 return warehouse.production_location.id 204 return warehouse.production_location.id
135 return False
136 205
137 def default_company(self): 206 def default_company(self):
138 return Transaction().context.get('company') or False 207 return Transaction().context.get('company')
139 208
140 def _move_values(self, from_location, to_location, company, bom_io, 209 def _move_values(self, from_location, to_location, company, product, uom,
141 quantity): 210 quantity):
142 values = { 211 values = {
143 'product': bom_io.product.id, 212 'product': product.id,
144 'product.rec_name': bom_io.product.rec_name, 213 'uom': uom.id,
145 'uom': bom_io.uom.id,
146 'uom.rec_name': bom_io.uom.rec_name,
147 'quantity': quantity, 214 'quantity': quantity,
148 'from_location': None, 215 'from_location': None,
149 'to_location': None, 216 'to_location': None,
150 'company': None, 217 'company': None,
218 'state': 'draft',
151 } 219 }
220 values['currency'] = company.currency.id if company else None
152 if from_location: 221 if from_location:
153 values['from_location'] = from_location.id 222 values['from_location'] = from_location.id
223 if to_location:
224 values['to_location'] = to_location.id
225 if company:
226 values['company'] = company.id
227 return values
228
229 def _explode_move_values(self, from_location, to_location, company,
230 bom_io, quantity):
231 pool = Pool()
232 move_obj = pool.get('stock.move')
233
234 values = self._move_values(from_location, to_location, company,
235 bom_io.product, bom_io.uom, quantity)
236 values['product.rec_name'] = bom_io.product.rec_name
237 values['uom.rec_name'] = bom_io.uom.rec_name
238 values['unit_price_required'] = \
239 move_obj.on_change_with_unit_price_required({
240 'from_location': (from_location.id if from_location else
241 None),
242 'to_location': to_location.id if to_location else None,
243 })
244 if from_location:
154 values['from_location.rec_name'] = from_location.rec_name 245 values['from_location.rec_name'] = from_location.rec_name
155 if to_location: 246 if to_location:
156 values['to_location'] = to_location.id
157 values['to_location.rec_name'] = to_location.rec_name 247 values['to_location.rec_name'] = to_location.rec_name
158 if company: 248 if company:
159 values['company'] = company.id,
160 values['company.rec_name'] = company.rec_name 249 values['company.rec_name'] = company.rec_name
161 return values 250 return values
162 251
163 def explode_bom(self, values): 252 def explode_bom(self, values):
164 pool = Pool() 253 pool = Pool()
165 bom_obj = pool.get('production.bom') 254 bom_obj = pool.get('production.bom')
166 product_obj = pool.get('product.product') 255 product_obj = pool.get('product.product')
167 uom_obj = pool.get('product.uom') 256 uom_obj = pool.get('product.uom')
168 input_obj = pool.get('production.bom.input') 257 input_obj = pool.get('production.bom.input')
169 output_obj = pool.get('production.bom.output') 258 output_obj = pool.get('production.bom.output')
170 location_obj = pool.get('stock.location') 259 location_obj = pool.get('stock.location')
171 company_obj = pool.get('company.company') 260 company_obj = pool.get('company.company')
172 261
173 if not (values.get('bom') 262 if not (values.get('bom')
174 and values.get('product') 263 and values.get('product')
175 and values.get('uom')): 264 and values.get('uom')):
176 return {} 265 return {}
177 inputs = { 266 inputs = {
178 'remove': [r['id'] for r in values.get('inputs') or []], 267 'remove': [r['id'] for r in values.get('inputs') or []],
179 'add': [], 268 'add': [],
180 } 269 }
181 outputs = { 270 outputs = {
182 'remove': [r['id'] for r in values.get('outputs') or []], 271 'remove': [r['id'] for r in values.get('outputs') or []],
183 'add': [], 272 'add': [],
184 } 273 }
185 changes = { 274 changes = {
186 'inputs': inputs, 275 'inputs': inputs,
187 'outputs': outputs, 276 'outputs': outputs,
277 'cost': Decimal(0),
188 } 278 }
189 279
190 bom = bom_obj.browse(values['bom']) 280 bom = bom_obj.browse(values['bom'])
191 product = product_obj.browse(values['product']) 281 product = product_obj.browse(values['product'])
192 quantity = values.get('quantity') or 0 282 quantity = values.get('quantity') or 0
193 uom = uom_obj.browse(values['uom']) 283 uom = uom_obj.browse(values['uom'])
194 if values.get('warehouse'): 284 if values.get('warehouse'):
195 warehouse = location_obj.browse(values['warehouse']) 285 warehouse = location_obj.browse(values['warehouse'])
196 storage_location = warehouse.storage_location 286 storage_location = warehouse.storage_location
197 else: 287 else:
198 storage_location = None 288 storage_location = None
199 if values.get('location'): 289 if values.get('location'):
200 location = location_obj.browse(values['location']) 290 location = location_obj.browse(values['location'])
201 else: 291 else:
202 location = None 292 location = None
203 if values.get('company'): 293 if values.get('company'):
204 company = company_obj.browse(values['company']) 294 company = company_obj.browse(values['company'])
205 else: 295 else:
206 company = None 296 company = None
207 297
208 factor = bom_obj.compute_factor(bom, product, quantity, uom) 298 factor = bom_obj.compute_factor(bom, product, quantity, uom)
209 for input_ in bom.inputs: 299 for input_ in bom.inputs:
210 quantity = input_obj.compute_quantity(input_, factor) 300 quantity = input_obj.compute_quantity(input_, factor)
211 values = self._move_values(storage_location, location, company, 301 values = self._explode_move_values(storage_location, location,
212 input_, quantity) 302 company, input_, quantity)
213 if values: 303 if values:
214 inputs['add'].append(values) 304 inputs['add'].append(values)
305 quantity = uom_obj.compute_qty(input_.uom, quantity,
306 input_.product.default_uom)
307 changes['cost'] += (Decimal(str(quantity)) *
308 input_.product.cost_price)
215 309
216 for output in bom.outputs: 310 for output in bom.outputs:
217 quantity = output_obj.compute_quantity(output, factor) 311 quantity = output_obj.compute_quantity(output, factor)
218 values = self._move_values(location, storage_location, company, 312 values = self._explode_move_values(location, storage_location,
219 output, quantity) 313 company, output, quantity)
220 if values: 314 if values:
315 values['unit_price'] = Decimal(0)
316 if output.product.id == values.get('product') and quantity:
317 values['unit_price'] = (changes['cost'] /
318 Decimal(str(quantity)))
221 outputs['add'].append(values) 319 outputs['add'].append(values)
222 return changes 320 return changes
223 321
224 def on_change_warehouse(self, values): 322 def on_change_warehouse(self, values):
225 location_obj = Pool().get('stock.location') 323 location_obj = Pool().get('stock.location')
226 changes = { 324 changes = {
227 'location': False, 325 'location': None,
228 } 326 }
229 if values.get('warehouse'): 327 if values.get('warehouse'):
230 warehouse = location_obj.browse(values['warehouse']) 328 warehouse = location_obj.browse(values['warehouse'])
231 changes['location'] = warehouse.production_location.id 329 changes['location'] = warehouse.production_location.id
232 return changes 330 return changes
233 331
234 def on_change_product(self, values): 332 def on_change_product(self, values):
235 product_obj = Pool().get('product.product') 333 product_obj = Pool().get('product.product')
236 334
237 result = {} 335 result = {}
238 if values.get('product'): 336 if values.get('product'):
239 product = product_obj.browse(values['product']) 337 product = product_obj.browse(values['product'])
240 uom_ids = [x.id for x in product.default_uom.category.uoms] 338 uom_ids = [x.id for x in product.default_uom.category.uoms]
241 if (not values.get('uom') 339 if (not values.get('uom')
242 or values.get('uom') not in uom_ids): 340 or values.get('uom') not in uom_ids):
243 result['uom'] = product.default_uom.id 341 result['uom'] = product.default_uom.id
244 result['uom.rec_name'] = product.default_uom.rec_name 342 result['uom.rec_name'] = product.default_uom.rec_name
245 result['unit_digits'] = product.default_uom.digits 343 result['unit_digits'] = product.default_uom.digits
246 else: 344 else:
247 result['uom'] = False 345 result['uom'] = None
248 result['uom.rec_name'] = '' 346 result['uom.rec_name'] = ''
249 result['unit_digits'] = 2 347 result['unit_digits'] = 2
250 348
251 values = values.copy() 349 values = values.copy()
252 values['uom'] = result['uom'] 350 values['uom'] = result['uom']
253 result.update(self.explode_bom(values)) 351 result.update(self.explode_bom(values))
254 return result 352 return result
255 353
256 def on_change_with_uom_category(self, values): 354 def on_change_with_uom_category(self, values):
257 product_obj = Pool().get('product.product') 355 product_obj = Pool().get('product.product')
258 if values.get('product'): 356 if values.get('product'):
259 product = product_obj.browse(values['product']) 357 product = product_obj.browse(values['product'])
260 return product.default_uom.category.id 358 return product.default_uom.category.id
261 return False
262 359
263 def get_uom_category(self, ids, name): 360 def get_uom_category(self, ids, name):
264 res = {} 361 res = {}
265 for input in self.browse(ids): 362 for production in self.browse(ids):
266 res[input.id] = input.product.default_uom.category.id 363 if production.product:
364 res[production.id] = production.product.default_uom.category.id
365 else:
366 res[production.id] = None
267 return res 367 return res
268 368
269 def on_change_with_unit_digits(self, values): 369 def on_change_with_unit_digits(self, values):
270 uom_obj = Pool().get('product.uom') 370 uom_obj = Pool().get('product.uom')
271 if values.get('uom'): 371 if values.get('uom'):
272 uom = uom_obj.browse(values['uom']) 372 uom = uom_obj.browse(values['uom'])
273 return uom.digits 373 return uom.digits
274 return 2 374 return 2
275 375
276 def get_unit_digits(self, ids, name): 376 def get_unit_digits(self, ids, name):
277 digits = {} 377 digits = {}
278 for production in self.browse(ids): 378 for production in self.browse(ids):
279 digits[production.id] = production.uom.digits 379 if production.uom:
380 digits[production.id] = production.uom.digits
381 else:
382 digits[production.id] = 2
280 return digits 383 return digits
281 384
282 def on_change_bom(self, values): 385 def on_change_bom(self, values):
283 return self.explode_bom(values) 386 return self.explode_bom(values)
284 387
285 def on_change_uom(self, values): 388 def on_change_uom(self, values):
286 return self.explode_bom(values) 389 return self.explode_bom(values)
287 390
288 def on_change_quantity(self, values): 391 def on_change_quantity(self, values):
289 return self.explode_bom(values) 392 return self.explode_bom(values)
393
394 def get_cost(self, ids, name):
395 costs = {}
396 for production in self.browse(ids):
397 costs[production.id] = Decimal(0)
398 for input_ in production.inputs:
399 if input_.cost_price is not None:
400 cost_price = input_.cost_price
401 else:
402 cost_price = input_.product.cost_price
403 costs[production.id] += (Decimal(str(input_.internal_quantity))
404 * cost_price)
405 return costs
406
407 def on_change_with_cost(self, values):
408 pool = Pool()
409 product_obj = pool.get('product.product')
410 uom_obj = pool.get('product.uom')
411
412 cost = Decimal(0)
413 if not values.get('inputs'):
414 return cost
415
416 product_ids = list(set(r['product'] for r in values['inputs'] if
417 r['product'] is not None))
418 id2product = dict((p.id, p) for p in product_obj.browse(product_ids))
419
420 uom_ids = list(set(r['uom'] for r in values['inputs']))
421 id2uom = dict((u.id, u) for u in uom_obj.browse(uom_ids))
422
423 for input_ in values['inputs']:
424 if (input_['product'] is None
425 or input_['uom'] is None
426 or input_['quantity'] is None):
427 continue
428 product = id2product[input_['product']]
429 quantity = uom_obj.compute_qty(id2uom[input_['uom']],
430 input_['quantity'], product.default_uom)
431 cost += Decimal(str(quantity)) * product.cost_price
432 return cost
433
434 def set_moves(self, production):
435 pool = Pool()
436 bom_obj = pool.get('production.bom')
437 move_obj = pool.get('stock.move')
438 input_obj = pool.get('production.bom.input')
439 output_obj = pool.get('production.bom.output')
440
441 storage_location = production.warehouse.storage_location
442 location = production.location
443 company = production.company
444
445 if not production.bom:
446 if production.product:
447 product = production.product
448 values = self._move_values(location, storage_location, company,
449 product, product.default_uom)
450 if values:
451 values['production_output'] = production.id
452 move_obj.create(values)
453 return
454
455 factor = bom_obj.compute_factor(production.bom, production.product,
456 production.quantity, production.uom)
457 cost = Decimal(0)
458 for input_ in production.bom.inputs:
459 quantity = input_obj.compute_quantity(input_, factor)
460 product = input_.product
461 values = self._move_values(storage_location, location, company,
462 product, product.default_uom, quantity)
463 if values:
464 values['production_input'] = production.id
465 move_obj.create(values)
466 cost += Decimal(str(quantity)) * product.cost_price
467
468 for output in production.bom.outputs:
469 quantity = output_obj.compute_quantity(output, factor)
470 product = output.product
471 values = self._move_values(location, storage_location, company,
472 product, product.default_uom, quantity)
473 if values:
474 values['production_output'] = production.id
475 if product == production.product:
476 values['unit_price'] = cost / Decimal(str(quantity))
477 move_obj.create(values)
478 self._set_move_planned_date([production.id])
479
480 def check_cost(self, ids):
481 pool = Pool()
482 currency_obj = pool.get('currency.currency')
483
484 for production in self.browse(ids):
485 if production.state != 'done':
486 continue
487 cost_price = Decimal(0)
488 for output in production.outputs:
489 cost_price += (Decimal(str(output.quantity))
490 * output.unit_price)
491 if not currency_obj.is_zero(production.company.currency,
492 production.cost - cost_price):
493 return False
494 return True
290 495
291 def create(self, values): 496 def create(self, values):
292 sequence_obj = Pool().get('ir.sequence') 497 sequence_obj = Pool().get('ir.sequence')
293 config_obj = Pool().get('production.configuration') 498 config_obj = Pool().get('production.configuration')
294 499
295 values = values.copy() 500 values = values.copy()
296 config = config_obj.browse(1) 501 config = config_obj.browse(1)
297 values['code'] = sequence_obj.get_id(config.production_sequence.id) 502 values['code'] = sequence_obj.get_id(config.production_sequence.id)
298 production_id = super(Production, self).create(values) 503 production_id = super(Production, self).create(values)
299 # call set_move_planned_date 504 self._set_move_planned_date(production_id)
300 return production_id 505 return production_id
301 506
302 def write(self, ids, values): 507 def write(self, ids, values):
303 result = super(Production, self).write(ids, values) 508 result = super(Production, self).write(ids, values)
304 # call set_move_planned_date 509 self._set_move_planned_date(ids)
305 return result 510 return result
306 511
512 def _get_move_planned_date(self, production):
513 "Return the planned dates for input and output moves"
514 return production.planned_date, production.planned_date
515
516 def _set_move_planned_date(self, ids):
517 "Set planned date of moves for the shipments"
518 pool = Pool()
519 move_obj = pool.get('stock.move')
520 if isinstance(ids, (int, long)):
521 ids = [ids]
522 for production in self.browse(ids):
523 dates = self._get_move_planned_date(production)
524 input_date, output_date = dates
525 move_obj.write([m.id for m in production.inputs
526 if m.state not in ('assigned', 'done', 'cancel')], {
527 'planned_date': input_date,
528 })
529 move_obj.write([m.id for m in production.outputs
530 if m.state not in ('assigned', 'done', 'cancel')], {
531 'planned_date': output_date,
532 })
533
534 @ModelView.button
535 @Workflow.transition('cancel')
536 def cancel(self, ids):
537 pool = Pool()
538 move_obj = pool.get('stock.move')
539 productions = self.browse(ids)
540 move_obj.write([m.id for p in productions
541 for m in p.inputs + p.outputs
542 if m.state != 'cancel'], {
543 'state': 'cancel',
544 })
545
546 @ModelView.button
547 @Workflow.transition('draft')
548 def draft(self, ids):
549 pool = Pool()
550 move_obj = pool.get('stock.move')
551 productions = self.browse(ids)
552 move_obj.write([m.id for p in productions
553 for m in p.inputs + p.outputs
554 if m.state != 'draft'], {
555 'state': 'draft',
556 })
557
558 @ModelView.button
559 @Workflow.transition('waiting')
560 def wait(self, ids):
561 pool = Pool()
562 move_obj = pool.get('stock.move')
563 productions = self.browse(ids)
564 move_obj.write([m.id for p in productions
565 for m in p.inputs + p.outputs
566 if m.state not in ('draft', 'done')], {
567 'state': 'draft',
568 })
569
570 @Workflow.transition('assigned')
571 def assign(self, ids):
572 pass
573
574 @ModelView.button
575 @Workflow.transition('running')
576 def run(self, ids):
577 pool = Pool()
578 move_obj = pool.get('stock.move')
579 productions = self.browse(ids)
580 move_obj.write([m.id for p in productions
581 for m in p.inputs
582 if m.state not in ('done', 'cancel')], {
583 'state': 'done',
584 })
585
586 @ModelView.button
587 @Workflow.transition('done')
588 def done(self, ids):
589 pool = Pool()
590 move_obj = pool.get('stock.move')
591 date_obj = pool.get('ir.date')
592 productions = self.browse(ids)
593 move_obj.write([m.id for p in productions
594 for m in p.outputs
595 if m.state not in ('done', 'cancel')], {
596 'state': 'done',
597 })
598 self.write(ids, {
599 'effective_date': date_obj.today(),
600 })
601
602 @ModelView.button
603 def assign_try(self, ids):
604 pool = Pool()
605 move_obj = pool.get('stock.move')
606 productions = self.browse(ids)
607 if move_obj.assign_try([m for p in productions
608 for m in p.inputs]):
609 self.assign(ids)
610 return True
611 else:
612 return False
613
614 @ModelView.button
615 def assign_force(self, ids):
616 pool = Pool()
617 move_obj = pool.get('stock.move')
618 productions = self.browse(ids)
619 move_obj.write([m.id for p in productions for m in p.inputs
620 if m.state != 'done'], {
621 'state': 'assigned',
622 })
623 self.assign(ids)
624
307 Production() 625 Production()
626
627
628 class AssignFailed(ModelView):
629 'Assign Production'
630 _name = 'production.assign.failed'
631 _description = __doc__
632
633 moves = fields.Many2Many('stock.move', None, None, 'Moves', readonly=True)
634
635 def default_moves(self):
636 pool = Pool()
637 production_obj = pool.get('production')
638 production_id = Transaction().context.get('active_id')
639 if not production_id:
640 return []
641 production = production_obj.browse(production_id)
642 return [m.id for m in production.inputs if m.state == 'draft']
643
644 AssignFailed()
645
646
647 class Assign(Wizard):
648 'Assign Production'
649 _name = 'production.assign'
650
651 start = StateTransition()
652 failed = StateView('production.assign.failed',
653 'production.assign_failed_view_form', [
654 Button('Force Assign', 'force', 'tryton-go-next',
655 states={
656 'invisible': ~Id('stock',
657 'group_stock_force_assignment').in_(
658 Eval('context', {}).get('groups', [])),
659 }),
660 Button('Ok', 'end', 'tryton-ok', True),
661 ])
662 force = StateTransition()
663
664 def transition_start(self, session):
665 pool = Pool()
666 production_obj = pool.get('production')
667
668 if production_obj.assign_try([Transaction().context['active_id']]):
669 return 'end'
670 else:
671 return 'failed'
672
673 def transition_force(self, session):
674 pool = Pool()
675 production_obj = pool.get('production')
676
677 production_obj.assign_force([Transaction().context['active_id']])
678 return 'end'
679
680 Assign()
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b