Skip to content
Extraits de code Groupes Projets
Valider 1f4b7b2c rédigé par Rémi - Le Filament's avatar Rémi - Le Filament
Parcourir les fichiers

[MIG] Migration to version 17.0

parent fdf5a016
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 121 ajouts et 1378 suppressions
# Do NOT update manually; changes here will be overwritten by Copier # Do NOT update manually; changes here will be overwritten by Copier
_commit: v1.14.2 _commit: v1.29
_src_path: https://github.com/OCA/oca-addons-repo-template.git _src_path: https://github.com/OCA/oca-addons-repo-template.git
ci: false additional_ruff_rules: []
dependency_installation_mode: PIP ci: GitHub
generate_requirements_txt: false convert_readme_fragments_to_markdown: true
enable_checklog_odoo: true
generate_requirements_txt: true
github_check_license: false github_check_license: false
github_ci_extra_env: {} github_ci_extra_env: {}
github_enable_codecov: false github_enable_codecov: false
...@@ -11,14 +13,15 @@ github_enable_makepot: false ...@@ -11,14 +13,15 @@ github_enable_makepot: false
github_enable_stale_action: false github_enable_stale_action: false
github_enforce_dev_status_compatibility: false github_enforce_dev_status_compatibility: false
include_wkhtmltopdf: false include_wkhtmltopdf: false
odoo_version: 16.0 odoo_test_flavor: OCB
odoo_version: 17.0
org_name: Le Filament org_name: Le Filament
org_slug: lefilament org_slug: lefilament
rebel_module_groups: [] rebel_module_groups: []
repo_description: null repo_description: ''
repo_name: Module Template repo_name: Template module
repo_slug: template_module repo_slug: lefilament
repo_website: https://le-filament.com repo_website: https://le-filament.com
travis_apt_packages: [] use_pyproject_toml: true
travis_apt_sources: [] use_ruff: true
...@@ -4,7 +4,7 @@ env: ...@@ -4,7 +4,7 @@ env:
# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449 # See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449
parserOptions: parserOptions:
ecmaVersion: 2019 ecmaVersion: 2022
overrides: overrides:
- files: - files:
...@@ -22,6 +22,7 @@ globals: ...@@ -22,6 +22,7 @@ globals:
odoo: readonly odoo: readonly
openerp: readonly openerp: readonly
owl: readonly owl: readonly
luxon: readonly
# Styling is handled by Prettier, so we only need to enable AST rules; # 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 # see https://github.com/OCA/maintainer-quality-tools/pull/618#issuecomment-558576890
......
[flake8]
max-line-length = 88
max-complexity = 16
# B = bugbear
# B9 = bugbear opinionated (incl line length)
select = C,E,F,W,B,B9
# E203: whitespace before ':' (black behaviour)
# E501: flake8 line length (covered by bugbear B950)
# W503: line break before binary operator (black behaviour)
ignore = E203,E501,W503
per-file-ignores=
__init__.py:F401
...@@ -3,6 +3,7 @@ __pycache__/ ...@@ -3,6 +3,7 @@ __pycache__/
*.py[cod] *.py[cod]
/.venv /.venv
/.pytest_cache /.pytest_cache
/.ruff_cache
# C extensions # C extensions
*.so *.so
...@@ -23,6 +24,16 @@ var/ ...@@ -23,6 +24,16 @@ var/
.installed.cfg .installed.cfg
*.egg *.egg
*.eggs *.eggs
.copier-answers.yml
# Debian packages
*.deb
# Redhat packages
*.rpm
# MacOS packages
*.dmg
# Installer logs # Installer logs
pip-log.txt pip-log.txt
......
[settings]
; see https://github.com/psf/black
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
combine_as_imports=True
use_parentheses=True
line_length=88
known_odoo=odoo
known_odoo_addons=odoo.addons
sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER
default_section=THIRDPARTY
ensure_newline_before_comments = True
...@@ -12,6 +12,12 @@ exclude: | ...@@ -12,6 +12,12 @@ exclude: |
/static/(src/)?lib/| /static/(src/)?lib/|
# Repos using Sphinx to generate docs don't need prettying # Repos using Sphinx to generate docs don't need prettying
^docs/_templates/.*\.html$| ^docs/_templates/.*\.html$|
# Don't bother non-technical authors with formatting issues in docs
readme/.*\.(rst|md)$|
# Ignore build and dist directories in addons
/build/|/dist/|
# Ignore test files in addons
/tests/samples/.*|
# You don't usually want a bot to modify your legal texts # You don't usually want a bot to modify your legal texts
(LICENSE.*|COPYING.*) (LICENSE.*|COPYING.*)
default_language_version: default_language_version:
...@@ -31,35 +37,39 @@ repos: ...@@ -31,35 +37,39 @@ repos:
name: en.po files cannot exist name: en.po files cannot exist
entry: found a en.po file entry: found a en.po file
language: fail language: fail
files: '[a-zA-Z0-9_]*/i18n/en\.po$' files:
'[a-zA-Z0-9_]*/i18n/en\.po$'
# - repo: https://github.com/sbidoul/whool
# rev: v0.5
# hooks:
# - id: whool-init
- repo: https://github.com/oca/maintainer-tools - repo: https://github.com/oca/maintainer-tools
rev: 4cd2b852214dead80822e93e6749b16f2785b2fe rev: d5fab7ee87fceee858a3d01048c78a548974d935
hooks: hooks:
# update the NOT INSTALLABLE ADDONS section above # update the NOT INSTALLABLE ADDONS section above
- id: oca-update-pre-commit-excluded-addons - id: oca-update-pre-commit-excluded-addons
- id: oca-fix-manifest-website - id: oca-fix-manifest-website
args: ["https://le-filament.com"] args: ["https://le-filament.com"]
- repo: https://github.com/myint/autoflake - id: oca-gen-addon-readme
rev: v1.6.1
hooks:
- id: autoflake
args: args:
- --expand-star-imports - --addons-dir=.
- --ignore-init-module-imports - --branch=17.0
- --in-place - --org-name=lefilament
- --remove-all-unused-imports - --repo-name=template_module
- --remove-duplicate-keys - --if-source-changed
- --remove-unused-variables - --keep-source-digest
- repo: https://github.com/psf/black - --convert-fragments-to-markdown
rev: 22.8.0 # - id: oca-gen-external-dependencies
- repo: https://github.com/OCA/odoo-pre-commit-hooks
rev: v0.0.25
hooks: hooks:
- id: black - id: oca-checks-odoo-module
- id: oca-checks-po
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1 rev: v2.7.1
hooks: hooks:
- id: prettier - id: prettier
name: prettier (with plugin-xml) name: prettier (with plugin-xml)
exclude: ^templates/
additional_dependencies: additional_dependencies:
- "prettier@2.7.1" - "prettier@2.7.1"
- "@prettier/plugin-xml@2.2.0" - "@prettier/plugin-xml@2.2.0"
...@@ -96,27 +106,14 @@ repos: ...@@ -96,27 +106,14 @@ repos:
- id: check-xml - id: check-xml
- id: mixed-line-ending - id: mixed-line-ending
args: ["--fix=lf"] args: ["--fix=lf"]
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/astral-sh/ruff-pre-commit
rev: v2.38.2 rev: v0.1.3
hooks:
- id: pyupgrade
args: ["--keep-percent-format"]
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort
name: isort except __init__.py
args:
- --settings=.
exclude: /__init__\.py$
- repo: https://github.com/PyCQA/flake8
rev: 3.9.2
hooks: hooks:
- id: flake8 - id: ruff
name: flake8 args: [--fix, --exit-non-zero-on-fix]
additional_dependencies: ["flake8-bugbear==21.9.2"] - id: ruff-format
- repo: https://github.com/OCA/pylint-odoo - repo: https://github.com/OCA/pylint-odoo
rev: 7.0.2 rev: v9.0.4
hooks: hooks:
- id: pylint_odoo - id: pylint_odoo
name: pylint with optional checks name: pylint with optional checks
......
...@@ -5,12 +5,12 @@ load-plugins=pylint_odoo ...@@ -5,12 +5,12 @@ load-plugins=pylint_odoo
score=n score=n
[ODOOLINT] [ODOOLINT]
readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
manifest_required_authors=Le Filament manifest-required-authors=Le Filament
manifest_required_keys=license manifest-required-keys=license
manifest_deprecated_keys=description,active 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 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=16.0 valid-odoo-versions=17.0
[MESSAGES CONTROL] [MESSAGES CONTROL]
disable=all disable=all
......
...@@ -4,12 +4,12 @@ load-plugins=pylint_odoo ...@@ -4,12 +4,12 @@ load-plugins=pylint_odoo
score=n score=n
[ODOOLINT] [ODOOLINT]
readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst" readme-template-url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
manifest_required_authors=Le Filament manifest-required-authors=Le Filament
manifest_required_keys=license manifest-required-keys=license
manifest_deprecated_keys=description,active 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 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=16.0 valid-odoo-versions=17.0
[MESSAGES CONTROL] [MESSAGES CONTROL]
disable=all disable=all
......
target-version = "py310"
fix = true
[lint]
extend-select = [
"B",
"C90",
"E501", # line too long (default 88)
"I", # isort
"UP", # pyupgrade
]
exclude = ["setup/*"]
[format]
exclude = ["setup/*"]
[per-file-ignores]
"__init__.py" = ["F401", "I001"] # ignore unused and unsorted imports in __init__.py
"__manifest__.py" = ["B018"] # useless expression
[isort]
section-order = ["future", "standard-library", "third-party", "odoo", "odoo-addons", "first-party", "local-folder"]
[isort.sections]
"odoo" = ["odoo"]
"odoo-addons" = ["odoo.addons"]
[mccabe]
max-complexity = 16
...@@ -6,35 +6,19 @@ ...@@ -6,35 +6,19 @@
"author": "Le Filament", "author": "Le Filament",
"category": "dashboard", "category": "dashboard",
"website": "https://le-filament.com", "website": "https://le-filament.com",
"version": "16.0.1.0.0", "version": "17.0.1.0.0",
"license": "AGPL-3", "license": "AGPL-3",
"depends": ["account", "crm", "hr_expense", "sale"], "depends": ["account_usability", "crm", "hr_expense", "sale"],
"data": [ "data": [
# security # security
"security/lefilament_dashboard_security.xml", "security/lefilament_dashboard_security.xml",
"security/ir.model.access.csv", "security/ir.model.access.csv",
# datas # datas
# templates
"templates/dashboard_detail.xml",
"templates/lefilament_dashboard.xml",
# views # views
"views/account_bank_statement_line.xml",
"views/account_move.xml",
"views/lefilament_dashboard.xml", "views/lefilament_dashboard.xml",
"views/res_company.xml", "views/res_company.xml",
# templates
# menus # menus
"views/menus.xml", "views/menus.xml",
], ],
"assets": {
"web._assets_primary_variables": [],
"web._assets_frontend_helpers": [],
"web.assets_frontend": [],
"web.assets_backend": [
"lefilament_tdb/static/src/js/dashboard_detail.js",
"lefilament_tdb/static/src/js/dashboard_overview.js",
"lefilament_tdb/static/src/css/lefilament_tdb.css",
],
"web.assets_tests": [],
"web.assets_qweb": [],
},
} }
<?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>
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
from datetime import date from datetime import date
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from psycopg2.extensions import AsIs
from odoo import api, fields, models from odoo import api, fields, models
from odoo.tools.safe_eval import safe_eval from odoo.tools.safe_eval import safe_eval
...@@ -150,7 +149,6 @@ class LeFilamentTdb(models.Model): ...@@ -150,7 +149,6 @@ class LeFilamentTdb(models.Model):
# ------------------------------------------------------ # ------------------------------------------------------
@api.model @api.model
def open_detail(self, target_model, name=None, domain=None, views=None): def open_detail(self, target_model, name=None, domain=None, views=None):
action = { action = {
"name": name or target_model, "name": name or target_model,
"type": "ir.actions.act_window", "type": "ir.actions.act_window",
...@@ -169,337 +167,3 @@ class LeFilamentTdb(models.Model): ...@@ -169,337 +167,3 @@ class LeFilamentTdb(models.Model):
def get_month_values(self): def get_month_values(self):
for data in self: for data in self:
data._compute_dashboard_values() data._compute_dashboard_values()
@api.model
def retrieve_datas_dashboard(self):
# Get fiscal years
fiscal_date = date(
date.today().year,
int(self.env.company.fiscalyear_last_month),
int(self.env.company.fiscalyear_last_day),
)
if date.today() > fiscal_date:
fiscal_year = fiscal_date
fiscal_year_next = fiscal_date + relativedelta(years=1)
else:
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.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),
]
)
# Orders
res["order_line_ids"] = self.env["sale.order.line"].search(
[
("invoice_status", "=", "to invoice"),
]
)
# Opportunities
res["lead_ids"] = self.env["crm.lead"].search(
[
"|",
("date_deadline", ">", fiscal_year_next),
("date_deadline", "=", False),
]
)
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(
[
("probability", "=", 100),
"|",
("date_deadline", "<=", fiscal_year_next),
("date_deadline", "=", False),
]
)
.mapped(lambda l: l.expected_revenue * l.probability / 100)
)
res["pipe_to_win"] = sum(
self.env["crm.lead"]
.search(
[
("probability", "!=", 100),
"|",
("date_deadline", "<=", fiscal_year_next),
("date_deadline", "=", False),
]
)
.mapped(lambda l: l.expected_revenue * l.probability / 100)
)
res["to_get"] = self.env["account.move"].search(
[
("move_type", "in", ("out_invoice", "out_refund")),
("state", "=", "posted"),
("payment_state", "in", ["not_paid", "partial", "in_payment"]),
]
)
res["to_pay"] = self.env["account.move"].search(
[
("move_type", "in", ("in_invoice", "in_refund")),
("state", "=", "posted"),
("payment_state", "in", ["not_paid", "partial", "in_payment"]),
]
)
res["date_maj"] = (
self.env["account.bank.statement.line"]
.search([], order="date desc", limit=1)
.date
)
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["in"] = self.env["account.bank.statement.line"].search(
[
("amount", ">", 0),
("date", ">", fiscal_year),
]
)
res["out"] = self.env["account.bank.statement.line"].search(
[
("amount", "<", 0),
("date", ">", fiscal_year),
]
)
res["variation"] = self.env["account.bank.statement.line"].search(
[
("date", ">", fiscal_year),
]
)
res["company_id"] = self.env.company
return res
@api.model
def dashboard_detail_values(self, date_start=None, date_end=None):
return {
"customer": self._customer_detail(date_start, date_end),
"employee_time": self._employee_time(date_start, date_end),
"date_start": date_start,
"date_end": date_end,
}
@api.model
def dashboard_detail_values_template(self, date_start=None, date_end=None):
return self.env["ir.ui.view"]._render_template(
"lefilament_tdb.dashboard_detail_values",
self.dashboard_detail_values(date_start, date_end),
)
def _customer_detail(self, date_start=None, date_end=None):
clause = "where 1=1 "
if date_start:
clause += f"and line_date >= '{date_start}' "
if date_end:
clause += f"and line_date <= '{date_end}' "
query = """
select
customer as "Client",
sum(prod) as "Imput.",
sum(invoiced + purchase + expense)::int as "Balance Prod",
sum(invoiced + purchase + expense)/NULLIF(sum(prod), 0) as "Taux Horaire",
sum(invoiced + invoiced_mco) as "Tot. Fact.",
sum(invoiced)::int as "Fact. Prod",
sum(invoiced_mco)::int as "Fact. Maint",
sum(purchase)::int as "Achats",
sum(expense)::int as "NdF"
from
(
-- Sélection des heures
select
aal.date as line_date,
p.name as customer,
-- contact != Filament et projet != Maintenance et pas flagué vacances
case when aal.partner_id != 1 or aal.partner_id is null and aal.holiday_id is null and project_id != 19 then unit_amount else 0 end as prod,
0 as invoiced,
0 as invoiced_mco,
0 as purchase,
0 as expense
from
account_analytic_line aal
left join
res_partner p on aal.partner_id = p.id
left join
hr_leave l on aal.holiday_id = l.id
left join
hr_leave_type lt on l.holiday_status_id = lt.id
where
aal.project_id is not null
and aal.date <= CURRENT_DATE
and (lt.active is true or lt.active is null)
and partner_id != 1
-- Sélection du facturé hors maintenance
union all
select
aml.date as line_date,
p.name as customer,
0 as prod,
(aml.credit - aml.debit) as invoiced,
0 as invoiced_mco,
0 as purchase,
0 as expense
from account_move_line aml
left join account_move i on aml.move_id = i.id
left join res_partner p on i.beneficiary_id = p.id
where
i.move_type in ('out_invoice', 'out_refund')
and i.state = 'posted'
and aml.product_id is not null
and aml.product_id not in (33, 34, 50, 51, 61, 62)
-- Sélection du facturé Maintenance
union all
select
aml.date as line_date,
p.name as customer,
0 as prod,
0 as invoiced,
(aml.credit - aml.debit) as invoiced_mco,
0 as purchase,
0 as expense
from account_move_line aml
left join account_move i on aml.move_id = i.id
left join res_partner p on i.beneficiary_id = p.id
where
i.move_type in ('out_invoice', 'out_refund')
and i.state = 'posted'
and aml.product_id is not null
and aml.product_id in (33, 34, 50, 51, 61, 62)
-- Sélection des charges
union all
select
aal.date as line_date,
p.name as customer,
0 as prod,
0 as invoiced,
0 as invoiced_mco,
amount as purchase,
0 as expense
from account_analytic_line aal
left join account_move_line aml on aal.move_line_id = aml.id
left join account_move i on aml.move_id = i.id
left join account_analytic_account a on aal.account_id = a.id
left join res_partner p on a.partner_id = p.id
where
(aal.plan_id is null or aal.plan_id = 1)
and i.state = 'posted'
and aml.journal_id = 2
-- Sélection des NDF
union all
select
aal.date as line_date,
p.name as customer,
0 as prod,
0 as invoiced,
0 as invoiced_mco,
0 as purchase,
amount as expense
from account_analytic_line aal
left join account_move_line aml on aal.move_line_id = aml.id
left join account_move i on aml.move_id = i.id
left join account_analytic_account a on aal.account_id = a.id
left join res_partner p on a.partner_id = p.id
where
(aal.plan_id is null or aal.plan_id = 1)
and i.state = 'posted'
and aml.journal_id = 9
) query
%s
group by
customer
order by
sum(invoiced) desc
"""
self.env.cr.execute(query, (AsIs(clause),))
result = self.env.cr.dictfetchall()
return result
def _employee_time(self, date_start=None, date_end=None):
clause = ""
if date_start:
clause += f" and aal.date >= '{date_start}'"
if date_end:
clause += f" and aal.date <= '{date_end}'"
query = """
select
employee as "Employé",
sum(production) as "Prod",
sum(internal) as "Interne",
sum(revenue) as "CA"
from (
select
p.name as employee,
0 as production,
0 as internal,
sum(aal.amount) as revenue
from
account_analytic_line aal
left join
account_analytic_account aa on aal.account_id = aa.id
left join
account_analytic_plan aap on aa.plan_id = aap.id
left join
res_partner p on aa.partner_id = p.id
where
aap.id = 3
%s
group by p.name
union
select
e.name as employee,
sum(case when aal.partner_id != 1 or aal.partner_id is null and aal.holiday_id is null then unit_amount else 0 end) as production,
sum(case when aal.partner_id = 1 and aal.holiday_id is null then unit_amount else 0 end) as internal,
0 as revenue
from
account_analytic_line aal
left join
hr_employee e on aal.employee_id = e.id
left join
hr_leave l on aal.holiday_id = l.id
left join
hr_leave_type lt on l.holiday_status_id = lt.id
where
aal.project_id is not null
%s
group by e.name
) query
group by employee
order by sum(production) desc
"""
self.env.cr.execute(query, (AsIs(clause), AsIs(clause),))
result = self.env.cr.dictfetchall()
return result
.lefilament_dashboard {
padding-top: 40px;
padding-bottom: 40px;
background-color: #fefefe;
}
.lefilament_dashboard .display-6,
.lefilament_dashboard .card-title {
color: #495057;
}
.lefilament_dashboard a.dashboard_view {
cursor: pointer;
}
p.card-maj {
font-size: 10px;
font-style: italic;
font-weight: 300;
}
/* Legende ProgressBar */
.table-legend {
width: 100%;
max-width: 100%;
margin: 10px 0;
border-collapse: separate;
border-spacing: 8px;
font-size: 11px;
}
.table-legend .nb {
text-align: right;
}
.table-legend-total td {
border-top: 1px solid #eee;
border-bottom: 1px solid #eee;
font-weight: 700;
padding: 2px 0;
}
.dashboard_detail {
padding-top: 10px;
padding-bottom: 40px;
background-color: #fefefe;
}
odoo.define("lefilament_tdb.dashboard_detail", 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 .button-period": "_onClickButtonPeriod",
"click #button-custom-date": "_onClickButtonCustomDate",
}),
async _onClickButtonPeriod(e) {
e.preventDefault();
var $target = $(e.currentTarget);
var data = $target.data();
var dashboard_detail_values = this.$el.find("#dashboard_detail_values");
await this._rpc({
model: "lefilament.dashboard",
method: "dashboard_detail_values_template",
args: [],
kwargs: {
date_start: data.dateStart || null,
date_end: data.dateEnd || null,
},
}).then(function (result) {
dashboard_detail_values.html(result);
});
},
async _onClickButtonCustomDate(e) {
e.preventDefault();
var dashboard_detail_values = this.$el.find("#dashboard_detail_values");
var date_start = this.$el.find("#custom-date-start")[0];
var date_end = this.$el.find("#custom-date-end")[0];
await this._rpc({
model: "lefilament.dashboard",
method: "dashboard_detail_values_template",
args: [],
kwargs: {
date_start: date_start.value || null,
date_end: date_end.value || null,
},
}).then(function (result) {
dashboard_detail_values.html(result);
});
},
});
const DashboardDetail = qweb.View.extend({
withSearchBar: false,
searchMenuTypes: [],
config: _.extend({}, qweb.View.prototype.config, {
Controller: Controller,
}),
});
viewRegistry.add("dashboard_detail", DashboardDetail);
});
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",
"click .dashboard_view": "_onClickDashboardAction",
}),
_onClickUpdateView() {
this.reload();
},
async _onClickDashboardAction(e) {
e.preventDefault();
var $target = $(e.currentTarget);
var self = this;
var data = $target.data();
await this._rpc({
model: "lefilament.dashboard",
method: "open_detail",
args: [data.targetModel],
kwargs: {
name: data.title,
domain: data.domain || null,
views: data.views || null,
},
}).then(function (action) {
if (action !== undefined) {
self.do_action(action);
}
});
},
});
const DashboardOverview = qweb.View.extend({
withSearchBar: false,
searchMenuTypes: [],
config: _.extend({}, qweb.View.prototype.config, {
Controller: Controller,
}),
});
viewRegistry.add("dashboard_overview", DashboardOverview);
});
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Template layout -->
<record id="lefilament_dashboard_detail" model="ir.ui.view">
<field name="name">lefilament.dashboard.detail</field>
<field name="type">qweb</field>
<field name="model">lefilament.dashboard</field>
<field name="arch" type="xml">
<qweb js_class="dashboard_detail">
<nav class="o_qweb_cp_buttons">
<div class="btn-group" role="group" aria-label="Dates buttons">
<button
type="object"
class="btn btn-outline-primary button-period"
name="this_month"
t-att-data-date-start="datetime.date.today().replace(day=1).strftime('%Y-%m-%d')"
t-att-data-date-end="(datetime.date.today().replace(day=1) + relativedelta(months=1, days=-1)).strftime('%Y-%m-%d')"
>
Ce mois-ci
</button>
<button
type="object"
class="btn btn-outline-primary button-period"
name="last_month"
t-att-data-date-start="(datetime.date.today().replace(day=1) + relativedelta(months=-1)).strftime('%Y-%m-%d')"
t-att-data-date-end="(datetime.date.today().replace(day=1) + relativedelta(days=-1)).strftime('%Y-%m-%d')"
>
Le mois dernier
</button>
<button
type="object"
class="btn btn-outline-primary button-period"
name="this_year"
t-att-data-date-start="datetime.date.today().replace(day=1, month=1).strftime('%Y-%m-%d')"
t-att-data-date-end="datetime.date.today().replace(day=31, month=12).strftime('%Y-%m-%d')"
>
Cette année
</button>
<button
type="object"
class="btn btn-outline-primary button-period"
name="last_year"
t-att-data-date-start="(datetime.date.today().replace(day=1, month=1) + relativedelta(years=-1)).strftime('%Y-%m-%d')"
t-att-data-date-end="(datetime.date.today().replace(day=31, month=12) + relativedelta(years=-1)).strftime('%Y-%m-%d')"
>
L'année dernière
</button>
<button
type="object"
class="btn btn-outline-primary button-period"
name="all"
data-date-start=""
data-date-end=""
>
Tout
</button>
</div>
<div class="btn-group ms-5" role="group">
<input type="date" class="form-control text-center" id="custom-date-start" />
<input type="date" class="form-control text-center" id="custom-date-end" />
<button
type="object"
id="button-custom-date"
class="btn btn-outline-primary"
>
Mettre à jour
</button>
</div>
</nav>
<div id="dashboard_detail_values">
<t t-value="records.dashboard_detail_values()" t-set="init_data" />
<t t-value="init_data.get('customer')" t-set="customer" />
<t t-value="init_data.get('employee_time')" t-set="employee_time" />
<t t-call="lefilament_tdb.dashboard_detail_values" />
</div>
</qweb>
</field>
</record>
<!-- Dashboard Values -->
<template id="dashboard_detail_values" name="dashboard_detail_values">
<div class="dashboard_detail">
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="mt-2 mb-4 display-6 text-center">
Période :
<t t-out="date_start" t-options="{'widget': 'date', 'format': 'dd/MM/YYYY'}" /> -
<t t-out="date_end" t-options="{'widget': 'date', 'format': 'dd/MM/YYYY'}" />
</div>
</div>
<div class="col-7">
<h3 class="text-uppercase py-2 mb-0">Rentabilité client</h3>
<hr class="mt-0" />
<t t-call="lefilament_tdb.dashboard_detail_table">
<t t-set="data" t-value="customer" />
</t>
</div>
<div class="col-5">
<h3 class="text-uppercase py-2 mb-0">Imputations</h3>
<hr class="mt-0" />
<t t-call="lefilament_tdb.dashboard_detail_table">
<t t-set="data" t-value="employee_time" />
</t>
</div>
</div>
</div>
</div>
</template>
<!-- Table Template -->
<template id="dashboard_detail_table" name="dashboard_detail_table">
<div t-if="data" class="px-4 mb-5" style="max-height: 600px; overflow: scroll; border: 1px solid #eee;">
<table class="table table-hover table-striped">
<thead>
<tr class="bg-100">
<th>#</th>
<th t-foreach="data[0].keys()" t-as="header">
<t t-out="header" />
</th>
</tr>
</thead>
<tbody>
<tr t-foreach="data" t-as="line">
<td t-out="line_index + 1" />
<t t-foreach="line.values()" t-as="v">
<td t-if="isinstance(v, (int, float))" class="text-end">
<t t-out="v" t-options="{'widget': 'float', 'precision': 0}" />
</td>
<td t-else="">
<t t-out="v" />
</td>
</t>
</tr>
</tbody>
<tfoot>
<tr class="bg-100">
<th>Total</th>
<th t-foreach="data[-1].items()" t-as="footer" class="text-end">
<t t-if="isinstance(footer[1], (int, float))">
<t
t-out="sum(list(map(lambda d: d.get(footer[0]) if d.get(footer[0]) else 0.0, data)))"
t-options="{'widget': 'float', 'precision': 0}"
/>
</t>
</th>
</tr>
</tfoot>
</table>
</div>
</template>
<!-- Action -->
<record id="le_filament_dashboard_detail_action" model="ir.actions.act_window">
<field name="name">Détail</field>
<field name="res_model">lefilament.dashboard</field>
<field name="view_mode">qweb</field>
<field name="view_id" ref="lefilament_dashboard_detail"/>
<field name="context">{'active_test': False}</field>
</record>
</odoo>
Ce diff est replié.
<?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>
<?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>
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
<field name="model">lefilament.dashboard</field> <field name="model">lefilament.dashboard</field>
<field name="type">pivot</field> <field name="type">pivot</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<graph string="TDB Le Filament"> <pivot string="TDB Le Filament">
<field name="ca_mois" type="measure" /> <field name="ca_mois" type="measure" />
<field name="pipe_mois" type="measure" /> <field name="pipe_mois" type="measure" />
<field name="date_tdb" type="row" /> <field name="date_tdb" type="row" />
</graph> </pivot>
</field> </field>
</record> </record>
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter