From 6a2ee7c84052ccbea13a7cb6fea228e7d4000f22 Mon Sep 17 00:00:00 2001 From: benjamin <benjamin@le-filament.com> Date: Mon, 16 Oct 2023 19:15:20 +0200 Subject: [PATCH] [MIG] refactoring & migration to 16.0 --- .copier-answers.yml | 24 + .eslintrc.yml | 11 +- .gitignore | 1 - .pre-commit-config.yaml | 51 +- .pylintrc | 39 +- .pylintrc-mandatory | 38 +- __manifest__.py | 33 +- data/cron_dashboard.xml | 15 + data/ir_module_category.xml | 12 - models/__init__.py | 1 - models/hr_employee.py | 11 - models/lefilament_tdb.py | 314 ++++-------- models/res_company.py | 19 +- security/ir.model.access.csv | 1 - security/lefilament_dashboard_security.xml | 20 +- static/src/css/lefilament_tdb.css | 91 ---- static/src/js/dashboard_overview.js | 26 + static/src/js/dashboard_year.js | 453 ----------------- static/src/js/previ_tresorerie.js | 274 ----------- static/src/js/tresorerie.js | 174 ------- static/src/xml/lefilament_tdb.xml | 277 ----------- static/src/xml/lefilament_treso.xml | 21 - templates/lefilament_dashboard.xml | 539 +++++++++++++++++++++ views/account_bank_statement_line.xml | 22 + views/account_move.xml | 59 +++ views/assets.xml | 32 -- views/lefilament_dashboard.xml | 143 ++++++ views/menus.xml | 47 ++ views/res_company.xml | 33 ++ views/schedule.xml | 21 - views/views.xml | 340 ------------- 31 files changed, 1136 insertions(+), 2006 deletions(-) create mode 100644 .copier-answers.yml create mode 100644 data/cron_dashboard.xml delete mode 100644 data/ir_module_category.xml delete mode 100644 models/hr_employee.py create mode 100644 static/src/js/dashboard_overview.js delete mode 100644 static/src/js/dashboard_year.js delete mode 100644 static/src/js/previ_tresorerie.js delete mode 100644 static/src/js/tresorerie.js delete mode 100644 static/src/xml/lefilament_tdb.xml delete mode 100644 static/src/xml/lefilament_treso.xml create mode 100644 templates/lefilament_dashboard.xml create mode 100644 views/account_bank_statement_line.xml create mode 100644 views/account_move.xml delete mode 100644 views/assets.xml create mode 100644 views/lefilament_dashboard.xml create mode 100644 views/menus.xml create mode 100644 views/res_company.xml delete mode 100644 views/schedule.xml delete mode 100644 views/views.xml diff --git a/.copier-answers.yml b/.copier-answers.yml new file mode 100644 index 0000000..c13a05f --- /dev/null +++ b/.copier-answers.yml @@ -0,0 +1,24 @@ +# Do NOT update manually; changes here will be overwritten by Copier +_commit: v1.14.2 +_src_path: https://github.com/OCA/oca-addons-repo-template.git +ci: false +dependency_installation_mode: PIP +generate_requirements_txt: false +github_check_license: false +github_ci_extra_env: {} +github_enable_codecov: false +github_enable_makepot: false +github_enable_stale_action: false +github_enforce_dev_status_compatibility: false +include_wkhtmltopdf: false +odoo_version: 16.0 +org_name: Le Filament +org_slug: lefilament +rebel_module_groups: [] +repo_description: null +repo_name: Module Template +repo_slug: template_module +repo_website: https://le-filament.com +travis_apt_packages: [] +travis_apt_sources: [] + diff --git a/.eslintrc.yml b/.eslintrc.yml index 88f2881..9429bc6 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -1,9 +1,16 @@ env: browser: true + es6: true # See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 parserOptions: - ecmaVersion: 2017 + ecmaVersion: 2019 + +overrides: + - files: + - "**/*.esm.js" + parserOptions: + sourceType: module # Globals available in Odoo that shouldn't produce errorings globals: @@ -14,7 +21,7 @@ globals: moment: readonly odoo: readonly openerp: readonly - Promise: readonly + owl: readonly # Styling is handled by Prettier, so we only need to enable AST rules; # see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890 diff --git a/.gitignore b/.gitignore index 818770f..9c283fd 100644 --- a/.gitignore +++ b/.gitignore @@ -15,7 +15,6 @@ build/ develop-eggs/ dist/ eggs/ -lib/ lib64/ parts/ sdist/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cb8b5ef..10acf1e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,7 +5,9 @@ exclude: | # Files and folders generated by bots, to avoid loops ^setup/|/static/description/index\.html$| # We don't want to mess with tool-generated files - .svg$|/tests/([^/]+/)?cassettes/| + .svg$|/tests/([^/]+/)?cassettes/|^.copier-answers.yml$|^.github/| + # Maybe reactivate this when all README files include prettier ignore tags? + ^README\.md$| # Library files can have extraneous formatting (even minimized) /static/(src/)?lib/| # Repos using Sphinx to generate docs don't need prettying @@ -14,7 +16,7 @@ exclude: | (LICENSE.*|COPYING.*) default_language_version: python: python3 - node: "14.13.0" + node: "16.17.0" repos: - repo: local hooks: @@ -25,13 +27,20 @@ repos: entry: found forbidden files; remove them language: fail files: "\\.rej$" + - id: en-po-files + name: en.po files cannot exist + entry: found a en.po file + language: fail + files: '[a-zA-Z0-9_]*/i18n/en\.po$' - repo: https://github.com/oca/maintainer-tools - rev: ab1d7f6 + rev: 4cd2b852214dead80822e93e6749b16f2785b2fe hooks: # update the NOT INSTALLABLE ADDONS section above - id: oca-update-pre-commit-excluded-addons + - id: oca-fix-manifest-website + args: ["https://le-filament.com"] - repo: https://github.com/myint/autoflake - rev: v1.4 + rev: v1.6.1 hooks: - id: autoflake args: @@ -42,22 +51,22 @@ repos: - --remove-duplicate-keys - --remove-unused-variables - repo: https://github.com/psf/black - rev: 20.8b1 + rev: 22.8.0 hooks: - id: black - repo: https://github.com/pre-commit/mirrors-prettier - rev: v2.1.2 + rev: v2.7.1 hooks: - id: prettier name: prettier (with plugin-xml) additional_dependencies: - - "prettier@2.1.2" - - "@prettier/plugin-xml@0.12.0" + - "prettier@2.7.1" + - "@prettier/plugin-xml@2.2.0" args: - --plugin=@prettier/plugin-xml files: \.(css|htm|html|js|json|jsx|less|md|scss|toml|ts|xml|yaml|yml)$ - repo: https://github.com/pre-commit/mirrors-eslint - rev: v7.8.1 + rev: v8.24.0 hooks: - id: eslint verbose: true @@ -65,7 +74,7 @@ repos: - --color - --fix - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v3.2.0 + rev: v4.3.0 hooks: - id: trailing-whitespace # exclude autogenerated files @@ -87,37 +96,33 @@ repos: - id: mixed-line-ending args: ["--fix=lf"] - repo: https://github.com/asottile/pyupgrade - rev: v2.7.2 + rev: v2.38.2 hooks: - id: pyupgrade args: ["--keep-percent-format"] - repo: https://github.com/PyCQA/isort - rev: 5.5.1 + rev: 5.12.0 hooks: - id: isort name: isort except __init__.py args: - --settings=. exclude: /__init__\.py$ - - repo: https://gitlab.com/PyCQA/flake8 - rev: 3.8.3 + - repo: https://github.com/PyCQA/flake8 + rev: 3.9.2 hooks: - id: flake8 name: flake8 - additional_dependencies: ["flake8-bugbear==20.1.4"] - - repo: https://github.com/PyCQA/pylint - rev: pylint-2.5.3 + additional_dependencies: ["flake8-bugbear==21.9.2"] + - repo: https://github.com/OCA/pylint-odoo + rev: 7.0.2 hooks: - - id: pylint + - id: pylint_odoo name: pylint with optional checks args: - --rcfile=.pylintrc - --exit-zero verbose: true - additional_dependencies: &pylint_deps - - pylint-odoo==3.5.0 - - id: pylint - name: pylint with mandatory checks + - id: pylint_odoo args: - --rcfile=.pylintrc-mandatory - additional_dependencies: *pylint_deps diff --git a/.pylintrc b/.pylintrc index c3d0a5c..71c476d 100644 --- a/.pylintrc +++ b/.pylintrc @@ -1,3 +1,5 @@ + + [MASTER] load-plugins=pylint_odoo score=n @@ -8,7 +10,7 @@ manifest_required_authors=Le Filament manifest_required_keys=license manifest_deprecated_keys=description,active license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 -valid_odoo_versions=14.0 +valid_odoo_versions=16.0 [MESSAGES CONTROL] disable=all @@ -64,6 +66,39 @@ enable=anomalous-backslash-in-string, use-vim-comment, wrong-tabs-instead-of-spaces, xml-syntax-error, + attribute-string-redundant, + character-not-valid-in-resource-link, + consider-merging-classes-inherited, + context-overridden, + create-user-wo-reset-password, + dangerous-filter-wo-user, + dangerous-qweb-replace-wo-priority, + deprecated-data-xml-node, + deprecated-openerp-xml-node, + duplicate-po-message-definition, + except-pass, + file-not-used, + invalid-commit, + manifest-maintainers-list, + missing-newline-extrafiles, + missing-readme, + missing-return, + odoo-addons-relative-import, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + renamed-field-parameter, + resource-not-exist, + str-format-used, + test-folder-imported, + translation-contains-variable, + translation-positional-used, + unnecessary-utf8-coding-comment, + website-manifest-key-not-valid-uri, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + external-request-timeout, # messages that do not cause the lint step to fail consider-merging-classes-inherited, create-user-wo-reset-password, @@ -73,7 +108,7 @@ enable=anomalous-backslash-in-string, invalid-commit, missing-manifest-dependency, missing-newline-extrafiles, - # missing-readme, + missing-readme, no-utf8-coding-comment, odoo-addons-relative-import, old-api7-method-defined, diff --git a/.pylintrc-mandatory b/.pylintrc-mandatory index 43ea239..ed2c217 100644 --- a/.pylintrc-mandatory +++ b/.pylintrc-mandatory @@ -1,3 +1,4 @@ + [MASTER] load-plugins=pylint_odoo score=n @@ -8,7 +9,7 @@ manifest_required_authors=Le Filament manifest_required_keys=license manifest_deprecated_keys=description,active license_allowed=AGPL-3,GPL-2,GPL-2 or any later version,GPL-3,GPL-3 or any later version,LGPL-3 -valid_odoo_versions=14.0 +valid_odoo_versions=16.0 [MESSAGES CONTROL] disable=all @@ -56,7 +57,40 @@ enable=anomalous-backslash-in-string, unreachable, use-vim-comment, wrong-tabs-instead-of-spaces, - xml-syntax-error + xml-syntax-error, + attribute-string-redundant, + character-not-valid-in-resource-link, + consider-merging-classes-inherited, + context-overridden, + create-user-wo-reset-password, + dangerous-filter-wo-user, + dangerous-qweb-replace-wo-priority, + deprecated-data-xml-node, + deprecated-openerp-xml-node, + duplicate-po-message-definition, + except-pass, + file-not-used, + invalid-commit, + manifest-maintainers-list, + missing-newline-extrafiles, + missing-readme, + missing-return, + odoo-addons-relative-import, + old-api7-method-defined, + po-msgstr-variables, + po-syntax-error, + renamed-field-parameter, + resource-not-exist, + str-format-used, + test-folder-imported, + translation-contains-variable, + translation-positional-used, + unnecessary-utf8-coding-comment, + website-manifest-key-not-valid-uri, + xml-attribute-translatable, + xml-deprecated-qweb-directive, + xml-deprecated-tree-attribute, + external-request-timeout [REPORTS] msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg} diff --git a/__manifest__.py b/__manifest__.py index 43e10ca..7858cb8 100644 --- a/__manifest__.py +++ b/__manifest__.py @@ -1,24 +1,39 @@ # © 2021 Le Filament (<https://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - { "name": "Le Filament - Tableau de Bord", "summary": "Rapports Le Filament", "author": "Le Filament", "category": "dashboard", "website": "https://le-filament.com", - "version": "14.0.1.0.0", + "version": "16.0.1.0.0", "license": "AGPL-3", "depends": ["account", "crm", "hr_expense", "sale"], "data": [ + # security "security/lefilament_dashboard_security.xml", "security/ir.model.access.csv", - "views/assets.xml", - "views/views.xml", - "views/schedule.xml", - "data/ir_module_category.xml", - ], - "qweb": [ - "static/src/xml/*.xml", + # datas + "data/cron_dashboard.xml", + # templates + "templates/lefilament_dashboard.xml", + # views + "views/account_bank_statement_line.xml", + "views/account_move.xml", + "views/lefilament_dashboard.xml", + "views/res_company.xml", + # menus + "views/menus.xml", ], + "assets": { + "web._assets_primary_variables": [], + "web._assets_frontend_helpers": [], + "web.assets_frontend": [], + "web.assets_backend": [ + "lefilament_tdb/static/src/js/dashboard_overview.js", + "lefilament_tdb/static/src/css/lefilament_tdb.css", + ], + "web.assets_tests": [], + "web.assets_qweb": [], + }, } diff --git a/data/cron_dashboard.xml b/data/cron_dashboard.xml new file mode 100644 index 0000000..b7438ab --- /dev/null +++ b/data/cron_dashboard.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8" ?> +<odoo noupdate="1"> + <record id="ir_cron_lefilament_tdb" forcecreate="True" model="ir.cron"> + <field name="name">Tableau de Bord - Le Filament</field> + <field eval="True" name="active" /> + <field name="user_id" ref="base.user_root" /> + <field name="interval_number">1</field> + <field name="interval_type">months</field> + <field name="numbercall">-1</field> + <field name="model_id" ref="model_lefilament_dashboard" /> + <field name="nextcall">2017-01-31 23:10:00</field> + <field name="state">code</field> + <field name="code">model.cron_new_data()</field> + </record> +</odoo> diff --git a/data/ir_module_category.xml b/data/ir_module_category.xml deleted file mode 100644 index 33396ed..0000000 --- a/data/ir_module_category.xml +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<odoo> - <data> - <record model="ir.module.category" id="module_category_dashboard"> - <field name="name">Dashboard</field> - <field name="description">Show main company dashboard</field> - <field name="sequence">30</field> - </record> - </data> -</odoo> diff --git a/models/__init__.py b/models/__init__.py index f35384a..cfea7bc 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -2,4 +2,3 @@ from . import lefilament_tdb from . import res_company -from . import hr_employee diff --git a/models/hr_employee.py b/models/hr_employee.py deleted file mode 100644 index 6e4f417..0000000 --- a/models/hr_employee.py +++ /dev/null @@ -1,11 +0,0 @@ -# © 2019 Le Filament (<http://www.le-filament.com>) -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -from odoo import fields, models - - -class HrEmployeeBase(models.AbstractModel): - _name = "hr.employee.base" - _inherit = "hr.employee.base" - - capital = fields.Float("Apport Capital Social", groups="hr.group_hr_user") diff --git a/models/lefilament_tdb.py b/models/lefilament_tdb.py index b70cbae..50419e2 100644 --- a/models/lefilament_tdb.py +++ b/models/lefilament_tdb.py @@ -1,12 +1,11 @@ # © 2019 Le Filament (<http://www.le-filament.com>) # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -from datetime import date, datetime +from datetime import date from dateutil.relativedelta import relativedelta from odoo import api, fields, models -from odoo.fields import Date class LeFilamentTdb(models.Model): @@ -16,7 +15,7 @@ class LeFilamentTdb(models.Model): name = fields.Char("Mois", compute="_compute_get_month", store=True) date_tdb = fields.Date( - "Date", required=True, default=Date.context_today, store=True + string="Date", required=True, default=lambda d: fields.Date.today(), store=True ) ca_mois = fields.Float("Facturé", compute="_compute_dashboard_values", store=True) cmd_mois = fields.Float( @@ -24,14 +23,15 @@ class LeFilamentTdb(models.Model): ) pipe_mois = fields.Float("Pipe", compute="_compute_dashboard_values", store=True) treso = fields.Float("Trésorerie", compute="_compute_dashboard_values", store=True) - variation = fields.Float( - "Variation", compute="_compute_dashboard_values", store=True - ) + variation = fields.Float(compute="_compute_dashboard_values", store=True) charges = fields.Float("Décaissé", compute="_compute_dashboard_values", store=True) encaisse = fields.Float("Encaissé", compute="_compute_dashboard_values", store=True) - charges_fixes = fields.Float("Charges Fixes", default=10000) - runway = fields.Float("Runway", compute="_compute_runway_value") + charges_fixes = fields.Float(default=10000) + runway = fields.Float(compute="_compute_runway_value") + # ------------------------------------------------------ + # Compute function + # ------------------------------------------------------ @api.depends("date_tdb") def _compute_dashboard_values(self): for record in self: @@ -143,10 +143,16 @@ class LeFilamentTdb(models.Model): months[record.date_tdb.month - 1] + " " + str(record.date_tdb.year) ) + # ------------------------------------------------------ + # CRON function + # ------------------------------------------------------ @api.model - def _new_data(self): - self.create({"date_tdb": Date.today()}) + def cron_new_data(self): + self.create({"date_tdb": fields.Date.today()}) + # ------------------------------------------------------ + # Business function + # ------------------------------------------------------ def get_month_values(self): for data in self: data._compute_dashboard_values() @@ -154,70 +160,53 @@ class LeFilamentTdb(models.Model): @api.model def retrieve_datas_dashboard(self): # Get fiscal years - fiscal_date = datetime( - datetime.now().year, + fiscal_date = date( + date.today().year, int(self.env.company.fiscalyear_last_month), int(self.env.company.fiscalyear_last_day), ) - if datetime.now() > fiscal_date: - fiscal_year = "'" + Date.to_string(fiscal_date) + "'" - fiscal_year_next = ( - "'" + Date.to_string(fiscal_date + relativedelta(years=1)) + "'" - ) + if date.today() > fiscal_date: + fiscal_year = fiscal_date + fiscal_year_next = fiscal_date + relativedelta(years=1) else: - fiscal_year = ( - "'" + Date.to_string(fiscal_date - relativedelta(years=1)) + "'" - ) - fiscal_year_next = "'" + Date.to_string(fiscal_date) + "'" + fiscal_year = fiscal_date - relativedelta(years=1) + fiscal_year_next = fiscal_date res = {} res["fiscal_year"] = fiscal_year res["fiscal_year_next"] = fiscal_year_next - res["target"] = self.env.user.company_id.ca_target - - res["facture"] = sum( - self.env["account.move"] - .search( - [ - ("move_type", "in", ("out_invoice", "out_refund")), - ("state", "=", "posted"), - ("invoice_date", ">", fiscal_year), - ("invoice_date", "<=", fiscal_year_next), - ] - ) - .mapped("amount_untaxed_signed") + res["target"] = self.env.company.ca_target + # Invoices + res["invoice_ids"] = self.env["account.move"].search( + [ + ("move_type", "in", ("out_invoice", "out_refund")), + ("state", "=", "posted"), + ("invoice_date", ">", fiscal_year), + ("invoice_date", "<=", fiscal_year_next), + ] ) - - res["commandes"] = sum( - self.env["sale.order.line"] - .search( - [ - ("invoice_status", "=", "to invoice"), - ] - ) - .mapped("untaxed_amount_to_invoice") + # Orders + res["order_line_ids"] = self.env["sale.order.line"].search( + [ + ("invoice_status", "=", "to invoice"), + ] ) - - res["pipe"] = sum( - self.env["crm.lead"] - .search( - [ - "|", - ("date_deadline", "<=", fiscal_year_next), - ("date_deadline", "=", False), - ] - ) - .mapped(lambda l: l.expected_revenue * l.probability / 100) + # Opportunities + res["lead_ids"] = self.env["crm.lead"].search( + [ + "|", + ("date_deadline", ">", fiscal_year_next), + ("date_deadline", "=", False), + ] ) - res["pipe_n1"] = sum( - self.env["crm.lead"] - .search( - [ - ("date_deadline", ">", fiscal_year_next), - ] - ) - .mapped(lambda l: l.expected_revenue * l.probability / 100) + + res["progress"] = ( + sum(res["invoice_ids"].mapped("amount_untaxed_signed")) + / self.env.company.ca_target + if self.env.company.ca_target + else 0 ) + res["pipe_win"] = sum( self.env["crm.lead"] .search( @@ -243,190 +232,51 @@ class LeFilamentTdb(models.Model): .mapped(lambda l: l.expected_revenue * l.probability / 100) ) - res["a_encaisser"] = sum( - self.env["account.move"] - .search( - [ - ("move_type", "in", ("out_invoice", "out_refund")), - ("state", "=", "posted"), - ("payment_state", "!=", "paid"), - ] - ) - .mapped("amount_residual_signed") + res["to_get"] = self.env["account.move"].search( + [ + ("move_type", "in", ("out_invoice", "out_refund")), + ("state", "=", "posted"), + ("payment_state", "!=", "paid"), + ] ) - res["a_payer"] = sum( - self.env["account.move"] - .search( - [ - ("move_type", "in", ("in_invoice", "in_refund")), - ("state", "=", "posted"), - ("payment_state", "!=", "paid"), - ] - ) - .mapped("amount_residual_signed") + res["to_pay"] = self.env["account.move"].search( + [ + ("move_type", "in", ("in_invoice", "in_refund")), + ("state", "=", "posted"), + ("payment_state", "!=", "paid"), + ] ) res["date_maj"] = ( - self.env["account.bank.statement"] + self.env["account.bank.statement.line"] .search([], order="date desc", limit=1) .date ) - res["tresorerie"] = sum( - self.env["account.bank.statement.line"].search([]).mapped("amount") - ) - res["treso_by_bank"] = self.env["account.bank.statement.line"].read_group( + res["statement_line_ids"] = self.env["account.bank.statement.line"].search([]) + res["cash_by_bank"] = self.env["account.bank.statement.line"].read_group( domain=[], fields=["journal_id", "amount"], groupby=["journal_id"], orderby="journal_id", ) - res["entree"] = sum( - self.env["account.bank.statement.line"] - .search( - [ - ("amount", ">", 0), - ("date", ">", fiscal_year), - ] - ) - .mapped("amount") - ) - res["sortie"] = sum( - self.env["account.bank.statement.line"] - .search( - [ - ("amount", "<", 0), - ("date", ">", fiscal_year), - ] - ) - .mapped("amount") - ) - res["variation"] = sum( - self.env["account.bank.statement.line"] - .search( - [ - ("date", ">", fiscal_year), - ] - ) - .mapped("amount") - ) - return res - - @api.model - def tresorerie(self): - self._cr.execute( - """ - SELECT to_char(date_trunc('month', date),'YYYY-MM') AS mois, - SUM(CASE WHEN amount > 0 - THEN amount ELSE 0 END) AS entree, - SUM(CASE WHEN amount < 0 - THEN amount ELSE 0 END) AS sortie, - SUM(amount) AS variation - FROM account_bank_statement_line - GROUP BY date_trunc('month', date) - ORDER BY date_trunc('month', date); - """ - ) - tresorerie = self._cr.dictfetchall() - - self._cr.execute( - """ - SELECT - (SELECT SUM(e.total_amount) AS fonds_propres - FROM hr_expense_sheet es, hr_expense e - WHERE es.id = e.sheet_id - AND e.payment_mode = 'own_account' - AND es.state != 'done' - ) AS cca, - (SELECT SUM(capital) AS capital FROM hr_employee) AS capital; - """ - ) - fonds_propres = self._cr.dictfetchall()[0] - - if not fonds_propres["cca"]: - fonds_propres["cca"] = 0 - - return {"tresorerie": tresorerie, "fonds_propres": fonds_propres} - - @api.model - def previ_tresorerie(self): - self._cr.execute( - """ - SELECT to_char(date_trunc('month', date),'YYYY-MM') AS mois, - SUM(SUM(amount)) OVER ( - ORDER BY date_trunc('month', date) - ) AS treso - FROM account_bank_statement_line - GROUP BY date_trunc('month', date) - ORDER BY date_trunc('month', date) DESC LIMIT 6; - """ - ) - tresorerie = self._cr.dictfetchall() - - self._cr.execute( - """ - SELECT - (SELECT SUM(e.total_amount) AS fonds_propres - FROM hr_expense_sheet es, hr_expense e - WHERE es.id = e.sheet_id - AND e.payment_mode = 'own_account' - AND es.state != 'done' - ) as cca, - (SELECT SUM(capital) AS capital FROM hr_employee) AS capital; - """ - ) - fonds_propres = self._cr.dictfetchall()[0] - - self._cr.execute( - """ - SELECT to_char(date_trunc('month', invoice_date_due),'YYYY-MM') AS mois, - SUM(CASE WHEN move_type = 'in_invoice' - THEN amount_residual_signed - ELSE 0 END - ) AS f_fournisseur, - SUM(CASE WHEN move_type = 'out_invoice' - THEN amount_residual_signed - ELSE 0 END - ) AS f_client - FROM account_move - WHERE state = 'posted' - AND payment_state IN ('not_paid','in_payment','partial') - GROUP BY date_trunc('month', invoice_date_due) - ORDER BY date_trunc('month', invoice_date_due); - """ + res["in"] = self.env["account.bank.statement.line"].search( + [ + ("amount", ">", 0), + ("date", ">", fiscal_year), + ] ) - factures = self._cr.dictfetchall() - - self._cr.execute( - """ - SELECT periode, - SUM(montant) - FROM previ_treso - WHERE periode != '1' - GROUP BY periode - ORDER BY periode; - """ + res["out"] = self.env["account.bank.statement.line"].search( + [ + ("amount", "<", 0), + ("date", ">", fiscal_year), + ] ) - charges_periode = self._cr.dictfetchall() - - self._cr.execute( - """ - SELECT to_char(date_trunc('month', date), 'YYYY-MM') as mois, - SUM(montant) - FROM previ_treso - WHERE periode = '1' - GROUP BY date_trunc('month', date); - """ + res["variation"] = self.env["account.bank.statement.line"].search( + [ + ("date", ">", fiscal_year), + ] ) - charges_fixes = self._cr.dictfetchall() + res["company_id"] = self.env.company - if not fonds_propres["cca"]: - fonds_propres["cca"] = 0 - - return { - "tresorerie": tresorerie, - "fonds_propres": fonds_propres, - "factures": factures, - "charges_fixes": charges_fixes, - "charges_periode": charges_periode, - } + return res diff --git a/models/res_company.py b/models/res_company.py index b89844e..1268209 100644 --- a/models/res_company.py +++ b/models/res_company.py @@ -8,21 +8,4 @@ class ResCompany(models.Model): _inherit = "res.company" ca_target = fields.Integer("Objectif Chiffre d'Affaire") - charges_fixes = fields.Integer("Charges Fixes") - previ_treso_ids = fields.One2many("previ.treso", "company_id", "Prévisionnel") - - -class PreviTreso(models.Model): - _name = "previ.treso" - _description = "Previsionnel de tresorerie" - _order = "name" - - company_id = fields.Many2one( - "res.company", "Company", default=lambda self: self.env.user.company.id - ) - name = fields.Char("Nom") - periode = fields.Selection( - [("12", "Mensuel"), ("3", "Trimestriel"), ("1", "Annuel")], string="Période" - ) - date = fields.Date("Date") - montant = fields.Float("Montant") + charges_fixes = fields.Integer() diff --git a/security/ir.model.access.csv b/security/ir.model.access.csv index a1c24a1..95140ba 100644 --- a/security/ir.model.access.csv +++ b/security/ir.model.access.csv @@ -1,3 +1,2 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_lefilament_dashboard_group_dashboard,lefilament.dashboard.user,model_lefilament_dashboard,group_dashboard,1,1,1,1 -access_previ_treso_group_erp_manager,previ.treso.user,model_previ_treso,base.group_erp_manager,1,1,1,1 diff --git a/security/lefilament_dashboard_security.xml b/security/lefilament_dashboard_security.xml index a305afe..dc92cd8 100644 --- a/security/lefilament_dashboard_security.xml +++ b/security/lefilament_dashboard_security.xml @@ -1,15 +1,17 @@ <?xml version="1.0" encoding="utf-8" ?> <!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<odoo> - <data noupdate="0"> +<odoo noupdate="0"> + <record model="ir.module.category" id="module_category_dashboard"> + <field name="name">Dashboard</field> + <field name="description">Show main company dashboard</field> + <field name="sequence">30</field> + </record> <!-- Définition des groupes utilisateurs --> - <record id="group_dashboard" model="res.groups"> - <field name="name">Voir les tableaux de bord</field> - <field name="category_id" ref="base.module_category_dashboard" /> - <field name="implied_ids" eval="[(4, ref('base.group_user'))]" /> - </record> - - </data> + <record id="group_dashboard" model="res.groups"> + <field name="name">Voir les tableaux de bord</field> + <field name="category_id" ref="lefilament_tdb.module_category_dashboard" /> + <field name="implied_ids" eval="[(4, ref('base.group_user'))]" /> + </record> </odoo> diff --git a/static/src/css/lefilament_tdb.css b/static/src/css/lefilament_tdb.css index c83a455..774b23c 100644 --- a/static/src/css/lefilament_tdb.css +++ b/static/src/css/lefilament_tdb.css @@ -1,95 +1,9 @@ -.positive { - color: #2ecc71; -} -.negative { - color: #e74c3c; -} - -.yeardashboard { - padding: 20px; - min-height: 100%; - max-width: 1600px; - margin: 0 auto; -} - -.yeardashboard h3 { - margin: 10px 0px; - font-size: 20px; - font-weight: 400; - border-bottom: 1px solid #ddd; - color: #5e6975; -} - -.card { - margin: 10px 0; -} -.card-body { - color: #73879c; -} -.card a { - color: inherit; -} -.card-number a { - color: #73879c; -} -.card-half { - float: left; - width: 50%; -} - p.card-maj { - margin: 0px; font-size: 10px; font-style: italic; font-weight: 300; } -.card-number { - font-size: 30px; - font-weight: 300; - margin: 0 !important; - font-family: "Helvetica Neue", Helvetica, "Open Sans", Arial, sans-serif; -} -.card-tab { - background-color: #fff; - color: #73879c; - padding: 20px; - margin: 0px 0 10px; - border-left: 1px solid rgba(0, 0, 0, 0.125); - border-right: 1px solid rgba(0, 0, 0, 0.125); - border-bottom: 1px solid rgba(0, 0, 0, 0.125); -} -.tresorerie .card-number { - font-size: 20px; - font-weight: 300; -} - -.card.card-cca { - -webkit-flex-direction: row; - flex-direction: row; -} -.card-cca-half { - width: 50%; -} - -#commandes, -#facture_non_encaisse, -#pipe, -#facture, -#fournisseur, -#statement_lines, -#releve { - cursor: pointer; -} - -.ca_target { - font-size: 18px; -} - -/* ProgressBar */ -canvas { - width: 100%; -} /* Legende ProgressBar */ .table-legend { width: 100%; @@ -108,8 +22,3 @@ canvas { font-weight: 700; padding: 2px 0; } - -#by-bank table td { - color: #73879c; - font-family: "Helvetica Neue", Helvetica, "Open Sans", Arial, sans-serif; -} diff --git a/static/src/js/dashboard_overview.js b/static/src/js/dashboard_overview.js new file mode 100644 index 0000000..e89bf86 --- /dev/null +++ b/static/src/js/dashboard_overview.js @@ -0,0 +1,26 @@ +odoo.define("lefilament_tdb.dashboard_overview", function (require) { + "use strict"; + + const qweb = require("web.qweb"); + const viewRegistry = require("web.view_registry"); + + const Controller = qweb.Controller.extend({ + events: _.extend({}, qweb.Controller.prototype.events, { + "click #update_view": "_onClickUpdateView", + }), + + _onClickUpdateView() { + this.reload(); + }, + }); + + const DashboardOverview = qweb.View.extend({ + withSearchBar: false, + searchMenuTypes: [], + config: _.extend({}, qweb.View.prototype.config, { + Controller: Controller, + }), + }); + + viewRegistry.add("dashboard_overview", DashboardOverview); +}); diff --git a/static/src/js/dashboard_year.js b/static/src/js/dashboard_year.js deleted file mode 100644 index 82b69e7..0000000 --- a/static/src/js/dashboard_year.js +++ /dev/null @@ -1,453 +0,0 @@ -// © 2019 Le Filament (<http://www.le-filament.com>) -// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -odoo.define("lefilament_tdb.dashboard_year", function (require) { - "use strict"; - - var core = require("web.core"); - var session = require("web.session"); - var AbstractAction = require("web.AbstractAction"); - - var YearDashboardView = AbstractAction.extend({ - template: "YearDashboard", - jsLibs: ["/web/static/lib/Chart/Chart.js"], - events: { - "click #facture": function (e) { - var fiscalyear = e.target.dataset.fiscalyear; - this.facture(fiscalyear); - }, - "click #facture_non_encaisse": function () { - this.facture_non_encaisse(); - }, - "click #commandes": function () { - this.commandes(); - }, - "click #pipe_link": function (e) { - var fiscalyearnext = e.target.dataset.fiscalyearnext; - this.pipe(fiscalyearnext); - }, - "click #pipe_n1_link": function (e) { - var fiscalyearnext = e.target.dataset.fiscalyearnext; - this.pipe_n1(fiscalyearnext); - }, - "click #fournisseur_link": function () { - this.fournisseur(); - }, - "click #releve": function () { - this.releve(); - }, - "click #statement_lines": function () { - this.statement_lines(); - }, - }, - - init: function () { - var result = this._super.apply(this, arguments); - return result; - }, - - willStart: function () { - var deferred = new jQuery.Deferred(); - var self = this; - this.values = {}; - this.progess = 0; - - this._rpc({ - model: "ir.model.data", - method: "xmlid_to_res_id", - args: ["account.view_invoice_form"], - }).then(function (results) { - self.invoice_view_id = results; - }); - - this._rpc({ - model: "ir.model.data", - method: "xmlid_to_res_id", - args: ["lefilament_tdb.view_invoice_tree"], - }).then(function (results) { - self.invoice_tree_id = results; - }); - - this._rpc({ - model: "ir.model.data", - method: "xmlid_to_res_id", - args: ["crm.crm_case_form_view_oppor"], - }).then(function (results) { - self.pipe_view_id = results; - }); - - this._rpc({ - model: "lefilament.dashboard", - method: "retrieve_datas_dashboard", - args: [], - }).then(function (results) { - self.values = results; - - self.pfact2 = self.values.facture; - self.pcomm2 = self.values.commandes; - self.ppipe2_win = self.values.pipe_win; - self.ppipe2_to_win = self.values.pipe_to_win; - - if (self.values.target > 0) { - self.pfact = ( - (self.values.facture / self.values.target) * - 100 - ).toFixed(0); - self.pcomm = ( - (self.values.commandes / self.values.target) * - 100 - ).toFixed(0); - self.ppipe_win = ( - (self.values.pipe_win / self.values.target) * - 100 - ).toFixed(0); - self.ppipe_to_win = ( - (self.values.pipe_to_win / self.values.target) * - 100 - ).toFixed(0); - self.ptarg = 100 - self.pfact; - self.ptarg2 = self.values.target - self.pfact2; - self.total = ( - ((self.values.facture + - self.values.commandes + - self.values.pipe_win) / - self.values.target) * - 100 - ).toFixed(0); - } else { - self.pfact = "n/a"; - self.pcomm = "n/a"; - self.ppipe_win = "n/a"; - self.ppipe_to_win = "n/a"; - self.ptarg = "n/a"; - self.ptarg2 = "n/a"; - self.total = "n/a"; - } - - self.total2 = self.pfact2 + self.pcomm2 + self.ppipe2_win; - - self.yeartarget = self.values.target; - - deferred.resolve(); - }); - return jQuery.when(this._super.apply(this, arguments), deferred); - }, - - start: function () { - return this.render_chart(); - }, - - render_chart: function () { - // /////////////////////////////////////// - // Etat d'avancement -> Bar Chart // - // /////////////////////////////////////// - - this.ctx = this.$el.find("#target")[0].getContext("2d"); - - var yeartarget = this.yeartarget; - var ptarg = this.ptarg; - var max_xaxis = 100; - - if (this.ptarg < 0) { - ptarg = 0; - max_xaxis = 100 - this.ptarg; - } - - var dataset_stacked = [ - {label: "Facturé", data: [this.pfact], backgroundColor: "#8ED8A2"}, - {label: "À facturer", data: [ptarg], backgroundColor: "#eee"}, - ]; - - var label = "Année " + moment(Date.now()).format("YYYY"); - - this.targetData = { - labels: [label], - datasets: dataset_stacked, - }; - - var options = { - responsive: true, - legend: { - display: false, - }, - layout: { - padding: {left: 0, right: 0, bottom: 20, top: 20}, - }, - scales: { - xAxes: [ - { - stacked: true, - scaleShowLabels: false, - display: true, - ticks: { - max: max_xaxis, - stepSize: 25, - fontSize: 9, - fontColor: "#999", - callback: function (value) { - return value + "%"; - }, - }, - gridLines: { - zeroLineColor: "rgba(0, 0, 0, 0.1)", - drawBorder: false, - tickMarkLength: 2, - }, - }, - ], - yAxes: [ - { - stacked: true, - scaleShowLabels: false, - display: false, - }, - ], - }, - tooltips: { - backgroundColor: "rgba(255,255,255,0.8)", - titleFontStyle: "normal", - titleFontColor: "#999", - bodyFontColor: "#777", - callbacks: { - label: function (tooltipItems, data) { - return ( - ( - (tooltipItems.xLabel * yeartarget) / - 100000 - ).toLocaleString("fr", {maximumFractionDigits: 2}) + - " K€" - ); - }, - }, - }, - }; - - this.chart = new Chart(this.ctx, { - type: "horizontalBar", - data: this.targetData, - options, - }); - }, - - render_monetary: function (value) { - var res = value.toLocaleString("fr", {maximumFractionDigits: 0}) + " €"; - return res; - }, - render_monetary_decimal: function (value) { - var res = value.toLocaleString("fr", {maximumFractionDigits: 2}) + " €"; - return res; - }, - render_keur: function (value) { - var res = - (value / 1000).toLocaleString("fr", {maximumFractionDigits: 0}) + " K€"; - return res; - }, - render_percent: function (value) { - var res = value.toLocaleString("fr", {maximumFractionDigits: 1}) + " %"; - return res; - }, - render_date: function (value) { - var dateFormat = new Date(value); - var res = moment(dateFormat).format("Do MMM YYYY"); - return res; - }, - render_monetary_color: function (value) { - if (value >= 0) - var res = - '<span class="positive">' + - value.toLocaleString("fr", {maximumFractionDigits: 0}) + - " €</span>"; - else - var res = - '<span class="negative">' + - value.toLocaleString("fr", {maximumFractionDigits: 0}) + - " €</span>"; - - return res; - }, - - facture: function (fiscalyear) { - var self = this; - var context = { - user_id: session.uid, - search_default_posted: 1, - }; - var action = { - type: "ir.actions.act_window", - res_model: "account.move", - view_mode: "tree,pivot,graph,form", - views: [ - [self.invoice_tree_id, "list"], - [false, "pivot"], - [false, "graph"], - [self.invoice_view_id, "form"], - ], - domain: [ - ["move_type", "in", ["out_invoice", "out_refund"]], - ["invoice_date", ">=", fiscalyear], - ], - target: "current", - name: "Facturé", - context: context, - }; - this.do_action(action); - }, - commandes: function () { - var context = {user_id: session.uid}; - - var action = { - type: "ir.actions.act_window", - res_model: "sale.order", - view_mode: "tree,form", - views: [ - [false, "list"], - [false, "form"], - ], - domain: [["invoice_status", "=", "to invoice"]], - target: "current", - name: "Commandes en cours", - context: context, - }; - - this.do_action(action); - }, - pipe: function (fiscalyearnext) { - var context = {user_id: session.uid}; - - var action = { - type: "ir.actions.act_window", - res_model: "crm.lead", - view_mode: "tree,form", - views: [ - [false, "kanban"], - [false, "list"], - [this.pipe_view_id, "form"], - ], - domain: [ - "|", - ["date_deadline", "<=", fiscalyearnext], - ["date_deadline", "=", null], - ["type", "=", "opportunity"], - ], - target: "current", - name: "Pipe", - context: context, - }; - - this.do_action(action); - }, - pipe_n1: function (fiscalyearnext) { - var context = {user_id: session.uid}; - - var action = { - type: "ir.actions.act_window", - res_model: "crm.lead", - view_mode: "kanban,tree,form", - views: [ - [false, "kanban"], - [false, "list"], - [this.pipe_view_id, "form"], - ], - domain: [ - ["type", "=", "opportunity"], - ["date_deadline", ">", fiscalyearnext], - ], - target: "current", - name: "Pipe", - context: context, - }; - - this.do_action(action); - }, - facture_non_encaisse: function () { - var self = this; - var context = {user_id: session.uid}; - - var action = { - type: "ir.actions.act_window", - res_model: "account.move", - view_mode: "tree,pivot,graph,form", - views: [ - [self.invoice_tree_id, "list"], - [false, "pivot"], - [false, "graph"], - [self.invoice_view_id, "form"], - ], - domain: [ - ["state", "=", "posted"], - ["payment_state", "in", ["not_paid", "in_payment", "partial"]], - ["move_type", "=", "out_invoice"], - ], - target: "current", - name: "Factures en cours", - context: context, - }; - console.log(action); - this.do_action(action); - }, - fournisseur: function () { - var self = this; - var context = {user_id: session.uid}; - - var action = { - type: "ir.actions.act_window", - res_model: "account.move", - view_mode: "tree,form", - views: [ - [self.invoice_tree_id, "list"], - [false, "form"], - ], - domain: [ - ["state", "=", "posted"], - ["payment_state", "in", ["not_paid", "in_payment", "partial"]], - ["move_type", "=", "in_invoice"], - ], - target: "current", - name: "Factures fournisseurs en cours", - context: context, - }; - - this.do_action(action); - }, - releve: function () { - var context = {user_id: session.uid}; - - var action = { - type: "ir.actions.act_window", - res_model: "account.bank.statement", - view_mode: "tree,form", - views: [ - [false, "list"], - [false, "form"], - ], - target: "current", - name: "Relevés en cours", - context: context, - }; - - this.do_action(action); - }, - statement_lines: function () { - var context = {user_id: session.uid}; - - var action = { - type: "ir.actions.act_window", - res_model: "account.bank.statement.line", - view_mode: "tree,pivot,graph,form", - views: [ - [false, "list"], - [false, "pivot"], - [false, "graph"], - [false, "form"], - ], - target: "current", - name: "Lignes de banque", - context: context, - }; - - this.do_action(action); - }, - }); - - core.action_registry.add("lefilament_tdb.dashboard_year", YearDashboardView); -}); diff --git a/static/src/js/previ_tresorerie.js b/static/src/js/previ_tresorerie.js deleted file mode 100644 index 3cd0838..0000000 --- a/static/src/js/previ_tresorerie.js +++ /dev/null @@ -1,274 +0,0 @@ -// © 2017 Le Filament (<http://www.le-filament.com>) -// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -odoo.define("lefilament_tdb.previ_tresorerie", function (require) { - "use strict"; - - var core = require("web.core"); - var AbstractAction = require("web.AbstractAction"); - - var TresorerieView = AbstractAction.extend({ - template: "Tresorerie", - jsLibs: ["/web/static/lib/Chart/Chart.js"], - - init: function () { - var result = this._super.apply(this, arguments); - return result; - }, - - willStart: function () { - var deferred = new jQuery.Deferred(); - var self = this; - this.values = {}; - - this._rpc({ - model: "lefilament.dashboard", - method: "previ_tresorerie", - args: [], - }).then(function (results) { - self.values = results; - deferred.resolve(); - }); - return jQuery.when(this._super.apply(this, arguments), deferred); - }, - - start: function () { - return this.render_chart(); - }, - - render_chart: function () { - // /////////////////////////////////////// - // Trésorerie -> Bar Chart // - // /////////////////////////////////////// - this.ctx = this.$el.find("#tresorerie")[0].getContext("2d"); - - var labels = []; - var data_months = []; - var data_year = []; - var month = moment().month(); - for (var i = -5; i < 7; i++) { - labels.push( - moment() - .month(month + i) - .format("MMM YYYY") - ); - data_months.push( - moment() - .month(month + i) - .format("MM") - ); - data_year.push( - moment() - .month(month + i) - .format("YYYY-MM") - ); - } - var treso_r = this.reverse_array(this.values.tresorerie); - var treso_r_length = treso_r.length; - - if (treso_r_length < 7) { - for (var j = 0; j < 6 - treso_r_length; j++) { - treso_r.unshift({treso: null}); - } - } - - var treso = []; - var cca = []; - var fonds_propres = []; - - var charges_an = 0; - var charges_fixes_an = []; - var charges_fixes = []; - - var client = 0; - var f_client = []; - var fournisseur = 0; - var f_fournisseur = []; - - var previsionnel = []; - - for (var k = 0; k < 12; k++) { - // CCA + Fonds Propres - cca.push(this.values.fonds_propres.cca); - fonds_propres.push( - this.values.fonds_propres.cca + this.values.fonds_propres.capital - ); - - // Trésorerie - if (treso_r[k]) { - treso.push(treso_r[k].treso); - } - - console.log(treso_r); - console.log(this.values.charges_periode); - - // Calcul des factures - _.each(this.values.factures, function (value) { - if (value.mois === data_year[k]) { - client = value.f_client; - fournisseur = value.f_fournisseur; - } - }); - if (client !== 0) { - f_client.push(client); - client = 0; - } else { - f_client.push(0); - } - if (fournisseur !== 0) { - f_fournisseur.push(fournisseur); - fournisseur = 0; - } else { - f_fournisseur.push(0); - } - - // Calcul des fixes annuelles - _.each(this.values.charges_fixes, function (value) { - if (value.mois === data_year[k]) { - charges_an = value.sum; - } - }); - if (charges_an !== 0) { - charges_fixes_an.push(charges_an); - charges_an = 0; - } else { - charges_fixes_an.push(0); - } - - // Calcul charges fixes - if (k < 5) { - charges_fixes.push(null); - } else if (k === 5) { - charges_fixes.push(treso_r[5].treso); - } else { - // Trimestres - if (this.values.charges_periode.length > 0) { - if (["01", "04", "07", "10"].indexOf(data_months[k]) >= 0) { - charges_fixes.push( - this.values.charges_periode[0].sum + - this.values.charges_periode[1].sum - ); - } else { - charges_fixes.push(this.values.charges_periode[1].sum); - } - } else { - charges_fixes.push(null); - } - } - } - - for (var l = 0; l < 12; l++) { - if (l > 4) { - previsionnel.push( - previsionnel[l - 1] + - charges_fixes[l] + - f_client[l] - - f_fournisseur[l] + - charges_fixes_an[l] - ); - } else { - previsionnel.push(null); - } - } - - var datasets = [ - { - label: "Trésorerie", - data: treso, - backgroundColor: "rgba(94, 142, 213, 0.08)", - borderColor: "#5E8ED5", - }, - { - label: "Prévisionnel", - data: previsionnel, - backgroundColor: "transparent", - borderColor: "rgba(94,142,213,0.6)", - borderDash: [5, 5], - }, - { - label: "Client", - data: f_client, - backgroundColor: "transparent", - borderColor: "#51d2b7", - borderWidth: 1.5, - radius: 1, - }, - { - label: "Fournisseur", - data: f_fournisseur, - backgroundColor: "transparent", - borderColor: "#FCA7B3", - borderWidth: 1.5, - radius: 1, - }, - { - label: "CCA", - data: cca, - backgroundColor: "transparent", - borderColor: "#FFDFA9", - borderWidth: 1.5, - radius: 0, - }, - { - label: "Fonds Propres", - data: fonds_propres, - backgroundColor: "transparent", - borderColor: "#A2BFEA", - borderWidth: 1.5, - radius: 0, - }, - ]; - - var options = { - scales: { - yAxes: [ - { - ticks: { - beginAtZero: true, - }, - }, - ], - }, - tooltips: { - backgroundColor: "rgba(255,255,255,0.8)", - titleFontStyle: "normal", - titleFontColor: "#999", - bodyFontColor: "#777", - callbacks: { - label: function (tooltipItems) { - return ( - " " + - (tooltipItems.yLabel / 1000).toLocaleString("fr", { - maximumFractionDigits: 1, - }) + - " k€" - ); - }, - }, - }, - responsive: true, - }; - - this.targetData = { - labels: labels, - datasets: datasets, - }; - - this.chart = new Chart(this.ctx, { - type: "line", - data: this.targetData, - options: options, - }); - }, - reverse_array: function (array) { - var tabLength = array.length - 1; - var new_array = []; - for (var m = tabLength; m > -1; m--) { - new_array.push(array[m]); - } - return new_array; - }, - }); - - core.action_registry.add("lefilament_tdb.previ_tresorerie", TresorerieView); -}); diff --git a/static/src/js/tresorerie.js b/static/src/js/tresorerie.js deleted file mode 100644 index a1f6d78..0000000 --- a/static/src/js/tresorerie.js +++ /dev/null @@ -1,174 +0,0 @@ -// © 2019 Le Filament (<http://www.le-filament.com>) -// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - -odoo.define("lefilament_tdb.tresorerie", function (require) { - "use strict"; - - var core = require("web.core"); - var AbstractAction = require("web.AbstractAction"); - - var TresorerieView = AbstractAction.extend({ - template: "Tresorerie", - jsLibs: ["/web/static/lib/Chart/Chart.js"], - - init: function () { - var result = this._super.apply(this, arguments); - return result; - }, - - willStart: function () { - var deferred = new jQuery.Deferred(); - var self = this; - this.values = {}; - - this._rpc({ - model: "lefilament.dashboard", - method: "tresorerie", - args: [], - }).then(function (results) { - self.values = results; - deferred.resolve(); - }); - - return jQuery.when(this._super.apply(this, arguments), deferred); - }, - - start: function () { - return this.render_chart(); - }, - - render_chart: function () { - // /////////////////////////////////////// - // Trésorerie -> Bar Chart // - // /////////////////////////////////////// - this.ctx = this.$el.find("#tresorerie")[0].getContext("2d"); - - var entree = []; - var sortie = []; - var variation = []; - var treso = []; - var cca = []; - var fonds_propres = []; - var labels = []; - var minTab = 11; - - var tabLength = this.values.tresorerie.length - 1; - - if (tabLength < 12) { - minTab = tabLength; - } - - _.each(this.values.tresorerie, function (value, key) { - if (key === 0) { - treso.push(value.variation); - } else { - var amount = treso[key - 1] + value.variation; - treso.push(amount); - } - }); - - for (var i = tabLength - minTab; i < tabLength + 1; i++) { - entree.push(this.values.tresorerie[i].entree); - sortie.push(this.values.tresorerie[i].sortie * -1); - variation.push(this.values.tresorerie[i].variation); - cca.push(this.values.fonds_propres.cca); - fonds_propres.push( - this.values.fonds_propres.cca + this.values.fonds_propres.capital - ); - labels.push(moment(this.values.tresorerie[i].mois).format("MMM YYYY")); - } - - var datasets = [ - { - label: "Trésorerie", - data: treso.slice(tabLength - 11, tabLength + 1), - backgroundColor: "transparent", - borderColor: "#5E8ED5", - }, - { - label: "CCA", - data: cca, - backgroundColor: "transparent", - borderColor: "#FFA063", - borderWidth: 1.5, - radius: 0, - }, - { - label: "Fonds Propres", - data: fonds_propres, - backgroundColor: "transparent", - borderColor: "#FCA7B3", - borderWidth: 1.5, - radius: 0, - }, - { - label: "Variation", - data: variation, - backgroundColor: "rgba(255, 197, 98, 0.3)", - borderColor: "#FFC562", - borderWidth: 1, - radius: 1, - }, - { - label: "Entrées", - data: entree, - backgroundColor: "rgba(81, 210, 183, 0.3)", - borderColor: "#51d2b7", - borderWidth: 1, - radius: 1, - }, - { - label: "Sorties", - data: sortie, - backgroundColor: "rgba(249, 96, 117, 0.3)", - borderColor: "#F96075", - borderWidth: 1, - radius: 1, - }, - ]; - - var options = { - scales: { - yAxes: [ - { - ticks: { - beginAtZero: true, - }, - }, - ], - }, - tooltips: { - backgroundColor: "rgba(255,255,255,0.8)", - titleFontStyle: "normal", - titleFontColor: "#999", - bodyFontColor: "#777", - callbacks: { - label: function (tooltipItems) { - return ( - " " + - (tooltipItems.yLabel / 1000).toLocaleString("fr", { - maximumFractionDigits: 1, - }) + - " k€" - ); - }, - }, - }, - responsive: true, - }; - - this.targetData = { - labels: labels, - datasets: datasets, - }; - - this.chart = new Chart(this.ctx, { - type: "line", - data: this.targetData, - options: options, - }); - }, - }); - - core.action_registry.add("lefilament_tdb.tresorerie", TresorerieView); -}); diff --git a/static/src/xml/lefilament_tdb.xml b/static/src/xml/lefilament_tdb.xml deleted file mode 100644 index 5c8c32e..0000000 --- a/static/src/xml/lefilament_tdb.xml +++ /dev/null @@ -1,277 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<templates xml:space="preserve"> - - <t t-name="YearDashboard"> - <div class="yeardashboard"> - <div class="row"> - <!-- COLONNE 1 --> - <div class="col-xs-12 col-sm-6 col-md-4"> - <h3>En Cours</h3> - <!-- Facturé --> - <div class="col-xs-12"> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Facturé</h5> - <p class="card-number"> - <a id="facture" t-attf-data-fiscalyear="#{widget.values.fiscal_year}"> - <t t-esc="widget.render_monetary(widget.values.facture)" /> - </a> - </p> - </div> - </div> - </div> - <!-- Commandes --> - <div class="col-xs-12"> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Commandes en cours</h5> - <p class="card-number"> - <a id="commandes"> - <t t-esc="widget.render_monetary(widget.values.commandes)" /> - </a> - </p> - </div> - </div> - </div> - <!-- Pipe --> - <div class="col-xs-12 dashboard-tab"> - <ul class="nav nav-tabs" id="myTab1"> - <li class="nav-item"> - <a class="nav-link active" data-toggle="tab" href="#pipe">Pipe</a> - </li> - <li class="nav-item"> - <a class="nav-link" data-toggle="tab" href="#pipe_n1">Pipe N+1</a> - </li> - </ul> - <div class="tab-content card-tab" id="myTab1Content"> - <div id="pipe" class="tab-pane fade show active in"> - <p class="card-number"> - <a - id="pipe_link" - t-attf-data-fiscalyearnext="#{widget.values.fiscal_year_next}" - > - <t t-esc="widget.render_monetary(widget.values.pipe)" /> - </a> - </p> - </div> - <div id="pipe_n1" class="tab-pane fade"> - <p class="card-number"> - <a - id="pipe_n1_link" - t-attf-data-fiscalyearnext="#{widget.values.fiscal_year_next}" - > - <t t-esc="widget.render_monetary(widget.values.pipe_n1)" /> - </a> - </p> - </div> - </div> - </div> - </div> - <!-- COLONNE 2 --> - <div class="col-xs-12 col-sm-6 col-md-4"> - <h3>Objectif</h3> - <div class="col-xs-12"> - <div class="card"> - <div class="card-body"> - <h5 class="card-title">Target</h5> - <p class="card-number"> - <t t-esc="widget.render_monetary(widget.values.target)" /> - </p> - <canvas id="target" width="auto" height="125" /> - <!-- <div id="hchart" ></div> --> - <table class="table-legend"> - <tr> - <td style="background-color: #8ED8A2; width: 20px;" /> - <td>Facturé</td> - <td class="nb"><t - t-esc="widget.render_percent(widget.pfact)" - /></td> - <td class="nb"><t t-esc="widget.render_keur(widget.pfact2)" /></td> - </tr> - <tr> - <td style="background-color: #F6DCA2; width: 20px;" /> - <td>Commandes</td> - <td class="nb"><t - t-esc="widget.render_percent(widget.pcomm)" - /></td> - <td class="nb"><t t-esc="widget.render_keur(widget.pcomm2)" /></td> - </tr> - <tr> - <td style="background-color: #F6CCA2; width: 20px;" /> - <td>Pipe Gagné</td> - <td class="nb"><t - t-esc="widget.render_percent(widget.ppipe_win)" - /></td> - <td class="nb"><t - t-esc="widget.render_keur(widget.ppipe2_win)" - /></td> - </tr> - <tr class="table-legend-total"> - <td style="width: 20px;" /> - <td>Total</td> - <td class="nb"><t - t-esc="widget.render_percent(widget.total)" - /></td> - <td class="nb"><t t-esc="widget.render_keur(widget.total2)" /></td> - </tr> - <tr> - <td style="width: 20px;" /> - <td /> - <td class="nb" /> - <td class="nb" /> - </tr> - <tr> - <td style="background-color: #F6ACA2; width: 20px;" /> - <td>Pipe</td> - <td class="nb"><t - t-esc="widget.render_percent(widget.ppipe_to_win)" - /></td> - <td class="nb"><t - t-esc="widget.render_keur(widget.ppipe2_to_win)" - /></td> - </tr> - <tr> - <td style="background-color: #eee; width: 20px;" /> - <td>À facturer</td> - <td class="nb"><t - t-esc="widget.render_percent(widget.ptarg)" - /></td> - <td class="nb"><t t-esc="widget.render_keur(widget.ptarg2)" /></td> - </tr> - </table> - </div> - </div> - </div> - </div> - <!-- COLONNE 3 --> - <div class="col-xs-12 col-sm-6 col-md-4 tresorerie"> - <h3>Trésorerie</h3> - <!-- Tréso --> - <div class="col-xs-12 dashboard-tab"> - <ul class="nav nav-tabs" id="tresoTab"> - <li class="nav-item"> - <a - class="nav-link active" - data-toggle="tab" - href="#treso" - >Trésorerie</a> - </li> - <li class="nav-item"> - <a - class="nav-link" - data-toggle="tab" - href="#by-bank" - >Solde banques</a> - </li> - </ul> - <div class="tab-content card-tab" id="tresoContent"> - <div id="treso" class="tab-pane fade show active in"> - <p class="card-maj">Denière mise à jour le <t - t-esc="widget.render_date(widget.values.date_maj)" - /></p> - <p class="card-number"> - <a id="releve"><strong><t - t-esc="widget.render_monetary(widget.values.tresorerie)" - /></strong></a> - </p> - </div> - <div id="by-bank" class="tab-pane fade"> - <table - class="table table-striped table-sm table-bordered table-hover" - > - <t t-foreach="widget.values.treso_by_bank" t-as="bank"> - <tr> - <td><t t-esc="bank.journal_id[1]" /></td> - <td class="text-right"><t - t-esc="widget.render_monetary_decimal(bank.amount)" - /></td> - </tr> - </t> - </table> - </div> - </div> - </div> - <!-- Non encaissé / Du --> - <div class="col-xs-12 dashboard-tab"> - <ul class="nav nav-tabs" id="tab3"> - <li class="nav-item"> - <a - class="nav-link active" - data-toggle="tab" - href="#non_encaisse" - >Facturé non encaissé</a> - </li> - <li class="nav-item"> - <a - class="nav-link" - data-toggle="tab" - href="#fournisseur" - >Fournisseurs</a> - </li> - </ul> - <div class="tab-content card-tab" id="myTab3Content"> - <div id="non_encaisse" class="tab-pane fade show active in"> - <p class="card-number"> - <a id="facture_non_encaisse"> - <t t-esc="widget.render_monetary(widget.values.a_encaisser)" /> - </a> - </p> - </div> - <div id="fournisseur" class="tab-pane fade"> - <p class="card-number"> - <a id="fournisseur_link"> - <t t-esc="widget.render_monetary(widget.values.a_payer)" /> - </a> - </p> - </div> - </div> - </div> - <!-- Variation --> - <div class="col-xs-12 dashboard-tab"> - <ul class="nav nav-tabs" id="myTab2"> - <li class="nav-item"> - <a - class="nav-link active" - data-toggle="tab" - href="#variation" - >Variation</a> - </li> - <li class="nav-item"> - <a class="nav-link" data-toggle="tab" href="#e_s">Entrées/Sorties</a> - </li> - </ul> - <div class="tab-content card-tab" id="myTab2Content"> - <div id="variation" class="tab-pane fade show active in"> - <p class="card-number"> - <a id="statement_lines"> - <t - t-raw="widget.render_monetary_color(widget.values.variation)" - /> - </a> - </p> - </div> - <div id="e_s" class="tab-pane fade"> - <div class="card-half"> - <h5 class="card-title">Encaissé</h5> - <p class="card-number"> - <t t-esc="widget.render_monetary(widget.values.entree)" /> - </p> - </div> - <div class="card-half"> - <h5 class="card-title">Sorties</h5> - <p class="card-number"> - <t t-esc="widget.render_monetary(widget.values.sortie)" /> - </p> - </div> - <div class="clearfix" /> - </div> - </div> - </div> - </div> - </div> - </div> - </t> - -</templates> diff --git a/static/src/xml/lefilament_treso.xml b/static/src/xml/lefilament_treso.xml deleted file mode 100644 index bb04b77..0000000 --- a/static/src/xml/lefilament_treso.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<templates xml:space="preserve"> - - - <t t-name="Tresorerie"> - - <div class="card"> - <div class="card-body"> - <p class="card-number"> - Trésorerie sur 12 mois - </p> - <hr /> - <canvas id="tresorerie" width="auto" height="100" /> - </div> - </div> - - </t> - -</templates> diff --git a/templates/lefilament_dashboard.xml b/templates/lefilament_dashboard.xml new file mode 100644 index 0000000..1c0b72c --- /dev/null +++ b/templates/lefilament_dashboard.xml @@ -0,0 +1,539 @@ +<?xml version="1.0" encoding="utf-8" ?> +<odoo> + <record id="lefilament_dashboard_overview_form" model="ir.ui.view"> + <field name="name">lefilament.dashboardt.overview</field> + <field name="type">qweb</field> + <field name="model">lefilament.dashboard</field> + <field name="arch" type="xml"> + <qweb js_class="lefilament_dashboard_overview"> + <nav class="o_qweb_cp_buttons"> + <button type="object" class="btn" id="update_view"> + <i class="fa fa-refresh" /> + </button> + </nav> + <div class="o_form_view o_form_readonly"> + <div class="o_form_sheet_bg"> + <div class="o_form_sheet position-relative"> + <t + t-set="values" + t-value="records.retrieve_datas_dashboard()" + /> + <div class="row"> + <!-- Column 1 --> + <div class="col-12 col-md-6 col-lg-4"> + <h3 + class="text-uppercase fw-bolder o_horizontal_separator mb-4" + >En Cours</h3> + <!-- Facturé --> + <div class="card mb32"> + <t + t-set="invoiced" + t-value="sum(values.get('invoice_ids').mapped('amount_untaxed_signed'))" + /> + <div class="card-body"> + <a + type="action" + data-model="account.move" + t-att-data-domain="[('id','in', values.get('invoice_ids').ids)]" + data-views='[[0, "list"], [0, "pivot"], [0, "graph"], [0, "form"]]' + tabindex="-1" + > + <h5 class="card-title">Facturé</h5> + <p class="display-6"> + <t + t-out="invoiced" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + </p> + </a> + </div> + </div> + <!-- Commandes --> + <div class="card mb32"> + <t + t-set="ordered" + t-value="sum(values.get('order_line_ids').mapped('price_subtotal'))" + /> + <div class="card-body"> + <a + type="action" + data-model="sale.order" + t-att-data-domain="[('id','in', values.get('order_line_ids').mapped('order_id').ids)]" + data-views='[[0, "list"], [0, "pivot"], [0, "graph"], [0, "form"]]' + tabindex="-1" + > + <h5 + class="card-title" + >Commandes en cours</h5> + <p class="display-6"> + <t + t-out="ordered" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + + </p> + </a> + </div> + </div> + <!-- Pipe --> + <div class="card mb32"> + <div class="card-body"> + <a + type="action" + data-model="crm.lead" + t-att-data-domain="[('id','in', values.get('lead_ids').ids)]" + data-views='[[0, "kanban"],[0, "list"], [0, "pivot"], [0, "graph"], [0, "form"]]' + tabindex="-1" + > + <h5 class="card-title">Pipe</h5> + <p class="display-6"> + <t + t-out="sum(values.get('lead_ids').mapped('prorated_revenue'))" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + + </p> + </a> + </div> + </div> + </div> + + <!-- Column 2 --> + <div class="col-12 col-md-6 col-lg-4"> + <h3 + class="text-uppercase fw-bolder o_horizontal_separator mb-4" + >Objectif</h3> + <div class="card"> + <div class="card-body"> + <p class="display-5 mb16"> + <t + t-out="values.get('target')" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + + </p> + <div class="progress" style="height: 60px;"> + <div + class="progress-bar progress-bar-striped bg-success" + role="progressbar" + t-att-aria-valuenow="values['progress'] * 100" + aria-valuemin="0" + aria-valuemax="100" + t-attf-style="width: {{values['progress'] * 100}}%; font-size: 14px; font-weight: 600;" + > + <t + t-out="round(values.get('progress') * 100, 0)" + t-options="{'widget': 'float', 'precision': 0}" + /> % + </div> + </div> + <table class="table-legend mt16"> + <tr> + <td + style="background-color: #8ED8A2; width: 20px;" + class="progress-bar-striped" + /> + <td>Facturé</td> + <td class="nb"><t + t-out="invoiced" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /></td> + <td class="nb"> + <t + t-out="values['progress'] * 100" + t-options="{'widget': 'float', 'precision': 0}" + /> % + </td> + </tr> + <tr> + <td + style="background-color: #F6DCA2; width: 20px;" + class="progress-bar-striped" + /> + <td>Commandes</td> + <td class="nb"><t + t-out="ordered" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /></td> + <td class="nb"> + <t + t-out="round(ordered / values['target'], 2) * 100" + t-options="{'widget': 'float', 'precision': 0}" + /> % + </td> + </tr> + <tr> + <td + style="background-color: #F6CCA2; width: 20px;" + class="progress-bar-striped" + /> + <td>Pipe Gagné</td> + <td class="nb"><t + t-out="values['pipe_win']" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /></td> + <td class="nb"><t + t-out="round(values['pipe_win'] / values['target'], 2) * 100" + t-options="{'widget': 'float', 'precision': 0}" + /> %</td> + </tr> + <tr class="table-legend-total"> + <td style="width: 20px;" /> + <td>Total</td> + <td class="nb"><t + t-out="(values['pipe_win'] + ordered + invoiced)" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /></td> + <td class="nb"> + <t + t-out="round((values['pipe_win'] + ordered + invoiced) / values['target'], 2) * 100" + t-options="{'widget': 'float', 'precision': 0}" + /> % + </td> + </tr> + <tr> + <td style="width: 20px;" /> + <td /> + <td class="nb" /> + <td class="nb" /> + </tr> + <tr> + <td + style="background-color: #eee; width: 20px;" + class="progress-bar-striped" + /> + <td>À facturer</td> + <td class="nb"> + <t + t-out="values['target'] - invoiced" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + </td> + <td class="nb"> + <t + t-out="round((values['target'] - invoiced) / values['target'], 2) * 100" + t-options="{'widget': 'float', 'precision': 0}" + /> % + </td> + </tr> + </table> + </div> + </div> + </div> + + <!-- Column 3 --> + <div class="col-12 col-md-6 col-lg-4"> + <h3 + class="text-uppercase fw-bolder o_horizontal_separator mb-4" + >Trésorerie</h3> + <!-- Banques --> + <div class="card mb32"> + <div class="card-body"> + <ul + class="nav nav-tabs" + id="cash-tab" + role="tablist" + > + <li + class="nav-item" + role="presentation" + > + <button + class="nav-link active" + id="cash-tab" + data-bs-toggle="tab" + data-bs-target="#cash" + type="button" + role="tab" + aria-controls="cash" + aria-selected="true" + > + Trésorerie + </button> + </li> + <li + class="nav-item" + role="presentation" + > + <button + class="nav-link" + id="bank-tab" + data-bs-toggle="tab" + data-bs-target="#bank" + type="button" + role="tab" + aria-controls="bank" + aria-selected="false" + >Banques + </button> + </li> + </ul> + <div + class="tab-content mt16" + id="cashContent" + > + <div + class="tab-pane fade show active" + id="cash" + role="tabpanel" + aria-labelledby="cash-tab" + > + <p class="card-maj"> + Denière mise à jour le <t + t-out="values['date_maj']" + t-options="{'widget': 'date', 'format': 'dd MMM yyyy'}" + /></p> + <a + type="action" + data-model="account.bank.statement" + t-att-data-domain="[('id','in', values.get('statement_line_ids').mapped('statement_id').ids)]" + data-views='[[0, "list"], [0, "pivot"], [0, "graph"], [0, "form"]]' + tabindex="-1" + > + <p class="display-6"> + <t + t-out="sum(values.get('statement_line_ids').mapped('amount'))" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + + </p> + </a> + </div> + <div + class="tab-pane fade" + id="bank" + role="tabpanel" + aria-labelledby="bank-tab" + > + <table + class="table table-striped table-sm table-bordered table-hover" + > + <t + t-foreach="values['cash_by_bank']" + t-as="bank" + > + <tr> + <td + t-out="bank['journal_id'][1]" + /> + <td + class="text-right" + t-out="bank['amount']" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + </tr> + </t> + </table> + </div> + </div> + </div> + </div> + + <!-- To paid --> + <div class="card mb32"> + <div class="card-body"> + <ul + class="nav nav-tabs" + id="cash-tab" + role="tablist" + > + <li + class="nav-item" + role="presentation" + > + <button + class="nav-link active" + id="cust_to_pay-tab" + data-bs-toggle="tab" + data-bs-target="#cust_to_pay" + type="button" + role="tab" + aria-controls="cust_to_pay" + aria-selected="true" + > + Facturé non encaissé + </button> + </li> + <li + class="nav-item" + role="presentation" + > + <button + class="nav-link" + id="provider_to_pay-tab" + data-bs-toggle="tab" + data-bs-target="#provider_to_pay" + type="button" + role="tab" + aria-controls="provider_to_pay" + aria-selected="false" + >Fournisseurs + </button> + </li> + </ul> + <div + class="tab-content mt16" + id="toPayContent" + > + <div + class="tab-pane fade show active" + id="cust_to_pay" + role="tabpanel" + aria-labelledby="cust_to_pay-tab" + > + <a + type="action" + data-model="account.move" + t-att-data-domain="[('id','in', values.get('to_get').ids)]" + data-views='[[0, "list"], [0, "pivot"], [0, "graph"], [0, "form"]]' + tabindex="-1" + > + <p class="display-6"> + <t + t-out="sum(values.get('to_get').mapped('amount_residual_signed'))" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + </p> + </a> + </div> + <div + class="tab-pane fade" + id="provider_to_pay" + role="tabpanel" + aria-labelledby="provider_to_pay-tab" + > + <a + type="action" + data-model="account.move" + t-att-data-domain="[('id','in', values.get('to_pay').ids)]" + data-views='[[0, "list"], [0, "pivot"], [0, "graph"], [0, "form"]]' + tabindex="-1" + > + <p class="display-6"> + <t + t-out="sum(values.get('to_pay').mapped('amount_residual_signed'))" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + </p> + </a> + </div> + </div> + </div> + </div> + + <!-- Variation --> + <div class="card mb32"> + <div class="card-body"> + <ul + class="nav nav-tabs" + id="variation-tab" + role="tablist" + > + <li + class="nav-item" + role="presentation" + > + <button + class="nav-link active" + id="variation-tab" + data-bs-toggle="tab" + data-bs-target="#variation" + type="button" + role="tab" + aria-controls="variation" + aria-selected="true" + > + Variation + </button> + </li> + <li + class="nav-item" + role="presentation" + > + <button + class="nav-link" + id="inout-tab" + data-bs-toggle="tab" + data-bs-target="#inout" + type="button" + role="tab" + aria-controls="inout" + aria-selected="false" + >Entrées/Sorties + </button> + </li> + </ul> + <div + class="tab-content mt16" + id="variationContent" + > + <div + class="tab-pane fade show active" + id="variation" + role="tabpanel" + aria-labelledby="variation-tab" + > + <a + type="action" + data-model="account.bank.statement.line" + t-att-data-domain="[('id','in', values.get('variation').ids)]" + data-views='[[0, "list"], [0, "pivot"], [0, "graph"], [0, "form"]]' + tabindex="-1" + > + <p class="display-6"> + <t + t-out="sum(values.get('variation').mapped('amount'))" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + + </p> + </a> + </div> + <div + class="tab-pane fade" + id="inout" + role="tabpanel" + aria-labelledby="inout-tab" + > + <div class="row"> + <div class="col-6"> + <p><strong + >Encaissé</strong></p> + <p class="display-6"> + <t + t-out="sum(values.get('in').mapped('amount'))" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + </p> + </div> + <div class="col-6"> + <p><strong + >Décaissé</strong></p> + <p class="display-6"> + <t + t-out="sum(values.get('out').mapped('amount'))" + t-options="{'widget': 'monetary', 'display_currency': values['company_id'].currency_id}" + /> + </p> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + </qweb> + </field> + </record> + + <record id="le_filament_dashboard_overview_action" model="ir.actions.act_window"> + <field name="name">Rapport Annuel</field> + <field name="res_model">lefilament.dashboard</field> + <field name="view_mode">qweb</field> + <field name="context">{'active_test': False}</field> + </record> +</odoo> diff --git a/views/account_bank_statement_line.xml b/views/account_bank_statement_line.xml new file mode 100644 index 0000000..4bda0cd --- /dev/null +++ b/views/account_bank_statement_line.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright 2023 Le Filament (<https://www.le-filament.com>) + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> +<odoo> + <record id="account_bank_statement_line_tree" model="ir.ui.view"> + <field name="name">account.bank.statement.line.tree</field> + <field name="model">account.bank.statement.line</field> + <field name="arch" type="xml"> + <tree> + <field name="statement_id" /> + <field name="move_id" /> + <field name="date" /> + <field name="payment_ref" optional="show" /> + <field name="ref" optional="show" /> + <field name="partner_id" /> + <field name="amount" /> + <field name="running_balance" optional="hide" /> + <field name="transaction_type" optional="hide" /> + </tree> + </field> + </record> +</odoo> diff --git a/views/account_move.xml b/views/account_move.xml new file mode 100644 index 0000000..2ab14c8 --- /dev/null +++ b/views/account_move.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> +<odoo> + + <record id="view_invoice_tree" model="ir.ui.view"> + <field name="name">account.invoice.tree</field> + <field name="model">account.move</field> + <field name="arch" type="xml"> + <tree> + <field name="name" decoration-bf="1" /> + <field name="invoice_date" string="Date Facturation" /> + <field name="partner_id" string="Client" /> + <field name="invoice_date_due" /> + <field name="invoice_origin" /> + <field name="payment_reference" optional="hide" /> + <field name="ref" optional="hide" /> + <field name="invoice_user_id" widget="many2one_avatar_user" /> + <field + name="amount_untaxed_signed" + string="Montant HT" + sum="Total" + decoration-bf="1" + /> + <field name="amount_tax_signed" sum="Total" optional="hide" /> + <field + name="amount_total_signed" + string="Total" + sum="Total" + optional="show" + /> + <field + name="amount_residual_signed" + string="Montant Dû" + sum="Amount Due" + optional="show" + /> + <field name="currency_id" invisible="1" /> + <field name="company_currency_id" invisible="1" /> + <field + name="state" + widget="badge" + decoration-success="state == 'posted'" + decoration-info="state == 'draft'" + optional="show" + /> + <field + name="payment_state" + widget="badge" + decoration-danger="payment_state == 'not_paid'" + decoration-warning="payment_state in ('partial', 'in_payment')" + decoration-success="payment_state in ('paid', 'reversed')" + attrs="{'invisible': [('payment_state', 'in', ('invoicing_legacy'))]}" + /> + <field name="move_type" invisible="1" /> + </tree> + </field> + </record> +</odoo> diff --git a/views/assets.xml b/views/assets.xml deleted file mode 100644 index aa3657e..0000000 --- a/views/assets.xml +++ /dev/null @@ -1,32 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<odoo> - <data> - - <template id="lefilament_tdb_assets_backend" inherit_id="web.assets_backend"> - <xpath expr="." position="inside"> - - <link - href="/lefilament_tdb/static/src/css/lefilament_tdb.css" - rel="stylesheet" - /> - - <script - type="text/javascript" - src="/lefilament_tdb/static/src/js/dashboard_year.js" - /> - <script - type="text/javascript" - src="/lefilament_tdb/static/src/js/tresorerie.js" - /> - <script - type="text/javascript" - src="/lefilament_tdb/static/src/js/previ_tresorerie.js" - /> - - </xpath> - </template> - - </data> -</odoo> diff --git a/views/lefilament_dashboard.xml b/views/lefilament_dashboard.xml new file mode 100644 index 0000000..d9331aa --- /dev/null +++ b/views/lefilament_dashboard.xml @@ -0,0 +1,143 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> +<odoo> + <!-- Tree view --> + <record id="lefilament_dashboard_tree" model="ir.ui.view"> + <field name="name">Le Filament Dashboard Treeview</field> + <field name="model">lefilament.dashboard</field> + <field name="arch" type="xml"> + <tree> + <field name="date_tdb" widget="date" /> + <field name="name" /> + <field name="ca_mois" sum="Chiffre d'Affaire" /> + <field name="pipe_mois" avg="pipe" /> + <field name="treso" avg="Treso" /> + <field name="variation" avg="Variation" /> + <field name="charges" avg="Décaissé" /> + <field name="encaisse" avg="Encaissé" /> + <field name="charges_fixes" /> + <field name="runway" /> + </tree> + </field> + </record> + + <!-- Pivot view --> + <record model="ir.ui.view" id="lefilament_dashboard_pivot"> + <field name="name">Le Filament Dashboard Pivot</field> + <field name="model">lefilament.dashboard</field> + <field name="type">pivot</field> + <field name="arch" type="xml"> + <graph string="TDB Le Filament"> + <field name="ca_mois" type="measure" /> + <field name="pipe_mois" type="measure" /> + <field name="date_tdb" type="row" /> + </graph> + </field> + </record> + + <!-- Graph view --> + <record model="ir.ui.view" id="lefilament_dashboard_graph"> + <field name="name">Le Filament Dashboard Graph</field> + <field name="model">lefilament.dashboard</field> + <field name="type">graph</field> + <field name="arch" type="xml"> + <graph string="TDB Le Filament"> + <field name="ca_mois" type="measure" /> + <field name="date_tdb" type="col" /> + </graph> + </field> + </record> + + <!-- Form view --> + <record id="lefilament_dashboard_form" model="ir.ui.view"> + <field name="name">Le Filament Dashboard Formview</field> + <field name="model">lefilament.dashboard</field> + <field name="arch" type="xml"> + <form string="Liste des Mois"> + <header> + <button + string="MaJ Valeurs" + type="object" + name="get_month_values" + class="oe_highlight" + /> + </header> + <div class="container"> + <div class="col-xs-12 tdb_form"> + <h3>Mois</h3> + <hr /> + <group> + <field name="date_tdb" widget="date" /> + <field name="name" /> + </group> + </div> + <div class="col-xs-6 tdb_form"> + <h3>Chiffres</h3> + <hr /> + <group> + <field name="ca_mois" widget="monetary" /> + <field name="cmd_mois" widget="monetary" /> + <field name="pipe_mois" widget="monetary" /> + </group> + </div> + <div class="col-xs-6 tdb_form"> + <h3>Trésorerie</h3> + <hr /> + <group> + <field name="treso" widget="monetary" /> + <field name="variation" widget="monetary" /> + <field name="charges" widget="monetary" /> + <field name="encaisse" widget="monetary" /> + <field name="charges_fixes" widget="monetary" /> + <field name="runway" widget="monetary" /> + </group> + </div> + </div> + </form> + </field> + </record> + + <!-- Search view --> + <record id="lefilament_dashboard_search" model="ir.ui.view"> + <field name="name">Le Filament Dashboard Searchview</field> + <field name="model">lefilament.dashboard</field> + <field name="arch" type="xml"> + <search> + <field name="name" /> + <filter + string="Cette année" + name="this_year" + domain="[ ('date_tdb', '>=', (context_today()-relativedelta(years=0)).strftime('%Y-01-01')),]" + /> + <filter + string="L'année dernière" + name="last_year" + domain="[ ('date_tdb', '>=', (context_today()-relativedelta(years=1)).strftime('%Y-01-01')), ('date_tdb', '<=', (context_today()-relativedelta(years=1)).strftime('%Y-12-31'))]" + /> + + <group expand="0" name="group_by" string="Group By"> + <filter + string="Trimestre" + name="trimestre" + context="{'group_by':'date_tdb:quarter'}" + domain="[]" + /> + <filter + string="An" + name="an" + context="{'group_by':'date_tdb:year'}" + domain="[]" + /> + </group> + </search> + </field> + </record> + + <!-- Actions --> + <record id="lefilament_dashboard_action" model="ir.actions.act_window"> + <field name="name">Dashboard - Le Filament</field> + <field name="res_model">lefilament.dashboard</field> + <field name="view_mode">tree,graph,form,pivot</field> + </record> +</odoo> diff --git a/views/menus.xml b/views/menus.xml new file mode 100644 index 0000000..5bdc593 --- /dev/null +++ b/views/menus.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> +<odoo> + <menuitem + id="lefilament_dashboard_menu" + name="Dashboard" + sequence="10" + groups="group_dashboard" + web_icon="lefilament_tdb,static/description/icon_menu.png" + /> + + <menuitem + id="lefilament_dashboard_report" + parent="lefilament_dashboard_menu" + name="Rapports" + sequence="1" + /> + + <menuitem + id="lefilament_dashboard_report_year" + parent="lefilament_dashboard_report" + name="Annuel" + sequence="1" + action="lefilament_tdb.le_filament_dashboard_overview_action" + /> + <menuitem + id="lefilament_dashboard_conf" + parent="lefilament_dashboard_menu" + name="Configuration" + sequence="10" + /> + <menuitem + id="lefilament_dashboard_datas" + parent="lefilament_dashboard_conf" + name="Données" + action="lefilament_tdb.lefilament_dashboard_action" + sequence="10" + /> + <menuitem + id="lefilament_dashboard_variables" + parent="lefilament_dashboard_conf" + name="Variables" + action="lefilament_tdb.lefilament_dashboard_variables_action" + sequence="10" + /> +</odoo> diff --git a/views/res_company.xml b/views/res_company.xml new file mode 100644 index 0000000..8bea63c --- /dev/null +++ b/views/res_company.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8" ?> +<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) + License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> +<odoo> + <!-- Form view --> + <record id="view_form_lefilament_company_form_inherited" model="ir.ui.view"> + <field name="name">res.company.form.tdb</field> + <field name="model">res.company</field> + <field name="inherit_id" ref="base.view_company_form" /> + <field name="arch" type="xml"> + <xpath expr="//page[1]" position="after"> + <page name="tdb" string="Tableau de Bord"> + <group> + <group string="Données Annuelles"> + <field name="ca_target" /> + </group> + <group string="Données Mensuelles"> + <field name="charges_fixes" /> + </group> + </group> + </page> + </xpath> + </field> + </record> + + <!-- Action --> + <record id="lefilament_dashboard_variables_action" model="ir.actions.act_window"> + <field name="name">Variables Dashboard</field> + <field name="res_model">res.company</field> + <field name="res_id">1</field> + <field name="view_mode">form</field> + </record> +</odoo> diff --git a/views/schedule.xml b/views/schedule.xml deleted file mode 100644 index 08af079..0000000 --- a/views/schedule.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<odoo> - <data noupdate="1"> - <record id="ir_cron_lefilament_tdb" model="ir.cron"> - <field name="name">Tableau de Bord - Le Filament</field> - <field name="active" eval="True" /> - <field name="user_id" ref="base.user_root" /> - <field name="interval_number">1</field> - <field name="interval_type">months</field> - <field name="numbercall">-1</field> - <field name="doall" eval="True" /> - <field name="nextcall">2017-01-31 23:10:00</field> - <field name="model_id" ref="model_lefilament_dashboard" /> - <field name="code">model._new_data()</field> - <field name="state">code</field> - <field name="priority" eval="5" /> - </record> - </data> -</odoo> diff --git a/views/views.xml b/views/views.xml deleted file mode 100644 index 1be129b..0000000 --- a/views/views.xml +++ /dev/null @@ -1,340 +0,0 @@ -<?xml version="1.0" encoding="utf-8" ?> -<!-- Copyright 2017 Le Filament (<https://www.le-filament.com>) - License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). --> -<odoo> - <data> - - <record id="lefilament_dashboard_action" model="ir.actions.act_window"> - <field name="name">Dashboard - Le Filament</field> - <field name="res_model">lefilament.dashboard</field> - <field name="view_mode">tree,graph,form,pivot</field> - </record> - - - <record - id="lefilament_dashboard_variables_action" - model="ir.actions.act_window" - > - <field name="name">Variables Dashboard Le Filament</field> - <field name="res_model">res.company</field> - <field name="res_id">1</field> - <field name="view_mode">form</field> - </record> - - <record id="action_year_page" model="ir.actions.client"> - <field name="name">Rapport Annuel</field> - <field name="tag">lefilament_tdb.dashboard_year</field> - <field name="binding_model_id" ref="model_lefilament_dashboard" /> - <field name="binding_type">action</field> - </record> - - <record id="action_tresorerie" model="ir.actions.client"> - <field name="name">Trésorerie</field> - <field name="tag">lefilament_tdb.tresorerie</field> - <field name="target">current</field> - <field name="binding_model_id" ref="model_lefilament_dashboard" /> - <field name="binding_type">action</field> - </record> - - <record id="action_previ_tresorerie" model="ir.actions.client"> - <field name="name">Prévisionnel Trésorerie</field> - <field name="tag">lefilament_tdb.previ_tresorerie</field> - <field name="target">current</field> - <field name="binding_model_id" ref="model_lefilament_dashboard" /> - <field name="binding_type">action</field> - </record> - - <menuitem - id="lefilament_dashboard_menu" - name="Dashboard" - sequence="10" - groups="group_dashboard" - web_icon="lefilament_tdb,static/description/icon_menu.png" - /> - - <menuitem - id="lefilament_dashboard_report" - parent="lefilament_dashboard_menu" - name="Rapports" - sequence="1" - /> - - <menuitem - id="lefilament_dashboard_report_year" - parent="lefilament_dashboard_report" - name="Annuel" - sequence="1" - action="action_year_page" - /> - <menuitem - id="lefilament_tresorerie" - parent="lefilament_dashboard_report" - name="Tréso" - sequence="3" - action="action_tresorerie" - /> - <menuitem - id="lefilament_previ_tresorerie" - parent="lefilament_dashboard_report" - name="Prévi Tréso" - sequence="3" - action="action_previ_tresorerie" - /> - - <menuitem - id="lefilament_dashboard_conf" - parent="lefilament_dashboard_menu" - name="Configuration" - sequence="10" - /> - <menuitem - id="lefilament_dashboard_datas" - parent="lefilament_dashboard_conf" - name="Données" - action="lefilament_dashboard_action" - sequence="10" - /> - <menuitem - id="lefilament_dashboard_variables" - parent="lefilament_dashboard_conf" - name="Variables" - action="lefilament_dashboard_variables_action" - sequence="10" - /> - - <record id="view_invoice_tree" model="ir.ui.view"> - <field name="name">account.invoice.tree</field> - <field name="model">account.move</field> - <field name="arch" type="xml"> - <tree string="Invoices"> - <field name="name" decoration-bf="1" /> - <field name="invoice_date" string="Date Facturation" /> - <field name="partner_id" string="Client" /> - <field name="invoice_date_due" /> - <field name="invoice_origin" /> - <field name="payment_reference" optional="hide" /> - <field name="ref" optional="hide" /> - <field name="invoice_user_id" widget="many2one_avatar_user" /> - <field - name="amount_untaxed_signed" - string="Montant HT" - sum="Total" - decoration-bf="1" - /> - <field name="amount_tax_signed" sum="Total" optional="hide" /> - <field - name="amount_total_signed" - string="Total" - sum="Total" - optional="show" - /> - <field - name="amount_residual_signed" - string="Montant Dû" - sum="Amount Due" - optional="show" - /> - <field name="currency_id" invisible="1" /> - <field name="company_currency_id" invisible="1" /> - <field - name="state" - widget="badge" - decoration-success="state == 'posted'" - decoration-info="state == 'draft'" - optional="show" - /> - <field - name="payment_state" - widget="badge" - decoration-danger="payment_state == 'not_paid'" - decoration-warning="payment_state in ('partial', 'in_payment')" - decoration-success="payment_state in ('paid', 'reversed')" - attrs="{'invisible': [('payment_state', 'in', ('invoicing_legacy'))]}" - /> - <field name="move_type" invisible="1" /> - </tree> - </field> - </record> - - - <record id="lefilament_dashboard_tree" model="ir.ui.view"> - <field name="name">Le Filament Dashboard Treeview</field> - <field name="model">lefilament.dashboard</field> - <field name="arch" type="xml"> - <tree string="Liste des Mois"> - <field name="date_tdb" widget="date" /> - <field name="name" /> - <field name="ca_mois" sum="Chiffre d'Affaire" /> - <field name="pipe_mois" avg="pipe" /> - <field name="treso" avg="Treso" /> - <field name="variation" avg="Variation" /> - <field name="charges" avg="Décaissé" /> - <field name="encaisse" avg="Encaissé" /> - <field name="charges_fixes" /> - <field name="runway" /> - </tree> - </field> - </record> - - <record model="ir.ui.view" id="lefilament_dashboard_pivot"> - <field name="name">Le Filament Dashboard Pivot</field> - <field name="model">lefilament.dashboard</field> - <field name="type">pivot</field> - <field name="arch" type="xml"> - <graph string="TDB Le Filament"> - <field name="ca_mois" type="measure" /> - <field name="pipe_mois" type="measure" /> - <field name="date_tdb" type="row" /> - </graph> - </field> - </record> - - <record model="ir.ui.view" id="lefilament_dashboard_graph"> - <field name="name">Le Filament Dashboard Graph</field> - <field name="model">lefilament.dashboard</field> - <field name="type">graph</field> - <field name="arch" type="xml"> - <graph string="TDB Le Filament"> - <field name="ca_mois" type="measure" /> - <field name="date_tdb" type="col" /> - </graph> - </field> - </record> - - <record id="lefilament_dashboard_form" model="ir.ui.view"> - <field name="name">Le Filament Dashboard Formview</field> - <field name="model">lefilament.dashboard</field> - <field name="arch" type="xml"> - <form string="Liste des Mois"> - <header> - <button - string="MaJ Valeurs" - type="object" - name="get_month_values" - class="oe_highlight" - /> - </header> - <div class="container"> - <div class="col-xs-12 tdb_form"> - <h3>Mois</h3> - <hr /> - <group> - <field name="date_tdb" widget="date" /> - <field name="name" /> - </group> - </div> - <div class="col-xs-6 tdb_form"> - <h3>Chiffres</h3> - <hr /> - <group> - <field name="ca_mois" widget="monetary" /> - <field name="cmd_mois" widget="monetary" /> - <field name="pipe_mois" widget="monetary" /> - </group> - </div> - <div class="col-xs-6 tdb_form"> - <h3>Trésorerie</h3> - <hr /> - <group> - <field name="treso" widget="monetary" /> - <field name="variation" widget="monetary" /> - <field name="charges" widget="monetary" /> - <field name="encaisse" widget="monetary" /> - <field name="charges_fixes" widget="monetary" /> - <field name="runway" widget="monetary" /> - </group> - </div> - </div> - </form> - </field> - </record> - - <!-- FILTRES --> - <record id="lefilament_dashboard_search" model="ir.ui.view"> - <field name="name">Le Filament Dashboard Searchview</field> - <field name="model">lefilament.dashboard</field> - <field name="arch" type="xml"> - <search> - <field name="name" /> - <filter - string="Cette année" - name="this_year" - domain="[ ('date_tdb', '>=', (context_today()-relativedelta(years=0)).strftime('%Y-01-01')),]" - /> - <filter - string="L'année dernière" - name="last_year" - domain="[ ('date_tdb', '>=', (context_today()-relativedelta(years=1)).strftime('%Y-01-01')), ('date_tdb', '<=', (context_today()-relativedelta(years=1)).strftime('%Y-12-31'))]" - /> - - <group expand="0" name="group_by" string="Group By"> - <filter - string="Trimestre" - name="trimestre" - context="{'group_by':'date_tdb:quarter'}" - domain="[]" - /> - <filter - string="An" - name="an" - context="{'group_by':'date_tdb:year'}" - domain="[]" - /> - </group> - </search> - </field> - </record> - - <!-- Company Form --> - <record id="view_form_lefilament_company_form_inherited" model="ir.ui.view"> - <field name="name">res.company.form.tdb</field> - <field name="model">res.company</field> - <field name="inherit_id" ref="base.view_company_form" /> - <field name="arch" type="xml"> - <xpath expr="//page[1]" position="after"> - <page name="tdb" string="Tableau de Bord"> - <group> - <group string="Données Annuelles"> - <field name="ca_target" /> - </group> - <group string="Données Mensuelles"> - <field name="charges_fixes" /> - </group> - </group> - </page> - <page name="tdb" string="Prévisonnel"> - <field name="previ_treso_ids" /> - </page> - </xpath> - </field> - </record> - - <!-- Company Form --> - <record id="view_form_lefilament_emplyee_form_inherited" model="ir.ui.view"> - <field name="name">hr.employee.form.tdb</field> - <field name="model">hr.employee</field> - <field name="inherit_id" ref="hr.view_employee_form" /> - <field name="arch" type="xml"> - <xpath expr="//field[@name='work_phone']" position="after"> - <field name="capital" /> - </xpath> - </field> - </record> - - <!-- Prévi Tréso --> - <record id="view_tree_lefilament_previ_treso" model="ir.ui.view"> - <field name="name">previ.treso</field> - <field name="model">previ.treso</field> - <field name="arch" type="xml"> - <tree string="Prévisionnel Tréso" editable="top"> - <field name="name" /> - <field name="periode" /> - <field name="date" /> - <field name="montant" sum="Total" /> - </tree> - </field> - </record> - - - </data> -</odoo> -- GitLab