Browse Source

Mar 27 [UPDT] : Updated 'pos_traceability_validation'

pull/278/merge
AjmalCybro 1 year ago
parent
commit
d7b78df875
  1. 4
      pos_traceability_validation/__manifest__.py
  2. 5
      pos_traceability_validation/doc/RELEASE_NOTES.md
  3. 2
      pos_traceability_validation/models/__init__.py
  4. 42
      pos_traceability_validation/models/serial_no_validation.py
  5. 72
      pos_traceability_validation/models/stock_lot.py
  6. BIN
      pos_traceability_validation/static/description/assets/screenshots/1.png
  7. BIN
      pos_traceability_validation/static/description/assets/screenshots/10.png
  8. BIN
      pos_traceability_validation/static/description/assets/screenshots/11.png
  9. BIN
      pos_traceability_validation/static/description/assets/screenshots/2.png
  10. BIN
      pos_traceability_validation/static/description/assets/screenshots/3.png
  11. BIN
      pos_traceability_validation/static/description/assets/screenshots/4.png
  12. BIN
      pos_traceability_validation/static/description/assets/screenshots/5.png
  13. BIN
      pos_traceability_validation/static/description/assets/screenshots/6.png
  14. BIN
      pos_traceability_validation/static/description/assets/screenshots/7.png
  15. BIN
      pos_traceability_validation/static/description/assets/screenshots/8.png
  16. BIN
      pos_traceability_validation/static/description/assets/screenshots/9.png
  17. BIN
      pos_traceability_validation/static/description/assets/screenshots/hero.gif
  18. 576
      pos_traceability_validation/static/description/index.html
  19. 77
      pos_traceability_validation/static/src/js/EditListPopup.js
  20. 37
      pos_traceability_validation/static/src/js/OrderWidget.js
  21. 90
      pos_traceability_validation/static/src/js/ProductScreen.js
  22. 69
      pos_traceability_validation/static/src/js/pos_models.js

4
pos_traceability_validation/__manifest__.py

@ -35,7 +35,9 @@
'depends': ['point_of_sale', 'stock'],
'assets': {
'web.assets_backend': [
'pos_traceability_validation/static/src/js/pos_models.js',
'pos_traceability_validation/static/src/js/EditListPopup.js',
'pos_traceability_validation/static/src/js/OrderWidget.js',
'pos_traceability_validation/static/src/js/ProductScreen.js',
],
},
'images': ['static/description/banner.jpg'],

5
pos_traceability_validation/doc/RELEASE_NOTES.md

@ -4,3 +4,8 @@
#### Version 16.0.1.0.0
#### ADD
- Initial Commit for POS Serial Number Validator
#### 11.02.2024
#### Version 16.0.1.1.0
#### REF
- Refactor the module and update the index

2
pos_traceability_validation/models/__init__.py

@ -18,4 +18,4 @@
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import serial_no_validation
from . import stock_lot

42
pos_traceability_validation/models/serial_no_validation.py

@ -1,42 +0,0 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
# Author: Jumana Jabin MP(<http://www.cybrosys.com>)
# you can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import api, models
class SerialNoValidation(models.Model):
"""Serial Number Validation Model.This model is used for serial number
validation in Odoo."""
_name = 'serial_no.validation'
@api.model
def validate_lots(self, lots):
""" This method validates a list of lots."""
processed = []
LotObj = self.env['stock.lot']
for lot in lots:
lot_id = LotObj.search([('name', '=', lot)], limit=1)
if lot_id.product_qty > 0 and lot not in processed:
processed.append(lot)
continue
if lot in processed:
return ['duplicate', lot]
return ['no_stock', lot]
return True

72
pos_traceability_validation/models/stock_lot.py

