From 647292a9635bae504d597068ea72cba1afc660b0 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:37:13 +0200 Subject: [PATCH 01/16] [IMP] fleet: Add a default value for 'acquisition_date' --- addons/fleet/models/fleet_vehicle.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index d7bac0d2925..676baa9f9e4 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -32,7 +32,8 @@ class FleetVehicle(models.Model): service_count = fields.Integer(compute="_compute_count_all", string='Services') fuel_logs_count = fields.Integer(compute="_compute_count_all", string='Fuel Log Count') odometer_count = fields.Integer(compute="_compute_count_all", string='Odometer') - acquisition_date = fields.Date('Immatriculation Date', required=False, help='Date when the vehicle has been immatriculated') + acquisition_date = fields.Date('Immatriculation Date', required=False, + default=fields.Date.today, help='Date when the vehicle has been immatriculated') color = fields.Char(help='Color of the vehicle') state_id = fields.Many2one('fleet.vehicle.state', 'State', default=_get_default_state, help='Current state of the vehicle', ondelete="set null") From b510e7f41b403f98f62e3421160d019495a4c13d Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:38:05 +0200 Subject: [PATCH 02/16] [IMP] fleet: Make the license plate not required It's not mandatory for a car in the fleet to have a license plate. It should be possible to create the car before the immatriculation date. --- addons/fleet/models/fleet_vehicle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 676baa9f9e4..76b26787ee7 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -19,7 +19,7 @@ class FleetVehicle(models.Model): name = fields.Char(compute="_compute_vehicle_name", store=True) active = fields.Boolean('Active', default=True, track_visibility="onchange") company_id = fields.Many2one('res.company', 'Company') - license_plate = fields.Char(required=True, track_visibility="onchange", + license_plate = fields.Char(track_visibility="onchange", help='License plate number of the vehicle (i = plate number for a car)') vin_sn = fields.Char('Chassis Number', help='Unique number written on the vehicle motor (VIN/SN number)', copy=False) driver_id = fields.Many2one('res.partner', 'Driver', track_visibility="onchange", help='Driver of the vehicle', copy=False) From 2bc85571a9748aa107130c6e272631f87c3eafff Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:40:00 +0200 Subject: [PATCH 03/16] [IMP] fleet: Display all the stages on the fleet.vehicle kanban view All the stage should be displayed to allow a user to move a car in another stage even if no other cars are into it. --- addons/fleet/models/fleet_vehicle.py | 7 ++++++- addons/fleet/views/fleet_vehicle_views.xml | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 76b26787ee7..96ce5575117 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -35,7 +35,8 @@ class FleetVehicle(models.Model): acquisition_date = fields.Date('Immatriculation Date', required=False, default=fields.Date.today, help='Date when the vehicle has been immatriculated') color = fields.Char(help='Color of the vehicle') - state_id = fields.Many2one('fleet.vehicle.state', 'State', default=_get_default_state, + state_id = fields.Many2one('fleet.vehicle.state', 'State', + default=_get_default_state, group_expand='_read_group_stage_ids', help='Current state of the vehicle', ondelete="set null") location = fields.Char(help='Location of the vehicle (garage, ...)') seats = fields.Integer('Seats Number', help='Number of seats of the vehicle') @@ -223,6 +224,10 @@ class FleetVehicle(models.Model): return super(FleetVehicle, self).write(vals) + @api.model + def _read_group_stage_ids(self, stages, domain, order): + return self.env['fleet.vehicle.state'].search([], order=order) + @api.multi def return_action_to_open(self): """ This opens the xml view specified in xml_id for the current vehicle """ diff --git a/addons/fleet/views/fleet_vehicle_views.xml b/addons/fleet/views/fleet_vehicle_views.xml index 0dc0463c778..c69e8250e60 100644 --- a/addons/fleet/views/fleet_vehicle_views.xml +++ b/addons/fleet/views/fleet_vehicle_views.xml @@ -227,6 +227,7 @@ fleet.vehicle form kanban,tree,form + {'search_default_groupby_status': 1}

