| @ -0,0 +1,51 @@ | |||||
|  | .. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg | ||||
|  |     :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html | ||||
|  |     :alt: License: AGPL-3 | ||||
|  | 
 | ||||
|  | Odoo Rental Sales | ||||
|  | =================== | ||||
|  | * The Odoo Rental Sales module allows businesses to create and manage rental orders, track the availability of rental products, and execute rental contracts and invoices. | ||||
|  | 
 | ||||
|  | Installation | ||||
|  | ============ | ||||
|  | 	- www.odoo.com/documentation/17.0/setup/install.html | ||||
|  | 	- Install our custom addon | ||||
|  | 
 | ||||
|  | License | ||||
|  | ------- | ||||
|  | General Public License, Version 3 (AGPL-3). | ||||
|  | (http://www.gnu.org/licenses/agpl-3.0-standalone.html) | ||||
|  | 
 | ||||
|  | Company | ||||
|  | ------- | ||||
|  | * `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | ||||
|  | 
 | ||||
|  | Credits | ||||
|  | ------- | ||||
|  | Developer: (V16)Aswathi PN, | ||||
|  |            (v17)JANISH BABU EK | ||||
|  |            (v18)Afthab K Naufal | ||||
|  |            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: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from . import models | ||||
|  | from . import wizard | ||||
| @ -0,0 +1,56 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | { | ||||
|  |     'name': 'Odoo Rental Sales', | ||||
|  |     'version': '18.0.1.0.0', | ||||
|  |     'category': 'Sales', | ||||
|  |     'summary': "The module helps in rental management.", | ||||
|  |     'description': "This module allows businesses to create rental orders, " | ||||
|  |                    "track the availability of rental products, and manage rental " | ||||
|  |                    "contracts and invoices.", | ||||
|  |     'author': 'Cybrosys Techno Solutions', | ||||
|  |     'company': 'Cybrosys Techno Solutions', | ||||
|  |     'maintainer': 'Cybrosys Techno Solutions', | ||||
|  |     'website': 'https://cybrosys.com', | ||||
|  |     'depends': ['product', 'sale_management', 'base'], | ||||
|  |     'data': [ | ||||
|  |         'security/rental_order_contract_security.xml', | ||||
|  |         'security/odoo_rental_sales_groups.xml', | ||||
|  |         'security/ir.model.access.csv', | ||||
|  |         'data/ir_sequence_data.xml', | ||||
|  |         'data/ir_corn_data.xml', | ||||
|  |         'wizard/rental_product_views.xml', | ||||
|  |         'views/product_product_views.xml', | ||||
|  |         'views/odoo_rental_sales_menus.xml', | ||||
|  |         'views/sale_order_views.xml', | ||||
|  |         'views/rental_order_contract_views.xml', | ||||
|  |         'views/rental_product_category_views.xml', | ||||
|  |         'views/rental_product_agreement_views.xml', | ||||
|  |         'views/uom_views.xml' | ||||
|  |     ], | ||||
|  |     'images': ['static/description/banner.jpg'], | ||||
|  |     'license': 'AGPL-3', | ||||
|  |     'installable': True, | ||||
|  |     'auto_install': False, | ||||
|  |     'application': False, | ||||
|  | } | ||||
|  | 
 | ||||
| @ -0,0 +1,15 @@ | |||||
|  | <?xml version="1.0" encoding="utf-8" ?> | ||||
|  | <odoo> | ||||
|  |     <data noupdate="1"> | ||||
|  |         <!--Schedule activity for calculating expiration of contract--> | ||||
|  |         <record id="rental_scheduler_recurring_action" model="ir.cron"> | ||||
|  |             <field name="name">Rental Scheduler Recurring Activity</field> | ||||
|  |             <field name="model_id" ref="model_rental_order_contract"/> | ||||
|  |             <field name="state">code</field> | ||||
|  |             <field name="code">model._contract_expiration()</field> | ||||
|  |             <field name="user_id" ref="base.user_root"/> | ||||
|  |             <field name="interval_number">1</field> | ||||
|  |             <field name="interval_type">days</field> | ||||
|  |         </record> | ||||
|  |     </data> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,21 @@ | |||||
|  | <?xml version="1.0" encoding="utf-8" ?> | ||||
|  | <odoo> | ||||
|  |     <data noupdate="1"> | ||||
|  |         <!--Sale order line sequence number--> | ||||
|  |         <record id="seq_sale_order_line" model="ir.sequence"> | ||||
|  |             <field name="name">Order Line Sequence</field> | ||||
|  |             <field name="code">sale.order.line</field> | ||||
|  |             <field name="prefix">RO</field> | ||||
|  |             <field name="padding">5</field> | ||||
|  |             <field name="company_id" eval="False"/> | ||||
|  |         </record> | ||||
|  |         <!--Rental contract sequence number--> | ||||
|  |         <record id="seq_rental_contract" model="ir.sequence"> | ||||
|  |             <field name="name">Rental Contract Sequence</field> | ||||
|  |             <field name="code">rental.order.contract</field> | ||||
|  |             <field name="prefix">ROC</field> | ||||
|  |             <field name="padding">5</field> | ||||
|  |             <field name="company_id" eval="False"/> | ||||
|  |         </record> | ||||
|  |     </data> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,6 @@ | |||||
|  | ## Module <odoo_rental_sales> | ||||
|  | 
 | ||||
|  | #### 19.02.2025 | ||||
|  | #### Version 18.0.1.0.0 | ||||
|  | #### ADD | ||||
|  | - Initial commit for Odoo Rental Sales | ||||
| @ -0,0 +1,27 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from . import product_product | ||||
|  | from . import rental_order_contract | ||||
|  | from . import rental_product_agreement | ||||
|  | from . import rental_product_category | ||||
|  | from . import sale_order | ||||
|  | from . import uom | ||||
| @ -0,0 +1,38 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class ProductProduct(models.Model): | ||||
|  |     """Created the class for inheriting the product model """ | ||||
|  |     _inherit = 'product.product' | ||||
|  | 
 | ||||
|  |     rental = fields.Boolean('Rental', | ||||
|  |                             help="Boolean field for checking the product is rental or not") | ||||
|  |     category_id = fields.Many2one('rental.product.category', | ||||
|  |                                   string='Rental Category', | ||||
|  |                                   help="Adding rental product category") | ||||
|  |     product_agreement_id = fields.Many2one('rental.product.agreement', | ||||
|  |                                            string='Product Agreement', | ||||
|  |                                            help="Set the product agreement") | ||||
|  |     security_amount = fields.Monetary(string='Security Amount', | ||||
|  |                                       help='To add the Security Amount') | ||||
| @ -0,0 +1,98 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from odoo import api, fields, models, _ | ||||
|  | from odoo.exceptions import UserError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class RentalOrderContract(models.Model): | ||||
|  |     """Created the class for creating a new model rental order contract""" | ||||
|  |     _name = "rental.order.contract" | ||||
|  |     _inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin'] | ||||
|  |     _description = 'Rental Order Contract' | ||||
|  |     _rec_name = 'reference_no' | ||||
|  | 
 | ||||
|  |     reference_no = fields.Char(string='Reference', copy=False, | ||||
|  |                                readonly=True, default=lambda self: _('New'), | ||||
|  |                                help='Create a reference number for rental contract') | ||||
|  |     partner_id = fields.Many2one('res.partner', string='Customer', | ||||
|  |                                  help='To set the customer for the contract') | ||||
|  |     product_id = fields.Many2one('product.product', string='Product', | ||||
|  |                                  domain="[('rental', '=', True)]", | ||||
|  |                                  help='To add the rental product') | ||||
|  |     qty = fields.Float(string='Quantity', help='To add the quantity') | ||||
|  |     currency_id = fields.Many2one('res.currency', string="Currency", | ||||
|  |                                   related='company_id.currency_id', | ||||
|  |                                   help='To add the company currency') | ||||
|  |     unit_price = fields.Monetary(string='Unit Price', readonly=True, | ||||
|  |                                  help='To set the unit price') | ||||
|  |     date_start = fields.Datetime(string='Start Date', | ||||
|  |                                  help='To set the start date') | ||||
|  |     date_end = fields.Datetime(string='End Date', help='To set the end date') | ||||
|  |     sale_order_id = fields.Many2one('sale.order', string='Sale Order', | ||||
|  |                                     help='To set the corresponding sale order') | ||||
|  |     rental_order_id = fields.Many2one('sale.order.line', string='Rental Order', | ||||
|  |                                       help='To set the corresponding rental order', | ||||
|  |                                       domain=[('is_rental', '=', True)]) | ||||
|  |     company_id = fields.Many2one('res.company', required=True, | ||||
|  |                                  default=lambda self: self.env.company, | ||||
|  |                                  string='Company', | ||||
|  |                                  help='To set the default company') | ||||
|  |     contract_status = fields.Selection( | ||||
|  |         [('new', 'New'), ('confirmed', 'Confirmed'), ('expired', 'Expired'), | ||||
|  |          ('cancel', 'Cancelled')], string='Contract Status', | ||||
|  |         default='new', help='To add contract status') | ||||
|  | 
 | ||||
|  |     @api.onchange('date_start', 'date_end') | ||||
|  |     def _onchange_date_start(self): | ||||
|  |         """Checking the end date is less than start date""" | ||||
|  |         if self.date_start and self.date_end and self.date_start > self.date_end: | ||||
|  |             raise UserError( | ||||
|  |                 _('The end date must be after or the same as the start date')) | ||||
|  | 
 | ||||
|  |     @api.model | ||||
|  |     def create(self, vals): | ||||
|  |         """Creating sequence for the rental contract""" | ||||
|  |         if vals.get('reference_no', _('New')) == _('New'): | ||||
|  |             vals['reference_no'] = self.env['ir.sequence'].next_by_code( | ||||
|  |                 'rental.order.contract') or _('New') | ||||
|  | 
 | ||||
|  |         return super(RentalOrderContract, self).create(vals) | ||||
|  | 
 | ||||
|  |     def action_confirm_contract(self): | ||||
|  |         """ Function for confirming the contract """ | ||||
|  |         self.contract_status = 'confirmed' | ||||
|  | 
 | ||||
|  |     def action_reset_contract(self): | ||||
|  |         """Function for reset the contract to draft""" | ||||
|  |         self.contract_status = 'new' | ||||
|  | 
 | ||||
|  |     def action_cancel_contract(self): | ||||
|  |         """ Function for cancel contract """ | ||||
|  |         self.contract_status = 'cancel' | ||||
|  | 
 | ||||
|  |     def _contract_expiration(self): | ||||
|  |         """Calculating the expiration date of the contract""" | ||||
|  |         rental_contract = self.env['rental.order.contract'].search( | ||||
|  |             [('contract_status', 'not in', ['expired', 'cancel'])]) | ||||
|  |         for rec in rental_contract: | ||||
|  |             if rec.date_end and rec.date_end.date() < fields.date.today(): | ||||
|  |                 rec.contract_status = 'expired' | ||||
| @ -0,0 +1,37 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class RentalProductAgreement(models.Model): | ||||
|  |     """Created the class for creating the model rental product agreement""" | ||||
|  |     _name = 'rental.product.agreement' | ||||
|  |     _description = 'Rental Product Agreement' | ||||
|  | 
 | ||||
|  |     name = fields.Char(string='Name', required=True, | ||||
|  |                        help='Name of the rental product agreement') | ||||
|  |     sequence = fields.Integer(string='Sequence', required=True, | ||||
|  |                               help='Sequence of the rental product agreement') | ||||
|  |     description = fields.Text(string='Description', | ||||
|  |                               help='Description of the rental product agreement') | ||||
|  |     agreement_file = fields.Binary(string='Product Agreement', | ||||
|  |                                    help='Agreement file of the rental product') | ||||
| @ -0,0 +1,43 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class RentalProductCategory(models.Model): | ||||
|  |     """Created the class for creating the model rental product category""" | ||||
|  |     _name = 'rental.product.category' | ||||
|  |     _description = 'Rental Product Category' | ||||
|  | 
 | ||||
|  |     name = fields.Char(string='Name', required=True, | ||||
|  |                        help='Name of product category') | ||||
|  | 
 | ||||
|  |     def action_view_rental_products(self): | ||||
|  |         """Showing the products under the rental category""" | ||||
|  |         self.ensure_one() | ||||
|  |         return { | ||||
|  |             'type': 'ir.actions.act_window', | ||||
|  |             'name': 'Rental Products', | ||||
|  |             'view_mode': 'tree', | ||||
|  |             'res_model': 'product.product', | ||||
|  |             'domain': [('category_id', '=', self.id)], | ||||
|  |             'context': "{'create': False}" | ||||
|  |         } | ||||
| @ -0,0 +1,167 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from odoo import api, fields, models, _ | ||||
|  | from odoo.exceptions import UserError | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SaleOrder(models.Model): | ||||
|  |     """Created the class for inheriting the model sale order""" | ||||
|  |     _inherit = 'sale.order' | ||||
|  | 
 | ||||
|  |     rental_status = fields.Selection( | ||||
|  |         [('new', 'New'), ('confirmed', 'Confirmed'), | ||||
|  |          ('expired', 'Expired'), | ||||
|  |          ('cancel', 'Cancelled')], | ||||
|  |         default='new', help='To show the rental status', string='Rental Status') | ||||
|  | 
 | ||||
|  |     def action_confirm(self): | ||||
|  |         """For creating rental order contract at the time of confirm the sale order.""" | ||||
|  |         res = super(SaleOrder, self).action_confirm() | ||||
|  |         for product in self.order_line: | ||||
|  |             if product.rental: | ||||
|  |                 product.is_rental = True | ||||
|  |                 self.env['rental.order.contract'].create([{ | ||||
|  |                     'partner_id': self.partner_id.id, | ||||
|  |                     'product_id': product.product_id.id, | ||||
|  |                     'qty': product.product_uom_qty, | ||||
|  |                     'unit_price': product.price_unit, | ||||
|  |                     'rental_order_id': product.id, | ||||
|  |                     'sale_order_id': self.id, | ||||
|  |                 }]) | ||||
|  |         return res | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class SaleOrderLine(models.Model): | ||||
|  |     """Created the class for inheriting the model sale order line""" | ||||
|  |     _inherit = 'sale.order.line' | ||||
|  |     _rec_name = 'reference_no' | ||||
|  | 
 | ||||
|  |     reference_no = fields.Char(string='Reference', readonly=True, | ||||
|  |                                default=lambda self: _('New'), | ||||
|  |                                help='To create reference number for sale order line') | ||||
|  |     initial_contract_id = fields.Many2one('rental.order.contract', | ||||
|  |                                           string='Initial Contract', | ||||
|  |                                           help='To add initial contract') | ||||
|  |     initial_start = fields.Datetime(string='Start Date', related='initial_contract_id.date_start', | ||||
|  |                                     help='To add the initial contract start date') | ||||
|  |     initial_end = fields.Datetime(string='End Date', related='initial_contract_id.date_end', | ||||
|  |                                   help='To add initial contract end date') | ||||
|  |     initial_qty = fields.Float(string='Quantity', related='initial_contract_id.qty', | ||||
|  |                                help='To add initial contract product quantity') | ||||
|  |     partner_id = fields.Many2one('res.partner', string='Partner', | ||||
|  |                                  help='To store the partner of the corresponding sale order') | ||||
|  |     current_contract_id = fields.Many2one('rental.order.contract', | ||||
|  |                                           string='Current Contract', | ||||
|  |                                           help='To add the current contract') | ||||
|  |     current_start = fields.Datetime(string='Start Date', related='current_contract_id.date_start', | ||||
|  |                                     help='To add the current contract start date') | ||||
|  |     current_end = fields.Datetime(string='End Date', related='current_contract_id.date_end', | ||||
|  |                                   help='To add the current contract end date') | ||||
|  |     current_qty = fields.Float(string='Quantity', related='current_contract_id.qty', | ||||
|  |                                help='To add the current contract product quantity') | ||||
|  |     last_renewal_time = fields.Datetime(string='Last Renewal Time', | ||||
|  |                                         help='To store the last renewal time of the contract') | ||||
|  |     is_rental = fields.Boolean(string='Rental', | ||||
|  |                                help='To check the sale order line contains rental product or not') | ||||
|  |     rental = fields.Boolean(string='Rental', related='product_id.rental', | ||||
|  |                             help='To check the sale order line product is rental product') | ||||
|  |     current_contract_values = fields.Boolean(string='Contract Value', | ||||
|  |                                              compute='_compute_current_contract_values', | ||||
|  |                                              help='To compute the contract values') | ||||
|  |     rental_status = fields.Selection( | ||||
|  |         [('new', 'New'), ('confirmed', 'Confirmed'), | ||||
|  |          ('cancel', 'Cancelled')], | ||||
|  |         default='new', help='To show the rental status', string='Rental Status') | ||||
|  |     rental_contract_ids = fields.One2many('rental.order.contract', | ||||
|  |                                           'rental_order_id', | ||||
|  |                                           string='Rental Contract', | ||||
|  |                                           help='To Shows the rental contract') | ||||
|  | 
 | ||||
|  |     @api.depends('rental_contract_ids') | ||||
|  |     def _compute_current_contract_values(self): | ||||
|  |         """For fetching the current contract values to the sale order line form view""" | ||||
|  |         for rec in self: | ||||
|  |             rec.current_contract_values = False | ||||
|  |             try: | ||||
|  |                 recs_sorted = \ | ||||
|  |                     rec.rental_contract_ids.sorted(key=lambda r: r.date_start)[0] if rec.rental_contract_ids.sorted( | ||||
|  |                         key=lambda r: r.date_start) else False | ||||
|  |                 rec.current_contract_values = True | ||||
|  |                 for record in rec.rental_contract_ids: | ||||
|  |                     if record.date_start and record.date_end: | ||||
|  |                         if record.date_start.date() <= fields.date.today() <= record.date_end.date(): | ||||
|  |                             rec.current_contract_id = record.id | ||||
|  |                             rec.last_renewal_time = record.date_end | ||||
|  |                     if recs_sorted: | ||||
|  |                         rec.initial_contract_id = recs_sorted.id | ||||
|  |             except: | ||||
|  |                 continue | ||||
|  | 
 | ||||
|  |     @api.onchange('initial_start', 'initial_end', 'current_start', 'current_end') | ||||
|  |     def _onchange_initial_start(self): | ||||
|  |         """Checking the end date is less than start date""" | ||||
|  |         if self.initial_start and self.initial_end and self.initial_start > self.initial_end: | ||||
|  |             raise UserError( | ||||
|  |                 _('The end date must be after or the same as the start date')) | ||||
|  |         if self.current_start and self.current_end and self.current_start > self.current_end: | ||||
|  |             raise UserError( | ||||
|  |                 _('The end date must be after or the same as the start date')) | ||||
|  | 
 | ||||
|  |     @api.model | ||||
|  |     def create(self, vals): | ||||
|  |         """ Function for adding reference number to the sale order line """ | ||||
|  |         if vals.get('reference_no', _('New')) == _('New'): | ||||
|  |             vals['reference_no'] = self.env['ir.sequence'].next_by_code( | ||||
|  |                 'sale.order.line') or _('New') | ||||
|  |         return super(SaleOrderLine, self).create(vals) | ||||
|  | 
 | ||||
|  |     def action_confirm(self): | ||||
|  |         """ Button function that confirm the order line products """ | ||||
|  |         self.rental_status = 'confirmed' | ||||
|  | 
 | ||||
|  |     def action_cancel(self): | ||||
|  |         """ Button function that cancel the order """ | ||||
|  |         self.rental_status = 'cancel' | ||||
|  | 
 | ||||
|  |     def action_renew_contract(self): | ||||
|  |         """For renewing the rental order""" | ||||
|  |         self.ensure_one() | ||||
|  |         vals = [] | ||||
|  |         if self.rental_contract_ids: | ||||
|  |             vals = [{ | ||||
|  |                 'partner_id': rec.partner_id.id, | ||||
|  |                 'product_id': rec.product_id.id, | ||||
|  |                 'rental_order_id': rec.rental_order_id.id, | ||||
|  |                 'sale_order_id': rec.sale_order_id.id, | ||||
|  |                 'qty': rec.qty, | ||||
|  |                 'unit_price': rec.unit_price, | ||||
|  |             } for rec in self.rental_contract_ids] | ||||
|  | 
 | ||||
|  |         contract_rec = self.env['rental.order.contract'].create(vals) | ||||
|  |         return { | ||||
|  |             'name': _('Renew Rental Order'), | ||||
|  |             'view_mode': 'form', | ||||
|  |             'res_model': 'rental.order.contract', | ||||
|  |             'type': 'ir.actions.act_window', | ||||
|  |             'target': 'new', | ||||
|  |             'res_id': contract_rec[0].id if contract_rec else False, | ||||
|  |         } | ||||
| @ -0,0 +1,30 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | ############################################################################# | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | # | ||||
|  | #    Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | ||||
|  | #    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | ||||
|  | # | ||||
|  | #    You can modify it under the terms of the GNU LESSER | ||||
|  | #    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | ||||
|  | # | ||||
|  | #    This program is distributed in the hope that it will be useful, | ||||
|  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  | #    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | ||||
|  | # | ||||
|  | #    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | ||||
|  | #    (LGPL v3) along with this program. | ||||
|  | #    If not, see <http://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################# | ||||
|  | from odoo import fields, models | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class Uom(models.Model): | ||||
|  |     """Created the class for inheriting the model uom """ | ||||
|  |     _inherit = 'uom.uom' | ||||
|  | 
 | ||||
|  |     is_rental = fields.Boolean(string='Rental', | ||||
|  |                                help='Check the uom is for rental product') | ||||
| 
 | 
| @ -0,0 +1,23 @@ | |||||
|  | <?xml version="1.0" encoding="utf-8"?> | ||||
|  | <odoo> | ||||
|  |    <!--  Rental security group --> | ||||
|  | 
 | ||||
|  |     <record model="ir.module.category" id="module_rental_category"> | ||||
|  |       <field name="name">Rental Sales</field> | ||||
|  |       <field name="description">Helps you handle your rental security.</field> | ||||
|  |       <field name="sequence">9</field> | ||||
|  |     </record> | ||||
|  | 
 | ||||
|  |     <record id="group_rental_sales_user" model="res.groups"> | ||||
|  |         <field name="name">User</field> | ||||
|  |         <field name="category_id" ref="module_rental_category"/> | ||||
|  |         <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/> | ||||
|  |     </record> | ||||
|  | 
 | ||||
|  |       <record id="group_rental_sales_manager" model="res.groups"> | ||||
|  |         <field name="name">Rental Sales Administrator</field> | ||||
|  |         <field name="category_id" ref="module_rental_category"/> | ||||
|  |         <field name="implied_ids" eval="[(4, ref('group_rental_sales_user'))]"/> | ||||
|  |         <field name="users" eval="[(4, ref('base.user_admin'))]"/> | ||||
|  |     </record> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,11 @@ | |||||
|  | <?xml version="1.0" encoding="utf-8" ?> | ||||
|  | <odoo> | ||||
|  |     <data noupdate="1"> | ||||
|  |         <!-- Multi company rule for rental contract--> | ||||
|  |         <record id="rental_order_contract_rule_company" model="ir.rule"> | ||||
|  |             <field name="name">Rental Order Contract Multi-Company</field> | ||||
|  |             <field name="model_id" ref="model_rental_order_contract"/> | ||||
|  |             <field name="domain_force">[('company_id', 'in', company_ids)]</field> | ||||
|  |         </record> | ||||
|  |     </data> | ||||
|  | </odoo> | ||||
| After Width: | Height: | Size: 52 KiB | 
| After Width: | Height: | Size: 2.2 KiB | 
| After Width: | Height: | Size: 28 KiB | 
| After Width: | Height: | Size: 628 KiB | 
| After Width: | Height: | Size: 355 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 210 KiB | 
| After Width: | Height: | Size: 209 KiB | 
| After Width: | Height: | Size: 109 KiB | 
| After Width: | Height: | Size: 495 B | 
| After Width: | Height: | Size: 1.0 KiB | 
| After Width: | Height: | Size: 624 B | 
| After Width: | Height: | Size: 136 KiB | 
| After Width: | Height: | Size: 214 KiB | 
| After Width: | Height: | Size: 36 KiB | 
| After Width: | Height: | Size: 3.6 KiB | 
| After Width: | Height: | Size: 310 B | 
| After Width: | Height: | Size: 929 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 3.3 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 17 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: 1.2 KiB | 
| After Width: | Height: | Size: 4.0 KiB | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 2.2 KiB | 
| After Width: | Height: | Size: 911 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 600 B | 
| After Width: | Height: | Size: 673 B | 
| After Width: | Height: | Size: 2.0 KiB | 
| After Width: | Height: | Size: 462 B | 
| After Width: | Height: | Size: 2.1 KiB | 
| After Width: | Height: | Size: 926 B | 
| After Width: | Height: | Size: 9.0 KiB | 
| After Width: | Height: | Size: 23 KiB | 
| After Width: | Height: | Size: 7.0 KiB | 
| After Width: | Height: | Size: 878 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 653 B | 
| After Width: | Height: | Size: 800 B | 
| After Width: | Height: | Size: 905 B | 
| After Width: | Height: | Size: 189 KiB | 
| After Width: | Height: | Size: 4.3 KiB | 
| After Width: | Height: | Size: 839 B | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 5.9 KiB | 
| After Width: | Height: | Size: 1.6 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.1 KiB | 
| 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: 875 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 760 KiB | 
| After Width: | Height: | Size: 92 KiB | 
| After Width: | Height: | Size: 697 KiB | 
| After Width: | Height: | Size: 1.1 MiB | 
| After Width: | Height: | Size: 738 KiB | 
| After Width: | Height: | Size: 740 KiB | 
| After Width: | Height: | Size: 91 KiB | 
| After Width: | Height: | Size: 229 KiB | 
| After Width: | Height: | Size: 39 KiB | 
| After Width: | Height: | Size: 90 KiB | 
| After Width: | Height: | Size: 132 KiB | 
| After Width: | Height: | Size: 75 KiB | 
| After Width: | Height: | Size: 80 KiB | 
| After Width: | Height: | Size: 80 KiB | 
| After Width: | Height: | Size: 29 KiB |