From 21503e3001f0c425148ace0579386922c594aa52 Mon Sep 17 00:00:00 2001 From: Arnaud LAYEC Date: Fri, 27 Feb 2026 16:40:16 +0100 Subject: [PATCH] [ADD] fleet_vehicle_category_analytic: Set analytic account on invoice line from vehicle, via vehicle categories precomit --- .../views/fleet_vehicle_views.xml | 1 + fleet_vehicle_category_analytic/README.rst | 104 ++++ fleet_vehicle_category_analytic/__init__.py | 1 + .../__manifest__.py | 18 + .../models/__init__.py | 1 + .../models/account_move_line.py | 30 ++ .../models/fleet_vehicle_category.py | 19 + .../pyproject.toml | 3 + .../readme/CONTRIBUTORS.md | 1 + .../readme/DESCRIPTION.md | 2 + .../readme/HISTORY.md | 3 + .../readme/USAGE.md | 12 + .../static/description/icon.png | Bin 0 -> 14952 bytes .../static/description/index.html | 456 ++++++++++++++++++ .../tests/__init__.py | 1 + .../test_fleet_vehicle_category_analytic.py | 113 +++++ .../views/fleet_vehicle_category_views.xml | 18 + 17 files changed, 783 insertions(+) create mode 100644 fleet_vehicle_category_analytic/README.rst create mode 100644 fleet_vehicle_category_analytic/__init__.py create mode 100644 fleet_vehicle_category_analytic/__manifest__.py create mode 100644 fleet_vehicle_category_analytic/models/__init__.py create mode 100644 fleet_vehicle_category_analytic/models/account_move_line.py create mode 100644 fleet_vehicle_category_analytic/models/fleet_vehicle_category.py create mode 100644 fleet_vehicle_category_analytic/pyproject.toml create mode 100644 fleet_vehicle_category_analytic/readme/CONTRIBUTORS.md create mode 100644 fleet_vehicle_category_analytic/readme/DESCRIPTION.md create mode 100644 fleet_vehicle_category_analytic/readme/HISTORY.md create mode 100644 fleet_vehicle_category_analytic/readme/USAGE.md create mode 100644 fleet_vehicle_category_analytic/static/description/icon.png create mode 100644 fleet_vehicle_category_analytic/static/description/index.html create mode 100644 fleet_vehicle_category_analytic/tests/__init__.py create mode 100644 fleet_vehicle_category_analytic/tests/test_fleet_vehicle_category_analytic.py create mode 100644 fleet_vehicle_category_analytic/views/fleet_vehicle_category_views.xml diff --git a/fleet_vehicle_category/views/fleet_vehicle_views.xml b/fleet_vehicle_category/views/fleet_vehicle_views.xml index bc7c48dab..e8300778e 100644 --- a/fleet_vehicle_category/views/fleet_vehicle_views.xml +++ b/fleet_vehicle_category/views/fleet_vehicle_views.xml @@ -29,6 +29,7 @@ + diff --git a/fleet_vehicle_category_analytic/README.rst b/fleet_vehicle_category_analytic/README.rst new file mode 100644 index 000000000..8a735df3c --- /dev/null +++ b/fleet_vehicle_category_analytic/README.rst @@ -0,0 +1,104 @@ +====================== +Fleet Vehicle Analytic +====================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:43e12b9a776f7464fecf6608fc4ee45d591ff74590d37fea45956cbe2b3d34eb + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Ffleet-lightgray.png?logo=github + :target: https://github.com/OCA/fleet/tree/18.0/fleet_vehicle_category_analytic + :alt: OCA/fleet +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/fleet-18-0/fleet-18-0-fleet_vehicle_category_analytic + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/fleet&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds analytic account definition per vehicle category. It +define this analytic account on the analytic distribution of account +move line. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Prerequisites: Analytic enabled, Vehicle added to Vehicle Categories. + +1. Browse to "Fleet / Configuration / Categories" and define an Analytic + Account on a Category +2. Create a new invoice from "Accounting / Vendors / Bills / [+ New]" +3. On the invoice line, set a vehicle belonging to the Category modified + at step 1. To view the "Vehicule" column on invoice lines, do not + forget to add the column. +4. Look at the Analytic Distribution: the Analytic Account previously + defined on the Category is added at 100%. + +Warning: this analytic is very simply merged / added to the existing +analytic distribution, which may lead to more than 100% distribution. + +Changelog +========= + +18.0.1.0.0 (2026-02-27) +----------------------- + +- [NEW] Module creation + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Arnaud Layec +* Akretion + +Contributors +------------ + +- Arnaud Layec + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/fleet `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/fleet_vehicle_category_analytic/__init__.py b/fleet_vehicle_category_analytic/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/fleet_vehicle_category_analytic/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/fleet_vehicle_category_analytic/__manifest__.py b/fleet_vehicle_category_analytic/__manifest__.py new file mode 100644 index 000000000..2aed48e58 --- /dev/null +++ b/fleet_vehicle_category_analytic/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2026 Arnaud Layec () +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + "name": "Fleet Vehicle Analytic", + "summary": """ + Define Analytic Account per vehicle category + """, + "version": "18.0.1.0.0", + "category": "Human Resources", + "author": "Arnaud Layec, Akretion, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/fleet", + "license": "AGPL-3", + "depends": ["account_fleet", "fleet_vehicle_category"], + "data": ["views/fleet_vehicle_category_views.xml"], + "installable": True, + "auto_install": False, +} diff --git a/fleet_vehicle_category_analytic/models/__init__.py b/fleet_vehicle_category_analytic/models/__init__.py new file mode 100644 index 000000000..031589050 --- /dev/null +++ b/fleet_vehicle_category_analytic/models/__init__.py @@ -0,0 +1 @@ +from . import account_move_line, fleet_vehicle_category diff --git a/fleet_vehicle_category_analytic/models/account_move_line.py b/fleet_vehicle_category_analytic/models/account_move_line.py new file mode 100644 index 000000000..623b4ba56 --- /dev/null +++ b/fleet_vehicle_category_analytic/models/account_move_line.py @@ -0,0 +1,30 @@ +# Copyright 2026 - Arnaud LAYEC +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class AccountMoveLine(models.Model): + _inherit = ["account.move.line"] + + @api.depends("vehicle_id") + def _compute_analytic_distribution(self): + """Inject the analytic account of the vehicle's category. + When the account is already present in the distribution its + percentage is kept as-is to avoid overriding manual adjustments made + through other sources; otherwise it is added at 100%. + """ + res = super()._compute_analytic_distribution() + for line in self: + if not line.vehicle_id: + continue + account = line.vehicle_id.vehicle_category_id.analytic_account_id + if not account: + continue + + distribution = line.analytic_distribution or {} + account_key = str(account.id) + if account_key not in distribution: + distribution[account_key] = 100 + line.analytic_distribution = distribution + return res diff --git a/fleet_vehicle_category_analytic/models/fleet_vehicle_category.py b/fleet_vehicle_category_analytic/models/fleet_vehicle_category.py new file mode 100644 index 000000000..460ad0b3a --- /dev/null +++ b/fleet_vehicle_category_analytic/models/fleet_vehicle_category.py @@ -0,0 +1,19 @@ +# Copyright 2026 - Arnaud LAYEC +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class FleetVehicleCategory(models.Model): + _inherit = ["fleet.vehicle.category"] + + company_id = fields.Many2one( + comodel_name="res.company", + readonly=True, + default=lambda self: self.env.company.root_id, + ) + analytic_account_id = fields.Many2one( + comodel_name="account.analytic.account", + string="Analytic Account", + check_company=True, + ) diff --git a/fleet_vehicle_category_analytic/pyproject.toml b/fleet_vehicle_category_analytic/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/fleet_vehicle_category_analytic/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/fleet_vehicle_category_analytic/readme/CONTRIBUTORS.md b/fleet_vehicle_category_analytic/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..83a4b7a81 --- /dev/null +++ b/fleet_vehicle_category_analytic/readme/CONTRIBUTORS.md @@ -0,0 +1 @@ +- Arnaud Layec \<\> diff --git a/fleet_vehicle_category_analytic/readme/DESCRIPTION.md b/fleet_vehicle_category_analytic/readme/DESCRIPTION.md new file mode 100644 index 000000000..9b7d7120c --- /dev/null +++ b/fleet_vehicle_category_analytic/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +This module adds analytic account definition per vehicle category. +It define this analytic account on the analytic distribution of account move line. diff --git a/fleet_vehicle_category_analytic/readme/HISTORY.md b/fleet_vehicle_category_analytic/readme/HISTORY.md new file mode 100644 index 000000000..e34e61532 --- /dev/null +++ b/fleet_vehicle_category_analytic/readme/HISTORY.md @@ -0,0 +1,3 @@ +## 18.0.1.0.0 (2026-02-27) + +- \[NEW\] Module creation diff --git a/fleet_vehicle_category_analytic/readme/USAGE.md b/fleet_vehicle_category_analytic/readme/USAGE.md new file mode 100644 index 000000000..597266114 --- /dev/null +++ b/fleet_vehicle_category_analytic/readme/USAGE.md @@ -0,0 +1,12 @@ + +Prerequisites: Analytic enabled, Vehicle added to Vehicle Categories. + +1. Browse to "Fleet / Configuration / Categories" and define an Analytic Account on a Category +2. Create a new invoice from "Accounting / Vendors / Bills / [+ New]" +3. On the invoice line, set a vehicle belonging to the Category modified at step 1. + To view the "Vehicule" column on invoice lines, do not forget to add the column. +4. Look at the Analytic Distribution: the Analytic Account previously defined on the Category + is added at 100%. + +Warning: this analytic is very simply merged / added to the existing analytic distribution, +which may lead to more than 100% distribution. diff --git a/fleet_vehicle_category_analytic/static/description/icon.png b/fleet_vehicle_category_analytic/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1743a4c1dcc18c1557665aaf8dabe8ed621546b9 GIT binary patch literal 14952 zcmV-uI+w+XP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>DIsHjQK~#8N<(&z* zo>g`4&pFA-0GSv90$~Oj0t9dfD3dr(Sgi~qqEf5kP)plO>wO+?@3n*N)86*h>(GiQ z!Kw&at0E|Z5UGMPhzu!8AOj?U41~<%Ip_X=|NnZw?<9fboX`Y3cYW`>_nOz*Yw!KO z?>C&J^Zgfps;{G?tD~>4v$M0WQ+Q`boof0(41MBt_I2qrKVpHEO4BZ4V@Rd4wW z%j#YIV$rED4vok@$86*RQ__iY0a$aUYbRH|{J2+keH~p+G5H0WtjnhQGBGYI)Kw!f zq;9^)**ItDP@vV*wCZ6xkup*q@FnUIe7>ZBp6@?j3GjMF|; zq+lyeffahOArDMZLc<=C0JKh1)+(mEglnL$w{qT82}F(C!eJ{h`tlpkobj4;IHch8 zO(Mxq$ltU<9eSV)7>6Cbc1cN*#9w1U!}OcsLC4Nf%9E2wi8bRITdyc|(F(MXEr8`5 zFY#%V%mE>A#IrpKkc`w)K~ey*0*aK!Zjw^M+AUuC`nsB=5fRY};$&zB5c@J>fACsz zAkh)KmwT^f$FXtLOM^h_5>3TH>ZYrsH(_Y(voWbzGhu&CeGPqDjqINc6LuqW0`3UV zo(6Ffn2OrFB&t2biw0hu$J2l|KQ5xws5E8-DY|Lp-+Abir9<}fjA5q6RdJ4}Wh%XV z8bj*~9NuoFAU0Krz${A>!Uf274;yXkHA13L00XX=1Hz+bJ*VRqqC}!xEK$*kf@J8D z6@%e)6cj|@Ke`Ca!VV7t51B1f=DA#*&4*PwoD_zoqtu#Y&{Zc=h=fvThJ~h}vsasj^&jNw{1Z}|L7U;4Z1U0*q+^M9|i4S|U*nRsc1x`P(6T7#SUbr*Gbb3gRU_E-B z1ag+`(%HQkN#D^tP6(V>Xc=ha=!utU3X1~w`l?-4c4$2Jv1S#w$|o~g4jc!Auv`2& zVV;M@hC`PS&54y)7+}g)tsvp&g;SKwt9zse=ibnIaHxjr$0=^j#R*I?^jLzBr#R=v zDB{(6&3xkluC>fDU4bouz?t(yDy~BaE01DJgL|~lR3X}62u(_vLk!rKXbfUuW|0bt zbG@vAL#ye4pAo_FS#0-Qe;p)3-|7?4Mh44ZH4KRKN-B9V&iF&U1#w2+8C1!VR*`nq zWjA4~saRpQQujs24)w}&4%3^_piD**04RBGg<(wN$w2vT!4 zu8r1W#kZ1G2rWp5lcW_pBmm_|Nj%rlWho1b2Om~xxn`6|8%|pC;3bDdf^VPXr5N@Q zEBi7QV~@~nWW_K6VzZPb1L^ZNwbY6>HHv3APNR5f%!H39vsx+GN@eHGY?S0sEHt6; z$dDj)vNp<+YhB9|8G72xLjk*Bu@J%{0`Y|_vL<<<*7374{2H+uRQxO)w7xGE#X$PfV78l}jYl^&*wvFwseQEku#*gfKruvaC>d#I@WuSipsE zyM|}*T#F-{yrB}y%A}|JpB;)t0fakPxpYTLHINcGM>i(fV{t5!%w%FIV7j~tNY9%r zjO;e2M+A{%V}Q4)lVw&|8A**Q$^^H`TaC>(=&l0=z?6HO%q zpd16Wb^_BaLuPY&Gn?b3fPIoRS`6A2ihs!+*0C%k6M=Yo1V@w17(k>2A}AKcu{Vrb zsfA?P;lfVhFopO6DH#$gN8lVlo0RMX5@USFy*6hITC-)YacRUGc!R)h(NK`M3sPdd zanu?TuVfL!va=ZCOnGLP$BPw|q2=Ov=fs#mh|q{7t-va_YDGb+1BtFezI;UFz?Q3{ z_Lg?O@BM!v3F9UWo+A+GWd(~0jI<<<1D-s6+00eV(6Y3OWuP>2fI?p)u_;;N5s(ts_ z^S5_~1WJCdiQ|u%d|=PU-pA%I&LaUpc~oyzK}cv-D1=TfZj2i>wKTrxqodL@4XUB~ z+H!fJ#>Ex~XuGA6b6N^cSKG4@3Tzoeox0Z8pQVmNPh$xeVg)|rzEi*_I!r-Z-?wZW z*ub}6#B{;~5hf4vaw{$S@!`{267Y5vhxk(9SH1E@qel;g8EV0(k=>`Cc8n&h79u=) z4Y;XUQ)JqLJjj^Mn^~*7jzSw3P%>&wh*^yfWLSB^Oq&z6rrcmdsi11>mddj)ZTmV=3@9&V5FH0 zQ!S0Aq+)dW;{#}Gs7c9$XnEJ;HFAq-<50DBVSOD9yJ8FR^S9(UMGl|22H_TH{jh;t zgY!nWd-(9;4ms!^KFo#ilRz_e0nZ7dTh-t_Cy-fS2C|c~kkM1Y)ViQeSwXFw;>Olm zRzlA0tL4Hn^nCqA+i``sK?}ak-Nt_wi$^e2f#FgR7o2K>@<5h-Qx8_4)JCsHS9>WF zV~Nk`NSE!R1GKqLaT@|W{o*RDj9by02uNCYC6sYy16U4hKgq)$bc&X2=z^E6hYB!g zs1OXkscp5Qd@)kx{Rj?E>NU^S5E&aLSf~nZpG<|6scFm{2BQ?d31RR&iHfAj&V=yt zVPFvrb@02vjNeshdWy+4C6z_ff?_ZMzTAb+)X0tN2UAt0@OI|gyH$NfYJ!2;o}J(c zWG0vtE0+lpHOl}n~ z8WIT4WJ#jTKcD?u1&<(*R39*8mD-qwBVh*4^bfGHZN~AU}gfL&G04NrE<^Yip|NN%vCW&

s^cU%^SF1(*yRW(utXYKntU31k- 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 mj74OS7)zxazF%VXb^JdKghtNT@T|}P0000 + + + + +Fleet Vehicle Analytic + + + +

+

Fleet Vehicle Analytic

+ + +

Beta License: AGPL-3 OCA/fleet Translate me on Weblate Try me on Runboat

+

This module adds analytic account definition per vehicle category. It +define this analytic account on the analytic distribution of account +move line.

+

Table of contents

+ +
+

Usage

+

Prerequisites: Analytic enabled, Vehicle added to Vehicle Categories.

+
    +
  1. Browse to “Fleet / Configuration / Categories” and define an Analytic +Account on a Category
  2. +
  3. Create a new invoice from “Accounting / Vendors / Bills / [+ New]”
  4. +
  5. On the invoice line, set a vehicle belonging to the Category modified +at step 1. To view the “Vehicule” column on invoice lines, do not +forget to add the column.
  6. +
  7. Look at the Analytic Distribution: the Analytic Account previously +defined on the Category is added at 100%.
  8. +
+

Warning: this analytic is very simply merged / added to the existing +analytic distribution, which may lead to more than 100% distribution.

+
+
+

Changelog

+
+

18.0.1.0.0 (2026-02-27)

+
    +
  • [NEW] Module creation
  • +
