Add support for filter by location on inventory report and inventory valuation
Refund option enabled by default on Return wizard
This commit is contained in:
@@ -1,2 +1 @@
|
||||
from . import sale_stock
|
||||
from . import wizard
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
from . import stock_return_picking
|
||||
@@ -1,18 +0,0 @@
|
||||
# Copyright 2017-2019 Akretion France (https://akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, api
|
||||
|
||||
|
||||
class StockReturnPicking(models.TransientModel):
|
||||
_inherit = 'stock.return.picking'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super(StockReturnPicking, self).default_get(fields)
|
||||
if res.get('product_return_moves'):
|
||||
for line in res['product_return_moves']:
|
||||
if len(line) == 3:
|
||||
line[2]['to_refund_so'] = True
|
||||
return res
|
||||
@@ -16,13 +16,16 @@ Stock Account Usability
|
||||
|
||||
The usability enhancements include:
|
||||
|
||||
* TODO update the list
|
||||
* activate the refund option by default in return wizard on pickings
|
||||
|
||||
* add ability to select a stock location on the inventory valuation report
|
||||
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['stock_account'],
|
||||
'data': [],
|
||||
'data': ['wizard/stock_quantity_history_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py
|
||||
index 0622c16d2b5..c078ac54324 100644
|
||||
--- a/addons/stock_account/models/product.py
|
||||
+++ b/addons/stock_account/models/product.py
|
||||
@@ -239,7 +239,7 @@ class ProductProduct(models.Model):
|
||||
|
||||
for product in self:
|
||||
if product.cost_method in ['standard', 'average']:
|
||||
- qty_available = product.with_context(company_owned=True, owner_id=False).qty_available
|
||||
+ qty_available = product.with_context(owner_id=False).qty_available
|
||||
price_used = product.standard_price
|
||||
if to_date:
|
||||
price_used = product.get_history_price(
|
||||
@@ -252,7 +252,7 @@ class ProductProduct(models.Model):
|
||||
if to_date:
|
||||
if product.product_tmpl_id.valuation == 'manual_periodic':
|
||||
product.stock_value = product_values[product.id]
|
||||
- product.qty_at_date = product.with_context(company_owned=True, owner_id=False).qty_available
|
||||
+ product.qty_at_date = product.with_context(owner_id=False).qty_available
|
||||
product.stock_fifo_manual_move_ids = StockMove.browse(product_move_ids[product.id])
|
||||
elif product.product_tmpl_id.valuation == 'real_time':
|
||||
valuation_account_id = product.categ_id.property_stock_valuation_account_id.id
|
||||
2
stock_account_usability/wizard/__init__.py
Normal file
2
stock_account_usability/wizard/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import stock_return_picking
|
||||
from . import stock_quantity_history
|
||||
35
stock_account_usability/wizard/stock_quantity_history.py
Normal file
35
stock_account_usability/wizard/stock_quantity_history.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright 2019 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
|
||||
|
||||
class StockQuantityHistory(models.TransientModel):
|
||||
_inherit = 'stock.quantity.history'
|
||||
|
||||
def open_table(self):
|
||||
action = super(StockQuantityHistory, self).open_table()
|
||||
if self.location_id and self.env.context.get('valuation'):
|
||||
# When we have 'valuation' in context
|
||||
# in both cases ('current inventory' and 'at specific date')
|
||||
# it returns an action on product.product,
|
||||
# the only difference is the context.
|
||||
# We have to make the same modifications, but
|
||||
# when self.compute_at_date, action['context'] is a dict
|
||||
# otherwize, action['context'] is a string
|
||||
if self.compute_at_date:
|
||||
# insert "location" in context for qty computation
|
||||
action['context']['location'] = self.location_id.id
|
||||
# When company_owned=True, the 'location' given in the
|
||||
# context is not taken into account
|
||||
# IMPORTANT: also requires a patch on the stock_account
|
||||
# module. Patch provided in this module.
|
||||
action['context']['company_owned'] = False
|
||||
else:
|
||||
action['context'] = {
|
||||
'location': self.location_id.id,
|
||||
'create': False,
|
||||
'edit': False,
|
||||
}
|
||||
return action
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2019 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_stock_quantity_history" model="ir.ui.view">
|
||||
<field name="name">stock_account_usability.stock.quantity.history.form</field>
|
||||
<field name="model">stock.quantity.history</field>
|
||||
<field name="inherit_id" ref="stock_account.view_stock_quantity_history"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date" position="after">
|
||||
<field name="location_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,12 +1,19 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2019 Akretion France (https://akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class StockReturnPickingLine(models.TransientModel):
|
||||
_inherit = 'stock.return.picking.line'
|
||||
class StockReturnPicking(models.TransientModel):
|
||||
_inherit = 'stock.return.picking'
|
||||
|
||||
to_refund = fields.Boolean(default=True)
|
||||
# Set to_refund to True by default
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super(StockReturnPicking, self).default_get(fields_list)
|
||||
if isinstance(res.get('product_return_moves'), list):
|
||||
for l in res['product_return_moves']:
|
||||
if len(l) == 3 and isinstance(l[2], dict):
|
||||
l[2]['to_refund'] = True
|
||||
return res
|
||||
|
||||
@@ -4,3 +4,4 @@ from . import stock
|
||||
from . import procurement
|
||||
from . import product
|
||||
from . import partner
|
||||
from . import wizard
|
||||
|
||||
@@ -28,6 +28,7 @@ This module has been written by Alexis de Lattre from Akretion <alexis.delattre@
|
||||
'data': [
|
||||
'stock_view.xml',
|
||||
'procurement_view.xml',
|
||||
'wizard/stock_quantity_history_view.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
|
||||
@@ -392,6 +392,38 @@ should be able to access it. So I add a menu entry under Inventory Control. -->
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Alternative search view for quants, used in the stock.quantity.history wizard -->
|
||||
<record id="quant_search_view_location_child_of" model="ir.ui.view">
|
||||
<field name="name">stock.quant.search with child_of for locations</field>
|
||||
<field name="model">stock.quant</field>
|
||||
<field name="priority" eval="1000"/>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Quants">
|
||||
<field name="product_id"/>
|
||||
<field name="location_id" operator="child_of" string="Location (children included)"/>
|
||||
<field name="package_id" groups="stock.group_tracking_lot"/>
|
||||
<field name="lot_id" groups="stock.group_production_lot"/>
|
||||
<field name="owner_id" groups="stock.group_tracking_owner"/>
|
||||
<separator/>
|
||||
<filter name='internal_loc' string="Internal Locations" domain="[('location_id.usage','=', 'internal')]"/>
|
||||
<filter name='transit_loc' string="Transit Locations" domain="[('location_id.usage' ,'=', 'transit')]"/>
|
||||
<separator/>
|
||||
<filter name="negative" string="Negative Stock" domain="[('quantity', '<', 0.0)]"/>
|
||||
<filter name="positive" string="Positive Stock" domain="[('quantity', '>', 0.0)]"/>
|
||||
<filter name="reserved" string="Reservations" domain="[('reserved_quantity', '>', 0.0)]"/>
|
||||
<group name="groupby">
|
||||
<filter string='Location' name="locationgroup" context="{'group_by': 'location_id'}"/>
|
||||
<filter string='Product' name="productgroup" context="{'group_by': 'product_id'}"/>
|
||||
<filter string='Owner' name="owner" context="{'group_by': 'owner_id'}" groups="stock.group_tracking_owner"/>
|
||||
<filter string='Lot/Serial Number' name="Lot_Serial_number" context="{'group_by': 'lot_id'}" groups="stock.group_production_lot"/>
|
||||
<filter string='Package' name="package" context="{'group_by': 'package_id'}" groups="stock.group_tracking_lot"/>
|
||||
<filter string='Company' name="company" context="{'group_by': 'company_id'}" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- more detailed stock.move tree view when using the button from product form -->
|
||||
<!-- TODO TEST
|
||||
<record id="stock.act_product_stock_move_open" model="ir.actions.act_window">
|
||||
@@ -402,12 +434,21 @@ should be able to access it. So I add a menu entry under Inventory Control. -->
|
||||
but it forces a group by on products that you can't remove
|
||||
So I create another "regular" Quants" menu entry -->
|
||||
<record id="stock_quant_action" model="ir.actions.act_window">
|
||||
<field name="name">Quants List</field>
|
||||
<field name="name">Quants</field>
|
||||
<field name="res_model">stock.quant</field>
|
||||
<field name="view_mode">tree,form,pivot</field>
|
||||
<field name="context">{'search_default_internal_loc': 1}</field>
|
||||
</record>
|
||||
|
||||
<!-- for the Inventory Report wizard -->
|
||||
<record id="stock_quantity_history_quant_action" model="ir.actions.act_window">
|
||||
<field name="name">Quants</field>
|
||||
<field name="res_model">stock.quant</field>
|
||||
<field name="view_mode">tree,form,pivot</field>
|
||||
<field name="search_view_id" ref="quant_search_view_location_child_of"/>
|
||||
</record>
|
||||
|
||||
|
||||
<menuitem id="stock_quant_menu" action="stock_quant_action"
|
||||
parent="stock.menu_stock_inventory_control"
|
||||
sequence="135"/>
|
||||
|
||||
3
stock_usability/wizard/__init__.py
Normal file
3
stock_usability/wizard/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import stock_quantity_history
|
||||
32
stock_usability/wizard/stock_quantity_history.py
Normal file
32
stock_usability/wizard/stock_quantity_history.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# Copyright 2019 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class StockQuantityHistory(models.TransientModel):
|
||||
_inherit = 'stock.quantity.history'
|
||||
|
||||
location_id = fields.Many2one(
|
||||
'stock.location', string='Stock Location',
|
||||
domain=[('usage', '=', 'internal')],
|
||||
help="If you select a stock location, the inventory report will be "
|
||||
"for this stock location and its children locations. If you leave "
|
||||
"this field empty, the inventory report will be for all the internal "
|
||||
"stock locations.")
|
||||
|
||||
def open_table(self):
|
||||
action = super(StockQuantityHistory, self).open_table()
|
||||
if self.compute_at_date:
|
||||
action['domain'] = "[('type', '=', 'product'), ('qty_available', '!=', 0)]"
|
||||
if self.location_id:
|
||||
if self.compute_at_date:
|
||||
# insert "location" in context for qty computation
|
||||
action['context']['location'] = self.location_id.id
|
||||
else:
|
||||
# force search view with child_of for location_id
|
||||
action = self.env.ref(
|
||||
'stock_usability.stock_quantity_history_quant_action').read()[0]
|
||||
action['context'] = {'search_default_location_id': self.location_id.id}
|
||||
return action
|
||||
23
stock_usability/wizard/stock_quantity_history_view.xml
Normal file
23
stock_usability/wizard/stock_quantity_history_view.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2019 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_stock_quantity_history" model="ir.ui.view">
|
||||
<field name="name">stock_usability.stock.quantity.history.form</field>
|
||||
<field name="model">stock.quantity.history</field>
|
||||
<field name="inherit_id" ref="stock.view_stock_quantity_history"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date" position="after">
|
||||
<field name="location_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
Reference in New Issue
Block a user