| @ -0,0 +1,46 @@ | |||||
|  | .. image:: https://img.shields.io/badge/license-LGPL--3-green.svg | ||||
|  |     :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html | ||||
|  |     :alt: License: LGPL-3 | ||||
|  | 
 | ||||
|  | Hotel Management | ||||
|  | ================ | ||||
|  |  A complete Hotel Management System that cover all areas of hotel services. | ||||
|  | 
 | ||||
|  | Configuration | ||||
|  | ============= | ||||
|  | * No additional configurations needed | ||||
|  | 
 | ||||
|  | License | ||||
|  | ------- | ||||
|  | General Public License, Version 3 (LGPL v3). | ||||
|  | https://www.gnu.org/licenses/lgpl-3.0-standalone.html | ||||
|  | 
 | ||||
|  | Company | ||||
|  | ------- | ||||
|  | * `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | ||||
|  | 
 | ||||
|  | Credits | ||||
|  | ------- | ||||
|  | * Developer:(V16) Unnimaya C O, Contact: odoo@cybrosys.com | ||||
|  | 
 | ||||
|  | Contacts | ||||
|  | -------- | ||||
|  | * Mail Contact : odoo@cybrosys.com | ||||
|  | * Website : https://cybrosys.com | ||||
|  | 
 | ||||
|  | Bug Tracker | ||||
|  | ----------- | ||||
|  | Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. | ||||
|  | 
 | ||||
|  | Maintainer | ||||
|  | ========== | ||||
|  | .. image:: https://cybrosys.com/images/logo.png | ||||
|  |    :target: https://cybrosys.com | ||||
|  | 
 | ||||
|  | This module is maintained by Cybrosys Technologies. | ||||
|  | 
 | ||||
|  | For support and more information, please visit `Our Website <https://cybrosys.com/>`__ | ||||
|  | 
 | ||||
|  | Further information | ||||
|  | =================== | ||||
|  | HTML Description: `<static/description/index.html>`__ | ||||
| @ -0,0 +1,24 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from . import controllers | ||||
|  | from . import models | ||||
|  | from . import wizard | ||||
| @ -0,0 +1,75 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | { | ||||
|  |     'name': 'Hotel Management', | ||||
|  |     'version': '16.0.1.0.0', | ||||
|  |     'category': 'Industries', | ||||
|  |     'summary': """A complete Hotel Management System that cover all areas of  | ||||
|  |      Hotel services""" , | ||||
|  |     'description': """The module helps you to manage rooms, amenities,  | ||||
|  |      services, food, events and vehicles. End Users can book rooms and reserve  | ||||
|  |      foods from hotel.""", | ||||
|  |     'author': 'Cybrosys Techno Solutions', | ||||
|  |     'company': 'Cybrosys Techno Solutions', | ||||
|  |     'maintainer': 'Cybrosys Techno Solutions', | ||||
|  |     'website': 'https://www.cybrosys.com', | ||||
|  |     'depends': ['account', 'event', 'fleet', 'lunch'], | ||||
|  |     'data': [ | ||||
|  |         'security/hotel_management_odoo_groups.xml', | ||||
|  |         'security/hotel_management_odoo_security.xml', | ||||
|  |         'security/ir.model.access.csv', | ||||
|  |         'data/ir_data_sequence.xml', | ||||
|  |         'views/account_move_views.xml', | ||||
|  |         'views/hotel_menu_views.xml', | ||||
|  |         'views/hotel_amenity_views.xml', | ||||
|  |         'views/hotel_service_views.xml', | ||||
|  |         'views/hotel_floor_views.xml', | ||||
|  |         'views/hotel_room_views.xml', | ||||
|  |         'views/lunch_product_views.xml', | ||||
|  |         'views/fleet_vehicle_model_views.xml', | ||||
|  |         'views/room_booking_views.xml', | ||||
|  |         'views/maintenance_team_views.xml', | ||||
|  |         'views/maintenance_request_views.xml', | ||||
|  |         'views/cleaning_team_views.xml', | ||||
|  |         'views/cleaning_request_views.xml', | ||||
|  |         'views/food_booking_line_views.xml', | ||||
|  |         'views/dashboard_view.xml', | ||||
|  |         'wizard/room_booking_detail_views.xml', | ||||
|  |         'wizard/sale_order_detail_views.xml', | ||||
|  |         'views/reporting_views.xml', | ||||
|  |         'report/room_booking_reports.xml', | ||||
|  |         'report/sale_order_reports.xml', | ||||
|  |     ], | ||||
|  |     'assets': { | ||||
|  |         'web.assets_backend': [ | ||||
|  |             'hotel_management_odoo/static/src/js/action_manager.js', | ||||
|  |             'hotel_management_odoo/static/src/css/dashboard.css', | ||||
|  |             'hotel_management_odoo/static/src/js/dashboard_action.js', | ||||
|  |             'hotel_management_odoo/static/src/xml/dashboard_templates.xml', | ||||
|  |         ], | ||||
|  |     }, | ||||
|  |     'images': ['static/description/banner.jpg'], | ||||
|  |     'license': 'LGPL-3', | ||||
|  |     'installable': True, | ||||
|  |     'auto_install': False, | ||||
|  |     'application': True, | ||||
|  | } | ||||
| @ -0,0 +1,22 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from . import hotel_management_odoo | ||||
| @ -0,0 +1,56 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | import json | ||||
|  | from odoo import http | ||||
|  | from odoo.http import content_disposition, request | ||||
|  | from odoo.tools import html_escape | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class XLSXReportController(http.Controller): | ||||
|  |     """Controller for XlsX report""" | ||||
|  | 
 | ||||
|  |     @http.route('/xlsx_reports', type='http', auth='user', | ||||
|  |                 methods=['POST'], csrf=False) | ||||
|  |     def get_room_booking_report_xlsx(self, model, options, output_format, | ||||
|  |                                      report_name): | ||||
|  |         """Function for generating xlsx report""" | ||||
|  |         report_obj = request.env[model].sudo() | ||||
|  |         options = json.loads(options) | ||||
|  |         try: | ||||
|  |             if output_format == 'xlsx': | ||||
|  |                 response = request.make_response( | ||||
|  |                     None, | ||||
|  |                     headers=[('Content-Type', 'application/vnd.ms-excel'), | ||||
|  |                              ('Content-Disposition', | ||||
|  |                               content_disposition(report_name + '.xlsx'))] | ||||
|  |                 ) | ||||
|  |                 report_obj.get_xlsx_report(options, response) | ||||
|  |                 response.set_cookie('fileToken', 'dummy token') | ||||
|  |                 return response | ||||
|  |         except Exception as e: | ||||
|  |             s_error = http.serialize_exception(e) | ||||
|  |             error = { | ||||
|  |                 'code': 200, | ||||
|  |                 'message': 'Odoo Server Error', | ||||
|  |                 'data': s_error | ||||
|  |             } | ||||
|  |             return request.make_response(html_escape(json.dumps(error))) | ||||
| @ -0,0 +1,26 @@ | |||||
|  | <?xml version="1.0" encoding="UTF-8" ?> | ||||
|  | <odoo> | ||||
|  |     <data noupdate="1"> | ||||
|  |         <!--         Room Booking Sequence--> | ||||
|  |         <record id="seq_hotel_folio" model="ir.sequence"> | ||||
|  |             <field name="name">Hotel Folio</field> | ||||
|  |             <field name="code">room.booking</field> | ||||
|  |             <field name="prefix">BOOKING/</field> | ||||
|  |             <field name="padding">5</field> | ||||
|  |         </record> | ||||
|  |         <!--        Cleaning Request sequence--> | ||||
|  |         <record id="seq_cleaning" model="ir.sequence"> | ||||
|  |             <field name="name">Cleaning Request</field> | ||||
|  |             <field name="code">cleaning.request</field> | ||||
|  |             <field name="prefix">CLEANING/</field> | ||||
|  |             <field name="padding">4</field> | ||||
|  |         </record> | ||||
|  |         <!--        Maintenance Request Sequence--> | ||||
|  |         <record id="seq_maintenance" model="ir.sequence"> | ||||
|  |             <field name="name">Maintenance Request</field> | ||||
|  |             <field name="code">maintenance.request</field> | ||||
|  |             <field name="prefix">MNTC/</field> | ||||
|  |             <field name="padding">5</field> | ||||
|  |         </record> | ||||
|  |     </data> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,7 @@ | |||||
|  | ## Module <hotel_management_odoo> | ||||
|  | 
 | ||||
|  | #### 27.11.2023 | ||||
|  | #### Version 16.0.1.0.0 | ||||
|  | #### ADD | ||||
|  | 
 | ||||
|  | - Initial commit for Hotel Management | ||||
| @ -0,0 +1,38 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from . import account_move | ||||
|  | from . import account_move_line | ||||
|  | from . import cleaning_request | ||||
|  | from . import cleaning_team | ||||
|  | from . import event_booking_line | ||||
|  | from . import fleet_booking_line | ||||
|  | from . import fleet_vehicle_model | ||||
|  | from . import food_booking_line | ||||
|  | from . import hotel_amenity | ||||
|  | from . import hotel_floor | ||||
|  | from . import hotel_room | ||||
|  | from . import hotel_service | ||||
|  | from . import maintenance_request | ||||
|  | from . import maintenance_team | ||||
|  | from . import room_booking | ||||
|  | from . import room_booking_line | ||||
|  | from . import service_booking_line | ||||
| @ -0,0 +1,35 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class AccountMove(models.Model): | ||||
|  |     """ | ||||
|  |     Inherited account. move for adding hotel booking reference field to | ||||
|  |     invoicing model. | ||||
|  |     """ | ||||
|  |     _inherit = "account.move" | ||||
|  | 
 | ||||
|  |     hotel_booking_id = fields.Many2one('room.booking', | ||||
|  |                                        string="Booking Reference", | ||||
|  |                                        readonly=True, help="Choose the Booking " | ||||
|  |                                                            "Reference") | ||||
| @ -0,0 +1,37 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class AccountMoveLine(models.Model): | ||||
|  |     """ | ||||
|  |     Adding Product Type field to Account Move Line model. | ||||
|  |     """ | ||||
|  |     _inherit = "account.move.line" | ||||
|  | 
 | ||||
|  |     product_type = fields.Selection([ | ||||
|  |         ('room', 'Room'), | ||||
|  |         ('food', 'Food'), | ||||
|  |         ('event', 'Event'), | ||||
|  |         ('service', 'Service'), | ||||
|  |         ('fleet', 'Fleet') | ||||
|  |     ], string="Product Type", help="Choose the product type") | ||||
| @ -0,0 +1,131 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, _ | ||||
|  | from odoo.exceptions import ValidationError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class CleaningRequest(models.Model): | ||||
|  |     """Class for creating and assigning Cleaning Request""" | ||||
|  |     _name = "cleaning.request" | ||||
|  |     _inherit = ["mail.thread", "mail.activity.mixin"] | ||||
|  |     _rec_name = "sequence" | ||||
|  |     _description = "Cleaning Request" | ||||
|  | 
 | ||||
|  |     sequence = fields.Char(string="Sequence", readonly=True, default='New', | ||||
|  |                            copy=False, tracking=True, | ||||
|  |                            help="Sequence for identifying the request") | ||||
|  |     state = fields.Selection([('draft', 'Draft'), | ||||
|  |                               ('assign', 'Assigned'), | ||||
|  |                               ('ongoing', 'Cleaning'), | ||||
|  |                               ('support', 'Waiting For Support'), | ||||
|  |                               ('done', 'Completed')], | ||||
|  |                              string="State", | ||||
|  |                              default='draft', help="State of cleaning request") | ||||
|  |     cleaning_type = fields.Selection(selection=[('room', 'Room'), | ||||
|  |                                                 ('hotel', 'Hotel'), | ||||
|  |                                                 ('vehicle', 'Vehicle')], | ||||
|  |                                      required=True, tracking=True, | ||||
|  |                                      string="Cleaning Type", | ||||
|  |                                      help="Choose what is to be cleaned") | ||||
|  |     room_id = fields.Many2one('hotel.room', string="Room", | ||||
|  |                               help="Choose the room") | ||||
|  |     hotel = fields.Char(string="Hotel", help="cleaning request space in hotel") | ||||
|  |     vehicle_id = fields.Many2one('fleet.vehicle.model', | ||||
|  |                                  string="Vehicle", | ||||
|  |                                  help="Cleaning request from vehicle") | ||||
|  |     support_team_ids = fields.Many2many('res.users', | ||||
|  |                                         string="Support Team", | ||||
|  |                                         help="Support team members") | ||||
|  |     support_reason = fields.Char(string='Support', help="Support Reason") | ||||
|  |     description = fields.Char(string="Description", | ||||
|  |                               help="Description about the cleaning") | ||||
|  |     team_id = fields.Many2one('cleaning.team', string="Team", | ||||
|  |                               required=True, | ||||
|  |                               tracking=True, | ||||
|  |                               help="Choose the team") | ||||
|  |     head_id = fields.Many2one('res.users', string="Head", | ||||
|  |                               related='team_id.team_head_id', | ||||
|  |                               help="Head of cleaning team") | ||||
|  |     assigned_id = fields.Many2one('res.users', string="Assigned To", | ||||
|  |                                   help="The team member to whom the request is " | ||||
|  |                                        "Assigned To") | ||||
|  |     domain_partner_ids = fields.Many2many('res.partner', | ||||
|  |                                           string="Domain Partner", | ||||
|  |                                           help="Choose the Domain Partner") | ||||
|  | 
 | ||||
|  |     @api.model | ||||
|  |     def create(self, vals_list): | ||||
|  |         """Sequence Generation""" | ||||
|  |         if vals_list.get('sequence', 'New') == 'New': | ||||
|  |             vals_list['sequence'] = self.env['ir.sequence'].next_by_code( | ||||
|  |                 'cleaning.request') | ||||
|  |         return super().create(vals_list) | ||||
|  | 
 | ||||
|  |     @api.onchange('team_id') | ||||
|  |     def _onchange_team_id(self): | ||||
|  |         """Function for updating the domain partner ids""" | ||||
|  |         self.update( | ||||
|  |             {'domain_partner_ids': self.team_id.member_ids.ids}) | ||||
|  | 
 | ||||
|  |     def action_assign_cleaning(self): | ||||
|  |         """Button action for updating the state to assign""" | ||||
|  |         self.update({'state': 'assign'}) | ||||
|  | 
 | ||||
|  |     def action_start_cleaning(self): | ||||
|  |         """Button action for updating the state to ongoing""" | ||||
|  |         self.write({'state': 'ongoing'}) | ||||
|  | 
 | ||||
|  |     def action_done_cleaning(self): | ||||
|  |         """Button action for  updating the state to done""" | ||||
|  |         self.write({'state': 'done'}) | ||||
|  | 
 | ||||
|  |     def action_assign_support(self): | ||||
|  |         """Button action for updating the state to support""" | ||||
|  |         if self.support_reason: | ||||
|  |             self.write({'state': 'support'}) | ||||
|  |         else: | ||||
|  |             raise ValidationError(_('Please enter the reason')) | ||||
|  | 
 | ||||
|  |     def action_assign_assign_support(self): | ||||
|  |         """Button action for updating the state to ongoing""" | ||||
|  |         if self.support_team_ids: | ||||
|  |             self.write({'state': 'ongoing'}) | ||||
|  |         else: | ||||
|  |             raise ValidationError(_('Please choose a support')) | ||||
|  | 
 | ||||
|  |     def action_maintain_request(self): | ||||
|  |         """Button action for creating the maintenance request""" | ||||
|  |         self.env['maintenance.request'].sudo().create({ | ||||
|  |             'date': fields.Date.today(), | ||||
|  |             'state': 'draft', | ||||
|  |             'type': self.cleaning_type, | ||||
|  |             'vehicle_maintenance_id': self.vehicle_id.id | ||||
|  |         }) | ||||
|  |         return { | ||||
|  |             'type': 'ir.actions.client', | ||||
|  |             'tag': 'display_notification', | ||||
|  |             'params': { | ||||
|  |                 'type': 'success', | ||||
|  |                 'message': "Maintenance Request Sent Successfully", | ||||
|  |                 'next': {'type': 'ir.actions.act_window_close'}, | ||||
|  |             } | ||||
|  |         } | ||||
| @ -0,0 +1,43 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class CleaningTeam(models.Model): | ||||
|  |     """ Model for creating Cleaning team and assigns Cleaning requests to | ||||
|  |     each team""" | ||||
|  |     _name = "cleaning.team" | ||||
|  |     _description = "Cleaning Team" | ||||
|  | 
 | ||||
|  |     name = fields.Char(string="Team Name", help="Name of the Team") | ||||
|  |     team_head_id = fields.Many2one('res.users', string="Team Head", | ||||
|  |                                    help="Choose the Team Head", | ||||
|  |                                    domain=lambda self: [ | ||||
|  |                                        ('groups_id', 'in', self.env.ref( | ||||
|  |                                            'hotel_management_odoo.' | ||||
|  |                                            'cleaning_team_group_head').id)]) | ||||
|  |     member_ids = fields.Many2many('res.users', string="Member", | ||||
|  |                                   domain=lambda self: [ | ||||
|  |                                       ('groups_id', 'in', self.env.ref( | ||||
|  |                                           'hotel_management_odoo.' | ||||
|  |                                           'cleaning_team_group_user').id)], | ||||
|  |                                   help="Team Members") | ||||
| @ -0,0 +1,123 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, tools | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class EventBookingLine(models.Model): | ||||
|  |     """Model that handles the event booking form""" | ||||
|  |     _name = "event.booking.line" | ||||
|  |     _description = "Hotel Event Line" | ||||
|  |     _rec_name = 'event_id' | ||||
|  | 
 | ||||
|  |     booking_id = fields.Many2one("room.booking", string="Booking", | ||||
|  |                                  help="Choose room booking reference", | ||||
|  |                                  ondelete="cascade") | ||||
|  |     event_id = fields.Many2one('event.event', string="Event", | ||||
|  |                                help="Choose the Event") | ||||
|  |     ticket_id = fields.Many2one('product.product', string="Ticket", | ||||
|  |                                 help="Choose the Ticket Type", | ||||
|  |                                 domain=[('detailed_type', '=', 'event')]) | ||||
|  |     description = fields.Char(string='Description', help="Detailed " | ||||
|  |                                                          "description of the " | ||||
|  |                                                          "event", | ||||
|  |                               related='event_id.display_name') | ||||
|  |     uom_qty = fields.Float(string="Quantity", default=1, | ||||
|  |                            help="The quantity converted into the UoM used by " | ||||
|  |                                 "the product") | ||||
|  |     uom_id = fields.Many2one('uom.uom', readonly=True, | ||||
|  |                              string="Unit of Measure", | ||||
|  |                              related='ticket_id.uom_id', help="This will set " | ||||
|  |                                                               "the unit of" | ||||
|  |                                                               " measure used") | ||||
|  |     price_unit = fields.Float(related='ticket_id.lst_price', string='Price', | ||||
|  |                               digits='Product Price', | ||||
|  |                               help="The selling price of the selected ticket.") | ||||
|  |     tax_ids = fields.Many2many('account.tax', | ||||
|  |                                'hotel_event_order_line_taxes_rel', | ||||
|  |                                'event_id', | ||||
|  |                                'tax_id', related='ticket_id.taxes_id', | ||||
|  |                                string='Taxes', | ||||
|  |                                help="Default taxes used when selling the event " | ||||
|  |                                     "tickets.", | ||||
|  |                                domain=[('type_tax_use', '=', 'sale')]) | ||||
|  |     currency_id = fields.Many2one( | ||||
|  |         related='booking_id.pricelist_id.currency_id', string='Currency', | ||||
|  |         help='The currency used', | ||||
|  |         store=True, precompute=True) | ||||
|  |     price_subtotal = fields.Float( | ||||
|  |         string="Subtotal", | ||||
|  |         compute='_compute_price_subtotal', | ||||
|  |         help="Total Price Excluding Tax", | ||||
|  |         store=True) | ||||
|  |     price_tax = fields.Float( | ||||
|  |         string="Total Tax", | ||||
|  |         compute='_compute_price_subtotal', | ||||
|  |         help="Tax Amount", | ||||
|  |         store=True) | ||||
|  |     price_total = fields.Float( | ||||
|  |         string="Total", | ||||
|  |         compute='_compute_price_subtotal', | ||||
|  |         help="Total Price Including Tax") | ||||
|  |     state = fields.Selection( | ||||
|  |         related='booking_id.state', | ||||
|  |         string="Order Status", | ||||
|  |         help="State of Room Booking", | ||||
|  |         copy=False) | ||||
|  | 
 | ||||
|  |     @api.depends('uom_qty', 'price_unit', 'tax_ids') | ||||
|  |     def _compute_price_subtotal(self): | ||||
|  |         """ | ||||
|  |         Compute the amounts of the Event booking line. | ||||
|  |         """ | ||||
|  |         for line in self: | ||||
|  |             tax_results = self.env['account.tax']._compute_taxes( | ||||
|  |                 [line._convert_to_tax_base_line_dict()]) | ||||
|  |             totals = list(tax_results['totals'].values())[0] | ||||
|  |             amount_untaxed = totals['amount_untaxed'] | ||||
|  |             amount_tax = totals['amount_tax'] | ||||
|  |             line.update({ | ||||
|  |                 'price_subtotal': amount_untaxed, | ||||
|  |                 'price_tax': amount_tax, | ||||
|  |                 'price_total': amount_untaxed + amount_tax, | ||||
|  |             }) | ||||
|  |             if self.env.context.get('import_file', | ||||
|  |                                     False) and not self.env.user. \ | ||||
|  |                     user_has_groups('account.group_account_manager'): | ||||
|  |                 line.tax_id.invalidate_recordset( | ||||
|  |                     ['invoice_repartition_line_ids']) | ||||
|  | 
 | ||||
|  |     def _convert_to_tax_base_line_dict(self): | ||||
|  |         """ Convert the current record to a dictionary in order to use the | ||||
|  |         generic taxes computation method | ||||
|  |         defined on account.tax. | ||||
|  |         :return: A python dictionary. | ||||
|  |         """ | ||||
|  |         self.ensure_one() | ||||
|  |         return self.env['account.tax']._convert_to_tax_base_line_dict( | ||||
|  |             self, | ||||
|  |             partner=self.booking_id.partner_id, | ||||
|  |             currency=self.currency_id, | ||||
|  |             taxes=self.tax_ids, | ||||
|  |             price_unit=self.price_unit, | ||||
|  |             quantity=self.uom_qty, | ||||
|  |             price_subtotal=self.price_subtotal, | ||||
|  |         ) | ||||
| @ -0,0 +1,128 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, tools | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class FleetBookingLine(models.Model): | ||||
|  |     """Model that handles the fleet booking""" | ||||
|  |     _name = "fleet.booking.line" | ||||
|  |     _description = "Hotel Fleet Line" | ||||
|  |     _rec_name = 'fleet_id' | ||||
|  | 
 | ||||
|  |     @tools.ormcache() | ||||
|  |     def _get_default_uom_id(self): | ||||
|  |         """Method for getting the default uom id""" | ||||
|  |         return self.env.ref('uom.product_uom_km') | ||||
|  | 
 | ||||
|  |     booking_id = fields.Many2one("room.booking", string="Booking", | ||||
|  |                                  ondelete="cascade", | ||||
|  |                                  help="Shows the room Booking") | ||||
|  |     fleet_id = fields.Many2one('fleet.vehicle.model', | ||||
|  |                                string="Vehicle", | ||||
|  |                                help='Indicates the Vehicle') | ||||
|  |     description = fields.Char(string='Description', | ||||
|  |                               related='fleet_id.display_name', | ||||
|  |                               help="Description of Vehicle") | ||||
|  |     uom_qty = fields.Float(string="Total KM", default=1, | ||||
|  |                            help="The quantity converted into the UoM used by " | ||||
|  |                                 "the product") | ||||
|  |     uom_id = fields.Many2one('uom.uom', readonly=True, | ||||
|  |                              string="Unit of Measure", | ||||
|  |                              default=_get_default_uom_id, help="This will set " | ||||
|  |                                                                "the unit of" | ||||
|  |                                                                " measure used") | ||||
|  |     price_unit = fields.Float(string='Rent/KM', related='fleet_id.price_per_km', | ||||
|  |                               digits='Product Price', | ||||
|  |                               help="The rent/km of the selected fleet.") | ||||
|  |     tax_ids = fields.Many2many('account.tax', | ||||
|  |                                'hotel_fleet_order_line_taxes_rel', | ||||
|  |                                'fleet_id', | ||||
|  |                                'tax_id', string='Taxes', | ||||
|  |                                help="Default taxes used when renting the fleet " | ||||
|  |                                     "models.", | ||||
|  |                                domain=[('type_tax_use', '=', 'sale')]) | ||||
|  |     currency_id = fields.Many2one( | ||||
|  |         related='booking_id.pricelist_id.currency_id', | ||||
|  |         string="Currency", | ||||
|  |         help='The currency used') | ||||
|  |     price_subtotal = fields.Float( | ||||
|  |         string="Subtotal", | ||||
|  |         compute='_compute_price_subtotal', help="Total price excluding tax", | ||||
|  |         store=True) | ||||
|  |     price_tax = fields.Float( | ||||
|  |         string="Total Tax", | ||||
|  |         compute='_compute_price_subtotal', help="Total tax amount", | ||||
|  |         store=True) | ||||
|  |     price_total = fields.Float( | ||||
|  |         string="Total", | ||||
|  |         compute='_compute_price_subtotal', | ||||
|  |         help="Total Price Including Tax", | ||||
|  |         store=True) | ||||
|  |     state = fields.Selection( | ||||
|  |         related='booking_id.state', | ||||
|  |         string="Order Status", | ||||
|  |         help=" Status of the Order", | ||||
|  |         copy=False) | ||||
|  | 
 | ||||
|  |     @api.depends('uom_qty', 'price_unit', 'tax_ids') | ||||
|  |     def _compute_price_subtotal(self): | ||||
|  |         """ | ||||
|  |         Compute the amounts of the room booking line. | ||||
|  |         """ | ||||
|  |         for line in self: | ||||
|  |             tax_results = self.env['account.tax']._compute_taxes( | ||||
|  |                 [line._convert_to_tax_base_line_dict()]) | ||||
|  |             totals = list(tax_results['totals'].values())[0] | ||||
|  |             amount_untaxed = totals['amount_untaxed'] | ||||
|  |             amount_tax = totals['amount_tax'] | ||||
|  |             line.update({ | ||||
|  |                 'price_subtotal': amount_untaxed, | ||||
|  |                 'price_tax': amount_tax, | ||||
|  |                 'price_total': amount_untaxed + amount_tax, | ||||
|  |             }) | ||||
|  |             if self.env.context.get('import_file', | ||||
|  |                                     False) and not self.env.user. \ | ||||
|  |                     user_has_groups('account.group_account_manager'): | ||||
|  |                 line.tax_id.invalidate_recordset( | ||||
|  |                     ['invoice_repartition_line_ids']) | ||||
|  | 
 | ||||
|  |     def _convert_to_tax_base_line_dict(self): | ||||
|  |         """ Convert the current record to a dictionary in order to use the | ||||
|  |         generic taxes computation method | ||||
|  |         defined on account.tax. | ||||
|  |         :return: A python dictionary. | ||||
|  |         """ | ||||
|  |         self.ensure_one() | ||||
|  |         return self.env['account.tax']._convert_to_tax_base_line_dict( | ||||
|  |             self, | ||||
|  |             partner=self.booking_id.partner_id, | ||||
|  |             currency=self.currency_id, | ||||
|  |             taxes=self.tax_ids, | ||||
|  |             price_unit=self.price_unit, | ||||
|  |             quantity=self.uom_qty, | ||||
|  |             price_subtotal=self.price_subtotal, | ||||
|  |         ) | ||||
|  | 
 | ||||
|  |     def search_available_vehicle(self): | ||||
|  |         """Returns list of booked vehicles""" | ||||
|  |         return (self.env['fleet.vehicle.model'].search( | ||||
|  |             [('id', 'in', self.search([]).mapped('fleet_id').ids)]).ids) | ||||
| @ -0,0 +1,39 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models, tools | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class FleetVehicleModel(models.Model): | ||||
|  |     """Inherits Fleet Model for Booking vehicles for hotel Customers""" | ||||
|  |     _inherit = 'fleet.vehicle.model' | ||||
|  | 
 | ||||
|  |     @tools.ormcache() | ||||
|  |     def _set_default_uom_id(self): | ||||
|  |         """Method for getting the default uom id""" | ||||
|  |         return self.env.ref('uom.product_uom_km') | ||||
|  | 
 | ||||
|  |     price_per_km = fields.Float(string="Price/KM", default=1.0, | ||||
|  |                                 help="Rent for Vehicle") | ||||
|  |     uom_id = fields.Many2one('uom.uom', | ||||
|  |                              string='Reference Uom', | ||||
|  |                              help="UOM of the product", | ||||
|  |                              default=_set_default_uom_id, required=True) | ||||
| @ -0,0 +1,124 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, tools | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class FoodBookingLine(models.Model): | ||||
|  |     """Model that handles the food booking""" | ||||
|  |     _name = "food.booking.line" | ||||
|  |     _description = "Hotel Food Line" | ||||
|  |     _rec_name = 'food_id' | ||||
|  | 
 | ||||
|  |     @tools.ormcache() | ||||
|  |     def _get_default_uom_id(self): | ||||
|  |         """Method for getting the default uom id""" | ||||
|  |         return self.env.ref('uom.product_uom_unit') | ||||
|  | 
 | ||||
|  |     booking_id = fields.Many2one("room.booking", string="Booking", | ||||
|  |                                  help="Shows the room Booking", | ||||
|  |                                  ondelete="cascade") | ||||
|  |     food_id = fields.Many2one('lunch.product', string="Product", | ||||
|  |                               help="Indicates the Food Product") | ||||
|  |     description = fields.Char(string='Description', | ||||
|  |                               help="Description of Food Product", | ||||
|  |                               related='food_id.display_name') | ||||
|  |     uom_qty = fields.Float(string="Qty", default=1, | ||||
|  |                            help="The quantity converted into the UoM used by " | ||||
|  |                                 "the product") | ||||
|  |     uom_id = fields.Many2one('uom.uom', readonly=True, | ||||
|  |                              string="Unit of Measure", | ||||
|  |                              default=_get_default_uom_id, help="This will set " | ||||
|  |                                                                "the unit of" | ||||
|  |                                                                " measure used") | ||||
|  |     price_unit = fields.Float(related='food_id.price', string='Price', | ||||
|  |                               digits='Product Price', | ||||
|  |                               help="The price of the selected food item.") | ||||
|  |     tax_ids = fields.Many2many('account.tax', | ||||
|  |                                'hotel_food_order_line_taxes_rel', | ||||
|  |                                'food_id', 'tax_id', | ||||
|  |                                string='Taxes', | ||||
|  |                                help="Default taxes used when selling the food" | ||||
|  |                                     " products.", | ||||
|  |                                domain=[('type_tax_use', '=', 'sale')]) | ||||
|  |     currency_id = fields.Many2one( | ||||
|  |         related='booking_id.pricelist_id.currency_id', | ||||
|  |         string="Currency", help='The currency used') | ||||
|  |     price_subtotal = fields.Float( | ||||
|  |         string="Subtotal", | ||||
|  |         compute='_compute_price_subtotal', help="Total Price Excluding Tax", | ||||
|  |         store=True) | ||||
|  |     price_tax = fields.Float( | ||||
|  |         string="Total Tax", | ||||
|  |         compute='_compute_price_subtotal', help="Tax Amount", | ||||
|  |         store=True) | ||||
|  |     price_total = fields.Float( | ||||
|  |         string="Total", | ||||
|  |         compute='_compute_price_subtotal', help="Total Price Including Tax", | ||||
|  |         store=True) | ||||
|  |     state = fields.Selection( | ||||
|  |         related='booking_id.state', | ||||
|  |         string="Order Status", help=" Status of the Order", | ||||
|  |         copy=False) | ||||
|  | 
 | ||||
|  |     @api.depends('uom_qty', 'price_unit', 'tax_ids') | ||||
|  |     def _compute_price_subtotal(self): | ||||
|  |         """ | ||||
|  |         Compute the amounts of the room booking line. | ||||
|  |         """ | ||||
|  |         for line in self: | ||||
|  |             tax_results = self.env['account.tax']._compute_taxes( | ||||
|  |                 [line._convert_to_tax_base_line_dict()]) | ||||
|  |             totals = list(tax_results['totals'].values())[0] | ||||
|  |             amount_untaxed = totals['amount_untaxed'] | ||||
|  |             amount_tax = totals['amount_tax'] | ||||
|  |             line.update({ | ||||
|  |                 'price_subtotal': amount_untaxed, | ||||
|  |                 'price_tax': amount_tax, | ||||
|  |                 'price_total': amount_untaxed + amount_tax, | ||||
|  |             }) | ||||
|  |             if self.env.context.get('import_file', | ||||
|  |                                     False) and not self.env.user. \ | ||||
|  |                     user_has_groups('account.group_account_manager'): | ||||
|  |                 line.tax_id.invalidate_recordset( | ||||
|  |                     ['invoice_repartition_line_ids']) | ||||
|  | 
 | ||||
|  |     def _convert_to_tax_base_line_dict(self): | ||||
|  |         """ Convert the current record to a dictionary in order to use the | ||||
|  |         generic taxes computation method | ||||
|  |         defined on account.tax. | ||||
|  |         :return: A python dictionary. | ||||
|  |         """ | ||||
|  |         self.ensure_one() | ||||
|  |         return self.env['account.tax']._convert_to_tax_base_line_dict( | ||||
|  |             self, | ||||
|  |             partner=self.booking_id.partner_id, | ||||
|  |             currency=self.currency_id, | ||||
|  |             taxes=self.tax_ids, | ||||
|  |             price_unit=self.price_unit, | ||||
|  |             quantity=self.uom_qty, | ||||
|  |             price_subtotal=self.price_subtotal, | ||||
|  |         ) | ||||
|  | 
 | ||||
|  |     def search_food_orders(self): | ||||
|  |         """Returns list of food orders""" | ||||
|  |         return (self.search([]).filtered(lambda r: r.booking_id.state not in [ | ||||
|  |             'check_out', 'cancel', 'done']).ids) | ||||
| @ -0,0 +1,36 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class HotelAmenity(models.Model): | ||||
|  |     """Model that handles all amenities of the hotel""" | ||||
|  |     _name = 'hotel.amenity' | ||||
|  |     _description = "Hotel Amenity" | ||||
|  |     _inherit = 'mail.thread' | ||||
|  |     _order = 'id desc' | ||||
|  | 
 | ||||
|  |     name = fields.Char(string='Name', help="Name of the amenity") | ||||
|  |     icon = fields.Image(string="Icon", required=True, | ||||
|  |                         help="Image of the amenity") | ||||
|  |     description = fields.Html(string="About", | ||||
|  |                               help="Specify the amenity description") | ||||
| @ -0,0 +1,34 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class HotelFloor(models.Model): | ||||
|  |     """Model that holds the Hotel Floors.""" | ||||
|  |     _name = "hotel.floor" | ||||
|  |     _description = "Floor" | ||||
|  |     _order = 'id desc' | ||||
|  | 
 | ||||
|  |     name = fields.Char(string="Name", help="Name of the floor", required=True) | ||||
|  |     user_id = fields.Many2one('res.users', string='Manager', | ||||
|  |                               help="Manager of the Floor", | ||||
|  |                               required=True) | ||||
| @ -0,0 +1,106 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, tools, _ | ||||
|  | from odoo.exceptions import ValidationError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class HotelRoom(models.Model): | ||||
|  |     """Model that holds all details regarding hotel room""" | ||||
|  |     _name = 'hotel.room' | ||||
|  |     _description = 'Rooms' | ||||
|  |     _inherit = ['mail.thread', 'mail.activity.mixin'] | ||||
|  | 
 | ||||
|  |     @tools.ormcache() | ||||
|  |     def _get_default_uom_id(self): | ||||
|  |         """Method for getting the default uom id""" | ||||
|  |         return self.env.ref('uom.product_uom_unit') | ||||
|  | 
 | ||||
|  |     name = fields.Char(string='Name', help="Name of the Room", index='trigram', | ||||
|  |                        required=True, translate=True) | ||||
|  |     status = fields.Selection([("available", "Available"), | ||||
|  |                                ("reserved", "Reserved"), | ||||
|  |                                ("occupied", "Occupied")], | ||||
|  |                               default="available", string="Status", | ||||
|  |                               help="Status of The Room", | ||||
|  |                               tracking=True) | ||||
|  |     is_room_avail = fields.Boolean(default=True, string="Available", | ||||
|  |                                    help="Check if the room is available") | ||||
|  |     list_price = fields.Float(string='Rent', digits='Product Price', | ||||
|  |                               help="The rent of the room.") | ||||
|  |     uom_id = fields.Many2one( | ||||
|  |         'uom.uom', string='Unit of Measure', | ||||
|  |         default=_get_default_uom_id, required=True, | ||||
|  |         help="Default unit of measure used for all stock operations.") | ||||
|  |     room_image = fields.Image(string="Room Image", max_width=1920, | ||||
|  |                               max_height=1920, help='Image of the room') | ||||
|  |     taxes_ids = fields.Many2many('account.tax', | ||||
|  |                                  'hotel_room_taxes_rel', | ||||
|  |                                  'room_id', 'tax_id', | ||||
|  |                                  help="Default taxes used when selling the" | ||||
|  |                                       " room.", string='Customer Taxes', | ||||
|  |                                  domain=[('type_tax_use', '=', 'sale')], | ||||
|  |                                  default=lambda self: self.env.company. | ||||
|  |                                  account_sale_tax_id) | ||||
|  |     room_amenities_ids = fields.Many2many("hotel.amenity", | ||||
|  |                                           string="Room Amenities", | ||||
|  |                                           help="List of room amenities.") | ||||
|  |     floor_id = fields.Many2one('hotel.floor', string='Floor', | ||||
|  |                                help="Automatically selects the Floor", | ||||
|  |                                tracking=True) | ||||
|  |     user_id = fields.Many2one('res.users', string="User", | ||||
|  |                               related='floor_id.user_id', | ||||
|  |                               help="Automatically selects the manager", | ||||
|  |                               tracking=True) | ||||
|  |     room_type = fields.Selection([('single', 'Single'), | ||||
|  |                                   ('double', 'Double'), | ||||
|  |                                   ('dormitory', 'Dormitory')], | ||||
|  |                                  required=True, string="Room Type", | ||||
|  |                                  help="Automatically selects the Room Type", | ||||
|  |                                  tracking=True, | ||||
|  |                                  default="single") | ||||
|  |     num_person = fields.Integer(string='Number Of Persons', | ||||
|  |                                 required=True, | ||||
|  |                                 help="Automatically chooses the No. of Persons", | ||||
|  |                                 tracking=True) | ||||
|  |     description = fields.Html(string='Description', help="Add description", | ||||
|  |                               translate=True) | ||||
|  | 
 | ||||
|  |     @api.constrains("num_person") | ||||
|  |     def _check_capacity(self): | ||||
|  |         """Check capacity function""" | ||||
|  |         for room in self: | ||||
|  |             if room.num_person <= 0: | ||||
|  |                 raise ValidationError(_("Room capacity must be more than 0")) | ||||
|  | 
 | ||||
|  |     @api.onchange("room_type") | ||||
|  |     def _onchange_room_type(self): | ||||
|  |         """ | ||||
|  |         Based on selected room type, number of person will be updated. | ||||
|  |         ---------------------------------------- | ||||
|  |         @param self: object pointer | ||||
|  |         """ | ||||
|  |         if self.room_type == "single": | ||||
|  |             self.num_person = 1 | ||||
|  |         elif self.room_type == "double": | ||||
|  |             self.num_person = 2 | ||||
|  |         else: | ||||
|  |             self.num_person = 4 | ||||
| @ -0,0 +1,46 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class HotelService(models.Model): | ||||
|  |     """Model that holds the all hotel services""" | ||||
|  |     _name = 'hotel.service' | ||||
|  |     _description = "Hotel Service" | ||||
|  |     _inherit = 'mail.thread' | ||||
|  |     _order = 'id desc' | ||||
|  | 
 | ||||
|  |     name = fields.Char(string="Service", | ||||
|  |                        help="Name of the service", | ||||
|  |                        required=True) | ||||
|  |     unit_price = fields.Float(string="Price", | ||||
|  |                               help="Price of the service", | ||||
|  |                               default=0.0) | ||||
|  |     taxes_ids = fields.Many2many('account.tax', | ||||
|  |                                  'hotel_service_taxes_rel', | ||||
|  |                                  'service_id', 'tax_id', | ||||
|  |                                  string='Customer Taxes', | ||||
|  |                                  help="Default taxes used when selling the" | ||||
|  |                                       " service product.", | ||||
|  |                                  domain=[('type_tax_use', '=', 'sale')], | ||||
|  |                                  default=lambda self: | ||||
|  |                                  self.env.company.account_sale_tax_id) | ||||
| @ -0,0 +1,151 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, _ | ||||
|  | from odoo.exceptions import ValidationError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class MaintenanceRequest(models.Model): | ||||
|  |     """Model that handles the maintenance requests""" | ||||
|  | 
 | ||||
|  |     _name = 'maintenance.request' | ||||
|  |     _inherit = ['mail.thread', 'mail.activity.mixin'] | ||||
|  |     _rec_name = 'sequence' | ||||
|  |     _description = "Maintenance Request" | ||||
|  | 
 | ||||
|  |     sequence = fields.Char(readonly=True, string="Sequence", copy=False, | ||||
|  |                            default='New', help='Sequence number for identifying' | ||||
|  |                                                ' maintenance request') | ||||
|  |     date = fields.Date(string="Date", help="Date of maintenance request", | ||||
|  |                        default=fields.Date.today) | ||||
|  |     state = fields.Selection(selection=[('draft', 'Draft'), | ||||
|  |                                         ('team_leader_approve', | ||||
|  |                                          'Waiting For User Assign'), | ||||
|  |                                         ('pending', 'Waiting For User To ' | ||||
|  |                                                     'Accept'), | ||||
|  |                                         ('ongoing', 'Ongoing'), | ||||
|  |                                         ('support', 'Waiting For Support'), | ||||
|  |                                         ('done', 'Done'), | ||||
|  |                                         ('verify', 'Pending For Verify'), | ||||
|  |                                         ('cancel', 'Canceled')], | ||||
|  |                              default='draft', string="State", | ||||
|  |                              help="State of maintenance request", | ||||
|  |                              tracking=True) | ||||
|  |     team_id = fields.Many2one('maintenance.team', | ||||
|  |                               string='Maintenance Team', | ||||
|  |                               help="Team for which this request is assigned", | ||||
|  |                               tracking=True) | ||||
|  |     team_head_id = fields.Many2one('res.users', | ||||
|  |                                    related='team_id.user_id', | ||||
|  |                                    string='Team Leader', | ||||
|  |                                    help="Head of the maintenance team") | ||||
|  |     assigned_user_id = fields.Many2one('res.users', | ||||
|  |                                        string='Assigned User', | ||||
|  |                                        tracking=True, | ||||
|  |                                        help="User to whom the request is " | ||||
|  |                                             "assigned") | ||||
|  |     type = fields.Selection(selection=[('room', 'Room'), | ||||
|  |                                        ('vehicle', 'Vehicle'), | ||||
|  |                                        ('hotel', 'Hotel'), | ||||
|  |                                        ('cleaning', 'Cleaning')], string="Type", | ||||
|  |                             help="The type for which the request is creating", | ||||
|  |                             tracking=True) | ||||
|  |     room_maintenance_ids = fields.Many2many('hotel.room', | ||||
|  |                                             string="Room Maintenance", | ||||
|  |                                             help="Choose Room Maintenance") | ||||
|  |     hotel_maintenance = fields.Char(string='Hotel Maintenance', | ||||
|  |                                     help="This is the Hotel Maintenance") | ||||
|  |     cleaning_maintenance = fields.Char(string='Cleaning Maintenance', | ||||
|  |                                        help="This is the Cleaning Maintenance") | ||||
|  |     vehicle_maintenance_id = fields.Many2one('fleet.vehicle.model', | ||||
|  |                                              string="Vehicle", | ||||
|  |                                              help="Choose Vehicle") | ||||
|  |     support_team_ids = fields.Many2many('res.users', | ||||
|  |                                         string="Support Team", | ||||
|  |                                         help="Choose Support Team") | ||||
|  |     support_reason = fields.Char(string='Support', | ||||
|  |                                  help="Reason for adding Support") | ||||
|  |     remarks = fields.Char(string='Remarks', help="Add Remarks") | ||||
|  |     domain_partner_ids = fields.Many2many('res.partner', | ||||
|  |                                           string="Partner", | ||||
|  |                                           help="For filtering Users") | ||||
|  | 
 | ||||
|  |     @api.model | ||||
|  |     def create(self, vals_list): | ||||
|  |         """Sequence Generation""" | ||||
|  |         if vals_list.get('sequence', 'New') == 'New': | ||||
|  |             vals_list['sequence'] = self.env['ir.sequence'].next_by_code( | ||||
|  |                 'maintenance.request') | ||||
|  |         return super().create(vals_list) | ||||
|  | 
 | ||||
|  |     @api.onchange('team_id') | ||||
|  |     def _onchange_team_id(self): | ||||
|  |         """Function for filtering the maintenance team user""" | ||||
|  |         self.update({ | ||||
|  |             'domain_partner_ids': self.team_id.member_ids.ids | ||||
|  |         }) | ||||
|  | 
 | ||||
|  |     def action_assign_team(self): | ||||
|  |         """Button action for changing the state to team_leader_approve""" | ||||
|  |         if self.team_id: | ||||
|  |             self.state = 'team_leader_approve' | ||||
|  |         else: | ||||
|  |             raise ValidationError( | ||||
|  |                 _("Please assign a Team")) | ||||
|  | 
 | ||||
|  |     def action_assign_user(self): | ||||
|  |         """Button action for changing the state to pending""" | ||||
|  |         if self.assigned_user_id: | ||||
|  |             self.state = 'pending' | ||||
|  |         else: | ||||
|  |             raise ValidationError( | ||||
|  |                 _("Please assign a User")) | ||||
|  | 
 | ||||
|  |     def action_start(self): | ||||
|  |         """Button action for changing the state to ongoing""" | ||||
|  |         self.state = 'ongoing' | ||||
|  | 
 | ||||
|  |     def action_support(self): | ||||
|  |         """Button action for changing the state to support""" | ||||
|  |         if self.support_reason: | ||||
|  |             self.state = 'support' | ||||
|  |         else: | ||||
|  |             raise ValidationError(_('Please enter the reason')) | ||||
|  | 
 | ||||
|  |     def action_complete(self): | ||||
|  |         """Button action for changing the state to verify""" | ||||
|  |         if self.remarks: | ||||
|  |             self.state = 'verify' | ||||
|  |         else: | ||||
|  |             raise ValidationError(_('Please Add remark')) | ||||
|  | 
 | ||||
|  |     def action_assign_support(self): | ||||
|  |         """Button action for changing the state to ongoing""" | ||||
|  |         if self.support_team_ids: | ||||
|  |             self.state = 'ongoing' | ||||
|  |         else: | ||||
|  |             raise ValidationError(_('Please choose support')) | ||||
|  | 
 | ||||
|  |     def action_verify(self): | ||||
|  |         """Button action for changing the state to done""" | ||||
|  |         self.state = 'done' | ||||
|  |         if self.vehicle_maintenance_id: | ||||
|  |             self.vehicle_maintenance_id.status = 'available' | ||||
| @ -0,0 +1,45 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class MaintenanceTeam(models.Model): | ||||
|  |     """Model that handles the maintenance team """ | ||||
|  |     _name = "maintenance.team" | ||||
|  |     _description = "Maintenance Team" | ||||
|  | 
 | ||||
|  |     name = fields.Char(string='Maintenance Team', | ||||
|  |                        help='Name of the maintenance team') | ||||
|  |     user_id = fields.Many2one('res.users', string='Team Leader', | ||||
|  |                               help="Leader of Team", | ||||
|  |                               domain=lambda self: [ | ||||
|  |                                   ('groups_id', 'in', self.env.ref( | ||||
|  |                                       'hotel_management_odoo.' | ||||
|  |                                       'maintenance_team_group_' | ||||
|  |                                       'leader').id)]) | ||||
|  |     member_ids = fields.Many2many('res.users', string='Members', | ||||
|  |                                   help="Members of the Team", | ||||
|  |                                   domain=lambda self: [ | ||||
|  |                                       ('groups_id', 'in', self.env.ref( | ||||
|  |                                           'hotel_management_odoo.' | ||||
|  |                                           'maintenance_' | ||||
|  |                                           'team_group_user').id)]) | ||||
| @ -0,0 +1,743 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from datetime import datetime, timedelta | ||||
|  | from odoo import api, fields, models, _ | ||||
|  | from odoo.exceptions import ValidationError | ||||
|  | from odoo.tools.safe_eval import pytz | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class RoomBooking(models.Model): | ||||
|  |     """Model that handles the hotel room booking and all operations related | ||||
|  |      to booking""" | ||||
|  |     _name = "room.booking" | ||||
|  |     _description = "Hotel Room Reservation" | ||||
|  |     _inherit = ['mail.thread', 'mail.activity.mixin'] | ||||
|  | 
 | ||||
|  |     name = fields.Char(string="Folio Number", readonly=True, index=True, | ||||
|  |                        default="New", help="Name of Folio") | ||||
|  |     company_id = fields.Many2one('res.company', string="Company", | ||||
|  |                                  help="Choose the Company", | ||||
|  |                                  required=True, index=True, | ||||
|  |                                  default=lambda self: self.env.company) | ||||
|  |     partner_id = fields.Many2one('res.partner', string="Customer", | ||||
|  |                                  help="Customers of hotel", | ||||
|  |                                  required=True, index=True, tracking=1, | ||||
|  |                                  domain="[('type', '!=', 'private')," | ||||
|  |                                         " ('company_id', 'in', " | ||||
|  |                                         "(False, company_id))]") | ||||
|  |     date_order = fields.Datetime( | ||||
|  |         string="Order Date", | ||||
|  |         required=True, copy=False, | ||||
|  |         help="Creation date of draft/sent orders," | ||||
|  |              " Confirmation date of confirmed orders.", | ||||
|  |         default=fields.Datetime.now) | ||||
|  |     is_checkin = fields.Boolean(default=False, string="Is Checkin", | ||||
|  |                                 help="sets to True if the room is occupied") | ||||
|  |     maintenance_request_sent = fields.Boolean(default=False, | ||||
|  |                                               string="Maintenance Request sent " | ||||
|  |                                                      "or Not", | ||||
|  |                                               help="sets to True if the " | ||||
|  |                                                    "maintenance request send " | ||||
|  |                                                    "once") | ||||
|  |     checkin_date = fields.Datetime(string="Check In", | ||||
|  |                                    help="Date of Checkin", | ||||
|  |                                    states={"draft": [("readonly", False)]}, | ||||
|  |                                    default=fields.Datetime.now() | ||||
|  |                                    ) | ||||
|  |     checkout_date = fields.Datetime(string="Check Out", | ||||
|  |                                     help="Date of Checkout", | ||||
|  |                                     states={"draft": [("readonly", False)]}, | ||||
|  |                                     default=fields.Datetime.now() + timedelta( | ||||
|  |                                         hours=23, minutes=59, seconds=59)) | ||||
|  |     hotel_policy = fields.Selection( | ||||
|  |         [("prepaid", "On Booking"), | ||||
|  |          ("manual", "On Check In"), | ||||
|  |          ("picking", "On Checkout"), | ||||
|  |          ], | ||||
|  |         default="manual", string="Hotel Policy", | ||||
|  |         help="Hotel policy for payment that " | ||||
|  |              "either the guest has to pay at " | ||||
|  |              "booking time, check-in " | ||||
|  |              "or check-out time.", tracking=True | ||||
|  |     ) | ||||
|  |     duration = fields.Integer(string="Duration in Days", | ||||
|  |                               help="Number of days which will automatically " | ||||
|  |                                    "count from the check-in and check-out " | ||||
|  |                                    "date.", ) | ||||
|  |     invoice_button_visible = fields.Boolean(string='Invoice Button Display', | ||||
|  |                                             help="Invoice button will be " | ||||
|  |                                                  "visible if this button is " | ||||
|  |                                                  "True") | ||||
|  |     invoice_status = fields.Selection( | ||||
|  |         selection=[('no_invoice', 'Nothing To Invoice'), | ||||
|  |                    ('to_invoice', 'To Invoice'), | ||||
|  |                    ('invoiced', 'Invoiced'), | ||||
|  |                    ], string="Invoice Status", | ||||
|  |         help="Status of the Invoice", | ||||
|  |         default='no_invoice', tracking=True) | ||||
|  |     hotel_invoice_id = fields.Many2one("account.move", | ||||
|  |                                        string="Invoice", | ||||
|  |                                        help="Indicates the invoice", | ||||
|  |                                        copy=False) | ||||
|  |     duration_visible = fields.Float(string="Duration", | ||||
|  |                                     help="A dummy field for Duration") | ||||
|  |     need_service = fields.Boolean(default=False, string="Need Service", | ||||
|  |                                   help="Check if a Service to be added with" | ||||
|  |                                        " the Booking") | ||||
|  |     need_fleet = fields.Boolean(default=False, string="Need Vehicle", | ||||
|  |                                 help="Check if a Fleet to be" | ||||
|  |                                      " added with the Booking") | ||||
|  |     need_food = fields.Boolean(default=False, string="Need Food", | ||||
|  |                                help="Check if a Food to be added with" | ||||
|  |                                     " the Booking") | ||||
|  |     need_event = fields.Boolean(default=False, string="Need Event", | ||||
|  |                                 help="Check if a Event to be added with" | ||||
|  |                                      " the Booking") | ||||
|  |     service_line_ids = fields.One2many("service.booking.line", | ||||
|  |                                        "booking_id", | ||||
|  |                                        string="Service", | ||||
|  |                                        help="Hotel services details provided to" | ||||
|  |                                             "Customer and it will included in " | ||||
|  |                                             "the main Invoice.") | ||||
|  |     event_line_ids = fields.One2many("event.booking.line", | ||||
|  |                                      'booking_id', | ||||
|  |                                      string="Event", | ||||
|  |                                      help="Hotel event reservation detail.") | ||||
|  |     vehicle_line_ids = fields.One2many("fleet.booking.line", | ||||
|  |                                        "booking_id", | ||||
|  |                                        string="Vehicle", | ||||
|  |                                        help="Hotel fleet reservation detail.") | ||||
|  |     room_line_ids = fields.One2many("room.booking.line", | ||||
|  |                                     "booking_id", string="Room", | ||||
|  |                                     help="Hotel room reservation detail.") | ||||
|  |     food_order_line_ids = fields.One2many("food.booking.line", | ||||
|  |                                           "booking_id", | ||||
|  |                                           string='Food', | ||||
|  |                                           help="Food details provided" | ||||
|  |                                                " to Customer and" | ||||
|  |                                                " it will included in the " | ||||
|  |                                                "main invoice.", ) | ||||
|  |     state = fields.Selection(selection=[('draft', 'Draft'), | ||||
|  |                                         ('reserved', 'Reserved'), | ||||
|  |                                         ('check_in', 'Check In'), | ||||
|  |                                         ('check_out', 'Check Out'), | ||||
|  |                                         ('cancel', 'Cancelled'), | ||||
|  |                                         ('done', 'Done')], string='State', | ||||
|  |                              help="State of the Booking", | ||||
|  |                              default='draft', tracking=True) | ||||
|  |     user_id = fields.Many2one( | ||||
|  |         comodel_name='res.partner', | ||||
|  |         string="Invoice Address", | ||||
|  |         compute='_compute_user_id', | ||||
|  |         help="Sets the User automatically", required=True, | ||||
|  |         domain="['|', ('company_id', '=', False), ('company_id', '='," | ||||
|  |                " company_id)]") | ||||
|  |     pricelist_id = fields.Many2one( | ||||
|  |         comodel_name='product.pricelist', | ||||
|  |         string="Pricelist", | ||||
|  |         compute='_compute_pricelist_id', | ||||
|  |         store=True, readonly=False,  | ||||
|  |         required=True, | ||||
|  |         tracking=1, | ||||
|  |         help="If you change the pricelist, only newly added lines" | ||||
|  |              " will be affected.") | ||||
|  |     currency_id = fields.Many2one( | ||||
|  |         string="Currency", help="This is the Currency used", | ||||
|  |         related='pricelist_id.currency_id', | ||||
|  |         depends=['pricelist_id.currency_id'], | ||||
|  |     ) | ||||
|  |     invoice_count = fields.Integer(compute='_compute_invoice_count', | ||||
|  |                                    string="Invoice " | ||||
|  |                                           "Count", | ||||
|  |                                    help="The number of invoices created") | ||||
|  |     account_move = fields.Integer(string='Invoice Id', | ||||
|  |                                   help="Id of the invoice created") | ||||
|  |     amount_untaxed = fields.Monetary(string="Total Untaxed Amount", | ||||
|  |                                      help="This indicates the total untaxed " | ||||
|  |                                           "amount", store=True, | ||||
|  |                                      compute='_compute_amount_untaxed', | ||||
|  |                                      tracking=5) | ||||
|  |     amount_tax = fields.Monetary(string="Taxes", help="Total Tax Amount", | ||||
|  |                                  store=True, compute='_compute_amount_untaxed') | ||||
|  |     amount_total = fields.Monetary(string="Total", store=True, | ||||
|  |                                    help="The total Amount including Tax", | ||||
|  |                                    compute='_compute_amount_untaxed', | ||||
|  |                                    tracking=4) | ||||
|  |     amount_untaxed_room = fields.Monetary(string="Room Untaxed", | ||||
|  |                                           help="Untaxed Amount for Room", | ||||
|  |                                           compute='_compute_amount_untaxed', | ||||
|  |                                           tracking=5) | ||||
|  |     amount_untaxed_food = fields.Monetary(string="Food Untaxed", | ||||
|  |                                           help="Untaxed Amount for Food", | ||||
|  |                                           compute='_compute_amount_untaxed', | ||||
|  |                                           tracking=5) | ||||
|  |     amount_untaxed_event = fields.Monetary(string="Event Untaxed", | ||||
|  |                                            help="Untaxed Amount for Event", | ||||
|  |                                            compute='_compute_amount_untaxed', | ||||
|  |                                            tracking=5) | ||||
|  |     amount_untaxed_service = fields.Monetary( | ||||
|  |         string="Service Untaxed", help="Untaxed Amount for Service", | ||||
|  |         compute='_compute_amount_untaxed', tracking=5) | ||||
|  |     amount_untaxed_fleet = fields.Monetary(string="Amount Untaxed", | ||||
|  |                                            help="Untaxed amount for Fleet", | ||||
|  |                                            compute='_compute_amount_untaxed', | ||||
|  |                                            tracking=5) | ||||
|  |     amount_taxed_room = fields.Monetary(string="Rom Tax", help="Tax for Room", | ||||
|  |                                         compute='_compute_amount_untaxed', | ||||
|  |                                         tracking=5) | ||||
|  |     amount_taxed_food = fields.Monetary(string="Food Tax", help="Tax for Food", | ||||
|  |                                         compute='_compute_amount_untaxed', | ||||
|  |                                         tracking=5) | ||||
|  |     amount_taxed_event = fields.Monetary(string="Event Tax", | ||||
|  |                                          help="Tax for Event", | ||||
|  |                                          compute='_compute_amount_untaxed', | ||||
|  |                                          tracking=5) | ||||
|  |     amount_taxed_service = fields.Monetary(string="Service Tax", | ||||
|  |                                            compute='_compute_amount_untaxed', | ||||
|  |                                            help="Tax for Service", tracking=5) | ||||
|  |     amount_taxed_fleet = fields.Monetary(string="Fleet Tax", | ||||
|  |                                          compute='_compute_amount_untaxed', | ||||
|  |                                          help="Tax for Fleet", tracking=5) | ||||
|  |     amount_total_room = fields.Monetary(string="Total Amount for Room", | ||||
|  |                                         compute='_compute_amount_untaxed', | ||||
|  |                                         help="This is the Total Amount for " | ||||
|  |                                              "Room", tracking=5) | ||||
|  |     amount_total_food = fields.Monetary(string="Total Amount for Food", | ||||
|  |                                         compute='_compute_amount_untaxed', | ||||
|  |                                         help="This is the Total Amount for " | ||||
|  |                                              "Food", tracking=5) | ||||
|  |     amount_total_event = fields.Monetary(string="Total Amount for Event", | ||||
|  |                                          compute='_compute_amount_untaxed', | ||||
|  |                                          help="This is the Total Amount for " | ||||
|  |                                               "Event", tracking=5) | ||||
|  |     amount_total_service = fields.Monetary(string="Total Amount for Service", | ||||
|  |                                            compute='_compute_amount_untaxed', | ||||
|  |                                            help="This is the Total Amount for " | ||||
|  |                                                 "Service", tracking=5) | ||||
|  |     amount_total_fleet = fields.Monetary(string="Total Amount for Fleet", | ||||
|  |                                          compute='_compute_amount_untaxed', | ||||
|  |                                          help="This is the Total Amount for " | ||||
|  |                                               "Fleet", tracking=5) | ||||
|  | 
 | ||||
|  |     @api.model | ||||
|  |     def create(self, vals_list): | ||||
|  |         """Sequence Generation""" | ||||
|  |         if vals_list.get('name', 'New') == 'New': | ||||
|  |             vals_list['name'] = self.env['ir.sequence'].next_by_code( | ||||
|  |                 'room.booking') | ||||
|  |         return super().create(vals_list) | ||||
|  | 
 | ||||
|  |     @api.depends('partner_id') | ||||
|  |     def _compute_user_id(self): | ||||
|  |         """Computes the User id""" | ||||
|  |         for order in self: | ||||
|  |             order.user_id = \ | ||||
|  |                 order.partner_id.address_get(['invoice'])[ | ||||
|  |                     'invoice'] if order.partner_id else False | ||||
|  | 
 | ||||
|  |     def _compute_invoice_count(self): | ||||
|  |         """Compute the invoice count""" | ||||
|  |         for record in self: | ||||
|  |             record.invoice_count = self.env['account.move'].search_count( | ||||
|  |                 [('ref', '=', self.name)]) | ||||
|  | 
 | ||||
|  |     @api.depends('partner_id') | ||||
|  |     def _compute_pricelist_id(self): | ||||
|  |         """Computes PriceList""" | ||||
|  |         for order in self: | ||||
|  |             if not order.partner_id: | ||||
|  |                 order.pricelist_id = False | ||||
|  |                 continue | ||||
|  |             order = order.with_company(order.company_id) | ||||
|  |             order.pricelist_id = order.partner_id.property_product_pricelist | ||||
|  | 
 | ||||
|  |     @api.depends('room_line_ids.price_subtotal', 'room_line_ids.price_tax', | ||||
|  |                  'room_line_ids.price_total', | ||||
|  |                  'food_order_line_ids.price_subtotal', | ||||
|  |                  'food_order_line_ids.price_tax', | ||||
|  |                  'food_order_line_ids.price_total', | ||||
|  |                  'service_line_ids.price_subtotal', | ||||
|  |                  'service_line_ids.price_tax', 'service_line_ids.price_total', | ||||
|  |                  'vehicle_line_ids.price_subtotal', | ||||
|  |                  'vehicle_line_ids.price_tax', 'vehicle_line_ids.price_total', | ||||
|  |                  'event_line_ids.price_subtotal', 'event_line_ids.price_tax', | ||||
|  |                  'event_line_ids.price_total', | ||||
|  |                  ) | ||||
|  |     def _compute_amount_untaxed(self, flag=False): | ||||
|  |         """Compute the total amounts of the Sale Order""" | ||||
|  |         amount_untaxed_room = 0.0 | ||||
|  |         amount_untaxed_food = 0.0 | ||||
|  |         amount_untaxed_fleet = 0.0 | ||||
|  |         amount_untaxed_event = 0.0 | ||||
|  |         amount_untaxed_service = 0.0 | ||||
|  |         amount_taxed_room = 0.0 | ||||
|  |         amount_taxed_food = 0.0 | ||||
|  |         amount_taxed_fleet = 0.0 | ||||
|  |         amount_taxed_event = 0.0 | ||||
|  |         amount_taxed_service = 0.0 | ||||
|  |         amount_total_room = 0.0 | ||||
|  |         amount_total_food = 0.0 | ||||
|  |         amount_total_fleet = 0.0 | ||||
|  |         amount_total_event = 0.0 | ||||
|  |         amount_total_service = 0.0 | ||||
|  |         room_lines = self.room_line_ids | ||||
|  |         food_lines = self.food_order_line_ids | ||||
|  |         service_lines = self.service_line_ids | ||||
|  |         fleet_lines = self.vehicle_line_ids | ||||
|  |         event_lines = self.event_line_ids | ||||
|  |         booking_list = [] | ||||
|  |         account_move_line = self.env['account.move.line'].search_read( | ||||
|  |             domain=[('ref', '=', self.name), | ||||
|  |                     ('display_type', '!=', 'payment_term')], | ||||
|  |             fields=['name', 'quantity', 'price_unit', 'product_type'], ) | ||||
|  |         for rec in account_move_line: | ||||
|  |             del rec['id'] | ||||
|  |         if room_lines: | ||||
|  |             amount_untaxed_room += sum(room_lines.mapped('price_subtotal')) | ||||
|  |             amount_taxed_room += sum(room_lines.mapped('price_tax')) | ||||
|  |             amount_total_room += sum(room_lines.mapped('price_total')) | ||||
|  |             for room in room_lines: | ||||
|  |                 booking_dict = {'name': room.room_id.name, | ||||
|  |                                 'quantity': room.uom_qty, | ||||
|  |                                 'price_unit': room.price_unit, | ||||
|  |                                 'product_type': 'room'} | ||||
|  |                 if booking_dict not in account_move_line: | ||||
|  |                     if not account_move_line: | ||||
|  |                         booking_list.append(booking_dict) | ||||
|  |                     else: | ||||
|  |                         for rec in account_move_line: | ||||
|  |                             if rec['product_type'] == 'room': | ||||
|  |                                 if booking_dict['name'] == rec['name'] and \ | ||||
|  |                                         booking_dict['price_unit'] == rec[ | ||||
|  |                                     'price_unit'] and booking_dict['quantity'] \ | ||||
|  |                                         != rec['quantity']: | ||||
|  |                                     booking_list.append( | ||||
|  |                                         {'name': room.room_id.name, | ||||
|  |                                          "quantity": booking_dict[ | ||||
|  |                                                          'quantity'] - rec[ | ||||
|  |                                                          'quantity'], | ||||
|  |                                          "price_unit": room.price_unit, | ||||
|  |                                          "product_type": 'room'}) | ||||
|  |                                 else: | ||||
|  |                                     booking_list.append(booking_dict) | ||||
|  |                     if flag: | ||||
|  |                         room.booking_line_visible = True | ||||
|  |         if food_lines: | ||||
|  |             for food in food_lines: | ||||
|  |                 booking_list.append(self.create_list(food)) | ||||
|  |             amount_untaxed_food += sum(food_lines.mapped('price_subtotal')) | ||||
|  |             amount_taxed_food += sum(food_lines.mapped('price_tax')) | ||||
|  |             amount_total_food += sum(food_lines.mapped('price_total')) | ||||
|  |         if service_lines: | ||||
|  |             for service in service_lines: | ||||
|  |                 booking_list.append(self.create_list(service)) | ||||
|  |             amount_untaxed_service += sum( | ||||
|  |                 service_lines.mapped('price_subtotal')) | ||||
|  |             amount_taxed_service += sum(service_lines.mapped('price_tax')) | ||||
|  |             amount_total_service += sum(service_lines.mapped('price_total')) | ||||
|  |         if fleet_lines: | ||||
|  |             for fleet in fleet_lines: | ||||
|  |                 booking_list.append(self.create_list(fleet)) | ||||
|  |             amount_untaxed_fleet += sum(fleet_lines.mapped('price_subtotal')) | ||||
|  |             amount_taxed_fleet += sum(fleet_lines.mapped('price_tax')) | ||||
|  |             amount_total_fleet += sum(fleet_lines.mapped('price_total')) | ||||
|  |         if event_lines: | ||||
|  |             for event in event_lines: | ||||
|  |                 booking_list.append(self.create_list(event)) | ||||
|  |             amount_untaxed_event += sum(event_lines.mapped('price_subtotal')) | ||||
|  |             amount_taxed_event += sum(event_lines.mapped('price_tax')) | ||||
|  |             amount_total_event += sum(event_lines.mapped('price_total')) | ||||
|  |         for rec in self: | ||||
|  |             rec.amount_untaxed = amount_untaxed_food + amount_untaxed_room + \ | ||||
|  |                                  amount_untaxed_fleet + \ | ||||
|  |                                  amount_untaxed_event + amount_untaxed_service | ||||
|  |             rec.amount_untaxed_food = amount_untaxed_food | ||||
|  |             rec.amount_untaxed_room = amount_untaxed_room | ||||
|  |             rec.amount_untaxed_fleet = amount_untaxed_fleet | ||||
|  |             rec.amount_untaxed_event = amount_untaxed_event | ||||
|  |             rec.amount_untaxed_service = amount_untaxed_service | ||||
|  |             rec.amount_tax = (amount_taxed_food + amount_taxed_room | ||||
|  |                               + amount_taxed_fleet | ||||
|  |                               + amount_taxed_event + amount_taxed_service) | ||||
|  |             rec.amount_taxed_food = amount_taxed_food | ||||
|  |             rec.amount_taxed_room = amount_taxed_room | ||||
|  |             rec.amount_taxed_fleet = amount_taxed_fleet | ||||
|  |             rec.amount_taxed_event = amount_taxed_event | ||||
|  |             rec.amount_taxed_service = amount_taxed_service | ||||
|  |             rec.amount_total = (amount_total_food + amount_total_room | ||||
|  |                                 + amount_total_fleet + amount_total_event | ||||
|  |                                 + amount_total_service) | ||||
|  |             rec.amount_total_food = amount_total_food | ||||
|  |             rec.amount_total_room = amount_total_room | ||||
|  |             rec.amount_total_fleet = amount_total_fleet | ||||
|  |             rec.amount_total_event = amount_total_event | ||||
|  |             rec.amount_total_service = amount_total_service | ||||
|  |         return booking_list | ||||
|  | 
 | ||||
|  |     @api.onchange('need_food') | ||||
|  |     def _onchange_need_food(self): | ||||
|  |         """Unlink Food Booking Line if Need Food is false""" | ||||
|  |         if not self.need_food and self.food_order_line_ids: | ||||
|  |             for food in self.food_order_line_ids: | ||||
|  |                 food.unlink() | ||||
|  | 
 | ||||
|  |     @api.onchange('need_service') | ||||
|  |     def _onchange_need_service(self): | ||||
|  |         """Unlink Service Booking Line if Need Service is False""" | ||||
|  |         if not self.need_service and self.service_line_ids: | ||||
|  |             for serv in self.service_line_ids: | ||||
|  |                 serv.unlink() | ||||
|  | 
 | ||||
