diff --git a/product_ageing_report/__init__.py b/product_ageing_report/__init__.py new file mode 100644 index 000000000..9b5cebcf5 --- /dev/null +++ b/product_ageing_report/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Linto C T() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +import wizard +import report diff --git a/product_ageing_report/__manifest__.py b/product_ageing_report/__manifest__.py new file mode 100644 index 000000000..aaa6619aa --- /dev/null +++ b/product_ageing_report/__manifest__.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Linto C T() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## +{ + 'name': "Stock Ageing Analysis", + 'version': '10.0.1.0.0', + 'summary': """Product Ageing Analysis With Filterations""", + 'description': """With this module, we can perform stock ageing analysis with optional filters such + as location, category, etc.""", + 'author': "Cybrosys Techno Solutions", + 'website': "https://www.cybrosys.com", + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'category': 'Stock', + 'depends': ['product', 'stock'], + 'data': [ + 'security/ir.model.access.csv', + 'wizard/product_ageing.xml', + 'report/report_ageing_products.xml', + ], + 'images': ['static/description/banner.jpg'], + 'license': 'AGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/product_ageing_report/report/__init__.py b/product_ageing_report/report/__init__.py new file mode 100644 index 000000000..3ca16594b --- /dev/null +++ b/product_ageing_report/report/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Linto C T() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +import report_ageing_products diff --git a/product_ageing_report/report/report_ageing_products.py b/product_ageing_report/report/report_ageing_products.py new file mode 100644 index 000000000..f13f00722 --- /dev/null +++ b/product_ageing_report/report/report_ageing_products.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Linto C T() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +from odoo import models, api +from datetime import datetime + + +class ReportAvgPrices(models.AbstractModel): + _name = 'report.product_ageing_report.report_ageing_analysis' + + def get_productss(self, docs): + """input : starting date, location and category + output: a dictionary with all the products and their stock for that currespnding intervals""" + + cr = self._cr + if docs.location_id and docs.product_categ: + cr.execute("select sq.id from stock_quant sq inner join product_product pp on(pp.id=sq.product_id) " + " inner join product_template pt on(pt.id=pp.product_tmpl_id and pt.categ_id in %s) " + "where sq.location_id in %s and sq.qty > 0 and sq.in_date <=%s", (tuple(docs.product_categ.ids), + tuple(docs.location_id.ids), docs.from_date)) + elif docs.location_id: + cr.execute("select sq.id from stock_quant sq where sq.location_id in %s and sq.qty > 0 and sq.in_date <=%s", + (tuple(docs.location_id.ids), docs.from_date)) + elif docs.product_categ: + cr.execute("select sq.id from stock_quant sq inner join product_product pp on(pp.id=sq.product_id) " + " inner join product_template pt on(pt.id=pp.product_tmpl_id and pt.categ_id in %s)" + "where sq.qty > 0 and sq.in_date <=%s", (tuple(docs.product_categ.ids), docs.from_date)) + else: + cr.execute("select id from stock_quant where qty > 0 and in_date <=%s", (docs.from_date,)) + quant_ids = cr.fetchall() + quant_id = [] + for i in quant_ids: + quant_id.append(i[0]) + rec = self.env['stock.quant'].browse(quant_id) + products = {} + product_list = [] + for i in rec: + date1 = datetime.strptime(docs.from_date, '%Y-%m-%d %H:%M:%S').date() + if len(i.history_ids) == 1 and i.product_id.id not in product_list: + product_list.append(i.product_id.id) + temp = { + 'product': i.product_id.name, + 'total_qty': i.qty, + } + qty = [0, 0, 0, 0, 0] + + date2 = datetime.strptime(i.in_date, '%Y-%m-%d %H:%M:%S').date() + no_days = (date1 - date2).days + t1 = 0 + t2 = docs.interval + for j in range(0, 5): + if no_days >= 4 * docs.interval: + qty[4] += i.qty + break + elif no_days in range(t1, t2): + qty[j] += i.qty + break + + t1 = t2 + t2 += docs.interval + temp['qty'] = qty + products[i.product_id.id] = temp + elif len(i.history_ids) == 1 and i.product_id.id in product_list: + date2 = datetime.strptime(i.in_date, '%Y-%m-%d %H:%M:%S').date() + no_days = (date1 - date2).days + t1 = 0 + t2 = docs.interval + for j in range(0, 5): + if no_days >= 4 * docs.interval: + products[i.product_id.id]['qty'][4] += i.qty + products[i.product_id.id]['total_qty'] += i.qty + break + elif no_days in range(t1, t2): + products[i.product_id.id]['qty'][j] += i.qty + products[i.product_id.id]['total_qty'] += i.qty + break + + t1 = t2 + t2 += docs.interval + return products + + @api.model + def render_html(self, docids, data=None): + """we are overwriting this function because we need to show values from other models in the report + we pass the objects in the docargs dictionary""" + + self.model = self.env.context.get('active_model') + docs = self.env[self.model].browse(self.env.context.get('active_id')) + products = self.get_productss(docs) + interval = ['0-'+str(docs.interval), + str(docs.interval)+'-'+str(2*docs.interval), + str(2*docs.interval)+'-'+str(3*docs.interval), + str(3*docs.interval)+'-'+str(4*docs.interval), + str(4*docs.interval)+'+'] + loc = "" + categ = "" + for i in docs.location_id: + if i.location_id.name and i.name: + loc += i.location_id.name+" / "+i.name+", " + for i in docs.product_categ: + if i.name: + categ += i.name+", " + loc = loc[:-2] + categ = categ[:-2] + docargs = { + 'doc_ids': self.ids, + 'doc_model': self.model, + 'docs': docs, + 'loc': loc, + 'categ': categ, + 'interval': interval, + 'products': products, + } + return self.env['report'].render('product_ageing_report.report_ageing_analysis', docargs) diff --git a/product_ageing_report/report/report_ageing_products.xml b/product_ageing_report/report/report_ageing_products.xml new file mode 100644 index 000000000..12c226446 --- /dev/null +++ b/product_ageing_report/report/report_ageing_products.xml @@ -0,0 +1,80 @@ + + + + + + \ No newline at end of file diff --git a/product_ageing_report/security/ir.model.access.csv b/product_ageing_report/security/ir.model.access.csv new file mode 100644 index 000000000..ec8e39de4 --- /dev/null +++ b/product_ageing_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 +ageing_inv_user,access_inv_user,product_ageing_report.model_product_ageing,stock.group_stock_user,1,1,1,1 +ageing_mgr,access_ageing_mgr,product_ageing_report.model_product_ageing,stock.group_stock_manager,1,1,1,1 + diff --git a/product_ageing_report/static/description/ageing-menu.png b/product_ageing_report/static/description/ageing-menu.png new file mode 100644 index 000000000..779d6d5e5 Binary files /dev/null and b/product_ageing_report/static/description/ageing-menu.png differ diff --git a/product_ageing_report/static/description/ageing-sample.png b/product_ageing_report/static/description/ageing-sample.png new file mode 100644 index 000000000..0e91a5027 Binary files /dev/null and b/product_ageing_report/static/description/ageing-sample.png differ diff --git a/product_ageing_report/static/description/ageing-wiz.png b/product_ageing_report/static/description/ageing-wiz.png new file mode 100644 index 000000000..5f42f90b2 Binary files /dev/null and b/product_ageing_report/static/description/ageing-wiz.png differ diff --git a/product_ageing_report/static/description/banner.jpg b/product_ageing_report/static/description/banner.jpg new file mode 100644 index 000000000..92effb57b Binary files /dev/null and b/product_ageing_report/static/description/banner.jpg differ diff --git a/product_ageing_report/static/description/cybro_logo.png b/product_ageing_report/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/product_ageing_report/static/description/cybro_logo.png differ diff --git a/product_ageing_report/static/description/icon.png b/product_ageing_report/static/description/icon.png new file mode 100644 index 000000000..cd3a2abeb Binary files /dev/null and b/product_ageing_report/static/description/icon.png differ diff --git a/product_ageing_report/static/description/index.html b/product_ageing_report/static/description/index.html new file mode 100644 index 000000000..16fa0d19d --- /dev/null +++ b/product_ageing_report/static/description/index.html @@ -0,0 +1,114 @@ +
+
+