+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Arnaud Layec
  • +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/fleet project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/fleet_vehicle_category_analytic/tests/__init__.py b/fleet_vehicle_category_analytic/tests/__init__.py new file mode 100644 index 000000000..6e1d2d7e0 --- /dev/null +++ b/fleet_vehicle_category_analytic/tests/__init__.py @@ -0,0 +1 @@ +from . import test_fleet_vehicle_category_analytic diff --git a/fleet_vehicle_category_analytic/tests/test_fleet_vehicle_category_analytic.py b/fleet_vehicle_category_analytic/tests/test_fleet_vehicle_category_analytic.py new file mode 100644 index 000000000..1657014f5 --- /dev/null +++ b/fleet_vehicle_category_analytic/tests/test_fleet_vehicle_category_analytic.py @@ -0,0 +1,113 @@ +# Copyright 2026 - Arnaud LAYEC +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import Command +from odoo.tests import tagged + +from odoo.addons.account.tests.common import AccountTestInvoicingCommon + + +@tagged("post_install", "-at_install") +class TestFleetVehicleCategoryAnalytic(AccountTestInvoicingCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + + # Analytic + analytic_plan = cls.env["account.analytic.plan"].create({"name": "Default"}) + analytic_account_vehicle = cls.env["account.analytic.account"].create( + { + "name": "Analytic Vehicle", + "plan_id": analytic_plan.id, + } + ) + analytic_account_other = analytic_account_vehicle.copy( + { + "name": "Analytic Other", + } + ) + cls.vehicle_key = str(analytic_account_vehicle.id) + cls.other_key = str(analytic_account_other.id) + + # Fleet + vehicle_brand = cls.env["fleet.vehicle.model.brand"].create( + {"name": "TestBrand"} + ) + vehicle_model = cls.env["fleet.vehicle.model"].create( + { + "name": "TestModel", + "brand_id": vehicle_brand.id, + } + ) + cls.vehicle_category = cls.env["fleet.vehicle.category"].create( + { + "name": "Test Category", + "analytic_account_id": analytic_account_vehicle.id, + } + ) + cls.vehicle = cls.env["fleet.vehicle"].create( + { + "name": "Test Vehicle", + "model_id": vehicle_model.id, + "vehicle_category_id": cls.vehicle_category.id, + "license_plate": "TEST-001", + } + ) + + # Helpers + def _create_vendor_bill(self, vehicle=None, analytic_distribution=None): + """Return a draft vendor bill with one product line.""" + line_vals = { + "name": "Test vehicle", + "account_id": self.company_data["default_account_expense"].id, + "quantity": 1, + "price_unit": 100.0, + "analytic_distribution": {self.other_key: 100}, + } + if vehicle: + line_vals["vehicle_id"] = vehicle.id + if analytic_distribution: + line_vals["analytic_distribution"] |= analytic_distribution + move = self.env["account.move"].create( + { + "move_type": "in_invoice", + "partner_id": self.partner_a.id, + "invoice_line_ids": [Command.create(line_vals)], + } + ) + line = move.invoice_line_ids[0] + if vehicle: + # we need to force-compute: since we give 'analytic_distribution' at + # line creation, _compute method is not called + line._compute_analytic_distribution() + return line + + # ====== Test cases =====# + def test_analytic_cascading_from_vehicle_category(self): + """Analytic should cascade from vehicle category to account move line + without overwritten existing analytic distribution + """ + line = self._create_vendor_bill(vehicle=self.vehicle) + self.assertIn(self.vehicle_key, line.analytic_distribution) + self.assertIn(self.other_key, line.analytic_distribution) + + def test_not_overwritten(self): + """If the category account is already in the distribution (e.g. set + manually), its percentage should not be overwritten""" + line = self._create_vendor_bill( + vehicle=self.vehicle, + analytic_distribution={self.vehicle_key: 50}, + ) + self.assertEqual(line.analytic_distribution.get(self.vehicle_key), 50) + + def test_without_vehicle(self): + """An account move line without a vehicle is not impacted""" + line = self._create_vendor_bill() + self.assertNotIn(self.vehicle_key, line.analytic_distribution) + self.assertIn(self.other_key, line.analytic_distribution) + + def test_without_category_analytic(self): + """A vehicle category without analytic should not modify anything""" + self.vehicle_category.analytic_account_id = False + line = self._create_vendor_bill(vehicle=self.vehicle) + self.assertIn(self.other_key, line.analytic_distribution) diff --git a/fleet_vehicle_category_analytic/views/fleet_vehicle_category_views.xml b/fleet_vehicle_category_analytic/views/fleet_vehicle_category_views.xml new file mode 100644 index 000000000..307fa5f7f --- /dev/null +++ b/fleet_vehicle_category_analytic/views/fleet_vehicle_category_views.xml @@ -0,0 +1,18 @@ + + + + + fleet.vehicle.category.form.analytic + fleet.vehicle.category + + + + + + + +