Browse Source

Jun 14: [ADD] Initial Commit 'stock_analysis_by_location_report'

pull/254/merge
RisvanaCybro 11 months ago
parent
commit
7cce24afc3
  1. 48
      stock_analysis_by_location_report/README.rst
  2. 25
      stock_analysis_by_location_report/__init__.py
  3. 55
      stock_analysis_by_location_report/__manifest__.py
  4. 22
      stock_analysis_by_location_report/controllers/__init__.py
  5. 57
      stock_analysis_by_location_report/controllers/stock_location_report.py
  6. 6
      stock_analysis_by_location_report/doc/RELEASE_NOTES.md
  7. 24
      stock_analysis_by_location_report/models/__init__.py
  8. 81
      stock_analysis_by_location_report/models/product_template.py
  9. 65
      stock_analysis_by_location_report/models/stock_location_product.py
  10. 65
      stock_analysis_by_location_report/models/stock_location_product_variant.py
  11. 22
      stock_analysis_by_location_report/report/__init__.py
  12. 107
      stock_analysis_by_location_report/report/stock_location_report.py
  13. 13
      stock_analysis_by_location_report/report/stock_location_report.xml
  14. 52
      stock_analysis_by_location_report/report/stock_location_report_templates.xml
  15. 4
      stock_analysis_by_location_report/security/ir.model.access.csv
  16. BIN
      stock_analysis_by_location_report/static/description/assets/icons/check.png
  17. BIN
      stock_analysis_by_location_report/static/description/assets/icons/chevron.png
  18. BIN
      stock_analysis_by_location_report/static/description/assets/icons/cogs.png
  19. BIN
      stock_analysis_by_location_report/static/description/assets/icons/consultation.png
  20. BIN
      stock_analysis_by_location_report/static/description/assets/icons/ecom-black.png
  21. BIN
      stock_analysis_by_location_report/static/description/assets/icons/education-black.png
  22. BIN
      stock_analysis_by_location_report/static/description/assets/icons/hotel-black.png
  23. BIN
      stock_analysis_by_location_report/static/description/assets/icons/license.png
  24. BIN
      stock_analysis_by_location_report/static/description/assets/icons/lifebuoy.png
  25. BIN
      stock_analysis_by_location_report/static/description/assets/icons/manufacturing-black.png
  26. BIN
      stock_analysis_by_location_report/static/description/assets/icons/pos-black.png
  27. BIN
      stock_analysis_by_location_report/static/description/assets/icons/puzzle.png
  28. BIN
      stock_analysis_by_location_report/static/description/assets/icons/restaurant-black.png
  29. BIN
      stock_analysis_by_location_report/static/description/assets/icons/service-black.png
  30. BIN
      stock_analysis_by_location_report/static/description/assets/icons/trading-black.png
  31. BIN
      stock_analysis_by_location_report/static/description/assets/icons/training.png
  32. BIN
      stock_analysis_by_location_report/static/description/assets/icons/update.png
  33. BIN
      stock_analysis_by_location_report/static/description/assets/icons/user.png
  34. BIN
      stock_analysis_by_location_report/static/description/assets/icons/wrench.png
  35. BIN
      stock_analysis_by_location_report/static/description/assets/misc/categories.png
  36. BIN
      stock_analysis_by_location_report/static/description/assets/misc/check-box.png
  37. BIN
      stock_analysis_by_location_report/static/description/assets/misc/compass.png
  38. BIN
      stock_analysis_by_location_report/static/description/assets/misc/corporate.png
  39. BIN
      stock_analysis_by_location_report/static/description/assets/misc/customer-support.png
  40. BIN
      stock_analysis_by_location_report/static/description/assets/misc/cybrosys-logo.png
  41. BIN
      stock_analysis_by_location_report/static/description/assets/misc/features.png
  42. BIN
      stock_analysis_by_location_report/static/description/assets/misc/logo.png
  43. BIN
      stock_analysis_by_location_report/static/description/assets/misc/pictures.png
  44. BIN
      stock_analysis_by_location_report/static/description/assets/misc/pie-chart.png
  45. BIN
      stock_analysis_by_location_report/static/description/assets/misc/right-arrow.png
  46. BIN
      stock_analysis_by_location_report/static/description/assets/misc/star.png
  47. BIN
      stock_analysis_by_location_report/static/description/assets/misc/support.png
  48. BIN
      stock_analysis_by_location_report/static/description/assets/misc/whatsapp.png
  49. BIN
      stock_analysis_by_location_report/static/description/assets/modules/export_stockinfo_xls.png
  50. BIN
      stock_analysis_by_location_report/static/description/assets/modules/inventory_barcode_scanning.png
  51. BIN
      stock_analysis_by_location_report/static/description/assets/modules/inventory_stock_dashboard_odoo.png
  52. BIN
      stock_analysis_by_location_report/static/description/assets/modules/product_barcode.png
  53. BIN
      stock_analysis_by_location_report/static/description/assets/modules/product_brand_inventory.png
  54. BIN
      stock_analysis_by_location_report/static/description/assets/modules/stock_last_purchase_price.png
  55. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/1.png
  56. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/2.png
  57. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/3.png
  58. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/4.png
  59. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/5.png
  60. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/6.png
  61. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/7.png
  62. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/8.png
  63. BIN
      stock_analysis_by_location_report/static/description/assets/screenshots/hero.gif
  64. BIN
      stock_analysis_by_location_report/static/description/banner.png
  65. BIN
      stock_analysis_by_location_report/static/description/icon.png
  66. 619
      stock_analysis_by_location_report/static/description/index.html
  67. 21
      stock_analysis_by_location_report/static/src/js/stock_report.js
  68. 25
      stock_analysis_by_location_report/views/menus.xml
  69. 31
      stock_analysis_by_location_report/views/product_template_views.xml
  70. 40
      stock_analysis_by_location_report/views/stock_location_product_variant_views.xml
  71. 40
      stock_analysis_by_location_report/views/stock_location_product_views.xml
  72. 22
      stock_analysis_by_location_report/wizard/__init__.py
  73. 140
      stock_analysis_by_location_report/wizard/stock_location_report.py
  74. 37
      stock_analysis_by_location_report/wizard/stock_location_report_views.xml