Stock Ageing Analysis

+

..Ageing Analysis for Products..

+

Cybrosys Technologies

+
+
+

Features:

+
+ Ageing analysis for products filtered by location.
+ Ageing analysis for products filtered by product category.
+ Ageing analysis for products filtered by date.
+ Ageing analysis for products with customizable intervals.
+
+
+
+ +
+
+
+

Overview

+

+ This module adds a new feature, 'Stock Ageing Analysis' to Odoo. We can perform the analysis + filtered by location, product category, date, etc. +

+
+
+
+ +
+
+

Menu

+
+
+ +
+
+


+
+
+

+ A new menu, 'Stock Ageing Analysis' is added under Inventory -> Reports for performing + this analysis. Clicking on this menu will open a new wizard. +

+

+
+
+
+ +
+
+

Ageing Analysis Wizard

+
+
+ +
+
+


+
+
+

+ Here we can set the filters we need to apply. If we need to filter the analysis by location, + we should specify those locations in the 'Location' field. If none selected, products in all + locations will be considered. The category filter also works in the same way. We can select the + categories from the 'Category' field. If none selected, all categories will be considered. +

+

+ The 'Date' field can be used to specify the starting date from which we need to start the checking. + Finally, the 'Interval' field specifies the length of interval in days. +

+
+
+
+
+
+
+