@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
# Author: Jumana Jabin MP(<http://www.cybrosys.com>)
# you can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import api, models
class StockLot(models.Model):
"""
This class is inherited for adding a new function to validate the lots and
serial numbers.
Methods:
validate_lots(lots):
check and validate the lots and serial numbers for the product
based on the stock location.
"""
_inherit = 'stock.lot'
@api.model
def validate_lots(self, lots, product_id, picking_type_id):
""" To check
- the invalid lots/ serial numbers
- duplicate serial numbers
- insufficient stock for the lots or serial numbers.
All these cases are checked based on the product and the stock location
set for the active PoS.
Args:
lots (list[str,..., str]): the lots for validation.
product_id (int): id of the selected product.
picking_type_id (int): id of the operation type added for the PoS.
Returns:
list[str, str] or Bool: True if the lot is valid, else the list of
the string that indicates the exception: 'invalid', 'duplicate' or
'no_stock' with the lot/ serial number.
"""
processed = []
if not product_id:
return ['invalid', 'product']
for lot in lots:
stock_lots = self.sudo().search([
('name', '=', lot), ('product_id', '=', product_id)])
if not stock_lots:
return ['invalid', lot]
picking_type = self.env['stock.picking.type'].sudo().browse(
picking_type_id)
stock_quant = self.env['stock.quant'].sudo().search(
[('location_id', '=', picking_type.default_location_src_id.id),
('lot_id', 'in', stock_lots.ids)])
if (stock_quant and stock_quant.available_quantity > 0
and lot not in processed):
processed.append(lot)
else:
if lot in processed:
return ['duplicate', lot]
return ['no_stock', lot]
return True

BIN
pos_traceability_validation/static/description/assets/screenshots/1.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 134 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/11.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/2.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 129 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/3.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 143 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/4.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

After

Width:  |  Height:  |  Size: 137 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/5.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 KiB

After

Width:  |  Height:  |  Size: 68 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/6.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 249 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/7.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 290 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/8.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

After

Width:  |  Height:  |  Size: 281 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

BIN
pos_traceability_validation/static/description/assets/screenshots/hero.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 475 KiB

576
pos_traceability_validation/static/description/index.html