48
stock_analysis_by_location_report/README.rst

@ -0,0 +1,48 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
Stock Analysis By Location Report
=================================
Analyse the product or product variant stock based on locations.
Configuration
-------------
* No additional configurations needed
Company
-------
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__
License
-------
Affero General Public License, Version 3 (AGPL v3).
(https://www.gnu.org/licenses/agpl-3.0-standalone.html)
Credits
-------
* Developers: (V16) Shafna K,
(V15) Aysha Shalin,
Contact: odoo@cybrosys.com
Contacts
--------
* Mail Contact : odoo@cybrosys.com
* Website : https://cybrosys.com
Bug Tracker
-----------
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported.
Maintainer
----------
.. image:: https://cybrosys.com/images/logo.png
:target: https://cybrosys.com
This module is maintained by Cybrosys Technologies.
For support and more information, please visit `Our Website <https://cybrosys.com/>`__
Further information
-------------------
HTML Description: `<static/description/index.html>`__

25
stock_analysis_by_location_report/__init__.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import controllers
from . import models
from . import report
from . import wizard

55
stock_analysis_by_location_report/__manifest__.py

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
{
'name': "Stock Analysis By Location Report",
'version': '15.0.1.0.0',
'category': 'Warehouse',
'summary': """Analyse the product or product variant stock based on
locations.""",
'description': """This module helps to analyse the stock informations in
each location. Also enables to print the details as a PDF or Excel report.""",
'author': " Cybrosys Techno Solutions",
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': 'https://www.cybrosys.com',
'depends': ['base', 'stock', 'product'],
'data': [
'security/ir.model.access.csv',
'views/stock_location_product_views.xml',
'views/stock_location_product_variant_views.xml',
'views/product_template_views.xml',
'report/stock_location_report.xml',
'report/stock_location_report_templates.xml',
'wizard/stock_location_report_views.xml',
'views/menus.xml',
],
'assets': {
'web.assets_backend': [
'stock_analysis_by_location_report/static/src/js/stock_report.js'
],
},
'images': ['static/description/banner.png'],
'license': 'AGPL-3',
'installable': True,
'auto_install': False,
'application': False,
}

22
stock_analysis_by_location_report/controllers/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import stock_location_report

57
stock_analysis_by_location_report/controllers/stock_location_report.py

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import json
from odoo import http
from odoo.http import content_disposition, request
from odoo.tools import html_escape
class StockLocationXLSVReport(http.Controller):
"""To create the route for xlsx report"""
@http.route('/report_excel', type='http', auth='user', methods=['POST'],
csrf=False)
def get_report_xlsx(self, model, options, output_format, report_name):
"""To generate the response"""
report_obj = request.env[model].with_user(request.session.uid)
options = json.loads(options)
token = 'dummy-because-api-expects-one'
try:
if output_format == 'xlsx':
response = request.make_response(
None,
headers=[
('Content-Type', 'application/vnd.ms-excel'),
('Content-Disposition',
content_disposition(report_name + '.xlsx'))
]
)
report_obj.get_xlsx_report(options, response)
response.set_cookie('fileToken', token)
return response
except Exception as e:
se = http.serialize_exception(e)
error = {
'code': 200,
'message': 'Odoo Server Error',
'data': se
}
return request.make_response(html_escape(json.dumps(error)))

6
stock_analysis_by_location_report/doc/RELEASE_NOTES.md

@ -0,0 +1,6 @@
## Module <stock_analysis_by_location_report>
#### 31.05.2024
#### Version 15.0.1.0.0
##### ADD
- Initial Commit for Stock Analysis By Location Report

24
stock_analysis_by_location_report/models/__init__.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import product_template
from . import stock_location_product
from . import stock_location_product_variant

81
stock_analysis_by_location_report/models/product_template.py

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import fields, models, _
class ProductTemplate(models.Model):
"""Inherited product template to add additional fields and compute methods
for quantity computation"""
_inherit = 'product.template'
qty_incoming = fields.Float(string='Incoming Qty',
compute='_compute_quantities', store=True,
help='Incoming quantity of the product')
qty_outgoing = fields.Float(string='Outgoing Qty',
compute='_compute_quantities', store=True,
help='Outgoing quantity of the product')
qty_avail = fields.Float(string='Available Qty',
compute='_compute_quantities', store=True,
help='Available quantity of the product')
qty_virtual = fields.Float(string='Virtual Qty',
compute='_compute_quantities', store=True,
help='Virtual quantity of the product')
def _compute_quantities(self):
"""Function for computing the incoming, outgoing,available, and virtual
quantities for the product template"""
res = super()._compute_quantities()
for template in self:
template.qty_incoming = template.incoming_qty
template.qty_outgoing = template.outgoing_qty
template.qty_avail = template.qty_available
template.qty_virtual = template.virtual_available
return res
class ProductProduct(models.Model):
"""Inherited product template to add additional fields and compute methods
for quantity computation"""
_inherit = 'product.product'
qty_incoming = fields.Float(string='Incoming Qty',
compute='_compute_quantities', store=True)
qty_outgoing = fields.Float(string='Outgoing Qty',
compute='_compute_quantities', store=True)
qty_avail = fields.Float(string='Available Qty',
compute='_compute_quantities', store=True)
qty_virtual = fields.Float(string='Virtual Qty',
compute='_compute_quantities', store=True)
def _compute_quantities_dict(self, lot_id, owner_id, package_id,
from_date=False, to_date=False):
"""Function for computing the incoming, outgoing,available, and virtual
quantities for the product"""
res = super()._compute_quantities_dict(lot_id, owner_id, package_id,
from_date=False, to_date=False)
for product in self.with_context(prefetch_fields=False):
product_id = product.id
product.qty_incoming = res[product_id]['incoming_qty']
product.qty_outgoing = res[product_id]['outgoing_qty']
product.qty_avail = res[product_id]['qty_available']
product.qty_virtual = res[product_id]['virtual_available']
return res

65
stock_analysis_by_location_report/models/stock_location_product.py

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import fields, models, tools
class ProductPivotReport(models.Model):
""" Model for generating pivot view based on product locations"""
_name = 'stock.location.product'
_description = "Product Location Report"
_auto = False
product_id = fields.Many2one('product.template', string="Product",
help='Name of the product')
location_id = fields.Many2one('stock.location', string='Location',
help='Choose the location')
on_hand_qty = fields.Integer(string='On Hand Quantity',
help='On hand quantity of the product')
qty_incoming = fields.Integer(string='Incoming Quantity',
help='Incoming quantity of the product')
qty_outgoing = fields.Integer(string='Outgoing Quantity',
help='Outgoing quantity of the product')
forecast_qty = fields.Integer(string='Forecast Quantity',
help='Forecasted quantity of the product')
def init(self):
"""Initialize the view. Drops the existing view if it exists and
creates a new view with the following columns for the Product model"""
tools.drop_view_if_exists(self._cr, self._table)
self._cr.execute(''' CREATE OR REPLACE VIEW %s AS (
SELECT row_number() OVER () AS id,
product_template.id AS product_id,
stock_location.id AS location_id,
SUM(stock_quant.quantity) AS on_hand_qty,
SUM(stock_quant.quantity +
product_template.qty_incoming - product_template.qty_outgoing)
AS forecast_qty,
SUM(product_template.qty_incoming) AS qty_incoming,
SUM(product_template.qty_outgoing) AS qty_outgoing
FROM product_template
INNER JOIN product_product ON
product_product.product_tmpl_id = product_template.id
INNER JOIN stock_quant ON stock_quant.product_id = product_product.id
INNER JOIN stock_location ON
stock_quant.location_id = stock_location.id
WHERE stock_location.usage = 'internal'
GROUP BY product_template.id, stock_location.id)''' % (self._table,))

65
stock_analysis_by_location_report/models/stock_location_product_variant.py

@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import fields, models, tools
class ProductPivotReport(models.Model):
""" Model for generating pivot view for product variants based on product
locations"""
_name = 'stock.location.product.variant'
_description = "Product Variant Location Report"
_auto = False
product_id = fields.Many2one('product.product', string="Product",
help='Name of the product')
location_id = fields.Many2one('stock.location', string='Location',
help='Choose the location')
on_hand_qty = fields.Integer(string='On Hand Quantity',
help='On hand quantity of the product')
qty_incoming = fields.Integer(string='Incoming Quantity',
help='Incoming quantity of the product')
qty_outgoing = fields.Integer(string='Outgoing Quantity',
help='Outgoing quantity of the product')
forecast_qty = fields.Integer(string='Forecast Quantity',
help='Forecasted quantity of the product')
def init(self):
"""Initialize the view. Drops the existing view if it exists and
creates a new view with the following columns for the Product variant
model"""
tools.drop_view_if_exists(self._cr, self._table)
self._cr.execute(''' CREATE OR REPLACE VIEW %s AS (
select row_number() OVER () as id,
stock_quant.product_id,
stock_quant.location_id,
stock_quant.quantity on_hand_qty,
(stock_quant.quantity +
product_product.qty_incoming - product_product.qty_outgoing)
AS forecast_qty,
product_product.qty_incoming,
product_product.qty_outgoing from product_product
inner JOIN stock_quant on stock_quant.product_id = product_product.id
inner join product_template on
product_product.product_tmpl_id = product_template.id
inner join stock_location on
stock_quant.location_id = stock_location.id
where stock_location.usage = 'internal')''' % (self._table,))

22
stock_analysis_by_location_report/report/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import stock_location_report

107
stock_analysis_by_location_report/report/stock_location_report.py

@ -0,0 +1,107 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, models
from odoo.tools import groupby
class StockLocationReport(models.AbstractModel):
"""To generate report based on query and get report values"""
_name = "report.stock_analysis_by_location_report.report_stock_location"
@api.model
def _get_report_values(self, docids, data=None):
""" To get the report values based on the user giving conditions """
value = self.query_data(data['report_type'], data['product_id'],
data['product_variant_id'])
grouped_data = {}
for product_id, group in (
groupby(value, key=lambda x: x['product'])):
grouped_data[product_id] = list(group)
return {
'grouped_data': grouped_data,
'var': value
}
def query_data(self, report_type, product_id, product_variant_id):
""" To fetch values from database using query """
if report_type == 'product':
query = """SELECT row_number() OVER () AS id,
product_template.name AS product,
stock_location.complete_name AS location,
SUM(stock_quant.quantity) AS on_hand_qty,
SUM(stock_quant.quantity +
product_template.qty_incoming - product_template.qty_outgoing)
AS forecast_qty,
SUM(product_template.qty_incoming) AS qty_incoming,
SUM(product_template.qty_outgoing) AS qty_outgoing
FROM product_template
INNER JOIN product_product ON
product_product.product_tmpl_id = product_template.id
INNER JOIN stock_quant ON
stock_quant.product_id = product_product.id
INNER JOIN stock_location ON
stock_quant.location_id = stock_location.id
WHERE stock_location.usage = 'internal'
GROUP BY product_template.id, stock_location.id"""
if product_id:
query = """SELECT row_number() OVER () AS id,
product_template.name AS product,
stock_location.complete_name AS location,
SUM(stock_quant.quantity) AS on_hand_qty,
SUM(stock_quant.quantity +
product_template.qty_incoming - product_template.qty_outgoing)
AS forecast_qty,
SUM(product_template.qty_incoming) AS qty_incoming,
SUM(product_template.qty_outgoing) AS qty_outgoing
FROM product_template
INNER JOIN product_product ON
product_product.product_tmpl_id = product_template.id
INNER JOIN stock_quant ON
stock_quant.product_id = product_product.id
INNER JOIN stock_location ON
stock_quant.location_id = stock_location.id
WHERE stock_location.usage = 'internal'
and product_template.id=%(product_id)s
GROUP BY product_template.id, stock_location.id"""
else:
query = """select product_template.name as Product,
stock_location.complete_name as Location,
stock_quant.quantity on_hand_qty,
(stock_quant.quantity +
product_product.qty_incoming - product_product.qty_outgoing)
AS forecast_qty, product_product.qty_incoming,
product_product.qty_outgoing from product_product
inner JOIN stock_quant on
stock_quant.product_id = product_product.id
inner join product_template
on product_product.product_tmpl_id = product_template.id
inner join stock_location on
stock_quant.location_id = stock_location.id
where stock_location.usage = 'internal'"""
if product_variant_id:
query += """ and product_id=%(product_variant_id)s"""
self.env.cr.execute(query,
{'report_type': report_type,
'product_id': product_id,
'product_variant_id': product_variant_id,
})
return self.env.cr.dictfetchall()

13
stock_analysis_by_location_report/report/stock_location_report.xml

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--Report action for stock analysis by location-->
<record id="stock_by_location_report" model="ir.actions.report">
<field name="name">Stock Location Report</field>
<field name="model">stock.move</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">stock_analysis_by_location_report.report_stock_location</field>
<field name="report_file">stock_analysis_by_location_report.report_stock_location</field>
<field name="print_report_name">'Stock Location Report - %s'</field>
<field name="binding_type">report</field>
</record>
</odoo>

52
stock_analysis_by_location_report/report/stock_location_report_templates.xml

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--Templates for the stock location report-->
<template id="report_stock_location">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<h2>Stock Location Report</h2>
<div>
<strong> Report Date:</strong>
<span t-esc="datetime.datetime.now().strftime('%Y-%m-%d')"/>
</div>
<table class="table">
<thead>
<tr>
<th>Product Name</th>
<th>Location</th>
<th>OnHand Quantity</th>
<th>Incoming Quantity</th>
<th>Outgoing Quantity</th>
<th>Forecast Quantity</th>
</tr>
</thead>
<tbody>
<t t-foreach="grouped_data.items()" t-as="group">
<t t-set="product_id" t-value="group[0]"/>
<t t-set="product_data" t-value="group[1]"/>
<t t-foreach="product_data" t-as="data">
<tr>
<td t-esc="product_id"/>
<td t-esc="data['location']"/>
<td t-esc="data['on_hand_qty']"/>
<td t-esc="data['qty_incoming']"/>
<td t-esc="data['qty_outgoing']"/>
<td t-esc="data['forecast_qty']"/>
</tr>
</t>
<tr>
<td colspan="2" style="text-align: right;"><strong>Total:</strong></td>
<td><strong><t t-esc="sum([x['on_hand_qty'] for x in product_data])"/></strong></td>
<td><strong><t t-esc="sum([x['qty_incoming'] for x in product_data])"/></strong></td>
<td><strong><t t-esc="sum([x['qty_outgoing'] for x in product_data])"/></strong></td>
<td><strong><t t-esc="sum([x['forecast_qty'] for x in product_data])"/></strong></td>
</tr>
</t>
</tbody>
</table>
</div>
</t>
</t>
</template>
</odoo>

4
stock_analysis_by_location_report/security/ir.model.access.csv

@ -0,0 +1,4 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_stock_location_product_variant,access.stock.location.product.variant,model_stock_location_product_variant,base.group_user,1,1,1,1
access_stock_location_product,access.stock.location.product,model_stock_location_product,base.group_user,1,1,1,1
access_stock_location_report,access.stock.location.report,model_stock_location_report,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_stock_location_product_variant access.stock.location.product.variant model_stock_location_product_variant base.group_user 1 1 1 1
3 access_stock_location_product access.stock.location.product model_stock_location_product base.group_user 1 1 1 1
4 access_stock_location_report access.stock.location.report model_stock_location_report base.group_user 1 1 1 1

BIN
stock_analysis_by_location_report/static/description/assets/icons/check.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
stock_analysis_by_location_report/static/description/assets/icons/chevron.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/cogs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
stock_analysis_by_location_report/static/description/assets/icons/consultation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
stock_analysis_by_location_report/static/description/assets/icons/ecom-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/education-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/hotel-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/license.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
stock_analysis_by_location_report/static/description/assets/icons/lifebuoy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
stock_analysis_by_location_report/static/description/assets/icons/manufacturing-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/pos-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/puzzle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/restaurant-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/service-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/trading-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/training.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/update.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
stock_analysis_by_location_report/static/description/assets/icons/user.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
stock_analysis_by_location_report/static/description/assets/icons/wrench.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/categories.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/check-box.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/compass.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/corporate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/customer-support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/cybrosys-logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/features.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

BIN
stock_analysis_by_location_report/static/description/assets/misc/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/pictures.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/pie-chart.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/right-arrow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

BIN
stock_analysis_by_location_report/static/description/assets/misc/star.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
stock_analysis_by_location_report/static/description/assets/misc/whatsapp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
stock_analysis_by_location_report/static/description/assets/modules/export_stockinfo_xls.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
stock_analysis_by_location_report/static/description/assets/modules/inventory_barcode_scanning.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

BIN
stock_analysis_by_location_report/static/description/assets/modules/inventory_stock_dashboard_odoo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
stock_analysis_by_location_report/static/description/assets/modules/product_barcode.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
stock_analysis_by_location_report/static/description/assets/modules/product_brand_inventory.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
stock_analysis_by_location_report/static/description/assets/modules/stock_last_purchase_price.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

BIN
stock_analysis_by_location_report/static/description/assets/screenshots/hero.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 KiB

BIN
stock_analysis_by_location_report/static/description/banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
stock_analysis_by_location_report/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

619
stock_analysis_by_location_report/static/description/index.html

@ -0,0 +1,619 @@
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;">
<!-- TITLE BAR -->
<div class="d-flex align-items-center justify-content-between"
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
<img src="assets/misc/cybrosys-logo.png" width="42" height="42"
style="width: 42px; height: 42px;"/>
<div>
<div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Community
</div>
<div style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Enterprise
</div>
<div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Odoo.sh
</div>
</div>
</div>
<!-- END OF TITLE BAR -->
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<!-- APP HERO -->
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
Stock Analysis By Location Report
</h1>
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">
This Module helps to Analyse the Product Quantities and
Movements across Various Locations.
</p>
<!-- END OF APP HERO -->
<img src="assets/screenshots/hero.gif" class="img-responsive"
style="width: 100%; margin-left: auto; margin-right: auto;"/>
</div>
</div>
</div>
</div>
<!-- NAVIGATION SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/compass.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Explore This Module</h2>
</div>
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
<div class="col-sm-12 col-md-6 my-3">
<a href="#overview">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn more about this module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#features">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View features of this module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#screenshots">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View screenshots for this module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
</div>
<!-- END OF NAVIGATION SECTION -->
<!-- OVERVIEW SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pie-chart.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Overview
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 py-4">
This module helps to provide an overview of Inventory Levels and Movements
based on Locations.It enables Stakeholders to Analyze Stock Availability,
Incoming and Outgoing Quantities, and Virtual Quantities across various
Stock Locations, aiding in Strategic Decision-making regarding Inventory
Management, Replenishment, and Distribution.
</div>
</div>
<!-- END OF OVERVIEW SECTION -->
<!-- FEATURES SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/features.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Features
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 col-md-6">
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Location wise Inventory Analysis</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Real Time Updates</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Generate Reports of Stock based on Location</span>
</div>
</div>
</div>
<!-- END OF FEATURES SECTION -->
<!-- SCREENSHOTS SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"
id="screenshots">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pictures.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Screenshots
</h2>
</div>
<div class="row">
<div class="col-sm-12">
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Stock Location Reports
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
A new Menu is added to get the View of Stock Locations and also
to get the Reports.
<img src="assets/screenshots/1.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Product Stock Location Report
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
By Clicking on the Products, you can get the Pivot view for the
Stock of Products based on Location
</p>
<img src="assets/screenshots/2.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Product Variant Stock Location Report
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
By Clicking on the Product Variants, you can get the Pivot view for the
Stock of Products Variants based on Location
</p>
<img src="assets/screenshots/3.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Stock Location PDF & Excel Report Wizard
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
When you click on Stock Location Reports MenuItem, a Wizard
will be open to select the Required Options.
</p>
<img src="assets/screenshots/4.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Stock Location PDF Report of Product
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
By Choosing the Product as Report Type and Clicking on Print PDF Button,
you can get PDF Reporting of Product's Report based on Location.
Below is the Sample Report.
</p>
<img src="assets/screenshots/5.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
XLSX Report Of Product
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
By Clicking on Print XLSX Button, you can get the Product's Stock Report based on Location
in Excel Format.
</p>
<img src="assets/screenshots/6.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Stock Location PDF Report Of Product Variants
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
By Choosing the Product Variant as Report Type and Clicking on Print PDF Button,
you can get PDF Reporting of Product Variant's Report based on Location.
Below is the Sample Report.
</p>
<img src="assets/screenshots/7.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
XLSX Report Of Product Variants
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
By Clicking on Print XLSX Button, you can get the Product
Variant's Stock Report based on Location in Excel Format.
</p>
<img src="assets/screenshots/8.png" class="img-thumbnail">
</div>
</div>
</div>
<!-- END OF SCREENSHOTS SECTION -->
<!-- RELATED PRODUCTS -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/categories.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Related Products
</h2>
</div>
<div class="row">
<div class="col-sm-12">
<div id="demo1" class="row carousel slide" data-ride="carousel">
<!-- The slideshow -->
<div class="carousel-inner" style="padding: 30px;">
<div class="carousel-item" style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/15.0/inventory_barcode_scanning/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/inventory_barcode_scanning.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/15.0/product_barcode/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/product_barcode.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/15.0/inventory_stock_dashboard_odoo/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/inventory_stock_dashboard_odoo.png">
</div>
</a>
</div>
</div>
<div class="carousel-item active"
style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/15.0/export_stockinfo_xls/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/export_stockinfo_xls.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/15.0/product_brand_inventory/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/product_brand_inventory.jpg">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/15.0/stock_last_purchase_price/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/stock_last_purchase_price.png">
</div>
</a>
</div>
</div>
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo1" data-slide="prev"
style="width:35px; color:#000"> <span
class="carousel-control-prev-icon"><i
class="fa fa-chevron-left"
style="font-size:24px"></i></span>
</a> <a class="carousel-control-next" href="#demo1"
data-slide="next" style="width:35px; color:#000">
<span class="carousel-control-next-icon"><i
class="fa fa-chevron-right"
style="font-size:24px"></i></span>
</a>
</div>
</div>
</div>
<!-- END OF RELATED PRODUCTS -->
<!-- OUR SERVICES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/star.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our Services</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/cogs.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Customization</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/wrench.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/lifebuoy.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Support</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/user.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Hire Odoo Developer</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/puzzle.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Integration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/update.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Migration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/consultation.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Consultancy</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/training.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/license.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo Licensing Consultancy</h6>
</div>
</div>
</div>
<!-- END OF OUR SERVICES -->
<!-- OUR INDUSTRIES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/corporate.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our Industries
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/trading-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Trading</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easily procure and sell your products</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/pos-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
POS</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easy configuration and convivial experience</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/education-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Education</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
A platform for educational management</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/manufacturing-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Manufacturing</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Plan, track and schedule your operations</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/ecom-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
E-commerce &amp; Website</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Mobile friendly, awe-inspiring product pages</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/service-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Service Management</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Keep track of services and invoice</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/restaurant-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Restaurant</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Run your bar or restaurant methodically</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/hotel-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Hotel Management</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
An all-inclusive hotel management application</p>
</div>
</div>
</div>
</div>
<!-- END OF OUR INDUSTRIES -->
<!-- SUPPORT -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/customer-support.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Support
</h2>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4 d-flex justify-content-center align-items-center"
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/support.png" height="48" width="48"
style="width: 42px; height: 42px;"/>
</div>
<div>
<h4>Need Help?</h4>
<p style="line-height: 100%;">Got questions or need help?
Get in touch.</p>
<a href="mailto:odoo@cybrosys.com">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
odoo@cybrosys.com</p>
</a>
</div>
</div>
</div>
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4 d-flex justify-content-center align-items-center"
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/whatsapp.png" height="52" width="52"
style="width: 52px; height: 52px;"/>
</div>
<div>
<h4>WhatsApp</h4>
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
<a href="https://api.whatsapp.com/send?phone=918606827707">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
+91 86068 27707</p>
</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
<img src="assets/misc/logo.png" width="144" height="31"
style="width:144px; height: 31px; margin-top: 40px;"/>
</div>
</div>
</div>
<!-- END OF SUPPORT -->

21
stock_analysis_by_location_report/static/src/js/stock_report.js

@ -0,0 +1,21 @@
/** @odoo-module */
/**
* registers a new handler to generate xlsx report
*/
import { registry } from "@web/core/registry";
import framework from 'web.framework';
import session from 'web.session';
registry.category("ir.actions.report handlers").add("xlsx", async (action) => {
if (action.report_type === 'xlsx') {
framework.blockUI();
var def = $.Deferred();
session.get_file({
url: '/report_excel',
data: action.data,
success: def.resolve.bind(def),
error: (error) => this.call('crash_manager', 'rpc_error', error),
complete: framework.unblockUI,
});
return def;
}
});

25
stock_analysis_by_location_report/views/menus.xml

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<menuitem id="menu_stock_location_report"
name="Stock Location Reports"
sequence="5"
parent="stock.menu_stock_root"
/>
<menuitem id="menu_product_variant_pivot_report"
name="Product Variant"
sequence="1"
action="product_variant_pivot_view_action"
parent="menu_stock_location_report"
/>
<menuitem id="menu_product_pivot_report"
name="Products"
sequence="0"
action="product_pivot_view_action"
parent="menu_stock_location_report"
/>
<menuitem id="menu_stock_location_report_pdf_excel"
name="Stock Location Reports"
parent="menu_stock_location_report"
action="stock_location_report_menu_action"
sequence="2"/>
</odoo>

31
stock_analysis_by_location_report/views/product_template_views.xml

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Inherited Form view for product template to add the field in the view-->
<record id="product_template_form_view" model="ir.ui.view">
<field name="name">product.template.view.form.inherit.stock.analysis.location.report</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<xpath expr="//group//field[@name='list_price']" position="after">
<field name="qty_incoming" invisible="1"/>
<field name="qty_outgoing" invisible="1"/>
<field name="qty_avail" invisible="1"/>
<field name="qty_virtual" invisible="1"/>
</xpath>
</field>
</record>
<!-- Inherited Form view for product to add the field in the view-->
<record id="product_normal_form_view" model="ir.ui.view">
<field name="name">product.product.view.form.inherit.stock.analysis.by.location.report</field>
<field name="model">product.product</field>
<field name="inherit_id" ref="product.product_normal_form_view"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='default_code']" position="after">
<field name="qty_incoming" invisible="1"/>
<field name="qty_outgoing" invisible="1"/>
<field name="qty_avail" invisible="1"/>
<field name="qty_virtual" invisible="1"/>
</xpath>
</field>
</record>
</odoo>

