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.
399 lines
20 KiB
399 lines
20 KiB
# -*- coding: utf-8 -*-
|
|
#############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
|
# Author: Afra MP (odoo@cybrosys.com)
|
|
#
|
|
# You can modify it under the terms of the GNU LESSER
|
|
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
|
|
#
|
|
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
|
|
# (LGPL v3) along with this program.
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
#############################################################################
|
|
from geopy import Nominatim
|
|
from math import cos, sin, asin, sqrt, radians
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class TruckBooking(models.Model):
|
|
"""Class to add truck_booking menu to view all truck_booking"""
|
|
_name = "truck.booking"
|
|
_inherit = 'mail.thread', 'mail.activity.mixin'
|
|
_description = "Truck Booking"
|
|
_rec_name = 'reference_no'
|
|
|
|
reference_no = fields.Char(string='Order Reference', readonly=True,
|
|
default=lambda self: _('New'), copy=False,
|
|
help='Order reference number')
|
|
partner_id = fields.Many2one('res.partner', string='Customer',
|
|
required=True, help='Customer Name')
|
|
company_id = fields.Many2one('res.company', string='Company',
|
|
default=lambda self: self.env.user.company_id.id,
|
|
help='Select the company to which this record belongs.')
|
|
from_location = fields.Char(string='Pickup City', required=True,
|
|
help='Goods source location')
|
|
to_location = fields.Char(string='Drop City', required=True,
|
|
help='Goods destination location')
|
|
distance = fields.Float(string='Distance', compute='_compute_distance',
|
|
store=True, help='Total distance to travel')
|
|
truck_id = fields.Many2one('fleet.vehicle.model', string='Truck Type',
|
|
domain=[('vehicle_type', '=', 'truck')],
|
|
required=True, help='Select the truck type')
|
|
goods_type_id = fields.Many2one('goods.type', string='Goods Type',
|
|
help='Select goods type', required=True)
|
|
weight = fields.Integer(string='Weight', help='Total weight of goods')
|
|
amount = fields.Float(string='Amount', compute='_compute_amount',
|
|
store=True,
|
|
help='Total amount is the distance travelled by the truck')
|
|
date = fields.Date(string='Date', help='Delivery date')
|
|
unit = fields.Selection(selection=[('kg', 'KG'), ('tons', 'Tons')],
|
|
string='Unit', default='kg', help='Select unit')
|
|
state = fields.Selection(selection=[('draft', 'Draft'),
|
|
('confirm', 'Confirm'),
|
|
('invoice', 'Invoiced')],
|
|
string='State', default="draft",
|
|
help="Booking State")
|
|
invoice_count = fields.Integer(string="Invoice Count",
|
|
compute='_compute_invoice_count',
|
|
help='Total invoice count')
|
|
invoiced_amount = fields.Float(string='Invoiced amount',
|
|
compute='_compute_invoiced_amount',
|
|
help='Total invoiced amount')
|
|
hide_invoice = fields.Boolean(string='Hide Invoice',
|
|
help="To hide create invoice button",
|
|
default=False)
|
|
|
|
@api.model
|
|
def create(self, vals_list):
|
|
"""Function to create sequence"""
|
|
if vals_list.get('reference_no', _('New')) == _('New'):
|
|
vals_list['reference_no'] = self.env['ir.sequence'].next_by_code(
|
|
'truck.booking') or _('New')
|
|
return super(TruckBooking, self).create(vals_list)
|
|
|
|
def action_confirm(self):
|
|
"""Function to change state to confirm"""
|
|
self.write({'state': 'confirm'})
|
|
|
|
@api.depends('from_location', 'to_location')
|
|
def _compute_distance(self):
|
|
"""Function to calculate distance between from and to location"""
|
|
for location in self:
|
|
locator = Nominatim(user_agent="myGeocoder")
|
|
from_location = locator.geocode(location.from_location)
|
|
to_location = locator.geocode(location.to_location)
|
|
if from_location is None or to_location is None:
|
|
raise ValidationError(_("Please enter valid city."))
|
|
else:
|
|
from_lat = radians(from_location.latitude)
|
|
from_long = radians(from_location.longitude)
|
|
to_lat = radians(to_location.latitude)
|
|
to_long = radians(to_location.longitude)
|
|
dist_long = to_long - from_long
|
|
dist_lat = to_lat - from_lat
|
|
comp = sin(dist_lat / 2) ** 2 + cos(from_lat) * cos(to_lat) * sin(dist_long / 2) ** 2
|
|
location.distance = int(2 * asin(sqrt(comp)) * 6371)
|
|
|
|
@api.depends('distance')
|
|
def _compute_amount(self):
|
|
"""Function to calculate amount for booking"""
|
|
for record in self:
|
|
amount = record.env['ir.config_parameter'].sudo().\
|
|
get_param('packers_and_movers_management.distance_amount')
|
|
total = float(amount) * record.distance
|
|
is_extra = record.env['ir.config_parameter'].sudo().\
|
|
get_param('packers_and_movers_management.is_extra')
|
|
if is_extra:
|
|
extra_amount = record.env['ir.config_parameter'].sudo(). \
|
|
get_param('packers_and_movers_management.extra_amount')
|
|
total *= float(extra_amount)
|
|
record.amount = total
|
|
|
|
def action_create_invoice(self):
|
|
"""Function to create invoice for the booking"""
|
|
invoice_id = self.env['account.move'].search(
|
|
[('invoice_origin', '=', self.reference_no),
|
|
('state', '=', 'draft')])
|
|
if not invoice_id:
|
|
invoice = self.env['account.move'].create([{
|
|
'move_type': 'out_invoice',
|
|
'partner_id': self.partner_id.id,
|
|
'invoice_origin': self.reference_no,
|
|
'invoice_line_ids': [(0, 0,{
|
|
'name': "{} to {}".format(self.from_location,self.to_location),
|
|
'quantity': 1,
|
|
'price_unit': self.amount - self.invoiced_amount,
|
|
'price_subtotal': self.amount})]}])
|
|
return {
|
|
'name': 'Invoice',
|
|
'view_mode': 'form',
|
|
'res_id': invoice.id,
|
|
'res_model': 'account.move',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current',
|
|
}
|
|
else:
|
|
invoice_id.write({'invoice_line_ids': [(0, 0,{
|
|
'name': "{} to {}".format(self.from_location,self.to_location),
|
|
'quantity': 1,
|
|
'price_unit': self.amount - self.invoiced_amount,
|
|
'price_subtotal': self.amount})]})
|
|
return {
|
|
'name': 'Invoice',
|
|
'view_mode': 'form',
|
|
'res_id': invoice_id.id,
|
|
'res_model': 'account.move',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current',
|
|
}
|
|
|
|
def _compute_invoice_count(self):
|
|
"""Function to count invoice"""
|
|
for record in self:
|
|
record.invoice_count = self.env['account.move'].\
|
|
search_count([('invoice_origin', '=', self.reference_no)])
|
|
|
|
def _compute_invoiced_amount(self):
|
|
"""Function to add invoiced amount"""
|
|
for record in self:
|
|
invoices = record.env['account.move'].search([
|
|
('invoice_origin', '=', record.reference_no),
|
|
('state', '!=', 'cancel')])
|
|
record.invoiced_amount = sum(invoices.mapped('amount_untaxed_signed'))
|
|
record.hide_invoice = sum(
|
|
invoices.mapped('amount_untaxed_signed')) == record.amount
|
|
|
|
def action_view_invoice(self):
|
|
"""Smart button to view the Corresponding Invoices for the truck_booking"""
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'Invoice',
|
|
'view_mode': 'tree,form',
|
|
'res_model': 'account.move',
|
|
'target': 'current',
|
|
'domain': [('invoice_origin', '=', self.reference_no)],
|
|
'context': {"create": False},
|
|
}
|
|
|
|
@api.model
|
|
def get_total_booking(self):
|
|
"""Function to get total booking, distance and invoice amount details"""
|
|
total_booking = self.env['truck.booking'].search_count([])
|
|
booking_ids = self.env['truck.booking'].search([])
|
|
invoice_ids = self.env['truck.booking'].\
|
|
search([('state', '=', 'invoice')]).mapped('amount')
|
|
return {'total_booking': total_booking,
|
|
'total_distance_count': sum(booking_ids.mapped('distance')),
|
|
'total_invoice': sum(invoice_ids),
|
|
'total_amount': sum(booking_ids.mapped('amount'))}
|
|
|
|
@api.model
|
|
def get_top_truck(self):
|
|
"""Function to return top truck and customer details query to js"""
|
|
self.env.cr.execute('''select fv.name,count(name) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
group by name order by count desc limit 10''')
|
|
truck = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select pr.name,count(name) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
group by name order by count desc limit 10''')
|
|
customer = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select tb.reference_no,pr.name,tb.date from
|
|
truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
where tb.date >= '%s' and tb.state = 'invoice'
|
|
order by tb.date''' % fields.date.today())
|
|
upcoming = self.env.cr.dictfetchall()
|
|
return {'truck': truck, 'customer': customer, 'upcoming': upcoming}
|
|
|
|
@api.model
|
|
def get_booking_analysis(self):
|
|
"""Function to return customer details to js for graph view"""
|
|
self.env.cr.execute('''select pr.name,sum(tb.amount) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
group by name''')
|
|
booking = self.env.cr.dictfetchall()
|
|
count = []
|
|
customer = []
|
|
for record in booking:
|
|
customer.append(record.get('name'))
|
|
count.append(record.get('sum'))
|
|
value = {'name': customer, 'count': count}
|
|
return value
|
|
|
|
@api.model
|
|
def get_truck_analysis(self):
|
|
"""Function to return truck details to js for graph view"""
|
|
self.env.cr.execute('''select fv.name,sum(tb.amount) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
group by name''')
|
|
booking = self.env.cr.dictfetchall()
|
|
count = []
|
|
customer = []
|
|
for record in booking:
|
|
customer.append(record.get('name'))
|
|
count.append(record.get('sum'))
|
|
return {'name': customer, 'count': count}
|
|
|
|
@api.model
|
|
def get_distance(self):
|
|
"""Function to return total distance on the basis of customer and truck"""
|
|
self.env.cr.execute('''select pr.name,sum(tb.distance) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
group by name''')
|
|
customer = self.env.cr.dictfetchall()
|
|
cust_sum = []
|
|
cust = []
|
|
for record in customer:
|
|
cust.append(record.get('name'))
|
|
cust_sum.append(record.get('sum'))
|
|
self.env.cr.execute('''select fv.name,sum(tb.distance) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
group by name''')
|
|
|
|
truck = self.env.cr.dictfetchall()
|
|
truck_sum = []
|
|
truck_name = []
|
|
for record in truck:
|
|
truck_name.append(record.get('name'))
|
|
truck_sum.append(record.get('sum'))
|
|
return {'cust': cust, 'cust_sum': cust_sum, 'truck_name': truck_name,
|
|
'truck_sum': truck_sum}
|
|
|
|
@api.model
|
|
def get_weight(self):
|
|
"""Function to get total weight of the goods"""
|
|
self.env.cr.execute('''select pr.name,sum(tb.weight) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
group by name''')
|
|
customer = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select fv.name,sum(tb.weight) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
group by name''')
|
|
truck = self.env.cr.dictfetchall()
|
|
cust_sum = []
|
|
cust = []
|
|
for record in customer:
|
|
cust.append(record.get('name'))
|
|
cust_sum.append(record.get('sum'))
|
|
truck_sum = []
|
|
truck_name = []
|
|
for record in truck:
|
|
truck_name.append(record.get('name'))
|
|
truck_sum.append(record.get('sum'))
|
|
return {'cust': cust, 'cust_sum': cust_sum, 'truck_name': truck_name,
|
|
'truck_sum': truck_sum}
|
|
|
|
@api.model
|
|
def get_select_filter(self,option):
|
|
"""Function to filter data on the bases of the year"""
|
|
if option == 'year':
|
|
create_date = '''create_date between (now() - interval '1 year') and now()'''
|
|
elif option == 'month':
|
|
create_date = '''create_date between (now() - interval '1 months') and now()'''
|
|
elif option == 'week':
|
|
create_date = '''create_date between (now() - interval '7 day') and now()'''
|
|
elif option == 'day':
|
|
create_date = '''create_date between (now() - interval '1 day') and now()'''
|
|
|
|
self.env.cr.execute('''select count(*) from truck_booking
|
|
where %s''' % create_date)
|
|
booking = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select sum(distance) from truck_booking
|
|
where %s''' % create_date)
|
|
distance = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select sum(amount) from truck_booking
|
|
where %s''' % create_date)
|
|
amount = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select sum(amount) from truck_booking
|
|
where state = 'invoice' and %s''' % create_date)
|
|
invoice = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select fv.name,count(name) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
where tb.%s
|
|
group by name
|
|
order by count desc
|
|
limit 10''' % create_date)
|
|
truck = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select pr.name,count(name) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
where tb.%s group by name
|
|
order by count desc limit 10''' % create_date)
|
|
customer = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select pr.name,sum(tb.amount) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
where tb.%s group by name''' % create_date)
|
|
cust_invoice = self.env.cr.dictfetchall()
|
|
cust_invoice_name = []
|
|
cust_invoice_sum = []
|
|
for record in cust_invoice:
|
|
cust_invoice_name.append(record.get('name'))
|
|
cust_invoice_sum.append(record.get('sum'))
|
|
self.env.cr.execute('''select fv.name,sum(tb.amount) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
where tb.%s group by name''' % create_date)
|
|
truck_invoice = self.env.cr.dictfetchall()
|
|
truck_invoice_name = []
|
|
truck_invoice_count = []
|
|
for record in truck_invoice:
|
|
truck_invoice_name.append(record.get('name'))
|
|
truck_invoice_count.append(record.get('sum'))
|
|
self.env.cr.execute('''select pr.name,sum(tb.distance) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
where tb.%s
|
|
group by name''' % create_date)
|
|
cust_distance = self.env.cr.dictfetchall()
|
|
cust_distance_name = []
|
|
cust_distance_count = []
|
|
for record in cust_distance:
|
|
cust_distance_name.append(record.get('name'))
|
|
cust_distance_count.append(record.get('sum'))
|
|
self.env.cr.execute('''select fv.name,sum(tb.distance) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
where tb.%s
|
|
group by name''' % create_date)
|
|
truck_distance = self.env.cr.dictfetchall()
|
|
truck_distance_name = []
|
|
truck_distance_count = []
|
|
for record in truck_distance:
|
|
truck_distance_name.append(record.get('name'))
|
|
truck_distance_count.append(record.get('sum'))
|
|
self.env.cr.execute('''select pr.name,sum(tb.weight) from truck_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
where tb.%s group by name''' % create_date)
|
|
cust_weight = self.env.cr.dictfetchall()
|
|
cust_weight_name = []
|
|
cust_weight_count = []
|
|
for record in cust_weight:
|
|
cust_weight_name.append(record.get('name'))
|
|
cust_weight_count.append(record.get('sum'))
|
|
self.env.cr.execute('''select fv.name,sum(tb.weight) from truck_booking as tb
|
|
inner join fleet_vehicle_model as fv on fv.id = tb.truck_id
|
|
where tb.%s group by name''' % create_date)
|
|
truck_weight = self.env.cr.dictfetchall()
|
|
truck_weight_name = []
|
|
truck_weight_count = []
|
|
for record in truck_weight:
|
|
truck_weight_name.append(record.get('name'))
|
|
truck_weight_count.append(record.get('sum'))
|
|
return {'booking': booking, 'distance': distance, 'amount': amount,
|
|
'invoice': invoice, 'truck': truck,'customer': customer,
|
|
'cust_invoice_name': cust_invoice_name, 'cust_invoice_sum':
|
|
cust_invoice_sum, 'truck_invoice_name': truck_invoice_name,
|
|
'truck_invoice_count': truck_invoice_count, 'cust_distance_name':
|
|
cust_distance_name, 'cust_distance_count': cust_distance_count,
|
|
'truck_distance_name': truck_distance_name,
|
|
'truck_distance_count': truck_distance_count,
|
|
'cust_weight_name': cust_weight_name, 'cust_weight_count':
|
|
cust_weight_count, 'truck_weight_name': truck_weight_name,
|
|
'truck_weight_count': truck_weight_count}
|
|
|