@ -1,280 +1,266 @@
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;">
<div class="container" style="background-color: #714B67; min-height: 600px; width: 100%; padding: 15px; position: relative;">
<!-- TITLE BAR -->
<div class="d-flex align-items-center justify-content-between"
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
<img src="assets/misc/cybrosys-logo.png" width="42" height="42"
style="width: 42px; height: 42px;"/>
<div>
<div
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<div class="row"
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
<img src="./assets/misc/cybrosys-logo.png"
style="width: 74px; height: 42px;"/>
<div class="my-3">
<div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block;
padding: 3px 10px; border-radius: 50px; position: relative; left: 838px; top: -27px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Community
</div>
<div
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<div style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block;
padding: 3px 10px; border-radius: 50px; position: relative; left: 849px; top: -27px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Enterprise
</div>
<div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
<div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block;
padding: 3px 10px; border-radius: 50px; position: relative; left: 859px; top: -27px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Odoo.sh
</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: 3rem !important; text-align: center !important;">
POS Serial Number Validator</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;">
Validate Serial Number of a Product by Checking
Availability in Stock </p>
<img src="./assets/screenshots/hero.gif" class="img-responsive"
width="100%" height="auto"/>
</div>
</div>
</div>
<!-- END OF TITLE BAR -->
<!-- APP HERO -->
<div class="app-container">
<h1 CLASS="app-name" style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
POS Serial Number Validator</h1>
<p class="app-info" style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">
Validate Serial Number of a Product by Checking Availability in Stock </p>
<!-- END OF APP HERO -->
<img src="./assets/screenshots/hero.gif"
style="width: 75%; height: auto; position: absolute; margin-left: auto; margin-right: auto; left: 12%; right: auto;"/>
</div>
<!-- END OF APP HERO -->
</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>
<!-- NAVIGATION SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/compass.png"/>
</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>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px;">
Explore This Module</h2>
</div>
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
<div class="col-sm-12 col-md-6 my-3">
<a href="#overview">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
<span
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn more about this module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</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 class="col-sm-12 col-md-6 my-3">
<a href="#features">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">
View features of this module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</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 class="col-sm-12 col-md-6 my-3">
<a href="#screenshots">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
<span
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View screenshots for this module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
</div>
<!-- END OF NAVIGATION SECTION -->
<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;">
This module validates the serial number of a product in
the Point of Sale (POS) by checking its availability in
stock. If the
serial number is not in stock or is a duplicate entry, it
displays an
error message.
</p>
<!-- OVERVIEW SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pie-chart.png"/>
</div>
<h2 class="mt-2 my-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px;">
Overview
</h2>
</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 class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 py-4">
<p style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;">
This module validates the serial number of a product in the Point of Sale (POS) by checking its availability in
stock. If the serial number is not in stock or is a duplicate entry, it displays an error message.
</p>
</div>
</div>
<!-- END OF OVERVIEW SECTION -->
<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;">
Community &amp; Enterprise Support</h4>
<p
style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;">
<!-- FEATURES SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/features.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px;">
Features
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 col-md-6">
<div class="d-flex align-items-center"
style="margin-top: 40px; margin-bottom: 40px">
<img src="assets/icons/check.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold; position:relative; top:-19px;">Community &amp; Enterprise Support</span>
<p style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;
position:absolute; left: 69px; top: 1589px;">
Available in Odoo 16.0 Community and Enterprise.</p>
</div>
</div>
<div class="col-md-6 pl-3 py-3 d-flex">
<div>
<img src="assets/icons/check.png">
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/icons/check.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold; position: relative; top: -18px;">Validates given Serial Number is Available in Stock</span>
</div>
<div>
<h4
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;">
Validates given Serial Number is Available in
Stock</h4>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/icons/check.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold; position: relative; top: -18px;">Prevents Duplicated Entry for more than one Quantity</span>
</div>
</div>
</div>
<!-- END OF FEATURES SECTION -->
<div class="col-md-6 pl-3 py-3 d-flex">
<div>
<img src="assets/icons/check.png">
<!-- SCREENSHOTS SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"
id="screenshots">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pictures.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px;">
Screenshots
</h2>
</div>
<div class="row">
<div class="col-sm-12">
<div class="mt-3" style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Enable Lots & Serial Numbers.</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
The user with Administration Settings access and Administrator access to inventory can enable the setting.</p>
<img src="assets/screenshots/1.png" class="img-thumbnail">
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Add the users to the group Manage Lots / Serial Numbers to use lots & serial numbers.</p>
<img src="assets/screenshots/2.png" class="img-thumbnail">
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Navigate to Inventory / Configuration / Settings and enable the setting Lots & Serial Numbers from the Traceability section.</p>
<img src="assets/screenshots/3.png" class="img-thumbnail">
</div>
<div class="mt-3" style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Enable Tracking for the Products</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
The traceability of the products are managed in the product form view, under the Inventory tab. Check if the Tracking option is enabled and select the By Unique Serial Number Or By Lots option.</p>
<img src="assets/screenshots/4.png" class="img-thumbnail">
</div>
<div class="mt-3" style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Add Lots or Serial Numbers for Products in Stock</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
The traceability of the products are managed in the product form view, under the Inventory tab. Check if the Tracking option is enabled and select the By Unique Serial Number Or By Lots option.</p>
<img src="assets/screenshots/5.png" class="img-thumbnail">
</div>
<div class="mt-3" style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
The Pop-up will be Displayed to Add the Lot/ Serial Number on Selecting the Products with Traceability.</h3>
<img src="assets/screenshots/6.png" class="img-thumbnail">
</div>
<div>
<h4
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;">
Prevents Duplicated Entry for more than one
Quantity</h4>
<div class="mt-3" style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Warning for Invalid Lot/ Serial Number.</h3>
<img src="assets/screenshots/7.png" class="img-thumbnail">
</div>
<div class="mt-3" style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Warning if the Product is Out of Stock.</h3>
<img src="assets/screenshots/8.png" class="img-thumbnail">
</div>
<div class="mt-3" style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Warning for Duplicate Serial Number.</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
It is possible to add multiple serial numbers for the selected product from the order line.</p>
<img src="assets/screenshots/11.png" class="img-thumbnail">
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
A validation is added to avoid adding duplicate serial numbers.</p>
<img src="assets/screenshots/9.png" class="img-thumbnail">
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
A warning will be displayed in this scenario.</p>
<img src="assets/screenshots/10.png" class="img-thumbnail">
</div>
</div>
</div>
<!-- END OF SCREENSHOTS SECTION -->
<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;">
Enable Lot & Serial Number for a Product and Assign Values</h4>
<img src="assets/screenshots/1.png"
class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
<img src="assets/screenshots/2.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;">
Add a Product with a Serial Number or Lot Number to the POS Product
Screen.</h4>
<img src="assets/screenshots/3.png"
class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
<img src="assets/screenshots/4.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;">
Warnings for invalid Serial Number</h4>
<img src="assets/screenshots/8.png"
class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
</div>
<div class="col-lg-12 my-3">
<h4 class="mt-3"
style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;">
Warnings for Duplicate Serial Number</h4>
<img src="assets/screenshots/5.png"
class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
<img src="assets/screenshots/6.png"
class="img-responsive img-thumbnail border" width="100%"
height="auto"/>
<!-- SUGGESTED PRODUCTS -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="./assets/misc/categories.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px;">
Related Products
</h2>
</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">
<div class="col-sm-12">
<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="carousel-inner" style="padding: 30px;">
<div class="carousel-item" style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/custom_receipts_for_pos/"
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"
style="border-radius: 0px;"
src="./assets/modules/1.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/16.0/pos_kitchen_screen_odoo/#"
<a href="https://apps.odoo.com/apps/modules/16.0/pos_kitchen_screen_odoo/"
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"
style="border-radius: 0px;"
src="./assets/modules/2.png">
</div>
</a>
@ -285,20 +271,21 @@
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/3.jpg">
style="border-radius: 0px;"
src="./assets/modules/3.png">
</div>
</a>
</div>
</div>
<div class="carousel-item" style="min-height:0px">
<div class="carousel-item active"
style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/pos_receipt_extend/"
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"
style="border-radius: 0px;"
src="./assets/modules/4.png">
</div>
</a>
@ -309,7 +296,7 @@
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"
style="border-radius: 0px;"
src="./assets/modules/5.png">
</div>
</a>
@ -320,7 +307,7 @@
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"
style="border-radius: 0px;"
src="./assets/modules/6.png">
</div>
</a>
@ -328,39 +315,34 @@
</div>
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo1"
data-slide="prev"
style="left:-25px;width: 35px;color: #000;"> <span
<a class="carousel-control-prev" href="#demo1" data-slide="prev"
style="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>
style="font-size:24px"></i></span>
</a> <a class="carousel-control-next" href="#demo1"
data-slide="next" style="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 -->
<!-- END OF RELATED PRODUCTS -->
<!-- OUR SERVICES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/star.png"/>
<img src="./assets/misc/star.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px;">
Our Services
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
@ -371,10 +353,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Customization</h6>
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;">
@ -383,10 +363,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
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;">
@ -395,11 +373,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Support</h6>
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;">
@ -408,11 +383,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Hire
Odoo
Developer</h6>
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;">
@ -421,10 +393,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Integration</h6>
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;">
@ -433,11 +403,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Migration</h6>
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;">
@ -446,10 +413,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Consultancy</h6>
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;">
@ -458,10 +423,8 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
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;">
@ -470,151 +433,125 @@
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Licensing Consultancy</h6>
Odoo Licensing Consultancy</h6>
</div>
</div>
</div>
<!-- END OF OUR SERVICES -->
<!-- OUR INDUSTRIES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/corporate.png"/>
<img src="./assets/misc/corporate.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our
Industries
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px;">
Our Industries
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/trading-black.png"
<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>
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: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/pos-black.png"
<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>
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: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/education-black.png"
<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>
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: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/manufacturing-black.png"
<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>
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: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/ecom-black.png"
<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 &amp; Website
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Mobile
friendly,
awe-inspiring product pages</p>
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: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/service-black.png"
<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>
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: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/restaurant-black.png"
<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>
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: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/hotel-black.png"
<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>
An all-inclusive hotel management application</p>
</div>
</div>
</div>
</div>
<!-- END OF OUR INDUSTRIES -->
<!-- SUPPORT -->
@ -622,10 +559,10 @@
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/customer-support.png"/>
<img src="./assets/misc/customer-support.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold; margin-left: 10px; ">
Support
</h2>
</div>
@ -635,10 +572,10 @@
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4"
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/support.png" height="48" width="48"
<img src="./assets/misc/support.png" height="48" width="48"
style="width: 42px; height: 42px;"/>
</div>
<div>
<div style="margin-left: 18px;">
<h4>Need Help?</h4>
<p style="line-height: 100%;">Got questions or need help?
Get in touch.</p>
@ -653,16 +590,15 @@
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4"
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/whatsapp.png" height="52" width="52"
<img src="./assets/misc/whatsapp.png" height="52" width="52"
style="width: 52px; height: 52px;"/>
</div>
<div>
<div style="margin-left: 18px;">
<h4>WhatsApp</h4>
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
<a href="https://api.whatsapp.com/send?phone=918606827707">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
+91 86068
27707</p>
+91 86068 27707</p>
</a>
</div>
</div>
@ -670,7 +606,7 @@
</div>
<div class="row">
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
<img src="assets/misc/logo.png" width="144" height="31"
<img src="./assets/misc/logo.png" width="144" height="31"
style="width:144px; height: 31px; margin-top: 40px;"/>
</div>
</div>