40
stock_analysis_by_location_report/views/stock_location_product_variant_views.xml

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Pivot view for product variants-->
<record id="stock_location_product_variant_view_pivot" model="ir.ui.view">
<field name="name">Product Variants: Stock Location Report</field>
<field name="model">stock.location.product.variant</field>
<field name="arch" type="xml">
<pivot string="Stock Location Report">
<field name="product_id" type="row"/>
<field name="location_id" type="row"/>
<field name="on_hand_qty" type="measure"/>
<field name="qty_incoming" type="measure"/>
<field name="qty_outgoing" type="measure"/>
<field name="forecast_qty" type="measure"/>
</pivot>
</field>
</record>
<!-- Tree view for product variants-->
<record id="product_variant_report_tree_view" model="ir.ui.view">
<field name="name">Product Variants: Stock Location Report</field>
<field name="model">stock.location.product.variant</field>
<field name="arch" type="xml">
<tree sample="1">
<field name="product_id"/>
<field name="location_id"/>
<field name="on_hand_qty"/>
<field name="qty_incoming"/>
<field name="qty_outgoing"/>
<field name="forecast_qty"/>
</tree>
</field>
</record>
<!-- Action for the pivot view for Product variants -->
<record id="product_variant_pivot_view_action" model="ir.actions.act_window">
<field name="name">Product Variants: Stock Location Report</field>
<field name="res_model">stock.location.product.variant</field>
<field name="view_mode">tree,form,pivot</field>
<field name="view_id" ref="stock_location_product_variant_view_pivot"/>
</record>
</odoo>

