Browse Source

Oct 7 : [FIX] Bug Fixed 'fleet_rental'

pull/195/merge
AjmalCybro 2 years ago
parent
commit
d246c51fbe
  1. 5
      fleet_rental/README.rst
  2. 3
      fleet_rental/__init__.py
  3. 11
      fleet_rental/__manifest__.py
  4. 2
      fleet_rental/data/fleet_rental_data.xml
  5. 6
      fleet_rental/doc/RELEASE_NOTES.md
  6. 6
      fleet_rental/models/__init__.py
  7. 314
      fleet_rental/models/car_rental.py
  8. 11
      fleet_rental/models/fleet.py
  9. 35
      fleet_rental/models/res_config_settings.py
  10. 2
      fleet_rental/reports/__init__.py
  11. 2
      fleet_rental/reports/rental_report.py
  12. 19
      fleet_rental/reports/rental_report.xml
  13. BIN
      fleet_rental/static/description/images/screenshot-12.png
  14. 565
      fleet_rental/static/description/index.html
  15. 119
      fleet_rental/views/car_rental_view.xml
  16. 17
      fleet_rental/views/checklist_view.xml
  17. 27
      fleet_rental/views/res_config_settings_views.xml

5
fleet_rental/README.rst

@ -1,8 +1,11 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
Fleet Rental Management v15
===========================
This module will helps you to give the vehicles for Rent.
Configuration
=============
* No additional configurations needed

3
fleet_rental/__init__.py

@ -3,7 +3,7 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
@ -19,6 +19,5 @@
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from . import models
from . import reports

11
fleet_rental/__manifest__.py

@ -3,7 +3,7 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
@ -22,28 +22,29 @@
{
'name': 'Fleet Rental Management',
'version': '15.0.1.0.0',
'version': '15.0.2.0.0',
'category': "Industries",
'summary': """This module will helps you to give the vehicles for Rent.""",
'description': "Module Helps You To Manage Rental Contracts, Odoo13, Odoo 13, Fleet, Rental, Rent, Vehicle management",
'category': "Industries",
'live_test_url': 'https://youtu.be/chN-n7nB3Ac',
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': "https://www.cybrosys.com",
'depends': ['base', 'account', 'fleet', 'mail'],
'data': [
'data/fleet_rental_data.xml',
'security/rental_security.xml',
'security/ir.model.access.csv',
'views/res_config_settings_views.xml',
'views/car_rental_view.xml',
'views/checklist_view.xml',
'views/car_tools_view.xml',
'reports/rental_report.xml'
],
'demo': [
],
'images': ['static/description/banner.png'],
'license': 'AGPL-3',
'installable': True,
'application': True,
'auto_install': False
}

2
fleet_rental/data/fleet_rental_data.xml

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0">
<record model="product.template" id="fleet_service_product">
<field name="name">Fleet Rental Service</field>
@ -745,5 +744,4 @@
</field>
</record>
</data>
</odoo>

6
fleet_rental/doc/RELEASE_NOTES.md

@ -3,8 +3,12 @@
#### 03.12.2020
#### Version 15.0.1.0.0
#### ADD
Initial Commit for Fleet Rental Management
- Initial Commit for Fleet Rental Management
#### 26.09.2023
#### Version 15.0.2.0.0
#### ADD
- Rental fleet Invoice product selection from Configuration Settings.

6
fleet_rental/models/__init__.py

@ -3,7 +3,7 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
@ -19,8 +19,6 @@
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from . import car_rental
from . import fleet
from . import res_config_settings

314
fleet_rental/models/car_rental.py

