diff --git a/fleet_rental/README.rst b/fleet_rental/README.rst new file mode 100644 index 000000000..a57376909 --- /dev/null +++ b/fleet_rental/README.rst @@ -0,0 +1,24 @@ +Fleet Rental Management +======================= +This module will helps you to give the vehicles for Rent. + +Features +======== + +* Multiple Plans for Rental Contract(Days/Weeks/Months/Years). +* Integrated with Accounting Module. +* Automatically Create Recurring Invoices. +* Sending email for confirmation, first payment and recurrent invoices. +* Check List Facility. +* Separate Tree view for Checklist. +* Damage Checking Facility. +* Billing Facility for Damages/Check Lists. +* Contract Payment Validations. +* Detailed Fleet Rental Analysis Report. +* Access Rights From Multiple Level. + +Credits +======= +Developer: Nilmar Shereef @ cybrosys, shereef@cybrosys.in +Developer: Jesni Banu @ cybrosys, jesni@cybrosys.in +Developer: Avinash NK @ cybrosys, avinash@cybrosys.in diff --git a/fleet_rental/__init__.py b/fleet_rental/__init__.py index d775f2dac..120a5f1a9 100644 --- a/fleet_rental/__init__.py +++ b/fleet_rental/__init__.py @@ -3,7 +3,7 @@ # # Cybrosys Technologies Pvt. Ltd. # Copyright (C) 2017-TODAY Cybrosys Technologies(). -# Author: Avinash Nk() +# Author: Cybrosys() # you can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. # @@ -21,3 +21,5 @@ # ############################################################################## import models +import reports + diff --git a/fleet_rental/__manifest__.py b/fleet_rental/__manifest__.py index 402a66cd4..979ecf616 100644 --- a/fleet_rental/__manifest__.py +++ b/fleet_rental/__manifest__.py @@ -3,7 +3,7 @@ # # Cybrosys Technologies Pvt. Ltd. # Copyright (C) 2017-TODAY Cybrosys Technologies(). -# Author: Avinash Nk() +# Author: Cybrosys() # you can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. # @@ -22,16 +22,19 @@ ############################################################################## { 'name': 'Fleet Rental Management', - 'summary': """This module will helps you to give the vehicles for Rent.""", - 'version': '10.0.1.0.0', + 'summary': """The Complete Solution for a Car/Vehicle Rental System""", + 'version': '10.0.2.0.0', 'author': 'Cybrosys Techno Solutions', 'website': "http://www.cybrosys.com", 'company': 'Cybrosys Techno Solutions', "category": "Industries", - 'depends': ['account', 'fleet'], - 'data': ['views/car_rental_view.xml', + 'depends': ['base', 'account', 'fleet', 'mail'], + 'data': ['security/rental_security.xml', + 'security/ir.model.access.csv', + 'views/car_rental_view.xml', 'views/checklist_view.xml', 'views/car_tools_view.xml', + 'reports/rental_report.xml', 'data/fleet_rental_data.xml', ], 'demo': [ diff --git a/fleet_rental/__manifest__.py~ b/fleet_rental/__manifest__.py~ new file mode 100644 index 000000000..7b7088bec --- /dev/null +++ b/fleet_rental/__manifest__.py~ @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## +{ + 'name': 'Fleet Rental Management', + 'summary': """This module will helps you to give the vehicles for Rent.""", + 'version': '10.0.2.0.0', + 'author': 'Cybrosys Techno Solutions', + 'website': "http://www.cybrosys.com", + 'company': 'Cybrosys Techno Solutions', + "category": "Industries", + 'depends': ['base', 'account', 'fleet', 'mail'], + 'data': ['security/rental_security.xml', + 'security/ir.model.access.csv', + 'views/car_rental_view.xml', + 'views/checklist_view.xml', + 'views/car_tools_view.xml', + 'reports/rental_report.xml', + 'data/fleet_rental_data.xml', + ], + 'demo': [ + ], + 'images': ['static/description/banner.jpg'], + 'license': 'LGPL-3', + 'installable': True, + 'application': False, +} diff --git a/fleet_rental/data/fleet_rental_data.xml b/fleet_rental/data/fleet_rental_data.xml index 664bae5d2..6e242ed54 100644 --- a/fleet_rental/data/fleet_rental_data.xml +++ b/fleet_rental/data/fleet_rental_data.xml @@ -9,5 +9,14 @@ Rent 3 + + User can only see his/her vehicle + + + + + + + \ No newline at end of file diff --git a/fleet_rental/models/__init__.py b/fleet_rental/models/__init__.py index b86259055..7731664e2 100644 --- a/fleet_rental/models/__init__.py +++ b/fleet_rental/models/__init__.py @@ -3,7 +3,7 @@ # # Cybrosys Technologies Pvt. Ltd. # Copyright (C) 2017-TODAY Cybrosys Technologies(). -# Author: Avinash Nk() +# Author: Cybrosys() # you can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. # @@ -21,3 +21,4 @@ # ############################################################################## import car_rental + diff --git a/fleet_rental/models/car_rental.py b/fleet_rental/models/car_rental.py index d3d49fe04..5ad9bc792 100644 --- a/fleet_rental/models/car_rental.py +++ b/fleet_rental/models/car_rental.py @@ -3,7 +3,7 @@ # # Cybrosys Technologies Pvt. Ltd. # Copyright (C) 2017-TODAY Cybrosys Technologies(). -# Author: Avinash Nk() +# Author: Cybrosys() # you can modify it under the terms of the GNU LESSER # GENERAL PUBLIC LICENSE (LGPL v3), Version 3. # @@ -22,24 +22,32 @@ ############################################################################## from datetime import datetime, date from odoo import models, fields, api, _ -from odoo.exceptions import UserError +from odoo.exceptions import UserError, Warning class CarRentalContract(models.Model): _name = 'car.rental.contract' + _description = 'Fleet Rental Management' + _inherit = ['mail.thread', 'ir.needaction_mixin'] - contract_name = fields.Char(string="Name", default="Draft Contract", readonly=True) - name = fields.Many2one('res.partner', required=True, help="Customer") - vehicle_id = fields.Many2one('fleet.vehicle', string="Vehicle To Rent", required=True) - car_brand = fields.Char(string="Car Brand", size=50) - car_color = fields.Char(string="Car Color", size=50) + image = fields.Binary(related='vehicle_id.image', string="Logo") + image_medium = fields.Binary(related='vehicle_id.image_medium', string="Logo (medium)") + image_small = fields.Binary(related='vehicle_id.image_small', string="Logo (small)") + name = fields.Char(string="Name", default="Draft Contract", readonly=True, copy=False) + customer_id = fields.Many2one('res.partner', required=True, string='Customer', help="Customer") + vehicle_id = fields.Many2one('fleet.vehicle', string="Vehicle", required=True, help="Vehicle") + car_brand = fields.Char(string="Fleet Brand", size=50) + car_color = fields.Char(string="Fleet Color", size=50) cost = fields.Float(string="Rent Cost", help="This fields is to determine the cost of rent per hour", required=True) - rent_start_date = fields.Date(string="Rent Start Date", required=True, default=datetime.today()) - rent_end_date = fields.Date(string="Rent End Date", required=True) + rent_start_date = fields.Date(string="Rent Start Date", required=True, default=datetime.today(), + help="Starting date of your contract", track_visibility='onchange') + rent_end_date = fields.Date(string="Rent End Date", required=True, help="Ending date of your contract", + track_visibility='onchange') state = fields.Selection([('draft', 'Draft'), ('running', 'Running'), ('cancel', 'Cancel'), - ('checking', 'Checking'), ('done', 'Done')], string="State", default="draft") + ('checking', 'Checking'), ('invoice', 'Invoice'), ('done', 'Done')], string="State", + default="draft", copy=False, track_visibility='onchange') notes = fields.Text(string="Details") - cost_generated = fields.Float('Recurring Cost', + cost_generated = fields.Float(string='Recurring Cost', help="Costs paid at regular intervals, depending on the cost frequency") cost_frequency = fields.Selection([('no', 'No'), ('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly'), ('yearly', 'Yearly')], string="Recurring Cost Frequency", @@ -48,18 +56,46 @@ class CarRentalContract(models.Model): default=lambda self: self.env['account.journal'].search([('id', '=', 1)])) account_type = fields.Many2one('account.account', 'Account', default=lambda self: self.env['account.account'].search([('id', '=', 17)])) - recurring_line = fields.One2many('fleet.rental.line', 'rental_number', readonly=True) - first_payment = fields.Float(string='First Payment') - first_invoice_created = fields.Boolean(string="First Invoice Created", invisible=True) + recurring_line = fields.One2many('fleet.rental.line', 'rental_number', readonly=True, help="Recurring Invoices", + copy=False) + first_payment = fields.Float(string='First Payment', help="Advance Payment", track_visibility='onchange') + first_payment_inv = fields.Many2one('account.invoice', copy=False) + first_invoice_created = fields.Boolean(string="First Invoice Created", invisible=True, copy=False) attachment_ids = fields.Many2many('ir.attachment', 'car_rent_checklist_ir_attachments_rel', 'rental_id', 'attachment_id', string="Attachments", help="Images of the vehicle before contract/any attachments") - checklist_line = fields.One2many('car.rental.checklist', 'checklist_number', string="Checklist") - total = fields.Float(string="Total(Tools)", readonly=True) - tools_missing_cost = fields.Float(string="Tools missing cost", readonly=True) - damage_cost = fields.Float(string="Damage cost") - damage_cost_sub = fields.Float(string="Damage cost", readonly=True) - total_cost = fields.Float(string="Total cost", readonly=True) + checklist_line = fields.One2many('car.rental.checklist', 'checklist_number', string="Checklist", help="Check List") + total = fields.Float(string="Total(Tools)", readonly=True, copy=False) + tools_missing_cost = fields.Float(string="Tools missing cost", readonly=True, copy=False) + damage_cost = fields.Float(string="Damage cost", copy=False) + damage_cost_sub = fields.Float(string="Damage cost", readonly=True, copy=False) + total_cost = fields.Float(string="Total cost", readonly=True, copy=False) + invoice_count = fields.Integer(compute='_invoice_count', string='# Invoice', copy=False) + sales_person = fields.Many2one('res.users', string='Sales Person', default=lambda self: self.env.uid, + track_visibility='always') + + @api.constrains('rent_start_date', 'rent_end_date') + def validate_dates(self): + if self.rent_end_date < self.rent_start_date: + raise Warning("Please select the valid end date.") + + @api.multi + def set_to_done(self): + invoice_ids = self.env['account.invoice'].search([('origin', '=', self.name)]) + f = 0 + for each in invoice_ids: + if each.state != 'paid': + f = 1 + break + if f == 0: + self.state = 'done' + else: + raise UserError("Some Invoices are pending") + + @api.multi + def _invoice_count(self): + invoice_ids = self.env['account.invoice'].search([('origin', '=', self.name)]) + self.invoice_count = len(invoice_ids) @api.constrains('state') def state_changer(self): @@ -108,7 +144,7 @@ class CarRentalContract(models.Model): start_date != date.today(): temp = 1 if temp == 1 and records.cost_frequency != "no" and records.state == "running": - supplier = records.name + supplier = records.customer_id inv_data = { 'name': supplier.name, 'reference': supplier.name, @@ -116,7 +152,7 @@ class CarRentalContract(models.Model): 'partner_id': supplier.id, 'currency_id': records.account_type.company_id.currency_id.id, 'journal_id': records.journal_type.id, - 'origin': records.vehicle_id.name, + 'origin': records.name, 'company_id': records.account_type.company_id.id, 'date_due': self.rent_end_date, } @@ -148,16 +184,36 @@ class CarRentalContract(models.Model): 'invoice_id': inv_id.id, } inv_line_obj.create(inv_line_data) + mail_content = _( + '

