Начальное наполнение

This commit is contained in:
parent 5eb8381fb3
commit a43ec1cf63
175 changed files with 179912 additions and 0 deletions

5
__init__.py Normal file
View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
from . import report

56
__manifest__.py Normal file
View File

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name' : 'Fleet',
'version' : '0.1',
'sequence': 185,
'category': 'Human Resources/Fleet',
'website' : 'https://www.odoo.com/app/fleet',
'summary' : 'Manage your fleet and track car costs',
'description' : """
Vehicle, leasing, insurances, cost
==================================
With this module, Odoo helps you managing all your vehicles, the
contracts associated to those vehicle as well as services, costs
and many other features necessary to the management of your fleet
of vehicle(s)
Main Features
-------------
* Add vehicles to your fleet
* Manage contracts for vehicles
* Reminder when a contract reach its expiration date
* Add services, odometer values for all vehicles
* Show all costs associated to a vehicle or to a type of service
* Analysis graph for costs
""",
'depends': [
'base',
'mail',
],
'data': [
'security/fleet_security.xml',
'security/ir.model.access.csv',
'views/fleet_vehicle_model_views.xml',
'views/fleet_vehicle_views.xml',
'views/fleet_vehicle_cost_views.xml',
'views/fleet_board_view.xml',
'views/mail_activity_views.xml',
'views/res_config_settings_views.xml',
'data/fleet_cars_data.xml',
'data/fleet_data.xml',
'data/mail_message_subtype_data.xml',
'data/mail_activity_type_data.xml',
],
'demo': ['data/fleet_demo.xml'],
'installable': True,
'application': True,
'assets': {
'web.assets_backend': [
'fleet/static/src/**/*',
],
},
'license': 'LGPL-3',
}

492
data/fleet_cars_data.xml Normal file
View File

@ -0,0 +1,492 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="brand_abarth" model="fleet.vehicle.model.brand">
<field name="name">Abarth</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_abarth-image.png"/>
</record>
<record id="brand_acura" model="fleet.vehicle.model.brand">
<field name="name">Acura</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_acura-image.png"/>
</record>
<record id="brand_alfa" model="fleet.vehicle.model.brand">
<field name="name">Alfa</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_alfa-image.png"/>
</record>
<record id="brand_audi" model="fleet.vehicle.model.brand">
<field name="name">Audi</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_audi-image.png"/>
</record>
<record id="brand_austin" model="fleet.vehicle.model.brand">
<field name="name">Austin</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_austin-image.png"/>
</record>
<record id="brand_bentley" model="fleet.vehicle.model.brand">
<field name="name">Bentley</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_bentley-image.png"/>
</record>
<record id="brand_bmw" model="fleet.vehicle.model.brand">
<field name="name">Bmw</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_bmw-image.png"/>
</record>
<record id="brand_bugatti" model="fleet.vehicle.model.brand">
<field name="name">Bugatti</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_bugatti-image.png"/>
</record>
<record id="brand_buick" model="fleet.vehicle.model.brand">
<field name="name">Buick</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_buick-image.png"/>
</record>
<record id="brand_byd" model="fleet.vehicle.model.brand">
<field name="name">Byd</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_byd-image.png"/>
</record>
<record id="brand_cadillac" model="fleet.vehicle.model.brand">
<field name="name">Cadillac</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_cadillac-image.png"/>
</record>
<record id="brand_chevrolet" model="fleet.vehicle.model.brand">
<field name="name">Chevrolet</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_chevrolet-image.png"/>
</record>
<record id="brand_chrysler" model="fleet.vehicle.model.brand">
<field name="name">Chrysler</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_chrysler-image.png"/>
</record>
<record id="brand_citroen" model="fleet.vehicle.model.brand">
<field name="name">Citroen</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_citroen-image.png"/>
</record>
<record id="brand_corre_la_licorne" model="fleet.vehicle.model.brand">
<field name="name">Corre La Licorne</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_corre-la-licorne-image.png"/>
</record>
<record id="brand_daewoo" model="fleet.vehicle.model.brand">
<field name="name">Daewoo</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_daewoo-image.png"/>
</record>
<record id="brand_dodge" model="fleet.vehicle.model.brand">
<field name="name">Dodge</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_dodge-image.png"/>
</record>
<record id="brand_ferrari" model="fleet.vehicle.model.brand">
<field name="name">Ferrari</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_ferrari-image.png"/>
</record>
<record id="brand_fiat" model="fleet.vehicle.model.brand">
<field name="name">Fiat</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_fiat-image.png"/>
</record>
<record id="brand_ford" model="fleet.vehicle.model.brand">
<field name="name">Ford</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_ford-image.png"/>
</record>
<record id="brand_holden" model="fleet.vehicle.model.brand">
<field name="name">Holden</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_holden-image.png"/>
</record>
<record id="brand_honda" model="fleet.vehicle.model.brand">
<field name="name">Honda</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_honda-image.png"/>
</record>
<record id="brand_hyundai" model="fleet.vehicle.model.brand">
<field name="name">Hyundai</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_hyundai-image.png"/>
</record>
<record id="brand_infiniti" model="fleet.vehicle.model.brand">
<field name="name">Infiniti</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_infiniti-image.png"/>
</record>
<record id="brand_isuzu" model="fleet.vehicle.model.brand">
<field name="name">Isuzu</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_isuzu-image.png"/>
</record>
<record id="brand_jaguar" model="fleet.vehicle.model.brand">
<field name="name">Jaguar</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_jaguar-image.png"/>
</record>
<record id="brand_jeep" model="fleet.vehicle.model.brand">
<field name="name">Jeep</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_jeep-image.png"/>
</record>
<record id="brand_kia" model="fleet.vehicle.model.brand">
<field name="name">Kia</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_kia-image.png"/>
</record>
<record id="brand_koenigsegg" model="fleet.vehicle.model.brand">
<field name="name">Koenigsegg</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_koenigsegg-image.png"/>
</record>
<record id="brand_lagonda" model="fleet.vehicle.model.brand">
<field name="name">Lagonda</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_lagonda-image.png"/>
</record>
<record id="brand_lamborghini" model="fleet.vehicle.model.brand">
<field name="name">Lamborghini</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_lamborghini-image.png"/>
</record>
<record id="brand_lancia" model="fleet.vehicle.model.brand">
<field name="name">Lancia</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_lancia-image.png"/>
</record>
<record id="brand_land_rover" model="fleet.vehicle.model.brand">
<field name="name">Land Rover</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_land-rover-image.png"/>
</record>
<record id="brand_lexus" model="fleet.vehicle.model.brand">
<field name="name">Lexus</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_lexus-image.png"/>
</record>
<record id="brand_lincoln" model="fleet.vehicle.model.brand">
<field name="name">Lincoln</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_lincoln-image.png"/>
</record>
<record id="brand_lotus" model="fleet.vehicle.model.brand">
<field name="name">Lotus</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_lotus-image.png"/>
</record>
<record id="brand_maserati" model="fleet.vehicle.model.brand">
<field name="name">Maserati</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_maserati-image.png"/>
</record>
<record id="brand_maybach" model="fleet.vehicle.model.brand">
<field name="name">Maybach</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_maybach-image.png"/>
</record>
<record id="brand_mazda" model="fleet.vehicle.model.brand">
<field name="name">Mazda</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_mazda-image.png"/>
</record>
<record id="brand_mercedes" model="fleet.vehicle.model.brand">
<field name="name">Mercedes</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_mercedes-image.png"/>
</record>
<record id="brand_mg" model="fleet.vehicle.model.brand">
<field name="name">Mg</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_mg-image.png"/>
</record>
<record id="brand_mini" model="fleet.vehicle.model.brand">
<field name="name">Mini</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_mini-image.png"/>
</record>
<record id="brand_mitsubishi" model="fleet.vehicle.model.brand">
<field name="name">Mitsubishi</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_mitsubishi-image.png"/>
</record>
<record id="brand_morgan" model="fleet.vehicle.model.brand">
<field name="name">Morgan</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_morgan-image.png"/>
</record>
<record id="brand_nissan" model="fleet.vehicle.model.brand">
<field name="name">Nissan</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_nissan-image.png"/>
</record>
<record id="brand_oldsmobile" model="fleet.vehicle.model.brand">
<field name="name">Oldsmobile</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_oldsmobile-image.png"/>
</record>
<record id="brand_opel" model="fleet.vehicle.model.brand">
<field name="name">Opel</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_opel-image.png"/>
</record>
<record id="brand_peugeot" model="fleet.vehicle.model.brand">
<field name="name">Peugeot</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_peugeot-image.png"/>
</record>
<record id="brand_pontiac" model="fleet.vehicle.model.brand">
<field name="name">Pontiac</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_pontiac-image.png"/>
</record>
<record id="brand_porsche" model="fleet.vehicle.model.brand">
<field name="name">Porsche</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_porsche-image.png"/>
</record>
<record id="brand_rambler" model="fleet.vehicle.model.brand">
<field name="name">Rambler</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_rambler-image.png"/>
</record>
<record id="brand_renault" model="fleet.vehicle.model.brand">
<field name="name">Renault</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_renault-image.png"/>
</record>
<record id="brand_rolls-royce" model="fleet.vehicle.model.brand">
<field name="name">Rolls-Royce</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_rolls-royce-image.png"/>
</record>
<record id="brand_saab" model="fleet.vehicle.model.brand">
<field name="name">Saab</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_saab-image.png"/>
</record>
<record id="brand_scion" model="fleet.vehicle.model.brand">
<field name="name">Scion</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_scion-image.png"/>
</record>
<record id="brand_skoda" model="fleet.vehicle.model.brand">
<field name="name">Skoda</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_skoda-image.png"/>
</record>
<record id="brand_smart" model="fleet.vehicle.model.brand">
<field name="name">Smart</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_smart-image.png"/>
</record>
<record id="brand_steyr" model="fleet.vehicle.model.brand">
<field name="name">Steyr</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_steyr-image.png"/>
</record>
<record id="brand_subaru" model="fleet.vehicle.model.brand">
<field name="name">Subaru</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_subaru-image.png"/>
</record>
<record id="brand_tesla_motors" model="fleet.vehicle.model.brand">
<field name="name">Tesla Motors</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_tesla-motors-image.png"/>
</record>
<record id="brand_toyota" model="fleet.vehicle.model.brand">
<field name="name">Toyota</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_toyota-image.png"/>
</record>
<record id="brand_trabant" model="fleet.vehicle.model.brand">
<field name="name">Trabant</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_trabant-image.png"/>
</record>
<record id="brand_volkswagen" model="fleet.vehicle.model.brand">
<field name="name">Volkswagen</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_volkswagen-image.png"/>
</record>
<record id="brand_volvo" model="fleet.vehicle.model.brand">
<field name="name">Volvo</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_volvo-image.png"/>
</record>
<record id="brand_willys" model="fleet.vehicle.model.brand">
<field name="name">Willys</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_willys-image.png"/>
</record>
<record id="brand_suzuki" model="fleet.vehicle.model.brand">
<field name="name">Suzuki</field>
<field name="image_128" type="base64" file="fleet/static/img/brand_suzuki-image.png"/>
</record>
<record id="model_corsa" model="fleet.vehicle.model">
<field name="name">Corsa</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_astra" model="fleet.vehicle.model">
<field name="name">Astra</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_agila" model="fleet.vehicle.model">
<field name="name">Agila</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_combotour" model="fleet.vehicle.model">
<field name="name">Combo Tour</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_meriva" model="fleet.vehicle.model">
<field name="name">Meriva</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_astragtc" model="fleet.vehicle.model">
<field name="name">AstraGTC</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_zafira" model="fleet.vehicle.model">
<field name="name">Zafira</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_zafiratourer" model="fleet.vehicle.model">
<field name="name">Zafira Tourer</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_insignia" model="fleet.vehicle.model">
<field name="name">Insignia</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_mokka" model="fleet.vehicle.model">
<field name="name">Mokka</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_antara" model="fleet.vehicle.model">
<field name="name">Antara</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_ampera" model="fleet.vehicle.model">
<field name="name">Ampera</field>
<field name="brand_id" ref="brand_opel" />
<field name="vehicle_type">car</field>
</record>
<record id="model_a1" model="fleet.vehicle.model">
<field name="name">A1</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_a3" model="fleet.vehicle.model">
<field name="name">A3</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_a4" model="fleet.vehicle.model">
<field name="name">A4</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_a5" model="fleet.vehicle.model">
<field name="name">A5</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_a6" model="fleet.vehicle.model">
<field name="name">A6</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_a7" model="fleet.vehicle.model">
<field name="name">A7</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_a8" model="fleet.vehicle.model">
<field name="name">A8</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_q3" model="fleet.vehicle.model">
<field name="name">Q3</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_q5" model="fleet.vehicle.model">
<field name="name">Q5</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_q7" model="fleet.vehicle.model">
<field name="name">Q7</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_tt" model="fleet.vehicle.model">
<field name="name">TT</field>
<field name="brand_id" ref="brand_audi" />
<field name="vehicle_type">car</field>
</record>
<record id="model_serie1" model="fleet.vehicle.model">
<field name="name">Serie 1</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_serie3" model="fleet.vehicle.model">
<field name="name">Serie 3</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_serie5" model="fleet.vehicle.model">
<field name="name">Serie 5</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_serie6" model="fleet.vehicle.model">
<field name="name">Serie 6</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_serie7" model="fleet.vehicle.model">
<field name="name">Serie 7</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_seriex" model="fleet.vehicle.model">
<field name="name">Serie X</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_seriez4" model="fleet.vehicle.model">
<field name="name">Serie Z4</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_seriem" model="fleet.vehicle.model">
<field name="name">Serie M</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_seriehybrid" model="fleet.vehicle.model">
<field name="name">Serie Hybrid</field>
<field name="brand_id" ref="brand_bmw" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classa" model="fleet.vehicle.model">
<field name="name">Class A</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classb" model="fleet.vehicle.model">
<field name="name">Class B</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classc" model="fleet.vehicle.model">
<field name="name">Class C</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classcl" model="fleet.vehicle.model">
<field name="name">Class CL</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classcls" model="fleet.vehicle.model">
<field name="name">Class CLS</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classe" model="fleet.vehicle.model">
<field name="name">Class E</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classm" model="fleet.vehicle.model">
<field name="name">Class M</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classgl" model="fleet.vehicle.model">
<field name="name">Class GL</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classglk" model="fleet.vehicle.model">
<field name="name">Class GLK</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classr" model="fleet.vehicle.model">
<field name="name">Class R</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classs" model="fleet.vehicle.model">
<field name="name">Class S</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classslk" model="fleet.vehicle.model">
<field name="name">Class SLK</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
<record id="model_classsls" model="fleet.vehicle.model">
<field name="name">SLS</field>
<field name="brand_id" ref="brand_mercedes" />
<field name="vehicle_type">car</field>
</record>
</odoo>

