1 from itertools import chain
2 from osv import osv, fields
6 from osv.orm import except_orm
7 from tools.translate import _
8 from import_base.mapper import *
9 ############################
10 ############################
12 ############################
13 ############################
15 class fleet_vehicle_cost(osv.Model):
16 _name = 'fleet.vehicle.cost'
17 _description = 'Cost of vehicle'
18 _order = 'date desc, vehicle_id asc'
20 def name_get(self, cr, uid, ids, context=None):
25 reads = self.browse(cr, uid, ids, context=context)
28 if record.vehicle_id.license_plate:
29 name = record.vehicle_id.license_plate
30 if record.cost_type.name:
31 name = name + ' / '+ record.cost_type.name
33 name = name + ' / '+ record.date
34 res.append((record.id, name))
37 def _cost_name_get_fnc(self, cr, uid, ids, name, unknow_none, context=None):
38 res = self.name_get(cr, uid, ids, context=context)
42 'name' : fields.function(_cost_name_get_fnc, type="char", string='Name', store=True),
43 #'name' : fields.char('Name',size=32),
44 'vehicle_id': fields.many2one('fleet.vehicle', 'Vehicle', required=True, help='Vehicle concerned by this fuel log'),
45 'cost_type': fields.many2one('fleet.service.type', 'Service type', required=False, help='Service type purchased with this cost'),
46 'amount': fields.float('Total Price'),
48 'parent_id': fields.many2one('fleet.vehicle.cost', 'Parent', required=False, help='Parent cost to this current cost'),
49 'cost_ids' : fields.one2many('fleet.vehicle.cost', 'parent_id', 'Included Services'),
51 'date' :fields.date('Cost Date',help='Date when the cost has been executed'),
60 def create(self, cr, uid, data, context=None):
61 if 'parent_id' in data and data['parent_id']:
62 data['vehicle_id'] = self.browse(cr, uid, data['parent_id'], context=context).vehicle_id.id
63 data['date'] = self.browse(cr, uid, data['parent_id'], context=context).date
64 cost_id = super(fleet_vehicle_cost, self).create(cr, uid, data, context=context)
67 ############################
68 ############################
70 ############################
71 ############################
73 class fleet_vehicle_tag(osv.Model):
74 _name = 'fleet.vehicle.tag'
76 'name': fields.char('Name', required=True, translate=True),
79 ############################
80 ############################
82 ############################
83 ############################
85 class fleet_vehicle_state(osv.Model):
86 _name = 'fleet.vehicle.state'
88 'name': fields.char('Name', required=True),
89 'sequence': fields.integer('Order',help="Used to order the note stages")
91 _order = 'sequence asc'
93 ############################
94 ############################
96 ############################
97 ############################
99 class fleet_vehicle_model(osv.Model):
101 def name_get(self, cr, uid, ids, context=None):
106 reads = self.browse(cr, uid, ids, context=context)
109 name = record.modelname
110 if record.brand.name:
111 name = record.brand.name+' / '+name
112 res.append((record.id, name))
115 def _model_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
116 res = self.name_get(cr, uid, ids, context=context)
119 def on_change_brand(self, cr, uid, ids, model_id, context=None):
124 brand = self.pool.get('fleet.vehicle.model.brand').browse(cr, uid, model_id, context=context)
128 'image' : brand.image,
132 _name = 'fleet.vehicle.model'
133 _description = 'Model of a vehicle'
136 'name' : fields.function(_model_name_get_fnc, type="char", string='Name', store=True),
137 'modelname' : fields.char('Model name', size=32, required=True),
138 'brand' : fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'),
139 'vendors': fields.many2many('res.partner','fleet_vehicle_model_vendors','model_id', 'partner_id',string='Vendors',required=False),
140 'image': fields.related('brand','image',type="binary",string="Logo",store=False),
141 'image_medium': fields.related('brand','image_medium',type="binary",string="Logo",store=False),
142 'image_small': fields.related('brand','image_small',type="binary",string="Logo",store=False),
145 ############################
146 ############################
148 ############################
149 ############################
151 class fleet_vehicle_model_brand(osv.Model):
152 _name = 'fleet.vehicle.model.brand'
153 _description = 'Brand model of the vehicle'
157 def _get_image(self, cr, uid, ids, name, args, context=None):
158 result = dict.fromkeys(ids, False)
159 for obj in self.browse(cr, uid, ids, context=context):
160 result[obj.id] = tools.image_get_resized_images(obj.image)
163 def _set_image(self, cr, uid, id, name, value, args, context=None):
164 return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
167 'name' : fields.char('Brand Name',size=32, required=True),
169 'image': fields.binary("Logo",
170 help="This field holds the image used as logo for the brand, limited to 1024x1024px."),
171 'image_medium': fields.function(_get_image, fnct_inv=_set_image,
172 string="Medium-sized photo", type="binary", multi="_get_image",
174 'fleet.vehicle.model.brand': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
176 help="Medium-sized logo of the brand. It is automatically "\
177 "resized as a 128x128px image, with aspect ratio preserved. "\
178 "Use this field in form views or some kanban views."),
179 'image_small': fields.function(_get_image, fnct_inv=_set_image,
180 string="Smal-sized photo", type="binary", multi="_get_image",
182 'fleet.vehicle.model.brand': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
184 help="Small-sized photo of the brand. It is automatically "\
185 "resized as a 64x64px image, with aspect ratio preserved. "\
186 "Use this field anywhere a small image is required."),
189 ############################
190 ############################
192 ############################
193 ############################
196 class fleet_vehicle(osv.Model):
198 _inherit = 'mail.thread'
200 def name_get(self, cr, uid, ids, context=None):
205 reads = self.browse(cr, uid, ids, context=context)
208 if record.license_plate:
209 name = record.license_plate
210 if record.model_id.modelname:
211 name = record.model_id.modelname + ' / ' + name
212 if record.model_id.brand.name:
213 name = record.model_id.brand.name+' / '+ name
214 res.append((record.id, name))
217 def _vehicle_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
218 res = self.name_get(cr, uid, ids, context=context)
221 def act_show_log_services(self, cr, uid, ids, context=None):
222 """ This opens log view to view and add new log for this vehicle
223 @return: the service log view
225 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_services', context)
227 'default_vehicle_id': ids[0]
229 res['domain']=[('vehicle_id','=', ids[0])]
232 def act_show_log_contract(self, cr, uid, ids, context=None):
233 """ This opens log view to view and add new log for this vehicle
234 @return: the contract log view
236 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_contract', context)
238 'default_vehicle_id': ids[0]
240 res['domain']=[('vehicle_id','=', ids[0])]
243 def act_show_log_fuel(self, cr, uid, ids, context=None):
244 """ This opens log view to view and add new log for this vehicle
245 @return: the fuel log view
247 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_fuel', context)
249 'default_vehicle_id': ids[0]
251 res['domain']=[('vehicle_id','=', ids[0])]
254 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
255 res = dict.fromkeys(ids, False)
256 for record in self.browse(cr,uid,ids,context=context):
257 ids = self.pool.get('fleet.vehicle.odometer').search(cr,uid,[('vehicle_id','=',record.id)],limit=1, order='value desc')
259 res[record.id] = str(self.pool.get('fleet.vehicle.odometer').browse(cr,uid,ids[0],context=context).value)
261 res[record.id] = str(0)
264 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
269 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
270 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
272 date = time.strftime('%Y-%m-%d')
273 data = {'value' : value,'date' : date,'vehicle_id' : id}
274 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
276 self.write(cr, uid, id, {'odometer_id': ''})
279 def str_to_date(self,strdate):
280 return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:]))
282 def get_overdue_contract_reminder_fnc(self,cr,uid,ids,context=None):
287 reads = self.browse(cr,uid,ids,context=context)
292 if (record.log_contracts):
293 for element in record.log_contracts:
294 if (element.state=='open' and element.expiration_date):
295 current_date_str=time.strftime('%Y-%m-%d')
296 due_time_str=element.expiration_date
297 #due_time_str=element.browse()
298 current_date=self.str_to_date(current_date_str)
299 due_time=self.str_to_date(due_time_str)
301 diff_time=int((due_time-current_date).days)
303 overdue = overdue +1;
304 res.append((record.id,overdue))
306 res.append((record.id,0))
310 def get_overdue_contract_reminder(self,cr,uid,ids,prop,unknow_none,context=None):
311 res = self.get_overdue_contract_reminder_fnc(cr, uid, ids, context=context)
314 def get_next_contract_reminder_fnc(self,cr,uid,ids,context=None):
319 reads = self.browse(cr,uid,ids,context=context)
324 if (record.log_contracts):
325 for element in record.log_contracts:
326 if (element.state=='open' and element.expiration_date):
327 current_date_str=time.strftime('%Y-%m-%d')
328 due_time_str=element.expiration_date
329 #due_time_str=element.browse()
330 current_date=self.str_to_date(current_date_str)
331 due_time=self.str_to_date(due_time_str)
333 diff_time=int((due_time-current_date).days)
334 if diff_time<15 and diff_time>=0:
335 due_soon = due_soon +1;
336 res.append((record.id,due_soon))
338 res.append((record.id,0))
342 def get_next_contract_reminder(self, cr, uid, ids, prop, unknow_none, context=None):
343 res = self.get_next_contract_reminder_fnc(cr, uid, ids, context=context)
346 def run_scheduler(self,cr,uid,context=None):
347 ids = self.pool.get('fleet.vehicle').search(cr, uid, [], offset=0, limit=None, order=None,context=None, count=False)
348 nexts = self.get_next_contract_reminder_fnc(cr,uid,ids,context=context)
349 overdues = self.get_overdue_contract_reminder_fnc(cr,uid,ids,context=context)
350 for key,value in nexts.items():
351 if value > 0 and overdues[key] > 0:
352 self.message_post(cr, uid, [key], body=str(value) + ' contract(s) has to be renewed soon and '+str(overdues[key])+' contract(s) is (are) overdued', context=context)
354 self.message_post(cr, uid, [key], body=str(value) + ' contract(s) has to be renewed soon!', context=context)
355 elif overdues[key] > 0 :
356 self.message_post(cr, uid, [key], body=str(overdues.key) + ' contract(s) is(are) overdued!', context=context)
359 _name = 'fleet.vehicle'
360 _description = 'Fleet Vehicle'
361 #_order = 'contract_renewal_overdue desc, contract_renewal_due_soon desc'
364 'name' : fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True),
366 'company_id': fields.many2one('res.company', 'Company'),
367 'license_plate' : fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
368 'vin_sn' : fields.char('Chassis Number', size=32, required=False, help='Unique number written on the vehicle motor (VIN/SN number)'),
369 'driver' : fields.many2one('res.partner', 'Driver',required=False, help='Driver of the vehicle', domain="['|',('customer','=',True),('employee','=',True)]"),
370 'model_id' : fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'),
371 'log_fuel' : fields.one2many('fleet.vehicle.log.fuel','vehicle_id', 'Fuel Logs'),
372 'log_services' : fields.one2many('fleet.vehicle.log.services','vehicle_id', 'Services Logs'),
373 'log_contracts' : fields.one2many('fleet.vehicle.log.contract','vehicle_id', 'Contracts'),
374 'acquisition_date' : fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'),
375 'color' : fields.char('Color',size=32, help='Color of the vehicle'),
376 'state': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle', ),
377 'location' : fields.char('Location',size=32, help='Location of the vehicle (garage, ...)'),
378 'doors' : fields.integer('Doors Number', help='Number of doors of the vehicle'),
379 'tag_ids' :fields.many2many('fleet.vehicle.tag','fleet_vehicle_vehicle_tag_rel','vehicle_tag_id','tag_id','Tags'),
381 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer Value',store=False,help='Odometer measure of the vehicle at the moment of this log'),
382 'odometer_unit': fields.selection([('kilometers', 'Kilometers'),('miles','Miles')], 'Odometer Unit', help='Unit of the odometer ',required=False),
384 'transmission' : fields.selection([('manual', 'Manual'),('automatic','Automatic')], 'Transmission', help='Transmission Used by the vehicle',required=False),
385 'fuel_type' : fields.selection([('gasoline', 'Gasoline'),('diesel','Diesel'),('electric','Electric'),('hybrid','Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle',required=False),
386 'horsepower' : fields.integer('Horsepower',required=False),
387 'horsepower_tax': fields.float('Horsepower Taxation'),
388 'power' : fields.integer('Power (kW)',required=False,help='Power in kW of the vehicle'),
389 'co2' : fields.float('CO2 Emissions',required=False,help='CO2 emissions of the vehicle'),
391 'image': fields.related('model_id','image',type="binary",string="Logo",store=False),
392 'image_medium': fields.related('model_id','image_medium',type="binary",string="Logo",store=False),
393 'image_small': fields.related('model_id','image_small',type="binary",string="Logo",store=False),
395 'contract_renewal_due_soon' : fields.function(get_next_contract_reminder,type="integer",string='Contract Renewal Due Soon',store=False),
396 'contract_renewal_overdue' : fields.function(get_overdue_contract_reminder,type="integer",string='Contract Renewal Overdue',store=False),
398 'car_value': fields.float('Car value', help='Value of the bought vehicle'),
399 #'leasing_value': fields.float('Leasing value',help='Value of the leasing(Monthly, usually'),
404 'odometer_unit' : 'kilometers',
407 def copy(self, cr, uid, id, default=None, context=None):
412 # 'name': self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint') or '',
419 return super(fleet_vehicle, self).copy(cr, uid, id, default, context=context)
421 def on_change_model(self, cr, uid, ids, model_id, context=None):
426 model = self.pool.get('fleet.vehicle.model').browse(cr, uid, model_id, context=context)
430 'image' : model.image,
433 def create(self, cr, uid, data, context=None):
434 vehicle_id = super(fleet_vehicle, self).create(cr, uid, data, context=context)
436 vehicle = self.browse(cr, uid, vehicle_id, context=context)
437 self.message_post(cr, uid, [vehicle_id], body='Vehicle %s has been added to the fleet!' % (vehicle.license_plate), context=context)
439 pass # group deleted: do not push a message
442 def write(self, cr, uid, ids, vals, context=None):
445 value = self.pool.get('res.partner').browse(cr,uid,vals['driver'],context=context).name
446 changes.append('Driver: from \'' + self.browse(cr, uid, ids, context)[0].driver.name + '\' to \'' + value+'\'')
448 value = self.pool.get('fleet.vehicle.state').browse(cr,uid,vals['state'],context=context).name
449 changes.append('State: from \'' + self.browse(cr, uid, ids, context)[0].state.name + '\' to \'' + value+'\'')
450 if 'license_plate' in vals:
451 changes.append('License Plate: from \'' + self.browse(cr, uid, ids, context)[0].license_plate + '\' to \'' + vals['license_plate']+'\'')
453 vehicle_id = super(fleet_vehicle,self).write(cr, uid, ids, vals, context)
457 self.message_post(cr, uid, [self.browse(cr, uid, ids, context)[0].id], body=", ".join(changes), context=context)
458 except Exception as e:
463 ############################
464 ############################
465 #Vehicle.odometer class
466 ############################
467 ############################
469 class fleet_vehicle_odometer(osv.Model):
470 _name='fleet.vehicle.odometer'
471 _description='Odometer log for a vehicle'
475 def name_get(self, cr, uid, ids, context=None):
480 reads = self.browse(cr, uid, ids, context=context)
483 if record.vehicle_id.name:
484 name = str(record.vehicle_id.name)
486 name = name+ ' / '+ str(record.date)
487 res.append((record.id, name))
490 def _vehicle_log_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
491 res = self.name_get(cr, uid, ids, context=context)
493 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
498 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
502 'unit' : odometer_unit,
507 'name' : fields.function(_vehicle_log_name_get_fnc, type="char", string='Name', store=True),
509 'date' : fields.date('Purchase Date'),
510 'value' : fields.float('Odometer Value',group_operator="max"),
511 'vehicle_id' : fields.many2one('fleet.vehicle', 'Vehicle', required=True),
512 'unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
516 'date' : time.strftime('%Y-%m-%d')
519 ############################
520 ############################
522 ############################
523 ############################
526 ############################
527 ############################
528 #Vehicle.log.fuel class
529 ############################
530 ############################
533 class fleet_vehicle_log_fuel(osv.Model):
535 #_inherits = {'fleet.vehicle.odometer': 'odometer_id'}
536 _inherits = {'fleet.vehicle.cost': 'cost_id'}
538 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
543 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
547 'odometer_unit' : odometer_unit,
551 def on_change_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
553 if liter > 0 and price_per_liter > 0:
554 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
555 elif liter > 0 and amount > 0:
556 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
557 elif price_per_liter > 0 and amount > 0:
558 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
562 def on_change_price_per_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
564 liter = float(liter);
565 price_per_liter = float(price_per_liter);
566 if price_per_liter > 0 and liter > 0:
567 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
568 elif price_per_liter > 0 and amount > 0:
569 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
570 elif liter > 0 and amount > 0:
571 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
575 def on_change_amount(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
577 if amount > 0 and liter > 0:
578 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
579 elif amount > 0 and price_per_liter > 0:
580 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
581 elif liter > 0 and price_per_liter > 0:
582 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
586 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
587 res = dict.fromkeys(ids, False)
588 for record in self.browse(cr,uid,ids,context=context):
589 if record.odometer_id:
590 res[record.id] = record.odometer_id.value
593 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
598 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
599 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
601 date = self.browse(cr, uid, id, context=context).date
603 date = time.strftime('%Y-%m-%d')
604 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
605 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
606 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
607 self.write(cr, uid, id, {'odometer_id': odometer_id})
609 self.write(cr, uid, id, {'odometer_id': ''})
612 def _get_default_service_type(self, cr, uid, context):
613 model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_service_refueling')
616 _name = 'fleet.vehicle.log.fuel'
619 #'name' : fields.char('Name',size=64),
620 'liter' : fields.float('Liter'),
621 'price_per_liter' : fields.float('Price Per Liter'),
622 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"),
623 'inv_ref' : fields.char('Invoice Reference', size=64),
624 'vendor_id' : fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
625 'notes' : fields.text('Notes'),
626 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
627 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer',store=False),
628 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
631 'purchaser_id': lambda self, cr, uid, ctx: uid,
632 'date' : time.strftime('%Y-%m-%d'),
633 'cost_type': _get_default_service_type,
636 ############################
637 ############################
638 #Vehicle.log.service class
639 ############################
640 ############################
643 class fleet_vehicle_log_services(osv.Model):
645 _inherits = {'fleet.vehicle.cost': 'cost_id'}
647 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
652 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
656 'odometer_unit' : odometer_unit,
660 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
661 res = dict.fromkeys(ids, False)
662 for record in self.browse(cr,uid,ids,context=context):
663 if record.odometer_id:
664 res[record.id] = record.odometer_id.value
667 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
672 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
673 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
675 date = self.browse(cr, uid, id, context=context).date
677 date = time.strftime('%Y-%m-%d')
678 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
679 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
680 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
681 self.write(cr, uid, id, {'odometer_id': odometer_id})
683 self.write(cr, uid, id, {'odometer_id': ''})
686 _name = 'fleet.vehicle.log.services'
689 #'name' : fields.char('Name',size=64),
691 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"),
692 'inv_ref' : fields.char('Invoice Reference', size=64),
693 'vendor_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
694 'notes' : fields.text('Notes'),
696 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
697 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer Value',store=False),
698 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
701 'purchaser_id': lambda self, cr, uid, ctx: uid,
702 'date' : time.strftime('%Y-%m-%d'),
705 ############################
706 ############################
707 #Vehicle.service.type class
708 ############################
709 ############################
711 class fleet_service_type(osv.Model):
712 _name = 'fleet.service.type'
714 'name': fields.char('Name', required=True, translate=True),
715 'category': fields.selection([('contract', 'Contract'), ('service', 'Service'),('both', 'Both')], 'Category',required=True, help='Choose wheter the service refer to contracts, vehicle services or both'),
721 ############################
722 ############################
723 #Vehicle.log.contract class
724 ############################
725 ############################
727 class fleet_vehicle_log_contract(osv.Model):
729 _inherits = {'fleet.vehicle.cost': 'cost_id'}
731 def name_get(self, cr, uid, ids, context=None):
736 reads = self.browse(cr, uid, ids, context=context)
739 if record.vehicle_id.name:
740 name = str(record.vehicle_id.name)
741 if record.cost_type.name:
742 name = name+ ' / '+ str(record.cost_type.name)
743 res.append((record.id, name))
746 def _vehicle_contract_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
747 res = self.name_get(cr, uid, ids, context=context)
750 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
751 res = dict.fromkeys(ids, False)
752 for record in self.browse(cr,uid,ids,context=context):
753 if record.odometer_id:
754 res[record.id] = record.odometer_id.value
757 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
762 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
763 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
765 date = self.browse(cr, uid, id, context=context).date
767 date = time.strftime('%Y-%m-%d')
768 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
769 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
770 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
771 self.write(cr, uid, id, {'odometer_id': odometer_id})
773 self.write(cr, uid, id, {'odometer_id': ''})
776 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
781 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
785 'odometer_unit' : odometer_unit,
789 def compute_next_year_date(self, strdate):
790 oneyear=datetime.timedelta(days=365)
791 curdate = self.str_to_date(strdate)
792 nextyear=curdate+oneyear#int(strdate[:4])+1
793 return str(nextyear)#+strdate[4:]
795 def on_change_start_date(self, cr, uid, ids, strdate, context=None):
798 return {'value' : {'expiration_date' : self.compute_next_year_date(strdate),}}
802 def str_to_date(self,strdate):
803 return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:]))
805 def get_warning_date(self,cr,uid,ids,prop,unknow_none,context=None):
810 reads = self.browse(cr,uid,ids,context=context)
813 #if (record.reminder==True):
814 if (record.expiration_date and record.state=='open'):
815 today=self.str_to_date(time.strftime('%Y-%m-%d'))
816 renew_date = self.str_to_date(record.expiration_date)
817 diff_time=int((renew_date-today).days)
819 res.append((record.id,0))
821 res.append((record.id,diff_time))
823 res.append((record.id,-1))
825 # res.append((record.id,-1))
828 _name = 'fleet.vehicle.log.contract'
829 _order='state,expiration_date'
831 'name' : fields.function(_vehicle_contract_name_get_fnc, type="text", string='Name', store=True),
832 #'name' : fields.char('Name',size=64),
834 #'cost_type': fields.many2one('fleet.service.type', 'Service type', required=False, help='Service type purchased with this cost', domain="[('category','=','contract')]"),
836 'start_date' : fields.date('Start Date', required=False, help='Date when the coverage of the contract begins'),
837 'expiration_date' : fields.date('Expiration Date', required=False, help='Date when the coverage of the contract expirates (by default, one year after begin date)'),
838 'warning_date' : fields.function(get_warning_date,type='integer',string='Warning Date',store=False),
840 'insurer_id' :fields.many2one('res.partner', 'Insurer', domain="[('supplier','=',True)]"),
841 'purchaser_id' : fields.many2one('res.partner', 'Contractor',domain="['|',('customer','=',True),('employee','=',True)]",help='Person to which the contract is signed for'),
842 'ins_ref' : fields.char('Contract Reference', size=64),
843 'state' : fields.selection([('open', 'In Progress'), ('closed', 'Terminated')], 'Status', readonly=True, help='Choose wheter the contract is still valid or not'),
844 #'reminder' : fields.boolean('Renewal Reminder', help="Warn the user a few days before the expiration date of this contract"),
845 'notes' : fields.text('Terms and Conditions', help='Write here all supplementary informations relative to this contract'),
846 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
847 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer Value',store=False,help='Odometer measure of the vehicle at the moment of this log'),
848 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
851 'purchaser_id': lambda self, cr, uid, ctx: uid,
852 'date' : time.strftime('%Y-%m-%d'),
853 'start_date' : time.strftime('%Y-%m-%d'),
855 #'expiration_date' : self.compute_next_year_date(time.strftime('%Y-%m-%d')),
859 def copy(self, cr, uid, id, default=None, context=None):
860 default = default or {}
861 current_object = self.browse(cr,uid,id,context)
862 default['start_date'] = time.strftime('%Y-%m-%d')
863 default['expiration_date'] = self.compute_next_year_date(time.strftime('%Y-%m-%d'))
864 #default['name'] = current_object.name
865 default['ins_ref'] = ''
866 default['state'] = 'open'
867 default['notes'] = ''
868 default['date'] = time.strftime('%Y-%m-%d')
870 #default['odometer'] = current_object.odometer
871 #default['odometer_unit'] = current_object.odometer_unit
872 return super(fleet_vehicle_log_contract, self).copy(cr, uid, id, default, context=context)
874 def contract_close(self, cr, uid, ids, *args):
875 self.write(cr, uid, ids, {'state': 'closed'})
878 def contract_open(self, cr, uid, ids, *args):
879 self.write(cr, uid, ids, {'state': 'open'})
883 ############################
884 ############################
885 #Vehicle.log.contract.state class
886 ############################
887 ############################
889 class fleet_contract_state(osv.Model):
890 _name = 'fleet.contract.state'
892 'name':fields.char('Contract Status',size=32),