Reminder Recurrent Payment!


Hi %s,
This is to remind you that the ' + 'recurrent payment for the ' + 'rental contract has to be done.' + 'Please make the payment at the earliest.' + '

' + 'Please find the details below:

' + '' + '' + '' + '
Contract Ref %s
Amount %s
Due Date %s
Responsible Person %s, %s
') % \ + (self.customer_id.name, self.name, inv_id.amount_total, inv_id.date_due, inv_id.user_id.name, + inv_id.user_id.mobile) + main_content = { + 'subject': "Reminder Recurrent Payment!", + 'author_id': self.env.user.partner_id.id, + 'body_html': mail_content, + 'email_to': self.customer_id.email, + } + self.env['mail.mail'].create(main_content).send() else: records.state = "checking" @api.multi def action_verify(self): - self.state = "done" + self.state = "invoice" if self.total_cost != 0: inv_obj = self.env['account.invoice'] inv_line_obj = self.env['account.invoice.line'] - supplier = self.name + supplier = self.customer_id inv_data = { 'name': supplier.name, 'reference': supplier.name, @@ -165,7 +221,7 @@ class CarRentalContract(models.Model): 'partner_id': supplier.id, 'currency_id': self.account_type.company_id.currency_id.id, 'journal_id': self.journal_type.id, - 'origin': self.vehicle_id.name, + 'origin': self.name, 'company_id': self.account_type.company_id.id, 'date_due': self.rent_end_date, } @@ -217,8 +273,24 @@ class CarRentalContract(models.Model): sequence_code = 'car.rental.sequence' order_date = self.create_date order_date = order_date[0:10] - self.contract_name = self.env['ir.sequence']\ + self.name = self.env['ir.sequence']\ .with_context(ir_sequence_date=order_date).next_by_code(sequence_code) + mail_content = _('

