Purpose ======= It is currently difficult to know exactly what is used for costs and services on the contracts. Hence it make it difficult to evolve the fleet application We should clean the models in order to have something that is clearer Specification ============= Cleanup of models: removed Fuel and Cost. Contract and Services are no longer inheriting Cost and are seperate models simplifying the use of Fleet. A contract now has included services and they are no longer generating cost. closes odoo/odoo#34090 Taskid: 1931775 Related: odoo/enterprise#4572 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
183 lines
8.9 KiB
Python
183 lines
8.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import UserError
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
class FleetVehicleLogContract(models.Model):
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_name = 'fleet.vehicle.log.contract'
|
|
_description = 'Contract information on a vehicle'
|
|
_order = 'state desc,expiration_date'
|
|
|
|
def compute_next_year_date(self, strdate):
|
|
oneyear = relativedelta(years=1)
|
|
start_date = fields.Date.from_string(strdate)
|
|
return fields.Date.to_string(start_date + oneyear)
|
|
|
|
vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', default=1, required=True, help='Vehicle concerned by this log')
|
|
cost_subtype_id = fields.Many2one('fleet.service.type', 'Type', help='Cost type purchased with this cost', domain=[('category', '=', 'contract')])
|
|
amount = fields.Float('Cost')
|
|
date = fields.Date(help='Date when the cost has been executed')
|
|
company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
|
|
currency_id = fields.Many2one('res.currency', related='company_id.currency_id')
|
|
name = fields.Char(string='Name', compute='_compute_contract_name', store=True)
|
|
active = fields.Boolean(default=True)
|
|
user_id = fields.Many2one('res.users', 'Responsible', default=lambda self: self.env.user, index=True)
|
|
start_date = fields.Date('Contract Start Date', default=fields.Date.context_today,
|
|
help='Date when the coverage of the contract begins')
|
|
expiration_date = fields.Date('Contract Expiration Date', default=lambda self:
|
|
self.compute_next_year_date(fields.Date.context_today(self)),
|
|
help='Date when the coverage of the contract expirates (by default, one year after begin date)')
|
|
days_left = fields.Integer(compute='_compute_days_left', string='Warning Date')
|
|
insurer_id = fields.Many2one('res.partner', 'Vendor')
|
|
purchaser_id = fields.Many2one(related='vehicle_id.driver_id', string='Driver')
|
|
ins_ref = fields.Char('Reference', size=64, copy=False)
|
|
state = fields.Selection([
|
|
('futur', 'Incoming'),
|
|
('open', 'In Progress'),
|
|
('expired', 'Expired'),
|
|
('closed', 'Closed')
|
|
], 'Status', default='open', readonly=True,
|
|
help='Choose whether the contract is still valid or not',
|
|
tracking=True,
|
|
copy=False)
|
|
notes = fields.Text('Terms and Conditions', help='Write here all supplementary information relative to this contract', copy=False)
|
|
cost_generated = fields.Float('Recurring Cost')
|
|
cost_frequency = fields.Selection([
|
|
('no', 'No'),
|
|
('daily', 'Daily'),
|
|
('weekly', 'Weekly'),
|
|
('monthly', 'Monthly'),
|
|
('yearly', 'Yearly')
|
|
], 'Recurring Cost Frequency', default='monthly', help='Frequency of the recuring cost', required=True)
|
|
service_ids = fields.Many2many('fleet.service.type', string="Included Services")
|
|
|
|
@api.depends('vehicle_id', 'cost_subtype_id')
|
|
def _compute_contract_name(self):
|
|
for record in self:
|
|
name = record.vehicle_id.name
|
|
if record.cost_subtype_id.name:
|
|
name = record.cost_subtype_id.name + ' ' + name
|
|
record.name = name
|
|
|
|
@api.depends('expiration_date', 'state')
|
|
def _compute_days_left(self):
|
|
"""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
|
|
"""
|
|
for record in self:
|
|
if record.expiration_date and record.state in ['open', 'expired']:
|
|
today = fields.Date.from_string(fields.Date.today())
|
|
renew_date = fields.Date.from_string(record.expiration_date)
|
|
diff_time = (renew_date - today).days
|
|
record.days_left = diff_time > 0 and diff_time or 0
|
|
else:
|
|
record.days_left = -1
|
|
|
|
def write(self, vals):
|
|
res = super(FleetVehicleLogContract, self).write(vals)
|
|
if vals.get('expiration_date') or vals.get('user_id'):
|
|
self.activity_reschedule(['fleet.mail_act_fleet_contract_to_renew'], date_deadline=vals.get('expiration_date'), new_user_id=vals.get('user_id'))
|
|
return res
|
|
|
|
def contract_close(self):
|
|
for record in self:
|
|
record.state = 'closed'
|
|
|
|
def contract_draft(self):
|
|
for record in self:
|
|
record.state = 'futur'
|
|
|
|
def contract_open(self):
|
|
for record in self:
|
|
record.state = 'open'
|
|
|
|
@api.model
|
|
def scheduler_manage_contract_expiration(self):
|
|
# 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
|
|
params = self.env['ir.config_parameter'].sudo()
|
|
delay_alert_contract = int(params.get_param('hr_fleet.delay_alert_contract', default=30))
|
|
date_today = fields.Date.from_string(fields.Date.today())
|
|
outdated_days = fields.Date.to_string(date_today + relativedelta(days=+delay_alert_contract))
|
|
nearly_expired_contracts = self.search([('state', '=', 'open'), ('expiration_date', '<', outdated_days)])
|
|
|
|
for contract in nearly_expired_contracts.filtered(lambda contract: contract.user_id):
|
|
contract.activity_schedule(
|
|
'fleet.mail_act_fleet_contract_to_renew', contract.expiration_date,
|
|
user_id=contract.user_id.id)
|
|
|
|
expired_contracts = self.search([('state', 'not in', ['expired', 'closed']), ('expiration_date', '<',fields.Date.today() )])
|
|
expired_contracts.write({'state': 'expired'})
|
|
|
|
futur_contracts = self.search([('state', 'not in', ['futur', 'closed']), ('start_date', '>', fields.Date.today())])
|
|
futur_contracts.write({'state': 'futur'})
|
|
|
|
now_running_contracts = self.search([('state', '=', 'futur'), ('start_date', '<=', fields.Date.today())])
|
|
now_running_contracts.write({'state': 'open'})
|
|
|
|
def run_scheduler(self):
|
|
self.scheduler_manage_contract_expiration()
|
|
|
|
class FleetVehicleLogServices(models.Model):
|
|
_name = 'fleet.vehicle.log.services'
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_rec_name = 'service_type_id'
|
|
_description = 'Services for vehicles'
|
|
|
|
@api.model
|
|
def default_get(self, default_fields):
|
|
res = super(FleetVehicleLogServices, self).default_get(default_fields)
|
|
service = self.env.ref('fleet.type_service_service_8', raise_if_not_found=False)
|
|
res.update({
|
|
'date': fields.Date.context_today(self),
|
|
'service_type_id': service.id if service else None,
|
|
})
|
|
return res
|
|
|
|
vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', default=1, required=True, help='Vehicle concerned by this log')
|
|
amount = fields.Float('Cost')
|
|
odometer_id = fields.Many2one('fleet.vehicle.odometer', 'Odometer', help='Odometer measure of the vehicle at the moment of this log')
|
|
odometer = fields.Float(compute="_get_odometer", inverse='_set_odometer', string='Odometer Value',
|
|
help='Odometer measure of the vehicle at the moment of this log')
|
|
odometer_unit = fields.Selection(related='vehicle_id.odometer_unit', string="Unit", readonly=True)
|
|
date = fields.Date(help='Date when the cost has been executed')
|
|
company_id = fields.Many2one('res.company', 'Company', default=lambda self: self.env.company)
|
|
currency_id = fields.Many2one('res.currency', related='company_id.currency_id')
|
|
purchaser_id = fields.Many2one(related='vehicle_id.driver_id', string="Driver")
|
|
inv_ref = fields.Char('Vendor Reference')
|
|
vendor_id = fields.Many2one('res.partner', 'Vendor')
|
|
notes = fields.Text()
|
|
service_type_id = fields.Many2one('fleet.service.type', 'Service Type', required=True)
|
|
|
|
def _get_odometer(self):
|
|
self.odometer = 0
|
|
for record in self:
|
|
if record.odometer_id:
|
|
record.odometer = record.odometer_id.value
|
|
|
|
def _set_odometer(self):
|
|
for record in self:
|
|
if not record.odometer:
|
|
raise UserError(_('Emptying the odometer value of a vehicle is not allowed.'))
|
|
odometer = self.env['fleet.vehicle.odometer'].create({
|
|
'value': record.odometer,
|
|
'date': record.date or fields.Date.context_today(record),
|
|
'vehicle_id': record.vehicle_id.id
|
|
})
|
|
self.odometer_id = odometer
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for data in vals_list:
|
|
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(FleetVehicleLogServices, self).create(vals_list) |