Compare commits

...

No commits in common. '13.0' and '12.0-mis_builder_analytic_cash_flow' have entirely different histories.

  1. 4
      .editorconfig
  2. 180
      .eslintrc.yml
  3. 10
      .flake8
  4. 12
      .isort.cfg
  5. 103
      .pre-commit-config.yaml
  6. 8
      .prettierrc.yml
  7. 88
      .pylintrc
  8. 66
      .pylintrc-mandatory
  9. 45
      .travis.yml
  10. 9
      README.md
  11. 82
      account_export_csv/README.rst
  12. 1
      account_export_csv/__init__.py
  13. 20
      account_export_csv/__manifest__.py
  14. 294
      account_export_csv/i18n/account_export_csv.pot
  15. 297
      account_export_csv/i18n/es_AR.po
  16. 307
      account_export_csv/i18n/fr.po
  17. 297
      account_export_csv/i18n/hr.po
  18. 305
      account_export_csv/i18n/nl.po
  19. 296
      account_export_csv/i18n/pt.po
  20. 16
      account_export_csv/readme/CONTRBUTORS.rst
  21. 9
      account_export_csv/readme/DESCRIPTION.rst
  22. 2
      account_export_csv/readme/ROADMAP.rst
  23. BIN
      account_export_csv/static/description/icon.png
  24. 426
      account_export_csv/static/description/index.html
  25. 1
      account_export_csv/tests/__init__.py
  26. 52
      account_export_csv/tests/test_account_export_csv.py
  27. 1
      account_export_csv/wizard/__init__.py
  28. 354
      account_export_csv/wizard/account_export_csv.py
  29. 64
      account_export_csv/wizard/account_export_csv_view.xml
  30. 39
      account_financial_report/README.rst
  31. 1
      account_financial_report/__init__.py
  32. 82
      account_financial_report/__manifest__.py
  33. 1775
      account_financial_report/i18n/account_financial_report.pot
  34. 1886
      account_financial_report/i18n/ar.po
  35. 2136
      account_financial_report/i18n/ca.po
  36. 2633
      account_financial_report/i18n/da.po
  37. 2139
      account_financial_report/i18n/de.po
  38. 1872
      account_financial_report/i18n/es.po
  39. 1829
      account_financial_report/i18n/es_AR.po
  40. 2014
      account_financial_report/i18n/fr.po
  41. 1930
      account_financial_report/i18n/fr_CH.po
  42. 1876
      account_financial_report/i18n/hr.po
  43. 1734
      account_financial_report/i18n/hr_HR.po
  44. 2001
      account_financial_report/i18n/it.po
  45. 1716
      account_financial_report/i18n/ja.po
  46. 2014
      account_financial_report/i18n/nl.po
  47. 1721
      account_financial_report/i18n/nl_NL.po
  48. 2172
      account_financial_report/i18n/pt.po
  49. 2084
      account_financial_report/i18n/pt_BR.po
  50. 2049
      account_financial_report/i18n/ro.po
  51. 2615
      account_financial_report/i18n/sl.po
  52. 8
      account_financial_report/menuitems.xml
  53. 1
      account_financial_report/models/__init__.py
  54. 9
      account_financial_report/models/account.py
  55. 63
      account_financial_report/models/account_group.py
  56. 24
      account_financial_report/models/account_move_line.py
  57. 25
      account_financial_report/models/ir_actions_report.py
  58. 14
      account_financial_report/readme/CONTRIBUTORS.rst
  59. 2
      account_financial_report/readme/DESCRIPTION.rst
  60. 7
      account_financial_report/readme/ROADMAP.rst
  61. 137
      account_financial_report/report/abstract_report.py
  62. 472
      account_financial_report/report/abstract_report_xlsx.py
  63. 951
      account_financial_report/report/aged_partner_balance.py
  64. 362
      account_financial_report/report/aged_partner_balance_xlsx.py
  65. 2565
      account_financial_report/report/general_ledger.py
  66. 358
      account_financial_report/report/general_ledger_xlsx.py
  67. 1185
      account_financial_report/report/journal_ledger.py
  68. 300
      account_financial_report/report/journal_ledger_xlsx.py
  69. 1207
      account_financial_report/report/open_items.py
  70. 208
      account_financial_report/report/open_items_xlsx.py
  71. 537
      account_financial_report/report/templates/aged_partner_balance.xml
  72. 666
      account_financial_report/report/templates/general_ledger.xml
  73. 567
      account_financial_report/report/templates/journal_ledger.xml
  74. 22
      account_financial_report/report/templates/layouts.xml
  75. 244
      account_financial_report/report/templates/open_items.xml
  76. 1165
      account_financial_report/report/templates/trial_balance.xml
  77. 184
      account_financial_report/report/templates/vat_report.xml
  78. 1294
      account_financial_report/report/trial_balance.py
  79. 347
      account_financial_report/report/trial_balance_xlsx.py
  80. 555
      account_financial_report/report/vat_report.py
  81. 60
      account_financial_report/report/vat_report_xlsx.py
  82. 158
      account_financial_report/reports.xml
  83. 72
      account_financial_report/static/description/index.html
  84. 28
      account_financial_report/static/src/css/report.css
  85. 120
      account_financial_report/static/src/js/account_financial_report_backend.js
  86. 86
      account_financial_report/static/src/js/account_financial_report_widgets.js
  87. 35
      account_financial_report/static/src/js/action_manager_report.js
  88. 51
      account_financial_report/static/src/js/client_action.js
  89. 58
      account_financial_report/static/src/js/report.js
  90. 17
      account_financial_report/static/src/xml/report.xml
  91. 5
      account_financial_report/tests/__init__.py
  92. 399
      account_financial_report/tests/abstract_test.py
  93. 78
      account_financial_report/tests/abstract_test_foreign_currency.py
  94. 75
      account_financial_report/tests/abstract_test_tax_report.py
  95. 41
      account_financial_report/tests/test_aged_partner_balance.py
  96. 835
      account_financial_report/tests/test_general_ledger.py
  97. 570
      account_financial_report/tests/test_journal_ledger.py
  98. 57
      account_financial_report/tests/test_open_items.py
  99. 1116
      account_financial_report/tests/test_trial_balance.py
  100. 594
      account_financial_report/tests/test_vat_report.py

4
.editorconfig

@ -7,11 +7,11 @@ indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.{json,yml,yaml,rst,md}]
[.eslintrc,*.{json,yml,yaml,rst,md}]
indent_size = 2
# Do not configure editor for libs and autogenerated content
[{*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst}]
[*/static/{lib,src/lib}/**,*/static/description/index.html,*/readme/../README.rst]
charset = unset
end_of_line = unset
indent_size = unset

180
.eslintrc.yml

@ -1,180 +0,0 @@
env:
browser: true
# See https://github.com/OCA/odoo-community.org/issues/37#issuecomment-470686449
parserOptions:
ecmaVersion: 2017
# Globals available in Odoo that shouldn't produce errorings
globals:
_: readonly
$: readonly
fuzzy: readonly
jQuery: readonly
moment: readonly
odoo: readonly
openerp: readonly
Promise: 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
rules:
accessor-pairs: warn
array-callback-return: warn
callback-return: warn
capitalized-comments:
- warn
- always
- ignoreConsecutiveComments: true
ignoreInlineComments: true
complexity:
- warn
- 15
constructor-super: warn
dot-notation: warn
eqeqeq: warn
global-require: warn
handle-callback-err: warn
id-blacklist: warn
id-match: warn
init-declarations: error
max-depth: warn
max-nested-callbacks: warn
max-statements-per-line: warn
no-alert: warn
no-array-constructor: warn
no-caller: warn
no-case-declarations: warn
no-class-assign: warn
no-cond-assign: error
no-const-assign: error
no-constant-condition: warn
no-control-regex: warn
no-debugger: error
no-delete-var: warn
no-div-regex: warn
no-dupe-args: error
no-dupe-class-members: error
no-dupe-keys: error
no-duplicate-case: error
no-duplicate-imports: error
no-else-return: warn
no-empty-character-class: warn
no-empty-function: error
no-empty-pattern: error
no-empty: warn
no-eq-null: error
no-eval: error
no-ex-assign: error
no-extend-native: warn
no-extra-bind: warn
no-extra-boolean-cast: warn
no-extra-label: warn
no-fallthrough: warn
no-func-assign: error
no-global-assign: error
no-implicit-coercion:
- warn
- allow: ["~"]
no-implicit-globals: warn
no-implied-eval: warn
no-inline-comments: warn
no-inner-declarations: warn
no-invalid-regexp: warn
no-irregular-whitespace: warn
no-iterator: warn
no-label-var: warn
no-labels: warn
no-lone-blocks: warn
no-lonely-if: error
no-mixed-requires: error
no-multi-str: warn
no-native-reassign: error
no-negated-condition: warn
no-negated-in-lhs: error
no-new-func: warn
no-new-object: warn
no-new-require: warn
no-new-symbol: warn
no-new-wrappers: warn
no-new: warn
no-obj-calls: warn
no-octal-escape: warn
no-octal: warn
no-param-reassign: warn
no-path-concat: warn
no-process-env: warn
no-process-exit: warn
no-proto: warn
no-prototype-builtins: warn
no-redeclare: warn
no-regex-spaces: warn
no-restricted-globals: warn
no-restricted-imports: warn
no-restricted-modules: warn
no-restricted-syntax: warn
no-return-assign: error
no-script-url: warn
no-self-assign: warn
no-self-compare: warn
no-sequences: warn
no-shadow-restricted-names: warn
no-shadow: warn
no-sparse-arrays: warn
no-sync: warn
no-this-before-super: warn
no-throw-literal: warn
no-undef-init: warn
no-undef: error
no-unmodified-loop-condition: warn
no-unneeded-ternary: error
no-unreachable: error
no-unsafe-finally: error
no-unused-expressions: error
no-unused-labels: error
no-unused-vars: error
no-use-before-define: error
no-useless-call: warn
no-useless-computed-key: warn
no-useless-concat: warn
no-useless-constructor: warn
no-useless-escape: warn
no-useless-rename: warn
no-void: warn
no-with: warn
operator-assignment: [error, always]
prefer-const: warn
radix: warn
require-yield: warn
sort-imports: warn
spaced-comment: [error, always]
strict: [error, function]
use-isnan: error
valid-jsdoc:
- warn
- prefer:
arg: param
argument: param
augments: extends
constructor: class
exception: throws
func: function
method: function
prop: property
return: returns
virtual: abstract
yield: yields
preferType:
array: Array
bool: Boolean
boolean: Boolean
number: Number
object: Object
str: String
string: String
requireParamDescription: false
requireReturn: false
requireReturnDescription: false
requireReturnType: false
valid-typeof: warn
yoda: warn

10
.flake8

@ -1,10 +0,0 @@
[flake8]
max-line-length = 80
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

12
.isort.cfg

@ -1,12 +0,0 @@
[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

103
.pre-commit-config.yaml

@ -1,103 +0,0 @@
exclude: |
(?x)
# Files and folders generated by bots, to avoid loops
^setup/|/static/description/index\.html$|
# 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
^docs/_templates/.*\.html$|
# You don't usually want a bot to modify your legal texts
(LICENSE.*|COPYING.*)
default_language_version:
python: python3
node: "14.13.0"
repos:
- repo: https://github.com/psf/black
rev: 19.10b0
hooks:
- id: black
- repo: https://github.com/prettier/pre-commit
rev: "v1.19.1"
hooks:
- id: prettier
# TODO Avoid awebdeveloper/pre-commit-prettier if possible
# HACK https://github.com/prettier/prettier/issues/7407
- repo: https://github.com/awebdeveloper/pre-commit-prettier
rev: v0.0.1
hooks:
- id: prettier
name: prettier xml plugin
additional_dependencies:
- "prettier@1.19.1"
- "@prettier/plugin-xml@0.7.2"
files: \.xml$
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v6.8.0
hooks:
- id: eslint
verbose: true
args:
- --color
- --fix
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.4.0
hooks:
- id: trailing-whitespace
# exclude autogenerated files
exclude: /README\.rst$|\.pot?$
- id: end-of-file-fixer
# exclude autogenerated files
exclude: /README\.rst$|\.pot?$
- id: debug-statements
- id: fix-encoding-pragma
args: ["--remove"]
- id: check-case-conflict
- id: check-docstring-first
- id: check-executables-have-shebangs
- id: check-merge-conflict
# exclude files where underlines are not distinguishable from merge conflicts
exclude: /README\.rst$|^docs/.*\.rst$
- id: check-symlinks
- id: check-xml
- id: mixed-line-ending
args: ["--fix=lf"]
- repo: https://gitlab.com/pycqa/flake8
rev: 3.7.9
hooks:
- id: flake8
name: flake8 except __init__.py
exclude: /__init__\.py$
additional_dependencies: ["flake8-bugbear==19.8.0"]
- id: flake8
name: flake8 only __init__.py
args: ["--extend-ignore=F401"] # ignore unused imports in __init__.py
files: /__init__\.py$
additional_dependencies: ["flake8-bugbear==19.8.0"]
- repo: https://github.com/pre-commit/mirrors-pylint
rev: v2.5.3
hooks:
- id: pylint
name: pylint with optional checks
args: ["--rcfile=.pylintrc", "--exit-zero"]
verbose: true
additional_dependencies: ["pylint-odoo==3.5.0"]
- id: pylint
name: pylint with mandatory checks
args: ["--rcfile=.pylintrc-mandatory"]
additional_dependencies: ["pylint-odoo==3.5.0"]
- repo: https://github.com/asottile/pyupgrade
rev: v1.26.2
hooks:
- id: pyupgrade
- repo: https://github.com/pre-commit/mirrors-isort
rev: v4.3.21
hooks:
- id: isort
name: isort except __init__.py
exclude: /__init__\.py$
- repo: https://github.com/acsone/setuptools-odoo
rev: 2.5.2
hooks:
- id: setuptools-odoo-make-default

8
.prettierrc.yml

@ -1,8 +0,0 @@
# Defaults for all prettier-supported languages.
# Prettier will complete this with settings from .editorconfig file.
bracketSpacing: false
printWidth: 88
proseWrap: always
semi: true
trailingComma: "es5"
xmlWhitespaceSensitivity: "ignore"

88
.pylintrc

@ -1,88 +0,0 @@
[MASTER]
load-plugins=pylint_odoo
score=n
[ODOOLINT]
readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
manifest_required_authors=Odoo Community Association (OCA)
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=13.0
[MESSAGES CONTROL]
disable=all
# This .pylintrc contains optional AND mandatory checks and is meant to be
# loaded in an IDE to have it check everything, in the hope this will make
# optional checks more visible to contributors who otherwise never look at a
# green travis to see optional checks that failed.
# .pylintrc-mandatory containing only mandatory checks is used the pre-commit
# config as a blocking check.
enable=anomalous-backslash-in-string,
api-one-deprecated,
api-one-multi-together,
assignment-from-none,
attribute-deprecated,
class-camelcase,
dangerous-default-value,
dangerous-view-replace-wo-priority,
development-status-allowed,
duplicate-id-csv,
duplicate-key,
duplicate-xml-fields,
duplicate-xml-record-id,
eval-referenced,
eval-used,
incoherent-interpreter-exec-perm,
license-allowed,
manifest-author-string,
manifest-deprecated-key,
manifest-required-author,
manifest-required-key,
manifest-version-format,
method-compute,
method-inverse,
method-required-super,
method-search,
missing-import-error,
missing-manifest-dependency,
openerp-exception-warning,
pointless-statement,
pointless-string-statement,
print-used,
redundant-keyword-arg,
redundant-modulename-xml,
reimported,
relative-import,
return-in-init,
rst-syntax-error,
sql-injection,
too-few-format-args,
translation-field,
translation-required,
unreachable,
use-vim-comment,
wrong-tabs-instead-of-spaces,
xml-syntax-error,
# messages that do not cause the lint step to fail
consider-merging-classes-inherited,
create-user-wo-reset-password,
dangerous-filter-wo-user,
deprecated-module,
file-not-used,
invalid-commit,
missing-newline-extrafiles,
missing-readme,
no-utf8-coding-comment,
odoo-addons-relative-import,
old-api7-method-defined,
redefined-builtin,
too-complex,
unnecessary-utf8-coding-comment
[REPORTS]
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
output-format=colorized
reports=no

66
.pylintrc-mandatory

@ -1,66 +0,0 @@
[MASTER]
load-plugins=pylint_odoo
score=n
[ODOOLINT]
readme_template_url="https://github.com/OCA/maintainer-tools/blob/master/template/module/README.rst"
manifest_required_authors=Odoo Community Association (OCA)
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=13.0
[MESSAGES CONTROL]
disable=all
enable=anomalous-backslash-in-string,
api-one-deprecated,
api-one-multi-together,
assignment-from-none,
attribute-deprecated,
class-camelcase,
dangerous-default-value,
dangerous-view-replace-wo-priority,
development-status-allowed,
duplicate-id-csv,
duplicate-key,
duplicate-xml-fields,
duplicate-xml-record-id,
eval-referenced,
eval-used,
incoherent-interpreter-exec-perm,
license-allowed,
manifest-author-string,
manifest-deprecated-key,
manifest-required-author,
manifest-required-key,
manifest-version-format,
method-compute,
method-inverse,
method-required-super,
method-search,
missing-import-error,
missing-manifest-dependency,
openerp-exception-warning,
pointless-statement,
pointless-string-statement,
print-used,
redundant-keyword-arg,
redundant-modulename-xml,
reimported,
relative-import,
return-in-init,
rst-syntax-error,
sql-injection,
too-few-format-args,
translation-field,
translation-required,
unreachable,
use-vim-comment,
wrong-tabs-instead-of-spaces,
xml-syntax-error
[REPORTS]
msg-template={path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
output-format=colorized
reports=no

45
.travis.yml

@ -1,45 +1,32 @@
language: python
cache:
directories:
- $HOME/.cache/pip
- $HOME/.cache/pre-commit
python:
- "3.6"
sudo: false
cache: pip
addons:
postgresql: "9.6"
apt:
packages:
- expect-dev # provides unbuffer utility
- python-lxml # because pip installation is slow
stages:
- linting
- test
jobs:
include:
- stage: linting
name: "pre-commit"
before_install:
install: pip install pre-commit
script: pre-commit run --all --show-diff-on-failure --verbose --color always
after_success:
- stage: test
env:
- TESTS="1" ODOO_REPO="odoo/odoo" MAKEPOT="1"
- stage: test
env:
- TESTS="1" ODOO_REPO="OCA/OCB"
language: python
python:
- "3.5"
env:
global:
- VERSION="13.0" TESTS="0" LINT_CHECK="0" MAKEPOT="0"
- VERSION="12.0" TESTS="0" LINT_CHECK="0"
matrix:
- LINT_CHECK="1"
- TESTS="1" ODOO_REPO="OCA/OCB"
- TESTS="1" ODOO_REPO="odoo/odoo" MAKEPOT="1"
install:
- git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git
${HOME}/maintainer-quality-tools
- git clone https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
- export WKHTMLTOPDF_VERSION=0.12.4
- travis_install_nightly
script:

9
README.md

@ -1,6 +1,6 @@
[![Runbot Status](https://runbot.odoo-community.org/runbot/badge/flat/91/13.0.svg)](https://runbot.odoo-community.org/runbot/repo/github-com-oca-account-financial-reporting-91)
[![Build Status](https://travis-ci.org/OCA/account-financial-reporting.svg?branch=13.0)](https://travis-ci.org/OCA/account-financial-reporting)
[![Coverage Status](https://coveralls.io/repos/OCA/account-financial-reporting/badge.png?branch=13.0)](https://coveralls.io/r/OCA/account-financial-reporting?branch=13.0)
[![Runbot Status](https://runbot.odoo-community.org/runbot/badge/flat/91/12.0.svg)](https://runbot.odoo-community.org/runbot/repo/github-com-oca-account-financial-reporting-91)
[![Build Status](https://travis-ci.org/OCA/account-financial-reporting.svg?branch=12.0)](https://travis-ci.org/OCA/account-financial-reporting)
[![Coverage Status](https://coveralls.io/repos/OCA/account-financial-reporting/badge.png?branch=12.0)](https://coveralls.io/r/OCA/account-financial-reporting?branch=12.0)
Odoo account financial reports
==============================
@ -12,3 +12,6 @@ others:
* One module based on webkit and totally rewritten by camptocamp, for standard
financial reports.
* Another based on RML completely improved by Vauxoo.

82
account_export_csv/README.rst

@ -0,0 +1,82 @@
==================
Account Export CSV
==================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--reporting-lightgray.png?logo=github
:target: https://github.com/OCA/account-financial-reporting/tree/12.0/account_export_csv
:alt: OCA/account-financial-reporting
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/account-financial-reporting-12-0/account-financial-reporting-12-0-account_export_csv
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/91/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
Add a wizard that allow you to export a csv file based on accounting
journal entries
- Trial Balance
- Analytic Balance (with accounts)
- Journal Entries
You can filter by date range
**Table of contents**
.. contents::
:local:
Known issues / Roadmap
======================
* rearange wizard view with only one button to generate file plus define a selection list to select report type
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-financial-reporting/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_export_csv%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Camptocamp
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/account-financial-reporting <https://github.com/OCA/account-financial-reporting/tree/12.0/account_export_csv>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
account_export_csv/__init__.py

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

20
account_export_csv/__manifest__.py

@ -0,0 +1,20 @@
# Copyright 2013 Camptocamp SA
# Copyright 2017 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Account Export CSV',
'summary': "Adds accounting CSV export",
'version': '12.0.1.2.0',
'depends': [
'account',
'date_range',
],
'author': "Camptocamp,Odoo Community Association (OCA)",
'website': 'http://www.camptocamp.com',
'license': 'AGPL-3',
'data': [
'wizard/account_export_csv_view.xml',
],
'installable': True,
}

294
account_export_csv/i18n/account_export_csv.pot

@ -0,0 +1,294 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_export_csv
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "<span string=\"-\" class=\"oe_inline\"/>"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:256
#, python-format
msgid "ACCOUNT CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:175
#: code:addons/account_export_csv/wizard/account_export_csv.py:267
#, python-format
msgid "ACCOUNT NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:269
#, python-format
msgid "AMOUNT CURRENCY"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:263
#, python-format
msgid "ANALYTIC ACCOUNT CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:271
#, python-format
msgid "ANALYTIC ACCOUNT NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:172
#, python-format
msgid "ANALYTIC CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:173
#, python-format
msgid "ANALYTIC NAME"
msgstr ""
#. module: account_export_csv
#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export
#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Accounting CSV Export"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Analytic Balance (with accounts)"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:121
#: code:addons/account_export_csv/wizard/account_export_csv.py:178
#: code:addons/account_export_csv/wizard/account_export_csv.py:268
#, python-format
msgid "BALANCE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:275
#, python-format
msgid "BANK STATEMENT"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:117
#: code:addons/account_export_csv/wizard/account_export_csv.py:174
#, python-format
msgid "CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:120
#: code:addons/account_export_csv/wizard/account_export_csv.py:177
#: code:addons/account_export_csv/wizard/account_export_csv.py:261
#, python-format
msgid "CREDIT"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__data
msgid "CSV"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:270
#, python-format
msgid "CURRENCY"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Close"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__company_id
msgid "Company"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_uid
msgid "Created by"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_date
msgid "Created on"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:254
#, python-format
msgid "DATE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:119
#: code:addons/account_export_csv/wizard/account_export_csv.py:176
#: code:addons/account_export_csv/wizard/account_export_csv.py:260
#, python-format
msgid "DEBIT"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:259
#, python-format
msgid "DESCRIPTION"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Date"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_end
msgid "Date End"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_start
msgid "Date Start"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_range_id
msgid "Date range"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__display_name
msgid "Display Name"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:266
#, python-format
msgid "ENTRY NUMBER"
msgstr ""
#. module: account_export_csv
#: model:ir.model,name:account_export_csv.model_account_csv_export
msgid "Export Accounting"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__export_filename
msgid "Export CSV Filename"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:262
#, python-format
msgid "FULL RECONCILE"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__id
msgid "ID"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,help:account_export_csv.field_account_csv_export__journal_ids
msgid "If empty, use all journals, only used for journal entries"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:272
#, python-format
msgid "JOURNAL"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:255
#, python-format
msgid "JOURNAL CODE"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Journal Entries"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__journal_ids
msgid "Journals"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export____last_update
msgid "Last Modified on"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_uid
msgid "Last Updated by"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_date
msgid "Last Updated on"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:118
#, python-format
msgid "NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:257
#, python-format
msgid "PARTNER NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:258
#, python-format
msgid "REF"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Report"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:273
#, python-format
msgid "TAX CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:274
#, python-format
msgid "TAX NAME"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Trial Balance"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "or"
msgstr ""

297
account_export_csv/i18n/es_AR.po

@ -0,0 +1,297 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_export_csv
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2020-09-10 19:00+0000\n"
"Last-Translator: Ignacio Buioli <ibuioli@gmail.com>\n"
"Language-Team: none\n"
"Language: es_AR\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 3.10\n"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "<span string=\"-\" class=\"oe_inline\"/>"
msgstr "<span string=\"-\" class=\"oe_inline\"/>"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:256
#, python-format
msgid "ACCOUNT CODE"
msgstr "CÓDIGO DE CUENTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:175
#: code:addons/account_export_csv/wizard/account_export_csv.py:267
#, python-format
msgid "ACCOUNT NAME"
msgstr "NOMBRE DE CUENTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:269
#, python-format
msgid "AMOUNT CURRENCY"
msgstr "MONEDA DE LA CUENTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:263
#, python-format
msgid "ANALYTIC ACCOUNT CODE"
msgstr "CÓDIGO DE LA CUENTA ANALÍTICA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:271
#, python-format
msgid "ANALYTIC ACCOUNT NAME"
msgstr "NOMBRE DE LA CUENTA ANALÍTICA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:172
#, python-format
msgid "ANALYTIC CODE"
msgstr "CÓDIGO ANALÍTICO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:173
#, python-format
msgid "ANALYTIC NAME"
msgstr "NOMBRE ANALÍTICO"
#. module: account_export_csv
#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export
#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Accounting CSV Export"
msgstr "Exportar CSV de Contabilidad"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Analytic Balance (with accounts)"
msgstr "Saldo Analítico (con cuentas)"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:121
#: code:addons/account_export_csv/wizard/account_export_csv.py:178
#: code:addons/account_export_csv/wizard/account_export_csv.py:268
#, python-format
msgid "BALANCE"
msgstr "SALDO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:275
#, python-format
msgid "BANK STATEMENT"
msgstr "DECLARACIÓN BANCARIA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:117
#: code:addons/account_export_csv/wizard/account_export_csv.py:174
#, python-format
msgid "CODE"
msgstr "CÓDIGO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:120
#: code:addons/account_export_csv/wizard/account_export_csv.py:177
#: code:addons/account_export_csv/wizard/account_export_csv.py:261
#, python-format
msgid "CREDIT"
msgstr "CRÉDITO"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__data
msgid "CSV"
msgstr "CSV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:270
#, python-format
msgid "CURRENCY"
msgstr "MONEDA"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Close"
msgstr "Cerrar"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__company_id
msgid "Company"
msgstr "Compañía"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_uid
msgid "Created by"
msgstr "Creado por"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_date
msgid "Created on"
msgstr "Creado en"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:254
#, python-format
msgid "DATE"
msgstr "FECHA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:119
#: code:addons/account_export_csv/wizard/account_export_csv.py:176
#: code:addons/account_export_csv/wizard/account_export_csv.py:260
#, python-format
msgid "DEBIT"
msgstr "DÉBITO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:259
#, python-format
msgid "DESCRIPTION"
msgstr "DESCRIPCIÓN"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Date"
msgstr "Fecha"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_end
msgid "Date End"
msgstr "Fecha fin"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_start
msgid "Date Start"
msgstr "Fecha inicio"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_range_id
msgid "Date range"
msgstr "Periodo"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__display_name
msgid "Display Name"
msgstr "Mostrar Nombre"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:266
#, python-format
msgid "ENTRY NUMBER"
msgstr "NÚMERO DE ENTRADA"
#. module: account_export_csv
#: model:ir.model,name:account_export_csv.model_account_csv_export
msgid "Export Accounting"
msgstr "Exportar Contabilidad"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__export_filename
msgid "Export CSV Filename"
msgstr "Exportar Nombre del archivo CSV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:262
#, python-format
msgid "FULL RECONCILE"
msgstr "RECONCILIACIÓN COMPLETA"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__id
msgid "ID"
msgstr "ID"
#. module: account_export_csv
#: model:ir.model.fields,help:account_export_csv.field_account_csv_export__journal_ids
msgid "If empty, use all journals, only used for journal entries"
msgstr ""
"Si está vacío, usa todos los diarios, solo se usa para entradas de diario"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:272
#, python-format
msgid "JOURNAL"
msgstr "DIARIO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:255
#, python-format
msgid "JOURNAL CODE"
msgstr "CÓDIGO DEL DIARIO"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Journal Entries"
msgstr "Asientos Contables"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__journal_ids
msgid "Journals"
msgstr "Diarios"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export____last_update
msgid "Last Modified on"
msgstr "Última modificación en"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_uid
msgid "Last Updated by"
msgstr "Última modificación por"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_date
msgid "Last Updated on"
msgstr "Última actualización en"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:118
#, python-format
msgid "NAME"
msgstr "NOMBRE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:257
#, python-format
msgid "PARTNER NAME"
msgstr "NOMBRE DEL SOCIO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:258
#, python-format
msgid "REF"
msgstr "REF"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Report"
msgstr "Reporte"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:273
#, python-format
msgid "TAX CODE"
msgstr "CÓDIGO DE IMPUESTO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:274
#, python-format
msgid "TAX NAME"
msgstr "NOMBRE DE IMPUESTO"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Trial Balance"
msgstr "Balance de Sumas y Saldos"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "or"
msgstr "o"

307
account_export_csv/i18n/fr.po

@ -0,0 +1,307 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_export_csv
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-04-10 15:11+0000\n"
"PO-Revision-Date: 2021-08-03 17:49+0000\n"
"Last-Translator: Pascal GOUHIER <pascal.gouhier@copagex.fr>\n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 4.3.2\n"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "<span string=\"-\" class=\"oe_inline\"/>"
msgstr "<span string=\"-\" class=\"oe_inline\"/>"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:256
#, python-format
msgid "ACCOUNT CODE"
msgstr "Numéro de compte"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:175
#: code:addons/account_export_csv/wizard/account_export_csv.py:267
#, python-format
msgid "ACCOUNT NAME"
msgstr "NOM DU COMPTE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:269
#, python-format
msgid "AMOUNT CURRENCY"
msgstr "MONTANT EN DEVISE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:263
#, python-format
msgid "ANALYTIC ACCOUNT CODE"
msgstr "CODE DU COMPTE ANALYTIQUE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:271
#, python-format
msgid "ANALYTIC ACCOUNT NAME"
msgstr "NOM DU COMPTE ANALYTIQUE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:172
#, python-format
msgid "ANALYTIC CODE"
msgstr "CODE ANALYTIQUE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:173
#, python-format
msgid "ANALYTIC NAME"
msgstr "NOM ANALYTIQUE"
#. module: account_export_csv
#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export
#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Accounting CSV Export"
msgstr "Export comptable CSV"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Analytic Balance (with accounts)"
msgstr "Balance analytique (avec comptes)"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:121
#: code:addons/account_export_csv/wizard/account_export_csv.py:178
#: code:addons/account_export_csv/wizard/account_export_csv.py:268
#, python-format
msgid "BALANCE"
msgstr "BALANCE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:275
#, python-format
msgid "BANK STATEMENT"
msgstr "RELEVE BANCAIRE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:117
#: code:addons/account_export_csv/wizard/account_export_csv.py:174
#, python-format
msgid "CODE"
msgstr "CODE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:120
#: code:addons/account_export_csv/wizard/account_export_csv.py:177
#: code:addons/account_export_csv/wizard/account_export_csv.py:261
#, python-format
msgid "CREDIT"
msgstr "CREDIT"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__data
msgid "CSV"
msgstr "CSV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:270
#, python-format
msgid "CURRENCY"
msgstr "DEVISE"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Close"
msgstr "Fermer"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__company_id
msgid "Company"
msgstr "Société"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_uid
msgid "Created by"
msgstr "Créé par"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_date
msgid "Created on"
msgstr "Créé le"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:254
#, python-format
msgid "DATE"
msgstr "Date"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:119
#: code:addons/account_export_csv/wizard/account_export_csv.py:176
#: code:addons/account_export_csv/wizard/account_export_csv.py:260
#, python-format
msgid "DEBIT"
msgstr "Débit"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:259
#, python-format
msgid "DESCRIPTION"
msgstr "DESCRIPTION"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Date"
msgstr "Date"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_end
msgid "Date End"
msgstr "Date de fin"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_start
msgid "Date Start"
msgstr "Date de début de période"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_range_id
msgid "Date range"
msgstr "Période"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:266
#, python-format
msgid "ENTRY NUMBER"
msgstr "Numéro d'écriture"
#. module: account_export_csv
#: model:ir.model,name:account_export_csv.model_account_csv_export
msgid "Export Accounting"
msgstr "Export comptable"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__export_filename
msgid "Export CSV Filename"
msgstr "Nom du fichier CSV d'export"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:262
#, python-format
msgid "FULL RECONCILE"
msgstr "RECONCILIATION COMPLETE"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__id
msgid "ID"
msgstr "ID"
#. module: account_export_csv
#: model:ir.model.fields,help:account_export_csv.field_account_csv_export__journal_ids
msgid "If empty, use all journals, only used for journal entries"
msgstr ""
"Si vide, utilise tous les journaux, utilisé uniquement pour les écritures"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:272
#, python-format
msgid "JOURNAL"
msgstr "JOURNAL"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:255
#, python-format
msgid "JOURNAL CODE"
msgstr "CODE DU JOURNAL"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Journal Entries"
msgstr "Ecritures comptables"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__journal_ids
msgid "Journals"
msgstr "Journaux"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_uid
msgid "Last Updated by"
msgstr "Dernière mise à jour par"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:118
#, python-format
msgid "NAME"
msgstr "NOM"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:257
#, python-format
msgid "PARTNER NAME"
msgstr "Nom du partenaire"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:258
#, python-format
msgid "REF"
msgstr "REF"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Report"
msgstr "Rapport"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:273
#, python-format
msgid "TAX CODE"
msgstr "CODE DE TAXE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:274
#, python-format
msgid "TAX NAME"
msgstr "NOM DE TAXE"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Trial Balance"
msgstr "Balance générale"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "or"
msgstr "ou"
#~ msgid "All periods in the fiscal year if empty"
#~ msgstr "Toutes les périodes de l'année fiscale si vide"
#~ msgid "Periods"
#~ msgstr "Périodes"
#~ msgid "Fiscalyear"
#~ msgstr "Année fiscale"

297
account_export_csv/i18n/hr.po

@ -0,0 +1,297 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_export_csv
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2020-03-05 12:13+0000\n"
"Last-Translator: Bole <bole@dajmi5.com>\n"
"Language-Team: none\n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 3.10\n"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "<span string=\"-\" class=\"oe_inline\"/>"
msgstr "<span string=\"-\" class=\"oe_inline\"/>"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:256
#, python-format
msgid "ACCOUNT CODE"
msgstr "ŠIFRA KONTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:175
#: code:addons/account_export_csv/wizard/account_export_csv.py:267
#, python-format
msgid "ACCOUNT NAME"
msgstr "NAZIV KONTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:269
#, python-format
msgid "AMOUNT CURRENCY"
msgstr "IZNOS U VALUTI"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:263
#, python-format
msgid "ANALYTIC ACCOUNT CODE"
msgstr "ŠIFRA ANALITIČKOG KONTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:271
#, python-format
msgid "ANALYTIC ACCOUNT NAME"
msgstr "NAZIV ANALITIČKOG KONTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:172
#, python-format
msgid "ANALYTIC CODE"
msgstr "ŠIFRA ANALITIKE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:173
#, python-format
msgid "ANALYTIC NAME"
msgstr "NAZIV ANALITIKE"
#. module: account_export_csv
#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export
#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Accounting CSV Export"
msgstr "Izvoz podataka u CSV"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Analytic Balance (with accounts)"
msgstr "Analitički saldo (sa kontima)"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:121
#: code:addons/account_export_csv/wizard/account_export_csv.py:178
#: code:addons/account_export_csv/wizard/account_export_csv.py:268
#, python-format
msgid "BALANCE"
msgstr "SALDO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:275
#, python-format
msgid "BANK STATEMENT"
msgstr "BANKOVNI IZVOD"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:117
#: code:addons/account_export_csv/wizard/account_export_csv.py:174
#, python-format
msgid "CODE"
msgstr "ŠIFRA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:120
#: code:addons/account_export_csv/wizard/account_export_csv.py:177
#: code:addons/account_export_csv/wizard/account_export_csv.py:261
#, python-format
msgid "CREDIT"
msgstr "POTRAŽUJE"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__data
msgid "CSV"
msgstr "CSV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:270
#, python-format
msgid "CURRENCY"
msgstr "VALUTA"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Close"
msgstr "Zatvori"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__company_id
msgid "Company"
msgstr "Tvrtka"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_uid
msgid "Created by"
msgstr "Kreirao"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_date
msgid "Created on"
msgstr "Kreirano"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:254
#, python-format
msgid "DATE"
msgstr "DATUM"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:119
#: code:addons/account_export_csv/wizard/account_export_csv.py:176
#: code:addons/account_export_csv/wizard/account_export_csv.py:260
#, python-format
msgid "DEBIT"
msgstr "DUGUJE"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:259
#, python-format
msgid "DESCRIPTION"
msgstr "OPIS"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Date"
msgstr "Datum"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_end
msgid "Date End"
msgstr "Završni datum"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_start
msgid "Date Start"
msgstr "Početni datum"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_range_id
msgid "Date range"
msgstr "Raspon datuma"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__display_name
msgid "Display Name"
msgstr "Naziv"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:266
#, python-format
msgid "ENTRY NUMBER"
msgstr "BROJ STAVKE"
#. module: account_export_csv
#: model:ir.model,name:account_export_csv.model_account_csv_export
msgid "Export Accounting"
msgstr "Izvoz podataka računovodstva"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__export_filename
msgid "Export CSV Filename"
msgstr "Naziv CVS datoteke"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:262
#, python-format
msgid "FULL RECONCILE"
msgstr "POTPUNO ZATVORENO"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__id
msgid "ID"
msgstr "ID"
#. module: account_export_csv
#: model:ir.model.fields,help:account_export_csv.field_account_csv_export__journal_ids
msgid "If empty, use all journals, only used for journal entries"
msgstr "Ako je prazno, koristi sve dnevnike, samo se odnosi na stavke dnevnika"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:272
#, python-format
msgid "JOURNAL"
msgstr "DNEVNIK"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:255
#, python-format
msgid "JOURNAL CODE"
msgstr "ŠIFRA DNEVNIKA"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Journal Entries"
msgstr "Stavke dnevnika"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__journal_ids
msgid "Journals"
msgstr "Dnevnici"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export____last_update
msgid "Last Modified on"
msgstr "Zadnje modificirano"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_uid
msgid "Last Updated by"
msgstr "Zadnje ažurirao"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_date
msgid "Last Updated on"
msgstr "Zadnje ažurirano"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:118
#, python-format
msgid "NAME"
msgstr "NAZIV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:257
#, python-format
msgid "PARTNER NAME"
msgstr "NAZIV PARTNERA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:258
#, python-format
msgid "REF"
msgstr "REF"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Report"
msgstr "Izvještaj"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:273
#, python-format
msgid "TAX CODE"
msgstr "ŠIFRA POREZA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:274
#, python-format
msgid "TAX NAME"
msgstr "NAZIV POREZA"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Trial Balance"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "or"
msgstr "ili"

305
account_export_csv/i18n/nl.po

@ -0,0 +1,305 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * account_export_csv
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-22 12:52+0000\n"
"PO-Revision-Date: 2013-08-22 12:52+0000\n"
"Last-Translator: <stefan@therp.nl>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "<span string=\"-\" class=\"oe_inline\"/>"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:256
#, python-format
msgid "ACCOUNT CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:175
#: code:addons/account_export_csv/wizard/account_export_csv.py:267
#, python-format
msgid "ACCOUNT NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:269
#, python-format
msgid "AMOUNT CURRENCY"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:263
#, python-format
msgid "ANALYTIC ACCOUNT CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:271
#, python-format
msgid "ANALYTIC ACCOUNT NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:172
#, python-format
msgid "ANALYTIC CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:173
#, python-format
msgid "ANALYTIC NAME"
msgstr ""
#. module: account_export_csv
#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export
#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Accounting CSV Export"
msgstr "CSV export financiën"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Analytic Balance (with accounts)"
msgstr "Kostenplaatsenbalans (met rekeningen)"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:121
#: code:addons/account_export_csv/wizard/account_export_csv.py:178
#: code:addons/account_export_csv/wizard/account_export_csv.py:268
#, python-format
msgid "BALANCE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:275
#, python-format
msgid "BANK STATEMENT"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:117
#: code:addons/account_export_csv/wizard/account_export_csv.py:174
#, python-format
msgid "CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:120
#: code:addons/account_export_csv/wizard/account_export_csv.py:177
#: code:addons/account_export_csv/wizard/account_export_csv.py:261
#, python-format
msgid "CREDIT"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__data
msgid "CSV"
msgstr "CSV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:270
#, python-format
msgid "CURRENCY"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Close"
msgstr "Sluiten"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__company_id
msgid "Company"
msgstr "Bedrijf"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_uid
msgid "Created by"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_date
msgid "Created on"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:254
#, python-format
msgid "DATE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:119
#: code:addons/account_export_csv/wizard/account_export_csv.py:176
#: code:addons/account_export_csv/wizard/account_export_csv.py:260
#, python-format
msgid "DEBIT"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:259
#, python-format
msgid "DESCRIPTION"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Date"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_end
msgid "Date End"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_start
msgid "Date Start"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_range_id
msgid "Date range"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__display_name
msgid "Display Name"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:266
#, python-format
msgid "ENTRY NUMBER"
msgstr ""
#. module: account_export_csv
#: model:ir.model,name:account_export_csv.model_account_csv_export
msgid "Export Accounting"
msgstr "Export Financiën"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__export_filename
msgid "Export CSV Filename"
msgstr "Export CSV bestandsnaam"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:262
#, python-format
msgid "FULL RECONCILE"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__id
msgid "ID"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,help:account_export_csv.field_account_csv_export__journal_ids
msgid "If empty, use all journals, only used for journal entries"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:272
#, python-format
msgid "JOURNAL"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:255
#, python-format
msgid "JOURNAL CODE"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Journal Entries"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__journal_ids
msgid "Journals"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export____last_update
msgid "Last Modified on"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_uid
msgid "Last Updated by"
msgstr ""
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_date
msgid "Last Updated on"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:118
#, python-format
msgid "NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:257
#, python-format
msgid "PARTNER NAME"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:258
#, python-format
msgid "REF"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Report"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:273
#, python-format
msgid "TAX CODE"
msgstr ""
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:274
#, python-format
msgid "TAX NAME"
msgstr ""
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Trial Balance"
msgstr "Proefbalans"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "or"
msgstr ""
#~ msgid "All periods in the fiscal year if empty"
#~ msgstr "Alle periodes van het boekjaar indien leeg"
#~ msgid "Periods"
#~ msgstr "Periodes"
#~ msgid "Fiscalyear"
#~ msgstr "Boekjaar"

296
account_export_csv/i18n/pt.po

@ -0,0 +1,296 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_export_csv
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2020-06-17 23:19+0000\n"
"Last-Translator: Fernando Colus <fcolus1@gmail.com>\n"
"Language-Team: none\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n > 1;\n"
"X-Generator: Weblate 3.10\n"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "<span string=\"-\" class=\"oe_inline\"/>"
msgstr "<span string=\"-\" class=\"oe_inline\"/>"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:256
#, python-format
msgid "ACCOUNT CODE"
msgstr "CÓDIGO DE CONTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:175
#: code:addons/account_export_csv/wizard/account_export_csv.py:267
#, python-format
msgid "ACCOUNT NAME"
msgstr "NOME DA CONTA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:269
#, python-format
msgid "AMOUNT CURRENCY"
msgstr "MONTANTE DA MOEDA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:263
#, python-format
msgid "ANALYTIC ACCOUNT CODE"
msgstr "CÓDIGO DE CONTA ANALÍTICA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:271
#, python-format
msgid "ANALYTIC ACCOUNT NAME"
msgstr "NOME DA CONTA ANALÍTICA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:172
#, python-format
msgid "ANALYTIC CODE"
msgstr "CÓDIGO ANALÍTICO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:173
#, python-format
msgid "ANALYTIC NAME"
msgstr "NOME ANALÍTICO"
#. module: account_export_csv
#: model:ir.actions.act_window,name:account_export_csv.action_account_csv_export
#: model:ir.ui.menu,name:account_export_csv.menu_account_csv_export
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Accounting CSV Export"
msgstr "Exportador de Contas csv"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Analytic Balance (with accounts)"
msgstr "Saldo Analítico (com contas)"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:121
#: code:addons/account_export_csv/wizard/account_export_csv.py:178
#: code:addons/account_export_csv/wizard/account_export_csv.py:268
#, python-format
msgid "BALANCE"
msgstr "SALDO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:275
#, python-format
msgid "BANK STATEMENT"
msgstr "EXTRATO BANCÁRIO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:117
#: code:addons/account_export_csv/wizard/account_export_csv.py:174
#, python-format
msgid "CODE"
msgstr "CÓDIGO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:120
#: code:addons/account_export_csv/wizard/account_export_csv.py:177
#: code:addons/account_export_csv/wizard/account_export_csv.py:261
#, python-format
msgid "CREDIT"
msgstr "CRÉDITO"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__data
msgid "CSV"
msgstr "CSV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:270
#, python-format
msgid "CURRENCY"
msgstr "DIVISA"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Close"
msgstr "Fecho"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__company_id
msgid "Company"
msgstr "Empresa"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_uid
msgid "Created by"
msgstr "Criado por"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__create_date
msgid "Created on"
msgstr "Criado em"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:254
#, python-format
msgid "DATE"
msgstr "DATA"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:119
#: code:addons/account_export_csv/wizard/account_export_csv.py:176
#: code:addons/account_export_csv/wizard/account_export_csv.py:260
#, python-format
msgid "DEBIT"
msgstr "DÉBITO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:259
#, python-format
msgid "DESCRIPTION"
msgstr "DESCRIÇÃO"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Date"
msgstr "Data"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_end
msgid "Date End"
msgstr "Data Final"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_start
msgid "Date Start"
msgstr "Data Inicial"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__date_range_id
msgid "Date range"
msgstr "Período"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__display_name
msgid "Display Name"
msgstr "Exibir nome"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:266
#, python-format
msgid "ENTRY NUMBER"
msgstr "NÚMERO DO MOVIMENTO"
#. module: account_export_csv
#: model:ir.model,name:account_export_csv.model_account_csv_export
msgid "Export Accounting"
msgstr "Exportar Contabilidade"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__export_filename
msgid "Export CSV Filename"
msgstr "Exportar Ficheiro CSV"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:262
#, python-format
msgid "FULL RECONCILE"
msgstr "RECONCILIAÇÃO COMPLETA"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__id
msgid "ID"
msgstr "ID"
#. module: account_export_csv
#: model:ir.model.fields,help:account_export_csv.field_account_csv_export__journal_ids
msgid "If empty, use all journals, only used for journal entries"
msgstr "Se vazio, usa todos os diários, apenas usada para movimentos de diário"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:272
#, python-format
msgid "JOURNAL"
msgstr "DIÁRIO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:255
#, python-format
msgid "JOURNAL CODE"
msgstr "CÓDIGO DE DIÁRIO"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Journal Entries"
msgstr "Movimentos de Diário"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__journal_ids
msgid "Journals"
msgstr "Diários"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export____last_update
msgid "Last Modified on"
msgstr "Última modificação em"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_uid
msgid "Last Updated by"
msgstr "Última Atualização Feita em"
#. module: account_export_csv
#: model:ir.model.fields,field_description:account_export_csv.field_account_csv_export__write_date
msgid "Last Updated on"
msgstr "Última Atualização em"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:118
#, python-format
msgid "NAME"
msgstr "NOME"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:257
#, python-format
msgid "PARTNER NAME"
msgstr "NOME DO PARCEIRO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:258
#, python-format
msgid "REF"
msgstr "REF"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Report"
msgstr "Relatório"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:273
#, python-format
msgid "TAX CODE"
msgstr "CÓDIGO DE IMPOSTO"
#. module: account_export_csv
#: code:addons/account_export_csv/wizard/account_export_csv.py:274
#, python-format
msgid "TAX NAME"
msgstr "NOME DE IMPOSTO"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "Trial Balance"
msgstr "Balancete"
#. module: account_export_csv
#: model_terms:ir.ui.view,arch_db:account_export_csv.account_csv_export_view
msgid "or"
msgstr "ou"

16
account_export_csv/readme/CONTRBUTORS.rst

@ -0,0 +1,16 @@
* Camptocamp
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
* Alexandre Fayolle <alexandre.fayolle@camptocamp.com>
* Vincent Renaville <vincent.renaville@camptocamp.com>
* Guewen Baconnier <guewen.baconnier@camptocamp.com>
* Acsone
* Stéphane Bidoul <stephane.bidoul@acsone.eu>
* Laetitia Gangloff <laetitia.gangloff@acsone.eu>
* Adrien Peiffer <adrien.peiffer@acsone.eu>
* Akretion
* David Béal <david.beal@akretion.com>

9
account_export_csv/readme/DESCRIPTION.rst

@ -0,0 +1,9 @@
Add a wizard that allow you to export a csv file based on accounting
journal entries
- Trial Balance
- Analytic Balance (with accounts)
- Journal Entries
You can filter by date range

2
account_export_csv/readme/ROADMAP.rst

@ -0,0 +1,2 @@
* rearange wizard view with only one button to generate file plus define a selection list to select report type

BIN
account_export_csv/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 9.2 KiB

426
account_export_csv/static/description/index.html

@ -0,0 +1,426 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<title>Account Export CSV</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="account-export-csv">
<h1 class="title">Account Export CSV</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/12.0/account_export_csv"><img alt="OCA/account-financial-reporting" src="https://img.shields.io/badge/github-OCA%2Faccount--financial--reporting-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-financial-reporting-12-0/account-financial-reporting-12-0-account_export_csv"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/91/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>Add a wizard that allow you to export a csv file based on accounting
journal entries</p>
<ul class="simple">
<li>Trial Balance</li>
<li>Analytic Balance (with accounts)</li>
<li>Journal Entries</li>
</ul>
<p>You can filter by date range</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#known-issues-roadmap" id="id1">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id2">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id3">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id4">Authors</a></li>
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id1">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>rearange wizard view with only one button to generate file plus define a selection list to select report type</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id2">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-financial-reporting/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_export_csv%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id3">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id4">Authors</a></h2>
<ul class="simple">
<li>Camptocamp</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/12.0/account_export_csv">OCA/account-financial-reporting</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

1
account_export_csv/tests/__init__.py

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

52
account_export_csv/tests/test_account_export_csv.py

@ -0,0 +1,52 @@
# Copyright 2017 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import date
from dateutil import relativedelta
import base64
from odoo.tests.common import TransactionCase
from odoo import fields
class TestAccountExportCsv(TransactionCase):
def setUp(self):
super(TestAccountExportCsv, self).setUp()
self.report_wizard = self.env['account.csv.export']
today_dt = date.today()
next_month_date = today_dt + relativedelta.relativedelta(months=1)
self.report_date_start = fields.Date.to_string(today_dt)
self.report_date_end = fields.Date.to_string(next_month_date)
def test_1(self):
report_wizard = self.report_wizard.create({
'date_start': self.report_date_start,
'date_end': self.report_date_end
})
report_wizard.action_manual_export_account()
def test_2(self):
report_wizard = self.report_wizard.create({
'date_start': self.report_date_start,
'date_end': self.report_date_end
})
report_wizard.action_manual_export_analytic()
def test_3(self):
report_wizard = self.report_wizard.create({
'date_start': self.report_date_start,
'date_end': self.report_date_end
})
report_wizard.action_manual_export_journal_entries()
def test_file_content(self):
report_wizard = self.report_wizard.create({
"date_start": "2000-01-01",
"date_end": "2200-01-01",
})
report_wizard.action_manual_export_journal_entries()
res = base64.decodestring(report_wizard.data)
line_number = self.env["account.move.line"].search_count([])
# check the number of lines in file: include header + EOF line
self.assertEqual(len(res.decode().split("\r\n")), line_number + 2)

1
account_export_csv/wizard/__init__.py

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

354
account_export_csv/wizard/account_export_csv.py

@ -0,0 +1,354 @@
# Copyright 2013 Camptocamp SA
# Copyright 2017 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import itertools
import tempfile
from io import StringIO, BytesIO
import base64
import csv
import codecs
from odoo import api, fields, models, _
class AccountingWriter(object):
"""
A CSV writer which will write rows to CSV file "f",
which is encoded in the given encoding.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
# Redirect output to a queue
self.queue = StringIO()
# created a writer with Excel formating settings
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
# we ensure that we do not try to encode none or bool
row = (x or '' for x in row)
self.writer.writerow(row)
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
# ... and reencode it into the target encoding as BytesIO
data = self.encoder.encode(data)
# write to the target stream
self.stream.write(data)
# seek() or truncate() have side effect if not used combinated
self.queue.truncate(0)
self.queue.seek(0)
# https://stackoverflow.com/questions/4330812/how-do-i-clear-a-stringio-object
# It fails when you use `self.queue = StringIO()` only add one line
def writerows(self, rows):
for row in rows:
self.writerow(row)
# https://docs.python.org/3/library/io.html#io.IOBase.close
self.queue.close()
class AccountCSVExport(models.TransientModel):
_name = 'account.csv.export'
_description = 'Export Accounting'
data = fields.Binary('CSV', readonly=True)
company_id = fields.Many2one(
comodel_name='res.company', string='Company', invisible=True,
default=lambda self: self._get_company_default())
date_start = fields.Date(required=True)
date_end = fields.Date(required=True)
date_range_id = fields.Many2one(
comodel_name='date.range', string='Date range')
journal_ids = fields.Many2many(
comodel_name='account.journal', string='Journals',
default=lambda s: s._get_journal_default(),
help='If empty, use all journals, only used for journal entries')
export_filename = fields.Char(
string='Export CSV Filename', size=128, default='account_export.csv')
@api.model
def _get_journal_default(self):
""" Implements your own default """
return False
@api.model
def _get_company_default(self):
return self.env.user.company_id
@api.onchange('date_range_id')
def _onchange_date_range(self):
if self.date_range_id:
self.date_start = self.date_range_id.date_start
self.date_end = self.date_range_id.date_end
@api.onchange('date_start', 'date_end')
def _onchange_dates(self):
if self.date_range_id:
if self.date_start != self.date_range_id.date_start or \
self.date_end != self.date_range_id.date_end:
self.date_range_id = False
def action_manual_export_account(self):
self.ensure_one()
rows = self._get_data("account")
file_data = BytesIO()
try:
writer = AccountingWriter(file_data)
writer.writerows(rows)
file_value = file_data.getvalue()
self.write({'data': base64.encodestring(file_value)})
finally:
file_data.close()
return {
'type': 'ir.actions.act_window',
'res_model': 'account.csv.export',
'view_mode': 'form',
'res_id': self.id,
'views': [(False, 'form')],
'target': 'new',
}
def _get_header_account(self):
return [
_('CODE'),
_('NAME'),
_('DEBIT'),
_('CREDIT'),
_('BALANCE'),
]
def _get_rows_account(self, journal_ids):
"""
Return list to generate rows of the CSV file
"""
self.ensure_one()
self.env.cr.execute("""
select ac.code,ac.name,
sum(debit) as sum_debit,
sum(credit) as sum_credit,
sum(debit) - sum(credit) as balance
from account_move_line as aml,account_account as ac
where aml.account_id = ac.id
AND aml.date >= %(date_start)s
AND aml.date <= %(date_end)s
group by ac.id,ac.code,ac.name
order by ac.code
""", {'date_start': self.date_start,
'date_end': self.date_end})
res = self.env.cr.fetchall()
rows = []
for line in res:
rows.append(list(line))
return rows
def action_manual_export_analytic(self):
self.ensure_one()
rows = self._get_data("analytic")
file_data = BytesIO()
try:
writer = AccountingWriter(file_data)
writer.writerows(rows)
file_value = file_data.getvalue()
self.write({'data': base64.encodestring(file_value)})
finally:
file_data.close()
return {
'type': 'ir.actions.act_window',
'res_model': 'account.csv.export',
'view_mode': 'form',
'view_type': 'form',
'res_id': self.id,
'views': [(False, 'form')],
'target': 'new',
}
def _get_header_analytic(self):
return [
_('ANALYTIC CODE'),
_('ANALYTIC NAME'),
_('CODE'),
_('ACCOUNT NAME'),
_('DEBIT'),
_('CREDIT'),
_('BALANCE'),
]
def _get_rows_analytic(self, journal_ids):
"""
Return list to generate rows of the CSV file
"""
self.ensure_one()
self.env.cr.execute(""" select aac.code as analytic_code,
aac.name as analytic_name,
ac.code,ac.name,
sum(debit) as sum_debit,
sum(credit) as sum_credit,
sum(debit) - sum(credit) as balance
from account_move_line
left outer join account_analytic_account as aac
on (account_move_line.analytic_account_id = aac.id)
inner join account_account as ac
on account_move_line.account_id = ac.id
AND account_move_line.date >= %(date_start)s
AND account_move_line.date <= %(date_end)s
group by aac.id,aac.code,aac.name,ac.id,ac.code,ac.name
order by aac.code
""", {'date_start': self.date_start,
'date_end': self.date_end})
res = self.env.cr.fetchall()
rows = []
for line in res:
rows.append(list(line))
return rows
def action_manual_export_journal_entries(self):
"""
Here we use TemporaryFile to avoid full filling the Odoo worker
Memory
We also write the data to the wizard with SQL query as write seems
to use too much memory as well.
Those improvements permitted to improve the export from a 100k line to
200k lines
with default `limit_memory_hard = 805306368` (768MB) with more lines,
you might encounter a MemoryError when trying to download the file even
if it has been generated.
To be able to export bigger volume of data, it is advised to set
limit_memory_hard to 2097152000 (2 GB) to generate the file and let
Odoo load it in the wizard when trying to download it.
Tested with up to a generation of 700k entry lines
"""
self.ensure_one()
rows = self._get_data("journal_entries")
with tempfile.TemporaryFile() as file_data:
writer = AccountingWriter(file_data)
writer.writerows(rows)
with tempfile.TemporaryFile() as base64_data:
file_data.seek(0)
base64.encode(file_data, base64_data)
base64_data.seek(0)
self.env.cr.execute("""
UPDATE account_csv_export
SET data = %s
WHERE id = %s""", (base64_data.read(), self.id))
return {
'type': 'ir.actions.act_window',
'res_model': 'account.csv.export',
'view_mode': 'form',
'res_id': self.id,
'views': [(False, 'form')],
'target': 'new',
}
def _get_header_journal_entries(self):
return [
# Standard Sage export fields
_('DATE'),
_('JOURNAL CODE'),
_('ACCOUNT CODE'),
_('PARTNER NAME'),
_('REF'),
_('DESCRIPTION'),
_('DEBIT'),
_('CREDIT'),
_('FULL RECONCILE'),
_('ANALYTIC ACCOUNT CODE'),
# Other fields
_('ENTRY NUMBER'),
_('ACCOUNT NAME'),
_('BALANCE'),
_('AMOUNT CURRENCY'),
_('CURRENCY'),
_('ANALYTIC ACCOUNT NAME'),
_('JOURNAL'),
_('TAX CODE'),
_('TAX NAME'),
_('BANK STATEMENT'),
]
def _get_rows_journal_entries(self, journal_ids):
"""
Create a generator of rows of the CSV file
"""
self.ensure_one()
self.env.cr.execute("""
SELECT
account_move_line.date AS date,
account_journal.name as journal,
account_account.code AS account_code,
res_partner.name AS partner_name,
account_move_line.ref AS ref,
account_move_line.name AS description,
account_move_line.debit AS debit,
account_move_line.credit AS credit,
account_full_reconcile.name as full_reconcile,
account_analytic_account.code AS analytic_account_code,
account_move.name AS entry_number,
account_account.name AS account_name,
account_move_line.debit - account_move_line.credit AS balance,
account_move_line.amount_currency AS amount_currency,
res_currency.name AS currency,
account_analytic_account.name AS analytic_account_name,
account_journal.name as journal,
acct.description as tax_code,
acct.name as tax_name,
account_bank_statement.name AS bank_statement
FROM
public.account_move_line
JOIN account_account on
(account_account.id=account_move_line.account_id)
JOIN account_journal on
(account_journal.id = account_move_line.journal_id)
LEFT JOIN res_currency on
(res_currency.id=account_move_line.currency_id)
LEFT JOIN account_full_reconcile on
(account_full_reconcile.id = account_move_line.full_reconcile_id)
LEFT JOIN res_partner on
(res_partner.id=account_move_line.partner_id)
LEFT JOIN account_move on
(account_move.id=account_move_line.move_id)
LEFT JOIN account_analytic_account on
(account_analytic_account.id=account_move_line.analytic_account_id)
LEFT JOIN account_bank_statement on
(account_bank_statement.id=account_move_line.statement_id)
LEFT JOIN account_tax acct on
(acct.id=account_move_line.tax_line_id)
WHERE account_move_line.date >= %(date_start)s
AND account_move_line.date <= %(date_end)s
AND account_journal.id IN %(journal_ids)s
ORDER BY account_move_line.date
""", {'journal_ids': tuple(journal_ids),
'date_start': self.date_start,
'date_end': self.date_end})
while 1:
# http://initd.org/psycopg/docs/cursor.html#cursor.fetchmany
# Set cursor.arraysize to minimize network round trips
self.env.cr.arraysize = 100
rows = self.env.cr.fetchmany()
if not rows:
break
for row in rows:
yield row
def _get_data(self, result_type):
self.ensure_one()
get_header_func = getattr(
self, ("_get_header_%s" % (result_type)), None)
get_rows_func = getattr(self, ("_get_rows_%s" % (result_type)), None)
if self.journal_ids:
journal_ids = [x.id for x in self.journal_ids]
else:
j_obj = self.env["account.journal"]
journal_ids = j_obj.search([]).ids
rows = itertools.chain((get_header_func(),),
get_rows_func(journal_ids))
return rows

64
account_export_csv/wizard/account_export_csv_view.xml

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="account_csv_export_view" model="ir.ui.view">
<field name="name">Accounting Entries CSV Export</field>
<field name="model">account.csv.export</field>
<field name="arch" type="xml">
<form string="Accounting CSV Export">
<group>
<group>
<field name="company_id" />
</group>
</group>
<group>
<group>
<field name="date_range_id" domain="['|', ('company_id', '=', company_id), ('company_id', '=', False)]"/>
<label for="date_start" string="Date" class="oe_inline"/>
<div>
<field name="date_start" class="oe_inline"/>
<span string="-" class="oe_inline"/>
<field name="date_end" class="oe_inline"/>
</div>
</group>
<group>
</group>
</group>
<div>
<label for="journal_ids" />
<field name="journal_ids"/>
</div>
<separator string ="Report" colspan="4"/>
<group colspan="4">
<field name="data" filename="export_filename"/>
</group>
<footer>
<button name="action_manual_export_account" string="Trial Balance" type="object" icon="fa-cog"/>
<button name="action_manual_export_analytic" string="Analytic Balance (with accounts)" type="object" icon="fa-cog"/>
<button name="action_manual_export_journal_entries" string="Journal Entries" type="object" icon="fa-cog"/>
or
<button string="Close" class="oe_link" special="cancel" />
</footer>
</form>
</field>
</record>
<record id="action_account_csv_export" model="ir.actions.act_window">
<field name="name">Accounting CSV Export</field>
<field name="res_model">account.csv.export</field>
<field name="type">ir.actions.act_window</field>
<field name="view_mode">form</field>
<field name="view_id" ref="account_csv_export_view"/>
<field name="target">new</field>
</record>
<menuitem
name="Accounting CSV Export"
action="action_account_csv_export"
id="menu_account_csv_export"
parent="account.menu_finance_reports"
sequence="110"
/>
</odoo>

39
account_financial_report/README.rst

@ -14,19 +14,19 @@ Account Financial Reports
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Faccount--financial--reporting-lightgray.png?logo=github
:target: https://github.com/OCA/account-financial-reporting/tree/13.0/account_financial_report
:target: https://github.com/OCA/account-financial-reporting/tree/12.0/account_financial_report
:alt: OCA/account-financial-reporting
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/account-financial-reporting-13-0/account-financial-reporting-13-0-account_financial_report
:target: https://translation.odoo-community.org/projects/account-financial-reporting-12-0/account-financial-reporting-12-0-account_financial_report
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/91/13.0
:target: https://runbot.odoo-community.org/runbot/91/12.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
This module adds a set of financial reports. They are accessible under
Invoicing / Reporting / OCA accounting reports.
Accounting / Reporting / OCA Reports.
- General ledger
- Trial Balance
@ -47,17 +47,6 @@ currency balances are not available.
.. contents::
:local:
Known issues / Roadmap
======================
* 'VAT Report' is valid only for cases where it's met that for each
Tax defined: all the "Account tags" of all the
'Repartition for Invoices' or 'Repartition for Credit Notes'
are different.
* It would be nice to have in reports a column indicating the
state of the entries when the option "All Entries" is selected
in "Target Moves" field in a wizard
Changelog
=========
@ -87,7 +76,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/account-financial-reporting/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_financial_report%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
`feedback <https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_financial_report%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
@ -100,12 +89,12 @@ Authors
* Camptocamp SA
* initOS GmbH
* redCOR AG
* ForgeFlow
* Eficent
Contributors
~~~~~~~~~~~~
* Jordi Ballester <jordi.ballester@forgeflow.com>
* Jordi Ballester <jordi.ballester@eficient.com>
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
* Simone Orsi <simone.orsi@abstract.com>
* Leonardo Pistone <leonardo.pistone@camptocamp.com>
@ -121,20 +110,14 @@ Contributors
* Akim Juillerat <akim.juillerat@camptocamp.com>
* Alexis de Lattre <alexis@via.ecp.fr>
* Mihai Fekete <feketemihai@gmail.com>
* Miquel Raïch <miquel.raich@forgeflow.com>
* Joan Sisquella <joan.sisquella@forgeflow.com>
* Miquel Raïch <miquel.raich@eficent.com>
* `Tecnativa <https://www.tecnativa.com>`__:
* Pedro M. Baeza
* Sergio Teruel
* Ernesto Tejeda
* Alexandre D. Díaz
* Lois Rilo <lois.rilo@forgeflow.com>
* `Sygel <https://www.sygel.es>`__:
* `Druidoo <https://www.druidoo.io>`__:
* Harald Panten
* Valentin Vinagre
* Iván Todorovich
Much of the work in this module was done at a sprint in Sorrento, Italy in
April 2016.
@ -152,6 +135,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/account-financial-reporting <https://github.com/OCA/account-financial-reporting/tree/13.0/account_financial_report>`_ project on GitHub.
This module is part of the `OCA/account-financial-reporting <https://github.com/OCA/account-financial-reporting/tree/12.0/account_financial_report>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

1
account_financial_report/__init__.py

@ -1,3 +1,4 @@
# Author: Damien Crier
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

82
account_financial_report/__manifest__.py

@ -1,48 +1,50 @@
# Author: Damien Crier
# Author: Julien Coux
# Copyright 2016 Camptocamp SA
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
"name": "Account Financial Reports",
"version": "13.0.1.8.0",
"category": "Reporting",
"summary": "OCA Financial Reports",
"author": "Camptocamp SA,"
"initOS GmbH,"
"redCOR AG,"
"ForgeFlow,"
"Odoo Community Association (OCA)",
'name': 'Account Financial Reports',
'version': '12.0.1.4.5',
'category': 'Reporting',
'summary': 'OCA Financial Reports',
'author': 'Camptocamp SA,'
'initOS GmbH,'
'redCOR AG,'
'Eficent,'
'Odoo Community Association (OCA)',
"website": "https://odoo-community.org/",
"depends": ["account", "date_range", "report_xlsx"],
"data": [
"wizard/aged_partner_balance_wizard_view.xml",
"wizard/general_ledger_wizard_view.xml",
"wizard/journal_ledger_wizard_view.xml",
"wizard/open_items_wizard_view.xml",
"wizard/trial_balance_wizard_view.xml",
"wizard/vat_report_wizard_view.xml",
"menuitems.xml",
"reports.xml",
"report/templates/layouts.xml",
"report/templates/aged_partner_balance.xml",
"report/templates/general_ledger.xml",
"report/templates/journal_ledger.xml",
"report/templates/open_items.xml",
"report/templates/trial_balance.xml",
"report/templates/vat_report.xml",
"view/account_view.xml",
"view/report_template.xml",
"view/report_general_ledger.xml",
"view/report_journal_ledger.xml",
"view/report_trial_balance.xml",
"view/report_open_items.xml",
"view/report_aged_partner_balance.xml",
"view/report_vat_report.xml",
'depends': [
'account',
'date_range',
'report_xlsx',
],
"qweb": ["static/src/xml/report.xml"],
"installable": True,
"application": True,
"auto_install": False,
"license": "AGPL-3",
'data': [
'wizard/aged_partner_balance_wizard_view.xml',
'wizard/general_ledger_wizard_view.xml',
'wizard/journal_ledger_wizard_view.xml',
'wizard/open_items_wizard_view.xml',
'wizard/trial_balance_wizard_view.xml',
'wizard/vat_report_wizard_view.xml',
'menuitems.xml',
'reports.xml',
'report/templates/layouts.xml',
'report/templates/aged_partner_balance.xml',
'report/templates/general_ledger.xml',
'report/templates/journal_ledger.xml',
'report/templates/open_items.xml',
'report/templates/trial_balance.xml',
'report/templates/vat_report.xml',
'view/account_view.xml',
'view/report_template.xml',
'view/report_general_ledger.xml',
'view/report_journal_ledger.xml',
'view/report_trial_balance.xml',
'view/report_open_items.xml',
'view/report_aged_partner_balance.xml',
'view/report_vat_report.xml',
],
'installable': True,
'application': True,
'auto_install': False,
'license': 'AGPL-3',
}

1775
account_financial_report/i18n/account_financial_report.pot
File diff suppressed because it is too large
View File

1886
account_financial_report/i18n/ar.po
File diff suppressed because it is too large
View File

2136
account_financial_report/i18n/ca.po
File diff suppressed because it is too large
View File

2633
account_financial_report/i18n/da.po
File diff suppressed because it is too large
View File

2139
account_financial_report/i18n/de.po
File diff suppressed because it is too large
View File

1872
account_financial_report/i18n/es.po
File diff suppressed because it is too large
View File

1829
account_financial_report/i18n/es_AR.po
File diff suppressed because it is too large
View File

2014
account_financial_report/i18n/fr.po
File diff suppressed because it is too large
View File

1930
account_financial_report/i18n/fr_CH.po
File diff suppressed because it is too large
View File

1876
account_financial_report/i18n/hr.po
File diff suppressed because it is too large
View File

1734
account_financial_report/i18n/hr_HR.po
File diff suppressed because it is too large
View File

2001
account_financial_report/i18n/it.po
File diff suppressed because it is too large
View File

1716
account_financial_report/i18n/ja.po
File diff suppressed because it is too large
View File

2014
account_financial_report/i18n/nl.po
File diff suppressed because it is too large
View File

1721
account_financial_report/i18n/nl_NL.po
File diff suppressed because it is too large
View File

2172
account_financial_report/i18n/pt.po
File diff suppressed because it is too large
View File

2084
account_financial_report/i18n/pt_BR.po
File diff suppressed because it is too large
View File

2049
account_financial_report/i18n/ro.po
File diff suppressed because it is too large
View File

2615
account_financial_report/i18n/sl.po
File diff suppressed because it is too large
View File

8
account_financial_report/menuitems.xml

@ -1,45 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<menuitem
parent="account.menu_finance_reports"
id="menu_oca_reports"
name="OCA accounting reports"
groups="account.group_account_manager,account.group_account_user"
/>
<menuitem
parent="menu_oca_reports"
action="action_general_ledger_wizard"
id="menu_general_ledger_wizard"
sequence="10"
/>
<menuitem
parent="menu_oca_reports"
action="action_journal_ledger_wizard"
id="menu_journal_ledger_wizard"
sequence="15"
/>
<menuitem
parent="menu_oca_reports"
action="action_trial_balance_wizard"
id="menu_trial_balance_wizard"
sequence="20"
/>
<menuitem
parent="menu_oca_reports"
action="action_open_items_wizard"
id="menu_open_items_wizard"
sequence="30"
/>
<menuitem
parent="menu_oca_reports"
action="action_aged_partner_balance_wizard"
id="menu_aged_partner_balance_wizard"
sequence="40"
/>
<menuitem
parent="menu_oca_reports"
action="action_vat_report_wizard"
id="menu_vat_report_wizard"
sequence="50"
/>
</odoo>

1
account_financial_report/models/__init__.py

@ -1,4 +1,3 @@
from . import account
from . import account_group
from . import account_move_line
from . import ir_actions_report

9
account_financial_report/models/account.py

@ -1,14 +1,13 @@
# © 2011 Guewen Baconnier (Camptocamp)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).-
from odoo import fields, models
from odoo import models, fields
class AccountAccount(models.Model):
_inherit = "account.account"
_inherit = 'account.account'
centralized = fields.Boolean(
"Centralized",
'Centralized',
help="If flagged, no details will be displayed in "
"the General Ledger report (the webkit one only), "
"only centralized amounts per period.",
)
"only centralized amounts per period.")

63
account_financial_report/models/account_group.py

@ -5,43 +5,27 @@ from odoo import api, fields, models
class AccountGroup(models.Model):
_inherit = "account.group"
_inherit = 'account.group'
group_child_ids = fields.One2many(
comodel_name="account.group", inverse_name="parent_id", string="Child Groups"
)
level = fields.Integer(string="Level", compute="_compute_level", store=True)
comodel_name='account.group',
inverse_name='parent_id',
string='Child Groups')
level = fields.Integer(
string='Level',
compute='_compute_level',
store=True)
account_ids = fields.One2many(
comodel_name="account.account", inverse_name="group_id", string="Accounts"
)
comodel_name='account.account',
inverse_name='group_id',
string="Accounts")
compute_account_ids = fields.Many2many(
"account.account",
compute="_compute_group_accounts",
string="Compute accounts",
store=True,
)
complete_name = fields.Char("Full Name", compute="_compute_complete_name")
complete_code = fields.Char("Full Code", compute="_compute_complete_code")
'account.account',
compute='_compute_group_accounts',
string="Compute accounts", store=True)
@api.depends("name", "parent_id.complete_name")
def _compute_complete_name(self):
""" Forms complete name of location from parent location to child location. """
if self.parent_id.complete_name:
self.complete_name = "{}/{}".format(self.parent_id.complete_name, self.name)
else:
self.complete_name = self.name
@api.depends("code_prefix", "parent_id.complete_code")
def _compute_complete_code(self):
""" Forms complete code of location from parent location to child location. """
if self.parent_id.complete_code:
self.complete_code = "{}/{}".format(
self.parent_id.complete_code, self.code_prefix
)
else:
self.complete_code = self.code_prefix
@api.depends("parent_id", "parent_id.level")
@api.multi
@api.depends('parent_id', 'parent_id.level')
def _compute_level(self):
for group in self:
if not group.parent_id:
@ -49,17 +33,14 @@ class AccountGroup(models.Model):
else:
group.level = group.parent_id.level + 1
@api.depends(
"code_prefix",
"account_ids",
"account_ids.code",
"group_child_ids",
"group_child_ids.account_ids.code",
)
@api.multi
@api.depends('code_prefix', 'account_ids', 'account_ids.code',
'group_child_ids', 'group_child_ids.account_ids.code')
def _compute_group_accounts(self):
account_obj = self.env["account.account"]
account_obj = self.env['account.account']
accounts = account_obj.search([])
for group in self:
prefix = group.code_prefix if group.code_prefix else group.name
gr_acc = accounts.filtered(lambda a: a.code.startswith(prefix)).ids
gr_acc = accounts.filtered(
lambda a: a.code.startswith(prefix)).ids
group.compute_account_ids = [(6, 0, gr_acc)]

24
account_financial_report/models/account_move_line.py

@ -4,8 +4,9 @@ from odoo import api, models
class AccountMoveLine(models.Model):
_inherit = "account.move.line"
_inherit = 'account.move.line'
@api.model_cr
def init(self):
"""
The join between accounts_partners subquery and account_move_line
@ -20,21 +21,10 @@ class AccountMoveLine(models.Model):
By adding the following index, performances are strongly increased.
:return:
"""
self._cr.execute(
"SELECT indexname FROM pg_indexes WHERE indexname = " "%s",
("account_move_line_account_id_partner_id_index",),
)
self._cr.execute('SELECT indexname FROM pg_indexes WHERE indexname = '
'%s',
('account_move_line_account_id_partner_id_index',))
if not self._cr.fetchone():
self._cr.execute(
"""
self._cr.execute("""
CREATE INDEX account_move_line_account_id_partner_id_index
ON account_move_line (account_id, partner_id)"""
)
@api.model
def search_count(self, args):
# In Big DataBase every time you change the domain widget this method
# takes a lot of time. This improves performance
if self.env.context.get("skip_search_count"):
return 0
return super(AccountMoveLine, self).search_count(args)
ON account_move_line (account_id, partner_id)""")

25
account_financial_report/models/ir_actions_report.py

@ -1,25 +0,0 @@
# Copyright 2020 Onestein (<https://www.onestein.eu>)
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import api, models
class IrActionsReport(models.Model):
_inherit = "ir.actions.report"
@api.model
def _prepare_account_financial_report_context(self, data):
lang = data and data.get("account_financial_report_lang") or ""
return dict(self.env.context or {}, lang=lang) if lang else False
@api.model
def render_qweb_html(self, docids, data=None):
context = self._prepare_account_financial_report_context(data)
obj = self.with_context(context) if context else self
return super(IrActionsReport, obj).render_qweb_html(docids, data)
@api.model
def render_xlsx(self, docids, data):
context = self._prepare_account_financial_report_context(data)
obj = self.with_context(context) if context else self
return super(IrActionsReport, obj).render_xlsx(docids, data)

14
account_financial_report/readme/CONTRIBUTORS.rst

@ -1,4 +1,4 @@
* Jordi Ballester <jordi.ballester@forgeflow.com>
* Jordi Ballester <jordi.ballester@eficient.com>
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
* Simone Orsi <simone.orsi@abstract.com>
* Leonardo Pistone <leonardo.pistone@camptocamp.com>
@ -14,20 +14,14 @@
* Akim Juillerat <akim.juillerat@camptocamp.com>
* Alexis de Lattre <alexis@via.ecp.fr>
* Mihai Fekete <feketemihai@gmail.com>
* Miquel Raïch <miquel.raich@forgeflow.com>
* Joan Sisquella <joan.sisquella@forgeflow.com>
* Miquel Raïch <miquel.raich@eficent.com>
* `Tecnativa <https://www.tecnativa.com>`__:
* Pedro M. Baeza
* Sergio Teruel
* Ernesto Tejeda
* Alexandre D. Díaz
* `Druidoo <https://www.druidoo.io>`__:
* Lois Rilo <lois.rilo@forgeflow.com>
* `Sygel <https://www.sygel.es>`__:
* Harald Panten
* Valentin Vinagre
* Iván Todorovich
Much of the work in this module was done at a sprint in Sorrento, Italy in
April 2016.

2
account_financial_report/readme/DESCRIPTION.rst

@ -1,5 +1,5 @@
This module adds a set of financial reports. They are accessible under
Invoicing / Reporting / OCA accounting reports.
Accounting / Reporting / OCA Reports.
- General ledger
- Trial Balance

7
account_financial_report/readme/ROADMAP.rst

@ -1,7 +0,0 @@
* 'VAT Report' is valid only for cases where it's met that for each
Tax defined: all the "Account tags" of all the
'Repartition for Invoices' or 'Repartition for Credit Notes'
are different.
* It would be nice to have in reports a column indicating the
state of the entries when the option "All Entries" is selected
in "Target Moves" field in a wizard

137
account_financial_report/report/abstract_report.py

@ -1,126 +1,23 @@
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
# Copyright 2018 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import api, models
from odoo import models
from psycopg2.extensions import AsIs
class AgedPartnerBalanceReport(models.AbstractModel):
_name = "report.account_financial_report.abstract_report"
_description = "Abstract Report"
class AbstractReport(models.AbstractModel):
_name = 'account_financial_report_abstract'
_description = 'Abstract Report'
@api.model
def _get_move_lines_domain_not_reconciled(
self, company_id, account_ids, partner_ids, only_posted_moves, date_from
):
domain = [
("account_id", "in", account_ids),
("company_id", "=", company_id),
("reconciled", "=", False),
]
if partner_ids:
domain += [("partner_id", "in", partner_ids)]
if only_posted_moves:
domain += [("move_id.state", "=", "posted")]
else:
domain += [("move_id.state", "in", ["posted", "draft"])]
if date_from:
domain += [("date", ">", date_from)]
return domain
@api.model
def _get_new_move_lines_domain(
self, new_ml_ids, account_ids, company_id, partner_ids, only_posted_moves
):
domain = [
("account_id", "in", account_ids),
("company_id", "=", company_id),
("id", "in", new_ml_ids),
]
if partner_ids:
domain += [("partner_id", "in", partner_ids)]
if only_posted_moves:
domain += [("move_id.state", "=", "posted")]
else:
domain += [("move_id.state", "in", ["posted", "draft"])]
return domain
def _recalculate_move_lines(
self,
move_lines,
debit_ids,
credit_ids,
debit_amount,
credit_amount,
ml_ids,
account_ids,
company_id,
partner_ids,
only_posted_moves,
):
debit_ids = set(debit_ids)
credit_ids = set(credit_ids)
in_credit_but_not_in_debit = credit_ids - debit_ids
reconciled_ids = list(debit_ids) + list(in_credit_but_not_in_debit)
reconciled_ids = set(reconciled_ids)
ml_ids = set(ml_ids)
new_ml_ids = reconciled_ids - ml_ids
new_ml_ids = list(new_ml_ids)
new_domain = self._get_new_move_lines_domain(
new_ml_ids, account_ids, company_id, partner_ids, only_posted_moves
)
ml_fields = [
"id",
"name",
"date",
"move_id",
"journal_id",
"account_id",
"partner_id",
"amount_residual",
"date_maturity",
"ref",
"debit",
"credit",
"reconciled",
"currency_id",
"amount_currency",
"amount_residual_currency",
]
new_move_lines = self.env["account.move.line"].search_read(
domain=new_domain, fields=ml_fields
def _transient_clean_rows_older_than(self, seconds):
assert self._transient, \
"Model %s is not transient, it cannot be vacuumed!" % self._name
# Never delete rows used in last 5 minutes
seconds = max(seconds, 300)
query = (
"DELETE FROM %s"
" WHERE COALESCE("
"write_date, create_date, (now() at time zone 'UTC'))"
"::timestamp < ((now() at time zone 'UTC') - interval %s)"
)
move_lines = move_lines + new_move_lines
for move_line in move_lines:
ml_id = move_line["id"]
if ml_id in debit_ids:
move_line["amount_residual"] += debit_amount[ml_id]
if ml_id in credit_ids:
move_line["amount_residual"] -= credit_amount[ml_id]
return move_lines
def _get_accounts_data(self, accounts_ids):
accounts = self.env["account.account"].browse(accounts_ids)
accounts_data = {}
for account in accounts:
accounts_data.update(
{
account.id: {
"id": account.id,
"code": account.code,
"name": account.name,
"hide_account": False,
"group_id": account.group_id.id,
"currency_id": account.currency_id or False,
"currency_name": account.currency_id.name,
"centralized": account.centralized,
}
}
)
return accounts_data
def _get_journals_data(self, journals_ids):
journals = self.env["account.journal"].browse(journals_ids)
journals_data = {}
for journal in journals:
journals_data.update({journal.id: {"id": journal.id, "code": journal.code}})
return journals_data
self.env.cr.execute(query, (AsIs(self._table), "%s seconds" % seconds))

472
account_financial_report/report/abstract_report_xlsx.py

@ -1,13 +1,16 @@
# Author: Julien Coux
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo import models
import datetime
from odoo.tools import format_date
class AbstractReportXslx(models.AbstractModel):
_name = "report.account_financial_report.abstract_report_xlsx"
_description = "Abstract XLSX Account Financial Report"
_inherit = "report.report_xlsx.abstract"
_name = 'report.account_financial_report.abstract_report_xlsx'
_inherit = 'report.report_xlsx.abstract'
def __init__(self, pool, cr):
# main sheet which will contains report
@ -32,16 +35,16 @@ class AbstractReportXslx(models.AbstractModel):
self.format_percent_bold_italic = None
def get_workbook_options(self):
return {"constant_memory": True}
return {'constant_memory': True}
def generate_xlsx_report(self, workbook, data, objects):
report = objects
self.row_pos = 0
self._define_formats(workbook, data)
self._define_formats(workbook)
report_name = self._get_report_name(report, data=data)
report_name = self._get_report_name(report)
report_footer = self._get_report_footer()
filters = self._get_report_filters(report)
self.columns = self._get_report_columns(report)
@ -54,13 +57,14 @@ class AbstractReportXslx(models.AbstractModel):
self._write_filters(filters)
self._generate_report_content(workbook, report, data)
self._generate_report_content(workbook, report)
self._write_report_footer(report_footer)
def _define_formats(self, workbook, data):
def _define_formats(self, workbook):
""" Add cell formats to current workbook.
Those formats can be used on all cell.
Available formats are :
* format_bold
* format_right
@ -72,60 +76,58 @@ class AbstractReportXslx(models.AbstractModel):
* format_amount
* format_percent_bold_italic
"""
self.format_bold = workbook.add_format({"bold": True})
self.format_right = workbook.add_format({"align": "right"})
self.format_left = workbook.add_format({"align": "left"})
self.format_bold = workbook.add_format({'bold': True})
self.format_right = workbook.add_format({'align': 'right'})
self.format_left = workbook.add_format({'align': 'left'})
self.format_right_bold_italic = workbook.add_format(
{"align": "right", "bold": True, "italic": True}
{'align': 'right', 'bold': True, 'italic': True}
)
self.format_header_left = workbook.add_format(
{"bold": True, "border": True, "bg_color": "#FFFFCC"}
)
{'bold': True,
'border': True,
'bg_color': '#FFFFCC'})
self.format_header_center = workbook.add_format(
{"bold": True, "align": "center", "border": True, "bg_color": "#FFFFCC"}
)
{'bold': True,
'align': 'center',
'border': True,
'bg_color': '#FFFFCC'})
self.format_header_right = workbook.add_format(
{"bold": True, "align": "right", "border": True, "bg_color": "#FFFFCC"}
)
{'bold': True,
'align': 'right',
'border': True,
'bg_color': '#FFFFCC'})
self.format_header_amount = workbook.add_format(
{"bold": True, "border": True, "bg_color": "#FFFFCC"}
)
company_id = data.get("company_id", False)
if company_id:
company = self.env["res.company"].browse(company_id)
currency = company.currency_id
else:
currency = self.env["res.company"]._get_user_currency()
{'bold': True,
'border': True,
'bg_color': '#FFFFCC'})
currency_id = self.env['res.company']._get_user_currency()
self.format_header_amount.set_num_format(
"#,##0." + "0" * currency.decimal_places
)
'#,##0.'+'0'*currency_id.decimal_places)
self.format_amount = workbook.add_format()
self.format_amount.set_num_format("#,##0." + "0" * currency.decimal_places)
self.format_amount_bold = workbook.add_format({"bold": True})
self.format_amount_bold.set_num_format("#,##0." + "0" * currency.decimal_places)
self.format_amount.set_num_format(
'#,##0.'+'0'*currency_id.decimal_places)
self.format_amount_bold = workbook.add_format({'bold': True})
self.format_amount_bold.set_num_format(
'#,##0.' + '0' * currency_id.decimal_places)
self.format_percent_bold_italic = workbook.add_format(
{"bold": True, "italic": True}
{'bold': True, 'italic': True}
)
self.format_percent_bold_italic.set_num_format("#,##0.00%")
self.format_percent_bold_italic.set_num_format('#,##0.00%')
def _set_column_width(self):
"""Set width for all defined columns.
Columns are defined with `_get_report_columns` method.
"""
for position, column in self.columns.items():
self.sheet.set_column(position, position, column["width"])
self.sheet.set_column(position, position, column['width'])
def _write_report_title(self, title):
"""Write report title on current line using all defined columns width.
Columns are defined with `_get_report_columns` method.
"""
self.sheet.merge_range(
self.row_pos,
0,
self.row_pos,
len(self.columns) - 1,
title,
self.format_bold,
self.row_pos, 0, self.row_pos, len(self.columns) - 1,
title, self.format_bold
)
self.row_pos += 3
@ -136,12 +138,8 @@ class AbstractReportXslx(models.AbstractModel):
if footer:
self.row_pos += 1
self.sheet.merge_range(
self.row_pos,
0,
self.row_pos,
len(self.columns) - 1,
footer,
self.format_left,
self.row_pos, 0, self.row_pos, len(self.columns) - 1,
footer, self.format_left
)
self.row_pos += 1
@ -158,20 +156,13 @@ class AbstractReportXslx(models.AbstractModel):
col_value = col_name + col_count_filter_name + 1
for title, value in filters:
self.sheet.merge_range(
self.row_pos,
col_name,
self.row_pos,
col_name + col_count_filter_name - 1,
title,
self.format_header_left,
)
self.row_pos, col_name,
self.row_pos, col_name + col_count_filter_name - 1,
title, self.format_header_left)
self.sheet.merge_range(
self.row_pos,
col_value,
self.row_pos,
col_value + col_count_filter_value - 1,
value,
)
self.row_pos, col_value,
self.row_pos, col_value + col_count_filter_value - 1,
value)
self.row_pos += 1
self.row_pos += 2
@ -180,12 +171,8 @@ class AbstractReportXslx(models.AbstractModel):
Columns are defined with `_get_report_columns` method.
"""
self.sheet.merge_range(
self.row_pos,
0,
self.row_pos,
len(self.columns) - 1,
title,
self.format_bold,
self.row_pos, 0, self.row_pos, len(self.columns) - 1,
title, self.format_bold
)
self.row_pos += 1
@ -194,9 +181,8 @@ class AbstractReportXslx(models.AbstractModel):
Columns are defined with `_get_report_columns` method.
"""
for col_pos, column in self.columns.items():
self.sheet.write(
self.row_pos, col_pos, column["header"], self.format_header_center
)
self.sheet.write(self.row_pos, col_pos, column['header'],
self.format_header_center)
self.row_pos += 1
def write_line(self, line_object):
@ -204,34 +190,30 @@ class AbstractReportXslx(models.AbstractModel):
Columns are defined with `_get_report_columns` method.
"""
for col_pos, column in self.columns.items():
value = getattr(line_object, column["field"])
cell_type = column.get("type", "string")
if cell_type == "many2one":
self.sheet.write_string(
self.row_pos, col_pos, value.name or "", self.format_right
)
elif cell_type == "string":
if (
hasattr(line_object, "account_group_id")
and line_object.account_group_id
):
value = getattr(line_object, column['field'])
if isinstance(value, datetime.date):
value = format_date(self.env, value)
cell_type = column.get('type', 'string')
if cell_type == 'many2one':
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_bold
)
self.row_pos, col_pos, value.name or '', self.format_right)
elif cell_type == 'string':
if hasattr(line_object, 'account_group_id') and \
line_object.account_group_id:
self.sheet.write_string(self.row_pos, col_pos, value or '',
self.format_bold)
else:
self.sheet.write_string(self.row_pos, col_pos, value or "")
elif cell_type == "amount":
if (
hasattr(line_object, "account_group_id")
and line_object.account_group_id
):
self.sheet.write_string(self.row_pos, col_pos, value or '')
elif cell_type == 'amount':
if hasattr(line_object, 'account_group_id') and \
line_object.account_group_id:
cell_format = self.format_amount_bold
else:
cell_format = self.format_amount
self.sheet.write_number(
self.row_pos, col_pos, float(value), cell_format
)
elif cell_type == "amount_currency":
elif cell_type == 'amount_currency':
if line_object.currency_id:
format_amt = self._get_currency_amt_format(line_object)
self.sheet.write_number(
@ -239,314 +221,151 @@ class AbstractReportXslx(models.AbstractModel):
)
self.row_pos += 1
def write_line_from_dict(self, line_dict):
"""Write a line on current line
"""
for col_pos, column in self.columns.items():
value = line_dict.get(column["field"], False)
cell_type = column.get("type", "string")
if cell_type == "string":
if (
line_dict.get("account_group_id", False)
and line_dict["account_group_id"]
):
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_bold
)
else:
if (
not isinstance(value, str)
and not isinstance(value, bool)
and not isinstance(value, int)
):
value = value and value.strftime("%d/%m/%Y")
self.sheet.write_string(self.row_pos, col_pos, value or "")
elif cell_type == "amount":
if (
line_dict.get("account_group_id", False)
and line_dict["account_group_id"]
):
cell_format = self.format_amount_bold
else:
cell_format = self.format_amount
self.sheet.write_number(
self.row_pos, col_pos, float(value), cell_format
)
elif cell_type == "amount_currency":
if line_dict.get("currency_name", False):
format_amt = self._get_currency_amt_format_dict(line_dict)
self.sheet.write_number(
self.row_pos, col_pos, float(value), format_amt
)
elif cell_type == "currency_name":
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_right
)
self.row_pos += 1
def write_initial_balance(self, my_object, label):
"""Write a specific initial balance line on current line
using defined columns field_initial_balance name.
Columns are defined with `_get_report_columns` method.
"""
col_pos_label = self._get_col_pos_initial_balance_label()
self.sheet.write(self.row_pos, col_pos_label, label, self.format_right)
for col_pos, column in self.columns.items():
if column.get("field_initial_balance"):
value = getattr(my_object, column["field_initial_balance"])
cell_type = column.get("type", "string")
if cell_type == "string":
self.sheet.write_string(self.row_pos, col_pos, value or "")
elif cell_type == "amount":
if column.get('field_initial_balance'):
value = getattr(my_object, column['field_initial_balance'])
cell_type = column.get('type', 'string')
if cell_type == 'string':
self.sheet.write_string(self.row_pos, col_pos, value or '')
elif cell_type == 'amount':
self.sheet.write_number(
self.row_pos, col_pos, float(value), self.format_amount
)
elif cell_type == "amount_currency":
elif cell_type == 'amount_currency':
if my_object.currency_id:
format_amt = self._get_currency_amt_format(my_object)
format_amt = self._get_currency_amt_format(
my_object)
self.sheet.write_number(
self.row_pos, col_pos, float(value), format_amt
self.row_pos, col_pos,
float(value), format_amt
)
elif column.get("field_currency_balance"):
value = getattr(my_object, column["field_currency_balance"])
cell_type = column.get("type", "string")
if cell_type == "many2one":
elif column.get('field_currency_balance'):
value = getattr(my_object, column['field_currency_balance'])
cell_type = column.get('type', 'string')
if cell_type == 'many2one':
if my_object.currency_id:
self.sheet.write_string(
self.row_pos, col_pos, value.name or "", self.format_right
)
self.row_pos += 1
def write_initial_balance_from_dict(self, my_object, label):
"""Write a specific initial balance line on current line
using defined columns field_initial_balance name.
Columns are defined with `_get_report_columns` method.
"""
col_pos_label = self._get_col_pos_initial_balance_label()
self.sheet.write(self.row_pos, col_pos_label, label, self.format_right)
for col_pos, column in self.columns.items():
if column.get("field_initial_balance"):
value = my_object.get(column["field_initial_balance"], False)
cell_type = column.get("type", "string")
if cell_type == "string":
self.sheet.write_string(self.row_pos, col_pos, value or "")
elif cell_type == "amount":
self.sheet.write_number(
self.row_pos, col_pos, float(value), self.format_amount
)
elif cell_type == "amount_currency":
if my_object["currency_id"]:
format_amt = self._get_currency_amt_format(my_object)
self.sheet.write_number(
self.row_pos, col_pos, float(value), format_amt
)
elif column.get("field_currency_balance"):
value = my_object.get(column["field_currency_balance"], False)
cell_type = column.get("type", "string")
if cell_type == "many2one":
if my_object["currency_id"]:
self.sheet.write_string(
self.row_pos, col_pos, value.name or "", self.format_right
self.row_pos, col_pos,
value.name or '',
self.format_right
)
self.row_pos += 1
def write_ending_balance(self, my_object, name, label):
"""Write a specific ending balance line on current line
using defined columns field_final_balance name.
Columns are defined with `_get_report_columns` method.
"""
for i in range(0, len(self.columns)):
self.sheet.write(self.row_pos, i, "", self.format_header_right)
self.sheet.write(self.row_pos, i, '', self.format_header_right)
row_count_name = self._get_col_count_final_balance_name()
col_pos_label = self._get_col_pos_final_balance_label()
self.sheet.merge_range(
self.row_pos,
0,
self.row_pos,
row_count_name - 1,
name,
self.format_header_left,
self.row_pos, 0, self.row_pos, row_count_name - 1, name,
self.format_header_left
)
self.sheet.write(self.row_pos, col_pos_label, label, self.format_header_right)
self.sheet.write(self.row_pos, col_pos_label, label,
self.format_header_right)
for col_pos, column in self.columns.items():
if column.get("field_final_balance"):
value = getattr(my_object, column["field_final_balance"])
cell_type = column.get("type", "string")
if cell_type == "string":
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_header_right
)
elif cell_type == "amount":
if column.get('field_final_balance'):
value = getattr(my_object, column['field_final_balance'])
cell_type = column.get('type', 'string')
if cell_type == 'string':
self.sheet.write_string(self.row_pos, col_pos, value or '',
self.format_header_right)
elif cell_type == 'amount':
self.sheet.write_number(
self.row_pos, col_pos, float(value), self.format_header_amount
self.row_pos, col_pos, float(value),
self.format_header_amount
)
elif cell_type == "amount_currency":
elif cell_type == 'amount_currency':
if my_object.currency_id:
format_amt = self._get_currency_amt_header_format(my_object)
format_amt = self._get_currency_amt_header_format(
my_object)
self.sheet.write_number(
self.row_pos, col_pos, float(value), format_amt
self.row_pos, col_pos, float(value),
format_amt
)
elif column.get("field_currency_balance"):
value = getattr(my_object, column["field_currency_balance"])
cell_type = column.get("type", "string")
if cell_type == "many2one":
elif column.get('field_currency_balance'):
value = getattr(my_object, column['field_currency_balance'])
cell_type = column.get('type', 'string')
if cell_type == 'many2one':
if my_object.currency_id:
self.sheet.write_string(
self.row_pos,
col_pos,
value.name or "",
self.format_header_right,
)
self.row_pos += 1
def write_ending_balance_from_dict(self, my_object, name, label):
"""Write a specific ending balance line on current line
using defined columns field_final_balance name.
Columns are defined with `_get_report_columns` method.
"""
for i in range(0, len(self.columns)):
self.sheet.write(self.row_pos, i, "", self.format_header_right)
row_count_name = self._get_col_count_final_balance_name()
col_pos_label = self._get_col_pos_final_balance_label()
self.sheet.merge_range(
self.row_pos,
0,
self.row_pos,
row_count_name - 1,
name,
self.format_header_left,
)
self.sheet.write(self.row_pos, col_pos_label, label, self.format_header_right)
for col_pos, column in self.columns.items():
if column.get("field_final_balance"):
value = my_object.get(column["field_final_balance"], False)
cell_type = column.get("type", "string")
if cell_type == "string":
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_header_right
)
elif cell_type == "amount":
self.sheet.write_number(
self.row_pos, col_pos, float(value), self.format_header_amount
)
elif cell_type == "amount_currency":
if my_object["currency_id"] and value:
format_amt = self._get_currency_amt_format_dict(my_object)
self.sheet.write_number(
self.row_pos, col_pos, float(value), format_amt
)
elif column.get("field_currency_balance"):
value = my_object.get(column["field_currency_balance"], False)
cell_type = column.get("type", "string")
if cell_type == "many2one":
if my_object["currency_id"]:
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_header_right
)
elif cell_type == "currency_name":
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_header_right
self.row_pos, col_pos,
value.name or '',
self.format_header_right
)
self.row_pos += 1
def _get_currency_amt_format(self, line_object):
""" Return amount format specific for each currency. """
if "account_group_id" in line_object and line_object["account_group_id"]:
format_amt = self.format_amount_bold
field_prefix = "format_amount_bold"
if hasattr(line_object, 'account_group_id') and \
line_object.account_group_id:
format_amt = getattr(self, 'format_amount_bold')
field_prefix = 'format_amount_bold'
else:
format_amt = self.format_amount
field_prefix = "format_amount"
if "currency_id" in line_object and line_object.get("currency_id", False):
field_name = "{}_{}".format(field_prefix, line_object["currency_id"].name)
if hasattr(self, field_name):
format_amt = getattr(self, field_name)
else:
format_amt = self.workbook.add_format()
self.field_name = format_amt
format_amount = "#,##0." + (
"0" * line_object["currency_id"].decimal_places
)
format_amt.set_num_format(format_amount)
return format_amt
def _get_currency_amt_format_dict(self, line_dict):
""" Return amount format specific for each currency. """
if line_dict.get("account_group_id", False) and line_dict["account_group_id"]:
format_amt = self.format_amount_bold
field_prefix = "format_amount_bold"
else:
format_amt = self.format_amount
field_prefix = "format_amount"
if line_dict.get("currency_id", False) and line_dict["currency_id"]:
if isinstance(line_dict["currency_id"], int):
currency = self.env["res.currency"].browse(line_dict["currency_id"])
else:
currency = line_dict["currency_id"]
field_name = "{}_{}".format(field_prefix, currency.name)
format_amt = getattr(self, 'format_amount')
field_prefix = 'format_amount'
if line_object.currency_id:
field_name = \
'%s_%s' % (field_prefix, line_object.currency_id.name)
if hasattr(self, field_name):
format_amt = getattr(self, field_name)
else:
format_amt = self.workbook.add_format()
self.field_name = format_amt
format_amount = "#,##0." + ("0" * currency.decimal_places)
setattr(self, 'field_name', format_amt)
format_amount = \
'#,##0.' + ('0' * line_object.currency_id.decimal_places)
format_amt.set_num_format(format_amount)
return format_amt
def _get_currency_amt_header_format(self, line_object):
""" Return amount header format for each currency. """
format_amt = self.format_header_amount
format_amt = getattr(self, 'format_header_amount')
if line_object.currency_id:
field_name = "format_header_amount_%s" % line_object.currency_id.name
field_name = \
'format_header_amount_%s' % line_object.currency_id.name
if hasattr(self, field_name):
format_amt = getattr(self, field_name)
else:
format_amt = self.workbook.add_format(
{"bold": True, "border": True, "bg_color": "#FFFFCC"}
)
self.field_name = format_amt
format_amount = "#,##0." + (
"0" * line_object.currency_id.decimal_places
)
{'bold': True,
'border': True,
'bg_color': '#FFFFCC'})
setattr(self, 'field_name', format_amt)
format_amount = \
'#,##0.' + ('0' * line_object.currency_id.decimal_places)
format_amt.set_num_format(format_amount)
return format_amt
def _get_currency_amt_header_format_dict(self, line_object):
""" Return amount header format for each currency. """
format_amt = self.format_header_amount
if line_object["currency_id"]:
field_name = "format_header_amount_%s" % line_object["currency_name"]
if hasattr(self, field_name):
format_amt = getattr(self, field_name)
else:
format_amt = self.workbook.add_format(
{"bold": True, "border": True, "bg_color": "#FFFFCC"}
)
self.field_name = format_amt
format_amount = "#,##0." + (
"0" * line_object["currency_id"].decimal_places
)
format_amt.set_num_format(format_amount)
return format_amt
def _generate_report_content(self, workbook, report, data):
def _generate_report_content(self, workbook, report):
"""
Allow to fetch report content to be displayed.
"""
raise NotImplementedError()
def _get_report_complete_name(self, report, prefix, data=None):
def _get_report_complete_name(self, report, prefix):
if report.company_id:
suffix = " - {} - {}".format(
report.company_id.name, report.company_id.currency_id.name
)
suffix = ' - %s - %s' % (
report.company_id.name, report.company_id.currency_id.name)
return prefix + suffix
return prefix
def _get_report_name(self, report, data=False):
def _get_report_name(self, report):
"""
Allow to define the report name.
Report name will be used as sheet name and as report title.
:return: the report name
"""
raise NotImplementedError()
@ -562,8 +381,11 @@ class AbstractReportXslx(models.AbstractModel):
"""
Allow to define the report columns
which will be used to generate report.
:return: the report columns as dict
:Example:
{
0: {'header': 'Simple column',
'field': 'field_name_on_my_object',
@ -579,7 +401,9 @@ class AbstractReportXslx(models.AbstractModel):
def _get_report_filters(self, report):
"""
:return: the report filters as list
:Example:
[
['first_filter_name', 'first_filter_value'],
['second_filter_name', 'second_filter_value']

951
account_financial_report/report/aged_partner_balance.py

@ -1,378 +1,633 @@
# © 2016 Julien Coux (Camptocamp)
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import operator
from datetime import date, datetime, timedelta
from odoo import models, fields, api
from odoo import api, models
from odoo.tools import float_is_zero
class AgedPartnerBalanceReport(models.TransientModel):
""" Here, we just define class fields.
For methods, go more bottom at this file.
class AgedPartnerBalanceReport(models.AbstractModel):
_name = "report.account_financial_report.aged_partner_balance"
_description = "Aged Partner Balance Report"
_inherit = "report.account_financial_report.abstract_report"
The class hierarchy is :
* AgedPartnerBalanceReport
** AgedPartnerBalanceReportAccount
*** AgedPartnerBalanceReportPartner
**** AgedPartnerBalanceReportLine
**** AgedPartnerBalanceReportMoveLine
If "show_move_line_details" is selected
"""
@api.model
def _initialize_account(self, ag_pb_data, acc_id):
ag_pb_data[acc_id] = {}
ag_pb_data[acc_id]["id"] = acc_id
ag_pb_data[acc_id]["residual"] = 0.0
ag_pb_data[acc_id]["current"] = 0.0
ag_pb_data[acc_id]["30_days"] = 0.0
ag_pb_data[acc_id]["60_days"] = 0.0
ag_pb_data[acc_id]["90_days"] = 0.0
ag_pb_data[acc_id]["120_days"] = 0.0
ag_pb_data[acc_id]["older"] = 0.0
return ag_pb_data
_name = 'report_aged_partner_balance'
_inherit = 'account_financial_report_abstract'
@api.model
def _initialize_partner(self, ag_pb_data, acc_id, prt_id):
ag_pb_data[acc_id][prt_id] = {}
ag_pb_data[acc_id][prt_id]["id"] = acc_id
ag_pb_data[acc_id][prt_id]["residual"] = 0.0
ag_pb_data[acc_id][prt_id]["current"] = 0.0
ag_pb_data[acc_id][prt_id]["30_days"] = 0.0
ag_pb_data[acc_id][prt_id]["60_days"] = 0.0
ag_pb_data[acc_id][prt_id]["90_days"] = 0.0
ag_pb_data[acc_id][prt_id]["120_days"] = 0.0
ag_pb_data[acc_id][prt_id]["older"] = 0.0
ag_pb_data[acc_id][prt_id]["move_lines"] = []
return ag_pb_data
# Filters fields, used for data computation
date_at = fields.Date()
only_posted_moves = fields.Boolean()
company_id = fields.Many2one(comodel_name='res.company')
filter_account_ids = fields.Many2many(comodel_name='account.account')
filter_partner_ids = fields.Many2many(comodel_name='res.partner')
show_move_line_details = fields.Boolean()
@api.model
def _calculate_amounts(
self, ag_pb_data, acc_id, prt_id, residual, due_date, date_at_object
):
ag_pb_data[acc_id]["residual"] += residual
ag_pb_data[acc_id][prt_id]["residual"] += residual
today = date_at_object
if not due_date or today <= due_date:
ag_pb_data[acc_id]["current"] += residual
ag_pb_data[acc_id][prt_id]["current"] += residual
elif today <= due_date + timedelta(days=30):
ag_pb_data[acc_id]["30_days"] += residual
ag_pb_data[acc_id][prt_id]["30_days"] += residual
elif today <= due_date + timedelta(days=60):
ag_pb_data[acc_id]["60_days"] += residual
ag_pb_data[acc_id][prt_id]["60_days"] += residual
elif today <= due_date + timedelta(days=90):
ag_pb_data[acc_id]["90_days"] += residual
ag_pb_data[acc_id][prt_id]["90_days"] += residual
elif today <= due_date + timedelta(days=120):
ag_pb_data[acc_id]["120_days"] += residual
ag_pb_data[acc_id][prt_id]["120_days"] += residual
else:
ag_pb_data[acc_id]["older"] += residual
ag_pb_data[acc_id][prt_id]["older"] += residual
return ag_pb_data
def _get_account_partial_reconciled(self, company_id, date_at_object):
domain = [("max_date", ">", date_at_object), ("company_id", "=", company_id)]
fields = ["debit_move_id", "credit_move_id", "amount"]
accounts_partial_reconcile = self.env["account.partial.reconcile"].search_read(
domain=domain, fields=fields
)
debit_amount = {}
credit_amount = {}
for account_partial_reconcile_data in accounts_partial_reconcile:
debit_move_id = account_partial_reconcile_data["debit_move_id"][0]
credit_move_id = account_partial_reconcile_data["credit_move_id"][0]
if debit_move_id not in debit_amount.keys():
debit_amount[debit_move_id] = 0.0
debit_amount[debit_move_id] += account_partial_reconcile_data["amount"]
if credit_move_id not in credit_amount.keys():
credit_amount[credit_move_id] = 0.0
credit_amount[credit_move_id] += account_partial_reconcile_data["amount"]
account_partial_reconcile_data.update(
{"debit_move_id": debit_move_id, "credit_move_id": credit_move_id}
# Open Items Report Data fields, used as base for compute the data reports
open_items_id = fields.Many2one(comodel_name='report_open_items')
# Data fields, used to browse report data
account_ids = fields.One2many(
comodel_name='report_aged_partner_balance_account',
inverse_name='report_id'
)
return accounts_partial_reconcile, debit_amount, credit_amount
def _get_move_lines_data(
self,
company_id,
account_ids,
partner_ids,
date_at_object,
date_from,
only_posted_moves,
show_move_line_details,
):
domain = self._get_move_lines_domain_not_reconciled(
company_id, account_ids, partner_ids, only_posted_moves, date_from
class AgedPartnerBalanceReportAccount(models.TransientModel):
_name = 'report_aged_partner_balance_account'
_inherit = 'account_financial_report_abstract'
_order = 'code ASC'
report_id = fields.Many2one(
comodel_name='report_aged_partner_balance',
ondelete='cascade',
index=True
)
ml_fields = [
"id",
"name",
"date",
"move_id",
"journal_id",
"account_id",
"partner_id",
"amount_residual",
"date_maturity",
"ref",
"reconciled",
]
move_lines = self.env["account.move.line"].search_read(
domain=domain, fields=ml_fields
# Data fields, used to keep link with real object
account_id = fields.Many2one(
'account.account',
index=True
)
journals_ids = set()
partners_ids = set()
partners_data = {}
ag_pb_data = {}
if date_at_object < date.today():
(
acc_partial_rec,
debit_amount,
credit_amount,
) = self._get_account_partial_reconciled(company_id, date_at_object)
if acc_partial_rec:
ml_ids = list(map(operator.itemgetter("id"), move_lines))
debit_ids = list(
map(operator.itemgetter("debit_move_id"), acc_partial_rec)
# Data fields, used for report display
code = fields.Char()
name = fields.Char()
cumul_amount_residual = fields.Float(digits=(16, 2))
cumul_current = fields.Float(digits=(16, 2))
cumul_age_30_days = fields.Float(digits=(16, 2))
cumul_age_60_days = fields.Float(digits=(16, 2))
cumul_age_90_days = fields.Float(digits=(16, 2))
cumul_age_120_days = fields.Float(digits=(16, 2))
cumul_older = fields.Float(digits=(16, 2))
percent_current = fields.Float(digits=(16, 2))
percent_age_30_days = fields.Float(digits=(16, 2))
percent_age_60_days = fields.Float(digits=(16, 2))
percent_age_90_days = fields.Float(digits=(16, 2))
percent_age_120_days = fields.Float(digits=(16, 2))
percent_older = fields.Float(digits=(16, 2))
# Data fields, used to browse report data
partner_ids = fields.One2many(
comodel_name='report_aged_partner_balance_partner',
inverse_name='report_account_id'
)
credit_ids = list(
map(operator.itemgetter("credit_move_id"), acc_partial_rec)
class AgedPartnerBalanceReportPartner(models.TransientModel):
_name = 'report_aged_partner_balance_partner'
_inherit = 'account_financial_report_abstract'
report_account_id = fields.Many2one(
comodel_name='report_aged_partner_balance_account',
ondelete='cascade',
index=True
)
move_lines = self._recalculate_move_lines(
move_lines,
debit_ids,
credit_ids,
debit_amount,
credit_amount,
ml_ids,
account_ids,
company_id,
partner_ids,
only_posted_moves,
# Data fields, used to keep link with real object
partner_id = fields.Many2one(
'res.partner',
index=True
)
move_lines = [
move_line
for move_line in move_lines
if move_line["date"] <= date_at_object
and not float_is_zero(move_line["amount_residual"], precision_digits=2)
]
for move_line in move_lines:
journals_ids.add(move_line["journal_id"][0])
acc_id = move_line["account_id"][0]
if move_line["partner_id"]:
prt_id = move_line["partner_id"][0]
prt_name = move_line["partner_id"][1]
else:
prt_id = 0
prt_name = ""
if prt_id not in partners_ids:
partners_data.update({prt_id: {"id": prt_id, "name": prt_name}})
partners_ids.add(prt_id)
if acc_id not in ag_pb_data.keys():
ag_pb_data = self._initialize_account(ag_pb_data, acc_id)
if prt_id not in ag_pb_data[acc_id]:
ag_pb_data = self._initialize_partner(ag_pb_data, acc_id, prt_id)
move_line_data = {}
if show_move_line_details:
if move_line["ref"] == move_line["name"]:
if move_line["ref"]:
ref_label = move_line["ref"]
else:
ref_label = ""
elif not move_line["ref"]:
ref_label = move_line["name"]
elif not move_line["name"]:
ref_label = move_line["ref"]
else:
ref_label = move_line["ref"] + str(" - ") + move_line["name"]
move_line_data.update(
{
"date": move_line["date"],
"entry": move_line["move_id"][1],
"jnl_id": move_line["journal_id"][0],
"acc_id": acc_id,
"partner": prt_name,
"ref_label": ref_label,
"due_date": move_line["date_maturity"],
"residual": move_line["amount_residual"],
}
# Data fields, used for report display
name = fields.Char()
# Data fields, used to browse report data
move_line_ids = fields.One2many(
comodel_name='report_aged_partner_balance_move_line',
inverse_name='report_partner_id'
)
ag_pb_data[acc_id][prt_id]["move_lines"].append(move_line_data)
ag_pb_data = self._calculate_amounts(
ag_pb_data,
acc_id,
prt_id,
move_line["amount_residual"],
move_line["date_maturity"],
date_at_object,
line_ids = fields.One2many(
comodel_name='report_aged_partner_balance_line',
inverse_name='report_partner_id'
)
journals_data = self._get_journals_data(list(journals_ids))
accounts_data = self._get_accounts_data(ag_pb_data.keys())
return ag_pb_data, accounts_data, partners_data, journals_data
@api.model
def _compute_maturity_date(self, ml, date_at_object):
ml.update(
{
"current": 0.0,
"30_days": 0.0,
"60_days": 0.0,
"90_days": 0.0,
"120_days": 0.0,
"older": 0.0,
}
def _generate_order_by(self, order_spec, query):
"""Custom order to display "No partner allocated" at last position."""
return """
ORDER BY
CASE
WHEN
"report_aged_partner_balance_partner"."partner_id" IS NOT NULL
THEN 0
ELSE 1
END,
"report_aged_partner_balance_partner"."name"
"""
class AgedPartnerBalanceReportLine(models.TransientModel):
_name = 'report_aged_partner_balance_line'
_inherit = 'account_financial_report_abstract'
report_partner_id = fields.Many2one(
comodel_name='report_aged_partner_balance_partner',
ondelete='cascade',
index=True
)
due_date = ml["due_date"]
amount = ml["residual"]
today = date_at_object
if not due_date or today <= due_date:
ml["current"] += amount
elif today <= due_date + timedelta(days=30):
ml["30_days"] += amount
elif today <= due_date + timedelta(days=60):
ml["60_days"] += amount
elif today <= due_date + timedelta(days=90):
ml["90_days"] += amount
elif today <= due_date + timedelta(days=120):
ml["120_days"] += amount
# Data fields, used for report display
partner = fields.Char()
amount_residual = fields.Float(digits=(16, 2))
current = fields.Float(digits=(16, 2))
age_30_days = fields.Float(digits=(16, 2))
age_60_days = fields.Float(digits=(16, 2))
age_90_days = fields.Float(digits=(16, 2))
age_120_days = fields.Float(digits=(16, 2))
older = fields.Float(digits=(16, 2))
class AgedPartnerBalanceReportMoveLine(models.TransientModel):
_name = 'report_aged_partner_balance_move_line'
_inherit = 'account_financial_report_abstract'
report_partner_id = fields.Many2one(
comodel_name='report_aged_partner_balance_partner',
ondelete='cascade',
index=True
)
# Data fields, used to keep link with real object
move_line_id = fields.Many2one('account.move.line')
# Data fields, used for report display
date = fields.Date()
date_due = fields.Date()
entry = fields.Char()
journal = fields.Char()
account = fields.Char()
partner = fields.Char()
label = fields.Char()
amount_residual = fields.Float(digits=(16, 2))
current = fields.Float(digits=(16, 2))
age_30_days = fields.Float(digits=(16, 2))
age_60_days = fields.Float(digits=(16, 2))
age_90_days = fields.Float(digits=(16, 2))
age_120_days = fields.Float(digits=(16, 2))
older = fields.Float(digits=(16, 2))
class AgedPartnerBalanceReportCompute(models.TransientModel):
""" Here, we just define methods.
For class fields, go more top at this file.
"""
_inherit = 'report_aged_partner_balance'
@api.multi
def print_report(self, report_type):
self.ensure_one()
if report_type == 'xlsx':
report_name = 'a_f_r.report_aged_partner_balance_xlsx'
else:
ml["older"] += amount
def _create_account_list(
self,
ag_pb_data,
accounts_data,
partners_data,
journals_data,
show_move_line_details,
date_at_oject,
):
aged_partner_data = []
for account in accounts_data.values():
acc_id = account["id"]
account.update(
{
"residual": ag_pb_data[acc_id]["residual"],
"current": ag_pb_data[acc_id]["current"],
"30_days": ag_pb_data[acc_id]["30_days"],
"60_days": ag_pb_data[acc_id]["60_days"],
"90_days": ag_pb_data[acc_id]["90_days"],
"120_days": ag_pb_data[acc_id]["120_days"],
"older": ag_pb_data[acc_id]["older"],
"partners": [],
report_name = 'account_financial_report.' \
'report_aged_partner_balance_qweb'
report = self.env['ir.actions.report'].search(
[('report_name', '=', report_name),
('report_type', '=', report_type)], limit=1)
return report.report_action(self, config=False)
def _get_html(self):
result = {}
rcontext = {}
context = dict(self.env.context)
report = self.browse(context.get('active_id'))
if report:
rcontext['o'] = report
result['html'] = self.env.ref(
'account_financial_report.report_aged_partner_balance').render(
rcontext)
return result
@api.model
def get_html(self, given_context=None):
return self._get_html()
def _prepare_report_open_items(self):
self.ensure_one()
return {
'date_at': self.date_at,
'only_posted_moves': self.only_posted_moves,
'company_id': self.company_id.id,
'filter_account_ids': [(6, 0, self.filter_account_ids.ids)],
'filter_partner_ids': [(6, 0, self.filter_partner_ids.ids)],
}
@api.multi
def compute_data_for_report(self):
self.ensure_one()
# Compute Open Items Report Data.
# The data of Aged Partner Balance Report
# are based on Open Items Report data.
model = self.env['report_open_items']
self.open_items_id = model.create(self._prepare_report_open_items())
self.open_items_id.compute_data_for_report()
# Compute report data
self._inject_account_values()
self._inject_partner_values()
self._inject_line_values()
self._inject_line_values(only_empty_partner_line=True)
if self.show_move_line_details:
self._inject_move_line_values()
self._inject_move_line_values(only_empty_partner_line=True)
self._compute_accounts_cumul()
# Refresh cache because all data are computed with SQL requests
self.invalidate_cache()
def _inject_account_values(self):
"""Inject report values for report_aged_partner_balance_account"""
query_inject_account = """
INSERT INTO
report_aged_partner_balance_account
(
report_id,
create_uid,
create_date,
account_id,
code,
name
)
for prt_id in ag_pb_data[acc_id]:
if isinstance(prt_id, int):
partner = {
"name": partners_data[prt_id]["name"],
"residual": ag_pb_data[acc_id][prt_id]["residual"],
"current": ag_pb_data[acc_id][prt_id]["current"],
"30_days": ag_pb_data[acc_id][prt_id]["30_days"],
"60_days": ag_pb_data[acc_id][prt_id]["60_days"],
"90_days": ag_pb_data[acc_id][prt_id]["90_days"],
"120_days": ag_pb_data[acc_id][prt_id]["120_days"],
"older": ag_pb_data[acc_id][prt_id]["older"],
}
if show_move_line_details:
move_lines = []
for ml in ag_pb_data[acc_id][prt_id]["move_lines"]:
ml.update(
{
"journal": journals_data[ml["jnl_id"]]["code"],
"account": accounts_data[ml["acc_id"]]["code"],
}
SELECT
%s AS report_id,
%s AS create_uid,
NOW() AS create_date,
rao.account_id,
rao.code,
rao.name
FROM
report_open_items_account rao
WHERE
rao.report_id = %s
"""
query_inject_account_params = (
self.id,
self.env.uid,
self.open_items_id.id,
)
self._compute_maturity_date(ml, date_at_oject)
move_lines.append(ml)
move_lines = sorted(move_lines, key=lambda k: (k["date"]))
partner.update({"move_lines": move_lines})
account["partners"].append(partner)
aged_partner_data.append(account)
return aged_partner_data
self.env.cr.execute(query_inject_account, query_inject_account_params)
@api.model
def _calculate_percent(self, aged_partner_data):
for account in aged_partner_data:
if abs(account["residual"]) > 0.01:
total = account["residual"]
account.update(
{
"percent_current": abs(
round((account["current"] / total) * 100, 2)
),
"percent_30_days": abs(
round((account["30_days"] / total) * 100, 2)
),
"percent_60_days": abs(
round((account["60_days"] / total) * 100, 2)
),
"percent_90_days": abs(
round((account["90_days"] / total) * 100, 2)
),
"percent_120_days": abs(
round((account["120_days"] / total) * 100, 2)
),
"percent_older": abs(
round((account["older"] / total) * 100, 2)
),
}
def _inject_partner_values(self):
"""Inject report values for report_aged_partner_balance_partner"""
query_inject_partner = """
INSERT INTO
report_aged_partner_balance_partner
(
report_account_id,
create_uid,
create_date,
partner_id,
name
)
else:
account.update(
{
"percent_current": 0.0,
"percent_30_days": 0.0,
"percent_60_days": 0.0,
"percent_90_days": 0.0,
"percent_120_days": 0.0,
"percent_older": 0.0,
}
SELECT
ra.id AS report_account_id,
%s AS create_uid,
NOW() AS create_date,
rpo.partner_id,
rpo.name
FROM
report_open_items_partner rpo
INNER JOIN
report_open_items_account rao ON rpo.report_account_id = rao.id
INNER JOIN
report_aged_partner_balance_account ra ON rao.code = ra.code
WHERE
rao.report_id = %s
AND ra.report_id = %s
"""
query_inject_partner_params = (
self.env.uid,
self.open_items_id.id,
self.id,
)
return aged_partner_data
def _get_report_values(self, docids, data):
wizard_id = data["wizard_id"]
company = self.env["res.company"].browse(data["company_id"])
company_id = data["company_id"]
account_ids = data["account_ids"]
partner_ids = data["partner_ids"]
date_at = data["date_at"]
date_at_object = datetime.strptime(date_at, "%Y-%m-%d").date()
date_from = data["date_from"]
only_posted_moves = data["only_posted_moves"]
show_move_line_details = data["show_move_line_details"]
self.env.cr.execute(query_inject_partner, query_inject_partner_params)
def _inject_line_values(self, only_empty_partner_line=False):
""" Inject report values for report_aged_partner_balance_line.
The "only_empty_partner_line" value is used
to compute data without partner.
"""
query_inject_line = """
WITH
date_range AS
(
ag_pb_data,
accounts_data,
partners_data,
journals_data,
) = self._get_move_lines_data(
company_id,
account_ids,
partner_ids,
date_at_object,
date_from,
only_posted_moves,
show_move_line_details,
SELECT
DATE %s AS date_current,
DATE %s - INTEGER '30' AS date_less_30_days,
DATE %s - INTEGER '60' AS date_less_60_days,
DATE %s - INTEGER '90' AS date_less_90_days,
DATE %s - INTEGER '120' AS date_less_120_days
)
aged_partner_data = self._create_account_list(
ag_pb_data,
accounts_data,
partners_data,
journals_data,
show_move_line_details,
date_at_object,
INSERT INTO
report_aged_partner_balance_line
(
report_partner_id,
create_uid,
create_date,
partner,
amount_residual,
current,
age_30_days,
age_60_days,
age_90_days,
age_120_days,
older
)
aged_partner_data = self._calculate_percent(aged_partner_data)
return {
"doc_ids": [wizard_id],
"doc_model": "open.items.report.wizard",
"docs": self.env["open.items.report.wizard"].browse(wizard_id),
"company_name": company.display_name,
"company_currency": company.currency_id,
"currency_name": company.currency_id.name,
"date_at": date_at,
"only_posted_moves": only_posted_moves,
"aged_partner_balance": aged_partner_data,
"show_move_lines_details": show_move_line_details,
}
SELECT
rp.id AS report_partner_id,
%s AS create_uid,
NOW() AS create_date,
rp.name,
SUM(rlo.amount_residual) AS amount_residual,
SUM(
CASE
WHEN rlo.date_due >= date_range.date_current
THEN rlo.amount_residual
END
) AS current,
SUM(
CASE
WHEN
rlo.date_due >= date_range.date_less_30_days
AND rlo.date_due < date_range.date_current
THEN rlo.amount_residual
END
) AS age_30_days,
SUM(
CASE
WHEN
rlo.date_due >= date_range.date_less_60_days
AND rlo.date_due < date_range.date_less_30_days
THEN rlo.amount_residual
END
) AS age_60_days,
SUM(
CASE
WHEN
rlo.date_due >= date_range.date_less_90_days
AND rlo.date_due < date_range.date_less_60_days
THEN rlo.amount_residual
END
) AS age_90_days,
SUM(
CASE
WHEN
rlo.date_due >= date_range.date_less_120_days
AND rlo.date_due < date_range.date_less_90_days
THEN rlo.amount_residual
END
) AS age_120_days,
SUM(
CASE
WHEN rlo.date_due < date_range.date_less_120_days
THEN rlo.amount_residual
END
) AS older
FROM
date_range,
report_open_items_move_line rlo
INNER JOIN
report_open_items_partner rpo ON rlo.report_partner_id = rpo.id
INNER JOIN
report_open_items_account rao ON rpo.report_account_id = rao.id
INNER JOIN
report_aged_partner_balance_account ra ON rao.code = ra.code
INNER JOIN
report_aged_partner_balance_partner rp
ON
ra.id = rp.report_account_id
"""
if not only_empty_partner_line:
query_inject_line += """
AND rpo.partner_id = rp.partner_id
"""
elif only_empty_partner_line:
query_inject_line += """
AND rpo.partner_id IS NULL
AND rp.partner_id IS NULL
"""
query_inject_line += """
WHERE
rao.report_id = %s
AND ra.report_id = %s
GROUP BY
rp.id
"""
query_inject_line_params = (self.date_at,) * 5
query_inject_line_params += (
self.env.uid,
self.open_items_id.id,
self.id,
)
self.env.cr.execute(query_inject_line, query_inject_line_params)
def _inject_move_line_values(self, only_empty_partner_line=False):
""" Inject report values for report_aged_partner_balance_move_line
The "only_empty_partner_line" value is used
to compute data without partner.
"""
query_inject_move_line = """
WITH
date_range AS
(
SELECT
DATE %s AS date_current,
DATE %s - INTEGER '30' AS date_less_30_days,
DATE %s - INTEGER '60' AS date_less_60_days,
DATE %s - INTEGER '90' AS date_less_90_days,
DATE %s - INTEGER '120' AS date_less_120_days
)
INSERT INTO
report_aged_partner_balance_move_line
(
report_partner_id,
create_uid,
create_date,
move_line_id,
date,
date_due,
entry,
journal,
account,
partner,
label,
amount_residual,
current,
age_30_days,
age_60_days,
age_90_days,
age_120_days,
older
)
SELECT
rp.id AS report_partner_id,
%s AS create_uid,
NOW() AS create_date,
rlo.move_line_id,
rlo.date,
rlo.date_due,
rlo.entry,
rlo.journal,
rlo.account,
rlo.partner,
rlo.label,
rlo.amount_residual AS amount_residual,
CASE
WHEN rlo.date_due >= date_range.date_current
THEN rlo.amount_residual
END AS current,
CASE
WHEN
rlo.date_due >= date_range.date_less_30_days
AND rlo.date_due < date_range.date_current
THEN rlo.amount_residual
END AS age_30_days,
CASE
WHEN
rlo.date_due >= date_range.date_less_60_days
AND rlo.date_due < date_range.date_less_30_days
THEN rlo.amount_residual
END AS age_60_days,
CASE
WHEN
rlo.date_due >= date_range.date_less_90_days
AND rlo.date_due < date_range.date_less_60_days
THEN rlo.amount_residual
END AS age_90_days,
CASE
WHEN
rlo.date_due >= date_range.date_less_120_days
AND rlo.date_due < date_range.date_less_90_days
THEN rlo.amount_residual
END AS age_120_days,
CASE
WHEN rlo.date_due < date_range.date_less_120_days
THEN rlo.amount_residual
END AS older
FROM
date_range,
report_open_items_move_line rlo
INNER JOIN
report_open_items_partner rpo ON rlo.report_partner_id = rpo.id
INNER JOIN
report_open_items_account rao ON rpo.report_account_id = rao.id
INNER JOIN
report_aged_partner_balance_account ra ON rao.code = ra.code
INNER JOIN
report_aged_partner_balance_partner rp
ON
ra.id = rp.report_account_id
"""
if not only_empty_partner_line:
query_inject_move_line += """
AND rpo.partner_id = rp.partner_id
"""
elif only_empty_partner_line:
query_inject_move_line += """
AND rpo.partner_id IS NULL
AND rp.partner_id IS NULL
"""
query_inject_move_line += """
WHERE
rao.report_id = %s
AND ra.report_id = %s
"""
query_inject_move_line_params = (self.date_at,) * 5
query_inject_move_line_params += (
self.env.uid,
self.open_items_id.id,
self.id,
)
self.env.cr.execute(query_inject_move_line,
query_inject_move_line_params)
def _compute_accounts_cumul(self):
""" Compute cumulative amount for
report_aged_partner_balance_account.
"""
query_compute_accounts_cumul = """
WITH
cumuls AS
(
SELECT
ra.id AS report_account_id,
SUM(rl.amount_residual) AS cumul_amount_residual,
SUM(rl.current) AS cumul_current,
SUM(rl.age_30_days) AS cumul_age_30_days,
SUM(rl.age_60_days) AS cumul_age_60_days,
SUM(rl.age_90_days) AS cumul_age_90_days,
SUM(rl.age_120_days) AS cumul_age_120_days,
SUM(rl.older) AS cumul_older
FROM
report_aged_partner_balance_line rl
INNER JOIN
report_aged_partner_balance_partner rp
ON rl.report_partner_id = rp.id
INNER JOIN
report_aged_partner_balance_account ra
ON rp.report_account_id = ra.id
WHERE
ra.report_id = %s
GROUP BY
ra.id
)
UPDATE
report_aged_partner_balance_account
SET
cumul_amount_residual = c.cumul_amount_residual,
cumul_current = c.cumul_current,
cumul_age_30_days = c.cumul_age_30_days,
cumul_age_60_days = c.cumul_age_60_days,
cumul_age_90_days = c.cumul_age_90_days,
cumul_age_120_days = c.cumul_age_120_days,
cumul_older = c.cumul_older,
percent_current =
CASE
WHEN c.cumul_amount_residual != 0
THEN 100 * c.cumul_current / c.cumul_amount_residual
END,
percent_age_30_days =
CASE
WHEN c.cumul_amount_residual != 0
THEN 100 * c.cumul_age_30_days / c.cumul_amount_residual
END,
percent_age_60_days =
CASE
WHEN c.cumul_amount_residual != 0
THEN 100 * c.cumul_age_60_days / c.cumul_amount_residual
END,
percent_age_90_days =
CASE
WHEN c.cumul_amount_residual != 0
THEN 100 * c.cumul_age_90_days / c.cumul_amount_residual
END,
percent_age_120_days =
CASE
WHEN c.cumul_amount_residual != 0
THEN 100 * c.cumul_age_120_days / c.cumul_amount_residual
END,
percent_older =
CASE
WHEN c.cumul_amount_residual != 0
THEN 100 * c.cumul_older / c.cumul_amount_residual
END
FROM
cumuls c
WHERE
id = c.report_account_id
"""
params_compute_accounts_cumul = (self.id,)
self.env.cr.execute(query_compute_accounts_cumul,
params_compute_accounts_cumul)

362
account_financial_report/report/aged_partner_balance_xlsx.py

@ -1,3 +1,4 @@
# Author: Julien Coux
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
@ -6,160 +7,123 @@ from odoo import _, models
class AgedPartnerBalanceXslx(models.AbstractModel):
_name = "report.a_f_r.report_aged_partner_balance_xlsx"
_description = "Aged Partner Balance XLSL Report"
_inherit = "report.account_financial_report.abstract_report_xlsx"
_name = 'report.a_f_r.report_aged_partner_balance_xlsx'
_inherit = 'report.account_financial_report.abstract_report_xlsx'
def _get_report_name(self, report, data=False):
company_id = data.get("company_id", False)
report_name = _("Aged Partner Balance")
if company_id:
company = self.env["res.company"].browse(company_id)
suffix = " - {} - {}".format(company.name, company.currency_id.name)
report_name = report_name + suffix
return report_name
def _get_report_name(self, report):
report_name = _('Aged Partner Balance')
return self._get_report_complete_name(report, report_name)
def _get_report_columns(self, report):
if not report.show_move_line_details:
return {
0: {"header": _("Partner"), "field": "name", "width": 70},
1: {
"header": _("Residual"),
"field": "residual",
"field_footer_total": "residual",
"type": "amount",
"width": 14,
},
2: {
"header": _("Current"),
"field": "current",
"field_footer_total": "current",
"field_footer_percent": "percent_current",
"type": "amount",
"width": 14,
},
3: {
"header": _(u"Age ≤ 30 d."),
"field": "30_days",
"field_footer_total": "30_days",
"field_footer_percent": "percent_30_days",
"type": "amount",
"width": 14,
},
4: {
"header": _(u"Age ≤ 60 d."),
"field": "60_days",
"field_footer_total": "60_days",
"field_footer_percent": "percent_60_days",
"type": "amount",
"width": 14,
},
5: {
"header": _(u"Age ≤ 90 d."),
"field": "90_days",
"field_footer_total": "90_days",
"field_footer_percent": "percent_90_days",
"type": "amount",
"width": 14,
},
6: {
"header": _(u"Age ≤ 120 d."),
"field": "120_days",
"field_footer_total": "120_days",
"field_footer_percent": "percent_120_days",
"type": "amount",
"width": 14,
},
7: {
"header": _("Older"),
"field": "older",
"field_footer_total": "older",
"field_footer_percent": "percent_older",
"type": "amount",
"width": 14,
},
0: {'header': _('Partner'), 'field': 'partner', 'width': 70},
1: {'header': _('Residual'),
'field': 'amount_residual',
'field_footer_total': 'cumul_amount_residual',
'type': 'amount',
'width': 14},
2: {'header': _('Current'),
'field': 'current',
'field_footer_total': 'cumul_current',
'field_footer_percent': 'percent_current',
'type': 'amount',
'width': 14},
3: {'header': _(u'Age ≤ 30 d.'),
'field': 'age_30_days',
'field_footer_total': 'cumul_age_30_days',
'field_footer_percent': 'percent_age_30_days',
'type': 'amount',
'width': 14},
4: {'header': _(u'Age ≤ 60 d.'),
'field': 'age_60_days',
'field_footer_total': 'cumul_age_60_days',
'field_footer_percent': 'percent_age_60_days',
'type': 'amount',
'width': 14},
5: {'header': _(u'Age ≤ 90 d.'),
'field': 'age_90_days',
'field_footer_total': 'cumul_age_90_days',
'field_footer_percent': 'percent_age_90_days',
'type': 'amount',
'width': 14},
6: {'header': _(u'Age ≤ 120 d.'),
'field': 'age_120_days',
'field_footer_total': 'cumul_age_120_days',
'field_footer_percent': 'percent_age_120_days',
'type': 'amount',
'width': 14},
7: {'header': _('Older'),
'field': 'older',
'field_footer_total': 'cumul_older',
'field_footer_percent': 'percent_older',
'type': 'amount',
'width': 14},
}
return {
0: {"header": _("Date"), "field": "date", "width": 11},
1: {"header": _("Entry"), "field": "entry", "width": 18},
2: {"header": _("Journal"), "field": "journal", "width": 8},
3: {"header": _("Account"), "field": "account", "width": 9},
4: {"header": _("Partner"), "field": "partner", "width": 25},
5: {"header": _("Ref - Label"), "field": "ref_label", "width": 40},
6: {"header": _("Due date"), "field": "due_date", "width": 11},
7: {
"header": _("Residual"),
"field": "residual",
"field_footer_total": "residual",
"field_final_balance": "residual",
"type": "amount",
"width": 14,
},
8: {
"header": _("Current"),
"field": "current",
"field_footer_total": "current",
"field_footer_percent": "percent_current",
"field_final_balance": "current",
"type": "amount",
"width": 14,
},
9: {
"header": _(u"Age ≤ 30 d."),
"field": "30_days",
"field_footer_total": "30_days",
"field_footer_percent": "percent_30_days",
"field_final_balance": "30_days",
"type": "amount",
"width": 14,
},
10: {
"header": _(u"Age ≤ 60 d."),
"field": "60_days",
"field_footer_total": "60_days",
"field_footer_percent": "percent_60_days",
"field_final_balance": "60_days",
"type": "amount",
"width": 14,
},
11: {
"header": _(u"Age ≤ 90 d."),
"field": "90_days",
"field_footer_total": "90_days",
"field_footer_percent": "percent_90_days",
"field_final_balance": "90_days",
"type": "amount",
"width": 14,
},
12: {
"header": _(u"Age ≤ 120 d."),
"field": "120_days",
"field_footer_total": "120_days",
"field_footer_percent": "percent_120_days",
"field_final_balance": "120_days",
"type": "amount",
"width": 14,
},
13: {
"header": _("Older"),
"field": "older",
"field_footer_total": "older",
"field_footer_percent": "percent_older",
"field_final_balance": "older",
"type": "amount",
"width": 14,
},
0: {'header': _('Date'), 'field': 'date', 'width': 11},
1: {'header': _('Entry'), 'field': 'entry', 'width': 18},
2: {'header': _('Journal'), 'field': 'journal', 'width': 8},
3: {'header': _('Account'), 'field': 'account', 'width': 9},
4: {'header': _('Partner'), 'field': 'partner', 'width': 25},
5: {'header': _('Ref - Label'), 'field': 'label', 'width': 40},
6: {'header': _('Due date'), 'field': 'date_due', 'width': 11},
7: {'header': _('Residual'),
'field': 'amount_residual',
'field_footer_total': 'cumul_amount_residual',
'field_final_balance': 'amount_residual',
'type': 'amount',
'width': 14},
8: {'header': _('Current'),
'field': 'current',
'field_footer_total': 'cumul_current',
'field_footer_percent': 'percent_current',
'field_final_balance': 'current',
'type': 'amount',
'width': 14},
9: {'header': _(u'Age ≤ 30 d.'),
'field': 'age_30_days',
'field_footer_total': 'cumul_age_30_days',
'field_footer_percent': 'percent_age_30_days',
'field_final_balance': 'age_30_days',
'type': 'amount',
'width': 14},
10: {'header': _(u'Age ≤ 60 d.'),
'field': 'age_60_days',
'field_footer_total': 'cumul_age_60_days',
'field_footer_percent': 'percent_age_60_days',
'field_final_balance': 'age_60_days',
'type': 'amount',
'width': 14},
11: {'header': _(u'Age ≤ 90 d.'),
'field': 'age_90_days',
'field_footer_total': 'cumul_age_90_days',
'field_footer_percent': 'percent_age_90_days',
'field_final_balance': 'age_90_days',
'type': 'amount',
'width': 14},
12: {'header': _(u'Age ≤ 120 d.'),
'field': 'age_120_days',
'field_footer_total': 'cumul_age_120_days',
'field_footer_percent': 'percent_age_120_days',
'field_final_balance': 'age_120_days',
'type': 'amount',
'width': 14},
13: {'header': _('Older'),
'field': 'older',
'field_footer_total': 'cumul_older',
'field_footer_percent': 'percent_older',
'field_final_balance': 'older',
'type': 'amount',
'width': 14},
}
def _get_report_filters(self, report):
return [
[_("Date at filter"), report.date_at.strftime("%d/%m/%Y")],
[
_("Target moves filter"),
_("All posted entries")
if report.target_move == "posted"
else _("All entries"),
],
[_('Date at filter'), report.date_at],
[_('Target moves filter'),
_('All posted entries') if report.only_posted_moves else _(
'All entries')],
]
def _get_col_count_filter_name(self):
@ -177,116 +141,94 @@ class AgedPartnerBalanceXslx(models.AbstractModel):
def _get_col_pos_final_balance_label(self):
return 5
def _generate_report_content(self, workbook, report, data):
res_data = self.env[
"report.account_financial_report.aged_partner_balance"
]._get_report_values(report, data)
show_move_line_details = res_data["show_move_lines_details"]
aged_partner_balance = res_data["aged_partner_balance"]
if not show_move_line_details:
def _generate_report_content(self, workbook, report):
if not report.show_move_line_details:
# For each account
for account in aged_partner_balance:
for account in report.account_ids:
# Write account title
self.write_array_title(account["code"] + " - " + account["name"])
self.write_array_title(account.code + ' - ' + account.name)
# Display array header for partners lines
self.write_array_header()
# Display partner lines
for partner in account["partners"]:
self.write_line_from_dict(partner)
for partner in account.partner_ids:
self.write_line(partner.line_ids)
# Display account lines
self.write_account_footer_from_dict(
report,
self.write_account_footer(report,
account,
("Total"),
"field_footer_total",
_('Total'),
'field_footer_total',
self.format_header_right,
self.format_header_amount,
False,
)
self.write_account_footer_from_dict(
report,
False)
self.write_account_footer(report,
account,
("Percents"),
"field_footer_percent",
_('Percents'),
'field_footer_percent',
self.format_right_bold_italic,
self.format_percent_bold_italic,
True,
)
True)
# 2 lines break
self.row_pos += 2
else:
# For each account
for account in aged_partner_balance:
for account in report.account_ids:
# Write account title
self.write_array_title(account["code"] + " - " + account["name"])
self.write_array_title(account.code + ' - ' + account.name)
# For each partner
for partner in account["partners"]:
for partner in account.partner_ids:
# Write partner title
self.write_array_title(partner["name"])
self.write_array_title(partner.name)
# Display array header for move lines
self.write_array_header()
# Display account move lines
for line in partner["move_lines"]:
self.write_line_from_dict(line)
for line in partner.move_line_ids:
self.write_line(line)
# Display ending balance line for partner
self.write_ending_balance_from_dict(partner)
self.write_ending_balance(partner.line_ids)
# Line break
self.row_pos += 1
# Display account lines
self.write_account_footer_from_dict(
report,
self.write_account_footer(report,
account,
("Total"),
"field_footer_total",
_('Total'),
'field_footer_total',
self.format_header_right,
self.format_header_amount,
False,
)
self.write_account_footer_from_dict(
report,
False)
self.write_account_footer(report,
account,
("Percents"),
"field_footer_percent",
_('Percents'),
'field_footer_percent',
self.format_right_bold_italic,
self.format_percent_bold_italic,
True,
)
True)
# 2 lines break
self.row_pos += 2
def write_ending_balance_from_dict(self, my_object):
def write_ending_balance(self, my_object):
"""
Specific function to write ending partner balance
for Aged Partner Balance
"""
name = None
label = _("Partner cumul aged balance")
super(AgedPartnerBalanceXslx, self).write_ending_balance_from_dict(
label = _('Partner cumul aged balance')
super(AgedPartnerBalanceXslx, self).write_ending_balance(
my_object, name, label
)
def write_account_footer_from_dict(
self,
report,
account,
label,
field_name,
string_format,
amount_format,
amount_is_percent,
):
def write_account_footer(self, report, account, label, field_name,
string_format, amount_format, amount_is_percent):
"""
Specific function to write account footer for Aged Partner Balance
"""
@ -296,20 +238,20 @@ class AgedPartnerBalanceXslx(models.AbstractModel):
if col_pos == col_pos_footer_label:
value = label
else:
value = account.get(column[field_name], False)
cell_type = column.get("type", "string")
if cell_type == "string" or col_pos == col_pos_footer_label:
self.sheet.write_string(
self.row_pos, col_pos, value or "", string_format
)
elif cell_type == "amount":
value = getattr(account, column[field_name])
cell_type = column.get('type', 'string')
if cell_type == 'string' or col_pos == col_pos_footer_label:
self.sheet.write_string(self.row_pos, col_pos, value or '',
string_format)
elif cell_type == 'amount':
number = float(value)
if amount_is_percent:
number /= 100
self.sheet.write_number(
self.row_pos, col_pos, number, amount_format
)
self.sheet.write_number(self.row_pos, col_pos,
number,
amount_format)
else:
self.sheet.write_string(self.row_pos, col_pos, "", string_format)
self.sheet.write_string(self.row_pos, col_pos, '',
string_format)
self.row_pos += 1

2565
account_financial_report/report/general_ledger.py
File diff suppressed because it is too large
View File

358
account_financial_report/report/general_ledger_xlsx.py

@ -1,3 +1,4 @@
# Author: Damien Crier
# Author: Julien Coux
# Copyright 2016 Camptocamp SA
@ -7,115 +8,94 @@ from odoo import _, models
class GeneralLedgerXslx(models.AbstractModel):
_name = "report.a_f_r.report_general_ledger_xlsx"
_description = "General Ledger XLSL Report"
_inherit = "report.account_financial_report.abstract_report_xlsx"
_name = 'report.a_f_r.report_general_ledger_xlsx'
_inherit = 'report.account_financial_report.abstract_report_xlsx'
def _get_report_name(self, report, data=False):
company_id = data.get("company_id", False)
report_name = _("General Ledger")
if company_id:
company = self.env["res.company"].browse(company_id)
suffix = " - {} - {}".format(company.name, company.currency_id.name)
report_name = report_name + suffix
return report_name
def _get_report_name(self, report):
report_name = _('General Ledger')
return self._get_report_complete_name(report, report_name)
def _get_report_columns(self, report):
res = [
{"header": _("Date"), "field": "date", "width": 11},
{"header": _("Entry"), "field": "entry", "width": 18},
{"header": _("Journal"), "field": "journal", "width": 8},
{"header": _("Account"), "field": "account", "width": 9},
{"header": _("Taxes"), "field": "taxes_description", "width": 15},
{"header": _("Partner"), "field": "partner_name", "width": 25},
{"header": _("Ref - Label"), "field": "ref_label", "width": 40},
]
if report.show_cost_center:
res += [
{
"header": _("Analytic Account"),
"field": "analytic_account",
"width": 20,
},
]
if report.show_analytic_tags:
res += [
{"header": _("Tags"), "field": "tags", "width": 10},
]
res += [
{"header": _("Rec."), "field": "rec_name", "width": 15},
{
"header": _("Debit"),
"field": "debit",
"field_initial_balance": "initial_debit",
"field_final_balance": "final_debit",
"type": "amount",
"width": 14,
},
{
"header": _("Credit"),
"field": "credit",
"field_initial_balance": "initial_credit",
"field_final_balance": "final_credit",
"type": "amount",
"width": 14,
},
{
"header": _("Cumul. Bal."),
"field": "balance",
"field_initial_balance": "initial_balance",
"field_final_balance": "final_balance",
"type": "amount",
"width": 14,
},
]
res = {
0: {'header': _('Date'), 'field': 'date', 'width': 11},
1: {'header': _('Entry'), 'field': 'entry', 'width': 18},
2: {'header': _('Journal'), 'field': 'journal', 'width': 8},
3: {'header': _('Account'), 'field': 'account', 'width': 9},
4: {'header': _('Taxes'),
'field': 'taxes_description',
'width': 15},
5: {'header': _('Partner'), 'field': 'partner', 'width': 25},
6: {'header': _('Ref - Label'), 'field': 'label', 'width': 40},
7: {'header': _('Cost center'),
'field': 'cost_center',
'width': 15},
8: {'header': _('Tags'),
'field': 'tags',
'width': 10},
9: {'header': _('Rec.'), 'field': 'matching_number', 'width': 5},
10: {'header': _('Debit'),
'field': 'debit',
'field_initial_balance': 'initial_debit',
'field_final_balance': 'final_debit',
'type': 'amount',
'width': 14},
11: {'header': _('Credit'),
'field': 'credit',
'field_initial_balance': 'initial_credit',
'field_final_balance': 'final_credit',
'type': 'amount',
'width': 14},
12: {'header': _('Cumul. Bal.'),
'field': 'cumul_balance',
'field_initial_balance': 'initial_balance',
'field_final_balance': 'final_balance',
'type': 'amount',
'width': 14},
}
if report.foreign_currency:
res += [
{
"header": _("Cur."),
"field": "currency_name",
"field_currency_balance": "currency_name",
"type": "currency_name",
"width": 7,
},
{
"header": _("Amount cur."),
"field": "bal_curr",
"field_initial_balance": "initial_bal_curr",
"field_final_balance": "final_bal_curr",
"type": "amount_currency",
"width": 14,
},
]
res_as_dict = {}
for i, column in enumerate(res):
res_as_dict[i] = column
return res_as_dict
foreign_currency = {
13: {'header': _('Cur.'),
'field': 'currency_id',
'field_currency_balance': 'currency_id',
'type': 'many2one', 'width': 7},
14: {'header': _('Amount cur.'),
'field': 'amount_currency',
'field_initial_balance':
'initial_balance_foreign_currency',
'field_final_balance':
'final_balance_foreign_currency',
'type': 'amount_currency',
'width': 14},
}
res = {**res, **foreign_currency}
return res
def _get_report_filters(self, report):
return [
[
_("Date range filter"),
_("From: %s To: %s") % (report.date_from, report.date_to),
_('Date range filter'),
_('From: %s To: %s') % (report.date_from, report.date_to),
],
[
_("Target moves filter"),
_("All posted entries")
if report.target_move == "posted"
else _("All entries"),
_('Target moves filter'),
_('All posted entries') if report.only_posted_moves
else _('All entries'),
],
[
_("Account balance at 0 filter"),
_("Hide") if report.hide_account_at_0 else _("Show"),
_('Account balance at 0 filter'),
_('Hide') if report.hide_account_at_0 else _('Show'),
],
[_("Centralize filter"), _("Yes") if report.centralize else _("No")],
[
_("Show analytic tags"),
_("Yes") if report.show_analytic_tags else _("No"),
_('Centralize filter'),
_('Yes') if report.centralize else _('No'),
],
[
_("Show foreign currency"),
_("Yes") if report.foreign_currency else _("No"),
_('Show analytic tags'),
_('Yes') if report.show_analytic_tags else _('No'),
],
[
_('Show foreign currency'),
_('Yes') if report.foreign_currency else _('No')
],
]
@ -134,197 +114,71 @@ class GeneralLedgerXslx(models.AbstractModel):
def _get_col_pos_final_balance_label(self):
return 5
# flake8: noqa: C901
def _generate_report_content(self, workbook, report, data):
res_data = self.env[
"report.account_financial_report.general_ledger"
]._get_report_values(report, data)
general_ledger = res_data["general_ledger"]
accounts_data = res_data["accounts_data"]
partners_data = res_data["partners_data"]
journals_data = res_data["journals_data"]
taxes_data = res_data["taxes_data"]
tags_data = res_data["tags_data"]
filter_partner_ids = res_data["filter_partner_ids"]
foreign_currency = res_data["foreign_currency"]
def _generate_report_content(self, workbook, report):
# For each account
for account in general_ledger:
for account in report.account_ids:
# Write account title
self.write_array_title(
account["code"] + " - " + accounts_data[account["id"]]["name"]
)
self.write_array_title(account.code + ' - ' + account.name)
if not account["partners"]:
if not account.partner_ids:
# Display array header for move lines
self.write_array_header()
# Display initial balance line for account
account.update(
{
"initial_debit": account["init_bal"]["debit"],
"initial_credit": account["init_bal"]["credit"],
"initial_balance": account["init_bal"]["balance"],
}
)
if foreign_currency:
account.update(
{"initial_bal_curr": account["init_bal"]["bal_curr"]}
)
self.write_initial_balance_from_dict(account)
self.write_initial_balance(account)
# Display account move lines
for line in account["move_lines"]:
line.update(
{
"account": account["code"],
"journal": journals_data[line["journal_id"]]["code"],
}
)
if line["currency_id"]:
line.update(
{
"currency_name": line["currency_id"][1],
"currency_id": line["currency_id"][0],
}
)
if line["ref_label"] != "Centralized entries":
taxes_description = ""
tags = ""
for tax_id in line["tax_ids"]:
taxes_description += taxes_data[tax_id]["tax_name"] + " "
for tag_id in line["tag_ids"]:
tags += tags_data[tag_id]["name"] + " "
line.update(
{"taxes_description": taxes_description, "tags": tags,}
)
self.write_line_from_dict(line)
# Display ending balance line for account
account.update(
{
"final_debit": account["fin_bal"]["debit"],
"final_credit": account["fin_bal"]["credit"],
"final_balance": account["fin_bal"]["balance"],
}
)
if foreign_currency:
account.update(
{"final_bal_curr": account["fin_bal"]["bal_curr"],}
)
self.write_ending_balance_from_dict(account)
for line in account.move_line_ids:
self.write_line(line)
else:
# For each partner
for partner in account["list_partner"]:
for partner in account.partner_ids:
# Write partner title
self.write_array_title(partners_data[partner["id"]]["name"])
self.write_array_title(partner.name)
# Display array header for move lines
self.write_array_header()
# Display initial balance line for partner
partner.update(
{
"initial_debit": partner["init_bal"]["debit"],
"initial_credit": partner["init_bal"]["credit"],
"initial_balance": partner["init_bal"]["balance"],
"name": partners_data[partner["id"]]["name"],
"type": "partner",
"currency_id": accounts_data[account["id"]]["currency_id"],
}
)
if foreign_currency:
partner.update(
{"initial_bal_curr": partner["init_bal"]["bal_curr"],}
)
self.write_initial_balance_from_dict(partner)
self.write_initial_balance(partner)
# Display account move lines
for line in partner["move_lines"]:
line.update(
{
"account": account["code"],
"journal": journals_data[line["journal_id"]]["code"],
}
)
if line["currency_id"]:
line.update(
{
"currency_name": line["currency_id"][1],
"currency_id": line["currency_id"][0],
}
)
if line["ref_label"] != "Centralized entries":
taxes_description = ""
tags = ""
for tax_id in line["tax_ids"]:
taxes_description += (
taxes_data[tax_id]["tax_name"] + " "
)
for tag_id in line["tag_ids"]:
tags += tags_data[tag_id]["name"] + " "
line.update(
{"taxes_description": taxes_description, "tags": tags,}
)
self.write_line_from_dict(line)
for line in partner.move_line_ids:
self.write_line(line)
# Display ending balance line for partner
partner.update(
{
"final_debit": partner["fin_bal"]["debit"],
"final_credit": partner["fin_bal"]["credit"],
"final_balance": partner["fin_bal"]["balance"],
}
)
if foreign_currency and partner["currency_id"]:
partner.update(
{
"final_bal_curr": partner["fin_bal"]["bal_curr"],
"currency_name": partner["currency_id"].name,
"currency_id": partner["currency_id"].id,
}
)
self.write_ending_balance_from_dict(partner)
self.write_ending_balance(partner)
# Line break
self.row_pos += 1
if not filter_partner_ids:
account.update(
{
"final_debit": account["fin_bal"]["debit"],
"final_credit": account["fin_bal"]["credit"],
"final_balance": account["fin_bal"]["balance"],
}
)
if foreign_currency and account["currency_id"]:
account.update(
{
"final_bal_curr": account["fin_bal"]["bal_curr"],
"currency_name": account["currency_id"].name,
"currency_id": account["currency_id"].id,
}
)
self.write_ending_balance_from_dict(account)
# Display ending balance line for account
if not report.filter_partner_ids:
self.write_ending_balance(account)
# 2 lines break
self.row_pos += 2
def write_initial_balance_from_dict(self, my_object):
def write_initial_balance(self, my_object):
"""Specific function to write initial balance for General Ledger"""
if "partner" in my_object["type"]:
label = _("Partner Initial balance")
elif "account" in my_object["type"]:
label = _("Initial balance")
super(GeneralLedgerXslx, self).write_initial_balance_from_dict(my_object, label)
if 'partner' in my_object._name:
label = _('Partner Initial balance')
my_object.currency_id = my_object.report_account_id.currency_id
elif 'account' in my_object._name:
label = _('Initial balance')
super(GeneralLedgerXslx, self).write_initial_balance(
my_object, label
)
def write_ending_balance_from_dict(self, my_object):
def write_ending_balance(self, my_object):
"""Specific function to write ending balance for General Ledger"""
if "partner" in my_object["type"]:
name = my_object["name"]
label = _("Partner ending balance")
elif "account" in my_object["type"]:
name = my_object["code"] + " - " + my_object["name"]
label = _("Ending balance")
super(GeneralLedgerXslx, self).write_ending_balance_from_dict(
if 'partner' in my_object._name:
name = my_object.name
label = _('Partner ending balance')
elif 'account' in my_object._name:
name = my_object.code + ' - ' + my_object.name
label = _('Ending balance')
super(GeneralLedgerXslx, self).write_ending_balance(
my_object, name, label
)

1185
account_financial_report/report/journal_ledger.py
File diff suppressed because it is too large
View File

300
account_financial_report/report/journal_ledger_xlsx.py

@ -7,57 +7,82 @@ from odoo import _, models
class JournalLedgerXslx(models.AbstractModel):
_name = "report.a_f_r.report_journal_ledger_xlsx"
_description = "Journal Ledger XLSX Report"
_inherit = "report.account_financial_report.abstract_report_xlsx"
_name = 'report.a_f_r.report_journal_ledger_xlsx'
_inherit = 'report.account_financial_report.abstract_report_xlsx'
def _get_report_name(self, report, data=False):
company_id = data.get("company_id", False)
report_name = _("Journal Ledger")
if company_id:
company = self.env["res.company"].browse(company_id)
suffix = " - {} - {}".format(company.name, company.currency_id.name)
report_name = report_name + suffix
return report_name
def _get_report_name(self, report):
report_name = _('Journal Ledger')
return self._get_report_complete_name(report, report_name)
def _get_report_columns(self, report):
columns = [
{"header": _("Entry"), "field": "entry", "width": 18},
{"header": _("Date"), "field": "date", "width": 11},
{"header": _("Account"), "field": "account_code", "width": 9},
{
'header': _('Entry'),
'field': 'entry',
'width': 18
},
{
'header': _('Date'),
'field': 'date',
'width': 11
},
{
'header': _('Account'),
'field': 'account_code',
'width': 9
},
]
if report.with_auto_sequence:
columns.insert(
0, {"header": _("Sequence"), "field": "auto_sequence", "width": 10}
)
if report.with_account_name:
columns.append(
{"header": _("Account Name"), "field": "account_name", "width": 15}
)
columns.append({
'header': _('Account Name'),
'field': 'account',
'width': 15
})
columns += [
{"header": _("Partner"), "field": "partner", "width": 25},
{"header": _("Ref - Label"), "field": "label", "width": 40},
{"header": _("Taxes"), "field": "taxes_description", "width": 11},
{"header": _("Debit"), "field": "debit", "type": "amount", "width": 14},
{"header": _("Credit"), "field": "credit", "type": "amount", "width": 14},
{
'header': _('Partner'),
'field': 'partner',
'width': 25
},
{
'header': _('Ref - Label'),
'field': 'label',
'width': 40
},
{
'header': _('Taxes'),
'field': 'taxes_description',
'width': 11
},
{
'header': _('Debit'),
'field': 'debit',
'type': 'amount',
'width': 14,
},
{
'header': _('Credit'),
'field': 'credit',
'type': 'amount',
'width': 14
}
]
if report.foreign_currency:
columns += [
{
"header": _("Currency"),
"field": "currency_name",
"width": 14,
"type": "currency_name",
'header': _('Currency'),
'field': 'currency_id',
'type': 'many2one',
'width': 14
},
{
"header": _("Amount Currency"),
"field": "amount_currency",
"type": "amount",
"width": 18,
'header': _('Amount Currency'),
'field': 'amount_currency',
'type': 'amount',
'width': 18
},
]
@ -68,43 +93,51 @@ class JournalLedgerXslx(models.AbstractModel):
def _get_journal_tax_columns(self, report):
return {
0: {"header": _("Name"), "field": "tax_name", "width": 35},
1: {"header": _("Description"), "field": "tax_code", "width": 18},
0: {
'header': _('Name'),
'field': 'tax_name',
'width': 35
},
1: {
'header': _('Description'),
'field': 'tax_code',
'width': 18
},
2: {
"header": _("Base Debit"),
"field": "base_debit",
"type": "amount",
"width": 14,
'header': _('Base Debit'),
'field': 'base_debit',
'type': 'amount',
'width': 14
},
3: {
"header": _("Base Credit"),
"field": "base_credit",
"type": "amount",
"width": 14,
'header': _('Base Credit'),
'field': 'base_credit',
'type': 'amount',
'width': 14
},
4: {
"header": _("Base Balance"),
"field": "base_balance",
"type": "amount",
"width": 14,
'header': _('Base Balance'),
'field': 'base_balance',
'type': 'amount',
'width': 14
},
5: {
"header": _("Tax Debit"),
"field": "tax_debit",
"type": "amount",
"width": 14,
'header': _('Tax Debit'),
'field': 'tax_debit',
'type': 'amount',
'width': 14
},
6: {
"header": _("Tax Credit"),
"field": "tax_credit",
"type": "amount",
"width": 14,
'header': _('Tax Credit'),
'field': 'tax_credit',
'type': 'amount',
'width': 14
},
7: {
"header": _("Tax Balance"),
"field": "tax_balance",
"type": "amount",
"width": 14,
'header': _('Tax Balance'),
'field': 'tax_balance',
'type': 'amount',
'width': 14
},
}
@ -117,89 +150,82 @@ class JournalLedgerXslx(models.AbstractModel):
def _get_report_filters(self, report):
target_label_by_value = {
value: label
for value, label in self.env[
"journal.ledger.report.wizard"
]._get_move_targets()
for value, label in
self.env['journal.ledger.report.wizard']._get_move_targets()
}
sort_option_label_by_value = {
value: label
for value, label in self.env[
"journal.ledger.report.wizard"
]._get_sort_options()
for value, label in
self.env['journal.ledger.report.wizard']._get_sort_options()
}
return [
[_("Company"), report.company_id.name],
[
_("Date range filter"),
_("From: %s To: %s") % (report.date_from, report.date_to),
_('Company'),
report.company_id.name
],
[
_('Date range filter'),
_('From: %s To: %s') % (report.date_from, report.date_to)
],
[
_("Target moves filter"),
_('Target moves filter'),
_("%s") % target_label_by_value[report.move_target],
],
[
_("Entries sorted by"),
_('Entries sorted by'),
_("%s") % sort_option_label_by_value[report.sort_option],
],
[
_("Journals"),
", ".join(
[
"{} - {}".format(report_journal.code, report_journal.name)
for report_journal in report.journal_ids
_('Journals'),
', '.join([
"%s - %s" % (report_journal.code, report_journal.name)
for report_journal in report.report_journal_ledger_ids
])
]
),
],
]
def _generate_report_content(self, workbook, report, data):
res_data = self.env[
"report.account_financial_report.journal_ledger"
]._get_report_values(report, data)
def _generate_report_content(self, workbook, report):
group_option = report.group_option
if group_option == "journal":
for ledger in res_data["Journal_Ledgers"]:
self._generate_journal_content(workbook, report, res_data, ledger)
elif group_option == "none":
self._generate_no_group_content(workbook, report, res_data)
if group_option == 'journal':
for report_journal in report.report_journal_ledger_ids:
self._generate_journal_content(workbook, report_journal)
elif group_option == 'none':
self._generate_no_group_content(workbook, report)
def _generate_no_group_content(self, workbook, report, res_data):
def _generate_no_group_content(self, workbook, report):
self._generate_moves_content(
workbook, "Report", report, res_data, res_data["Moves"]
workbook, report, "Report", report.report_move_ids)
self._generate_no_group_taxes_summary(workbook, report)
def _generate_journal_content(self, workbook, report_journal):
sheet_name = "%s (%s) - %s" % (
report_journal.code,
report_journal.currency_id.name,
report_journal.name,
)
self._generate_no_group_taxes_summary(workbook, report, res_data)
def _generate_journal_content(self, workbook, report, res_data, ledger):
journal = self.env["account.journal"].browse(ledger["id"])
currency_name = (
journal.currency_id
and journal.currency_id.name
or journal.company_id.currency_id.name
)
sheet_name = "{} ({}) - {}".format(journal.code, currency_name, journal.name)
self._generate_moves_content(
workbook, sheet_name, report, res_data, ledger["report_moves"]
)
self._generate_journal_taxes_summary(workbook, ledger)
def _generate_no_group_taxes_summary(self, workbook, report, res_data):
self._generate_taxes_summary(workbook, "Tax Report", res_data["tax_line_data"])
def _generate_journal_taxes_summary(self, workbook, ledger):
journal = self.env["account.journal"].browse(ledger["id"])
currency_name = (
journal.currency_id
and journal.currency_id.name
or journal.company_id.currency_id.name
workbook, report_journal.report_id, sheet_name,
report_journal.report_move_ids)
self._generate_journal_taxes_summary(workbook, report_journal)
def _generate_no_group_taxes_summary(self, workbook, report):
self._generate_taxes_summary(
workbook, report, "Tax Report", report.report_tax_line_ids)
def _generate_journal_taxes_summary(self, workbook, report_journal):
sheet_name = "Tax - %s (%s) - %s" % (
report_journal.code,
report_journal.currency_id.name,
report_journal.name,
)
sheet_name = "Tax - {} ({}) - {}".format(
journal.code, currency_name, journal.name
)
self._generate_taxes_summary(workbook, sheet_name, ledger["tax_lines"])
report = report_journal.report_id
self._generate_taxes_summary(
workbook, report, sheet_name, report_journal.report_tax_line_ids)
def _generate_moves_content(self, workbook, sheet_name, report, res_data, moves):
def _generate_moves_content(self, workbook, report, sheet_name, moves):
self.workbook = workbook
self.sheet = workbook.add_worksheet(sheet_name)
self._set_column_width()
@ -210,47 +236,15 @@ class JournalLedgerXslx(models.AbstractModel):
self.row_pos += 2
self.write_array_header()
account_ids_data = res_data["account_ids_data"]
partner_ids_data = res_data["partner_ids_data"]
currency_ids_data = res_data["currency_ids_data"]
move_ids_data = res_data["move_ids_data"]
for move in moves:
for line in move["report_move_lines"]:
currency_data = currency_ids_data.get(line["currency_id"], False)
currency_name = currency_data and currency_data["name"] or ""
account_data = account_ids_data.get(line["account_id"], False)
account_name = account_data and account_data["name"] or ""
account_code = account_data and account_data["code"] or ""
move_data = move_ids_data.get(line["move_id"], False)
move_entry = move_data and move_data["entry"] or ""
line["partner"] = self._get_partner_name(
line["partner_id"], partner_ids_data
)
line["auto_sequence"] = line["auto_sequence"]
line["account_code"] = account_code
line["account_name"] = account_name
line["currency_name"] = currency_name
line["entry"] = move_entry
line["taxes_description"] = report._get_ml_tax_description(
line,
res_data["tax_line_data"].get(line["tax_line_id"]),
res_data["move_line_ids_taxes_data"].get(
line["move_line_id"], False
),
)
self.write_line_from_dict(line)
for line in move.report_move_line_ids:
self.write_line(line)
self.row_pos += 1
def _generate_taxes_summary(self, workbook, sheet_name, tax_lines_dict):
def _generate_taxes_summary(self, workbook, report, sheet_name, tax_lines):
self.workbook = workbook
self.sheet = workbook.add_worksheet(sheet_name)
self.row_pos = 1
self.write_array_title(sheet_name)
self.row_pos += 2
def _get_partner_name(self, partner_id, partner_data):
if partner_id in partner_data.keys():
return partner_data[partner_id]["name"]
else:
return ""

1207
account_financial_report/report/open_items.py
File diff suppressed because it is too large
View File

208
account_financial_report/report/open_items_xlsx.py

@ -6,86 +6,63 @@ from odoo import _, models
class OpenItemsXslx(models.AbstractModel):
_name = "report.a_f_r.report_open_items_xlsx"
_description = "Open Items XLSX Report"
_inherit = "report.account_financial_report.abstract_report_xlsx"
def _get_report_name(self, report, data=False):
company_id = data.get("company_id", False)
report_name = _("Open Items")
if company_id:
company = self.env["res.company"].browse(company_id)
suffix = " - {} - {}".format(company.name, company.currency_id.name)
report_name = report_name + suffix
return report_name
_name = 'report.a_f_r.report_open_items_xlsx'
_inherit = 'report.account_financial_report.abstract_report_xlsx'
def _get_report_name(self, report):
report_name = _('Open Items')
return self._get_report_complete_name(report, report_name)
def _get_report_columns(self, report):
res = {
0: {"header": _("Date"), "field": "date", "width": 11},
1: {"header": _("Entry"), "field": "move_name", "width": 18},
2: {"header": _("Journal"), "field": "journal", "width": 8},
3: {"header": _("Account"), "field": "account", "width": 9},
4: {"header": _("Partner"), "field": "partner_name", "width": 25},
5: {"header": _("Ref - Label"), "field": "ref_label", "width": 40},
6: {"header": _("Due date"), "field": "date_maturity", "width": 11},
7: {
"header": _("Original"),
"field": "original",
"type": "amount",
"width": 14,
},
8: {
"header": _("Residual"),
"field": "amount_residual",
"field_final_balance": "residual",
"type": "amount",
"width": 14,
},
0: {'header': _('Date'), 'field': 'date', 'width': 11},
1: {'header': _('Entry'), 'field': 'entry', 'width': 18},
2: {'header': _('Journal'), 'field': 'journal', 'width': 8},
3: {'header': _('Account'), 'field': 'account', 'width': 9},
4: {'header': _('Partner'), 'field': 'partner', 'width': 25},
5: {'header': _('Ref - Label'), 'field': 'label', 'width': 40},
6: {'header': _('Due date'), 'field': 'date_due', 'width': 11},
7: {'header': _('Original'),
'field': 'amount_total_due',
'type': 'amount',
'width': 14},
8: {'header': _('Residual'),
'field': 'amount_residual',
'field_final_balance': 'final_amount_residual',
'type': 'amount',
'width': 14},
}
if report.foreign_currency:
foreign_currency = {
9: {
"header": _("Cur."),
"field": "currency_name",
"field_currency_balance": "currency_name",
"type": "currency_name",
"width": 7,
},
10: {
"header": _("Cur. Original"),
"field": "amount_currency",
"field_final_balance": "amount_currency",
"type": "amount_currency",
"width": 14,
},
11: {
"header": _("Cur. Residual"),
"field": "amount_residual_currency",
"field_final_balance": "amount_currency",
"type": "amount_currency",
"width": 14,
},
9: {'header': _('Cur.'), 'field': 'currency_id',
'field_currency_balance': 'currency_id',
'type': 'many2one', 'width': 7},
10: {'header': _('Cur. Original'),
'field': 'amount_total_due_currency',
'field_final_balance':
'final_amount_total_due_currency',
'type': 'amount_currency',
'width': 14},
11: {'header': _('Cur. Residual'),
'field': 'amount_residual_currency',
'field_final_balance':
'final_amount_residual_currency',
'type': 'amount_currency',
'width': 14},
}
res = {**res, **foreign_currency}
return res
def _get_report_filters(self, report):
return [
[_("Date at filter"), report.date_at.strftime("%d/%m/%Y")],
[
_("Target moves filter"),
_("All posted entries")
if report.target_move == "posted"
else _("All entries"),
],
[
_("Account balance at 0 filter"),
_("Hide") if report.hide_account_at_0 else _("Show"),
],
[
_("Show foreign currency"),
_("Yes") if report.foreign_currency else _("No"),
],
[_('Date at filter'), report.date_at],
[_('Target moves filter'),
_('All posted entries') if report.only_posted_moves else _(
'All entries')],
[_('Account balance at 0 filter'),
_('Hide') if report.hide_account_at_0 else _('Show')],
[_('Show foreign currency'),
_('Yes') if report.foreign_currency else _('No')],
]
def _get_col_count_filter_name(self):
@ -100,102 +77,43 @@ class OpenItemsXslx(models.AbstractModel):
def _get_col_pos_final_balance_label(self):
return 5
def _generate_report_content(self, workbook, report, data):
res_data = self.env[
"report.account_financial_report.open_items"
]._get_report_values(report, data)
def _generate_report_content(self, workbook, report):
# For each account
Open_items = res_data["Open_Items"]
accounts_data = res_data["accounts_data"]
partners_data = res_data["partners_data"]
journals_data = res_data["journals_data"]
total_amount = res_data["total_amount"]
show_partner_details = res_data["show_partner_details"]
for account_id in Open_items.keys():
for account in report.account_ids:
# Write account title
self.write_array_title(
accounts_data[account_id]["code"]
+ " - "
+ accounts_data[account_id]["name"]
)
self.write_array_title(account.code + ' - ' + account.name)
# For each partner
if Open_items[account_id]:
if show_partner_details:
for partner_id in Open_items[account_id]:
type_object = "partner"
for partner in account.partner_ids:
# Write partner title
self.write_array_title(partners_data[partner_id]["name"])
self.write_array_title(partner.name)
# Display array header for move lines
self.write_array_header()
# Display account move lines
for line in Open_items[account_id][partner_id]:
line.update(
{
"account": accounts_data[account_id]["code"],
"journal": journals_data[line["journal_id"]][
"code"
],
}
)
self.write_line_from_dict(line)
for line in partner.move_line_ids:
self.write_line(line)
# Display ending balance line for partner
partners_data[partner_id].update(
{
"currency_id": accounts_data[account_id]["currency_id"],
"currency_name": accounts_data[account_id][
"currency_name"
],
}
)
self.write_ending_balance_from_dict(
partners_data[partner_id],
type_object,
total_amount,
account_id,
partner_id,
)
self.write_ending_balance(partner, 'partner')
# Line break
self.row_pos += 1
else:
# Display array header for move lines
self.write_array_header()
# Display account move lines
for line in Open_items[account_id]:
line.update(
{
"account": accounts_data[account_id]["code"],
"journal": journals_data[line["journal_id"]]["code"],
}
)
self.write_line_from_dict(line)
# Display ending balance line for account
type_object = "account"
self.write_ending_balance_from_dict(
accounts_data[account_id], type_object, total_amount, account_id
)
self.write_ending_balance(account, 'account')
# 2 lines break
self.row_pos += 2
def write_ending_balance_from_dict(
self, my_object, type_object, total_amount, account_id=False, partner_id=False
):
def write_ending_balance(self, my_object, type_object):
"""Specific function to write ending balance for Open Items"""
if type_object == "partner":
name = my_object["name"]
my_object["residual"] = total_amount[account_id][partner_id]["residual"]
label = _("Partner ending balance")
elif type_object == "account":
name = my_object["code"] + " - " + my_object["name"]
my_object["residual"] = total_amount[account_id]["residual"]
label = _("Ending balance")
super(OpenItemsXslx, self).write_ending_balance_from_dict(
my_object, name, label
)
if type_object == 'partner':
name = my_object.name
label = _('Partner ending balance')
my_object.currency_id = my_object.report_account_id.currency_id
elif type_object == 'account':
name = my_object.code + ' - ' + my_object.name
label = _('Ending balance')
super(OpenItemsXslx, self).write_ending_balance(my_object, name, label)

537
account_financial_report/report/templates/aged_partner_balance.xml

@ -1,91 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="aged_partner_balance">
<template id="report_aged_partner_balance_qweb">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="account_financial_report.internal_layout">
<t
t-call="account_financial_report.report_aged_partner_balance_base"
/>
<t t-call="account_financial_report.report_aged_partner_balance_base"/>
</t>
</t>
</t>
</template>
<template id="report_aged_partner_balance_base">
<!-- Saved flag fields into variables, used to define columns display -->
<t t-set="show_move_line_details" t-value="show_move_line_details" />
<t t-set="show_move_line_details" t-value="o.show_move_line_details"/>
<!-- Defines global variables used by internal layout -->
<t t-set="title">Aged Partner Balance - <t t-raw="company_name" /> - <t
t-raw="currency_name"
/></t>
<t t-set="title">Aged Partner Balance - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t>
<t t-set="company_name" t-value="o.company_id.name"/>
<div class="page">
<div class="row">
<h4
class="mt0"
t-esc="title or 'Odoo Report'"
style="text-align: center;"
/>
<h4 class="mt0" t-esc="title or 'Odoo Report'" style="text-align: center;"/>
</div>
<!-- Display filters -->
<t t-call="account_financial_report.report_aged_partner_balance_filters"/>
<t t-foreach="aged_partner_balance" t-as="account">
<t t-foreach="o.account_ids" t-as="account">
<div class="page_break">
<!-- Display account header -->
<div class="act_as_table list_table" style="margin-top: 10px;"/>
<div class="act_as_caption account_title" style="width: 100%;">
<span t-esc="account['code']" />
<div class="act_as_caption account_title"
style="width: 100%;">
<span t-field="account.code"/>
-
<span t-esc="account['name']" />
<span t-field="account.name"/>
</div>
<!-- Display account lines -->
<t t-if="not show_move_line_details">
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_table data_table"
style="width: 100%;">
<!-- Display account header -->
<t
t-call="account_financial_report.report_aged_partner_balance_lines_header"
/>
<t t-foreach="account['partners']" t-as="partner">
<t t-call="account_financial_report.report_aged_partner_balance_lines_header"/>
<t t-foreach="account.partner_ids" t-as="partner">
<!-- Display one line per partner -->
<t
t-call="account_financial_report.report_aged_partner_balance_lines"
/>
<t t-call="account_financial_report.report_aged_partner_balance_lines"/>
</t>
</div>
<!-- Display account footer -->
<t
t-call="account_financial_report.report_aged_partner_balance_account_ending_cumul"
/>
<t t-call="account_financial_report.report_aged_partner_balance_account_ending_cumul"/>
</t>
<!-- Display account move lines -->
<t t-if="show_move_line_details">
<!-- Display account partners -->
<t t-foreach="account['partners']" t-as="partner">
<t t-foreach="account.partner_ids" t-as="partner">
<div class="page_break">
<!-- Display partner header -->
<div class="act_as_caption account_title">
<span t-esc="partner['name']" />
<span t-field="partner.name"/>
</div>
<!-- Display partner move lines -->
<t
t-call="account_financial_report.report_aged_partner_balance_move_lines"
/>
<t t-call="account_financial_report.report_aged_partner_balance_move_lines"/>
<!-- Display partner footer -->
<t
t-call="account_financial_report.report_aged_partner_balance_partner_ending_cumul"
>
<t t-set="partner_cumul_line" t-value="partner" />
<t t-call="account_financial_report.report_aged_partner_balance_partner_ending_cumul">
<t t-set="partner_cumul_line" t-value="partner.line_ids"/>
</t>
</div>
</t>
<!-- Display account footer -->
<t
t-call="account_financial_report.report_aged_partner_balance_account_ending_cumul"
/>
<t t-call="account_financial_report.report_aged_partner_balance_account_ending_cumul"/>
</t>
</div>
</t>
</div>
</template>
<template id="report_aged_partner_balance_filters">
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_row labels">
@ -94,15 +90,16 @@
</div>
<div class="act_as_row">
<div class="act_as_cell">
<span t-esc="date_at" />
<span t-field="o.date_at"/>
</div>
<div class="act_as_cell">
<t t-if="only_posted_moves">All posted entries</t>
<t t-if="not only_posted_moves">All entries</t>
<t t-if="o.only_posted_moves">All posted entries</t>
<t t-if="not o.only_posted_moves">All entries</t>
</div>
</div>
</div>
</template>
<template id="report_aged_partner_balance_lines_header">
<!-- Display table headers for lines -->
<div class="act_as_thead">
@ -126,64 +123,48 @@
</div>
</div>
</template>
<template id="report_aged_partner_balance_lines">
<!-- Display each partner lines -->
<!-- Display each lines -->
<t t-foreach="partner.line_ids" t-as="line">
<!-- # lines -->
<div class="act_as_row lines">
<!--## partner-->
<div class="act_as_cell left">
<span t-esc="partner['name']" />
<span t-field="line.partner"/>
</div>
<!--## amount_residual-->
<div class="act_as_cell amount">
<span
t-esc="partner['residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## current-->
<div class="act_as_cell amount">
<span
t-esc="partner['current']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_30_days-->
<div class="act_as_cell amount">
<span
t-esc="partner['30_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_60_days-->
<div class="act_as_cell amount">
<span
t-esc="partner['60_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_90_days-->
<div class="act_as_cell amount">
<span
t-esc="partner['90_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_120_days-->
<div class="act_as_cell amount">
<span
t-esc="partner['120_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## older-->
<div class="act_as_cell amount">
<span
t-esc="partner['older']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
</div>
</t>
</template>
<template id="report_aged_partner_balance_move_lines">
<div class="act_as_table data_table" style="width: 100%;">
<!-- Display table headers for move lines -->
@ -229,220 +210,186 @@
</div>
</div>
<!-- Display each move lines -->
<t t-foreach="partner['move_lines']" t-as="line">
<t t-foreach="partner.move_line_ids" t-as="line">
<!-- # lines or centralized lines -->
<div class="act_as_row lines">
<!--## date-->
<div class="act_as_cell left">
<span
t-att-res-id="line.move_line_id.id"
res-model="account.move.line"
view-type="form"
>
<span>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action"
style="color: black;">
<!--## We don't use t-field because it throws an error on click -->
<t t-esc="line['date']" t-options="{'widget': 'date'}" />
<t t-esc="line.date" t-options="{'widget': 'date'}"/></a>
</span>
</div>
<!--## move-->
<div class="act_as_cell left">
<span
t-att-res-id="line.move_line_id.move_id.id"
res-model="account.move"
view-type="form"
>
<t t-raw="line['entry']" />
<span>
<a t-att-data-active-id="line.move_line_id.move_id.id"
t-att-data-res-model="'account.move'"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.entry"/></a>
</span>
</div>
<!--## journal-->
<div class="act_as_cell left">
<span
t-att-res-id="line.move_line_id.move_id.journal_id.id"
res-model="account.journal"
view-type="form"
>
<t t-raw="line['journal']" />
<span>
<a t-att-data-active-id="line.move_line_id.move_id.journal_id.id"
t-att-data-res-model="'account.journal'"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.journal"/></a>
</span>
</div>
<!--## account code-->
<div class="act_as_cell left">
<span
t-att-res-id="line.move_line_id.account_id.id"
res-model="account.account"
view-type="form"
>
<t t-raw="line['account']" />
<span>
<a t-att-data-active-id="line.move_line_id.account_id.id"
t-att-data-res-model="'account.account'"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.account"/></a>
</span>
</div>
<!--## partner-->
<div class="act_as_cell left">
<span
t-att-res-id="line.move_line_id.partner_id.id"
res-model="res.partner"
view-type="form"
>
<t t-raw="line['partner']" />
<span>
<a t-att-data-active-id="line.move_line_id.partner_id.id"
t-att-data-res-model="'res.partner'"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.partner"/></a>
</span>
</div>
<!--## ref - label-->
<div class="act_as_cell left">
<span
t-att-res-id="line.move_line_id.id"
res-model="account.move.line"
view-type="form"
>
<t t-raw="line['ref_label']" />
<span>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.label"/></a>
</span>
</div>
<!--## date_due-->
<div class="act_as_cell left">
<span
t-att-res-id="line.move_line_id.id"
res-model="account.move.line"
view-type="form"
>
<span>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action"
style="color: black;">
<!--## We don't use t-field because it throws an error on click -->
<t
t-esc="line['due_date']"
t-options="{'widget': 'date'}"
/>
<t t-esc="line.date_due" t-options="{'widget': 'date'}"/></a>
</span>
</div>
<!--## amount_residual-->
<div class="act_as_cell amount">
<span
domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
res-model="account.move.line"
>
<t
t-raw="line['residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span>
<a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
style="color: black;">
<t t-raw="line.amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</div>
<!--## current-->
<div class="act_as_cell amount">
<t t-if="line.current == 0">
<span
t-field="line.current"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<t t-else="">
<span
domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
res-model="account.move.line"
>
<t
t-raw="line['current']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-if="line.current != 0">
<span>
<a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
style="color: black;">
<t t-raw="line.current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.current == 0">
<span t-field="line.current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</t>
</div>
<!--## age_30_days-->
<div class="act_as_cell amount">
<t t-if="line.age_30_days == 0">
<span
t-field="line.age_30_days"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<t t-else="">
<span
domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
res-model="account.move.line"
>
<t
t-raw="line['30_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-if="line.age_30_days != 0">
<span>
<a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
style="color: black;">
<t t-raw="line.age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.age_30_days == 0">
<span t-field="line.age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</t>
</div>
<!--## age_60_days-->
<div class="act_as_cell amount">
<t t-if="line.age_60_days == 0">
<span
t-field="line.age_60_days"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<t t-else="">
<span
domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
res-model="account.move.line"
>
<t
t-raw="line['60_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-if="line.age_60_days != 0">
<span>
<a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
style="color: black;">
<t t-raw="line.age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.age_60_days == 0">
<span t-field="line.age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</t>
</div>
<!--## age_90_days-->
<div class="act_as_cell amount">
<t t-if="line.age_90_days == 0">
<span
t-field="line.age_90_days"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<t t-else="">
<span
domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
res-model="account.move.line"
>
<t
t-raw="line['90_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-if="line.age_90_days != 0">
<span>
<a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
style="color: black;">
<t t-raw="line.age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.age_90_days == 0">
<span t-field="line.age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</t>
</div>
<!--## age_120_days-->
<div class="act_as_cell amount">
<t t-if="line.age_120_days == 0">
<span
t-field="line.age_120_days"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<t t-else="">
<span
domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
res-model="account.move.line"
>
<t
t-raw="line['120_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-if="line.age_120_days != 0">
<span>
<a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
style="color: black;">
<t t-raw="line.age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.age_120_days == 0">
<span t-field="line.age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</t>
</div>
<!--## older-->
<div class="act_as_cell amount">
<t t-if="line.older == 0">
<span
t-field="line.older"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<t t-else="">
<span
domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
res-model="account.move.line"
>
<t
t-raw="line['older']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-if="line.older != 0">
<span>
<a t-att-data-domain="[('id', 'in', (line.move_line_id | line.move_line_id.matched_debit_ids.mapped('debit_move_id') | line.move_line_id.matched_credit_ids.mapped('credit_move_id')).ids)]"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
style="color: black;">
<t t-raw="line.older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="line.older == 0">
<span t-field="line.older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</t>
</div>
</div>
</t>
</div>
</template>
<template id="report_aged_partner_balance_partner_ending_cumul">
<!-- Display ending balance line for partner -->
<div class="act_as_table list_table" style="width: 100%;">
@ -454,56 +401,36 @@
<div class="act_as_cell" style="width: 6.00%;"/>
<!--## amount_residual-->
<div class="act_as_cell amount" style="width: 6.00%;">
<span
t-esc="partner_cumul_line['residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="partner_cumul_line.amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## current-->
<div class="act_as_cell amount" style="width: 6.00%;">
<span
t-esc="partner_cumul_line['current']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="partner_cumul_line.current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_30_days-->
<div class="act_as_cell amount" style="width: 6.00%;">
<span
t-esc="partner_cumul_line['30_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="partner_cumul_line.age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_60_days-->
<div class="act_as_cell amount" style="width: 6.00%;">
<span
t-esc="partner_cumul_line['60_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="partner_cumul_line.age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_90_days-->
<div class="act_as_cell amount" style="width: 6.00%;">
<span
t-esc="partner_cumul_line['90_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="partner_cumul_line.age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_120_days-->
<div class="act_as_cell amount" style="width: 6.00%;">
<span
t-esc="partner_cumul_line['120_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="partner_cumul_line.age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## older-->
<div class="act_as_cell amount" style="width: 6.00%;">
<span
t-esc="partner_cumul_line['older']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="partner_cumul_line.older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
</div>
</div>
</template>
<template id="report_aged_partner_balance_account_ending_cumul">
<!-- Display ending balance line for account -->
<div class="act_as_table list_table" style="width: 100%;">
@ -513,52 +440,31 @@
<div class="act_as_cell right" style="width: 32.52%;">Total</div>
<!--## amount_residual-->
<div class="act_as_cell amount" style="width: 9.64%;">
<span
t-esc="account['residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## current-->
<div class="act_as_cell amount" style="width: 9.64%;">
<span
t-esc="account['current']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_30_days-->
<div class="act_as_cell amount" style="width: 9.64%;">
<span
t-esc="account['30_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_60_days-->
<div class="act_as_cell amount" style="width: 9.64%;">
<span
t-esc="account['60_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_90_days-->
<div class="act_as_cell amount" style="width: 9.64%;">
<span
t-esc="account['90_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_120_days-->
<div class="act_as_cell amount" style="width: 9.64%;">
<span
t-esc="account['120_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## older-->
<div class="act_as_cell amount" style="width: 9.64%;">
<span
t-esc="account['older']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
</t>
<t t-if="show_move_line_details">
@ -568,52 +474,31 @@
<div class="act_as_cell" style="width: 6.00%;"/>
<!--## amount_residual-->
<div class="act_as_cell amount" style="width: 6.00%">
<span
t-esc="account['residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## current-->
<div class="act_as_cell amount" style="width: 6.00%">
<span
t-esc="account['current']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_current" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_30_days-->
<div class="act_as_cell amount" style="width: 6.00%">
<span
t-esc="account['30_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_30_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_60_days-->
<div class="act_as_cell amount" style="width: 6.00%">
<span
t-esc="account['60_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_60_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_90_days-->
<div class="act_as_cell amount" style="width: 6.00%">
<span
t-esc="account['90_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_90_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## age_120_days-->
<div class="act_as_cell amount" style="width: 6.00%">
<span
t-esc="account['120_days']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_age_120_days" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## older-->
<div class="act_as_cell amount" style="width: 6.00%">
<span
t-esc="account['older']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="account.cumul_older" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
</t>
</div>
@ -625,34 +510,23 @@
<!--## amount_residual-->
<div class="act_as_cell amount" style="width: 9.64%;"/>
<!--## current-->
<div class="act_as_cell amount" style="width: 9.64%;"><span
t-esc="account['percent_current']"
/>%
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_current"/>%
</div>
<!--## age_30_days-->
<div class="act_as_cell amount" style="width: 9.64%;"><span
t-esc="account['percent_30_days']"
/>%
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_30_days"/>%
</div>
<!--## age_60_days-->
<div class="act_as_cell amount" style="width: 9.64%;"><span
t-esc="account['percent_60_days']"
/>%
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_60_days"/>%
</div>
<!--## age_90_days-->
<div class="act_as_cell amount" style="width: 9.64%;"><span
t-esc="account['percent_90_days']"
/>%
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_90_days"/>%
</div>
<!--## age_120_days-->
<div class="act_as_cell amount" style="width: 9.64%;"><span
t-esc="account['percent_120_days']"
/>%
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_age_120_days"/>
%
</div>
<!--## older-->
<div class="act_as_cell amount" style="width: 9.64%;"><span
t-esc="account['percent_older']"
/>%
<div class="act_as_cell amount" style="width: 9.64%;"><span t-field="account.percent_older"/>%
</div>
</t>
<t t-if="show_move_line_details">
@ -664,37 +538,26 @@
<!--## amount_residual-->
<div class="act_as_cell amount" style="width: 6.00%"/>
<!--## current-->
<div class="act_as_cell amount" style="width: 6.00%"><span
t-esc="account['percent_current']"
/>%
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_current"/>%
</div>
<!--## age_30_days-->
<div class="act_as_cell amount" style="width: 6.00%"><span
t-esc="account['percent_30_days']"
/>%
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_30_days"/>%
</div>
<!--## age_60_days-->
<div class="act_as_cell amount" style="width: 6.00%"><span
t-esc="account['percent_60_days']"
/>%
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_60_days"/>%
</div>
<!--## age_90_days-->
<div class="act_as_cell amount" style="width: 6.00%"><span
t-esc="account['percent_90_days']"
/>%
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_90_days"/>%
</div>
<!--## age_120_days-->
<div class="act_as_cell amount" style="width: 6.00%"><span
t-esc="account['percent_120_days']"
/>%
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_age_120_days"/>%
</div>
<!--## older-->
<div class="act_as_cell amount" style="width: 6.00%"><span
t-esc="account['percent_older']"
/>%
<div class="act_as_cell amount" style="width: 6.00%"><span t-field="account.percent_older"/>%
</div>
</t>
</div>
</div>
</template>
</odoo>

666
account_financial_report/report/templates/general_ledger.xml

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="general_ledger">
<template id="report_general_ledger_qweb">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="account_financial_report.internal_layout">
@ -9,101 +10,72 @@
</t>
</t>
</template>
<template id="report_general_ledger_base">
<!-- Saved flag fields into variables, used to define columns display -->
<t t-set="foreign_currency" t-value="foreign_currency" />
<t t-set="filter_partner_ids" t-value="filter_partner_ids" />
<t t-set="show_analytic_tags" t-value="o.show_analytic_tags"/>
<t t-set="show_cost_center" t-value="o.show_cost_center"/>
<t t-set="foreign_currency" t-value="o.foreign_currency"/>
<!-- Defines global variables used by internal layout -->
<t t-set="title">General Ledger - <t t-raw="company_name" /> - <t
t-raw="currency_name"
/></t>
<t t-set="title">General Ledger - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t>
<t t-set="company_name" t-value="o.company_id.name"/>
<div class="page">
<div class="row">
<h4
class="mt0"
t-esc="title or 'Odoo Report'"
style="text-align: center;"
/>
<h4 class="mt0" t-esc="title or 'Odoo Report'" style="text-align: center;"/>
</div>
<!-- Display filters -->
<t t-call="account_financial_report.report_general_ledger_filters"/>
<t t-foreach="general_ledger" t-as="account">
<t t-foreach="o.account_ids" t-as="account">
<div class="page_break">
<!-- Display account header -->
<div class="act_as_table list_table" style="margin-top: 10px;"/>
<div class="act_as_caption account_title" style="width: 100%">
<span
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'code')"
/> -
<span
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'name')"
/>
</div>
<t t-if="not account['partners']">
<div class="act_as_caption account_title"
style="width: 100%">
<span t-field="account.code"/> - <span t-field="account.name"/>
</div>
<t t-if="not account.partner_ids">
<!-- Display account move lines without partner regroup -->
<t t-set="type" t-value='"account_type"'/>
<t
t-call="account_financial_report.report_general_ledger_lines"
>
<t t-call="account_financial_report.report_general_ledger_lines">
<t t-set="account_or_partner_object" t-value="account"/>
</t>
<!-- Display account footer -->
<t
t-call="account_financial_report.report_general_ledger_ending_cumul"
>
<t t-set="account_or_partner_object" t-value="account" />
<t t-set="type" t-value='"account_type"' />
</t>
</t>
<t t-if="account['partners']">
<t t-if="account.partner_ids">
<!-- Display account partners -->
<t t-foreach="account['list_partner']" t-as="partner">
<t t-foreach="account.partner_ids" t-as="partner">
<t t-set="type" t-value='"partner_type"'/>
<div class="page_break">
<!-- Display partner header -->
<div class="act_as_caption account_title">
<span
t-esc="o._get_atr_from_dict(partner['id'], partners_data, 'name')"
/>
<span t-field="partner.name"/>
</div>
<!-- Display partner move lines -->
<t
t-call="account_financial_report.report_general_ledger_lines"
>
<t
t-set="account_or_partner_object"
t-value="partner"
/>
<t t-call="account_financial_report.report_general_ledger_lines">
<t t-set="account_or_partner_object" t-value="partner"/>
</t>
<!-- Display partner footer -->
<t
t-call="account_financial_report.report_general_ledger_ending_cumul"
>
<t
t-set="account_or_partner_object"
t-value="partner"
/>
<t t-call="account_financial_report.report_general_ledger_ending_cumul">
<t t-set="account_or_partner_object" t-value="partner"/>
<t t-set="type" t-value='"partner_type"'/>
</t>
</div>
</t>
</t>
<!-- Display account footer -->
<t t-if="not filter_partner_ids">
<t
t-call="account_financial_report.report_general_ledger_ending_cumul"
>
<t
t-set="account_or_partner_object"
t-value="account"
/>
<t t-if="not o.filter_partner_ids" t-call="account_financial_report.report_general_ledger_ending_cumul">
<t t-set="account_or_partner_object" t-value="account"/>
<t t-set="type" t-value='"account_type"'/>
</t>
</t>
</t>
</div>
</t>
</div>
</template>
<template id="account_financial_report.report_general_ledger_filters">
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_row labels">
@ -115,29 +87,31 @@
</div>
<div class="act_as_row">
<div class="act_as_cell">
From: <span t-esc="date_from" /> To: <span t-esc="date_to" />
From: <span t-field="o.date_from"/> To: <span t-field="o.date_to"/>
</div>
<div class="act_as_cell">
<t t-if="only_posted_moves">All posted entries</t>
<t t-if="not only_posted_moves">All entries</t>
<t t-if="o.only_posted_moves">All posted entries</t>
<t t-if="not o.only_posted_moves">All entries</t>
</div>
<div class="act_as_cell">
<t t-if="hide_account_at_0">Hide</t>
<t t-if="not hide_account_at_0">Show</t>
<t t-if="o.hide_account_at_0">Hide</t>
<t t-if="not o.hide_account_at_0">Show</t>
</div>
<div class="act_as_cell">
<t t-if="centralize">Yes</t>
<t t-if="not centralize">No</t>
<t t-if="o.centralize">Yes</t>
<t t-if="not o.centralize">No</t>
</div>
<div class="act_as_cell">
<t t-if="show_analytic_tags">Yes</t>
<t t-if="not show_analytic_tags">No</t>
<t t-if="o.show_analytic_tags">Yes</t>
<t t-if="not o.show_analytic_tags">No</t>
</div>
</div>
</div>
</template>
<template id="account_financial_report.report_general_ledger_lines">
<div class="act_as_table data_table" style="width: 100%;">
<!-- Display table headers for lines -->
<div class="act_as_thead">
<div class="act_as_row labels">
@ -156,14 +130,12 @@
<div class="act_as_cell" style="width: 12.01%;">Partner
</div>
<!--## ref - label-->
<div class="act_as_cell" style="width: 16.9%;">Ref -
<div class="act_as_cell" style="width: 22.9%;">Ref -
Label</div>
<t t-if="show_cost_center">
<!--## cost_center-->
<div
class="act_as_cell"
style="width: 8.03%;"
>Analytic Account</div>
<div class="act_as_cell" style="width: 8.03%;">Cost
center</div>
</t>
<t t-if="show_analytic_tags">
<!--## analytic tags-->
@ -172,25 +144,20 @@
<!--## matching_number-->
<div class="act_as_cell" style="width: 2.41%;">Rec.</div>
<!--## debit-->
<div class="act_as_cell amount" style="width: 8.02%;">Debit</div>
<div class="act_as_cell amount" style="width: 6.02%;">Debit</div>
<!--## credit-->
<div class="act_as_cell amount" style="width: 8.02%;">Credit</div>
<div class="act_as_cell amount" style="width: 6.02%;">Credit</div>
<!--## balance cumulated-->
<div
class="act_as_cell amount"
style="width: 8.02%;"
>Cumul. Bal.</div>
<div class="act_as_cell amount" style="width: 6.02%;">Cumul. Bal.</div>
<t t-if="foreign_currency">
<!--## currency_name-->
<div class="act_as_cell" style="width: 2.08%;">Cur.</div>
<!--## amount_currency-->
<div
class="act_as_cell amount"
style="width: 5.19%;"
>Amount cur.</div>
<div class="act_as_cell amount" style="width: 5.19%;">Amount cur.</div>
</t>
</div>
</div>
<!-- Display first line with initial balance -->
<div class="act_as_row lines">
<!--## date-->
@ -213,386 +180,289 @@
</t>
<t t-if="show_analytic_tags">
<!--## analytic tags-->
<div class="act_as_cell" />
<div class="act_as_cell"></div>
</t>
<!--## matching_number-->
<div class="act_as_cell"/>
<!--## debit-->
<div class="act_as_cell amount">
<t t-if="type == 'account_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('date', '&lt;', date_from),
('debit', '&lt;&gt;', 0)]"
/>
<span t-att-domain="domain" res-model="account.move.line">
<t
t-raw="account_or_partner_object['init_bal']['debit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.account_id.id),
('date', '&lt;', o.date_from.strftime('%Y-%m-%d')),
('debit', '&lt;&gt;', 0)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="type == 'partner_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('partner_id', '=', partner['id']),
('date', '&lt;', date_from),
('debit', '&lt;&gt;', 0)]"
/>
<span t-att-domain="domain" res-model="account.move.line">
<t
t-raw="account_or_partner_object['init_bal']['debit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.report_account_id.account_id.id),
('partner_id', '=', account_or_partner_object.partner_id.id),
('date', '&lt;', o.date_from.strftime('%Y-%m-%d')),
('debit', '&lt;&gt;', 0)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</div>
<!--## credit-->
<div class="act_as_cell amount">
<t t-if="type == 'account_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('date', '&lt;', date_from),
('credit', '&lt;&gt;', 0)]"
/>
<span t-att-domain="domain" res-model="account.move.line">
<t
t-raw="account_or_partner_object['init_bal']['credit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.account_id.id),
('date', '&lt;', o.date_from.strftime('%Y-%m-%d')),
('credit', '&lt;&gt;', 0)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="type == 'partner_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('partner_id', '=', partner['id']),
('date', '&lt;', date_from),
('credit', '&lt;&gt;', 0)]"
/>
<span t-att-domain="domain" res-model="account.move.line">
<t
t-raw="account_or_partner_object['init_bal']['credit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.report_account_id.account_id.id),
('partner_id', '=', account_or_partner_object.partner_id.id),
('date', '&lt;', o.date_from.strftime('%Y-%m-%d')),
('credit', '&lt;&gt;', 0)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</div>
<!--## balance cumulated-->
<div class="act_as_cell amount">
<t t-if="type == 'account_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('date', '&lt;', date_from)]"
/>
<span t-att-domain="domain" res-model="account.move.line">
<t
t-raw="account_or_partner_object['init_bal']['balance']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.account_id.id),
('date', '&lt;', o.date_from.strftime('%Y-%m-%d'))]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
<t t-if="type == 'partner_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('partner_id', '=', partner['id']),
('date', '&lt;', date_from)]"
/>
<span t-att-domain="domain" res-model="account.move.line">
<t
t-raw="account_or_partner_object['init_bal']['balance']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.report_account_id.account_id.id),
('partner_id', '=', account_or_partner_object.partner_id.id),
('date', '&lt;', o.date_from.strftime('%Y-%m-%d'))]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</div>
<t t-if="foreign_currency">
<t
t-if="o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')"
>
<t t-if="account.account_id.currency_id.id">
<div class="act_as_cell amount" style="width: 2.08%;">
<span
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'currency_name')"
/>
<span t-field="account.account_id.currency_id.display_name"/>
</div>
<div class="act_as_cell amount" style="width: 5.19%;">
<t t-if="type == 'account_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('date', '&lt;', o.date_from)]"
/>
<span
t-att-domain="domain"
res-model="account.move.line"
>
<t
t-raw="account_or_partner_object['init_bal']['bal_curr']"
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.account_id.id),
('date', '&lt;', o.date_from)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account.account_id.currency_id}"/></a>
</span>
</t>
<t t-if="type == 'partner_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('partner_id', '=', partner['id']),
('date', '&lt;', o.date_from)]"
/>
<span
t-att-domain="domain"
res-model="account.move.line"
>
<t
t-raw="account_or_partner_object['init_bal']['bal_curr']"
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.report_account_id.account_id.id),
('partner_id', '=', account_or_partner_object.partner_id.id),
('date', '&lt;', o.date_from)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;">
<t t-raw="account_or_partner_object.initial_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account.account_id.currency_id}"/></a>
</span>
</t>
</div>
</t>
<t
t-if="not o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')"
>
<t t-if="not account.account_id.currency_id.id">
<div class="act_as_cell" style="width: 2.08%;"/>
<div class="act_as_cell" style="width: 5.19%;"/>
</t>
</t>
</div>
<!-- Display each lines -->
<t t-foreach="account_or_partner_object['move_lines']" t-as="line">
<t t-foreach="account_or_partner_object.move_line_ids" t-as="line">
<!-- # lines or centralized lines -->
<div class="act_as_row lines">
<!--## date-->
<div class="act_as_cell left">
<t t-if="line['id']">
<!--## We don't use t-field because it throws an error on click -->
<span
t-att-res-id="line['id']"
res-model="account.move.line"
view-type="form"
>
<t
t-esc="line['date']"
t-options="{'widget': 'date'}"
/>
</span>
</t>
<t t-else="">
<t t-set="res_model" t-value="'account.move.line'"/>
<span>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<!--## We don't use t-field because it throws an error on click -->
<t
t-esc="line['date']"
t-options="{'widget': 'date'}"
/>
<t t-esc="line.date" t-options="{'widget': 'date'}"/></a>
</span>
</t>
</div>
<!--## move-->
<div class="act_as_cell left">
<t t-if="line['entry_id']">
<span
t-att-res-id="line['entry_id']"
res-model="account.move"
view-type="form"
>
<t t-raw="line['entry']" />
<t t-set="res_model" t-value="'account.move'"/>
<span>
<a t-att-data-active-id="line.move_line_id.move_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.entry"/></a>
</span>
</t>
</div>
<!--## journal-->
<div class="act_as_cell left">
<span
t-att-res-id="line['journal_id']"
res-model="account.journal"
view-type="form"
>
<t
t-raw="o._get_atr_from_dict(line['journal_id'], journals_data, 'code')"
/>
<t t-set="res_model" t-value="'account.journal'"/>
<span>
<a t-att-data-active-id="line.move_line_id.move_id.journal_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.journal"/></a>
</span>
</div>
<!--## account code-->
<div class="act_as_cell left">
<span
t-att-res-id="account['id']"
res-model="account.account"
view-type="form"
>
<t
t-raw="o._get_atr_from_dict(account['id'], accounts_data, 'code')"
/>
<t t-set="res_model" t-value="'account.account'"/>
<span>
<a t-att-data-active-id="line.move_line_id.account_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.account"/></a>
</span>
</div>
<!--## taxes-->
<div class="act_as_cell left">
<t t-if="taxes_data and line['tax_ids']">
<t t-foreach="line['tax_ids']" t-as="tax_id">
<span
t-esc="o._get_atr_from_dict(tax_id, taxes_data, 'tax_name')"
/>
</t>
</t>
</div>
<div class="act_as_cell left"><span t-field="line.taxes_description"/></div>
<!--## partner-->
<div class="act_as_cell left">
<t t-if="line['partner_id']">
<span
t-att-res-id="line['partner_id']"
res-model="res.partner"
view-type="form"
>
<t t-raw="line['partner_name']" />
<t t-set="res_model" t-value="'res.partner'"/>
<span t-if="line.partner">
<a t-att-data-active-id="line.move_line_id.partner_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;"><t t-raw="line.partner"/></a>
</span>
</t>
</div>
<!--## ref - label-->
<div class="act_as_cell left">
<t t-if="line['id']">
<span
t-att-res-id="line['id']"
res-model="account.move.line"
view-type="form"
>
<t t-raw="line['ref_label']" />
</span>
</t>
<t t-else="">
<t t-set="res_model" t-value="'account.move.line'"/>
<span>
<t t-raw="line['ref_label']" />
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.label"/></a>
</span>
</t>
</div>
<!--## cost_center-->
<t t-if="show_cost_center">
<div class="act_as_cell left">
<t t-if="line['analytic_account_id']">
<span
t-att-res-id="line['analytic_account_id']"
res-model="account.analytic.account"
view-type="form"
>
<t t-raw="line['analytic_account']" />
<t t-set="res_model" t-value="'account.analytic.account'"/>
<span t-if="line.cost_center">
<a t-att-data-active-id="line.move_line_id.analytic_account_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;"><t t-raw="line.cost_center"/></a>
</span>
</t>
</div>
</t>
<t t-if="show_analytic_tags">
<!--## analytic tags-->
<div class="act_as_cell left">
<t t-if="line['tag_ids']">
<t t-foreach="line['tag_ids']" t-as="tag_id">
<span
t-esc="o._get_atr_from_dict(tag_id, tags_data, 'name')"
/>
</t>
</t>
</div>
<div class="act_as_cell left"><span t-field="line.tags"/></div>
</t>
<!--## matching_number-->
<div class="act_as_cell">
<t t-if="line['rec_id']">
<span
t-att-res-id="line['rec_id']"
res-model="account.full.reconcile"
view-type="form"
>
<t t-raw="line['rec_name']" />
<t t-set="res_model" t-value="'account.full.reconcile'"/>
<span t-if="line.matching_number">
<a t-att-data-active-id="line.move_line_id.full_reconcile_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;"><t t-raw="line.matching_number"/></a>
</span>
</t>
</div>
<!--## debit-->
<div class="act_as_cell amount">
<t t-if="line['id']">
<span
t-att-res-id="line['id']"
res-model="account.move.line"
view-type="form"
>
<t
t-raw="line['debit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</span>
</t>
<t t-else="">
<t t-set="res_model" t-value="'account.move.line'"/>
<span>
<t
t-raw="line['debit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action_monetary"
style="color: black;">
<t t-raw="line.debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</div>
<!--## credit-->
<div class="act_as_cell amount">
<t t-if="line['id']">
<span
t-att-res-id="line['id']"
res-model="account.move.line"
view-type="form"
>
<t
t-raw="line['credit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</span>
</t>
<t t-else="">
<t t-set="res_model" t-value="'account.move.line'"/>
<span>
<t
t-raw="line['credit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action_monetary"
style="color: black;">
<t t-raw="line.credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</div>
<!--## balance cumulated-->
<div class="act_as_cell amount">
<t t-if="line['id']">
<span
t-att-res-id="line['id']"
res-model="account.move.line"
view-type="form"
>
<t
t-raw="line['balance']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</span>
</t>
<t t-else="">
<t t-set="res_model" t-value="'account.move.line'"/>
<span>
<t
t-raw="line['balance']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action_monetary"
style="color: black;">
<t t-raw="line.cumul_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</t>
</div>
<t t-if="foreign_currency">
<t t-if="line['currency_id']">
<t t-if="line.currency_id.id">
<!--## currency_name-->
<div class="act_as_cell amount" style="width: 2.08%;">
<span t-esc="line['currency_id'][1]" />
<span t-field="line.currency_id.display_name"/>
</div>
<!--## amount_currency-->
<div class="act_as_cell amount" style="width: 5.19%;">
<span
t-att-res-id="line['id']"
res-model="account.move.line"
view-type="form"
>
<t t-raw="line['bal_curr']" />
<t t-set="res_model" t-value="'account.move.line'"/>
<span>
<a t-att-data-active-id="line.move_line_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.amount_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/></a>
</span>
</div>
</t>
<t t-if="not line['currency_id']">
<t t-if="not line.currency_id.id">
<!--## currency_name-->
<div class="act_as_cell amount" style="width: 2.08%;"/>
<!--## amount_currency-->
@ -603,28 +473,22 @@
</t>
</div>
</template>
<template id="account_financial_report.report_general_ledger_ending_cumul">
<!-- Display ending balance line for account or partner -->
<div class="act_as_table list_table" style="width: 100%;">
<div class="act_as_row labels" style="font-weight: bold;">
<!--## date-->
<t t-if='type == "account_type"'>
<div class="act_as_cell first_column" style="width: 41.32%;"><span
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'code')"
/> - <span
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'name')"
/></div>
<div
class="act_as_cell right"
style="width: 16.9%;"
>Ending balance</div>
<div class="act_as_cell first_column"
style="width: 41.32%;"><span
t-field="account_or_partner_object.code"/> - <span t-field="account_or_partner_object.name"/></div>
<div class="act_as_cell right"
style="width: 22.9%;">Ending balance</div>
</t>
<t t-if='type == "partner_type"'>
<div class="act_as_cell first_column" style="width: 41.32%;"/>
<div
class="act_as_cell right"
style="width: 16.9%;"
>Partner ending balance</div>
<div class="act_as_cell right" style="width: 22.9%;">Partner ending balance</div>
</t>
<t t-if="show_cost_center">
<!--## cost_center-->
@ -632,88 +496,57 @@
</t>
<t t-if="show_analytic_tags">
<!--## analytic tags-->
<div class="act_as_cell" style="width: 4.75%;" />
<div class="act_as_cell" style="width: 4.75%;"></div>
</t>
<!--## matching_number-->
<div class="act_as_cell" style="width: 2.41%;"/>
<!--## debit-->
<div class="act_as_cell amount" style="width: 8.02%;">
<span
t-esc="account_or_partner_object['fin_bal']['debit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<div class="act_as_cell amount" style="width: 6.02%;">
<span t-field="account_or_partner_object.final_debit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## credit-->
<div class="act_as_cell amount" style="width: 8.02%;">
<span
t-esc="account_or_partner_object['fin_bal']['credit']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<div class="act_as_cell amount" style="width: 6.02%;">
<span t-field="account_or_partner_object.final_credit" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## balance cumulated-->
<div class="act_as_cell amount" style="width: 8.02%;">
<span
t-esc="account_or_partner_object['fin_bal']['balance']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<div class="act_as_cell amount" style="width: 6.02%;">
<span t-field="account_or_partner_object.final_balance" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## currency_name + amount_currency-->
<t t-if="foreign_currency">
<t
t-if="o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')"
>
<t t-if="account.account_id.currency_id.id">
<div class="act_as_cell amount" style="width: 2.08%;">
<span
t-esc="o._get_atr_from_dict(account['id'], accounts_data, 'currency_name')"
/>
<span t-field="account.account_id.currency_id.display_name"/>
</div>
<div class="act_as_cell amount" style="width: 5.19%;">
<t t-if="type == 'account_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('date', '&lt;', date_from)]"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.account_id.id),
('date', '&lt;', o.date_from)]"/>
<span>
<a
t-att-data-t-att-domain="domain"
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;"
>
<t
t-raw="account_or_partner_object['fin_bal']['bal_curr']"
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}"
/>
</a>
style="color: black;">
<t t-raw="account_or_partner_object.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.account_id.currency_id}"/></a>
</span>
</t>
<t t-if="type == 'partner_type'">
<t
t-set="domain"
t-value="[('account_id', '=', account['id']),
('partner_id', '=', partner['id']),
('date', '&lt;', date_from)]"
/>
<t t-set="domain"
t-value="[('account_id', '=', account_or_partner_object.report_account_id.account_id.id),
('partner_id', '=', account_or_partner_object.partner_id.id),
('date', '&lt;', o.date_from)]"/>
<span>
<a
t-att-data-t-att-domain="domain"
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_monetary_multi"
style="color: black;"
>
<t
t-raw="account_or_partner_object['fin_bal']['bal_curr']"
t-options="{'widget': 'monetary', 'display_currency': o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')}"
/>
</a>
style="color: black;">
<t t-raw="account_or_partner_object.final_balance_foreign_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.report_account_id.currency_id}"/></a>
</span>
</t>
</div>
</t>
<t
t-if="not o._get_atr_from_dict(account['id'], accounts_data, 'currency_id')"
>
<t t-if="not account.account_id.currency_id ">
<div class="act_as_cell amount" style="width: 2.08%;"/>
<div class="act_as_cell amount" style="width: 5.19%;"/>
</t>
@ -721,4 +554,5 @@
</div>
</div>
</template>
</odoo>

567
account_financial_report/report/templates/journal_ledger.xml

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2018 ForgeFlow S.L.
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<template id="journal_ledger">
<template id="report_journal_ledger_qweb">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="account_financial_report.internal_layout">
@ -11,212 +10,176 @@
</t>
</t>
</template>
<template id="report_journal_ledger_base">
<t t-set="with_auto_sequence" t-value="with_auto_sequence" />
<t t-set="display_currency" t-value="foreign_currency" />
<t t-set="display_account_name" t-value="with_account_name" />
<t t-set="title">Journal Ledger - <t t-raw="company_name" /> - <t
t-raw="currency_name"
/></t>
<t t-set="company_name" t-value="Company_Name" />
<t t-set="display_currency" t-value="o.foreign_currency"/>
<t t-set="display_account_name" t-value="o.with_account_name"/>
<t t-set="title">Journal Ledger - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t>
<t t-set="company_name" t-value="o.company_id.name"/>
<div class="page">
<div class="row">
<h4
class="mt0"
t-esc="title or 'Odoo Report'"
style="text-align: center;"
/>
<h4 class="mt0" t-esc="title or 'Odoo Report'" style="text-align: center;"/>
</div>
<t t-if="group_option == 'none'">
<t t-if="o.group_option == 'none'">
<div class="page_break">
<t t-call="account_financial_report.report_journal_all"/>
<br/>
<t t-call="account_financial_report.report_journal_all_taxes"/>
</div>
</t>
<t t-if="group_option == 'journal'">
<t t-foreach="Journal_Ledgers" t-as="journal">
<t t-if="o.group_option == 'journal'">
<t t-foreach="o.report_journal_ledger_ids" t-as="journal">
<div class="page_break">
<t
t-call="account_financial_report.report_journal_ledger_journal"
/>
<t t-call="account_financial_report.report_journal_ledger_journal"/>
<br/>
<t
t-call="account_financial_report.report_journal_ledger_journal_taxes"
/>
<t t-call="account_financial_report.report_journal_ledger_journal_taxes"/>
<br/>
</div>
</t>
</t>
</div>
</template>
<template id="account_financial_report.report_journal_all">
<div class="act_as_table list_table" style="margin-top: 10px;"/>
<div class="act_as_table data_table" style="width: 100%;">
<t
t-call="account_financial_report.report_journal_ledger_journal_table_header"
/>
<t t-foreach="Moves" t-as="move">
<t t-call="account_financial_report.report_journal_ledger_journal_table_header"/>
<t t-foreach="o.report_move_ids" t-as="move">
<t t-call="account_financial_report.report_journal_move"/>
</t>
</div>
</template>
<template id="account_financial_report.report_journal_ledger_journal">
<div class="act_as_table list_table" style="margin-top: 10px;"/>
<div class="act_as_caption account_title" style="width: 100%;">
<span t-esc="journal['name']" /> (<span
t-esc="journal['currency_name']"
/>) - <span t-esc="date_from" t-options="{'widget': 'date'}" /> to <span
t-esc="date_to"
t-options="{'widget': 'date'}"
/> - <span t-esc="move_target" /> Moves
<span t-field="journal.name"/> (<span t-field="journal.currency_id.display_name"/>) - <span t-field="o.date_from"/> to <span t-field="o.date_to"/> - <span t-field="o.move_target"/> Moves
</div>
<div class="act_as_table data_table" style="width: 100%;">
<t
t-call="account_financial_report.report_journal_ledger_journal_table_header"
/>
<t
t-call="account_financial_report.report_journal_ledger_journal_first_line"
/>
<t t-foreach="journal['report_moves']" t-as="move">
<t t-call="account_financial_report.report_journal_ledger_journal_table_header"/>
<t t-call="account_financial_report.report_journal_ledger_journal_first_line"/>
<t t-foreach="journal.report_move_ids" t-as="move">
<t t-call="account_financial_report.report_journal_move"/>
</t>
</div>
</template>
<template id="account_financial_report.report_journal_ledger_journal_table_header">
<t t-if="not display_account_name">
<t t-set="account_column_style">
width: 8.11%;
</t>
<t t-if="not with_auto_sequence">
<t t-set="label_column_style">
width: 38.92%;
</t>
</t>
<t t-else="">
<t t-set="label_column_style">
width: 31.35%;
</t>
</t>
</t>
<t t-else="">
<t t-if="not with_auto_sequence">
<t t-set="account_column_style">
width: 23.78%;
</t>
</t>
<t t-else="">
<t t-set="account_column_style">
width: 16.21%;
</t>
</t>
<t t-set="label_column_style">
width: 23.24%;
</t>
</t>
<div class="act_as_thead">
<div class="act_as_row labels">
<t t-if="with_auto_sequence">
<div
class="act_as_cell first_column"
name="entry"
style="width: 7.57%;"
>
Sequence
</div>
</t>
<div
t-att-class="'act_as_cell' if with_auto_sequence else 'act_as_cell first_column'"
class="act_as_cell"
<div class="act_as_cell first_column"
name="entry"
style="width: 7.57%;"
>
style="width: 7.57%;">
Entry
</div>
<div class="act_as_cell" name="date" style="width: 5.41%;">
<div class="act_as_cell"
name="date"
style="width: 5.41%;">
Date
</div>
<div
class="act_as_cell"
name="account"
t-att-style="account_column_style"
>
<div class="act_as_cell"
name="account" t-att-style="account_column_style">
Account
</div>
<div class="act_as_cell" name="partner" style="width: 15.14%;">
<div class="act_as_cell"
name="partner"
style="width: 15.14%;">
Partner
</div>
<div class="act_as_cell" name="label" t-att-style="label_column_style">
<div class="act_as_cell"
name="label" t-att-style="label_column_style">
Ref - Label
</div>
<div class="act_as_cell" name="taxes" style="width: 7.57%;">
<div class="act_as_cell"
name="taxes"
style="width: 7.57%;">
Taxes
</div>
<div class="act_as_cell" name="debit" style="width: 8.65%;">
<div class="act_as_cell"
name="debit"
style="width: 8.65%;">
Debit
</div>
<div class="act_as_cell" name="credit" style="width: 8.65%;">
<div class="act_as_cell"
name="credit"
style="width: 8.65%;">
Credit
</div>
<t t-if="display_currency">
<div class="act_as_cell" name="currency_name" style="width: 2.16%;">
<div class="act_as_cell"
name="currency_name"
style="width: 2.16%;">
Cur.
</div>
<div
class="act_as_cell"
<div class="act_as_cell"
name="amount_currency"
style="width: 6.49%;"
>
style="width: 6.49%;">
Amount Cur.
</div>
</t>
</div>
</div>
</template>
<template id="account_financial_report.report_journal_ledger_journal_first_line">
<div class="act_as_row lines">
<div class="act_as_cell" name="Sequence" />
<div class="act_as_cell" name="entry" />
<div class="act_as_cell" name="date" />
<div class="act_as_cell" name="account" />
<div class="act_as_cell" name="partner" />
<div class="act_as_cell" name="label" />
<div class="act_as_cell" name="taxes" />
<div class="act_as_cell amount" name="debit">
<b>
<span
t-esc="journal['debit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</b>
</div>
<div class="act_as_cell amount" name="credit">
<b>
<span
t-esc="journal['credit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</b>
<div class="act_as_cell"
name="entry"/>
<div class="act_as_cell"
name="date"/>
<div class="act_as_cell"
name="account"/>
<div class="act_as_cell"
name="partner"/>
<div class="act_as_cell"
name="label"/>
<div class="act_as_cell"
name="taxes"/>
<div class="act_as_cell amount"
name="debit">
<b><span t-field="journal.debit"/></b>
</div>
<div class="act_as_cell amount"
name="credit">
<b><span t-field="journal.credit"/></b>
</div>
<t t-if="display_currency">
<div class="act_as_cell" name="currency_name">
<div class="act_as_cell"
name="currency_name">
</div>
<div class="act_as_cell amount" name="amount_currency">
<div class="act_as_cell amount"
name="amount_currency">
</div>
</t>
</div>
<div style="width: 100%"/>
</template>
<template id="account_financial_report.report_journal_move">
<t t-set="display_move_info" t-value="True"/>
<t t-set="last_partner" t-eval="None"/>
<t t-set="display_partner" t-eval="True"/>
<t t-foreach="move['report_move_lines']" t-as="move_line">
<t t-foreach="move.report_move_line_ids" t-as="move_line">
<div class="act_as_row lines">
<t
t-set="current_partner"
t-value="o._get_partner_name(move_line['partner_id'], partner_ids_data)"
/>
<t t-set="current_partner" t-value="move_line.partner_id"/>
<t t-set="display_partner" t-value="current_partner != last_partner"/>
<t t-call="account_financial_report.report_journal_move_line"/>
<t t-set="last_partner" t-value="current_partner"/>
@ -224,295 +187,279 @@
</div>
</t>
</template>
<template id="account_financial_report.report_journal_move_line">
<div class="act_as_cell left" name="auto_sequence" t-if="with_auto_sequence">
<span t-if="display_move_info" t-esc="move_line['auto_sequence']" />
</div>
<div class="act_as_cell left" name="entry">
<t t-if="display_move_info">
<span
t-att-res-id="move_line['move_id']"
res-model="account.move"
view-type="form"
>
<t
t-esc="o._get_atr_from_dict(move_line['move_id'], move_ids_data, 'entry')"
/>
</span>
</t>
<div class="act_as_cell left"
name="entry">
<span t-if="display_move_info" t-field="move_line.entry"/>
</div>
<div class="act_as_cell left"
name="date">
<span t-if="display_move_info" t-field="move_line.date"/>
</div>
<div class="act_as_cell left" name="date">
<span
t-if="display_move_info"
t-esc="move_line['date']"
t-options="{'widget': 'date'}"
/>
</div>
<div class="act_as_cell left" name="account">
<span
t-esc="o._get_atr_from_dict(move_line['account_id'], account_ids_data, 'code')"
/>
<div class="act_as_cell left"
name="account">
<span t-field="move_line.account_code"/>
<span t-if="display_account_name">
- <span
t-esc="o._get_atr_from_dict(move_line['account_id'], account_ids_data, 'name')"
/>
- <span t-field="move_line.account"/>
</span>
</div>
<div class="act_as_cell left" name="partner">
<span
t-if="display_partner"
t-esc="o._get_partner_name(move_line['partner_id'], partner_ids_data)"
/>
</div>
<div class="act_as_cell left" name="label">
<span t-if="move_line['label']" t-esc="move_line['label']" />
<span t-if="not move_line['label']">/</span>
</div>
<div class="act_as_cell left" name="taxes">
<t
t-set="tax_line_dat"
t-value="o._get_data_from_dict(move_line['tax_line_id'], tax_line_data)"
/>
<t
t-set="move_line_ids_taxes_dat"
t-value="o._get_data_from_dict(move_line['move_line_id'], move_line_ids_taxes_data)"
/>
<span
t-esc="o._get_ml_tax_description(move_line, tax_line_dat, move_line_ids_taxes_dat)"
/>
</div>
<div class="act_as_cell amount" name="debit">
<t t-if="move_line['debit']">
<span
t-esc="move_line['debit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
<div class="act_as_cell left"
name="partner">
<span t-if="display_partner" t-field="move_line.partner"/>
</div>
<div class="act_as_cell left"
name="label">
<span t-field="move_line.label"/>
</div>
<div class="act_as_cell left"
name="taxes">
<span t-field="move_line.taxes_description"/>
</div>
<div class="act_as_cell amount"
name="debit">
<t t-if="move_line.debit">
<span t-field="move_line.debit"/>
</t>
</div>
<div class="act_as_cell amount" name="credit">
<t t-if="move_line['credit']">
<span
t-esc="move_line['credit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
<div class="act_as_cell amount"
name="credit">
<t t-if="move_line.credit">
<span t-field="move_line.credit"/>
</t>
</div>
<t t-if="display_currency">
<div class="act_as_cell" name="currency_name">
<t t-if="move_line['currency_id']">
<span t-esc="currency_ids_data.get(move_line['currency_id'], '')" />
<div class="act_as_cell"
name="currency_name">
<t t-if="move_line.currency_name">
<span t-field="move_line.currency_name"/>
</t>
</div>
<div class="act_as_cell amount" name="amount_currency">
<t
t-if="move_line['amount_currency']"
t-options="{'widget': 'float', 'precision': 2}"
>
<span
t-esc="move_line['amount_currency']"
t-options="{'widget': 'float', 'precision': 2}"
/>
<div class="act_as_cell amount"
name="amount_currency">
<t t-if="move_line.amount_currency">
<span t-field="move_line.amount_currency"/>
</t>
</div>
</t>
</template>
<template id="account_financial_report.report_journal_ledger_journal_taxes">
<b>Taxes summary</b>
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_thead">
<div class="act_as_row labels">
<div
class="act_as_cell first_column"
<div class="act_as_cell first_column"
name="name"
style="width: 30.97%;"
>
style="width: 30.97%;">
Name
</div>
<div class="act_as_cell" name="description" style="width: 13.27%;">
<div class="act_as_cell"
name="description"
style="width: 13.27%;">
Description
</div>
<div class="act_as_cell" name="base_amount" style="width: 27.88%;">
<div class="act_as_cell"
name="base_amount"
style="width: 27.88%;">
Base Amount
</div>
<div class="act_as_cell" name="tax_amount" style="width: 27.88%;">
<div class="act_as_cell"
name="tax_amount"
style="width: 27.88%;">
Tax Amount
</div>
</div>
</div>
</div>
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_row labels">
<div
class="act_as_cell first_column"
<div class="act_as_cell first_column"
name="name"
style="width: 30.97%;"
/>
<div class="act_as_cell" name="description" style="width: 13.27%;" />
<div class="act_as_cell" name="base_debit" style="width: 9.29%;">
style="width: 30.97%;"/>
<div class="act_as_cell"
name="description"
style="width: 13.27%;"/>
<div class="act_as_cell"
name="base_debit"
style="width: 9.29%;">
Debit
</div>
<div class="act_as_cell" name="base_credit" style="width: 9.29%;">
<div class="act_as_cell"
name="base_credit"
style="width: 9.29%;">
Credit
</div>
<div class="act_as_cell" name="base_balance" style="width: 9.29%;">
<div class="act_as_cell"
name="base_balance"
style="width: 9.29%;">
Balance
</div>
<div class="act_as_cell" name="tax_debit" style="width: 9.29%;">
<div class="act_as_cell"
name="tax_debit"
style="width: 9.29%;">
Debit
</div>
<div class="act_as_cell" name="tax_credit" style="width: 9.29%;">
<div class="act_as_cell"
name="tax_credit"
style="width: 9.29%;">
Credit
</div>
<div class="act_as_cell" name="tax_balance" style="width: 9.29%;">
<div class="act_as_cell"
name="tax_balance"
style="width: 9.29%;">
Balance
</div>
</div>
<t t-foreach="journal['tax_lines']" t-as="tax_line">
<t t-foreach="journal.report_tax_line_ids" t-as="tax_line">
<div class="act_as_row lines">
<div class="act_as_cell left" name="tax_name">
<span t-esc="tax_line['tax_name']" />
</div>
<div class="act_as_cell left" name="tax_code">
<span t-esc="tax_line['tax_code']" />
</div>
<div class="act_as_cell amount" name="base_debit">
<span
t-esc="tax_line['base_debit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="base_credit">
<span
t-esc="tax_line['base_credit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="base_balance">
<span
t-esc="tax_line['base_balance']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="tax_debit">
<span
t-esc="tax_line['tax_debit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="tax_credit">
<span
t-esc="tax_line['tax_credit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="tax_balance">
<span
t-esc="tax_line['tax_balance']"
t-options="{'widget': 'float', 'precision': 2}"
/>
<div class="act_as_cell left"
name="tax_name">
<span t-field="tax_line.tax_name"/>
</div>
<div class="act_as_cell left"
name="tax_code">
<span t-field="tax_line.tax_code"/>
</div>
<div class="act_as_cell amount"
name="base_debit">
<span t-field="tax_line.base_debit"/>
</div>
<div class="act_as_cell amount"
name="base_credit">
<span t-field="tax_line.base_credit"/>
</div>
<div class="act_as_cell amount"
name="base_balance">
<span t-field="tax_line.base_balance"/>
</div>
<div class="act_as_cell amount"
name="tax_debit">
<span t-field="tax_line.tax_debit"/>
</div>
<div class="act_as_cell amount"
name="tax_credit">
<span t-field="tax_line.tax_credit"/>
</div>
<div class="act_as_cell amount"
name="tax_balance">
<span t-field="tax_line.tax_balance"/>
</div>
</div>
</t>
</div>
</template>
<template id="account_financial_report.report_journal_all_taxes">
<b>Taxes summary</b>
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_thead">
<div class="act_as_row labels">
<div
class="act_as_cell first_column"
<div class="act_as_cell first_column"
name="name"
style="width: 30.97%;"
>
style="width: 30.97%;">
Name
</div>
<div class="act_as_cell" name="description" style="width: 13.27%;">
<div class="act_as_cell"
name="description"
style="width: 13.27%;">
Description
</div>
<div class="act_as_cell" name="base_amount" style="width: 27.88%;">
<div class="act_as_cell"
name="base_amount"
style="width: 27.88%;">
Base Amount
</div>
<div class="act_as_cell" name="tax_amount" style="width: 27.88%;">
<div class="act_as_cell"
name="tax_amount"
style="width: 27.88%;">
Tax Amount
</div>
</div>
</div>
</div>
<div class="act_as_table data_table" style="width: 100%;">10
<div class="act_as_row labels">
<div
class="act_as_cell first_column"
<div class="act_as_cell first_column"
name="name"
style="width: 30.97%;"
/>
<div class="act_as_cell" name="description" style="width: 13.27%;" />
<div class="act_as_cell" name="base_debit" style="width: 9.29%;">
style="width: 30.97%;"/>
<div class="act_as_cell"
name="description"
style="width: 13.27%;"/>
<div class="act_as_cell"
name="base_debit"
style="width: 9.29%;">
Debit
</div>
<div class="act_as_cell" name="base_credit" style="width: 9.29%;">
<div class="act_as_cell"
name="base_credit"
style="width: 9.29%;">
Credit
</div>
<div class="act_as_cell" name="base_balance" style="width: 9.29%;">
<div class="act_as_cell"
name="base_balance"
style="width: 9.29%;">
Balance
</div>
<div class="act_as_cell" name="tax_debit" style="width: 9.29%;">
<div class="act_as_cell"
name="tax_debit"
style="width: 9.29%;">
Debit
</div>
<div class="act_as_cell" name="tax_credit" style="width: 9.29%;">
<div class="act_as_cell"
name="tax_credit"
style="width: 9.29%;">
Credit
</div>
<div class="act_as_cell" name="tax_balance" style="width: 9.29%;">
<div class="act_as_cell"
name="tax_balance"
style="width: 9.29%;">
Balance
</div>
</div>
<t t-foreach="ReportTaxLines" t-as="tax_line">
<t t-foreach="o.report_tax_line_ids" t-as="tax_line">
<div class="act_as_row lines">
<div class="act_as_cell left" name="tax_name">
<span t-esc="tax_line['tax_name']" />
</div>
<div class="act_as_cell left" name="tax_code">
<span t-esc="tax_line['tax_code']" />
</div>
<div class="act_as_cell amount" name="base_debit">
<span
t-esc="tax_line['base_debit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="base_credit">
<span
t-esc="tax_line['base_credit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="base_balance">
<span
t-esc="tax_line['base_balance']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="tax_debit">
<span
t-esc="tax_line['tax_debit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="tax_credit">
<span
t-esc="tax_line['tax_credit']"
t-options="{'widget': 'float', 'precision': 2}"
/>
</div>
<div class="act_as_cell amount" name="tax_balance">
<span
t-esc="tax_line['tax_balance']"
t-options="{'widget': 'float', 'precision': 2}"
/>
<div class="act_as_cell left"
name="tax_name">
<span t-field="tax_line.tax_name"/>
</div>
<div class="act_as_cell left"
name="tax_code">
<span t-field="tax_line.tax_code"/>
</div>
<div class="act_as_cell amount"
name="base_debit">
<span t-field="tax_line.base_debit"/>
</div>
<div class="act_as_cell amount"
name="base_credit">
<span t-field="tax_line.base_credit"/>
</div>
<div class="act_as_cell amount"
name="base_balance">
<span t-field="tax_line.base_balance"/>
</div>
<div class="act_as_cell amount"
name="tax_debit">
<span t-field="tax_line.tax_debit"/>
</div>
<div class="act_as_cell amount"
name="tax_credit">
<span t-field="tax_line.tax_credit"/>
</div>
<div class="act_as_cell amount"
name="tax_balance">
<span t-field="tax_line.tax_balance"/>
</div>
</div>
</t>
</div>
</template>
</odoo>

22
account_financial_report/report/templates/layouts.xml

@ -1,32 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="account_financial_report.internal_layout">
<div class="article o_account_financial_reports_page">
<link
href="/account_financial_report/static/src/css/report.css"
rel="stylesheet"
/>
<div class="article">
<link href="/account_financial_report/static/src/css/report.css" rel="stylesheet"/>
<t t-raw="0" />
</div>
<div class="footer">
<div class="row">
<div class="col-6 custom_footer">
<span
t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"
/>
<span t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"/>
</div>
<div class="col-6 text-right custom_footer">
<ul class="list-inline">
<li class="list-inline-item">
<span class="page" />
</li>
<li class="list-inline-item"><span class="page"/></li>
<li class="list-inline-item">/</li>
<li class="list-inline-item">
<span class="topage" />
</li>
<li class="list-inline-item"><span class="topage"/></li>
</ul>
</div>
</div>
</div>
</template>
</odoo>

244
account_financial_report/report/templates/open_items.xml

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="open_items">
<template id="account_financial_report.report_open_items_qweb">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="account_financial_report.internal_layout">
@ -9,98 +10,60 @@
</t>
</t>
</template>
<template id="account_financial_report.report_open_items_base">
<!-- Saved flag fields into variables, used to define columns display -->
<t t-set="foreign_currency" t-value="foreign_currency" />
<t t-set="foreign_currency" t-value="o.foreign_currency"/>
<!-- Defines global variables used by internal layout -->
<t t-set="title">Open Items - <t t-raw="company_name" /> - <t
t-raw="currency_name"
/></t>
<t t-set="company_name" t-value="Company_Name" />
<t t-set="title">Open Items - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t>
<t t-set="company_name" t-value="o.company_id.name"/>
<div class="page">
<div class="row">
<h4
class="mt0"
t-esc="title or 'Odoo Report'"
style="text-align: center;"
/>
<h4 class="mt0" t-esc="title or 'Odoo Report'" style="text-align: center;"/>
</div>
<!-- Display filters -->
<t t-call="account_financial_report.report_open_items_filters"/>
<t t-foreach="Open_Items.keys()" t-as="account_id">
<t t-foreach="o.account_ids" t-as="account">
<div class="page_break">
<!-- Display account header -->
<div class="act_as_table list_table" style="margin-top: 10px;" />
<div class="account_title" style="width: 100%;">
<span t-esc="accounts_data[account_id]['code']" />
<div class="account_title"
style="width: 100%;">
<span t-field="account.code"/>
-
<span t-esc="accounts_data[account_id]['name']" />
<span t-field="account.name"/>
</div>
<t t-if="not show_partner_details">
<div class="act_as_table data_table" style="width: 100%;">
<t
t-call="account_financial_report.report_open_items_lines_header"
/>
<!-- Display account move lines -->
<t t-foreach="Open_Items[account_id]" t-as="line">
<t
t-call="account_financial_report.report_open_items_lines"
/>
</t>
</div>
</t>
<t t-if="show_partner_details">
<div class="page_break">
<!-- Display account partners -->
<t t-foreach="Open_Items[account_id]" t-as="partner_id">
<div class="act_as_caption account_title">
<span t-esc="partners_data[partner_id]['name']" />
</div>
<div class="act_as_table data_table" style="width: 100%;">
<t t-foreach="account.partner_ids" t-as="partner">
<div class="page_break">
<!-- Display partner header -->
<t
t-call="account_financial_report.report_open_items_lines_header"
/>
<!-- Display partner move lines -->
<t
t-foreach="Open_Items[account_id][partner_id]"
t-as="line"
>
<t
t-call="account_financial_report.report_open_items_lines"
/>
</t>
<div class="account_title">
<span t-field="partner.name"/>
</div>
<t
t-call="account_financial_report.report_open_items_ending_cumul"
>
<t
t-set="account_or_partner_id"
t-value="partners_data[partner_id]"
/>
<t
t-set="currency_id"
t-value="accounts_data[account_id]['currency_name']"
/>
<!-- Display partner move lines -->
<t t-call="account_financial_report.report_open_items_lines"/>
<!-- Display partner footer -->
<t t-call="account_financial_report.report_open_items_ending_cumul">
<t t-set="account_or_partner_object" t-value="partner"/>
<t t-set="type" t-value='"partner_type"'/>
</t>
</t>
</div>
</t>
<!-- Display account footer -->
<t t-call="account_financial_report.report_open_items_ending_cumul">
<t
t-set="account_or_partner_id"
t-value="accounts_data[account_id]"
/>
<t
t-set="currency_id"
t-value="accounts_data[account_id]['currency_name']"
/>
<t t-set="account_or_partner_object" t-value="account"/>
<t t-set="type" t-value='"account_type"'/>
</t>
</div>
</t>
</div>
</template>
<template id="account_financial_report.report_open_items_filters">
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_row labels">
@ -110,20 +73,22 @@
</div>
<div class="act_as_row">
<div class="act_as_cell">
<span t-esc="date_at" />
<span t-field="o.date_at"/>
</div>
<div class="act_as_cell">
<t t-if="target_move == 'posted'">All posted entries</t>
<t t-if="target_move == 'all'">All entries</t>
<t t-if="o.only_posted_moves">All posted entries</t>
<t t-if="not o.only_posted_moves">All entries</t>
</div>
<div class="act_as_cell">
<t t-if="hide_account_at_0">Hide</t>
<t t-if="not hide_account_at_0">Show</t>
<t t-if="o.hide_account_at_0">Hide</t>
<t t-if="not o.hide_account_at_0">Show</t>
</div>
</div>
</div>
</template>
<template id="account_financial_report.report_open_items_lines_header">
<template id="account_financial_report.report_open_items_lines">
<div class="act_as_table data_table" style="width: 100%;">
<!-- Display table headers for lines -->
<div class="act_as_thead">
<div class="act_as_row labels">
@ -154,106 +119,85 @@
<!--## currency_name-->
<div class="act_as_cell" style="width: 2.25%;">Cur.</div>
<!--## amount_total_due_currency-->
<div
class="act_as_cell amount"
style="width: 6.57%;"
>Cur. Original</div>
<div class="act_as_cell amount" style="width: 6.57%;">Cur. Original</div>
<!--## amount_residual_currency-->
<div
class="act_as_cell amount"
style="width: 6.57%;"
>Cur. Residual</div>
<div class="act_as_cell amount" style="width: 6.57%;">Cur. Residual</div>
</t>
</div>
</div>
</template>
<template id="account_financial_report.report_open_items_lines">
<!-- Display each lines -->
<t t-foreach="partner.move_line_ids" t-as="line">
<!-- # lines or centralized lines -->
<div class="act_as_row lines">
<!--## date-->
<div class="act_as_cell left">
<span t-raw="line['date'].strftime('%d/%m/%Y')" />
<span t-field="line.date"/>
</div>
<!--## move-->
<div class="act_as_cell left">
<span
t-att-res-id="line['entry_id']"
res-model="account.move"
view-type="form"
>
<t t-esc="line['move_name']" />
<t t-set="res_model" t-value="'account.move'"/>
<span>
<a t-att-data-active-id="line.move_line_id.move_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.entry"/>
</a>
</span>
</div>
<!--## journal-->
<div class="act_as_cell left">
<span
t-att-res-id="journals_data[line['journal_id']]['id']"
res-model="account.journal"
view-type="form"
>
<t t-esc="journals_data[line['journal_id']]['code']" />
</span>
<span t-field="line.journal"/>
</div>
<!--## account code-->
<div class="act_as_cell left">
<span
t-att-res-id="accounts_data[account_id]['id']"
res-model="account.account"
view-type="form"
>
<t t-esc="accounts_data[account_id]['code']" />
</span>
<span t-field="line.account"/>
</div>
<!--## partner-->
<div class="act_as_cell left">
<span
t-if="line.get('partner_id', False)"
t-att-res-id="line['partner_id']"
res-model="res.partner"
view-type="form"
>
<t t-esc="line['partner_name']" />
<t t-set="res_model" t-value="'res.partner'"/>
<span t-if="line.partner">
<a t-att-data-active-id="line.move_line_id.partner_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
style="color: black;">
<t t-raw="line.partner"/>
</a>
</span>
</div>
<!--## ref - label-->
<div class="act_as_cell left">
<span t-esc="line['ref_label']" />
<span t-field="line.label"/>
</div>
<!--## date_due-->
<div class="act_as_cell left">
<span t-esc="line['date_maturity']" />
<span t-field="line.date_due"/>
</div>
<!--## amount_total_due-->
<div class="act_as_cell amount">
<span
t-if="line.get('original', False)"
t-esc="line['original']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.amount_total_due" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## amount_residual-->
<div class="act_as_cell amount">
<span
t-esc="line['amount_residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<span t-field="line.amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<t t-if="foreign_currency">
<t t-if="line['currency_id']">
<t t-if="line.currency_id.id">
<!--## currency_name-->
<div class="act_as_cell amount">
<span t-esc="line['currency_name']" />
<span t-field="line.currency_id.display_name"/>
</div>
<!--## amount_total_due_currency-->
<div class="act_as_cell amount">
<span t-esc="line['amount_currency']" />
<span t-field="line.amount_total_due_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/>
</div>
<!--## amount_residual_currency-->
<div class="act_as_cell amount">
<span t-esc="line['amount_residual_currency']" />
<span t-field="line.amount_residual_currency" t-options="{'widget': 'monetary', 'display_currency': line.currency_id}"/>
</div>
</t>
<t t-if="not line['currency_id']">
<t t-if="not line.currency_id.id">
<!--## currency_name-->
<div class="act_as_cell"/>
<!--## amount_total_due_currency-->
@ -263,7 +207,10 @@
</t>
</t>
</div>
</t>
</div>
</template>
<template id="account_financial_report.report_open_items_ending_cumul">
<!-- Display ending balance line for account or partner -->
<div class="act_as_table list_table" style="width: 100%;">
@ -271,19 +218,18 @@
<!--## date-->
<t t-if='type == "account_type"'>
<div class="act_as_cell first_column" style="width: 36.34%;">
<span t-esc="accounts_data[account_id]['code']" />
<span t-field="account_or_partner_object.code"/>
-
<span t-esc="accounts_data[account_id]['name']" />
<span t-field="account_or_partner_object.name"/>
</div>
<div class="act_as_cell right" style="width: 28.66%;">Ending
balance</div>
</t>
<t t-if='type == "partner_type"'>
<div class="act_as_cell first_column" style="width: 36.34%;" />
<div
class="act_as_cell right"
style="width: 28.66%;"
>Partner ending balance</div>
<div class="act_as_cell first_column"
style="width: 36.34%;"/>
<div class="act_as_cell right"
style="width: 28.66%;">Partner ending balance</div>
</t>
<!--## date_due-->
<div class="act_as_cell" style="width: 6.47%;"/>
@ -291,21 +237,25 @@
<div class="act_as_cell amount" style="width: 6.57%;"/>
<!--## amount_currency-->
<div class="act_as_cell amount" style="width: 6.57%;">
<t t-if='type == "account_type"'>
<span
t-esc="total_amount[account_id]['residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<t t-if='type == "partner_type"'>
<span
t-esc="total_amount[account_id][partner_id]['residual']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
</t>
<span t-field="account_or_partner_object.final_amount_residual" t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/>
</div>
<!--## amount_total_due_currency + amount_residual_currency -->
<t t-if="foreign_currency">
<t t-if="account_or_partner_object.currency_id.id">
<!--## currency_name-->
<div class="act_as_cell amount" style="width: 2.25%;">
<span t-field="account_or_partner_object.currency_id.display_name"/>
</div>
<!--## amount_total_due_currency-->
<div class="act_as_cell amount" style="width: 6.57%;">
<span t-field="account_or_partner_object.final_amount_total_due_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.currency_id}"/>
</div>
<!--## amount_residual_currency-->
<div class="act_as_cell amount" style="width: 6.57%;">
<span t-field="account_or_partner_object.final_amount_residual_currency" t-options="{'widget': 'monetary', 'display_currency': account_or_partner_object.currency_id}"/>
</div>
</t>
<t t-if="not account_or_partner_object.currency_id.id">
<!--## currency_name-->
<div class="act_as_cell"/>
<!--## amount_total_due_currency-->
@ -313,7 +263,9 @@
<!--## amount_residual_currency-->
<div class="act_as_cell"/>
</t>
</t>
</div>
</div>
</template>
</odoo>

1165
account_financial_report/report/templates/trial_balance.xml
File diff suppressed because it is too large
View File

184
account_financial_report/report/templates/vat_report.xml

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="vat_report">
<template id="account_financial_report.report_vat_report_qweb">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="account_financial_report.internal_layout">
@ -9,18 +10,13 @@
</t>
</t>
</template>
<template id="account_financial_report.report_vat_report_base">
<t t-set="title">VAT Report - <t t-raw="company_name" /> - <t
t-raw="currency_name"
/></t>
<t t-set="company_name" t-value="company_name" />
<t t-set="title">VAT Report - <t t-raw="o.company_id.name"/> - <t t-raw="o.company_id.currency_id.name"/></t>
<t t-set="company_name" t-value="o.company_id.name"/>
<div class="page">
<div class="row">
<h4
class="mt0"
t-esc="title or 'Odoo Report'"
style="text-align: center;"
/>
<h4 class="mt0" t-esc="title or 'Odoo Report'" style="text-align: center;"/>
</div>
<!-- Display filters -->
<t t-call="account_financial_report.report_vat_report_filters"/>
@ -30,10 +26,7 @@
<div class="act_as_thead">
<div class="act_as_row labels">
<!--## code-->
<div
class="act_as_cell first_column"
style="width: 5%;"
>Code</div>
<div class="act_as_cell first_column" style="width: 5%;">Code</div>
<!--## name-->
<div class="act_as_cell" style="width: 65%;">Name</div>
<!--## net-->
@ -42,99 +35,105 @@
<div class="act_as_cell" style="width: 15%;">Tax</div>
</div>
</div>
<t t-foreach="vat_report" t-as="tag_or_group">
<t t-foreach="o.taxtags_ids" t-as="tag">
<div class="act_as_row lines" style="font-weight: bold;">
<div
class="act_as_cell left oe_tooltip_string"
style="width: 5%;"
>
<span
t-att-res-id="res_id"
t-att-res-model="res_model"
view-type="form"
>
<t t-att-style="style" t-raw="tag_or_group['code']" />
<t t-if="tag.taxtag_id">
<t t-set="res_model" t-value="'account.account.tag'"/>
<t t-set="res_id" t-value="tag.taxtag_id.id"/>
</t>
<t t-if="tag.taxgroup_id">
<t t-set="res_model" t-value="'account.tax.group'"/>
<t t-set="res_id" t-value="tag.taxgroup_id.id"/>
</t>
<div class="act_as_cell left oe_tooltip_string" style="width: 5%;">
<span>
<a t-att-data-active-id="res_id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
t-att-style="style">
<t t-att-style="style" t-raw="tag.code"/></a>
</span>
</div>
<div
class="act_as_cell left oe_tooltip_string"
style="width: 65%;"
>
<span
t-att-res-id="res_id"
t-att-res-model="res_model"
view-type="form"
>
<t t-att-style="style" t-raw="tag_or_group['name']" />
<div class="act_as_cell left oe_tooltip_string" style="width: 65%;">
<span>
<a t-att-data-active-id="res_id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
t-att-style="style"><t t-att-style="style" t-raw="tag.name"/></a>
</span>
</div>
<div class="act_as_cell amount" style="width: 15%;">
<t
t-att-style="style"
t-raw="tag_or_group['net']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('tax_ids', 'in', [tax.tax_id.id for tax in tag.tax_ids]),
('date', '&gt;=', o.date_from.strftime('%Y-%m-%d')),
('date', '&lt;=', o.date_to.strftime('%Y-%m-%d'))]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="tag.net"
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</div>
<div class="act_as_cell amount" style="width: 15%;">
<t
t-att-style="style"
t-raw="tag_or_group['tax']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('tax_line_id', 'in', [tax.tax_id.id for tax in tag.tax_ids]),
('date', '&gt;=', o.date_from.strftime('%Y-%m-%d')),
('date', '&lt;=', o.date_to.strftime('%Y-%m-%d')),
('tax_exigible', '=', True)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="tag.tax"
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</div>
</div>
<t t-if="tax_detail">
<t t-foreach="tag_or_group['taxes']" t-as="tax">
<t t-if="o.tax_detail">
<t t-foreach="tag.tax_ids" t-as="tax">
<t t-set="res_model" t-value="'account.tax'"/>
<div class="act_as_row lines">
<div class="act_as_cell" style="width: 5%;"/>
<div
class="act_as_cell left oe_tooltip_string"
style="padding-left: 20px; width: 65%;"
>
<span
t-att-res-id="tax['id']"
t-att-res-model="res_model"
view-type="form"
>
<t t-att-style="style" t-raw="tax['name']" />
<div class="act_as_cell left oe_tooltip_string" style="padding-left: 20px; width: 65%;">
<span>
<a t-att-data-active-id="tax.tax_id.id"
t-att-data-res-model="res_model"
class="o_account_financial_reports_web_action"
t-att-style="style"><t t-att-style="style" t-raw="tax.name"/></a>
</span>
</div>
<div class="act_as_cell amount" style="width: 15%;">
<t
t-set="domain"
t-value="[('tax_ids', 'in', tax['id']),
('date', '&gt;=', date_from),
('date', '&lt;=', date_to),
('tax_exigible', '=', True)]"
/>
<span
t-att-domain="domain"
res-model="account.move.line"
>
<t
t-att-style="style"
t-raw="tax['net']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('tax_ids', 'in', tax.tax_id.ids),
('date', '&gt;=', o.date_from.strftime('%Y-%m-%d')),
('date', '&lt;=', o.date_to.strftime('%Y-%m-%d')),
('tax_exigible', '=', True)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="tax.net"
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</div>
<div class="act_as_cell amount" style="width: 15%;">
<t
t-set="domain"
t-value="[('tax_line_id', '=', tax['id']),
('date', '&gt;=', date_from),
('date', '&lt;=', date_to),
('tax_exigible', '=', True)]"
/>
<span
t-att-domain="domain"
res-model="account.move.line"
>
<t
t-att-style="style"
t-raw="tax['tax']"
t-options="{'widget': 'monetary', 'display_currency': company_currency}"
/>
<t t-set="domain"
t-value="[('tax_line_id', '=', tax.tax_id.id),
('date', '&gt;=', o.date_from.strftime('%Y-%m-%d')),
('date', '&lt;=', o.date_to.strftime('%Y-%m-%d')),
('tax_exigible', '=', True)]"/>
<span>
<a t-att-data-domain="domain"
t-att-data-res-model="'account.move.line'"
class="o_account_financial_reports_web_action_multi"
t-att-style="style">
<t t-att-style="style" t-raw="tax.tax"
t-options="{'widget': 'monetary', 'display_currency': res_company.currency_id}"/></a>
</span>
</div>
</div>
@ -144,6 +143,7 @@
</div>
</div>
</template>
<template id="account_financial_report.report_vat_report_filters">
<div class="act_as_table data_table" style="width: 100%;">
<div class="act_as_row labels">
@ -153,13 +153,13 @@
</div>
<div class="act_as_row">
<div class="act_as_cell">
<span t-esc="date_from" />
<span t-field="o.date_from"/>
</div>
<div class="act_as_cell">
<span t-esc="date_to" />
<span t-field="o.date_to"/>
</div>
<div class="act_as_cell">
<span t-esc="based_on" />
<span t-field="o.based_on"/>
</div>
</div>
</div>

1294
account_financial_report/report/trial_balance.py
File diff suppressed because it is too large
View File

347
account_financial_report/report/trial_balance_xlsx.py

@ -7,164 +7,112 @@ from odoo import _, models
class TrialBalanceXslx(models.AbstractModel):
_name = "report.a_f_r.report_trial_balance_xlsx"
_description = "Trial Balance XLSX Report"
_inherit = "report.account_financial_report.abstract_report_xlsx"
_name = 'report.a_f_r.report_trial_balance_xlsx'
_inherit = 'report.account_financial_report.abstract_report_xlsx'
def _get_report_name(self, report, data=False):
company_id = data.get("company_id", False)
report_name = _("Trial Balance")
if company_id:
company = self.env["res.company"].browse(company_id)
suffix = " - {} - {}".format(company.name, company.currency_id.name)
report_name = report_name + suffix
return report_name
def _get_report_name(self, report):
report_name = _('Trial Balance')
return self._get_report_complete_name(report, report_name)
def _get_report_columns(self, report):
if not report.show_partner_details:
res = {
0: {"header": _("Code"), "field": "code", "width": 10},
1: {"header": _("Account"), "field": "name", "width": 60},
2: {
"header": _("Initial balance"),
"field": "initial_balance",
"type": "amount",
"width": 14,
},
3: {
"header": _("Debit"),
"field": "debit",
"type": "amount",
"width": 14,
},
4: {
"header": _("Credit"),
"field": "credit",
"type": "amount",
"width": 14,
},
5: {
"header": _("Period balance"),
"field": "balance",
"type": "amount",
"width": 14,
},
6: {
"header": _("Ending balance"),
"field": "ending_balance",
"type": "amount",
"width": 14,
},
0: {'header': _('Code'), 'field': 'code', 'width': 10},
1: {'header': _('Account'), 'field': 'name', 'width': 60},
2: {'header': _('Initial balance'),
'field': 'initial_balance',
'type': 'amount',
'width': 14},
3: {'header': _('Debit'),
'field': 'debit',
'type': 'amount',
'width': 14},
4: {'header': _('Credit'),
'field': 'credit',
'type': 'amount',
'width': 14},
5: {'header': _('Period balance'),
'field': 'period_balance',
'type': 'amount',
'width': 14},
6: {'header': _('Ending balance'),
'field': 'final_balance',
'type': 'amount',
'width': 14},
}
if report.foreign_currency:
foreign_currency = {
7: {
"header": _("Cur."),
"field": "currency_id",
"field_currency_balance": "currency_id",
"type": "many2one",
"width": 7,
},
8: {
"header": _("Initial balance"),
"field": "initial_currency_balance",
"type": "amount_currency",
"width": 14,
},
9: {
"header": _("Ending balance"),
"field": "ending_currency_balance",
"type": "amount_currency",
"width": 14,
},
7: {'header': _('Cur.'),
'field': 'currency_id',
'field_currency_balance': 'currency_id',
'type': 'many2one', 'width': 7},
8: {'header': _('Initial balance'),
'field': 'initial_balance_foreign_currency',
'type': 'amount_currency',
'width': 14},
9: {'header': _('Ending balance'),
'field': 'final_balance_foreign_currency',
'type': 'amount_currency',
'width': 14},
}
res = {**res, **foreign_currency}
return res
else:
res = {
0: {"header": _("Partner"), "field": "name", "width": 70},
1: {
"header": _("Initial balance"),
"field": "initial_balance",
"type": "amount",
"width": 14,
},
2: {
"header": _("Debit"),
"field": "debit",
"type": "amount",
"width": 14,
},
3: {
"header": _("Credit"),
"field": "credit",
"type": "amount",
"width": 14,
},
4: {
"header": _("Period balance"),
"field": "balance",
"type": "amount",
"width": 14,
},
5: {
"header": _("Ending balance"),
"field": "ending_balance",
"type": "amount",
"width": 14,
},
0: {'header': _('Partner'), 'field': 'name', 'width': 70},
1: {'header': _('Initial balance'),
'field': 'initial_balance',
'type': 'amount',
'width': 14},
2: {'header': _('Debit'),
'field': 'debit',
'type': 'amount',
'width': 14},
3: {'header': _('Credit'),
'field': 'credit',
'type': 'amount',
'width': 14},
4: {'header': _('Period balance'),
'field': 'period_balance',
'type': 'amount',
'width': 14},
5: {'header': _('Ending balance'),
'field': 'final_balance',
'type': 'amount',
'width': 14},
}
if report.foreign_currency:
foreign_currency = {
6: {
"header": _("Cur."),
"field": "currency_id",
"field_currency_balance": "currency_id",
"type": "many2one",
"width": 7,
},
7: {
"header": _("Initial balance"),
"field": "initial_currency_balance",
"type": "amount_currency",
"width": 14,
},
8: {
"header": _("Ending balance"),
"field": "ending_currency_balance",
"type": "amount_currency",
"width": 14,
},
6: {'header': _('Cur.'),
'field': 'currency_id',
'field_currency_balance': 'currency_id',
'type': 'many2one', 'width': 7},
7: {'header': _('Initial balance'),
'field': 'initial_balance_foreign_currency',
'type': 'amount_currency',
'width': 14},
8: {'header': _('Ending balance'),
'field': 'final_balance_foreign_currency',
'type': 'amount_currency',
'width': 14},
}
res = {**res, **foreign_currency}
return res
def _get_report_filters(self, report):
return [
[
_("Date range filter"),
_("From: %s To: %s") % (report.date_from, report.date_to),
],
[
_("Target moves filter"),
_("All posted entries")
if report.target_move == "posted"
else _("All entries"),
],
[
_("Account at 0 filter"),
_("Hide") if report.hide_account_at_0 else _("Show"),
],
[
_("Show foreign currency"),
_("Yes") if report.foreign_currency else _("No"),
],
[
_("Limit hierarchy levels"),
_("Level %s" % report.show_hierarchy_level)
if report.limit_hierarchy_level
else _("No limit"),
],
[_('Date range filter'),
_('From: %s To: %s') % (report.date_from, report.date_to)],
[_('Target moves filter'),
_('All posted entries') if report.only_posted_moves else _(
'All entries')],
[_('Account at 0 filter'),
_('Hide') if report.hide_account_at_0 else _('Show')],
[_('Show foreign currency'),
_('Yes') if report.foreign_currency else _('No')],
[_('Limit hierarchy levels'),
_('Level %s' % report.show_hierarchy_level) if
report.limit_hierarchy_level else _('No limit')],
]
def _get_col_count_filter_name(self):
@ -173,133 +121,72 @@ class TrialBalanceXslx(models.AbstractModel):
def _get_col_count_filter_value(self):
return 3
def _generate_report_content(self, workbook, report, data):
res_data = self.env[
"report.account_financial_report.trial_balance"
]._get_report_values(report, data)
trial_balance = res_data["trial_balance"]
total_amount = res_data["total_amount"]
partners_data = res_data["partners_data"]
accounts_data = res_data["accounts_data"]
hierarchy_on = res_data["hierarchy_on"]
show_partner_details = res_data["show_partner_details"]
show_hierarchy_level = res_data["show_hierarchy_level"]
foreign_currency = res_data["foreign_currency"]
limit_hierarchy_level = res_data["limit_hierarchy_level"]
if not show_partner_details:
def _generate_report_content(self, workbook, report):
if not report.show_partner_details:
# Display array header for account lines
self.write_array_header()
# For each account
if not show_partner_details:
for balance in trial_balance:
if hierarchy_on == "relation":
if limit_hierarchy_level:
if show_hierarchy_level > balance["level"]:
# Display account lines
self.write_line_from_dict(balance)
else:
self.write_line_from_dict(balance)
elif hierarchy_on == "computed":
if balance["type"] == "account_type":
if limit_hierarchy_level:
if show_hierarchy_level > balance["level"]:
for account in report.account_ids.filtered(lambda a: not a.hide_line):
if not report.show_partner_details:
# Display account lines
self.write_line_from_dict(balance)
else:
self.write_line_from_dict(balance)
else:
self.write_line_from_dict(balance)
self.write_line(account, 'account')
else:
for account_id in total_amount:
# Write account title
self.write_array_title(
accounts_data[account_id]["code"]
+ "- "
+ accounts_data[account_id]["name"]
)
self.write_array_title(account.code + ' - ' + account.name)
# Display array header for partner lines
self.write_array_header()
# For each partner
for partner_id in total_amount[account_id]:
if isinstance(partner_id, int):
for partner in account.partner_ids:
# Display partner lines
self.write_line_from_dict_order(
total_amount[account_id][partner_id],
partners_data[partner_id],
)
self.write_line(partner, 'partner')
# Display account footer line
accounts_data[account_id].update(
{
"initial_balance": total_amount[account_id]["initial_balance"],
"credit": total_amount[account_id]["credit"],
"debit": total_amount[account_id]["debit"],
"balance": total_amount[account_id]["balance"],
"ending_balance": total_amount[account_id]["ending_balance"],
}
)
if foreign_currency:
accounts_data[account_id].update(
{
"initial_currency_balance": total_amount[account_id][
"initial_currency_balance"
],
"ending_currency_balance": total_amount[account_id][
"ending_currency_balance"
],
}
)
self.write_account_footer(
accounts_data[account_id],
accounts_data[account_id]["code"]
+ "- "
+ accounts_data[account_id]["name"],
)
self.write_account_footer(account,
account.code + ' - ' + account.name)
# Line break
self.row_pos += 2
def write_line_from_dict_order(self, total_amount, partner_data):
total_amount.update({"name": str(partner_data["name"])})
self.write_line_from_dict(total_amount)
def write_line(self, line_object, type_object):
"""Write a line on current line using all defined columns field name.
Columns are defined with `_get_report_columns` method.
"""
if type_object == "partner":
if type_object == 'partner':
line_object.currency_id = line_object.report_account_id.currency_id
elif type_object == "account":
elif type_object == 'account':
line_object.currency_id = line_object.currency_id
super(TrialBalanceXslx, self).write_line(line_object)
def write_account_footer(self, account, name_value):
"""Specific function to write account footer for Trial Balance"""
format_amt = self._get_currency_amt_header_format_dict(account)
format_amt = self._get_currency_amt_header_format(account)
for col_pos, column in self.columns.items():
if column["field"] == "name":
if column['field'] == 'name':
value = name_value
else:
value = account[column["field"]]
cell_type = column.get("type", "string")
if cell_type == "string":
value = getattr(account, column['field'])
cell_type = column.get('type', 'string')
if cell_type == 'string':
self.sheet.write_string(self.row_pos, col_pos, value or '',
self.format_header_left)
elif cell_type == 'amount':
self.sheet.write_number(self.row_pos, col_pos, float(value),
self.format_header_amount)
elif cell_type == 'many2one':
self.sheet.write_string(
self.row_pos, col_pos, value or "", self.format_header_left
)
elif cell_type == "amount":
self.row_pos, col_pos, value.name or '',
self.format_header_right)
elif cell_type == 'amount_currency' and account.currency_id:
self.sheet.write_number(
self.row_pos, col_pos, float(value), self.format_header_amount
)
elif cell_type == "many2one" and account["currency_id"]:
self.sheet.write_string(
self.row_pos, col_pos, value.name or "", self.format_header_right
)
elif cell_type == "amount_currency" and account["currency_id"]:
self.sheet.write_number(self.row_pos, col_pos, float(value), format_amt)
self.row_pos, col_pos, float(value),
format_amt)
else:
self.sheet.write_string(
self.row_pos, col_pos, "", self.format_header_right
)
self.row_pos, col_pos, '',
self.format_header_right)
self.row_pos += 1

555
account_financial_report/report/vat_report.py

@ -1,239 +1,356 @@
# Copyright 2018 Forest and Biomass Romania
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import operator
from odoo import api, models
class VATReport(models.AbstractModel):
_name = "report.account_financial_report.vat_report"
_description = "Vat Report Report"
def _get_tax_data(self, tax_ids):
taxes = self.env["account.tax"].browse(tax_ids)
tax_data = {}
for tax in taxes:
tax_data.update(
{
tax.id: {
"id": tax.id,
"name": tax.name,
"tax_group_id": tax.tax_group_id.id,
"type_tax_use": tax.type_tax_use,
"amount_type": tax.amount_type,
"tags_ids": tax.invoice_repartition_line_ids.tag_ids.ids,
}
}
)
return tax_data
from odoo import api, fields, models
@api.model
def _get_tax_report_domain(self, company_id, date_from, date_to, only_posted_moves):
domain = [
("company_id", "=", company_id),
("date", ">=", date_from),
("date", "<=", date_to),
("tax_line_id", "!=", False),
("tax_exigible", "=", True),
]
if only_posted_moves:
domain += [("move_id.state", "=", "posted")]
else:
domain += [("move_id.state", "in", ["posted", "draft"])]
return domain
@api.model
def _get_net_report_domain(self, company_id, date_from, date_to, only_posted_moves):
domain = [
("company_id", "=", company_id),
("date", ">=", date_from),
("date", "<=", date_to),
("tax_exigible", "=", True),
]
if only_posted_moves:
domain += [("move_id.state", "=", "posted")]
else:
domain += [("move_id.state", "in", ["posted", "draft"])]
return domain
class VATReport(models.TransientModel):
_name = "report_vat_report"
_inherit = 'account_financial_report_abstract'
""" Here, we just define class fields.
For methods, go more bottom at this file.
def _get_vat_report_data(self, company_id, date_from, date_to, only_posted_moves):
tax_domain = self._get_tax_report_domain(
company_id, date_from, date_to, only_posted_moves
The class hierarchy is :
* VATReport
** VATReportTaxTags
*** VATReportTax
"""
# Filters fields, used for data computation
company_id = fields.Many2one(comodel_name='res.company')
date_from = fields.Date()
date_to = fields.Date()
based_on = fields.Selection([('taxtags', 'Tax Tags'),
('taxgroups', 'Tax Groups')],
string='Based On',
required=True,
default='taxtags')
tax_detail = fields.Boolean('Tax Detail')
# Data fields, used to browse report data
taxtags_ids = fields.One2many(
comodel_name='report_vat_report_taxtag',
inverse_name='report_id'
)
ml_fields = [
"id",
"tax_base_amount",
"balance",
"tax_line_id",
"tax_ids",
"analytic_tag_ids",
"tag_ids",
]
tax_move_lines = self.env["account.move.line"].search_read(
domain=tax_domain, fields=ml_fields,
class VATReportTaxTags(models.TransientModel):
_name = 'report_vat_report_taxtag'
_inherit = 'account_financial_report_abstract'
_order = 'code ASC'
report_id = fields.Many2one(
comodel_name='report_vat_report',
ondelete='cascade',
index=True
)
net_domain = self._get_net_report_domain(
company_id, date_from, date_to, only_posted_moves
# Data fields, used to keep link with real object
taxtag_id = fields.Many2one(
'account.account.tag',
index=True
)
taxed_move_lines = self.env["account.move.line"].search_read(
domain=net_domain, fields=ml_fields,
taxgroup_id = fields.Many2one(
'account.tax.group',
index=True
)
taxed_move_lines = list(filter(lambda d: d["tax_ids"], taxed_move_lines))
vat_data = []
for tax_move_line in tax_move_lines:
vat_data.append(
{
"net": 0.0,
"tax": tax_move_line["balance"],
"tax_line_id": tax_move_line["tax_line_id"][0],
}
# Data fields, used for report display
code = fields.Char()
name = fields.Char()
net = fields.Float(digits=(16, 2))
tax = fields.Float(digits=(16, 2))
# Data fields, used to browse report data
tax_ids = fields.One2many(
comodel_name='report_vat_report_tax',
inverse_name='report_tax_id',
string='Taxes'
)
for taxed_move_line in taxed_move_lines:
for tax_id in taxed_move_line["tax_ids"]:
vat_data.append(
{
"net": taxed_move_line["balance"],
"tax": 0.0,
"tax_line_id": tax_id,
}
class VATReportTax(models.TransientModel):
_name = 'report_vat_report_tax'
_inherit = 'account_financial_report_abstract'
_order = 'name ASC'
report_tax_id = fields.Many2one(
comodel_name='report_vat_report_taxtag',
ondelete='cascade',
index=True
)
tax_ids = list(map(operator.itemgetter("tax_line_id"), vat_data))
tax_ids = list(set(tax_ids))
tax_data = self._get_tax_data(tax_ids)
return vat_data, tax_data
def _get_tax_group_data(self, tax_group_ids):
tax_groups = self.env["account.tax.group"].browse(tax_group_ids)
tax_group_data = {}
for tax_group in tax_groups:
tax_group_data.update(
{
tax_group.id: {
"id": tax_group.id,
"name": tax_group.name,
"code": str(tax_group.sequence),
}
}
# Data fields, used to keep link with real object
tax_id = fields.Many2one(
'account.tax',
index=True,
string='Tax ID',
)
return tax_group_data
def _get_vat_report_group_data(self, vat_report_data, tax_data, tax_detail):
vat_report = {}
for tax_move_line in vat_report_data:
tax_id = tax_move_line["tax_line_id"]
if tax_data[tax_id]["amount_type"] == "group":
pass
else:
tax_group_id = tax_data[tax_id]["tax_group_id"]
if tax_group_id not in vat_report.keys():
vat_report[tax_group_id] = {}
vat_report[tax_group_id]["net"] = 0.0
vat_report[tax_group_id]["tax"] = 0.0
vat_report[tax_group_id][tax_id] = dict(tax_data[tax_id])
vat_report[tax_group_id][tax_id].update({"net": 0.0, "tax": 0.0})
# Data fields, used for report display
code = fields.Char()
name = fields.Char()
net = fields.Float(digits=(16, 2))
tax = fields.Float(digits=(16, 2))
class VATReportCompute(models.TransientModel):
""" Here, we just define methods.
For class fields, go more top at this file.
"""
_inherit = 'report_vat_report'
@api.multi
def print_report(self, report_type='qweb'):
self.ensure_one()
if report_type == 'xlsx':
report_name = 'a_f_r.report_vat_report_xlsx'
else:
if tax_id not in vat_report[tax_group_id].keys():
vat_report[tax_group_id][tax_id] = dict(tax_data[tax_id])
vat_report[tax_group_id][tax_id].update(
{"net": 0.0, "tax": 0.0}
report_name = 'account_financial_report.report_vat_report_qweb'
context = dict(self.env.context)
action = self.env['ir.actions.report'].search(
[('report_name', '=', report_name),
('report_type', '=', report_type)], limit=1)
return action.with_context(context).report_action(self, config=False)
def _get_html(self):
result = {}
rcontext = {}
context = dict(self.env.context)
report = self.browse(context.get('active_id'))
if report:
rcontext['o'] = report
result['html'] = self.env.ref(
'account_financial_report.report_vat_report').render(
rcontext)
return result
@api.model
def get_html(self, given_context=None):
return self.with_context(given_context)._get_html()
@api.multi
def compute_data_for_report(self):
self.ensure_one()
# Compute report data
if self.based_on == 'taxtags':
self._inject_taxtags_values()
self._inject_tax_taxtags_values()
elif self.based_on == 'taxgroups':
self._inject_taxgroups_values()
self._inject_tax_taxgroups_values()
# Refresh cache because all data are computed with SQL requests
self.refresh()
def _inject_taxtags_values(self):
"""Inject report values for report_vat_report_taxtags."""
query_inject_taxtags = """
WITH
taxtags AS
(SELECT coalesce(regexp_replace(tag.name,
'[^0-9\\.]+', '', 'g'), ' ') AS code,
tag.name, tag.id,
coalesce(sum(movetax.tax_base_amount), 0.00) AS net,
coalesce(sum(movetax.balance), 0.00) AS tax
FROM
account_account_tag AS tag
INNER JOIN account_tax_account_tag AS taxtag
ON tag.id = taxtag.account_account_tag_id
INNER JOIN account_tax AS tax
ON tax.id = taxtag.account_tax_id
INNER JOIN account_move_line AS movetax
ON movetax.tax_line_id = tax.id
INNER JOIN account_move AS move
ON move.id = movetax.move_id
WHERE tag.id is not null AND movetax.tax_exigible
AND move.company_id = %s AND move.date >= %s
AND move.date <= %s AND move.state = 'posted'
GROUP BY tag.id
ORDER BY code, tag.name
)
vat_report[tax_group_id]["net"] += tax_move_line["net"]
vat_report[tax_group_id]["tax"] += tax_move_line["tax"]
vat_report[tax_group_id][tax_id]["net"] += tax_move_line["net"]
vat_report[tax_group_id][tax_id]["tax"] += tax_move_line["tax"]
tax_group_data = self._get_tax_group_data(vat_report.keys())
vat_report_list = []
for tax_group_id in vat_report.keys():
vat_report[tax_group_id]["name"] = tax_group_data[tax_group_id]["name"]
vat_report[tax_group_id]["code"] = tax_group_data[tax_group_id]["code"]
if tax_detail:
vat_report[tax_group_id]["taxes"] = []
for tax_id in vat_report[tax_group_id]:
if isinstance(tax_id, int):
vat_report[tax_group_id]["taxes"].append(
vat_report[tax_group_id][tax_id]
INSERT INTO
report_vat_report_taxtag
(
report_id,
create_uid,
create_date,
taxtag_id,
code,
name,
net, tax
)
vat_report_list.append(vat_report[tax_group_id])
return vat_report_list
def _get_tags_data(self, tags_ids):
tags = self.env["account.account.tag"].browse(tags_ids)
tags_data = {}
for tag in tags:
tags_data.update({tag.id: {"code": "", "name": tag.name}})
return tags_data
def _get_vat_report_tag_data(self, vat_report_data, tax_data, tax_detail):
vat_report = {}
for tax_move_line in vat_report_data:
tax_id = tax_move_line["tax_line_id"]
tags_ids = tax_data[tax_id]["tags_ids"]
if tax_data[tax_id]["amount_type"] == "group":
continue
else:
if tags_ids:
for tag_id in tags_ids:
if tag_id not in vat_report.keys():
vat_report[tag_id] = {}
vat_report[tag_id]["net"] = 0.0
vat_report[tag_id]["tax"] = 0.0
vat_report[tag_id][tax_id] = dict(tax_data[tax_id])
vat_report[tag_id][tax_id].update({"net": 0.0, "tax": 0.0})
else:
if tax_id not in vat_report[tag_id].keys():
vat_report[tag_id][tax_id] = dict(tax_data[tax_id])
vat_report[tag_id][tax_id].update(
{"net": 0.0, "tax": 0.0}
SELECT
%s AS report_id,
%s AS create_uid,
NOW() AS create_date,
tag.id,
tag.code,
tag.name,
abs(tag.net),
abs(tag.tax)
FROM
taxtags tag
"""
query_inject_taxtags_params = (self.company_id.id, self.date_from,
self.date_to, self.id, self.env.uid)
self.env.cr.execute(query_inject_taxtags, query_inject_taxtags_params)
def _inject_taxgroups_values(self):
"""Inject report values for report_vat_report_taxtags."""
query_inject_taxgroups = """
WITH
taxgroups AS
(SELECT coalesce(taxgroup.sequence, 0) AS code,
taxgroup.name, taxgroup.id,
coalesce(sum(movetax.tax_base_amount), 0.00) AS net,
coalesce(sum(movetax.balance), 0.00) AS tax
FROM
account_tax_group AS taxgroup
INNER JOIN account_tax AS tax
ON tax.tax_group_id = taxgroup.id
INNER JOIN account_move_line AS movetax
ON movetax.tax_line_id = tax.id
INNER JOIN account_move AS move
ON move.id = movetax.move_id
WHERE taxgroup.id is not null AND movetax.tax_exigible
AND move.company_id = %s AND move.date >= %s
AND move.date <= %s AND move.state = 'posted'
GROUP BY taxgroup.id
ORDER BY code, taxgroup.name
)
vat_report[tag_id][tax_id]["net"] += tax_move_line["net"]
vat_report[tag_id][tax_id]["tax"] += tax_move_line["tax"]
vat_report[tag_id]["net"] += tax_move_line["net"]
vat_report[tag_id]["tax"] += tax_move_line["tax"]
tags_data = self._get_tags_data(vat_report.keys())
vat_report_list = []
for tag_id in vat_report.keys():
vat_report[tag_id]["name"] = tags_data[tag_id]["name"]
vat_report[tag_id]["code"] = tags_data[tag_id]["code"]
if tax_detail:
vat_report[tag_id]["taxes"] = []
for tax_id in vat_report[tag_id]:
if isinstance(tax_id, int):
vat_report[tag_id]["taxes"].append(vat_report[tag_id][tax_id])
vat_report_list.append(vat_report[tag_id])
return vat_report_list
def _get_report_values(self, docids, data):
wizard_id = data["wizard_id"]
company = self.env["res.company"].browse(data["company_id"])
company_id = data["company_id"]
date_from = data["date_from"]
date_to = data["date_to"]
based_on = data["based_on"]
tax_detail = data["tax_detail"]
only_posted_moves = data["only_posted_moves"]
vat_report_data, tax_data = self._get_vat_report_data(
company_id, date_from, date_to, only_posted_moves
INSERT INTO
report_vat_report_taxtag
(
report_id,
create_uid,
create_date,
taxgroup_id,
code,
name,
net, tax
)
if based_on == "taxgroups":
vat_report = self._get_vat_report_group_data(
vat_report_data, tax_data, tax_detail
SELECT
%s AS report_id,
%s AS create_uid,
NOW() AS create_date,
groups.id,
groups.code,
groups.name,
abs(groups.net),
abs(groups.tax)
FROM
taxgroups groups
"""
query_inject_taxgroups_params = (self.company_id.id, self.date_from,
self.date_to, self.id, self.env.uid)
self.env.cr.execute(query_inject_taxgroups,
query_inject_taxgroups_params)
def _inject_tax_taxtags_values(self):
""" Inject report values for report_vat_report_tax. """
# pylint: disable=sql-injection
query_inject_tax = """
WITH
taxtags_tax AS
(
SELECT
tag.id AS report_tax_id, ' ' AS code,
tax.name, tax.id,
coalesce(sum(movetax.tax_base_amount), 0.00) AS net,
coalesce(sum(movetax.balance), 0.00) AS tax
FROM
report_vat_report_taxtag AS tag
INNER JOIN account_tax_account_tag AS taxtag
ON tag.taxtag_id = taxtag.account_account_tag_id
INNER JOIN account_tax AS tax
ON tax.id = taxtag.account_tax_id
INNER JOIN account_move_line AS movetax
ON movetax.tax_line_id = tax.id
INNER JOIN account_move AS move
ON move.id = movetax.move_id
WHERE tag.id is not null AND movetax.tax_exigible
AND tag.report_id = %s AND move.company_id = %s
AND move.date >= %s AND move.date <= %s
AND move.state = 'posted'
GROUP BY tag.id, tax.id
ORDER BY tax.name
)
else:
vat_report = self._get_vat_report_tag_data(
vat_report_data, tax_data, tax_detail
INSERT INTO
report_vat_report_tax
(
report_tax_id,
create_uid,
create_date,
tax_id,
name,
net,
tax
)
SELECT
tt.report_tax_id,
%s AS create_uid,
NOW() AS create_date,
tt.id,
tt.name,
abs(tt.net),
abs(tt.tax)
FROM
taxtags_tax tt
"""
query_inject_tax_params = (self.id, self.company_id.id, self.date_from,
self.date_to, self.env.uid)
self.env.cr.execute(query_inject_tax, query_inject_tax_params)
def _inject_tax_taxgroups_values(self):
""" Inject report values for report_vat_report_tax. """
# pylint: disable=sql-injection
query_inject_tax = """
WITH
taxtags_tax AS
(
SELECT
taxtag.id AS report_tax_id, ' ' AS code,
tax.name, tax.id,
coalesce(sum(movetax.tax_base_amount), 0.00) AS net,
coalesce(sum(movetax.balance), 0.00) AS tax
FROM
report_vat_report_taxtag AS taxtag
INNER JOIN account_tax AS tax
ON tax.tax_group_id = taxtag.taxgroup_id
INNER JOIN account_move_line AS movetax
ON movetax.tax_line_id = tax.id
INNER JOIN account_move AS move
ON move.id = movetax.move_id
WHERE taxtag.id is not null AND movetax.tax_exigible
AND taxtag.report_id = %s AND move.company_id = %s
AND move.date >= %s AND move.date <= %s
AND move.state = 'posted'
GROUP BY taxtag.id, tax.id
ORDER BY tax.name
)
INSERT INTO
report_vat_report_tax
(
report_tax_id,
create_uid,
create_date,
tax_id,
name,
net,
tax
)
return {
"doc_ids": [wizard_id],
"doc_model": "open.items.report.wizard",
"docs": self.env["open.items.report.wizard"].browse(wizard_id),
"company_name": company.display_name,
"company_currency": company.currency_id,
"currency_name": company.currency_id.name,
"date_to": data["date_to"],
"date_from": data["date_from"],
"based_on": data["based_on"],
"tax_detail": data["tax_detail"],
"vat_report": vat_report,
}
SELECT
tt.report_tax_id,
%s AS create_uid,
NOW() AS create_date,
tt.id,
tt.name,
abs(tt.net),
abs(tt.tax)
FROM
taxtags_tax tt
"""
query_inject_tax_params = (self.id, self.company_id.id, self.date_from,
self.date_to, self.env.uid)
self.env.cr.execute(query_inject_tax, query_inject_tax_params)

60
account_financial_report/report/vat_report_xlsx.py

@ -5,35 +5,32 @@ from odoo import _, models
class VATReportXslx(models.AbstractModel):
_name = "report.a_f_r.report_vat_report_xlsx"
_description = "Vat Report XLSX Report"
_inherit = "report.account_financial_report.abstract_report_xlsx"
def _get_report_name(self, report, data):
company_id = data.get("company_id", False)
report_name = _("Vat Report")
if company_id:
company = self.env["res.company"].browse(company_id)
suffix = " - {} - {}".format(company.name, company.currency_id.name)
report_name = report_name + suffix
return report_name
_name = 'report.a_f_r.report_vat_report_xlsx'
_inherit = 'report.account_financial_report.abstract_report_xlsx'
def _get_report_name(self, report):
report_name = _('VAT Report')
return self._get_report_complete_name(report, report_name)
def _get_report_columns(self, report):
return {
0: {"header": _("Code"), "field": "code", "width": 5},
1: {"header": _("Name"), "field": "name", "width": 100},
2: {"header": _("Net"), "field": "net", "type": "amount", "width": 14},
3: {"header": _("Tax"), "field": "tax", "type": "amount", "width": 14},
0: {'header': _('Code'), 'field': 'code', 'width': 5},
1: {'header': _('Name'), 'field': 'name', 'width': 100},
2: {'header': _('Net'),
'field': 'net',
'type': 'amount',
'width': 14},
3: {'header': _('Tax'),
'field': 'tax',
'type': 'amount',
'width': 14},
}
def _get_report_filters(self, report):
return [
[_("Date from"), report.date_from.strftime("%d/%m/%Y")],
[_("Date to"), report.date_to.strftime("%d/%m/%Y")],
[
_("Based on"),
_("Tax Tags") if report.based_on == "taxtags" else _("Tax Groups"),
],
[_('Date from'), report.date_from],
[_('Date to'), report.date_to],
[_('Based on'), report.based_on],
]
def _get_col_count_filter_name(self):
@ -42,19 +39,14 @@ class VATReportXslx(models.AbstractModel):
def _get_col_count_filter_value(self):
return 2
def _generate_report_content(self, workbook, report, data):
res_data = self.env[
"report.account_financial_report.vat_report"
]._get_report_values(report, data)
vat_report = res_data["vat_report"]
tax_detail = res_data["tax_detail"]
# For each tax_tag tax_group
def _generate_report_content(self, workbook, report):
# For each taxtag
self.write_array_header()
for tag_or_group in vat_report:
for taxtag in report.taxtags_ids:
# Write taxtag line
self.write_line_from_dict(tag_or_group)
self.write_line(taxtag)
# For each tax if detail taxes
if tax_detail:
for tax in tag_or_group["taxes"]:
self.write_line_from_dict(tax)
if report.tax_detail:
for tax in taxtag.tax_ids:
self.write_line(tax)

158
account_financial_report/reports.xml

@ -1,121 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- PDF/HMTL REPORTS -->
<!-- General Ledger -->
<report
id="action_print_report_general_ledger_qweb"
model="general.ledger.report.wizard"
id="action_report_general_ledger_qweb"
model="report_general_ledger"
string="General Ledger"
report_type="qweb-pdf"
menu="False"
name="account_financial_report.general_ledger"
file="account_financial_report.general_ledger"
name="account_financial_report.report_general_ledger_qweb"
file="account_financial_report.report_general_ledger_qweb"
/>
<report
id="action_print_report_general_ledger_html"
model="general.ledger.report.wizard"
id="action_report_general_ledger_html"
model="report_general_ledger"
string="General Ledger"
report_type="qweb-html"
menu="False"
name="account_financial_report.general_ledger"
file="account_financial_report.general_ledger"
name="account_financial_report.report_general_ledger_qweb"
file="account_financial_report.report_general_ledger_html"
/>
<!-- Journal Ledger -->
<report
id="action_print_journal_ledger_wizard_qweb"
model="journal.ledger.report.wizard"
report_type="qweb-pdf"
menu="False"
id="action_report_journal_ledger_qweb"
model="report_journal_ledger"
string="Journal Ledger"
name="account_financial_report.journal_ledger"
file="account_financial_report.journal_ledger"
report_type="qweb-pdf"
name="account_financial_report.report_journal_ledger_qweb"
file="account_financial_report.report_journal_ledger_qweb"
/>
<report
id="action_print_journal_ledger_wizard_html"
model="journal.ledger.report.wizard"
report_type="qweb-html"
menu="False"
id="action_report_journal_ledger_html"
model="report_journal_ledger"
string="Journal Ledger"
name="account_financial_report.journal_ledger"
file="account_financial_report.journal_ledger"
report_type="qweb-html"
name="account_financial_report.report_journal_ledger_qweb"
file="account_financial_report.report_journal_ledger_html"
/>
<!-- Trial Balance -->
<report
id="action_report_trial_balance_qweb"
model="trial.balance.report.wizard"
model="report_trial_balance"
string="Trial Balance"
menu="False"
report_type="qweb-pdf"
name="account_financial_report.trial_balance"
file="account_financial_report.trial_balance"
name="account_financial_report.report_trial_balance_qweb"
file="account_financial_report.report_trial_balance_qweb"
/>
<report
id="action_report_trial_balance_html"
model="trial.balance.report.wizard"
model="report_trial_balance"
string="Trial Balance"
menu="False"
report_type="qweb-html"
name="account_financial_report.trial_balance"
file="account_financial_report.trial_balance"
name="account_financial_report.report_trial_balance_qweb"
file="account_financial_report.report_trial_balance_html"
/>
<!-- Open Items -->
<report
id="action_print_report_open_items_qweb"
model="open.items.report.wizard"
id="action_report_open_items_qweb"
model="report_open_items"
string="Open Items"
menu="False"
report_type="qweb-pdf"
name="account_financial_report.open_items"
file="account_financial_report.open_items"
name="account_financial_report.report_open_items_qweb"
file="account_financial_report.report_open_items_qweb"
/>
<report
id="action_print_report_open_items_html"
model="open.items.report.wizard"
id="action_report_open_items_html"
model="report_open_items"
string="Open Items"
menu="False"
report_type="qweb-html"
name="account_financial_report.open_items"
file="account_financial_report.open_items"
name="account_financial_report.report_open_items_qweb"
file="account_financial_report.report_open_items_html"
/>
<!-- Aged Partner Balance -->
<report
id="action_print_report_aged_partner_balance_qweb"
model="aged.partner.balance.report.wizard"
id="action_report_aged_partner_balance_qweb"
model="report_aged_partner_balance"
string="Aged Partner Balance"
report_type="qweb-pdf"
menu="False"
name="account_financial_report.aged_partner_balance"
file="account_financial_report.aged_partner_balance"
name="account_financial_report.report_aged_partner_balance_qweb"
file="account_financial_report.report_aged_partner_balance_qweb"
/>
<report
id="action_print_report_aged_partner_balance_html"
model="aged.partner.balance.report.wizard"
id="action_report_aged_partner_balance_html"
model="report_aged_partner_balance"
string="Aged Partner Balance"
report_type="qweb-html"
menu="False"
name="account_financial_report.aged_partner_balance"
file="account_financial_report.aged_partner_balance"
name="account_financial_report.report_aged_partner_balance_qweb"
file="account_financial_report.report_aged_partner_balance_html"
/>
<!-- VAT Report -->
<report
id="action_print_report_vat_report_qweb"
model="vat.report.wizard"
id="action_report_vat_report_qweb"
model="report_vat_report"
string="VAT Report"
report_type="qweb-pdf"
menu="False"
name="account_financial_report.vat_report"
file="account_financial_report.vat_report"
name="account_financial_report.report_vat_report_qweb"
file="account_financial_report.report_vat_report_qweb"
/>
<report
id="action_print_report_vat_report_html"
model="vat.report.wizard"
id="action_report_vat_report_html"
model="report_vat_report"
string="VAT Report"
report_type="qweb-html"
menu="False"
name="account_financial_report.vat_report"
file="account_financial_report.vat_report"
name="account_financial_report.report_vat_report_qweb"
file="account_financial_report.report_vat_report_html"
/>
<!-- PDF REPORTS : paperformat -->
<record id="report_qweb_paperformat" model="report.paperformat">
<field name="name">Account financial report qweb paperformat</field>
<field name="default" eval="True"/>
@ -131,74 +128,83 @@
<field name="header_spacing">10</field>
<field name="dpi">110</field>
</record>
<record id="action_print_report_general_ledger_qweb" model="ir.actions.report">
<field name="paperformat_id" ref="report_qweb_paperformat" />
</record>
<record id="action_print_journal_ledger_wizard_qweb" model="ir.actions.report">
<record id="action_report_general_ledger_qweb" model="ir.actions.report">
<field name="paperformat_id" ref="report_qweb_paperformat"/>
</record>
<record id="action_report_trial_balance_qweb" model="ir.actions.report">
<field name="paperformat_id" ref="report_qweb_paperformat"/>
</record>
<record id="action_print_report_open_items_qweb" model="ir.actions.report">
<record id="action_report_open_items_qweb" model="ir.actions.report">
<field name="paperformat_id" ref="report_qweb_paperformat"/>
</record>
<record
id="action_print_report_aged_partner_balance_qweb"
model="ir.actions.report"
>
<record id="action_report_aged_partner_balance_qweb"
model="ir.actions.report">
<field name="paperformat_id" ref="report_qweb_paperformat"/>
</record>
<record id="action_print_report_vat_report_qweb" model="ir.actions.report">
<record id="action_report_vat_report_qweb"
model="ir.actions.report">
<field name="paperformat_id" ref="report_qweb_paperformat"/>
</record>
<!-- XLSX REPORTS -->
<record id="action_report_general_ledger_xlsx" model="ir.actions.report">
<field name="name">General Ledger XLSX</field>
<field name="model">general.ledger.report.wizard</field>
<field name="model">report_general_ledger</field>
<field name="type">ir.actions.report</field>
<field name="report_name">a_f_r.report_general_ledger_xlsx</field>
<field name="report_type">xlsx</field>
<field name="report_file">report_general_ledger</field>
</record>
<record id="action_report_journal_ledger_xlsx" model="ir.actions.report">
<field name="name">Journal Ledger XLSX</field>
<field name="model">journal.ledger.report.wizard</field>
<field name="model">report_journal_ledger</field>
<field name="type">ir.actions.report</field>
<field name="report_name">a_f_r.report_journal_ledger_xlsx</field>
<field name="report_type">xlsx</field>
<field name="report_file">report_journal_ledger</field>
</record>
<record id="action_report_trial_balance_xlsx" model="ir.actions.report">
<field name="name">Trial Balance XLSX</field>
<field name="model">trial.balance.report.wizard</field>
<field name="model">report_trial_balance</field>
<field name="type">ir.actions.report</field>
<field name="report_name">a_f_r.report_trial_balance_xlsx</field>
<field name="report_type">xlsx</field>
<field name="report_file">report_trial_balance</field>
</record>
<record id="action_report_open_items_xlsx" model="ir.actions.report">
<field name="name">Open Items XLSX</field>
<field name="model">open.items.report.wizard</field>
<field name="model">report_open_items</field>
<field name="type">ir.actions.report</field>
<field name="report_name">a_f_r.report_open_items_xlsx</field>
<field name="report_type">xlsx</field>
<field name="report_file">report_open_items</field>
</record>
<record id="action_report_aged_partner_balance_xlsx" model="ir.actions.report">
<field name="name">Aged Partner Balance XLSX</field>
<field name="model">aged.partner.balance.report.wizard</field>
<field name="model">report_aged_partner_balance</field>
<field name="type">ir.actions.report</field>
<field name="report_name">a_f_r.report_aged_partner_balance_xlsx</field>
<field name="report_type">xlsx</field>
<field name="report_file">report_aged_partner_balance</field>
</record>
<record id="action_report_vat_report_xlsx" model="ir.actions.report">
<field name="name">VAT Report XLSX</field>
<field name="model">vat.report.wizard</field>
<field name="model">report_vat_report</field>
<field name="type">ir.actions.report</field>
<field name="report_name">a_f_r.report_vat_report_xlsx</field>
<field name="report_type">xlsx</field>
<field name="report_file">report_vat_report</field>
</record>
</odoo>

72
account_financial_report/static/description/index.html

@ -367,9 +367,9 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/13.0/account_financial_report"><img alt="OCA/account-financial-reporting" src="https://img.shields.io/badge/github-OCA%2Faccount--financial--reporting-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-financial-reporting-13-0/account-financial-reporting-13-0-account_financial_report"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/91/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/12.0/account_financial_report"><img alt="OCA/account-financial-reporting" src="https://img.shields.io/badge/github-OCA%2Faccount--financial--reporting-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/account-financial-reporting-12-0/account-financial-reporting-12-0-account_financial_report"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/91/12.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This module adds a set of financial reports. They are accessible under
Invoicing / Reporting / OCA accounting reports.</p>
Accounting / Reporting / OCA Reports.</p>
<ul class="simple">
<li>General ledger</li>
<li>Trial Balance</li>
@ -386,44 +386,31 @@ currency balances are not available.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#known-issues-roadmap" id="id4">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#changelog" id="id5">Changelog</a><ul>
<li><a class="reference internal" href="#id1" id="id6">11.0.2.5.0 (2019-04-26)</a></li>
<li><a class="reference internal" href="#id2" id="id7">11.0.2.4.1 (2019-01-08)</a></li>
<li><a class="reference internal" href="#id3" id="id8">11.0.2.3.1 (2018-11-29)</a></li>
<li><a class="reference internal" href="#changelog" id="id4">Changelog</a><ul>
<li><a class="reference internal" href="#id1" id="id5">11.0.2.5.0 (2019-04-26)</a></li>
<li><a class="reference internal" href="#id2" id="id6">11.0.2.4.1 (2019-01-08)</a></li>
<li><a class="reference internal" href="#id3" id="id7">11.0.2.3.1 (2018-11-29)</a></li>
</ul>
</li>
<li><a class="reference internal" href="#bug-tracker" id="id9">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id10">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id11">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id12">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id13">Maintainers</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id8">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id9">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id10">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id11">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id12">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id4">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>‘VAT Report’ is valid only for cases where it’s met that for each
Tax defined: all the “Account tags” of all the
‘Repartition for Invoices’ or ‘Repartition for Credit Notes’
are different.</li>
<li>It would be nice to have in reports a column indicating the
state of the entries when the option “All Entries” is selected
in “Target Moves” field in a wizard</li>
</ul>
</div>
<div class="section" id="changelog">
<h1><a class="toc-backref" href="#id5">Changelog</a></h1>
<h1><a class="toc-backref" href="#id4">Changelog</a></h1>
<div class="section" id="id1">
<h2><a class="toc-backref" href="#id6">11.0.2.5.0 (2019-04-26)</a></h2>
<h2><a class="toc-backref" href="#id5">11.0.2.5.0 (2019-04-26)</a></h2>
<ul class="simple">
<li>In the Trial Balance you have an option to hide parent hierarchy levels</li>
</ul>
</div>
<div class="section" id="id2">
<h2><a class="toc-backref" href="#id7">11.0.2.4.1 (2019-01-08)</a></h2>
<h2><a class="toc-backref" href="#id6">11.0.2.4.1 (2019-01-08)</a></h2>
<ul class="simple">
<li>Handle better multicompany behaviour</li>
<li>Improve how title appears in the reports</li>
@ -431,7 +418,7 @@ in “Target Moves” field in a wizard</li>
</ul>
</div>
<div class="section" id="id3">
<h2><a class="toc-backref" href="#id8">11.0.2.3.1 (2018-11-29)</a></h2>
<h2><a class="toc-backref" href="#id7">11.0.2.3.1 (2018-11-29)</a></h2>
<ul class="simple">
<li>In the Trial Balance you can apply a filter by hierarchy levels</li>
<li>In the General Ledger you can apply a filter by Analytic Tag</li>
@ -440,28 +427,28 @@ in “Target Moves” field in a wizard</li>
</div>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id9">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#id8">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/account-financial-reporting/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_financial_report%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<a class="reference external" href="https://github.com/OCA/account-financial-reporting/issues/new?body=module:%20account_financial_report%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id10">Credits</a></h1>
<h1><a class="toc-backref" href="#id9">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id11">Authors</a></h2>
<h2><a class="toc-backref" href="#id10">Authors</a></h2>
<ul class="simple">
<li>Camptocamp SA</li>
<li>initOS GmbH</li>
<li>redCOR AG</li>
<li>ForgeFlow</li>
<li>Eficent</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id12">Contributors</a></h2>
<h2><a class="toc-backref" href="#id11">Contributors</a></h2>
<ul class="simple">
<li>Jordi Ballester &lt;<a class="reference external" href="mailto:jordi.ballester&#64;forgeflow.com">jordi.ballester&#64;forgeflow.com</a>&gt;</li>
<li>Jordi Ballester &lt;<a class="reference external" href="mailto:jordi.ballester&#64;eficient.com">jordi.ballester&#64;eficient.com</a>&gt;</li>
<li>Yannick Vaucher &lt;<a class="reference external" href="mailto:yannick.vaucher&#64;camptocamp.com">yannick.vaucher&#64;camptocamp.com</a>&gt;</li>
<li>Simone Orsi &lt;<a class="reference external" href="mailto:simone.orsi&#64;abstract.com">simone.orsi&#64;abstract.com</a>&gt;</li>
<li>Leonardo Pistone &lt;<a class="reference external" href="mailto:leonardo.pistone&#64;camptocamp.com">leonardo.pistone&#64;camptocamp.com</a>&gt;</li>
@ -477,19 +464,14 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<li>Akim Juillerat &lt;<a class="reference external" href="mailto:akim.juillerat&#64;camptocamp.com">akim.juillerat&#64;camptocamp.com</a>&gt;</li>
<li>Alexis de Lattre &lt;<a class="reference external" href="mailto:alexis&#64;via.ecp.fr">alexis&#64;via.ecp.fr</a>&gt;</li>
<li>Mihai Fekete &lt;<a class="reference external" href="mailto:feketemihai&#64;gmail.com">feketemihai&#64;gmail.com</a>&gt;</li>
<li>Miquel Raïch &lt;<a class="reference external" href="mailto:miquel.raich&#64;forgeflow.com">miquel.raich&#64;forgeflow.com</a>&gt;</li>
<li>Joan Sisquella &lt;<a class="reference external" href="mailto:joan.sisquella&#64;forgeflow.com">joan.sisquella&#64;forgeflow.com</a>&gt;</li>
<li>Miquel Raïch &lt;<a class="reference external" href="mailto:miquel.raich&#64;eficent.com">miquel.raich&#64;eficent.com</a>&gt;</li>
<li><a class="reference external" href="https://www.tecnativa.com">Tecnativa</a>:<ul>
<li>Pedro M. Baeza</li>
<li>Sergio Teruel</li>
<li>Ernesto Tejeda</li>
<li>Alexandre D. Díaz</li>
</ul>
</li>
<li>Lois Rilo &lt;<a class="reference external" href="mailto:lois.rilo&#64;forgeflow.com">lois.rilo&#64;forgeflow.com</a>&gt;</li>
<li><a class="reference external" href="https://www.sygel.es">Sygel</a>:<ul>
<li>Harald Panten</li>
<li>Valentin Vinagre</li>
<li><a class="reference external" href="https://www.druidoo.io">Druidoo</a>:<ul>
<li>Iván Todorovich</li>
</ul>
</li>
</ul>
@ -497,13 +479,13 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
April 2016.</p>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id13">Maintainers</a></h2>
<h2><a class="toc-backref" href="#id12">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org"><img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" /></a>
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/13.0/account_financial_report">OCA/account-financial-reporting</a> project on GitHub.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/account-financial-reporting/tree/12.0/account_financial_report">OCA/account-financial-reporting</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>

28
account_financial_report/static/src/css/report.css

@ -16,18 +16,13 @@
.act_as_tbody {
display: table-row-group !important;
}
.list_table,
.data_table,
.totals_table {
.list_table, .data_table, .totals_table{
width: 100% !important;
}
.act_as_row.labels {
background-color: #f0f0f0 !important;
background-color:#F0F0F0 !important;
}
.list_table,
.data_table,
.totals_table,
.list_table .act_as_row {
.list_table, .data_table, .totals_table, .list_table .act_as_row {
border-left:0px;
border-right:0px;
text-align:center;
@ -42,9 +37,7 @@
font-weight: bold;
text-align: center;
}
.list_table .act_as_row.labels,
.list_table .act_as_row.initial_balance,
.list_table .act_as_row.lines {
.list_table .act_as_row.labels, .list_table .act_as_row.initial_balance, .list_table .act_as_row.lines {
border-color:grey !important;
border-bottom:1px solid lightGrey !important;
}
@ -52,13 +45,10 @@
border: 1px solid lightGrey;
text-align: center;
}
.data_table .act_as_cell,
.list_table .act_as_cell,
.totals_table .act_as_cell {
.data_table .act_as_cell, .list_table .act_as_cell, .totals_table .act_as_cell {
word-wrap: break-word;
}
.data_table .act_as_row.labels,
.totals_table .act_as_row.labels {
.data_table .act_as_row.labels, .totals_table .act_as_row.labels {
font-weight: bold;
}
.initial_balance .act_as_cell {
@ -69,7 +59,7 @@
font-weight:bold;
}
.account_title.labels {
background-color: #f0f0f0 !important;
background-color:#F0F0F0 !important;
}
.act_as_cell.amount {
word-wrap:normal;
@ -81,9 +71,9 @@
.act_as_cell.right {
text-align:right;
}
/*.list_table .act_as_cell {*/
.list_table .act_as_cell{
/* border-right:1px solid lightGrey; uncomment to active column lines */
/*}*/
}
.list_table .act_as_cell.first_column {
padding-left: 0px;
/* border-left:1px solid lightGrey; uncomment to active column lines */

120
account_financial_report/static/src/js/account_financial_report_backend.js

@ -0,0 +1,120 @@
odoo.define('account_financial_report.account_financial_report_backend', function (require) {
'use strict';
var core = require('web.core');
var Widget = require('web.Widget');
var ControlPanelMixin = require('web.ControlPanelMixin');
var ReportWidget = require(
'account_financial_report.account_financial_report_widget'
);
var report_backend = Widget.extend(ControlPanelMixin, {
// Stores all the parameters of the action.
events: {
'click .o_account_financial_reports_print': 'print',
'click .o_account_financial_reports_export': 'export',
},
init: function (parent, action) {
this.actionManager = parent;
this.given_context = {};
this.odoo_context = action.context;
this.controller_url = action.context.url;
if (action.context.context) {
this.given_context = action.context.context;
}
this.given_context.active_id = action.context.active_id ||
action.params.active_id;
this.given_context.model = action.context.active_model || false;
this.given_context.ttype = action.context.ttype || false;
return this._super.apply(this, arguments);
},
willStart: function () {
return $.when(this.get_html());
},
set_html: function () {
var self = this;
var def = $.when();
if (!this.report_widget) {
this.report_widget = new ReportWidget(this, this.given_context);
def = this.report_widget.appendTo(this.$el);
}
def.then(function () {
self.report_widget.$el.html(self.html);
});
},
start: function () {
this.set_html();
return this._super();
},
// Fetches the html and is previous report.context if any,
// else create it
get_html: function () {
var self = this;
var defs = [];
return this._rpc({
model: this.given_context.model,
method: 'get_html',
args: [self.given_context],
context: self.odoo_context,
})
.then(function (result) {
self.html = result.html;
defs.push(self.update_cp());
return $.when.apply($, defs);
});
},
// Updates the control panel and render the elements that have yet
// to be rendered
update_cp: function () {
if (this.$buttons) {
var status = {
breadcrumbs: this.actionManager.get_breadcrumbs(),
cp_content: {$buttons: this.$buttons},
};
return this.update_control_panel(status);
}
},
do_show: function () {
this._super();
this.update_cp();
},
print: function () {
var self = this;
this._rpc({
model: this.given_context.model,
method: 'print_report',
args: [this.given_context.active_id, 'qweb-pdf'],
context: self.odoo_context,
}).then(function (result) {
self.do_action(result);
});
},
export: function () {
var self = this;
this._rpc({
model: this.given_context.model,
method: 'print_report',
args: [this.given_context.active_id, 'xlsx'],
context: self.odoo_context,
}).then(function (result) {
self.do_action(result);
});
},
canBeRemoved: function () {
return $.when();
},
on_attach_callback: function () {
this.isInDOM = true;
},
on_detach_callback: function () {
this.isInDOM = false;
},
});
core.action_registry.add(
"account_financial_report_backend",
report_backend
);
return report_backend;
});

86
account_financial_report/static/src/js/account_financial_report_widgets.js

@ -0,0 +1,86 @@
odoo.define('account_financial_report.account_financial_report_widget', function
(require) {
'use strict';
var Widget = require('web.Widget');
var accountFinancialReportWidget = Widget.extend({
events: {
'click .o_account_financial_reports_web_action':
'boundLink',
'click .o_account_financial_reports_web_action_multi':
'boundLinkmulti',
'click .o_account_financial_reports_web_action_monetary':
'boundLinkMonetary',
'click .o_account_financial_reports_web_action_monetary_multi':
'boundLinkMonetarymulti',
},
init: function () {
this._super.apply(this, arguments);
},
start: function () {
return this._super.apply(this, arguments);
},
boundLink: function (e) {
var res_model = $(e.target).data('res-model');
var res_id = $(e.target).data('active-id');
return this.do_action({
type: 'ir.actions.act_window',
res_model: res_model,
res_id: res_id,
views: [[false, 'form']],
target: 'current',
});
},
boundLinkmulti: function (e) {
var res_model = $(e.target).data('res-model');
var domain = $(e.target).data('domain');
if (!res_model) {
res_model = $(e.target.parentElement).data('res-model');
}
if (!domain) {
domain = $(e.target.parentElement).data('domain');
}
return this.do_action({
type: 'ir.actions.act_window',
name: this._toTitleCase(res_model.split('.').join(' ')),
res_model: res_model,
domain: domain,
views: [[false, "list"], [false, "form"]],
target: 'current',
});
},
boundLinkMonetary: function (e) {
var res_model = $(e.target.parentElement).data('res-model');
var res_id = $(e.target.parentElement).data('active-id');
return this.do_action({
type: 'ir.actions.act_window',
res_model: res_model,
res_id: res_id,
views: [[false, 'form']],
target: 'current',
});
},
boundLinkMonetarymulti: function (e) {
var res_model = $(e.target.parentElement).data('res-model');
var domain = $(e.target.parentElement).data('domain');
return this.do_action({
type: 'ir.actions.act_window',
res_model: res_model,
domain: domain,
views: [[false, "list"], [false, "form"]],
target: 'current',
});
},
_toTitleCase: function (str) {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() +
txt.substr(1).toLowerCase();
});
},
});
return accountFinancialReportWidget;
});

35
account_financial_report/static/src/js/action_manager_report.js

@ -1,35 +0,0 @@
odoo.define("account_financial_report.ReportActionManager", function(require) {
"use strict";
const ActionManager = require("web.ActionManager");
require("web.ReportActionManager");
ActionManager.include({
/**
* @override
*/
_executeReportClientAction: function(action, options) {
const MODULE_NAME = "account_financial_report";
// When 'report_action' is called from the backend, Odoo hardcodes the action tag.
// We have to make a hack to use our own report controller.
if (action.report_file.startsWith(`${MODULE_NAME}.`)) {
const urls = this._makeReportUrls(action);
const clientActionOptions = _.extend({}, options, {
context: action.context,
data: action.data,
display_name: action.display_name,
name: action.name,
report_file: action.report_file,
report_name: action.report_name,
report_url: urls.html,
});
return this.doAction(
"account_financial_report.client_action",
clientActionOptions
);
}
return this._super.apply(this, arguments);
},
});
});

51
account_financial_report/static/src/js/client_action.js

@ -1,51 +0,0 @@
odoo.define("account_financial_report.client_action", function(require) {
"use strict";
var ReportAction = require("report.client_action");
var core = require("web.core");
var QWeb = core.qweb;
const AFRReportAction = ReportAction.extend({
start: function() {
return this._super.apply(this, arguments).then(() => {
this.$buttons = $(
QWeb.render(
"account_financial_report.client_action.ControlButtons",
{}
)
);
this.$buttons.on("click", ".o_report_print", this.on_click_print);
this.$buttons.on("click", ".o_report_export", this.on_click_export);
this._update_control_panel();
});
},
on_click_export: function() {
const action = {
type: "ir.actions.report",
report_type: "xlsx",
report_name: this._get_xlsx_name(this.report_name),
report_file: this._get_xlsx_name(this.report_file),
data: this.data,
context: this.context,
display_name: this.title,
};
return this.do_action(action);
},
/**
* @param {String} str
* @returns {String}
*/
_get_xlsx_name: function(str) {
const parts = str.split(".");
return `a_f_r.report_${parts[parts.length - 1]}_xlsx`;
},
});
core.action_registry.add("account_financial_report.client_action", AFRReportAction);
return AFRReportAction;
});

58
account_financial_report/static/src/js/report.js

@ -1,58 +0,0 @@
odoo.define("account_financial_report.report", function(require) {
"use strict";
require("web.dom_ready");
const utils = require("report.utils");
if (window.self === window.top) {
return;
}
const web_base_url = $("html").attr("web-base-url");
const trusted_host = utils.get_host_from_url(web_base_url);
const trusted_protocol = utils.get_protocol_from_url(web_base_url);
const trusted_origin = utils.build_origin(trusted_protocol, trusted_host);
/**
* Convert a model name to a capitalized title style
* Example: account.mode.line --> Account Move Line
*
* @param {String} str
* @returns {String}
*/
function toTitleCase(str) {
return str
.replaceAll(".", " ")
.replace(
/\w\S*/g,
txt => `${txt.charAt(0).toUpperCase()}${txt.substr(1).toLowerCase()}`
);
}
// Allow sending commands to the webclient
// `do_action` command with domain
$("[res-model][domain]")
.wrap("<a/>")
.attr("href", "#")
.on("click", function(ev) {
ev.preventDefault();
const res_model = $(this).attr("res-model");
const action = {
type: "ir.actions.act_window",
res_model: res_model,
domain: $(this).attr("domain"),
name: toTitleCase(res_model),
views: [
[false, "list"],
[false, "form"],
],
};
window.parent.postMessage(
{
message: "report:do_action",
action: action,
},
trusted_origin
);
});
});

17
account_financial_report/static/src/xml/report.xml

@ -1,17 +0,0 @@
<template>
<!-- Buttons of the Control Panel -->
<t t-name="account_financial_report.client_action.ControlButtons">
<div class="o_report_buttons">
<button
type="button"
class="btn btn-primary o_report_print"
title="Print"
>Print</button>
<button
type="button"
class="btn btn-secondary o_report_export"
title="Export"
>Export</button>
</div>
</t>
</template>

5
account_financial_report/tests/__init__.py

@ -1,6 +1,11 @@
# © 2016 Julien Coux (Camptocamp)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).-
from . import abstract_test
from . import abstract_test_tax_report
from . import abstract_test_foreign_currency
from . import test_aged_partner_balance
from . import test_general_ledger
from . import test_journal_ledger
from . import test_open_items

399
account_financial_report/tests/abstract_test.py

@ -0,0 +1,399 @@
# Author: Julien Coux
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from odoo.tests import common
from odoo.tools import test_reports
_logger = logging.getLogger(__name__)
class AbstractTest(common.TransactionCase):
"""Common technical tests for all reports."""
at_install = False
post_install = True
accounts = {}
def with_context(self, *args, **kwargs):
context = dict(args[0] if args else self.env.context, **kwargs)
self.env = self.env(context=context)
return self
def _chart_template_create(self):
transfer_account_id = self.env['account.account.template'].create({
'code': '000',
'name': 'Liquidity Transfers',
'reconcile': True,
'user_type_id': self.ref(
"account.data_account_type_current_assets"),
})
self.chart = self.env['account.chart.template'].create({
'name': 'Test COA',
'code_digits': 4,
'bank_account_code_prefix': 1014,
'cash_account_code_prefix': 1014,
'currency_id': self.ref('base.USD'),
'transfer_account_code_prefix': '000',
})
transfer_account_id.update({
'chart_template_id': self.chart.id,
})
self.env['ir.model.data'].create({
'res_id': transfer_account_id.id,
'model': transfer_account_id._name,
'name': 'Liquidity Transfers',
})
act = self.env['account.account.template'].create({
'code': '001',
'name': 'Expenses',
'user_type_id': self.ref("account.data_account_type_expenses"),
'chart_template_id': self.chart.id,
'reconcile': True,
})
self.env['ir.model.data'].create({
'res_id': act.id,
'model': act._name,
'name': 'expenses',
})
act = self.env['account.account.template'].create({
'code': '002',
'name': 'Product Sales',
'user_type_id': self.ref("account.data_account_type_revenue"),
'chart_template_id': self.chart.id,
'reconcile': True,
})
self.env['ir.model.data'].create({
'res_id': act.id,
'model': act._name,
'name': 'sales',
})
act = self.env['account.account.template'].create({
'code': '003',
'name': 'Account Receivable',
'user_type_id': self.ref("account.data_account_type_receivable"),
'chart_template_id': self.chart.id,
'reconcile': True,
})
self.env['ir.model.data'].create({
'res_id': act.id,
'model': act._name,
'name': 'receivable',
})
act = self.env['account.account.template'].create({
'code': '004',
'name': 'Account Payable',
'user_type_id': self.ref("account.data_account_type_payable"),
'chart_template_id': self.chart.id,
'reconcile': True,
})
self.env['ir.model.data'].create({
'res_id': act.id,
'model': act._name,
'name': 'payable',
})
def _add_chart_of_accounts(self):
self.company = self.env['res.company'].create({
'name': 'Spanish test company',
})
self.env.ref('base.group_multi_company').write({
'users': [(4, self.env.uid)],
})
self.env.user.write({
'company_ids': [(4, self.company.id)],
'company_id': self.company.id,
})
self.with_context(
company_id=self.company.id, force_company=self.company.id)
self.chart.try_loading_for_current_company()
self.revenue = self.env['account.account'].search(
[('user_type_id', '=', self.ref(
"account.data_account_type_revenue"))], limit=1)
self.expense = self.env['account.account'].search(
[('user_type_id', '=', self.ref(
"account.data_account_type_expenses"))], limit=1)
self.receivable = self.env['account.account'].search(
[('user_type_id', '=', self.ref(
"account.data_account_type_receivable"))], limit=1)
self.payable = self.env['account.account'].search(
[('user_type_id', '=', self.ref(
"account.data_account_type_payable"))], limit=1)
return True
def _journals_create(self):
self.journal_sale = self.env['account.journal'].create({
'company_id': self.company.id,
'name': 'Test journal for sale',
'type': 'sale',
'code': 'TSALE',
'default_debit_account_id': self.revenue.id,
'default_credit_account_id': self.revenue.id,
})
self.journal_purchase = self.env['account.journal'].create({
'company_id': self.company.id,
'name': 'Test journal for purchase',
'type': 'purchase',
'code': 'TPUR',
'default_debit_account_id': self.expense.id,
'default_credit_account_id': self.expense.id,
})
return True
def _invoice_create(self):
self.partner = self.env['res.partner'].create({
'name': 'Test partner',
'company_id': self.company.id,
'property_account_receivable_id': self.receivable.id,
'property_account_payable_id': self.payable.id,
})
# customer invoice
customer_invoice_lines = [(0, False, {
'name': 'Test description #1',
'account_id': self.revenue.id,
'quantity': 1.0,
'price_unit': 100.0,
}), (0, False, {
'name': 'Test description #2',
'account_id': self.revenue.id,
'quantity': 2.0,
'price_unit': 25.0,
})]
self.invoice_out = self.env['account.invoice'].create({
'partner_id': self.partner.id,
'type': 'out_invoice',
'invoice_line_ids': customer_invoice_lines,
'account_id': self.partner.property_account_receivable_id.id,
'journal_id': self.journal_sale.id,
})
self.invoice_out.action_invoice_open()
# vendor bill
vendor_invoice_lines = [(0, False, {
'name': 'Test description #1',
'account_id': self.revenue.id,
'quantity': 1.0,
'price_unit': 100.0,
}), (0, False, {
'name': 'Test description #2',
'account_id': self.revenue.id,
'quantity': 2.0,
'price_unit': 25.0,
})]
self.invoice_in = self.env['account.invoice'].create({
'partner_id': self.partner.id,
'type': 'in_invoice',
'invoice_line_ids': vendor_invoice_lines,
'account_id': self.partner.property_account_payable_id.id,
'journal_id': self.journal_purchase.id,
})
self.invoice_in.action_invoice_open()
def setUp(self):
super(AbstractTest, self).setUp()
self.with_context()
self._chart_template_create()
self._add_chart_of_accounts()
self._journals_create()
self._invoice_create()
self.model = self._getReportModel()
self.qweb_report_name = self._getQwebReportName()
self.xlsx_report_name = self._getXlsxReportName()
self.xlsx_action_name = self._getXlsxReportActionName()
self.report_title = self._getReportTitle()
self.base_filters = self._getBaseFilters()
self.additional_filters = self._getAdditionalFiltersToBeTested()
self.report = self.model.create(self.base_filters)
self.report.compute_data_for_report()
def test_html(self):
test_reports.try_report(self.env.cr, self.env.uid,
self.qweb_report_name,
[self.report.id],
report_type='qweb-html')
def test_qweb(self):
test_reports.try_report(self.env.cr, self.env.uid,
self.qweb_report_name,
[self.report.id],
report_type='qweb-pdf')
def test_xlsx(self):
test_reports.try_report(self.env.cr, self.env.uid,
self.xlsx_report_name,
[self.report.id],
report_type='xlsx')
def test_print(self):
self.report.print_report('qweb')
self.report.print_report('xlsx')
def test_02_generation_report_html(self):
"""Check if report HTML is correctly generated"""
# Check if returned report action is correct
report_type = 'qweb-html'
report_action = self.report.print_report(report_type)
self.assertDictContainsSubset(
{
'type': 'ir.actions.report',
'report_name': self.qweb_report_name,
'report_type': 'qweb-html',
},
report_action
)
# Check if report template is correct
report = self.env['ir.actions.report'].search(
[('report_name', '=', self.qweb_report_name),
('report_type', '=', report_type)], limit=1)
self.assertEqual(report.report_type, 'qweb-html')
rep = report.render(self.report.ids, {})
self.assertTrue(self.report_title.encode('utf8') in rep[0])
self.assertTrue(
self.report.account_ids[0].name.encode('utf8') in rep[0]
)
def test_04_compute_data(self):
"""Check that the SQL queries work with all filters options"""
for filters in [{}] + self.additional_filters:
current_filter = self.base_filters.copy()
current_filter.update(filters)
report = self.model.create(current_filter)
report.compute_data_for_report()
self.assertGreaterEqual(len(report.account_ids), 1)
# Same filters with only one account
current_filter = self.base_filters.copy()
current_filter.update(filters)
report_accounts = report.account_ids.filtered('account_id')
current_filter.update({
'filter_account_ids':
[(6, 0, report_accounts[0].account_id.ids)],
})
report2 = self.model.create(current_filter)
report2.compute_data_for_report()
self.assertEqual(len(report2.account_ids), 1)
self.assertEqual(report2.account_ids.name,
report_accounts[0].name)
if self._partner_test_is_possible(filters):
# Same filters with only one partner
report_partner_ids = report.account_ids.mapped('partner_ids')
partner_ids = report_partner_ids.mapped('partner_id')
current_filter = self.base_filters.copy()
current_filter.update(filters)
current_filter.update({
'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
})
report3 = self.model.create(current_filter)
report3.compute_data_for_report()
self.assertGreaterEqual(len(report3.account_ids), 1)
report_partner_ids3 = report3.account_ids.mapped('partner_ids')
partner_ids3 = report_partner_ids3.mapped('partner_id')
self.assertEqual(len(partner_ids3), 1)
self.assertEqual(
partner_ids3.name,
partner_ids[0].name
)
# Same filters with only one partner and one account
report_partner_ids = report3.account_ids.mapped('partner_ids')
report_account_id = report_partner_ids.filtered(
lambda p: p.partner_id
)[0].report_account_id
current_filter = self.base_filters.copy()
current_filter.update(filters)
current_filter.update({
'filter_account_ids':
[(6, 0, report_account_id.account_id.ids)],
'filter_partner_ids': [(6, 0, partner_ids[0].ids)],
})
report4 = self.model.create(current_filter)
report4.compute_data_for_report()
self.assertEqual(len(report4.account_ids), 1)
self.assertEqual(report4.account_ids.name,
report_account_id.account_id.name)
report_partner_ids4 = report4.account_ids.mapped('partner_ids')
partner_ids4 = report_partner_ids4.mapped('partner_id')
self.assertEqual(len(partner_ids4), 1)
self.assertEqual(
partner_ids4.name,
partner_ids[0].name
)
def _partner_test_is_possible(self, filters):
"""
:return:
a boolean to indicate if partner test is possible
with current filters
"""
return True
def _getReportModel(self):
"""
:return: the report model name
"""
raise NotImplementedError()
def _getQwebReportName(self):
"""
:return: the qweb report name
"""
raise NotImplementedError()
def _getXlsxReportName(self):
"""
:return: the xlsx report name
"""
raise NotImplementedError()
def _getXlsxReportActionName(self):
"""
:return: the xlsx report action name
"""
raise NotImplementedError()
def _getReportTitle(self):
"""
:return: the report title displayed into the report
"""
raise NotImplementedError()
def _getBaseFilters(self):
"""
:return: the minimum required filters to generate report
"""
raise NotImplementedError()
def _getAdditionalFiltersToBeTested(self):
"""
:return: the additional filters to generate report variants
"""
raise NotImplementedError()

78
account_financial_report/tests/abstract_test_foreign_currency.py

@ -0,0 +1,78 @@
# Copyright 2018 Forest and Biomass Romania
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from . import abstract_test
_logger = logging.getLogger(__name__)
class AbstractTestForeignCurrency(abstract_test.AbstractTest):
"""Common technical tests for all reports."""
def _chart_template_create(self):
super(AbstractTestForeignCurrency, self)._chart_template_create()
# Account for foreign payments
self.account_type_other = self.env['account.account.type'].create(
{'name': 'foreign expenses',
'type': 'other',
})
act = self.env['account.account.template'].create({
'code': '0012',
'name': 'Foreign Expenses',
'user_type_id': self.account_type_other.id,
'chart_template_id': self.chart.id,
'currency_id': self.env.ref('base.EUR').id,
})
self.env['ir.model.data'].create({
'res_id': act.id,
'model': act._name,
'name': 'foreign expenses',
})
return True
def _add_chart_of_accounts(self):
super(AbstractTestForeignCurrency, self)._add_chart_of_accounts()
self.foreign_expense = self.env['account.account'].search(
[('currency_id', '=', self.env.ref('base.EUR').id)], limit=1)
self.foreign_currency_id = self.foreign_expense.currency_id
return True
def _journals_create(self):
super(AbstractTestForeignCurrency, self)._journals_create()
self.journal_foreign_purchases = self.env['account.journal'].create({
'company_id': self.company.id,
'name': 'Test journal for purchase',
'type': 'purchase',
'code': 'TFORPUR',
'default_debit_account_id': self.foreign_expense.id,
'default_credit_account_id': self.foreign_expense.id,
'currency_id': self.foreign_currency_id.id,
})
return True
def _invoice_create(self):
super(AbstractTestForeignCurrency, self)._invoice_create()
# vendor bill foreign currency
foreign_vendor_invoice_lines = [(0, False, {
'name': 'Test description #1',
'account_id': self.revenue.id,
'quantity': 1.0,
'price_unit': 100.0,
'currency_id': self.foreign_currency_id.id,
}), (0, False, {
'name': 'Test description #2',
'account_id': self.revenue.id,
'quantity': 2.0,
'price_unit': 25.0,
'currency_id': self.foreign_currency_id.id,
})]
self.foreign_invoice_in = self.env['account.invoice'].create({
'partner_id': self.partner.id,
'type': 'in_invoice',
'invoice_line_ids': foreign_vendor_invoice_lines,
'account_id': self.partner.property_account_payable_id.id,
'journal_id': self.journal_foreign_purchases.id,
})
self.foreign_invoice_in.action_invoice_open()
return True

75
account_financial_report/tests/abstract_test_tax_report.py

@ -0,0 +1,75 @@
# Copyright 2018 Forest and Biomass Romania
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import logging
from odoo.tests.common import TransactionCase
from odoo.tools import test_reports
_logger = logging.getLogger(__name__)
class AbstractTest(TransactionCase):
"""Common technical tests for all reports."""
def setUp(cls):
super(AbstractTest, cls).setUp()
cls.model = cls._getReportModel()
cls.qweb_report_name = cls._getQwebReportName()
cls.xlsx_report_name = cls._getXlsxReportName()
cls.xlsx_action_name = cls._getXlsxReportActionName()
cls.report_title = cls._getReportTitle()
cls.base_filters = cls._getBaseFilters()
cls.report = cls.model.create(cls.base_filters)
cls.report.compute_data_for_report()
def test_html(self):
test_reports.try_report(self.env.cr, self.env.uid,
self.qweb_report_name,
[self.report.id],
report_type='qweb-html')
def test_qweb(self):
test_reports.try_report(self.env.cr, self.env.uid,
self.qweb_report_name,
[self.report.id],
report_type='qweb-pdf')
def test_xlsx(self):
test_reports.try_report(self.env.cr, self.env.uid,
self.xlsx_report_name,
[self.report.id],
report_type='xlsx')
def test_print(self):
self.report.print_report('qweb')
self.report.print_report('xlsx')
def test_generation_report_html(self):
"""Check if report HTML is correctly generated"""
# Check if returned report action is correct
report_type = 'qweb-html'
report_action = self.report.print_report(report_type)
self.assertDictContainsSubset(
{
'type': 'ir.actions.report',
'report_name': self.qweb_report_name,
'report_type': 'qweb-html',
},
report_action
)
# Check if report template is correct
report = self.env['ir.actions.report'].search(
[('report_name', '=', self.qweb_report_name),
('report_type', '=', report_type)], limit=1)
self.assertEqual(report.report_type, 'qweb-html')
rep = report.render(self.report.ids, {})
self.assertTrue(self.report_title.encode('utf8') in rep[0])

41
account_financial_report/tests/test_aged_partner_balance.py

@ -0,0 +1,41 @@
# Author: Julien Coux
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from datetime import date
from . import abstract_test
class TestAgedPartnerBalance(abstract_test.AbstractTest):
"""
Technical tests for Aged Partner Balance Report.
"""
def _getReportModel(self):
return self.env['report_aged_partner_balance']
def _getQwebReportName(self):
return 'account_financial_report.report_aged_partner_balance_qweb'
def _getXlsxReportName(self):
return 'a_f_r.report_aged_partner_balance_xlsx'
def _getXlsxReportActionName(self):
return 'account_financial_report.' \
'action_report_aged_partner_balance_xlsx'
def _getReportTitle(self):
return 'Odoo'
def _getBaseFilters(self):
return {
'date_at': date(date.today().year, 12, 31),
'company_id': self.company.id,
}
def _getAdditionalFiltersToBeTested(self):
return [
{'only_posted_moves': True},
{'show_move_line_details': True},
{'only_posted_moves': True, 'show_move_line_details': True},
]

835
account_financial_report/tests/test_general_ledger.py
File diff suppressed because it is too large
View File

570
account_financial_report/tests/test_journal_ledger.py

@ -1,340 +1,364 @@
# Copyright 2017 ACSONE SA/NV
# Copyright 2019-20 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import datetime
from datetime import datetime, date
from dateutil.relativedelta import relativedelta
from odoo.fields import Date
from odoo.tests.common import Form, TransactionCase
from odoo.tests.common import TransactionCase
from . import abstract_test_foreign_currency as a_t_f_c
class TestJournalReport(TransactionCase):
def setUp(self):
super(TestJournalReport, self).setUp()
self.AccountObj = self.env["account.account"]
self.InvoiceObj = self.env["account.move"]
self.JournalObj = self.env["account.journal"]
self.MoveObj = self.env["account.move"]
self.TaxObj = self.env["account.tax"]
self.JournalLedgerReportWizard = self.env["journal.ledger.report.wizard"]
self.JournalLedgerReport = self.env[
"report.account_financial_report.journal_ledger"
]
self.company = self.env.ref("base.main_company")
self.company.account_sale_tax_id = False
self.company.account_purchase_tax_id = False
today = datetime.today()
last_year = today - relativedelta(years=1)
class TestJournalLedger(a_t_f_c.AbstractTestForeignCurrency):
"""
Technical tests for General Ledger Report.
"""
def _getReportModel(self):
return self.env['report_journal_ledger']
self.previous_fy_date_start = Date.to_string(last_year.replace(month=1, day=1))
self.previous_fy_date_end = Date.to_string(last_year.replace(month=12, day=31))
self.fy_date_start = Date.to_string(today.replace(month=1, day=1))
self.fy_date_end = Date.to_string(today.replace(month=12, day=31))
def _getQwebReportName(self):
return 'account_financial_report.report_journal_ledger_qweb'
self.receivable_account = self.AccountObj.search(
[("user_type_id.name", "=", "Receivable")], limit=1
)
self.income_account = self.AccountObj.search(
[("user_type_id.name", "=", "Income")], limit=1
)
self.expense_account = self.AccountObj.search(
[("user_type_id.name", "=", "Expenses")], limit=1
)
self.payable_account = self.AccountObj.search(
[("user_type_id.name", "=", "Payable")], limit=1
)
def _getXlsxReportName(self):
return 'a_f_r.report_journal_ledger_xlsx'
self.journal_sale = self.JournalObj.create(
{
"name": "Test journal sale",
"code": "TST-JRNL-S",
"type": "sale",
"company_id": self.company.id,
}
)
self.journal_purchase = self.JournalObj.create(
{
"name": "Test journal purchase",
"code": "TST-JRNL-P",
"type": "purchase",
"company_id": self.company.id,
}
)
def _getXlsxReportActionName(self):
return 'account_financial_report.' \
'action_report_journal_ledger_xlsx'
self.tax_15_s = self.TaxObj.create(
{
"sequence": 30,
"name": "Tax 15.0% (Percentage of Price)",
"amount": 15.0,
"amount_type": "percent",
"include_base_amount": False,
"type_tax_use": "sale",
}
)
def _getReportTitle(self):
return 'Odoo'
self.tax_20_s = self.TaxObj.create(
{
"sequence": 30,
"name": "Tax 20.0% (Percentage of Price)",
"amount": 20.0,
"amount_type": "percent",
"include_base_amount": False,
"type_tax_use": "sale",
def _getBaseFilters(self):
return {
'date_from': date(date.today().year, 1, 1),
'date_to': date(date.today().year, 12, 31),
'company_id': self.company.id,
'journal_ids': [(6, 0, self.journal_sale.ids)]
}
)
self.tax_15_p = self.TaxObj.create(
def _getAdditionalFiltersToBeTested(self):
return [
{'move_target': "All",
'sort_option': "Date",
'group_option': "Journal",
'with_account_name': True,
'foreign_currency': True},
]
def test_02_generation_report_html(self):
"""Check if report HTML is correctly generated"""
# Check if returned report action is correct
report_type = 'qweb-html'
report_action = self.report.print_report(report_type)
self.assertDictContainsSubset(
{
"sequence": 30,
"name": "Tax 15.0% (Percentage of Price)",
"amount": 15.0,
"amount_type": "percent",
"include_base_amount": False,
"type_tax_use": "purchase",
}
'type': 'ir.actions.report',
'report_name': self.qweb_report_name,
'report_type': 'qweb-html',
},
report_action
)
self.tax_20_p = self.TaxObj.create(
{
"sequence": 30,
"name": "Tax 20.0% (Percentage of Price)",
"amount": 20.0,
"amount_type": "percent",
"include_base_amount": False,
"type_tax_use": "purchase",
}
# Check if report template is correct
report = self.env['ir.actions.report'].search(
[('report_name', '=', self.qweb_report_name),
('report_type', '=', report_type)], limit=1)
self.assertEqual(report.report_type, 'qweb-html')
rep = report.render(self.report.ids, {})
self.assertTrue(self.report_title.encode('utf8') in rep[0])
self.assertTrue(
self.report.journal_ids[0].name.encode('utf8') in rep[0]
)
self.partner_2 = self.env.ref("base.res_partner_2")
def test_04_compute_data(self):
return True
class TestJournalReport(TransactionCase):
def setUp(self):
super(TestJournalReport, self).setUp()
self.AccountObj = self.env['account.account']
self.InvoiceObj = self.env['account.invoice']
self.JournalObj = self.env['account.journal']
self.JournalReportObj = self.env['journal.ledger.report.wizard']
self.MoveObj = self.env['account.move']
self.ReportJournalLedger = self.env['report_journal_ledger']
self.TaxObj = self.env['account.tax']
self.company = self.env.ref('base.main_company')
today = datetime.today()
last_year = today - relativedelta(years=1)
self.previous_fy_date_start = Date.to_string(
last_year.replace(month=1, day=1))
self.previous_fy_date_end = Date.to_string(
last_year.replace(month=12, day=31))
self.fy_date_start = Date.to_string(
today.replace(month=1, day=1))
self.fy_date_end = Date.to_string(
today.replace(month=12, day=31))
self.receivable_account = self.AccountObj.search([
('user_type_id.name', '=', 'Receivable')
], limit=1)
self.income_account = self.AccountObj.search([
('user_type_id.name', '=', 'Income')
], limit=1)
self.payable_account = self.AccountObj.search([
('user_type_id.name', '=', 'Payable')
], limit=1)
self.journal_sale = self.JournalObj.create({
'name': "Test journal sale",
'code': "TST-JRNL-S",
'type': 'sale',
'company_id': self.company.id,
})
self.journal_purchase = self.JournalObj.create({
'name': "Test journal purchase",
'code': "TST-JRNL-P",
'type': 'sale',
'company_id': self.company.id,
})
self.tax_15_s = self.TaxObj.create({
'sequence': 30,
'name': 'Tax 15.0% (Percentage of Price)',
'amount': 15.0,
'amount_type': 'percent',
'include_base_amount': False,
'type_tax_use': 'sale',
})
self.tax_20_s = self.TaxObj.create({
'sequence': 30,
'name': 'Tax 20.0% (Percentage of Price)',
'amount': 20.0,
'amount_type': 'percent',
'include_base_amount': False,
'type_tax_use': 'sale',
})
self.tax_15_p = self.TaxObj.create({
'sequence': 30,
'name': 'Tax 15.0% (Percentage of Price)',
'amount': 15.0,
'amount_type': 'percent',
'include_base_amount': False,
'type_tax_use': 'purchase',
})
self.tax_20_p = self.TaxObj.create({
'sequence': 30,
'name': 'Tax 20.0% (Percentage of Price)',
'amount': 20.0,
'amount_type': 'percent',
'include_base_amount': False,
'type_tax_use': 'purchase',
})
self.partner_2 = self.env.ref('base.res_partner_2')
def _add_move(
self,
date,
journal,
receivable_debit,
receivable_credit,
income_debit,
income_credit,
):
move_name = "move name"
self, date, journal,
receivable_debit, receivable_credit, income_debit, income_credit):
move_name = 'move name'
move_vals = {
"journal_id": journal.id,
"date": date,
"line_ids": [
(
0,
0,
{
"name": move_name,
"debit": receivable_debit,
"credit": receivable_credit,
"account_id": self.receivable_account.id,
},
),
(
0,
0,
{
"name": move_name,
"debit": income_debit,
"credit": income_credit,
"account_id": self.income_account.id,
},
),
],
'journal_id': journal.id,
'date': date,
'line_ids': [
(0, 0, {
'name': move_name,
'debit': receivable_debit,
'credit': receivable_credit,
'account_id': self.receivable_account.id
}),
(0, 0, {
'name': move_name,
'debit': income_debit,
'credit': income_credit,
'account_id': self.income_account.id
}),
]
}
return self.MoveObj.create(move_vals)
def check_report_journal_debit_credit(
self, res_data, expected_debit, expected_credit
):
self, report, expected_debit, expected_credit):
self.assertEqual(
expected_debit, sum([rec["debit"] for rec in res_data["Journal_Ledgers"]])
expected_debit,
sum([journal.debit for journal in
report.report_journal_ledger_ids])
)
self.assertEqual(
expected_credit, sum([rec["credit"] for rec in res_data["Journal_Ledgers"]])
expected_credit,
sum([journal.credit for journal in
report.report_journal_ledger_ids])
)
def check_report_journal_debit_credit_taxes(
self,
res_data,
expected_base_debit,
expected_base_credit,
expected_tax_debit,
expected_tax_credit,
):
for rec in res_data["Journal_Ledgers"]:
self, report,
expected_base_debit, expected_base_credit,
expected_tax_debit, expected_tax_credit):
self.assertEqual(
expected_base_debit,
sum([tax_line["base_debit"] for tax_line in rec["tax_lines"]]),
sum([
journal.base_debit
for journal in report.report_journal_ledger_tax_line_ids
])
)
self.assertEqual(
expected_base_credit,
sum([tax_line["base_credit"] for tax_line in rec["tax_lines"]]),
sum([
journal.base_credit
for journal in report.report_journal_ledger_tax_line_ids
])
)
self.assertEqual(
expected_tax_debit,
sum([tax_line["tax_debit"] for tax_line in rec["tax_lines"]]),
sum([
journal.tax_debit
for journal in report.report_journal_ledger_tax_line_ids
])
)
self.assertEqual(
expected_tax_credit,
sum([tax_line["tax_credit"] for tax_line in rec["tax_lines"]]),
sum([
journal.tax_credit
for journal in report.report_journal_ledger_tax_line_ids
])
)
def test_01_test_total(self):
today_date = Date.today()
last_year_date = Date.to_string(datetime.today() - relativedelta(years=1))
last_year_date = Date.to_string(
datetime.today() - relativedelta(years=1))
move1 = self._add_move(today_date, self.journal_sale, 0, 100, 100, 0)
move2 = self._add_move(last_year_date, self.journal_sale, 0, 100, 100, 0)
move1 = self._add_move(
today_date, self.journal_sale,
0, 100, 100, 0)
move2 = self._add_move(
last_year_date, self.journal_sale,
0, 100, 100, 0)
wiz = self.JournalLedgerReportWizard.create(
{
"date_from": self.fy_date_start,
"date_to": self.fy_date_end,
"company_id": self.company.id,
"journal_ids": [(6, 0, self.journal_sale.ids)],
"move_target": "all",
}
)
data = wiz._prepare_report_journal_ledger()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 100, 100)
report = self.ReportJournalLedger.create({
'date_from': self.fy_date_start,
'date_to': self.fy_date_end,
'company_id': self.company.id,
'journal_ids': [(6, 0, self.journal_sale.ids)]
})
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 100, 100)
move3 = self._add_move(today_date, self.journal_sale, 0, 100, 100, 0)
move3 = self._add_move(
today_date, self.journal_sale,
0, 100, 100, 0)
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 200, 200)
wiz.move_target = "posted"
data = wiz._prepare_report_journal_ledger()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 0, 0)
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 200, 200)
report.move_target = 'posted'
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 0, 0)
move1.post()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 100, 100)
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 100, 100)
move2.post()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 100, 100)
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 100, 100)
move3.post()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 200, 200)
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 200, 200)
wiz.date_from = self.previous_fy_date_start
data = wiz._prepare_report_journal_ledger()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 300, 300)
report.date_from = self.previous_fy_date_start
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 300, 300)
def test_02_test_taxes_out_invoice(self):
move_form = Form(
self.env["account.move"].with_context(default_type="out_invoice")
)
move_form.partner_id = self.partner_2
move_form.journal_id = self.journal_sale
with move_form.invoice_line_ids.new() as line_form:
line_form.name = "test"
line_form.quantity = 1.0
line_form.price_unit = 100
line_form.account_id = self.income_account
line_form.tax_ids.add(self.tax_15_s)
with move_form.invoice_line_ids.new() as line_form:
line_form.name = "test"
line_form.quantity = 1.0
line_form.price_unit = 100
line_form.account_id = self.income_account
line_form.tax_ids.add(self.tax_15_s)
line_form.tax_ids.add(self.tax_20_s)
invoice = move_form.save()
invoice.post()
wiz = self.JournalLedgerReportWizard.create(
{
"date_from": self.fy_date_start,
"date_to": self.fy_date_end,
"company_id": self.company.id,
"journal_ids": [(6, 0, self.journal_sale.ids)],
"move_target": "all",
invoice_values = {
'journal_id': self.journal_sale.id,
'partner_id': self.partner_2.id,
'type': 'out_invoice',
'invoice_line_ids': [
(0, 0, {
'quantity': 1.0,
'price_unit': 100,
'account_id': self.receivable_account.id,
'name': "Test",
'invoice_line_tax_ids': [(6, 0, [self.tax_15_s.id])],
}),
(0, 0, {
'quantity': 1.0,
'price_unit': 100,
'account_id': self.receivable_account.id,
'name': "Test",
'invoice_line_tax_ids': [(6, 0, [
self.tax_15_s.id, self.tax_20_s.id
])],
})
]
}
)
data = wiz._prepare_report_journal_ledger()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 250, 250)
self.check_report_journal_debit_credit_taxes(res_data, 0, 300, 0, 50)
invoice = self.InvoiceObj.create(invoice_values)
invoice.action_invoice_open()
report = self.ReportJournalLedger.create({
'date_from': self.fy_date_start,
'date_to': self.fy_date_end,
'company_id': self.company.id,
'journal_ids': [(6, 0, self.journal_sale.ids)]
})
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 250, 250)
self.check_report_journal_debit_credit_taxes(report, 0, 300, 0, 50)
def test_03_test_taxes_in_invoice(self):
# invoice_values = {
# "journal_id": self.journal_purchase.id,
# "partner_id": self.partner_2.id,
# "type": "in_invoice",
# "invoice_line_ids": [
# (
# 0,
# 0,
# {
# "quantity": 1.0,
# "price_unit": 100,
# "account_id": self.payable_account.id,
# "name": "Test",
# "tax_ids": [(6, 0, [self.tax_15_p.id])],
# },
# ),
# (
# 0,
# 0,
# {
# "quantity": 1.0,
# "price_unit": 100,
# "account_id": self.payable_account.id,
# "name": "Test",
# "tax_ids": [
# (6, 0, [self.tax_15_p.id, self.tax_20_p.id])
# ],
# },
# ),
# ],
# }
# invoice = self.InvoiceObj.create(invoice_values)
# invoice.post()
move_form = Form(
self.env["account.move"].with_context(default_type="in_invoice")
)
move_form.partner_id = self.partner_2
move_form.journal_id = self.journal_purchase
with move_form.invoice_line_ids.new() as line_form:
line_form.name = "test"
line_form.quantity = 1.0
line_form.price_unit = 100
line_form.account_id = self.expense_account
line_form.tax_ids.add(self.tax_15_p)
with move_form.invoice_line_ids.new() as line_form:
line_form.name = "test"
line_form.quantity = 1.0
line_form.price_unit = 100
line_form.account_id = self.expense_account
line_form.tax_ids.add(self.tax_15_p)
line_form.tax_ids.add(self.tax_20_p)
invoice = move_form.save()
invoice.post()
wiz = self.JournalLedgerReportWizard.create(
{
"date_from": self.fy_date_start,
"date_to": self.fy_date_end,
"company_id": self.company.id,
"journal_ids": [(6, 0, self.journal_purchase.ids)],
"move_target": "all",
invoice_values = {
'journal_id': self.journal_sale.id,
'partner_id': self.partner_2.id,
'type': 'in_invoice',
'invoice_line_ids': [
(0, 0, {
'quantity': 1.0,
'price_unit': 100,
'account_id': self.payable_account.id,
'name': "Test",
'invoice_line_tax_ids': [(6, 0, [self.tax_15_p.id])],
}),
(0, 0, {
'quantity': 1.0,
'price_unit': 100,
'account_id': self.payable_account.id,
'name': "Test",
'invoice_line_tax_ids': [(6, 0, [
self.tax_15_p.id, self.tax_20_p.id
])],
})
]
}
)
data = wiz._prepare_report_journal_ledger()
res_data = self.JournalLedgerReport._get_report_values(wiz, data)
self.check_report_journal_debit_credit(res_data, 250, 250)
self.check_report_journal_debit_credit_taxes(res_data, 300, 0, 50, 0)
invoice = self.InvoiceObj.create(invoice_values)
invoice.action_invoice_open()
report = self.ReportJournalLedger.create({
'date_from': self.fy_date_start,
'date_to': self.fy_date_end,
'company_id': self.company.id,
'journal_ids': [(6, 0, self.journal_sale.ids)]
})
report.compute_data_for_report()
self.check_report_journal_debit_credit(report, 250, 250)
self.check_report_journal_debit_credit_taxes(report, 300, 0, 50, 0)

57
account_financial_report/tests/test_open_items.py

@ -2,22 +2,59 @@
# Copyright 2016 Camptocamp SA
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from odoo.tests.common import TransactionCase
from datetime import date
from . import abstract_test_foreign_currency as a_t_f_c
class TestOpenItems(TransactionCase):
class TestOpenItems(a_t_f_c.AbstractTestForeignCurrency):
"""
Technical tests for Open Items Report.
"""
def _getReportModel(self):
return self.env['report_open_items']
def _getQwebReportName(self):
return 'account_financial_report.report_open_items_qweb'
def _getXlsxReportName(self):
return 'a_f_r.report_open_items_xlsx'
def _getXlsxReportActionName(self):
return 'account_financial_report.action_report_open_items_xlsx'
def _getReportTitle(self):
return 'Odoo'
def _getBaseFilters(self):
return {
'date_at': date(date.today().year, 12, 31),
'company_id': self.company.id,
'foreign_currency': True,
}
def _getAdditionalFiltersToBeTested(self):
return [
{'only_posted_moves': True},
{'hide_account_at_0': True},
{'only_posted_moves': True, 'hide_account_at_0': True},
]
def test_partner_filter(self):
partner_1 = self.env.ref("base.res_partner_1")
partner_2 = self.env.ref("base.res_partner_2")
partner_3 = self.env.ref("base.res_partner_3")
partner_4 = self.env.ref("base.res_partner_4")
partner_1.write({"is_company": False, "parent_id": partner_2.id})
partner_3.write({"is_company": False})
partner_1 = self.env.ref('base.res_partner_1')
partner_2 = self.env.ref('base.res_partner_2')
partner_3 = self.env.ref('base.res_partner_3')
partner_4 = self.env.ref('base.res_partner_4')
partner_1.write({'is_company': False,
'parent_id': partner_2.id})
partner_3.write({'is_company': False})
expected_list = [partner_2.id, partner_3.id, partner_4.id]
context = {
"active_ids": [partner_1.id, partner_2.id, partner_3.id, partner_4.id],
"active_model": "res.partner",
'active_ids': [
partner_1.id, partner_2.id, partner_3.id, partner_4.id
],
'active_model': 'res.partner'
}
wizard = self.env["open.items.report.wizard"].with_context(context)

1116
account_financial_report/tests/test_trial_balance.py
File diff suppressed because it is too large
View File

594
account_financial_report/tests/test_vat_report.py

@ -1,368 +1,300 @@
# Copyright 2018 Forest and Biomass Romania
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import time
from datetime import date
from odoo.tests import common
from . import abstract_test_tax_report
class TestVAT(abstract_test_tax_report.AbstractTest):
"""
Technical tests for VAT Report.
"""
def _getReportModel(self):
return self.env['report_vat_report']
def _getQwebReportName(self):
return 'account_financial_report.report_vat_report_qweb'
def _getXlsxReportName(self):
return 'a_f_r.report_vat_report_xlsx'
def _getXlsxReportActionName(self):
return 'account_financial_report.action_report_vat_report_xlsx'
def _getReportTitle(self):
return 'Odoo'
def _getBaseFilters(self):
return {
'date_from': date(date.today().year, 1, 1),
'date_to': date(date.today().year, 12, 31),
'company_id': self.env.user.company_id.id,
}
def _getAdditionalFiltersToBeTested(self):
return [
{'based_on': 'taxtags'},
{'based_on': 'taxgroups'},
{'tax_details': True},
{'based_on': 'taxtags', 'tax_details': True},
{'based_on': 'taxgroups', 'tax_details': True},
]
class TestVATReport(common.TransactionCase):
def setUp(self):
super(TestVATReport, self).setUp()
self.date_from = time.strftime("%Y-%m-01")
self.date_to = time.strftime("%Y-%m-28")
self.company = self.env.ref("base.main_company")
self.receivable_account = self.env["account.account"].search(
[
("company_id", "=", self.company.id),
("user_type_id.name", "=", "Receivable"),
],
limit=1,
)
self.income_account = self.env["account.account"].search(
[
("company_id", "=", self.company.id),
("user_type_id.name", "=", "Income"),
],
limit=1,
)
self.tax_account = self.env["account.account"].search(
[
("company_id", "=", self.company.id),
(
"user_type_id",
"=",
self.date_from = time.strftime('%Y-%m-01')
self.date_to = time.strftime('%Y-%m-28')
self.company = self.env.ref('base.main_company')
self.receivable_account = self.env['account.account'].search([
('company_id', '=', self.company.id),
('user_type_id.name', '=', 'Receivable')
], limit=1)
self.income_account = self.env['account.account'].search([
('company_id', '=', self.company.id),
('user_type_id.name', '=', 'Income')
], limit=1)
self.tax_account = self.env['account.account'].search([
('company_id', '=', self.company.id),
('user_type_id',
'=',
self.env.ref(
"account.data_account_type_non_current_liabilities"
).id,
),
],
limit=1,
)
self.bank_journal = self.env["account.journal"].search(
[("type", "=", "bank"), ("company_id", "=", self.company.id)], limit=1
)
self.tax_tag_01 = self.env["account.account.tag"].create(
{
"name": "Tag 01",
"applicability": "taxes",
"country_id": self.company.country_id.id,
}
)
self.tax_tag_02 = self.env["account.account.tag"].create(
{
"name": "Tag 02",
"applicability": "taxes",
"country_id": self.company.country_id.id,
}
)
self.tax_tag_03 = self.env["account.account.tag"].create(
{
"name": "Tag 03",
"applicability": "taxes",
"country_id": self.company.country_id.id,
}
)
self.tax_group_10 = self.env["account.tax.group"].create(
{"name": "Tax 10%", "sequence": 1}
)
self.tax_group_20 = self.env["account.tax.group"].create(
{"name": "Tax 20%", "sequence": 2}
)
self.tax_10 = self.env["account.tax"].create(
{
"name": "Tax 10.0%",
"amount": 10.0,
"amount_type": "percent",
"type_tax_use": "sale",
"company_id": self.company.id,
"tax_group_id": self.tax_group_10.id,
"invoice_repartition_line_ids": [
(0, 0, {"factor_percent": 100, "repartition_type": "base"}),
(
0,
0,
{
"factor_percent": 100,
"repartition_type": "tax",
"account_id": self.tax_account.id,
"tag_ids": [
(6, 0, [self.tax_tag_01.id, self.tax_tag_02.id])
],
},
),
],
"refund_repartition_line_ids": [
(0, 0, {"factor_percent": 100, "repartition_type": "base"}),
(
0,
0,
{
"factor_percent": 100,
"repartition_type": "tax",
"account_id": self.tax_account.id,
},
),
],
}
)
self.tax_20 = self.env["account.tax"].create(
{
"sequence": 30,
"name": "Tax 20.0%",
"amount": 20.0,
"amount_type": "percent",
"type_tax_use": "sale",
"company_id": self.company.id,
"cash_basis_transition_account_id": self.tax_account.id,
"tax_group_id": self.tax_group_20.id,
"invoice_repartition_line_ids": [
(0, 0, {"factor_percent": 100, "repartition_type": "base"}),
(
0,
0,
{
"factor_percent": 100,
"repartition_type": "tax",
"account_id": self.tax_account.id,
"tag_ids": [
(6, 0, [self.tax_tag_02.id, self.tax_tag_03.id])
],
},
),
],
"refund_repartition_line_ids": [
(0, 0, {"factor_percent": 100, "repartition_type": "base"}),
(
0,
0,
{
"factor_percent": 100,
"repartition_type": "tax",
"account_id": self.tax_account.id,
},
),
],
}
)
'account.data_account_type_non_current_liabilities').id)
], limit=1)
self.bank_journal = self.env['account.journal'].search([
('type', '=', 'bank'), ('company_id', '=', self.company.id)
], limit=1)
self.tax_tag_01 = self.env['account.account.tag'].create({
'name': 'Tag 01',
'applicability': 'taxes'
})
self.tax_tag_02 = self.env['account.account.tag'].create({
'name': 'Tag 02',
'applicability': 'taxes'
})
self.tax_tag_03 = self.env['account.account.tag'].create({
'name': 'Tag 03',
'applicability': 'taxes'
})
self.tax_group_10 = self.env['account.tax.group'].create({
'name': 'Tax 10%',
'sequence': 1
})
self.tax_group_20 = self.env['account.tax.group'].create({
'name': 'Tax 20%',
'sequence': 2
})
self.tax_10 = self.env['account.tax'].create({
'name': 'Tax 10.0%',
'amount': 10.0,
'amount_type': 'percent',
'type_tax_use': 'sale',
'account_id': self.tax_account.id,
'company_id': self.company.id,
'refund_account_id': self.tax_account.id,
'tax_group_id': self.tax_group_10.id,
'tag_ids': [(6, 0, [self.tax_tag_01.id, self.tax_tag_02.id])]
})
self.tax_20 = self.env['account.tax'].create({
'sequence': 30,
'name': 'Tax 20.0%',
'amount': 20.0,
'amount_type': 'percent',
'type_tax_use': 'sale',
'tax_exigibility': 'on_payment',
'account_id': self.tax_account.id,
'company_id': self.company.id,
'refund_account_id': self.tax_account.id,
'cash_basis_account_id': self.tax_account.id,
'tax_group_id': self.tax_group_20.id,
'tag_ids': [(6, 0, [self.tax_tag_02.id, self.tax_tag_03.id])]
})
move_form = common.Form(
self.env["account.move"].with_context(default_type="out_invoice")
)
move_form.partner_id = self.env.ref("base.res_partner_2")
move_form.invoice_date = time.strftime("%Y-%m-03")
with move_form.invoice_line_ids.new() as line_form:
line_form.product_id = self.env.ref("product.product_product_4")
line_form.quantity = 1.0
line_form.price_unit = 100.0
line_form.account_id = self.income_account
line_form.tax_ids.add(self.tax_10)
invoice = move_form.save()
invoice.post()
invoice = self.env['account.invoice'].create({
'partner_id': self.env.ref('base.res_partner_2').id,
'account_id': self.receivable_account.id,
'company_id': self.company.id,
'date_invoice': time.strftime('%Y-%m-03'),
'type': 'out_invoice',
})
move_form = common.Form(
self.env["account.move"].with_context(default_type="out_invoice")
)
move_form.partner_id = self.env.ref("base.res_partner_2")
move_form.invoice_date = time.strftime("%Y-%m-04")
with move_form.invoice_line_ids.new() as line_form:
line_form.product_id = self.env.ref("product.product_product_4")
line_form.quantity = 1.0
line_form.price_unit = 250.0
line_form.account_id = self.income_account
line_form.tax_ids.add(self.tax_20)
invoice = move_form.save()
invoice.post()
self.env['account.invoice.line'].create({
'product_id': self.env.ref('product.product_product_4').id,
'quantity': 1.0,
'price_unit': 100.0,
'invoice_id': invoice.id,
'name': 'product',
'account_id': self.income_account.id,
'invoice_line_tax_ids': [(6, 0, [self.tax_10.id])],
})
invoice.compute_taxes()
invoice.action_invoice_open()
def _get_report_lines(self, taxgroups=False):
based_on = "taxtags"
if taxgroups:
based_on = "taxgroups"
vat_report = self.env["vat.report.wizard"].create(
{
"date_from": self.date_from,
"date_to": self.date_to,
"company_id": self.company.id,
"based_on": based_on,
"tax_detail": True,
}
)
data = vat_report._prepare_vat_report()
res_data = self.env[
"report.account_financial_report.vat_report"
]._get_report_values(vat_report, data)
return res_data
self.cbinvoice = self.env['account.invoice'].create({
'partner_id': self.env.ref('base.res_partner_2').id,
'account_id': self.receivable_account.id,
'company_id': self.company.id,
'date_invoice': time.strftime('%Y-%m-05'),
'type': 'out_invoice',
})
def check_tag_or_group_in_report(self, tag_or_group_name, vat_report):
tag_or_group_in_report = False
for tag_or_group in vat_report:
if tag_or_group["name"] == tag_or_group_name:
tag_or_group_in_report = True
break
return tag_or_group_in_report
self.env['account.invoice.line'].create({
'product_id': self.env.ref('product.product_product_4').id,
'quantity': 1.0,
'price_unit': 500.0,
'invoice_id': self.cbinvoice.id,
'name': 'product',
'account_id': self.income_account.id,
'invoice_line_tax_ids': [(6, 0, [self.tax_20.id])],
})
self.cbinvoice.compute_taxes()
self.cbinvoice.action_invoice_open()
def check_tax_in_report(self, tax_name, vat_report):
tax_in_report = False
for tag_or_group in vat_report:
if tag_or_group["taxes"]:
for tax in tag_or_group["taxes"]:
if tax["name"] == tax_name:
tax_in_report = True
return tax_in_report
def _get_tag_or_group_line(self, tag_or_group_name, vat_report):
tag_or_group_net = False
tag_or_group_tax = False
for tag_or_group in vat_report:
if tag_or_group["name"] == tag_or_group_name:
tag_or_group_net = tag_or_group["net"]
tag_or_group_tax = tag_or_group["tax"]
return tag_or_group_net, tag_or_group_tax
def _get_tax_line(self, tax_name, vat_report):
tax_net = False
tax_tax = False
for tag_or_group in vat_report:
if tag_or_group["taxes"]:
for tax in tag_or_group["taxes"]:
if tax["name"] == tax_name:
tax_net = tax["net"]
tax_tax = tax["tax"]
return tax_net, tax_tax
def _get_report_lines(self):
self.cbinvoice.pay_and_reconcile(
self.bank_journal.id, 300, date(
date.today().year, date.today().month, 10))
vat_report = self.env['report_vat_report'].create({
'date_from': self.date_from,
'date_to': self.date_to,
'company_id': self.company.id,
'based_on': 'taxtags',
'tax_detail': True,
})
vat_report.compute_data_for_report()
lines = {}
vat_taxtag_model = self.env['report_vat_report_taxtag']
lines['tag_01'] = vat_taxtag_model.search([
('report_id', '=', vat_report.id),
('taxtag_id', '=', self.tax_tag_01.id),
])
lines['tag_02'] = vat_taxtag_model.search([
('report_id', '=', vat_report.id),
('taxtag_id', '=', self.tax_tag_02.id),
])
lines['tag_03'] = vat_taxtag_model.search([
('report_id', '=', vat_report.id),
('taxtag_id', '=', self.tax_tag_03.id),
])
vat_tax_model = self.env['report_vat_report_tax']
lines['tax_10'] = vat_tax_model.search([
('report_tax_id', '=', lines['tag_02'].id),
('tax_id', '=', self.tax_10.id),
])
lines['tax_20'] = vat_tax_model.search([
('report_tax_id', '=', lines['tag_02'].id),
('tax_id', '=', self.tax_20.id),
])
vat_report['based_on'] = 'taxgroups'
vat_report.compute_data_for_report()
lines['group_10'] = vat_taxtag_model.search([
('report_id', '=', vat_report.id),
('taxgroup_id', '=', self.tax_group_10.id),
])
lines['group_20'] = vat_taxtag_model.search([
('report_id', '=', vat_report.id),
('taxgroup_id', '=', self.tax_group_20.id),
])
vat_tax_model = self.env['report_vat_report_tax']
lines['tax_group_10'] = vat_tax_model.search([
('report_tax_id', '=', lines['group_10'].id),
('tax_id', '=', self.tax_10.id),
])
lines['tax_group_20'] = vat_tax_model.search([
('report_tax_id', '=', lines['group_20'].id),
('tax_id', '=', self.tax_20.id),
])
return lines
def test_01_compute(self):
# Generate the vat lines
res_data = self._get_report_lines()
vat_report = res_data["vat_report"]
lines = self._get_report_lines()
# Check report based on taxtags
check_tax_tag_01 = self.check_tag_or_group_in_report(
self.tax_tag_01.name, vat_report
)
self.assertTrue(check_tax_tag_01)
check_tax_tag_02 = self.check_tag_or_group_in_report(
self.tax_tag_02.name, vat_report
)
self.assertTrue(check_tax_tag_02)
check_tax_tag_03 = self.check_tag_or_group_in_report(
self.tax_tag_03.name, vat_report
)
self.assertTrue(check_tax_tag_03)
check_tax_10 = self.check_tax_in_report(self.tax_10.name, vat_report)
self.assertTrue(check_tax_10)
check_tax_20 = self.check_tax_in_report(self.tax_20.name, vat_report)
self.assertTrue(check_tax_20)
tag_01_net, tag_01_tax = self._get_tag_or_group_line(
self.tax_tag_01.name, vat_report
)
tag_02_net, tag_02_tax = self._get_tag_or_group_line(
self.tax_tag_02.name, vat_report
)
tag_03_net, tag_03_tax = self._get_tag_or_group_line(
self.tax_tag_03.name, vat_report
)
tax_10_net, tax_10_tax = self._get_tax_line(self.tax_10.name, vat_report)
tax_20_net, tax_20_tax = self._get_tax_line(self.tax_20.name, vat_report)
self.assertEqual(tag_01_net, -100)
self.assertEqual(tag_01_tax, -10)
self.assertEqual(tag_02_net, -350)
self.assertEqual(tag_02_tax, -60)
self.assertEqual(tag_03_net, -250)
self.assertEqual(tag_03_tax, -50)
self.assertEqual(tax_10_net, -100)
self.assertEqual(tax_10_tax, -10)
self.assertEqual(tax_20_net, -250)
self.assertEqual(tax_20_tax, -50)
self.assertEqual(len(lines['tag_01']), 1)
self.assertEqual(len(lines['tag_02']), 1)
self.assertEqual(len(lines['tag_03']), 1)
self.assertEqual(len(lines['tax_10']), 1)
self.assertEqual(len(lines['tax_20']), 1)
self.assertEqual(lines['tag_01'].net, 100)
self.assertEqual(lines['tag_01'].tax, 10)
self.assertEqual(lines['tag_02'].net, 350)
self.assertEqual(lines['tag_02'].tax, 60)
self.assertEqual(lines['tag_03'].net, 250)
self.assertEqual(lines['tag_03'].tax, 50)
self.assertEqual(lines['tax_10'].net, 100)
self.assertEqual(lines['tax_10'].tax, 10)
self.assertEqual(lines['tax_20'].net, 250)
self.assertEqual(lines['tax_20'].tax, 50)
# Check report based on taxgroups
res_data = self._get_report_lines(taxgroups=True)
vat_report = res_data["vat_report"]
check_group_10 = self.check_tag_or_group_in_report(
self.tax_group_10.name, vat_report
)
self.assertTrue(check_group_10)
check_group_20 = self.check_tag_or_group_in_report(
self.tax_group_20.name, vat_report
)
self.assertTrue(check_group_20)
check_tax_10 = self.check_tax_in_report(self.tax_10.name, vat_report)
self.assertTrue(check_tax_10)
check_tax_20 = self.check_tax_in_report(self.tax_20.name, vat_report)
self.assertTrue(check_tax_20)
group_10_net, group_10_tax = self._get_tag_or_group_line(
self.tax_group_10.name, vat_report
)
group_20_net, group_20_tax = self._get_tag_or_group_line(
self.tax_group_20.name, vat_report
)
tax_10_net, tax_10_tax = self._get_tax_line(self.tax_10.name, vat_report)
tax_20_net, tax_20_tax = self._get_tax_line(self.tax_20.name, vat_report)
self.assertEqual(len(lines['group_10']), 1)
self.assertEqual(len(lines['group_20']), 1)
self.assertEqual(len(lines['tax_group_10']), 1)
self.assertEqual(len(lines['tax_group_20']), 1)
self.assertEqual(lines['group_10'].net, 100)
self.assertEqual(lines['group_10'].tax, 10)
self.assertEqual(lines['group_20'].net, 250)
self.assertEqual(lines['group_20'].tax, 50)
self.assertEqual(lines['tax_group_10'].net, 100)
self.assertEqual(lines['tax_group_10'].tax, 10)
self.assertEqual(lines['tax_group_20'].net, 250)
self.assertEqual(lines['tax_group_20'].tax, 50)
self.assertEqual(group_10_net, -100)
self.assertEqual(group_10_tax, -10)
self.assertEqual(group_20_net, -250)
self.assertEqual(group_20_tax, -50)
self.assertEqual(tax_10_net, -100)
self.assertEqual(tax_10_tax, -10)
self.assertEqual(tax_20_net, -250)
self.assertEqual(tax_20_tax, -50)
def test_get_report_html(self):
vat_report = self.env['report_vat_report'].create({
'date_from': self.date_from,
'date_to': self.date_to,
'company_id': self.company.id,
'tax_detail': True,
})
vat_report.compute_data_for_report()
vat_report.get_html(given_context={})
def test_wizard_date_range(self):
vat_wizard = self.env["vat.report.wizard"]
date_range = self.env["date.range"]
self.type = self.env["date.range.type"].create(
{"name": "Month", "company_id": False, "allow_overlap": False}
)
dt = date_range.create(
{
"name": "FS2016",
"date_start": time.strftime("%Y-%m-01"),
"date_end": time.strftime("%Y-%m-28"),
"type_id": self.type.id,
}
)
vat_wizard = self.env['vat.report.wizard']
date_range = self.env['date.range']
self.type = self.env['date.range.type'].create(
{'name': 'Month',
'company_id': False,
'allow_overlap': False})
dt = date_range.create({
'name': 'FS2016',
'date_start': time.strftime('%Y-%m-01'),
'date_end': time.strftime('%Y-%m-28'),
'type_id': self.type.id,
})
wizard = vat_wizard.create(
{
"date_range_id": dt.id,
"date_from": time.strftime("%Y-%m-28"),
"date_to": time.strftime("%Y-%m-01"),
"tax_detail": True,
}
)
{'date_range_id': dt.id,
'date_from': time.strftime('%Y-%m-28'),
'date_to': time.strftime('%Y-%m-01'),
'tax_detail': True})
wizard.onchange_date_range_id()
self.assertEqual(
wizard.date_from, date(date.today().year, date.today().month, 1)
)
self.assertEqual(
wizard.date_to, date(date.today().year, date.today().month, 28)
)
wizard._export("qweb-pdf")
self.assertEqual(wizard.date_from, date(
date.today().year, date.today().month, 1))
self.assertEqual(wizard.date_to, date(
date.today().year, date.today().month, 28))
wizard._export('qweb-pdf')
wizard.button_export_html()
wizard.button_export_pdf()
wizard.button_export_xlsx()
wizard = vat_wizard.create(
{
"date_range_id": dt.id,
"date_from": time.strftime("%Y-%m-28"),
"date_to": time.strftime("%Y-%m-01"),
"based_on": "taxgroups",
"tax_detail": True,
}
)
{'date_range_id': dt.id,
'date_from': time.strftime('%Y-%m-28'),
'date_to': time.strftime('%Y-%m-01'),
'based_on': 'taxgroups',
'tax_detail': True})
wizard.onchange_date_range_id()
self.assertEqual(
wizard.date_from, date(date.today().year, date.today().month, 1)
)
self.assertEqual(
wizard.date_to, date(date.today().year, date.today().month, 28)
)
wizard._export("qweb-pdf")
self.assertEqual(wizard.date_from, date(
date.today().year, date.today().month, 1))
self.assertEqual(wizard.date_to, date(
date.today().year, date.today().month, 28))
wizard._export('qweb-pdf')
wizard.button_export_html()
wizard.button_export_pdf()
wizard.button_export_xlsx()

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

Loading…
Cancel
Save