@ -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> |