46
data/fleet_data.xml Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record forcecreate="True" id="ir_cron_contract_costs_generator" model="ir.cron">
<field name="name">Fleet: Generate contracts costs based on costs frequency</field>
<field name="model_id" ref="model_fleet_vehicle_log_contract"/>
<field name="state">code</field>
<field name="code">model.run_scheduler()</field>
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
</record>
<record id="fleet_vehicle_state_new_request" model="fleet.vehicle.state">
<field name="name">New Request</field>
<field name="sequence">4</field>
</record>
<record id="fleet_vehicle_state_to_order" model="fleet.vehicle.state">
<field name="name">To Order</field>
<field name="sequence">5</field>
</record>
<record id="fleet_vehicle_state_registered" model="fleet.vehicle.state">
<field name="name">Registered</field>
<field name="sequence">7</field>
</record>
<record id="fleet_vehicle_state_downgraded" model="fleet.vehicle.state">
<field name="name">Downgraded</field>
<field name="sequence">8</field>
</record>
<record id="type_contract_omnium" model="fleet.service.type">
<field name="name">Omnium</field>
<field name="category">contract</field>
</record>
<record id="type_contract_leasing" model="fleet.service.type">
<field name="name">Leasing</field>
<field name="category">contract</field>
</record>
</data>
</odoo>

823
data/fleet_demo.xml Normal file
View File

@ -0,0 +1,823 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="base.user_demo" model="res.users">
<field name="groups_id" eval="[(3, ref('fleet.fleet_group_manager'))]"/>
</record>
<record id="fleet_vehicle_state_ordered" model="fleet.vehicle.state">
<field name="name">Ordered</field>
<field name="sequence">6</field>
</record>
<record id="fleet_vehicle_state_reserve" model="fleet.vehicle.state">
<field name="name">Reserve</field>
<field name="sequence">9</field>
</record>
<record id="fleet_vehicle_state_waiting_list" model="fleet.vehicle.state">
<field name="name">Waiting List</field>
<field name="sequence">10</field>
</record>
<record id="type_service_service_1" model="fleet.service.type">
<field name="name">Calculation Benefit In Kind</field>
<field name="category">service</field>
</record>
<record id="type_service_service_2" model="fleet.service.type">
<field name="name">Depreciation and Interests</field>
<field name="category">service</field>
</record>
<record id="type_service_service_3" model="fleet.service.type">
<field name="name">Tax roll</field>
<field name="category">service</field>
</record>
<record id="type_service_service_5" model="fleet.service.type">
<field name="name">Summer tires</field>
<field name="category">service</field>
</record>
<record id="type_service_service_6" model="fleet.service.type">
<field name="name">Snow tires</field>
<field name="category">service</field>
</record>
<record id="type_service_service_7" model="fleet.service.type">
<field name="name">Repair and maintenance</field>
<field name="category">service</field>
</record>
<record id="type_service_service_8" model="fleet.service.type">
<field name="name">Assistance</field>
<field name="category">service</field>
</record>
<record id="type_service_service_9" model="fleet.service.type">
<field name="name">Replacement Vehicle</field>
<field name="category">service</field>
</record>
<record id="type_service_service_10" model="fleet.service.type">
<field name="name">Management Fee</field>
<field name="category">service</field>
</record>
<record id="type_service_service_11" model="fleet.service.type">
<field name="name">Rent (Excluding VAT)</field>
<field name="category">service</field>
</record>
<record id="type_service_service_12" model="fleet.service.type">
<field name="name">Entry into service tax</field>
<field name="category">service</field>
</record>
<record id="type_service_service_13" model="fleet.service.type">
<field name="name">Total expenses (Excluding VAT)</field>
<field name="category">service</field>
</record>
<record id="type_service_service_14" model="fleet.service.type">
<field name="name">Residual value (Excluding VAT)</field>
<field name="category">service</field>
</record>
<record id="type_service_service_15" model="fleet.service.type">
<field name="name">Options</field>
<field name="category">service</field>
</record>
<record id="type_service_service_16" model="fleet.service.type">
<field name="name">Emissions</field>
<field name="category">service</field>
</record>
<record id="type_service_service_17" model="fleet.service.type">
<field name="name">Touring Assistance</field>
<field name="category">service</field>
</record>
<record id="type_service_service_18" model="fleet.service.type">
<field name="name">Residual value in %</field>
<field name="category">service</field>
</record>
<record id="type_service_1" model="fleet.service.type">
<field name="name">A/C Compressor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_2" model="fleet.service.type">
<field name="name">A/C Condenser Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_3" model="fleet.service.type">
<field name="name">A/C Diagnosis</field>
<field name="category">service</field>
</record>
<record id="type_service_4" model="fleet.service.type">
<field name="name">A/C Evaporator Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_5" model="fleet.service.type">
<field name="name">A/C Recharge</field>
<field name="category">service</field>
</record>
<record id="type_service_6" model="fleet.service.type">
<field name="name">Air Filter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_7" model="fleet.service.type">
<field name="name">Alternator Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_7" model="fleet.service.type">
<field name="name">Ball Joint Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_9" model="fleet.service.type">
<field name="name">Battery Inspection</field>
<field name="category">service</field>
</record>
<record id="type_service_10" model="fleet.service.type">
<field name="name">Battery Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_11" model="fleet.service.type">
<field name="name">Brake Caliper Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_12" model="fleet.service.type">
<field name="name">Brake Inspection</field>
<field name="category">service</field>
</record>
<record id="type_service_13" model="fleet.service.type">
<field name="name">Brake Pad(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_14" model="fleet.service.type">
<field name="name">Car Wash</field>
<field name="category">service</field>
</record>
<record id="type_service_15" model="fleet.service.type">
<field name="name">Catalytic Converter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_16" model="fleet.service.type">
<field name="name">Charging System Diagnosis</field>
<field name="category">service</field>
</record>
<record id="type_service_17" model="fleet.service.type">
<field name="name">Door Window Motor/Regulator Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_18" model="fleet.service.type">
<field name="name">Engine Belt Inspection</field>
<field name="category">service</field>
</record>
<record id="type_service_19" model="fleet.service.type">
<field name="name">Engine Coolant Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_20" model="fleet.service.type">
<field name="name">Engine/Drive Belt(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_21" model="fleet.service.type">
<field name="name">Exhaust Manifold Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_22" model="fleet.service.type">
<field name="name">Fuel Injector Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_23" model="fleet.service.type">
<field name="name">Fuel Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_24" model="fleet.service.type">
<field name="name">Head Gasket(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_25" model="fleet.service.type">
<field name="name">Heater Blower Motor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_26" model="fleet.service.type">
<field name="name">Heater Control Valve Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_27" model="fleet.service.type">
<field name="name">Heater Core Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_28" model="fleet.service.type">
<field name="name">Heater Hose Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_29" model="fleet.service.type">
<field name="name">Ignition Coil Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_30" model="fleet.service.type">
<field name="name">Intake Manifold Gasket Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_31" model="fleet.service.type">
<field name="name">Oil Change</field>
<field name="category">service</field>
</record>
<record id="type_service_32" model="fleet.service.type">
<field name="name">Oil Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_33" model="fleet.service.type">
<field name="name">Other Maintenance</field>
<field name="category">service</field>
</record>
<record id="type_service_34" model="fleet.service.type">
<field name="name">Oxygen Sensor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_35" model="fleet.service.type">
<field name="name">Power Steering Hose Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_36" model="fleet.service.type">
<field name="name">Power Steering Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_37" model="fleet.service.type">
<field name="name">Radiator Repair</field>
<field name="category">service</field>
</record>
<record id="type_service_38" model="fleet.service.type">
<field name="name">Resurface Rotors</field>
<field name="category">service</field>
</record>
<record id="type_service_39" model="fleet.service.type">
<field name="name">Rotate Tires</field>
<field name="category">service</field>
</record>
<record id="type_service_40" model="fleet.service.type">
<field name="name">Rotor Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_41" model="fleet.service.type">
<field name="name">Spark Plug Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_42" model="fleet.service.type">
<field name="name">Starter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_43" model="fleet.service.type">
<field name="name">Thermostat Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_44" model="fleet.service.type">
<field name="name">Tie Rod End Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_45" model="fleet.service.type">
<field name="name">Tire Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_46" model="fleet.service.type">
<field name="name">Tire Service</field>
<field name="category">service</field>
</record>
<record id="type_service_47" model="fleet.service.type">
<field name="name">Transmission Filter Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_48" model="fleet.service.type">
<field name="name">Transmission Fluid Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_49" model="fleet.service.type">
<field name="name">Transmission Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_50" model="fleet.service.type">
<field name="name">Water Pump Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_51" model="fleet.service.type">
<field name="name">Wheel Alignment</field>
<field name="category">service</field>
</record>
<record id="type_service_52" model="fleet.service.type">
<field name="name">Wheel Bearing Replacement</field>
<field name="category">service</field>
</record>
<record id="type_service_53" model="fleet.service.type">
<field name="name">Windshield Wiper(s) Replacement</field>
<field name="category">service</field>
</record>
<record id="type_contract_repairing" model="fleet.service.type">
<field name="name">Repairing</field>
<field name="category">contract</field>
</record>
<record id="type_service_refueling" model="fleet.service.type">
<field name="name">Refueling</field>
<field name="category">service</field>
</record>
<record id="vehicle_tag_junior" model="fleet.vehicle.tag" >
<field name="name">Junior</field>
<field name="color" eval="1"/>
</record>
<record id="vehicle_tag_senior" model="fleet.vehicle.tag" >
<field name="name">Senior</field>
<field name="color" eval="2"/>
</record>
<record id="vehicle_tag_leasing" model="fleet.vehicle.tag" >
<field name="name">Employee Car</field>
<field name="color" eval="3"/>
</record>
<record id="vehicle_tag_purchased" model="fleet.vehicle.tag" >
<field name="name">Purchased</field>
<field name="color" eval="4"/>
</record>
<record id="model_category_1" model="fleet.vehicle.model.category">
<field name="name">Break</field>
</record>
<record id="model_category_2" model="fleet.vehicle.model.category">
<field name="name">SUV</field>
</record>
<record id="model_category_3" model="fleet.vehicle.model.category">
<field name="name">Sport Car</field>
</record>
<record id="model_category_4" model="fleet.vehicle.model.category">
<field name="name">Compact</field>
</record>
<record id="vehicle_1" model="fleet.vehicle">
<field name="license_plate">1-ACK-205</field>
<field name="vin_sn">5454541</field>
<field name="model_id" ref="model_astra"/>
<field name="color">Black</field>
<field name="location">Grand-Rosiere</field>
<field name="doors">5</field>
<field name="driver_id" ref="base.partner_demo" />
<field name="acquisition_date" eval="(DateTime.now() - timedelta(days=336)).strftime('%Y-%m-%d')" />
<field name="state_id" ref="fleet_vehicle_state_registered"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">20000</field>
<field name="manager_id" ref="base.user_admin"/>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_purchased'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>
</record>
<record id="vehicle_2" model="fleet.vehicle">
<field name="license_plate">1-SYN-404</field>
<field name="vin_sn">1337</field>
<field name="model_id" ref="model_corsa"/>
<field name="color">Red</field>
<field name="location">Grand-Rosiere</field>
<field name="doors">5</field>
<field name="driver_id" ref="base.res_partner_address_25" />
<field name="acquisition_date" eval="(DateTime.now() - timedelta(days=233)).strftime('%Y-%m-%d')" />
<field name="state_id" ref="fleet_vehicle_state_downgraded"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">16000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_purchased'),ref('fleet.vehicle_tag_junior')])]" name="tag_ids"/>
</record>
<record id="vehicle_3" model="fleet.vehicle">
<field name="license_plate">1-BMW-001</field>
<field name="vin_sn">54818</field>
<field name="model_id" ref="model_serie1"/>
<field name="color">Titanium Grey</field>
<field name="location">Grand-Rosiere</field>
<field name="doors">3</field>
<field name="driver_id" ref="base.res_partner_address_17" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state_id" ref="fleet_vehicle_state_registered"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">20000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_purchased'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>
</record>
<record id="vehicle_4" model="fleet.vehicle">
<field name="license_plate">1-AUD-001</field>
<field name="vin_sn">455257985</field>
<field name="model_id" ref="model_a1"/>
<field name="color">White</field>
<field name="location">Grand-Rosiere</field>
<field name="doors">3</field>
<field name="driver_id" ref="base.res_partner_address_16" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state_id" ref="fleet_vehicle_state_registered"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">20000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_purchased'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>
</record>
<record id="vehicle_5" model="fleet.vehicle">
<field name="license_plate">1-MER-001</field>
<field name="vin_sn">789546128</field>
<field name="model_id" ref="model_classa"/>
<field name="color">Brown</field>
<field name="location">Grand-Rosiere</field>
<field name="doors">5</field>
<field name="driver_id" ref="base.res_partner_address_15" />
<field name="acquisition_date" eval="time.strftime('%Y-%m-%d 2:00:00')" />
<field name="state_id" ref="fleet_vehicle_state_registered"/>
<field name="odometer_unit">kilometers</field>
<field name="car_value">18000</field>
<field eval="[(6,0,[ref('vehicle_tag_leasing'),ref('fleet.vehicle_tag_purchased'),ref('fleet.vehicle_tag_senior')])]" name="tag_ids"/>
</record>
<record id="log_odometer_1" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=336)).strftime('%Y-%m-%d')" />
<field name="value">0</field>
</record>
<record id="log_odometer_2" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=304)).strftime('%Y-%m-%d')" />
<field name="value">658</field>
</record>
<record id="log_odometer_3" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=289)).strftime('%Y-%m-%d')" />
<field name="value">1360</field>
</record>
<record id="log_odometer_4" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=260)).strftime('%Y-%m-%d')" />
<field name="value">2044</field>
</record>
<record id="log_odometer_5" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=230)).strftime('%Y-%m-%d')" />
<field name="value">2756</field>
</record>
<record id="log_odometer_6" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=185)).strftime('%Y-%m-%d')" />
<field name="value">3410</field>
</record>
<record id="log_odometer_7" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=165)).strftime('%Y-%m-%d')" />
<field name="value">3750</field>
</record>
<record id="log_odometer_8" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=140)).strftime('%Y-%m-%d')" />
<field name="value">4115</field>
</record>
<record id="log_odometer_9" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=120)).strftime('%Y-%m-%d')" />
<field name="value">4750</field>
</record>
<record id="log_odometer_10" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=105)).strftime('%Y-%m-%d')" />
<field name="value">5171</field>
</record>
<record id="log_odometer_11" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=85)).strftime('%Y-%m-%d')" />
<field name="value">5873</field>
</record>
<record id="log_odometer_12" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=55)).strftime('%Y-%m-%d')" />
<field name="value">6571</field>
</record>
<record id="log_odometer_13" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=32)).strftime('%Y-%m-%d')" />
<field name="value">7954</field>
</record>
<record id="log_odometer_14" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_1" />
<field name="date" eval="(DateTime.now() - timedelta(days=2)).strftime('%Y-%m-%d')" />
<field name="value">7981</field>
</record>
<record id="log_odometer_15" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=233)).strftime('%Y-%m-%d')" />
<field name="value">0</field>
</record>
<record id="log_odometer_16" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=233)).strftime('%Y-%m-%d')" />
<field name="value">702</field>
</record>
<record id="log_odometer_17" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=215)).strftime('%Y-%m-%d')" />
<field name="value">1205.4</field>
</record>
<record id="log_odometer_18" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=200)).strftime('%Y-%m-%d')" />
<field name="value">2122</field>
</record>
<record id="log_odometer_19" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=180)).strftime('%Y-%m-%d')" />
<field name="value">2430</field>
</record>
<record id="log_odometer_20" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=165)).strftime('%Y-%m-%d')" />
<field name="value">3015</field>
</record>
<record id="log_odometer_21" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=150)).strftime('%Y-%m-%d')" />
<field name="value">3602.1</field>
</record>
<record id="log_odometer_22" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=124)).strftime('%Y-%m-%d')" />
<field name="value">4205.5</field>
</record>
<record id="log_odometer_23" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=96)).strftime('%Y-%m-%d')" />
<field name="value">4935</field>
</record>
<record id="log_odometer_24" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=80)).strftime('%Y-%m-%d')" />
<field name="value">5555</field>
</record>
<record id="log_odometer_25" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=55)).strftime('%Y-%m-%d')" />
<field name="value">5987</field>
</record>
<record id="log_odometer_26" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=45)).strftime('%Y-%m-%d')" />
<field name="value">6571</field>
</record>
<record id="log_odometer_27" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=30)).strftime('%Y-%m-%d')" />
<field name="value">7201.5</field>
</record>
<record id="log_odometer_28" model="fleet.vehicle.odometer">
<field name="vehicle_id" ref="vehicle_2" />
<field name="date" eval="(DateTime.now() - timedelta(days=10)).strftime('%Y-%m-%d')" />
<field name="value">8001.2</field>
</record>
<record id="log_service_1" model="fleet.vehicle.log.services" >
<field name="vehicle_id" ref="vehicle_2" />
<field name="amount">650</field>
<field name="service_type_id" ref="type_service_service_7"/>
<field name="date" eval="(DateTime.now() - timedelta(days=60)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="inv_ref">4586</field>
<field name="vendor_id" ref="base.res_partner_2" />
<field name="notes">Usual vehicle repairing</field>
<field name="state">done</field>
</record>
<record id="log_service_2" model="fleet.vehicle.log.services" >
<field name="vehicle_id" ref="vehicle_2" />
<field name="amount">350</field>
<field name="service_type_id" ref="type_service_service_7"/>
<field name="date" eval="(DateTime.now() - timedelta(days=30)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="inv_ref">4814</field>
<field name="vendor_id" ref="base.res_partner_2" />
<field name="notes">After crash repairing</field>
<field name="state">done</field>
</record>
<record id="log_service_3" model="fleet.vehicle.log.services" >
<field name="vehicle_id" ref="vehicle_1" />
<field name="amount">513</field>
<field name="service_type_id" ref="type_service_service_7"/>
<field name="date" eval="(DateTime.now() - timedelta(days=15)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="inv_ref">124</field>
<field name="vendor_id" ref="base.res_partner_2" />
<field name="notes">Maintenance</field>
<field name="state">done</field>
</record>
<record id="log_service_4" model="fleet.vehicle.log.services" >
<field name="vehicle_id" ref="vehicle_3" />
<field name="amount">412</field>
<field name="service_type_id" ref="type_service_service_7"/>
<field name="date" eval="(DateTime.now() - timedelta(days=120)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="inv_ref">20984</field>
<field name="vendor_id" ref="base.res_partner_2" />
<field name="notes">Maintenance</field>
<field name="state">done</field>
</record>
<record id="log_service_5" model="fleet.vehicle.log.services" >
<field name="vehicle_id" ref="vehicle_4" />
<field name="amount">275</field>
<field name="service_type_id" ref="type_service_service_7"/>
<field name="date" eval="(DateTime.now() - timedelta(days=100)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="inv_ref">241</field>
<field name="vendor_id" ref="base.res_partner_2" />
<field name="notes">Maintenance</field>
<field name="state">done</field>
</record>
<record id="log_service_6" model="fleet.vehicle.log.services" >
<field name="vehicle_id" ref="vehicle_5" />
<field name="amount">302</field>
<field name="service_type_id" ref="type_service_service_7"/>
<field name="date" eval="(DateTime.now() - timedelta(days=65)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="inv_ref">22513</field>
<field name="vendor_id" ref="base.res_partner_2" />
<field name="notes">Maintenance</field>
<field name="state">done</field>
</record>
<record id="log_contract_1" model="fleet.vehicle.log.contract" >
<field name="vehicle_id" ref="vehicle_2" />
<field name="cost_subtype_id" ref="type_contract_leasing" />
<field name="amount">0</field>
<field name="name">Daily leasing contract</field>
<field name="cost_generated">20</field>
<field name="cost_frequency">daily</field>
<field name="expiration_date" eval="(DateTime.now() - timedelta(days=233)).strftime('%Y-%m-%d')" />
<field name="expiration_date" eval="(DateTime.now() + timedelta(5)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="insurer_id" ref="base.res_partner_2" />
<field name="notes">Daily leasing contract</field>
<field name="state">open</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="[(6,0,[ref('fleet.type_contract_omnium'),ref('fleet.type_service_service_3'),ref('fleet.type_service_service_2')])]" name="service_ids"/>
</record>
<record id="log_contract_2" model="fleet.vehicle.log.contract" >
<field name="vehicle_id" ref="vehicle_1" />
<field name="cost_subtype_id" ref="type_contract_leasing" />
<field name="amount">0</field>
<field name="name">Weekly leasing contract</field>
<field name="cost_generated">150</field>
<field name="cost_frequency">weekly</field>
<field name="date" eval="time.strftime('%Y-01-01')" />
<field name="start_date" eval="(DateTime.now() - timedelta(days=289)).strftime('%Y-%m-%d')" />
<field name="expiration_date" eval="(DateTime.now() + timedelta(-1)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="insurer_id" ref="base.res_partner_2" />
<field name="notes">Weekly leasing contract</field>
<field name="state">open</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="[(6,0,[ref('fleet.type_contract_omnium'),ref('fleet.type_service_service_3'),ref('fleet.type_service_service_2')])]" name="service_ids"/>
</record>
<record id="log_contract_3" model="fleet.vehicle.log.contract" >
<field name="vehicle_id" ref="vehicle_3" />
<field name="cost_subtype_id" ref="type_contract_leasing" />
<field name="amount">0</field>
<field name="name">Monthly leasing</field>
<field name="cost_generated">400</field>
<field name="cost_frequency">monthly</field>
<field name="date" eval="time.strftime('%Y-01-01')"/>
<field name="start_date" eval="time.strftime('%Y-01-01')" />
<field name="expiration_date" eval="time.strftime('%Y-12-31')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="insurer_id" ref="base.res_partner_2" />
<field name="notes">Monthly leasing contract</field>
<field name="state">open</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="[(6,0,[ref('fleet.type_contract_omnium'),ref('fleet.type_service_service_3'),ref('fleet.type_service_service_2')])]" name="service_ids"/>
</record>
<record id="log_contract_4" model="fleet.vehicle.log.contract" >
<field name="vehicle_id" ref="vehicle_4" />
<field name="cost_subtype_id" ref="type_contract_leasing" />
<field name="amount">0</field>
<field name="name">Yearly leasing</field>
<field name="cost_generated">4000</field>
<field name="cost_frequency">yearly</field>
<field name="date" eval="time.strftime('%Y-01-01')" />
<field name="start_date" eval="time.strftime('%Y-01-01')" />
<field name="expiration_date" eval="time.strftime('%Y-12-31')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="insurer_id" ref="base.res_partner_2" />
<field name="notes">Yearly leasing contract</field>
<field name="state">open</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="[(6,0,[ref('fleet.type_contract_omnium'),ref('fleet.type_service_service_3'),ref('fleet.type_service_service_2')])]" name="service_ids"/>
</record>
<record id="log_contract_5" model="fleet.vehicle.log.contract" >
<field name="vehicle_id" ref="vehicle_5" />
<field name="cost_subtype_id" ref="type_contract_leasing" />
<field name="amount">17000</field>
<field name="name">Unique leasing</field>
<field name="cost_generated">0</field>
<field name="cost_frequency">no</field>
<field name="date" eval="(DateTime.now() - timedelta(days=300)).strftime('%Y-%m-%d')" />
<field name="start_date" eval="(DateTime.now() - timedelta(days=300)).strftime('%Y-%m-%d')" />
<field name="expiration_date" eval="(DateTime.now() + timedelta(-60)).strftime('%Y-%m-%d')" />
<field name="purchaser_id" ref="base.res_partner_address_18" />
<field name="insurer_id" ref="base.res_partner_2" />
<field name="notes">Unique leasing contract</field>
<field name="state">open</field>
<field name="user_id" ref="base.user_admin"/>
<field eval="[(6,0,[ref('fleet.type_contract_omnium'),ref('fleet.type_service_service_3'),ref('fleet.type_service_service_2')])]" name="service_ids"/>
</record>
</odoo>

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="mail_act_fleet_contract_to_renew" model="mail.activity.type">
<field name="name">Contract to Renew</field>
<field name="icon">fa-car</field>
<field name="res_model">fleet.vehicle.log.contract</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="mt_fleet_driver_updated" model="mail.message.subtype">
<field name="name">Changed Driver</field>
<field name="sequence">0</field>
<field name="res_model">fleet.vehicle</field>
<field name="default" eval="True"/>
<field name="description">Changed Driver</field>
</record>
</data>
</odoo>

