[IMP] mrp: Produce wizard save and produce another

When a user produces multiple finished products with SN/lots, he has to
save the wizard go back to the production order and click again on produce
button for the second SN/lot. It could be annoying with a huge number of
SN/lots to encode.

This commit adds a 'Continue' button that saves the wizard and directly
opens a new with the new lot/SN.
This commit is contained in:
Tejas Shahu
2018-12-11 16:09:55 +00:00
committed by Arnold Moyaux
parent 38b1debece
commit 2590cf2e6d
3 changed files with 55 additions and 24 deletions
+49 -21
View File
@@ -19,14 +19,11 @@ class MrpProductProduce(models.TransientModel):
production = self.env['mrp.production'].browse(self._context['active_id'])
serial_finished = (production.product_id.tracking == 'serial')
todo_uom = production.product_uom_id.id
todo_quantity = self._get_todo(production)
if serial_finished:
todo_quantity = 1.0
if production.product_uom_id.uom_type != 'reference':
todo_uom = self.env['uom.uom'].search([('category_id', '=', production.product_uom_id.category_id.id), ('uom_type', '=', 'reference')]).id
else:
main_product_moves = production.move_finished_ids.filtered(lambda x: x.product_id.id == production.product_id.id)
todo_quantity = production.product_qty - sum(main_product_moves.mapped('quantity_done'))
todo_quantity = todo_quantity if (todo_quantity > 0) else 0
if 'production_id' in fields:
res['production_id'] = production.id
if 'product_id' in fields:
@@ -47,6 +44,25 @@ class MrpProductProduce(models.TransientModel):
lot_id = fields.Many2one('stock.production.lot', string='Lot/Serial Number')
produce_line_ids = fields.One2many('mrp.product.produce.line', 'product_produce_id', string='Product to Track')
product_tracking = fields.Selection(related="product_id.tracking", readonly=False)
is_pending_production = fields.Boolean(compute='_compute_pending_production')
@api.depends('product_qty')
def _compute_pending_production(self):
""" Compute if it exits remaining quantity once the quantity on the
current wizard will be processed. The purpose is to display or not
button 'continue'.
"""
for product_produce in self:
remaining_qty = product_produce._get_todo(product_produce.production_id)
product_produce.is_pending_production = remaining_qty - product_produce.product_qty > 0.0
def continue_production(self):
""" Save current wizard and directly opens a new. """
self.ensure_one()
self._record_production()
action = self.production_id.open_produce_product()
action['context'] = {'active_id': self.production_id.id}
return action
def action_generate_serial(self):
self.ensure_one()
@@ -67,23 +83,9 @@ class MrpProductProduce(models.TransientModel):
@api.multi
def do_produce(self):
# Nothing to do for lots since values are created using default data (stock.move.lots)
quantity = self.product_qty
if float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) <= 0:
raise UserError(_("The production order for '%s' has no quantity specified.") % self.product_id.display_name)
for move in self.production_id.move_finished_ids:
if move.product_id.tracking == 'none' and move.state not in ('done', 'cancel'):
rounding = move.product_uom.rounding
if move.product_id.id == self.production_id.product_id.id:
move.quantity_done += float_round(quantity, precision_rounding=rounding)
elif move.unit_factor:
# byproducts handling
move.quantity_done += float_round(quantity * move.unit_factor, precision_rounding=rounding)
self.check_finished_move_lots()
if self.production_id.state == 'confirmed':
self.production_id.write({
'date_start': datetime.now(),
})
""" Save the current wizard and go back to the MO. """
self.ensure_one()
self._record_production()
return {'type': 'ir.actions.act_window_close'}
@api.multi
@@ -138,6 +140,32 @@ class MrpProductProduce(models.TransientModel):
pl.move_id._generate_consumed_move_line(pl.qty_done, self.lot_id, lot=pl.lot_id)
return True
def _get_todo(self, production):
""" This method will return remaining todo quantity of production. """
main_product_moves = production.move_finished_ids.filtered(lambda x: x.product_id.id == production.product_id.id)
todo_quantity = production.product_qty - sum(main_product_moves.mapped('quantity_done'))
todo_quantity = todo_quantity if (todo_quantity > 0) else 0
return todo_quantity
def _record_production(self):
# Nothing to do for lots since values are created using default data (stock.move.lots)
quantity = self.product_qty
if float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) <= 0:
raise UserError(_("The production order for '%s' has no quantity specified.") % self.product_id.display_name)
for move in self.production_id.move_finished_ids:
if move.product_id.tracking == 'none' and move.state not in ('done', 'cancel'):
rounding = move.product_uom.rounding
if move.product_id.id == self.production_id.product_id.id:
move.quantity_done += float_round(quantity, precision_rounding=rounding)
elif move.unit_factor:
# byproducts handling
move.quantity_done += float_round(quantity * move.unit_factor, precision_rounding=rounding)
self.check_finished_move_lots()
if self.production_id.state == 'confirmed':
self.production_id.write({
'date_start': datetime.now(),
})
@api.onchange('product_qty')
def _onchange_product_qty(self):
lines = []
@@ -11,6 +11,7 @@
<field name="serial" invisible="1"/>
<field name="production_id" invisible="1"/>
<field name="product_id" readonly="1"/>
<field name="is_pending_production" invisible="1"/>
<label for="product_qty"/>
<div class="o_row">
<field name="product_qty" attrs="{'readonly': [('serial', '=', True)]}"/>
@@ -39,8 +40,10 @@
</field>
</group>
<footer>
<button name="do_produce" type="object" string="Record Production" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel" />
<button name="continue_production" attrs="{'invisible':[('is_pending_production', '=', False)]}" type="object" string="Continue" class="btn-primary"/>
<button name="do_produce" type="object" string="Save" class="btn-default btn-secondary" attrs="{'invisible':[('is_pending_production', '=', False)]}"/>
<button name="do_produce" type="object" string="Save" class="btn-primary" attrs="{'invisible':[('is_pending_production', '=', True)]}"/>
<button string="Discard" class="btn-default btn-secondary" special="cancel"/>
</footer>
</form>
</field>
@@ -559,7 +559,7 @@ tour.register('main_flow_tour', {
content: _t("Produce"),
position: "bottom",
}, {
trigger: ".modal-footer .btn-primary:first",
trigger: ".modal-footer .btn-primary:nth-child(3)",
content: _t('Record Production'),
position: 'bottom',
}, {