40
stock_analysis_by_location_report/views/stock_location_product_views.xml

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Pivot view for Products-->
<record id="stock_location_product_view_pivot" model="ir.ui.view">
<field name="name">Product: Stock Location Report</field>
<field name="model">stock.location.product</field>
<field name="arch" type="xml">
<pivot string="Stock Location Report">
<field name="product_id" type="row"/>
<field name="location_id" type="row"/>
<field name="on_hand_qty" type="measure"/>
<field name="qty_incoming" type="measure"/>
<field name="qty_outgoing" type="measure"/>
<field name="forecast_qty" type="measure"/>
</pivot>
</field>
</record>
<!-- Tree view for product report view-->
<record id="product_report_tree_view" model="ir.ui.view">
<field name="name">Product: Stock Location Report</field>
<field name="model">stock.location.product</field>
<field name="arch" type="xml">
<tree sample="1">
<field name="product_id"/>
<field name="location_id"/>
<field name="on_hand_qty"/>
<field name="qty_incoming"/>
<field name="qty_outgoing"/>
<field name="forecast_qty"/>
</tree>
</field>
</record>
<!-- Action for the pivot view for Products-->
<record id="product_pivot_view_action" model="ir.actions.act_window">
<field name="name">Product: Stock Location Report</field>
<field name="res_model">stock.location.product</field>
<field name="view_mode">tree,form,pivot</field>
<field name="view_id" ref="stock_location_product_view_pivot"/>
</record>
</odoo>