Order Confirmed!


Hi %s,
This is to notify that your rental contract has ' + 'been confirmed.

' + 'Please find the details below:

' + '
' + '' + '
Reference Number %s
Time Range %s to %s
Vehicle %s
Point Of Contact %s , %s
') % \ + (self.customer_id.name, self.name, self.rent_start_date, self.rent_end_date, + self.vehicle_id.name, self.sales_person.name, self.sales_person.mobile) + main_content = { + 'subject': _('Confirmed: %s - %s') % + (self.name, self.vehicle_id.name), + 'author_id': self.env.user.partner_id.id, + 'body_html': mail_content, + 'email_to': self.customer_id.email, + } + self.env['mail.mail'].create(main_content).send() @api.multi def action_cancel(self): @@ -228,64 +300,125 @@ class CarRentalContract(models.Model): def force_checking(self): self.state = "checking" + @api.multi + def action_view_invoice(self): + inv_obj = self.env['account.invoice'].search([('origin', '=', self.name)]) + inv_ids = [] + for each in inv_obj: + inv_ids.append(each.id) + view_id = self.env.ref('account.invoice_form').id + if inv_ids: + if len(inv_ids) <= 1: + value = { + 'view_type': 'form', + 'view_mode': 'form', + 'res_model': 'account.invoice', + 'view_id': view_id, + 'type': 'ir.actions.act_window', + 'name': _('Invoice'), + 'res_id': inv_ids and inv_ids[0] + } + else: + value = { + 'domain': str([('id', 'in', inv_ids)]), + 'view_type': 'form', + 'view_mode': 'tree,form', + 'res_model': 'account.invoice', + 'view_id': False, + 'type': 'ir.actions.act_window', + 'name': _('Invoice'), + 'res_id': inv_ids + } + + return value + @api.multi def action_invoice_create(self): - self.first_invoice_created = True - inv_obj = self.env['account.invoice'] - inv_line_obj = self.env['account.invoice.line'] - supplier = self.name - inv_data = { - 'name': supplier.name, - 'reference': supplier.name, - 'account_id': supplier.property_account_payable_id.id, - 'partner_id': supplier.id, - 'currency_id': self.account_type.company_id.currency_id.id, - 'journal_id': self.journal_type.id, - 'origin': self.vehicle_id.name, - 'company_id': self.account_type.company_id.id, - 'date_due': self.rent_end_date, - } - inv_id = inv_obj.create(inv_data) - product_id = self.env['product.product'].search([("name", "=", "Fleet Rental Service")]) - if product_id.property_account_income_id.id: - income_account = product_id.property_account_income_id.id - elif product_id.categ_id.property_account_income_categ_id.id: - income_account = product_id.categ_id.property_account_income_categ_id.id - else: - raise UserError( - _('Please define income account for this product: "%s" (id:%d).') % (product_id.name, - product_id.id)) - inv_line_data = { - 'name': self.vehicle_id.name, - 'account_id': income_account, - 'price_unit': self.first_payment, - 'quantity': 1, - 'product_id': product_id.id, - 'invoice_id': inv_id.id, - } - inv_line_obj.create(inv_line_data) - imd = self.env['ir.model.data'] - action = imd.xmlid_to_object('account.action_invoice_tree1') - list_view_id = imd.xmlid_to_res_id('account.invoice_tree') - form_view_id = imd.xmlid_to_res_id('account.invoice_form') - result = { - 'name': action.name, - 'help': action.help, - 'type': 'ir.actions.act_window', - 'views': [[list_view_id, 'tree'], [form_view_id, 'form'], [False, 'graph'], [False, 'kanban'], - [False, 'calendar'], [False, 'pivot']], - 'target': action.target, - 'context': action.context, - 'res_model': 'account.invoice', - } - if len(inv_id) > 1: - result['domain'] = "[('id','in',%s)]" % inv_id.ids - elif len(inv_id) == 1: - result['views'] = [(form_view_id, 'form')] - result['res_id'] = inv_id.ids[0] + for each in self: + rent_date = datetime.strptime(each.rent_start_date, "%Y-%m-%d").date() + if each.cost_frequency != 'no' and rent_date < date.today(): + rental_days = (date.today() - rent_date).days + for each1 in range(1, rental_days): + each.fleet_scheduler() + recurrent_obj = self.env.ref('fleet_rental.cron_scheduler_for_fleet') + if datetime.today() > datetime.strptime(recurrent_obj.nextcall, "%Y-%m-%d %H:%M:%S"): + each.fleet_scheduler() + + if self.first_payment != 0: + self.first_invoice_created = True + inv_obj = self.env['account.invoice'] + inv_line_obj = self.env['account.invoice.line'] + supplier = self.customer_id + inv_data = { + 'name': supplier.name, + 'reference': supplier.name, + 'account_id': supplier.property_account_payable_id.id, + 'partner_id': supplier.id, + 'currency_id': self.account_type.company_id.currency_id.id, + 'journal_id': self.journal_type.id, + 'origin': self.name, + 'company_id': self.account_type.company_id.id, + 'date_due': self.rent_end_date, + } + inv_id = inv_obj.create(inv_data) + self.first_payment_inv = inv_id.id + product_id = self.env['product.product'].search([("name", "=", "Fleet Rental Service")]) + if product_id.property_account_income_id.id: + income_account = product_id.property_account_income_id.id + elif product_id.categ_id.property_account_income_categ_id.id: + income_account = product_id.categ_id.property_account_income_categ_id.id + else: + raise UserError( + _('Please define income account for this product: "%s" (id:%d).') % (product_id.name, + product_id.id)) + inv_line_data = { + 'name': self.vehicle_id.name, + 'account_id': income_account, + 'price_unit': self.first_payment, + 'quantity': 1, + 'product_id': product_id.id, + 'invoice_id': inv_id.id, + } + inv_line_obj.create(inv_line_data) + inv_id.action_invoice_open() + mail_content = _( + '