77
pos_traceability_validation/static/src/js/EditListPopup.js

@ -0,0 +1,77 @@
odoo.define('pos_traceability_validation.PoSEditListPopup', function (require) {
"use strict";
const EditListPopup = require('point_of_sale.EditListPopup');
const Registries = require('point_of_sale.Registries');
var rpc = require('web.rpc');
/**
* EditListPopup Override
*
* This module overrides the EditListPopup component in the Point of Sale (POS) module
* to add custom behavior for serial number validation.
*/
const PosEditlistpopup = (EditListPopup) =>
class extends EditListPopup {
constructor() {
super(...arguments);
this.product = this.props.product;
}
/**
* On confirming from the popup after adding lots/ serial numbers,
* the values are passed to the function validate_lots() for the
* validation. The corresponding error messages will be displayed
* on the popup if the lot is invalid or duplicated, or there is
* no insufficient stock.
*/
async confirm() {
if (this.props.title == 'Lot/Serial Number(s) Required'){
var lot_string = this.state.array
var lot_names = [];
for (var i = 0; i < lot_string.length; i++) {
if (lot_string[i].text != ""){
lot_names.push(lot_string[i].text);
}
}
const picking_type_id = this.env.pos.config && this.env.pos.config.picking_type_id && this.env.pos.config.picking_type_id[0]
const result = await rpc.query({
model: 'stock.lot',
method: 'validate_lots',
args: [lot_names, this.props.product, picking_type_id]
})
if(result != true){
if(result[0] == 'no_stock'){
this.showPopup('ErrorPopup', {
'title': this.env._t('Out of stock'),
'body': this.env._t("The product is out of stock for " + result[1] + '.'),
});
}
else if(result[0] == 'duplicate'){
this.showPopup('ErrorPopup', {
'title': this.env._t('Duplicate entry'),
'body': this.env._t("Duplicate entry for " + result[1] + '.'),
});
}
else if(result[0] == 'invalid'){
this.showPopup('ErrorPopup', {
'title': this.env._t('Invalid Lot/ Serial Number'),
'body': this.env._t("The Lot/ Serial Number " + result[1]+ ' is not available for this product.'),
});
}
}
else{
this.env.posbus.trigger('close-popup', {
popupId: this.props.id,
response: { confirmed: true, payload: await this.getPayload() },
});
}
}
else{
this.env.posbus.trigger('close-popup', {
popupId: this.props.id,
response: { confirmed: true, payload: await this.getPayload() },
});
}
}
};
Registries.Component.extend(EditListPopup, PosEditlistpopup);
return EditListPopup;
});

