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 _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
256 res = dict.fromkeys(ids, False)
257 for record in self.browse(cr,uid,ids,context=context):
258 ids = self.pool.get('fleet.vehicle.odometer').search(cr,uid,[('vehicle_id','=',record.id)],limit=1, order='value desc')
260 res[record.id] = str(self.pool.get('fleet.vehicle.odometer').browse(cr,uid,ids[0],context=context).value)
262 res[record.id] = str(0)
265 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
270 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
271 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
273 date = time.strftime('%Y-%m-%d')
274 data = {'value' : value,'date' : date,'vehicle_id' : id}
275 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
277 self.write(cr, uid, id, {'odometer_id': ''})
280 def str_to_date(self,strdate):
281 return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:]))
283 def get_overdue_contract_reminder_fnc(self,cr,uid,ids,context=None):
288 reads = self.browse(cr,uid,ids,context=context)
293 if (record.log_contracts):
294 for element in record.log_contracts:
295 if (element.state=='open' and element.expiration_date):
296 current_date_str=time.strftime('%Y-%m-%d')
297 due_time_str=element.expiration_date
298 #due_time_str=element.browse()
299 current_date=self.str_to_date(current_date_str)
300 due_time=self.str_to_date(due_time_str)
302 diff_time=int((due_time-current_date).days)
304 overdue = overdue +1;
305 res.append((record.id,overdue))
307 res.append((record.id,0))
311 def get_overdue_contract_reminder(self,cr,uid,ids,prop,unknow_none,context=None):
312 res = self.get_overdue_contract_reminder_fnc(cr, uid, ids, context=context)
315 def get_next_contract_reminder_fnc(self,cr,uid,ids,context=None):
320 reads = self.browse(cr,uid,ids,context=context)
325 if (record.log_contracts):
326 for element in record.log_contracts:
327 if (element.state=='open' and element.expiration_date):
328 current_date_str=time.strftime('%Y-%m-%d')
329 due_time_str=element.expiration_date
330 #due_time_str=element.browse()
331 current_date=self.str_to_date(current_date_str)
332 due_time=self.str_to_date(due_time_str)
334 diff_time=int((due_time-current_date).days)
335 if diff_time<15 and diff_time>=0:
336 due_soon = due_soon +1;
337 res.append((record.id,due_soon))
339 res.append((record.id,0))
343 def get_next_contract_reminder(self, cr, uid, ids, prop, unknow_none, context=None):
344 res = self.get_next_contract_reminder_fnc(cr, uid, ids, context=context)
347 def run_scheduler(self,cr,uid,context=None):
348 ids = self.pool.get('fleet.vehicle').search(cr, uid, [], offset=0, limit=None, order=None,context=None, count=False)
349 nexts = self.get_next_contract_reminder_fnc(cr,uid,ids,context=context)
350 overdues = self.get_overdue_contract_reminder_fnc(cr,uid,ids,context=context)
351 for key,value in nexts.items():
352 if value > 0 and overdues[key] > 0:
353 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)
355 self.message_post(cr, uid, [key], body=str(value) + ' contract(s) has to be renewed soon!', context=context)
356 elif overdues[key] > 0 :
357 self.message_post(cr, uid, [key], body=str(overdues[key]) + ' contract(s) is(are) overdued!', context=context)
360 _name = 'fleet.vehicle'
361 _description = 'Fleet Vehicle'
362 #_order = 'contract_renewal_overdue desc, contract_renewal_due_soon desc'
363 _order= 'license_plate asc'
365 'name' : fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True),
367 'company_id': fields.many2one('res.company', 'Company'),
368 'license_plate' : fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'),
369 'vin_sn' : fields.char('Chassis Number', size=32, required=False, help='Unique number written on the vehicle motor (VIN/SN number)'),
370 'driver' : fields.many2one('res.partner', 'Driver',required=False, help='Driver of the vehicle', domain="[('employee','=',True)]"),
371 'model_id' : fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'),
372 'log_fuel' : fields.one2many('fleet.vehicle.log.fuel','vehicle_id', 'Fuel Logs'),
373 'log_services' : fields.one2many('fleet.vehicle.log.services','vehicle_id', 'Services Logs'),
374 'log_contracts' : fields.one2many('fleet.vehicle.log.contract','vehicle_id', 'Contracts'),
375 'acquisition_date' : fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'),
376 'color' : fields.char('Color',size=32, help='Color of the vehicle'),
377 'state': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle'),
378 'location' : fields.char('Location',size=32, help='Location of the vehicle (garage, ...)'),
379 'doors' : fields.integer('Doors Number', help='Number of doors of the vehicle'),
380 'tag_ids' :fields.many2many('fleet.vehicle.tag','fleet_vehicle_vehicle_tag_rel','vehicle_tag_id','tag_id','Tags'),
382 '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'),
383 'odometer_unit': fields.selection([('kilometers', 'Kilometers'),('miles','Miles')], 'Odometer Unit', help='Unit of the odometer ',required=True),
385 'transmission' : fields.selection([('manual', 'Manual'),('automatic','Automatic')], 'Transmission', help='Transmission Used by the vehicle',required=False),
386 'fuel_type' : fields.selection([('gasoline', 'Gasoline'),('diesel','Diesel'),('electric','Electric'),('hybrid','Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle',required=False),
387 'horsepower' : fields.integer('Horsepower',required=False),
388 'horsepower_tax': fields.float('Horsepower Taxation'),
389 'power' : fields.integer('Power (kW)',required=False,help='Power in kW of the vehicle'),
390 'co2' : fields.float('CO2 Emissions',required=False,help='CO2 emissions of the vehicle'),
392 'image': fields.related('model_id','image',type="binary",string="Logo",store=False),
393 'image_medium': fields.related('model_id','image_medium',type="binary",string="Logo",store=False),
394 'image_small': fields.related('model_id','image_small',type="binary",string="Logo",store=False),
396 'contract_renewal_due_soon' : fields.function(get_next_contract_reminder,type="integer",string='Contract Renewal Due Soon',store=False),
397 'contract_renewal_overdue' : fields.function(get_overdue_contract_reminder,type="integer",string='Contract Renewal Overdue',store=False),
399 'car_value': fields.float('Car value', help='Value of the bought vehicle'),
400 #'leasing_value': fields.float('Leasing value',help='Value of the leasing(Monthly, usually'),
405 'odometer_unit' : 'kilometers',
406 'state' : lambda s,cr,uid,c:s.get_state(cr,uid,'Active',context=c),
409 def get_state(self,cr,uid,state_name,context=None):
410 states=self.pool.get('fleet.vehicle.state').search(cr,uid,[('name','=',state_name)],context=context,limit=1)
413 def copy(self, cr, uid, id, default=None, context=None):
418 # 'name': self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint') or '',
426 return super(fleet_vehicle, self).copy(cr, uid, id, default, context=context)
428 def on_change_model(self, cr, uid, ids, model_id, context=None):
433 model = self.pool.get('fleet.vehicle.model').browse(cr, uid, model_id, context=context)
437 'image' : model.image,
440 def create(self, cr, uid, data, context=None):
441 vehicle_id = super(fleet_vehicle, self).create(cr, uid, data, context=context)
443 vehicle = self.browse(cr, uid, vehicle_id, context=context)
444 self.message_post(cr, uid, [vehicle_id], body='Vehicle %s has been added to the fleet!' % (vehicle.license_plate), context=context)
446 pass # group deleted: do not push a message
449 def write(self, cr, uid, ids, vals, context=None):
452 value = self.pool.get('res.partner').browse(cr,uid,vals['driver'],context=context).name
453 changes.append('Driver: from \'' + self.browse(cr, uid, ids, context)[0].driver.name + '\' to \'' + value+'\'')
455 value = self.pool.get('fleet.vehicle.state').browse(cr,uid,vals['state'],context=context).name
456 changes.append('State: from \'' + self.browse(cr, uid, ids, context)[0].state.name + '\' to \'' + value+'\'')
457 if 'license_plate' in vals:
458 changes.append('License Plate: from \'' + self.browse(cr, uid, ids, context)[0].license_plate + '\' to \'' + vals['license_plate']+'\'')
460 vehicle_id = super(fleet_vehicle,self).write(cr, uid, ids, vals, context)
464 self.message_post(cr, uid, [self.browse(cr, uid, ids, context)[0].id], body=", ".join(changes), context=context)
465 except Exception as e:
470 ############################
471 ############################
472 #Vehicle.odometer class
473 ############################
474 ############################
476 class fleet_vehicle_odometer(osv.Model):
477 _name='fleet.vehicle.odometer'
478 _description='Odometer log for a vehicle'
482 def name_get(self, cr, uid, ids, context=None):
487 reads = self.browse(cr, uid, ids, context=context)
490 if record.vehicle_id.name:
491 name = str(record.vehicle_id.name)
493 name = name+ ' / '+ str(record.date)
494 res.append((record.id, name))
497 def _vehicle_log_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
498 res = self.name_get(cr, uid, ids, context=context)
500 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
505 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
509 'unit' : odometer_unit,
514 'name' : fields.function(_vehicle_log_name_get_fnc, type="char", string='Name', store=True),
516 'date' : fields.date('Purchase Date'),
517 'value' : fields.float('Odometer Value',group_operator="max"),
518 'vehicle_id' : fields.many2one('fleet.vehicle', 'Vehicle', required=True),
519 'unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
523 'date' : time.strftime('%Y-%m-%d')
526 ############################
527 ############################
529 ############################
530 ############################
533 ############################
534 ############################
535 #Vehicle.log.fuel class
536 ############################
537 ############################
540 class fleet_vehicle_log_fuel(osv.Model):
542 #_inherits = {'fleet.vehicle.odometer': 'odometer_id'}
543 _inherits = {'fleet.vehicle.cost': 'cost_id'}
545 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
550 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
554 'odometer_unit' : odometer_unit,
558 def on_change_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
560 if liter > 0 and price_per_liter > 0:
561 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
562 elif liter > 0 and amount > 0:
563 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
564 elif price_per_liter > 0 and amount > 0:
565 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
569 def on_change_price_per_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
571 liter = float(liter);
572 price_per_liter = float(price_per_liter);
573 if price_per_liter > 0 and liter > 0:
574 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
575 elif price_per_liter > 0 and amount > 0:
576 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
577 elif liter > 0 and amount > 0:
578 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
582 def on_change_amount(self, cr, uid, ids, liter, price_per_liter, amount, context=None):
584 if amount > 0 and liter > 0:
585 return {'value' : {'price_per_liter' : float(amount) / float(liter),}}
586 elif amount > 0 and price_per_liter > 0:
587 return {'value' : {'liter' : float(amount) / float(price_per_liter),}}
588 elif liter > 0 and price_per_liter > 0:
589 return {'value' : {'amount' : float(liter) * float(price_per_liter),}}
593 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
594 res = dict.fromkeys(ids, False)
595 for record in self.browse(cr,uid,ids,context=context):
596 if record.odometer_id:
597 res[record.id] = record.odometer_id.value
600 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
605 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
606 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
608 date = self.browse(cr, uid, id, context=context).date
610 date = time.strftime('%Y-%m-%d')
611 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
612 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
613 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
614 self.write(cr, uid, id, {'odometer_id': odometer_id})
616 self.write(cr, uid, id, {'odometer_id': ''})
619 def _get_default_service_type(self, cr, uid, context):
620 model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_service_refueling')
623 _name = 'fleet.vehicle.log.fuel'
626 #'name' : fields.char('Name',size=64),
627 'liter' : fields.float('Liter'),
628 'price_per_liter' : fields.float('Price Per Liter'),
629 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"),
630 'inv_ref' : fields.char('Invoice Reference', size=64),
631 'vendor_id' : fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
632 'notes' : fields.text('Notes'),
633 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
634 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer',store=False),
635 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
636 'amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True),
639 'purchaser_id': lambda self, cr, uid, ctx: uid,
640 'date' : time.strftime('%Y-%m-%d'),
641 'cost_type': _get_default_service_type,
644 ############################
645 ############################
646 #Vehicle.log.service class
647 ############################
648 ############################
651 class fleet_vehicle_log_services(osv.Model):
653 _inherits = {'fleet.vehicle.cost': 'cost_id'}
655 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
660 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
664 'odometer_unit' : odometer_unit,
668 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
669 res = dict.fromkeys(ids, False)
670 for record in self.browse(cr,uid,ids,context=context):
671 if record.odometer_id:
672 res[record.id] = record.odometer_id.value
675 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
680 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
681 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
683 date = self.browse(cr, uid, id, context=context).date
685 date = time.strftime('%Y-%m-%d')
686 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
687 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
688 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
689 self.write(cr, uid, id, {'odometer_id': odometer_id})
691 self.write(cr, uid, id, {'odometer_id': ''})
694 _name = 'fleet.vehicle.log.services'
697 #'name' : fields.char('Name',size=64),
699 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"),
700 'inv_ref' : fields.char('Invoice Reference', size=64),
701 'vendor_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"),
702 'notes' : fields.text('Notes'),
704 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
705 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer Value',store=False),
706 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
707 'amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True),
710 'purchaser_id': lambda self, cr, uid, ctx: uid,
711 'date' : time.strftime('%Y-%m-%d'),
714 ############################
715 ############################
716 #Vehicle.service.type class
717 ############################
718 ############################
720 class fleet_service_type(osv.Model):
721 _name = 'fleet.service.type'
723 'name': fields.char('Name', required=True, translate=True),
724 'category': fields.selection([('contract', 'Contract'), ('service', 'Service'),('both', 'Both')], 'Category',required=True, help='Choose wheter the service refer to contracts, vehicle services or both'),
730 ############################
731 ############################
732 #Vehicle.log.contract class
733 ############################
734 ############################
736 class fleet_vehicle_log_contract(osv.Model):
738 _inherits = {'fleet.vehicle.cost': 'cost_id'}
740 def name_get(self, cr, uid, ids, context=None):
745 reads = self.browse(cr, uid, ids, context=context)
748 if record.vehicle_id.name:
749 name = str(record.vehicle_id.name)
750 if record.cost_type.name:
751 name = name+ ' / '+ str(record.cost_type.name)
752 res.append((record.id, name))
755 def _vehicle_contract_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None):
756 res = self.name_get(cr, uid, ids, context=context)
759 def _get_odometer(self, cr, uid, ids, odometer_id, arg, context):
760 res = dict.fromkeys(ids, False)
761 for record in self.browse(cr,uid,ids,context=context):
762 if record.odometer_id:
763 res[record.id] = record.odometer_id.value
766 def _set_odometer(self, cr, uid, id, name, value, args=None, context=None):
771 #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field')
772 raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field')
774 date = self.browse(cr, uid, id, context=context).date
776 date = time.strftime('%Y-%m-%d')
777 vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id
778 data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id}
779 odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context)
780 self.write(cr, uid, id, {'odometer_id': odometer_id})
782 self.write(cr, uid, id, {'odometer_id': ''})
785 def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None):
790 odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit
794 'odometer_unit' : odometer_unit,
798 def compute_next_year_date(self, strdate):
799 oneyear=datetime.timedelta(days=365)
800 curdate = self.str_to_date(strdate)
801 nextyear=curdate+oneyear#int(strdate[:4])+1
802 return str(nextyear)#+strdate[4:]
804 def on_change_start_date(self, cr, uid, ids, strdate, context=None):
807 return {'value' : {'expiration_date' : self.compute_next_year_date(strdate),}}
811 def str_to_date(self,strdate):
812 return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:]))
814 def get_warning_date(self,cr,uid,ids,prop,unknow_none,context=None):
819 reads = self.browse(cr,uid,ids,context=context)
822 #if (record.reminder==True):
823 if (record.expiration_date and record.state=='open'):
824 today=self.str_to_date(time.strftime('%Y-%m-%d'))
825 renew_date = self.str_to_date(record.expiration_date)
826 diff_time=int((renew_date-today).days)
828 res.append((record.id,0))
830 res.append((record.id,diff_time))
832 res.append((record.id,-1))
834 # res.append((record.id,-1))
837 _name = 'fleet.vehicle.log.contract'
838 _order='state,expiration_date'
840 'name' : fields.function(_vehicle_contract_name_get_fnc, type="text", string='Name', store=True),
841 #'name' : fields.char('Name',size=64),
843 #'cost_type': fields.many2one('fleet.service.type', 'Service type', required=False, help='Service type purchased with this cost', domain="[('category','=','contract')]"),
845 'start_date' : fields.date('Start Date', required=False, help='Date when the coverage of the contract begins'),
846 'expiration_date' : fields.date('Expiration Date', required=False, help='Date when the coverage of the contract expirates (by default, one year after begin date)'),
847 'warning_date' : fields.function(get_warning_date,type='integer',string='Warning Date',store=False),
849 'insurer_id' :fields.many2one('res.partner', 'Insurer', domain="[('supplier','=',True)]"),
850 'purchaser_id' : fields.many2one('res.partner', 'Contractor',domain="['|',('customer','=',True),('employee','=',True)]",help='Person to which the contract is signed for'),
851 'ins_ref' : fields.char('Contract Reference', size=64),
852 'state' : fields.selection([('open', 'In Progress'), ('closed', 'Terminated')], 'Status', readonly=True, help='Choose wheter the contract is still valid or not'),
853 #'reminder' : fields.boolean('Renewal Reminder', help="Warn the user a few days before the expiration date of this contract"),
854 'notes' : fields.text('Terms and Conditions', help='Write here all supplementary informations relative to this contract'),
855 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'),
856 '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'),
857 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True),
860 'purchaser_id': lambda self, cr, uid, ctx: uid,
861 'date' : time.strftime('%Y-%m-%d'),
862 'start_date' : time.strftime('%Y-%m-%d'),
864 #'expiration_date' : self.compute_next_year_date(time.strftime('%Y-%m-%d')),
868 def copy(self, cr, uid, id, default=None, context=None):
869 default = default or {}
870 current_object = self.browse(cr,uid,id,context)
871 default['start_date'] = time.strftime('%Y-%m-%d')
872 default['expiration_date'] = self.compute_next_year_date(time.strftime('%Y-%m-%d'))
873 #default['name'] = current_object.name
874 default['ins_ref'] = ''
875 default['state'] = 'open'
876 default['notes'] = ''
877 default['date'] = time.strftime('%Y-%m-%d')
879 #default['odometer'] = current_object.odometer
880 #default['odometer_unit'] = current_object.odometer_unit
881 return super(fleet_vehicle_log_contract, self).copy(cr, uid, id, default, context=context)
883 def contract_close(self, cr, uid, ids, *args):
884 self.write(cr, uid, ids, {'state': 'closed'})
887 def contract_open(self, cr, uid, ids, *args):
888 self.write(cr, uid, ids, {'state': 'open'})
892 ############################
893 ############################
894 #Vehicle.log.contract.state class
895 ############################
896 ############################
898 class fleet_contract_state(osv.Model):
899 _name = 'fleet.contract.state'
901 'name':fields.char('Contract Status',size=32),