@ -3,7 +3,7 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
@ -22,7 +22,7 @@
from datetime import datetime, date, timedelta
from odoo import models, fields, api, _
from odoo.exceptions import UserError, Warning
from odoo.exceptions import UserError
class CarRentalContract(models.Model):
@ -40,7 +40,8 @@ class CarRentalContract(models.Model):
if str(each.date_from) <= str(self.rent_start_date) <= str(each.date_to):
i.write({'rental_check_availability': False})
elif str(self.rent_start_date) < str(each.date_from):
if str(each.date_from) <= str(self.rent_end_date) <= str(each.date_to):
if str(each.date_from) <= str(self.rent_end_date) <= str(
each.date_to):
i.write({'rental_check_availability': False})
elif str(self.rent_end_date) > str(each.date_to):
i.write({'rental_check_availability': False})
@ -50,37 +51,54 @@ class CarRentalContract(models.Model):
i.write({'rental_check_availability': True})
image = fields.Binary(related='vehicle_id.image_128', string="Image of Vehicle")
reserved_fleet_id = fields.Many2one('rental.fleet.reserved', invisible=True, copy=False)
reserved_fleet_id = fields.Many2one('rental.fleet.reserved', invisible=True,
copy=False)
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",
customer_id = fields.Many2one('res.partner', required=True, string='Customer',
help="Customer")
vehicle_id = fields.Many2one('fleet.vehicle', string="Vehicle", required=True,
help="Vehicle",
readonly=True,
states={'draft': [('readonly', False)]}
)
car_brand = fields.Many2one('fleet.vehicle.model.brand', string="Fleet Brand", size=50,
related='vehicle_id.model_id.brand_id', store=True, readonly=True)
car_color = fields.Char(string="Fleet Color", size=50, related='vehicle_id.color', store=True, copy=False,
car_brand = fields.Many2one('fleet.vehicle.model.brand', string="Fleet Brand",
size=50,
related='vehicle_id.model_id.brand_id', store=True,
readonly=True)
car_color = fields.Char(string="Fleet Color", size=50, related='vehicle_id.color',
store=True, copy=False,
default='#FFFFFF', readonly=True)
cost = fields.Float(string="Rent Cost", help="This fields is to determine the cost of rent", required=True)
rent_start_date = fields.Date(string="Rent Start Date", required=True, default=str(date.today()),
help="Start date of contract", track_visibility='onchange')
rent_end_date = fields.Date(string="Rent End Date", required=True, help="End date of contract",
cost = fields.Float(string="Rent Cost",
help="This fields is to determine the cost of rent",
required=True)
rent_start_date = fields.Date(string="Rent Start Date", required=True,
default=str(date.today()),
help="Start date of contract",
track_visibility='onchange')
rent_end_date = fields.Date(string="Rent End Date", required=True,
help="End date of contract",
track_visibility='onchange')
state = fields.Selection(
[('draft', 'Draft'), ('reserved', 'Reserved'), ('running', 'Running'), ('cancel', 'Cancel'),
('checking', 'Checking'), ('invoice', 'Invoice'), ('done', 'Done')], string="State",
[('draft', 'Draft'), ('reserved', 'Reserved'), ('running', 'Running'),
('cancel', 'Cancel'),
('checking', 'Checking'), ('invoice', 'Invoice'), ('done', 'Done')],
string="State",
default="draft", copy=False, track_visibility='onchange')
notes = fields.Text(string="Details & Notes")
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",
help='Frequency of the recurring cost', required=True)
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, default='no')
journal_type = fields.Many2one('account.journal', 'Journal',
default=lambda self: self.env['account.journal'].search([('id', '=', 1)]))
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",
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="Transaction/Office/Contract charge amount, must paid by customer side other "
@ -88,11 +106,14 @@ class CarRentalContract(models.Model):
track_visibility='onchange',
required=True)
first_payment_inv = fields.Many2one('account.move', 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',
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",
checklist_line = fields.One2many('car.rental.checklist', 'checklist_number',
string="Checklist",
help="Facilities/Accessories, That should verify when closing the contract.",
states={'invoice': [('readonly', True)],
'done': [('readonly', True)],
@ -103,9 +124,11 @@ class CarRentalContract(models.Model):
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", readonly=True, copy=False)
invoice_count = fields.Integer(compute='_invoice_count', string='# Invoice', copy=False)
invoice_count = fields.Integer(compute='_invoice_count', string='# Invoice',
copy=False)
check_verify = fields.Boolean(compute='check_action_verify', copy=False)
sales_person = fields.Many2one('res.users', string='Sales Person', default=lambda self: self.env.uid,
sales_person = fields.Many2one('res.users', string='Sales Person',
default=lambda self: self.env.uid,
track_visibility='always')
def action_run(self):
@ -128,10 +151,11 @@ class CarRentalContract(models.Model):
@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.")
raise UserError("Please select the valid end date.")
def set_to_done(self):
invoice_ids = self.env['account.move'].search([('invoice_origin', '=', self.name)])
invoice_ids = self.env['account.move'].search(
[('invoice_origin', '=', self.name)])
f = 0
for each in invoice_ids:
if each.payment_state != 'paid':
@ -143,7 +167,8 @@ class CarRentalContract(models.Model):
raise UserError("Some Invoices are pending")
def _invoice_count(self):
invoice_ids = self.env['account.move'].search([('invoice_origin', '=', self.name)])
invoice_ids = self.env['account.move'].search(
[('invoice_origin', '=', self.name)])
self.invoice_count = len(invoice_ids)
@api.constrains('state')
@ -181,24 +206,22 @@ class CarRentalContract(models.Model):
supplier = self.customer_id
inv_data = {
'ref': 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,
'invoice_origin': self.name,
# 'company_id': self.account_type.company_id.id,
'invoice_date_due': self.rent_end_date,
}
inv_id = inv_obj.create(inv_data)
product_id = self.env['product.product'].search([("name", "=", "Fleet Rental Service")])
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))
_('Please define income account for this product: "%s" (id:%d).') % (
product_id.name,
product_id.id))
recurring_data = {
'name': self.vehicle_id.name,
'date_today': rent_date,
@ -229,7 +252,8 @@ class CarRentalContract(models.Model):
'<tr/><tr><td>Amount <td/><td> %s<td/><tr/>'
'<tr/><tr><td>Due Date <td/><td> %s<td/><tr/>'
'<tr/><tr><td>Responsible Person <td/><td> %s, %s<td/><tr/><table/>') % \
(self.customer_id.name, self.name, inv_id.amount_total, inv_id.invoice_date_due,
(self.customer_id.name, self.name, inv_id.amount_total,
inv_id.invoice_date_due,
inv_id.user_id.name,
inv_id.user_id.mobile)
main_content = {
@ -247,7 +271,8 @@ class CarRentalContract(models.Model):
recurring_obj = self.env['fleet.rental.line']
today = date.today()
for records in self.search([]):
start_date = datetime.strptime(str(records.rent_start_date), '%Y-%m-%d').date()
start_date = datetime.strptime(str(records.rent_start_date),
'%Y-%m-%d').date()
end_date = datetime.strptime(str(records.rent_end_date), '%Y-%m-%d').date()
if end_date >= date.today():
temp = 0
@ -278,15 +303,17 @@ class CarRentalContract(models.Model):
'invoice_date_due': self.rent_end_date,
}
inv_id = inv_obj.create(inv_data)
product_id = self.env['product.product'].search([("name", "=", "Fleet Rental Service")])
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))
_('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,
@ -318,7 +345,8 @@ class CarRentalContract(models.Model):
'<tr/><tr><td>Amount <td/><td> %s<td/><tr/>'
'<tr/><tr><td>Due Date <td/><td> %s<td/><tr/>'
'<tr/><tr><td>Responsible Person <td/><td> %s, %s<td/><tr/><table/>') % \
(self.customer_id.name, self.name, inv_id.amount_total, inv_id.invoice_date_due,
(self.customer_id.name, self.name, inv_id.amount_total,
inv_id.invoice_date_due,
inv_id.user_id.name,
inv_id.user_id.mobile)
main_content = {
@ -341,9 +369,7 @@ class CarRentalContract(models.Model):
inv_line_obj = self.env['account.move.line']
supplier = self.customer_id
inv_data = {
# 'name': supplier.name,
'ref': 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,
@ -352,15 +378,17 @@ class CarRentalContract(models.Model):
'invoice_date_due': self.rent_end_date,
}
inv_id = inv_obj.create(inv_data)
product_id = self.env['product.product'].search([("name", "=", "Fleet Rental Service")])
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))
_('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,
@ -376,28 +404,14 @@ class CarRentalContract(models.Model):
list_view_id = self.env.ref('account.view_move_form', False)
form_view_id = self.env.ref('account.view_move_tree', False)
result = {
# 'domain': "[('id', '=', " + str(inv_id) + ")]",
'name': 'Fleet Rental Invoices',
'view_mode': 'form',
'res_model': 'account.move',
'type': 'ir.actions.act_window',
'views': [(list_view_id.id, 'tree'), (form_view_id.id, '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.move',
# }
if len(inv_id) > 1:
result['domain'] = "[('id','in',%s)]" % inv_id.ids
# elif len(inv_id) == 1:
# result['views'] = [(form_view_id.id, 'form')]
# result['res_id'] = inv_id.ids[0]
else:
result = {'type': 'ir.actions.act_window_close'}
return result
@ -417,28 +431,32 @@ class CarRentalContract(models.Model):
else:
check_availability = 0
if check_availability == 0:
reserved_id = self.vehicle_id.rental_reserved_time.create({'customer_id': self.customer_id.id,
'date_from': self.rent_start_date,
'date_to': self.rent_end_date,
'reserved_obj': self.vehicle_id.id
})
reserved_id = self.vehicle_id.rental_reserved_time.create(
{'customer_id': self.customer_id.id,
'date_from': self.rent_start_date,
'date_to': self.rent_end_date,
'reserved_obj': self.vehicle_id.id
})
self.write({'reserved_fleet_id': reserved_id.id})
else:
raise Warning('Sorry This vehicle is already booked by another customer')
raise UserError('Sorry This vehicle is already booked by another customer')
self.state = "reserved"
sequence_code = 'car.rental.sequence'
order_date = self.create_date
order_date = str(order_date)[0:10]
self.name = self.env['ir.sequence'] \
.with_context(ir_sequence_date=order_date).next_by_code(sequence_code)
mail_content = _('<h3>Order Confirmed!</h3><br/>Hi %s, <br/> This is to notify that your rental contract has '
'been confirmed. <br/><br/>'
'Please find the details below:<br/><br/>'
'<table><tr><td>Reference Number<td/><td> %s<td/><tr/>'
'<tr><td>Time Range <td/><td> %s to %s <td/><tr/><tr><td>Vehicle <td/><td> %s<td/><tr/>'
'<tr><td>Point Of Contact<td/><td> %s , %s<td/><tr/><table/>') % \
(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)
mail_content = _(
'<h3>Order Confirmed!</h3><br/>Hi %s, <br/> This is to notify that your rental contract has '
'been confirmed. <br/><br/>'
'Please find the details below:<br/><br/>'
'<table><tr><td>Reference Number<td/><td> %s<td/><tr/>'
'<tr><td>Time Range <td/><td> %s to %s <td/><tr/><tr><td>Vehicle <td/><td> %s<td/><tr/>'
'<tr><td>Point Of Contact<td/><td> %s , %s<td/><tr/><table/>') % \
(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),
@ -482,7 +500,6 @@ class CarRentalContract(models.Model):
'view_id': False,
'type': 'ir.actions.act_window',
'name': _('Invoice'),
# 'res_id': inv_ids
}
return value
@ -497,7 +514,8 @@ class CarRentalContract(models.Model):
if each.cost_frequency == 'monthly':
rental_days = int(rental_days / 30)
for each1 in range(0, rental_days + 1):
if rent_date > datetime.strptime(str(each.rent_end_date), "%Y-%m-%d").date():
if rent_date > datetime.strptime(str(each.rent_end_date),
"%Y-%m-%d").date():
break
each.fleet_scheduler1(rent_date)
if each.cost_frequency == 'daily':
@ -507,76 +525,74 @@ class CarRentalContract(models.Model):
if each.cost_frequency == 'monthly':
rent_date = rent_date + timedelta(days=30)
if self.first_payment != 0:
self.first_invoice_created = True
inv_obj = self.env['account.move']
inv_line_obj = self.env['account.move.line']
supplier = self.customer_id
inv_data = {
# 'name': supplier.name,
'ref': supplier.name,
'move_type': 'out_invoice',
# '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,
'invoice_origin': self.name,
'company_id': self.account_type.company_id.id,
'invoice_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))
if inv_id:
list_value = [(0, 0, {
'name': self.vehicle_id.name,
'price_unit': self.first_payment,
'quantity': 1.0,
'account_id': income_account,
'product_id': product_id.id,
'move_id': inv_id.id,
})]
inv_id.write({'invoice_line_ids': list_value})
mail_content = _(
'<h3>First Payment Received!</h3><br/>Hi %s, <br/> This is to notify that your first payment has '
'been received. <br/><br/>'
'Please find the details below:<br/><br/>'
'<table><tr><td>Invoice Number<td/><td> %s<td/><tr/>'
'<tr><td>Date<td/><td> %s <td/><tr/><tr><td>Amount <td/><td> %s<td/><tr/><table/>') % (
self.customer_id.name, inv_id.payment_reference, inv_id.invoice_date, inv_id.amount_total)
main_content = {
'subject': _('Payment Received: %s') % inv_id.payment_reference,
'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 = self.env.ref('account.action_move_out_invoice_type')
# action = imd._xmlid_lookup('account.action_move_out_invoice_type')
# action = imd._xmlid_to_res_id('account.action_move_out_invoice_type')
result = {
'name': action.name,
'type': 'ir.actions.act_window',
'views': [[False, 'form']],
'target': 'current',
'res_id': inv_id.id,
'res_model': 'account.move',
}
return result
self.first_invoice_created = True
inv_obj = self.env['account.move']
inv_line_obj = self.env['account.move.line']
supplier = self.customer_id
inv_data = {
'ref': supplier.name,
'move_type': 'out_invoice',
'partner_id': supplier.id,
'currency_id': self.account_type.company_id.currency_id.id,
'journal_id': self.journal_type.id,
'invoice_origin': self.name,
'company_id': self.account_type.company_id.id,
'invoice_date_due': self.rent_end_date,
}
inv_id = inv_obj.create(inv_data)
self.first_payment_inv = inv_id.id
fleet_rental_product_id = int(
self.env['ir.config_parameter'].sudo().get_param(
'fleet_service_product_id'))
product_id = self.env['product.template'].sudo().browse(
fleet_rental_product_id).product_variant_id
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 Warning("Please enter advance amount to make first payment")
raise UserError(
_('Please define income account for this product: "%s" (id:%d).') % (
product_id.name,
product_id.id))
if inv_id:
list_value = [(0, 0, {
'name': self.vehicle_id.name,
'price_unit': self.first_payment,
'quantity': 1.0,
'account_id': income_account,
'product_id': product_id.id,
'move_id': inv_id.id,
})]
inv_id.write({'invoice_line_ids': list_value})
mail_content = _(
'<h3>First Payment Received!</h3><br/>Hi %s, <br/> This is to notify that your first payment has '
'been received. <br/><br/>'
'Please find the details below:<br/><br/>'
'<table><tr><td>Invoice Number<td/><td> %s<td/><tr/>'
'<tr><td>Date<td/><td> %s <td/><tr/><tr><td>Amount <td/><td> %s<td/><tr/><table/>') % (
self.customer_id.name, inv_id.payment_reference,
inv_id.invoice_date, inv_id.amount_total)
main_content = {
'subject': _('Payment Received: %s') % inv_id.payment_reference,
'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 = self.env.ref('account.action_move_out_invoice_type')
result = {
'name': action.name,
'type': 'ir.actions.act_window',
'views': [[False, 'form']],
'target': 'current',
'res_id': inv_id.id,
'res_model': 'account.move',
}
return result
class FleetRentalLine(models.Model):
@ -587,7 +603,8 @@ class FleetRentalLine(models.Model):
account_info = fields.Char('Account')
recurring_amount = fields.Float('Amount')
rental_number = fields.Many2one('car.rental.contract', string='Rental Number')
payment_info = fields.Char(compute='paid_info', string='Payment Stage', default='draft')
payment_info = fields.Char(compute='paid_info', string='Payment Stage',
default='draft')
invoice_number = fields.Integer(string='Invoice ID')
invoice_ref = fields.Many2one('account.move', string='Invoice Ref')
date_due = fields.Date(string='Due Date', related='invoice_ref.invoice_date_due')
@ -595,7 +612,8 @@ class FleetRentalLine(models.Model):
def paid_info(self):
for each in self:
if self.env['account.move'].browse(each.invoice_number):
each.payment_info = self.env['account.move'].browse(each.invoice_number).state
each.payment_info = self.env['account.move'].browse(
each.invoice_number).state
else:
each.payment_info = 'Record Deleted'

11
fleet_rental/models/fleet.py

@ -3,7 +3,7 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
@ -38,7 +38,8 @@ class EmployeeFleet(models.Model):
rental_check_availability = fields.Boolean(default=True, copy=False)
color = fields.Char(string='Color', default='#FFFFFF')
rental_reserved_time = fields.One2many('rental.fleet.reserved', 'reserved_obj', string='Reserved Time', readonly=1,
rental_reserved_time = fields.One2many('rental.fleet.reserved', 'reserved_obj',
string='Reserved Time', readonly=1,
ondelete='cascade')
fuel_type = fields.Selection([('gasoline', 'Gasoline'),
('diesel', 'Diesel'),
@ -47,5 +48,7 @@ class EmployeeFleet(models.Model):
('petrol', 'Petrol')],
'Fuel Type', help='Fuel Used by the vehicle')
_sql_constraints = [('vin_sn_unique', 'unique (vin_sn)', "Chassis Number already exists !"),
('license_plate_unique', 'unique (license_plate)', "License plate already exists !")]
_sql_constraints = [
('vin_sn_unique', 'unique (vin_sn)', "Chassis Number already exists !"),
('license_plate_unique', 'unique (license_plate)',
"License plate already exists !")]

35
fleet_rental/models/res_config_settings.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
from odoo import api, fields, models
class ResConfigSettings(models.TransientModel):
"""Inherit configuration settings"""
_inherit = 'res.config.settings'
def _get_default_product(self):
return self.env.ref('fleet_rental.fleet_service_product').id
fleet_service_product_id = fields.Many2one('product.template',
string="Product",
config_parameter='fleet_service_product_id',
default=_get_default_product)

2
fleet_rental/reports/__init__.py

@ -3,7 +3,7 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO

2
fleet_rental/reports/rental_report.py

@ -3,7 +3,7 @@
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2021-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Technogies @cybrosys(odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO

19
fleet_rental/reports/rental_report.xml

@ -2,14 +2,15 @@
<odoo>
<data>
<record id="view_report_car_rental" model="ir.ui.view">
<record id="view_report_car_rental" model="ir.ui.view">
<field name="name">report.fleet.rental.pivot</field>
<field name="model">report.fleet.rental</field>
<field name="arch" type="xml">
<pivot string="Fleet Rental Analysis" display_quantity="true" disable_linking="True">
<field name="name" type="row"/>
</pivot>
</field>
<pivot string="Fleet Rental Analysis" display_quantity="true"
disable_linking="True">
<field name="name" type="row"/>
</pivot>
</field>
</record>
<record id="action_fleet_rental_analysis" model="ir.actions.act_window">
@ -17,10 +18,14 @@
<field name="res_model">report.fleet.rental</field>
<field name="view_mode">pivot</field>
<field name="context">{'group_by_no_leaf':1,'group_by':[]}</field>
<field name="help">This report allows you to analyse the performance of your Fleet Rental. </field>
<field name="help">This report allows you to analyse the performance of your
Fleet Rental.
</field>
</record>
<menuitem name="Fleet Rental Analysis" action="action_fleet_rental_analysis" id="menu_fleet_rental_analysis" parent="fleet.menu_fleet_reporting" sequence="1"/>
<menuitem name="Fleet Rental Analysis" action="action_fleet_rental_analysis"
id="menu_fleet_rental_analysis" parent="fleet.menu_fleet_reporting"
sequence="1"/>
</data>
</odoo>

BIN
fleet_rental/static/description/images/screenshot-12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

565
fleet_rental/static/description/index.html

File diff suppressed because it is too large

119
fleet_rental/views/car_rental_view.xml

@ -14,16 +14,16 @@
<data>
<record id="cron_scheduler_for_fleet" model="ir.cron">
<field name="name">Fleet scheduler</field>
<field name="model_id" ref="fleet_rental.model_car_rental_contract"/>
<field name="state">code</field>
<field name="code">model.fleet_scheduler()</field>
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="name">Fleet scheduler</field>
<field name="model_id" ref="fleet_rental.model_car_rental_contract"/>
<field name="state">code</field>
<field name="code">model.fleet_scheduler()</field>
<field name="active" eval="True"/>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
</record>
<record model="ir.ui.view" id="rental_fleet_vehicle_inherit_form_view">
@ -49,25 +49,33 @@
<form string="car_result">
<header>
<button name="action_confirm" string="Confirm" type="object"
attrs="{'invisible': [('state', '!=', 'draft')]}" class="oe_highlight"/>
attrs="{'invisible': [('state', '!=', 'draft')]}"
class="oe_highlight"/>
<button name="action_run" string="Run" type="object"
attrs="{'invisible': [('state', '!=', 'reserved')]}" class="oe_highlight"/>
attrs="{'invisible': [('state', '!=', 'reserved')]}"
class="oe_highlight"/>
<button name="action_cancel" string="Cancel" type="object"
attrs="{'invisible': [('state', 'not in', ('draft', 'reserved'))]}" class="oe_highlight"/>
attrs="{'invisible': [('state', 'not in', ('draft', 'reserved'))]}"
class="oe_highlight"/>
<button name="action_invoice_create" string="Create Invoice"
attrs="{'invisible': ['|',('state', '!=', 'running'),
('first_invoice_created','=',True)]}" type="object" class="oe_highlight"/>
('first_invoice_created','=',True)]}" type="object"
class="oe_highlight"/>
<button name="force_checking" string="Force Checking"
attrs="{'invisible': ['|',('state','!=','running'),
('first_invoice_created','=',False)]}" type="object" class="oe_highlight"/>
('first_invoice_created','=',False)]}" type="object"
class="oe_highlight"/>
<button name="set_to_done" string="Set to Done"
states="invoice" type="object" class="oe_highlight"/>
<field name="state" widget="statusbar" statusbar_visible="draft,running,done"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,running,done"/>
</header>
<sheet>
<div class="oe_button_box" name="buttons">
<button name='action_view_invoice' class="oe_stat_button" type="object" icon="fa-money">
<field string="Invoice" name="invoice_count" widget="statinfo" />
<button name='action_view_invoice' class="oe_stat_button"
type="object" icon="fa-money">
<field string="Invoice" name="invoice_count"
widget="statinfo"/>
</button>
</div>
<field name="image" widget='image' class="oe_avatar"/>
@ -77,17 +85,21 @@
</h1>
</div>
<group>
<separator string="Contract Details " colspan="4" />
<separator string="Contract Details " colspan="4"/>
<group>
<field name="customer_id" string="Customer" attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="rent_start_date" attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="rent_end_date" attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="customer_id" string="Customer"
attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="rent_start_date"
attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="rent_end_date"
attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="vehicle_id" domain="[('rental_check_availability','=',True),
('state_id.name','!=','Inactive')]"
options="{'no_create': True}"/>
options="{'no_create': True}"/>
<field name="journal_type" invisible="1"/>
<field name="check_verify" invisible="1" />
<field name="sales_person" attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="check_verify" invisible="1"/>
<field name="sales_person"
attrs="{'readonly': [('state','!=','draft')]}"/>
</group>
<group>
<field name="car_brand"/>
@ -96,25 +108,27 @@
<label for="first_payment"/>
<div>
<field name="first_payment" class="oe_inline"
attrs="{'readonly': ['|', ('state','not in',('draft', 'running')),
attrs="{'readonly': ['|', ('state','not in',('draft', 'running')),
('first_invoice_created','=',True)]}"/>
<field name="first_payment_inv" style="width:142px;" readonly="1"/>
<field name="first_payment_inv" style="width:142px;"
readonly="1"/>
</div>
<field name="account_type" invisible="1"/>
<field name="cost" invisible="1"/>
<label for="cost_generated"/>
<div>
<field name="cost_frequency" class="oe_inline"
attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="cost_generated" style="width:142px;"
attrs="{'invisible': [('cost_frequency','=','no')],
<div>
<field name="cost_frequency" class="oe_inline"
attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="cost_generated" style="width:142px;"
attrs="{'invisible': [('cost_frequency','=','no')],
'readonly': [('state','!=','draft')],
'required': [('cost_frequency','not in',[None,False,'no'])]}"/>
</div>
</div>
</group>
</group>
<notebook>
<page string="Recurring Invoices" attrs="{'invisible': [('cost_frequency','in',[None,False,'no'])]}">
<page string="Recurring Invoices"
attrs="{'invisible': [('cost_frequency','in',[None,False,'no'])]}">
<field name="recurring_line" mode="tree">
<tree string="Fleet Reccurring Lines"
colors="#0b7a35:payment_info=='paid';#f20b07:payment_info!='paid'">
@ -131,14 +145,18 @@
<page string="Checklist">
<group>
<group>
<field name="attachment_ids" widget="many2many_binary" class="oe_inline"/>
<field name="attachment_ids"
widget="many2many_binary"
class="oe_inline"/>
</group>
<group>
<field name="damage_cost" attrs="{'invisible': [('state','!=','checking')]}"/>
<field name="damage_cost"
attrs="{'invisible': [('state','!=','checking')]}"/>
</group>
</group>
<field name="checklist_line">
<tree string="Fleet Checklist Lines" editable="bottom">
<tree string="Fleet Checklist Lines"
editable="bottom">
<field name="name"/>
<field name="checklist_active"/>
<field name="checklist_number" invisible="True"/>
@ -148,8 +166,10 @@
<sheet>
<group>
<field name="name"/>
<field name="checklist_active" invisible="1"/>
<field name="checklist_number" invisible="1"/>
<field name="checklist_active"
invisible="1"/>
<field name="checklist_number"
invisible="1"/>
</group>
</sheet>
</form>
@ -159,11 +179,13 @@
<field name="total"/>
<field name="tools_missing_cost"/>
<field name="damage_cost_sub"/>
<field name="total_cost" class="oe_subtotal_footer_separator"/>
<field name="total_cost"
class="oe_subtotal_footer_separator"/>
</group>
</div>
<div style="float: right;margin-left: 78%;margin-bottom: 36px;">
<button name="action_verify" string="Verify" type="object"
<button name="action_verify" string="Verify"
type="object"
style="width: 100px !important;height: 40px;"
attrs="{'invisible': [('state', '!=', 'checking')]}"
class="oe_subtotal_footer oe_right oe_highlight"/>
@ -171,7 +193,7 @@
</page>
</notebook>
<group>
<field name="notes"/>
<field name="notes"/>
</group>
</sheet>
<div class="oe_chatter">
@ -190,10 +212,10 @@
<tree string="car_contract_result" decoration-info="state == 'draft'">
<field name="name"/>
<field name="customer_id" string="Customer"/>
<field name="vehicle_id"/>
<field name="vehicle_id"/>
<field name="cost"/>
<field name="car_brand"/>
<field name="car_color"/>
<field name="car_color"/>
<field name="rent_start_date"/>
<field name="rent_end_date"/>
<field name="state"/>
@ -207,10 +229,13 @@
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Fleet Rental" id="fleet.menu_root" sequence="115" groups="fleet.fleet_group_user"
<menuitem name="Fleet Rental" id="fleet.menu_root" sequence="115"
groups="fleet.fleet_group_user"
web_icon="fleet,static/description/icon.png"/>
<menuitem id="menu_car_parent" sequence="1" name="Rental Management" parent="fleet.menu_root"/>
<menuitem id="menu_car_rental_contract" parent="menu_car_parent" name="Rental Contract"
<menuitem id="menu_car_parent" sequence="1" name="Rental Management"
parent="fleet.menu_root"/>
<menuitem id="menu_car_rental_contract" parent="menu_car_parent"
name="Rental Contract"
action="action_car_rental_contract" sequence="1"/>
</data>
</odoo>

17
fleet_rental/views/checklist_view.xml

@ -9,8 +9,10 @@
<form string="car_checklist2" create="false">
<header>
<button name="action_verify" string="Create invoice" type="object"
attrs="{'invisible': ['|',('state','!=', 'checking'),('check_verify','=',True)]}" class="oe_highlight"/>
<field name="state" widget="statusbar" statusbar_visible="checking"/>
attrs="{'invisible': ['|',('state','!=', 'checking'),('check_verify','=',True)]}"
class="oe_highlight"/>
<field name="state" widget="statusbar"
statusbar_visible="checking"/>
</header>
<sheet>
<group>
@ -22,13 +24,15 @@
</group>
<group>
<field name="damage_cost"/>
<field name="attachment_ids" widget="many2many_binary" class="oe_inline" readonly="1"/>
<field name="attachment_ids" widget="many2many_binary"
class="oe_inline" readonly="1"/>
</group>
</group>
<notebook>
<page string="Checklist">
<field name="checklist_line">
<tree string="Fleet Checklist Lines" create="false" editable="bottom">
<tree string="Fleet Checklist Lines" create="false"
editable="bottom">
<field name="name"/>
<field name="checklist_active"/>
<field name="price"/>
@ -39,7 +43,8 @@
<field name="total"/>
<field name="tools_missing_cost"/>
<field name="damage_cost_sub"/>
<field name="total_cost" class="oe_subtotal_footer_separator"/>
<field name="total_cost"
class="oe_subtotal_footer_separator"/>
</group>
</div>
</page>
@ -70,7 +75,7 @@
<field name="view_id" ref="car_rental_contract_checklist_form_view"/>
</record>
<record id="action_fleet_rent_checklist_form" model="ir.actions.act_window.view">
<record id="action_fleet_rent_checklist_form" model="ir.actions.act_window.view">
<field eval="2" name="sequence"/>
<field name="view_mode">form</field>
<field name="view_id" ref="car_rental_contract_checklist_form_view"/>

27
fleet_rental/views/res_config_settings_views.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- Fleet settings form view inherited -->
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.fleet.rental</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="1"/>
<field name="inherit_id" ref="fleet.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='end_contract_setting']" position="inside">
<div class="col-12 col-lg-6 o_setting_box" id="discount_limit ">
<div class="o_setting_left_pane">
</div>
<div class="o_setting_right_pane">
<span class="o_form_label">Default Fleet Rental Service Product
</span>
<div class="row mt16">
<label for="fleet_service_product_id"
class="col-lg-4 o_light_label"/>
<field name="fleet_service_product_id" class="oe_inline"/>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save