Compare commits
merge into: OCA:13.0
OCA:10.0
OCA:11.0
OCA:12.0
OCA:12.0-mis_builder_analytic_cash_flow
OCA:13.0
OCA:13.0-ocabot-merge-pr-804-by-JordiBForgeFlow-bump-patch
OCA:14.0
OCA:6.0
OCA:6.1
OCA:7.0
OCA:8.0
OCA:9.0
pull from: OCA:11.0
OCA:10.0
OCA:11.0
OCA:12.0
OCA:12.0-mis_builder_analytic_cash_flow
OCA:13.0
OCA:13.0-ocabot-merge-pr-804-by-JordiBForgeFlow-bump-patch
OCA:14.0
OCA:6.0
OCA:6.1
OCA:7.0
OCA:8.0
OCA:9.0
No commits in common. '13.0' and '11.0' have entirely different histories.
284 changed files with 44096 additions and 44306 deletions
-
4.editorconfig
-
180.eslintrc.yml
-
10.flake8
-
12.isort.cfg
-
103.pre-commit-config.yaml
-
8.prettierrc.yml
-
88.pylintrc
-
66.pylintrc-mandatory
-
50.travis.yml
-
2LICENSE
-
13README.md
-
44account_financial_report/README.rst
-
1account_financial_report/__init__.py
-
83account_financial_report/__manifest__.py
-
2339account_financial_report/i18n/account_financial_report.pot
-
2462account_financial_report/i18n/ar.po
-
2396account_financial_report/i18n/ca.po
-
2565account_financial_report/i18n/de.po
-
2495account_financial_report/i18n/es.po
-
1873account_financial_report/i18n/es_AR.po
-
2811account_financial_report/i18n/fr.po
-
2100account_financial_report/i18n/fr_CH.po
-
1799account_financial_report/i18n/hr.po
-
2307account_financial_report/i18n/hr_HR.po
-
2728account_financial_report/i18n/it.po
-
1813account_financial_report/i18n/ja.po
-
2598account_financial_report/i18n/nl.po
-
2291account_financial_report/i18n/nl_NL.po
-
2307account_financial_report/i18n/pt.po
-
2664account_financial_report/i18n/pt_BR.po
-
2634account_financial_report/i18n/ro.po
-
2572account_financial_report/i18n/sl.po
-
72account_financial_report/menuitems.xml
-
1account_financial_report/models/__init__.py
-
11account_financial_report/models/account.py
-
63account_financial_report/models/account_group.py
-
24account_financial_report/models/account_move_line.py
-
25account_financial_report/models/ir_actions_report.py
-
16account_financial_report/readme/CONTRIBUTORS.rst
-
5account_financial_report/readme/DESCRIPTION.rst
-
7account_financial_report/readme/ROADMAP.rst
-
137account_financial_report/report/abstract_report.py
-
467account_financial_report/report/abstract_report_xlsx.py
-
973account_financial_report/report/aged_partner_balance.py
-
386account_financial_report/report/aged_partner_balance_xlsx.py
-
2546account_financial_report/report/general_ledger.py
-
358account_financial_report/report/general_ledger_xlsx.py
-
1167account_financial_report/report/journal_ledger.py
-
302account_financial_report/report/journal_ledger_xlsx.py
-
1151account_financial_report/report/open_items.py
-
242account_financial_report/report/open_items_xlsx.py
-
603account_financial_report/report/templates/aged_partner_balance.xml
-
754account_financial_report/report/templates/general_ledger.xml
-
627account_financial_report/report/templates/journal_ledger.xml
-
32account_financial_report/report/templates/layouts.xml
-
438account_financial_report/report/templates/open_items.xml
-
1199account_financial_report/report/templates/trial_balance.xml
-
194account_financial_report/report/templates/vat_report.xml
-
1296account_financial_report/report/trial_balance.py
-
353account_financial_report/report/trial_balance_xlsx.py
-
569account_financial_report/report/vat_report.py
-
60account_financial_report/report/vat_report_xlsx.py
-
236account_financial_report/reports.xml
-
77account_financial_report/static/description/index.html
-
74account_financial_report/static/src/css/report.css
-
111account_financial_report/static/src/js/account_financial_report_backend.js
-
85account_financial_report/static/src/js/account_financial_report_widgets.js
-
35account_financial_report/static/src/js/action_manager_report.js
-
51account_financial_report/static/src/js/client_action.js
-
58account_financial_report/static/src/js/report.js
-
17account_financial_report/static/src/xml/report.xml
-
5account_financial_report/tests/__init__.py
-
408account_financial_report/tests/abstract_test.py
-
78account_financial_report/tests/abstract_test_foreign_currency.py
-
75account_financial_report/tests/abstract_test_tax_report.py
-
41account_financial_report/tests/test_aged_partner_balance.py
-
853account_financial_report/tests/test_general_ledger.py
-
600account_financial_report/tests/test_journal_ledger.py
-
59account_financial_report/tests/test_open_items.py
-
1129account_financial_report/tests/test_trial_balance.py
-
591account_financial_report/tests/test_vat_report.py
-
6account_financial_report/view/account_view.xml
-
6account_financial_report/view/report_aged_partner_balance.xml
-
6account_financial_report/view/report_general_ledger.xml
-
6account_financial_report/view/report_journal_ledger.xml
-
6account_financial_report/view/report_open_items.xml
-
76account_financial_report/view/report_template.xml
-
8account_financial_report/view/report_trial_balance.xml
-
6account_financial_report/view/report_vat_report.xml
-
1account_financial_report/wizard/__init__.py
-
52account_financial_report/wizard/abstract_wizard.py
-
174account_financial_report/wizard/aged_partner_balance_wizard.py
-
102account_financial_report/wizard/aged_partner_balance_wizard_view.xml
-
376account_financial_report/wizard/general_ledger_wizard.py
-
191account_financial_report/wizard/general_ledger_wizard_view.xml
-
197account_financial_report/wizard/journal_ledger_wizard.py
-
82account_financial_report/wizard/journal_ledger_wizard_view.xml
-
213account_financial_report/wizard/open_items_wizard.py
-
123account_financial_report/wizard/open_items_wizard_view.xml
-
325account_financial_report/wizard/trial_balance_wizard.py
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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 |
|
@ -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" |
|
@ -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 |
|
@ -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 |
|
@ -1,14 +1,17 @@ |
|||||
[![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/11.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=11.0)](https://travis-ci.org/OCA/account-financial-reporting) |
||||
|
[![Coverage Status](https://coveralls.io/repos/OCA/account-financial-reporting/badge.png?branch=11.0)](https://coveralls.io/r/OCA/account-financial-reporting?branch=11.0) |
||||
|
|
||||
Odoo account financial reports |
Odoo account financial reports |
||||
============================== |
============================== |
||||
|
|
||||
This project aims to deal with modules related to financial reports. You'll |
|
||||
find modules that print legal and official reports. This includes, among |
|
||||
|
This project aims to deal with modules related to financial reports. You'll |
||||
|
find modules that print legal and official reports. This includes, among |
||||
others: |
others: |
||||
|
|
||||
* One module based on webkit and totally rewritten by camptocamp, for standard |
* One module based on webkit and totally rewritten by camptocamp, for standard |
||||
financial reports. |
financial reports. |
||||
* Another based on RML completely improved by Vauxoo. |
* Another based on RML completely improved by Vauxoo. |
||||
|
|
||||
|
|
||||
|
|
@ -1,48 +1,51 @@ |
|||||
# Author: Damien Crier |
# Author: Damien Crier |
||||
# Author: Julien Coux |
# Author: Julien Coux |
||||
# Copyright 2016 Camptocamp SA |
# 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). |
# 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': '11.0.2.6.0', |
||||
|
'category': 'Reporting', |
||||
|
'summary': 'OCA Financial Reports', |
||||
|
'author': 'Camptocamp SA,' |
||||
|
'initOS GmbH,' |
||||
|
'redCOR AG,' |
||||
|
'Eficent,' |
||||
|
'Odoo Community Association (OCA)', |
||||
"website": "https://odoo-community.org/", |
"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', |
||||
|
'account_invoicing', |
||||
|
'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', |
||||
} |
} |
2339
account_financial_report/i18n/account_financial_report.pot
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2462
account_financial_report/i18n/ar.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2396
account_financial_report/i18n/ca.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2565
account_financial_report/i18n/de.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2495
account_financial_report/i18n/es.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1873
account_financial_report/i18n/es_AR.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2811
account_financial_report/i18n/fr.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2100
account_financial_report/i18n/fr_CH.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1799
account_financial_report/i18n/hr.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2307
account_financial_report/i18n/hr_HR.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2728
account_financial_report/i18n/it.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1813
account_financial_report/i18n/ja.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2598
account_financial_report/i18n/nl.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2291
account_financial_report/i18n/nl_NL.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2307
account_financial_report/i18n/pt.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2664
account_financial_report/i18n/pt_BR.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2634
account_financial_report/i18n/ro.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2572
account_financial_report/i18n/sl.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,45 +1,101 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
|
|
||||
<menuitem |
<menuitem |
||||
parent="account.menu_finance_reports" |
parent="account.menu_finance_reports" |
||||
id="menu_oca_reports" |
id="menu_oca_reports" |
||||
name="OCA accounting reports" |
name="OCA accounting reports" |
||||
groups="account.group_account_manager,account.group_account_user" |
groups="account.group_account_manager,account.group_account_user" |
||||
/> |
|
||||
|
/> |
||||
|
|
||||
<menuitem |
<menuitem |
||||
parent="menu_oca_reports" |
parent="menu_oca_reports" |
||||
action="action_general_ledger_wizard" |
action="action_general_ledger_wizard" |
||||
id="menu_general_ledger_wizard" |
id="menu_general_ledger_wizard" |
||||
sequence="10" |
sequence="10" |
||||
/> |
|
||||
|
/> |
||||
|
|
||||
<menuitem |
<menuitem |
||||
parent="menu_oca_reports" |
parent="menu_oca_reports" |
||||
action="action_journal_ledger_wizard" |
action="action_journal_ledger_wizard" |
||||
id="menu_journal_ledger_wizard" |
id="menu_journal_ledger_wizard" |
||||
sequence="15" |
sequence="15" |
||||
/> |
|
||||
|
/> |
||||
|
|
||||
<menuitem |
<menuitem |
||||
parent="menu_oca_reports" |
parent="menu_oca_reports" |
||||
action="action_trial_balance_wizard" |
action="action_trial_balance_wizard" |
||||
id="menu_trial_balance_wizard" |
id="menu_trial_balance_wizard" |
||||
sequence="20" |
sequence="20" |
||||
/> |
|
||||
|
/> |
||||
|
|
||||
<menuitem |
<menuitem |
||||
parent="menu_oca_reports" |
parent="menu_oca_reports" |
||||
action="action_open_items_wizard" |
action="action_open_items_wizard" |
||||
id="menu_open_items_wizard" |
id="menu_open_items_wizard" |
||||
sequence="30" |
sequence="30" |
||||
/> |
|
||||
|
/> |
||||
|
|
||||
<menuitem |
<menuitem |
||||
parent="menu_oca_reports" |
parent="menu_oca_reports" |
||||
action="action_aged_partner_balance_wizard" |
action="action_aged_partner_balance_wizard" |
||||
id="menu_aged_partner_balance_wizard" |
id="menu_aged_partner_balance_wizard" |
||||
sequence="40" |
sequence="40" |
||||
/> |
|
||||
|
/> |
||||
|
|
||||
<menuitem |
<menuitem |
||||
parent="menu_oca_reports" |
parent="menu_oca_reports" |
||||
action="action_vat_report_wizard" |
action="action_vat_report_wizard" |
||||
id="menu_vat_report_wizard" |
id="menu_vat_report_wizard" |
||||
sequence="50" |
sequence="50" |
||||
/> |
|
||||
|
/> |
||||
|
|
||||
|
<!-- Hide odoo PDF reports menu --> |
||||
|
<menuitem |
||||
|
id="account.menu_finance_legal_statement" |
||||
|
name="PDF Reports" |
||||
|
parent="account.menu_finance_reports" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_general_ledger" |
||||
|
name="General Ledger" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
action="account.action_account_general_ledger_menu" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_general_Balance_report" |
||||
|
name="Trial Balance" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
action="account.action_account_balance_menu" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_account_report_bs" |
||||
|
name="Balance Sheet" |
||||
|
action="account.action_account_report_bs" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_account_report_pl" |
||||
|
name="Profit and Loss" |
||||
|
action="account.action_account_report_pl" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
|
<menuitem |
||||
|
id="account.menu_aged_trial_balance" |
||||
|
name="Aged Partner Balance" |
||||
|
action="account.action_account_aged_balance_view" |
||||
|
parent="account.menu_finance_legal_statement" |
||||
|
groups="base.group_erp_manager" |
||||
|
/> |
||||
|
|
||||
</odoo> |
</odoo> |
@ -1,4 +1,3 @@ |
|||||
from . import account |
from . import account |
||||
from . import account_group |
from . import account_group |
||||
from . import account_move_line |
from . import account_move_line |
||||
from . import ir_actions_report |
|
@ -1,14 +1,13 @@ |
|||||
# © 2011 Guewen Baconnier (Camptocamp) |
# © 2011 Guewen Baconnier (Camptocamp) |
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).- |
# 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): |
class AccountAccount(models.Model): |
||||
_inherit = "account.account" |
|
||||
|
_inherit = 'account.account' |
||||
|
|
||||
centralized = fields.Boolean( |
centralized = fields.Boolean( |
||||
"Centralized", |
|
||||
|
'Centralized', |
||||
help="If flagged, no details will be displayed in " |
help="If flagged, no details will be displayed in " |
||||
"the General Ledger report (the webkit one only), " |
|
||||
"only centralized amounts per period.", |
|
||||
) |
|
||||
|
"the General Ledger report (the webkit one only), " |
||||
|
"only centralized amounts per period.") |
@ -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) |
|
@ -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 |
|
@ -1,126 +1,21 @@ |
|||||
# 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). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
from odoo import api, models |
|
||||
|
from odoo import models |
||||
|
|
||||
|
|
||||
class AgedPartnerBalanceReport(models.AbstractModel): |
|
||||
_name = "report.account_financial_report.abstract_report" |
|
||||
_description = "Abstract Report" |
|
||||
|
class AbstractReport(models.AbstractModel): |
||||
|
_name = 'account_financial_report_abstract' |
||||
|
|
||||
@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 |
|
||||
) |
|
||||
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 |
|
||||
|
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 """ + self._table + """ |
||||
|
WHERE COALESCE( |
||||
|
write_date, create_date, (now() at time zone 'UTC'))::timestamp |
||||
|
< ((now() at time zone 'UTC') - interval %s) |
||||
|
""" |
||||
|
self.env.cr.execute(query, ("%s seconds" % seconds,)) |
@ -1,378 +1,633 @@ |
|||||
# © 2016 Julien Coux (Camptocamp) |
# © 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). |
# 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() |
||||
|
|
||||
|
# 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' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
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 |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
account_id = fields.Many2one( |
||||
|
'account.account', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# 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' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
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 |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
partner_id = fields.Many2one( |
||||
|
'res.partner', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# 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' |
||||
|
) |
||||
|
line_ids = fields.One2many( |
||||
|
comodel_name='report_aged_partner_balance_line', |
||||
|
inverse_name='report_partner_id' |
||||
|
) |
||||
|
|
||||
@api.model |
@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 |
|
||||
|
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 |
||||
|
) |
||||
|
|
||||
|
# 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: |
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} |
|
||||
) |
|
||||
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 |
|
||||
|
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) |
||||
|
|
||||
|
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 |
||||
|
) |
||||
|
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, |
||||
) |
) |
||||
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 |
|
||||
|
self.env.cr.execute(query_inject_account, query_inject_account_params) |
||||
|
|
||||
|
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 |
||||
|
) |
||||
|
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, |
||||
) |
) |
||||
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) |
|
||||
) |
|
||||
credit_ids = list( |
|
||||
map(operator.itemgetter("credit_move_id"), acc_partial_rec) |
|
||||
) |
|
||||
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, |
|
||||
) |
|
||||
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"], |
|
||||
} |
|
||||
) |
|
||||
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, |
|
||||
) |
|
||||
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 |
|
||||
|
self.env.cr.execute(query_inject_partner, query_inject_partner_params) |
||||
|
|
||||
@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 _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 |
||||
|
( |
||||
|
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 |
||||
) |
) |
||||
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 |
|
||||
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": [], |
|
||||
} |
|
||||
) |
|
||||
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"], |
|
||||
} |
|
||||
) |
|
||||
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 |
|
||||
|
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 |
||||
|
) |
||||
|
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) |
||||
|
|
||||
@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) |
|
||||
), |
|
||||
} |
|
||||
) |
|
||||
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, |
|
||||
} |
|
||||
) |
|
||||
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"] |
|
||||
|
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 |
||||
( |
( |
||||
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_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, |
||||
) |
) |
||||
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, |
|
||||
} |
|
||||
|
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) |
2546
account_financial_report/report/general_ledger.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1167
account_financial_report/report/journal_ledger.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1151
account_financial_report/report/open_items.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,518 +1,465 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
<!-- Copyright 2018 ForgeFlow S.L. |
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template id="journal_ledger"> |
|
||||
|
|
||||
|
<template id="report_journal_ledger_qweb"> |
||||
<t t-call="web.html_container"> |
<t t-call="web.html_container"> |
||||
<t t-foreach="docs" t-as="o"> |
<t t-foreach="docs" t-as="o"> |
||||
<t t-call="account_financial_report.internal_layout"> |
<t t-call="account_financial_report.internal_layout"> |
||||
<t t-call="account_financial_report.report_journal_ledger_base" /> |
|
||||
|
<t t-call="account_financial_report.report_journal_ledger_base"/> |
||||
</t> |
</t> |
||||
</t> |
</t> |
||||
</t> |
</t> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="report_journal_ledger_base"> |
<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="page"> |
||||
<div class="row"> |
<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> |
</div> |
||||
<t t-if="group_option == 'none'"> |
|
||||
|
<t t-if="o.group_option == 'none'"> |
||||
<div class="page_break"> |
<div class="page_break"> |
||||
<t t-call="account_financial_report.report_journal_all" /> |
|
||||
<br /> |
|
||||
<t t-call="account_financial_report.report_journal_all_taxes" /> |
|
||||
|
<t t-call="account_financial_report.report_journal_all"/> |
||||
|
<br/> |
||||
|
<t t-call="account_financial_report.report_journal_all_taxes"/> |
||||
</div> |
</div> |
||||
</t> |
</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"> |
<div class="page_break"> |
||||
<t |
|
||||
t-call="account_financial_report.report_journal_ledger_journal" |
|
||||
/> |
|
||||
<br /> |
|
||||
<t |
|
||||
t-call="account_financial_report.report_journal_ledger_journal_taxes" |
|
||||
/> |
|
||||
<br /> |
|
||||
|
<t t-call="account_financial_report.report_journal_ledger_journal"/> |
||||
|
<br/> |
||||
|
<t t-call="account_financial_report.report_journal_ledger_journal_taxes"/> |
||||
|
<br/> |
||||
</div> |
</div> |
||||
</t> |
</t> |
||||
</t> |
</t> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_all"> |
<template id="account_financial_report.report_journal_all"> |
||||
<div class="act_as_table list_table" style="margin-top: 10px;" /> |
|
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;"/> |
||||
<div class="act_as_table data_table" style="width: 100%;"> |
<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_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> |
</t> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_ledger_journal"> |
<template id="account_financial_report.report_journal_ledger_journal"> |
||||
<div class="act_as_table list_table" style="margin-top: 10px;" /> |
|
||||
|
<div class="act_as_table list_table" style="margin-top: 10px;"/> |
||||
<div class="act_as_caption account_title" style="width: 100%;"> |
<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> |
||||
|
|
||||
<div class="act_as_table data_table" style="width: 100%;"> |
<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_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> |
</t> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_ledger_journal_table_header"> |
<template id="account_financial_report.report_journal_ledger_journal_table_header"> |
||||
<t t-if="not display_account_name"> |
<t t-if="not display_account_name"> |
||||
<t t-set="account_column_style"> |
<t t-set="account_column_style"> |
||||
width: 8.11%; |
width: 8.11%; |
||||
</t> |
</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-set="label_column_style"> |
||||
|
width: 38.92%; |
||||
</t> |
</t> |
||||
</t> |
</t> |
||||
<t t-else=""> |
<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-set="account_column_style"> |
||||
|
width: 23.78%; |
||||
</t> |
</t> |
||||
<t t-set="label_column_style"> |
<t t-set="label_column_style"> |
||||
width: 23.24%; |
width: 23.24%; |
||||
</t> |
</t> |
||||
</t> |
</t> |
||||
|
|
||||
<div class="act_as_thead"> |
<div class="act_as_thead"> |
||||
<div class="act_as_row labels"> |
<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" |
|
||||
name="entry" |
|
||||
style="width: 7.57%;" |
|
||||
> |
|
||||
|
<div class="act_as_cell first_column" |
||||
|
name="entry" |
||||
|
style="width: 7.57%;"> |
||||
Entry |
Entry |
||||
</div> |
</div> |
||||
<div class="act_as_cell" name="date" style="width: 5.41%;"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="date" |
||||
|
style="width: 5.41%;"> |
||||
Date |
Date |
||||
</div> |
</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 |
Account |
||||
</div> |
</div> |
||||
<div class="act_as_cell" name="partner" style="width: 15.14%;"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="partner" |
||||
|
style="width: 15.14%;"> |
||||
Partner |
Partner |
||||
</div> |
</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 |
Ref - Label |
||||
</div> |
</div> |
||||
<div class="act_as_cell" name="taxes" style="width: 7.57%;"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="taxes" |
||||
|
style="width: 7.57%;"> |
||||
Taxes |
Taxes |
||||
</div> |
</div> |
||||
<div class="act_as_cell" name="debit" style="width: 8.65%;"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="debit" |
||||
|
style="width: 8.65%;"> |
||||
Debit |
Debit |
||||
</div> |
</div> |
||||
<div class="act_as_cell" name="credit" style="width: 8.65%;"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="credit" |
||||
|
style="width: 8.65%;"> |
||||
Credit |
Credit |
||||
</div> |
</div> |
||||
<t t-if="display_currency"> |
<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. |
Cur. |
||||
</div> |
</div> |
||||
<div |
|
||||
class="act_as_cell" |
|
||||
name="amount_currency" |
|
||||
style="width: 6.49%;" |
|
||||
> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="amount_currency" |
||||
|
style="width: 6.49%;"> |
||||
Amount Cur. |
Amount Cur. |
||||
</div> |
</div> |
||||
</t> |
</t> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_ledger_journal_first_line"> |
<template id="account_financial_report.report_journal_ledger_journal_first_line"> |
||||
<div class="act_as_row lines"> |
<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 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> |
||||
<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 amount" |
||||
|
name="credit"> |
||||
|
<b><span t-field="journal.credit"/></b> |
||||
</div> |
</div> |
||||
<t t-if="display_currency"> |
<t t-if="display_currency"> |
||||
<div class="act_as_cell" name="currency_name"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="currency_name"> |
||||
</div> |
</div> |
||||
<div class="act_as_cell amount" name="amount_currency"> |
|
||||
|
<div class="act_as_cell amount" |
||||
|
name="amount_currency"> |
||||
</div> |
</div> |
||||
</t> |
</t> |
||||
</div> |
</div> |
||||
<div style="width: 100%" /> |
|
||||
|
<div style="width: 100%"/> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_move"> |
<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-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_line_ids" t-as="move_line"> |
||||
<div class="act_as_row lines"> |
<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="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" /> |
|
||||
<t t-set="display_move_info" t-value="False" /> |
|
||||
|
<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"/> |
||||
|
<t t-set="display_move_info" t-value="False"/> |
||||
</div> |
</div> |
||||
</t> |
</t> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_move_line"> |
<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> |
||||
<div class="act_as_cell left" name="date"> |
|
||||
<span |
|
||||
t-if="display_move_info" |
|
||||
t-esc="move_line['date']" |
|
||||
t-options="{'widget': 'date'}" |
|
||||
/> |
|
||||
|
<div class="act_as_cell left" |
||||
|
name="date"> |
||||
|
<span t-if="display_move_info" t-field="move_line.date"/> |
||||
</div> |
</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-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> |
</span> |
||||
</div> |
</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 class="act_as_cell left" |
||||
|
name="partner"> |
||||
|
<span t-if="display_partner" t-field="move_line.partner"/> |
||||
</div> |
</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 class="act_as_cell left" |
||||
|
name="label"> |
||||
|
<span t-field="move_line.label"/> |
||||
</div> |
</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 class="act_as_cell left" |
||||
|
name="taxes"> |
||||
|
<span t-field="move_line.taxes_description"/> |
||||
</div> |
</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 amount" |
||||
|
name="debit"> |
||||
|
<t t-if="move_line.debit"> |
||||
|
<span t-field="move_line.debit"/> |
||||
</t> |
</t> |
||||
</div> |
</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> |
</t> |
||||
</div> |
</div> |
||||
<t t-if="display_currency"> |
<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> |
</t> |
||||
</div> |
</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> |
</t> |
||||
</div> |
</div> |
||||
</t> |
</t> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_ledger_journal_taxes"> |
<template id="account_financial_report.report_journal_ledger_journal_taxes"> |
||||
<b>Taxes summary</b> |
<b>Taxes summary</b> |
||||
<div class="act_as_table data_table" style="width: 100%;"> |
<div class="act_as_table data_table" style="width: 100%;"> |
||||
<div class="act_as_thead"> |
<div class="act_as_thead"> |
||||
<div class="act_as_row labels"> |
<div class="act_as_row labels"> |
||||
<div |
|
||||
class="act_as_cell first_column" |
|
||||
name="name" |
|
||||
style="width: 30.97%;" |
|
||||
> |
|
||||
|
<div class="act_as_cell first_column" |
||||
|
name="name" |
||||
|
style="width: 30.97%;"> |
||||
Name |
Name |
||||
</div> |
</div> |
||||
<div class="act_as_cell" name="description" style="width: 13.27%;"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="description" |
||||
|
style="width: 13.27%;"> |
||||
Description |
Description |
||||
</div> |
</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 |
Base Amount |
||||
</div> |
</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 |
Tax Amount |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="act_as_table data_table" style="width: 100%;"> |
<div class="act_as_table data_table" style="width: 100%;"> |
||||
<div class="act_as_row labels"> |
<div class="act_as_row labels"> |
||||
<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%;"> |
|
||||
|
<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%;"> |
||||
Debit |
Debit |
||||
</div> |
</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 |
Credit |
||||
</div> |
</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 |
Balance |
||||
</div> |
</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 |
Debit |
||||
</div> |
</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 |
Credit |
||||
</div> |
</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 |
Balance |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
<t t-foreach="journal['tax_lines']" 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> |
|
||||
</div> |
|
||||
|
|
||||
|
<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-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> |
</t> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
<template id="account_financial_report.report_journal_all_taxes"> |
<template id="account_financial_report.report_journal_all_taxes"> |
||||
<b>Taxes summary</b> |
<b>Taxes summary</b> |
||||
<div class="act_as_table data_table" style="width: 100%;"> |
<div class="act_as_table data_table" style="width: 100%;"> |
||||
<div class="act_as_thead"> |
<div class="act_as_thead"> |
||||
<div class="act_as_row labels"> |
<div class="act_as_row labels"> |
||||
<div |
|
||||
class="act_as_cell first_column" |
|
||||
name="name" |
|
||||
style="width: 30.97%;" |
|
||||
> |
|
||||
|
<div class="act_as_cell first_column" |
||||
|
name="name" |
||||
|
style="width: 30.97%;"> |
||||
Name |
Name |
||||
</div> |
</div> |
||||
<div class="act_as_cell" name="description" style="width: 13.27%;"> |
|
||||
|
<div class="act_as_cell" |
||||
|
name="description" |
||||
|
style="width: 13.27%;"> |
||||
Description |
Description |
||||
</div> |
</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 |
Base Amount |
||||
</div> |
</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 |
Tax Amount |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="act_as_table data_table" style="width: 100%;">10 |
<div class="act_as_table data_table" style="width: 100%;">10 |
||||
<div class="act_as_row labels"> |
<div class="act_as_row labels"> |
||||
<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%;"> |
|
||||
|
<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%;"> |
||||
Debit |
Debit |
||||
</div> |
</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 |
Credit |
||||
</div> |
</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 |
Balance |
||||
</div> |
</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 |
Debit |
||||
</div> |
</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 |
Credit |
||||
</div> |
</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 |
Balance |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<t t-foreach="ReportTaxLines" 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> |
|
||||
</div> |
|
||||
|
<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-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> |
</t> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
</odoo> |
</odoo> |
@ -1,32 +1,26 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
|
|
||||
<template id="account_financial_report.internal_layout"> |
<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" |
|
||||
/> |
|
||||
<t t-raw="0" /> |
|
||||
|
<div class="article"> |
||||
|
<link href="/account_financial_report/static/src/css/report.css" rel="stylesheet"/> |
||||
|
<t t-raw="0" /> |
||||
</div> |
</div> |
||||
|
|
||||
<div class="footer"> |
<div class="footer"> |
||||
<div class="row"> |
<div class="row"> |
||||
<div class="col-6 custom_footer"> |
|
||||
<span |
|
||||
t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')" |
|
||||
/> |
|
||||
|
<div class="col-xs-6 custom_footer"> |
||||
|
<span t-esc="context_timestamp(datetime.datetime.now()).strftime('%Y-%m-%d %H:%M')"/> |
||||
</div> |
</div> |
||||
<div class="col-6 text-right custom_footer"> |
|
||||
|
<div class="col-xs-6 text-right custom_footer"> |
||||
<ul class="list-inline"> |
<ul class="list-inline"> |
||||
<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><span class="page"/></li> |
||||
|
<li>/</li> |
||||
|
<li><span class="topage"/></li> |
||||
</ul> |
</ul> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
</odoo> |
</odoo> |
1199
account_financial_report/report/templates/trial_balance.xml
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1296
account_financial_report/report/trial_balance.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,239 +1,354 @@ |
|||||
# Copyright 2018 Forest and Biomass Romania |
# 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). |
# 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")] |
|
||||
|
|
||||
|
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. |
||||
|
|
||||
|
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' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
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 |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
taxtag_id = fields.Many2one( |
||||
|
'account.account.tag', |
||||
|
index=True |
||||
|
) |
||||
|
taxgroup_id = fields.Many2one( |
||||
|
'account.tax.group', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# 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' |
||||
|
) |
||||
|
|
||||
|
|
||||
|
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 |
||||
|
) |
||||
|
|
||||
|
# Data fields, used to keep link with real object |
||||
|
tax_id = fields.Many2one( |
||||
|
'account.tax', |
||||
|
index=True |
||||
|
) |
||||
|
|
||||
|
# 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: |
else: |
||||
domain += [("move_id.state", "in", ["posted", "draft"])] |
|
||||
return domain |
|
||||
|
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) |
||||
|
|
||||
|
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 |
@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 |
|
||||
|
def get_html(self, given_context=None): |
||||
|
return self.with_context(given_context)._get_html() |
||||
|
|
||||
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 |
|
||||
) |
|
||||
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, |
|
||||
|
@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 |
||||
) |
) |
||||
net_domain = self._get_net_report_domain( |
|
||||
company_id, date_from, date_to, only_posted_moves |
|
||||
|
INSERT INTO |
||||
|
report_vat_report_taxtag |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
taxtag_id, |
||||
|
code, |
||||
|
name, |
||||
|
net, tax |
||||
|
) |
||||
|
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 |
||||
) |
) |
||||
taxed_move_lines = self.env["account.move.line"].search_read( |
|
||||
domain=net_domain, fields=ml_fields, |
|
||||
|
INSERT INTO |
||||
|
report_vat_report_taxtag |
||||
|
( |
||||
|
report_id, |
||||
|
create_uid, |
||||
|
create_date, |
||||
|
taxgroup_id, |
||||
|
code, |
||||
|
name, |
||||
|
net, tax |
||||
|
) |
||||
|
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 |
||||
) |
) |
||||
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], |
|
||||
} |
|
||||
) |
|
||||
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, |
|
||||
} |
|
||||
) |
|
||||
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), |
|
||||
} |
|
||||
} |
|
||||
) |
|
||||
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}) |
|
||||
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} |
|
||||
) |
|
||||
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] |
|
||||
) |
|
||||
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} |
|
||||
) |
|
||||
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_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 |
||||
) |
) |
||||
if based_on == "taxgroups": |
|
||||
vat_report = self._get_vat_report_group_data( |
|
||||
vat_report_data, tax_data, tax_detail |
|
||||
) |
|
||||
else: |
|
||||
vat_report = self._get_vat_report_tag_data( |
|
||||
vat_report_data, tax_data, tax_detail |
|
||||
) |
|
||||
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, |
|
||||
} |
|
||||
|
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) |
@ -0,0 +1,111 @@ |
|||||
|
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); |
||||
|
}); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
core.action_registry.add( |
||||
|
"account_financial_report_backend", |
||||
|
report_backend |
||||
|
); |
||||
|
return report_backend; |
||||
|
}); |
@ -0,0 +1,85 @@ |
|||||
|
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; |
||||
|
|
||||
|
}); |
@ -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); |
|
||||
}, |
|
||||
}); |
|
||||
}); |
|
@ -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; |
|
||||
}); |
|
@ -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 |
|
||||
); |
|
||||
}); |
|
||||
}); |
|
@ -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> |
|
@ -0,0 +1,408 @@ |
|||||
|
# 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_id': transfer_account_id.id, |
||||
|
}) |
||||
|
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', |
||||
|
'external_report_layout': 'standard', |
||||
|
}) |
||||
|
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) |
||||
|
wizard = self.env['wizard.multi.charts.accounts'].create({ |
||||
|
'company_id': self.company.id, |
||||
|
'chart_template_id': self.chart.id, |
||||
|
'code_digits': 4, |
||||
|
'currency_id': self.ref('base.USD'), |
||||
|
'transfer_account_id': self.chart.transfer_account_id.id, |
||||
|
}) |
||||
|
wizard.onchange_chart_template_id() |
||||
|
wizard.execute() |
||||
|
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() |
@ -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 |
@ -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]) |
@ -0,0 +1,41 @@ |
|||||
|
# Author: Julien Coux |
||||
|
# Copyright 2016 Camptocamp SA |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
|
import time |
||||
|
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': time.strftime('%Y-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}, |
||||
|
] |
853
account_financial_report/tests/test_general_ledger.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,340 +1,366 @@ |
|||||
# Copyright 2017 ACSONE SA/NV |
# 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). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from datetime import datetime |
|
||||
|
import time |
||||
|
|
||||
|
from datetime import datetime |
||||
from dateutil.relativedelta import relativedelta |
from dateutil.relativedelta import relativedelta |
||||
|
|
||||
from odoo.fields import Date |
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': time.strftime('%Y-01-01'), |
||||
|
'date_to': time.strftime('%Y-12-31'), |
||||
|
'company_id': self.company.id, |
||||
|
'journal_ids': [(6, 0, self.journal_sale.ids)] |
||||
|
} |
||||
|
|
||||
|
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""" |
||||
|
|
||||
self.tax_15_p = self.TaxObj.create( |
|
||||
|
# 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( |
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 = { |
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) |
return self.MoveObj.create(move_vals) |
||||
|
|
||||
def check_report_journal_debit_credit( |
def check_report_journal_debit_credit( |
||||
self, res_data, expected_debit, expected_credit |
|
||||
): |
|
||||
|
self, report, expected_debit, expected_credit): |
||||
self.assertEqual( |
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( |
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( |
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.assertEqual( |
|
||||
expected_base_debit, |
|
||||
sum([tax_line["base_debit"] for tax_line in rec["tax_lines"]]), |
|
||||
) |
|
||||
self.assertEqual( |
|
||||
expected_base_credit, |
|
||||
sum([tax_line["base_credit"] for tax_line in rec["tax_lines"]]), |
|
||||
) |
|
||||
self.assertEqual( |
|
||||
expected_tax_debit, |
|
||||
sum([tax_line["tax_debit"] for tax_line in rec["tax_lines"]]), |
|
||||
) |
|
||||
self.assertEqual( |
|
||||
expected_tax_credit, |
|
||||
sum([tax_line["tax_credit"] for tax_line in rec["tax_lines"]]), |
|
||||
) |
|
||||
|
self, report, |
||||
|
expected_base_debit, expected_base_credit, |
||||
|
expected_tax_debit, expected_tax_credit): |
||||
|
|
||||
|
self.assertEqual( |
||||
|
expected_base_debit, |
||||
|
sum([ |
||||
|
journal.base_debit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_base_credit, |
||||
|
sum([ |
||||
|
journal.base_credit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_tax_debit, |
||||
|
sum([ |
||||
|
journal.tax_debit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
self.assertEqual( |
||||
|
expected_tax_credit, |
||||
|
sum([ |
||||
|
journal.tax_credit |
||||
|
for journal in report.report_journal_ledger_tax_line_ids |
||||
|
]) |
||||
|
) |
||||
|
|
||||
def test_01_test_total(self): |
def test_01_test_total(self): |
||||
today_date = Date.today() |
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) |
|
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 200, 200) |
||||
|
|
||||
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.move_target = 'posted' |
||||
|
report.compute_data_for_report() |
||||
|
self.check_report_journal_debit_credit(report, 0, 0) |
||||
|
|
||||
move1.post() |
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() |
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() |
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): |
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", |
|
||||
} |
|
||||
) |
|
||||
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_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 |
||||
|
])], |
||||
|
}) |
||||
|
] |
||||
|
} |
||||
|
invoice = self.InvoiceObj.create(invoice_values) |
||||
|
invoice.action_invoice_open() |
||||
|
|
||||
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", |
|
||||
} |
|
||||
) |
|
||||
data = wiz._prepare_report_journal_ledger() |
|
||||
res_data = self.JournalLedgerReport._get_report_values(wiz, data) |
|
||||
|
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(res_data, 250, 250) |
|
||||
self.check_report_journal_debit_credit_taxes(res_data, 300, 0, 50, 0) |
|
||||
|
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_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 |
||||
|
])], |
||||
|
}) |
||||
|
] |
||||
|
} |
||||
|
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) |
1129
account_financial_report/tests/test_trial_balance.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,368 +1,295 @@ |
|||||
# Copyright 2018 Forest and Biomass Romania |
# 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). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
||||
|
|
||||
import time |
import time |
||||
from datetime import date |
|
||||
|
|
||||
from odoo.tests import common |
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': time.strftime('%Y-01-01'), |
||||
|
'date_to': time.strftime('%Y-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): |
class TestVATReport(common.TransactionCase): |
||||
|
|
||||
def setUp(self): |
def setUp(self): |
||||
super(TestVATReport, self).setUp() |
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.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, |
|
||||
}, |
|
||||
), |
|
||||
], |
|
||||
} |
|
||||
) |
|
||||
|
|
||||
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() |
|
||||
|
|
||||
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.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' |
||||
|
}) |
||||
|
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': 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])] |
||||
|
}) |
||||
|
|
||||
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 |
|
||||
|
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', |
||||
|
}) |
||||
|
|
||||
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': 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 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 |
|
||||
|
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 _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 |
|
||||
|
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 _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, time.strftime('%Y-%m-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): |
def test_01_compute(self): |
||||
# Generate the vat lines |
# 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 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 |
# 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): |
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( |
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() |
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, time.strftime('%Y-%m-01')) |
||||
|
self.assertEqual(wizard.date_to, time.strftime('%Y-%m-28')) |
||||
|
wizard._export('qweb-pdf') |
||||
wizard.button_export_html() |
wizard.button_export_html() |
||||
wizard.button_export_pdf() |
wizard.button_export_pdf() |
||||
wizard.button_export_xlsx() |
wizard.button_export_xlsx() |
||||
wizard = vat_wizard.create( |
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() |
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, time.strftime('%Y-%m-01')) |
||||
|
self.assertEqual(wizard.date_to, time.strftime('%Y-%m-28')) |
||||
|
wizard._export('qweb-pdf') |
||||
wizard.button_export_html() |
wizard.button_export_html() |
||||
wizard.button_export_pdf() |
wizard.button_export_pdf() |
||||
wizard.button_export_xlsx() |
wizard.button_export_xlsx() |
@ -1,13 +1,13 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<record model="ir.ui.view" id="view_account_specific_form"> |
<record model="ir.ui.view" id="view_account_specific_form"> |
||||
<field name="name">account.account.form.inherit</field> |
<field name="name">account.account.form.inherit</field> |
||||
<field name="inherit_id" ref="account.view_account_form" /> |
|
||||
|
<field name="inherit_id" ref="account.view_account_form"/> |
||||
<field name="model">account.account</field> |
<field name="model">account.account</field> |
||||
<field name="type">form</field> |
<field name="type">form</field> |
||||
<field name="arch" type="xml"> |
<field name="arch" type="xml"> |
||||
<field name="deprecated" position="after"> |
<field name="deprecated" position="after"> |
||||
<field name="centralized" /> |
|
||||
|
<field name="centralized"/> |
||||
</field> |
</field> |
||||
</field> |
</field> |
||||
</record> |
</record> |
||||
|
@ -1,9 +1,9 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template id="report_aged_partner_balance"> |
<template id="report_aged_partner_balance"> |
||||
<div class="o_account_financial_reports_page"> |
<div class="o_account_financial_reports_page"> |
||||
<t t-call="account_financial_report.report_buttons" /> |
|
||||
<t t-call="account_financial_report.report_aged_partner_balance_base" /> |
|
||||
|
<t t-call="account_financial_report.report_buttons"/> |
||||
|
<t t-call="account_financial_report.report_aged_partner_balance_base"/> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
</odoo> |
</odoo> |
@ -1,9 +1,9 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template id="report_general_ledger"> |
<template id="report_general_ledger"> |
||||
<div class="o_account_financial_reports_page"> |
<div class="o_account_financial_reports_page"> |
||||
<t t-call="account_financial_report.report_buttons" /> |
|
||||
<t t-call="account_financial_report.report_general_ledger_base" /> |
|
||||
|
<t t-call="account_financial_report.report_buttons"/> |
||||
|
<t t-call="account_financial_report.report_general_ledger_base"/> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
</odoo> |
</odoo> |
@ -1,9 +1,9 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template id="report_journal_ledger"> |
<template id="report_journal_ledger"> |
||||
<div class="o_account_financial_reports_page"> |
<div class="o_account_financial_reports_page"> |
||||
<t t-call="account_financial_report.report_buttons" /> |
|
||||
<t t-call="account_financial_report.report_journal_ledger_base" /> |
|
||||
|
<t t-call="account_financial_report.report_buttons"/> |
||||
|
<t t-call="account_financial_report.report_journal_ledger_base"/> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
</odoo> |
</odoo> |
@ -1,9 +1,9 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template id="report_open_items"> |
<template id="report_open_items"> |
||||
<div class="o_account_financial_reports_page"> |
<div class="o_account_financial_reports_page"> |
||||
<t t-call="account_financial_report.report_buttons" /> |
|
||||
<t t-call="account_financial_report.report_open_items_base" /> |
|
||||
|
<t t-call="account_financial_report.report_buttons"/> |
||||
|
<t t-call="account_financial_report.report_open_items_base"/> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
</odoo> |
</odoo> |
@ -1,31 +1,57 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template |
|
||||
id="account_financial_report_assets_backend" |
|
||||
name="account_financial_report assets_backend" |
|
||||
inherit_id="web.assets_backend" |
|
||||
> |
|
||||
|
|
||||
|
<template id="account_financial_report_assets_backend" |
||||
|
name="account_financial_report assets" inherit_id="web.assets_backend"> |
||||
<xpath expr="." position="inside"> |
<xpath expr="." position="inside"> |
||||
<script |
|
||||
type="text/javascript" |
|
||||
src="/account_financial_report/static/src/js/action_manager_report.js" |
|
||||
/> |
|
||||
<script |
|
||||
type="text/javascript" |
|
||||
src="/account_financial_report/static/src/js/client_action.js" |
|
||||
/> |
|
||||
|
<link href="/account_financial_report/static/src/css/report.css" rel="stylesheet"/> |
||||
|
<script type="text/javascript" |
||||
|
src="/account_financial_report/static/src/js/account_financial_report_backend.js"/> |
||||
|
<script type="text/javascript" |
||||
|
src="/account_financial_report/static/src/js/account_financial_report_widgets.js"/> |
||||
</xpath> |
</xpath> |
||||
</template> |
</template> |
||||
<template |
|
||||
id="account_financial_report_assets_common" |
|
||||
name="account_financial_report report_assets" |
|
||||
inherit_id="web.report_assets_common" |
|
||||
> |
|
||||
<xpath expr="." position="inside"> |
|
||||
<script |
|
||||
type="text/javascript" |
|
||||
src="/account_financial_report/static/src/js/report.js" |
|
||||
/> |
|
||||
</xpath> |
|
||||
|
<template id="report_buttons"> |
||||
|
<div class="button_row"> |
||||
|
<button class="o_account_financial_reports_print btn btn-sm oe_button"><span class="fa fa-print"/> Print</button> |
||||
|
<button class="o_account_financial_reports_export btn btn-sm oe_button"><span class="fa fa-download"/> Export</button> |
||||
|
</div> |
||||
</template> |
</template> |
||||
|
|
||||
|
<record id="action_report_general_ledger" model="ir.actions.client"> |
||||
|
<field name="name">General Ledger</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field name="context" eval="{'active_model': 'report_general_ledger'}" /> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_journal_ledger" model="ir.actions.client"> |
||||
|
<field name="name">Journal</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field name="context" eval="{'active_model': 'report_journal_ledger'}" /> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_open_items" model="ir.actions.client"> |
||||
|
<field name="name">Open Items</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field name="context" eval="{'active_model': 'report_open_items'}" /> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_trial_balance" model="ir.actions.client"> |
||||
|
<field name="name">Trial Balance</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field name="context" eval="{'active_model': 'report_trial_balance'}" /> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_aged_partner_balance" model="ir.actions.client"> |
||||
|
<field name="name">Aged Partner Balance</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field name="context" eval="{'active_model': 'report_aged_partner_balance'}" /> |
||||
|
</record> |
||||
|
|
||||
|
<record id="action_report_vat_report" model="ir.actions.client"> |
||||
|
<field name="name">VAT Report</field> |
||||
|
<field name="tag">account_financial_report_backend</field> |
||||
|
<field name="context" eval="{'active_model': 'report_vat_report'}" /> |
||||
|
</record> |
||||
|
|
||||
</odoo> |
</odoo> |
@ -1,9 +1,11 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
|
|
||||
<template id="report_trial_balance"> |
<template id="report_trial_balance"> |
||||
<div class="o_account_financial_reports_page"> |
<div class="o_account_financial_reports_page"> |
||||
<t t-call="account_financial_report.report_buttons" /> |
|
||||
<t t-call="account_financial_report.report_trial_balance_base" /> |
|
||||
|
<t t-call="account_financial_report.report_buttons"/> |
||||
|
<t t-call="account_financial_report.report_trial_balance_base"/> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
|
|
||||
</odoo> |
</odoo> |
@ -1,9 +1,9 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
<template id="report_vat_report"> |
<template id="report_vat_report"> |
||||
<div class="o_account_financial_reports_page"> |
<div class="o_account_financial_reports_page"> |
||||
<t t-call="account_financial_report.report_buttons" /> |
|
||||
<t t-call="account_financial_report.report_vat_report_base" /> |
|
||||
|
<t t-call="account_financial_report.report_buttons"/> |
||||
|
<t t-call="account_financial_report.report_vat_report_base"/> |
||||
</div> |
</div> |
||||
</template> |
</template> |
||||
</odoo> |
</odoo> |
@ -1,52 +0,0 @@ |
|||||
# Copyright 2019 Lorenzo Battistini @ TAKOBI |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|
||||
|
|
||||
from odoo import fields, models |
|
||||
|
|
||||
|
|
||||
class AbstractWizard(models.AbstractModel): |
|
||||
_name = "account_financial_report_abstract_wizard" |
|
||||
_description = "Abstract Wizard" |
|
||||
|
|
||||
def _get_partner_ids_domain(self): |
|
||||
return [ |
|
||||
"&", |
|
||||
"|", |
|
||||
("company_id", "=", self.company_id.id), |
|
||||
("company_id", "=", False), |
|
||||
"|", |
|
||||
("parent_id", "=", False), |
|
||||
("is_company", "=", True), |
|
||||
] |
|
||||
|
|
||||
def _default_partners(self): |
|
||||
context = self.env.context |
|
||||
if context.get("active_ids") and context.get("active_model") == "res.partner": |
|
||||
partners = self.env["res.partner"].browse(context["active_ids"]) |
|
||||
corp_partners = partners.filtered("parent_id") |
|
||||
partners -= corp_partners |
|
||||
partners |= corp_partners.mapped("commercial_partner_id") |
|
||||
return partners.ids |
|
||||
|
|
||||
company_id = fields.Many2one( |
|
||||
comodel_name="res.company", |
|
||||
default=lambda self: self.env.company.id, |
|
||||
required=False, |
|
||||
string="Company", |
|
||||
domain=lambda self: [("id", "in", self.env.companies.ids)], |
|
||||
) |
|
||||
|
|
||||
def button_export_html(self): |
|
||||
self.ensure_one() |
|
||||
report_type = "qweb-html" |
|
||||
return self._export(report_type) |
|
||||
|
|
||||
def button_export_pdf(self): |
|
||||
self.ensure_one() |
|
||||
report_type = "qweb-pdf" |
|
||||
return self._export(report_type) |
|
||||
|
|
||||
def button_export_xlsx(self): |
|
||||
self.ensure_one() |
|
||||
report_type = "xlsx" |
|
||||
return self._export(report_type) |
|
@ -1,99 +1,59 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<odoo> |
<odoo> |
||||
|
|
||||
<!-- AGED PARTNER BALANCE --> |
<!-- AGED PARTNER BALANCE --> |
||||
<record id="aged_partner_balance_wizard" model="ir.ui.view"> |
<record id="aged_partner_balance_wizard" model="ir.ui.view"> |
||||
<field name="name">Aged Partner Balance</field> |
<field name="name">Aged Partner Balance</field> |
||||
<field name="model">aged.partner.balance.report.wizard</field> |
|
||||
|
<field name="model">aged.partner.balance.wizard</field> |
||||
<field name="arch" type="xml"> |
<field name="arch" type="xml"> |
||||
<form> |
<form> |
||||
<group name="main_info"> |
<group name="main_info"> |
||||
<field |
|
||||
name="company_id" |
|
||||
options="{'no_create': True}" |
|
||||
groups="base.group_multi_company" |
|
||||
/> |
|
||||
|
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/> |
||||
</group> |
</group> |
||||
<group name="filters"> |
<group name="filters"> |
||||
<group name="date_range"> |
<group name="date_range"> |
||||
<field name="date_at" /> |
|
||||
<field name="date_from" /> |
|
||||
|
<field name="date_at"/> |
||||
</group> |
</group> |
||||
<group name="other_filters"> |
<group name="other_filters"> |
||||
<field name="target_move" widget="radio" /> |
|
||||
<field name="show_move_line_details" /> |
|
||||
|
<field name="target_move" widget="radio"/> |
||||
|
<field name="show_move_line_details"/> |
||||
</group> |
</group> |
||||
</group> |
</group> |
||||
<group name="partner_filter" col="1"> |
<group name="partner_filter" col="1"> |
||||
<label for="partner_ids" /> |
|
||||
<field |
|
||||
name="partner_ids" |
|
||||
nolabel="1" |
|
||||
widget="many2many_tags" |
|
||||
options="{'no_create': True}" |
|
||||
/> |
|
||||
|
<label for="partner_ids"/> |
||||
|
<field name="partner_ids" nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}"/> |
||||
</group> |
</group> |
||||
<group name="account_filter" col="4"> |
<group name="account_filter" col="4"> |
||||
<label for="account_ids" colspan="4" /> |
|
||||
<field name="receivable_accounts_only" /> |
|
||||
<field name="payable_accounts_only" /> |
|
||||
<label for="account_code_from" string="From Code" /> |
|
||||
<div> |
|
||||
<div class="o_row"> |
|
||||
<field |
|
||||
name="account_code_from" |
|
||||
class="oe_inline" |
|
||||
options="{'no_create': True}" |
|
||||
/> |
|
||||
<span class="oe_inline"> |
|
||||
To |
|
||||
</span> |
|
||||
<field |
|
||||
name="account_code_to" |
|
||||
class="oe_inline" |
|
||||
options="{'no_create': True}" |
|
||||
/> |
|
||||
</div> |
|
||||
</div> |
|
||||
<field |
|
||||
name="account_ids" |
|
||||
nolabel="1" |
|
||||
widget="many2many_tags" |
|
||||
options="{'no_create': True}" |
|
||||
colspan="4" |
|
||||
/> |
|
||||
|
<label for="account_ids" colspan="4"/> |
||||
|
<field name="receivable_accounts_only"/> |
||||
|
<field name="payable_accounts_only"/> |
||||
|
<field name="account_ids" nolabel="1" |
||||
|
widget="many2many_tags" |
||||
|
options="{'no_create': True}" |
||||
|
colspan="4"/> |
||||
</group> |
</group> |
||||
<footer> |
<footer> |
||||
<button |
|
||||
name="button_export_html" |
|
||||
string="View" |
|
||||
type="object" |
|
||||
default_focus="1" |
|
||||
class="oe_highlight" |
|
||||
/> |
|
||||
|
<button name="button_export_html" string="View" |
||||
|
type="object" default_focus="1" class="oe_highlight"/> |
||||
or |
or |
||||
<button |
|
||||
name="button_export_pdf" |
|
||||
string="Export PDF" |
|
||||
type="object" |
|
||||
/> |
|
||||
|
<button name="button_export_pdf" string="Export PDF" type="object"/> |
||||
or |
or |
||||
<button |
|
||||
name="button_export_xlsx" |
|
||||
string="Export XLSX" |
|
||||
type="object" |
|
||||
/> |
|
||||
|
<button name="button_export_xlsx" string="Export XLSX" type="object"/> |
||||
or |
or |
||||
<button string="Cancel" class="oe_link" special="cancel" /> |
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
</footer> |
</footer> |
||||
</form> |
</form> |
||||
</field> |
</field> |
||||
</record> |
</record> |
||||
<act_window |
|
||||
id="action_aged_partner_balance_wizard" |
|
||||
name="Aged Partner Balance" |
|
||||
res_model="aged.partner.balance.report.wizard" |
|
||||
view_mode="form" |
|
||||
view_id="aged_partner_balance_wizard" |
|
||||
target="new" |
|
||||
/> |
|
||||
|
|
||||
|
<act_window id="action_aged_partner_balance_wizard" |
||||
|
name="Aged Partner Balance" |
||||
|
res_model="aged.partner.balance.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="aged_partner_balance_wizard" |
||||
|
target="new" /> |
||||
|
|
||||
</odoo> |
</odoo> |
@ -1,157 +1,160 @@ |
|||||
# Copyright 2017 ACSONE SA/NV |
# Copyright 2017 ACSONE SA/NV |
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from odoo import _, api, fields, models |
|
||||
|
from odoo import api, fields, models, _ |
||||
|
from odoo.tools.safe_eval import safe_eval |
||||
|
from odoo.tools import pycompat |
||||
|
|
||||
|
|
||||
class JournalLedgerReportWizard(models.TransientModel): |
class JournalLedgerReportWizard(models.TransientModel): |
||||
"""Journal Ledger report wizard.""" |
"""Journal Ledger report wizard.""" |
||||
|
|
||||
_name = "journal.ledger.report.wizard" |
|
||||
|
_name = 'journal.ledger.report.wizard' |
||||
_description = "Journal Ledger Report Wizard" |
_description = "Journal Ledger Report Wizard" |
||||
_inherit = "account_financial_report_abstract_wizard" |
|
||||
|
|
||||
date_range_id = fields.Many2one(comodel_name="date.range", string="Date range") |
|
||||
date_from = fields.Date(string="Start date", required=True) |
|
||||
date_to = fields.Date(string="End date", required=True) |
|
||||
|
company_id = fields.Many2one( |
||||
|
comodel_name='res.company', |
||||
|
default=lambda self: self.env.user.company_id, |
||||
|
string='Company', |
||||
|
required=False, |
||||
|
ondelete='cascade', |
||||
|
) |
||||
|
date_range_id = fields.Many2one( |
||||
|
comodel_name='date.range', |
||||
|
string='Date range', |
||||
|
) |
||||
|
date_from = fields.Date( |
||||
|
string="Start date", |
||||
|
required=True |
||||
|
) |
||||
|
date_to = fields.Date( |
||||
|
string="End date", |
||||
|
required=True |
||||
|
) |
||||
journal_ids = fields.Many2many( |
journal_ids = fields.Many2many( |
||||
comodel_name="account.journal", string="Journals", required=False |
|
||||
|
comodel_name='account.journal', |
||||
|
string="Journals", |
||||
|
required=False, |
||||
) |
) |
||||
move_target = fields.Selection( |
move_target = fields.Selection( |
||||
selection="_get_move_targets", default="posted", required=True |
|
||||
|
selection='_get_move_targets', |
||||
|
default='all', |
||||
|
required=True, |
||||
) |
) |
||||
foreign_currency = fields.Boolean() |
foreign_currency = fields.Boolean() |
||||
sort_option = fields.Selection( |
sort_option = fields.Selection( |
||||
selection="_get_sort_options", |
|
||||
|
selection='_get_sort_options', |
||||
string="Sort entries by", |
string="Sort entries by", |
||||
default="move_name", |
|
||||
|
default='move_name', |
||||
required=True, |
required=True, |
||||
) |
) |
||||
group_option = fields.Selection( |
group_option = fields.Selection( |
||||
selection="_get_group_options", |
|
||||
|
selection='_get_group_options', |
||||
string="Group entries by", |
string="Group entries by", |
||||
default="journal", |
|
||||
|
default='journal', |
||||
required=True, |
required=True, |
||||
) |
) |
||||
with_account_name = fields.Boolean(default=False) |
|
||||
with_auto_sequence = fields.Boolean(string="Show Auto Sequence", default=False) |
|
||||
|
with_account_name = fields.Boolean( |
||||
|
default=False, |
||||
|
) |
||||
|
|
||||
@api.model |
@api.model |
||||
def _get_move_targets(self): |
def _get_move_targets(self): |
||||
return [("all", _("All")), ("posted", _("Posted")), ("draft", _("Not Posted"))] |
|
||||
|
return [ |
||||
|
('all', _("All")), |
||||
|
('posted', _("Posted")), |
||||
|
('draft', _("Not Posted")) |
||||
|
] |
||||
|
|
||||
@api.model |
@api.model |
||||
def _get_sort_options(self): |
def _get_sort_options(self): |
||||
return [("move_name", _("Entry number")), ("date", _("Date"))] |
|
||||
|
return [ |
||||
|
('move_name', _("Entry number")), |
||||
|
('date', _("Date")), |
||||
|
] |
||||
|
|
||||
@api.model |
@api.model |
||||
def _get_group_options(self): |
def _get_group_options(self): |
||||
return [("journal", _("Journal")), ("none", _("No group"))] |
|
||||
|
return [ |
||||
|
('journal', _("Journal")), |
||||
|
('none', _("No group")), |
||||
|
] |
||||
|
|
||||
@api.onchange("date_range_id") |
|
||||
|
@api.onchange('date_range_id') |
||||
def onchange_date_range_id(self): |
def onchange_date_range_id(self): |
||||
self.date_from = self.date_range_id.date_start |
self.date_from = self.date_range_id.date_start |
||||
self.date_to = self.date_range_id.date_end |
self.date_to = self.date_range_id.date_end |
||||
|
|
||||
@api.onchange("company_id") |
|
||||
|
@api.onchange('company_id') |
||||
def onchange_company_id(self): |
def onchange_company_id(self): |
||||
"""Handle company change.""" |
"""Handle company change.""" |
||||
if ( |
|
||||
self.company_id |
|
||||
and self.date_range_id.company_id |
|
||||
and self.date_range_id.company_id != self.company_id |
|
||||
): |
|
||||
|
if self.company_id and self.date_range_id.company_id and \ |
||||
|
self.date_range_id.company_id != self.company_id: |
||||
self.date_range_id = False |
self.date_range_id = False |
||||
if self.company_id and self.journal_ids: |
if self.company_id and self.journal_ids: |
||||
self.journal_ids = self.journal_ids.filtered( |
self.journal_ids = self.journal_ids.filtered( |
||||
lambda p: p.company_id == self.company_id or not p.company_id |
|
||||
) |
|
||||
res = {"domain": {"journal_ids": []}} |
|
||||
|
lambda p: p.company_id == self.company_id or not p.company_id) |
||||
|
res = {'domain': {'journal_ids': []}} |
||||
if not self.company_id: |
if not self.company_id: |
||||
return res |
return res |
||||
else: |
else: |
||||
res["domain"]["journal_ids"] += [("company_id", "=", self.company_id.id)] |
|
||||
|
res['domain']['journal_ids'] += [ |
||||
|
('company_id', '=', self.company_id.id)] |
||||
return res |
return res |
||||
|
|
||||
def _print_report(self, report_type): |
|
||||
|
@api.multi |
||||
|
def button_export_html(self): |
||||
self.ensure_one() |
self.ensure_one() |
||||
data = self._prepare_report_journal_ledger() |
|
||||
if report_type == "xlsx": |
|
||||
report_name = "a_f_r.report_journal_ledger_xlsx" |
|
||||
else: |
|
||||
report_name = "account_financial_report.journal_ledger" |
|
||||
return ( |
|
||||
self.env["ir.actions.report"] |
|
||||
.search( |
|
||||
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
|
||||
limit=1, |
|
||||
) |
|
||||
.report_action(self, data=data) |
|
||||
) |
|
||||
|
action = self.env.ref( |
||||
|
'account_financial_report.action_report_journal_ledger') |
||||
|
vals = action.read()[0] |
||||
|
context1 = vals.get('context', {}) |
||||
|
if isinstance(context1, pycompat.string_types): |
||||
|
context1 = safe_eval(context1) |
||||
|
model = self.env['report_journal_ledger'] |
||||
|
report = model.create(self._prepare_report_journal_ledger()) |
||||
|
report.compute_data_for_report() |
||||
|
context1['active_id'] = report.id |
||||
|
context1['active_ids'] = report.ids |
||||
|
vals['context'] = context1 |
||||
|
return vals |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_pdf(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'qweb-pdf' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
|
def button_export_xlsx(self): |
||||
|
self.ensure_one() |
||||
|
report_type = 'xlsx' |
||||
|
return self._export(report_type) |
||||
|
|
||||
|
@api.multi |
||||
def _prepare_report_journal_ledger(self): |
def _prepare_report_journal_ledger(self): |
||||
self.ensure_one() |
self.ensure_one() |
||||
journals = self.journal_ids |
journals = self.journal_ids |
||||
if not journals: |
if not journals: |
||||
# Not selecting a journal means that we'll display all journals |
# Not selecting a journal means that we'll display all journals |
||||
journals = self.env["account.journal"].search( |
|
||||
[("company_id", "=", self.company_id.id)] |
|
||||
) |
|
||||
|
journals = self.env['account.journal'].search( |
||||
|
[('company_id', '=', self.company_id.id)]) |
||||
return { |
return { |
||||
"wizard_id": self.id, |
|
||||
"date_from": self.date_from, |
|
||||
"date_to": self.date_to, |
|
||||
"move_target": self.move_target, |
|
||||
"foreign_currency": self.foreign_currency, |
|
||||
"company_id": self.company_id.id, |
|
||||
"journal_ids": journals.ids, |
|
||||
"sort_option": self.sort_option, |
|
||||
"group_option": self.group_option, |
|
||||
"with_account_name": self.with_account_name, |
|
||||
"account_financial_report_lang": self.env.lang, |
|
||||
"with_auto_sequence": self.with_auto_sequence, |
|
||||
|
'date_from': self.date_from, |
||||
|
'date_to': self.date_to, |
||||
|
'move_target': self.move_target, |
||||
|
'foreign_currency': self.foreign_currency, |
||||
|
'company_id': self.company_id.id, |
||||
|
'journal_ids': [(6, 0, journals.ids)], |
||||
|
'sort_option': self.sort_option, |
||||
|
'group_option': self.group_option, |
||||
|
'with_account_name': self.with_account_name, |
||||
} |
} |
||||
|
|
||||
def _export(self, report_type): |
def _export(self, report_type): |
||||
"""Default export is PDF.""" |
"""Default export is PDF.""" |
||||
self.ensure_one() |
self.ensure_one() |
||||
return self._print_report(report_type) |
|
||||
|
|
||||
@api.model |
|
||||
def _get_ml_tax_description( |
|
||||
self, move_line_data, tax_line_data, move_line_taxes_data |
|
||||
): |
|
||||
taxes_description = "" |
|
||||
if move_line_data["tax_line_id"]: |
|
||||
taxes_description = tax_line_data["description"] or tax_line_data["name"] |
|
||||
elif move_line_taxes_data: |
|
||||
tax_names = [] |
|
||||
for tax_key in move_line_taxes_data: |
|
||||
tax = move_line_taxes_data[tax_key] |
|
||||
tax_names.append(tax["description"] or tax["name"]) |
|
||||
taxes_description = ",".join(tax_names) |
|
||||
return taxes_description |
|
||||
|
|
||||
@api.model |
|
||||
def _get_partner_name(self, partner_id, partner_data): |
|
||||
if partner_id in partner_data.keys(): |
|
||||
return partner_data[partner_id]["name"] |
|
||||
else: |
|
||||
return "" |
|
||||
|
|
||||
@api.model |
|
||||
def _get_atr_from_dict(self, obj_id, data, key): |
|
||||
try: |
|
||||
return data[obj_id][key] |
|
||||
except KeyError: |
|
||||
return data[str(obj_id)][key] |
|
||||
|
|
||||
@api.model |
|
||||
def _get_data_from_dict(self, obj_id, data): |
|
||||
if data: |
|
||||
if isinstance(list(data.keys())[0], int): |
|
||||
return data.get(obj_id, False) |
|
||||
else: |
|
||||
return data.get(obj_id(obj_id), False) |
|
||||
else: |
|
||||
return False |
|
||||
|
model = self.env['report_journal_ledger'] |
||||
|
report = model.create(self._prepare_report_journal_ledger()) |
||||
|
report.compute_data_for_report() |
||||
|
return report.print_report(report_type) |
@ -1,76 +1,66 @@ |
|||||
<?xml version="1.0" encoding="utf-8" ?> |
|
||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
<!-- Copyright 2017 ACSONE SA/NV |
<!-- Copyright 2017 ACSONE SA/NV |
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). --> |
||||
|
|
||||
<odoo> |
<odoo> |
||||
|
|
||||
|
|
||||
<record id="journal_ledger_wizard" model="ir.ui.view"> |
<record id="journal_ledger_wizard" model="ir.ui.view"> |
||||
<field name="name">Journal Ledger</field> |
<field name="name">Journal Ledger</field> |
||||
<field name="model">journal.ledger.report.wizard</field> |
<field name="model">journal.ledger.report.wizard</field> |
||||
<field name="arch" type="xml"> |
<field name="arch" type="xml"> |
||||
<form> |
<form> |
||||
<group> |
<group> |
||||
<field name="company_id" groups="base.group_multi_company" /> |
|
||||
|
<field name="company_id" groups="base.group_multi_company"/> |
||||
</group> |
</group> |
||||
<separator string="Periods" /> |
|
||||
|
|
||||
|
<separator string="Periods"/> |
||||
<group> |
<group> |
||||
<group> |
<group> |
||||
<field name="date_range_id" /> |
|
||||
<field name="date_from" /> |
|
||||
<field name="date_to" /> |
|
||||
|
<field name="date_range_id"/> |
||||
|
<field name="date_from"/> |
||||
|
<field name="date_to"/> |
||||
</group> |
</group> |
||||
<group /> |
|
||||
|
<group/> |
||||
</group> |
</group> |
||||
<separator string="Options" /> |
|
||||
|
|
||||
|
<separator string="Options"/> |
||||
<group name="options"> |
<group name="options"> |
||||
<group> |
<group> |
||||
<field |
|
||||
name="move_target" |
|
||||
widget="radio" |
|
||||
options="{'horizontal': true}" |
|
||||
/> |
|
||||
<field name="sort_option" /> |
|
||||
<field name="group_option" /> |
|
||||
<field name="foreign_currency" /> |
|
||||
<field name="with_account_name" /> |
|
||||
<field name="with_auto_sequence" /> |
|
||||
|
<field name="move_target" widget="radio" options="{'horizontal': true}"/> |
||||
|
<field name="sort_option"/> |
||||
|
<field name="group_option"/> |
||||
|
<field name="foreign_currency"/> |
||||
|
<field name="with_account_name"/> |
||||
</group> |
</group> |
||||
<group /> |
|
||||
|
<group/> |
||||
</group> |
</group> |
||||
<separator string="Journals" /> |
|
||||
|
|
||||
|
<separator string="Journals"/> |
||||
<group> |
<group> |
||||
<field name="journal_ids" widget="many2many_tags" /> |
|
||||
|
<field name="journal_ids" widget="many2many_tags"/> |
||||
</group> |
</group> |
||||
|
|
||||
<footer> |
<footer> |
||||
<button |
|
||||
name="button_export_html" |
|
||||
string="View" |
|
||||
type="object" |
|
||||
default_focus="1" |
|
||||
class="oe_highlight" |
|
||||
/> |
|
||||
|
<button name="button_export_html" string="View" |
||||
|
type="object" default_focus="1" class="oe_highlight"/> |
||||
or |
or |
||||
<button |
|
||||
name="button_export_pdf" |
|
||||
string="Export PDF" |
|
||||
type="object" |
|
||||
/> |
|
||||
|
<button name="button_export_pdf" string="Export PDF" type="object"/> |
||||
or |
or |
||||
<button |
|
||||
name="button_export_xlsx" |
|
||||
string="Export XLSX" |
|
||||
type="object" |
|
||||
/> |
|
||||
|
<button name="button_export_xlsx" string="Export XLSX" type="object"/> |
||||
or |
or |
||||
<button string="Cancel" class="oe_link" special="cancel" /> |
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
</footer> |
</footer> |
||||
</form> |
</form> |
||||
</field> |
</field> |
||||
</record> |
</record> |
||||
<act_window |
|
||||
id="action_journal_ledger_wizard" |
|
||||
name="Journal Ledger" |
|
||||
res_model="journal.ledger.report.wizard" |
|
||||
view_mode="form" |
|
||||
view_id="journal_ledger_wizard" |
|
||||
target="new" |
|
||||
/> |
|
||||
|
|
||||
|
<act_window id="action_journal_ledger_wizard" |
||||
|
name="Journal Ledger" |
||||
|
res_model="journal.ledger.report.wizard" |
||||
|
view_type="form" |
||||
|
view_mode="form" |
||||
|
view_id="journal_ledger_wizard" |
||||
|
target="new" /> |
||||
|
|
||||
</odoo> |
</odoo> |
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue