1 from itertools import chain
2 from osv import osv, fields
6 from osv.orm import except_orm
7 from tools.translate import _
8 ############################
9 ############################
11 ############################
12 ############################
14 class fleet_vehicle_cost(osv.Model):
15 _name = 'fleet.vehicle.cost'
16 _description = 'Cost of vehicle'
17 _order = 'date desc, vehicle_id asc'
19 def name_get(self, cr, uid, ids, context=None):
24 reads = self.browse(cr, uid, ids, context=context)
27 if record.vehicle_id.license_plate:
28 name = record.vehicle_id.license_plate
29 if record.cost_type.name:
30 name = name + ' / '+ record.cost_type.name
32 name = name + ' / '+ record.date
33 res.append((record.id, name))
36 def _cost_name_get_fnc(self, cr, uid, ids, name, unknow_none, context=None):
37 res = self.name_get(cr, uid, ids, context=context)
41 'name' : fields.function(_cost_name_get_fnc, type="char", string='Name', store=True),
42 #'name' : fields.char('Name',size=32),
43 'vehicle_id': fields.many2one('fleet.vehicle', 'Vehicle', required=True, help='Vehicle concerned by this fuel log'),
44 'cost_type': fields.many2one('fleet.service.type', 'Service type', required=False, help='Service type purchased with this cost'),
45 'amount': fields.float('Total Price'),
47 'parent_id': fields.many2one('fleet.vehicle.cost', 'Parent', required=False, help='Parent cost to this current cost'),
48 'cost_ids' : fields.one2many('fleet.vehicle.cost', 'parent_id', 'Included Services'),
50 'date' :fields.date('Cost Date',help='Date when the cost has been executed'),
59 def create(self, cr, uid, data, context=None):
60 if 'parent_id' in data and data['parent_id']:
61 data['vehicle_id'] = self.browse(cr, uid, data['parent_id'], context=context).vehicle_id.id
62 data['date'] = self.browse(cr, uid, data['parent_id'], context=context).date
63 cost_id = super(fleet_vehicle_cost, self).create(cr, uid, data, context=context)
66 ############################
67 ############################
69 ############################
70 ############################
72 class fleet_vehicle_tag(osv.Model):
73 _name = 'fleet.vehicle.tag'
75 'name': fields.char('Name', required=True, translate=True),
78 ############################
79 ############################
81 ############################
82 ############################
84 class fleet_vehicle_state(osv.Model):
85 _name = 'fleet.vehicle.state'
87 'name': fields.char('Name', required=True),
88 'sequence': fields.integer('Order',help="Used to order the note stages")
90 _order = 'sequence asc'
91 _sql_constraints = [('fleet_state_name_unique','unique(name)','State name already exists')]
94 ############################
95 ############################
97 ############################
98 ############################
100 class fleet_vehicle_model(osv.Model):
102 def name_get(self, cr, uid, ids, context=None):
107 reads = self.browse(cr, uid, ids, context=context)
110 name = record.modelname
111 if record.brand.name:
112 name = record.brand.name+' / '+name
113 res.append((record.id, name))
116 def _model_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
117 res = self.name_get(cr, uid, ids, context=context)
120 def on_change_brand(self, cr, uid, ids, model_id, context=None):
125 brand = self.pool.get('fleet.vehicle.model.brand').browse(cr, uid, model_id, context=context)
129 'image' : brand.image,
133 _name = 'fleet.vehicle.model'
134 _description = 'Model of a vehicle'
137 'name' : fields.function(_model_name_get_fnc, type="char", string='Name', store=True),
138 'modelname' : fields.char('Model name', size=32, required=True),
139 'brand' : fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'),
140 'vendors': fields.many2many('res.partner','fleet_vehicle_model_vendors','model_id', 'partner_id',string='Vendors',required=False),
141 'image': fields.related('brand','image',type="binary",string="Logo",store=False),
142 'image_medium': fields.related('brand','image_medium',type="binary",string="Logo",store=False),
143 'image_small': fields.related('brand','image_small',type="binary",string="Logo",store=False),
146 ############################
147 ############################
149 ############################
150 ############################
152 class fleet_vehicle_model_brand(osv.Model):
153 _name = 'fleet.vehicle.model.brand'
154 _description = 'Brand model of the vehicle'
158 def _get_image(self, cr, uid, ids, name, args, context=None):
159 result = dict.fromkeys(ids, False)
160 for obj in self.browse(cr, uid, ids, context=context):
161 result[obj.id] = tools.image_get_resized_images(obj.image)
164 def _set_image(self, cr, uid, id, name, value, args, context=None):
165 return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
168 'name' : fields.char('Brand Name',size=32, required=True),
170 'image': fields.binary("Logo",
171 help="This field holds the image used as logo for the brand, limited to 1024x1024px."),
172 'image_medium': fields.function(_get_image, fnct_inv=_set_image,
173 string="Medium-sized photo", type="binary", multi="_get_image",
175 'fleet.vehicle.model.brand': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
177 help="Medium-sized logo of the brand. It is automatically "\
178 "resized as a 128x128px image, with aspect ratio preserved. "\
179 "Use this field in form views or some kanban views."),
180 'image_small': fields.function(_get_image, fnct_inv=_set_image,
181 string="Smal-sized photo", type="binary", multi="_get_image",
183 'fleet.vehicle.model.brand': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
185 help="Small-sized photo of the brand. It is automatically "\
186 "resized as a 64x64px image, with aspect ratio preserved. "\
187 "Use this field anywhere a small image is required."),
190 ############################
191 ############################
193 ############################
194 ############################
197 class fleet_vehicle(osv.Model):
199 _inherit = 'mail.thread'
201 def name_get(self, cr, uid, ids, context=None):
206 reads = self.browse(cr, uid, ids, context=context)
209 if record.license_plate:
210 name = record.license_plate
211 if record.model_id.modelname:
212 name = record.model_id.modelname + ' / ' + name
213 if record.model_id.brand.name:
214 name = record.model_id.brand.name+' / '+ name
215 res.append((record.id, name))
218 def _vehicle_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
219 res = self.name_get(cr, uid, ids, context=context)
222 def act_show_log_services(self, cr, uid, ids, context=None):
223 """ This opens log view to view and add new log for this vehicle
224 @return: the service log view
226 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_services', context)
228 'default_vehicle_id': ids[0]
230 res['domain']=[('vehicle_id','=', ids[0])]
233 def act_show_log_contract(self, cr, uid, ids, context=None):
234 """ This opens log view to view and add new log for this vehicle
235 @return: the contract log view
237 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_contract', context)
239 'default_vehicle_id': ids[0]
241 res['domain']=[('vehicle_id','=', ids[0])]
244 def act_show_log_fuel(self, cr, uid, ids, context=None):
245 """ This opens log view to view and add new log for this vehicle
246 @return: the fuel log view
248 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_fuel', context)
250 'default_vehicle_id': ids[0]
252 res['domain']=[('vehicle_id','=', ids[0])]
255 def act_show_log_cost(self, cr, uid, ids, context=None):
256 """ This opens log view to view and add new log for this vehicle
257 @return: the costs log view
259 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_cost', context)
261 'default_vehicle_id': ids[0]
263 res['domain']=[('vehicle_id','=', ids[0])]
266 def act_show_log_odometer(self, cr, uid, ids, context=None):
267 """ This opens log view to view and add new log for this vehicle
268 @return: the odometer log view
270 res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_show_log_odometer', context)
272 'default_vehicle_id': ids[0]
274 res['domain']=[('vehicle_id','=', ids[0])]
277 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
278 res = dict.fromkeys(ids, False)
279 for record in self.browse(cr,uid,ids,context=context):
280 ids = self.pool.get('fleet.vehicle.odometer').search(cr,uid,[('vehicle_id','=',record.id)],limit=1, order='value desc')
282 res[record.id] = str(self.pool.get('fleet.vehicle.odometer').browse(cr,uid,ids[0],context=context).value)
284 res[record.id] = str(0)
287 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
292 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
293 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
295 date = time.strftime('%Y-%m-%d')
296 data = {'value' : value,'date' : date,'vehicle_id' : id}
297 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
299 self.write(cr, uid, id, {'odometer_id': ''})
302 def str_to_date(self,strdate):
303 return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:]))
305 def get_overdue_contract_reminder_fnc(self,cr,uid,ids,context=None):
310 reads = self.browse(cr,uid,ids,context=context)
315 if (record.log_contracts):
316 for element in record.log_contracts:
317 if (element.state=='open' and element.expiration_date):
318 current_date_str=time.strftime('%Y-%m-%d')
319 due_time_str=element.expiration_date
320 #due_time_str=element.browse()
321 current_date=self.str_to_date(current_date_str)
322 due_time=self.str_to_date(due_time_str)
324 diff_time=int((due_time-current_date).days)
326 overdue = overdue +1;
327 res.append((record.id,overdue))
329 res.append((record.id,0))
333 def get_overdue_contract_reminder(self,cr,uid,ids,prop,unknow_none,context=None):
334 res = self.get_overdue_contract_reminder_fnc(cr, uid, ids, context=context)
337 def get_next_contract_reminder_fnc(self,cr,uid,ids,context=None):
342 reads = self.browse(cr,uid,ids,context=context)
347 if (record.log_contracts):
348 for element in record.log_contracts:
349 if (element.state=='open' and element.expiration_date):
350 current_date_str=time.strftime('%Y-%m-%d')
351 due_time_str=element.expiration_date
352 #due_time_str=element.browse()
353 current_date=self.str_to_date(current_date_str)
354 due_time=self.str_to_date(due_time_str)
356 diff_time=int((due_time-current_date).days)
357 if diff_time<15 and diff_time>=0:
358 due_soon = due_soon +1;
359 res.append((record.id,due_soon))
361 res.append((record.id,0))
365 def get_next_contract_reminder(self, cr, uid, ids, prop, unknow_none, context=None):
366 res = self.get_next_contract_reminder_fnc(cr, uid, ids, context=context)
369 def run_scheduler(self,cr,uid,context=None):
370 ids = self.pool.get('fleet.vehicle').search(cr, uid, [], offset=0, limit=None, order=None,context=None, count=False)
371 nexts = self.get_next_contract_reminder_fnc(cr,uid,ids,context=context)
372 overdues = self.get_overdue_contract_reminder_fnc(cr,uid,ids,context=context)
373 for key,value in nexts.items():
374 if value > 0 and overdues[key] > 0:
375 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)
377 self.message_post(cr, uid, [key], body=str(value) + ' contract(s) has to be renewed soon!', context=context)
378 elif overdues[key] > 0 :
379 self.message_post(cr, uid, [key], body=str(overdues[key]) + ' contract(s) is(are) overdued!', context=context)
382 _name = 'fleet.vehicle'
383 _description = 'Fleet Vehicle'
384 #_order = 'contract_renewal_overdue desc, contract_renewal_due_soon desc'
385 _order= 'license_plate asc'
387 'name' : fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True),
389 'company_id': fields.many2one('res.company', 'Company'),
390 'license_plate' : fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
391 'vin_sn' : fields.char('Chassis Number', size=32, required=False, help='Unique number written on the vehicle motor (VIN/SN number)'),
392 'driver' : fields.many2one('res.partner', 'Driver',required=False, help='Driver of the vehicle'),
393 'model_id' : fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'),
394 'log_fuel' : fields.one2many('fleet.vehicle.log.fuel','vehicle_id', 'Fuel Logs'),
395 'log_services' : fields.one2many('fleet.vehicle.log.services','vehicle_id', 'Services Logs'),
396 'log_contracts' : fields.one2many('fleet.vehicle.log.contract','vehicle_id', 'Contracts'),
397 'acquisition_date' : fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'),
398 'color' : fields.char('Color',size=32, help='Color of the vehicle'),
399 'state': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle',ondelete="set null"),
400 'location' : fields.char('Location',size=32, help='Location of the vehicle (garage, ...)'),
401 'seats' : fields.integer('Seats Number', help='Number of seats of the vehicle'),
402 'doors' : fields.integer('Doors Number', help='Number of doors of the vehicle'),
403 'tag_ids' :fields.many2many('fleet.vehicle.tag','fleet_vehicle_vehicle_tag_rel','vehicle_tag_id','tag_id','Tags'),
405 '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'),
406 'odometer_unit': fields.selection([('kilometers', 'Kilometers'),('miles','Miles')], 'Odometer Unit', help='Unit of the odometer ',required=True),
408 'transmission' : fields.selection([('manual', 'Manual'),('automatic','Automatic')], 'Transmission', help='Transmission Used by the vehicle',required=False),
409 'fuel_type' : fields.selection([('gasoline', 'Gasoline'),('diesel','Diesel'),('electric','Electric'),('hybrid','Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle',required=False),
410 'horsepower' : fields.integer('Horsepower',required=False),
411 'horsepower_tax': fields.float('Horsepower Taxation'),
412 'power' : fields.integer('Power (kW)',required=False,help='Power in kW of the vehicle'),
413 'co2' : fields.float('CO2 Emissions',required=False,help='CO2 emissions of the vehicle'),
415 'image': fields.related('model_id','image',type="binary",string="Logo",store=False),
416 'image_medium': fields.related('model_id','image_medium',type="binary",string="Logo",store=False),
417 'image_small': fields.related('model_id','image_small',type="binary",string="Logo",store=False),
419 'contract_renewal_due_soon' : fields.function(get_next_contract_reminder,type="integer",string='Contracts to renew',store=False),
420 'contract_renewal_overdue' : fields.function(get_overdue_contract_reminder,type="integer",string='Contracts Overdued',store=False),
422 'car_value': fields.float('Car Value', help='Value of the bought vehicle'),
423 #'leasing_value': fields.float('Leasing value',help='Value of the leasing(Monthly, usually'),
428 'odometer_unit' : 'kilometers',
429 'state' : lambda s,cr,uid,c:s.get_state(cr,uid,'Active',context=c),
432 def get_state(self,cr,uid,state_name,context=None):
433 states=self.pool.get('fleet.vehicle.state').search(cr,uid,[('name','=',state_name)],context=context,limit=1)
436 def copy(self, cr, uid, id, default=None, context=None):
441 # 'name': self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint') or '',
449 return super(fleet_vehicle, self).copy(cr, uid, id, default, context=context)
451 def on_change_model(self, cr, uid, ids, model_id, context=None):
456 model = self.pool.get('fleet.vehicle.model').browse(cr, uid, model_id, context=context)
460 'image' : model.image,
463 def create(self, cr, uid, data, context=None):
464 vehicle_id = super(fleet_vehicle, self).create(cr, uid, data, context=context)
466 vehicle = self.browse(cr, uid, vehicle_id, context=context)
467 self.message_post(cr, uid, [vehicle_id], body='Vehicle %s has been added to the fleet!' % (vehicle.license_plate), context=context)
469 pass # group deleted: do not push a message
472 def write(self, cr, uid, ids, vals, context=None):
475 value = self.pool.get('res.partner').browse(cr,uid,vals['driver'],context=context).name
476 olddriver = self.browse(cr, uid, ids, context)[0].driver
478 olddriver = olddriver.name
481 changes.append('Driver: from \'' + olddriver + '\' to \'' + value+'\'')
483 value = self.pool.get('fleet.vehicle.state').browse(cr,uid,vals['state'],context=context).name
484 oldstate = self.browse(cr, uid, ids, context)[0].state
486 oldstate=oldstate.name
489 changes.append('State: from \'' + oldstate + '\' to \'' + value+'\'')
490 if 'license_plate' in vals:
491 old_license_plate = self.browse(cr, uid, ids, context)[0].license_plate
492 if not old_license_plate:
493 old_license_plate = 'None'
494 changes.append('License Plate: from \'' + old_license_plate + '\' to \'' + vals['license_plate']+'\'')
496 vehicle_id = super(fleet_vehicle,self).write(cr, uid, ids, vals, context)
500 self.message_post(cr, uid, [self.browse(cr, uid, ids, context)[0].id], body=", ".join(changes), context=context)
501 except Exception as e:
506 ############################
507 ############################
508 #Vehicle.odometer class
509 ############################
510 ############################
512 class fleet_vehicle_odometer(osv.Model):
513 _name='fleet.vehicle.odometer'
514 _description='Odometer log for a vehicle'
518 def name_get(self, cr, uid, ids, context=None):
523 reads = self.browse(cr, uid, ids, context=context)
526 if record.vehicle_id.name:
527 name = str(record.vehicle_id.name)
529 name = name+ ' / '+ str(record.date)
530 res.append((record.id, name))
533 def _vehicle_log_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
534 res = self.name_get(cr, uid, ids, context=context)
536 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
541 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
545 'unit' : odometer_unit,
550 'name' : fields.function(_vehicle_log_name_get_fnc, type="char", string='Name', store=True),
552 'date' : fields.date('Purchase Date'),
553 'value' : fields.float('Odometer Value',group_operator="max"),
554 'vehicle_id' : fields.many2one('fleet.vehicle', 'Vehicle', required=True),
555 'unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
559 'date' : time.strftime('%Y-%m-%d')
562 ############################
563 ############################
565 ############################
566 ############################
569 ############################
570 ############################
571 #Vehicle.log.fuel class
572 ############################
573 ############################
576 class fleet_vehicle_log_fuel(osv.Model):
578 #_inherits = {'fleet.vehicle.odometer': 'odometer_id'}
579 _inherits = {'fleet.vehicle.cost': 'cost_id'}
581 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
586 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
590 'odometer_unit' : odometer_unit,
594 def on_change_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
596 if liter > 0 and price_per_liter > 0:
597 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
598 elif liter > 0 and amount > 0:
599 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
600 elif price_per_liter > 0 and amount > 0:
601 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
605 def on_change_price_per_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
607 liter = float(liter);
608 price_per_liter = float(price_per_liter);
609 if price_per_liter > 0 and liter > 0:
610 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
611 elif price_per_liter > 0 and amount > 0:
612 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
613 elif liter > 0 and amount > 0:
614 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
618 def on_change_amount(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
620 if amount > 0 and liter > 0:
621 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
622 elif amount > 0 and price_per_liter > 0:
623 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
624 elif liter > 0 and price_per_liter > 0:
625 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
629 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
630 res = dict.fromkeys(ids, False)
631 for record in self.browse(cr,uid,ids,context=context):
632 if record.odometer_id:
633 res[record.id] = record.odometer_id.value
636 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
641 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
642 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
644 date = self.browse(cr, uid, id, context=context).date
646 date = time.strftime('%Y-%m-%d')
647 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
648 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
649 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
650 self.write(cr, uid, id, {'odometer_id': odometer_id})
652 self.write(cr, uid, id, {'odometer_id': ''})
655 def _get_default_service_type(self, cr, uid, context):
656 model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_service_refueling')
659 _name = 'fleet.vehicle.log.fuel'
662 #'name' : fields.char('Name',size=64),
663 'liter' : fields.float('Liter'),
664 'price_per_liter' : fields.float('Price Per Liter'),
665 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"),
666 'inv_ref' : fields.char('Invoice Reference', size=64),
667 'vendor_id' : fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
668 'notes' : fields.text('Notes'),
669 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
670 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer',store=False),
671 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
672 'cost_amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True),
675 'purchaser_id': lambda self, cr, uid, ctx: uid,
676 'date' : time.strftime('%Y-%m-%d'),
677 'cost_type': _get_default_service_type,
680 ############################
681 ############################
682 #Vehicle.log.service class
683 ############################
684 ############################
687 class fleet_vehicle_log_services(osv.Model):
689 _inherits = {'fleet.vehicle.cost': 'cost_id'}
691 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
696 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
700 'odometer_unit' : odometer_unit,
704 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
705 res = dict.fromkeys(ids, False)
706 for record in self.browse(cr,uid,ids,context=context):
707 if record.odometer_id:
708 res[record.id] = record.odometer_id.value
711 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
716 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
717 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
719 date = self.browse(cr, uid, id, context=context).date
721 date = time.strftime('%Y-%m-%d')
722 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
723 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
724 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
725 self.write(cr, uid, id, {'odometer_id': odometer_id})
727 self.write(cr, uid, id, {'odometer_id': ''})
730 _name = 'fleet.vehicle.log.services'
733 #'name' : fields.char('Name',size=64),
735 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"),
736 'inv_ref' : fields.char('Invoice Reference', size=64),
737 'vendor_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
738 'notes' : fields.text('Notes'),
740 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
741 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer Value',store=False),
742 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
743 'cost_amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True),
746 'purchaser_id': lambda self, cr, uid, ctx: uid,
747 'date' : time.strftime('%Y-%m-%d'),
750 ############################
751 ############################
752 #Vehicle.service.type class
753 ############################
754 ############################
756 class fleet_service_type(osv.Model):
757 _name = 'fleet.service.type'
759 'name': fields.char('Name', required=True, translate=True),
760 'category': fields.selection([('contract', 'Contract'), ('service', 'Service'),('both', 'Both')], 'Category',required=True, help='Choose wheter the service refer to contracts, vehicle services or both'),
766 ############################
767 ############################
768 #Vehicle.log.contract class
769 ############################
770 ############################
772 class fleet_vehicle_log_contract(osv.Model):
774 _inherits = {'fleet.vehicle.cost': 'cost_id'}
776 def name_get(self, cr, uid, ids, context=None):
781 reads = self.browse(cr, uid, ids, context=context)
784 if record.vehicle_id.name:
785 name = str(record.vehicle_id.name)
786 if record.cost_type.name:
787 name = name+ ' / '+ str(record.cost_type.name)
788 res.append((record.id, name))
791 def _vehicle_contract_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
792 res = self.name_get(cr, uid, ids, context=context)
795 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
796 res = dict.fromkeys(ids, False)
797 for record in self.browse(cr,uid,ids,context=context):
798 if record.odometer_id:
799 res[record.id] = record.odometer_id.value
802 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
807 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
808 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
810 date = self.browse(cr, uid, id, context=context).date
812 date = time.strftime('%Y-%m-%d')
813 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
814 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
815 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
816 self.write(cr, uid, id, {'odometer_id': odometer_id})
818 self.write(cr, uid, id, {'odometer_id': ''})
821 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
826 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
830 'odometer_unit' : odometer_unit,
834 def compute_next_year_date(self, strdate):
835 oneyear=datetime.timedelta(days=365)
836 curdate = self.str_to_date(strdate)
837 nextyear=curdate+oneyear#int(strdate[:4])+1
838 return str(nextyear)#+strdate[4:]
840 def on_change_start_date(self, cr, uid, ids, strdate, context=None):
843 return {'value' : {'expiration_date' : self.compute_next_year_date(strdate),}}
847 def str_to_date(self,strdate):
848 return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:]))
850 def get_warning_date(self,cr,uid,ids,prop,unknow_none,context=None):
855 reads = self.browse(cr,uid,ids,context=context)
858 #if (record.reminder==True):
859 if (record.expiration_date and record.state=='open'):
860 today=self.str_to_date(time.strftime('%Y-%m-%d'))
861 renew_date = self.str_to_date(record.expiration_date)
862 diff_time=int((renew_date-today).days)
864 res.append((record.id,0))
866 res.append((record.id,diff_time))
868 res.append((record.id,-1))
870 # res.append((record.id,-1))
873 _name = 'fleet.vehicle.log.contract'
874 _order='state,expiration_date'
876 'name' : fields.function(_vehicle_contract_name_get_fnc, type="text", string='Name', store=True),
877 #'name' : fields.char('Name',size=64),
879 #'cost_type': fields.many2one('fleet.service.type', 'Service type', required=False, help='Service type purchased with this cost', domain="[('category','=','contract')]"),
881 'start_date' : fields.date('Contract Start Date', required=False, help='Date when the coverage of the contract begins'),
882 'expiration_date' : fields.date('Contract Expiration Date', required=False, help='Date when the coverage of the contract expirates (by default, one year after begin date)'),
883 'warning_date' : fields.function(get_warning_date,type='integer',string='Warning Date',store=False),
885 'insurer_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
886 'purchaser_id' : fields.many2one('res.partner', 'Contractor',domain="['|',('customer','=',True),('employee','=',True)]",help='Person to which the contract is signed for'),
887 'ins_ref' : fields.char('Contract Reference', size=64),
888 'state' : fields.selection([('open', 'In Progress'), ('closed', 'Terminated')], 'Status', readonly=True, help='Choose wheter the contract is still valid or not'),
889 #'reminder' : fields.boolean('Renewal Reminder', help="Warn the user a few days before the expiration date of this contract"),
890 'notes' : fields.text('Terms and Conditions', help='Write here all supplementary informations relative to this contract'),
891 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
892 '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'),
893 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
894 'cost_amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True),
897 'purchaser_id': lambda self, cr, uid, ctx: uid,
898 'date' : time.strftime('%Y-%m-%d'),
899 'start_date' : time.strftime('%Y-%m-%d'),
901 #'expiration_date' : self.compute_next_year_date(time.strftime('%Y-%m-%d')),
905 def copy(self, cr, uid, id, default=None, context=None):
906 default = default or {}
907 current_object = self.browse(cr,uid,id,context)
908 default['start_date'] = time.strftime('%Y-%m-%d')
909 default['expiration_date'] = self.compute_next_year_date(time.strftime('%Y-%m-%d'))
910 #default['name'] = current_object.name
911 default['ins_ref'] = ''
912 default['state'] = 'open'
913 default['notes'] = ''
914 default['date'] = time.strftime('%Y-%m-%d')
916 #default['odometer'] = current_object.odometer
917 #default['odometer_unit'] = current_object.odometer_unit
918 return super(fleet_vehicle_log_contract, self).copy(cr, uid, id, default, context=context)
920 def contract_close(self, cr, uid, ids, *args):
921 self.write(cr, uid, ids, {'state': 'closed'})
924 def contract_open(self, cr, uid, ids, *args):
925 self.write(cr, uid, ids, {'state': 'open'})
929 ############################
930 ############################
931 #Vehicle.log.contract.state class
932 ############################
933 ############################
935 class fleet_contract_state(osv.Model):
936 _name = 'fleet.contract.state'
938 'name':fields.char('Contract Status',size=32),