diff --git a/inventory_valuation_report/README.rst b/inventory_valuation_report/README.rst new file mode 100644 index 000000000..f05f9bf22 --- /dev/null +++ b/inventory_valuation_report/README.rst @@ -0,0 +1,46 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: https://www.gnu.org/licenses/Agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Inventory Valuation Report +=========================== +* Inventory Valuation Report Module for Odoo 16 + +Installation +============ + - www.odoo.com/documentation/16.0/setup/install.html + - Install our custom addon + +License +------- +Affero General Public License, Version 3 (AGPL v3). +(https://www.gnu.org/licenses/Agpl-3.0-standalone.html) + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer:(V16) Sumith S, Contact:odoo@cybrosys.com + +Contacts +-------- +* Mail Contact : odoo@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 https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ diff --git a/inventory_valuation_report/__init__.py b/inventory_valuation_report/__init__.py new file mode 100644 index 000000000..092604d9e --- /dev/null +++ b/inventory_valuation_report/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +from . import controllers +from . import report +from . import wizards diff --git a/inventory_valuation_report/__manifest__.py b/inventory_valuation_report/__manifest__.py new file mode 100644 index 000000000..934fbebfc --- /dev/null +++ b/inventory_valuation_report/__manifest__.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +{ + 'name': 'Inventory Valuation Report', + 'version': '16.0.1.0.0', + 'summary': """This Module will print the report for your inventory + valuation""", + 'description': """This Module helps to get a systematic analysis of + the inventory valuation""", + 'category': 'Inventory', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'depends': ['base', 'stock', 'purchase', 'web', 'sale_management'], + 'website': 'https://www.cybrosys.com', + 'data': [ + 'security/ir.model.access.csv', + 'wizards/valuation_report_views.xml', + 'report/valuation_report_pdf_templates.xml', + 'report/inventory_valuation_reports.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'inventory_valuation_report/static/src/js/action_manager.js', + ], + }, + 'images': ['static/description/banner.png'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/inventory_valuation_report/controllers/__init__.py b/inventory_valuation_report/controllers/__init__.py new file mode 100644 index 000000000..ee040c513 --- /dev/null +++ b/inventory_valuation_report/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +from . import valuation_report diff --git a/inventory_valuation_report/controllers/valuation_report.py b/inventory_valuation_report/controllers/valuation_report.py new file mode 100644 index 000000000..2d2c0848c --- /dev/null +++ b/inventory_valuation_report/controllers/valuation_report.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +"""Controller to print the xlsx report""" +import json +from odoo import http +from odoo.http import content_disposition, request +from odoo.tools import html_escape + + +class XLSXReportController(http.Controller): + """Print xlsx report""" + + @http.route('/xlsx_reports', type='http', auth='user', methods=['POST'], + csrf=False) + def get_report_xlsx(self, model, options, output_format, report_name, + token='tkn'): + uid = request.session.uid + report_obj = request.env[model].with_user(uid) + options = json.loads(options) + 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) + 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))) diff --git a/inventory_valuation_report/doc/RELEASE_NOTES.md b/inventory_valuation_report/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..dc70709a6 --- /dev/null +++ b/inventory_valuation_report/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 31.01.2024 +#### Version 16.0.1.0.0 +#### ADD +- Initial commit for Inventory Valuation Report. diff --git a/inventory_valuation_report/report/__init__.py b/inventory_valuation_report/report/__init__.py new file mode 100644 index 000000000..aebc92013 --- /dev/null +++ b/inventory_valuation_report/report/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +from . import inventory_valuation_report diff --git a/inventory_valuation_report/report/inventory_valuation_report.py b/inventory_valuation_report/report/inventory_valuation_report.py new file mode 100644 index 000000000..2b7cc0a4e --- /dev/null +++ b/inventory_valuation_report/report/inventory_valuation_report.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +"""Model to get the report values""" +from odoo import api, models +from odoo.exceptions import ValidationError + + +class InventoryReport(models.AbstractModel): + _name = "report.inventory_valuation_report.report_inventory_valuation" + _description = "Model to print the pdf report of the inventory Valuation" + + @api.model + def _get_report_values(self, doc_ids, data): + """ + Prepare the values for the inventory valuation PDF report. + :param docids: the IDs of the records that will be used to generate the report. + :type docids: list + :param data: the data used to filter the records that will be displayed in the report. + :type data: dict + :return: a dictionary containing the report data. + :rtype: dict + :raise: ValidationError if no data is found that matches the specified filters. + This method prepares the data that will be used to generate the inventory valuation PDF report. + It takes a list of document IDs and a dictionary of filters as input, and returns a dictionary + containing the data that will be displayed in the report.""" + product_id = [] + + query = """select product_product.id as product_id,product_template.default_code as default_code , + product_template.name->>'en_US' as name, product_category.name as category from product_template join + product_product on product_product.product_tmpl_id = product_template.id join product_category on + product_template.categ_id = product_category.id""" + + def get_data(res): + val_sum = 0 + for rec in res: + product_id.append(rec['product_id']) + + for i in range(len(res)): + product = self.env['product.product'].browse(product_id[i]) + + purchase_count = self.env['purchase.order.line'].search( + [('product_id', '=', product_id[i])]) + valuation = self.env['stock.valuation.layer'].search( + [('product_id', '=', product_id[i])], + order="create_date desc", limit=1) + internal_locations = self.env['stock.location'].search( + [('usage', '=', 'internal')]) + internal_qty = 0 + for quant in internal_locations: + stock_quant = self.env['stock.quant'].search( + [('location_id', '=', quant.id), + ('product_id', '=', product_id[i])] + ) + + if product.tracking == 'lot': + lot_qty_count = sum( + qty.available_quantity for qty in + stock_quant.mapped( + 'lot_id.quant_ids')) + internal_qty += lot_qty_count + else: + internal_qty += sum( + stock_quant.mapped('available_quantity')) + + adjustment_rec = self.env['stock.quant'].search( + [('product_id', '=', product_id[i])], + order="create_date desc", limit=1) + adjustment = adjustment_rec.inventory_diff_quantity + res[i][ + 'costing_method'] = product.categ_id.property_cost_method + res[i]['standard_price'] = product.standard_price + res[i]['sale_qty'] = product.sales_count + res[i]['received_qty'] = sum( + purchase_count.mapped('product_uom_qty')) + res[i]['beginning'] = res[i]['received_qty'] - res[i][ + 'sale_qty'] + res[i]['valuation'] = valuation.value + + res[i]['internal'] = internal_qty + res[i]['adjustment'] = adjustment + val_sum += valuation.value + res[i]['valuation_sum'] = val_sum + + return res + + if data['my_company_id']: + new_query = f""" join res_company on res_company.id=product_template.company_id where res_company.id='{data['my_company_id']}'""" + query += new_query + + if data['from_date']: + new_query = f""" and product_product.create_date >= '{data['from_date']}'""" + query += new_query + + if data['end_date']: + new_query = f""" and product_product.create_date <= '{data['end_date']}'""" + query += new_query + + product = tuple(data['products']) + categories = tuple(data['categories']) + + if data['filter_by'] == 'product': + if len(product) == 1: + new_query = f""" and product_product.id = {product[0]} """ + query += new_query + elif len(product) > 1: + new_query = f""" and product_product.id in {product} """ + query += new_query + else: + raise ValidationError('No Product Found') + elif data['filter_by'] == 'category': + if data['categories']: + if len(categories) == 1: + new_query = f""" and product_category.id = {categories[0]}""" + query += new_query + elif len(categories) > 1: + new_query = f""" and product_category.id in {categories} """ + query += new_query + else: + raise ValidationError('No Category Found') + + self.env.cr.execute(query) + record = self.env.cr.dictfetchall() + if len(record) > 0: + result = get_data(record) + return { + 'data': data, + 'company': self.env.company, + 'result': result, + } + else: + raise ValidationError('No Data Found !') diff --git a/inventory_valuation_report/report/inventory_valuation_reports.xml b/inventory_valuation_report/report/inventory_valuation_reports.xml new file mode 100644 index 000000000..8e63d0e00 --- /dev/null +++ b/inventory_valuation_report/report/inventory_valuation_reports.xml @@ -0,0 +1,13 @@ + + + + + Valuation Report + valuation.report + qweb-pdf + inventory_valuation_report.report_inventory_valuation + inventory_valuation_report.report_inventory_valuation + Inventory Valuation Report + + diff --git a/inventory_valuation_report/report/valuation_report_pdf_templates.xml b/inventory_valuation_report/report/valuation_report_pdf_templates.xml new file mode 100644 index 000000000..151b1eb56 --- /dev/null +++ b/inventory_valuation_report/report/valuation_report_pdf_templates.xml @@ -0,0 +1,223 @@ + + + + diff --git a/inventory_valuation_report/security/ir.model.access.csv b/inventory_valuation_report/security/ir.model.access.csv new file mode 100644 index 000000000..548ea37f5 --- /dev/null +++ b/inventory_valuation_report/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_valuation_report,valuation.report,model_valuation_report,base.group_user,1,1,1,1 diff --git a/inventory_valuation_report/static/description/assets/icons/check.png b/inventory_valuation_report/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/check.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/chevron.png b/inventory_valuation_report/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/chevron.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/cogs.png b/inventory_valuation_report/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/cogs.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/consultation.png b/inventory_valuation_report/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/consultation.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/ecom-black.png b/inventory_valuation_report/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/ecom-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/education-black.png b/inventory_valuation_report/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/education-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/hotel-black.png b/inventory_valuation_report/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/hotel-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/license.png b/inventory_valuation_report/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/license.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/lifebuoy.png b/inventory_valuation_report/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/lifebuoy.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/manufacturing-black.png b/inventory_valuation_report/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/manufacturing-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/pos-black.png b/inventory_valuation_report/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/pos-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/puzzle.png b/inventory_valuation_report/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/puzzle.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/restaurant-black.png b/inventory_valuation_report/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/restaurant-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/service-black.png b/inventory_valuation_report/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/service-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/trading-black.png b/inventory_valuation_report/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/trading-black.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/training.png b/inventory_valuation_report/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/training.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/update.png b/inventory_valuation_report/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/update.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/user.png b/inventory_valuation_report/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/user.png differ diff --git a/inventory_valuation_report/static/description/assets/icons/wrench.png b/inventory_valuation_report/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/inventory_valuation_report/static/description/assets/icons/wrench.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/categories.png b/inventory_valuation_report/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/categories.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/check-box.png b/inventory_valuation_report/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/check-box.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/compass.png b/inventory_valuation_report/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/compass.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/corporate.png b/inventory_valuation_report/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/corporate.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/customer-support.png b/inventory_valuation_report/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/customer-support.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/cybrosys-logo.png b/inventory_valuation_report/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/cybrosys-logo.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/features.png b/inventory_valuation_report/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/features.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/logo.png b/inventory_valuation_report/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/logo.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/pictures.png b/inventory_valuation_report/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/pictures.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/pie-chart.png b/inventory_valuation_report/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/pie-chart.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/right-arrow.png b/inventory_valuation_report/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/right-arrow.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/star.png b/inventory_valuation_report/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/star.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/support.png b/inventory_valuation_report/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/support.png differ diff --git a/inventory_valuation_report/static/description/assets/misc/whatsapp.png b/inventory_valuation_report/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/misc/whatsapp.png differ diff --git a/inventory_valuation_report/static/description/assets/modules/1.png b/inventory_valuation_report/static/description/assets/modules/1.png new file mode 100644 index 000000000..05f58a9b2 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/modules/1.png differ diff --git a/inventory_valuation_report/static/description/assets/modules/2.png b/inventory_valuation_report/static/description/assets/modules/2.png new file mode 100644 index 000000000..33372bdc1 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/modules/2.png differ diff --git a/inventory_valuation_report/static/description/assets/modules/3.png b/inventory_valuation_report/static/description/assets/modules/3.png new file mode 100644 index 000000000..99298bf4b Binary files /dev/null and b/inventory_valuation_report/static/description/assets/modules/3.png differ diff --git a/inventory_valuation_report/static/description/assets/modules/4.gif b/inventory_valuation_report/static/description/assets/modules/4.gif new file mode 100644 index 000000000..beb106101 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/modules/4.gif differ diff --git a/inventory_valuation_report/static/description/assets/modules/5.png b/inventory_valuation_report/static/description/assets/modules/5.png new file mode 100644 index 000000000..42d7af8e6 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/modules/5.png differ diff --git a/inventory_valuation_report/static/description/assets/modules/6.png b/inventory_valuation_report/static/description/assets/modules/6.png new file mode 100644 index 000000000..f088c60a2 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/modules/6.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/1.png b/inventory_valuation_report/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..13dfab57e Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/1.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/2.png b/inventory_valuation_report/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..bc024a639 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/2.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/3.png b/inventory_valuation_report/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..01379fa77 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/3.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/4.png b/inventory_valuation_report/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..41a4192a0 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/4.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/5.png b/inventory_valuation_report/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..e122c94dd Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/5.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/6.png b/inventory_valuation_report/static/description/assets/screenshots/6.png new file mode 100644 index 000000000..7628d4028 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/6.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/7.png b/inventory_valuation_report/static/description/assets/screenshots/7.png new file mode 100644 index 000000000..a2ff6a42f Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/7.png differ diff --git a/inventory_valuation_report/static/description/assets/screenshots/hero.gif b/inventory_valuation_report/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..1e77e6800 Binary files /dev/null and b/inventory_valuation_report/static/description/assets/screenshots/hero.gif differ diff --git a/inventory_valuation_report/static/description/banner.png b/inventory_valuation_report/static/description/banner.png new file mode 100644 index 000000000..1dc4760fd Binary files /dev/null and b/inventory_valuation_report/static/description/banner.png differ diff --git a/inventory_valuation_report/static/description/icon.png b/inventory_valuation_report/static/description/icon.png new file mode 100644 index 000000000..5dfadfebe Binary files /dev/null and b/inventory_valuation_report/static/description/icon.png differ diff --git a/inventory_valuation_report/static/description/index.html b/inventory_valuation_report/static/description/index.html new file mode 100644 index 000000000..9aafafbd8 --- /dev/null +++ b/inventory_valuation_report/static/description/index.html @@ -0,0 +1,621 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ + + +

+ Inventory Valuation Report

+

+ Get Reports of your stock adjustments.

+ + + +
+ + +
+
+ +
+

+ Explore This + Module

+
+ + + + +
+
+ +
+

+ Overview +

+
+
+
+ This module prints the Inventory Valuation Report of the stock + adjustments in pdf and xlsx format.The module also has a feature to + print the summary report of the valuation report. +
+
+ + + +
+
+ +
+

+ Features +

+
+
+
+
+ + Print Pdf Report for an Inventory Valuation. +
+
+ + Print Xslx Report for an Inventory Valuation. +
+
+ + Custom Filter based on Product and Category. +
+
+
+ + + +
+
+ +
+

+ Screenshots +

+
+
+
+ +
+

+ Inventory Valuation Report

+

+ Select the inventory valuation report from reporting.

+ +
+ +
+

+ Wizard for Report Printing.

+

+ +
+ +
+

+ Customized Filter based on Product and Category.

+

+ +
+
+

+ Enable the Product Filter to select the Product.

+

+ +
+
+

+ Enable the Category Filter to select the Product Category.

+

+ +
+
+

+ Printing Summary Valuation Report.

+

+ +
+
+

+ Print Valuation Report in Xslx.

+

+ +
+ +
+
+ + + +
+
+ +
+