First Payment Received!


Hi %s,
This is to notify that your first payment has ' + 'been received.

' + 'Please find the details below:

' + '
' + '
Invoice Number %s
Date %s
Amount %s
') % \ + (self.customer_id.name, inv_id.number, inv_id.date_invoice, inv_id.amount_total) + main_content = { + 'subject': _('Payment Received: %s') % inv_id.number, + 'author_id': self.env.user.partner_id.id, + 'body_html': mail_content, + 'email_to': self.customer_id.email, + } + self.env['mail.mail'].create(main_content).send() + imd = self.env['ir.model.data'] + action = imd.xmlid_to_object('account.action_invoice_tree1') + list_view_id = imd.xmlid_to_res_id('account.invoice_tree') + form_view_id = imd.xmlid_to_res_id('account.invoice_form') + result = { + 'name': action.name, + 'help': action.help, + 'type': 'ir.actions.act_window', + 'views': [[list_view_id, 'tree'], [form_view_id, 'form'], [False, 'graph'], [False, 'kanban'], + [False, 'calendar'], [False, 'pivot']], + 'target': action.target, + 'context': action.context, + 'res_model': 'account.invoice', + } + if len(inv_id) > 1: + result['domain'] = "[('id','in',%s)]" % inv_id.ids + elif len(inv_id) == 1: + result['views'] = [(form_view_id, 'form')] + result['res_id'] = inv_id.ids[0] + else: + result = {'type': 'ir.actions.act_window_close'} + return result else: - result = {'type': 'ir.actions.act_window_close'} - return result + raise Warning("Please enter advance amount to make first payment") @api.onchange('vehicle_id') def update_fields(self): @@ -302,23 +435,25 @@ class FleetRentalLine(models.Model): date_today = fields.Date('Date') account_info = fields.Char('Account') recurring_amount = fields.Float('Amount') - rental_number = fields.Integer('Rental Number') - payment_info = fields.Char(string='Payment Stage', compute='paid_info') + rental_number = fields.Many2one('car.rental.contract', string='Rental Number') + payment_info = fields.Char(compute='paid_info', string='Payment Stage', default='draft') invoice_number = fields.Integer(string='Invoice ID') - @api.one + @api.multi + @api.depends('payment_info') def paid_info(self): - if self.env['account.invoice'].browse(self.invoice_number): - self.payment_info = self.env['account.invoice'].browse(self.invoice_number).state - else: - self.payment_info = 'Record Deleted' + for each in self: + if self.env['account.invoice'].browse(each.invoice_number): + each.payment_info = self.env['account.invoice'].browse(each.invoice_number).state + else: + each.payment_info = 'Record Deleted' class CarRentalChecklist(models.Model): _name = 'car.rental.checklist' name = fields.Many2one('car.tools', string="Name") - checklist_active = fields.Boolean(string="Active", default=True) + checklist_active = fields.Boolean(string="Active", default=False) checklist_number = fields.Many2one('car.rental.contract', string="Checklist number") price = fields.Float(string="Price") diff --git a/fleet_rental/reports/__init__.py b/fleet_rental/reports/__init__.py new file mode 100644 index 000000000..45a7847e4 --- /dev/null +++ b/fleet_rental/reports/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## +import rental_report + diff --git a/fleet_rental/reports/rental_report.py b/fleet_rental/reports/rental_report.py new file mode 100644 index 000000000..1f7909e37 --- /dev/null +++ b/fleet_rental/reports/rental_report.py @@ -0,0 +1,103 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2017-TODAY Cybrosys Technologies(). +# Author: Cybrosys() +# you can modify it under the terms of the GNU LESSER +# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. +# +# It is forbidden to publish, distribute, sublicense, or sell copies +# of the Software or modified copies of the Software. +# +# 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 +# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. +# If not, see . +# +############################################################################## +from odoo import models, fields, tools + + +class FleetRentalReport(models.Model): + _name = "report.fleet.rental" + _description = "Fleet Rental Analysis" + _auto = False + + name = fields.Char(string="Name") + customer_id = fields.Many2one('res.partner') + vehicle_id = fields.Many2one('fleet.vehicle') + car_brand = fields.Char(string="Car Brand") + car_color = fields.Char(string="Car Color") + cost = fields.Float(string="Rent Cost") + rent_start_date = fields.Date(string="Rent Start Date") + rent_end_date = fields.Date(string="Rent End Date") + state = fields.Selection([('draft', 'Draft'), ('running', 'Running'), ('cancel', 'Cancel'), + ('checking', 'Checking'), ('done', 'Done')], string="State") + cost_frequency = fields.Selection([('no', 'No'), ('daily', 'Daily'), ('weekly', 'Weekly'), ('monthly', 'Monthly'), + ('yearly', 'Yearly')], string="Recurring Cost Frequency") + total = fields.Float(string="Total(Tools)") + tools_missing_cost = fields.Float(string="Tools missing cost") + damage_cost = fields.Float(string="Damage cost") + damage_cost_sub = fields.Float(string="Damage cost") + total_cost = fields.Float(string="Total cost") + + _order = 'name desc' + + def _select(self): + select_str = """ + SELECT + (select 1 ) AS nbr, + t.id as id, + t.name as name, + t.car_brand as car_brand, + t.customer_id as customer_id, + t.vehicle_id as vehicle_id, + t.car_color as car_color, + t.cost as cost, + t.rent_start_date as rent_start_date, + t.rent_end_date as rent_end_date, + t.state as state, + t.cost_frequency as cost_frequency, + t.total as total, + t.tools_missing_cost as tools_missing_cost, + t.damage_cost as damage_cost, + t.damage_cost_sub as damage_cost_sub, + t.total_cost as total_cost + """ + return select_str + + def _group_by(self): + group_by_str = """ + GROUP BY + t.id, + name, + car_brand, + customer_id, + vehicle_id, + car_color, + cost, + rent_start_date, + rent_end_date, + state, + cost_frequency, + total, + tools_missing_cost, + damage_cost, + damage_cost_sub, + total_cost + """ + return group_by_str + + def init(self): + tools.sql.drop_view_if_exists(self._cr, 'report_fleet_rental') + self._cr.execute(""" + CREATE view report_fleet_rental as + %s + FROM car_rental_contract t + %s + """ % (self._select(), self._group_by())) diff --git a/fleet_rental/reports/rental_report.xml b/fleet_rental/reports/rental_report.xml new file mode 100644 index 000000000..17ee96ee3 --- /dev/null +++ b/fleet_rental/reports/rental_report.xml @@ -0,0 +1,25 @@ + + + + + report.fleet.rental.pivot + report.fleet.rental + + + + + + + + + Fleet Rental Analysis + report.fleet.rental + form + pivot + {'group_by_no_leaf':1,'group_by':[]} + This report allows you to analyse the performance of your Fleet Rental. + + + + + \ No newline at end of file diff --git a/fleet_rental/security/ir.model.access.csv b/fleet_rental/security/ir.model.access.csv new file mode 100644 index 000000000..2ae93eb5d --- /dev/null +++ b/fleet_rental/security/ir.model.access.csv @@ -0,0 +1,21 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +fleet_car_rental_contract_access_right_user,fleet_car_rental_contract_access_right,model_car_rental_contract,rental_group_user,1,1,1,0 +fleet_car_rental_contract_access_right_manager,fleet_car_rental_contract_access_right1,model_car_rental_contract,fleet.fleet_group_manager,1,1,1,1 +fleet_fleet_rental_line_access_right_user,fleet_fleet_rental_line_access_right,model_fleet_rental_line,rental_group_user,1,1,1,0 +fleet_fleet_rental_line_access_right_manager,fleet_fleet_rental_line_access_right1,model_fleet_rental_line,fleet.fleet_group_manager,1,1,1,1 +fleet_car_rental_checklist_access_right_user,fleet_car_rental_checklist_access_right,model_car_rental_checklist,rental_group_user,1,1,1,0 +fleet_car_rental_checklist_access_right_manager,fleet_car_rental_checklist_access_right1,model_car_rental_checklist,fleet.fleet_group_manager,1,1,1,1 +fleet_car_tools_access_right_user,fleet_car_tools_access_right,model_car_tools,rental_group_user,1,1,1,0 +fleet_car_tools_contract_access_right_manager,fleet_car_tools_access_right1,model_car_tools,fleet.fleet_group_manager,1,1,1,1 +fleet_report_fleet_rental_access_right_user,fleet_report_fleet_rental_access_right,model_report_fleet_rental,rental_group_user,1,1,1,0 +fleet_report_fleet_rental_access_right_manager,fleet_report_fleet_rental_access_right1,model_report_fleet_rental,fleet.fleet_group_manager,1,1,1,1 +fleet_cron_right_user,fleet_vehicle_access_right1,base.model_ir_cron,rental_group_user,1,1,1,0 +fleet_cron_right_user1,fleet_vehicle_access_right11,base.model_ir_cron,fleet.fleet_group_manager,1,1,1,0 +fleet_vehicle_model_access_right_user,fleet_vehicle_model_access_right,fleet.model_fleet_vehicle_model,rental_group_user,1,1,1,0 +fleet_vehicle_model_brand_access_right_user,fleet_vehicle_model_brand_access_right,fleet.model_fleet_vehicle_model_brand,rental_group_user,1,1,1,0 +fleet_vehicle_access_right_user,fleet_vehicle_access_right,fleet.model_fleet_vehicle,rental_group_user,1,1,1,0 +fleet_vehicle_access_right_user1,fleet_vehicle_access_right,fleet.model_fleet_vehicle,fleet.fleet_group_user,1,1,1,0 + + + + diff --git a/fleet_rental/security/rental_security.xml b/fleet_rental/security/rental_security.xml new file mode 100644 index 000000000..8c2247b31 --- /dev/null +++ b/fleet_rental/security/rental_security.xml @@ -0,0 +1,18 @@ + + + + + Rental User + + + + + + Manager + + + + + + diff --git a/fleet_rental/static/description/banner.jpg b/fleet_rental/static/description/banner.jpg index edce0c10f..5e6b5642c 100644 Binary files a/fleet_rental/static/description/banner.jpg and b/fleet_rental/static/description/banner.jpg differ diff --git a/fleet_rental/static/description/check_list_form.png b/fleet_rental/static/description/check_list_form.png index d41b6e3af..e52026090 100644 Binary files a/fleet_rental/static/description/check_list_form.png and b/fleet_rental/static/description/check_list_form.png differ diff --git a/fleet_rental/static/description/check_list_tree.png b/fleet_rental/static/description/check_list_tree.png index da353c2f9..febc4704b 100644 Binary files a/fleet_rental/static/description/check_list_tree.png and b/fleet_rental/static/description/check_list_tree.png differ diff --git a/fleet_rental/static/description/checklist_contract.png b/fleet_rental/static/description/checklist_contract.png index df860af71..ead008916 100644 Binary files a/fleet_rental/static/description/checklist_contract.png and b/fleet_rental/static/description/checklist_contract.png differ diff --git a/fleet_rental/static/description/contract_menu.png b/fleet_rental/static/description/contract_menu.png index 946914b17..cb80cbea7 100644 Binary files a/fleet_rental/static/description/contract_menu.png and b/fleet_rental/static/description/contract_menu.png differ diff --git a/fleet_rental/static/description/email1.png b/fleet_rental/static/description/email1.png new file mode 100644 index 000000000..9fbd5896f Binary files /dev/null and b/fleet_rental/static/description/email1.png differ diff --git a/fleet_rental/static/description/email2.png b/fleet_rental/static/description/email2.png new file mode 100644 index 000000000..6cd54feec Binary files /dev/null and b/fleet_rental/static/description/email2.png differ diff --git a/fleet_rental/static/description/email3.png b/fleet_rental/static/description/email3.png new file mode 100644 index 000000000..5ccaecafd Binary files /dev/null and b/fleet_rental/static/description/email3.png differ diff --git a/fleet_rental/static/description/icon.png b/fleet_rental/static/description/icon.png index d6298cb96..da2ab45be 100644 Binary files a/fleet_rental/static/description/icon.png and b/fleet_rental/static/description/icon.png differ diff --git a/fleet_rental/static/description/index.html b/fleet_rental/static/description/index.html index 22cde20c5..54eb37c98 100644 --- a/fleet_rental/static/description/index.html +++ b/fleet_rental/static/description/index.html @@ -1,17 +1,23 @@
-

