diff --git a/second_uom/__init__.py b/second_uom/__init__.py
new file mode 100644
index 00000000000..0650744f6bc
--- /dev/null
+++ b/second_uom/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/second_uom/__manifest__.py b/second_uom/__manifest__.py
new file mode 100644
index 00000000000..030c1469e22
--- /dev/null
+++ b/second_uom/__manifest__.py
@@ -0,0 +1,19 @@
+{
+ 'name': 'second_uom',
+ 'description': "Add Button for second uom",
+ 'author': "meet kavathiya",
+ 'website': 'https://www.odoo.com/',
+ 'category': '',
+ 'version': '0.1',
+ 'application': True,
+ 'installable': True,
+ 'depends': ['point_of_sale'],
+ 'data': ['views/product_views.xml'],
+ 'assets': {
+ 'point_of_sale._assets_pos': [
+ 'second_uom/static/src/app/**/*.js',
+ 'second_uom/static/src/app/**/*.xml',
+ ],
+ },
+ 'license': 'LGPL-3',
+}
diff --git a/second_uom/models/__init__.py b/second_uom/models/__init__.py
new file mode 100644
index 00000000000..049669dd0fe
--- /dev/null
+++ b/second_uom/models/__init__.py
@@ -0,0 +1,2 @@
+from . import product_template
+from . import product_product
diff --git a/second_uom/models/product_product.py b/second_uom/models/product_product.py
new file mode 100644
index 00000000000..f1874b40557
--- /dev/null
+++ b/second_uom/models/product_product.py
@@ -0,0 +1,11 @@
+from odoo import api, models
+
+
+class InheritedProductProduct(models.Model):
+ _inherit = 'product.product'
+
+ @api.model
+ def _load_pos_data_fields(self, config):
+ params = super()._load_pos_data_fields(config)
+ params.append('pos_second_uom_id')
+ return params
diff --git a/second_uom/models/product_template.py b/second_uom/models/product_template.py
new file mode 100644
index 00000000000..6e189f27f1d
--- /dev/null
+++ b/second_uom/models/product_template.py
@@ -0,0 +1,30 @@
+from odoo import api, fields, models
+
+
+class InheritedProductTemplate(models.Model):
+ _inherit = 'product.template'
+
+ pos_second_uom_id = fields.Many2one(
+ 'uom.uom',
+ string="POS Second UoM",
+ help="Secondary unit of measure for quick quantity conversion in the POS popup.",
+ )
+ uom_root_id = fields.Many2one(
+ 'uom.uom', string="UoM Root", compute='_compute_uom_root_id'
+ )
+
+ @api.depends('uom_id')
+ def _compute_uom_root_id(self):
+ for record in self:
+ if record.uom_id and record.uom_id.parent_path:
+ root_id = int(record.uom_id.parent_path.split('/')[0])
+ record.uom_root_id = root_id
+ else:
+ record.uom_root_id = False
+
+ @api.onchange('uom_id')
+ def _onchange_uom_id_clear_second(self):
+ if self.pos_second_uom_id and not self.uom_id._has_common_reference(
+ self.pos_second_uom_id
+ ):
+ self.pos_second_uom_id = False
diff --git a/second_uom/static/src/app/components/uom_popup/second_uom_popup.js b/second_uom/static/src/app/components/uom_popup/second_uom_popup.js
new file mode 100644
index 00000000000..43164cf6f90
--- /dev/null
+++ b/second_uom/static/src/app/components/uom_popup/second_uom_popup.js
@@ -0,0 +1,14 @@
+import { NumberPopup } from "@point_of_sale/app/components/popups/number_popup/number_popup";
+
+export class SecondUomPopup extends NumberPopup {
+ static template = "second_uom.SecondUomPopup";
+ static props = {
+ ...NumberPopup.props,
+ uomName: { type: String },
+ };
+
+ confirm() {
+ this.props.getPayload(this.state.buffer);
+ this.props.close();
+ }
+}
diff --git a/second_uom/static/src/app/components/uom_popup/second_uom_popup.xml b/second_uom/static/src/app/components/uom_popup/second_uom_popup.xml
new file mode 100644
index 00000000000..17685b3236d
--- /dev/null
+++ b/second_uom/static/src/app/components/uom_popup/second_uom_popup.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+ Unit:
+
+
+
+
+ ()
+
+
+
+
diff --git a/second_uom/static/src/app/screens/product_screen/control_buttons/control_buttons.js b/second_uom/static/src/app/screens/product_screen/control_buttons/control_buttons.js
new file mode 100644
index 00000000000..8ebc3808a0b
--- /dev/null
+++ b/second_uom/static/src/app/screens/product_screen/control_buttons/control_buttons.js
@@ -0,0 +1,32 @@
+import { ControlButtons } from "@point_of_sale/app/screens/product_screen/control_buttons/control_buttons";
+import { SecondUomPopup } from "@second_uom/app/components/uom_popup/second_uom_popup";
+import { patch } from "@web/core/utils/patch";
+import { makeAwaitable } from "@point_of_sale/app/utils/make_awaitable_dialog";
+
+patch(ControlButtons.prototype, {
+ displaySecondUomBtn() {
+ const selectedLine = this.currentOrder?.getSelectedOrderline();
+ return selectedLine && selectedLine.product_id.pos_second_uom_id;
+ },
+
+ async clickSecondUom() {
+ const selectedLine = this.currentOrder.getSelectedOrderline();
+ if (!selectedLine) return;
+
+ const secondUom = selectedLine.product_id.pos_second_uom_id;
+ const mainUom = selectedLine.product_id.uom_id;
+
+ const result = await makeAwaitable(this.dialog, SecondUomPopup, {
+ title: "Secondary Unit Entry",
+ uomName: secondUom.name,
+ startingValue: 0,
+ });
+
+ if (result !== null && result !== undefined) {
+ const enteredQty = parseFloat(result);
+ if (isNaN(enteredQty)) return;
+ const newMainQty = (enteredQty * secondUom.factor) / mainUom.factor;
+ selectedLine.setQuantity(newMainQty);
+ }
+ }
+});
diff --git a/second_uom/static/src/app/screens/product_screen/control_buttons/control_buttons.xml b/second_uom/static/src/app/screens/product_screen/control_buttons/control_buttons.xml
new file mode 100644
index 00000000000..748b08d4d69
--- /dev/null
+++ b/second_uom/static/src/app/screens/product_screen/control_buttons/control_buttons.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/second_uom/views/product_views.xml b/second_uom/views/product_views.xml
new file mode 100644
index 00000000000..06df256796e
--- /dev/null
+++ b/second_uom/views/product_views.xml
@@ -0,0 +1,13 @@
+
+
+
+ product.template.form.inherit.second.uom
+ product.template
+
+
+
+
+
+
+
+