diff --git a/table_reservation_on_website/README.rst b/table_reservation_on_website/README.rst index fa402a0ba..29e94c902 100644 --- a/table_reservation_on_website/README.rst +++ b/table_reservation_on_website/README.rst @@ -8,7 +8,7 @@ This module allows to reserve tables in POS and website. Configuration ============= -* No additional configurations needed.z +* No additional configurations needed. Company ------- diff --git a/table_reservation_on_website/controllers/table_reservation_on_website.py b/table_reservation_on_website/controllers/table_reservation_on_website.py index d306944b7..e58f7e818 100644 --- a/table_reservation_on_website/controllers/table_reservation_on_website.py +++ b/table_reservation_on_website/controllers/table_reservation_on_website.py @@ -199,7 +199,7 @@ class TableReservation(http.Controller): '' '
' 'Dear' + ' ' + request.env.user.name + ',' '
''
' - 'Your table booking at ' + request.env['restaurant.floor'].browse(int(kwargs.get('floors'))).name + ' ' + 'has been confirmed on '+str(reservation.date)+' for '+reservation.starting_at+' to '+reservation.ending_at + '.' + final_sentence + + 'Your table booking at ' + request.env['restaurant.floor'].sudo().browse(int(kwargs.get('floors'))).name + ' ' + 'has been confirmed on '+str(reservation.date)+' for '+reservation.starting_at+' to '+reservation.ending_at + '.' + final_sentence + '
''
' '' '
' diff --git a/table_reservation_on_website/controllers/table_reservation_on_website_website_sale.py b/table_reservation_on_website/controllers/table_reservation_on_website_website_sale.py index 36975fcc4..a01e0d714 100644 --- a/table_reservation_on_website/controllers/table_reservation_on_website_website_sale.py +++ b/table_reservation_on_website/controllers/table_reservation_on_website_website_sale.py @@ -106,7 +106,7 @@ class WebsiteSalePayment(WebsiteSale): '' '
' 'Dear' + ' ' + request.env.user.name + ',' '
''
' - 'Your table booking at ' + request.env['restaurant.floor'].browse(int(order.floors)).name + ' ' + 'has been confirmed on '+str(reservation.date)+' for '+reservation.starting_at+' to '+reservation.ending_at + '.' + final_sentence + + 'Your table booking at ' + request.env['restaurant.floor'].sudo().browse(int(order.floors)).name + ' ' + 'has been confirmed on '+str(reservation.date)+' for '+reservation.starting_at+' to '+reservation.ending_at + '.' + final_sentence + '
''
' '' '
' diff --git a/table_reservation_on_website/models/pos_config.py b/table_reservation_on_website/models/pos_config.py index 9788b55cc..758e845ef 100644 --- a/table_reservation_on_website/models/pos_config.py +++ b/table_reservation_on_website/models/pos_config.py @@ -36,6 +36,8 @@ class PosConfig(models.Model): string="Reservation Charge", compute="_compute_has_reservation_charge", help="Enable to apply charge for reservations.") + is_paid = fields.Boolean(string="Is paid reservation", + help="To identify if the reservation is already paid") def _compute_has_lead_time(self): """ To check whether lead time is enabled from settings """ diff --git a/table_reservation_on_website/models/table_reservation.py b/table_reservation_on_website/models/table_reservation.py index d142793e7..ff55cdf37 100644 --- a/table_reservation_on_website/models/table_reservation.py +++ b/table_reservation_on_website/models/table_reservation.py @@ -20,9 +20,11 @@ # ############################################################################### from datetime import date, datetime, timedelta -import re +import pytz, re +from pytz import timezone from odoo import api, fields, models, _ -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError +from odoo.tools.populate import compute class TableReservation(models.Model): @@ -39,9 +41,13 @@ class TableReservation(models.Model): floor_id = fields.Many2one(comodel_name='restaurant.floor', string="Floor Plan", help="Booked floor", required=True) - booked_tables_ids = fields.Many2many(comodel_name='restaurant.table', - string="Tables", required=True, - help="Booked tables") + available_tables = fields.Many2many( + 'restaurant.table', 'available_tables_rel', + string="Tables", store=True, compute="_compute_available_tables") + booked_tables_ids = fields.Many2many( + comodel_name='restaurant.table', relation='booked_tables_rel', + string="Tables", domain=lambda self: "["f"('id', 'in', available_tables)]", + required=True, help="Booked tables") date = fields.Date(string="Date", help="Date of reservation", required=True) starting_at = fields.Char(string="Starting At", @@ -85,6 +91,32 @@ class TableReservation(models.Model): rec.lead_time = lead_times rec.lead_time_computed = True + @api.depends('floor_id', 'date', 'starting_at', 'ending_at') + def _compute_available_tables(self): + """ Compute available non reserved tables in the selected floor """ + if self.floor_id: + for record in self: + tables = self.env['restaurant.table'].search([('floor_id', '=', + self.floor_id.id)]) + table_inbetween = [] + reserved = self.search([('floor_id', '=', self.floor_id.id), + ('date', '=', self.date), + ('state', '=', 'reserved')]) + if record.starting_at: + start_time_new = datetime.strptime( + self.starting_at, "%H:%M").time() + for rec in reserved: + start_at = datetime.strptime(rec.starting_at, "%H:%M").time() + end_at = datetime.strptime(rec.ending_at, "%H:%M").time() + if start_at <= start_time_new <= end_at: + for table in rec.booked_tables_ids: + table_inbetween.append(table.id) + table_floor = [rec.id for rec in tables if + rec.id not in table_inbetween] + record.available_tables = [(6, 0, table_floor)] + else: + tables = self.env['restaurant.table'].browse([]) + self.available_tables = [(6, 0, [table.id for table in tables])] @api.model def create(self, vals): """ Super create function to add sequence number """ @@ -107,29 +139,6 @@ class TableReservation(models.Model): raise UserError(_("Invalid time format! [ " "format HH:MM]")) - @api.onchange("floor_id") - def _onchange_floor_id(self): - """ To show the tables corresponding the floor """ - tables = self.env['restaurant.table'].search([('floor_id', '=', - self.floor_id.id)]) - table_inbetween = [] - reserved = self.search([('floor_id', '=', self.floor_id.id), - ('date', '=', self.date), - ('state', '=', 'reserved')]) - if self.starting_at: - start_time_new = datetime.strptime( - self.starting_at, "%H:%M").time() - for rec in reserved: - start_at = datetime.strptime(rec.starting_at, "%H:%M").time() - end_at = datetime.strptime(rec.ending_at, "%H:%M").time() - if start_at <= start_time_new <= end_at: - for table in rec.booked_tables_ids: - table_inbetween.append(table.id) - table_floor = [rec.id for rec in tables if - rec.id not in table_inbetween] - domain = [('id', 'in', table_floor)] - return {'domain': {'booked_tables_ids': domain}} - @api.depends("booked_tables_ids") def _compute_booking_amount(self): """ For computing the booking amount """ @@ -169,6 +178,11 @@ class TableReservation(models.Model): ('state', '=', 'reserved')]) return reservations + @api.constrains('date', 'starting_at', 'ending_at') + def _onchange_date(self): + if self.date < datetime.now().date(): + raise ValidationError(_("You can't select a past date.")) + @api.model def edit_reservations(self, booking_id, date, customer, start_time, end_time, floor, table_ids, lead, order_name=None): @@ -347,3 +361,11 @@ class TableReservation(models.Model): res.update({ 'state': 'cancel' }) + + @api.model + def add_payment(self, table_id, floor_id): + """ Add payment to the table reservations from POS. """ + selected_table = self.env['restaurant.table'].search([ + ('id', '=', table_id), ('floor_id', '=', floor_id)]) + product_id = self.env.ref('table_reservation_on_website.product_product_table_booking_pos') + return {'product': product_id.id, 'rate': selected_table.rate} diff --git a/table_reservation_on_website/static/src/app/booking_popup/createBookingPopup.js b/table_reservation_on_website/static/src/app/booking_popup/createBookingPopup.js index 8ed345414..d14932d2a 100644 --- a/table_reservation_on_website/static/src/app/booking_popup/createBookingPopup.js +++ b/table_reservation_on_website/static/src/app/booking_popup/createBookingPopup.js @@ -187,13 +187,12 @@ export class createBookingPopup extends AbstractAwaitablePopup { this.state.Table, this.state.date, this.state.start_time, this.state.end_time, this.state.partner, this.state.lead_time, this.state.floor, this.pos.get_order().name]) this.cancel(); - this.pos.showScreen('ProductScreen'); - var product = this.pos.db.product_by_id[data] - product['lst_price'] = this.state.amount - this.pos.get_order().set_partner(this.pos.db.partner_by_id[parseInt(this.state.partner)]) - this.pos.get_order().add_product(product, { - quantity: 1, - }); +// this.pos.showScreen('ProductScreen'); +// var product = this.pos.db.product_by_id[data] +// product['lst_price'] = this.state.amount +// this.pos.get_order().add_product(product, { +// quantity: 1, +// }); } else{ this.popup.add(ErrorPopup, { diff --git a/table_reservation_on_website/static/src/app/screens/floor_screen/floor_screen.js b/table_reservation_on_website/static/src/app/screens/floor_screen/floor_screen.js index f6dd2b26b..03ba78ad4 100644 --- a/table_reservation_on_website/static/src/app/screens/floor_screen/floor_screen.js +++ b/table_reservation_on_website/static/src/app/screens/floor_screen/floor_screen.js @@ -7,7 +7,7 @@ patch(FloorScreen.prototype, { super.setup(...arguments); await this.fetchActiveTables(); }, - /** + /** onSelectTable For showing reserved tables in pos floor screen **/ async fetchActiveTables() { @@ -25,7 +25,6 @@ patch(FloorScreen.prototype, { reserved_tables.forEach(function(record) { record.reserved = true; }); - } catch (error) { console.error('Error fetching active tables:', error); } @@ -33,5 +32,56 @@ patch(FloorScreen.prototype, { get activeTables() { this.fetchActiveTables(); return this.activeFloor ? this.activeFloor.tables : null; + }, + async onSelectTable(table, ev) { +// if (table['reserved'] == true){ +// console.log("hello welcome", this.env.services.pos) +// var data = await this.orm.call('table.reservation', 'add_payment', [table.id, table.floor.id]) +// const current_order = this.pos.get_order(); +// console.log("prod", current_order) +// if (this.pos.get_order){ +// } +// this.pos.get_order().add_product(product, { +// quantity: 1, +// }); +// } + if (this.pos.isEditMode) { + if (ev.ctrlKey || ev.metaKey) { + this.state.selectedTableIds.push(table.id); + } else { + this.state.selectedTableIds = []; + this.state.selectedTableIds.push(table.id); + } + } else { + if (this.pos.orderToTransfer && table.order_count > 0) { + const { confirmed } = await this.popup.add(ConfirmPopup, { + title: _t("Table is not empty"), + body: _t( + "The table already contains an order. Do you want to proceed and transfer the order here?" + ), + confirmText: _t("Yes"), + }); + if (!confirmed) { + // We don't want to change the table if the transfer is not done. + table = this.pos.tables_by_id[this.pos.orderToTransfer.tableId]; + this.pos.orderToTransfer = null; + } + } + if (this.pos.orderToTransfer) { + await this.pos.transferTable(table); + } else { + try { + await this.pos.setTable(table); + } catch (e) { + if (!(e instanceof ConnectionLostError)) { + throw e; + } + // Reject error in a separate stack to display the offline popup, but continue the flow + Promise.reject(e); + } + } + const order = this.pos.get_order(); + this.pos.showScreen(order.get_screen_data().name); + } } }); diff --git a/table_reservation_on_website/static/src/app/screens/product_screen/product_screen.js b/table_reservation_on_website/static/src/app/screens/product_screen/product_screen.js index d532304f5..c97e9e08f 100644 --- a/table_reservation_on_website/static/src/app/screens/product_screen/product_screen.js +++ b/table_reservation_on_website/static/src/app/screens/product_screen/product_screen.js @@ -1,10 +1,34 @@ /** @odoo-module */ import { patch } from "@web/core/utils/patch"; import { ProductScreen } from "@point_of_sale/app/screens/product_screen/product_screen"; +let productDetails = []; patch(ProductScreen.prototype, { // Override the bookTable function for displaying and booking of tables bookTable() { this.pos.showScreen("ReservationsScreen"); }, + get currentOrder() { + let productDetails = []; + const current_order = this.pos.get_order(); + if (current_order.pos.table['reserved'] == true && current_order.orderlines.length == 0){ + var data = this.orm.call('table.reservation', 'add_payment', [current_order.pos.table.id, current_order.pos.table.floor.id]) + data.then(result => { + productDetails.push({ + product_id: result.product, + rate: result.rate + }); + // Adding payment to the table during the reservation + var product = this.pos.db.product_by_id[productDetails[0].product_id] + product['lst_price'] = productDetails[0].rate + if (current_order.orderlines.length == 0){ + console.log('prodsss', product['lst_price']) + this.pos.get_order().add_product(product, { + quantity: 1, + }); + } + }) + } + return this.pos.get_order(); + } }); diff --git a/table_reservation_on_website/views/table_reservation_views.xml b/table_reservation_on_website/views/table_reservation_views.xml index a69ae8daf..f6babbcd7 100644 --- a/table_reservation_on_website/views/table_reservation_views.xml +++ b/table_reservation_on_website/views/table_reservation_views.xml @@ -49,6 +49,7 @@ +