2430
i18n/af.po Normal file

File diff suppressed because it is too large Load Diff

2426
i18n/am.po Normal file

File diff suppressed because it is too large Load Diff

2507
i18n/ar.po Normal file

File diff suppressed because it is too large Load Diff

2446
i18n/az.po Normal file

File diff suppressed because it is too large Load Diff

2516
i18n/bg.po Normal file

File diff suppressed because it is too large Load Diff

2432
i18n/bs.po Normal file

File diff suppressed because it is too large Load Diff

2538
i18n/ca.po Normal file

File diff suppressed because it is too large Load Diff

2513
i18n/cs.po Normal file

File diff suppressed because it is too large Load Diff

2513
i18n/da.po Normal file

File diff suppressed because it is too large Load Diff

2523
i18n/de.po Normal file

File diff suppressed because it is too large Load Diff

2437
i18n/el.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/en_GB.po Normal file

File diff suppressed because it is too large Load Diff

2525
i18n/es.po Normal file

File diff suppressed because it is too large Load Diff

2527
i18n/es_419.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_BO.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_CL.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_CO.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_CR.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_DO.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_EC.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_PE.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_PY.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/es_VE.po Normal file

File diff suppressed because it is too large Load Diff

2513
i18n/et.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/eu.po Normal file

File diff suppressed because it is too large Load Diff

2503
i18n/fa.po Normal file

File diff suppressed because it is too large Load Diff

2534
i18n/fi.po Normal file

File diff suppressed because it is too large Load Diff

2481
i18n/fleet.pot Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/fo.po Normal file

File diff suppressed because it is too large Load Diff

2522
i18n/fr.po Normal file

File diff suppressed because it is too large Load Diff

2427
i18n/fr_BE.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/fr_CA.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/gl.po Normal file

File diff suppressed because it is too large Load Diff

2436
i18n/gu.po Normal file

File diff suppressed because it is too large Load Diff

2514
i18n/he.po Normal file

File diff suppressed because it is too large Load Diff

2454
i18n/hr.po Normal file

File diff suppressed because it is too large Load Diff

2511
i18n/hu.po Normal file

File diff suppressed because it is too large Load Diff

2515
i18n/id.po Normal file

File diff suppressed because it is too large Load Diff

2431
i18n/is.po Normal file

File diff suppressed because it is too large Load Diff

2514
i18n/it.po Normal file

File diff suppressed because it is too large Load Diff

2499
i18n/ja.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/ka.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/kab.po Normal file

File diff suppressed because it is too large Load Diff

2432
i18n/km.po Normal file

File diff suppressed because it is too large Load Diff

2501
i18n/ko.po Normal file

File diff suppressed because it is too large Load Diff

2430
i18n/lb.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/lo.po Normal file

File diff suppressed because it is too large Load Diff

2529
i18n/lt.po Normal file

File diff suppressed because it is too large Load Diff

2498
i18n/lv.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/mk.po Normal file

File diff suppressed because it is too large Load Diff

2451
i18n/mn.po Normal file

File diff suppressed because it is too large Load Diff

2441
i18n/nb.po Normal file

File diff suppressed because it is too large Load Diff

2426
i18n/ne.po Normal file

File diff suppressed because it is too large Load Diff

2516
i18n/nl.po Normal file

File diff suppressed because it is too large Load Diff

2515
i18n/pl.po Normal file

File diff suppressed because it is too large Load Diff

2499
i18n/pt.po Normal file

File diff suppressed because it is too large Load Diff

2520
i18n/pt_BR.po Normal file

File diff suppressed because it is too large Load Diff

2445
i18n/ro.po Normal file

File diff suppressed because it is too large Load Diff

2535
i18n/ru.po Normal file

File diff suppressed because it is too large Load Diff

2508
i18n/sk.po Normal file

File diff suppressed because it is too large Load Diff

2512
i18n/sl.po Normal file

File diff suppressed because it is too large Load Diff

2429
i18n/sq.po Normal file

File diff suppressed because it is too large Load Diff

2516
i18n/sr.po Normal file

File diff suppressed because it is too large Load Diff

2433
i18n/sr@latin.po Normal file

File diff suppressed because it is too large Load Diff

2521
i18n/sv.po Normal file

File diff suppressed because it is too large Load Diff

2508
i18n/th.po Normal file

File diff suppressed because it is too large Load Diff

2530
i18n/tr.po Normal file

File diff suppressed because it is too large Load Diff

2519
i18n/uk.po Normal file

File diff suppressed because it is too large Load Diff

2511
i18n/vi.po Normal file

File diff suppressed because it is too large Load Diff

2503
i18n/zh_CN.po Normal file

File diff suppressed because it is too large Load Diff

2501
i18n/zh_TW.po Normal file

File diff suppressed because it is too large Load Diff

16
models/__init__.py Normal file
View File

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import fleet_service_type
from . import fleet_vehicle
from . import fleet_vehicle_assignation_log
from . import fleet_vehicle_log_contract
from . import fleet_vehicle_log_services
from . import fleet_vehicle_model
from . import fleet_vehicle_model_brand
from . import fleet_vehicle_model_category
from . import fleet_vehicle_odometer
from . import fleet_vehicle_state
from . import fleet_vehicle_tag
from . import res_config_settings
from . import res_partner