|  |     @api.onchange('need_fleet') | ||||
|  |     def _onchange_need_fleet(self): | ||||
|  |         """Unlink Fleet Booking Line if Need Fleet is False""" | ||||
|  |         if not self.need_fleet: | ||||
|  |             if self.vehicle_line_ids: | ||||
|  |                 for fleet in self.vehicle_line_ids: | ||||
|  |                     fleet.unlink() | ||||
|  | 
 | ||||
|  |     @api.onchange('need_event') | ||||
|  |     def _onchange_need_event(self): | ||||
|  |         """Unlink Event Booking Line if Need Event is False""" | ||||
|  |         if not self.need_event: | ||||
|  |             if self.event_line_ids: | ||||
|  |                 for event in self.event_line_ids: | ||||
|  |                     event.unlink() | ||||
|  | 
 | ||||
|  |     @api.onchange('food_order_line_ids', 'room_line_ids', | ||||
|  |                   'service_line_ids', 'vehicle_line_ids', 'event_line_ids') | ||||
|  |     def _onchange_room_line_ids(self): | ||||
|  |         """Invokes the Compute amounts function""" | ||||
|  |         self._compute_amount_untaxed() | ||||
|  |         self.invoice_button_visible = False | ||||
|  | 
 | ||||
|  |     @api.constrains("room_line_ids") | ||||
|  |     def _check_duplicate_folio_room_line(self): | ||||
|  |         """ | ||||
|  |         This method is used to validate the room_lines. | ||||
|  |         ------------------------------------------------ | ||||
|  |         @param self: object pointer | ||||
|  |         @return: raise warning depending on the validation | ||||
|  |         """ | ||||
|  |         for record in self: | ||||
|  |             # Create a set of unique ids | ||||
|  |             ids = set() | ||||
|  |             for line in record.room_line_ids: | ||||
|  |                 if line.room_id.id in ids: | ||||
|  |                     raise ValidationError( | ||||
|  |                         _( | ||||
|  |                             """Room Entry Duplicates Found!, """ | ||||
|  |                             """You Cannot Book "%s" Room More Than Once!""" | ||||
|  |                         ) | ||||
|  |                         % line.room_id.name | ||||
|  |                     ) | ||||
|  |                 ids.add(line.room_id.id) | ||||
|  | 
 | ||||
|  |     def create_list(self, line_ids): | ||||
|  |         """Returns a Dictionary containing the Booking line Values""" | ||||
|  |         account_move_line = self.env['account.move.line'].search_read( | ||||
|  |             domain=[('ref', '=', self.name), | ||||
|  |                     ('display_type', '!=', 'payment_term')], | ||||
|  |             fields=['name', 'quantity', 'price_unit', 'product_type'], ) | ||||
|  |         for rec in account_move_line: | ||||
|  |             del rec['id'] | ||||
|  |         booking_dict = {} | ||||
|  |         for line in line_ids: | ||||
|  |             name = "" | ||||
|  |             product_type = "" | ||||
|  |             if line_ids._name == 'food.booking.line': | ||||
|  |                 name = line.food_id.name | ||||
|  |                 product_type = 'food' | ||||
|  |             elif line_ids._name == 'fleet.booking.line': | ||||
|  |                 name = line.fleet_id.name | ||||
|  |                 product_type = 'fleet' | ||||
|  |             elif line_ids._name == 'service.booking.line': | ||||
|  |                 name = line.service_id.name | ||||
|  |                 product_type = 'service' | ||||
|  |             elif line_ids._name == 'event.booking.line': | ||||
|  |                 name = line.event_id.name | ||||
|  |                 product_type = 'event' | ||||
|  |             booking_dict = {'name': name, | ||||
|  |                             'quantity': line.uom_qty, | ||||
|  |                             'price_unit': line.price_unit, | ||||
|  |                             'product_type': product_type} | ||||
|  |         return booking_dict | ||||
|  | 
 | ||||