Fleet Rental Management

+

Fleet/Vehicle Rental Management

This module helps with an opportunity to give the vehicles for Rent.

-

Author : Cybrosys Techno Solutions , www.cybrosys.com

+

Cybrosys Technologies

Features:

+ Multiple Plans for Rental Contract(Days/Weeks/Months/Years).
Integrated with Accounting Module.
Automatically Create Recurring Invoices.
- Check list Facility.
+ Sending email for confirmation, first payment and recurrent invoices.
+ Check List Facility.
Separate Tree view for Checklist.
Damage Checking Facility.
+ Billing Facility for Damages/Check Lists.
+ Contract Payment Validations.
+ Detailed Fleet Rental Analysis Report.
+ Access Rights From Multiple Level.
@@ -20,42 +26,49 @@

Overview

-

- This module is an extension to the fleet module which helps - with an opportunity to rent your car. Currently fleet module - does not have connection with accounting module. But in this - module, we integrate the module with accounting. +

+ This module is an application for Vehicle Rental System by Cybrosys Technologies which helps in managing the rental of fleet/vehicle. + It manages fleet/vehicle property by extending the basic fleet module of Odoo. + Currently fleet module does not have any connection with accounting module. But in this module, + we integrate the module with accounting also.

+
-

Menu

+

Fleet Rental Management

