[IMP] stock: validate inventory adjustment with product tracked
When you have some product tracked in an inventory adjustment, the lot/serial number is not required, so when you confirm an inventory adjustment with product tracked for which you didn't provide serial/lot number you get a warning to inform you. TASK-30921
This commit is contained in:
committed by
Pierre Masereel
parent
ba5918ffcb
commit
692847255c
@@ -45,6 +45,7 @@
|
||||
'wizard/stock_quantity_history.xml',
|
||||
'wizard/stock_warn_insufficient_qty_views.xml',
|
||||
'wizard/product_replenish_views.xml',
|
||||
'wizard/stock_track_confirmation_views.xml',
|
||||
|
||||
'views/res_partner_views.xml',
|
||||
'views/product_strategy_views.xml',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.addons import decimal_precision as dp
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools import float_utils
|
||||
from odoo.tools import float_utils, float_compare
|
||||
|
||||
|
||||
class Inventory(models.Model):
|
||||
@@ -162,6 +162,23 @@ class Inventory(models.Model):
|
||||
self.mapped('line_ids').write({'product_qty': 0})
|
||||
return True
|
||||
|
||||
def action_validate(self):
|
||||
inventory_lines = self.line_ids.filtered(lambda l: l.product_id.tracking in ['lot', 'serial'] and not l.prod_lot_id and l.theoretical_qty != l.product_qty)
|
||||
lines = self.line_ids.filtered(lambda l: float_compare(l.product_qty, 1, precision_rounding=l.product_uom_id.rounding) > 0 and l.product_id.tracking == 'serial' and l.prod_lot_id)
|
||||
if inventory_lines and not lines:
|
||||
wiz_lines = [(0, 0, {'product_id': product.id, 'tracking': product.tracking}) for product in inventory_lines.mapped('product_id')]
|
||||
wiz = self.env['stock.track.confirmation'].create({'inventory_id': self.id, 'tracking_line_ids': wiz_lines})
|
||||
return {
|
||||
'name': _('Tracked Products in Inventory Adjustment'),
|
||||
'type': 'ir.actions.act_window',
|
||||
'view_mode': 'form',
|
||||
'res_model': 'stock.track.confirmation',
|
||||
'target': 'new',
|
||||
'res_id': wiz.id,
|
||||
}
|
||||
else:
|
||||
self.action_done()
|
||||
|
||||
def action_done(self):
|
||||
negative = next((line for line in self.mapped('line_ids') if line.product_qty < 0 and line.product_qty != line.theoretical_qty), False)
|
||||
if negative:
|
||||
|
||||
@@ -135,7 +135,9 @@ class TestInventory(TransactionCase):
|
||||
'product_qty': 10,
|
||||
'location_id': self.stock_location.id,
|
||||
})
|
||||
inventory.action_done()
|
||||
res_dict_for_warning_lot = inventory.action_validate()
|
||||
wizard_warning_lot = self.env[(res_dict_for_warning_lot.get('res_model'))].browse(res_dict_for_warning_lot.get('res_id'))
|
||||
wizard_warning_lot.action_confirm()
|
||||
|
||||
# check
|
||||
self.assertEqual(self.env['stock.quant']._get_available_quantity(self.product2, self.stock_location, lot_id=lot1, strict=True), 1.0)
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
<form string="Inventory Adjustment">
|
||||
<header>
|
||||
<button name="action_start" states="draft" string="Start Inventory" type="object" class="oe_highlight" groups="stock.group_stock_user"/>
|
||||
<button name="action_done" states="confirm" string="Validate Inventory" type="object" class="oe_highlight" groups="stock.group_stock_manager"/>
|
||||
<button name="action_validate" states="confirm" string="Validate Inventory" type="object" class="oe_highlight" groups="stock.group_stock_manager"/>
|
||||
<button name="action_cancel_draft" states="cancel" string="Set to Draft" type="object"/>
|
||||
<button name="action_cancel_draft" states="confirm" string="Cancel Inventory" type="object"/>
|
||||
<field name="state" widget="statusbar" statusbar_visible="draft,confirm,done"/>
|
||||
|
||||
@@ -10,3 +10,4 @@ from . import stock_overprocessed_transfer
|
||||
from . import stock_quantity_history
|
||||
from . import stock_warn_insufficient_qty
|
||||
from . import product_replenish
|
||||
from . import stock_track_confirmation
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, models, fields, tools
|
||||
|
||||
|
||||
class StockTrackConfirmation(models.TransientModel):
|
||||
_name = 'stock.track.confirmation'
|
||||
|
||||
tracking_line_ids = fields.One2many('stock.track.line', 'wizard_id')
|
||||
inventory_id = fields.Many2one('stock.inventory', 'Inventory')
|
||||
|
||||
@api.one
|
||||
def action_confirm(self):
|
||||
return self.inventory_id._action_done()
|
||||
|
||||
class StockTrackingLines(models.TransientModel):
|
||||
_name = 'stock.track.line'
|
||||
|
||||
product_id = fields.Many2one('product.product', 'Product', readonly=True)
|
||||
tracking = fields.Selection([('lot', 'Tracked by lot'), ('serial', 'Tracked by serial number')], readonly=True)
|
||||
wizard_id = fields.Many2one('stock.track.confirmation', readonly=True)
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<odoo>
|
||||
<record id="view_stock_track_confirmation" model="ir.ui.view">
|
||||
<field name="name">stock.track.confirmation.view.form</field>
|
||||
<field name="model">stock.track.confirmation</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Lots or serial numbers were not provided to tracked products">
|
||||
<field name="inventory_id" invisible="1"/>
|
||||
<p>Some products of the inventory adjustment are tracked. Are you sure you don't want to specify a serial or lot number for them?</p>
|
||||
<strong>Product(s) tracked: </strong>
|
||||
<field name="tracking_line_ids" readonly="1">
|
||||
<tree>
|
||||
<field name="product_id"/>
|
||||
<field name="tracking"/>
|
||||
</tree>
|
||||
</field>
|
||||
<footer>
|
||||
<button name="action_confirm" string="Confirm" type="object" class="btn-primary"/>
|
||||
<button string="Discard" special="cancel" class="btn-default"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user