Browse Source

[ADD] Initial Commit

pull/30/merge
SHEREEF PT 8 years ago
parent
commit
2108241991
  1. 25
      product_ageing_report/__init__.py
  2. 45
      product_ageing_report/__manifest__.py
  3. 24
      product_ageing_report/report/__init__.py
  4. 134
      product_ageing_report/report/report_ageing_products.py
  5. 80
      product_ageing_report/report/report_ageing_products.xml
  6. 4
      product_ageing_report/security/ir.model.access.csv
  7. BIN
      product_ageing_report/static/description/ageing-menu.png
  8. BIN
      product_ageing_report/static/description/ageing-sample.png
  9. BIN
      product_ageing_report/static/description/ageing-wiz.png
  10. BIN
      product_ageing_report/static/description/banner.jpg
  11. BIN
      product_ageing_report/static/description/cybro_logo.png
  12. BIN
      product_ageing_report/static/description/icon.png
  13. 114
      product_ageing_report/static/description/index.html
  14. 25
      product_ageing_report/wizard/__init__.py
  15. 44
      product_ageing_report/wizard/product_ageing.py
  16. 46
      product_ageing_report/wizard/product_ageing.xml

25
product_ageing_report/__init__.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Linto C T(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import wizard
import report

45
product_ageing_report/__manifest__.py

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Linto C T(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'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,
}

24
product_ageing_report/report/__init__.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Linto C T(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import report_ageing_products

134
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(<https://www.cybrosys.com>).
# Author: Linto C T(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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)

80
product_ageing_report/report/report_ageing_products.xml

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_ageing_analysis">
<t t-call="report.html_container">
<t t-call="report.external_layout">
<t t-foreach="docs" t-as="o">
<div class="page">
<div class="row">
<div class="mt32 mb32">
<h3 style="text-align:center;" >Stock Ageing Analysis</h3>
</div>
<div class="mt32 mb32">
<t t-if="categ">
<b>Product Category:</b> <span t-esc="categ" />
</t>
<br /><br />
<b>Date :</b> <span t-esc="docs.from_date" />
<div>
<t t-if="loc">
<b>Location:</b> <span t-esc="loc" style="float:left;"/>
</t>
<br />
<br />
</div>
<div>
<b>Interval(Days):</b> <span t-esc="docs.interval" />
</div>
</div>
</div>
<div class="row">
<div class="mt32 mb32">
<table style="border:1px solid;width:100%;">
<thead>
<tr style="height:35px;border:1px solid;">
<th style="vertical-align:middle;text-align:center;border:1px solid;">Product</th>
<t t-foreach="interval" t-as="i">
<th style="vertical-align:middle;text-align:center;border:1px solid;">
<t t-esc="i" />
</th>
</t>
<th style="vertical-align:middle;text-align:center;border:1px solid;">Total</th>
</tr>
</thead>
<tbody>
<t t-foreach="products" t-as="p">
<tr style="width:100%;height:30px;border:1px solid">
<td style="vertical-align:middle;text-align:center;border:1px solid;">
<span t-esc="products[p]['product']"/>
</td>
<t t-foreach="products[p]['qty']" t-as="qty">
<td style="vertical-align:middle;text-align:center;border:1px solid;">
<span t-esc="qty"/>
</td>
</t>
<td style="vertical-align:middle;text-align:center;border:1px solid;">
<span t-esc="products[p]['total_qty']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
</div>
</div>
</t>
</t>
</t>
</template>
<report
id="report_product_ageing"
model="stock.quant"
report_type="qweb-html"
string="Ageing Analysis"
name="product_ageing_report.report_ageing_analysis"
file="product_ageing_report.report_ageing_analysis"
menu="False"
/>
</odoo>

4
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 ageing_inv_user access_inv_user product_ageing_report.model_product_ageing stock.group_stock_user 1 1 1 1
3 ageing_mgr access_ageing_mgr product_ageing_report.model_product_ageing stock.group_stock_manager 1 1 1 1

BIN
product_ageing_report/static/description/ageing-menu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
product_ageing_report/static/description/ageing-sample.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
product_ageing_report/static/description/ageing-wiz.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
product_ageing_report/static/description/banner.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

BIN
product_ageing_report/static/description/cybro_logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
product_ageing_report/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

114
product_ageing_report/static/description/index.html

@ -0,0 +1,114 @@
<section class="oe_container">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Stock Ageing Analysis</h2>
<h3 class="oe_slogan">..Ageing Analysis for Products..</h3>
<h4 class="oe_slogan"><a href="https://www.cybrosys.com">Cybrosys Technologies</a> </h4>
</div>
<div class="oe_row oe_spaced" style="padding-left:65px;">
<h4>Features:</h4>
<div>
<span style="color:green;"> &#9745; </span> Ageing analysis for products filtered by location.<br/>
<span style="color:green;"> &#9745; </span> Ageing analysis for products filtered by product category.<br/>
<span style="color:green;"> &#9745; </span> Ageing analysis for products filtered by date.<br/>
<span style="color:green;"> &#9745; </span> Ageing analysis for products with customizable intervals.<br/>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<div class="oe_picture">
<h3 class="oe_slogan">Overview</h3>
<p class="oe_mt32">
This module adds a new feature, 'Stock Ageing Analysis' to Odoo. We can perform the analysis
filtered by location, product category, date, etc.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h3 class="oe_slogan">Menu</h3>
<div class="oe_span6" style="text-align: center;">
<div class="oe_demo oe_picture oe_screenshot">
<img style="border:10px solid white;width:87% !important;" src="ageing-menu.png">
</div>
</div>
<br><br><br>
<div>
<div>
<p class="text-justify">
A new menu, 'Stock Ageing Analysis' is added under Inventory -> Reports for performing
this analysis. Clicking on this menu will open a new wizard.
<p>
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h3 class="oe_slogan">Ageing Analysis Wizard</h3>
<div class="oe_span12" style="text-align: center;">
<div class="oe_demo oe_picture oe_screenshot">
<img style="border:10px solid white;width:100% !important;" src="ageing-wiz.png">
</div>
</div>
<br><br><br>
<div>
<div>
<p class="text-justify">
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.
<p>
<p class="text-justify">
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.
</p>
</div>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<h3 class="oe_slogan">Sample Report</h3>
<div>
<p class="text-justify">
After filling the required details, click on the 'Print' button.
<p>
</div>
<div style="text-align: center;">
<div class="oe_demo oe_picture">
<img style="border-top:1px solid !important;border-bottom:1px solid !important;border-left:1px solid !important;border-right:1px solid !important;width:100% !important;" src="ageing-sample.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2>
<div class="oe_slogan" style="margin-top:10px !important;">
<div>
<a class="btn btn-primary btn-lg mt8"
style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com"><i
class="fa fa-envelope"></i> Email </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;"
href="https://www.cybrosys.com/contact/"><i
class="fa fa-phone"></i> Contact Us </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;"
href="https://www.cybrosys.com/odoo-customization-and-installation/"><i
class="fa fa-check-square"></i> Request Customization </a>
</div>
<br>
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block">
<div>
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;"></i></a></td>
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;"></i></a></td>
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px;padding-left: 8px;"></i></a></td>
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;"></i></a></td>
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;"></i></a></td>
</div>
</div>
</section>

25
product_ageing_report/wizard/__init__.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Linto C T(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import product_ageing

44
product_ageing_report/wizard/product_ageing.py

@ -0,0 +1,44 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Linto C T(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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)

46
product_ageing_report/wizard/product_ageing.xml

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="ageing_analysis_view" model="ir.ui.view">
<field name="name">Ageing Analysis Wizard</field>
<field name="model">product.ageing</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<group>
<field name="location_id" widget="many2many_tags" />
<field name="product_categ" widget="many2many_tags" />
</group>
<group>
<field name="from_date" />
<field name="interval" />
</group>
</group>
</sheet>
<footer>
<button string="Print" name="compute_ageing" type="object" class="btn-primary"/>
<button string="Discard" class="btn-default" special="cancel"/>
</footer>
</form>
</field>
</record>
<record id="action_prod_ageing_analysis" model="ir.actions.act_window">
<field name="name">Stock Ageing Analysis</field>
<field name="res_model">product.ageing</field>
<field name="type">ir.actions.act_window</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="view_id" ref="ageing_analysis_view"/>
<field name="target">new</field>
</record>
<menuitem name="Stock Ageing Analysis" id="prod_ageing_analysis" action="action_prod_ageing_analysis"
parent="stock.menu_warehouse_report"/>
</data>
</odoo>
Loading…
Cancel
Save