-

Fleet -> Rental Management

+

Fleet Rental -> Rental Management

-
-
- -
- ☛ When you install the module, an extra menu - Rental Management created under Fleet Menu. +
+ +
+ +
+
+ ☛ When you install the module, an extra menu named Rental Management is created + under the Fleet Menu. Also "Fleet" menu is replaced as "Fleet Rental". Here you can see different color + codes according to each state. This helps you in finding out contracts easily.

-

Fleet -> Rental Management -> Rental Contract

+

Fleet Rental -> Rental Management -> Rental Contract

- ☛ This is the Rental Contract form. you can see the Recurring - lines created according to the Recurring cost +
+ ☛ This is the Rental Contract form. You can see the Recurring lines created according to + the Recurring cost. And also you can see all the invoices related to this contract from the smart + button "Invoices". +
@@ -71,14 +84,13 @@
-
+

- Here you can add the list of tools given with the vehicle. - When the vehicle is returned back, the checklist can be validated - and helps you to identify the tools that are not returned. - The price of unreturned tools will be added to the missing tool cost. - The renter have to pay that amount and you can also add damage cost if any. - Check the damages by using the images of vehicle uploaded before the contract. + Here you can add the list of tools given with the vehicle. + When the vehicle is returned back, the checklist can be validated and helps you to identify the + tools that are not returned. The price of unreturned tools will be added to the missing tool cost. + The renter have to pay that amount and you can also add damage cost if any. Check the damages by + using the images of vehicle uploaded before the contract.