37
pos_traceability_validation/static/src/js/OrderWidget.js

@ -0,0 +1,37 @@
odoo.define('pos_traceability_validation.PoSOrderWidget', function (require) {
'use strict';
const OrderWidget = require('point_of_sale.OrderWidget');
const Registries = require('point_of_sale.Registries');
/**
* Extends OrderWidget for passing the product IDs to the EditListPopup
* validation
*/
const PoSOrderWidget = (OrderWidget) =>
class extends OrderWidget {
async _editPackLotLines(event) {
const orderline = event.detail.orderline;
const isAllowOnlyOneLot = orderline.product.isAllowOnlyOneLot();
const packLotLinesToEdit = orderline.getPackLotLinesToEdit(isAllowOnlyOneLot);
const { confirmed, payload } = await this.showPopup('EditListPopup', {
title: this.env._t('Lot/Serial Number(s) Required'),
isSingleItem: isAllowOnlyOneLot,
array: packLotLinesToEdit,
product: orderline.product.id
});
if (confirmed) {
// Segregate the old and new packlot lines
const modifiedPackLotLines = Object.fromEntries(
payload.newArray.filter(item => item.id).map(item => [item.id, item.text])
);
const newPackLotLines = payload.newArray
.filter(item => !item.id)
.map(item => ({ lot_name: item.text }));
orderline.setPackLotLines({ modifiedPackLotLines, newPackLotLines });
}
this.order.select_orderline(event.detail.orderline);
}
}
Registries.Component.extend(OrderWidget, PoSOrderWidget);
return OrderWidget;
});