+ Related Products +

+
+
+
+ +
+
+ + + + +
+
+ +
+

+ Our Services +

+
+ +
+
+
+
+ +
+
+ Odoo + Customization
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Support
+
+ + +
+
+ +
+
+ Hire + Odoo + Developer
+
+ +
+
+ +
+
+ Odoo + Integration
+
+ +
+
+ +
+
+ Odoo + Migration
+
+ + +
+
+ +
+
+ Odoo + Consultancy
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+ +
+ + + + + +
+
+ +
+

+ Our + Industries +

+
+ +
+
+
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products

+
+
+ +
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+ +
+
+ +
+ Education +
+

+ A platform for + educational management

+
+
+ +
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations

+
+
+ +
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+ +
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice

+
+
+ +
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically

+
+
+ +
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

+
+
+
+
+ + + + +
+
+ +
+

+ Support +

+
+
+
+
+
+
+ +
+
+

Need Help?

+

Got questions or need help? + Get in touch.

+ +

+ odoo@cybrosys.com

+
+
+
+
+
+
+
+ +
+
+

WhatsApp

+

Say hi to us on WhatsApp!

+ +

+ +91 86068 + 27707

+
+
+
+
+
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/inventory_valuation_report/static/src/js/action_manager.js b/inventory_valuation_report/static/src/js/action_manager.js new file mode 100644 index 000000000..653eb1f8f --- /dev/null +++ b/inventory_valuation_report/static/src/js/action_manager.js @@ -0,0 +1,30 @@ +/** @odoo-module */ +/** + * @module ir.actions.report handlers + * @description Contains handlers for generating XLSX reports in Odoo + */ + +import { registry } from "@web/core/registry"; +import { download } from "@web/core/network/download"; +import framework from 'web.framework'; +import session from 'web.session'; + +/** + * Add handler for generating XLSX reports. + * @param {Object} action - The action object containing report information + * @returns {Promise} - A Promise that resolves when the report is generated and downloaded + */ +registry.category("ir.actions.report handlers").add("xlsx", async (action) => { + if (action.report_type === 'xlsx') { + framework.blockUI(); + var def = $.Deferred(); + session.get_file({ + url: '/xlsx_reports', + data: action.data, + success: def.resolve.bind(def), + error: (error) => this.call('crash_manager', 'rpc_error', error), + complete: framework.unblockUI, + }); + return def; + } +}); diff --git a/inventory_valuation_report/wizards/__init__.py b/inventory_valuation_report/wizards/__init__.py new file mode 100644 index 000000000..ee040c513 --- /dev/null +++ b/inventory_valuation_report/wizards/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +from . import valuation_report diff --git a/inventory_valuation_report/wizards/valuation_report.py b/inventory_valuation_report/wizards/valuation_report.py new file mode 100644 index 000000000..084b3adbd --- /dev/null +++ b/inventory_valuation_report/wizards/valuation_report.py @@ -0,0 +1,349 @@ +# -*- coding: utf-8 -*- +################################################################################ +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies(). +# Author: Sumith Sivan() +# +# 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 . +# +################################################################################ +import io +import json + +from odoo import api, fields, models +from odoo.exceptions import ValidationError +from odoo.tools import date_utils + +try: + from odoo.tools.misc import xlsxwriter +except ImportError: + import xlsxwriter + + +class WizardReport(models.TransientModel): + """Valuation report xlsx template """ + _name = 'valuation.report' + + company_id = fields.Many2one("res.company", sting="Company", required=True) + warehouse_ids = fields.Many2many("stock.warehouse", string="Warehouse", + required=True) + + product_ids = fields.Many2many("product.product", + help="Select the products") + category_ids = fields.Many2many("product.category") + filter_by = fields.Selection( + [('product', 'Product'), ('category', 'Category')], string='Filter By') + start_date = fields.Datetime(string="Start Date") + end_date = fields.Datetime(string="End Date", ) + summary = fields.Boolean(string="Summary", help="Print Summary Report") + + @api.onchange('company_id') + def _compute_warehouse(self): + if self.company_id: + self.warehouse_ids = self.env['stock.warehouse'].search([ + ('company_id', '=', self.company_id.id) + ]).ids + else: + self.warehouse_ids = False + return {'domain': { + 'warehouse_ids': [('company_id', '=', self.company_id.id)]}} + + def action_btn_pdf(self): + """Function to print pdf report""" + product = self.env['product.product'].search( + [('detailed_type', '=', 'product')]) + default_code = [] + product_ids = [] + category_ids = [] + warehouse = [rec.name for rec in self.warehouse_ids] + + if self.filter_by == "product": + default_code = [rec.default_code for rec in self.product_ids] + product_ids = [int(rec.id) for rec in self.product_ids] + + if self.filter_by == "category": + category_ids = [int(rec.id) for rec in self.category_ids] + data = { + 'from_date': self.start_date, + 'end_date': self.end_date, + 'my_company': self.company_id.name, + 'my_company_id': self.company_id.id, + 'currency': self.company_id.currency_id.name, + 'warehouse': warehouse, + 'filter_by': self.filter_by, + 'products': product_ids, + 'default_code': default_code, + 'categories': category_ids, + 'summary': self.summary, + 'all_product': product, + + } + return self.env.ref( + 'inventory_valuation_report.action_report_valuation_report').report_action( + self, + data=data) + + def action_btn_xlsx(self): + """Function to print xlsx report""" + if self.warehouse_ids: + warehouse_names = [rec.name for rec in self.warehouse_ids] + warehouse = ', '.join(warehouse_names) + if str(self.start_date) > str(self.end_date): + raise ValidationError('Start Date must be less than End Date') + + query = """select product_product.id as product_id,product_template.default_code as default_code , + product_template.name->>'en_US' as name, product_category.name as category from product_template join + product_product on product_product.product_tmpl_id = product_template.id join product_category on + product_template.categ_id = product_category.id """ + + def get_data(res): + product_id = [rec['product_id'] for rec in res] + + for i in range(len(res)): + product = self.env['product.product'].browse(product_id[i]) + purchase_count = self.env['purchase.order.line'].search( + [('product_id', '=', product_id[i])]) + valuation = self.env['stock.valuation.layer'].search( + [('product_id', '=', product_id[i])], + order="create_date desc", limit=1) + internal_locations = self.env['stock.location'].search( + [('usage', '=', 'internal')]) + internal_qty = 0 + + for quant in internal_locations: + tracking = product.tracking + if tracking == 'lot': + lot_qty = self.env['stock.lot'].search( + [('product_id', '=', product_id[i])]) + lot_qty_count = self.env['stock.quant'].search([ + ('product_id', '=', product_id[i]), + ('lot_id', 'in', lot_qty.ids), + ('location_id', '=', quant.id) + ]) + internal_qty += sum( + lot_qty_count.mapped('available_quantity')) + else: + internal_stock_quant = self.env['stock.quant'].search( + [('location_id', '=', quant.id), + ('product_id', '=', product_id[i])]) + internal_qty += internal_stock_quant.available_quantity + + adjustment_rec = self.env['stock.quant'].search( + [('product_id', '=', product_id[i])], + order="create_date desc", limit=1) + adjustment = adjustment_rec.inventory_diff_quantity + res[i][ + 'costing_method'] = product.categ_id.property_cost_method + res[i]['standard_price'] = product.standard_price + res[i]['sale_qty'] = product.sales_count + res[i]['received_qty'] = sum( + purchase_count.mapped('product_uom_qty')) + res[i]['beginning'] = res[i]['received_qty'] - res[i][ + 'sale_qty'] + res[i]['valuation'] = valuation.value + res[i]['internal'] = internal_qty + res[i]['adjustment'] = adjustment + return res + + product_ids = [rec.id for rec in self.product_ids] + category_ids = [rec.id for rec in self.category_ids] + + if self.company_id: + query += f""" join res_company on res_company.id=product_template.company_id where res_company.id = '{self.company_id.id}'""" + + if self.start_date: + query += f""" and product_product.create_date >= '{self.start_date}'""" + + if self.end_date: + query += f""" and product_product.create_date <= '{self.end_date}'""" + + product = tuple(product_ids) + categories = tuple(category_ids) + + if self.filter_by == 'product': + if len(product) == 1: + query += f""" and product_product.id = {product[0]} """ + elif len(product) > 1: + query += f""" and product_product.id in {product} """ + else: + raise ValidationError('No Product Found') + if self.filter_by == 'category': + if len(categories) == 1: + query += f""" and product_category.id = {categories[0]}""" + + elif len(categories) > 1: + query += f""" and product_category.id in {categories} """ + else: + raise ValidationError('No Category Found') + + self.env.cr.execute(query) + record = self.env.cr.dictfetchall() + result = get_data(record) + data = { + 'from_date': self.start_date, + 'end_date': self.end_date, + 'my_company': self.company_id.name, + 'currency': self.company_id.currency_id.name, + 'warehouse': warehouse, + 'summary': self.summary, + 'excel_result': result + } + return { + 'type': 'ir.actions.report', + 'report_type': 'xlsx', + 'data': { + 'model': 'valuation.report', + 'output_format': 'xlsx', + 'options': json.dumps(data, default=date_utils.json_default), + 'report_name': 'Excel Report Name', + } + } + + def get_xlsx_report(self, data, response): + """xlsx report template""" + output = io.BytesIO() + workbook = xlsxwriter.Workbook(output, {'in_memory': True}) + sheet = workbook.add_worksheet() + cell_format = workbook.add_format({'font_size': '12px'}) + head = workbook.add_format( + {'align': 'center', 'bold': True, 'font_size': '20px'}) + txt = workbook.add_format({'align': 'center', 'font_size': '10px'}) + columns = ['C:C', 'B:B', 'D:D', 'E:E', 'F:F', 'G:G', 'H:H', 'I:I', + 'J:J', 'L:L', 'M:M'] + for column in columns: + sheet.set_column(column, 20) + if data['summary']: + sheet.merge_range('B2:I3', 'Summary Valuation REPORT', head) + if data['from_date']: + sheet.write('B5', 'Start Date', cell_format) + sheet.write('B6', data['from_date'], txt) + if data['end_date']: + sheet.write('D5', 'End Date', cell_format) + sheet.write('D6', data['end_date'], txt) + if data['my_company']: + sheet.write('F5', 'Company', cell_format) + sheet.write('F6', data['my_company'], txt) + if data['warehouse']: + sheet.merge_range('G5:H5', 'Warehouse(s)', cell_format) + sheet.merge_range('G6:H6', data['warehouse'], txt) + if data['currency']: + sheet.write('I5', 'Currency', cell_format) + sheet.write('I6', data['currency'], txt) + sheet.write('B8', 'Sl.No', txt) + sheet.write('C8', 'Category', txt) + sheet.write('D8', 'Costing Method', txt) + sheet.write('E8', 'Cost Price', txt) + sheet.write('F8', 'Beginning', txt) + sheet.write('G8', 'Internal', txt) + sheet.write('H8', 'Received', txt) + sheet.write('I8', 'Sales', txt) + sheet.write('J8', 'Adjustment', txt) + sheet.write('K8', 'Ending', txt) + sheet.write('L8', 'Valuation', txt) + + row_number = 9 + column_number = 1 + count = 1 + for i in data['excel_result']: + sheet.write(row_number, column_number, count, txt) + sheet.write(row_number, column_number + 1, i['category'], txt) + sheet.write(row_number, column_number + 2, i['costing_method'], + txt) + sheet.write(row_number, column_number + 3, i['standard_price'], + txt) + sheet.write(row_number, column_number + 4, + i['received_qty'] - i['sale_qty'], txt) + sheet.write(row_number, column_number + 5, i['internal'], txt) + sheet.write(row_number, column_number + 6, i['received_qty'], + txt) + sheet.write(row_number, column_number + 7, i['sale_qty'], txt) + sheet.write(row_number, column_number + 8, i['adjustment'], + txt) + sheet.write(row_number, column_number + 9, + i['beginning'] + i['received_qty'] - i['sale_qty'] + + i['adjustment'], txt) + sheet.write(row_number, column_number + 10, i['valuation'], + txt) + + row_number += 1 + count += 1 + workbook.close() + output.seek(0) + response.stream.write(output.read()) + output.close() + else: + sheet.merge_range('B2:I3', 'Inventory Valuation REPORT', head) + if data['from_date']: + sheet.write('B5', 'Start Date', cell_format) + sheet.write('B6', data['from_date'], txt) + if data['end_date']: + sheet.write('D5', 'End Date', cell_format) + sheet.write('D6', data['end_date'], txt) + if data['my_company']: + sheet.write('F5', 'Company', cell_format) + sheet.write('F6', data['my_company'], txt) + if data['warehouse']: + sheet.merge_range('G5:H5', 'Warehouse(s)', cell_format) + sheet.merge_range('G6:H6', data['warehouse'], txt) + if data['currency']: + sheet.write('I5', 'Currency', cell_format) + sheet.write('I6', data['currency'], txt) + + sheet.write('B9', 'Sl.No', txt) + sheet.write('C9', 'Default Code', txt) + sheet.write('D9', 'Name', txt) + sheet.write('E9', 'Category', txt) + sheet.write('F9', 'Costing Method', txt) + sheet.write('G9', 'Cost Price', txt) + sheet.write('H9', 'Beginning', txt) + sheet.write('I9', 'Internal', txt) + sheet.write('J9', 'Received', txt) + sheet.write('K9', 'Sales', txt) + sheet.write('L9', 'Adjustment', txt) + sheet.write('M9', 'Ending', txt) + sheet.write('N9', 'Valuation', txt) + + row_number = 10 + column_number = 1 + count = 1 + for i in data['excel_result']: + sheet.write(row_number, column_number, count, txt) + sheet.write(row_number, column_number + 1, i['default_code'], + txt) + sheet.write(row_number, column_number + 2, i['name'], txt) + sheet.write(row_number, column_number + 3, i['category'], txt) + sheet.write(row_number, column_number + 4, i['costing_method'], + txt) + sheet.write(row_number, column_number + 5, i['standard_price'], + txt) + sheet.write(row_number, column_number + 6, + i['received_qty'] - i['sale_qty'], txt) + sheet.write(row_number, column_number + 7, i['internal'], txt) + sheet.write(row_number, column_number + 8, i['received_qty'], + txt) + sheet.write(row_number, column_number + 9, i['sale_qty'], txt) + sheet.write(row_number, column_number + 10, i['adjustment'], + txt) + sheet.write(row_number, column_number + 11, + i['beginning'] + i['received_qty'] - i['sale_qty'] + + i['adjustment'], txt) + sheet.write(row_number, column_number + 12, i['valuation'], + txt) + row_number += 1 + count += 1 + workbook.close() + output.seek(0) + response.stream.write(output.read()) + output.close() diff --git a/inventory_valuation_report/wizards/valuation_report_views.xml b/inventory_valuation_report/wizards/valuation_report_views.xml new file mode 100644 index 000000000..edc78e56d --- /dev/null +++ b/inventory_valuation_report/wizards/valuation_report_views.xml @@ -0,0 +1,92 @@ + + + + + + + + valuation.report.wizard + valuation.report + +
+ +
+
+

Company

+ + + +
+

Filter By

+ + + +
+
+

Warehouse

+ + + +
+ + + +
+
+

Valuation

+ + + + +
+
+
+ + + + + +
+
+ + + + + +
+
+
+
+
+
+
+ + + + Report + valuation.report + form + + new + + + + +