22
stock_analysis_by_location_report/wizard/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import stock_location_report

140
stock_analysis_by_location_report/wizard/stock_location_report.py

@ -0,0 +1,140 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Aysha Shalin (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import io
import json
from odoo import fields, models, _
from odoo.tools import date_utils, groupby
try:
from odoo.tools.misc import xlsxwriter
except ImportError:
import xlsxwriter
class StockLocation(models.TransientModel):
"""Transient model to give the input values for the
generation of report values"""
_name = "stock.location.report"
_description = "Stock Location Report Wizard"
report_type = fields.Selection([
('product', 'Products'),
('product_variant', 'Product Variant')
], string="Report Type", default='product',
help="Choose the product type")
product_variant_id = fields.Many2one('product.product',
string="Product Variant",
help="choose the product variant of "
"which the detail should be"
" known")
product_id = fields.Many2one('product.template', string="Product",
help="choose the product of which the detail "
"should be known")
def action_pdf_report(self):
""" To pass values in wizard"""
data = {
'model_id': self.id,
'report_type': self.report_type,
'product_id': self.product_id.id,
'product_variant_id': self.product_variant_id.id,
}
return self.env.ref(
'stock_analysis_by_location_report.stock_by_location_report').report_action(
None, data=data)
def action_xlsx_report(self):
""" To print the XLSX report type"""
query = self.env[
'report.stock_analysis_by_location_report.report_stock_location'].query_data(
self.report_type, self.product_id.id, self.product_variant_id.id)
data = {
'report_type': self.report_type,
'product_id': self.product_id.id,
'product_variant_id': self.product_variant_id.id,
'var': query
}
return {
'type': 'ir.actions.report',
'data': {'model': 'stock.location.report',
'options': json.dumps(data,
default=date_utils.json_default),
'output_format': 'xlsx',
'report_name': 'Stock Location Report',
},
'report_type': 'xlsx',
}
def get_xlsx_report(self, data, response):
"""To get the report values for xlsx report"""
query_result = data['var']
grouped_data = {}
for product_id, group in groupby(query_result,
key=lambda x: x['product']):
grouped_data[product_id] = list(group)
output = io.BytesIO()
workbook = xlsxwriter.Workbook(output, {'in_memory': True})
sheet = workbook.add_worksheet()
grey_cell_format = workbook.add_format(
{'bold': True, 'bg_color': '#D3D3D3'})
head = workbook.add_format(
{'align': 'center', 'bold': True, 'font_size': '20px',
'bg_color': 'gray'})
txt_head = workbook.add_format({'font_size': '10px', 'align': 'left',
'bold': True})
sheet.set_column(0, 0, 20)
sheet.set_column(1, 1, 10)
sheet.set_column(2, 2, 10)
sheet.merge_range('A1:B1', 'Report Date:' + str(fields.Date.today()),
txt_head)
sheet.merge_range('A2:F3', 'STOCK LOCATION REPORT', head)
sheet.write('A6', 'Product', grey_cell_format)
sheet.write('B6', 'Location', grey_cell_format)
sheet.write('C6', 'Onhand Qty', grey_cell_format)
sheet.write('D6', 'Incoming Qty', grey_cell_format)
sheet.write('E6', 'Outgoing Qty', grey_cell_format)
sheet.write('F6', 'Forecast Qty', grey_cell_format)
row = 6
for product_id, product_data in grouped_data.items():
for data in product_data:
sheet.write(row, 0, product_id)
sheet.write(row, 1, data['location'])
sheet.write(row, 2, data['on_hand_qty'])
sheet.write(row, 3, data['qty_incoming'])
sheet.write(row, 4, data['qty_outgoing'])
sheet.write(row, 5, data['forecast_qty'])
row += 1
sheet.write(row, 0, 'Total:', grey_cell_format)
sheet.write(row, 1, '', grey_cell_format)
sheet.write(row, 2, sum(x['on_hand_qty'] for x in product_data),
grey_cell_format)
sheet.write(row, 3, sum(x['qty_incoming'] for x in product_data),
grey_cell_format)
sheet.write(row, 4, sum(x['qty_outgoing'] for x in product_data),
grey_cell_format)
sheet.write(row, 5, sum(x['forecast_qty'] for x in product_data),
grey_cell_format)
row += 1
workbook.close()
output.seek(0)
response.stream.write(output.read())
output.close()

37
stock_analysis_by_location_report/wizard/stock_location_report_views.xml

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!--Form view of wizard that opens to generate report-->
<record id="stock_location_report_view_form" model="ir.ui.view">
<field name="name">stock.location.report.view.form.inherit.stock.analysis.location.report</field>
<field name="model">stock.location.report</field>
<field name="arch" type="xml">
<form string="Stock Location Report">
<group class="oe_title">
<group>
<field name="report_type" widget="radio"/>
<field name="product_variant_id" attrs="{'invisible':[('report_type','in',('product'))]}"/>
<field name="product_id" attrs="{'invisible':[('report_type','in',('product_variant'))]}"/>
</group>
</group>
<footer>
<button name="action_pdf_report" string="Print PDF"
type="object" class="btn-primary"/>
<button name="action_xlsx_report" string="PRINT XLSX"
type="object" default_focus="1"
class="btn-primary"/>
<button string="Cancel" class="btn-secondary"
special="cancel"/>
</footer>
</form>
</field>
</record>
<!--Window action of stock location report-->
<record id="stock_location_report_menu_action" model="ir.actions.act_window">
<field name="name">Stock Location PDF &amp; Excel Report</field>
<field name="res_model">stock.location.report</field>
<field name="view_mode">form</field>
<field name="view_id" ref="stock_location_report_view_form"/>
<field name="target">new</field>
</record>
</odoo>
Loading…
Cancel
Save