90
pos_traceability_validation/static/src/js/ProductScreen.js

@ -0,0 +1,90 @@
odoo.define('pos_traceability_validation.PoSProductScreen', function (require) {
'use strict';
const ProductScreen = require('point_of_sale.ProductScreen');
const Registries = require('point_of_sale.Registries');
/**
* Extends ProductScreen for passing the product ID to the EditListPopup
* validation
*/
const PoSProductScreen = (ProductScreen) =>
class extends ProductScreen {
async _getAddProductOptions(product, base_code) {
let price_extra = 0.0;
let draftPackLotLines, weight, description, packLotLinesToEdit;
if (this.env.pos.config.product_configurator && _.some(product.attribute_line_ids, (id) => id in this.env.pos.attributes_by_ptal_id)) {
let attributes = _.map(product.attribute_line_ids, (id) => this.env.pos.attributes_by_ptal_id[id])
.filter((attr) => attr !== undefined);
let { confirmed, payload } = await this.showPopup('ProductConfiguratorPopup', {
product: product,
attributes: attributes,
});
if (confirmed) {
description = payload.selected_attributes.join(', ');
price_extra += payload.price_extra;
} else {
return;
}
}
// Gather lot information if required.
if (['serial', 'lot'].includes(product.tracking) && (this.env.pos.picking_type.use_create_lots || this.env.pos.picking_type.use_existing_lots)) {
const isAllowOnlyOneLot = product.isAllowOnlyOneLot();
if (isAllowOnlyOneLot) {
packLotLinesToEdit = [];
} else {
const orderline = this.currentOrder
.get_orderlines()
.filter(line => !line.get_discount())
.find(line => line.product.id === product.id);
if (orderline) {
packLotLinesToEdit = orderline.getPackLotLinesToEdit();
} else {
packLotLinesToEdit = [];
}
}
const { confirmed, payload } = await this.showPopup('EditListPopup', {
title: this.env._t('Lot/Serial Number(s) Required'),
isSingleItem: isAllowOnlyOneLot,
array: packLotLinesToEdit,
product: product.id
});
if (confirmed) {
// Segregate the old and new packlot lines
const modifiedPackLotLines = Object.fromEntries(
payload.newArray.filter(item => item.id).map(item => [item.id, item.text])
);
const newPackLotLines = payload.newArray
.filter(item => !item.id)
.map(item => ({ lot_name: item.text }));
draftPackLotLines = { modifiedPackLotLines, newPackLotLines };
} else {
// We don't proceed on adding product.
return;
}
}
// Take the weight if necessary.
if (product.to_weight && this.env.pos.config.iface_electronic_scale) {
// Show the ScaleScreen to weigh the product.
if (this.isScaleAvailable) {
const { confirmed, payload } = await this.showTempScreen('ScaleScreen', {
product,
});
if (confirmed) {
weight = payload.weight;
} else {
// do not add the product;
return;
}
} else {
await this._onScaleNotAvailable();
}
}
if (base_code && this.env.pos.db.product_packaging_by_barcode[base_code.code]) {
weight = this.env.pos.db.product_packaging_by_barcode[base_code.code].qty;
}
return { draftPackLotLines, quantity: weight, description, price_extra };
}
}
Registries.Component.extend(ProductScreen, PoSProductScreen);
return ProductScreen;
});

