You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

361 lines
16 KiB

# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Swaraj R (<https://www.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 datetime import datetime
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class VehicleSubscription(models.Model):
"""Created new model to add new fields and function"""
_name = "fleet.subscription"
_description = "Fleet Subscription"
_inherit = "mail.thread"
_rec_name = 'vehicle_id'
vehicle_id = fields.Many2one('fleet.vehicle', string="Vehicle",
domain="[('id', 'in',vehicle_ids)]",
required=True,
help="This field help you to choose vehicle")
vehicle_ids = fields.Many2many('fleet.vehicle', string="Vehicle",
compute='_compute_vehicle_ids',
help="Returns vehicle by satisfying "
"the domain")
model_id = fields.Many2one(related="vehicle_id.model_id", string='Model',
help="This field help you to choose model "
"of vehicle")
price = fields.Float(string='Price',
help="Compute field which results the price of "
"vehicle")
uptodate_price = fields.Float(compute="_compute_uptodate_price",
string='Price',
help="Compute field which results the price "
"of vehicle until the date ")
extra_price = fields.Float(string="Extra Price",
help="Compute field which results the extra "
"price of vehicle")
start_date = fields.Date(string="Start Date", required=True,
help="Start date of subscription")
end_date = fields.Date(string="End Date", required=True,
help="End date of subscription")
cancellation_date = fields.Date(string="Cancellation Date",
default=fields.Date.today(),
help="Subscription cancellation date")
duration = fields.Integer(string="Duration", compute='_compute_duration',
help="Compute subscription duration")
cancel_duration = fields.Integer(string="Duration",
compute='_compute_cancel_duration',
help="compute cancel duration")
state = fields.Selection(
selection=[('draft', 'Draft'), ('subscribed', 'Subscribed'),
('cancel', 'Cancelled'), ('expired', 'Expired')
], string='State', default='draft',
help="States of subscription")
street = fields.Char(string="Street", help="Choose the street")
state_id = fields.Many2one("res.country.state", string='State',
ondelete='restrict',
domain="[('country_id', '=?', country_id)]",
help="Choose the state")
city = fields.Char(string="City", help="Choose the city")
country_id = fields.Many2one('res.country', string='Country',
ondelete='restrict', help="Choose the country")
fuel = fields.Selection(selection=[('with_fuel', 'With Fuel'),
('without_fuel', 'Without Fuel')],
string="Fuel Choice", default='without_fuel',
help="Help you to choose the type of fuel")
fuel_type = fields.Selection(string="Fuel Type",
related="vehicle_id.model_id.default_fuel_type"
, help="Fuel type will be given which is"
" related to the model")
fuel_rate = fields.Integer(string="Rate", default=300, help="Rate of fuel")
charge_km = fields.Integer(string="Charge in km", default=12,
help="Rate per kilometer")
default_km = fields.Float(string="Default KMS",
related='vehicle_id.free_km',
help="Default km is set based on free km of "
"vehicle which is given by authorised "
"person")
extra_km = fields.Float(string="Extra KMS", default=1,
help="As per customer he/she can choose extra km")
mileage = fields.Float(string='Mileage',
related='vehicle_id.model_id.mileage',
help="Helps to set mileage of vehicle")
sale = fields.Integer(string="sale", compute='_compute_sale',
help="Helps you to store count of sale")
invoice = fields.Integer(string="Invoice", compute='_compute_invoice',
help="Helps you to store count of invoice")
invoice_ids = fields.Many2many('account.move', string='Invoices',
help="Used to store ids of invoices")
customer_id = fields.Many2one('res.partner', string="Customer",
required=True,
help="Helps you to choose customer")
sale_id = fields.Many2one('sale.order', string='sale', readonly=True,
help="Stores id of sale order")
refund_id = fields.Many2one('account.move', string='Refund', readonly=True,
help="Stores id of invoice which belongs "
"to refund")
insurance_type_id = fields.Many2one('vehicle.insurance',
domain="[('vehicle_id', '=',"
"vehicle_id)]")
refund = fields.Integer(compute='_compute_refund',
help="Helps you to store count of refund")
seating_capacity = fields.Integer(string='Seating Capacity',
help="Seating capacity of vehicle can "
"be set")
is_invisible_sub = fields.Boolean(string="Approve Subscription",
help="As subscription request get "
"approved this will be enabled")
def _get_vehicle_domain(self):
"""This method retrieves the vehicles that meet the following
criteria"""
insurance_ids = self.env['vehicle.insurance'].search([]).mapped(
'vehicle_id')
domain = []
for record in insurance_ids:
state = record.log_services.mapped('state')
if 'done' in state and 'running' not in state and 'new' \
not in state and 'cancelled' not in state:
if not self.search(
[('vehicle_id', '=', record.id),
('state', '!=', 'subscribe')]):
domain.append(record.id)
return domain
@api.onchange('vehicle_id')
def _onchange_vehicle_id(self):
"""Function used to fill the seating capacity"""
if self.vehicle_id:
self.seating_capacity = self.vehicle_id.model_id.seats
@api.onchange('seating_capacity')
def _onchange_seating_capacity(self):
"""As the seating capacity changes vehicles are shown """
if self.seating_capacity != self.vehicle_id.model_id.seats:
self.vehicle_id = False
@api.onchange('default_km')
def _onchange_default_km(self):
"""Charge per km is set as onchange of default_km"""
if self.default_km <= self.vehicle_id.free_km:
self.charge_km = 0
@api.depends('vehicle_id', 'seating_capacity')
def _compute_vehicle_ids(self):
"""Compute the vehicle_IDS based on the vehicle and seating capacity."""
for rec in self:
if not rec.vehicle_ids:
domain = rec._get_vehicle_domain()
if rec.seating_capacity:
model_id = self.env['fleet.vehicle'].search(
[('state_id', '=', 'registered'),
('model_id.seats', '=', rec.seating_capacity),
('id', 'in', domain)])
for record in model_id:
self.vehicle_ids = [(4, record.id)]
else:
model_id = self.env['fleet.vehicle'].search(
[('id', 'in', domain)])
for record in model_id:
self.vehicle_ids = [(4, record.id)]
@api.depends('start_date', 'end_date')
def _compute_duration(self):
"""Compute duration based on start and end date"""
for record in self:
if record.end_date:
if record.end_date < record.start_date:
raise ValidationError(_(
"End date should be greater than start date."))
if record.start_date and record.end_date:
start = record.start_date.strftime("%Y-%m-%d")
end = record.end_date.strftime("%Y-%m-%d")
start_datetime = datetime.strptime(start, "%Y-%m-%d")
end_datetime = datetime.strptime(end, "%Y-%m-%d")
delta = end_datetime - start_datetime
record.duration = delta.days
else:
record.duration = 0
@api.depends('start_date', 'cancellation_date')
def _compute_cancel_duration(self):
"""Compute duration based on cancellation date"""
for record in self:
if record.start_date and record.cancellation_date:
start = record.start_date.strftime("%Y-%m-%d")
end = record.cancellation_date.strftime("%Y-%m-%d")
start_datetime = datetime.strptime(start, "%Y-%m-%d")
end_datetime = datetime.strptime(end, "%Y-%m-%d")
delta = end_datetime - start_datetime
record.cancel_duration = delta.days
else:
record.cancel_duration = 0
@api.depends('cancel_duration')
def _compute_uptodate_price(self):
"""Compute price as per the cancellation date"""
for rec in self:
rec.uptodate_price = (
(rec.sale_id.order_line.price_unit / rec.duration) * (
(rec.cancellation_date - rec.start_date).days))
def action_get_car_insurance(self):
"""Get the action to view the car
insurance associated with the subscription."""
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': 'Insurance',
'view_mode': 'form',
'res_model': 'vehicle.insurance',
'res_id': self.insurance_type_id.id,
'context': [('create', '=', False)]
}
def action_get_sale(self):
"""Get the action to view the sale
associated with the subscription."""
return {
'type': 'ir.actions.act_window',
'name': 'Sale Order',
'view_mode': 'form',
'res_model': 'sale.order',
'res_id': self.sale_id.id,
'context': [('create', '=', False)]
}
def _compute_sale(self):
"""Used to calculate the sale count"""
for record in self:
record.sale = self.env['sale.order'].search_count(
[('id', '=', self.sale_id.id)])
def action_get_refund(self):
"""Get the action to view the refund
associated with the subscription."""
return {
'type': 'ir.actions.act_window',
'name': 'Refund',
'view_mode': 'form',
'res_id': self.refund_id.id,
'res_model': 'account.move',
'context': [('create', '=', False)]
}
def _compute_refund(self):
"""Used to calculate count of refund"""
for record in self:
record.refund = self.env['account.move'].search_count(
[('id', '=', self.refund_id.id)])
def action_get_invoice(self):
"""Get the action to view the invoice
associated with the subscription."""
invoice_ids = self.invoice_ids + self.sale_id.invoice_ids
return {
'type': 'ir.actions.act_window',
'name': 'Sale Order',
'view_mode': 'tree,form',
'res_model': 'account.move',
'domain': [('id', 'in', invoice_ids.ids)],
'context': [('create', '=', False)]
}
def _compute_invoice(self):
"""Used to calculate invoice count"""
for record in self:
invoice_ids = record.invoice_ids + record.sale_id.invoice_ids
record.invoice = self.env['account.move'].search_count(
[('id', 'in', invoice_ids.ids)])
def action_invoice(self):
"""Used to generate invoice on clicking the button"""
self.write({'state': 'subscribed'})
product_template_id = self.env.ref(
'vehicle_subscription.product_template_vehicle_subscription_form').id
product_id = self.env['product.product'].search(
[('product_tmpl_id', '=', product_template_id)])
sale_order_id = self.env['sale.order'].create({
'partner_id': self.customer_id.id,
})
line = self.env["sale.order.line"].create({
'product_id': product_id.id,
'product_uom_qty': 1,
'price_unit': self.price,
'order_id': sale_order_id.id
})
self.sale_id = sale_order_id
def action_request(self):
"""Request for change subscription is generated """
return {
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'change.subscription',
'target': 'new',
}
def action_cancel(self):
"""Proceed with cancellation of subscription"""
product_template_id = self.env.ref(
'vehicle_subscription.product_template_vehicle_subscription_form').id
product_id = self.env['product.product'].search(
[('product_tmpl_id', '=', product_template_id)])
invoice = self.env['account.move'].search(
[('id', 'in', self.invoice_ids.ids),
('payment_state', 'in', ['paid', 'partial'])]).mapped(
'amount_untaxed_signed')
invoiced_amount = sum(invoice)
total_price = self.uptodate_price
if invoiced_amount == total_price:
self.write({'state': 'cancel'})
self.sale_id.action_done()
elif invoiced_amount > total_price:
self.write({'state': 'cancel'})
self.refund_id = self.env['account.move'].create({
'move_type': 'out_refund',
'invoice_date': fields.Date.today(),
'partner_id': self.customer_id.id,
'invoice_line_ids': [(0, 0, {
'product_id': product_id.id,
'name': self.vehicle_id.name,
'price_unit': self.uptodate_price,
})]
})
else:
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Warning'),
'message': 'you need to pay amount till date inorder to '
'cancel subscription',
'sticky': True,
}
}
@api.onchange('end_date')
def _onchange_end_date(self):
"""Check expiry for subscription"""
if self.end_date:
if self.end_date < fields.Date.today():
self.write({'state': 'expired'})
self.sale_id.action_done()