@ -0,0 +1,46 @@ |
|||
.. 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 |
|||
|
|||
Product Expiry Dashboard |
|||
======================== |
|||
Product Expiry Dashboard allow users to view all the product details those are about to expire. |
|||
|
|||
Configuration |
|||
============= |
|||
* No additional configurations needed |
|||
|
|||
License |
|||
------- |
|||
General Public License, Version 3 (AGPL v3). |
|||
(https://www.gnu.org/licenses/agpl-3.0-standalone.html) |
|||
|
|||
Company |
|||
------- |
|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ |
|||
|
|||
Credits |
|||
------- |
|||
* Developer:(V15) Unnimaya C O, 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>`__ |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Unnimaya C O (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 models |
@ -0,0 +1,53 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Unnimaya C O (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': 'Product Expiry Dashboard', |
|||
'version': '15.0.1.0.0', |
|||
'category': 'Warehouse', |
|||
'summary': """Allow users to view all the product details those are going to |
|||
expire.""", |
|||
'description': """Product Expiry Dashboard display graphical view of |
|||
expiredproducts, nearly expiring products, their locations and |
|||
warehouses. This app allows take significant decisions quickly by |
|||
overseeing the products that will expire soon""", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'website': 'https://www.cybrosys.com', |
|||
'depends': ['stock', 'product_expiry'], |
|||
'data': ['views/product_expiry_view.xml'], |
|||
'assets': { |
|||
'web.assets_backend': [ |
|||
'/odoo_product_expiry_dashboard/static/src/js/product_expiry_action.js', |
|||
'/odoo_product_expiry_dashboard/static/src/css/style.css', |
|||
'https://cdn.jsdelivr.net/npm/chart.js' |
|||
], |
|||
'web.assets_qweb': [ |
|||
'/odoo_product_expiry_dashboard/static/src/xml/odoo_product_expiry_dashboard.xml', |
|||
], |
|||
}, |
|||
'images': ['static/description/banner.jpg'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
'application': False, |
|||
} |
@ -0,0 +1,7 @@ |
|||
## Module <odoo_product_expiry_dashboard> |
|||
|
|||
#### 13.10.2023 |
|||
#### Version 15.0.1.0.0 |
|||
#### ADD |
|||
|
|||
- Initial commit for Product Expiry Dashboard |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Unnimaya C O (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_production_lot |
@ -0,0 +1,195 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################ |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# |
|||
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Unnimaya C O (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, fields, models |
|||
|
|||
|
|||
class StockProductionLot(models.Model): |
|||
"""Inherited to include the functions for fetching the data which is to be |
|||
displayed on the dashboard""" |
|||
_inherit = "stock.production.lot" |
|||
|
|||
@api.model |
|||
def get_product_expiry(self, *args): |
|||
"""Returns the data to be displayed on the dashboard tiles""" |
|||
expiry_dict = {"expired": 0, "today": 0, "one_day": 0, "seven_day": 0, |
|||
"thirty_day": 0, |
|||
"one_twenty_day": 0} |
|||
search_params = [] |
|||
if args[0].get('start_date') and args[0].get('end_date'): |
|||
search_params = [ |
|||
('expiration_date', '>=', args[0].get('start_date')), |
|||
('expiration_date', '<=', args[0].get('end_date'))] |
|||
elif args[0].get('start_date'): |
|||
search_params = [ |
|||
('expiration_date', '>=', args[0].get('start_date'))] |
|||
elif args[0].get('end_date'): |
|||
search_params = [('expiration_date', '<=', args[0].get('end_date'))] |
|||
for record in self.search(search_params): |
|||
if record.expiration_date and record.product_qty != 0: |
|||
date_difference = (fields.Date.to_date( |
|||
record.expiration_date) - fields.Date.today()).days |
|||
if date_difference == 0: |
|||
expiry_dict["today"] += record.product_qty |
|||
elif date_difference == 1: |
|||
expiry_dict["one_day"] += record.product_qty |
|||
elif 7 >= date_difference > 1: |
|||
expiry_dict["seven_day"] += record.product_qty |
|||
elif 30 >= date_difference > 7: |
|||
expiry_dict["thirty_day"] += record.product_qty |
|||
elif 120 >= date_difference > 30: |
|||
expiry_dict["one_twenty_day"] += record.product_qty |
|||
search_params.append(('expiration_date', '<', fields.date.today())) |
|||
expiry_dict["expired"] = \ |
|||
sum(self.search(search_params).mapped('product_qty')) |
|||
return expiry_dict |
|||
|
|||
@api.model |
|||
def get_expired_product(self, *args): |
|||
"""Function for fetching the expired products""" |
|||
search_params = [('expiration_date', '<', fields.date.today())] |
|||
if args[0].get('start_date'): |
|||
search_params.append( |
|||
('expiration_date', '>=', args[0].get('start_date'))) |
|||
if args[0].get('end_date'): |
|||
search_params.append(('expiration_date', '<=', |
|||
args[0].get('end_date'))) |
|||
products_dict = {record: {'product_qty': record.product_qty, |
|||
'product': record.product_id.name} |
|||
for record in self.search(search_params)} |
|||
expired_products_dict = {product: sum(data['product_qty'] |
|||
for lot, data in |
|||
products_dict.items() if |
|||
data['product'] == product) |
|||
for product in set( |
|||
data['product'] for lot, data in products_dict.items())} |
|||
return expired_products_dict |
|||
|
|||
@api.model |
|||
def get_product_expiry_by_category(self, *args): |
|||
"""Functions for fetching the category of expired products""" |
|||
search_params = [('expiration_date', '<', fields.date.today())] |
|||
if args[0].get('start_date'): |
|||
search_params.append( |
|||
('expiration_date', '>=', args[0].get('start_date'))) |
|||
if args[0].get('end_date'): |
|||
search_params.append(('expiration_date', '<=', |
|||
args[0].get('end_date'))) |
|||
products_category_dict = {record: {'product_qty': record.product_qty, |
|||
'product_category': |
|||
record.product_id.categ_id.name} |
|||
for record in self.search(search_params)} |
|||
expired_product_category_dict = {product: sum(data['product_qty'] |
|||
for lot, data in |
|||
products_category_dict. |
|||
items() if |
|||
data['product_category'] |
|||
== product) |
|||
for product in |
|||
set(data['product_category'] |
|||
for lot, data in |
|||
products_category_dict.items())} |
|||
return expired_product_category_dict |
|||
|
|||
@api.model |
|||
def get_near_expiry_category(self): |
|||
"""Function for fetching the category of products expiring in 7 days""" |
|||
product_dict = {record: {'category': record.product_id.categ_id.name, |
|||
'product_qty': record.product_qty |
|||
} |
|||
for record in self.search([]) |
|||
if |
|||
record.expiration_date and record.product_qty and 7 >= |
|||
(fields.Date.to_date(record.expiration_date) - |
|||
fields.Date.today()).days > 0} |
|||
nearby_exp_products_dict = {product: sum( |
|||
data['product_qty'] for lot, data in product_dict.items() if |
|||
data['category'] == product) |
|||
for product in |
|||
set(data['category'] for lot, data in |
|||
product_dict.items()) |
|||
} |
|||
return nearby_exp_products_dict |
|||
|
|||
@api.model |
|||
def get_near_expiry_product(self): |
|||
"""Function for fetching the products expiring in 7 days""" |
|||
product_dict = {record: {'product_name': record.product_id.name, |
|||
'product_qty': record.product_qty |
|||
} |
|||
for record in self.search([]) |
|||
if |
|||
record.expiration_date and record.product_qty and 7 >= |
|||
(fields.Date.to_date(record.expiration_date) - |
|||
fields.Date.today()).days > 0} |
|||
nearby_exp_products_dict = {product: sum( |
|||
data['product_qty'] for lot, data in product_dict.items() if |
|||
data['product_name'] == product) |
|||
for product in |
|||
set(data['product_name'] for lot, data in |
|||
product_dict.items()) |
|||
} |
|||
return nearby_exp_products_dict |
|||
|
|||
@api.model |
|||
def get_product_expired_today(self): |
|||
"""Function for fetching the products expiring today""" |
|||
return len([record for record in self.search([]) if |
|||
record.expiration_date and |
|||
fields.Date.to_date(record.expiration_date) == |
|||
fields.date.today()]) |
|||
|
|||
@api.model |
|||
def get_expire_product_location(self): |
|||
"""Function for fetching the location of products expiring in 7 days""" |
|||
location_dict = { |
|||
record: {'location': location.location_id.display_name, |
|||
'count': location.inventory_quantity_auto_apply} for |
|||
record in self.search([]) if |
|||
record.expiration_date and record.product_qty and 7 >= ( |
|||
fields.Date.to_date( |
|||
record.expiration_date) - fields.Date.today()).days > 0 |
|||
for location in record.quant_ids if |
|||
location.inventory_quantity_auto_apply > 0} |
|||
nearby_expiry_location = {product: sum( |
|||
data['count'] for lot, data in location_dict.items() if |
|||
data['location'] == product) for product in set( |
|||
data['location'] for lot, data in location_dict.items())} |
|||
return nearby_expiry_location |
|||
|
|||
@api.model |
|||
def get_expire_product_warehouse(self): |
|||
"""Function for fetching the warehouse of products expiring in 7 days""" |
|||
warehouse_dict = { |
|||
record: { |
|||
'warehouse': location.location_id.warehouse_id.display_name, |
|||
'count': location.inventory_quantity_auto_apply} for |
|||
record in self.search([]) if |
|||
record.expiration_date and record.product_qty and 7 >= ( |
|||
fields.Date.to_date( |
|||
record.expiration_date) - fields.Date.today()).days > 0 |
|||
for location in record.quant_ids if |
|||
location.inventory_quantity_auto_apply > 0} |
|||
nearby_expiry_warehouse = {product: sum( |
|||
data['count'] for lot, data in warehouse_dict.items() if |
|||
data['warehouse'] == product) for product in set( |
|||
data['warehouse'] for lot, data in warehouse_dict.items())} |
|||
return nearby_expiry_warehouse |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 576 B |
After Width: | Height: | Size: 733 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 673 B |
After Width: | Height: | Size: 878 B |
After Width: | Height: | Size: 653 B |
After Width: | Height: | Size: 905 B |
After Width: | Height: | Size: 839 B |
After Width: | Height: | Size: 427 B |
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 988 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 67 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 70 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 136 KiB |
After Width: | Height: | Size: 57 KiB |
After Width: | Height: | Size: 238 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 7.9 KiB |
@ -0,0 +1,626 @@ |
|||
<div class="container" |
|||
style="padding: 1rem !important; margin-bottom: 1rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12 d-flex justify-content-between" |
|||
style="border-bottom: 1px solid #d5d5d5;"> |
|||
<div class="my-3"> |
|||
<img src="./assets/icons/logo.png" |
|||
style="width: auto !important; height: 40px !important;"> |
|||
</div> |
|||
<div class="my-3 d-flex align-items-center"> |
|||
<div |
|||
style="background-color: #7C7BAD !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> |
|||
<i class="fa fa-check mr-1"></i>Community |
|||
</div> |
|||
<div |
|||
style="background-color: #875A7B !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> |
|||
<i class="fa fa-check mr-1"></i>Enterprise |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="container" style="padding: 0rem 1.5rem 4rem !important"> |
|||
<div class="row" style="height: 900px !important;"> |
|||
<div class="col-sm-12 col-md-12 col-lg-12" |
|||
style="padding: 4rem 1rem !important; background-color: #714B67 !important; height: 600px !important; border-radius: 20px !important;"> |
|||
<h1 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #FFFFFF !important; font-size: 3.5rem !important; text-align: center !important;"> |
|||
Product Expiry Dashboard</h1> |
|||
<p |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 300 !important; color: #FFFFFF !important; font-size: 1.4rem !important; text-align: center !important;"> |
|||
Product Expiry Dashboard Allow Users to View All the Product |
|||
Details those are About to Expire. |
|||
</p> |
|||
<img src="./assets/screenshots/hero.gif" class="img-responsive" |
|||
width="100%" height="auto"/> |
|||
</div> |
|||
</div> |
|||
<div class="row"> |
|||
<div class="col-md-12" |
|||
style="border-bottom: 1px solid #d5d5d5 !important; margin-bottom: 2rem !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-compass mr-2"></i>Explore this module |
|||
</h2> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a href="#overview" style="text-decoration: none !important;"> |
|||
<div class="row" |
|||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> |
|||
<div class="col-8"> |
|||
<h3 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> |
|||
Overview</h3> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> |
|||
Learn more about this module</p> |
|||
</div> |
|||
<div class="col-4 text-right d-flex justify-content-end align-items-center"> |
|||
<i class="fa fa-chevron-right" |
|||
style="color: #714B67 !important;"></i> |
|||
</div> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a href="#features" style="text-decoration: none !important;"> |
|||
<div class="row" |
|||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> |
|||
<div class="col-8"> |
|||
<h3 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> |
|||
Features</h3> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> |
|||
View features of this module</p> |
|||
</div> |
|||
<div class="col-4 text-right d-flex justify-content-end align-items-center"> |
|||
<i class="fa fa-chevron-right" |
|||
style="color: #714B67 !important;"></i> |
|||
</div> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<a href="#screenshots" style="text-decoration: none !important;"> |
|||
<div class="row" |
|||
style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> |
|||
<div class="col-8"> |
|||
<h3 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> |
|||
Screenshots</h3> |
|||
<p |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> |
|||
See key screenshots of this module</p> |
|||
</div> |
|||
<div class="col-4 text-right d-flex justify-content-end align-items-center"> |
|||
<i class="fa fa-chevron-right" |
|||
style="color: #714B67 !important;"></i> |
|||
</div> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="row" id="overview"> |
|||
<div class="col-md-12" |
|||
style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-pie-chart mr-2"></i>Overview |
|||
</h2> |
|||
</div> |
|||
<div class="col-mg-12 pl-3"> |
|||
<p style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;"> |
|||
Product Expiry Dashboard display counts of expired products, |
|||
nearly expiring products, graphical view of expired |
|||
products, nearly expiring products, their locations and |
|||
warehouses. This app allows take significant decisions quickly |
|||
by overseeing the products which will expire soon. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
<div class="row" id="features"> |
|||
<div class="col-md-12" |
|||
style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-star mr-2"></i>Features |
|||
</h2> |
|||
</div> |
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Shows all Products which are already Expired.</h4> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Shows all Products which will Expire Today.</h4> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Contains Tiles for displaying Count of Products which will |
|||
Expire soon based on their Expiry Date.</h4> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Graphical view of Expired Products</h4> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-6 pl-3 py-3 d-flex"> |
|||
<div> |
|||
<img src="assets/icons/check.png"> |
|||
</div> |
|||
<div> |
|||
<h4 style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Graphical view of Nearly Expiring Products based on their |
|||
Location and Warehouse</h4> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="row" id="screenshots"> |
|||
<div class="col-md-12" |
|||
style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> |
|||
<h2 |
|||
style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> |
|||
<i class="fa fa-image mr-2"></i>Screenshots |
|||
</h2> |
|||
</div> |
|||
<div class="col-lg-12 my-2"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Product Expiry Dashboard view</h4> |
|||
<img src="assets/screenshots/Screenshot1.png" |
|||
class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto"/> |
|||
</div> |
|||
<div class="col-lg-12 my-2"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Bottom part of Product Expiry Dashboard</h4> |
|||
<img src="assets/screenshots/Screenshot2.png" |
|||
class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto"/> |
|||
</div> |
|||
<div class="col-lg-12 my-2"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Count of Expiring Products if no Start or End Date selected</h4> |
|||
<img src="assets/screenshots/Screenshot3.png" |
|||
class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto"/> |
|||
</div> |
|||
<div class="col-lg-12 my-2"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Count of Products whose Expiry Date is between Start or End Date |
|||
selected</h4> |
|||
<img src="assets/screenshots/Screenshot5.png" |
|||
class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto"/> |
|||
</div> |
|||
<div class="col-lg-12 my-2"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
Click on any Tile to view corresponding Products</h4> |
|||
<img src="assets/screenshots/Screenshot6.png" |
|||
class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto"/> |
|||
</div> |
|||
<div class="col-lg-12 my-2"> |
|||
<h4 class="mt-2" |
|||
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> |
|||
List of Products corresponding to the Tile clicked</h4> |
|||
<img src="assets/screenshots/Screenshot7.png" |
|||
class="img-responsive img-thumbnail border" width="100%" |
|||
height="auto"/> |
|||
</div> |
|||
|
|||
</div> |
|||
<!-- SUGGESTED PRODUCTS --> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center" |
|||
style="text-align: center; padding: 2.5rem 1rem !important;"> |
|||
<h2 style="color: #212529 !important;">Suggested Products</h2> |
|||
<hr style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
<div id="demo1" class="row carousel slide" data-ride="carousel"> |
|||
<!-- The slideshow --> |
|||
<div class="carousel-inner"> |
|||
<div class="carousel-item active" style="min-height:0px"> |
|||
<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-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/export_stock.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/stock_intercompany_transfer/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/inter_company.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-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/brand_inventory.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
<div class="carousel-item" style="min-height:0px"> |
|||
<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_batch_report/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/serial_number.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/average_landed_cost/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/avg_lc.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/scrap_move_report/" |
|||
target="_blank"> |
|||
<div style="border-radius:10px"> |
|||
<img class="img img-responsive center-block" |
|||
style="border-top-left-radius:10px; border-top-right-radius:10px" |
|||
src="./assets/modules/scrap.png"> |
|||
</div> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Left and right controls --> |
|||
<a class="carousel-control-prev" href="#demo1" data-slide="prev" |
|||
style="left:-25px;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="right:-25px;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 SUGGESTED PRODUCTS --> |
|||
|
|||
<!-- OUR SERVICES --> |
|||
<section class="container" style="margin-top: 6rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Our Services</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
</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: #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> |
|||
</section> |
|||
<!-- END OF OUR SERVICES --> |
|||
<!-- OUR INDUSTRIES --> |
|||
<section class="container" style="margin-top: 6rem !important;"> |
|||
<div class="row"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Our Industries</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
</div> |
|||
<div class="col-lg-3"> |
|||
<div class="my-4 d-flex flex-column justify-content-center" |
|||
style="background-color: #f6f8f9 !important; border-radius: 10px; 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: 10px; 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: 10px; 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: 10px; 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: 10px; 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 & 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: 10px; 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: 10px; 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: 10px; 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> |
|||
</section> |
|||
<!--END OF OUR INDUSTRIES --> |
|||
<!-- FOOTER --> |
|||
<!-- Footer Section --> |
|||
<section class="container" style="margin: 5rem auto 2rem;"> |
|||
<div class="row" style="max-width:1540px;"> |
|||
<div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> |
|||
<h2 style="color: #212529 !important;">Need Help?</h2> |
|||
<hr |
|||
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> |
|||
</div> |
|||
</div> |
|||
<!-- Contact Cards --> |
|||
<div class="row d-flex justify-content-center align-items-center" |
|||
style="max-width:1540px; margin: 0 auto 2rem auto;"> |
|||
<div class="col-lg-12" |
|||
style="padding: 0rem 3rem 2rem; border-radius: 10px; margin-right: 3rem; "> |
|||
<div class="row mt-4"> |
|||
<div class="col-lg-6"> |
|||
<a href="mailto:odoo@cybrosys.com" target="_blank" |
|||
class="btn btn-block mb-2 deep_hover" |
|||
style="text-decoration: none; background-color: #4d4d4d; color: #FFF; border-radius: 4px;"><i |
|||
class="fa fa-envelope mr-2"></i>odoo@cybrosys.com</a> |
|||
</div> |
|||
<div class="col-lg-6"> |
|||
<a href="https://api.whatsapp.com/send?phone=918606827707" |
|||
target="_blank" |
|||
class="btn btn-block mb-2 deep_hover" |
|||
style="text-decoration: none; background-color: #25D366; color: #FFF; border-radius: 4px;"><i |
|||
class="fa fa-whatsapp mr-2"></i>+91 86068 27707</a> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
<!-- End of Contact Cards --> |
|||
</section> |
|||
<!-- Footer --> |
|||
<section class="oe_container" style="padding: 2rem 3rem 1rem;"> |
|||
<div class="row" |
|||
style="max-width:1540px; margin: 0 auto; margin-right: 3rem; "> |
|||
<!-- Logo --> |
|||
<div class="col-lg-12 d-flex justify-content-center align-items-center" |
|||
style="margin-top: 3rem;"> |
|||
<img src="https://www.cybrosys.com/images/logo.png" |
|||
width="200px" height="auto"/> |
|||
</div> |
|||
<!-- End of Logo --> |
|||
<div class="col-lg-12"> |
|||
<hr |
|||
style="margin-top: 3rem;background: linear-gradient(90deg, rgba(2,0,36,0) 0%, rgba(229,229,229,1) 33%, rgba(229,229,229,1) 58%, rgba(0,212,255,0) 100%); height: 2px; border-style: none;"> |
|||
<!-- End of Footer Section --> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<!-- END OF FOOTER --> |
|||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" |
|||
integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" |
|||
crossorigin="anonymous"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/js/bootstrap.bundle.min.js" |
|||
integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" |
|||
crossorigin="anonymous"></script> |
@ -0,0 +1,86 @@ |
|||
.order-card { |
|||
color: #fff; |
|||
} |
|||
|
|||
.bg-c-red { |
|||
background: linear-gradient(45deg, #e60000, #ff8080); |
|||
} |
|||
|
|||
.bg-c-lavender { |
|||
background: linear-gradient(45deg, #d279d2, #df9fdf); |
|||
} |
|||
|
|||
.bg-c-blue { |
|||
background: linear-gradient(45deg,#4099ff,#73b4ff); |
|||
} |
|||
|
|||
.bg-c-green { |
|||
background: linear-gradient(45deg,#2ed8b6,#59e0c5); |
|||
} |
|||
|
|||
.bg-c-yellow { |
|||
background: linear-gradient(45deg,#FFB64D,#ffcb80); |
|||
} |
|||
|
|||
.bg-c-pink { |
|||
background: linear-gradient(45deg,#FF5370,#ff869a); |
|||
} |
|||
|
|||
.card { |
|||
border-radius: 5px; |
|||
-webkit-box-shadow: 0 1px 2.94px 0.06px rgba(4,26,55,0.16); |
|||
box-shadow: 0 1px 2.94px 0.06px rgba(4,26,55,0.16); |
|||
border: none; |
|||
margin-bottom: 30px; |
|||
-webkit-transition: all 0.3s ease-in-out; |
|||
transition: all 0.3s ease-in-out; |
|||
} |
|||
|
|||
.card{ |
|||
width:110% |
|||
} |
|||
|
|||
.card .card-block { |
|||
padding: 25px; |
|||
} |
|||
|
|||
.order-card i { |
|||
font-size: 26px; |
|||
} |
|||
|
|||
.f-left { |
|||
float: left; |
|||
} |
|||
|
|||
.f-right { |
|||
float: right; |
|||
} |
|||
|
|||
.card-block:hover{ |
|||
box-shadow: 5px 5px 10px #ccc; |
|||
} |
|||
|
|||
.expiry_dashboard_row{ |
|||
padding-left: 250px; |
|||
} |
|||
|
|||
.dashboard-heading{ |
|||
min-height: 140px; |
|||
padding: 20px; |
|||
text-align: center; |
|||
background: #376270; |
|||
} |
|||
|
|||
.banner-heading { |
|||
color: #ffffff; |
|||
font-size: 45px; |
|||
margin: 0; |
|||
} |
|||
|
|||
.product_expired_heading{ |
|||
background: aliceblue; |
|||
width: 236px; |
|||
float: left; |
|||
border-radius: 16px; |
|||
height: 102px; |
|||
} |
@ -0,0 +1,396 @@ |
|||
odoo.define('odoo_product_expiry_dashboard.product_expiry', function (require) { |
|||
'use strict'; |
|||
var AbstractAction = require('web.AbstractAction'); |
|||
var core = require('web.core'); |
|||
var rpc = require('web.rpc'); |
|||
var ProductExpiryDashboard = AbstractAction.extend({ |
|||
template: 'ProductExpiryDashboard', |
|||
events: { |
|||
//Events
|
|||
'change #start_date': 'filter_date', |
|||
'change #end_date': 'filter_date', |
|||
'click .expired': 'expired_click', |
|||
'click .today': 'today_click', |
|||
'click .one-day': 'one_day_click', |
|||
'click .seven-day': 'seven_day_click', |
|||
'click .thirty-day': 'thirty_day_click', |
|||
'click .one-twenty-day': 'one_twenty_day_click' |
|||
}, |
|||
start: function () { |
|||
//Call functions to fetch the data to display on the dashboard
|
|||
this.fetch_products_expiry() |
|||
this.render_expired_products_graph() |
|||
this.expiry_by_category() |
|||
this.near_exp_category() |
|||
this.near_exp_products() |
|||
this.product_expired_today() |
|||
this.get_expire_product_location() |
|||
this.get_expire_product_warehouse() |
|||
}, |
|||
filter_date(ev) { |
|||
//Works if start date or end date is changed. Fetch the data according to
|
|||
//the date chosen
|
|||
var start_date = this.$("#start_date").val() |
|||
var end_date = this.$("#end_date").val() |
|||
this.fetch_products_expiry(start_date, end_date) |
|||
this.render_expired_products_graph(start_date, end_date) |
|||
this.expiry_by_category(start_date, end_date) |
|||
}, |
|||
fetch_products_expiry(start_date, end_date) { |
|||
//Fetch the data to be displayed on the tiles of the dashboard.
|
|||
this.$('#expired').remove() |
|||
this.$("#today").remove() |
|||
this.$("#one_day").remove() |
|||
this.$("#seven_day").remove() |
|||
this.$("#thirty_day").remove() |
|||
this.$("#one_twenty_day").remove() |
|||
var date_dict = { 'start_date': start_date, 'end_date': end_date } |
|||
rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_product_expiry', |
|||
args: [date_dict] |
|||
}).then(function (result) { |
|||
$(".expired").append('<center>' |
|||
+ '<span style="font-size: xxx-large;" id="expired">' + result['expired'] + '</span>' |
|||
+ '</center>') |
|||
$(".today").append('<center>' |
|||
+ '<span style="font-size: xxx-large;" id="today">' + result['today'] + '</span>' |
|||
+ '</center>') |
|||
$(".one-day").append('<center>' |
|||
+ '<span style="font-size: xxx-large;" id="one_day">' + result['one_day'] + '</span>' |
|||
+ '</center>') |
|||
$(".seven-day").append('<center>' |
|||
+ '<span style="font-size: xxx-large;" id="seven_day">' + result['seven_day'] + '</span>' |
|||
+ '</center>') |
|||
$(".thirty-day").append('<center>' |
|||
+ '<span style="font-size: xxx-large;" id="thirty_day">' + result['thirty_day'] + '</span>' |
|||
+ '</center>') |
|||
$(".one-twenty-day").append('<center>' |
|||
+ '<span style="font-size: xxx-large;" id="one_twenty_day">' + result['one_twenty_day'] + '</span>' |
|||
+ '</center>') |
|||
}) |
|||
}, |
|||
product_expired_today() { |
|||
//Function for fetching all products expiring today
|
|||
rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_product_expired_today' |
|||
}).then(function (result) { |
|||
$('.product_expired_heading').append('<p style="font-size: 38px;margin-top: -10px;">' + result + '</p>') |
|||
}) |
|||
}, |
|||
render_expired_products_graph(start_date, end_date) { |
|||
//Function for rendering the graph of expired products
|
|||
let chartStatus = Chart.getChart('expired_product_count'); |
|||
if (chartStatus != undefined) { |
|||
chartStatus.destroy(); |
|||
} |
|||
var product_array = [] |
|||
var expired_qty_array = [] |
|||
var date_dict = { 'start_date': start_date, 'end_date': end_date } |
|||
let data = rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_expired_product', |
|||
args: [date_dict] |
|||
}).then(function (result) { |
|||
$.each(result, function (index, name) { |
|||
product_array.push(index) |
|||
expired_qty_array.push(name) |
|||
}) |
|||
if (product_array.length != 0) { |
|||
const ctx = $('#expired_product_count') |
|||
new Chart(ctx, { |
|||
type: 'pie', |
|||
data: { |
|||
labels: product_array, |
|||
datasets: [{ |
|||
label: 'Quantity', |
|||
data: expired_qty_array, |
|||
borderWidth: 1, |
|||
backgroundColor: ["#e60000", "#d279d2", "#4099ff","#2ed8b6", |
|||
"#FFB64D, #ffcb80"], |
|||
}] |
|||
}, |
|||
}); |
|||
$(".chart_heading").show() |
|||
} |
|||
else { |
|||
$(".chart_heading").hide() |
|||
} |
|||
}) |
|||
}, |
|||
expiry_by_category(start_date, end_date) { |
|||
//Function for rendering the graph of product's expiry based on their
|
|||
//category
|
|||
let chartStatus = Chart.getChart('expired_product_category_count'); |
|||
if (chartStatus != undefined) { |
|||
chartStatus.destroy(); |
|||
} |
|||
var product_category_array = [] |
|||
var expired_qty_array = [] |
|||
var date_dict = { 'start_date': start_date, 'end_date': end_date } |
|||
rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_product_expiry_by_category', |
|||
args: [date_dict] |
|||
}).then(function (result) { |
|||
$.each(result, function (index, name) { |
|||
product_category_array.push(index) |
|||
expired_qty_array.push(name) |
|||
}) |
|||
if (product_category_array.length != 0) { |
|||
const ctx = $('#expired_product_category_count') |
|||
new Chart(ctx, { |
|||
type: 'bar', |
|||
data: { |
|||
labels: product_category_array, |
|||
datasets: [{ |
|||
label: 'Quantity', |
|||
data: expired_qty_array, |
|||
borderWidth: 1, |
|||
backgroundColor: ["#4099ff", "#e60000", "#d279d2", "#2ed8b6", |
|||
"#FFB64D, #ffcb80"], |
|||
}] |
|||
}, |
|||
}); |
|||
} |
|||
else { |
|||
$(".chart_heading").hide() |
|||
} |
|||
}) |
|||
}, |
|||
near_exp_products() { |
|||
//Function for rendering graph of products expiring in 7 days
|
|||
var product_array = [] |
|||
var nearby_expire_qty = [] |
|||
rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_near_expiry_product', |
|||
}).then(function (result) { |
|||
$.each(result, function (index, name) { |
|||
product_array.push(index) |
|||
nearby_expire_qty.push(name) |
|||
}) |
|||
if (product_array.length != 0) { |
|||
const ctx = $('#nearby_expire_product') |
|||
new Chart(ctx, { |
|||
type: 'doughnut', |
|||
data: { |
|||
labels: product_array, |
|||
datasets: [{ |
|||
label: 'Quantity', |
|||
data: nearby_expire_qty, |
|||
borderWidth: 1, |
|||
backgroundColor: ["#ffcb80", "#4099ff", "#e60000", "#d279d2", |
|||
"#2ed8b6", "#FFB64D"], |
|||
}] |
|||
}, |
|||
}); |
|||
} |
|||
}) |
|||
}, |
|||
near_exp_category() { |
|||
//Function for rendering graph of products expiring in 7 days based on
|
|||
//their category
|
|||
var product_category_array = [] |
|||
var nearby_expire_qty = [] |
|||
rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_near_expiry_category', |
|||
}).then(function (result) { |
|||
$.each(result, function (index, name) { |
|||
product_category_array.push(index) |
|||
nearby_expire_qty.push(name) |
|||
}) |
|||
const ctx = $('#nearby_expire_catg') |
|||
new Chart(ctx, { |
|||
type: 'line', |
|||
data: { |
|||
labels: product_category_array, |
|||
datasets: [{ |
|||
label: 'Quantity', |
|||
data: nearby_expire_qty, |
|||
backgroundColor: ["#FFB64D", "#4099ff", "#e60000", "#d279d2", |
|||
"#2ed8b6", "#ffcb80"], |
|||
borderWidth: 1 |
|||
}] |
|||
}, |
|||
}) |
|||
}) |
|||
}, |
|||
get_expire_product_location() { |
|||
//Function for rendering graph of expiring products based on
|
|||
//their location
|
|||
var product_location_array = [] |
|||
var nearby_expire_qty = [] |
|||
rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_expire_product_location', |
|||
}).then(function (result) { |
|||
$.each(result, function (index, name) { |
|||
product_location_array.push(index) |
|||
nearby_expire_qty.push(name) |
|||
}) |
|||
const ctx = $('#nearby_expire_location') |
|||
new Chart(ctx, { |
|||
type: 'pie', |
|||
data: { |
|||
labels: product_location_array, |
|||
datasets: [{ |
|||
label: 'Quantity', |
|||
data: nearby_expire_qty, |
|||
backgroundColor: ["#ffcb80", "#FFB64D", "#4099ff", "#e60000", |
|||
"#d279d2", "#2ed8b6"], |
|||
borderWidth: 1 |
|||
}] |
|||
}, |
|||
}) |
|||
}) |
|||
}, |
|||
get_expire_product_warehouse() { |
|||
//Function for rendering graph of expiring products based on
|
|||
//their warehouse
|
|||
var product_warehouse_array = [] |
|||
var nearby_expire_qty = [] |
|||
rpc.query({ |
|||
model: 'stock.production.lot', |
|||
method: 'get_expire_product_warehouse', |
|||
}).then(function (result) { |
|||
$.each(result, function (index, name) { |
|||
product_warehouse_array.push(index) |
|||
nearby_expire_qty.push(name) |
|||
}) |
|||
const ctx = $('#nearby_expire_warehouse') |
|||
new Chart(ctx, { |
|||
type: 'doughnut', |
|||
data: { |
|||
labels: product_warehouse_array, |
|||
datasets: [{ |
|||
label: 'Quantity', |
|||
data: nearby_expire_qty, |
|||
borderWidth: 1, |
|||
backgroundColor: ["#4099ff", "#e60000", "#ffcb80", "#FFB64D", |
|||
"#d279d2", "#2ed8b6"], |
|||
}] |
|||
}, |
|||
}) |
|||
}) |
|||
}, |
|||
expired_click(){ |
|||
//Click event of expired products tile
|
|||
this.click_event(-1,"Expired") |
|||
}, |
|||
today_click() { |
|||
//Click event of expire today tile
|
|||
this.click_event(0,"Expire Today"); |
|||
}, |
|||
one_day_click() { |
|||
//Click event of expire in one day tile
|
|||
this.click_event(1,"Expiry in One Day"); |
|||
}, |
|||
seven_day_click() { |
|||
//Click event of expire in one 7 days tile
|
|||
this.click_event(7, "Expiry in Seven Days"); |
|||
}, |
|||
thirty_day_click() { |
|||
//Click event of expire in 30 days tile
|
|||
this.click_event(30, "Expiry in Thirty Days"); |
|||
}, |
|||
one_twenty_day_click() { |
|||
//Click event of expire in 120 day tile
|
|||
this.click_event(120, "Expiry in One Twenty Days"); |
|||
}, |
|||
click_event(days,name){ |
|||
//Function for displaying corresponding products while clicking on a tile
|
|||
var today = new Date(); |
|||
var start_date = this.$("#start_date").val() |
|||
var end_date = this.$("#end_date").val() |
|||
var Domain = [] |
|||
if(start_date != ""){ |
|||
Domain.push(['expiration_date', '>=', start_date]) |
|||
} |
|||
if(end_date != ""){ |
|||
Domain.push(['expiration_date', '<=', end_date]) |
|||
} |
|||
today.setDate(today.getDate()) |
|||
today.setHours(0, 0, 0, 0); |
|||
var dateString = today.toLocaleDateString(); |
|||
var timeString = today.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }); |
|||
var formattedDateTime = dateString + ' ' + timeString; |
|||
if(days==-1){ |
|||
Domain.push(['expiration_date', '<', formattedDateTime]) |
|||
} |
|||
else if(days==0){ |
|||
Domain.push(['expiration_date', '=', formattedDateTime]) |
|||
} |
|||
else if(days==1){ |
|||
// Calculate the end date for the next-day range (one days from
|
|||
// the today).
|
|||
today.setDate(today.getDate() + 1); |
|||
today.setHours(0, 0, 0, 0); |
|||
// Format the date and time as a formatted date-time string.
|
|||
var dateString = today.toLocaleDateString(); |
|||
var timeString = today.toLocaleTimeString([], { hour: '2-digit', |
|||
minute: '2-digit', second: '2-digit' }); |
|||
var formattedDateTime = dateString + ' ' + timeString; |
|||
Domain.push(['expiration_date', '=', formattedDateTime]) |
|||
} |
|||
else if(days==7){ |
|||
// Calculate the end date for the seven-day range (6th days from
|
|||
// today).
|
|||
today.setDate(today.getDate() + 1); |
|||
today.setHours(0, 0, 0, 0); |
|||
var dateString = today.toLocaleDateString(); |
|||
var timeString = today.toLocaleTimeString([], { hour: '2-digit', minute: |
|||
'2-digit', second: '2-digit' }); |
|||
var tomorrow_date = dateString + ' ' + timeString; |
|||
today.setDate(today.getDate() + 6); |
|||
var dateString = today.toLocaleDateString(); |
|||
var seven_day_date = dateString + ' ' + timeString; |
|||
Domain.push(['expiration_date', '<=', seven_day_date], |
|||
['expiration_date', '>', tomorrow_date]) |
|||
} |
|||
else if(days==30){ |
|||
today.setDate(today.getDate() + 8); |
|||
today.setHours(0, 0, 0, 0); |
|||
var dateString = today.toLocaleDateString(); |
|||
var timeString = today.toLocaleTimeString([], { hour: '2-digit', minute: |
|||
'2-digit', second: '2-digit' }); |
|||
var seventh_day = dateString + ' ' + timeString; |
|||
// Calculate the end date for the thirty-day range (thirty days from
|
|||
// the eighth day).
|
|||
today.setDate(today.getDate() + 22); |
|||
dateString = today.toLocaleDateString(); |
|||
var thirty_day_date = dateString + ' ' + timeString; |
|||
Domain.push(['expiration_date', '<=', thirty_day_date], |
|||
['expiration_date', '>', seventh_day]) |
|||
} |
|||
else if(days==120){ |
|||
today.setDate(today.getDate() + 31); |
|||
today.setHours(0, 0, 0, 0); |
|||
var dateString = today.toLocaleDateString(); |
|||
var timeString = today.toLocaleTimeString([], { hour: '2-digit', minute: |
|||
'2-digit', second: '2-digit' }); |
|||
var thirtieth_day = dateString + ' ' + timeString; |
|||
// Calculate the end date for the one hundred twenty-day range
|
|||
// (eighty-nine days from the thirty-first day).
|
|||
today.setDate(today.getDate() + 89); |
|||
dateString = today.toLocaleDateString(); |
|||
var day_one_twenty = dateString + ' ' + timeString; |
|||
Domain.push(['expiration_date', '<=', day_one_twenty], |
|||
['expiration_date', '>', thirtieth_day]) |
|||
} |
|||
this.do_action({ |
|||
name: name, |
|||
type: 'ir.actions.act_window', |
|||
view_mode: 'list', |
|||
res_model: 'stock.production.lot', |
|||
views: [[false, 'list'], [false, 'form']], |
|||
domain: Domain, |
|||
target: 'current', |
|||
}) |
|||
}, |
|||
}); |
|||
core.action_registry.add("product_expiry", ProductExpiryDashboard); |
|||
return ProductExpiryDashboard; |
|||
}); |
@ -0,0 +1,216 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<template id="expiry_dashboard_template"> |
|||
<t t-name="ProductExpiryDashboard"> |
|||
<div class="o_action_manager" |
|||
style="height:100%; overflow-y: scroll; overflow-x: hidden;"> |
|||
<section class="dashboard_main_section" id="main_section_manager"> |
|||
<!-- Dashboard Header--> |
|||
<div class="dashboard-heading shadow-sm"> |
|||
<center> |
|||
<div style="width: 544px"> |
|||
<h1 class="banner-heading">Product Expiry Dashboard |
|||
</h1> |
|||
</div> |
|||
</center> |
|||
<div class="col-4 col-sm-4 col-md-4" |
|||
style="float: right;color: white;"> |
|||
<form class="form-group"> |
|||
<span>Start Date:</span> |
|||
<input type="date" id="start_date" |
|||
name="start_date"/> |
|||
<span>End Date:</span> |
|||
<input type="date" id="end_date" name="end_date"/> |
|||
</form> |
|||
</div> |
|||
</div> |
|||
<br/> |
|||
<div class="card-group"> |
|||
<!-- Dashboard Tiles--> |
|||
<div class="card"> |
|||
<div class="card-body"> |
|||
<div class="container"> |
|||
<div class="row"> |
|||
<div class="col-md-2 col-xl-6" |
|||
style="float: left"> |
|||
<div class="card bg-c-red order-card"> |
|||
<div class="card-block expired"> |
|||
<h2 style="color:white; |
|||
text-align:center;"> |
|||
Expired |
|||
</h2> |
|||
<hr/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-2 col-xl-6" |
|||
style="float: right"> |
|||
<div class="card bg-c-lavender |
|||
order-card"> |
|||
<div class="card-block today"> |
|||
<h2 style="color:white; |
|||
text-align:center;"> |
|||
Expire Today |
|||
</h2> |
|||
<hr/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-2 col-xl-6" |
|||
style="float: left"> |
|||
<div class="card bg-c-blue order-card"> |
|||
<div class="card-block one-day"> |
|||
<h2 style="color:white; |
|||
text-align:center;"> |
|||
Expire |
|||
in 1 Day |
|||
</h2> |
|||
<hr/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-2 col-xl-6" |
|||
style="float: right"> |
|||
<div class="card bg-c-green order-card"> |
|||
<div class="card-block seven-day"> |
|||
<h2 style="color:white; |
|||
text-align:center;"> |
|||
Expire |
|||
in 7 Days |
|||
</h2> |
|||
<hr/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-2 col-xl-6" |
|||
style="float: left"> |
|||
<div class="card bg-c-yellow |
|||
order-card"> |
|||
<div class="card-block thirty-day"> |
|||
<h2 style="color:white; |
|||
text-align:center;"> |
|||
Expire |
|||
in 30 Days |
|||
</h2> |
|||
<hr/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="col-md-2 col-xl-6" |
|||
style="float: right"> |
|||
<div class="card bg-c-pink order-card"> |
|||
<div class="card-block |
|||
one-twenty-day"> |
|||
<h2 style="color:white; |
|||
text-align:center;"> |
|||
Expire |
|||
in 120 Days |
|||
</h2> |
|||
<hr/> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="card"> |
|||
<!-- Graph of Expired Products--> |
|||
<div class="card-body"> |
|||
<center> |
|||
<h2 class="card-title">Expired Products</h2> |
|||
<div style="max-width: 250px; |
|||
margin-right: 120px;"> |
|||
<canvas id="expired_product_count"/> |
|||
</div> |
|||
</center> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<!-- Graph of Expired Products by Category--> |
|||
<div class="card-body"> |
|||
<center> |
|||
<h2 class="card-title">Expired Products by |
|||
Category |
|||
</h2> |
|||
<div style="max-width: 500px; |
|||
margin-right: 120px;"> |
|||
<canvas |
|||
id="expired_product_category_count"/> |
|||
</div> |
|||
</center> |
|||
</div> |
|||
</div> |
|||
<div class="card"> |
|||
<!-- Graph of Products Expiring in 7 Days--> |
|||
<div class="card-body"> |
|||
<center> |
|||
<h2 class="chart_heading"> |
|||
Products Expiring in 7 Days |
|||
</h2> |
|||
<div style="max-width: 250px; |
|||
margin-right: 120px;"> |
|||
<canvas id="nearby_expire_product"/> |
|||
</div> |
|||
</center> |
|||
</div> |
|||
<br/> |
|||
<br/> |
|||
<!-- Graph of Category of Products expiring of in |
|||
7 Days--> |
|||
<div class="card-body"> |
|||
<center> |
|||
<div> |
|||
<center> |
|||
<h2>Category Products Expiring of in 7 |
|||
Days |
|||
</h2> |
|||
</center> |
|||
<div style="max-width: 500px; |
|||
margin-right: 120px;"> |
|||
<canvas id="nearby_expire_catg"/> |
|||
</div> |
|||
</div> |
|||
</center> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="row"> |
|||
<!-- Graph of location of Products expiring of in 7 Days--> |
|||
<div class="col-sm-6"> |
|||
<div class="card"> |
|||
<div class="card-body"> |
|||
<center> |
|||
<h2 class="chart_heading">Location of |
|||
Products Expiring in 7 Days |
|||
</h2> |
|||
<div style="max-width: 500px; |
|||
margin-right: 120px;"> |
|||
<canvas id="nearby_expire_location"/> |
|||
</div> |
|||
</center> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<!-- Graph of warehouse of Products expiring of in 7 Days--> |
|||
<div class="col-sm-6" > |
|||
<div class="card"> |
|||
<div class="card-body"> |
|||
<center> |
|||
<h2 class="chart_heading">Warehouse of |
|||
Products |
|||
Expiring in 7 Days |
|||
</h2> |
|||
<div style="max-width: 500px; |
|||
margin-right: 120px;"> |
|||
<canvas id="nearby_expire_warehouse"/> |
|||
</div> |
|||
</center> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
</div> |
|||
</t> |
|||
</template> |
@ -0,0 +1,16 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<!-- Product Expiry Dashboard action--> |
|||
<record id="expiry_dashboard_action" model="ir.actions.client"> |
|||
<field name="name">Expiry Dashboard</field> |
|||
<field name="tag">product_expiry</field> |
|||
<field name="target">current</field> |
|||
</record> |
|||
<!-- Product Expiry Dashboard menu--> |
|||
<menuitem |
|||
id="expiry_dashboard_menu" |
|||
name="Product Expiry Dashboard" |
|||
action="expiry_dashboard_action" |
|||
parent="stock.menu_stock_root" |
|||
sequence="99"/> |
|||
</odoo> |