From 216c6273690f7493fb916779154140bd15f877ac Mon Sep 17 00:00:00 2001 From: Alaguraj0361 Date: Tue, 17 Mar 2026 14:56:47 +0530 Subject: [PATCH] Implement online order management with service mode selection, KDS integration, and dedicated POS order fields. --- .../views/pos_order_line_views.xml | 4 +- addons/dine360_online_orders/__init__.py | 1 + addons/dine360_online_orders/__manifest__.py | 5 ++ .../controllers/__init__.py | 1 + .../dine360_online_orders/controllers/main.py | 14 +++++ .../dine360_online_orders/models/__init__.py | 3 + .../models/pos_config.py | 10 +++ .../dine360_online_orders/models/pos_order.py | 24 +++++++ .../models/pos_order_line.py | 15 +++++ .../models/res_config_settings.py | 7 +++ .../models/sale_order.py | 14 +++++ .../static/src/js/service_mode.js | 62 +++++++++++++++++++ .../views/kds_override_views.xml | 27 ++++++++ .../views/pos_config_views.xml | 22 +++++++ .../views/pos_order_views.xml | 7 +++ .../views/website_sale_templates.xml | 29 +++++++++ 16 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 addons/dine360_online_orders/controllers/__init__.py create mode 100644 addons/dine360_online_orders/controllers/main.py create mode 100644 addons/dine360_online_orders/models/pos_config.py create mode 100644 addons/dine360_online_orders/models/pos_order_line.py create mode 100644 addons/dine360_online_orders/models/res_config_settings.py create mode 100644 addons/dine360_online_orders/static/src/js/service_mode.js create mode 100644 addons/dine360_online_orders/views/pos_config_views.xml create mode 100644 addons/dine360_online_orders/views/website_sale_templates.xml diff --git a/addons/dine360_kds/views/pos_order_line_views.xml b/addons/dine360_kds/views/pos_order_line_views.xml index d79521a..563ac13 100644 --- a/addons/dine360_kds/views/pos_order_line_views.xml +++ b/addons/dine360_kds/views/pos_order_line_views.xml @@ -25,8 +25,8 @@
- - + +
diff --git a/addons/dine360_online_orders/__init__.py b/addons/dine360_online_orders/__init__.py index 0650744..f7209b1 100644 --- a/addons/dine360_online_orders/__init__.py +++ b/addons/dine360_online_orders/__init__.py @@ -1 +1,2 @@ from . import models +from . import controllers diff --git a/addons/dine360_online_orders/__manifest__.py b/addons/dine360_online_orders/__manifest__.py index 92b15e3..bc4ae0f 100644 --- a/addons/dine360_online_orders/__manifest__.py +++ b/addons/dine360_online_orders/__manifest__.py @@ -16,6 +16,8 @@ 'security/ir.model.access.csv', 'views/pos_order_views.xml', 'views/kds_override_views.xml', + 'views/pos_config_views.xml', + 'views/website_sale_templates.xml', ], 'assets': { 'point_of_sale._assets_pos': [ @@ -24,6 +26,9 @@ 'dine360_online_orders/static/src/js/online_orders_navbar.js', 'dine360_online_orders/static/src/xml/online_orders_screen.xml', ], + 'web.assets_frontend': [ + 'dine360_online_orders/static/src/js/service_mode.js', + ], }, 'installable': True, 'application': False, diff --git a/addons/dine360_online_orders/controllers/__init__.py b/addons/dine360_online_orders/controllers/__init__.py new file mode 100644 index 0000000..12a7e52 --- /dev/null +++ b/addons/dine360_online_orders/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/addons/dine360_online_orders/controllers/main.py b/addons/dine360_online_orders/controllers/main.py new file mode 100644 index 0000000..4b6e196 --- /dev/null +++ b/addons/dine360_online_orders/controllers/main.py @@ -0,0 +1,14 @@ +from odoo import http +from odoo.http import request + +class Dine360OnlineOrders(http.Controller): + + @http.route('/shop/update_service_mode', type='json', auth="public", website=True) + def update_service_mode(self, service_mode, **post): + order = request.website.sale_get_order() + if order and service_mode in ['pickup', 'delivery', 'dine_in']: + order.sudo().write({ + 'dine360_service_mode': service_mode, + 'dine360_order_source': 'web' + }) + return True diff --git a/addons/dine360_online_orders/models/__init__.py b/addons/dine360_online_orders/models/__init__.py index 5055bda..8a88826 100644 --- a/addons/dine360_online_orders/models/__init__.py +++ b/addons/dine360_online_orders/models/__init__.py @@ -1,2 +1,5 @@ from . import pos_order from . import sale_order +from . import pos_config +from . import res_config_settings +from . import pos_order_line diff --git a/addons/dine360_online_orders/models/pos_config.py b/addons/dine360_online_orders/models/pos_config.py new file mode 100644 index 0000000..3a413ef --- /dev/null +++ b/addons/dine360_online_orders/models/pos_config.py @@ -0,0 +1,10 @@ +from odoo import models, fields + +class PosConfig(models.Model): + _inherit = 'pos.config' + + is_kiosk = fields.Boolean(string='Is Self-Order Kiosk', default=False) + kiosk_service_mode = fields.Selection([ + ('pickup', 'Pickup'), + ('dine_in', 'Dine-In') + ], string='Default Kiosk Service Mode', default='dine_in') diff --git a/addons/dine360_online_orders/models/pos_order.py b/addons/dine360_online_orders/models/pos_order.py index 27ae89f..389eb84 100644 --- a/addons/dine360_online_orders/models/pos_order.py +++ b/addons/dine360_online_orders/models/pos_order.py @@ -31,6 +31,18 @@ class PosOrder(models.Model): default=fields.Datetime.now ) + dine360_order_source = fields.Selection([ + ('web', 'Customer Self (Web)'), + ('kiosk', 'Store Self (Kiosk)'), + ('pos', 'Standard POS') + ], string='Order Source', default='pos') + + dine360_service_mode = fields.Selection([ + ('pickup', 'Pickup'), + ('delivery', 'Delivery'), + ('dine_in', 'Dine-In') + ], string='Service Mode', default='dine_in') + @api.depends('partner_id', 'partner_id.name') def _compute_online_customer_name(self): for order in self: @@ -80,6 +92,16 @@ class PosOrder(models.Model): _logger.info("Online order %s rejected", self.name) return True + @api.model_create_multi + def create(self, vals_list): + for vals in vals_list: + if 'session_id' in vals: + session = self.env['pos.session'].browse(vals['session_id']) + if session.config_id.is_kiosk: + vals['dine360_order_source'] = 'kiosk' + vals['dine360_service_mode'] = session.config_id.kiosk_service_mode + return super().create(vals_list) + @api.model def get_online_orders(self, config_id): """Fetch pending online orders for a specific POS config""" @@ -112,6 +134,8 @@ class PosOrder(models.Model): 'amount_total': order.amount_total, 'date_order': order.date_order.isoformat() if order.date_order else '', 'sale_order_name': order.sale_order_id.name if order.sale_order_id else '', + 'service_mode': order.dine360_service_mode, + 'order_source': order.dine360_order_source, 'note': order.note or '', 'lines': lines, }) diff --git a/addons/dine360_online_orders/models/pos_order_line.py b/addons/dine360_online_orders/models/pos_order_line.py new file mode 100644 index 0000000..cd3a7b3 --- /dev/null +++ b/addons/dine360_online_orders/models/pos_order_line.py @@ -0,0 +1,15 @@ +from odoo import models, fields, api + +class PosOrderLine(models.Model): + _inherit = 'pos.order.line' + + dine360_order_source = fields.Selection( + related='order_id.dine360_order_source', + string='Order Source', + store=True + ) + dine360_service_mode = fields.Selection( + related='order_id.dine360_service_mode', + string='Service Mode', + store=True + ) diff --git a/addons/dine360_online_orders/models/res_config_settings.py b/addons/dine360_online_orders/models/res_config_settings.py new file mode 100644 index 0000000..3c49767 --- /dev/null +++ b/addons/dine360_online_orders/models/res_config_settings.py @@ -0,0 +1,7 @@ +from odoo import models, fields + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + is_kiosk = fields.Boolean(related='pos_config_id.is_kiosk', readonly=False) + kiosk_service_mode = fields.Selection(related='pos_config_id.kiosk_service_mode', readonly=False) diff --git a/addons/dine360_online_orders/models/sale_order.py b/addons/dine360_online_orders/models/sale_order.py index 139693a..bfdab3c 100644 --- a/addons/dine360_online_orders/models/sale_order.py +++ b/addons/dine360_online_orders/models/sale_order.py @@ -12,6 +12,18 @@ class SaleOrderOnline(models.Model): help='The POS order created from this website sale order' ) + dine360_order_source = fields.Selection([ + ('web', 'Customer Self (Web)'), + ('kiosk', 'Store Self (Kiosk)'), + ('pos', 'Standard POS') + ], string='Order Source', default='web') + + dine360_service_mode = fields.Selection([ + ('pickup', 'Pickup'), + ('delivery', 'Delivery'), + ('dine_in', 'Dine-In') + ], string='Service Mode', default='pickup') + def _create_pos_order_for_kds(self, sale_order): """ Override from dine360_kds to also mark the POS order as an online order. @@ -35,6 +47,8 @@ class SaleOrderOnline(models.Model): 'online_order_status': 'pending', 'sale_order_id': sale_order.id, 'online_order_date': fields.Datetime.now(), + 'dine360_order_source': sale_order.dine360_order_source, + 'dine360_service_mode': sale_order.dine360_service_mode, }) # Link back to sale order diff --git a/addons/dine360_online_orders/static/src/js/service_mode.js b/addons/dine360_online_orders/static/src/js/service_mode.js new file mode 100644 index 0000000..3cde396 --- /dev/null +++ b/addons/dine360_online_orders/static/src/js/service_mode.js @@ -0,0 +1,62 @@ +/** @odoo-module **/ + +import publicWidget from "@web/legacy/js/public/public_widget"; +import { jsonrpc } from "@web/core/network/rpc_service"; + +publicWidget.registry.ServiceModeSelector = publicWidget.Widget.extend({ + selector: '#service_mode_selector', + events: { + 'change input[name="dine360_service_mode"]': '_onChangeServiceMode', + }, + + start: function () { + // Init visual selection + this.$('input[name="dine360_service_mode"]:checked').closest('.service-option').find('.service-card') + .css({ 'border-color': '#FECD4F', 'background-color': '#fffdf6', 'box-shadow': '0 4px 10px rgba(254, 205, 79, 0.2)' }); + return this._super.apply(this, arguments); + }, + + _onChangeServiceMode: function (ev) { + var $input = $(ev.currentTarget); + var mode = $input.val(); + + // Reset styles + this.$('.service-card').css({ 'border-color': '', 'background-color': '', 'box-shadow': '' }); + // Apply active styles + $input.closest('.service-option').find('.service-card') + .css({ 'border-color': '#FECD4F', 'background-color': '#fffdf6', 'box-shadow': '0 4px 10px rgba(254, 205, 79, 0.2)' }); + + // Hide error if present + this.$('#service_mode_error').addClass('d-none'); + + // RPC Call to update order + jsonrpc('/shop/update_service_mode', { + service_mode: mode + }); + } +}); + +// Intercept checkout to ensure a service mode is selected +publicWidget.registry.CartCheckoutValidation = publicWidget.Widget.extend({ + selector: '.oe_cart', + events: { + 'click a[href="/shop/checkout"]': '_onCheckoutClicked', + }, + + _onCheckoutClicked: function (ev) { + // If there's a selector on the page + if (this.$('#service_mode_selector').length > 0) { + var selectedMode = this.$('input[name="dine360_service_mode"]:checked').val(); + if (!selectedMode) { + ev.preventDefault(); + this.$('#service_mode_error').removeClass('d-none'); + + // Highlight the box + this.$('#service_mode_selector').css('border', '1px solid #dc3545').addClass('shake-animation'); + setTimeout(() => { + this.$('#service_mode_selector').removeClass('shake-animation'); + }, 500); + } + } + } +}); diff --git a/addons/dine360_online_orders/views/kds_override_views.xml b/addons/dine360_online_orders/views/kds_override_views.xml index b922ec8..e31d236 100644 --- a/addons/dine360_online_orders/views/kds_override_views.xml +++ b/addons/dine360_online_orders/views/kds_override_views.xml @@ -10,4 +10,31 @@ '|', ('order_id.is_online_order', '=', False), ('order_id.online_order_status', '!=', 'pending') ] + + + + pos.order.line.kds.kanban.inherit + pos.order.line + + + + + + + +
+ + + + + + + + + +
+
+
+
diff --git a/addons/dine360_online_orders/views/pos_config_views.xml b/addons/dine360_online_orders/views/pos_config_views.xml new file mode 100644 index 0000000..6ce0ca6 --- /dev/null +++ b/addons/dine360_online_orders/views/pos_config_views.xml @@ -0,0 +1,22 @@ + + + + res.config.settings.view.form.inherit.dine360 + res.config.settings + + + + + + +
+
+
+
+
+
+
+
+
diff --git a/addons/dine360_online_orders/views/pos_order_views.xml b/addons/dine360_online_orders/views/pos_order_views.xml index 83e90a4..d8f4858 100644 --- a/addons/dine360_online_orders/views/pos_order_views.xml +++ b/addons/dine360_online_orders/views/pos_order_views.xml @@ -15,6 +15,11 @@ decoration-success="online_order_status=='confirmed'" decoration-danger="online_order_status=='rejected'"/> + + @@ -33,6 +38,8 @@ decoration-success="online_order_status=='confirmed'" decoration-danger="online_order_status=='rejected'"/> + + diff --git a/addons/dine360_online_orders/views/website_sale_templates.xml b/addons/dine360_online_orders/views/website_sale_templates.xml new file mode 100644 index 0000000..da39bd5 --- /dev/null +++ b/addons/dine360_online_orders/views/website_sale_templates.xml @@ -0,0 +1,29 @@ + + + +