X-Git-Url: http://git.inspyration.org/?a=blobdiff_plain;f=addons%2Ffleet%2Ffleet.py;h=7c5e01415e1e19a9461af24a46aea368346710ec;hb=ee844c0ac678153015b1dc7854b0acfc0b8f9bcd;hp=611d78bff8e27958c0222c90d241cab4caa4333d;hpb=96520de1c09e24990887f638cbaaff6f834b51b6;p=odoo%2Fodoo.git diff --git a/addons/fleet/fleet.py b/addons/fleet/fleet.py index 611d78b..7c5e014 100644 --- a/addons/fleet/fleet.py +++ b/addons/fleet/fleet.py @@ -1,86 +1,101 @@ # -*- coding: utf-8 -*- -from itertools import chain -from osv import osv, fields +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2010 Tiny SPRL (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import fields, osv import time import datetime -import tools -from osv.orm import except_orm -from tools.translate import _ +from openerp import tools +from openerp.osv.orm import except_orm +from openerp.tools.translate import _ from dateutil.relativedelta import relativedelta -############################ -############################ -#Vehicle.cost class -############################ -############################ + +def str_to_datetime(strdate): + return datetime.datetime.strptime(strdate, tools.DEFAULT_SERVER_DATE_FORMAT) class fleet_vehicle_cost(osv.Model): _name = 'fleet.vehicle.cost' - _description = 'Cost of vehicle' + _description = 'Cost related to a vehicle' _order = 'date desc, vehicle_id asc' - def name_get(self, cr, uid, ids, context=None): - if context is None: - context = {} - if not ids: - return [] - reads = self.browse(cr, uid, ids, context=context) - res = [] - for record in reads: - if record.vehicle_id.license_plate: - name = record.vehicle_id.license_plate - if record.cost_subtype.name: - name = name + ' / '+ record.cost_subtype.name - if record.date: - name = name + ' / '+ record.date - res.append((record.id, name)) + def _get_odometer(self, cr, uid, ids, odometer_id, arg, context): + res = dict.fromkeys(ids, False) + for record in self.browse(cr,uid,ids,context=context): + if record.odometer_id: + res[record.id] = record.odometer_id.value return res - def year_get(self, cr, uid, ids, context=None): - if context is None: - context = {} - if not ids: - return [] - reads = self.browse(cr, uid, ids, context=context) - res = [] - for record in reads: - res.append((record.id, str(record.date[:4]))) - return res + def _set_odometer(self, cr, uid, id, name, value, args=None, context=None): + if not value: + raise except_orm(_('Operation not allowed!'), _('Emptying the odometer value of a vehicle is not allowed.')) + date = self.browse(cr, uid, id, context=context).date + if not(date): + date = fields.date.context_today(self, cr, uid, context=context) + vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id + data = {'value': value, 'date': date, 'vehicle_id': vehicle_id.id} + odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context) + return self.write(cr, uid, id, {'odometer_id': odometer_id}, context=context) def _year_get_fnc(self, cr, uid, ids, name, unknow_none, context=None): - res = self.year_get(cr, uid, ids, context=context) - return dict(res) + res = {} + for record in self.browse(cr, uid, ids, context=context): + if (record.date): + res[record.id] = str(time.strptime(record.date, tools.DEFAULT_SERVER_DATE_FORMAT).tm_year) + else: + res[record.id] = _('Unknown') + return res def _cost_name_get_fnc(self, cr, uid, ids, name, unknow_none, context=None): - res = self.name_get(cr, uid, ids, context=context) - return dict(res) + res = {} + for record in self.browse(cr, uid, ids, context=context): + name = record.vehicle_id.name + if record.cost_subtype_id.name: + name += ' / '+ record.cost_subtype_id.name + if record.date: + name += ' / '+ record.date + res[record.id] = name + return res _columns = { - 'name' : fields.function(_cost_name_get_fnc, type="char", string='Name', store=True), - #'name' : fields.char('Name',size=32), - 'vehicle_id': fields.many2one('fleet.vehicle', 'Vehicle', required=True, help='Vehicle concerned by this fuel log'), - 'cost_subtype': fields.many2one('fleet.service.type', 'Type', required=False, help='Cost type purchased with this cost'), + 'name': fields.function(_cost_name_get_fnc, type="char", string='Name', store=True), + 'vehicle_id': fields.many2one('fleet.vehicle', 'Vehicle', required=True, help='Vehicle concerned by this log'), + 'cost_subtype_id': fields.many2one('fleet.service.type', 'Type', help='Cost type purchased with this cost'), 'amount': fields.float('Total Price'), - 'cost_type' : fields.selection([('contract', 'Contract'),('services','Services'),('fuel','Fuel'),('other','Other')], 'Category of the cost', help='For internal purpose only',required=True), - 'parent_id': fields.many2one('fleet.vehicle.cost', 'Parent', required=False, help='Parent cost to this current cost'), - 'cost_ids' : fields.one2many('fleet.vehicle.cost', 'parent_id', 'Included Services'), - + 'cost_type': fields.selection([('contract', 'Contract'), ('services','Services'), ('fuel','Fuel'), ('other','Other')], 'Category of the cost', help='For internal purpose only', required=True), + 'parent_id': fields.many2one('fleet.vehicle.cost', 'Parent', help='Parent cost to this current cost'), + 'cost_ids': fields.one2many('fleet.vehicle.cost', 'parent_id', 'Included Services'), + 'odometer_id': fields.many2one('fleet.vehicle.odometer', 'Odometer', help='Odometer measure of the vehicle at the moment of this log'), + 'odometer': fields.function(_get_odometer, fnct_inv=_set_odometer, type='float', string='Odometer Value', help='Odometer measure of the vehicle at the moment of this log'), + 'odometer_unit': fields.related('vehicle_id', 'odometer_unit', type="char", string="Unit", readonly=True), 'date' :fields.date('Date',help='Date when the cost has been executed'), - - 'contract_id' : fields.many2one('fleet.vehicle.log.contract', 'Contract', required=False, help='Contract attached to this cost'), - 'auto_generated' : fields.boolean('automatically generated',readonly=True,required=True), - - 'year' : fields.function(_year_get_fnc, type="char", string='Year', store=True), + 'contract_id': fields.many2one('fleet.vehicle.log.contract', 'Contract', help='Contract attached to this cost'), + 'auto_generated': fields.boolean('Automatically Generated', readonly=True, required=True), + 'year': fields.function(_year_get_fnc, type="char", string='Year', store=True), } _defaults ={ - 'parent_id':None, - 'auto_generated' : False, - 'cost_type' : 'other', + 'cost_type': 'other', } - - def create(self, cr, uid, data, context=None): + #make sure that the data are consistent with values of parent and contract records given if 'parent_id' in data and data['parent_id']: parent = self.browse(cr, uid, data['parent_id'], context=context) data['vehicle_id'] = parent.vehicle_id.id @@ -89,18 +104,14 @@ class fleet_vehicle_cost(osv.Model): if 'contract_id' in data and data['contract_id']: contract = self.pool.get('fleet.vehicle.log.contract').browse(cr, uid, data['contract_id'], context=context) data['vehicle_id'] = contract.vehicle_id.id - data['cost_subtype'] = contract.cost_subtype.id + data['cost_subtype_id'] = contract.cost_subtype_id.id data['cost_type'] = contract.cost_type - if not('cost_type' in data and data['cost_type']): - data['cost_type'] = 'other' - cost_id = super(fleet_vehicle_cost, self).create(cr, uid, data, context=context) - return cost_id + if 'odometer' in data and not data['odometer']: + #if received value for odometer is 0, then remove it from the data as it would result to the creation of a + #odometer log with 0, which is to be avoided + del(data['odometer']) + return super(fleet_vehicle_cost, self).create(cr, uid, data, context=context) -############################ -############################ -#Vehicle.tag class -############################ -############################ class fleet_vehicle_tag(osv.Model): _name = 'fleet.vehicle.tag' @@ -108,79 +119,51 @@ class fleet_vehicle_tag(osv.Model): 'name': fields.char('Name', required=True, translate=True), } -############################ -############################ -#Vehicle.state class -############################ -############################ - class fleet_vehicle_state(osv.Model): _name = 'fleet.vehicle.state' + _order = 'sequence asc' _columns = { 'name': fields.char('Name', required=True), - 'sequence': fields.integer('Order',help="Used to order the note stages") + 'sequence': fields.integer('Sequence', help="Used to order the note stages") } - _order = 'sequence asc' - _sql_constraints = [('fleet_state_name_unique','unique(name)','State name already exists')] - + _sql_constraints = [('fleet_state_name_unique','unique(name)', 'State name already exists')] -############################ -############################ -#Vehicle.model class -############################ -############################ class fleet_vehicle_model(osv.Model): - def name_get(self, cr, uid, ids, context=None): - if context is None: - context = {} - if not ids: - return [] - reads = self.browse(cr, uid, ids, context=context) - res = [] - for record in reads: + def _model_name_get_fnc(self, cr, uid, ids, field_name, arg, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): name = record.modelname - if record.brand.name: - name = record.brand.name+' / '+name - res.append((record.id, name)) + if record.brand_id.name: + name = record.brand_id.name + ' / ' + name + res[record.id] = name return res - def _model_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): - res = self.name_get(cr, uid, ids, context=context) - return dict(res) - def on_change_brand(self, cr, uid, ids, model_id, context=None): - if not model_id: - return {} - + return {'value': {'image_medium': False}} brand = self.pool.get('fleet.vehicle.model.brand').browse(cr, uid, model_id, context=context) - return { - 'value' : { - 'image_medium' : brand.image, + 'value': { + 'image_medium': brand.image, } } _name = 'fleet.vehicle.model' _description = 'Model of a vehicle' + _order = 'name asc' _columns = { - 'name' : fields.function(_model_name_get_fnc, type="char", string='Name', store=True), - 'modelname' : fields.char('Model name', size=32, required=True), - 'brand' : fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'), - 'vendors': fields.many2many('res.partner','fleet_vehicle_model_vendors','model_id', 'partner_id',string='Vendors',required=False), - 'image': fields.related('brand','image',type="binary",string="Logo",store=False), - 'image_medium': fields.related('brand','image_medium',type="binary",string="Logo",store=False), - 'image_small': fields.related('brand','image_small',type="binary",string="Logo",store=False), + 'name': fields.function(_model_name_get_fnc, type="char", string='Name', store=True), + 'modelname': fields.char('Model name', size=32, required=True), + 'brand_id': fields.many2one('fleet.vehicle.model.brand', 'Model Brand', required=True, help='Brand of the vehicle'), + 'vendors': fields.many2many('res.partner', 'fleet_vehicle_model_vendors', 'model_id', 'partner_id', string='Vendors'), + 'image': fields.related('brand_id', 'image', type="binary", string="Logo"), + 'image_medium': fields.related('brand_id', 'image_medium', type="binary", string="Logo"), + 'image_small': fields.related('brand_id', 'image_small', type="binary", string="Logo"), } -############################ -############################ -#Vehicle.brand class -############################ -############################ class fleet_vehicle_model_brand(osv.Model): _name = 'fleet.vehicle.model.brand' @@ -193,13 +176,12 @@ class fleet_vehicle_model_brand(osv.Model): for obj in self.browse(cr, uid, ids, context=context): result[obj.id] = tools.image_get_resized_images(obj.image) return result - + def _set_image(self, cr, uid, id, name, value, args, context=None): return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context) _columns = { - 'name' : fields.char('Brand Name',size=32, required=True), - + 'name': fields.char('Brand Name', size=64, required=True), 'image': fields.binary("Logo", help="This field holds the image used as logo for the brand, limited to 1024x1024px."), 'image_medium': fields.function(_get_image, fnct_inv=_set_image, @@ -220,271 +202,122 @@ class fleet_vehicle_model_brand(osv.Model): "Use this field anywhere a small image is required."), } -############################ -############################ -#Vehicle class -############################ -############################ - class fleet_vehicle(osv.Model): _inherit = 'mail.thread' - def name_get(self, cr, uid, ids, context=None): - if context is None: - context = {} - if not ids: - return [] - reads = self.browse(cr, uid, ids, context=context) - res = [] - for record in reads: - if record.license_plate: - name = record.license_plate - if record.model_id.modelname: - name = record.model_id.modelname + ' / ' + name - if record.model_id.brand.name: - name = record.model_id.brand.name+' / '+ name - res.append((record.id, name)) - return res - def _vehicle_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): - res = self.name_get(cr, uid, ids, context=context) - return dict(res) - - def act_show_log_services(self, cr, uid, ids, context=None): - """ This opens log view to view and add new log for this vehicle - @return: the service log view - """ - res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','fleet_vehicle_log_services_act', context) - res['context'] = { - 'default_vehicle_id': ids[0] - } - res['domain']=[('vehicle_id','=', ids[0])] - return res - - def act_show_log_contract(self, cr, uid, ids, context=None): - """ This opens log view to view and add new log for this vehicle - @return: the contract log view - """ - res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','fleet_vehicle_log_contract_act', context) - res['context'] = { - 'default_vehicle_id': ids[0] - } - res['domain']=[('vehicle_id','=', ids[0])] + res = {} + for record in self.browse(cr, uid, ids, context=context): + res[record.id] = record.model_id.brand_id.name + '/' + record.model_id.modelname + ' / ' + record.license_plate return res - def act_show_log_fuel(self, cr, uid, ids, context=None): - """ This opens log view to view and add new log for this vehicle - @return: the fuel log view - """ - res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','fleet_vehicle_log_fuel_act', context) - res['context'] = { - 'default_vehicle_id': ids[0] - } - res['domain']=[('vehicle_id','=', ids[0])] - return res + def return_action_to_open(self, cr, uid, ids, context=None): + """ This opens the xml view specified in xml_id for the current vehicle """ + if context is None: + context = {} + if context.get('xml_id'): + res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet', context['xml_id'], context=context) + res['context'] = context + res['context'].update({'default_vehicle_id': ids[0]}) + res['domain'] = [('vehicle_id','=', ids[0])] + return res + return False def act_show_log_cost(self, cr, uid, ids, context=None): - """ This opens log view to view and add new log for this vehicle + """ This opens log view to view and add new log for this vehicle, groupby default to only show effective costs @return: the costs log view """ - res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','fleet_vehicle_costs_act', context) - res['context'] = { + if context is None: + context = {} + res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','fleet_vehicle_costs_act', context=context) + res['context'] = context + res['context'].update({ 'default_vehicle_id': ids[0], - 'search_default_parent_false' : True - } - res['domain']=[('vehicle_id','=', ids[0])] - return res - - def act_show_log_odometer(self, cr, uid, ids, context=None): - """ This opens log view to view and add new log for this vehicle - @return: the odometer log view - """ - res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','fleet_vehicle_odometer_act', context) - res['context'] = { - 'default_vehicle_id': ids[0] - } - res['domain']=[('vehicle_id','=', ids[0])] + 'search_default_parent_false': True + }) + res['domain'] = [('vehicle_id','=', ids[0])] return res def _get_odometer(self, cr, uid, ids, odometer_id, arg, context): - res = dict.fromkeys(ids, False) - for record in self.browse(cr,uid,ids,context=context): - ids = self.pool.get('fleet.vehicle.odometer').search(cr,uid,[('vehicle_id','=',record.id)],limit=1, order='value desc') + res = dict.fromkeys(ids, 0) + for record in self.browse(cr,uid,ids,context=context): + ids = self.pool.get('fleet.vehicle.odometer').search(cr, uid, [('vehicle_id', '=', record.id)], limit=1, order='value desc') if len(ids) > 0: - res[record.id] = str(self.pool.get('fleet.vehicle.odometer').browse(cr,uid,ids[0],context=context).value) - else: - res[record.id] = str(0) + res[record.id] = self.pool.get('fleet.vehicle.odometer').browse(cr, uid, ids[0], context=context).value return res def _set_odometer(self, cr, uid, id, name, value, args=None, context=None): if value: - try: - value = float(value) - except ValueError: - #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field') - raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field') - - date = time.strftime('%Y-%m-%d') - data = {'value' : value,'date' : date,'vehicle_id' : id} - odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context) - return value - self.write(cr, uid, id, {'odometer_id': ''}) - return False - - def str_to_date(self,strdate): - return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:])) - - def get_overdue_contract_reminder_fnc(self,cr,uid,ids,context=None): - if context is None: - context={} - if not ids: - return dict([]) - reads = self.browse(cr,uid,ids,context=context) - res=[] - - for record in reads: - overdue=0 - if (record.log_contracts): - for element in record.log_contracts: - if ((element.state=='open' or element.state=='toclose') and element.expiration_date): - current_date_str=time.strftime('%Y-%m-%d') - due_time_str=element.expiration_date - #due_time_str=element.browse() - current_date=self.str_to_date(current_date_str) - due_time=self.str_to_date(due_time_str) - - diff_time=int((due_time-current_date).days) - if diff_time<0: - overdue = overdue +1; - res.append((record.id,overdue)) - else: - res.append((record.id,0)) - - return dict(res) - - def get_overdue_contract_reminder(self,cr,uid,ids,prop,unknow_none,context=None): - res = self.get_overdue_contract_reminder_fnc(cr, uid, ids, context=context) - return res - - def get_next_contract_reminder_fnc(self,cr,uid,ids,context=None): - if context is None: - context={} - if not ids: - return dict([]) - reads = self.browse(cr,uid,ids,context=context) - res=[] - - for record in reads: - due_soon=0 - if (record.log_contracts): - for element in record.log_contracts: - if ((element.state=='open' or element.state=='toclose') and element.expiration_date): - current_date_str=time.strftime('%Y-%m-%d') - due_time_str=element.expiration_date - #due_time_str=element.browse() - current_date=self.str_to_date(current_date_str) - due_time=self.str_to_date(due_time_str) - - diff_time=int((due_time-current_date).days) - if diff_time<15 and diff_time>=0: - due_soon = due_soon +1; - res.append((record.id,due_soon)) - else: - res.append((record.id,0)) - - return dict(res) + date = fields.date.context_today(self, cr, uid, context=context) + data = {'value': value, 'date': date, 'vehicle_id': id} + return self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context) def _search_get_overdue_contract_reminder(self, cr, uid, obj, name, args, context): res = [] for field, operator, value in args: - #assert field == name - vehicle_ids = self.search(cr, uid, []) - renew_ids = self.get_overdue_contract_reminder_fnc(cr,uid,vehicle_ids,context=context) - res_ids = [] - for renew_key,renew_value in renew_ids.items(): - if eval(str(renew_value) + " " + str(operator) + " " + str(value)): - res_ids.append(renew_key) - res.append(('id', 'in', res_ids)) + assert operator in ('=', '!=', '<>') and value in (True, False), 'Operation not supported' + if (operator == '=' and value == True) or (operator in ('<>', '!=') and value == False): + search_operator = 'in' + else: + search_operator = 'not in' + today = fields.date.context_today(self, cr, uid, context=context) + cr.execute('select cost.vehicle_id, count(contract.id) as contract_number FROM fleet_vehicle_cost cost left join fleet_vehicle_log_contract contract on contract.cost_id = cost.id WHERE contract.expiration_date is not null AND contract.expiration_date < %s AND contract.state IN (\'open\', \'toclose\') GROUP BY cost.vehicle_id', (today,)) + res_ids = [x[0] for x in cr.fetchall()] + res.append(('id', search_operator, res_ids)) return res - + def _search_contract_renewal_due_soon(self, cr, uid, obj, name, args, context): res = [] for field, operator, value in args: - #assert field == name - vehicle_ids = self.search(cr, uid, []) - renew_ids = self.get_next_contract_reminder_fnc(cr,uid,vehicle_ids,context=context) - res_ids = [] - for renew_key,renew_value in renew_ids.items(): - if eval(str(renew_value) + " " + str(operator) + " " + str(value)): - res_ids.append(renew_key) - res.append(('id', 'in', res_ids)) + assert operator in ('=', '!=', '<>') and value in (True, False), 'Operation not supported' + if (operator == '=' and value == True) or (operator in ('<>', '!=') and value == False): + search_operator = 'in' + else: + search_operator = 'not in' + today = fields.date.context_today(self, cr, uid, context=context) + datetime_today = datetime.datetime.strptime(today, tools.DEFAULT_SERVER_DATE_FORMAT) + limit_date = str((datetime_today + relativedelta(days=+15)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)) + cr.execute('select cost.vehicle_id, count(contract.id) as contract_number FROM fleet_vehicle_cost cost left join fleet_vehicle_log_contract contract on contract.cost_id = cost.id WHERE contract.expiration_date is not null AND contract.expiration_date > %s AND contract.expiration_date < %s AND contract.state IN (\'open\', \'toclose\') GROUP BY cost.vehicle_id', (today, limit_date)) + res_ids = [x[0] for x in cr.fetchall()] + res.append(('id', search_operator, res_ids)) return res - def get_next_contract_reminder(self, cr, uid, ids, prop, unknow_none, context=None): - res = self.get_next_contract_reminder_fnc(cr, uid, ids, context=context) + def _get_contract_reminder_fnc(self, cr, uid, ids, field_names, unknow_none, context=None): + res= {} + for record in self.browse(cr, uid, ids, context=context): + overdue = False + due_soon = False + total = 0 + name = '' + for element in record.log_contracts: + if element.state in ('open', 'toclose') and element.expiration_date: + current_date_str = fields.date.context_today(self, cr, uid, context=context) + due_time_str = element.expiration_date + current_date = str_to_datetime(current_date_str) + due_time = str_to_datetime(due_time_str) + diff_time = (due_time-current_date).days + if diff_time < 0: + overdue = True + total += 1 + if diff_time < 15 and diff_time >= 0: + due_soon = True; + total += 1 + if overdue or due_soon: + ids = self.pool.get('fleet.vehicle.log.contract').search(cr,uid,[('vehicle_id', '=', record.id), ('state', 'in', ('open', 'toclose'))], limit=1, order='expiration_date asc') + if len(ids) > 0: + #we display only the name of the oldest overdue/due soon contract + name=(self.pool.get('fleet.vehicle.log.contract').browse(cr, uid, ids[0], context=context).cost_subtype_id.name) + + res[record.id] = { + 'contract_renewal_overdue': overdue, + 'contract_renewal_due_soon': due_soon, + 'contract_renewal_total': (total - 1), #we remove 1 from the real total for display purposes + 'contract_renewal_name': name, + } return res - def get_contract_renewal_names(self,cr,uid,ids,function_name,args,context=None): - if not ids: - return dict([]) - reads = self.browse(cr,uid,ids,context=context) - res=[] - for record in reads: - if (record.log_contracts): - ids = self.pool.get('fleet.vehicle.log.contract').search(cr,uid,[('vehicle_id','=',record.id),'|',('state','=','open'),('state','=','toclose')],limit=1,order='expiration_date asc') - if len(ids) > 0: - res.append((record.id,self.pool.get('fleet.vehicle.log.contract').browse(cr,uid,ids[0],context=context).cost_subtype.name)) - else: - res.append((record.id,'')) - return dict(res) - - def get_total_contract_reminder(self,cr,uid,ids,prop,unknow_none,context=None): - if context is None: - context={} - if not ids: - return dict([]) - reads = self.browse(cr,uid,ids,context=context) - res=[] - - for record in reads: - due_soon=0 - if (record.log_contracts): - for element in record.log_contracts: - if ((element.state=='open' or element.state=='toclose') and element.expiration_date): - current_date_str=time.strftime('%Y-%m-%d') - due_time_str=element.expiration_date - - current_date=self.str_to_date(current_date_str) - due_time=self.str_to_date(due_time_str) - - diff_time=int((due_time-current_date).days) - if diff_time<15: - due_soon = due_soon +1; - if due_soon>0: - due_soon=due_soon-1 - res.append((record.id,due_soon)) - else: - res.append((record.id,0)) - - return dict(res) - - def run_scheduler(self,cr,uid,context=None): - ids = self.pool.get('fleet.vehicle.log.contract').search(cr, uid, ['&',('state','=','open'),('expiration_date','<',(datetime.date.today() + relativedelta(days=+15)).strftime('%Y-%m-%d'))], offset=0, limit=None, order=None,context=None, count=False) - res = {} - for contract in self.pool.get('fleet.vehicle.log.contract').browse(cr,uid,ids,context=context): - if contract.vehicle_id.id in res: - res[contract.vehicle_id.id] += 1 - else : - res[contract.vehicle_id.id] = 1 - - for vehicle,value in res.items(): - self.message_post(cr, uid, vehicle, body=str(value) + ' contract(s) need(s) to be renewed and/or closed!', context=context) - - self.pool.get('fleet.vehicle.log.contract').write(cr,uid,ids,{'state' : 'toclose'},context=context) - return True - def _get_default_state(self, cr, uid, context): try: model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'vehicle_state_active') @@ -493,64 +326,53 @@ class fleet_vehicle(osv.Model): return model_id _name = 'fleet.vehicle' - _description = 'Fleet Vehicle' - #_order = 'contract_renewal_overdue desc, contract_renewal_due_soon desc' + _description = 'Information on a vehicle' _order= 'license_plate asc' _columns = { - 'name' : fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True), - + 'name': fields.function(_vehicle_name_get_fnc, type="char", string='Name', store=True), 'company_id': fields.many2one('res.company', 'Company'), - 'license_plate' : fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'), - 'vin_sn' : fields.char('Chassis Number', size=32, required=False, help='Unique number written on the vehicle motor (VIN/SN number)'), - 'driver' : fields.many2one('res.partner', 'Driver',required=False, help='Driver of the vehicle'), - 'model_id' : fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'), - 'log_fuel' : fields.one2many('fleet.vehicle.log.fuel','vehicle_id', 'Fuel Logs'), - 'log_services' : fields.one2many('fleet.vehicle.log.services','vehicle_id', 'Services Logs'), - 'log_contracts' : fields.one2many('fleet.vehicle.log.contract','vehicle_id', 'Contracts'), - 'acquisition_date' : fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'), - 'color' : fields.char('Color',size=32, help='Color of the vehicle'), - 'state': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle',ondelete="set null"), - 'location' : fields.char('Location',size=32, help='Location of the vehicle (garage, ...)'), - 'seats' : fields.integer('Seats Number', help='Number of seats of the vehicle'), - 'doors' : fields.integer('Doors Number', help='Number of doors of the vehicle'), - 'tag_ids' :fields.many2many('fleet.vehicle.tag','fleet_vehicle_vehicle_tag_rel','vehicle_tag_id','tag_id','Tags'), - - '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'), + 'license_plate': fields.char('License Plate', size=32, required=True, help='License plate number of the vehicle (ie: plate number for a car)'), + 'vin_sn': fields.char('Chassis Number', size=32, help='Unique number written on the vehicle motor (VIN/SN number)'), + 'driver_id': fields.many2one('res.partner', 'Driver', help='Driver of the vehicle'), + 'model_id': fields.many2one('fleet.vehicle.model', 'Model', required=True, help='Model of the vehicle'), + 'log_fuel': fields.one2many('fleet.vehicle.log.fuel', 'vehicle_id', 'Fuel Logs'), + 'log_services': fields.one2many('fleet.vehicle.log.services', 'vehicle_id', 'Services Logs'), + 'log_contracts': fields.one2many('fleet.vehicle.log.contract', 'vehicle_id', 'Contracts'), + 'acquisition_date': fields.date('Acquisition Date', required=False, help='Date when the vehicle has been bought'), + 'color': fields.char('Color', size=32, help='Color of the vehicle'), + 'state_id': fields.many2one('fleet.vehicle.state', 'State', help='Current state of the vehicle', ondelete="set null"), + 'location': fields.char('Location', size=128, help='Location of the vehicle (garage, ...)'), + 'seats': fields.integer('Seats Number', help='Number of seats of the vehicle'), + 'doors': fields.integer('Doors Number', help='Number of doors of the vehicle'), + 'tag_ids' :fields.many2many('fleet.vehicle.tag', 'fleet_vehicle_vehicle_tag_rel', 'vehicle_tag_id','tag_id', 'Tags'), + 'odometer': fields.function(_get_odometer, fnct_inv=_set_odometer, type='float', string='Last Odometer', help='Odometer measure of the vehicle at the moment of this log'), 'odometer_unit': fields.selection([('kilometers', 'Kilometers'),('miles','Miles')], 'Odometer Unit', help='Unit of the odometer ',required=True), - - 'transmission' : fields.selection([('manual', 'Manual'),('automatic','Automatic')], 'Transmission', help='Transmission Used by the vehicle',required=False), - 'fuel_type' : fields.selection([('gasoline', 'Gasoline'),('diesel','Diesel'),('electric','Electric'),('hybrid','Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle',required=False), - 'horsepower' : fields.integer('Horsepower',required=False), + 'transmission': fields.selection([('manual', 'Manual'), ('automatic', 'Automatic')], 'Transmission', help='Transmission Used by the vehicle'), + 'fuel_type': fields.selection([('gasoline', 'Gasoline'), ('diesel', 'Diesel'), ('electric', 'Electric'), ('hybrid', 'Hybrid')], 'Fuel Type', help='Fuel Used by the vehicle'), + 'horsepower': fields.integer('Horsepower'), 'horsepower_tax': fields.float('Horsepower Taxation'), - 'power' : fields.integer('Power (kW)',required=False,help='Power in kW of the vehicle'), - 'co2' : fields.float('CO2 Emissions',required=False,help='CO2 emissions of the vehicle'), - - 'image': fields.related('model_id','image',type="binary",string="Logo",store=False), - 'image_medium': fields.related('model_id','image_medium',type="binary",string="Logo",store=False), - 'image_small': fields.related('model_id','image_small',type="binary",string="Logo",store=False), - - 'contract_renewal_due_soon' : fields.function(get_next_contract_reminder,fnct_search=_search_contract_renewal_due_soon,type="integer",string='Contracts to renew',store=False), - 'contract_renewal_overdue' : fields.function(get_overdue_contract_reminder,fnct_search=_search_get_overdue_contract_reminder,type="integer",string='Contracts Overdued',store=False), - 'contract_renewal_name' : fields.function(get_contract_renewal_names,type="text",string='Name of contract to renew soon',store=False), - 'contract_renewal_total' : fields.function(get_total_contract_reminder,type="integer",string='Total of contracts due or overdue minus one',store=False), - + 'power': fields.integer('Power (kW)', help='Power in kW of the vehicle'), + 'co2': fields.float('CO2 Emissions', help='CO2 emissions of the vehicle'), + 'image': fields.related('model_id', 'image', type="binary", string="Logo"), + 'image_medium': fields.related('model_id', 'image_medium', type="binary", string="Logo"), + 'image_small': fields.related('model_id', 'image_small', type="binary", string="Logo"), + 'contract_renewal_due_soon': fields.function(_get_contract_reminder_fnc, fnct_search=_search_contract_renewal_due_soon, type="boolean", string='Has Contracts to renew', multi='contract_info'), + 'contract_renewal_overdue': fields.function(_get_contract_reminder_fnc, fnct_search=_search_get_overdue_contract_reminder, type="boolean", string='Has Contracts Overdued', multi='contract_info'), + 'contract_renewal_name': fields.function(_get_contract_reminder_fnc, type="text", string='Name of contract to renew soon', multi='contract_info'), + 'contract_renewal_total': fields.function(_get_contract_reminder_fnc, type="integer", string='Total of contracts due or overdue minus one', multi='contract_info'), 'car_value': fields.float('Car Value', help='Value of the bought vehicle'), - #'leasing_value': fields.float('Leasing value',help='Value of the leasing(Monthly, usually'), } _defaults = { - 'doors' : 5, - 'odometer_unit' : 'kilometers', - 'state' : _get_default_state, + 'doors': 5, + 'odometer_unit': 'kilometers', + 'state_id': _get_default_state, } def copy(self, cr, uid, id, default=None, context=None): if not default: default = {} - default.update({ - # 'name': self.pool.get('ir.sequence').get(cr, uid, 'stock.orderpoint') or '', - #'log_ids':[], 'log_fuel':[], 'log_contracts':[], 'log_services':[], @@ -560,217 +382,161 @@ class fleet_vehicle(osv.Model): return super(fleet_vehicle, self).copy(cr, uid, id, default, context=context) def on_change_model(self, cr, uid, ids, model_id, context=None): - if not model_id: return {} - model = self.pool.get('fleet.vehicle.model').browse(cr, uid, model_id, context=context) - return { - 'value' : { - 'image_medium' : model.image, + 'value': { + 'image_medium': model.image, } } + def create(self, cr, uid, data, context=None): vehicle_id = super(fleet_vehicle, self).create(cr, uid, data, context=context) - try: - vehicle = self.browse(cr, uid, vehicle_id, context=context) - self.message_post(cr, uid, [vehicle_id], body='Vehicle %s has been added to the fleet!' % (vehicle.license_plate), context=context) - except: - pass # group deleted: do not push a message + vehicle = self.browse(cr, uid, vehicle_id, context=context) + self.message_post(cr, uid, [vehicle_id], body=_('Vehicle %s has been added to the fleet!') % (vehicle.license_plate), context=context) return vehicle_id def write(self, cr, uid, ids, vals, context=None): + """ + This function write an entry in the openchatter whenever we change important information + on the vehicle like the model, the drive, the state of the vehicle or its license plate + """ for vehicle in self.browse(cr, uid, ids, context): changes = [] if 'model_id' in vals and vehicle.model_id.id != vals['model_id']: value = self.pool.get('fleet.vehicle.model').browse(cr,uid,vals['model_id'],context=context).name - oldmodel = vehicle.model_id - if oldmodel: - oldmodel = oldmodel.name - else: - oldmodel = 'None' - changes.append('Model: from \'' + oldmodel + '\' to \'' + value+'\'') - if 'driver' in vals and vehicle.driver.id != vals['driver']: - value = self.pool.get('res.partner').browse(cr,uid,vals['driver'],context=context).name - olddriver = vehicle.driver - if olddriver: - olddriver = olddriver.name - else: - olddriver = 'None' - changes.append('Driver: from \'' + olddriver + '\' to \'' + value+'\'') - if 'state' in vals and vehicle.state.id != vals['state']: - value = self.pool.get('fleet.vehicle.state').browse(cr,uid,vals['state'],context=context).name - oldstate = vehicle.state - if oldstate: - oldstate=oldstate.name - else: - oldstate = 'None' - changes.append('State: from \'' + oldstate + '\' to \'' + value+'\'') + oldmodel = vehicle.model_id.name or _('None') + changes.append(_("Model: from '%s' to '%s'") %(oldmodel, value)) + if 'driver_id' in vals and vehicle.driver_id.id != vals['driver_id']: + value = self.pool.get('res.partner').browse(cr,uid,vals['driver_id'],context=context).name + olddriver = (vehicle.driver_id.name) or _('None') + changes.append(_("Driver: from '%s' to '%s'") %(olddriver, value)) + if 'state_id' in vals and vehicle.state_id.id != vals['state_id']: + value = self.pool.get('fleet.vehicle.state').browse(cr,uid,vals['state_id'],context=context).name + oldstate = vehicle.state_id.name or _('None') + changes.append(_("State: from '%s' to '%s'") %(oldstate, value)) if 'license_plate' in vals and vehicle.license_plate != vals['license_plate']: - old_license_plate = vehicle.license_plate - if not old_license_plate: - old_license_plate = 'None' - changes.append('License Plate: from \'' + old_license_plate + '\' to \'' + vals['license_plate']+'\'') - - vehicle_id = super(fleet_vehicle,self).write(cr, uid, ids, vals, context) - - try: - if len(changes) > 0: - self.message_post(cr, uid, [self.browse(cr, uid, ids, context)[0].id], body=", ".join(changes), context=context) - except Exception as e: - print e - pass + old_license_plate = vehicle.license_plate or _('None') + changes.append(_("License Plate: from '%s' to '%s'") %(old_license_plate, vals['license_plate'])) + + if len(changes) > 0: + self.message_post(cr, uid, [vehicle.id], body=", ".join(changes), context=context) + + vehicle_id = super(fleet_vehicle,self).write(cr, uid, ids, vals, context) return True -############################ -############################ -#Vehicle.odometer class -############################ -############################ class fleet_vehicle_odometer(osv.Model): _name='fleet.vehicle.odometer' _description='Odometer log for a vehicle' - _order='date desc' - def name_get(self, cr, uid, ids, context=None): - if context is None: - context = {} - if not ids: - return [] - reads = self.browse(cr, uid, ids, context=context) - res = [] - for record in reads: - if record.vehicle_id.name: - name = str(record.vehicle_id.name) + def _vehicle_log_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + name = record.vehicle_id.name if record.date: name = name+ ' / '+ str(record.date) - res.append((record.id, name)) + res[record.id] = name return res - def _vehicle_log_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): - res = self.name_get(cr, uid, ids, context=context) - return dict(res) def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None): - if not vehicle_id: return {} - odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit - return { - 'value' : { - 'unit' : odometer_unit, + 'value': { + 'unit': odometer_unit, } } _columns = { - 'name' : fields.function(_vehicle_log_name_get_fnc, type="char", string='Name', store=True), - - 'date' : fields.date('Date'), - 'value' : fields.float('Odometer Value',group_operator="max"), - 'vehicle_id' : fields.many2one('fleet.vehicle', 'Vehicle', required=True), - 'unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True), - + 'name': fields.function(_vehicle_log_name_get_fnc, type="char", string='Name', store=True), + 'date': fields.date('Date'), + 'value': fields.float('Odometer Value', group_operator="max"), + 'vehicle_id': fields.many2one('fleet.vehicle', 'Vehicle', required=True), + 'unit': fields.related('vehicle_id', 'odometer_unit', type="char", string="Unit", readonly=True), } _defaults = { - 'date' : time.strftime('%Y-%m-%d') + 'date': fields.date.context_today, } -############################ -############################ -#Vehicle.log classes -############################ -############################ - - -############################ -############################ -#Vehicle.log.fuel class -############################ -############################ - class fleet_vehicle_log_fuel(osv.Model): - #_inherits = {'fleet.vehicle.odometer': 'odometer_id'} - _inherits = {'fleet.vehicle.cost': 'cost_id'} - def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None): - if not vehicle_id: return {} - - odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit - + vehicle = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context) + odometer_unit = vehicle.odometer_unit + driver = vehicle.driver_id.id return { - 'value' : { - 'odometer_unit' : odometer_unit, + 'value': { + 'odometer_unit': odometer_unit, + 'purchaser_id': driver, } } def on_change_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None): - - if liter > 0 and price_per_liter > 0: - return {'value' : {'amount' : float(liter) * float(price_per_liter),}} - elif liter > 0 and amount > 0: - return {'value' : {'price_per_liter' : float(amount) / float(liter),}} - elif price_per_liter > 0 and amount > 0: - return {'value' : {'liter' : float(amount) / float(price_per_liter),}} + #need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not + #make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per + #liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead + #of 3.0/2=1.5) + #If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine + #onchange. And in order to verify that there is no change in the result, we have to limit the precision of the + #computation to 2 decimal + liter = float(liter) + price_per_liter = float(price_per_liter) + amount = float(amount) + if liter > 0 and price_per_liter > 0 and round(liter*price_per_liter,2) != amount: + return {'value' : {'amount' : round(liter * price_per_liter,2),}} + elif amount > 0 and liter > 0 and round(amount/liter,2) != price_per_liter: + return {'value' : {'price_per_liter' : round(amount / liter,2),}} + elif amount > 0 and price_per_liter > 0 and round(amount/price_per_liter,2) != liter: + return {'value' : {'liter' : round(amount / price_per_liter,2),}} else : return {} def on_change_price_per_liter(self, cr, uid, ids, liter, price_per_liter, amount, context=None): - - liter = float(liter); - price_per_liter = float(price_per_liter); - if price_per_liter > 0 and liter > 0: - return {'value' : {'amount' : float(liter) * float(price_per_liter),}} - elif price_per_liter > 0 and amount > 0: - return {'value' : {'liter' : float(amount) / float(price_per_liter),}} - elif liter > 0 and amount > 0: - return {'value' : {'price_per_liter' : float(amount) / float(liter),}} + #need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not + #make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per + #liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead + #of 3.0/2=1.5) + #If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine + #onchange. And in order to verify that there is no change in the result, we have to limit the precision of the + #computation to 2 decimal + liter = float(liter) + price_per_liter = float(price_per_liter) + amount = float(amount) + if liter > 0 and price_per_liter > 0 and round(liter*price_per_liter,2) != amount: + return {'value' : {'amount' : round(liter * price_per_liter,2),}} + elif amount > 0 and price_per_liter > 0 and round(amount/price_per_liter,2) != liter: + return {'value' : {'liter' : round(amount / price_per_liter,2),}} + elif amount > 0 and liter > 0 and round(amount/liter,2) != price_per_liter: + return {'value' : {'price_per_liter' : round(amount / liter,2),}} else : return {} def on_change_amount(self, cr, uid, ids, liter, price_per_liter, amount, context=None): - - if amount > 0 and liter > 0: - return {'value' : {'price_per_liter' : float(amount) / float(liter),}} - elif amount > 0 and price_per_liter > 0: - return {'value' : {'liter' : float(amount) / float(price_per_liter),}} - elif liter > 0 and price_per_liter > 0: - return {'value' : {'amount' : float(liter) * float(price_per_liter),}} + #need to cast in float because the value receveid from web client maybe an integer (Javascript and JSON do not + #make any difference between 3.0 and 3). This cause a problem if you encode, for example, 2 liters at 1.5 per + #liter => total is computed as 3.0, then trigger an onchange that recomputes price_per_liter as 3/2=1 (instead + #of 3.0/2=1.5) + #If there is no change in the result, we return an empty dict to prevent an infinite loop due to the 3 intertwine + #onchange. And in order to verify that there is no change in the result, we have to limit the precision of the + #computation to 2 decimal + liter = float(liter) + price_per_liter = float(price_per_liter) + amount = float(amount) + if amount > 0 and liter > 0 and round(amount/liter,2) != price_per_liter: + return {'value': {'price_per_liter': round(amount / liter,2),}} + elif amount > 0 and price_per_liter > 0 and round(amount/price_per_liter,2) != liter: + return {'value': {'liter': round(amount / price_per_liter,2),}} + elif liter > 0 and price_per_liter > 0 and round(liter*price_per_liter,2) != amount: + return {'value': {'amount': round(liter * price_per_liter,2),}} else : return {} - - def _get_odometer(self, cr, uid, ids, odometer_id, arg, context): - res = dict.fromkeys(ids, False) - for record in self.browse(cr,uid,ids,context=context): - if record.odometer_id: - res[record.id] = record.odometer_id.value - return res - - def _set_odometer(self, cr, uid, id, name, value, args=None, context=None): - if value: - try: - value = float(value) - except ValueError: - #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field') - raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field') - - date = self.browse(cr, uid, id, context=context).date - if not(date): - date = time.strftime('%Y-%m-%d') - vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id - data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id} - odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context) - self.write(cr, uid, id, {'odometer_id': odometer_id}) - return value - self.write(cr, uid, id, {'odometer_id': ''}) - return False def _get_default_service_type(self, cr, uid, context): try: @@ -780,80 +546,40 @@ class fleet_vehicle_log_fuel(osv.Model): return model_id _name = 'fleet.vehicle.log.fuel' + _description = 'Fuel log for vehicles' + _inherits = {'fleet.vehicle.cost': 'cost_id'} _columns = { - #'name' : fields.char('Name',size=64), - 'liter' : fields.float('Liter'), - 'price_per_liter' : fields.float('Price Per Liter'), - 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"), - 'inv_ref' : fields.char('Invoice Reference', size=64), - 'vendor_id' : fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"), - 'notes' : fields.text('Notes'), - 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'), - 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer',store=False), - 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True), - 'cost_amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True), + 'liter': fields.float('Liter'), + 'price_per_liter': fields.float('Price Per Liter'), + 'purchaser_id': fields.many2one('res.partner', 'Purchaser', domain="['|',('customer','=',True),('employee','=',True)]"), + 'inv_ref': fields.char('Invoice Reference', size=64), + 'vendor_id': fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"), + 'notes': fields.text('Notes'), + 'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database } _defaults = { - 'purchaser_id': lambda self, cr, uid, ctx: uid, - 'date' : time.strftime('%Y-%m-%d'), - 'cost_subtype': _get_default_service_type, + 'date': fields.date.context_today, + 'cost_subtype_id': _get_default_service_type, + 'cost_type': 'fuel', } - def create(self, cr, uid, data, context=None): - data['cost_type'] = 'fuel' - cost_id = super(fleet_vehicle_log_fuel, self).create(cr, uid, data, context=context) - return cost_id - -############################ -############################ -#Vehicle.log.service class -############################ -############################ class fleet_vehicle_log_services(osv.Model): - _inherits = {'fleet.vehicle.cost': 'cost_id'} - def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None): - if not vehicle_id: return {} - - odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit - + vehicle = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context) + odometer_unit = vehicle.odometer_unit + driver = vehicle.driver_id.id return { - 'value' : { - 'odometer_unit' : odometer_unit, + 'value': { + 'odometer_unit': odometer_unit, + 'purchaser_id': driver, } } - def _get_odometer(self, cr, uid, ids, odometer_id, arg, context): - res = dict.fromkeys(ids, False) - for record in self.browse(cr,uid,ids,context=context): - if record.odometer_id: - res[record.id] = record.odometer_id.value - return res - - def _set_odometer(self, cr, uid, id, name, value, args=None, context=None): - if value: - try: - value = float(value) - except ValueError: - #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field') - raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field') - - date = self.browse(cr, uid, id, context=context).date - if not(date): - date = time.strftime('%Y-%m-%d') - vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id - data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id} - odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context) - self.write(cr, uid, id, {'odometer_id': odometer_id}) - return value - self.write(cr, uid, id, {'odometer_id': ''}) - return False - def _get_default_service_type(self, cr, uid, context): try: model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_service_service_8') @@ -861,335 +587,248 @@ class fleet_vehicle_log_services(osv.Model): model_id = False return model_id + _inherits = {'fleet.vehicle.cost': 'cost_id'} _name = 'fleet.vehicle.log.services' + _description = 'Services for vehicles' _columns = { - - #'name' : fields.char('Name',size=64), - - 'purchaser_id' : fields.many2one('res.partner', 'Purchaser',domain="['|',('customer','=',True),('employee','=',True)]"), - 'inv_ref' : fields.char('Invoice Reference', size=64), - 'vendor_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"), - 'notes' : fields.text('Notes'), - - 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'), - 'odometer' : fields.function(_get_odometer,fnct_inv=_set_odometer,type='char',string='Odometer Value',store=False), - 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True), - 'cost_amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True), + 'purchaser_id': fields.many2one('res.partner', 'Purchaser', domain="['|',('customer','=',True),('employee','=',True)]"), + 'inv_ref': fields.char('Invoice Reference', size=64), + 'vendor_id': fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"), + 'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database + 'notes': fields.text('Notes'), } _defaults = { - 'purchaser_id': lambda self, cr, uid, ctx: uid, - 'date' : time.strftime('%Y-%m-%d'), - 'cost_subtype' : _get_default_service_type + 'date': fields.date.context_today, + 'cost_subtype_id': _get_default_service_type, + 'cost_type': 'services' } - def create(self, cr, uid, data, context=None): - data['cost_type'] = 'services' - cost_id = super(fleet_vehicle_log_services, self).create(cr, uid, data, context=context) - return cost_id -############################ -############################ -#Vehicle.service.type class -############################ -############################ class fleet_service_type(osv.Model): _name = 'fleet.service.type' + _description = 'Type of services available on a vehicle' _columns = { 'name': fields.char('Name', required=True, translate=True), - 'category': fields.selection([('contract', 'Contract'), ('service', 'Service'),('both', 'Both')], 'Category',required=True, help='Choose wheter the service refer to contracts, vehicle services or both'), + 'category': fields.selection([('contract', 'Contract'), ('service', 'Service'), ('both', 'Both')], 'Category', required=True, help='Choose wheter the service refer to contracts, vehicle services or both'), } - #_defaults = { - # 'category': 'both' - #} -############################ -############################ -#Vehicle.log.contract class -############################ -############################ class fleet_vehicle_log_contract(osv.Model): - _inherits = {'fleet.vehicle.cost': 'cost_id'} - - def run_scheduler(self,cr,uid,context=None): - - d = datetime.date.today() - #d = datetime.datetime(2012, 12, 01) - + def scheduler_manage_auto_costs(self, cr, uid, context=None): + #This method is called by a cron task + #It creates costs for contracts having the "recurring cost" field setted, depending on their frequency + #For example, if a contract has a reccuring cost of 200 with a weekly frequency, this method creates a cost of 200 on the first day of each week, from the date of the last recurring costs in the database to today + #If the contract has not yet any recurring costs in the database, the method generates the recurring costs from the start_date to today + #The created costs are associated to a contract thanks to the many2one field contract_id + #If the contract has no start_date, no cost will be created, even if the contract has recurring costs + vehicle_cost_obj = self.pool.get('fleet.vehicle.cost') + d = datetime.datetime.strptime(fields.date.context_today(self, cr, uid, context=context), tools.DEFAULT_SERVER_DATE_FORMAT).date() contract_ids = self.pool.get('fleet.vehicle.log.contract').search(cr, uid, [('state','!=','closed')], offset=0, limit=None, order=None,context=None, count=False) - deltas = {'yearly' : relativedelta(years=+1),'monthly' : relativedelta(months=+1),'weekly' : relativedelta(weeks=+1),'daily' : relativedelta(days=+1)} - for contract in self.pool.get('fleet.vehicle.log.contract').browse(cr,uid,contract_ids,context=context): + deltas = {'yearly': relativedelta(years=+1), 'monthly': relativedelta(months=+1), 'weekly': relativedelta(weeks=+1), 'daily': relativedelta(days=+1)} + for contract in self.pool.get('fleet.vehicle.log.contract').browse(cr, uid, contract_ids, context=context): if not contract.start_date or contract.cost_frequency == 'no': - break; - if contract.generated_cost_ids != []: - last_cost_id = self.pool.get('fleet.vehicle.cost').search(cr, uid, ['&',('contract_id','=',contract.id),('auto_generated','=',True)], offset=0, limit=1, order='date desc',context=None, count=False) - last_cost_date = self.pool.get('fleet.vehicle.cost').browse(cr,uid,last_cost_id[0],context=None).date - found = True - else : - found = False - last_cost_date = contract.start_date - startdate = datetime.datetime.strptime(last_cost_date,'%Y-%m-%d').date() + continue + found = False + last_cost_date = contract.start_date + if contract.generated_cost_ids: + last_autogenerated_cost_id = vehicle_cost_obj.search(cr, uid, ['&', ('contract_id','=',contract.id), ('auto_generated','=',True)], offset=0, limit=1, order='date desc',context=context, count=False) + if last_autogenerated_cost_id: + found = True + last_cost_date = vehicle_cost_obj.browse(cr, uid, last_autogenerated_cost_id[0], context=context).date + startdate = datetime.datetime.strptime(last_cost_date, tools.DEFAULT_SERVER_DATE_FORMAT).date() if found: startdate += deltas.get(contract.cost_frequency) - while (startdate < d) & (startdate < datetime.datetime.strptime(contract.expiration_date,'%Y-%m-%d').date()): - data = {'amount' : contract.cost_generated,'date' : startdate.strftime('%Y-%m-%d'),'vehicle_id' : contract.vehicle_id.id,'cost_subtype' : contract.cost_subtype.id,'contract_id' : contract.id,'auto_generated' : True} - print data + while (startdate <= d) & (startdate <= datetime.datetime.strptime(contract.expiration_date, tools.DEFAULT_SERVER_DATE_FORMAT).date()): + data = { + 'amount': contract.cost_generated, + 'date': startdate.strftime(tools.DEFAULT_SERVER_DATE_FORMAT), + 'vehicle_id': contract.vehicle_id.id, + 'cost_subtype_id': contract.cost_subtype_id.id, + 'contract_id': contract.id, + 'auto_generated': True + } cost_id = self.pool.get('fleet.vehicle.cost').create(cr, uid, data, context=context) startdate += deltas.get(contract.cost_frequency) return True - - def name_get(self, cr, uid, ids, context=None): - if context is None: - context = {} - if not ids: - return [] - reads = self.browse(cr, uid, ids, context=context) - res = [] - for record in reads: - if record.vehicle_id.name: - name = str(record.vehicle_id.name) - if record.cost_subtype.name: - name = name+ ' / '+ str(record.cost_subtype.name) - if record.date: - name = name+ ' / '+ record.date - res.append((record.id, name)) - return res - def _vehicle_contract_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): - res = self.name_get(cr, uid, ids, context=context) - return dict(res) + def scheduler_manage_contract_expiration(self, cr, uid, context=None): + #This method is called by a cron task + #It manages the state of a contract, possibly by posting a message on the vehicle concerned and updating its status + datetime_today = datetime.datetime.strptime(fields.date.context_today(self, cr, uid, context=context), tools.DEFAULT_SERVER_DATE_FORMAT) + limit_date = (datetime_today + relativedelta(days=+15)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT) + ids = self.search(cr, uid, ['&', ('state', '=', 'open'), ('expiration_date', '<', limit_date)], offset=0, limit=None, order=None, context=context, count=False) + res = {} + for contract in self.browse(cr, uid, ids, context=context): + if contract.vehicle_id.id in res: + res[contract.vehicle_id.id] += 1 + else: + res[contract.vehicle_id.id] = 1 - def _get_odometer(self, cr, uid, ids, odometer_id, arg, context): - res = dict.fromkeys(ids, False) - for record in self.browse(cr,uid,ids,context=context): - if record.odometer_id: - res[record.id] = record.odometer_id.value - return res + for vehicle, value in res.items(): + self.pool.get('fleet.vehicle').message_post(cr, uid, vehicle, body=_('%s contract(s) need(s) to be renewed and/or closed!') % (str(value)), context=context) + return self.write(cr, uid, ids, {'state': 'toclose'}, context=context) - def _set_odometer(self, cr, uid, id, name, value, args=None, context=None): - if value: - try: - value = float(value) - except ValueError: - #_logger.exception(value+' is not a correct odometer value. Please, fill a float for this field') - raise except_orm(_('Error!'), value+' is not a correct odometer value. Please, fill a float for this field') - - date = self.browse(cr, uid, id, context=context).date - if not(date): - date = time.strftime('%Y-%m-%d') - vehicle_id = self.browse(cr, uid, id, context=context).vehicle_id - data = {'value' : value,'date' : date,'vehicle_id' : vehicle_id.id} - odometer_id = self.pool.get('fleet.vehicle.odometer').create(cr, uid, data, context=context) - self.write(cr, uid, id, {'odometer_id': odometer_id}) - return value - self.write(cr, uid, id, {'odometer_id': ''}) - return False + def run_scheduler(self, cr, uid, context=None): + self.scheduler_manage_auto_costs(cr, uid, context=context) + self.scheduler_manage_contract_expiration(cr, uid, context=context) + return True - def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None): + def _vehicle_contract_name_get_fnc(self, cr, uid, ids, prop, unknow_none, context=None): + res = {} + for record in self.browse(cr, uid, ids, context=context): + name = record.vehicle_id.name + if record.cost_subtype_id.name: + name += ' / '+ record.cost_subtype_id.name + if record.date: + name += ' / '+ record.date + res[record.id] = name + return res + def on_change_vehicle(self, cr, uid, ids, vehicle_id, context=None): if not vehicle_id: return {} - odometer_unit = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context).odometer_unit - return { - 'value' : { - 'odometer_unit' : odometer_unit, + 'value': { + 'odometer_unit': odometer_unit, } } def compute_next_year_date(self, strdate): - oneyear=datetime.timedelta(days=365) - curdate = self.str_to_date(strdate) - nextyear=curdate+oneyear#int(strdate[:4])+1 - return str(nextyear)#+strdate[4:] + oneyear = datetime.timedelta(days=365) + curdate = str_to_datetime(strdate) + return datetime.datetime.strftime(curdate + oneyear, tools.DEFAULT_SERVER_DATE_FORMAT) def on_change_start_date(self, cr, uid, ids, strdate, enddate, context=None): - if (strdate): - - return {'value' : {'expiration_date' : self.compute_next_year_date(strdate),}} - else: - return {} - - def str_to_date(self,strdate): - return datetime.datetime(int(strdate[:4]),int(strdate[5:7]),int(strdate[8:])) - - def get_warning_date(self,cr,uid,ids,prop,unknow_none,context=None): - if context is None: - context={} - if not ids: - return dict([]) - reads = self.browse(cr,uid,ids,context=context) - res=[] - for record in reads: - #if (record.reminder==True): - if (record.expiration_date and (record.state=='open' or record.state=='toclose')): - today=self.str_to_date(time.strftime('%Y-%m-%d')) - renew_date = self.str_to_date(record.expiration_date) - diff_time=int((renew_date-today).days) - if (diff_time<=0): - res.append((record.id,0)) - else: - res.append((record.id,diff_time)) + return {'value': {'expiration_date': self.compute_next_year_date(strdate),}} + return {} + + def get_days_left(self, cr, uid, ids, prop, unknow_none, context=None): + """return a dict with as value for each contract an integer + if contract is in an open state and is overdue, return 0 + if contract is in a closed state, return -1 + otherwise return the number of days before the contract expires + """ + res = {} + for record in self.browse(cr, uid, ids, context=context): + if (record.expiration_date and (record.state == 'open' or record.state == 'toclose')): + today = str_to_datetime(time.strftime(tools.DEFAULT_SERVER_DATE_FORMAT)) + renew_date = str_to_datetime(record.expiration_date) + diff_time = (renew_date-today).days + res[record.id] = diff_time > 0 and diff_time or 0 else: - res.append((record.id,-1)) - #else: - # res.append((record.id,-1)) - return dict(res) - - def act_renew_contract(self,cr,uid,ids,context=None): - - - contracts = self.browse(cr,uid,ids,context=context) - res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid ,'fleet','act_renew_contract', context) - for element in contracts: - temp = [] - temp.append(('default_vehicle_id',element.vehicle_id.id)) - temp.append(('default_cost_subtype',element.cost_subtype.id)) - temp.append(('default_amount',element.amount)) - temp.append(('default_odometer_id',element.odometer_id.id)) - temp.append(('default_odometer_unit',element.odometer_unit)) - temp.append(('default_insurer_id',element.insurer_id.id)) - cost_temp = [] - for costs in element.cost_ids: - cost_temp.append(costs.id) - temp.append(('default_cost_ids',cost_temp)) - temp.append(('default_date',time.strftime('%Y-%m-%d'))) - temp.append(('default_start_date',str(self.str_to_date(element.expiration_date)+datetime.timedelta(days=1)))) - temp.append(('default_purchaser_id',element.purchaser_id.id)) - temp.append(('default_ins_ref',element.ins_ref)) - #temp.append(('default_state','open')) - temp.append(('default_notes',element.notes)) - temp.append(('default_cost_frequency',element.cost_frequency)) - generated_cost = [] - for gen_cost in element.generated_cost_ids: - generated_cost.append(gen_cost.id) - temp.append(('default_generated_cost_ids',generated_cost)) - temp.append(('default_parent_id',element.parent_id.id)) - temp.append(('default_cost_type',element.cost_type)) - temp.append(('default_cost_subtype',element.cost_subtype.id)) + res[record.id] = -1 + return res + def act_renew_contract(self, cr, uid, ids, context=None): + assert len(ids) == 1, "This operation should only be done for 1 single contract at a time, as it it suppose to open a window as result" + for element in self.browse(cr, uid, ids, context=context): #compute end date - startdate = self.str_to_date(element.start_date) - enddate = self.str_to_date(element.expiration_date) - diffdate = (enddate-startdate) - newenddate = enddate+diffdate - temp.append(('default_expiration_date',str(newenddate))) - - - #data = self.read(cr, uid, ids, ['vehicle_id', 'cost_subtype', 'amount', 'odometer_id', 'odometer_unit', 'insurer_id', 'cost_ids', 'expiration_date', \ - # 'date', 'start_date', 'purchaser_id', 'ins_ref' ,'notes','cost_frequency', 'generated_cost']) - - - res['context'] = dict(temp) - #return super(fleet_vehicle_log_contract, self).copy(cr, uid, ids, default={}, context=None) - return res + startdate = str_to_datetime(element.start_date) + enddate = str_to_datetime(element.expiration_date) + diffdate = (enddate - startdate) + default = { + 'date': fields.date.context_today(self, cr, uid, context=context), + 'start_date': datetime.datetime.strftime(str_to_datetime(element.expiration_date) + datetime.timedelta(days=1), tools.DEFAULT_SERVER_DATE_FORMAT), + 'expiration_date': datetime.datetime.strftime(enddate + diffdate, tools.DEFAULT_SERVER_DATE_FORMAT), + } + newid = super(fleet_vehicle_log_contract, self).copy(cr, uid, element.id, default, context=context) + mod, modid = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'fleet_vehicle_log_contract_form') + return { + 'name':_("Renew Contract"), + 'view_mode': 'form', + 'view_id': modid, + 'view_type': 'tree,form', + 'res_model': 'fleet.vehicle.log.contract', + 'type': 'ir.actions.act_window', + 'nodestroy': True, + 'domain': '[]', + 'res_id': newid, + 'context': {'active_id':newid}, + } - def _get_default_contract_type(self, cr, uid, context): + def _get_default_contract_type(self, cr, uid, context=None): try: model, model_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'fleet', 'type_contract_leasing') except ValueError: model_id = False return model_id - def on_change_indic_cost(self,cr,uid,ids,cost_ids,context=None): - contracts = self.browse(cr,uid,ids,context=context) - totalsum=0 - for element in contracts: - for cost in element.cost_ids: - totalsum=totalsum+cost.amount + def on_change_indic_cost(self, cr, uid, ids, cost_ids, context=None): + totalsum = 0.0 for element in cost_ids: - if element[1] is False and element[2] is not False: - totalsum = totalsum+element[2]['amount'] + if element and len(element) == 3 and element[2] is not False: + totalsum += element[2].get('amount', 0.0) return { - 'value' : { - 'sum_cost' : totalsum, + 'value': { + 'sum_cost': totalsum, } } - def _get_sum_cost(self, cr, uid, ids, odometer_id, arg, context): - contracts = self.browse(cr,uid,ids,context=context) - totalsum=0 - res = [] - for element in contracts: - for cost in element.cost_ids: - totalsum=totalsum+cost.amount - res.append((element.id,totalsum)) - return dict(res) + def _get_sum_cost(self, cr, uid, ids, field_name, arg, context=None): + res = {} + for contract in self.browse(cr, uid, ids, context=context): + totalsum = 0 + for cost in contract.cost_ids: + totalsum += cost.amount + res[contract.id] = totalsum + return res + _inherits = {'fleet.vehicle.cost': 'cost_id'} _name = 'fleet.vehicle.log.contract' - _order='state,expiration_date' + _description = 'Contract information on a vehicle' + _order='state desc,expiration_date' _columns = { - 'name' : fields.function(_vehicle_contract_name_get_fnc, type="text", string='Name', store=True), - - 'start_date' : fields.date('Contract Start Date', required=False, help='Date when the coverage of the contract begins'), - '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)'), - 'warning_date' : fields.function(get_warning_date,type='integer',string='Warning Date',store=False), - - 'insurer_id' :fields.many2one('res.partner', 'Supplier', domain="[('supplier','=',True)]"), - 'purchaser_id' : fields.many2one('res.partner', 'Contractor',domain="['|',('customer','=',True),('employee','=',True)]",help='Person to which the contract is signed for'), - 'ins_ref' : fields.char('Contract Reference', size=64), - 'state' : fields.selection([('open', 'In Progress'),('toclose','To Close'), ('closed', 'Terminated')], 'Status', readonly=True, help='Choose wheter the contract is still valid or not'), - #'reminder' : fields.boolean('Renewal Reminder', help="Warn the user a few days before the expiration date of this contract"), - 'notes' : fields.text('Terms and Conditions', help='Write here all supplementary informations relative to this contract'), - 'odometer_id' : fields.many2one('fleet.vehicle.odometer', 'Odometer', required=False, help='Odometer measure of the vehicle at the moment of this log'), - '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'), - 'odometer_unit': fields.related('vehicle_id','odometer_unit',type="char",string="Unit",store=False, readonly=True), - 'cost_amount': fields.related('cost_id','amount',type="float",string="Amount",store=True, readonly=True), - 'cost_generated': fields.float('Recurring Cost Amount',help="Costs paid at regular intervals, depending on the cost frequency. If the cost frequency is set to unique, the cost will be logged at the start date"), - 'cost_frequency': fields.selection([('no','No'),('daily', 'Daily'),('weekly','Weekly'),('monthly','Monthly'),('yearly','Yearly')], 'Recurring Cost Frequency', help='Frequency of the recuring cost',required=True), - 'generated_cost_ids' : fields.one2many('fleet.vehicle.cost', 'contract_id', 'Generated Costs',ondelete='cascade'), - 'sum_cost' : fields.function(_get_sum_cost,type='float', string='Indicative Costs Total',readonly=True), + 'name': fields.function(_vehicle_contract_name_get_fnc, type="text", string='Name', store=True), + 'start_date': fields.date('Contract Start Date', help='Date when the coverage of the contract begins'), + 'expiration_date': fields.date('Contract Expiration Date', help='Date when the coverage of the contract expirates (by default, one year after begin date)'), + 'days_left': fields.function(get_days_left, type='integer', string='Warning Date'), + 'insurer_id' :fields.many2one('res.partner', 'Supplier'), + 'purchaser_id': fields.many2one('res.partner', 'Contractor', help='Person to which the contract is signed for'), + 'ins_ref': fields.char('Contract Reference', size=64), + 'state': fields.selection([('open', 'In Progress'), ('toclose','To Close'), ('closed', 'Terminated')], 'Status', readonly=True, help='Choose wheter the contract is still valid or not'), + 'notes': fields.text('Terms and Conditions', help='Write here all supplementary informations relative to this contract'), + 'cost_generated': fields.float('Recurring Cost Amount', help="Costs paid at regular intervals, depending on the cost frequency. If the cost frequency is set to unique, the cost will be logged at the start date"), + 'cost_frequency': fields.selection([('no','No'), ('daily', 'Daily'), ('weekly','Weekly'), ('monthly','Monthly'), ('yearly','Yearly')], 'Recurring Cost Frequency', help='Frequency of the recuring cost', required=True), + 'generated_cost_ids': fields.one2many('fleet.vehicle.cost', 'contract_id', 'Generated Costs', ondelete='cascade'), + 'sum_cost': fields.function(_get_sum_cost, type='float', string='Indicative Costs Total'), + 'cost_amount': fields.related('cost_id', 'amount', string='Amount', type='float', store=True), #we need to keep this field as a related with store=True because the graph view doesn't support (1) to address fields from inherited table and (2) fields that aren't stored in database } _defaults = { - 'purchaser_id': lambda self, cr, uid, ctx: uid, - 'date' : time.strftime('%Y-%m-%d'), - 'start_date' : time.strftime('%Y-%m-%d'), + 'purchaser_id': lambda self, cr, uid, ctx: self.pool.get('res.users').browse(cr, uid, uid, context=ctx).partner_id.id or False, + 'date': fields.date.context_today, + 'start_date': fields.date.context_today, 'state':'open', - 'expiration_date' : lambda self,cr,uid,ctx: self.compute_next_year_date(time.strftime('%Y-%m-%d')), - 'cost_frequency' : 'no', - 'cost_subtype' : _get_default_contract_type, + 'expiration_date': lambda self, cr, uid, ctx: self.compute_next_year_date(fields.date.context_today(self, cr, uid, context=ctx)), + 'cost_frequency': 'no', + 'cost_subtype_id': _get_default_contract_type, + 'cost_type': 'contract', } def copy(self, cr, uid, id, default=None, context=None): - default = default or {} - current_object = self.browse(cr,uid,id,context) - default['date'] = time.strftime('%Y-%m-%d') - default['start_date'] = time.strftime('%Y-%m-%d') - default['expiration_date'] = self.compute_next_year_date(time.strftime('%Y-%m-%d')) - #default['name'] = current_object.name + if default is None: + default = {} + today = fields.date.context_today(self, cr, uid, context=context) + default['date'] = today + default['start_date'] = today + default['expiration_date'] = self.compute_next_year_date(today) default['ins_ref'] = '' default['state'] = 'open' default['notes'] = '' - default['date'] = time.strftime('%Y-%m-%d') - - #default['odometer'] = current_object.odometer - #default['odometer_unit'] = current_object.odometer_unit return super(fleet_vehicle_log_contract, self).copy(cr, uid, id, default, context=context) - def contract_close(self, cr, uid, ids, *args): - self.write(cr, uid, ids, {'state': 'closed'}) - return True - - def contract_open(self, cr, uid, ids, *args): - self.write(cr, uid, ids, {'state': 'open'}) - return True - def create(self, cr, uid, data, context=None): - data['cost_type'] = 'contract' - cost_id = super(fleet_vehicle_log_contract, self).create(cr, uid, data, context=context) - return cost_id + def contract_close(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'state': 'closed'}, context=context) - -############################ -############################ -#Vehicle.log.contract.state class -############################ -############################ + def contract_open(self, cr, uid, ids, context=None): + return self.write(cr, uid, ids, {'state': 'open'}, context=context) class fleet_contract_state(osv.Model): _name = 'fleet.contract.state' + _description = 'Contains the different possible status of a leasing contract' + _columns = { - 'name':fields.char('Contract Status',size=32), - } \ No newline at end of file + 'name':fields.char('Contract Status', size=64, required=True), + }