|  |     def action_reserve(self): | ||||
|  |         """Button Reserve Function""" | ||||
|  |         if self.state == 'reserved': | ||||
|  |             message = _("Room Already Reserved.") | ||||
|  |             return { | ||||
|  |                 'type': 'ir.actions.client', | ||||
|  |                 'tag': 'display_notification', | ||||
|  |                 'params': { | ||||
|  |                     'type': 'warning', | ||||
|  |                     'message': message, | ||||
|  |                     'next': {'type': 'ir.actions.act_window_close'}, | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         if self.room_line_ids: | ||||
|  |             for room in self.room_line_ids: | ||||
|  |                 room.room_id.write({ | ||||
|  |                     'status': 'reserved', | ||||
|  |                 }) | ||||
|  |                 room.room_id.is_room_avail = False | ||||
|  |             self.write({"state": "reserved"}) | ||||
|  |             return { | ||||
|  |                 'type': 'ir.actions.client', | ||||
|  |                 'tag': 'display_notification', | ||||
|  |                 'params': { | ||||
|  |                     'type': 'success', | ||||
|  |                     'message': "Rooms reserved Successfully!", | ||||
|  |                     'next': {'type': 'ir.actions.act_window_close'}, | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         raise ValidationError(_("Please Enter Room Details")) | ||||
|  | 
 | ||||
|  |     def action_cancel(self): | ||||
|  |         """ | ||||
|  |         @param self: object pointer | ||||
|  |         """ | ||||
|  |         if self.room_line_ids: | ||||
|  |             for room in self.room_line_ids: | ||||
|  |                 room.room_id.write({ | ||||
|  |                     'status': 'available', | ||||
|  |                 }) | ||||
|  |                 room.room_id.is_room_avail = True | ||||
|  |         self.write({"state": "cancel"}) | ||||
|  | 
 | ||||
|  |     def action_maintenance_request(self): | ||||
|  |         """ | ||||
|  |         Function that handles the maintenance request | ||||
|  |         """ | ||||
|  |         room_list = [] | ||||
|  |         for rec in self.room_line_ids.room_id.ids: | ||||
|  |             room_list.append(rec) | ||||
|  |         if room_list: | ||||
|  |             room_id = self.env['hotel.room'].search([ | ||||
|  |                 ('id', 'in', room_list)]) | ||||
|  |             self.env['maintenance.request'].sudo().create({ | ||||
|  |                 'date': fields.Date.today(), | ||||
|  |                 'state': 'draft', | ||||
|  |                 'type': 'room', | ||||
|  |                 'room_maintenance_ids': room_id.ids, | ||||
|  |             }) | ||||
|  |             self.maintenance_request_sent = True | ||||
|  |             return { | ||||
|  |                 'type': 'ir.actions.client', | ||||
|  |                 'tag': 'display_notification', | ||||
|  |                 'params': { | ||||
|  |                     'type': 'success', | ||||
|  |                     'message': "Maintenance Request Sent Successfully", | ||||
|  |                     'next': {'type': 'ir.actions.act_window_close'}, | ||||
|  |                 } | ||||
|  |             } | ||||
|  |         raise ValidationError(_("Please Enter Room Details")) | ||||
|  | 
 | ||||
|  |     def action_done(self): | ||||
|  |         """Button action_confirm function""" | ||||
|  |         for rec in self.env['account.move'].search( | ||||
|  |                 [('ref', '=', self.name)]): | ||||
|  |             if rec.payment_state != 'not_paid': | ||||
|  |                 self.write({"state": "done"}) | ||||
|  |                 self.is_checkin = False | ||||
|  |                 if self.room_line_ids: | ||||
|  |                     return { | ||||
|  |                         'type': 'ir.actions.client', | ||||
|  |                         'tag': 'display_notification', | ||||
|  |                         'params': { | ||||
|  |                             'type': 'success', | ||||
|  |                             'message': "Booking Checked Out Successfully!", | ||||
|  |                             'next': {'type': 'ir.actions.act_window_close'}, | ||||
|  |                         } | ||||
|  |                     } | ||||
|  |             raise ValidationError(_('Your Invoice is Due for Payment.')) | ||||
|  |         self.write({"state": "done"}) | ||||
|  | 
 | ||||
|  |     def action_checkout(self): | ||||
|  |         """Button action_heck_out function""" | ||||
|  |         self.write({"state": "check_out"}) | ||||
|  |         for room in self.room_line_ids: | ||||
|  |             room.room_id.write({ | ||||
|  |                 'status': 'available', | ||||
|  |                 'is_room_avail': True | ||||
|  |             }) | ||||
|  |             room.write({'checkout_date': datetime.today()}) | ||||
|  | 
 | ||||
|  |     def action_invoice(self): | ||||
|  |         """Method for creating invoice""" | ||||
|  |         if not self.room_line_ids: | ||||
|  |             raise ValidationError(_("Please Enter Room Details")) | ||||
|  |         booking_list = self._compute_amount_untaxed(True) | ||||
|  |         if booking_list: | ||||
|  |             account_move = self.env["account.move"].create([{ | ||||
|  |                 'move_type': 'out_invoice', | ||||
|  |                 'invoice_date': fields.Date.today(), | ||||
|  |                 'partner_id': self.partner_id.id, | ||||
|  |                 'ref': self.name, | ||||
|  |             }]) | ||||
|  |             for rec in booking_list: | ||||
|  |                 account_move.invoice_line_ids.create([{ | ||||
|  |                     'name': rec['name'], | ||||
|  |                     'quantity': rec['quantity'], | ||||
|  |                     'price_unit': rec['price_unit'], | ||||
|  |                     'move_id': account_move.id, | ||||
|  |                     'price_subtotal': rec['quantity'] * rec['price_unit'], | ||||
|  |                     'product_type': rec['product_type'], | ||||
|  |                 }]) | ||||
|  |             self.write({'invoice_status': "invoiced"}) | ||||
|  |             self.invoice_button_visible = True | ||||
|  |             return { | ||||
|  |                 'type': 'ir.actions.act_window', | ||||
|  |                 'name': 'Invoices', | ||||
|  |                 'view_mode': 'form', | ||||
|  |                 'view_type': 'form', | ||||
|  |                 'res_model': 'account.move', | ||||
|  |                 'view_id': self.env.ref('account.view_move_form').id, | ||||
|  |                 'res_id': account_move.id, | ||||
|  |                 'context': "{'create': False}" | ||||
|  |             } | ||||
|  | 
 | ||||
|  |     def action_view_invoices(self): | ||||
|  |         """Method for Returning invoice View""" | ||||
|  |         return { | ||||
|  |             'type': 'ir.actions.act_window', | ||||
|  |             'name': 'Invoices', | ||||
|  |             'view_mode': 'tree,form', | ||||
|  |             'view_type': 'tree,form', | ||||
|  |             'res_model': 'account.move', | ||||
|  |             'domain': [('ref', '=', self.name)], | ||||
|  |             'context': "{'create': False}" | ||||
|  |         } | ||||
|  | 
 | ||||
|  |     def action_checkin(self): | ||||
|  |         """ | ||||
|  |         @param self: object pointer | ||||
|  |         """ | ||||
|  |         if not self.room_line_ids: | ||||
|  |             raise ValidationError(_("Please Enter Room Details")) | ||||
|  |         else: | ||||
|  |             for room in self.room_line_ids: | ||||
|  |                 room.room_id.write({ | ||||
|  |                     'status': 'occupied', | ||||
|  |                 }) | ||||
|  |                 room.room_id.is_room_avail = False | ||||
|  |             self.write({"state": "check_in"}) | ||||
|  |             return { | ||||
|  |                 'type': 'ir.actions.client', | ||||
|  |                 'tag': 'display_notification', | ||||
|  |                 'params': { | ||||
|  |                     'type': 'success', | ||||
|  |                     'message': "Booking Checked In Successfully!", | ||||
|  |                     'next': {'type': 'ir.actions.act_window_close'}, | ||||
|  |                 } | ||||
|  |             } | ||||
|  | 
 | ||||
|  |     def get_details(self): | ||||
|  |         """ Returns different counts for displaying in dashboard""" | ||||
|  |         today = datetime.today() | ||||
|  |         tz_name = self.env.user.tz | ||||
|  |         today_utc = pytz.timezone('UTC').localize(today, | ||||
|  |                                                   is_dst=False) | ||||
|  |         context_today = today_utc.astimezone(pytz.timezone(tz_name)) | ||||
|  |         total_room = self.env['hotel.room'].search_count([]) | ||||
|  |         check_in = self.env['room.booking'].search_count( | ||||
|  |             [('state', '=', 'check_in')]) | ||||
|  |         available_room = self.env['hotel.room'].search( | ||||
|  |             [('status', '=', 'available')]) | ||||
|  |         reservation = self.env['room.booking'].search_count( | ||||
|  |             [('state', '=', 'reserved')]) | ||||
|  |         check_outs = self.env['room.booking'].search([]) | ||||
|  |         check_out = 0 | ||||
|  |         staff = 0 | ||||
|  |         for rec in check_outs: | ||||
|  |             for room in rec.room_line_ids: | ||||
|  |                 if room.checkout_date.date() == context_today.date(): | ||||
|  |                     check_out += 1 | ||||
|  |             """staff""" | ||||
|  |             staff = self.env['res.users'].search_count( | ||||
|  |                 [('groups_id', 'in', | ||||
|  |                   [self.env.ref('hotel_management_odoo.hotel_group_admin').id, | ||||
|  |                    self.env.ref( | ||||
|  |                        'hotel_management_odoo.cleaning_team_group_head').id, | ||||
|  |                    self.env.ref( | ||||
|  |                        'hotel_management_odoo.cleaning_team_group_user').id, | ||||
|  |                    self.env.ref( | ||||
|  |                        'hotel_management_odoo.hotel_group_reception').id, | ||||
|  |                    self.env.ref( | ||||
|  |                        'hotel_management_odoo.maintenance_team_group_leader').id, | ||||
|  |                    self.env.ref( | ||||
|  |                        'hotel_management_odoo.maintenance_team_group_user').id | ||||
|  |                    ])]) | ||||
|  |         total_vehicle = self.env['fleet.vehicle.model'].search_count([]) | ||||
|  |         available_vehicle = total_vehicle - self.env[ | ||||
|  |             'fleet.booking.line'].search_count( | ||||
|  |             [('state', '=', 'check_in')]) | ||||
|  |         total_event = self.env['event.event'].search_count([]) | ||||
|  |         pending_event = self.env['event.event'].search([]) | ||||
|  |         pending_events = 0 | ||||
|  |         today_events = 0 | ||||
|  |         for pending in pending_event: | ||||
|  |             if pending.date_end >= fields.datetime.now(): | ||||
|  |                 pending_events += 1 | ||||
|  |             if pending.date_end.date() == fields.date.today(): | ||||
|  |                 today_events += 1 | ||||
|  |         food_items = self.env['lunch.product'].search_count([]) | ||||
|  |         food_order = len(self.env['food.booking.line'].search([]).filtered( | ||||
|  |             lambda r: r.booking_id.state not in ['check_out', 'cancel', | ||||
|  |                                                  'done'])) | ||||
|  |         """total Revenue""" | ||||
|  |         total_revenue = 0 | ||||
|  |         today_revenue = 0 | ||||
|  |         pending_payment = 0 | ||||
|  |         for rec in self.env['account.move'].search( | ||||
|  |                 [('payment_state', '=', 'paid')]): | ||||
|  |             if rec.ref: | ||||
|  |                 if 'BOOKING' in rec.ref: | ||||
|  |                     total_revenue += rec.amount_total | ||||
|  |                     if rec.date == fields.date.today(): | ||||
|  |                         today_revenue += rec.amount_total | ||||
|  |         for rec in self.env['account.move'].search( | ||||
|  |                 [('payment_state', '=', 'not_paid')]): | ||||
|  |             if rec.ref: | ||||
|  |                 if 'BOOKING' in rec.ref: | ||||
|  |                     pending_payment += rec.amount_total | ||||
|  |         return { | ||||
|  |             'total_room': total_room, | ||||
|  |             'available_room': len(available_room), | ||||
|  |             'staff': staff, | ||||
|  |             'check_in': check_in, | ||||
|  |             'reservation': reservation, | ||||
|  |             'check_out': check_out, | ||||
|  |             'total_vehicle': total_vehicle, | ||||
|  |             'available_vehicle': available_vehicle, | ||||
|  |             'total_event': total_event, | ||||
|  |             'today_events': today_events, | ||||
|  |             'pending_events': pending_events, | ||||
|  |             'food_items': food_items, | ||||
|  |             'food_order': food_order, | ||||
|  |             'total_revenue': round(total_revenue, 2), | ||||
|  |             'today_revenue': round(today_revenue, 2), | ||||
|  |             'pending_payment': round(pending_payment, 2), | ||||
|  |             'currency_symbol': self.env.user.company_id.currency_id.symbol, | ||||
|  |             'currency_position': self.env.user.company_id.currency_id.position | ||||
|  |         } | ||||
| @ -0,0 +1,149 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, tools, _ | ||||
|  | from odoo.exceptions import ValidationError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class RoomBookingLine(models.Model): | ||||
|  |     """Model that handles the room booking form""" | ||||
|  |     _name = "room.booking.line" | ||||
|  |     _description = "Hotel Folio Line" | ||||
|  |     _rec_name = 'room_id' | ||||
|  | 
 | ||||
|  |     @tools.ormcache() | ||||
|  |     def _set_default_uom_id(self): | ||||
|  |         return self.env.ref('uom.product_uom_day') | ||||
|  | 
 | ||||
|  |     booking_id = fields.Many2one("room.booking", string="Booking", | ||||
|  |                                  help="Indicates the Room", | ||||
|  |                                  ondelete="cascade") | ||||
|  |     checkin_date = fields.Datetime(string="Check In", | ||||
|  |                                    help="You can choose the date," | ||||
|  |                                         " Otherwise sets to current Date", | ||||
|  |                                    required=True) | ||||
|  |     checkout_date = fields.Datetime(string="Check Out", | ||||
|  |                                     help="You can choose the date," | ||||
|  |                                          " Otherwise sets to current Date", | ||||
|  |                                     required=True) | ||||
|  |     room_id = fields.Many2one('hotel.room', string="Room", | ||||
|  |                               domain=[('status', '=', 'available')], | ||||
|  |                               help="Indicates the Room", | ||||
|  |                               required=True) | ||||
|  |     uom_qty = fields.Float(string="Duration", | ||||
|  |                            help="The quantity converted into the UoM used by " | ||||
|  |                                 "the product", readonly=True) | ||||
|  |     uom_id = fields.Many2one('uom.uom', | ||||
|  |                              default=_set_default_uom_id, | ||||
|  |                              string="Unit of Measure", | ||||
|  |                              help="This will set the unit of measure used", | ||||
|  |                              readonly=True) | ||||
|  |     price_unit = fields.Float(related='room_id.list_price', string='Rent', | ||||
|  |                               digits='Product Price', | ||||
|  |                               help="The rent price of the selected room.") | ||||
|  |     tax_ids = fields.Many2many('account.tax', | ||||
|  |                                'hotel_room_order_line_taxes_rel', | ||||
|  |                                'room_id', 'tax_id', | ||||
|  |                                related='room_id.taxes_ids', | ||||
|  |                                string='Taxes', | ||||
|  |                                help="Default taxes used when selling the room.", | ||||
|  |                                domain=[('type_tax_use', '=', 'sale')]) | ||||
|  |     currency_id = fields.Many2one(string='Currency', | ||||
|  |                                   related='booking_id.pricelist_id.currency_id', | ||||
|  |                                   help='The currency used') | ||||
|  |     price_subtotal = fields.Float( | ||||
|  |         string="Subtotal", | ||||
|  |         compute='_compute_price_subtotal', help="Total Price excluding Tax", | ||||
|  |         store=True) | ||||
|  |     price_tax = fields.Float( | ||||
|  |         string="Total Tax", | ||||
|  |         compute='_compute_price_subtotal', help="Tax Amount", | ||||
|  |         store=True) | ||||
|  |     price_total = fields.Float( | ||||
|  |         string="Total", | ||||
|  |         compute='_compute_price_subtotal', help="Total Price including Tax", | ||||
|  |         store=True) | ||||
|  |     state = fields.Selection( | ||||
|  |         related='booking_id.state', | ||||
|  |         string="Order Status", help=" Status of the Order", | ||||
|  |         copy=False, precompute=True) | ||||
|  |     booking_line_visible = fields.Boolean(default=False, | ||||
|  |                                           string="Booking Line Visible", | ||||
|  |                                           help="If True, then Booking Line will" | ||||
|  |                                                " be visible") | ||||
|  | 
 | ||||
|  |     @api.onchange("checkin_date", "checkout_date") | ||||
|  |     def _onchange_checkin_date(self): | ||||
|  |         """ | ||||
|  |         When you change checkin_date or checkout_date it will check | ||||
|  |         and update the qty of hotel service line | ||||
|  |         ----------------------------------------------------------------- | ||||
|  |         @param self: object pointer | ||||
|  |         """ | ||||
|  |         if self.checkout_date < self.checkin_date: | ||||
|  |             raise ValidationError( | ||||
|  |                 _("Checkout must be greater or equal checkin date")) | ||||
|  |         if self.checkin_date and self.checkout_date: | ||||
|  |             diffdate = self.checkout_date - self.checkin_date | ||||
|  |             qty = diffdate.days | ||||
|  |             if diffdate.total_seconds() > 0: | ||||
|  |                 qty = qty + 1 | ||||
|  |             self.uom_qty = qty | ||||
|  | 
 | ||||
|  |     @api.depends('uom_qty', 'price_unit', 'tax_ids') | ||||
|  |     def _compute_price_subtotal(self): | ||||
|  |         """ | ||||
|  |         Compute the amounts of the room booking line. | ||||
|  |         """ | ||||
|  |         for line in self: | ||||
|  |             tax_results = self.env['account.tax']._compute_taxes( | ||||
|  |                 [line._convert_to_tax_base_line_dict()]) | ||||
|  |             totals = list(tax_results['totals'].values())[0] | ||||
|  |             amount_untaxed = totals['amount_untaxed'] | ||||
|  |             amount_tax = totals['amount_tax'] | ||||
|  |             line.update({ | ||||
|  |                 'price_subtotal': amount_untaxed, | ||||
|  |                 'price_tax': amount_tax, | ||||
|  |                 'price_total': amount_untaxed + amount_tax, | ||||
|  |             }) | ||||
|  |             if self.env.context.get('import_file', | ||||
|  |                                     False) and not self.env.user. \ | ||||
|  |                     user_has_groups('account.group_account_manager'): | ||||
|  |                 line.tax_id.invalidate_recordset( | ||||
|  |                     ['invoice_repartition_line_ids']) | ||||
|  | 
 | ||||
|  |     def _convert_to_tax_base_line_dict(self): | ||||
|  |         """ Convert the current record to a dictionary in order to use the | ||||
|  |         generic taxes computation method | ||||
|  |         defined on account.tax. | ||||
|  | 
 | ||||
|  |         :return: A python dictionary. | ||||
|  |         """ | ||||
|  |         self.ensure_one() | ||||
|  |         return self.env['account.tax']._convert_to_tax_base_line_dict( | ||||
|  |             self, | ||||
|  |             partner=self.booking_id.partner_id, | ||||
|  |             currency=self.currency_id, | ||||
|  |             taxes=self.tax_ids, | ||||
|  |             price_unit=self.price_unit, | ||||
|  |             quantity=self.uom_qty, | ||||
|  |             price_subtotal=self.price_subtotal, | ||||
|  |         ) | ||||
| @ -0,0 +1,121 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ################################################################################ | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: Unnimaya C O (odoo@cybrosys.com) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ################################################################################ | ||||
|  | from odoo import api, fields, models, tools | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class ServiceBookingLine(models.Model): | ||||
|  |     """Model that handles the service booking form""" | ||||
|  |     _name = "service.booking.line" | ||||
|  |     _description = "Hotel service Line" | ||||
|  | 
 | ||||
|  |     @tools.ormcache() | ||||
|  |     def _get_default_uom_id(self): | ||||
|  |         """Returns default product uom unit""" | ||||
|  |         return self.env.ref('uom.product_uom_unit') | ||||
|  | 
 | ||||
|  |     booking_id = fields.Many2one("room.booking", string="Booking", | ||||
|  |                                  help="Indicates the Room Booking", | ||||
|  |                                  ondelete="cascade") | ||||
|  |     service_id = fields.Many2one('hotel.service', string="Service", | ||||
|  |                                  help="Indicates the Service") | ||||
|  |     description = fields.Char(string='Description', related='service_id.name', | ||||
|  |                               help="Description of the Service") | ||||
|  |     uom_qty = fields.Float(string="Qty", default=1.0, | ||||
|  |                            help="The quantity converted into the UoM used by " | ||||
|  |                                 "the product") | ||||
|  |     uom_id = fields.Many2one('uom.uom', readonly=True, | ||||
|  |                              string="Unit of Measure", | ||||
|  |                              help="This will set the unit of measure used", | ||||
|  |                              default=_get_default_uom_id) | ||||
|  |     price_unit = fields.Float(string='Price', related='service_id.unit_price', | ||||
|  |                               digits='Product Price', | ||||
|  |                               help="The price of the selected service.") | ||||
|  |     tax_ids = fields.Many2many('account.tax', | ||||
|  |                                'hotel_service_order_line_taxes_rel', | ||||
|  |                                'service_id', 'tax_id', | ||||
|  |                                related='service_id.taxes_ids', string='Taxes', | ||||
|  |                                help="Default taxes used when selling the " | ||||
|  |                                     "services.", | ||||
|  |                                domain=[('type_tax_use', '=', 'sale')]) | ||||
|  |     currency_id = fields.Many2one(string='Currency', | ||||
|  |                                   related='booking_id.pricelist_id.currency_id', | ||||
|  |                                   help='The currency used') | ||||
|  |     price_subtotal = fields.Float( | ||||
|  |         string="Subtotal", | ||||
|  |         compute='_compute_price_subtotal', help="Total Price Excluding Tax", | ||||
|  |         store=True) | ||||
|  |     price_tax = fields.Float( | ||||
|  |         string="Total Tax", | ||||
|  |         compute='_compute_price_subtotal', help="Tax Amount", | ||||
|  |         store=True) | ||||
|  |     price_total = fields.Float( | ||||
|  |         string="Total", | ||||
|  |         compute='_compute_price_subtotal', help="Total Price Including Tax", | ||||
|  |         store=True) | ||||
|  |     state = fields.Selection( | ||||
|  |         related='booking_id.state', | ||||
|  |         string="Order Status", help=" Status of the Order", | ||||
|  |         copy=False) | ||||
|  |     booking_line_visible = fields.Boolean(default=False, | ||||
|  |                                           string="Booking Line Visible", | ||||
|  |                                           help="If true, Booking line will be" | ||||
|  |                                                " visible") | ||||
|  | 
 | ||||
|  |     @api.depends('uom_qty', 'price_unit', 'tax_ids') | ||||
|  |     def _compute_price_subtotal(self): | ||||
|  |         """ | ||||
|  |         Compute the amounts of the room booking line. | ||||
|  |         """ | ||||
|  |         for line in self: | ||||
|  |             tax_results = self.env['account.tax']._compute_taxes( | ||||
|  |                 [line._convert_to_tax_base_line_dict()]) | ||||
|  |             totals = list(tax_results['totals'].values())[0] | ||||
|  |             amount_untaxed = totals['amount_untaxed'] | ||||
|  |             amount_tax = totals['amount_tax'] | ||||
|  | 
 | ||||
|  |             line.update({ | ||||
|  |                 'price_subtotal': amount_untaxed, | ||||
|  |                 'price_tax': amount_tax, | ||||
|  |                 'price_total': amount_untaxed + amount_tax, | ||||
|  |             }) | ||||
|  |             if self.env.context.get('import_file', | ||||
|  |                                     False) and not self.env.user. \ | ||||
|  |                     user_has_groups('account.group_account_manager'): | ||||
|  |                 line.tax_id.invalidate_recordset( | ||||
|  |                     ['invoice_repartition_line_ids']) | ||||
|  | 
 | ||||
|  |     def _convert_to_tax_base_line_dict(self): | ||||
|  |         """ Convert the current record to a dictionary in order to use the | ||||
|  |          generic taxes computation method | ||||
|  |         defined on account.tax. | ||||
|  |         :return: A python dictionary. | ||||
|  |         """ | ||||
|  |         self.ensure_one() | ||||
|  |         return self.env['account.tax']._convert_to_tax_base_line_dict( | ||||
|  |             self, | ||||
|  |             partner=self.booking_id.partner_id, | ||||
|  |             currency=self.currency_id, | ||||
|  |             taxes=self.tax_ids, | ||||
|  |             price_unit=self.price_unit, | ||||
|  |             quantity=self.uom_qty, | ||||
|  |             price_subtotal=self.price_subtotal, | ||||
|  |         ) | ||||
| @ -0,0 +1,60 @@ | |||||
|  | <?xml version = "1.0" encoding = "UTF-8" ?> | ||||
|  | <odoo> | ||||
|  |     <!--    Room booking report action--> | ||||
|  |     <record id="action_report_room_booking" model="ir.actions.report"> | ||||
|  |         <field name="name">Room Booking Order</field> | ||||
|  |         <field name="model">room.booking</field> | ||||
|  |         <field name="report_type">qweb-pdf</field> | ||||
|  |         <field name="report_name">hotel_management_odoo.report_room_booking</field> | ||||
|  |         <field name="report_file">hotel_management_odoo.report_room_booking</field> | ||||
|  |         <field name="binding_model_id" ref="model_room_booking"/> | ||||
|  |         <field name="binding_type">report</field> | ||||
|  |     </record> | ||||
|  |     <!--    Room booking template--> | ||||
|  |     <template id="report_room_booking"> | ||||
|  |         <t t-call="web.html_container"> | ||||
|  |             <t t-call="web.external_layout"> | ||||
|  |                 <div class="page"> | ||||
|  |                     <h2>Room Booking</h2> | ||||
|  |                     <br/> | ||||
|  |                     <table class="table"> | ||||
|  |                         <thead> | ||||
|  |                             <tr> | ||||
|  |                                 <th>Sl No.</th> | ||||
|  |                                 <th>Guest Name</th> | ||||
|  |                                 <th>Room No.</th> | ||||
|  |                                 <th>Check-In</th> | ||||
|  |                                 <th>Check-Out</th> | ||||
|  |                                 <th>Reference No.</th> | ||||
|  |                             </tr> | ||||
|  |                         </thead> | ||||
|  |                         <t t-set="i" t-value="0"/> | ||||
|  |                         <t t-foreach="booking" t-as="line"> | ||||
|  |                             <t t-set="i" t-value="i+1"/> | ||||
|  |                             <tr> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="i"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['partner_id']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['room']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['checkin_date']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['checkin_date']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['name']"/> | ||||
|  |                                 </td> | ||||
|  |                             </tr> | ||||
|  |                         </t> | ||||
|  |                     </table> | ||||
|  |                 </div> | ||||
|  |             </t> | ||||
|  |         </t> | ||||
|  |     </template> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,61 @@ | |||||
|  | <?xml version = "1.0" encoding = "UTF-8" ?> | ||||
|  | <odoo> | ||||
|  |     <!--    Sale order report action--> | ||||
|  |     <record id="action_report_sale_order" model="ir.actions.report"> | ||||
|  |    <field name="name">Sale Order</field> | ||||
|  |    <field name="model">room.booking</field> | ||||
|  |    <field name="report_type">qweb-pdf</field> | ||||
|  |    <field name="report_name">hotel_management_odoo.report_sale_order</field> | ||||
|  |    <field name="report_file">hotel_management_odoo.report_sale_order</field> | ||||
|  |    <field name="binding_model_id" ref="model_room_booking"/> | ||||
|  |    <field name="binding_type">report</field> | ||||
|  | </record> | ||||
|  |     <!--    Sale order report template--> | ||||
|  |     <template id="report_sale_order"> | ||||
|  |         <t t-call="web.html_container"> | ||||
|  |             <t t-call="web.external_layout"> | ||||
|  |                 <div class="page"> | ||||
|  |                     <div class="oe_structure"/> | ||||
|  |                     <h2>Sale Order</h2> | ||||
|  |                     <br/> | ||||
|  |                     <table class="table"> | ||||
|  |                         <thead> | ||||
|  |                             <tr> | ||||
|  |                                 <th>Sl No.</th> | ||||
|  |                                 <th>Guest Name</th> | ||||
|  |                                 <th>Check-In</th> | ||||
|  |                                 <th>Check-Out</th> | ||||
|  |                                 <th>Reference No.</th> | ||||
|  |                                 <th>Amount Total</th> | ||||
|  |                             </tr> | ||||
|  |                         </thead> | ||||
|  |                         <t t-set="i" t-value="0"/> | ||||
|  |                         <t t-foreach="booking" t-as="line"> | ||||
|  |                             <t t-set="i" t-value="i+1"/> | ||||
|  |                             <tr> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="i"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['partner_id']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['checkin_date']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['checkin_date']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['name']"/> | ||||
|  |                                 </td> | ||||
|  |                                 <td> | ||||
|  |                                     <t t-esc="line['amount_total']"/> | ||||
|  |                                 </td> | ||||
|  |                             </tr> | ||||
|  |                         </t> | ||||
|  |                     </table> | ||||
|  |                 </div> | ||||
|  |             </t> | ||||
|  |         </t> | ||||
|  |     </template> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,53 @@ | |||||
|  | <?xml version="1.0" encoding="utf-8" ?> | ||||
|  | <odoo> | ||||
|  |     <!--    Hotel Access Groups--> | ||||
|  |     <record id="module_category_hotel_management" model="ir.module.category"> | ||||
|  |         <field name="name">Hotel Management</field> | ||||
|  |         <field name="description">Hotel Access Groups</field> | ||||
|  |         <field name="sequence">20</field> | ||||
|  |     </record> | ||||
|  |     <!--    Maintenance Team User groups--> | ||||
|  |     <record id="maintenance_team_group_user" model="res.groups"> | ||||
|  |         <field name="name">Maintenance Team User</field> | ||||
|  |         <field name="category_id" | ||||
|  |                ref="hotel_management_odoo.module_category_hotel_management"/> | ||||
|  |     </record> | ||||
|  |     <!--    Maintenance Team Leader group--> | ||||
|  |     <record id="maintenance_team_group_leader" model="res.groups"> | ||||
|  |         <field name="name">Maintenance Team Leader</field> | ||||
|  |         <field name="category_id" | ||||
|  |                ref="hotel_management_odoo.module_category_hotel_management"/> | ||||
|  |         <field name="implied_ids" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.maintenance_team_group_user'))]"/> | ||||
|  |     </record> | ||||
|  |     <!--    Reception groups--> | ||||
|  |     <record id="hotel_group_reception" model="res.groups"> | ||||
|  |         <field name="name">Receptionist</field> | ||||
|  |         <field name="category_id" | ||||
|  |                ref="hotel_management_odoo.module_category_hotel_management"/> | ||||
|  |     </record> | ||||
|  |     <!--    Cleaning Team User group--> | ||||
|  |     <record id="cleaning_team_group_user" model="res.groups"> | ||||
|  |         <field name="name">Cleaning Team User</field> | ||||
|  |         <field name="category_id" | ||||
|  |                ref="hotel_management_odoo.module_category_hotel_management"/> | ||||
|  |     </record> | ||||
|  |     <!--    Cleaning Team Head group--> | ||||
|  |     <record id="cleaning_team_group_head" model="res.groups"> | ||||
|  |         <field name="name">Cleaning Team Head</field> | ||||
|  |         <field name="category_id" | ||||
|  |                ref="hotel_management_odoo.module_category_hotel_management"/> | ||||
|  |         <field name="implied_ids" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.cleaning_team_group_user'))]"/> | ||||
|  |     </record> | ||||
|  |     <!--Hotel Admin group--> | ||||
|  |     <record id="hotel_group_admin" model="res.groups"> | ||||
|  |         <field name="name">Admin</field> | ||||
|  |         <field name="category_id" | ||||
|  |                ref="hotel_management_odoo.module_category_hotel_management"/> | ||||
|  |         <field name="implied_ids" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.maintenance_team_group_leader')), | ||||
|  |                        (4, ref('hotel_management_odoo.cleaning_team_group_head')), | ||||
|  |                        (4, ref('hotel_group_reception')), ]"/> | ||||
|  |     </record> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,67 @@ | |||||
|  | <?xml version="1.0" encoding="utf-8" ?> | ||||
|  | <odoo> | ||||
|  |     <!--  MAINTENANCE RECORD RULE--> | ||||
|  |     <record id="maintenance_request_rule_leader" | ||||
|  |             model="ir.rule"> | ||||
|  |         <field name="name">Record Rule for Maintenance team leader</field> | ||||
|  |         <field ref="model_maintenance_request" name="model_id"/> | ||||
|  |         <field name="groups" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.maintenance_team_group_leader'))]"/> | ||||
|  |         <field name="domain_force">[('team_head_id', '=', user.id)]</field> | ||||
|  |         <field name="perm_read" eval="True"/> | ||||
|  |         <field name="perm_write" eval="True"/> | ||||
|  |         <field name="perm_create" eval="True"/> | ||||
|  |         <field name="perm_unlink" eval="True"/> | ||||
|  |     </record> | ||||
|  |     <!--    Record Rule for Maintenance User--> | ||||
|  |     <record id="maintenance_request_rule_user" | ||||
|  |             model="ir.rule"> | ||||
|  |         <field name="name">Record Rule for Maintenance User</field> | ||||
|  |         <field ref="model_maintenance_request" name="model_id"/> | ||||
|  |         <field name="groups" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.maintenance_team_group_user'))]"/> | ||||
|  |         <field name="domain_force">[('assigned_user_id', '=', user.id)]</field> | ||||
|  |         <field name="perm_read" eval="True"/> | ||||
|  |         <field name="perm_write" eval="True"/> | ||||
|  |         <field name="perm_create" eval="True"/> | ||||
|  |         <field name="perm_unlink" eval="True"/> | ||||
|  |     </record> | ||||
|  |     <!--    Record Rule for hotel Admin--> | ||||
|  |     <record id="maintenance_request_rule_admin" | ||||
|  |             model="ir.rule"> | ||||
|  |         <field name="name">Record Rule for hotel Admin</field> | ||||
|  |         <field ref="model_maintenance_request" name="model_id"/> | ||||
|  |         <field name="groups" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.hotel_group_admin'))]"/> | ||||
|  |         <field name="domain_force">[(1,'=',1)]</field> | ||||
|  |         <field name="perm_read" eval="True"/> | ||||
|  |         <field name="perm_write" eval="True"/> | ||||
|  |         <field name="perm_create" eval="True"/> | ||||
|  |         <field name="perm_unlink" eval="True"/> | ||||
|  |     </record> | ||||
|  |     <!--    CLEANING HEAD RECORD RULE--> | ||||
|  |     <record id="cleaning_request_rule_head" model="ir.rule"> | ||||
|  |         <field name="name">Cleaning Head Record Rule</field> | ||||
|  |         <field name="model_id" ref="model_cleaning_request"/> | ||||
|  |         <field name="groups" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.cleaning_team_group_head'))]"/> | ||||
|  |         <field name="domain_force">[('team_id.team_head_id.id', '=', user.id)] | ||||
|  |         </field> | ||||
|  |     </record> | ||||
|  |     <!--    CLEANING USER RECORD RULE--> | ||||
|  |     <record id="cleaning_request_rule_user" model="ir.rule"> | ||||
|  |         <field name="name">Cleaning User Record Rule</field> | ||||
|  |         <field name="model_id" ref="model_cleaning_request"/> | ||||
|  |         <field name="groups" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.cleaning_team_group_user'))]"/> | ||||
|  |         <field name="domain_force">[('assigned_id.id', '=', user.id)]</field> | ||||
|  |     </record> | ||||
|  |     <!--    CLEANING ADMIN RECORD RULE--> | ||||
|  |     <record id="cleaning_request_rule_admin" model="ir.rule"> | ||||
|  |         <field name="name">Cleaning Admin Record Rule</field> | ||||
|  |         <field name="model_id" ref="model_cleaning_request"/> | ||||
|  |         <field name="groups" | ||||
|  |                eval="[(4, ref('hotel_management_odoo.hotel_group_admin'))]"/> | ||||
|  |         <field name="domain_force">[(1, '=', 1)]</field> | ||||
|  |     </record> | ||||
|  | </odoo> | ||||
| 
 | 
| After Width: | Height: | Size: 3.6 KiB | 
| After Width: | Height: | Size: 310 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 576 B | 
| After Width: | Height: | Size: 733 B | 
| After Width: | Height: | Size: 911 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 673 B | 
| After Width: | Height: | Size: 878 B | 
| After Width: | Height: | Size: 653 B | 
| After Width: | Height: | Size: 905 B | 
| After Width: | Height: | Size: 839 B | 
| After Width: | Height: | Size: 427 B | 
| After Width: | Height: | Size: 627 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 988 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 1.5 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.9 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 2.1 KiB | 
| After Width: | Height: | Size: 4.4 KiB | 
| After Width: | Height: | Size: 589 B | 
| After Width: | Height: | Size: 3.4 KiB | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 2.3 KiB | 
| After Width: | Height: | Size: 967 B | 
| After Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 3.8 KiB | 
| After Width: | Height: | Size: 5.0 KiB | 
| After Width: | Height: | Size: 92 KiB | 
| After Width: | Height: | Size: 81 KiB | 
| After Width: | Height: | Size: 94 KiB | 
| After Width: | Height: | Size: 91 KiB | 
| After Width: | Height: | Size: 92 KiB | 
| After Width: | Height: | Size: 91 KiB | 
| After Width: | Height: | Size: 89 KiB | 
| After Width: | Height: | Size: 486 KiB | 
| After Width: | Height: | Size: 54 KiB | 
| After Width: | Height: | Size: 87 KiB | 
| After Width: | Height: | Size: 360 KiB | 
| After Width: | Height: | Size: 174 KiB | 
| After Width: | Height: | Size: 53 KiB | 
| After Width: | Height: | Size: 45 KiB | 
| After Width: | Height: | Size: 52 KiB | 
| After Width: | Height: | Size: 40 KiB | 
| After Width: | Height: | Size: 86 KiB | 
| After Width: | Height: | Size: 103 KiB | 
| After Width: | Height: | Size: 53 KiB | 
| After Width: | Height: | Size: 99 KiB | 
| After Width: | Height: | Size: 108 KiB | 
| After Width: | Height: | Size: 118 KiB | 
| After Width: | Height: | Size: 87 KiB | 
| After Width: | Height: | Size: 66 KiB | 
| After Width: | Height: | Size: 82 KiB | 
| After Width: | Height: | Size: 96 KiB | 
| After Width: | Height: | Size: 103 KiB | 
| After Width: | Height: | Size: 95 KiB | 
| After Width: | Height: | Size: 83 KiB | 
| After Width: | Height: | Size: 75 KiB | 
| After Width: | Height: | Size: 116 KiB | 
| After Width: | Height: | Size: 78 KiB | 
| After Width: | Height: | Size: 107 KiB | 
| After Width: | Height: | Size: 63 KiB | 
| After Width: | Height: | Size: 70 KiB | 
| After Width: | Height: | Size: 95 KiB |