69
pos_traceability_validation/static/src/js/pos_models.js

@ -1,69 +0,0 @@
odoo.define('pos_traceability_validation.pos_models', function (require) {
"use strict";
/**
* EditListPopup Override
*
* This module overrides the EditListPopup component in the Point of Sale (POS) module
* to add custom behavior for serial number validation.
*/
const EditListPopup = require('point_of_sale.EditListPopup');
const Registries = require('point_of_sale.Registries');
var rpc = require('web.rpc');
const PosEditlistpopup = (EditListPopup) =>
class extends EditListPopup {
/**
* Confirm Override
*
* Overrides the base confirm method to handle serial number validation.
* If the title of the popup is 'Lot/Serial Number(s) Required', it validates
* the entered lot numbers using the 'serial_no.validation' model.
*/
async confirm() {
if (this.props.title == 'Lot/Serial Number(s) Required'){
var lot_string = this.state.array
var lot_names = [];
for (var i = 0; i < lot_string.length; i++) {
if (lot_string[i].text != ""){
lot_names.push(lot_string[i].text);
}
}
const result = await rpc.query({
model: 'serial_no.validation',
method: 'validate_lots',
args: [lot_names]
})
if(result != true){
if(result[0] == 'no_stock'){
this.showPopup('ErrorPopup', {
'title': this.env._t('Insufficient stock'),
'body': this.env._t("Insufficient stock for " + result[1]),
});
}
else if(result[0] == 'duplicate'){
this.showPopup('ErrorPopup', {
'title': this.env._t('Duplicate entry'),
'body': this.env._t("Duplicate entry for " + result[1]),
});
}
else if(result[0] == 'except'){
alert("Exception occurred with " + result[1])
this.showPopup('ErrorPopup', {
'title': this.env._t('Exception'),
'body': this.env._t("Exception occurred with" + result[1]),
});
}
}
else{
this.props.resolve({ confirmed: true, payload: await this.getPayload() });
this.trigger('close-popup');
}
}
else{
this.props.resolve({ confirmed: true, payload: await this.getPayload() });
this.trigger('close-popup');
}
}
};
Registries.Component.extend(EditListPopup, PosEditlistpopup);
return EditListPopup;
});
Loading…
Cancel
Save