-
-
Notifications
You must be signed in to change notification settings - Fork 602
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ADD] pos_stock_available_online: Add new module to sync product avai…
…lability with POS
- Loading branch information
1 parent
dbf3aa3
commit 942fcd6
Showing
22 changed files
with
420 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
wait a bot :) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "Point of Sale Stock Available Online", | ||
"version": "16.0.1.0.0", | ||
"category": "Sales/Point of Sale", | ||
"summary": "Show the available quantity of products in the in the Point of Sale ", | ||
"depends": ["point_of_sale", "stock_available", "base_automation"], | ||
"website": "https://github.com/OCA/pos", | ||
"author": "Cetmix, Odoo Community Association (OCA)", | ||
"maintainers": ["GabbasovDinar", "CetmixGitDrone"], | ||
"installable": True, | ||
"data": ["views/res_config_settings_view.xml"], | ||
"assets": { | ||
"point_of_sale.assets": [ | ||
"pos_stock_available_online/static/src/css/**/*.css", | ||
"pos_stock_available_online/static/src/js/**/*.js", | ||
"pos_stock_available_online/static/src/xml/**/*.xml", | ||
], | ||
}, | ||
"license": "LGPL-3", | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from . import pos_config | ||
from . import pos_session | ||
from . import res_config_settings | ||
from . import stock_quant | ||
from . import stock_warehouse |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import logging | ||
|
||
from odoo import fields, models | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class PosConfig(models.Model): | ||
_inherit = "pos.config" | ||
|
||
display_product_quantity = fields.Boolean( | ||
default=True, | ||
) | ||
additional_warehouse_ids = fields.Many2many( | ||
"stock.warehouse", | ||
"pos_config_stock_warehouse_rel", | ||
"pos_config_id", | ||
"warehouse_id", | ||
string="Additional Warehouses", | ||
help="For the selected warehouses will be displayed " | ||
"quantity of available products in the POS", | ||
) | ||
minimum_product_quantity_alert = fields.Float( | ||
default=0.0, | ||
) | ||
|
||
def _get_channel_name(self): | ||
""" | ||
Return full channel name as combination, POS Config ID and const CHANNEL | ||
""" | ||
self.ensure_one() | ||
return '["{}","{}"]'.format("pos_stock_available_online", self.id) | ||
|
||
def _notify_available_quantity(self, message): | ||
""" | ||
Notify POSes about product updates | ||
""" | ||
if not isinstance(message, list): | ||
message = [message] | ||
notifications = [] | ||
for config in self: | ||
notifications.append( | ||
[config._get_channel_name(), "pos.config/product_update", message] | ||
) | ||
if notifications: | ||
self.env["bus.bus"]._sendmany(notifications) | ||
_logger.debug("POS notifications for %s: %s", self.ids, notifications) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
from odoo import models | ||
|
||
|
||
class PosSession(models.Model): | ||
_inherit = "pos.session" | ||
|
||
def _process_pos_ui_product_product(self, products): | ||
config = self.config_id | ||
if config.display_product_quantity: | ||
product_obj = self.env["product.product"] | ||
for product_info in products: | ||
product = product_obj.browse(product_info["id"]) | ||
# prepared first main warehouse info | ||
warehouse_info = [config.warehouse_id._prepare_vals_for_pos(product)] | ||
# prepared additional warehouses info | ||
for warehouse in config.additional_warehouse_ids: | ||
warehouse_info.append(warehouse._prepare_vals_for_pos(product)) | ||
product_info["warehouse_info"] = warehouse_info | ||
|
||
return super()._process_pos_ui_product_product(products) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from odoo import fields, models | ||
|
||
|
||
class ResConfigSettings(models.TransientModel): | ||
_inherit = "res.config.settings" | ||
|
||
pos_display_product_quantity = fields.Boolean( | ||
related="pos_config_id.display_product_quantity", | ||
readonly=False, | ||
) | ||
pos_additional_warehouse_ids = fields.Many2many( | ||
"stock.warehouse", | ||
related="pos_config_id.additional_warehouse_ids", | ||
readonly=False, | ||
) | ||
pos_minimum_product_quantity_alert = fields.Float( | ||
related="pos_config_id.minimum_product_quantity_alert", | ||
readonly=False, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import logging | ||
|
||
from odoo import models | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class StockQuant(models.Model): | ||
_inherit = "stock.quant" | ||
|
||
def _prepare_pos_message(self): | ||
""" | ||
Return prepared message to send to POS | ||
""" | ||
self.ensure_one() | ||
return self.warehouse_id._prepare_vals_for_pos(self.product_id) | ||
|
||
def _notify_pos(self): | ||
""" | ||
Send notification to POS | ||
""" | ||
pos_session_obj = self.env["pos.session"] | ||
for quant in self: | ||
warehouse_id = quant.warehouse_id.id | ||
configs = pos_session_obj.search( | ||
[ | ||
("state", "=", "opened"), | ||
("display_product_quantity", "=", True), | ||
"|", | ||
("config_id.additional_warehouse_ids", "in", [warehouse_id]), | ||
("config_id.warehouse_id", "=", warehouse_id), | ||
], | ||
).mapped("config_id") | ||
if configs: | ||
configs._notify_available_quantity(quant._prepare_pos_message()) | ||
|
||
def write(self, vals): | ||
res = super().write(vals) | ||
self._notify_pos() | ||
return res |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from odoo import models | ||
|
||
|
||
class StockWarehouse(models.Model): | ||
_inherit = "stock.warehouse" | ||
|
||
def _prepare_vals_for_pos(self, product): | ||
""" | ||
Prepare warehouse info data to send a POS | ||
""" | ||
self.ensure_one() | ||
return { | ||
"id": self.id, | ||
"name": self.name, | ||
"quantity": product.with_context(warehouse=self.id).immediately_usable_qty, | ||
"product_id": product.id, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Select PoS > Configuration > Settings > select additional warehouses |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
* Cetmix <https://cetmix.com/> | ||
* Dinar Gabbasov |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
TODO |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
.pos .product-list .warehouse-info { | ||
position: absolute; | ||
right: 0; | ||
top: 0; | ||
padding: 0 5px; | ||
font-weight: bold; | ||
} | ||
.pos .product-list .warehouse-info .warehouse { | ||
padding: 5px 0; | ||
margin-left: auto; | ||
width: fit-content; | ||
} | ||
.pos .product-list .warehouse-info .warehouse .quantity { | ||
color: white; | ||
padding: 4px; | ||
float: right; | ||
} | ||
.pos .product-list .warehouse-info .warehouse .warehouse-name { | ||
display: block; | ||
color: #696969; | ||
font-size: 10px; | ||
text-align: right; | ||
} | ||
.pos .product-list .warehouse-info .warehouse.total .warehouse-name { | ||
font-weight: bold; | ||
} | ||
.pos .product-list .warehouse-info .warehouse .quantity.available { | ||
background: #32a868; | ||
} | ||
.pos .product-list .warehouse-info .warehouse .quantity.not-available { | ||
background: #ef5350; | ||
} |
36 changes: 36 additions & 0 deletions
36
pos_stock_available_online/static/src/js/Screens/ProductScreen/ProductItem.esm.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** @odoo-module **/ | ||
|
||
import ProductItem from "point_of_sale.ProductItem"; | ||
import Registries from "point_of_sale.Registries"; | ||
import {format} from "web.field_utils"; | ||
import utils from "web.utils"; | ||
|
||
const StockProductItem = (ProductItem) => | ||
class StockProductItem extends ProductItem { | ||
format_quantity(quantity) { | ||
const unit = this.env.pos.units_by_id[this.props.product.uom_id[0]]; | ||
var formattedQuantity = `${quantity}`; | ||
if (unit) { | ||
if (unit.rounding) { | ||
var decimals = this.env.pos.dp["Product Unit of Measure"]; | ||
formattedQuantity = format.float(quantity, { | ||
digits: [69, decimals], | ||
}); | ||
} else { | ||
formattedQuantity = utils.round_precision(quantity, 1).toFixed(0); | ||
} | ||
} | ||
return `${formattedQuantity}`; | ||
} | ||
get display_total_quantity() { | ||
return this.format_quantity(this.total_quantity); | ||
} | ||
get total_quantity() { | ||
return this.props.product.warehouse_info.reduce( | ||
(partialSum, warehouse) => partialSum + warehouse.quantity, | ||
0 | ||
); | ||
} | ||
}; | ||
|
||
Registries.Component.extend(ProductItem, StockProductItem); |
63 changes: 63 additions & 0 deletions
63
pos_stock_available_online/static/src/js/Screens/ProductScreen/ProductsWidget.esm.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** @odoo-module **/ | ||
|
||
import ProductsWidget from "point_of_sale.ProductsWidget"; | ||
import Registries from "point_of_sale.Registries"; | ||
|
||
const StockProductsWidget = (ProductsWidget) => | ||
class StockProductsWidget extends ProductsWidget { | ||
setup() { | ||
super.setup(); | ||
this.env.services.bus_service.addChannel(this._getChannelName()); | ||
this.env.services.bus_service.addEventListener( | ||
"notification", | ||
this._onNotification.bind(this) | ||
); | ||
} | ||
_getChannelName() { | ||
return JSON.stringify([ | ||
"pos_stock_available_online", | ||
String(this.env.pos.config.id), | ||
]); | ||
} | ||
_onNotification({detail: notifications}) { | ||
var payloads = []; | ||
for (const {payload, type} of notifications) { | ||
if (type === "pos.config/product_update") { | ||
payloads.push(payload); | ||
} | ||
} | ||
this._handleNotification(payloads); | ||
} | ||
async _handleNotification(payloads) { | ||
if (this.env.isDebug()) { | ||
console.log("Payloads:", payloads); | ||
} | ||
const db = this.env.pos.db; | ||
const ProductIds = []; | ||
for (const payload of payloads) { | ||
for (const message of payload) { | ||
var product = db.get_product_by_id(message.product_id); | ||
if (product) { | ||
// Update warehouse info of the product | ||
var warehouse = product.warehouse_info.find( | ||
(wh) => wh.id === message.id | ||
); | ||
if (warehouse) { | ||
warehouse.quantity = message.quantity; | ||
} else { | ||
product.warehouse_info.push(message); | ||
} | ||
} else { | ||
ProductIds.push(message.id); | ||
} | ||
} | ||
} | ||
if (ProductIds.length) { | ||
await this.env.pos._addProducts([...new Set(ProductIds)], false); | ||
} | ||
// Re-render product list without category switching | ||
this.render(true); | ||
} | ||
}; | ||
|
||
Registries.Component.extend(ProductsWidget, StockProductsWidget); |
42 changes: 42 additions & 0 deletions
42
pos_stock_available_online/static/src/xml/Screens/ProductScreen/ProductItem.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
<?xml version="1.0" encoding="UTF-8" ?> | ||
<templates id="template" xml:space="preserve"> | ||
|
||
<t | ||
t-name="ProductItem" | ||
t-inherit="point_of_sale.ProductItem" | ||
t-inherit-mode="extension" | ||
owl="1" | ||
> | ||
<xpath expr="//div[hasclass('product-img')]" position="before"> | ||
<div t-if="env.pos.config.display_product_quantity" class="warehouse-info"> | ||
<div class="warehouse total"> | ||
<span | ||
t-attf-class="quantity {{total_quantity > env.pos.config.minimum_product_quantity_alert ? 'available' : 'not-available'}}" | ||
> | ||
<t t-esc="display_total_quantity" /> | ||
</span> | ||
<span class="warehouse-name"> | ||
Total | ||
</span> | ||
</div> | ||
<t | ||
t-foreach="props.product.warehouse_info" | ||
t-as="warehouse" | ||
t-key="warehouse.id" | ||
> | ||
<div class="warehouse"> | ||
<span | ||
t-attf-class="quantity {{warehouse.quantity > env.pos.config.minimum_product_quantity_alert ? 'available' : 'not-available'}}" | ||
> | ||
<t t-esc="format_quantity(warehouse.quantity)" /> | ||
</span> | ||
<span class="warehouse-name"> | ||
<t t-esc="warehouse.name" /> | ||
</span> | ||
</div> | ||
</t> | ||
</div> | ||
</xpath> | ||
</t> | ||
|
||
</templates> |
Oops, something went wrong.