@@ -88,7 +100,7 @@

Checklist Easy Access

-
+
@@ -98,17 +110,95 @@
- ☛ +
+ You can also create invoice against the checklist from here. The checklists are those which are in the checking state, that means the ones ready for checking the operation. - If there is any damage or any missing tool, then you can - charge that from customer. + If there is any damage or any missing tool, then you can charge all that from customer. +
+
+
+
+ +
+
+

Email Notifications

+
+
+ + ☛The system will send email notification to notify the confirmation of contract.
+ ☛The system will notify the first payment through email.
+ ☛The system will remind all recurrent invoices through email.
+ Note:- You should configure outgoing and incoming e-mail settings from your odoo for email service. +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+

Contract Payment Validations

+
+
+ +
+
+ ☛ + Here you can see you have 4 invoices and this contract is in 'Invoice' state. + So you can set this contract to done only if all the invoices are in 'paid' state. + Otherwise it will raise a warning as follow. + + +
+
+ +
+
+
+
+ +
+
+

Fleet Rental Analysis Report

+
+
+ +
+ ☛ + You can also analyse all your fleet rentals from Fleet Rental -> Reports -> Fleet Rental Analysis. +
+
+

Access Rights

+
+ ☛Fleet Manager :- Fleet manager has the complete access across the fleet rental management
+ ☛Fleet Rental User :- Fleet rental user can read, write and create the records. +
+
+
+ +

Need Any Help?

diff --git a/fleet_rental/static/description/index.html~ b/fleet_rental/static/description/index.html~ new file mode 100644 index 000000000..7b3fd6a31 --- /dev/null +++ b/fleet_rental/static/description/index.html~ @@ -0,0 +1,228 @@ +
+
+

Fleet/Vehicle Rental Management

+

This module helps with an opportunity to give the vehicles for Rent.

+

Cybrosys Technologies

+
+
+

Features:

+
+ Multiple Plans for Rental Contract(Days/Weeks/Months/Years).
+ Integrated with Accounting Module.
+ Automatically Create Recurring Invoices.
+ Sending email for confirmation, first payment and recurrent invoices.
+ Check List Facility.
+ Separate Tree view for Checklist.
+ Damage Checking Facility.
+ Billing Facility for Damages/Check Lists.
+ Contract Payment Validations.
+ Detailed Fleet Rental Analysis Report.
+ Access Rights From Multiple Level.
+
+
+
+ +
+
+
+

Overview

+

+ This module is an application for Vehicle Rental System which helps in managing the rental of fleet/vehicle. + It manages fleet/vehicle property by extending the basic fleet module of Odoo. + Currently fleet module does not have any connection with accounting module. But in this module, + we integrate the module with accounting also. +

+
+
+
+ +
+
+

Fleet Rental Management

+
+

+

Fleet Rental -> Rental Management

+

+

