2012-10-23 13:46:54 +00:00
# -*- coding: utf-8 -*-
2012-10-31 14:28:30 +00:00
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# 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 for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
2012-09-26 14:13:52 +00:00
import time
2012-10-01 15:23:04 +00:00
import datetime
2012-12-06 14:56:32 +00:00
from openerp import tools
from openerp . osv . orm import except_orm
from openerp . tools . translate import _
2012-10-23 17:25:36 +00:00
from dateutil . relativedelta import relativedelta
2012-11-05 17:41:10 +00:00
2012-11-08 11:56:58 +00:00
def str_to_datetime ( strdate ) :
2012-11-05 17:41:10 +00:00
return datetime . datetime . strptime ( strdate , tools . DEFAULT_SERVER_DATE_FORMAT )
2012-09-26 14:13:52 +00:00
2012-10-03 08:57:02 +00:00
class fleet_vehicle_cost ( osv . Model ) :
_name = ' fleet.vehicle.cost '
2012-11-05 17:41:10 +00:00
_description = ' Cost related to a vehicle '
2012-10-04 15:07:01 +00:00
_order = ' date desc, vehicle_id asc '
2012-11-05 17:41:10 +00:00
def _get_odometer ( self , cr , uid , ids , odometer_id , arg , context ) :
res = dict . fromkeys ( ids , False )
for record in self . browse ( cr , uid , ids , context = context ) :
if record . odometer_id :
res [ record . id ] = record . odometer_id . value
2012-10-04 15:07:01 +00:00
return res
2012-11-05 17:41:10 +00:00
def _set_odometer ( self , cr , uid , id , name , value , args = None , context = None ) :
if not value :
raise except_orm ( _ ( ' Operation not allowed! ' ) , _ ( ' Emptying the odometer value of a vehicle is not allowed. ' ) )
date = self . browse ( cr , uid , id , context = context ) . date
if not ( date ) :
date = fields . date . context_today ( self , cr , uid , context = context )
vehicle_id = self . browse ( cr , uid , id , context = context ) . vehicle_id
data = { ' value ' : value , ' date ' : date , ' vehicle_id ' : vehicle_id . id }
odometer_id = self . pool . get ( ' fleet.vehicle.odometer ' ) . create ( cr , uid , data , context = context )
return self . write ( cr , uid , id , { ' odometer_id ' : odometer_id } , context = context )
2012-10-29 12:13:54 +00:00
2012-10-03 08:57:02 +00:00
_columns = {
2014-02-17 13:39:30 +00:00
' name ' : fields . related ( ' vehicle_id ' , ' name ' , type = " char " , string = ' Name ' , store = True ) ,
2012-11-05 17:41:10 +00:00
' vehicle_id ' : fields . many2one ( ' fleet.vehicle ' , ' Vehicle ' , required = True , help = ' Vehicle concerned by this log ' ) ,
2012-12-06 10:50:33 +00:00
' cost_subtype_id ' : fields . many2one ( ' fleet.service.type ' , ' Type ' , help = ' Cost type purchased with this cost ' ) ,
2013-03-25 06:25:07 +00:00
' amount ' : fields . float ( ' Total Price ' ) ,
2012-11-05 17:41:10 +00:00
' cost_type ' : fields . selection ( [ ( ' contract ' , ' Contract ' ) , ( ' services ' , ' Services ' ) , ( ' fuel ' , ' Fuel ' ) , ( ' other ' , ' Other ' ) ] , ' Category of the cost ' , help = ' For internal purpose only ' , required = True ) ,
' parent_id ' : fields . many2one ( ' fleet.vehicle.cost ' , ' Parent ' , help = ' Parent cost to this current cost ' ) ,
' cost_ids ' : fields . one2many ( ' fleet.vehicle.cost ' , ' parent_id ' , ' Included Services ' ) ,
' odometer_id ' : fields . many2one ( ' fleet.vehicle.odometer ' , ' Odometer ' , help = ' Odometer measure of the vehicle at the moment of this log ' ) ,
' odometer ' : fields . function ( _get_odometer , fnct_inv = _set_odometer , type = ' float ' , string = ' Odometer Value ' , help = ' Odometer measure of the vehicle at the moment of this log ' ) ,
' odometer_unit ' : fields . related ( ' vehicle_id ' , ' odometer_unit ' , type = " char " , string = " Unit " , readonly = True ) ,
2012-10-19 13:18:54 +00:00
' date ' : fields . date ( ' Date ' , help = ' Date when the cost has been executed ' ) ,
2012-11-05 17:41:10 +00:00
' contract_id ' : fields . many2one ( ' fleet.vehicle.log.contract ' , ' Contract ' , help = ' Contract attached to this cost ' ) ,
2012-11-08 08:21:56 +00:00
' auto_generated ' : fields . boolean ( ' Automatically Generated ' , readonly = True , required = True ) ,
2012-10-03 08:57:02 +00:00
}
2012-10-05 08:29:15 +00:00
2012-10-25 09:51:29 +00:00
_defaults = {
2012-11-05 17:41:10 +00:00
' cost_type ' : ' other ' ,
2012-10-05 10:09:20 +00:00
}
2012-10-04 09:17:53 +00:00
def create ( self , cr , uid , data , context = None ) :
2012-11-08 11:56:58 +00:00
#make sure that the data are consistent with values of parent and contract records given
2012-10-05 09:58:18 +00:00
if ' parent_id ' in data and data [ ' parent_id ' ] :
2012-10-24 15:56:02 +00:00
parent = self . browse ( cr , uid , data [ ' parent_id ' ] , context = context )
data [ ' vehicle_id ' ] = parent . vehicle_id . id
data [ ' date ' ] = parent . date
2012-10-25 08:15:08 +00:00
data [ ' cost_type ' ] = parent . cost_type
2012-10-23 07:53:28 +00:00
if ' contract_id ' in data and data [ ' contract_id ' ] :
2012-10-24 15:56:02 +00:00
contract = self . pool . get ( ' fleet.vehicle.log.contract ' ) . browse ( cr , uid , data [ ' contract_id ' ] , context = context )
data [ ' vehicle_id ' ] = contract . vehicle_id . id
2012-12-06 10:50:33 +00:00
data [ ' cost_subtype_id ' ] = contract . cost_subtype_id . id
2012-10-25 08:15:08 +00:00
data [ ' cost_type ' ] = contract . cost_type
2012-11-07 15:17:26 +00:00
if ' odometer ' in data and not data [ ' odometer ' ] :
2012-11-08 11:56:58 +00:00
#if received value for odometer is 0, then remove it from the data as it would result to the creation of a
#odometer log with 0, which is to be avoided
2012-11-07 15:17:26 +00:00
del ( data [ ' odometer ' ] )
2012-11-05 17:41:10 +00:00
return super ( fleet_vehicle_cost , self ) . create ( cr , uid , data , context = context )
2012-10-03 08:57:02 +00:00
2012-09-27 08:09:12 +00:00
class fleet_vehicle_tag ( osv . Model ) :
_name = ' fleet.vehicle.tag '
_columns = {
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
}
2012-09-27 13:24:50 +00:00
class fleet_vehicle_state ( osv . Model ) :
_name = ' fleet.vehicle.state '
2012-11-05 17:41:10 +00:00
_order = ' sequence asc '
2012-09-27 13:24:50 +00:00
_columns = {
' name ' : fields . char ( ' Name ' , required = True ) ,
2012-12-19 07:04:15 +00:00
' sequence ' : fields . integer ( ' Sequence ' , help = " Used to order the note stages " )
2012-09-27 13:24:50 +00:00
}
2012-11-05 17:41:10 +00:00
_sql_constraints = [ ( ' fleet_state_name_unique ' , ' unique(name) ' , ' State name already exists ' ) ]
2012-10-18 15:20:05 +00:00
2012-09-27 13:24:50 +00:00
2012-09-19 16:13:27 +00:00
class fleet_vehicle_model ( osv . Model ) :
2012-09-21 09:57:15 +00:00
2012-11-05 17:41:10 +00:00
def _model_name_get_fnc ( self , cr , uid , ids , field_name , arg , context = None ) :
res = { }
for record in self . browse ( cr , uid , ids , context = context ) :
2012-09-21 15:42:44 +00:00
name = record . modelname
2012-12-06 10:50:33 +00:00
if record . brand_id . name :
name = record . brand_id . name + ' / ' + name
2012-11-05 17:41:10 +00:00
res [ record . id ] = name
2012-09-21 15:42:44 +00:00
return res
2012-09-28 11:42:10 +00:00
def on_change_brand ( self , cr , uid , ids , model_id , context = None ) :
if not model_id :
2012-11-05 17:41:10 +00:00
return { ' value ' : { ' image_medium ' : False } }
2012-09-28 11:42:10 +00:00
brand = self . pool . get ( ' fleet.vehicle.model.brand ' ) . browse ( cr , uid , model_id , context = context )
return {
2012-11-05 17:41:10 +00:00
' value ' : {
' image_medium ' : brand . image ,
2012-09-28 11:42:10 +00:00
}
}
2012-09-19 16:13:27 +00:00
_name = ' fleet.vehicle.model '
2012-09-20 15:21:21 +00:00
_description = ' Model of a vehicle '
2012-10-29 14:08:57 +00:00
_order = ' name asc '
2012-09-19 16:13:27 +00:00
_columns = {
2012-11-05 17:41:10 +00:00
' name ' : fields . function ( _model_name_get_fnc , type = " char " , string = ' Name ' , store = True ) ,
2014-05-21 09:52:05 +00:00
' modelname ' : fields . char ( ' Model name ' , required = True ) ,
2012-12-06 10:50:33 +00:00
' brand_id ' : fields . many2one ( ' fleet.vehicle.model.brand ' , ' Model Brand ' , required = True , help = ' Brand of the vehicle ' ) ,
2012-11-05 17:41:10 +00:00
' vendors ' : fields . many2many ( ' res.partner ' , ' fleet_vehicle_model_vendors ' , ' model_id ' , ' partner_id ' , string = ' Vendors ' ) ,
2012-12-06 10:50:33 +00:00
' image ' : fields . related ( ' brand_id ' , ' image ' , type = " binary " , string = " Logo " ) ,
2013-11-25 09:37:41 +00:00
' image_medium ' : fields . related ( ' brand_id ' , ' image_medium ' , type = " binary " , string = " Logo (medium) " ) ,
' image_small ' : fields . related ( ' brand_id ' , ' image_small ' , type = " binary " , string = " Logo (small) " ) ,
2012-09-19 16:13:27 +00:00
}
2012-10-03 14:57:57 +00:00
2012-09-20 13:11:32 +00:00
class fleet_vehicle_model_brand ( osv . Model ) :
_name = ' fleet.vehicle.model.brand '
_description = ' Brand model of the vehicle '
2012-09-28 14:00:36 +00:00
2012-10-01 15:41:30 +00:00
_order = ' name asc '
2012-09-28 14:00:36 +00:00
def _get_image ( self , cr , uid , ids , name , args , context = None ) :
result = dict . fromkeys ( ids , False )
for obj in self . browse ( cr , uid , ids , context = context ) :
result [ obj . id ] = tools . image_get_resized_images ( obj . image )
return result
2012-11-05 17:41:10 +00:00
2012-09-28 14:00:36 +00:00
def _set_image ( self , cr , uid , id , name , value , args , context = None ) :
return self . write ( cr , uid , [ id ] , { ' image ' : tools . image_resize_image_big ( value ) } , context = context )
2012-09-20 13:11:32 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Brand Name ' , required = True ) ,
2012-09-28 14:00:36 +00:00
' image ' : fields . binary ( " Logo " ,
help = " This field holds the image used as logo for the brand, limited to 1024x1024px. " ) ,
' image_medium ' : fields . function ( _get_image , fnct_inv = _set_image ,
string = " Medium-sized photo " , type = " binary " , multi = " _get_image " ,
store = {
2012-10-01 15:25:29 +00:00
' fleet.vehicle.model.brand ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' image ' ] , 10 ) ,
2012-09-28 14:00:36 +00:00
} ,
help = " Medium-sized logo of the brand. It is automatically " \
" resized as a 128x128px image, with aspect ratio preserved. " \
" Use this field in form views or some kanban views. " ) ,
' image_small ' : fields . function ( _get_image , fnct_inv = _set_image ,
string = " Smal-sized photo " , type = " binary " , multi = " _get_image " ,
store = {
2012-10-01 15:25:29 +00:00
' fleet.vehicle.model.brand ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' image ' ] , 10 ) ,
2012-09-28 14:00:36 +00:00
} ,
help = " Small-sized photo of the brand. It is automatically " \
" resized as a 64x64px image, with aspect ratio preserved. " \
" Use this field anywhere a small image is required. " ) ,
2012-09-20 13:11:32 +00:00
}
2012-10-03 14:57:57 +00:00
2012-09-19 16:13:27 +00:00
class fleet_vehicle ( osv . Model ) :
2012-09-24 09:07:05 +00:00
2012-09-24 11:57:39 +00:00
_inherit = ' mail.thread '
2012-09-24 09:07:05 +00:00
def _vehicle_name_get_fnc ( self , cr , uid , ids , prop , unknow_none , context = None ) :
2012-11-05 17:41:10 +00:00
res = { }
for record in self . browse ( cr , uid , ids , context = context ) :
2012-12-06 10:50:33 +00:00
res [ record . id ] = record . model_id . brand_id . name + ' / ' + record . model_id . modelname + ' / ' + record . license_plate
2012-11-05 17:41:10 +00:00
return res
2012-09-24 09:07:05 +00:00
2012-11-07 11:07:57 +00:00
def return_action_to_open ( self , cr , uid , ids , context = None ) :
""" This opens the xml view specified in xml_id for the current vehicle """
2012-11-08 08:21:56 +00:00
if context is None :
2012-11-08 08:58:28 +00:00
context = { }
2012-11-08 08:21:56 +00:00
if context . get ( ' xml_id ' ) :
2012-11-07 11:07:57 +00:00
res = self . pool . get ( ' ir.actions.act_window ' ) . for_xml_id ( cr , uid , ' fleet ' , context [ ' xml_id ' ] , context = context )
2012-11-08 08:58:28 +00:00
res [ ' context ' ] = context
2012-11-08 08:21:56 +00:00
res [ ' context ' ] . update ( { ' default_vehicle_id ' : ids [ 0 ] } )
res [ ' domain ' ] = [ ( ' vehicle_id ' , ' = ' , ids [ 0 ] ) ]
2012-11-07 11:07:57 +00:00
return res
2012-11-08 08:21:56 +00:00
return False
2012-09-27 07:57:26 +00:00
2012-10-19 09:22:35 +00:00
def act_show_log_cost ( self , cr , uid , ids , context = None ) :
2012-11-07 11:07:57 +00:00
""" This opens log view to view and add new log for this vehicle, groupby default to only show effective costs
2012-10-19 09:22:35 +00:00
@return : the costs log view
"""
2012-11-08 08:58:28 +00:00
if context is None :
context = { }
2012-11-08 08:21:56 +00:00
res = self . pool . get ( ' ir.actions.act_window ' ) . for_xml_id ( cr , uid , ' fleet ' , ' fleet_vehicle_costs_act ' , context = context )
2012-11-08 08:58:28 +00:00
res [ ' context ' ] = context
2012-11-08 08:21:56 +00:00
res [ ' context ' ] . update ( {
2012-10-24 12:17:19 +00:00
' default_vehicle_id ' : ids [ 0 ] ,
2012-11-08 08:21:56 +00:00
' search_default_parent_false ' : True
} )
res [ ' domain ' ] = [ ( ' vehicle_id ' , ' = ' , ids [ 0 ] ) ]
2012-10-19 09:22:35 +00:00
return res
2012-10-05 14:35:59 +00:00
def _get_odometer ( self , cr , uid , ids , odometer_id , arg , context ) :
2012-11-05 17:41:10 +00:00
res = dict . fromkeys ( ids , 0 )
for record in self . browse ( cr , uid , ids , context = context ) :
ids = self . pool . get ( ' fleet.vehicle.odometer ' ) . search ( cr , uid , [ ( ' vehicle_id ' , ' = ' , record . id ) ] , limit = 1 , order = ' value desc ' )
2012-10-05 14:35:59 +00:00
if len ( ids ) > 0 :
2012-11-05 17:41:10 +00:00
res [ record . id ] = self . pool . get ( ' fleet.vehicle.odometer ' ) . browse ( cr , uid , ids [ 0 ] , context = context ) . value
2012-09-28 10:22:11 +00:00
return res
2012-10-05 14:35:59 +00:00
def _set_odometer ( self , cr , uid , id , name , value , args = None , context = None ) :
if value :
2012-11-05 17:41:10 +00:00
date = fields . date . context_today ( self , cr , uid , context = context )
data = { ' value ' : value , ' date ' : date , ' vehicle_id ' : id }
return self . pool . get ( ' fleet.vehicle.odometer ' ) . create ( cr , uid , data , context = context )
2012-10-19 13:18:54 +00:00
def _search_get_overdue_contract_reminder ( self , cr , uid , obj , name , args , context ) :
res = [ ]
for field , operator , value in args :
2012-11-08 11:56:58 +00:00
assert operator in ( ' = ' , ' != ' , ' <> ' ) and value in ( True , False ) , ' Operation not supported '
if ( operator == ' = ' and value == True ) or ( operator in ( ' <> ' , ' != ' ) and value == False ) :
search_operator = ' in '
else :
search_operator = ' not in '
2012-11-07 16:19:32 +00:00
today = fields . date . context_today ( self , cr , uid , context = context )
cr . execute ( ' select cost.vehicle_id, count(contract.id) as contract_number FROM fleet_vehicle_cost cost left join fleet_vehicle_log_contract contract on contract.cost_id = cost.id WHERE contract.expiration_date is not null AND contract.expiration_date < %s AND contract.state IN ( \' open \' , \' toclose \' ) GROUP BY cost.vehicle_id ' , ( today , ) )
res_ids = [ x [ 0 ] for x in cr . fetchall ( ) ]
2012-11-08 11:56:58 +00:00
res . append ( ( ' id ' , search_operator , res_ids ) )
2012-10-19 13:18:54 +00:00
return res
2012-11-08 08:21:56 +00:00
2012-10-19 13:18:54 +00:00
def _search_contract_renewal_due_soon ( self , cr , uid , obj , name , args , context ) :
res = [ ]
for field , operator , value in args :
2012-11-08 11:56:58 +00:00
assert operator in ( ' = ' , ' != ' , ' <> ' ) and value in ( True , False ) , ' Operation not supported '
if ( operator == ' = ' and value == True ) or ( operator in ( ' <> ' , ' != ' ) and value == False ) :
search_operator = ' in '
else :
search_operator = ' not in '
2012-11-07 16:19:32 +00:00
today = fields . date . context_today ( self , cr , uid , context = context )
datetime_today = datetime . datetime . strptime ( today , tools . DEFAULT_SERVER_DATE_FORMAT )
limit_date = str ( ( datetime_today + relativedelta ( days = + 15 ) ) . strftime ( tools . DEFAULT_SERVER_DATE_FORMAT ) )
cr . execute ( ' select cost.vehicle_id, count(contract.id) as contract_number FROM fleet_vehicle_cost cost left join fleet_vehicle_log_contract contract on contract.cost_id = cost.id WHERE contract.expiration_date is not null AND contract.expiration_date > %s AND contract.expiration_date < %s AND contract.state IN ( \' open \' , \' toclose \' ) GROUP BY cost.vehicle_id ' , ( today , limit_date ) )
res_ids = [ x [ 0 ] for x in cr . fetchall ( ) ]
2012-11-08 13:11:32 +00:00
res . append ( ( ' id ' , search_operator , res_ids ) )
2012-10-19 13:18:54 +00:00
return res
2012-11-08 08:21:56 +00:00
def _get_contract_reminder_fnc ( self , cr , uid , ids , field_names , unknow_none , context = None ) :
2012-11-07 11:07:57 +00:00
res = { }
2012-11-05 17:41:10 +00:00
for record in self . browse ( cr , uid , ids , context = context ) :
2012-11-08 09:10:21 +00:00
overdue = False
due_soon = False
2012-11-08 10:03:16 +00:00
total = 0
2012-11-07 11:07:57 +00:00
name = ' '
2012-11-05 17:41:10 +00:00
for element in record . log_contracts :
2012-11-08 08:21:56 +00:00
if element . state in ( ' open ' , ' toclose ' ) and element . expiration_date :
2012-11-07 11:07:57 +00:00
current_date_str = fields . date . context_today ( self , cr , uid , context = context )
due_time_str = element . expiration_date
2012-11-08 11:56:58 +00:00
current_date = str_to_datetime ( current_date_str )
due_time = str_to_datetime ( due_time_str )
2012-11-07 11:07:57 +00:00
diff_time = ( due_time - current_date ) . days
if diff_time < 0 :
2012-11-08 09:10:21 +00:00
overdue = True
2012-11-08 11:56:58 +00:00
total + = 1
if diff_time < 15 and diff_time > = 0 :
2012-11-08 09:10:21 +00:00
due_soon = True ;
2012-11-08 11:56:58 +00:00
total + = 1
2012-11-08 09:10:21 +00:00
if overdue or due_soon :
2012-11-08 08:21:56 +00:00
ids = self . pool . get ( ' fleet.vehicle.log.contract ' ) . search ( cr , uid , [ ( ' vehicle_id ' , ' = ' , record . id ) , ( ' state ' , ' in ' , ( ' open ' , ' toclose ' ) ) ] , limit = 1 , order = ' expiration_date asc ' )
2012-11-08 09:10:21 +00:00
if len ( ids ) > 0 :
2012-11-08 08:21:56 +00:00
#we display only the name of the oldest overdue/due soon contract
2012-12-06 10:50:33 +00:00
name = ( self . pool . get ( ' fleet.vehicle.log.contract ' ) . browse ( cr , uid , ids [ 0 ] , context = context ) . cost_subtype_id . name )
2012-11-07 11:07:57 +00:00
res [ record . id ] = {
2012-11-08 08:21:56 +00:00
' contract_renewal_overdue ' : overdue ,
' contract_renewal_due_soon ' : due_soon ,
2012-11-08 10:03:16 +00:00
' contract_renewal_total ' : ( total - 1 ) , #we remove 1 from the real total for display purposes
2012-11-08 08:21:56 +00:00
' contract_renewal_name ' : name ,
2012-11-07 11:07:57 +00:00
}
2012-11-05 17:41:10 +00:00
return res
2012-10-22 08:18:33 +00:00
2012-10-25 11:58:30 +00:00
def _get_default_state ( self , cr , uid , context ) :
try :
model , model_id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( cr , uid , ' fleet ' , ' vehicle_state_active ' )
except ValueError :
model_id = False
return model_id
2014-03-26 12:20:23 +00:00
def _count_all ( self , cr , uid , ids , field_name , arg , context = None ) :
2014-05-07 07:56:45 +00:00
Odometer = self . pool [ ' fleet.vehicle.odometer ' ]
LogFuel = self . pool [ ' fleet.vehicle.log.fuel ' ]
LogService = self . pool [ ' fleet.vehicle.log.services ' ]
LogContract = self . pool [ ' fleet.vehicle.log.contract ' ]
Cost = self . pool [ ' fleet.vehicle.cost ' ]
return {
vehicle_id : {
' odometer_count ' : Odometer . search_count ( cr , uid , [ ( ' vehicle_id ' , ' = ' , vehicle_id ) ] , context = context ) ,
' fuel_logs_count ' : LogFuel . search_count ( cr , uid , [ ( ' vehicle_id ' , ' = ' , vehicle_id ) ] , context = context ) ,
' service_count ' : LogService . search_count ( cr , uid , [ ( ' vehicle_id ' , ' = ' , vehicle_id ) ] , context = context ) ,
' contract_count ' : LogContract . search_count ( cr , uid , [ ( ' vehicle_id ' , ' = ' , vehicle_id ) ] , context = context ) ,
' cost_count ' : Cost . search_count ( cr , uid , [ ( ' vehicle_id ' , ' = ' , vehicle_id ) , ( ' parent_id ' , ' = ' , False ) ] , context = context )
}
for vehicle_id in ids
}
2012-10-25 11:58:30 +00:00
2012-09-19 16:13:27 +00:00
_name = ' fleet.vehicle '
2012-11-07 11:07:57 +00:00
_description = ' Information on a vehicle '
2012-10-18 15:20:05 +00:00
_order = ' license_plate asc '
2012-09-19 16:13:27 +00:00
_columns = {
2012-11-05 17:41:10 +00:00
' name ' : fields . function ( _vehicle_name_get_fnc , type = " char " , string = ' Name ' , store = True ) ,
2012-09-27 08:00:59 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' ) ,
2014-05-21 09:52:05 +00:00
' license_plate ' : fields . char ( ' License Plate ' , required = True , help = ' License plate number of the vehicle (ie: plate number for a car) ' ) ,
2014-07-06 14:44:26 +00:00
' vin_sn ' : fields . char ( ' Chassis Number ' , help = ' Unique number written on the vehicle motor (VIN/SN number) ' , copy = False ) ,
2012-12-10 09:15:02 +00:00
' driver_id ' : fields . many2one ( ' res.partner ' , ' Driver ' , help = ' Driver of the vehicle ' ) ,
' model_id ' : fields . many2one ( ' fleet.vehicle.model ' , ' Model ' , required = True , help = ' Model of the vehicle ' ) ,
' log_fuel ' : fields . one2many ( ' fleet.vehicle.log.fuel ' , ' vehicle_id ' , ' Fuel Logs ' ) ,
2012-11-05 17:41:10 +00:00
' log_services ' : fields . one2many ( ' fleet.vehicle.log.services ' , ' vehicle_id ' , ' Services Logs ' ) ,
' log_contracts ' : fields . one2many ( ' fleet.vehicle.log.contract ' , ' vehicle_id ' , ' Contracts ' ) ,
2014-03-26 12:20:23 +00:00
' cost_count ' : fields . function ( _count_all , type = ' integer ' , string = " Costs " , multi = True ) ,
' contract_count ' : fields . function ( _count_all , type = ' integer ' , string = ' Contracts ' , multi = True ) ,
' service_count ' : fields . function ( _count_all , type = ' integer ' , string = ' Services ' , multi = True ) ,
' fuel_logs_count ' : fields . function ( _count_all , type = ' integer ' , string = ' Fuel Logs ' , multi = True ) ,
' odometer_count ' : fields . function ( _count_all , type = ' integer ' , string = ' Odometer ' , multi = True ) ,
2012-11-05 17:41:10 +00:00
' acquisition_date ' : fields . date ( ' Acquisition Date ' , required = False , help = ' Date when the vehicle has been bought ' ) ,
2014-05-21 09:52:05 +00:00
' color ' : fields . char ( ' Color ' , help = ' Color of the vehicle ' ) ,
2012-12-06 10:50:33 +00:00
' state_id ' : fields . many2one ( ' fleet.vehicle.state ' , ' State ' , help = ' Current state of the vehicle ' , ondelete = " set null " ) ,
2014-05-21 09:52:05 +00:00
' location ' : fields . char ( ' Location ' , help = ' Location of the vehicle (garage, ...) ' ) ,
2012-11-05 17:41:10 +00:00
' seats ' : fields . integer ( ' Seats Number ' , help = ' Number of seats of the vehicle ' ) ,
' doors ' : fields . integer ( ' Doors Number ' , help = ' Number of doors of the vehicle ' ) ,
2014-07-06 14:44:26 +00:00
' tag_ids ' : fields . many2many ( ' fleet.vehicle.tag ' , ' fleet_vehicle_vehicle_tag_rel ' , ' vehicle_tag_id ' , ' tag_id ' , ' Tags ' , copy = False ) ,
2012-11-09 13:06:03 +00:00
' odometer ' : fields . function ( _get_odometer , fnct_inv = _set_odometer , type = ' float ' , string = ' Last Odometer ' , help = ' Odometer measure of the vehicle at the moment of this log ' ) ,
2012-10-18 15:20:05 +00:00
' odometer_unit ' : fields . selection ( [ ( ' kilometers ' , ' Kilometers ' ) , ( ' miles ' , ' Miles ' ) ] , ' Odometer Unit ' , help = ' Unit of the odometer ' , required = True ) ,
2012-11-05 17:41:10 +00:00
' transmission ' : fields . selection ( [ ( ' manual ' , ' Manual ' ) , ( ' automatic ' , ' Automatic ' ) ] , ' Transmission ' , help = ' Transmission Used by the vehicle ' ) ,
' fuel_type ' : fields . selection ( [ ( ' gasoline ' , ' Gasoline ' ) , ( ' diesel ' , ' Diesel ' ) , ( ' electric ' , ' Electric ' ) , ( ' hybrid ' , ' Hybrid ' ) ] , ' Fuel Type ' , help = ' Fuel Used by the vehicle ' ) ,
' horsepower ' : fields . integer ( ' Horsepower ' ) ,
2012-09-21 14:34:15 +00:00
' horsepower_tax ' : fields . float ( ' Horsepower Taxation ' ) ,
2013-03-18 11:12:02 +00:00
' power ' : fields . integer ( ' Power ' , help = ' Power in kW of the vehicle ' ) ,
2012-11-05 17:41:10 +00:00
' co2 ' : fields . float ( ' CO2 Emissions ' , help = ' CO2 emissions of the vehicle ' ) ,
' image ' : fields . related ( ' model_id ' , ' image ' , type = " binary " , string = " Logo " ) ,
2013-11-25 09:37:41 +00:00
' image_medium ' : fields . related ( ' model_id ' , ' image_medium ' , type = " binary " , string = " Logo (medium) " ) ,
' image_small ' : fields . related ( ' model_id ' , ' image_small ' , type = " binary " , string = " Logo (small) " ) ,
2012-11-08 11:56:58 +00:00
' contract_renewal_due_soon ' : fields . function ( _get_contract_reminder_fnc , fnct_search = _search_contract_renewal_due_soon , type = " boolean " , string = ' Has Contracts to renew ' , multi = ' contract_info ' ) ,
' contract_renewal_overdue ' : fields . function ( _get_contract_reminder_fnc , fnct_search = _search_get_overdue_contract_reminder , type = " boolean " , string = ' Has Contracts Overdued ' , multi = ' contract_info ' ) ,
2012-11-07 11:07:57 +00:00
' contract_renewal_name ' : fields . function ( _get_contract_reminder_fnc , type = " text " , string = ' Name of contract to renew soon ' , multi = ' contract_info ' ) ,
' contract_renewal_total ' : fields . function ( _get_contract_reminder_fnc , type = " integer " , string = ' Total of contracts due or overdue minus one ' , multi = ' contract_info ' ) ,
2012-10-19 12:06:44 +00:00
' car_value ' : fields . float ( ' Car Value ' , help = ' Value of the bought vehicle ' ) ,
2012-09-28 14:00:36 +00:00
}
2012-09-27 08:00:59 +00:00
_defaults = {
2012-11-05 17:41:10 +00:00
' doors ' : 5 ,
' odometer_unit ' : ' kilometers ' ,
2012-12-06 10:50:33 +00:00
' state_id ' : _get_default_state ,
2012-09-27 08:00:59 +00:00
}
2012-09-19 16:13:27 +00:00
def on_change_model ( self , cr , uid , ids , model_id , context = None ) :
if not model_id :
return { }
model = self . pool . get ( ' fleet.vehicle.model ' ) . browse ( cr , uid , model_id , context = context )
return {
2012-11-05 17:41:10 +00:00
' value ' : {
' image_medium ' : model . image ,
2012-09-19 16:13:27 +00:00
}
}
2012-11-05 17:41:10 +00:00
2012-09-25 11:47:14 +00:00
def create ( self , cr , uid , data , context = None ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } , mail_create_nolog = True )
2012-09-25 11:47:14 +00:00
vehicle_id = super ( fleet_vehicle , self ) . create ( cr , uid , data , context = context )
2012-11-07 13:11:44 +00:00
vehicle = self . browse ( cr , uid , vehicle_id , context = context )
2013-03-18 10:42:28 +00:00
self . message_post ( cr , uid , [ vehicle_id ] , body = _ ( ' %s %s has been added to the fleet! ' ) % ( vehicle . model_id . name , vehicle . license_plate ) , context = context )
2012-09-25 11:47:14 +00:00
return vehicle_id
2012-09-19 16:13:27 +00:00
2012-09-25 13:49:41 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
2012-11-07 14:20:44 +00:00
"""
This function write an entry in the openchatter whenever we change important information
on the vehicle like the model , the drive , the state of the vehicle or its license plate
"""
2012-10-29 13:21:35 +00:00
for vehicle in self . browse ( cr , uid , ids , context ) :
changes = [ ]
2012-10-29 14:05:48 +00:00
if ' model_id ' in vals and vehicle . model_id . id != vals [ ' model_id ' ] :
value = self . pool . get ( ' fleet.vehicle.model ' ) . browse ( cr , uid , vals [ ' model_id ' ] , context = context ) . name
2012-11-07 14:20:44 +00:00
oldmodel = vehicle . model_id . name or _ ( ' None ' )
2012-11-08 11:56:58 +00:00
changes . append ( _ ( " Model: from ' %s ' to ' %s ' " ) % ( oldmodel , value ) )
2012-12-06 10:50:33 +00:00
if ' driver_id ' in vals and vehicle . driver_id . id != vals [ ' driver_id ' ] :
value = self . pool . get ( ' res.partner ' ) . browse ( cr , uid , vals [ ' driver_id ' ] , context = context ) . name
olddriver = ( vehicle . driver_id . name ) or _ ( ' None ' )
2012-11-08 11:56:58 +00:00
changes . append ( _ ( " Driver: from ' %s ' to ' %s ' " ) % ( olddriver , value ) )
2012-12-06 10:50:33 +00:00
if ' state_id ' in vals and vehicle . state_id . id != vals [ ' state_id ' ] :
value = self . pool . get ( ' fleet.vehicle.state ' ) . browse ( cr , uid , vals [ ' state_id ' ] , context = context ) . name
oldstate = vehicle . state_id . name or _ ( ' None ' )
2012-11-08 11:56:58 +00:00
changes . append ( _ ( " State: from ' %s ' to ' %s ' " ) % ( oldstate , value ) )
2012-10-29 13:21:35 +00:00
if ' license_plate ' in vals and vehicle . license_plate != vals [ ' license_plate ' ] :
2012-11-07 14:20:44 +00:00
old_license_plate = vehicle . license_plate or _ ( ' None ' )
2012-11-08 11:56:58 +00:00
changes . append ( _ ( " License Plate: from ' %s ' to ' %s ' " ) % ( old_license_plate , vals [ ' license_plate ' ] ) )
2012-11-07 13:11:44 +00:00
if len ( changes ) > 0 :
self . message_post ( cr , uid , [ vehicle . id ] , body = " , " . join ( changes ) , context = context )
2012-11-07 11:23:55 +00:00
vehicle_id = super ( fleet_vehicle , self ) . write ( cr , uid , ids , vals , context )
2012-10-29 13:21:35 +00:00
return True
2012-09-25 13:49:41 +00:00
2012-10-03 14:57:57 +00:00
2012-09-26 14:13:52 +00:00
class fleet_vehicle_odometer ( osv . Model ) :
_name = ' fleet.vehicle.odometer '
_description = ' Odometer log for a vehicle '
2012-09-28 10:22:11 +00:00
_order = ' date desc '
2012-11-05 17:41:10 +00:00
def _vehicle_log_name_get_fnc ( self , cr , uid , ids , prop , unknow_none , context = None ) :
res = { }
for record in self . browse ( cr , uid , ids , context = context ) :
name = record . vehicle_id . name
2014-11-13 15:02:11 +00:00
if not name :
name = record . date
elif record . date :
name + = ' / ' + record . date
2012-11-05 17:41:10 +00:00
res [ record . id ] = name
2012-09-27 15:05:24 +00:00
return res
2012-10-02 12:43:34 +00:00
def on_change_vehicle ( self , cr , uid , ids , vehicle_id , context = None ) :
if not vehicle_id :
return { }
odometer_unit = self . pool . get ( ' fleet.vehicle ' ) . browse ( cr , uid , vehicle_id , context = context ) . odometer_unit
return {
2012-11-05 17:41:10 +00:00
' value ' : {
' unit ' : odometer_unit ,
2012-10-02 12:43:34 +00:00
}
}
2012-09-26 14:13:52 +00:00
_columns = {
2012-11-05 17:41:10 +00:00
' name ' : fields . function ( _vehicle_log_name_get_fnc , type = " char " , string = ' Name ' , store = True ) ,
' date ' : fields . date ( ' Date ' ) ,
' value ' : fields . float ( ' Odometer Value ' , group_operator = " max " ) ,
' vehicle_id ' : fields . many2one ( ' fleet.vehicle ' , ' Vehicle ' , required = True ) ,
' unit ' : fields . related ( ' vehicle_id ' , ' odometer_unit ' , type = " char " , string = " Unit " , readonly = True ) ,
2012-09-26 14:13:52 +00:00
}
_defaults = {
2012-11-05 17:41:10 +00:00
' date ' : fields . date . context_today ,
2012-09-26 14:13:52 +00:00
}
2012-10-03 14:57:57 +00:00
2012-09-21 15:10:22 +00:00
class fleet_vehicle_log_fuel ( osv . Model ) :
2012-09-24 10:17:20 +00:00
2012-10-02 12:43:34 +00:00
def on_change_vehicle ( self , cr , uid , ids , vehicle_id , context = None ) :
if not vehicle_id :
return { }
2012-12-10 14:03:17 +00:00
vehicle = self . pool . get ( ' fleet.vehicle ' ) . browse ( cr , uid , vehicle_id , context = context )
odometer_unit = vehicle . odometer_unit
driver = vehicle . driver_id . id
2012-10-02 12:43:34 +00:00
return {
2012-11-05 17:41:10 +00:00
' value ' : {
' odometer_unit ' : odometer_unit ,
2012-12-10 14:03:17 +00:00
' purchaser_id ' : driver ,
2012-10-02 12:43:34 +00:00
}
}
2012-09-25 08:40:05 +00:00
def on_change_liter ( self , cr , uid , ids , liter , price_per_liter , amount , context = None ) :
2012-11-08 11:56:58 +00:00
#need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
#make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
#liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
#of 3.0/2=1.5)
2013-01-04 12:52:34 +00:00
#If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine
#onchange. And in order to verify that there is no change in the result, we have to limit the precision of the
#computation to 2 decimal
2012-11-08 09:48:15 +00:00
liter = float ( liter )
price_per_liter = float ( price_per_liter )
amount = float ( amount )
2013-01-04 12:52:34 +00:00
if liter > 0 and price_per_liter > 0 and round ( liter * price_per_liter , 2 ) != amount :
return { ' value ' : { ' amount ' : round ( liter * price_per_liter , 2 ) , } }
elif amount > 0 and liter > 0 and round ( amount / liter , 2 ) != price_per_liter :
return { ' value ' : { ' price_per_liter ' : round ( amount / liter , 2 ) , } }
elif amount > 0 and price_per_liter > 0 and round ( amount / price_per_liter , 2 ) != liter :
return { ' value ' : { ' liter ' : round ( amount / price_per_liter , 2 ) , } }
2012-09-25 08:40:05 +00:00
else :
return { }
2012-09-24 10:17:20 +00:00
2012-09-25 08:40:05 +00:00
def on_change_price_per_liter ( self , cr , uid , ids , liter , price_per_liter , amount , context = None ) :
2012-11-08 11:56:58 +00:00
#need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
#make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
#liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
#of 3.0/2=1.5)
2013-01-04 12:52:34 +00:00
#If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine
#onchange. And in order to verify that there is no change in the result, we have to limit the precision of the
#computation to 2 decimal
2012-11-08 09:48:15 +00:00
liter = float ( liter )
price_per_liter = float ( price_per_liter )
amount = float ( amount )
2013-01-04 12:52:34 +00:00
if liter > 0 and price_per_liter > 0 and round ( liter * price_per_liter , 2 ) != amount :
return { ' value ' : { ' amount ' : round ( liter * price_per_liter , 2 ) , } }
elif amount > 0 and price_per_liter > 0 and round ( amount / price_per_liter , 2 ) != liter :
return { ' value ' : { ' liter ' : round ( amount / price_per_liter , 2 ) , } }
elif amount > 0 and liter > 0 and round ( amount / liter , 2 ) != price_per_liter :
return { ' value ' : { ' price_per_liter ' : round ( amount / liter , 2 ) , } }
2012-09-25 08:40:05 +00:00
else :
return { }
def on_change_amount ( self , cr , uid , ids , liter , price_per_liter , amount , context = None ) :
2012-11-08 11:56:58 +00:00
#need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not
#make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per
#liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead
#of 3.0/2=1.5)
2013-01-04 12:52:34 +00:00
#If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine
#onchange. And in order to verify that there is no change in the result, we have to limit the precision of the
#computation to 2 decimal
2012-11-08 09:48:15 +00:00
liter = float ( liter )
price_per_liter = float ( price_per_liter )
amount = float ( amount )
2013-01-04 12:52:34 +00:00
if amount > 0 and liter > 0 and round ( amount / liter , 2 ) != price_per_liter :
return { ' value ' : { ' price_per_liter ' : round ( amount / liter , 2 ) , } }
elif amount > 0 and price_per_liter > 0 and round ( amount / price_per_liter , 2 ) != liter :
return { ' value ' : { ' liter ' : round ( amount / price_per_liter , 2 ) , } }
elif liter > 0 and price_per_liter > 0 and round ( liter * price_per_liter , 2 ) != amount :
return { ' value ' : { ' amount ' : round ( liter * price_per_liter , 2 ) , } }
else :
return { }
2012-10-03 14:57:57 +00:00
2012-10-04 14:32:53 +00:00
def _get_default_service_type ( self , cr , uid , context ) :
2012-10-25 11:58:30 +00:00
try :
model , model_id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( cr , uid , ' fleet ' , ' type_service_refueling ' )
except ValueError :
model_id = False
2012-10-04 14:32:53 +00:00
return model_id
2012-09-24 10:17:20 +00:00
2012-09-21 15:10:22 +00:00
_name = ' fleet.vehicle.log.fuel '
2012-11-07 11:07:57 +00:00
_description = ' Fuel log for vehicles '
2012-11-05 17:41:10 +00:00
_inherits = { ' fleet.vehicle.cost ' : ' cost_id ' }
2012-09-26 14:13:52 +00:00
2012-09-21 15:10:22 +00:00
_columns = {
2012-11-05 17:41:10 +00:00
' liter ' : fields . float ( ' Liter ' ) ,
' price_per_liter ' : fields . float ( ' Price Per Liter ' ) ,
' purchaser_id ' : fields . many2one ( ' res.partner ' , ' Purchaser ' , domain = " [ ' | ' ,( ' customer ' , ' = ' ,True),( ' employee ' , ' = ' ,True)] " ) ,
' inv_ref ' : fields . char ( ' Invoice Reference ' , size = 64 ) ,
' vendor_id ' : fields . many2one ( ' res.partner ' , ' Supplier ' , domain = " [( ' supplier ' , ' = ' ,True)] " ) ,
' notes ' : fields . text ( ' Notes ' ) ,
2013-11-21 12:06:37 +00:00
' cost_id ' : fields . many2one ( ' fleet.vehicle.cost ' , ' Cost ' , required = True , ondelete = ' cascade ' ) ,
2012-11-05 17:41:10 +00:00
' cost_amount ' : fields . related ( ' cost_id ' , ' amount ' , string = ' Amount ' , type = ' float ' , store = True ) , #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
2012-09-26 14:56:03 +00:00
}
2012-09-27 14:34:30 +00:00
_defaults = {
2012-11-05 17:41:10 +00:00
' date ' : fields . date . context_today ,
2012-12-06 10:50:33 +00:00
' cost_subtype_id ' : _get_default_service_type ,
2012-11-05 17:41:10 +00:00
' cost_type ' : ' fuel ' ,
2012-09-27 14:34:30 +00:00
}
2012-10-03 14:57:57 +00:00
2012-09-26 14:56:03 +00:00
class fleet_vehicle_log_services ( osv . Model ) :
2012-10-02 12:43:34 +00:00
def on_change_vehicle ( self , cr , uid , ids , vehicle_id , context = None ) :
if not vehicle_id :
return { }
2012-12-10 14:03:17 +00:00
vehicle = self . pool . get ( ' fleet.vehicle ' ) . browse ( cr , uid , vehicle_id , context = context )
odometer_unit = vehicle . odometer_unit
driver = vehicle . driver_id . id
2012-10-02 12:43:34 +00:00
return {
2012-11-05 17:41:10 +00:00
' value ' : {
' odometer_unit ' : odometer_unit ,
2012-12-10 14:03:17 +00:00
' purchaser_id ' : driver ,
2012-10-02 12:43:34 +00:00
}
}
2012-10-25 09:51:29 +00:00
def _get_default_service_type ( self , cr , uid , context ) :
2012-10-25 11:58:30 +00:00
try :
model , model_id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( cr , uid , ' fleet ' , ' type_service_service_8 ' )
except ValueError :
model_id = False
2012-10-25 09:51:29 +00:00
return model_id
2012-11-05 17:41:10 +00:00
_inherits = { ' fleet.vehicle.cost ' : ' cost_id ' }
2012-09-26 14:56:03 +00:00
_name = ' fleet.vehicle.log.services '
2012-11-07 11:07:57 +00:00
_description = ' Services for vehicles '
2012-09-26 14:56:03 +00:00
_columns = {
2012-11-05 17:41:10 +00:00
' purchaser_id ' : fields . many2one ( ' res.partner ' , ' Purchaser ' , domain = " [ ' | ' ,( ' customer ' , ' = ' ,True),( ' employee ' , ' = ' ,True)] " ) ,
2014-05-21 09:52:05 +00:00
' inv_ref ' : fields . char ( ' Invoice Reference ' ) ,
2012-11-05 17:41:10 +00:00
' vendor_id ' : fields . many2one ( ' res.partner ' , ' Supplier ' , domain = " [( ' supplier ' , ' = ' ,True)] " ) ,
' cost_amount ' : fields . related ( ' cost_id ' , ' amount ' , string = ' Amount ' , type = ' float ' , store = True ) , #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
' notes ' : fields . text ( ' Notes ' ) ,
2013-11-21 12:06:37 +00:00
' cost_id ' : fields . many2one ( ' fleet.vehicle.cost ' , ' Cost ' , required = True , ondelete = ' cascade ' ) ,
2012-09-21 15:10:22 +00:00
}
2012-09-27 14:34:30 +00:00
_defaults = {
2012-11-05 17:41:10 +00:00
' date ' : fields . date . context_today ,
2012-12-06 10:50:33 +00:00
' cost_subtype_id ' : _get_default_service_type ,
2012-11-05 17:41:10 +00:00
' cost_type ' : ' services '
2012-09-27 14:34:30 +00:00
}
2012-09-21 15:10:22 +00:00
2012-10-03 14:57:57 +00:00
class fleet_service_type ( osv . Model ) :
_name = ' fleet.service.type '
2012-11-05 17:41:10 +00:00
_description = ' Type of services available on a vehicle '
2012-09-24 15:38:26 +00:00
_columns = {
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
2012-11-05 17:41:10 +00:00
' category ' : fields . selection ( [ ( ' contract ' , ' Contract ' ) , ( ' service ' , ' Service ' ) , ( ' both ' , ' Both ' ) ] , ' Category ' , required = True , help = ' Choose wheter the service refer to contracts, vehicle services or both ' ) ,
2012-10-04 11:58:06 +00:00
}
2012-09-24 15:38:26 +00:00
2012-10-03 14:57:57 +00:00
2012-10-02 14:36:37 +00:00
class fleet_vehicle_log_contract ( osv . Model ) :
2012-10-04 09:17:53 +00:00
2012-11-08 11:56:58 +00:00
def scheduler_manage_auto_costs ( self , cr , uid , context = None ) :
2012-11-07 13:11:44 +00:00
#This method is called by a cron task
#It creates costs for contracts having the "recurring cost" field setted, depending on their frequency
#For example, if a contract has a reccuring cost of 200 with a weekly frequency, this method creates a cost of 200 on the first day of each week, from the date of the last recurring costs in the database to today
#If the contract has not yet any recurring costs in the database, the method generates the recurring costs from the start_date to today
#The created costs are associated to a contract thanks to the many2one field contract_id
#If the contract has no start_date, no cost will be created, even if the contract has recurring costs
2012-11-05 17:41:10 +00:00
vehicle_cost_obj = self . pool . get ( ' fleet.vehicle.cost ' )
2012-11-07 11:07:57 +00:00
d = datetime . datetime . strptime ( fields . date . context_today ( self , cr , uid , context = context ) , tools . DEFAULT_SERVER_DATE_FORMAT ) . date ( )
2012-10-29 12:13:54 +00:00
contract_ids = self . pool . get ( ' fleet.vehicle.log.contract ' ) . search ( cr , uid , [ ( ' state ' , ' != ' , ' closed ' ) ] , offset = 0 , limit = None , order = None , context = None , count = False )
2012-11-05 17:41:10 +00:00
deltas = { ' yearly ' : relativedelta ( years = + 1 ) , ' monthly ' : relativedelta ( months = + 1 ) , ' weekly ' : relativedelta ( weeks = + 1 ) , ' daily ' : relativedelta ( days = + 1 ) }
for contract in self . pool . get ( ' fleet.vehicle.log.contract ' ) . browse ( cr , uid , contract_ids , context = context ) :
2012-10-25 09:06:50 +00:00
if not contract . start_date or contract . cost_frequency == ' no ' :
2012-11-05 17:41:10 +00:00
continue
found = False
last_cost_date = contract . start_date
if contract . generated_cost_ids :
last_autogenerated_cost_id = vehicle_cost_obj . search ( cr , uid , [ ' & ' , ( ' contract_id ' , ' = ' , contract . id ) , ( ' auto_generated ' , ' = ' , True ) ] , offset = 0 , limit = 1 , order = ' date desc ' , context = context , count = False )
if last_autogenerated_cost_id :
found = True
2012-11-08 11:56:58 +00:00
last_cost_date = vehicle_cost_obj . browse ( cr , uid , last_autogenerated_cost_id [ 0 ] , context = context ) . date
2012-11-05 17:41:10 +00:00
startdate = datetime . datetime . strptime ( last_cost_date , tools . DEFAULT_SERVER_DATE_FORMAT ) . date ( )
2012-10-24 15:33:11 +00:00
if found :
2012-10-25 09:06:50 +00:00
startdate + = deltas . get ( contract . cost_frequency )
2012-11-30 09:54:49 +00:00
while ( startdate < = d ) & ( startdate < = datetime . datetime . strptime ( contract . expiration_date , tools . DEFAULT_SERVER_DATE_FORMAT ) . date ( ) ) :
2012-11-05 17:41:10 +00:00
data = {
' amount ' : contract . cost_generated ,
' date ' : startdate . strftime ( tools . DEFAULT_SERVER_DATE_FORMAT ) ,
' vehicle_id ' : contract . vehicle_id . id ,
2012-12-06 10:50:33 +00:00
' cost_subtype_id ' : contract . cost_subtype_id . id ,
2012-11-05 17:41:10 +00:00
' contract_id ' : contract . id ,
' auto_generated ' : True
}
2012-10-23 17:25:36 +00:00
cost_id = self . pool . get ( ' fleet.vehicle.cost ' ) . create ( cr , uid , data , context = context )
2012-10-25 09:06:50 +00:00
startdate + = deltas . get ( contract . cost_frequency )
2012-11-08 11:56:58 +00:00
return True
2012-11-07 11:07:57 +00:00
2012-11-08 11:56:58 +00:00
def scheduler_manage_contract_expiration ( self , cr , uid , context = None ) :
#This method is called by a cron task
#It manages the state of a contract, possibly by posting a message on the vehicle concerned and updating its status
datetime_today = datetime . datetime . strptime ( fields . date . context_today ( self , cr , uid , context = context ) , tools . DEFAULT_SERVER_DATE_FORMAT )
limit_date = ( datetime_today + relativedelta ( days = + 15 ) ) . strftime ( tools . DEFAULT_SERVER_DATE_FORMAT )
ids = self . search ( cr , uid , [ ' & ' , ( ' state ' , ' = ' , ' open ' ) , ( ' expiration_date ' , ' < ' , limit_date ) ] , offset = 0 , limit = None , order = None , context = context , count = False )
res = { }
for contract in self . browse ( cr , uid , ids , context = context ) :
if contract . vehicle_id . id in res :
res [ contract . vehicle_id . id ] + = 1
else :
res [ contract . vehicle_id . id ] = 1
for vehicle , value in res . items ( ) :
self . pool . get ( ' fleet.vehicle ' ) . message_post ( cr , uid , vehicle , body = _ ( ' %s contract(s) need(s) to be renewed and/or closed! ' ) % ( str ( value ) ) , context = context )
return self . write ( cr , uid , ids , { ' state ' : ' toclose ' } , context = context )
2012-11-07 11:07:57 +00:00
2012-11-08 11:56:58 +00:00
def run_scheduler ( self , cr , uid , context = None ) :
self . scheduler_manage_auto_costs ( cr , uid , context = context )
self . scheduler_manage_contract_expiration ( cr , uid , context = context )
2012-10-23 13:46:54 +00:00
return True
2012-10-04 12:12:56 +00:00
def _vehicle_contract_name_get_fnc ( self , cr , uid , ids , prop , unknow_none , context = None ) :
2012-11-05 17:41:10 +00:00
res = { }
for record in self . browse ( cr , uid , ids , context = context ) :
name = record . vehicle_id . name
2012-12-06 10:50:33 +00:00
if record . cost_subtype_id . name :
name + = ' / ' + record . cost_subtype_id . name
2012-11-05 17:41:10 +00:00
if record . date :
name + = ' / ' + record . date
res [ record . id ] = name
2012-10-03 14:57:57 +00:00
return res
2012-10-02 12:43:34 +00:00
def on_change_vehicle ( self , cr , uid , ids , vehicle_id , context = None ) :
if not vehicle_id :
return { }
odometer_unit = self . pool . get ( ' fleet.vehicle ' ) . browse ( cr , uid , vehicle_id , context = context ) . odometer_unit
return {
2012-11-05 17:41:10 +00:00
' value ' : {
' odometer_unit ' : odometer_unit ,
2012-10-02 12:43:34 +00:00
}
}
2012-09-28 10:10:40 +00:00
def compute_next_year_date ( self , strdate ) :
2012-11-05 17:41:10 +00:00
oneyear = datetime . timedelta ( days = 365 )
2012-11-08 11:56:58 +00:00
curdate = str_to_datetime ( strdate )
2012-11-05 17:41:10 +00:00
return datetime . datetime . strftime ( curdate + oneyear , tools . DEFAULT_SERVER_DATE_FORMAT )
2012-09-28 09:12:01 +00:00
2012-10-23 13:01:52 +00:00
def on_change_start_date ( self , cr , uid , ids , strdate , enddate , context = None ) :
2012-09-28 10:10:40 +00:00
if ( strdate ) :
2012-11-05 17:41:10 +00:00
return { ' value ' : { ' expiration_date ' : self . compute_next_year_date ( strdate ) , } }
return { }
2012-10-03 09:00:08 +00:00
2012-11-08 11:56:58 +00:00
def get_days_left ( self , cr , uid , ids , prop , unknow_none , context = None ) :
2012-11-07 11:07:57 +00:00
""" return a dict with as value for each contract an integer
if contract is in an open state and is overdue , return 0
if contract is in a closed state , return - 1
otherwise return the number of days before the contract expires
"""
2012-11-08 11:56:58 +00:00
res = { }
for record in self . browse ( cr , uid , ids , context = context ) :
if ( record . expiration_date and ( record . state == ' open ' or record . state == ' toclose ' ) ) :
today = str_to_datetime ( time . strftime ( tools . DEFAULT_SERVER_DATE_FORMAT ) )
renew_date = str_to_datetime ( record . expiration_date )
diff_time = ( renew_date - today ) . days
res [ record . id ] = diff_time > 0 and diff_time or 0
2012-10-03 09:00:08 +00:00
else :
2012-11-08 11:56:58 +00:00
res [ record . id ] = - 1
2012-11-07 11:07:57 +00:00
return res
2012-10-03 09:00:08 +00:00
2012-11-08 11:56:58 +00:00
def act_renew_contract ( self , cr , uid , ids , context = None ) :
assert len ( ids ) == 1 , " This operation should only be done for 1 single contract at a time, as it it suppose to open a window as result "
for element in self . browse ( cr , uid , ids , context = context ) :
2012-10-23 13:01:52 +00:00
#compute end date
2012-11-08 11:56:58 +00:00
startdate = str_to_datetime ( element . start_date )
enddate = str_to_datetime ( element . expiration_date )
diffdate = ( enddate - startdate )
default = {
' date ' : fields . date . context_today ( self , cr , uid , context = context ) ,
' start_date ' : datetime . datetime . strftime ( str_to_datetime ( element . expiration_date ) + datetime . timedelta ( days = 1 ) , tools . DEFAULT_SERVER_DATE_FORMAT ) ,
' expiration_date ' : datetime . datetime . strftime ( enddate + diffdate , tools . DEFAULT_SERVER_DATE_FORMAT ) ,
}
2012-11-13 15:26:39 +00:00
newid = super ( fleet_vehicle_log_contract , self ) . copy ( cr , uid , element . id , default , context = context )
2012-11-08 11:56:58 +00:00
mod , modid = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( cr , uid , ' fleet ' , ' fleet_vehicle_log_contract_form ' )
2012-11-07 11:07:57 +00:00
return {
' name ' : _ ( " Renew Contract " ) ,
' view_mode ' : ' form ' ,
' view_id ' : modid ,
2012-11-07 11:23:55 +00:00
' view_type ' : ' tree,form ' ,
2012-11-07 11:07:57 +00:00
' res_model ' : ' fleet.vehicle.log.contract ' ,
' type ' : ' ir.actions.act_window ' ,
' nodestroy ' : True ,
' domain ' : ' [] ' ,
2012-11-07 11:23:55 +00:00
' res_id ' : newid ,
' context ' : { ' active_id ' : newid } ,
2012-11-07 11:07:57 +00:00
}
2012-10-23 13:01:52 +00:00
2012-11-05 17:41:10 +00:00
def _get_default_contract_type ( self , cr , uid , context = None ) :
2012-10-25 11:58:30 +00:00
try :
model , model_id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( cr , uid , ' fleet ' , ' type_contract_leasing ' )
except ValueError :
model_id = False
return model_id
2012-10-22 08:18:33 +00:00
2012-11-05 17:41:10 +00:00
def on_change_indic_cost ( self , cr , uid , ids , cost_ids , context = None ) :
totalsum = 0.0
2012-10-29 13:35:34 +00:00
for element in cost_ids :
2014-09-26 16:36:13 +00:00
if element and len ( element ) == 3 and isinstance ( element [ 2 ] , dict ) :
2012-11-05 17:41:10 +00:00
totalsum + = element [ 2 ] . get ( ' amount ' , 0.0 )
2012-10-29 13:35:34 +00:00
return {
2012-11-05 17:41:10 +00:00
' value ' : {
' sum_cost ' : totalsum ,
2012-10-29 13:35:34 +00:00
}
}
2012-11-05 17:41:10 +00:00
def _get_sum_cost ( self , cr , uid , ids , field_name , arg , context = None ) :
res = { }
for contract in self . browse ( cr , uid , ids , context = context ) :
totalsum = 0
for cost in contract . cost_ids :
totalsum + = cost . amount
res [ contract . id ] = totalsum
return res
2012-10-29 13:35:34 +00:00
2012-11-05 17:41:10 +00:00
_inherits = { ' fleet.vehicle.cost ' : ' cost_id ' }
2012-10-02 14:36:37 +00:00
_name = ' fleet.vehicle.log.contract '
2012-11-07 11:07:57 +00:00
_description = ' Contract information on a vehicle '
2012-10-29 14:25:20 +00:00
_order = ' state desc,expiration_date '
2012-09-21 15:10:22 +00:00
_columns = {
2012-11-05 17:41:10 +00:00
' name ' : fields . function ( _vehicle_contract_name_get_fnc , type = " text " , string = ' Name ' , store = True ) ,
' start_date ' : fields . date ( ' Contract Start Date ' , help = ' Date when the coverage of the contract begins ' ) ,
' expiration_date ' : fields . date ( ' Contract Expiration Date ' , help = ' Date when the coverage of the contract expirates (by default, one year after begin date) ' ) ,
2012-11-07 11:07:57 +00:00
' days_left ' : fields . function ( get_days_left , type = ' integer ' , string = ' Warning Date ' ) ,
2012-11-09 13:06:03 +00:00
' insurer_id ' : fields . many2one ( ' res.partner ' , ' Supplier ' ) ,
' purchaser_id ' : fields . many2one ( ' res.partner ' , ' Contractor ' , help = ' Person to which the contract is signed for ' ) ,
2014-07-06 14:44:26 +00:00
' ins_ref ' : fields . char ( ' Contract Reference ' , size = 64 , copy = False ) ,
' state ' : fields . selection ( [ ( ' open ' , ' In Progress ' ) , ( ' toclose ' , ' To Close ' ) , ( ' closed ' , ' Terminated ' ) ] ,
' Status ' , readonly = True , help = ' Choose wheter the contract is still valid or not ' ,
copy = False ) ,
' notes ' : fields . text ( ' Terms and Conditions ' , help = ' Write here all supplementary informations relative to this contract ' , copy = False ) ,
2012-11-05 17:41:10 +00:00
' cost_generated ' : fields . float ( ' Recurring Cost Amount ' , help = " Costs paid at regular intervals, depending on the cost frequency. If the cost frequency is set to unique, the cost will be logged at the start date " ) ,
' cost_frequency ' : fields . selection ( [ ( ' no ' , ' No ' ) , ( ' daily ' , ' Daily ' ) , ( ' weekly ' , ' Weekly ' ) , ( ' monthly ' , ' Monthly ' ) , ( ' yearly ' , ' Yearly ' ) ] , ' Recurring Cost Frequency ' , help = ' Frequency of the recuring cost ' , required = True ) ,
2014-07-06 14:44:26 +00:00
' generated_cost_ids ' : fields . one2many ( ' fleet.vehicle.cost ' , ' contract_id ' , ' Generated Costs ' ) ,
2012-11-05 17:41:10 +00:00
' sum_cost ' : fields . function ( _get_sum_cost , type = ' float ' , string = ' Indicative Costs Total ' ) ,
2013-11-21 12:06:37 +00:00
' cost_id ' : fields . many2one ( ' fleet.vehicle.cost ' , ' Cost ' , required = True , ondelete = ' cascade ' ) ,
2012-11-05 17:41:10 +00:00
' cost_amount ' : fields . related ( ' cost_id ' , ' amount ' , string = ' Amount ' , type = ' float ' , store = True ) , #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database
2012-09-21 15:10:22 +00:00
}
2012-09-27 14:34:30 +00:00
_defaults = {
2012-12-16 19:20:37 +00:00
' purchaser_id ' : lambda self , cr , uid , ctx : self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = ctx ) . partner_id . id or False ,
2012-11-05 17:41:10 +00:00
' date ' : fields . date . context_today ,
' start_date ' : fields . date . context_today ,
2012-10-03 09:54:04 +00:00
' state ' : ' open ' ,
2012-11-05 17:41:10 +00:00
' expiration_date ' : lambda self , cr , uid , ctx : self . compute_next_year_date ( fields . date . context_today ( self , cr , uid , context = ctx ) ) ,
' cost_frequency ' : ' no ' ,
2012-12-06 10:50:33 +00:00
' cost_subtype_id ' : _get_default_contract_type ,
2012-11-05 17:41:10 +00:00
' cost_type ' : ' contract ' ,
2012-09-27 14:34:30 +00:00
}
2012-09-21 15:10:22 +00:00
2012-11-07 11:07:57 +00:00
def contract_close ( self , cr , uid , ids , context = None ) :
2012-11-08 08:21:56 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' closed ' } , context = context )
2012-10-03 09:54:04 +00:00
2012-11-07 11:07:57 +00:00
def contract_open ( self , cr , uid , ids , context = None ) :
2012-11-08 08:21:56 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' open ' } , context = context )
2012-10-03 14:57:57 +00:00
class fleet_contract_state ( osv . Model ) :
_name = ' fleet.contract.state '
2012-11-05 17:41:10 +00:00
_description = ' Contains the different possible status of a leasing contract '
2012-10-03 14:57:57 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Contract Status ' , required = True ) ,
2012-11-05 17:41:10 +00:00
}