diff --git a/fleet_rental/README.rst b/fleet_rental/README.rst new file mode 100644 index 000000000..50acbc397 --- /dev/null +++ b/fleet_rental/README.rst @@ -0,0 +1,24 @@ +Fleet Rental Management v9 +========================== +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 new file mode 100644 index 000000000..0a58443d4 --- /dev/null +++ b/fleet_rental/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2016-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 models +import reports + diff --git a/fleet_rental/__openerp__.py b/fleet_rental/__openerp__.py new file mode 100644 index 000000000..d317453a1 --- /dev/null +++ b/fleet_rental/__openerp__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2016-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': """The Complete Solution for a Car/Vehicle Rental System""", + 'version': '9.0.1.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 new file mode 100644 index 000000000..9a086c072 --- /dev/null +++ b/fleet_rental/data/fleet_rental_data.xml @@ -0,0 +1,22 @@ + + + + + Fleet Rental Service + service + + + 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 new file mode 100644 index 000000000..8280b8335 --- /dev/null +++ b/fleet_rental/models/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2016-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 car_rental + diff --git a/fleet_rental/models/car_rental.py b/fleet_rental/models/car_rental.py new file mode 100644 index 000000000..25428d9c7 --- /dev/null +++ b/fleet_rental/models/car_rental.py @@ -0,0 +1,470 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2016-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 datetime import datetime, date +from openerp import models, fields, api, _ +from openerp.exceptions import UserError, Warning + + +class CarRentalContract(models.Model): + _name = 'car.rental.contract' + _description = 'Fleet Rental Management' + _inherit = ['mail.thread', 'ir.needaction_mixin'] + + 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, help="Customer") + vehicle_id = fields.Many2one('fleet.vehicle', string="Vehicle", required=True, help="Vehicle", copy=False) + 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(), + 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'), ('invoice', 'Invoice'), ('done', 'Done')], string="State", + default="draft", copy=False, track_visibility='onchange') + notes = fields.Text(string="Details") + cost_generated = fields.Float('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", + help='Frequency of the recurring cost', required=True) + journal_type = fields.Many2one('account.journal', 'Journal', + 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, 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", 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): + if self.state == "running": + state_id = self.env['fleet.vehicle.state'].search([('name', '=', "Rent")]).id + self.vehicle_id.write({'state_id': state_id}) + elif self.state == "done": + state_id = self.env['fleet.vehicle.state'].search([('name', '=', "Active")]).id + self.vehicle_id.write({'state_id': state_id}) + + @api.constrains('checklist_line', 'damage_cost') + def total_updater(self): + total = 0.0 + tools_missing_cost = 0.0 + for records in self.checklist_line: + total += records.price + if not records.checklist_active: + tools_missing_cost += records.price + self.total = total + self.tools_missing_cost = tools_missing_cost + self.damage_cost_sub = self.damage_cost + self.total_cost = tools_missing_cost + self.damage_cost + + @api.model + def fleet_scheduler(self): + inv_obj = self.env['account.invoice'] + inv_line_obj = self.env['account.invoice.line'] + recurring_obj = self.env['fleet.rental.line'] + today = date.today() + for records in self.search([]): + start_date = datetime.strptime(records.rent_start_date, '%Y-%m-%d').date() + end_date = datetime.strptime(records.rent_end_date, '%Y-%m-%d').date() + if end_date >= date.today(): + temp = 0 + if records.cost_frequency == 'daily': + temp = 1 + elif records.cost_frequency == 'weekly': + week_days = (date.today() - start_date).days + if week_days % 7 == 0 and week_days != 0: + temp = 1 + elif records.cost_frequency == 'monthly': + if start_date.day == date.today().day and start_date != date.today(): + temp = 1 + elif records.cost_frequency == 'yearly': + if start_date.day == date.today().day and start_date.month == date.today().month and \ + start_date != date.today(): + temp = 1 + if temp == 1 and records.cost_frequency != "no" and records.state == "running": + supplier = records.customer_id + inv_data = { + 'name': supplier.name, + 'reference': supplier.name, + 'account_id': supplier.property_account_payable_id.id, + 'partner_id': supplier.id, + 'currency_id': records.account_type.company_id.currency_id.id, + 'journal_id': records.journal_type.id, + 'origin': records.name, + 'company_id': records.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 + elif product_id.categ_id.property_account_income_categ_id.id: + income_account = product_id.categ_id.property_account_income_categ_id + else: + raise UserError( + _('Please define income account for this product: "%s" (id:%d).') % (product_id.name, + product_id.id)) + recurring_data = { + 'name': records.vehicle_id.name, + 'date_today': today, + 'account_info': income_account.name, + 'rental_number': records.id, + 'recurring_amount': records.cost_generated, + 'invoice_number': inv_id.id + } + recurring_obj.create(recurring_data) + inv_line_data = { + 'name': records.vehicle_id.name, + 'account_id': income_account.id, + 'price_unit': records.cost_generated, + 'quantity': 1, + 'product_id': product_id.id, + '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 = "invoice" + if self.total_cost != 0: + 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) + 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 + elif product_id.categ_id.property_account_income_categ_id.id: + income_account = product_id.categ_id.property_account_income_categ_id + else: + raise UserError( + _('Please define income account for this product: "%s" (id:%d).') % (product_id.name, + product_id.id)) + inv_line_data = { + 'name': "Damage/Tools missing cost", + 'account_id': income_account.id, + 'price_unit': self.total_cost, + '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] + else: + result = {'type': 'ir.actions.act_window_close'} + return result + + @api.multi + def action_confirm(self): + self.state = "running" + sequence_code = 'car.rental.sequence' + order_date = self.create_date + order_date = order_date[0:10] + 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): + self.state = "cancel" + + @api.multi + 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): + 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) + mail_content = _( + '

First Payment Received!


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

' + 'Please find the details below:

' + '
' + '
Contract Ref %s
Amount %s
') % \ + (self.customer_id.name, self.name, 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: + raise Warning("Please enter advance amount to make first payment") + + @api.onchange('vehicle_id') + def update_fields(self): + if self.vehicle_id: + obj = self.env['fleet.vehicle'].search([('name', '=', self.vehicle_id.name)]) + self.car_brand = obj.model_id.brand_id.name + self.car_color = obj.color + + +class FleetRentalLine(models.Model): + _name = 'fleet.rental.line' + + name = fields.Char('Description') + date_today = fields.Date('Date') + account_info = fields.Char('Account') + recurring_amount = fields.Float('Amount') + rental_number = fields.Many2one('car.rental.contract', string='Rental Number') + payment_info = fields.Char(string='Payment Stage', compute='paid_info') + invoice_number = fields.Integer(string='Invoice ID') + + @api.multi + @api.depends('payment_info') + def paid_info(self): + 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=False) + checklist_number = fields.Many2one('car.rental.contract', string="Checklist number") + price = fields.Float(string="Price") + + @api.onchange('name') + def onchange_name(self): + self.price = self.name.price + + +class CarTools(models.Model): + _name = 'car.tools' + + name = fields.Char(string="Name") + 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..f4c32841a --- /dev/null +++ b/fleet_rental/reports/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2016-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..640403e1f --- /dev/null +++ b/fleet_rental/reports/rental_report.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +from openerp 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, cr): + tools.sql.drop_view_if_exists(cr, 'report_fleet_rental') + 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..1475ebfb2 --- /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..3f29f9968 --- /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.group_fleet_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.group_fleet_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.group_fleet_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.group_fleet_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.group_fleet_manager,1,1,1,1 +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_user1,fleet_vehicle_access_right,fleet.model_fleet_vehicle,rental_group_user,1,1,1,0 +fleet_vehicle_access_right_user,fleet_vehicle_access_right",fleet.model_fleet_vehicle,fleet.group_fleet_user,1,1,1,0 +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.group_fleet_manager,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..cd902d251 --- /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 new file mode 100644 index 000000000..5e6b5642c Binary files /dev/null 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 new file mode 100644 index 000000000..e52026090 Binary files /dev/null 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 new file mode 100644 index 000000000..febc4704b Binary files /dev/null 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 new file mode 100644 index 000000000..ead008916 Binary files /dev/null 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 new file mode 100644 index 000000000..cb80cbea7 Binary files /dev/null and b/fleet_rental/static/description/contract_menu.png differ diff --git a/fleet_rental/static/description/cybro_logo.png b/fleet_rental/static/description/cybro_logo.png new file mode 100644 index 000000000..bb309114c Binary files /dev/null and b/fleet_rental/static/description/cybro_logo.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 new file mode 100644 index 000000000..da2ab45be Binary files /dev/null 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 new file mode 100644 index 000000000..54eb37c98 --- /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 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. +

+
+
+
+ +
+
+

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 new file mode 100644 index 000000000..c80ff0a07 Binary files /dev/null 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 new file mode 100644 index 000000000..eea4a4003 --- /dev/null +++ b/fleet_rental/views/car_rental_view.xml @@ -0,0 +1,206 @@ + + + + + Car Rental Sequence + car.rental.sequence + RENT/%(range_year)s/ + + + + 4 + + + + + + Fleet scheduler + + 1 + days + -1 + + + + + + + car.contract.result.form + car.rental.contract + form + +
+
+
+ +
+ +
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+
+
+
+ + + +
+
+ + +
+ +
+
+ + + car_contract_tree_view.tree + car.rental.contract + tree + + + + + + + + + + + + + + + + + Rental Contract + car.rental.contract + form + tree,form + [('sales_person','=', uid)] + + + + + +
+
diff --git a/fleet_rental/views/car_tools_view.xml b/fleet_rental/views/car_tools_view.xml new file mode 100644 index 000000000..b1c268d58 --- /dev/null +++ b/fleet_rental/views/car_tools_view.xml @@ -0,0 +1,46 @@ + + + + + car_rental_contract_tools_form_view.form + car.tools + form + +
+ + + + + + + + + + + +
+
+ + + car_rental_contract_tools_tree_view.tree + car.tools + tree + + + + + + + + + + Tools + car.tools + form + tree,form + + + +
+
diff --git a/fleet_rental/views/checklist_view.xml b/fleet_rental/views/checklist_view.xml new file mode 100644 index 000000000..a0a67d486 --- /dev/null +++ b/fleet_rental/views/checklist_view.xml @@ -0,0 +1,88 @@ + + + + + car_rental_contract_checklist_form_view.form + car.rental.contract + form + +
+
+
+ + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+
+
+ +
+
+ + + 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)] + + + + + + form + + + + + + + tree + + + + + +
+