+
+ +
+ +
+
+ ☛ When you install the module, an extra menu named Rental Management is created + under the Fleet Menu. Also "Fleet" menu is replaced as "Fleet Rental". Here you can see different color + codes according to each state. This helps you in finding out contracts easily. +
+
+
+
+

+

Fleet Rental -> Rental Management -> Rental Contract

+

+

+
+ +
+
+ ☛ This is the Rental Contract form. You can see the Recurring lines created according to + the Recurring cost. And also you can see all the invoices related to this contract from the smart + button "Invoices". +
+
+
+
+ +
+
+

Checklist

+
+
+ +
+ ☛ Checklist Tab in Rental Contract Form. +
+
+
+
+

+ Here you can add the list of tools given with the vehicle. + When the vehicle is returned back, the checklist can be validated and helps you to identify the + tools that are not returned. The price of unreturned tools will be added to the missing tool cost. + The renter have to pay that amount and you can also add damage cost if any. Check the damages by + using the images of vehicle uploaded before the contract. +

+

+
+
+
+ +
+
+

Checklist Easy Access

+
+
+ +
+ ☛ No need to open all rental contract to see the checklist. +
+
+
+ +
+
+ + You can also create invoice against the checklist from here. + The checklists are those which are in the checking state, + that means the ones ready for checking the operation. + If there is any damage or any missing tool, then you can charge all that from customer. +
+
+
+
+ +
+
+

Email Notifications

+
+
+ + ☛The system will send email notification to notify the confirmation of contract.
+ ☛The system will notify the first payment through email.
+ ☛The system will remind all recurrent invoices through email.
+ Note:- You should configure outgoing and incoming e-mail settings from your odoo for email service. +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+

Contract Payment Validations

+
+
+ +
+
+ ☛ + Here you can see you have 4 invoices and this contract is in 'Invoice' state. + So you can set this contract to done only if all the invoices are in 'paid' state. + Otherwise it will raise a warning as follow. + + +
+
+ +
+
+
+
+ +
+
+

Fleet Rental Analysis Report

+
+
+ +
+ ☛ + You can also analyse all your fleet rentals from Fleet Rental -> Reports -> Fleet Rental Analysis. + +
+
+
+ +
+
+

Access Rights

+
+ ☛Fleet Manager :- Fleet manager has the complete access across the fleet rental management
+ ☛Fleet Rental User :- Fleet rental user can read, write and create the records. +
+
+
+ +
+

Need Any Help?

+ +
+ + + diff --git a/fleet_rental/static/description/menu_items.png b/fleet_rental/static/description/menu_items.png index d13360f41..c80ff0a07 100644 Binary files a/fleet_rental/static/description/menu_items.png and b/fleet_rental/static/description/menu_items.png differ diff --git a/fleet_rental/static/description/rental_inv.png b/fleet_rental/static/description/rental_inv.png new file mode 100644 index 000000000..def84f9bb Binary files /dev/null and b/fleet_rental/static/description/rental_inv.png differ diff --git a/fleet_rental/static/description/rental_validation.png b/fleet_rental/static/description/rental_validation.png new file mode 100644 index 000000000..665b0acbe Binary files /dev/null and b/fleet_rental/static/description/rental_validation.png differ diff --git a/fleet_rental/static/description/report.png b/fleet_rental/static/description/report.png new file mode 100644 index 000000000..f6a4d8ff3 Binary files /dev/null and b/fleet_rental/static/description/report.png differ diff --git a/fleet_rental/views/car_rental_view.xml b/fleet_rental/views/car_rental_view.xml index aae96c269..4c3cef11a 100644 --- a/fleet_rental/views/car_rental_view.xml +++ b/fleet_rental/views/car_rental_view.xml @@ -11,6 +11,7 @@ 4 + Fleet scheduler @@ -22,6 +23,7 @@ + car.contract.result.form car.rental.contract @@ -39,114 +41,143 @@ +
+ +
+

+ +

+
+ + + + + + - - - - - - - - - - - - - - - - - - +
+ + + + + + + + - - - - - - - - - - - - - - + + + - - - - - - + - - - - - - -
- - - - - - - - -
-
- - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + -
-
-
-
-
- - - + + + + + + +
+ + + + + + + + +
+
+ + + + + + +
+
+
+ + + + + +
+ + +
+ car_contract_tree_view.tree car.rental.contract tree - - + + + @@ -157,12 +188,17 @@ + Rental Contract car.rental.contract form + [('sales_person','=', uid)] tree,form + + diff --git a/fleet_rental/views/car_tools_view.xml b/fleet_rental/views/car_tools_view.xml index 79960a1f6..1f62e1cc5 100644 --- a/fleet_rental/views/car_tools_view.xml +++ b/fleet_rental/views/car_tools_view.xml @@ -20,6 +20,7 @@
+ car_rental_contract_tools_tree_view.tree car.tools @@ -31,12 +32,14 @@ + Tools car.tools form tree,form + diff --git a/fleet_rental/views/checklist_view.xml b/fleet_rental/views/checklist_view.xml index dd05f980b..6b801975c 100644 --- a/fleet_rental/views/checklist_view.xml +++ b/fleet_rental/views/checklist_view.xml @@ -15,11 +15,11 @@ - + - + @@ -45,23 +45,26 @@ + car_rental_contract_checklist_tree_view.tree car.rental.contract tree - - + + + Checklist car.rental.contract form tree,form + [('state', 'in', ('running', 'checking')), ('sales_person','=', uid)] @@ -78,6 +81,7 @@ +