From 24b0e642a9b8313534b8b54ac38d8e18f3f61cdc Mon Sep 17 00:00:00 2001 From: Alaguraj0361 Date: Thu, 8 Oct 2026 19:15:21 +0530 Subject: [PATCH] add online order management and POS synchronization features for dine360 --- addons/dine360_dashboard/controllers/main.py | 49 ++++++++++++++++--- .../static/src/js/dashboard_pages.js | 4 ++ .../dine360_dashboard/views/orders_page.xml | 26 +++++++--- .../dine360_online_orders/models/pos_order.py | 46 ++++++++++++----- .../models/sale_order.py | 26 ++++++++-- 5 files changed, 123 insertions(+), 28 deletions(-) diff --git a/addons/dine360_dashboard/controllers/main.py b/addons/dine360_dashboard/controllers/main.py index 6920dbf..22ee90f 100644 --- a/addons/dine360_dashboard/controllers/main.py +++ b/addons/dine360_dashboard/controllers/main.py @@ -262,10 +262,18 @@ def get_dashboard_context(active_page='dashboard'): all_online = SaleOrder.search(domain) online_orders_data['has_online_orders'] = bool(all_online) - pending_domain = domain + [('state', 'in', ['draft', 'sent'])] - confirmed_domain = domain + [('state', 'in', ['sale', 'done'])] + if 'online_order_status' in SaleOrder._fields: + pending_domain = domain + [('online_order_status', '=', 'pending')] + confirmed_domain = domain + [('online_order_status', '=', 'confirmed')] + cooking_domain = domain + [('online_order_status', '=', 'cooking')] + else: + pending_domain = domain + [('state', 'in', ['draft', 'sent'])] + confirmed_domain = domain + [('state', 'in', ['sale', 'done'])] + cooking_domain = [] + online_orders_data['pending_count'] = SaleOrder.search_count(pending_domain) online_orders_data['confirmed_count'] = SaleOrder.search_count(confirmed_domain) + online_orders_data['cooking_count'] = SaleOrder.search_count(cooking_domain) if cooking_domain else 0 today_start = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) today_orders = SaleOrder.search(domain + [('date_order', '>=', today_start)]) @@ -289,7 +297,7 @@ def get_dashboard_context(active_page='dashboard'): 'customer': o.partner_id.name or 'Guest', 'phone': o.partner_id.phone or o.partner_id.mobile or '', 'amount': f"{symbol}{o.amount_total:,.2f}", - 'status': getattr(o, 'online_order_status', o.state) or 'confirmed', + 'status': getattr(o, 'online_order_status', False) or ('confirmed' if o.state in ['sale', 'done'] else 'pending'), 'date': o.date_order.strftime('%d %b, %H:%M') if o.date_order else '', 'url': f"/web#id={o.id}&model=sale.order&view_type=form", }) @@ -695,10 +703,39 @@ class Dine360DashboardController(http.Controller): if order_id and 'sale.order' in request.env: order = request.env['sale.order'].sudo().browse(order_id) if order.exists(): - if hasattr(order, 'online_order_status'): + if status == 'confirmed': + if hasattr(order, 'action_accept_online_order'): + order.action_accept_online_order() + else: + if order.state in ['draft', 'sent']: + order.action_confirm() + order.write({'online_order_status': 'confirmed'}) + elif status == 'cooking': + if hasattr(order, 'action_cook_online_order'): + order.action_cook_online_order() + else: + order.write({'online_order_status': 'cooking'}) + if order.pos_order_id: + order.pos_order_id.write({'online_order_status': 'cooking'}) + if hasattr(order.pos_order_id, 'lines'): + order.pos_order_id.lines.write({'preparation_status': 'preparing'}) + elif status in ['delivered', 'ready']: + if hasattr(order, 'action_deliver_online_order'): + order.action_deliver_online_order() + else: + order.write({'online_order_status': 'delivered'}) + if order.pos_order_id: + order.pos_order_id.write({'online_order_status': 'delivered'}) + if hasattr(order.pos_order_id, 'lines'): + order.pos_order_id.lines.write({'preparation_status': 'ready'}) + elif status == 'rejected': + if hasattr(order, 'action_reject_online_order'): + order.action_reject_online_order() + else: + order._action_cancel() + order.write({'online_order_status': 'rejected'}) + else: order.write({'online_order_status': status}) - elif status == 'confirmed' and order.state == 'draft': - order.action_confirm() return request.make_response( json.dumps({'success': True, 'order_id': order_id, 'status': status}), diff --git a/addons/dine360_dashboard/static/src/js/dashboard_pages.js b/addons/dine360_dashboard/static/src/js/dashboard_pages.js index cc60991..c3038e4 100644 --- a/addons/dine360_dashboard/static/src/js/dashboard_pages.js +++ b/addons/dine360_dashboard/static/src/js/dashboard_pages.js @@ -204,6 +204,10 @@ document.addEventListener('DOMContentLoaded', function () { const orderId = this.getAttribute('data-order-id'); const newStatus = this.getAttribute('data-status'); + if (newStatus === 'rejected' && !confirm('Are you sure you want to cancel / reject this online order?')) { + return; + } + this.disabled = true; this.innerHTML = ''; diff --git a/addons/dine360_dashboard/views/orders_page.xml b/addons/dine360_dashboard/views/orders_page.xml index 2c98349..e4cc055 100644 --- a/addons/dine360_dashboard/views/orders_page.xml +++ b/addons/dine360_dashboard/views/orders_page.xml @@ -59,7 +59,7 @@ Cooking
In Kitchen
-
+
@@ -156,28 +156,40 @@ Delivered + + Rejected + -
+
- + - - - + + Completed + + + Cancelled + +
diff --git a/addons/dine360_online_orders/models/pos_order.py b/addons/dine360_online_orders/models/pos_order.py index b539d25..44bb6dd 100644 --- a/addons/dine360_online_orders/models/pos_order.py +++ b/addons/dine360_online_orders/models/pos_order.py @@ -15,6 +15,8 @@ class PosOrder(models.Model): online_order_status = fields.Selection([ ('pending', 'Pending Kitchen'), ('confirmed', 'Confirmed'), + ('cooking', 'Cooking'), + ('delivered', 'Delivered'), ('rejected', 'Rejected'), ], string='Online Order Status', default='pending') @@ -88,17 +90,13 @@ class PosOrder(models.Model): else: _logger.warning("Could not find a suitable POS Payment Method for online order %s", self.name) - # Set all order lines to 'waiting' so KDS picks them up - for line in self.lines: - if line.product_id.is_kitchen_item and line.product_id.type != 'service': - line.write({ - 'preparation_status': 'waiting', - }) - - # Notify KDS - self.lines.filtered( - lambda l: l.product_id.is_kitchen_item and l.product_id.type != 'service' - )._notify_kds() + # Set kitchen order lines to 'waiting' so KDS picks them up + kitchen_lines = self.lines.filtered( + lambda l: (l.product_id.is_kitchen_item or l.product_id.type != 'service') and l.product_id.name not in ['Tips', 'Discount', 'Standard delivery'] + ) + if kitchen_lines: + kitchen_lines.write({'preparation_status': 'waiting'}) + kitchen_lines._notify_kds() # Notify POS that order was confirmed if self.config_id: @@ -111,6 +109,32 @@ class PosOrder(models.Model): _logger.info("Online order %s confirmed and sent to KDS", self.name) return True + def action_cook_online_order(self): + """Chef starts cooking the online order""" + self.ensure_one() + self.write({'online_order_status': 'cooking'}) + kitchen_lines = self.lines.filtered( + lambda l: (l.product_id.is_kitchen_item or l.product_id.type != 'service') and l.product_id.name not in ['Tips', 'Discount', 'Standard delivery'] + ) + if kitchen_lines: + kitchen_lines.write({'preparation_status': 'preparing'}) + kitchen_lines._notify_kds() + _logger.info("Online order %s marked cooking in KDS", self.name) + return True + + def action_deliver_online_order(self): + """Kitchen marks the online order ready / served""" + self.ensure_one() + self.write({'online_order_status': 'delivered'}) + kitchen_lines = self.lines.filtered( + lambda l: (l.product_id.is_kitchen_item or l.product_id.type != 'service') and l.product_id.name not in ['Tips', 'Discount', 'Standard delivery'] + ) + if kitchen_lines: + kitchen_lines.write({'preparation_status': 'ready'}) + kitchen_lines._notify_kds() + _logger.info("Online order %s marked ready/delivered in KDS", self.name) + return True + def action_reject_online_order(self): """Cashier rejects the online order""" self.ensure_one() diff --git a/addons/dine360_online_orders/models/sale_order.py b/addons/dine360_online_orders/models/sale_order.py index ea1dcbe..85aac1b 100644 --- a/addons/dine360_online_orders/models/sale_order.py +++ b/addons/dine360_online_orders/models/sale_order.py @@ -42,25 +42,29 @@ class SaleOrderOnline(models.Model): online_order_status = fields.Selection([ ('pending', 'Pending Kitchen'), ('confirmed', 'Confirmed'), + ('cooking', 'Cooking'), + ('delivered', 'Delivered'), ('rejected', 'Rejected'), - ], string='Online Order Status', compute='_compute_online_order_status', store=True) + ], string='Online Order Status', compute='_compute_online_order_status', store=True, readonly=False) is_online_order_accepted_manually = fields.Boolean(string='Manually Accepted', default=False) @api.depends('pos_order_id.online_order_status', 'state', 'order_source', 'is_online_order_accepted_manually') def _compute_online_order_status(self): for order in self: - if order.pos_order_id: + if order.pos_order_id and order.pos_order_id.online_order_status: order.online_order_status = order.pos_order_id.online_order_status elif order.state == 'cancel': order.online_order_status = 'rejected' elif order.order_source == 'online' and order.state in ['draft', 'sent', 'sale']: - if order.is_online_order_accepted_manually: + if order.online_order_status in ['cooking', 'delivered']: + continue + elif order.is_online_order_accepted_manually: order.online_order_status = 'confirmed' else: order.online_order_status = 'pending' else: - order.online_order_status = False + order.online_order_status = order.online_order_status or False def action_accept_online_order(self): for order in self: @@ -82,6 +86,20 @@ class SaleOrderOnline(models.Model): order._compute_online_order_status() return {'type': 'ir.actions.client', 'tag': 'reload'} + def action_cook_online_order(self): + for order in self: + order.online_order_status = 'cooking' + if order.pos_order_id: + order.pos_order_id.action_cook_online_order() + return True + + def action_deliver_online_order(self): + for order in self: + order.online_order_status = 'delivered' + if order.pos_order_id: + order.pos_order_id.action_deliver_online_order() + return True + def action_reject_online_order(self): for order in self: if order.state in ['draft', 'sent', 'sale']: