[IMP] fleet: Improve general UX (Back2basics)
Overall UI review of the fleet app. Also changes the behaviour of shared fields between vehicles and vehicle models. Task ID: 2468228 closes odoo/odoo#72943 Related: odoo/upgrade#2601 Related: odoo/enterprise#19356 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
committed by
Yannick Tivisse
parent
4077f5189a
commit
c80002f660
@@ -5,8 +5,17 @@ from dateutil.relativedelta import relativedelta
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.osv import expression
|
||||
from odoo.addons.fleet.models.fleet_vehicle_model import FUEL_TYPES
|
||||
|
||||
|
||||
#Some fields don't have the exact same name
|
||||
MODEL_FIELDS_TO_VEHICLE = {
|
||||
'transmission': 'transmission', 'model_year': 'model_year', 'electric_assistance': 'electric_assistance',
|
||||
'color': 'color', 'seats': 'seats', 'doors': 'doors', 'trailer_hook': 'trailer_hook',
|
||||
'default_co2': 'co2', 'co2_standard': 'co2_standard', 'default_fuel_type': 'fuel_type',
|
||||
'power': 'power', 'horsepower': 'horsepower', 'horsepower_tax': 'horsepower_tax',
|
||||
}
|
||||
|
||||
class FleetVehicle(models.Model):
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_name = 'fleet.vehicle'
|
||||
@@ -18,7 +27,7 @@ class FleetVehicle(models.Model):
|
||||
return state if state and state.id else False
|
||||
|
||||
name = fields.Char(compute="_compute_vehicle_name", store=True)
|
||||
description = fields.Html("Vehicle Description")
|
||||
description = fields.Html("Vehicle Description", help="Add a note about this vehicle")
|
||||
active = fields.Boolean('Active', default=True, tracking=True)
|
||||
fleet_id = fields.Many2one('fleet.category', string='Fleet')
|
||||
manager_id = fields.Many2one(
|
||||
@@ -35,10 +44,12 @@ class FleetVehicle(models.Model):
|
||||
store=True,
|
||||
)
|
||||
currency_id = fields.Many2one('res.currency', related='company_id.currency_id')
|
||||
country_id = fields.Many2one('res.country', related='company_id.country_id')
|
||||
country_code = fields.Char(related='country_id.code')
|
||||
license_plate = fields.Char(tracking=True,
|
||||
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)
|
||||
trailer_hook = fields.Boolean(default=False)
|
||||
trailer_hook = fields.Boolean(default=False, string='Trailer Hitch', compute='_compute_model_fields', store=True, readonly=False)
|
||||
driver_id = fields.Many2one('res.partner', 'Driver', tracking=True, help='Driver of the vehicle', copy=False)
|
||||
future_driver_id = fields.Many2one('res.partner', 'Future Driver', tracking=True, help='Next Driver of the vehicle', copy=False, domain="['|', ('company_id', '=', False), ('company_id', '=', company_id)]")
|
||||
model_id = fields.Many2one('fleet.vehicle.model', 'Model',
|
||||
@@ -56,15 +67,15 @@ class FleetVehicle(models.Model):
|
||||
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')
|
||||
color = fields.Char(help='Color of the vehicle', compute='_compute_model_fields', store=True, readonly=False)
|
||||
state_id = fields.Many2one('fleet.vehicle.state', 'State',
|
||||
default=_get_default_state, group_expand='_read_group_stage_ids',
|
||||
tracking=True,
|
||||
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')
|
||||
model_year = fields.Char('Model Year', help='Year of the model')
|
||||
doors = fields.Integer('Doors Number', help='Number of doors of the vehicle', compute="_compute_doors", store=True, readonly=True)
|
||||
seats = fields.Integer('Seats Number', help='Number of seats of the vehicle', compute='_compute_model_fields', store=True, readonly=False)
|
||||
model_year = fields.Char('Model Year', help='Year of the model', compute='_compute_model_fields', store=True, readonly=False)
|
||||
doors = fields.Integer('Doors Number', help='Number of doors of the vehicle', compute='_compute_model_fields', store=True, readonly=False)
|
||||
tag_ids = fields.Many2many('fleet.vehicle.tag', 'fleet_vehicle_vehicle_tag_rel', 'vehicle_tag_id', 'tag_id', 'Tags', copy=False)
|
||||
odometer = fields.Float(compute='_get_odometer', inverse='_set_odometer', string='Last Odometer',
|
||||
help='Odometer measure of the vehicle at the moment of this log')
|
||||
@@ -74,23 +85,13 @@ class FleetVehicle(models.Model):
|
||||
], 'Odometer Unit', default='kilometers', help='Unit of the odometer ', required=True)
|
||||
transmission = fields.Selection(
|
||||
[('manual', 'Manual'), ('automatic', 'Automatic')], 'Transmission', help='Transmission Used by the vehicle',
|
||||
compute='_compute_transmission', store=True, readonly=False)
|
||||
fuel_type = fields.Selection([
|
||||
('gasoline', 'Gasoline'),
|
||||
('diesel', 'Diesel'),
|
||||
('lpg', 'LPG'),
|
||||
('electric', 'Electric'),
|
||||
('hybrid', 'Hybrid'),
|
||||
('plug_in_hybrid_diesel', 'Plug-in Hybrid Diesel'),
|
||||
('plug_in_hybrid_gasoline', 'Plug-in Hybrid Gasoline'),
|
||||
('full_hybrid_gasoline', 'Full Hybrid Gasoline'),
|
||||
('cng', 'CNG'),
|
||||
('hydrogen', 'Hydrogen'),
|
||||
], 'Fuel Type', help='Fuel Used by the vehicle')
|
||||
horsepower = fields.Integer()
|
||||
horsepower_tax = fields.Float('Horsepower Taxation')
|
||||
power = fields.Integer('Power', help='Power in kW of the vehicle')
|
||||
co2 = fields.Float('CO2 Emissions', help='CO2 emissions of the vehicle')
|
||||
compute='_compute_model_fields', store=True, readonly=False)
|
||||
fuel_type = fields.Selection(FUEL_TYPES, 'Fuel Type', help='Fuel Used by the vehicle', compute='_compute_model_fields', store=True, readonly=False)
|
||||
horsepower = fields.Integer(compute='_compute_model_fields', store=True, readonly=False)
|
||||
horsepower_tax = fields.Float('Horsepower Taxation', compute='_compute_model_fields', store=True, readonly=False)
|
||||
power = fields.Integer('Power', help='Power in kW of the vehicle', compute='_compute_model_fields', store=True, readonly=False)
|
||||
co2 = fields.Float('CO2 Emissions', help='CO2 emissions of the vehicle', compute='_compute_model_fields', store=True, readonly=False)
|
||||
co2_standard = fields.Char(compute='_compute_model_fields', store=True, readonly=False)
|
||||
image_128 = fields.Image(related='model_id.image_128', readonly=True)
|
||||
contract_renewal_due_soon = fields.Boolean(compute='_compute_contract_reminder', search='_search_contract_renewal_due_soon',
|
||||
string='Has Contracts to renew')
|
||||
@@ -111,7 +112,7 @@ class FleetVehicle(models.Model):
|
||||
plan_to_change_bike = fields.Boolean(related='driver_id.plan_to_change_bike', store=True, readonly=False)
|
||||
vehicle_type = fields.Selection(related='model_id.vehicle_type')
|
||||
frame_type = fields.Selection([('diamant', 'Diamant'), ('trapez', 'Trapez'), ('wave', 'Wave')], help="Frame type of the bike")
|
||||
electric_assistance = fields.Boolean()
|
||||
electric_assistance = fields.Boolean(compute='_compute_model_fields', store=True, readonly=False)
|
||||
frame_size = fields.Float()
|
||||
|
||||
@api.depends('fleet_id')
|
||||
@@ -126,10 +127,21 @@ class FleetVehicle(models.Model):
|
||||
if record.fleet_id:
|
||||
record.company_id = record.fleet_id.company_id
|
||||
|
||||
@api.depends('vehicle_type')
|
||||
def _compute_doors(self):
|
||||
for record in self:
|
||||
record.doors = 5 if record.model_id.vehicle_type == 'car' else 0
|
||||
@api.depends('model_id')
|
||||
def _compute_model_fields(self):
|
||||
'''
|
||||
Copies all the related fields from the model to the vehicle
|
||||
'''
|
||||
model_values = dict()
|
||||
for vehicle in self.filtered('model_id'):
|
||||
if vehicle.model_id.id in model_values:
|
||||
write_vals = model_values[vehicle.model_id.id]
|
||||
else:
|
||||
# copy if value is truthy
|
||||
write_vals = {MODEL_FIELDS_TO_VEHICLE[key]: vehicle.model_id[key] for key in MODEL_FIELDS_TO_VEHICLE\
|
||||
if vehicle.model_id[key]}
|
||||
model_values[vehicle.model_id.id] = write_vals
|
||||
vehicle.write(write_vals)
|
||||
|
||||
@api.depends('model_id.brand_id.name', 'model_id.name', 'license_plate')
|
||||
def _compute_vehicle_name(self):
|
||||
@@ -201,12 +213,6 @@ class FleetVehicle(models.Model):
|
||||
record.contract_renewal_name = name
|
||||
record.contract_state = state
|
||||
|
||||
@api.depends('model_id')
|
||||
def _compute_transmission(self):
|
||||
for vehicle in self:
|
||||
if vehicle.model_id:
|
||||
vehicle.transmission = vehicle.model_id.transmission
|
||||
|
||||
def _get_analytic_name(self):
|
||||
# This function is used in fleet_account and is overrided in l10n_be_hr_payroll_fleet
|
||||
return self.license_plate or _('No plate')
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
from odoo import _, api, fields, models
|
||||
|
||||
|
||||
FUEL_TYPES = [
|
||||
('gasoline', 'Gasoline'), ('diesel', 'Diesel'), ('lpg', 'LPG'),
|
||||
('electric', 'Electric'), ('hybrid', 'Hybrid'), ('plug_in_hybrid_diesel', 'Plug-in Hybrid Diesel'),
|
||||
('plug_in_hybrid_gasoline', 'Plug-in Hybrid Gasoline'), ('full_hybrid_gasoline', 'Full Hybrid Gasoline'),
|
||||
('cng', 'CNG'), ('hydrogen', 'Hydrogen'),
|
||||
]
|
||||
|
||||
class FleetVehicleModel(models.Model):
|
||||
_name = 'fleet.vehicle.model'
|
||||
_description = 'Model of a vehicle'
|
||||
@@ -18,6 +25,18 @@ class FleetVehicleModel(models.Model):
|
||||
vehicle_type = fields.Selection([('car', 'Car'), ('bike', 'Bike')], default='car', required=True)
|
||||
transmission = fields.Selection([('manual', 'Manual'), ('automatic', 'Automatic')], 'Transmission', help='Transmission Used by the vehicle')
|
||||
vehicle_count = fields.Integer(compute='_compute_vehicle_count')
|
||||
model_year = fields.Integer()
|
||||
color = fields.Char()
|
||||
seats = fields.Integer(string='Seats Number')
|
||||
doors = fields.Integer(string='Doors Number')
|
||||
trailer_hook = fields.Boolean(default=False, string='Trailer Hitch')
|
||||
default_co2 = fields.Float('CO2 Emissions')
|
||||
co2_standard = fields.Char()
|
||||
default_fuel_type = fields.Selection(FUEL_TYPES, 'Fuel Type', default='diesel')
|
||||
power = fields.Integer('Power')
|
||||
horsepower = fields.Integer()
|
||||
horsepower_tax = fields.Float('Horsepower Taxation')
|
||||
electric_assistance = fields.Boolean(default=False)
|
||||
|
||||
@api.depends('name', 'brand_id')
|
||||
def name_get(self):
|
||||
|
||||
@@ -32,21 +32,57 @@
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Information" name="information" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}">
|
||||
<group string="Vehicle Information">
|
||||
<field name="transmission"/>
|
||||
<page string="Information" name="information">
|
||||
<group>
|
||||
<group string="Model" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}">
|
||||
<field name="seats"/>
|
||||
<field name="doors"/>
|
||||
<field name="color"/>
|
||||
<field name="model_year"/>
|
||||
<field name="trailer_hook"/>
|
||||
</group>
|
||||
<group id="vehicle_information" string="Vehicle Information" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}">
|
||||
<field name="electric_assistance"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Engine" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}">
|
||||
<group>
|
||||
<field name="default_fuel_type" required="1"/>
|
||||
<label for="default_co2"/>
|
||||
<div class="o_row" name="default_co2">
|
||||
<field name="default_co2"/><span>g/km</span>
|
||||
</div>
|
||||
<field name="co2_standard"/>
|
||||
<field name="transmission"/>
|
||||
</group>
|
||||
<group>
|
||||
<label for="power"/>
|
||||
<div class="o_row">
|
||||
<field name="power"/><span>kW</span>
|
||||
</div>
|
||||
<field name="horsepower"/>
|
||||
<field name="horsepower_tax"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Vendors" name="vendors">
|
||||
<field name="vendors">
|
||||
<kanban quick_create="false" create="true">
|
||||
<field name="name"/>
|
||||
<field name="phone"/>
|
||||
<field name="email"/>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div style="position: relative" class="oe_kanban_global_click">
|
||||
<div>
|
||||
<div class="o_kanban_record_title">
|
||||
<field name="name"/>
|
||||
<div class="o_kanban_details float-right">
|
||||
<span class="text-muted">
|
||||
<t t-if="record.phone.raw_value"><field name="phone"/><br/></t>
|
||||
<t t-if="record.email.raw_value"><field name="email"/></t>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
</header>
|
||||
<sheet>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="country_code" invisible="1"/>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button name="open_assignation_logs"
|
||||
type="object"
|
||||
@@ -76,53 +77,66 @@
|
||||
<field name="location"/>
|
||||
</group>
|
||||
<group string="Vehicle">
|
||||
<field name="acquisition_date" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<field name="vin_sn"/>
|
||||
<label for="odometer" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<div class="o_row" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}">
|
||||
<field name="odometer"/>
|
||||
<field name="odometer_unit"/>
|
||||
</div>
|
||||
<field name="acquisition_date" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<field name="vin_sn"/>
|
||||
<field name="trailer_hook"/>
|
||||
<field name="car_value" widget="monetary"/>
|
||||
<field name="net_car_value" widget="monetary"/>
|
||||
<field name="residual_value" widget="monetary"/>
|
||||
<field name="manager_id" domain="[('share', '=', False)]"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group string="Contract" name="contract">
|
||||
<field name="manager_id" domain="[('share', '=', False)]"/>
|
||||
<field name="first_contract_date"/>
|
||||
</group>
|
||||
<group string="Model">
|
||||
<field name="seats" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<field name="doors" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<field name="color"/>
|
||||
<field name="model_year"/>
|
||||
<field name="frame_type" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}"/>
|
||||
<label for="frame_size" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}"/>
|
||||
<div class="o_row" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}">
|
||||
<field name="frame_size" /><span>cm</span>
|
||||
</div>
|
||||
<field name="electric_assistance" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}"/>
|
||||
</group>
|
||||
<group string="Engine" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}">
|
||||
<field name="transmission"/>
|
||||
<field name="fuel_type"/>
|
||||
<label for="co2"/>
|
||||
<div class="o_row" name="co2">
|
||||
<field name="co2"/><span>g/km</span>
|
||||
</div>
|
||||
<field name="horsepower"/>
|
||||
<field name="horsepower_tax" widget="monetary"/>
|
||||
<label for="power"/>
|
||||
<div class="o_row">
|
||||
<field name="power"/><span>kW</span>
|
||||
</div>
|
||||
</group>
|
||||
<group string="Description">
|
||||
<field name="description" nolabel="1" placeholder="Write here any other information related to this vehicle" />
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Tax Info">
|
||||
<group>
|
||||
<group string="Fiscality">
|
||||
<field name="horsepower_tax" widget="monetary"/>
|
||||
</group>
|
||||
<group string="Contract">
|
||||
<field name="first_contract_date"/>
|
||||
<field name="car_value" widget="monetary"/>
|
||||
<field name="net_car_value" widget="monetary"/>
|
||||
<field name="residual_value" widget="monetary"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Model">
|
||||
<group>
|
||||
<group string="Model">
|
||||
<field name="model_year"/>
|
||||
<field name="transmission"/>
|
||||
<field name="color"/>
|
||||
<field name="seats" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<field name="doors" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<field name="trailer_hook" attrs="{'invisible': [('vehicle_type', '!=', 'car')]}"/>
|
||||
<field name="frame_type" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}"/>
|
||||
<label for="frame_size" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}"/>
|
||||
<div class="o_row" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}">
|
||||
<field name="frame_size" /><span>cm</span>
|
||||
</div>
|
||||
<field name="electric_assistance" attrs="{'invisible': [('vehicle_type', '!=', 'bike')]}"/>
|
||||
</group>
|
||||
<group string="Engine">
|
||||
<field name="horsepower"/>
|
||||
<label for="power"/>
|
||||
<div class="o_row">
|
||||
<field name="power"/><span>kW</span>
|
||||
</div>
|
||||
<field name="fuel_type"/>
|
||||
<label for="co2"/>
|
||||
<div class="o_row" name="co2">
|
||||
<field name="co2"/><span>g/km</span>
|
||||
</div>
|
||||
<field name="co2_standard"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Note">
|
||||
<field name="description" nolabel="1" placeholder="Write here any other information related to this vehicle" />
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_follower_ids"/>
|
||||
|
||||
Reference in New Issue
Block a user