Sample Report

+
+

+ After filling the required details, click on the 'Print' button. +

+

+
+
+ +
+
+
+
+
+

Need Any Help?

+ +
\ No newline at end of file diff --git a/product_ageing_report/wizard/__init__.py b/product_ageing_report/wizard/__init__.py new file mode 100644 index 000000000..578d0a386 --- /dev/null +++ b/product_ageing_report/wizard/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Linto C T() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +import product_ageing + diff --git a/product_ageing_report/wizard/product_ageing.py b/product_ageing_report/wizard/product_ageing.py new file mode 100644 index 000000000..4c13523b6 --- /dev/null +++ b/product_ageing_report/wizard/product_ageing.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Linto C T() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. +# +# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## + +from odoo import models, fields, api + + +class AgeingAnalysis(models.Model): + _name = 'product.ageing' + + from_date = fields.Datetime(string="Starting Date", required=True) + location_id = fields.Many2many('stock.location', string="Location") + product_categ = fields.Many2many('product.category', string="Category") + interval = fields.Integer(string="Interval(days)", default=30, required=True) + + @api.model + def compute_ageing(self, data): + """Redirects to the report with the values obtained from the wizard + 'data['form']': date duration""" + rec = self.browse(data) + data = {} + data['form'] = rec.read(['from_date', 'location_id', 'product_categ', 'interval']) + return self.env['report'].get_action(rec, 'product_ageing_report.report_ageing_analysis', + data=data) + diff --git a/product_ageing_report/wizard/product_ageing.xml b/product_ageing_report/wizard/product_ageing.xml new file mode 100644 index 000000000..7f371f0e9 --- /dev/null +++ b/product_ageing_report/wizard/product_ageing.xml @@ -0,0 +1,46 @@ + + + + + Ageing Analysis Wizard + product.ageing + +
+ + + + + + + + + + + + +
+
+
+
+
+ + + Stock Ageing Analysis + product.ageing + ir.actions.act_window + form + form + + new + + + + +
+
+ + +