View File

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class FleetServiceType(models.Model):
_name = 'fleet.service.type'
_description = 'Fleet Service Type'
_order = 'name'
name = fields.Char(required=True, translate=True)
category = fields.Selection([
('contract', 'Contract'),
('service', 'Service')
], 'Category', required=True, help='Choose whether the service refer to contracts, vehicle services or both')

414
models/fleet_vehicle.py Normal file
View File

@ -0,0 +1,414 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from collections import defaultdict
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', 'category_id': 'category_id',
}
class FleetVehicle(models.Model):
_inherit = ['mail.thread', 'mail.activity.mixin', 'avatar.mixin']
_name = 'fleet.vehicle'
_description = 'Vehicle'
_order = 'license_plate asc, acquisition_date asc'
_rec_names_search = ['name', 'driver_id.name']
def _get_default_state(self):
state = self.env.ref('fleet.fleet_vehicle_state_new_request', raise_if_not_found=False)
return state if state and state.id else False
name = fields.Char(compute="_compute_vehicle_name", store=True)
description = fields.Html("Vehicle Description")
active = fields.Boolean('Active', default=True, tracking=True)
manager_id = fields.Many2one(
'res.users', 'Fleet Manager',
domain=lambda self: [('groups_id', 'in', self.env.ref('fleet.fleet_group_manager').id), ('company_id', 'in', self.env.companies.ids)],
)
company_id = fields.Many2one(
'res.company', 'Company',
default=lambda self: self.env.company,
)
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', depends=['country_id'])
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, string='Trailer Hitch', compute='_compute_model_fields', store=True, readonly=False)
driver_id = fields.Many2one('res.partner', 'Driver', tracking=True, help='Driver address of the vehicle', copy=False)
future_driver_id = fields.Many2one('res.partner', 'Future Driver', tracking=True, help='Next Driver Address of the vehicle', copy=False, check_company=True)
model_id = fields.Many2one('fleet.vehicle.model', 'Model',
tracking=True, required=True)
brand_id = fields.Many2one('fleet.vehicle.model.brand', 'Brand', related="model_id.brand_id", store=True, readonly=False)
log_drivers = fields.One2many('fleet.vehicle.assignation.log', 'vehicle_id', string='Assignment Logs')
log_services = fields.One2many('fleet.vehicle.log.services', 'vehicle_id', 'Services Logs')
log_contracts = fields.One2many('fleet.vehicle.log.contract', 'vehicle_id', 'Contracts')
contract_count = fields.Integer(compute="_compute_count_all", string='Contract Count')
service_count = fields.Integer(compute="_compute_count_all", string='Services')
odometer_count = fields.Integer(compute="_compute_count_all", string='Odometer')
history_count = fields.Integer(compute="_compute_count_all", string="Drivers History Count")
next_assignation_date = fields.Date('Assignment Date', help='This is the date at which the car will be available, if not set it means available instantly')
order_date = fields.Date('Order Date')
acquisition_date = fields.Date('Registration Date', required=False,
default=fields.Date.today, help='Date of vehicle registration')
write_off_date = fields.Date('Cancellation Date', tracking=True, help="Date when the vehicle's license plate has been cancelled/removed.")
first_contract_date = fields.Date(string="First Contract Date", default=fields.Date.today)
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', 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')
odometer_unit = fields.Selection([
('kilometers', 'km'),
('miles', 'mi')
], 'Odometer Unit', default='kilometers', required=True)
transmission = fields.Selection(
[('manual', 'Manual'), ('automatic', 'Automatic')], 'Transmission',
compute='_compute_model_fields', store=True, readonly=False)
fuel_type = fields.Selection(FUEL_TYPES, 'Fuel Type', 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, tracking=True, group_operator=None)
co2_standard = fields.Char('CO2 Standard', compute='_compute_model_fields', store=True, readonly=False)
category_id = fields.Many2one('fleet.vehicle.model.category', 'Category', 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')
contract_renewal_overdue = fields.Boolean(compute='_compute_contract_reminder', search='_search_get_overdue_contract_reminder',
string='Has Contracts Overdue')
contract_renewal_name = fields.Text(compute='_compute_contract_reminder', string='Name of contract to renew soon')
contract_renewal_total = fields.Text(compute='_compute_contract_reminder', string='Total of contracts due or overdue minus one')
contract_state = fields.Selection(
[('futur', 'Incoming'),
('open', 'In Progress'),
('expired', 'Expired'),
('closed', 'Closed')
], string='Last Contract State', compute='_compute_contract_reminder', required=False)
car_value = fields.Float(string="Catalog Value (VAT Incl.)")
net_car_value = fields.Float(string="Purchase Value")
residual_value = fields.Float()
plan_to_change_car = fields.Boolean(related='driver_id.plan_to_change_car', store=True, readonly=False)
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')], string="Bike Frame Type")
electric_assistance = fields.Boolean(compute='_compute_model_fields', store=True, readonly=False)
frame_size = fields.Float()
service_activity = fields.Selection([
('none', 'None'),
('overdue', 'Overdue'),
('today', 'Today'),
], compute='_compute_service_activity')
vehicle_properties = fields.Properties('Properties', definition='model_id.vehicle_properties_definition', copy=True)
@api.depends('log_services')
def _compute_service_activity(self):
for vehicle in self:
activities_state = set(state for state in vehicle.log_services.mapped('activity_state') if state and state != 'planned')
vehicle.service_activity = sorted(activities_state)[0] if activities_state else 'none'
@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.update(write_vals)
@api.depends('model_id.brand_id.name', 'model_id.name', 'license_plate')
def _compute_vehicle_name(self):
for record in self:
record.name = (record.model_id.brand_id.name or '') + '/' + (record.model_id.name or '') + '/' + (record.license_plate or _('No Plate'))
def _get_odometer(self):
FleetVehicalOdometer = self.env['fleet.vehicle.odometer']
for record in self:
vehicle_odometer = FleetVehicalOdometer.search([('vehicle_id', '=', record.id)], limit=1, order='value desc')
if vehicle_odometer:
record.odometer = vehicle_odometer.value
else:
record.odometer = 0
def _set_odometer(self):
for record in self:
if record.odometer:
date = fields.Date.context_today(record)
data = {'value': record.odometer, 'date': date, 'vehicle_id': record.id}
self.env['fleet.vehicle.odometer'].create(data)
def _compute_count_all(self):
Odometer = self.env['fleet.vehicle.odometer']
LogService = self.env['fleet.vehicle.log.services'].with_context(active_test=False)
LogContract = self.env['fleet.vehicle.log.contract'].with_context(active_test=False)
History = self.env['fleet.vehicle.assignation.log']
odometers_data = Odometer._read_group([('vehicle_id', 'in', self.ids)], ['vehicle_id'], ['__count'])
services_data = LogService._read_group([('vehicle_id', 'in', self.ids)], ['vehicle_id', 'active'], ['__count'])
logs_data = LogContract._read_group([('vehicle_id', 'in', self.ids), ('state', '!=', 'closed')], ['vehicle_id', 'active'], ['__count'])
histories_data = History._read_group([('vehicle_id', 'in', self.ids)], ['vehicle_id'], ['__count'])
mapped_odometer_data = defaultdict(lambda: 0)
mapped_service_data = defaultdict(lambda: defaultdict(lambda: 0))
mapped_log_data = defaultdict(lambda: defaultdict(lambda: 0))
mapped_history_data = defaultdict(lambda: 0)
for vehicle, count in odometers_data:
mapped_odometer_data[vehicle.id] = count
for vehicle, active, count in services_data:
mapped_service_data[vehicle.id][active] = count
for vehicle, active, count in logs_data:
mapped_log_data[vehicle.id][active] = count
for vehicle, count in histories_data:
mapped_history_data[vehicle.id] = count
for vehicle in self:
vehicle.odometer_count = mapped_odometer_data[vehicle.id]
vehicle.service_count = mapped_service_data[vehicle.id][vehicle.active]
vehicle.contract_count = mapped_log_data[vehicle.id][vehicle.active]
vehicle.history_count = mapped_history_data[vehicle.id]
@api.depends('log_contracts')
def _compute_contract_reminder(self):
params = self.env['ir.config_parameter'].sudo()
delay_alert_contract = int(params.get_param('hr_fleet.delay_alert_contract', default=30))
for record in self:
overdue = False
due_soon = False
total = 0
name = ''
state = ''
for element in record.log_contracts:
if element.state in ('open', 'expired') and element.expiration_date:
current_date_str = fields.Date.context_today(record)
due_time_str = element.expiration_date
current_date = fields.Date.from_string(current_date_str)
due_time = fields.Date.from_string(due_time_str)
diff_time = (due_time - current_date).days
if diff_time < 0:
overdue = True
total += 1
if diff_time < delay_alert_contract:
due_soon = True
total += 1
if overdue or due_soon:
log_contract = self.env['fleet.vehicle.log.contract'].search([
('vehicle_id', '=', record.id),
('state', 'in', ('open', 'expired'))
], limit=1, order='expiration_date asc')
if log_contract:
# we display only the name of the oldest overdue/due soon contract
name = log_contract.name
state = log_contract.state
record.contract_renewal_overdue = overdue
record.contract_renewal_due_soon = due_soon
record.contract_renewal_total = total - 1 # we remove 1 from the real total for display purposes
record.contract_renewal_name = name
record.contract_state = state
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')
def _search_contract_renewal_due_soon(self, operator, value):
params = self.env['ir.config_parameter'].sudo()
delay_alert_contract = int(params.get_param('hr_fleet.delay_alert_contract', default=30))
res = []
assert operator in ('=', '!=', '<>') and value in (True, False), 'Operation not supported'
if (operator == '=' and value is True) or (operator in ('<>', '!=') and value is False):
search_operator = 'in'
else:
search_operator = 'not in'
today = fields.Date.context_today(self)
datetime_today = fields.Datetime.from_string(today)
limit_date = fields.Datetime.to_string(datetime_today + relativedelta(days=+delay_alert_contract))
res_ids = self.env['fleet.vehicle.log.contract'].search([
('expiration_date', '>', today),
('expiration_date', '<', limit_date),
('state', 'in', ['open', 'expired'])
]).mapped('vehicle_id').ids
res.append(('id', search_operator, res_ids))
return res
def _search_get_overdue_contract_reminder(self, operator, value):
res = []
assert operator in ('=', '!=', '<>') and value in (True, False), 'Operation not supported'
if (operator == '=' and value is True) or (operator in ('<>', '!=') and value is False):
search_operator = 'in'
else:
search_operator = 'not in'
today = fields.Date.context_today(self)
res_ids = self.env['fleet.vehicle.log.contract'].search([
('expiration_date', '!=', False),
('expiration_date', '<', today),
('state', 'in', ['open', 'expired'])
]).mapped('vehicle_id').ids
res.append(('id', search_operator, res_ids))
return res
def _clean_vals_internal_user(self, vals):
# Fleet administrator may not have rights to write on partner
# related fields when the driver_id is a res.user.
# This trick is used to prevent access right error.
su_vals = {}
if self.env.su:
return su_vals
if 'plan_to_change_car' in vals:
su_vals['plan_to_change_car'] = vals.pop('plan_to_change_car')
if 'plan_to_change_bike' in vals:
su_vals['plan_to_change_bike'] = vals.pop('plan_to_change_bike')
return su_vals
@api.model_create_multi
def create(self, vals_list):
ptc_values = [self._clean_vals_internal_user(vals) for vals in vals_list]
vehicles = super().create(vals_list)
for vehicle, vals, ptc_value in zip(vehicles, vals_list, ptc_values):
if ptc_value:
vehicle.sudo().write(ptc_value)
if 'driver_id' in vals and vals['driver_id']:
vehicle.create_driver_history(vals)
if 'future_driver_id' in vals and vals['future_driver_id']:
state_waiting_list = self.env.ref('fleet.fleet_vehicle_state_waiting_list', raise_if_not_found=False)
states = vehicle.mapped('state_id').ids
if not state_waiting_list or state_waiting_list.id not in states:
future_driver = self.env['res.partner'].browse(vals['future_driver_id'])
if self.vehicle_type == 'bike':
future_driver.sudo().write({'plan_to_change_bike': True})
if self.vehicle_type == 'car':
future_driver.sudo().write({'plan_to_change_car': True})
return vehicles
def write(self, vals):
if 'driver_id' in vals and vals['driver_id']:
driver_id = vals['driver_id']
for vehicle in self.filtered(lambda v: v.driver_id.id != driver_id):
vehicle.create_driver_history(vals)
if vehicle.driver_id:
vehicle.activity_schedule(
'mail.mail_activity_data_todo',
user_id=vehicle.manager_id.id or self.env.user.id,
note=_('Specify the End date of %s', vehicle.driver_id.name))
if 'future_driver_id' in vals and vals['future_driver_id']:
state_waiting_list = self.env.ref('fleet.fleet_vehicle_state_waiting_list', raise_if_not_found=False)
states = self.mapped('state_id').ids if 'state_id' not in vals else [vals['state_id']]
if not state_waiting_list or state_waiting_list.id not in states:
future_driver = self.env['res.partner'].browse(vals['future_driver_id'])
if self.vehicle_type == 'bike':
future_driver.sudo().write({'plan_to_change_bike': True})
if self.vehicle_type == 'car':
future_driver.sudo().write({'plan_to_change_car': True})
if 'active' in vals and not vals['active']:
self.env['fleet.vehicle.log.contract'].search([('vehicle_id', 'in', self.ids)]).active = False
self.env['fleet.vehicle.log.services'].search([('vehicle_id', 'in', self.ids)]).active = False
su_vals = self._clean_vals_internal_user(vals)
if su_vals:
self.sudo().write(su_vals)
res = super(FleetVehicle, self).write(vals)
return res
def _get_driver_history_data(self, vals):
self.ensure_one()
return {
'vehicle_id': self.id,
'driver_id': vals['driver_id'],
'date_start': fields.Date.today(),
}
def create_driver_history(self, vals):
for vehicle in self:
self.env['fleet.vehicle.assignation.log'].create(
vehicle._get_driver_history_data(vals),
)
def action_accept_driver_change(self):
# Find all the vehicles of the same type for which the driver is the future_driver_id
# remove their driver_id and close their history using current date
vehicles = self.search([('driver_id', 'in', self.mapped('future_driver_id').ids), ('vehicle_type', '=', self.vehicle_type)])
vehicles.write({'driver_id': False})
for vehicle in self:
if vehicle.vehicle_type == 'bike':
vehicle.future_driver_id.sudo().write({'plan_to_change_bike': False})
if vehicle.vehicle_type == 'car':
vehicle.future_driver_id.sudo().write({'plan_to_change_car': False})
vehicle.driver_id = vehicle.future_driver_id
vehicle.future_driver_id = False
@api.model
def _read_group_stage_ids(self, stages, domain, order):
return self.env['fleet.vehicle.state'].search([], order=order)
def return_action_to_open(self):
""" This opens the xml view specified in xml_id for the current vehicle """
self.ensure_one()
xml_id = self.env.context.get('xml_id')
if xml_id:
res = self.env['ir.actions.act_window']._for_xml_id('fleet.%s' % xml_id)
res.update(
context=dict(self.env.context, default_vehicle_id=self.id, group_by=False),
domain=[('vehicle_id', '=', self.id)]
)
return res
return False
def act_show_log_cost(self):
""" 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
"""
self.ensure_one()
copy_context = dict(self.env.context)
copy_context.pop('group_by', None)
res = self.env['ir.actions.act_window']._for_xml_id('fleet.fleet_vehicle_costs_action')
res.update(
context=dict(copy_context, default_vehicle_id=self.id, search_default_parent_false=True),
domain=[('vehicle_id', '=', self.id)]
)
return res
def _track_subtype(self, init_values):
self.ensure_one()
if 'driver_id' in init_values or 'future_driver_id' in init_values:
return self.env.ref('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': 'Assignment 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}
}

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class FleetVehicleAssignationLog(models.Model):
_name = "fleet.vehicle.assignation.log"
_description = "Drivers history on a vehicle"
_order = "create_date desc, date_start desc"
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")
@api.depends('driver_id', 'vehicle_id')
def _compute_display_name(self):
for rec in self:
rec.display_name = f'{rec.vehicle_id.name} - {rec.driver_id.name}'

View File

@ -0,0 +1,151 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
class FleetVehicleLogContract(models.Model):
_inherit = ['mail.thread', 'mail.activity.mixin']
_name = 'fleet.vehicle.log.contract'
_description = 'Vehicle Contract'
_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', required=True, check_company=True)
cost_subtype_id = fields.Many2one('fleet.service.type', 'Type', help='Cost type purchased with this cost', domain=[('category', '=', 'contract')])
amount = fields.Monetary('Cost', tracking=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')
name = fields.Char(string='Name', compute='_compute_contract_name', store=True, readonly=False)
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')
expires_today = fields.Boolean(compute='_compute_days_left')
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.Html('Terms and Conditions', copy=False)
cost_generated = fields.Monetary('Recurring Cost', tracking=True)
cost_frequency = fields.Selection([
('no', 'No'),
('daily', 'Daily'),
('weekly', 'Weekly'),
('monthly', 'Monthly'),
('yearly', 'Yearly')
], 'Recurring Cost Frequency', default='monthly', required=True)
service_ids = fields.Many2many('fleet.service.type', string="Included Services")
@api.depends('vehicle_id.name', 'cost_subtype_id')
def _compute_contract_name(self):
for record in self:
name = record.vehicle_id.name
if name and 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
"""
today = fields.Date.from_string(fields.Date.today())
for record in self:
if record.expiration_date and record.state in ['open', 'expired']:
renew_date = fields.Date.from_string(record.expiration_date)
diff_time = (renew_date - today).days
record.days_left = diff_time if diff_time > 0 else 0
record.expires_today = diff_time == 0
else:
record.days_left = -1
record.expires_today = False
def write(self, vals):
res = super(FleetVehicleLogContract, self).write(vals)
if 'start_date' in vals or 'expiration_date' in vals:
date_today = fields.Date.today()
future_contracts, running_contracts, expired_contracts = self.env[self._name], self.env[self._name], self.env[self._name]
for contract in self.filtered(lambda c: c.start_date and c.state != 'closed'):
if date_today < contract.start_date:
future_contracts |= contract
elif not contract.expiration_date or contract.start_date <= date_today <= contract.expiration_date:
running_contracts |= contract
else:
expired_contracts |= contract
future_contracts.action_draft()
running_contracts.action_open()
expired_contracts.action_expire()
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 action_close(self):
self.write({'state': 'closed'})
def action_draft(self):
self.write({'state': 'futur'})
def action_open(self):
self.write({'state': 'open'})
def action_expire(self):
self.write({'state': 'expired'})
@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))
reminder_activity_type = self.env.ref('fleet.mail_act_fleet_contract_to_renew', raise_if_not_found=False) or self.env['mail.activity.type']
nearly_expired_contracts = self.search([
('state', '=', 'open'),
('expiration_date', '<', outdated_days),
('user_id', '!=', False)
]
).filtered(
lambda nec: reminder_activity_type not in nec.activity_ids.activity_type_id
)
for contract in nearly_expired_contracts:
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()

View File

@ -0,0 +1,75 @@
# -*- 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
class FleetVehicleLogServices(models.Model):
_name = 'fleet.vehicle.log.services'
_inherit = ['mail.thread', 'mail.activity.mixin']
_rec_name = 'service_type_id'
_description = 'Services for vehicles'
active = fields.Boolean(default=True)
vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', required=True)
manager_id = fields.Many2one('res.users', 'Fleet Manager', related='vehicle_id.manager_id', store=True)
amount = fields.Monetary('Cost')
description = fields.Char('Description')
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', default=fields.Date.context_today)
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('res.partner', string="Driver", compute='_compute_purchaser_id', readonly=False, store=True)
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,
default=lambda self: self.env.ref('fleet.type_service_service_7', raise_if_not_found=False),
)
state = fields.Selection([
('new', 'New'),
('running', 'Running'),
('done', 'Done'),
('cancelled', 'Cancelled'),
], default='new', string='Stage', group_expand='_expand_states', tracking=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)
@api.depends('vehicle_id')
def _compute_purchaser_id(self):
for service in self:
service.purchaser_id = service.vehicle_id.driver_id
def _expand_states(self, states, domain, order):
return [key for key, dummy in self._fields['state'].selection]

View File

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _, api, fields, models
from odoo.osv import expression
FUEL_TYPES = [
('diesel', 'Diesel'),
('gasoline', 'Gasoline'),
('full_hybrid', 'Full Hybrid'),
('plug_in_hybrid_diesel', 'Plug-in Hybrid Diesel'),
('plug_in_hybrid_gasoline', 'Plug-in Hybrid Gasoline'),
('cng', 'CNG'),
('lpg', 'LPG'),
('hydrogen', 'Hydrogen'),
('electric', 'Electric'),
]
class FleetVehicleModel(models.Model):
_name = 'fleet.vehicle.model'
_inherit = ['avatar.mixin']
_description = 'Model of a vehicle'
_order = 'name asc'
name = fields.Char('Model name', required=True)
brand_id = fields.Many2one('fleet.vehicle.model.brand', 'Manufacturer', required=True)
category_id = fields.Many2one('fleet.vehicle.model.category', 'Category')
vendors = fields.Many2many('res.partner', 'fleet_vehicle_model_vendors', 'model_id', 'partner_id', string='Vendors')
image_128 = fields.Image(related='brand_id.image_128', readonly=True)
active = fields.Boolean(default=True)
vehicle_type = fields.Selection([('car', 'Car'), ('bike', 'Bike')], default='car', required=True)
transmission = fields.Selection([('manual', 'Manual'), ('automatic', 'Automatic')], 'Transmission')
vehicle_count = fields.Integer(compute='_compute_vehicle_count', search='_search_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='electric')
power = fields.Integer('Power')
horsepower = fields.Integer()
horsepower_tax = fields.Float('Horsepower Taxation')
electric_assistance = fields.Boolean(default=False)
vehicle_properties_definition = fields.PropertiesDefinition('Vehicle Properties')
@api.model
def _name_search(self, name, domain=None, operator='ilike', limit=None, order=None):
domain = domain or []
if operator != 'ilike' or (name or '').strip():
name_domain = ['|', ('name', 'ilike', name), ('brand_id.name', 'ilike', name)]
domain = expression.AND([name_domain, domain])
return self._search(domain, limit=limit, order=order)
@api.depends('brand_id')
def _compute_display_name(self):
for record in self:
name = record.name
if record.brand_id.name:
name = f"{record.brand_id.name}/{name}"
record.display_name = name
def _compute_vehicle_count(self):
group = self.env['fleet.vehicle']._read_group(
[('model_id', 'in', self.ids)], ['model_id'], aggregates=['__count'],
)
count_by_model = {model.id: count for model, count in group}
for model in self:
model.vehicle_count = count_by_model.get(model.id, 0)
@api.model
def _search_vehicle_count(self, operator, value):
if operator not in ['=', '!=', '<', '>'] or not isinstance(value, int):
raise NotImplementedError(_('Operation not supported.'))
fleet_models = self.env['fleet.vehicle.model'].search([])
if operator == '=':
fleet_models = fleet_models.filtered(lambda m: m.vehicle_count == value)
elif operator == '!=':
fleet_models = fleet_models.filtered(lambda m: m.vehicle_count != value)
elif operator == '<':
fleet_models = fleet_models.filtered(lambda m: m.vehicle_count < value)
elif operator == '>':
fleet_models = fleet_models.filtered(lambda m: m.vehicle_count > value)
return [('id', 'in', fleet_models.ids)]
def action_model_vehicle(self):
self.ensure_one()
view = {
'type': 'ir.actions.act_window',
'view_mode': 'kanban,tree,form',
'res_model': 'fleet.vehicle',
'name': _('Vehicles'),
'context': {'search_default_model_id': self.id, 'default_model_id': self.id}
}
return view

View File

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class FleetVehicleModelBrand(models.Model):
_name = 'fleet.vehicle.model.brand'
_description = 'Brand of the vehicle'
_order = 'name asc'
name = fields.Char('Name', required=True)
active = fields.Boolean(default=True)
image_128 = fields.Image("Logo", max_width=128, max_height=128)
model_count = fields.Integer(compute="_compute_model_count", string="", store=True)
model_ids = fields.One2many('fleet.vehicle.model', 'brand_id')
@api.depends('model_ids')
def _compute_model_count(self):
model_data = self.env['fleet.vehicle.model']._read_group([
('brand_id', 'in', self.ids),
], ['brand_id'], ['__count'])
models_brand = {brand.id: count for brand, count in model_data}
for record in self:
record.model_count = models_brand.get(record.id, 0)
def action_brand_model(self):
self.ensure_one()
view = {
'type': 'ir.actions.act_window',
'view_mode': 'tree,form',
'res_model': 'fleet.vehicle.model',
'name': 'Models',
'context': {'search_default_brand_id': self.id, 'default_brand_id': self.id}
}
return view

View File

@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class FleetVehicleModelCategory(models.Model):
_name = 'fleet.vehicle.model.category'
_description = 'Category of the model'
_order = 'sequence asc, id asc'
_sql_constraints = [
('name_uniq', 'UNIQUE (name)', 'Category name must be unique')
]
name = fields.Char(required=True)
sequence = fields.Integer()

View File

@ -0,0 +1,32 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
class FleetVehicleOdometer(models.Model):
_name = 'fleet.vehicle.odometer'
_description = 'Odometer log for a vehicle'
_order = 'date desc'
name = fields.Char(compute='_compute_vehicle_log_name', store=True)
date = fields.Date(default=fields.Date.context_today)
value = fields.Float('Odometer Value', group_operator="max")
vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', required=True)
unit = fields.Selection(related='vehicle_id.odometer_unit', string="Unit", readonly=True)
driver_id = fields.Many2one(related="vehicle_id.driver_id", string="Driver", readonly=False)
@api.depends('vehicle_id', 'date')
def _compute_vehicle_log_name(self):
for record in self:
name = record.vehicle_id.name
if not name:
name = str(record.date)
elif record.date:
name += ' / ' + str(record.date)
record.name = name
@api.onchange('vehicle_id')
def _onchange_vehicle(self):
if self.vehicle_id:
self.unit = self.vehicle_id.odometer_unit

View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class FleetVehicleState(models.Model):
_name = 'fleet.vehicle.state'
_order = 'sequence asc'
_description = 'Vehicle Status'
name = fields.Char(required=True, translate=True)
sequence = fields.Integer()
_sql_constraints = [('fleet_state_name_unique', 'unique(name)', 'State name already exists')]

View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class FleetVehicleTag(models.Model):
_name = 'fleet.vehicle.tag'
_description = 'Vehicle Tag'
name = fields.Char('Tag Name', required=True, translate=True)
color = fields.Integer('Color')
_sql_constraints = [('name_uniq', 'unique (name)', "Tag name already exists!")]

View File

@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = ['res.config.settings']
delay_alert_contract = fields.Integer(string='Delay alert contract outdated', default=30, config_parameter='hr_fleet.delay_alert_contract')

11
models/res_partner.py Normal file
View File

@ -0,0 +1,11 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
plan_to_change_car = fields.Boolean('Plan To Change Car', default=False, tracking=True)
plan_to_change_bike = fields.Boolean('Plan To Change Bike', default=False)

1
report/__init__.py Normal file
View File

@ -0,0 +1 @@
from . import fleet_report

156
report/fleet_report.py Normal file
View File

@ -0,0 +1,156 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from psycopg2 import sql
from odoo import tools
from odoo import api, fields, models
class FleetReport(models.Model):
_name = "fleet.vehicle.cost.report"
_description = "Fleet Analysis Report"
_auto = False
_order = 'date_start desc'
company_id = fields.Many2one('res.company', 'Company', readonly=True)
vehicle_id = fields.Many2one('fleet.vehicle', 'Vehicle', readonly=True)
name = fields.Char('Vehicle Name', readonly=True)
driver_id = fields.Many2one('res.partner', 'Driver', readonly=True)
fuel_type = fields.Char('Fuel', readonly=True)
date_start = fields.Date('Date', readonly=True)
vehicle_type = fields.Selection([('car', 'Car'), ('bike', 'Bike')], readonly=True)
cost = fields.Float('Cost', readonly=True)
cost_type = fields.Selection(string='Cost Type', selection=[
('contract', 'Contract'),
('service', 'Service')
], readonly=True)
def init(self):
query = """
WITH service_costs AS (
SELECT
ve.id AS vehicle_id,
ve.company_id AS company_id,
ve.name AS name,
ve.driver_id AS driver_id,
ve.fuel_type AS fuel_type,
date(date_trunc('month', d)) AS date_start,
vem.vehicle_type as vehicle_type,
COALESCE(sum(se.amount), 0) AS
COST,
'service' AS cost_type
FROM
fleet_vehicle ve
JOIN
fleet_vehicle_model vem ON vem.id = ve.model_id
CROSS JOIN generate_series((
SELECT
min(date)
FROM fleet_vehicle_log_services), CURRENT_DATE + '1 month'::interval, '1 month') d
LEFT JOIN fleet_vehicle_log_services se ON se.vehicle_id = ve.id
AND date_trunc('month', se.date) = date_trunc('month', d)
WHERE
ve.active AND se.active AND se.state != 'cancelled'
GROUP BY
ve.id,
ve.company_id,
vem.vehicle_type,
ve.name,
date_start,
d
ORDER BY
ve.id,
date_start
),
contract_costs AS (
SELECT
ve.id AS vehicle_id,
ve.company_id AS company_id,
ve.name AS name,
ve.driver_id AS driver_id,
ve.fuel_type AS fuel_type,
date(date_trunc('month', d)) AS date_start,
vem.vehicle_type as vehicle_type,
(COALESCE(sum(co.amount), 0) + COALESCE(sum(cod.cost_generated * extract(day FROM least (date_trunc('month', d) + interval '1 month', cod.expiration_date) - greatest (date_trunc('month', d), cod.start_date))), 0) + COALESCE(sum(com.cost_generated), 0) + COALESCE(sum(coy.cost_generated), 0)) AS
COST,
'contract' AS cost_type
FROM
fleet_vehicle ve
JOIN
fleet_vehicle_model vem ON vem.id = ve.model_id
CROSS JOIN generate_series((
SELECT
min(acquisition_date)
FROM fleet_vehicle), CURRENT_DATE + '1 month'::interval, '1 month') d
LEFT JOIN fleet_vehicle_log_contract co ON co.vehicle_id = ve.id
AND date_trunc('month', co.date) = date_trunc('month', d)
LEFT JOIN fleet_vehicle_log_contract cod ON cod.vehicle_id = ve.id
AND date_trunc('month', cod.start_date) <= date_trunc('month', d)
AND date_trunc('month', cod.expiration_date) >= date_trunc('month', d)
AND cod.cost_frequency = 'daily'
LEFT JOIN fleet_vehicle_log_contract com ON com.vehicle_id = ve.id
AND date_trunc('month', com.start_date) <= date_trunc('month', d)
AND date_trunc('month', com.expiration_date) >= date_trunc('month', d)
AND com.cost_frequency = 'monthly'
LEFT JOIN fleet_vehicle_log_contract coy ON coy.vehicle_id = ve.id
AND d BETWEEN coy.start_date and coy.expiration_date
AND date_part('month', coy.date) = date_part('month', d)
AND coy.cost_frequency = 'yearly'
WHERE
ve.active
GROUP BY
ve.id,
ve.company_id,
vem.vehicle_type,
ve.name,
date_start,
d
ORDER BY
ve.id,
date_start
)
SELECT row_number() OVER (ORDER BY vehicle_id ASC) as id,
company_id,
vehicle_id,
name,
driver_id,
fuel_type,
date_start,
vehicle_type,
COST,
cost_type
FROM (
SELECT
company_id,
vehicle_id,
name,
driver_id,
fuel_type,
date_start,
vehicle_type,
COST,
'service' as cost_type
FROM
service_costs sc
UNION ALL (
SELECT
company_id,
vehicle_id,
name,
driver_id,
fuel_type,
date_start,
vehicle_type,
COST,
'contract' as cost_type
FROM
contract_costs cc)
) c
"""
tools.drop_view_if_exists(self.env.cr, self._table)
self.env.cr.execute(
sql.SQL("""CREATE or REPLACE VIEW {} as ({})""").format(
sql.Identifier(self._table),
sql.SQL(query)
))

111
security/fleet_security.xml Normal file
View File

@ -0,0 +1,111 @@
<?xml version="1.0" ?>
<odoo>
<record id="module_fleet_category" model="ir.module.category">
<field name="name">Fleet</field>
<field name="sequence">17</field>
</record>
<record id="fleet_group_user" model="res.groups">
<field name="name">Officer: Manage all vehicles</field>
<field name="category_id" ref="base.module_category_human_resources_fleet"/>
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="fleet_group_manager" model="res.groups">
<field name="name">Administrator</field>
<field name="implied_ids" eval="[(4, ref('fleet_group_user'))]"/>
<field name="category_id" ref="base.module_category_human_resources_fleet"/>
<field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
</record>
<data noupdate="1">
<record id="base.default_user" model="res.users">
<field name="groups_id" eval="[(4,ref('fleet.fleet_group_manager'))]"/>
</record>
<record id="fleet_rule_contract_visibility_user" model="ir.rule">
<field name="name">User can only see his/her contracts</field>
<field name="model_id" ref="model_fleet_vehicle_log_contract"/>
<field name="groups" eval="[(4, ref('fleet_group_user'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
<field name="domain_force">[('vehicle_id.driver_id','=',user.partner_id.id)]</field>
</record>
<record id="fleet_rule_service_visibility_user" model="ir.rule">
<field name="name">User can only see his/her vehicle's services</field>
<field name="model_id" ref="model_fleet_vehicle_log_services"/>
<field name="groups" eval="[(4, ref('fleet_group_user'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
<field name="domain_force">[('vehicle_id.driver_id','=',user.partner_id.id)]</field>
</record>
<record id="fleet_rule_odometer_visibility_user" model="ir.rule">
<field name="name">User can only see his/her vehicle's odometer</field>
<field name="model_id" ref="model_fleet_vehicle_odometer"/>
<field name="groups" eval="[(4, ref('fleet_group_user'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_unlink" eval="True"/>
<field name="domain_force">[('vehicle_id.driver_id','=',user.partner_id.id)]</field>
</record>
<record id="fleet_rule_vehicle_visibility_user" model="ir.rule">
<field name="name">User can only see his/her vehicle</field>
<field name="model_id" ref="model_fleet_vehicle"/>
<field name="groups" eval="[(4, ref('fleet_group_user'))]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="False"/>
<field name="perm_unlink" eval="False"/>
<field name="domain_force">[('driver_id','=',user.partner_id.id)]</field>
</record>
<record id="fleet_rule_contract_visibility_manager" model="ir.rule">
<field name="name">Administrator has all rights on vehicle's contracts</field>
<field name="model_id" ref="model_fleet_vehicle_log_contract"/>
<field name="groups" eval="[Command.link(ref('fleet_group_manager'))]"/>
</record>
<record id="fleet_rule_service_visibility_manager" model="ir.rule">
<field name="name">Administrator has all rights on vehicle's services</field>
<field name="model_id" ref="model_fleet_vehicle_log_services"/>
<field name="groups" eval="[Command.link(ref('fleet_group_manager'))]"/>
</record>
<record id="fleet_rule_odometer_visibility_manager" model="ir.rule">
<field name="name">Administrator has all rights on vehicle's vehicle's odometer</field>
<field name="model_id" ref="model_fleet_vehicle_odometer"/>
<field name="groups" eval="[Command.link(ref('fleet_group_manager'))]"/>
</record>
<record id="fleet_rule_vehicle_visibility_manager" model="ir.rule">
<field name="name">Administrator has all rights on vehicle</field>
<field name="model_id" ref="model_fleet_vehicle"/>
<field name="groups" eval="[Command.link(ref('fleet_group_manager'))]"/>
</record>
<record id="ir_rule_fleet_vehicle" model="ir.rule">
<field name="name">Fleet vehicle: Multi Company</field>
<field name="model_id" ref="model_fleet_vehicle"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
</record>
<record id="ir_rule_fleet_vehicle_log_contract" model="ir.rule">
<field name="name">Fleet vehicle log contract: Multi Company</field>
<field name="model_id" ref="model_fleet_vehicle_log_contract"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
</record>
<record id="ir_rule_fleet_report" model="ir.rule">
<field name="name">Costs Analysis: Multi Company</field>
<field name="model_id" ref="model_fleet_vehicle_cost_report"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
</record>
<record id="ir_rule_fleet_odometer" model="ir.rule">
<field name="name">Fleet odometer: Multi Company</field>
<field name="model_id" ref="model_fleet_vehicle_odometer"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('vehicle_id.company_id', '=', False), ('vehicle_id.company_id', 'in', company_ids)]</field>
</record>
<record id="ir_rule_fleet_log_services" model="ir.rule">
<field name="name">Fleet log services: Multi Company</field>
<field name="model_id" ref="model_fleet_vehicle_log_services"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,23 @@
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
fleet_vehicle_model_access_right_user,fleet_vehicle_model_access_right,model_fleet_vehicle_model,fleet_group_user,1,0,0,0
fleet_vehicle_tag_access_right_user,fleet_vehicle_tag_access_right,model_fleet_vehicle_tag,fleet_group_user,1,0,0,0
fleet_vehicle_state_access_right_user,fleet_vehicle_state_access_right,model_fleet_vehicle_state,fleet_group_user,1,0,0,0
fleet_vehicle_model_brand_access_right_user,fleet_vehicle_model_brand_access_right,model_fleet_vehicle_model_brand,fleet_group_user,1,0,0,0
fleet_vehicle_model_brand_category_right_user,fleet_vehicle_model_category_access_right,model_fleet_vehicle_model_category,fleet_group_user,1,0,0,0
fleet_vehicle_access_right_user,fleet_vehicle_access_right,model_fleet_vehicle,fleet_group_user,1,1,0,0
fleet_vehicle_log_services_access_right_user,fleet_vehicle_log_services_access_right,model_fleet_vehicle_log_services,fleet_group_user,1,0,0,0
fleet_vehicle_log_contract_access_right_user,fleet_vehicle_log_contract_access_right,model_fleet_vehicle_log_contract,fleet_group_user,1,0,0,0
fleet_service_type_access_right_user,fleet_service_type_access_right,model_fleet_service_type,fleet_group_user,1,0,0,0
fleet_vehicle_model_access_right,fleet_vehicle_model_access_right,model_fleet_vehicle_model,fleet_group_manager,1,1,1,1
fleet_vehicle_tag_access_right,fleet_vehicle_tag_access_right,model_fleet_vehicle_tag,fleet_group_manager,1,1,1,1
fleet_vehicle_state_access_right,fleet_vehicle_state_access_right,model_fleet_vehicle_state,fleet_group_manager,1,1,1,1
fleet_vehicle_odometer_access_right,fleet_vehicle_odometer_access_right,model_fleet_vehicle_odometer,fleet_group_user,1,1,1,1
fleet_vehicle_model_brand_access_right,fleet_vehicle_model_brand_access_right,model_fleet_vehicle_model_brand,fleet_group_manager,1,1,1,1
fleet_vehicle_model_category_access_right,fleet_vehicle_model_brand_category_right,model_fleet_vehicle_model_category,fleet_group_manager,1,1,1,1
fleet_vehicle_access_right,fleet_vehicle_access_right,model_fleet_vehicle,fleet_group_manager,1,1,1,1
fleet_vehicle_log_services_access_right,fleet_vehicle_log_services_access_right,model_fleet_vehicle_log_services,fleet_group_manager,1,1,1,1
fleet_vehicle_log_contract_access_right,fleet_vehicle_log_contract_access_right,model_fleet_vehicle_log_contract,fleet_group_manager,1,1,1,1
fleet_service_type_access_right,fleet_service_type_access_right,model_fleet_service_type,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
access_fleet_report_manager,fleet_vehicle_cost_report_access_right,model_fleet_vehicle_cost_report,fleet_group_manager,1,0,0,0
1 id name model_id/id group_id/id perm_read perm_write perm_create perm_unlink
2 fleet_vehicle_model_access_right_user fleet_vehicle_model_access_right model_fleet_vehicle_model fleet_group_user 1 0 0 0
3 fleet_vehicle_tag_access_right_user fleet_vehicle_tag_access_right model_fleet_vehicle_tag fleet_group_user 1 0 0 0
4 fleet_vehicle_state_access_right_user fleet_vehicle_state_access_right model_fleet_vehicle_state fleet_group_user 1 0 0 0
5 fleet_vehicle_model_brand_access_right_user fleet_vehicle_model_brand_access_right model_fleet_vehicle_model_brand fleet_group_user 1 0 0 0
6 fleet_vehicle_model_brand_category_right_user fleet_vehicle_model_category_access_right model_fleet_vehicle_model_category fleet_group_user 1 0 0 0
7 fleet_vehicle_access_right_user fleet_vehicle_access_right model_fleet_vehicle fleet_group_user 1 1 0 0
8 fleet_vehicle_log_services_access_right_user fleet_vehicle_log_services_access_right model_fleet_vehicle_log_services fleet_group_user 1 0 0 0
9 fleet_vehicle_log_contract_access_right_user fleet_vehicle_log_contract_access_right model_fleet_vehicle_log_contract fleet_group_user 1 0 0 0
10 fleet_service_type_access_right_user fleet_service_type_access_right model_fleet_service_type fleet_group_user 1 0 0 0
11 fleet_vehicle_model_access_right fleet_vehicle_model_access_right model_fleet_vehicle_model fleet_group_manager 1 1 1 1
12 fleet_vehicle_tag_access_right fleet_vehicle_tag_access_right model_fleet_vehicle_tag fleet_group_manager 1 1 1 1
13 fleet_vehicle_state_access_right fleet_vehicle_state_access_right model_fleet_vehicle_state fleet_group_manager 1 1 1 1
14 fleet_vehicle_odometer_access_right fleet_vehicle_odometer_access_right model_fleet_vehicle_odometer fleet_group_user 1 1 1 1
15 fleet_vehicle_model_brand_access_right fleet_vehicle_model_brand_access_right model_fleet_vehicle_model_brand fleet_group_manager 1 1 1 1
16 fleet_vehicle_model_category_access_right fleet_vehicle_model_brand_category_right model_fleet_vehicle_model_category fleet_group_manager 1 1 1 1
17 fleet_vehicle_access_right fleet_vehicle_access_right model_fleet_vehicle fleet_group_manager 1 1 1 1
18 fleet_vehicle_log_services_access_right fleet_vehicle_log_services_access_right model_fleet_vehicle_log_services fleet_group_manager 1 1 1 1
19 fleet_vehicle_log_contract_access_right fleet_vehicle_log_contract_access_right model_fleet_vehicle_log_contract fleet_group_manager 1 1 1 1
20 fleet_service_type_access_right fleet_service_type_access_right model_fleet_service_type fleet_group_manager 1 1 1 1
21 access_mail_activity_type_fleet_manager mail.activity.type.fleet.manager mail.model_mail_activity_type fleet.fleet_group_manager 1 1 1 1
22 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
23 access_fleet_report_manager fleet_vehicle_cost_report_access_right model_fleet_vehicle_cost_report fleet_group_manager 1 0 0 0

BIN
static/description/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1 @@
<svg width="50" height="50" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><path d="M30 25a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z" fill="#1AD3BB"/><path fill-rule="evenodd" clip-rule="evenodd" d="M50 25c0 13.807-11.193 25-25 25S0 38.807 0 25 11.193 0 25 0s25 11.193 25 25ZM19.577 43.215C20.696 40.136 22 35.568 22 31h6c0 4.568 1.304 9.136 2.423 12.215a19.042 19.042 0 0 0 12.792-12.792C40.136 29.304 35.568 28 31 28v-6c4.568 0 9.136-1.304 12.215-2.423C40.88 11.726 33.609 6 25 6S9.12 11.726 6.785 19.577C9.864 20.696 14.432 22 19 22v6c-4.568 0-9.136 1.304-12.215 2.423a19.042 19.042 0 0 0 12.792 12.792Z" fill="#985184"/><path fill-rule="evenodd" clip-rule="evenodd" d="M25 34a9 9 0 1 0 0-18 9 9 0 0 0 0 18Zm0-4a5 5 0 1 0 0-10 5 5 0 0 0 0 10Z" fill="#712258"/></svg>

After

Width:  |  Height:  |  Size: 767 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Some files were not shown because too many files have changed in this diff Show More