Create a new vehicle From 47857a63ace46dd3d4d302fcafb46a75c242cb86 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:41:30 +0200 Subject: [PATCH 04/16] [IMP] fleet: Remove the unicity constraint on the driver It should be possible to assign 2 vehicles to the same person. The constraint is too restrictive. --- addons/fleet/models/fleet_vehicle.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 96ce5575117..5adaa742e2e 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -73,10 +73,6 @@ class FleetVehicle(models.Model): car_value = fields.Float(string="Catalog Value (VAT Incl.)", help='Value of the bought vehicle') residual_value = fields.Float() - _sql_constraints = [ - ('driver_id_unique', 'UNIQUE(driver_id)', 'Only one car can be assigned to the same employee!') - ] - @api.depends('model_id.brand_id.name', 'model_id.name', 'license_plate') def _compute_vehicle_name(self): for record in self: From 13bd8e7db64aeaafbbef9fa6a83dc933934f08dc Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:42:59 +0200 Subject: [PATCH 05/16] [IMP] fleet: Order cars by plate, then by acquisition date This commit allow users to see in the kanban/list view the oldest cars with no plates --- addons/fleet/models/fleet_vehicle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 5adaa742e2e..d2fe8e0f77f 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -10,7 +10,7 @@ class FleetVehicle(models.Model): _inherit = 'mail.thread' _name = 'fleet.vehicle' _description = 'Information on a vehicle' - _order = 'license_plate asc' + _order = 'license_plate asc, acquisition_date asc' def _get_default_state(self): state = self.env.ref('fleet.vehicle_state_active', raise_if_not_found=False) From 3fc4c3b966e80ab96f3f7c63f6718664a1a70ab7 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:46:29 +0200 Subject: [PATCH 06/16] [IMP] fleet: Add an informative 'First Contract Date' field The goal of this field is to be able to keep the value of the first contract even if it has been closed/deteled. It could be used to compute the depreciation of the car. --- addons/fleet/models/fleet_vehicle.py | 1 + addons/fleet/views/fleet_vehicle_views.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index d2fe8e0f77f..9ee90cb6a31 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -34,6 +34,7 @@ class FleetVehicle(models.Model): odometer_count = fields.Integer(compute="_compute_count_all", string='Odometer') acquisition_date = fields.Date('Immatriculation Date', required=False, default=fields.Date.today, help='Date when the vehicle has been immatriculated') + first_contract_date = fields.Date(string="First Contract Date", default=fields.Date.today) color = fields.Char(help='Color of the vehicle') state_id = fields.Many2one('fleet.vehicle.state', 'State', default=_get_default_state, group_expand='_read_group_stage_ids', diff --git a/addons/fleet/views/fleet_vehicle_views.xml b/addons/fleet/views/fleet_vehicle_views.xml index c69e8250e60..e2be8f8dc58 100644 --- a/addons/fleet/views/fleet_vehicle_views.xml +++ b/addons/fleet/views/fleet_vehicle_views.xml @@ -83,6 +83,7 @@ + From 7356c3b5b686e2eabaa597ca37ddaaff378d3f75 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:51:30 +0200 Subject: [PATCH 07/16] [IMP] fleet: Add 'Next Activities' on vehicles This commit adds: - The button on the chatter - The button on the kanban card and a progress bar on top of the stage --- addons/fleet/models/fleet_vehicle.py | 2 +- addons/fleet/views/fleet_vehicle_views.xml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 9ee90cb6a31..07b4f340691 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -7,7 +7,7 @@ from odoo import api, fields, models, _ class FleetVehicle(models.Model): - _inherit = 'mail.thread' + _inherit = ['mail.thread', 'mail.activity.mixin'] _name = 'fleet.vehicle' _description = 'Information on a vehicle' _order = 'license_plate asc, acquisition_date asc' diff --git a/addons/fleet/views/fleet_vehicle_views.xml b/addons/fleet/views/fleet_vehicle_views.xml index e2be8f8dc58..adc0022dcbc 100644 --- a/addons/fleet/views/fleet_vehicle_views.xml +++ b/addons/fleet/views/fleet_vehicle_views.xml @@ -112,6 +112,7 @@

+
@@ -178,6 +179,9 @@ + + + @@ -215,6 +219,9 @@ +
+ +
From 879f2ba9c7e38c3e40dc10bec0b1d4c0dbaec726 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:54:57 +0200 Subject: [PATCH 08/16] [IMP] l10n_be_hr_payroll_fleet: Create a related contract when creating a new vehicle Create a new contract with a recurring cost amount depreciated equal to the amount defined on the model. --- addons/l10n_be_hr_payroll_fleet/models/fleet.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/addons/l10n_be_hr_payroll_fleet/models/fleet.py b/addons/l10n_be_hr_payroll_fleet/models/fleet.py index da0bf8600fc..a3757321c2e 100644 --- a/addons/l10n_be_hr_payroll_fleet/models/fleet.py +++ b/addons/l10n_be_hr_payroll_fleet/models/fleet.py @@ -66,6 +66,17 @@ class FleetVehicle(models.Model): acquisition_date = vehicle._get_acquisition_date() vehicle.name += u" \u2022 " + str(round(vehicle.total_depreciated_cost, 2)) + u" \u2022 " + acquisition_date + @api.model + def create(self, vals): + res = super(FleetVehicle, self).create(vals) + if not res.log_contracts: + self.env['fleet.vehicle.log.contract'].create({ + 'vehicle_id': res.id, + 'recurring_cost_amount_depreciated': res.model_id.default_recurring_cost_amount_depreciated, + 'purchaser_id': res.driver_id.id, + }) + return res + def _get_acquisition_date(self): self.ensure_one() return babel.dates.format_date( From 2958bcc3837750b2c37588a46ab19196b759915c Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 10:58:40 +0200 Subject: [PATCH 09/16] [IMP] fleet: Archive related contracts when archiving a vehicle --- addons/fleet/models/fleet_vehicle.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 07b4f340691..16bf953e79a 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -219,7 +219,10 @@ class FleetVehicle(models.Model): if len(changes) > 0: self.message_post(body=", ".join(changes)) - return super(FleetVehicle, self).write(vals) + res = super(FleetVehicle, self).write(vals) + if 'active' in vals and not vals['active']: + self.mapped('log_contracts').write({'active': False}) + return res @api.model def _read_group_stage_ids(self, stages, domain, order): From 50dfff24620692a6574267b9cdc24178c7b7dfbb Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 11:09:17 +0200 Subject: [PATCH 10/16] [IMP] fleet: Allow to search vehicles based on the driver name --- addons/fleet/models/fleet_vehicle.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 16bf953e79a..e56c83014b6 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -4,6 +4,7 @@ from dateutil.relativedelta import relativedelta from odoo import api, fields, models, _ +from odoo.osv import expression class FleetVehicle(models.Model): @@ -228,6 +229,17 @@ class FleetVehicle(models.Model): def _read_group_stage_ids(self, stages, domain, order): return self.env['fleet.vehicle.state'].search([], order=order) + @api.model + def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): + domain = args or [] + domain = expression.AND([domain, [('name', operator, name)]]) + access_rights_uid = name_get_uid or self._uid + partners = self.env['res.partner']._search([('name', operator, name)], access_rights_uid=access_rights_uid) + if partners: + domain = expression.OR([domain, ['|', ('driver_id', 'in', partners.ids), ('driver_id', '=', False)]]) + rec = self._search(domain, limit=limit, access_rights_uid=access_rights_uid) + return rec.name_get() + @api.multi def return_action_to_open(self): """ This opens the xml view specified in xml_id for the current vehicle """ From 52fdeacfe102c5fa3d5c6b45d9b7dec60fb74f03 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 11:11:00 +0200 Subject: [PATCH 11/16] [IMP] l10n_be_hr_payroll_fleet: Set default values on model onchange --- addons/l10n_be_hr_payroll_fleet/models/fleet.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/addons/l10n_be_hr_payroll_fleet/models/fleet.py b/addons/l10n_be_hr_payroll_fleet/models/fleet.py index a3757321c2e..9fdf0c96efa 100644 --- a/addons/l10n_be_hr_payroll_fleet/models/fleet.py +++ b/addons/l10n_be_hr_payroll_fleet/models/fleet.py @@ -120,12 +120,19 @@ class FleetVehicle(models.Model): atn = car_value * min(0.18, (0.055 + 0.001 * (co2 - reference))) * magic_coeff return max(1280, atn) / 12.0 + @api.onchange('model_id') + def _onchange_model_id(self): + self.car_value = self.model_id.default_car_value + self.co2 = self.model_id.default_co2 + self.fuel_type = self.model_id.default_fuel_type + class FleetVehicleLogContract(models.Model): _inherit = 'fleet.vehicle.log.contract' recurring_cost_amount_depreciated = fields.Float("Recurring Cost Amount (depreciated)") + class FleetVehicleModel(models.Model): _inherit = 'fleet.vehicle.model' From ef8befeef48ed2de0477355b0741a67856a1ba80 Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 11:16:09 +0200 Subject: [PATCH 12/16] [IMP] fleet: Add subtype to track driver modifications --- addons/fleet/data/mail_data.xml | 24 ++++++++++++++++-------- addons/fleet/models/fleet_vehicle.py | 7 +++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/addons/fleet/data/mail_data.xml b/addons/fleet/data/mail_data.xml index a8098b50f6c..0fb2cbc3c96 100644 --- a/addons/fleet/data/mail_data.xml +++ b/addons/fleet/data/mail_data.xml @@ -1,10 +1,18 @@ - + + + + Contract to Renew + fa-car + + - - Contract to Renew - fa-car - - - - + + Changed Driver + 0 + fleet.vehicle + + Changed Driver + + + diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index e56c83014b6..59932524f2d 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -269,6 +269,13 @@ class FleetVehicle(models.Model): ) return res + @api.multi + def _track_subtype(self, init_values): + self.ensure_one() + if 'driver_id' in init_values: + return 'fleet.mt_fleet_driver_updated' + return super(FleetVehicle, self)._track_subtype(init_values) + class FleetVehicleOdometer(models.Model): _name = 'fleet.vehicle.odometer' From 02775e6cd2d007c991cebf5c6a0457ad546970ec Mon Sep 17 00:00:00 2001 From: Yannick Tivisse Date: Fri, 27 Apr 2018 12:02:25 +0200 Subject: [PATCH 13/16] [IMP] fleet: Introduce fleet.vehicle.assignation.log model Purpose ======= Currently it's impossible to know who was driving a given car at a given time. We have some piece of information like the immatriculation date of a vehicle or the date of the first contract. But it's not enough. This is problematic to solve a rather common issue: - Who is gonna pay the fine for having exceeded the speed limit? Specification ============= Introduce a simple model fleet.vehicle.assignation.log, containing info about: - The driver - The vehicle - The start Date - The end Date A simple button on the fleet vehicle should be sufficient to solve the issue. We cannot generate data from the salary package as these dates can't be predicted at the contract signature. --- addons/fleet/models/fleet_vehicle.py | 39 ++++++++++++++++++++++ addons/fleet/security/ir.model.access.csv | 1 + addons/fleet/views/fleet_vehicle_views.xml | 14 ++++++++ 3 files changed, 54 insertions(+) diff --git a/addons/fleet/models/fleet_vehicle.py b/addons/fleet/models/fleet_vehicle.py index 59932524f2d..93fadf2814f 100644 --- a/addons/fleet/models/fleet_vehicle.py +++ b/addons/fleet/models/fleet_vehicle.py @@ -193,6 +193,13 @@ class FleetVehicle(models.Model): else: self.image_medium = False + @api.model + def create(self, vals): + res = super(FleetVehicle, self).create(vals) + if 'driver_id' in vals and vals['driver_id']: + res.create_driver_history(vals['driver_id']) + return res + @api.multi def write(self, vals): """ @@ -221,10 +228,20 @@ class FleetVehicle(models.Model): self.message_post(body=", ".join(changes)) res = super(FleetVehicle, self).write(vals) + if 'driver_id' in vals and vals['driver_id']: + self.create_driver_history(vals['driver_id']) if 'active' in vals and not vals['active']: self.mapped('log_contracts').write({'active': False}) return res + def create_driver_history(self, driver_id): + for vehicle in self: + self.env['fleet.vehicle.assignation.log'].create({ + 'vehicle_id': vehicle.id, + 'driver_id': driver_id, + 'date_start': fields.Date.today(), + }) + @api.model def _read_group_stage_ids(self, stages, domain, order): return self.env['fleet.vehicle.state'].search([], order=order) @@ -276,6 +293,17 @@ class FleetVehicle(models.Model): return 'fleet.mt_fleet_driver_updated' return super(FleetVehicle, self)._track_subtype(init_values) + def open_assignation_logs(self): + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': 'Assignation Logs', + 'view_mode': 'tree', + 'res_model': 'fleet.vehicle.assignation.log', + 'domain': [('vehicle_id', '=', self.id)], + 'context': {'default_driver_id': self.driver_id.id, 'default_vehicle_id': self.id} + } + class FleetVehicleOdometer(models.Model): _name = 'fleet.vehicle.odometer' @@ -333,3 +361,14 @@ class FleetServiceType(models.Model): ('contract', 'Contract'), ('service', 'Service') ], 'Category', required=True, help='Choose whether the service refer to contracts, vehicle services or both') + + +class FleetVehicleAssignationLog(models.Model): + _name = "fleet.vehicle.assignation.log" + _description = "Drivers history on a vehicle" + _order = "date_start" + + vehicle_id = fields.Many2one('fleet.vehicle', string="Vehicle", required=True) + driver_id = fields.Many2one('res.partner', string="Driver", required=True) + date_start = fields.Date(string="Start Date") + date_end = fields.Date(string="End Date") diff --git a/addons/fleet/security/ir.model.access.csv b/addons/fleet/security/ir.model.access.csv index 78090d174e0..a5c93dc9914 100644 --- a/addons/fleet/security/ir.model.access.csv +++ b/addons/fleet/security/ir.model.access.csv @@ -20,3 +20,4 @@ fleet_vehicle_log_contract_access_right,fleet_vehicle_log_contract_access_right, fleet_service_type_access_right,fleet_service_type_access_right,model_fleet_service_type,fleet_group_manager,1,1,1,1 access_fleet_vehicle_cost,access_fleet_vehicle_cost,model_fleet_vehicle_cost,fleet_group_manager,1,1,1,1 access_mail_activity_type_fleet_manager,mail.activity.type.fleet.manager,mail.model_mail_activity_type,fleet.fleet_group_manager,1,1,1,1 +access_fleet_vehicle_assignation_log_fleet_group_user,fleet_vehicle_assignation_log fleet_group_user,fleet.model_fleet_vehicle_assignation_log,fleet.fleet_group_user,1,1,1,1 diff --git a/addons/fleet/views/fleet_vehicle_views.xml b/addons/fleet/views/fleet_vehicle_views.xml index adc0022dcbc..3761f1c2986 100644 --- a/addons/fleet/views/fleet_vehicle_views.xml +++ b/addons/fleet/views/fleet_vehicle_views.xml @@ -11,6 +11,7 @@
+