diff --git a/addons/dine360_kds/__init__.py b/addons/dine360_kds/__init__.py new file mode 100644 index 0000000..0650744 --- /dev/null +++ b/addons/dine360_kds/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/addons/dine360_kds/__manifest__.py b/addons/dine360_kds/__manifest__.py new file mode 100644 index 0000000..541dd54 --- /dev/null +++ b/addons/dine360_kds/__manifest__.py @@ -0,0 +1,30 @@ +{ + 'name': 'Dine360 Kitchen Display System', + 'version': '1.0', + 'category': 'Sales/Point of Sale', + 'summary': 'Dedicated KDS for Restaurant Kitchen', + 'description': """ + Professional Kitchen Display System: + - Real-time order tracking + - Preparation status management + - Cooking time tracking + - Kanban dashboard for chefs + - Floor/Table based organization + """, + 'author': 'Dine360', + 'depends': ['point_of_sale', 'pos_restaurant', 'dine360_restaurant'], + 'data': [ + 'security/ir.model.access.csv', + 'views/pos_order_line_views.xml', + 'views/product_views.xml', + 'views/kds_menus.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'dine360_kds/static/src/css/kds_style.css', + ], + }, + 'installable': True, + 'application': True, + 'license': 'LGPL-3', +} diff --git a/addons/dine360_kds/models/__init__.py b/addons/dine360_kds/models/__init__.py new file mode 100644 index 0000000..0c6d361 --- /dev/null +++ b/addons/dine360_kds/models/__init__.py @@ -0,0 +1,2 @@ +from . import pos_order_line +from . import product diff --git a/addons/dine360_kds/models/pos_order_line.py b/addons/dine360_kds/models/pos_order_line.py new file mode 100644 index 0000000..3771477 --- /dev/null +++ b/addons/dine360_kds/models/pos_order_line.py @@ -0,0 +1,46 @@ +from odoo import models, fields, api, _ + +class PosOrderLine(models.Model): + _inherit = 'pos.order.line' + + preparation_status = fields.Selection([ + ('waiting', 'Waiting'), + ('preparing', 'Preparing'), + ('ready', 'Ready'), + ('served', 'Served'), + ('cancelled', 'Cancelled') + ], string='Preparation Status', default='waiting', tracking=True) + + color = fields.Integer(string='Color', default=0) + preparation_time_start = fields.Datetime(string='Start Time') + preparation_time_end = fields.Datetime(string='Ready Time') + cooking_time = fields.Integer(string='Cooking Time (min)', compute='_compute_cooking_time', store=True) + + table_id = fields.Many2one('restaurant.table', related='order_id.table_id', string='Table', store=True) + floor_id = fields.Many2one('restaurant.floor', related='order_id.table_id.floor_id', string='Floor', store=True) + + @api.depends('preparation_time_start', 'preparation_time_end') + def _compute_cooking_time(self): + for line in self: + if line.preparation_time_start and line.preparation_time_end: + diff = line.preparation_time_end - line.preparation_time_start + line.cooking_time = int(diff.total_seconds() / 60) + else: + line.cooking_time = 0 + + def action_start_preparing(self): + self.write({ + 'preparation_status': 'preparing', + 'preparation_time_start': fields.Datetime.now() + }) + + def action_mark_ready(self): + self.write({ + 'preparation_status': 'ready', + 'preparation_time_end': fields.Datetime.now() + }) + + def action_mark_served(self): + self.write({ + 'preparation_status': 'served' + }) diff --git a/addons/dine360_kds/models/product.py b/addons/dine360_kds/models/product.py new file mode 100644 index 0000000..008b5b3 --- /dev/null +++ b/addons/dine360_kds/models/product.py @@ -0,0 +1,10 @@ +from odoo import models, fields + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + is_kitchen_item = fields.Boolean( + string='Show in KDS', + default=True, + help="If checked, this product will appear in the Kitchen Display System when ordered." + ) diff --git a/addons/dine360_kds/security/ir.model.access.csv b/addons/dine360_kds/security/ir.model.access.csv new file mode 100644 index 0000000..4cad7d3 --- /dev/null +++ b/addons/dine360_kds/security/ir.model.access.csv @@ -0,0 +1,4 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_kds_order_line_kitchen,pos.order.line.kitchen,point_of_sale.model_pos_order_line,dine360_restaurant.group_restaurant_kitchen,1,1,0,0 +access_kds_order_line_manager,pos.order.line.manager,point_of_sale.model_pos_order_line,dine360_restaurant.group_restaurant_manager,1,1,1,1 +access_kds_order_line_user,pos.order.line.user,point_of_sale.model_pos_order_line,base.group_user,1,1,1,0 diff --git a/addons/dine360_kds/static/src/css/kds_style.css b/addons/dine360_kds/static/src/css/kds_style.css new file mode 100644 index 0000000..c9d5f32 --- /dev/null +++ b/addons/dine360_kds/static/src/css/kds_style.css @@ -0,0 +1,49 @@ +.role_kitchen_card { + transition: transform 0.2s ease, box-shadow 0.2s ease; + cursor: default !important; +} + +.role_kitchen_card:hover { + transform: translateY(-2px); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1) !important; +} + +.o_kanban_group { + background-color: #f4f7fa !important; + border-radius: 15px !important; + margin: 10px !important; + padding: 10px !important; +} + +.o_kanban_header { + background: transparent !important; + padding: 15px 10px !important; +} + +.o_kanban_header_title { + font-weight: 700 !important; + text-transform: uppercase !important; + letter-spacing: 1px !important; +} + +/* Specific colors for status columns */ +.o_kanban_group[data-id="waiting"] .o_kanban_header_title { + color: #f0ad4e; +} + +.o_kanban_group[data-id="preparing"] .o_kanban_header_title { + color: #5bc0de; +} + +.o_kanban_group[data-id="ready"] .o_kanban_header_title { + color: #5cb85c; +} + +.o_kanban_group[data-id="served"] .o_kanban_header_title { + color: #777; +} + +.badge.rounded-pill { + padding: 0.5em 1em; + font-weight: 600; +} \ No newline at end of file diff --git a/addons/dine360_kds/views/kds_menus.xml b/addons/dine360_kds/views/kds_menus.xml new file mode 100644 index 0000000..3f82300 --- /dev/null +++ b/addons/dine360_kds/views/kds_menus.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/addons/dine360_kds/views/pos_order_line_views.xml b/addons/dine360_kds/views/pos_order_line_views.xml new file mode 100644 index 0000000..b246f31 --- /dev/null +++ b/addons/dine360_kds/views/pos_order_line_views.xml @@ -0,0 +1,138 @@ + + + + pos.order.line.kds.kanban + pos.order.line + + + + + + + + + + + + + + + + + + + x + + + + + + + + + + + + Note: + + + + + + + + + + + + + + + + + Start Cooking + + + Mark Ready + + + Served + + + + + + + + + + + + + + pos.order.line.kds.tree + pos.order.line + + + + + + + + + + + + + + + + + pos.order.line.kds.search + pos.order.line + + + + + + + + + + + + + + + + + + + + + + + + + Kitchen Display System + pos.order.line + kanban,tree,form + [('product_id.is_kitchen_item', '=', True)] + + {'search_default_in_progress': 1, 'search_default_group_status': 1} + + + Welcome to the Kitchen! + + + Orders sent from the POS will appear here for preparation. + + + + diff --git a/addons/dine360_kds/views/product_views.xml b/addons/dine360_kds/views/product_views.xml new file mode 100644 index 0000000..0566568 --- /dev/null +++ b/addons/dine360_kds/views/product_views.xml @@ -0,0 +1,13 @@ + + + + product.template.form.kds + product.template + + + + + + + + diff --git a/addons/dine360_restaurant/models/__pycache__/__init__.cpython-310.pyc b/addons/dine360_restaurant/models/__pycache__/__init__.cpython-310.pyc index be10abf..0ef01d4 100644 Binary files a/addons/dine360_restaurant/models/__pycache__/__init__.cpython-310.pyc and b/addons/dine360_restaurant/models/__pycache__/__init__.cpython-310.pyc differ
+ Welcome to the Kitchen! +
+ Orders sent from the POS will appear here for preparation. +