Odometer field function for vehicle
[odoo/odoo.git] / addons / fleet / fleet.py
1 from itertools import chain
2 from osv import osv, fields
3 import time
4
5 class fleet_vehicle_model_type(osv.Model):
6     _name = 'fleet.vehicle.type'
7     _description = 'Type of the vehicle'
8     _columns = {
9         'name' : fields.char('Name', size=32, required=True),
10     }
11
12 class fleet_vehicle_tag(osv.Model):
13     _name = 'fleet.vehicle.tag'
14     _columns = {
15         'name': fields.char('Name', required=True, translate=True),
16     }
17
18 class fleet_vehicle_state(osv.Model):
19     _name = 'fleet.vehicle.state'
20     _columns = {
21         'name': fields.char('Name', required=True),
22         'sequence': fields.integer('Order',help="Used to order the note stages")
23     }
24     _order = 'sequence asc'
25
26 class fleet_vehicle_model(osv.Model):
27
28     def name_get(self, cr, uid, ids, context=None):
29         if context is None:
30             context = {}
31         if not ids:
32             return []
33         reads = self.browse(cr, uid, ids, context=context)
34         res = []
35         for record in reads:
36             name = record.modelname
37             if record.brand.name:
38                 name = record.brand.name+' / '+name
39             res.append((record.id, name))
40         return res
41
42     def _model_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
43         res = self.name_get(cr, uid, ids, context=context)
44         return dict(res)
45
46     _name = 'fleet.vehicle.model'
47     _description = 'Model of a vehicle'
48
49     _columns = {
50         'name' : fields.function(_model_name_get_fnc, type="char", string='Name', store=True),
51         'modelname' : fields.char('Model name', size=32, required=True), 
52         'brand' : fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'),
53         'vendors': fields.many2many('res.partner','fleet_vehicle_model_vendors','model_id', 'partner_id',string='Vendors',required=False),
54         'image': fields.related('brand','image',type="binary",string="Logo",store=False)
55     }
56
57 class fleet_vehicle_model_brand(osv.Model):
58     _name = 'fleet.vehicle.model.brand'
59     _description = 'Brand model of the vehicle'
60     _columns = {
61         'name' : fields.char('Brand Name',size=32, required=True),
62         'image': fields.binary("Logo",help="This field holds the image used as logo for the brand, limited to 128x128px."),
63     }
64
65 class fleet_vehicle(osv.Model):
66
67     _inherit = 'mail.thread'
68
69     def name_get(self, cr, uid, ids, context=None):
70         if context is None:
71             context = {}
72         if not ids:
73             return []
74         reads = self.browse(cr, uid, ids, context=context)
75         res = []
76         for record in reads:
77             if record.license_plate:
78                 name = record.license_plate
79             if record.model_id.modelname:
80                 name = record.model_id.modelname + ' / ' + name
81             if record.model_id.brand.name:
82                 name = record.model_id.brand.name+' / '+ name
83             res.append((record.id, name))
84         return res
85
86     def _vehicle_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
87         res = self.name_get(cr, uid, ids, context=context)
88         return dict(res)
89
90     def act_show_log_services(self, cr, uid, ids, context=None):
91         """ This opens log view to view and add new log for this vehicle
92             @return: the service log view
93         """
94         res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_services', context)
95         res['context'] = {
96             'default_vehicle_id': ids[0]
97         }
98         res['domain']=[('vehicle_id','=', ids[0])]
99         return res
100
101     def act_show_log_insurance(self, cr, uid, ids, context=None):
102         """ This opens log view to view and add new log for this vehicle
103             @return: the insurance log view
104         """
105         res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_insurance', context)
106         res['context'] = {
107             'default_vehicle_id': ids[0]
108         }
109         res['domain']=[('vehicle_id','=', ids[0])]
110         return res
111
112     def act_show_log_fuel(self, cr, uid, ids, context=None):
113         """ This opens log view to view and add new log for this vehicle
114             @return: the fuel log view
115         """
116         res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_fuel', context)
117         res['context'] = {
118             'default_vehicle_id': ids[0]
119         }
120         res['domain']=[('vehicle_id','=', ids[0])]
121         return res    
122
123     def get_odometer(self, cr, uid, ids, context=None):
124         if context is None:
125             context = {}
126         if not ids:
127             return []
128         reads = self.browse(cr, uid, ids, context=context)
129         res = []
130         for record in reads:
131             odometers = self.pool.get('fleet.vehicle.odometer').search(cr,uid,[('vehicle_id','=',record.id)], order='date desc')
132             if len(odometers) > 0:
133                 res.append((record.id,self.pool.get('fleet.vehicle.odometer').browse(cr, uid, odometers[0], context=context).value))
134             else :
135                 res.append((record.id,0))
136         return res
137
138     def _vehicle_odometer_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
139         res = self.get_odometer(cr, uid, ids, context=context)
140         return dict(res)
141
142     _name = 'fleet.vehicle'
143     _description = 'Fleet Vehicle'
144
145     _columns = {
146         'name' : fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True),
147         'company_id': fields.many2one('res.company', 'Company'),
148         'license_plate' : fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
149         'vin_sn' : fields.char('Chassis Number', size=32, required=False, help='Unique number written on the vehicle motor (VIN/SN number)'),
150         'driver' : fields.many2one('res.partner', 'Driver',required=False, help='Driver of the vehicle'),
151         'model_id' : fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'),
152         'log_ids' : fields.one2many('fleet.vehicle.log', 'vehicle_id', 'Other Logs'),
153         'log_fuel' : fields.one2many('fleet.vehicle.log.fuel','vehicle_id', 'Fuel Logs'),
154         'log_services' : fields.one2many('fleet.vehicle.log.services','vehicle_id', 'Services Logs'),
155         'log_insurances' : fields.one2many('fleet.vehicle.log.insurance','vehicle_id', 'Insurances'),
156         'acquisition_date' : fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'),
157         'acquisition_price' : fields.integer('Price', help='Price of the bought vehicle'),
158         'color' : fields.char('Color',size=32, help='Color of the vehicle'),
159         'state': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle', domain='[]'),
160         'location' : fields.char('Location',size=32, help='Location of the vehicle (garage, ...)'),
161         'doors' : fields.integer('Doors Number', help='Number of doors of the vehicle'),
162         'tag_ids' :fields.many2many('fleet.vehicle.tag','vehicle_vehicle_tag_rel','vehicle_tag_id','tag_id','Tags'),
163
164         'odometer' : fields.function(_vehicle_odometer_get_fnc, type="float", string='Odometer', store=False),
165
166         'transmission' : fields.selection([('manual', 'Manual'),('automatic','Automatic')], 'Transmission', help='Transmission Used by the vehicle',required=False),
167         'fuel_type' : fields.selection([('gasoline', 'Gasoline'),('diesel','Diesel'),('electric','Electric'),('hybrid','Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle',required=False),
168         'horsepower' : fields.integer('Horsepower',required=False),
169         'horsepower_tax': fields.float('Horsepower Taxation'),
170         'power' : fields.integer('Power (kW)',required=False,help='Power in kW of the vehicle'),
171         'co2' : fields.float('CO2 Emissions',required=False,help='CO2 emissions of the vehicle'),
172
173         'image': fields.related('model_id','image',type="binary",string="Logo",store=False)
174     }
175     _defaults = {
176         'doors' : 5,
177     }
178
179     def on_change_model(self, cr, uid, ids, model_id, context=None):
180         # print "ids: %r" % (ids,)
181         # print "model_id: %r" % (model_id,)
182         # print "context: %r" % (context,)
183         # import logging
184         # logger = logging.getLogger('fleet.vehicle')
185         # logger.info('Hello')
186
187         # import ipdb
188         # ipdb.set_trace()
189
190         if not model_id:
191             return {}
192
193         model = self.pool.get('fleet.vehicle.model').browse(cr, uid, model_id, context=context)
194
195         print "model: %r" % (model.name,)
196
197         return {
198             'value' : {
199                 'message' : "You have selected this %s model" % (model.name,),
200             }
201         }
202     def create(self, cr, uid, data, context=None):
203         vehicle_id = super(fleet_vehicle, self).create(cr, uid, data, context=context)
204         try:
205             vehicle = self.browse(cr, uid, vehicle_id, context=context)
206             self.message_post(cr, uid, [vehicle_id], body='Vehicle %s has been added to the fleet!' % (vehicle.license_plate), context=context)
207         except:
208             pass # group deleted: do not push a message
209         return vehicle_id
210
211     def write(self, cr, uid, ids, vals, context=None):
212         vehicle_id = super(fleet_vehicle,self).write(cr, uid, ids, vals, context)
213         try:
214             changes = {}
215             for key,value in vals.items():
216                 if key == 'license_plate' or key == 'driver':
217                     changes[key] = value
218             if len(changes) > 0:
219                 self.message_post(cr, uid, [vehicle_id], body='Vehicle edited. Changes : '+ str(changes), context=context)
220                 #self.message_post(cr, uid, [vehicle_id], body='Vehicle edited. Changes : '+ ','.join(chain(*str(changes.items()))), context=context)
221         except Exception as e:
222             print e
223             pass
224         return vehicle_id
225
226 class fleet_vehicle_odometer(osv.Model):
227     _name='fleet.vehicle.odometer'
228     _description='Odometer log for a vehicle'
229
230     _order='date desc'
231
232     def name_get(self, cr, uid, ids, context=None):
233         if context is None:
234             context = {}
235         if not ids:
236             return []
237         reads = self.browse(cr, uid, ids, context=context)
238         res = []
239         for record in reads:
240             if record.vehicle_id.name:
241                 name = str(record.vehicle_id.name)
242             if record.date:
243                 name = name+ ' / '+ str(record.date)
244             res.append((record.id, name))
245         return res
246
247     def _vehicle_log_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
248         res = self.name_get(cr, uid, ids, context=context)
249         return dict(res)
250
251     def get_month(self, cr, uid, ids, context=None):
252         if context is None:
253             context = {}
254         if not ids:
255             return []
256         months = ['January','February','March','April','May','June','July','August','September','October','November','December']
257         reads = self.browse(cr, uid, ids, context=context)
258         res = []
259         for record in reads:
260             res.append((record.id,months[int(record.date.split('-')[1])-1]))
261         return res
262
263     def _vehicle_log_month_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
264         res = self.get_month(cr, uid, ids, context=context)
265         return dict(res)
266         
267     _columns = {
268         'name' : fields.function(_vehicle_log_name_get_fnc, type="char", string='Name', store=True),
269
270         'date' : fields.date('Date'),
271         'value' : fields.float('Odometer Value'),
272         'unit' : fields.selection([('kilometers', 'Kilometers'),('miles','Miles')], 'Odometer Unit', help='Unit of the measurement',required=False),
273         'vehicle_id' : fields.many2one('fleet.vehicle', 'Vehicle', required=True),
274         'month' : fields.function(_vehicle_log_month_get_fnc,string="Month", type="char",size=32, store=True)
275     }
276     _defaults = {
277         'date' : time.strftime('%Y-%m-%d')
278     }
279
280 class fleet_vehicle_log_fuel(osv.Model):
281
282     _inherits = {'fleet.vehicle.odometer': 'odometer_id'}
283
284     def on_change_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
285
286         if liter > 0 and price_per_liter > 0:
287             return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
288         elif liter > 0 and amount > 0:
289             return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
290         elif price_per_liter > 0 and amount > 0:
291             return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
292         else :
293             return {}
294
295     def on_change_price_per_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
296
297         liter = float(liter);
298         price_per_liter = float(price_per_liter);
299         if price_per_liter > 0 and liter > 0:
300             return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
301         elif price_per_liter > 0 and amount > 0:
302             return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
303         elif liter > 0 and amount > 0:
304             return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
305         else :
306             return {}
307
308     def on_change_amount(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
309
310         if amount > 0 and liter > 0:
311             return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
312         elif amount > 0 and price_per_liter > 0:
313             return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
314         elif liter > 0 and price_per_liter > 0:
315             return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
316         else :
317             return {}
318         
319
320     _name = 'fleet.vehicle.log.fuel'
321
322     _columns = {
323         #'name' : fields.char('Name',size=64),
324
325         'liter' : fields.float('Liter'),
326         'price_per_liter' : fields.float('Price Per Liter'),
327         'amount': fields.float('Total price'),
328         'purchaser_id' : fields.many2one('res.partner', 'Purchaser'),
329         'inv_ref' : fields.char('Invoice Reference', size=64),
330         'vendor_id' : fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
331         'notes' : fields.text('Notes'),
332     }
333     _defaults = {
334         'purchaser_id': lambda self, cr, uid, ctx: uid,
335     }
336
337 class fleet_vehicle_log_services(osv.Model):
338
339     _inherits = {'fleet.vehicle.odometer': 'odometer_id'}    
340
341     _name = 'fleet.vehicle.log.services'
342     _columns = {
343
344         #'name' : fields.char('Name',size=64),
345         'date' :fields.date('Service Date',help='Date when the service will be/has been performed'),
346         'amount' :fields.float('Cost', help="Total cost of the service"),
347         'service_ids' :fields.many2many('fleet.service.type','vehicle_service_type_rel','vehicle_service_type_id','service_id','Services completed'),
348         'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="[('supplier','=',False)]"),
349         'inv_ref' : fields.char('Invoice Reference', size=64),
350         'vendor_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
351         'notes' : fields.text('Notes'),
352     }
353     _defaults = {
354         'purchaser_id': lambda self, cr, uid, ctx: uid,
355         'date' : time.strftime('%Y-%m-%d'),
356     }
357
358 class fleet_insurance_type(osv.Model):
359     _name = 'fleet.insurance.type'
360     _columns = {
361         'name': fields.char('Name', required=True, translate=True),
362     }
363
364 class fleet_vehicle_log_insurance(osv.Model):
365     _inherits = {'fleet.vehicle.odometer': 'odometer_id'}
366
367     def compute_next_year_date(self, strdate):
368         nextyear=int(strdate[:4])+1
369         return str(nextyear)+strdate[4:]
370
371     def on_change_start_date(self, cr, uid, ids, strdate, context=None):
372         if (strdate):
373            
374             return {'value' : {'expiration_date' : self.compute_next_year_date(strdate),}}
375         else:
376             return {}
377
378     _name = 'fleet.vehicle.log.insurance'
379     _columns = {
380
381         #'name' : fields.char('Name',size=64),
382
383         'insurance_type' : fields.many2one('fleet.insurance.type', 'Type', required=False, help='Type of the insurance'),
384         'start_date' : fields.date('Start Date', required=False, help='Date when the coverage of the insurance begins'),
385         'expiration_date' : fields.date('Expiration Date', required=False, help='Date when the coverage of the insurance expirates'),
386         'price' : fields.float('Price', help="Cost of the insurance for the specified period"),
387         'insurer_id' :fields.many2one('res.partner', 'Insurer', domain="[('supplier','=',True)]"),
388         'purchaser_id' : fields.many2one('res.partner', 'Purchaser'),
389         'ins_ref' : fields.char('Insurance Reference', size=64),
390         'notes' : fields.text('Terms and Conditions'),
391     }
392     _defaults = {
393         'purchaser_id': lambda self, cr, uid, ctx: uid,
394         'start_date' : time.strftime('%Y-%m-%d'),
395         #'expiration_date' : self.compute_next_year_date(time.strftime('%Y-%m-%d')),
396     
397     }
398
399 class fleet_service_type(osv.Model):
400     _name = 'fleet.service.type'
401     _columns = {
402         'name': fields.char('Name', required=True, translate=True),
403     }