@ -0,0 +1,42 @@ | 
				
			|||||
 | 
					.. image:: https://img.shields.io/badge/license-OPL--1-red.svg | 
				
			||||
 | 
					    :target: https://www.odoo.com/documentation/17.0/legal/licenses.html#odoo-apps | 
				
			||||
 | 
					    :alt: License: OPL-1 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Advanced Fleet Rental Management | 
				
			||||
 | 
					========================== | 
				
			||||
 | 
					Advanced Fleet Rental Management system is designed to streamline the process of managing a fleet of vehicles for rental businesses | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					License | 
				
			||||
 | 
					------- | 
				
			||||
 | 
					Odoo Proprietary License v1.0. | 
				
			||||
 | 
					(https://www.odoo.com/documentation/17.0/legal/licenses.html#odoo-apps) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Company | 
				
			||||
 | 
					------- | 
				
			||||
 | 
					* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Credits | 
				
			||||
 | 
					------- | 
				
			||||
 | 
					* Developer: (V17)Anfas Faisal K, 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 https://www.cybrosys.com | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Further information | 
				
			||||
 | 
					=================== | 
				
			||||
 | 
					HTML Description: `<static/description/index.html>`__ | 
				
			||||
@ -0,0 +1,23 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from . import models | 
				
			||||
 | 
					from . import wizard | 
				
			||||
@ -0,0 +1,71 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					{ | 
				
			||||
 | 
					    'name': 'Advanced Fleet Rental Management', | 
				
			||||
 | 
					    'version': '17.0.1.0.0', | 
				
			||||
 | 
					    'category': "Extra Tools", | 
				
			||||
 | 
					    'summary': """This module will helps you to give the vehicles for Rent.""", | 
				
			||||
 | 
					    'description': "This module enhances Odoo’s fleet management " | 
				
			||||
 | 
					                   "functionality for vehicle rentals, including cars, " | 
				
			||||
 | 
					                   "vans, bikes, and jeeps. Key features include:" | 
				
			||||
 | 
					                   "Detailed rental contracts and invoicing." | 
				
			||||
 | 
					                   "Management of daily, hourly, and kilometer-based rental terms." | 
				
			||||
 | 
					                   "Integration with Odoo’s accounting module for automated invoicing and payments." | 
				
			||||
 | 
					                   "Tracking of vehicle status, maintenance, and extra service charges." | 
				
			||||
 | 
					                   "A user-friendly dashboard for monitoring fleet performance and rental contracts.", | 
				
			||||
 | 
					    'author': 'Cybrosys Techno Solutions', | 
				
			||||
 | 
					    'company': 'Cybrosys Techno Solutions', | 
				
			||||
 | 
					    'maintainer': 'Cybrosys Techno Solutions', | 
				
			||||
 | 
					    'website': "https://www.cybrosys.com", | 
				
			||||
 | 
					    'depends': ['fleet', 'mail', 'sale_management', 'account', ], | 
				
			||||
 | 
					    'data': [ | 
				
			||||
 | 
					        'security/ir.model.access.csv', | 
				
			||||
 | 
					        'data/ir_cron_data.xml', | 
				
			||||
 | 
					        'data/product_product_data.xml', | 
				
			||||
 | 
					        'data/ir_sequence_data.xml', | 
				
			||||
 | 
					        'views/fleet_vehicle_views.xml', | 
				
			||||
 | 
					        'views/fleet_dashboard.xml', | 
				
			||||
 | 
					        'views/multi_image_views.xml', | 
				
			||||
 | 
					        'views/fleet_rental_contract_views.xml', | 
				
			||||
 | 
					        'report/fleet_rental_contract_report.xml', | 
				
			||||
 | 
					        'report/fleet_rental_contract_template.xml', | 
				
			||||
 | 
					        'views/res_partner_views.xml', | 
				
			||||
 | 
					        'views/account_move_views.xml', | 
				
			||||
 | 
					        'views/rental_payment_plan_views.xml', | 
				
			||||
 | 
					        'views/cancellation_policy_views.xml', | 
				
			||||
 | 
					        'views/fleet_dashboard.xml', | 
				
			||||
 | 
					        'wizard/damage_invoice_views.xml', | 
				
			||||
 | 
					    ], | 
				
			||||
 | 
					    'assets': { | 
				
			||||
 | 
					        'web.assets_backend': [ | 
				
			||||
 | 
					            'advanced_fleet_rental/static/src/js/fleet_dashboard.js', | 
				
			||||
 | 
					            'advanced_fleet_rental/static/src/xml/fleet_dashboard.xml', | 
				
			||||
 | 
					            'advanced_fleet_rental/static/src/css/xero_dashboard.css', | 
				
			||||
 | 
					            'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.0/chart.umd.min.js', | 
				
			||||
 | 
					        ] | 
				
			||||
 | 
					    }, | 
				
			||||
 | 
					    'images': ['static/description/banner.jpg'], | 
				
			||||
 | 
					    'license': 'OPL-1', | 
				
			||||
 | 
					    'installable': True, | 
				
			||||
 | 
					    'auto_install': False, | 
				
			||||
 | 
					    'application': False, | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,16 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="utf-8" ?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					    <data noupdate="1"> | 
				
			||||
 | 
					<!-- Schedule action for generating automatic database backup--> | 
				
			||||
 | 
					        <record id="ir_cron_auto_invoice_create" model="ir.cron"> | 
				
			||||
 | 
					            <field name="name">Fleet : Automatic Invoice Creation</field> | 
				
			||||
 | 
					            <field name="model_id" ref="model_rental_payment_plan"/> | 
				
			||||
 | 
					            <field name="state">code</field> | 
				
			||||
 | 
					            <field name="code">model._schedule_auto_invoice_checker()</field> | 
				
			||||
 | 
					            <field name="interval_number">1</field> | 
				
			||||
 | 
					            <field name="interval_type">days</field> | 
				
			||||
 | 
					            <field name="numbercall">-1</field> | 
				
			||||
 | 
					            <field name="active">False</field> | 
				
			||||
 | 
					        </record> | 
				
			||||
 | 
					    </data> | 
				
			||||
 | 
					</odoo> | 
				
			||||
@ -0,0 +1,11 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					<!--    Sequence Number--> | 
				
			||||
 | 
					    <record id="vehicle_sequence_id" model="ir.sequence"> | 
				
			||||
 | 
					        <field name="name">Vehicle Rental Code</field> | 
				
			||||
 | 
					        <field name="code">vehicle.sequence</field> | 
				
			||||
 | 
					        <field name="prefix">VC/%(year)s/%(month)s/%(day)s/</field> | 
				
			||||
 | 
					        <field name="padding">5</field> | 
				
			||||
 | 
					        <field name="number_next">1</field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					</odoo> | 
				
			||||
@ -0,0 +1,49 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="utf-8"?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					    <data noupdate="1"> | 
				
			||||
 | 
					        <!--Vehicle Rental Charge--> | 
				
			||||
 | 
					        <record id="product_product_vehicle_rental_charge" model="product.product"> | 
				
			||||
 | 
					            <field name="name">Vehicle Rent Charge</field> | 
				
			||||
 | 
					            <field name="default_code">VRC</field> | 
				
			||||
 | 
					            <field name="description">Lets you charge a fixed rate for Vehicle Rental.</field> | 
				
			||||
 | 
					            <field name="type">service</field> | 
				
			||||
 | 
					            <field name="sale_ok" eval="True"/> | 
				
			||||
 | 
					            <field name="purchase_ok" eval="False"/> | 
				
			||||
 | 
					            <field name="list_price">0.0</field> | 
				
			||||
 | 
					            <field name="invoice_policy">order</field> | 
				
			||||
 | 
					        </record> | 
				
			||||
 | 
					        <!--Extra Charge--> | 
				
			||||
 | 
					        <record id="product_product_vehicle_extra_rental_charge" model="product.product"> | 
				
			||||
 | 
					            <field name="name">Extra Charges</field> | 
				
			||||
 | 
					            <field name="default_code">EC</field> | 
				
			||||
 | 
					            <field name="description">Fixed rate for Extra Charges.</field> | 
				
			||||
 | 
					            <field name="type">service</field> | 
				
			||||
 | 
					            <field name="sale_ok" eval="True"/> | 
				
			||||
 | 
					            <field name="purchase_ok" eval="False"/> | 
				
			||||
 | 
					            <field name="list_price">0.0</field> | 
				
			||||
 | 
					            <field name="invoice_policy">order</field> | 
				
			||||
 | 
					        </record> | 
				
			||||
 | 
					        <!--Damage Charge--> | 
				
			||||
 | 
					        <record id="product_product_vehicle_damage_charge" model="product.product"> | 
				
			||||
 | 
					            <field name="name">Damage Charge</field> | 
				
			||||
 | 
					            <field name="default_code">DC</field> | 
				
			||||
 | 
					            <field name="description">Fixed rate for Damage Charges.</field> | 
				
			||||
 | 
					            <field name="type">service</field> | 
				
			||||
 | 
					            <field name="sale_ok" eval="True"/> | 
				
			||||
 | 
					            <field name="purchase_ok" eval="False"/> | 
				
			||||
 | 
					            <field name="list_price">0.0</field> | 
				
			||||
 | 
					            <field name="invoice_policy">order</field> | 
				
			||||
 | 
					        </record> | 
				
			||||
 | 
					        <!--Cancellation Charge--> | 
				
			||||
 | 
					        <record id="product_product_vehicle_cancel_charge" model="product.product"> | 
				
			||||
 | 
					            <field name="name">Cancellation Charge</field> | 
				
			||||
 | 
					            <field name="default_code">CC</field> | 
				
			||||
 | 
					            <field name="description">Fixed rate for Cancellation Charges.</field> | 
				
			||||
 | 
					            <field name="type">service</field> | 
				
			||||
 | 
					            <field name="sale_ok" eval="True"/> | 
				
			||||
 | 
					            <field name="purchase_ok" eval="False"/> | 
				
			||||
 | 
					            <field name="list_price">0.0</field> | 
				
			||||
 | 
					            <field name="invoice_policy">order</field> | 
				
			||||
 | 
					        </record> | 
				
			||||
 | 
					    </data> | 
				
			||||
 | 
					</odoo> | 
				
			||||
@ -0,0 +1,7 @@ | 
				
			|||||
 | 
					## Module <advanced_fleet_rental> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#### 07.04.2025 | 
				
			||||
 | 
					#### Version 17.0.1.0.0 | 
				
			||||
 | 
					#### ADD | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					- Initial commit for Advanced Fleet Rental Management | 
				
			||||
@ -0,0 +1,31 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from . import account_move | 
				
			||||
 | 
					from . import cancellation_policy | 
				
			||||
 | 
					from . import extra_service | 
				
			||||
 | 
					from . import fleet_dashboard | 
				
			||||
 | 
					from . import fleet_rental_contract | 
				
			||||
 | 
					from . import fleet_vehicle | 
				
			||||
 | 
					from . import insurance_policy | 
				
			||||
 | 
					from . import multi_image | 
				
			||||
 | 
					from . import rental_payment_plan | 
				
			||||
 | 
					
 | 
				
			||||
@ -0,0 +1,38 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from odoo import fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class AccountMove(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Inherits the 'account.move' model to add a relationship with the | 
				
			||||
 | 
					    'fleet.rental.contract' model. This allows linking a vehicle rental | 
				
			||||
 | 
					    contract to an accounting move. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _inherit = "account.move" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    vehicle_rental_id = fields.Many2one('fleet.rental.contract', | 
				
			||||
 | 
					                                        string="Vehicle Contract", | 
				
			||||
 | 
					                                        readonly=True) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
@ -0,0 +1,37 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from odoo import  fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class CancellationPolicy(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Model for defining a cancellation policy, including the policy name, | 
				
			||||
 | 
					    creation date, and detailed terms and conditions. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _name = 'cancellation.policy' | 
				
			||||
 | 
					    _description = 'Cancellation Policy' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    name = fields.Char(string='Policy Name', required=True, | 
				
			||||
 | 
					                       help='Name of the cancellation policy.') | 
				
			||||
 | 
					    terms_conditions = fields.Text(string='Terms & Conditions', | 
				
			||||
 | 
					                                   help='Detailed terms and conditions ' | 
				
			||||
 | 
					                                        'of the cancellation policy.') | 
				
			||||
@ -0,0 +1,66 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from odoo import api, fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class ExtraService(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Model for defining extra services that can be added to a fleet rental | 
				
			||||
 | 
					    contract Each service is associated with a product, and the total amount | 
				
			||||
 | 
					    is computed based on the quantity and unit price of the product. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _name = 'extra.service' | 
				
			||||
 | 
					    _description = 'Extra Services' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    product_id = fields.Many2one('product.product', | 
				
			||||
 | 
					                                 string='Product', | 
				
			||||
 | 
					                                 required=True, | 
				
			||||
 | 
					                                 help='Description of the extra service.') | 
				
			||||
 | 
					    quantity = fields.Float(string='Quantity', default=1.0, | 
				
			||||
 | 
					                            required=True, | 
				
			||||
 | 
					                            help='Quantity of the extra service.') | 
				
			||||
 | 
					    unit_price = fields.Float(string='Unit Price', | 
				
			||||
 | 
					                              related='product_id.lst_price', store=True, | 
				
			||||
 | 
					                              readonly=False, | 
				
			||||
 | 
					                              help='Unit price of the extra service.') | 
				
			||||
 | 
					    amount = fields.Float(string='Amount', compute='_compute_amount', | 
				
			||||
 | 
					                          store=True, | 
				
			||||
 | 
					                          help='Total amount for the extra service.') | 
				
			||||
 | 
					    description = fields.Char(string='Description', | 
				
			||||
 | 
					                              help='Description of the Product') | 
				
			||||
 | 
					    contract_id = fields.Many2one('fleet.rental.contract', | 
				
			||||
 | 
					                                  string='Contract Rent', | 
				
			||||
 | 
					                                  help='Reference to the vehicle rent.') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.depends('quantity', 'unit_price') | 
				
			||||
 | 
					    def _compute_amount(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Compute the total amount for the extra service based on the | 
				
			||||
 | 
					        quantity and unit price. The amount is calculated as | 
				
			||||
 | 
					        quantity * unit_price and stored in the 'amount' field. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        for service in self: | 
				
			||||
 | 
					            service.amount = service.quantity * service.unit_price | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
@ -0,0 +1,102 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from odoo import api, models | 
				
			||||
 | 
					from datetime import datetime, timedelta | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class FleetDashboard(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Model for the Fleet Dashboard, providing various statistics and data | 
				
			||||
 | 
					    related to the fleet vehicles, contracts, and invoices. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _name = 'fleet.dashboard' | 
				
			||||
 | 
					    _description = 'Fleet Dashboard' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.model | 
				
			||||
 | 
					    def get_datas(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Retrieves overall statistics related to fleet vehicles, contracts, | 
				
			||||
 | 
					        and invoices. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        total_vehicles = self.env['fleet.vehicle'].search_count([]) | 
				
			||||
 | 
					        operational_vehicles = self.env['fleet.vehicle'].search_count( | 
				
			||||
 | 
					            [('status', '=', 'operational')]) | 
				
			||||
 | 
					        maintenance_vehicles = self.env['fleet.vehicle'].search_count( | 
				
			||||
 | 
					            [('status', '=', 'undermaintenance')]) | 
				
			||||
 | 
					        all_invoices = self.env['account.move'].search_count( | 
				
			||||
 | 
					            [('vehicle_rental_id', '!=', False)]) | 
				
			||||
 | 
					        pending_invoices = self.env['account.move'].search_count([ | 
				
			||||
 | 
					            ('vehicle_rental_id', '!=', False), | 
				
			||||
 | 
					            ('state', '=', 'posted'), | 
				
			||||
 | 
					            ('payment_state', '!=', 'paid') | 
				
			||||
 | 
					        ]) | 
				
			||||
 | 
					        total_contracts = self.env['fleet.rental.contract'].search_count([]) | 
				
			||||
 | 
					        total_contract_working = self.env[ | 
				
			||||
 | 
					            'fleet.rental.contract'].search_count( | 
				
			||||
 | 
					            [('state', '=', 'in_progress')]) | 
				
			||||
 | 
					        total_contract_returned = self.env[ | 
				
			||||
 | 
					            'fleet.rental.contract'].search_count( | 
				
			||||
 | 
					            [('state', '=', 'return')]) | 
				
			||||
 | 
					        total_contract_cancel = self.env['fleet.rental.contract'].search_count( | 
				
			||||
 | 
					            [('state', '=', 'cancel')]) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        return { | 
				
			||||
 | 
					            'total_vehicles': total_vehicles, | 
				
			||||
 | 
					            'total_contracts': total_contracts, | 
				
			||||
 | 
					            'total_contract_working': total_contract_working, | 
				
			||||
 | 
					            'total_contract_return': total_contract_returned, | 
				
			||||
 | 
					            'total_contract_cancel': total_contract_cancel, | 
				
			||||
 | 
					            'operational': operational_vehicles, | 
				
			||||
 | 
					            'under_maintenance': maintenance_vehicles, | 
				
			||||
 | 
					            'all_customers': self.env['res.partner'].search_count([]), | 
				
			||||
 | 
					            'all_invoices': all_invoices, | 
				
			||||
 | 
					            'pending_invoices': pending_invoices, | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.model | 
				
			||||
 | 
					    def get_monthly_contract_invoices(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Retrieves the count of posted invoices for each month of the | 
				
			||||
 | 
					        current year related to vehicle rentals. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        current_year = datetime.now().year | 
				
			||||
 | 
					        data = [] | 
				
			||||
 | 
					        labels = ['January', 'February', 'March', 'April', 'May', 'June', | 
				
			||||
 | 
					                  'July', 'August', 'September', 'October', 'November', | 
				
			||||
 | 
					                  'December'] | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        for month in range(1, 13): | 
				
			||||
 | 
					            start_date = datetime(current_year, month, 1) | 
				
			||||
 | 
					            end_date = (start_date + timedelta(days=32)).replace( | 
				
			||||
 | 
					                day=1) - timedelta(days=1) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            invoice_count = self.env['account.move'].search_count([ | 
				
			||||
 | 
					                ('vehicle_rental_id', '!=', False), | 
				
			||||
 | 
					                ('invoice_date', '>=', start_date), | 
				
			||||
 | 
					                ('invoice_date', '<=', end_date), | 
				
			||||
 | 
					                ('state', '=', 'posted') | 
				
			||||
 | 
					            ]) | 
				
			||||
 | 
					            data.append(invoice_count) | 
				
			||||
 | 
					        return { | 
				
			||||
 | 
					            'labels': labels, | 
				
			||||
 | 
					            'data': data | 
				
			||||
 | 
					        } | 
				
			||||
@ -0,0 +1,677 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from datetime import date | 
				
			||||
 | 
					from odoo import api, fields, models, _ | 
				
			||||
 | 
					from dateutil.relativedelta import relativedelta | 
				
			||||
 | 
					from odoo.exceptions import ValidationError | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class FleetRentalContract(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Represents a car rental contract, including details about the customer, | 
				
			||||
 | 
					    vehicle, rental period, charges, and various related information. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _name = 'fleet.rental.contract' | 
				
			||||
 | 
					    _description = 'Fleet Rental Contract' | 
				
			||||
 | 
					    _inherit = ['mail.thread', 'mail.activity.mixin'] | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    name = fields.Char(string="Sequence", | 
				
			||||
 | 
					                       default=lambda self: _('New'), | 
				
			||||
 | 
					                       copy=False, readonly=True, tracking=True, | 
				
			||||
 | 
					                       help='Unique contract number for the rental agreement.') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    state = fields.Selection( | 
				
			||||
 | 
					        [('new', 'New'), | 
				
			||||
 | 
					         ('in_progress', 'In Progress'), | 
				
			||||
 | 
					         ('return', 'Return'), ('cancel', 'Cancel')], | 
				
			||||
 | 
					        string='State', default='new', | 
				
			||||
 | 
					        help='Contract Progress', | 
				
			||||
 | 
					        group_expand='_group_expand_states',tracking=True) | 
				
			||||
 | 
					    customer_id = fields.Many2one( | 
				
			||||
 | 
					        'res.partner', string='Customer', | 
				
			||||
 | 
					        help='The customer who is renting the vehicle.', | 
				
			||||
 | 
					        required=True, tracking=True) | 
				
			||||
 | 
					    email = fields.Char(string='Email', | 
				
			||||
 | 
					                        related='customer_id.email', | 
				
			||||
 | 
					                        help='Email address of the customer.', | 
				
			||||
 | 
					                        readonly=False) | 
				
			||||
 | 
					    phone = fields.Char('Phone', related='customer_id.phone', | 
				
			||||
 | 
					                        help="Phone Number of the customer") | 
				
			||||
 | 
					    pickup_date = fields.Datetime( | 
				
			||||
 | 
					        string='Pick-up Date', | 
				
			||||
 | 
					        help='Date and time when the vehicle will be picked up.', | 
				
			||||
 | 
					        required=True, tracking=True) | 
				
			||||
 | 
					    dropoff_date = fields.Datetime( | 
				
			||||
 | 
					        string='Drop-off Date', | 
				
			||||
 | 
					        help='Date and time when the vehicle will be returned.', | 
				
			||||
 | 
					        required=True, tracking=True) | 
				
			||||
 | 
					    pickup_location = fields.Char( | 
				
			||||
 | 
					        string='Pick-Up Location', | 
				
			||||
 | 
					        help='Location where the vehicle will be picked up.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    dropoff_location = fields.Char( | 
				
			||||
 | 
					        string='Drop-Off Location', | 
				
			||||
 | 
					        help='Location where the vehicle will be dropped off.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    pickup_street = fields.Char( | 
				
			||||
 | 
					        string='Pick-Up Street', | 
				
			||||
 | 
					        help='Street address for the pick-up location.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    dropoff_street = fields.Char( | 
				
			||||
 | 
					        string='Drop-Off Street', | 
				
			||||
 | 
					        help='Street address for the drop-off location.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    pickup_city = fields.Char( | 
				
			||||
 | 
					        string='Pick-Up City', | 
				
			||||
 | 
					        help='City where the vehicle will be picked up.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    dropoff_city = fields.Char( | 
				
			||||
 | 
					        string='Drop-Off City', | 
				
			||||
 | 
					        help='City where the vehicle will be dropped off.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    pickup_state_id = fields.Many2one( | 
				
			||||
 | 
					        'res.country.state', | 
				
			||||
 | 
					        string='Pick-Up State', | 
				
			||||
 | 
					        help='State where the vehicle will be picked up.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    dropoff_state_id = fields.Many2one( | 
				
			||||
 | 
					        'res.country.state', | 
				
			||||
 | 
					        string='Drop-Off State', | 
				
			||||
 | 
					        help='State where the vehicle will be dropped off.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    pickup_zip = fields.Char( | 
				
			||||
 | 
					        string='Pick-Up ZIP', | 
				
			||||
 | 
					        help='ZIP code for the pick-up location.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    dropoff_zip = fields.Char(string='Drop-Off ZIP', | 
				
			||||
 | 
					                              help='ZIP code for the drop-off location.') | 
				
			||||
 | 
					    pickup_country_id = fields.Many2one( | 
				
			||||
 | 
					        'res.country', | 
				
			||||
 | 
					        string='Pick-Up Country', | 
				
			||||
 | 
					        help='Country where the vehicle will be picked up.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    dropoff_country_id = fields.Many2one( | 
				
			||||
 | 
					        'res.country', | 
				
			||||
 | 
					        string='Drop-Off Country', | 
				
			||||
 | 
					        help='Country where the vehicle will be dropped off.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    vehicle_id = fields.Many2one( | 
				
			||||
 | 
					        'fleet.vehicle', string='Vehicle', | 
				
			||||
 | 
					        help='The vehicle being rented.', | 
				
			||||
 | 
					        required=True) | 
				
			||||
 | 
					    model = fields.Char(related='vehicle_id.model_id.name', string='Model', | 
				
			||||
 | 
					                        help='Model of the rented vehicle.') | 
				
			||||
 | 
					    transmission = fields.Selection( | 
				
			||||
 | 
					        [('automatic', 'Automatic'), ('manual', 'Manual')], | 
				
			||||
 | 
					        string='Transmission', related='vehicle_id.transmission', | 
				
			||||
 | 
					        help='Transmission type of the rented vehicle.') | 
				
			||||
 | 
					    fuel_type = fields.Selection( | 
				
			||||
 | 
					        [ | 
				
			||||
 | 
					            ('diesel', 'Diesel'), | 
				
			||||
 | 
					            ('gasoline', 'Gasoline'), | 
				
			||||
 | 
					            ('full_hybrid', 'Full Hybrid'), | 
				
			||||
 | 
					            ('plug_in_hybrid_diesel', 'Plug-in Hybrid Diesel'), | 
				
			||||
 | 
					            ('plug_in_hybrid_gasoline', 'Plug-in Hybrid Gasoline'), | 
				
			||||
 | 
					            ('cng', 'CNG'), | 
				
			||||
 | 
					            ('lpg', 'LPG'), | 
				
			||||
 | 
					            ('hydrogen', 'Hydrogen'), | 
				
			||||
 | 
					            ('electric', 'Electric'), | 
				
			||||
 | 
					        ], string='Fuel Type', related='vehicle_id.fuel_type', | 
				
			||||
 | 
					        help='Fuel type of the rented vehicle.') | 
				
			||||
 | 
					    last_odometer = fields.Float( | 
				
			||||
 | 
					        string='Last Odometer', | 
				
			||||
 | 
					        related='vehicle_id.odometer', | 
				
			||||
 | 
					        help='Last recorded odometer reading of the vehicle.') | 
				
			||||
 | 
					    odometer_unit = fields.Selection( | 
				
			||||
 | 
					        [('kilometers', 'km'), ('miles', 'mi')], | 
				
			||||
 | 
					        string='Odometer Unit', default='kilometers', | 
				
			||||
 | 
					        related='vehicle_id.odometer_unit', | 
				
			||||
 | 
					        help='Unit of measurement for the odometer reading.') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    driver_required = fields.Boolean( | 
				
			||||
 | 
					        string='Driver Required', | 
				
			||||
 | 
					        help='Indicates if a driver is required for the rental.') | 
				
			||||
 | 
					    driver_id = fields.Many2one( | 
				
			||||
 | 
					        'res.partner', string='Driver', | 
				
			||||
 | 
					        help='Driver assigned to the rental if required.') | 
				
			||||
 | 
					    charge_type = fields.Selection( | 
				
			||||
 | 
					        [('excluding', 'Excluding in rent charge'), | 
				
			||||
 | 
					         ('including', 'Including in rent charge')], | 
				
			||||
 | 
					        string='Charge Type', | 
				
			||||
 | 
					        help='Specifies if the driver charge is included in the rental ' | 
				
			||||
 | 
					             'charge or not.') | 
				
			||||
 | 
					    driver_charge = fields.Float( | 
				
			||||
 | 
					        string='Driver Charge', | 
				
			||||
 | 
					        help='Charge for the driver if not included ' | 
				
			||||
 | 
					             'in the rental charge.') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    # Rent Details | 
				
			||||
 | 
					    rent_type = fields.Selection( | 
				
			||||
 | 
					        [('hours', 'Hours'), ('days', 'Days'), | 
				
			||||
 | 
					         ('kilometers', 'Kilometers')], | 
				
			||||
 | 
					        string='Rent Type', | 
				
			||||
 | 
					        default='hours', | 
				
			||||
 | 
					        help='Type of rent calculation (per day, per kilometer, or per mile).') | 
				
			||||
 | 
					    rent_per_hour = fields.Float(string='Rent / Hour', | 
				
			||||
 | 
					                                 help='Rental charge per hour.', | 
				
			||||
 | 
					                                 related='vehicle_id.rent_hour') | 
				
			||||
 | 
					    total_hours = fields.Float(string='Total Hours ', | 
				
			||||
 | 
					                               help="Total Hours Taken for Rent", | 
				
			||||
 | 
					                               compute='_compute_rental_period', store=True, | 
				
			||||
 | 
					                               readonly=False) | 
				
			||||
 | 
					    rent_per_day = fields.Float(string='Rent / Day', | 
				
			||||
 | 
					                                help='Rental charge per day.', | 
				
			||||
 | 
					                                related='vehicle_id.rent_day') | 
				
			||||
 | 
					    total_days = fields.Integer(string='Total Days', | 
				
			||||
 | 
					                                help='Total number of rental days.', | 
				
			||||
 | 
					                                compute='_compute_rental_period', store=True, | 
				
			||||
 | 
					                                readonly=False) | 
				
			||||
 | 
					    rent_per_km = fields.Float(string='Rent / KM', | 
				
			||||
 | 
					                               help='Rental charge per km.' | 
				
			||||
 | 
					                               , related='vehicle_id.rent_kilometer') | 
				
			||||
 | 
					    total_km = fields.Integer(string='Total KM', | 
				
			||||
 | 
					                              help='Total Kilometers.') | 
				
			||||
 | 
					    total_rental_charge = fields.Float( | 
				
			||||
 | 
					        string='Total Rental Charge', | 
				
			||||
 | 
					        compute='_compute_total_rental_charge', store=True, | 
				
			||||
 | 
					        help='Total rental charge for the contract.') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    payment_type = fields.Selection( | 
				
			||||
 | 
					        [('daily', 'Daily'), ('weekly', 'Weekly'), | 
				
			||||
 | 
					         ('monthly', 'Monthly'), | 
				
			||||
 | 
					         ('full', 'Fully')], | 
				
			||||
 | 
					        string='Payment Type', | 
				
			||||
 | 
					        help='Payment schedule for the rental charge.', | 
				
			||||
 | 
					        default='full') | 
				
			||||
 | 
					    invoice_item_id = fields.Many2one( | 
				
			||||
 | 
					        'product.product', | 
				
			||||
 | 
					        string='Invoice Item', | 
				
			||||
 | 
					        help='Description of the item to be invoiced.', | 
				
			||||
 | 
					        default=lambda self: self.env.ref( | 
				
			||||
 | 
					            'advanced_fleet_rental.product_product_vehicle_rental_charge')) | 
				
			||||
 | 
					    is_extra_charge = fields.Boolean(string='Is any extra charge', | 
				
			||||
 | 
					                                     help='Indicates if there are any extra ' | 
				
			||||
 | 
					                                          'charges applicable.') | 
				
			||||
 | 
					    extra_per_hour = fields.Float(string='Extra Charges / Hour', | 
				
			||||
 | 
					                                  help='Rental charge per hour.', | 
				
			||||
 | 
					                                  related='vehicle_id.charge_hour') | 
				
			||||
 | 
					    total_extra_hours = fields.Integer(string='Total Extra Hours', | 
				
			||||
 | 
					                                       help='Total number of rental hours.') | 
				
			||||
 | 
					    extra_per_day = fields.Float(string='Extra Charges / Day', | 
				
			||||
 | 
					                                 help='Rental charge per hour.', | 
				
			||||
 | 
					                                 related='vehicle_id.charge_day') | 
				
			||||
 | 
					    total_extra_days = fields.Integer(string='Total Extra Days', | 
				
			||||
 | 
					                                      help='Total number of rental days.') | 
				
			||||
 | 
					    extra_per_km = fields.Float(string='Extra Charges / KM', | 
				
			||||
 | 
					                                help='Rental charge per hour.', | 
				
			||||
 | 
					                                related='vehicle_id.charge_kilometer') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    total_extra_km = fields.Float(string='Total Extra K/M', | 
				
			||||
 | 
					                                  help="Total Extra K/M taken") | 
				
			||||
 | 
					    total_extra_charge = fields.Float(string="Total Extra Charge", | 
				
			||||
 | 
					                                      help="Extra Charges per K/M", | 
				
			||||
 | 
					                                      compute='_compute_total_extra_charge' | 
				
			||||
 | 
					                                      , store=True) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    rental_payment_plan_ids = (fields.One2many | 
				
			||||
 | 
					                               ('rental.payment.plan', | 
				
			||||
 | 
					                                'contract_id', | 
				
			||||
 | 
					                                string="Vehicle Payment Details", | 
				
			||||
 | 
					                                help="Details of the paymentplans for the" | 
				
			||||
 | 
					                                     " vehicle rental.")) | 
				
			||||
 | 
					    extra_service_ids = (fields.One2many | 
				
			||||
 | 
					                         ('extra.service', | 
				
			||||
 | 
					                          'contract_id', | 
				
			||||
 | 
					                          string="Extra Services", | 
				
			||||
 | 
					                          help="List of extra services associated with this" | 
				
			||||
 | 
					                               "vehicle rental." | 
				
			||||
 | 
					                          )) | 
				
			||||
 | 
					    is_extra_invoice_created = fields.Boolean( | 
				
			||||
 | 
					        string='Extra Invoice Created', | 
				
			||||
 | 
					        help="Indicates whether an extra invoice has been created for the" | 
				
			||||
 | 
					             " extra services.") | 
				
			||||
 | 
					    image_ids = fields.One2many( | 
				
			||||
 | 
					        'multi.image', | 
				
			||||
 | 
					        'contract_id', | 
				
			||||
 | 
					        string="Images of the Vehicle", | 
				
			||||
 | 
					        help="Images related to the Vehicles of vehicle rental." | 
				
			||||
 | 
					    ) | 
				
			||||
 | 
					    insurance_ids = fields.One2many( | 
				
			||||
 | 
					        'insurance.policy', | 
				
			||||
 | 
					        'contract_id', | 
				
			||||
 | 
					        string="Insurance Policy", | 
				
			||||
 | 
					        help="Insurance policies associated with the vehicle rental.") | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    vehicle_to_invoice_count = fields.Integer( | 
				
			||||
 | 
					        string='Number of vehicle rent to invoice', | 
				
			||||
 | 
					        compute='_compute_vehicle_to_invoice', | 
				
			||||
 | 
					        readonly=True, | 
				
			||||
 | 
					        help="Number of vehicle rental invoices that is created." | 
				
			||||
 | 
					    ) | 
				
			||||
 | 
					    is_damaged_invoiced = fields.Boolean( | 
				
			||||
 | 
					        string='Damage Invoice Created', | 
				
			||||
 | 
					        help="Indicates whether an extra invoice has been created for the" | 
				
			||||
 | 
					             " extra services.") | 
				
			||||
 | 
					    cancellation_policy_id = fields.Many2one( | 
				
			||||
 | 
					        'cancellation.policy', string='Cancellation Policy', | 
				
			||||
 | 
					        help='Select the cancellation policy applicable for this record. ' | 
				
			||||
 | 
					             'The cancellation charges will be calculated based on the ' | 
				
			||||
 | 
					             'selected policy.') | 
				
			||||
 | 
					    cancellation_charge = fields.Float(string='Cancellation Charge') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    cancellation_terms = fields.Text( | 
				
			||||
 | 
					        string='Cancellation Terms and Conditions', | 
				
			||||
 | 
					        related="cancellation_policy_id.terms_conditions", | 
				
			||||
 | 
					        readonly=False) | 
				
			||||
 | 
					    is_cancelled_invoiced = fields.Boolean( | 
				
			||||
 | 
					        string='Cancelled Invoice Created', | 
				
			||||
 | 
					        help="Indicates whether an cancelled invoice has been created for the" | 
				
			||||
 | 
					             "Cancellation Policy.") | 
				
			||||
 | 
					    digital_sign = fields.Binary(string='Signature', help="Binary field to " | 
				
			||||
 | 
					                                                          "store digital " | 
				
			||||
 | 
					                                                          "signatures.") | 
				
			||||
 | 
					    sign_date = fields.Datetime( | 
				
			||||
 | 
					        string='Sign Date', | 
				
			||||
 | 
					        help='Date and time of the signature signed.') | 
				
			||||
 | 
					    currency_id = fields.Many2one( | 
				
			||||
 | 
					        'res.currency', 'Currency', | 
				
			||||
 | 
					        default=lambda self: self.env.user.company_id.currency_id.id, | 
				
			||||
 | 
					        help="if you select this currency bidding will be on that currency " | 
				
			||||
 | 
					             "itself") | 
				
			||||
 | 
					    damage_description = fields.Text(string="Damage Description") | 
				
			||||
 | 
					    damage_amount = fields.Float(string="Damage Amount", | 
				
			||||
 | 
					                                 help="Total Amount for the damages") | 
				
			||||
 | 
					    # Responsible | 
				
			||||
 | 
					    responsible_id = fields.Many2one( | 
				
			||||
 | 
					        'res.users', string='Responsible', | 
				
			||||
 | 
					        help='User responsible for managing the rental contract.', | 
				
			||||
 | 
					        required=True, tracking=True) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.onchange('pickup_state_id') | 
				
			||||
 | 
					    def _onchange_pickup_state(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Automatically updates the 'Pick-Up Country' field based on the selected 'Pick-Up State'. | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        When a user selects a state for vehicle pick-up, this method fetches the corresponding | 
				
			||||
 | 
					        country from the selected state and sets it in the 'Pick-Up Country' field. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        if self.pickup_state_id: | 
				
			||||
 | 
					            self.pickup_country_id = self.pickup_state_id.country_id | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.onchange('dropoff_state_id') | 
				
			||||
 | 
					    def _onchange_dropoff_state(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Automatically updates the 'Drop-Off Country' field based on the selected 'Drop-Off State'. | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        When a user selects a state for vehicle drop-off, this method fetches the corresponding | 
				
			||||
 | 
					        country from the selected state and sets it in the 'Drop-Off Country' field. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        if self.dropoff_state_id: | 
				
			||||
 | 
					            self.dropoff_country_id = self.dropoff_state_id.country_id | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def _group_expand_states(self, states, domain, order): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Expands the available group states for selection. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        return ['new', 'in_progress', 'return', 'cancel'] | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.model | 
				
			||||
 | 
					    def create(self, vals_list): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Override the create method to set a default sequence number if not | 
				
			||||
 | 
					        provided. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        if vals_list.get('name', 'New') == 'New': | 
				
			||||
 | 
					            vals_list['name'] = self.env['ir.sequence'].next_by_code( | 
				
			||||
 | 
					                'vehicle.sequence') or 'New' | 
				
			||||
 | 
					        return super().create(vals_list) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.depends('extra_per_hour', 'total_extra_hours', 'extra_per_day', | 
				
			||||
 | 
					                 'total_extra_days', 'extra_per_km', 'total_extra_km') | 
				
			||||
 | 
					    def _compute_total_extra_charge(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Compute the total extra charge based on the rent type and extra usage | 
				
			||||
 | 
					        (hours, days, kilometers). | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        for record in self: | 
				
			||||
 | 
					            if record.rent_type == 'hours': | 
				
			||||
 | 
					                record.total_extra_charge = (record.extra_per_hour * | 
				
			||||
 | 
					                                             record.total_extra_hours) | 
				
			||||
 | 
					            elif record.rent_type == 'days': | 
				
			||||
 | 
					                record.total_extra_charge = (record.extra_per_day * | 
				
			||||
 | 
					                                             record.total_extra_days) | 
				
			||||
 | 
					            elif record.rent_type == 'kilometers': | 
				
			||||
 | 
					                record.total_extra_charge = ( | 
				
			||||
 | 
					                        record.extra_per_km * record.total_extra_km) | 
				
			||||
 | 
					            else: | 
				
			||||
 | 
					                record.total_extra_charge = 0 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.depends( | 
				
			||||
 | 
					        'rent_type', | 
				
			||||
 | 
					        'rent_per_hour', 'total_hours', | 
				
			||||
 | 
					        'rent_per_day', 'total_days', | 
				
			||||
 | 
					        'rent_per_km', 'total_km', | 
				
			||||
 | 
					        'driver_charge', 'charge_type', | 
				
			||||
 | 
					        'driver_required' | 
				
			||||
 | 
					    ) | 
				
			||||
 | 
					    def _compute_total_rental_charge(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Compute the total rental charge based on the rent type and usage | 
				
			||||
 | 
					        (hours, days, kilometers). Include driver charge if applicable. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        for record in self: | 
				
			||||
 | 
					            if record.rent_type == 'hours': | 
				
			||||
 | 
					                record.total_rental_charge = ( | 
				
			||||
 | 
					                        record.rent_per_hour * record.total_hours) | 
				
			||||
 | 
					            elif record.rent_type == 'days': | 
				
			||||
 | 
					                record.total_rental_charge = ( | 
				
			||||
 | 
					                        record.rent_per_day * record.total_days) | 
				
			||||
 | 
					            elif record.rent_type == 'kilometers': | 
				
			||||
 | 
					                record.total_rental_charge = ( | 
				
			||||
 | 
					                        record.rent_per_km * record.total_km) | 
				
			||||
 | 
					            else: | 
				
			||||
 | 
					                record.total_rental_charge = 0 | 
				
			||||
 | 
					            if record.charge_type == 'including' and record.driver_required: | 
				
			||||
 | 
					                record.total_rental_charge += record.driver_charge | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_create_extra_invoice(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Create an invoice for extra charges incurred during the rental period. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        product_id = self.env.ref( | 
				
			||||
 | 
					            'advanced_fleet_rental.product_product_vehicle_extra_rental_charge') | 
				
			||||
 | 
					        invoice_vals = { | 
				
			||||
 | 
					            'partner_id': self.customer_id.id, | 
				
			||||
 | 
					            'move_type': 'out_invoice', | 
				
			||||
 | 
					            'vehicle_rental_id': self.id, | 
				
			||||
 | 
					            'invoice_date': date.today(), | 
				
			||||
 | 
					            'invoice_line_ids': [(0, 0, { | 
				
			||||
 | 
					                'product_id': product_id.id, | 
				
			||||
 | 
					                'name': product_id.name, | 
				
			||||
 | 
					                'quantity': 1, | 
				
			||||
 | 
					                'price_unit': self.total_extra_charge, | 
				
			||||
 | 
					            })], | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					        invoice = self.env['account.move'].create(invoice_vals) | 
				
			||||
 | 
					        invoice.action_post() | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_installment(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Generate the rental payment plan based on the selected payment type. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        self.ensure_one() | 
				
			||||
 | 
					        self.rental_payment_plan_ids.unlink() | 
				
			||||
 | 
					        if self.rent_type == 'kilometers' and self.total_km == 0: | 
				
			||||
 | 
					            raise ValidationError( | 
				
			||||
 | 
					                _('If the rent type is "kilometers", the total ' | 
				
			||||
 | 
					                  'kilometers cannot be 0.')) | 
				
			||||
 | 
					        if self.rent_type == 'hours' and self.payment_type != 'full': | 
				
			||||
 | 
					            raise ValidationError( | 
				
			||||
 | 
					                _('If the rent type is "hours", the payment type must be ' | 
				
			||||
 | 
					                  '"full".')) | 
				
			||||
 | 
					        if self.rent_type == 'kilometers' and self.payment_type != 'full': | 
				
			||||
 | 
					            raise ValidationError( | 
				
			||||
 | 
					                _('If the rent type is "kilometers", the payment type must be ' | 
				
			||||
 | 
					                  '"full".')) | 
				
			||||
 | 
					        if (self.rent_type == 'days' and self.payment_type == 'weekly' | 
				
			||||
 | 
					                and self.total_days < 7): | 
				
			||||
 | 
					            raise ValidationError(_( | 
				
			||||
 | 
					                'The total days are less than a week. ' | 
				
			||||
 | 
					                'Please select a valid payment type.')) | 
				
			||||
 | 
					        if (self.rent_type == 'days' and self.payment_type == 'monthly' | 
				
			||||
 | 
					                and self.total_days < 30): | 
				
			||||
 | 
					            raise ValidationError(_( | 
				
			||||
 | 
					                'The total days are less than a month. ' | 
				
			||||
 | 
					                'Please select a valid payment type.')) | 
				
			||||
 | 
					        pick_up = self.pickup_date | 
				
			||||
 | 
					        drop_date = self.dropoff_date | 
				
			||||
 | 
					        total_amount = self.total_rental_charge | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        if self.payment_type == 'full': | 
				
			||||
 | 
					            self.env['rental.payment.plan'].create({ | 
				
			||||
 | 
					                'contract_id': self.id, | 
				
			||||
 | 
					                'invoice_item_id': self.invoice_item_id.id, | 
				
			||||
 | 
					                'payment_date': pick_up, | 
				
			||||
 | 
					                'payment_amount': total_amount, | 
				
			||||
 | 
					                'payment_state': 'not_paid', | 
				
			||||
 | 
					            }) | 
				
			||||
 | 
					            return | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        # Calculate interval and number of installments based on rent_type | 
				
			||||
 | 
					        if self.rent_type == 'hours': | 
				
			||||
 | 
					            amount_per_unit = self.rent_per_hour | 
				
			||||
 | 
					            base_interval = relativedelta(hours=1) | 
				
			||||
 | 
					        elif self.rent_type == 'days': | 
				
			||||
 | 
					            amount_per_unit = self.rent_per_day | 
				
			||||
 | 
					            base_interval = relativedelta(days=1) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        if self.payment_type == 'daily': | 
				
			||||
 | 
					            payment_interval = relativedelta(days=1) | 
				
			||||
 | 
					            current_date = pick_up | 
				
			||||
 | 
					        elif self.payment_type == 'weekly': | 
				
			||||
 | 
					            payment_interval = relativedelta(weeks=1) | 
				
			||||
 | 
					            current_date = pick_up | 
				
			||||
 | 
					        elif self.payment_type == 'monthly': | 
				
			||||
 | 
					            payment_interval = relativedelta(months=1) | 
				
			||||
 | 
					            current_date = pick_up + payment_interval | 
				
			||||
 | 
					        else: | 
				
			||||
 | 
					            payment_interval = base_interval | 
				
			||||
 | 
					        while current_date < drop_date: | 
				
			||||
 | 
					            next_date = min(current_date + payment_interval, drop_date) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            # Calculate units in this payment period | 
				
			||||
 | 
					            if self.rent_type == 'hours': | 
				
			||||
 | 
					                units_in_period = ( | 
				
			||||
 | 
					                                          next_date - current_date).total_seconds() / 3600 | 
				
			||||
 | 
					            elif self.rent_type == 'days': | 
				
			||||
 | 
					                units_in_period = (next_date - current_date).days | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            installment_amount = units_in_period * amount_per_unit | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            if installment_amount > 0: | 
				
			||||
 | 
					                self.env['rental.payment.plan'].create({ | 
				
			||||
 | 
					                    'contract_id': self.id, | 
				
			||||
 | 
					                    'invoice_item_id': self.invoice_item_id.id, | 
				
			||||
 | 
					                    'payment_date': current_date, | 
				
			||||
 | 
					                    'payment_amount': installment_amount, | 
				
			||||
 | 
					                    'payment_state': 'not_paid', | 
				
			||||
 | 
					                }) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            current_date = next_date | 
				
			||||
 | 
					        # Handle any remaining amount due to rounding | 
				
			||||
 | 
					        remaining_amount = total_amount - sum( | 
				
			||||
 | 
					            self.rental_payment_plan_ids.mapped('payment_amount')) | 
				
			||||
 | 
					        if remaining_amount > 0: | 
				
			||||
 | 
					            self.env['rental.payment.plan'].create({ | 
				
			||||
 | 
					                'contract_id': self.id, | 
				
			||||
 | 
					                'invoice_item_id': self.invoice_item_id.id, | 
				
			||||
 | 
					                'payment_date': drop_date, | 
				
			||||
 | 
					                'payment_amount': remaining_amount, | 
				
			||||
 | 
					                'payment_state': 'not_paid', | 
				
			||||
 | 
					            }) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.depends('pickup_date', 'dropoff_date') | 
				
			||||
 | 
					    def _compute_rental_period(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Compute the total rental period in hours and days based on pickup | 
				
			||||
 | 
					         and drop-off dates. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        for record in self: | 
				
			||||
 | 
					            if record.pickup_date and record.dropoff_date: | 
				
			||||
 | 
					                pickup = fields.Datetime.from_string(record.pickup_date) | 
				
			||||
 | 
					                dropoff = fields.Datetime.from_string(record.dropoff_date) | 
				
			||||
 | 
					                delta = dropoff - pickup | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                # Calculate total days | 
				
			||||
 | 
					                total_days = delta.days + 1 | 
				
			||||
 | 
					                record.total_days = total_days | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                # Calculate total hours | 
				
			||||
 | 
					                total_hours = delta.total_seconds() / 3600 | 
				
			||||
 | 
					                record.total_hours = total_hours | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					            else: | 
				
			||||
 | 
					                record.total_days = 0 | 
				
			||||
 | 
					                record.total_hours = 0 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.constrains('rent_type', 'pickup_date', 'dropoff_date', 'total_hours', | 
				
			||||
 | 
					                    'total_days', ) | 
				
			||||
 | 
					    def _check_rental_period(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Ensure the drop-off date is not before the pick-up date. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        for record in self: | 
				
			||||
 | 
					            if record.pickup_date and record.dropoff_date: | 
				
			||||
 | 
					                pickup = fields.Datetime.from_string(record.pickup_date) | 
				
			||||
 | 
					                dropoff = fields.Datetime.from_string(record.dropoff_date) | 
				
			||||
 | 
					                delta = dropoff - pickup | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                if record.rent_type == 'hours': | 
				
			||||
 | 
					                    total_hours_computed = delta.total_seconds() / 3600 | 
				
			||||
 | 
					                    if record.total_hours > total_hours_computed: | 
				
			||||
 | 
					                        raise ValidationError( | 
				
			||||
 | 
					                            f'The total hours ({record.total_hours})' | 
				
			||||
 | 
					                            f' exceed the period between the pickup ' | 
				
			||||
 | 
					                            f'and dropoff dates.') | 
				
			||||
 | 
					                    if record.total_hours == 0: | 
				
			||||
 | 
					                        raise ValidationError( | 
				
			||||
 | 
					                            f'The total hours cannot be zero.') | 
				
			||||
 | 
					                if record.rent_type == 'days': | 
				
			||||
 | 
					                    total_days_computed = delta.days + 1 | 
				
			||||
 | 
					                    if record.total_days > total_days_computed: | 
				
			||||
 | 
					                        raise ValidationError( | 
				
			||||
 | 
					                            f'The total days ({record.total_days})' | 
				
			||||
 | 
					                            f' exceed the period between the pickup ' | 
				
			||||
 | 
					                            f'and dropoff dates.') | 
				
			||||
 | 
					                    if record.total_days == 0: | 
				
			||||
 | 
					                        raise ValidationError( | 
				
			||||
 | 
					                            f'The total days cannot be zero.') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_account_tab(self): | 
				
			||||
 | 
					        """View the Invoices in the Smart Tab.""" | 
				
			||||
 | 
					        return { | 
				
			||||
 | 
					            'type': 'ir.actions.act_window', | 
				
			||||
 | 
					            'name': 'Invoices', | 
				
			||||
 | 
					            'res_model': 'account.move', | 
				
			||||
 | 
					            'target': 'current', | 
				
			||||
 | 
					            'domain': [('partner_id', '=', self.customer_id.id), | 
				
			||||
 | 
					                       ('vehicle_rental_id', '=', self.id)], | 
				
			||||
 | 
					            'view_mode': 'tree,form', | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def _compute_vehicle_to_invoice(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Computes the number of invoices related to the vehicle rental | 
				
			||||
 | 
					        contract and updates the 'vehicle_to_invoice_count' field for each record. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        for record in self: | 
				
			||||
 | 
					            record.vehicle_to_invoice_count = self.env[ | 
				
			||||
 | 
					                'account.move'].search_count([ | 
				
			||||
 | 
					                ('vehicle_rental_id', '=', record.id) | 
				
			||||
 | 
					            ]) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_extra_invoice_charge(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Creates an invoice for extra services added to the vehicle | 
				
			||||
 | 
					        rental contract. If there are no extra services, raises a | 
				
			||||
 | 
					        ValidationError. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        if self.extra_service_ids: | 
				
			||||
 | 
					            invoice_line_vals = [ | 
				
			||||
 | 
					                { | 
				
			||||
 | 
					                    'product_id': line.product_id.id, | 
				
			||||
 | 
					                    'name': line.description or line.product_id.name, | 
				
			||||
 | 
					                    'quantity': line.quantity, | 
				
			||||
 | 
					                    'price_unit': line.amount, | 
				
			||||
 | 
					                } | 
				
			||||
 | 
					                for line in self.extra_service_ids | 
				
			||||
 | 
					            ] | 
				
			||||
 | 
					            invoice_vals = { | 
				
			||||
 | 
					                'move_type': 'out_invoice', | 
				
			||||
 | 
					                'partner_id': self.customer_id.id, | 
				
			||||
 | 
					                'invoice_line_ids': [(0, 0, line) for line in | 
				
			||||
 | 
					                                     invoice_line_vals], | 
				
			||||
 | 
					                'vehicle_rental_id': self.id, | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            invoice = self.env['account.move'].create(invoice_vals) | 
				
			||||
 | 
					            invoice.action_post() | 
				
			||||
 | 
					            self.is_extra_invoice_created = True | 
				
			||||
 | 
					        else: | 
				
			||||
 | 
					            raise ValidationError( | 
				
			||||
 | 
					                _('Add Extra Services Products.')) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_damage_invoice(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        This method opens a new window to link invoices and remove invoices | 
				
			||||
 | 
					        for the current sale order. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        return { | 
				
			||||
 | 
					            "type": "ir.actions.act_window", | 
				
			||||
 | 
					            "name": "Damage Invoices", | 
				
			||||
 | 
					            "view_mode": "form", | 
				
			||||
 | 
					            "res_model": "damage.invoice", | 
				
			||||
 | 
					            "target": "new", | 
				
			||||
 | 
					            "context": { | 
				
			||||
 | 
					                "default_contract_id": self.id, | 
				
			||||
 | 
					            }, | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_cancel(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Cancels the rental contract by setting its state to 'cancel'. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        self.write({'state': 'cancel'}) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_cancel_charges(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Creates an invoice for the cancellation charges based on the contract's | 
				
			||||
 | 
					        cancellation policy. The invoice is created using a predefined product | 
				
			||||
 | 
					        for cancellation charges. If the cancellation policy is not set, | 
				
			||||
 | 
					        it raises a ValidationError. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        if self.cancellation_policy_id: | 
				
			||||
 | 
					            product_id = self.env.ref( | 
				
			||||
 | 
					                'advanced_fleet_rental.product_product_vehicle_cancel_charge') | 
				
			||||
 | 
					            invoice_vals = { | 
				
			||||
 | 
					                'partner_id': self.customer_id.id, | 
				
			||||
 | 
					                'move_type': 'out_invoice', | 
				
			||||
 | 
					                'vehicle_rental_id': self.id, | 
				
			||||
 | 
					                'invoice_date': date.today(), | 
				
			||||
 | 
					                'invoice_line_ids': [(0, 0, { | 
				
			||||
 | 
					                    'product_id': product_id.id, | 
				
			||||
 | 
					                    'name': self.cancellation_terms, | 
				
			||||
 | 
					                    'quantity': 1, | 
				
			||||
 | 
					                    'price_unit': self.cancellation_charge, | 
				
			||||
 | 
					                })], | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					            invoice = self.env['account.move'].create(invoice_vals) | 
				
			||||
 | 
					            self.is_cancelled_invoiced = True | 
				
			||||
 | 
					            return { | 
				
			||||
 | 
					                'type': 'ir.actions.act_window', | 
				
			||||
 | 
					                'res_model': 'account.move', | 
				
			||||
 | 
					                'view_mode': 'form', | 
				
			||||
 | 
					                'res_id': invoice.id, | 
				
			||||
 | 
					                'target': 'current', | 
				
			||||
 | 
					            } | 
				
			||||
 | 
					        else: | 
				
			||||
 | 
					            raise ValidationError( | 
				
			||||
 | 
					                _("No cancellation policy set on the contract.")) | 
				
			||||
@ -0,0 +1,45 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from odoo import fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class FleetVehicle(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Inherits from 'fleet.vehicle' to add additional fields and functionality. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _inherit = 'fleet.vehicle' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    status = fields.Selection([ | 
				
			||||
 | 
					        ('operational', 'Operational'), | 
				
			||||
 | 
					        ('undermaintenance', 'Under Maintenance'), | 
				
			||||
 | 
					    ], default='operational') | 
				
			||||
 | 
					    rent_hour = fields.Float(string='Rent / Hour', help="Rent per hour") | 
				
			||||
 | 
					    rent_day = fields.Float(string='Rent / Day', help="Rent per day") | 
				
			||||
 | 
					    rent_kilometer = fields.Float(string='Rent / Kilometer', | 
				
			||||
 | 
					                                  help="Rent per kilometer") | 
				
			||||
 | 
					    charge_hour = fields.Float(string='Extra Charge / Hour', | 
				
			||||
 | 
					                               help="Extra charge per hour") | 
				
			||||
 | 
					    charge_day = fields.Float(string='Extra Charge / Day', | 
				
			||||
 | 
					                              help="Extra charge per day") | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    charge_kilometer = fields.Float(string='Extra Charge / Kilometer', | 
				
			||||
 | 
					                                    help="Extra charge per kilometer") | 
				
			||||
@ -0,0 +1,55 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from odoo import fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class InsurancePolicy(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Model for managing insurance policies related to fleet rental contracts. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _name = 'insurance.policy' | 
				
			||||
 | 
					    _description = 'Insurance Policy' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    policy_number = fields.Char( | 
				
			||||
 | 
					        string='Policy Number', | 
				
			||||
 | 
					        required=True, | 
				
			||||
 | 
					        help='Unique identifier for the insurance policy.') | 
				
			||||
 | 
					    name = fields.Char( | 
				
			||||
 | 
					        string='Name', | 
				
			||||
 | 
					        required=True, | 
				
			||||
 | 
					        help='Name of the insurance policy.') | 
				
			||||
 | 
					    description = fields.Char( | 
				
			||||
 | 
					        string='Description', | 
				
			||||
 | 
					        help='Brief description of the insurance policy.') | 
				
			||||
 | 
					    document = fields.Binary( | 
				
			||||
 | 
					        string='Document', | 
				
			||||
 | 
					        help='Upload the document related to the insurance policy.') | 
				
			||||
 | 
					    file_name = fields.Char( | 
				
			||||
 | 
					        string="File Name", | 
				
			||||
 | 
					        help='File Name of the Document') | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    policy_amount = fields.Float( | 
				
			||||
 | 
					        string='Policy Amount', | 
				
			||||
 | 
					        help='Total amount covered by the insurance policy.') | 
				
			||||
 | 
					    contract_id = fields.Many2one('fleet.rental.contract', | 
				
			||||
 | 
					                                  string='Contract Rent', | 
				
			||||
 | 
					                                  help='Reference to the vehicle rent.') | 
				
			||||
@ -0,0 +1,35 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from odoo import fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class MultiImage(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Model for storing multiple images related to a fleet rental contract. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _name = 'multi.image' | 
				
			||||
 | 
					    _description = 'Multi Image' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    image = fields.Binary(string="Image", help="Upload the Images") | 
				
			||||
 | 
					    contract_id = fields.Many2one( | 
				
			||||
 | 
					        'fleet.rental.contract', string='Rental Contract', | 
				
			||||
 | 
					        ondelete='cascade', readonly=True) | 
				
			||||
@ -0,0 +1,105 @@ | 
				
			|||||
 | 
					# -*- coding: utf-8 -*- | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Cybrosys Technologies Pvt. Ltd. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			||||
 | 
					#    Author: Anfas Faisal K (odoo@cybrosys.com) | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    This program is under the terms of the Odoo Proprietary License v1.0(OPL-1) | 
				
			||||
 | 
					#    It is forbidden to publish, distribute, sublicense, or sell copies of the | 
				
			||||
 | 
					#    Software or modified copies of the Software. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					#    THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
				
			||||
 | 
					#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
				
			||||
 | 
					#    FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL | 
				
			||||
 | 
					#    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER | 
				
			||||
 | 
					#    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING | 
				
			||||
 | 
					#    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 
				
			||||
 | 
					#    DEALINGS IN THE SOFTWARE. | 
				
			||||
 | 
					# | 
				
			||||
 | 
					############################################################################### | 
				
			||||
 | 
					from datetime import date | 
				
			||||
 | 
					from odoo import api, fields, models | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					class RentalPaymentPlan(models.Model): | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    Model for managing rental payment plans associated with fleet rental | 
				
			||||
 | 
					    contracts. | 
				
			||||
 | 
					    """ | 
				
			||||
 | 
					    _name = 'rental.payment.plan' | 
				
			||||
 | 
					    _description = 'Rental Payment Plan' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    contract_id = fields.Many2one( | 
				
			||||
 | 
					        'fleet.rental.contract', string='Rental Contract', | 
				
			||||
 | 
					        ondelete='cascade') | 
				
			||||
 | 
					    invoice_item_id = fields.Many2one('product.product', | 
				
			||||
 | 
					                                   string='Invoice Item', ) | 
				
			||||
 | 
					    payment_date = fields.Date(string='Payment Date' ) | 
				
			||||
 | 
					    payment_amount = fields.Float( | 
				
			||||
 | 
					        string='Payment Amount', | 
				
			||||
 | 
					        help='Amount to be paid based on the invoice item.') | 
				
			||||
 | 
					    invoice_id = fields.Many2one('account.move', string='Invoice', | 
				
			||||
 | 
					                                 readonly=True) | 
				
			||||
 | 
					    payment_state = fields.Selection( | 
				
			||||
 | 
					        [ | 
				
			||||
 | 
					            ('not_paid', 'Not Paid'), | 
				
			||||
 | 
					            ('in_payment', 'In Payment'), | 
				
			||||
 | 
					            ('paid', 'Paid'), | 
				
			||||
 | 
					            ('partial', 'Partially Paid'), | 
				
			||||
 | 
					            ('reversed', 'Reversed'), | 
				
			||||
 | 
					            ('invoicing_legacy', 'Invoicing App Legacy'), | 
				
			||||
 | 
					        ], compute='_compute_payment_state', | 
				
			||||
 | 
					        string='Payment State') | 
				
			||||
 | 
					    is_invoiced = fields.Boolean(string="Invoice Button", help="Invoiced") | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.depends('invoice_id.payment_state') | 
				
			||||
 | 
					    def _compute_payment_state(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Computes the payment state based on the associated invoice's | 
				
			||||
 | 
					        payment state. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        for record in self: | 
				
			||||
 | 
					            if record.invoice_id: | 
				
			||||
 | 
					                record.payment_state = record.invoice_id.payment_state | 
				
			||||
 | 
					            else: | 
				
			||||
 | 
					                record.payment_state = 'not_paid' | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    def action_create_invoice(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Creates an invoice for the payment plan. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        self.ensure_one() | 
				
			||||
 | 
					        invoice_vals = { | 
				
			||||
 | 
					            'partner_id': self.contract_id.customer_id.id, | 
				
			||||
 | 
					            'move_type': 'out_invoice', | 
				
			||||
 | 
					            'invoice_date': self.payment_date, | 
				
			||||
 | 
					            'vehicle_rental_id': self.contract_id.id, | 
				
			||||
 | 
					            'invoice_line_ids': [(0, 0, { | 
				
			||||
 | 
					                'product_id': self.invoice_item_id.id, | 
				
			||||
 | 
					                'name': self.invoice_item_id.name, | 
				
			||||
 | 
					                'quantity': 1, | 
				
			||||
 | 
					                'price_unit': self.payment_amount, | 
				
			||||
 | 
					            })], | 
				
			||||
 | 
					        } | 
				
			||||
 | 
					        invoice = self.env['account.move'].create(invoice_vals) | 
				
			||||
 | 
					        invoice.action_post() | 
				
			||||
 | 
					        self.invoice_id = invoice.id | 
				
			||||
 | 
					        self.is_invoiced = True | 
				
			||||
 | 
					        return invoice | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    @api.model | 
				
			||||
 | 
					    def _schedule_auto_invoice_checker(self): | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        Scheduled action to automatically generate invoices for rental payment | 
				
			||||
 | 
					        plans where the payment date is today. Searches for payment plans with | 
				
			||||
 | 
					        today's date and no associated invoice, and generates invoices for them. | 
				
			||||
 | 
					        """ | 
				
			||||
 | 
					        today = date.today() | 
				
			||||
 | 
					        payment_plans = self.search([ | 
				
			||||
 | 
					            ('payment_date', '=', today), | 
				
			||||
 | 
					            ('invoice_id', '=', False) | 
				
			||||
 | 
					        ]) | 
				
			||||
 | 
					        for plan in payment_plans: | 
				
			||||
 | 
					            plan.action_create_invoice() | 
				
			||||
@ -0,0 +1,13 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="UTF-8"?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					<!--    Report Function inside Contract Form--> | 
				
			||||
 | 
					    <record id="vehicle_contract_report" model="ir.actions.report"> | 
				
			||||
 | 
					        <field name="name">Vehicle Rental Report</field> | 
				
			||||
 | 
					        <field name="model">fleet.rental.contract</field> | 
				
			||||
 | 
					        <field name="report_type">qweb-pdf</field> | 
				
			||||
 | 
					        <field name="report_name">advanced_fleet_rental.report_fleet_rental_contract</field> | 
				
			||||
 | 
					        <field name="report_file">advanced_fleet_rental.report_fleet_rental_contract</field> | 
				
			||||
 | 
					        <field name="binding_model_id" ref="model_fleet_rental_contract"/> | 
				
			||||
 | 
					        <field name="binding_type">report</field> | 
				
			||||
 | 
					    </record> | 
				
			||||
 | 
					</odoo> | 
				
			||||
@ -0,0 +1,393 @@ | 
				
			|||||
 | 
					<?xml version="1.0" encoding="UTF-8" ?> | 
				
			||||
 | 
					<odoo> | 
				
			||||
 | 
					    <!-- Report Template--> | 
				
			||||
 | 
					    <template id="report_fleet_rental_contract"> | 
				
			||||
 | 
					        <t t-call="web.html_container"> | 
				
			||||
 | 
					            <t t-foreach="docs" t-as="data"> | 
				
			||||
 | 
					                <t t-call="web.external_layout"> | 
				
			||||
 | 
					                    <div class="page" style="font-size: 12pt;"> | 
				
			||||
 | 
					                        <h2 style="text-align: center;">Vehicle Contract | 
				
			||||
 | 
					                            Details | 
				
			||||
 | 
					                        </h2> | 
				
			||||
 | 
					                        <p>Reference Number: | 
				
			||||
 | 
					                            <span t-field="data.name"/> | 
				
			||||
 | 
					                        </p> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid transparent; border-collapse: collapse; width: 100%;"> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td colspan="2"> | 
				
			||||
 | 
					                                    <strong>Customer Details</strong> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td style="width: 50%;"> | 
				
			||||
 | 
					                                    <span>Customer:</span> | 
				
			||||
 | 
					                                    <span t-field="data.customer_id.name"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                                <td style="width: 50%; text-align: right;"> | 
				
			||||
 | 
					                                    <span>Phone:</span> | 
				
			||||
 | 
					                                    <span t-field="data.customer_id.phone"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Email:</span> | 
				
			||||
 | 
					                                    <span t-field="data.email"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid transparent; width: 100%; margin-top: 10px;"> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td colspan="2"> | 
				
			||||
 | 
					                                    <strong>Pick-Up & Drop-Off Details | 
				
			||||
 | 
					                                    </strong> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <span>Pick-up Date:</span> | 
				
			||||
 | 
					                                    <span t-field="data.pickup_date"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Pick-Up Location:</span> | 
				
			||||
 | 
					                                    <span t-field="data.pickup_location"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span t-field="data.pickup_street"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span t-field="data.pickup_city"/>, | 
				
			||||
 | 
					                                    <span t-field="data.pickup_state_id.name"/> | 
				
			||||
 | 
					                                    <span t-field="data.pickup_zip"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span t-field="data.pickup_country_id.name"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <span>Drop-off Date:</span> | 
				
			||||
 | 
					                                    <span t-field="data.dropoff_date"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Drop-Off Location:</span> | 
				
			||||
 | 
					                                    <span t-field="data.dropoff_location"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span t-field="data.dropoff_street"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span t-field="data.dropoff_city"/>, | 
				
			||||
 | 
					                                    <span t-field="data.dropoff_state_id.name"/> | 
				
			||||
 | 
					                                    <span t-field="data.dropoff_zip"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span t-field="data.dropoff_country_id.name"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <!--Vehicle Deatils--> | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid transparent; width: 100%; margin-top: 10px;"> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td colspan="2"> | 
				
			||||
 | 
					                                    <strong>Vehicle Details</strong> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <span>Vehicle:</span> | 
				
			||||
 | 
					                                    <span t-field="data.vehicle_id.name"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Model:</span> | 
				
			||||
 | 
					                                    <span t-field="data.model"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Transmission:</span> | 
				
			||||
 | 
					                                    <span t-field="data.transmission"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Fuel Type:</span> | 
				
			||||
 | 
					                                    <span t-field="data.fuel_type"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Last Odometer:</span> | 
				
			||||
 | 
					                                    <span t-field="data.last_odometer"/> | 
				
			||||
 | 
					                                    <span t-field="data.odometer_unit"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <t t-if="data.driver_required"> | 
				
			||||
 | 
					                                        <span>Driver:</span> | 
				
			||||
 | 
					                                        <span t-field="data.driver_id.name"/> | 
				
			||||
 | 
					                                        <br/> | 
				
			||||
 | 
					                                        <span>Driver Charge Type:</span> | 
				
			||||
 | 
					                                        <span t-field="data.charge_type"/> | 
				
			||||
 | 
					                                        <br/> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                                        <span>Driver Charge:</span> | 
				
			||||
 | 
					                                        <span t-field="data.driver_charge" | 
				
			||||
 | 
					                                              t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                    </t> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid transparent; width: 100%; margin-top: 10px;"> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <strong>Rent Details</strong> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                                    <span>Rent Type:</span> | 
				
			||||
 | 
					                                    <span t-field="data.rent_type"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Rent /</span> | 
				
			||||
 | 
					                                    <span t-field="data.rent_type"/> | 
				
			||||
 | 
					                                    <span>:</span> | 
				
			||||
 | 
					                                    <span t-field="data.rent_per_hour" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'hours'" | 
				
			||||
 | 
					                                          t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                    <span t-field="data.rent_per_day" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'days'" | 
				
			||||
 | 
					                                          t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                    <span t-field="data.rent_per_km" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'kilometers'" | 
				
			||||
 | 
					                                          t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Total</span> | 
				
			||||
 | 
					                                    <span t-field="data.rent_type"/> | 
				
			||||
 | 
					                                    <span>:</span> | 
				
			||||
 | 
					                                    <span t-field="data.total_hours" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'hours'"/> | 
				
			||||
 | 
					                                    <span t-field="data.total_days" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'days'"/> | 
				
			||||
 | 
					                                    <span t-field="data.total_km" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'kilometers'"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Total:</span> | 
				
			||||
 | 
					                                    <span t-field="data.total_rental_charge" | 
				
			||||
 | 
					                                          t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <strong>Payment Details</strong> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Payment Type:</span> | 
				
			||||
 | 
					                                    <span t-field="data.payment_type"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Invoice Item:</span> | 
				
			||||
 | 
					                                    <span t-field="data.invoice_item_id"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					                        <!--              Extra Charges Details--> | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid transparent; width: 100%; margin-top: 10px;"> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <strong>Extra Charges Details</strong> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Is any extra charges:</span> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                                    <span t-field="data.is_extra_charge"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Total Extra:</span> | 
				
			||||
 | 
					                                    <span t-field="data.rent_type"/> | 
				
			||||
 | 
					                                    : | 
				
			||||
 | 
					                                    <span t-field="data.total_extra_hours" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'hours'"/> | 
				
			||||
 | 
					                                    <span t-field="data.total_extra_days" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'days'"/> | 
				
			||||
 | 
					                                    <span t-field="data.total_extra_km" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'kilometers'"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                                    <span>Extra Charge /</span> | 
				
			||||
 | 
					                                    <span t-field="data.rent_type"/> | 
				
			||||
 | 
					                                    <span t-field="data.extra_per_hour" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'hours'"/> | 
				
			||||
 | 
					                                    <span t-field="data.extra_per_day" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'days'"/> | 
				
			||||
 | 
					                                    <span t-field="data.extra_per_km" | 
				
			||||
 | 
					                                          t-if="data.rent_type == 'kilometers'"/> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Total Extra Charges:</span> | 
				
			||||
 | 
					                                    <span t-field="data.total_extra_charge" | 
				
			||||
 | 
					                                          t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                                <td style="width: 50%; vertical-align: top;"> | 
				
			||||
 | 
					                                    <strong>Responsible Details</strong> | 
				
			||||
 | 
					                                    <br/> | 
				
			||||
 | 
					                                    <span>Responsible:</span> | 
				
			||||
 | 
					                                    <span t-field="data.responsible_id.name"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					                        <!--Vehicle Payment Option--> | 
				
			||||
 | 
					                        <h4 style="margin-top: 20px;">Vehicle Payment Option | 
				
			||||
 | 
					                        </h4> | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid black; border-collapse: collapse; width: 100%;"> | 
				
			||||
 | 
					                            <thead> | 
				
			||||
 | 
					                                <tr style="background-color: #f2f2f2;"> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Invoice Item | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Payment Date | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Payment Amount Invoice | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Payment State | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                </tr> | 
				
			||||
 | 
					                            </thead> | 
				
			||||
 | 
					                            <tbody> | 
				
			||||
 | 
					                                <tr t-foreach="data.rental_payment_plan_ids" | 
				
			||||
 | 
					                                    t-as="payment"> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="payment.invoice_item_id"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="payment.payment_date"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="payment.payment_amount" | 
				
			||||
 | 
					                                              t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                        <t t-if="payment.invoice_id"> | 
				
			||||
 | 
					                                            <span t-field="payment.invoice_id.name"/> | 
				
			||||
 | 
					                                        </t> | 
				
			||||
 | 
					                                        <t t-else=""> | 
				
			||||
 | 
					                                            Draft Invoice | 
				
			||||
 | 
					                                        </t> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="payment.payment_state"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                </tr> | 
				
			||||
 | 
					                            </tbody> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					                        <!-- Insurance Policy--> | 
				
			||||
 | 
					                        <h4 style="margin-top: 20px;">Insurance Policy</h4> | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid black; border-collapse: collapse; width: 100%;"> | 
				
			||||
 | 
					                            <thead> | 
				
			||||
 | 
					                                <tr style="background-color: #f2f2f2;"> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Policy Number | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Name | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Description | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Policy Amount | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                </tr> | 
				
			||||
 | 
					                            </thead> | 
				
			||||
 | 
					                            <tbody> | 
				
			||||
 | 
					                                <tr t-foreach="data.insurance_ids" | 
				
			||||
 | 
					                                    t-as="insurance"> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="insurance.policy_number"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="insurance.name"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="insurance.description"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="insurance.policy_amount" | 
				
			||||
 | 
					                                              t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                </tr> | 
				
			||||
 | 
					                            </tbody> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					                        <!--Extra Services--> | 
				
			||||
 | 
					                        <h4 style="margin-top: 20px;">Extra Services</h4> | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid black; border-collapse: collapse; width: 100%;"> | 
				
			||||
 | 
					                            <thead> | 
				
			||||
 | 
					                                <tr style="background-color: #f2f2f2;"> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Product | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Qty | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Description | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                    <th style="border: 1px solid black; padding: 5px; text-align: left;"> | 
				
			||||
 | 
					                                        Amount | 
				
			||||
 | 
					                                    </th> | 
				
			||||
 | 
					                                </tr> | 
				
			||||
 | 
					                            </thead> | 
				
			||||
 | 
					                            <tbody> | 
				
			||||
 | 
					                                <tr t-foreach="data.extra_service_ids" | 
				
			||||
 | 
					                                    t-as="service"> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="service.product_id"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="service.quantity"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="service.description"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                    <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                        <span t-field="service.amount" | 
				
			||||
 | 
					                                              t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                    </td> | 
				
			||||
 | 
					                                </tr> | 
				
			||||
 | 
					                            </tbody> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					                        <!-- Damage Details Tab --> | 
				
			||||
 | 
					                        <h4 style="margin-top: 20px;">Vehicle Damages</h4> | 
				
			||||
 | 
					                        <table class="table table-sm" | 
				
			||||
 | 
					                               style="border: 1px solid black; border-collapse: collapse; width: 100%;"> | 
				
			||||
 | 
					                            <tr> | 
				
			||||
 | 
					                                <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                    <strong>Total Damage Amount:</strong> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                                <td style="border: 1px solid black; padding: 5px;"> | 
				
			||||
 | 
					                                    <span t-field="data.damage_amount" | 
				
			||||
 | 
					                                          t-options="{'widget': 'monetary', 'display_currency': data.currency_id}"/> | 
				
			||||
 | 
					                                </td> | 
				
			||||
 | 
					                            </tr> | 
				
			||||
 | 
					                        </table> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <p style="margin-top: 10px;"> | 
				
			||||
 | 
					                            <strong>Descriptions</strong> | 
				
			||||
 | 
					                        </p> | 
				
			||||
 | 
					                        <p t-field="data.damage_description"/> | 
				
			||||
 | 
					                        <!-- Vehicle Images --> | 
				
			||||
 | 
					                        <h4 style="margin-top: 20px;">Vehicle Images</h4> | 
				
			||||
 | 
					                        <div class="vehicle-images" | 
				
			||||
 | 
					                             style="text-align: center;"> | 
				
			||||
 | 
					                            <t t-foreach="data.image_ids" t-as="image_record"> | 
				
			||||
 | 
					                                <img t-if="image_record.image" | 
				
			||||
 | 
					                                     t-att-src="image_record.image and ('data:image/png;base64,%s' % image_record.image.decode('utf-8'))" | 
				
			||||
 | 
					                                     alt="Vehicle Image" | 
				
			||||
 | 
					                                     style="max-width: 200px; margin: 10px;"/> | 
				
			||||
 | 
					                            </t> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                        <!-- Signature Section --> | 
				
			||||
 | 
					                        <div class="signature-section" | 
				
			||||
 | 
					                             style="margin-top: 30px; text-align: right;"> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					                            <p>Signature Date: | 
				
			||||
 | 
					                                <span t-field="data.sign_date"/> | 
				
			||||
 | 
					                            </p> | 
				
			||||
 | 
					                            <p> | 
				
			||||
 | 
					                                <strong>Signature</strong> | 
				
			||||
 | 
					                                <img t-if="data.digital_sign" | 
				
			||||
 | 
					                                     class="mobile-hide" | 
				
			||||
 | 
					                                     t-attf-src="data:image/png;base64,{{data.digital_sign}}" | 
				
			||||
 | 
					                                     style="width:125px; margin-top:8px;margin-bottom:-25px;" | 
				
			||||
 | 
					                                     alt="Signature"/> | 
				
			||||
 | 
					                            </p> | 
				
			||||
 | 
					                        </div> | 
				
			||||
 | 
					                    </div> | 
				
			||||
 | 
					                </t> | 
				
			||||
 | 
					            </t> | 
				
			||||
 | 
					        </t> | 
				
			||||
 | 
					    </template> | 
				
			||||
 | 
					</odoo> | 
				
			||||
		
		
			
  | 
| 
		 After Width: | Height: | Size: 2.2 KiB  | 
| 
		 After Width: | Height: | Size: 28 KiB  | 
| 
		 After Width: | Height: | Size: 628 KiB  | 
| 
		 After Width: | Height: | Size: 19 KiB  | 
| 
		 After Width: | Height: | Size: 16 KiB  | 
| 
		 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: 16 KiB  | 
| 
		 After Width: | Height: | Size: 542 B  | 
| 
		 After Width: | Height: | Size: 576 B  | 
| 
		 After Width: | Height: | Size: 733 B  | 
| 
		 After Width: | Height: | Size: 4.3 KiB  | 
| 
		 After Width: | Height: | Size: 4.0 KiB  | 
| 
		 After Width: | Height: | Size: 911 B  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 1.1 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 673 B  | 
| 
		 After Width: | Height: | Size: 2.0 KiB  | 
| 
		 After Width: | Height: | Size: 878 B  | 
| 
		 After Width: | Height: | Size: 18 KiB  | 
| 
		 After Width: | Height: | Size: 653 B  | 
| 
		 After Width: | Height: | Size: 905 B  | 
| 
		 After Width: | Height: | Size: 4.3 KiB  | 
| 
		 After Width: | Height: | Size: 839 B  | 
| 
		 After Width: | Height: | Size: 5.9 KiB  | 
| 
		 After Width: | Height: | Size: 34 KiB  | 
| 
		 After Width: | Height: | Size: 26 KiB  | 
| 
		 After Width: | Height: | Size: 3.8 KiB  | 
| 
		 After Width: | Height: | Size: 23 KiB  | 
| 
		 After Width: | Height: | Size: 1.9 KiB  | 
| 
		 After Width: | Height: | Size: 2.3 KiB  | 
| 
		 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: 3.7 KiB  | 
| 
		 After Width: | Height: | Size: 5.0 KiB  | 
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
| 
		 After Width: | Height: | Size: 912 KiB  | 
| 
		 After Width: | Height: | Size: 81 KiB  | 
| 
		 After Width: | Height: | Size: 46 KiB  | 
| 
		 After Width: | Height: | Size: 44 KiB  | 
| 
		 After Width: | Height: | Size: 46 KiB  | 
| 
		 After Width: | Height: | Size: 85 KiB  | 
| 
		 After Width: | Height: | Size: 97 KiB  | 
| 
		 After Width: | Height: | Size: 162 KiB  | 
| 
		 After Width: | Height: | Size: 407 KiB  | 
| 
		 After Width: | Height: | Size: 87 KiB  | 
| 
		 After Width: | Height: | Size: 134 KiB  | 
| 
		 After Width: | Height: | Size: 96 KiB  | 
| 
		 After Width: | Height: | Size: 107 KiB  | 
| 
		 After Width: | Height: | Size: 102 KiB  | 
| 
		 After Width: | Height: | Size: 74 KiB  | 
| 
		 After Width: | Height: | Size: 120 KiB  | 
| 
		 After Width: | Height: | Size: 353 KiB  | 
| 
		 After Width: | Height: | Size: 118 KiB  | 
| 
		 After Width: | Height: | Size: 15 KiB  | 
| 
		 After Width: | Height: | Size: 19 KiB  | 
| 
		 After Width: | Height: | Size: 184 KiB  | 
| 
		 After Width: | Height: | Size: 231 KiB  | 
| 
		 After Width: | Height: | Size: 71 KiB  | 
| 
		 After Width: | Height: | Size: 96 KiB  | 
| 
		 After Width: | Height: | Size: 265 KiB  | 
| 
		 After Width: | Height: | Size: 85 KiB  | 
| 
		 After Width: | Height: | Size: 114 KiB  | 
| 
		 After Width: | Height: | Size: 87 KiB  | 
| 
		 After Width: | Height: | Size: 103 KiB  | 
| 
		 After Width: | Height: | Size: 103 KiB  | 
| 
		 After Width: | Height: | Size: 410 KiB  | 
| 
		 After Width: | Height: | Size: 880 KiB  | 
| 
		 After Width: | Height: | Size: 95 KiB  | 
| 
		 After Width: | Height: | Size: 20 KiB  | 
@ -0,0 +1,78 @@ | 
				
			|||||
 | 
					.components{ | 
				
			||||
 | 
					    margin: 40px !important; | 
				
			||||
 | 
					    border-radius: 17px; | 
				
			||||
 | 
					    padding-bottom: 25px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.heading{ | 
				
			||||
 | 
					    margin-top:15px; | 
				
			||||
 | 
					    margin-bottom:8px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.tile{ | 
				
			||||
 | 
					    height: 125px; | 
				
			||||
 | 
					    border-radius: 30px; | 
				
			||||
 | 
					    display: flex; | 
				
			||||
 | 
					    justify-content: center; | 
				
			||||
 | 
					    flex-direction: column; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					.tile:hover{ | 
				
			||||
 | 
					  box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					.card:hover{ | 
				
			||||
 | 
					  box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.chart{ | 
				
			||||
 | 
					    margin: 40px !important; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					.row_table{ | 
				
			||||
 | 
					    margin: 40px !important; | 
				
			||||
 | 
					    padding-bottom: 40px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					/* Basic styling for the header */ | 
				
			||||
 | 
					.contracts-header { | 
				
			||||
 | 
					  font-family: 'Poppins', 'Open Sans', sans-serif; | 
				
			||||
 | 
					  font-size: 1.5rem; | 
				
			||||
 | 
					  font-weight: 600; | 
				
			||||
 | 
					  color: #333; | 
				
			||||
 | 
					  margin-bottom: 1.5rem; | 
				
			||||
 | 
					  padding-bottom: 0.5rem; | 
				
			||||
 | 
					  position: relative; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* Option 1: With subtle text shadow */ | 
				
			||||
 | 
					.contracts-header-shadow { | 
				
			||||
 | 
					  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* Option 2: With gradient text color */ | 
				
			||||
 | 
					.contracts-header-gradient { | 
				
			||||
 | 
					  background: linear-gradient(90deg, #3498db, #2980b9); | 
				
			||||
 | 
					  -webkit-background-clip: text; | 
				
			||||
 | 
					  background-clip: text; | 
				
			||||
 | 
					  color: transparent; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* Option 3: With icon prefix */ | 
				
			||||
 | 
					.contracts-header-icon::before { | 
				
			||||
 | 
					  content: "📄 "; | 
				
			||||
 | 
					  margin-right: 8px; | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* Option 4: With subtle background */ | 
				
			||||
 | 
					.contracts-header-background { | 
				
			||||
 | 
					  background-color: #f5f9ff; | 
				
			||||
 | 
					  padding: 10px 15px; | 
				
			||||
 | 
					  border-radius: 6px; | 
				
			||||
 | 
					  border-bottom: none; | 
				
			||||
 | 
					  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/* Option 5: Uppercase with letter spacing */ | 
				
			||||
 | 
					.contracts-header-uppercase { | 
				
			||||
 | 
					  text-transform: uppercase; | 
				
			||||
 | 
					  letter-spacing: 1.5px; | 
				
			||||
 | 
					  font-size: 1.2rem; | 
				
			||||
 | 
					} | 
				
			||||
| 
		 After Width: | Height: | Size: 8.0 KiB  | 
| 
		 After Width: | Height: | Size: 5.9 KiB  |