committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 35822 additions and 17335 deletions
-
34account_financial_report/README.rst
-
3account_financial_report/__manifest__.py
-
1749account_financial_report/i18n/account_financial_report.pot
-
1852account_financial_report/i18n/ar.po
-
1726account_financial_report/i18n/ca.po
-
2611account_financial_report/i18n/da.po
-
2120account_financial_report/i18n/de.po
-
1824account_financial_report/i18n/es.po
-
1785account_financial_report/i18n/es_AR.po
-
1914account_financial_report/i18n/fr.po
-
1899account_financial_report/i18n/fr_CH.po
-
1852account_financial_report/i18n/hr.po
-
1704account_financial_report/i18n/hr_HR.po
-
1969account_financial_report/i18n/it.po
-
1678account_financial_report/i18n/ja.po
-
1968account_financial_report/i18n/nl.po
-
1693account_financial_report/i18n/nl_NL.po
-
2133account_financial_report/i18n/pt.po
-
2052account_financial_report/i18n/pt_BR.po
-
2028account_financial_report/i18n/ro.po
-
2615account_financial_report/i18n/sl.po
-
1account_financial_report/models/__init__.py
-
20account_financial_report/models/account_group.py
-
10account_financial_report/models/account_move_line.py
-
25account_financial_report/models/ir_actions_report.py
-
9account_financial_report/readme/CONTRIBUTORS.rst
-
1account_financial_report/readme/ROADMAP.rst
-
1account_financial_report/report/__init__.py
-
25account_financial_report/report/abstract_report.py
-
208account_financial_report/report/abstract_report_xlsx.py
-
1051account_financial_report/report/aged_partner_balance.py
-
153account_financial_report/report/aged_partner_balance_xlsx.py
-
2535account_financial_report/report/general_ledger.py
-
269account_financial_report/report/general_ledger_xlsx.py
-
1039account_financial_report/report/journal_ledger.py
-
123account_financial_report/report/journal_ledger_xlsx.py
-
1291account_financial_report/report/open_items.py
-
160account_financial_report/report/open_items_xlsx.py
-
595account_financial_report/report/templates/aged_partner_balance.xml
-
481account_financial_report/report/templates/general_ledger.xml
-
200account_financial_report/report/templates/journal_ledger.xml
-
412account_financial_report/report/templates/open_items.xml
-
1125account_financial_report/report/templates/trial_balance.xml
-
217account_financial_report/report/templates/vat_report.xml
-
1288account_financial_report/report/trial_balance.py
-
129account_financial_report/report/trial_balance_xlsx.py
-
573account_financial_report/report/vat_report.py
-
41account_financial_report/report/vat_report_xlsx.py
-
134account_financial_report/reports.xml
-
70account_financial_report/static/description/index.html
-
33account_financial_report/static/src/js/account_financial_report_backend.js
-
4account_financial_report/tests/__init__.py
-
444account_financial_report/tests/abstract_test.py
-
94account_financial_report/tests/abstract_test_foreign_currency.py
-
89account_financial_report/tests/abstract_test_tax_report.py
-
41account_financial_report/tests/test_aged_partner_balance.py
-
608account_financial_report/tests/test_general_ledger.py
-
366account_financial_report/tests/test_journal_ledger.py
-
39account_financial_report/tests/test_open_items.py
-
770account_financial_report/tests/test_trial_balance.py
-
410account_financial_report/tests/test_vat_report.py
-
30account_financial_report/view/report_template.xml
-
0account_financial_report/view/report_vat_report.xml
-
9account_financial_report/wizard/abstract_wizard.py
-
108account_financial_report/wizard/aged_partner_balance_wizard.py
-
23account_financial_report/wizard/aged_partner_balance_wizard_view.xml
-
174account_financial_report/wizard/general_ledger_wizard.py
-
114account_financial_report/wizard/general_ledger_wizard_view.xml
-
100account_financial_report/wizard/journal_ledger_wizard.py
-
101account_financial_report/wizard/open_items_wizard.py
-
20account_financial_report/wizard/open_items_wizard_view.xml
-
109account_financial_report/wizard/trial_balance_wizard.py
-
18account_financial_report/wizard/trial_balance_wizard_view.xml
-
49account_financial_report/wizard/vat_report_wizard.py
-
9account_financial_report/wizard/vat_report_wizard_view.xml
1749
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
1852
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
1726
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
2611
account_financial_report/i18n/da.po
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2120
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
1824
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
1785
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
1914
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
1899
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
1852
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
1704
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
1969
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
1678
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
1968
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
1693
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
2133
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
2052
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
2028
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
2615
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,4 +1,3 @@ |
|||
from . import account |
|||
from . import account_group |
|||
from . import account_move_line |
|||
from . import ir_actions_report |
@ -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) |
@ -0,0 +1,25 @@ |
|||
# Copyright 2018 Camptocamp SA |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
from psycopg2.extensions import AsIs |
|||
|
|||
from odoo import models |
|||
|
|||
|
|||
class AbstractReport(models.AbstractModel): |
|||
_name = "account_financial_report_abstract" |
|||
_description = "Abstract Report" |
|||
|
|||
def _transient_clean_rows_older_than(self, seconds): |
|||
assert self._transient, ( |
|||
"Model %s is not transient, it cannot be vacuumed!" % self._name |
|||
) |
|||
# Never delete rows used in last 5 minutes |
|||
seconds = max(seconds, 300) |
|||
query = ( |
|||
"DELETE FROM %s" |
|||
" WHERE COALESCE(" |
|||
"write_date, create_date, (now() at time zone 'UTC'))" |
|||
"::timestamp < ((now() at time zone 'UTC') - interval %s)" |
|||
) |
|||
self.env.cr.execute(query, (AsIs(self._table), "%s seconds" % seconds)) |
1051
account_financial_report/report/aged_partner_balance.py
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2535
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
1039
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
1291
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
1125
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
1288
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,234 +1,361 @@ |
|||
# Copyright 2018 Forest and Biomass Romania |
|||
# Copyright 2020 ForgeFlow S.L. (https://www.forgeflow.com) |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import operator |
|||
|
|||
from odoo import api, models |
|||
|
|||
|
|||
class VATReport(models.AbstractModel): |
|||
_name = "report.account_financial_report.vat_report" |
|||
_description = "Vat Report Report" |
|||
|
|||
def _get_tax_data(self, tax_ids): |
|||
taxes = self.env["account.tax"].browse(tax_ids) |
|||
tax_data = {} |
|||
for tax in taxes: |
|||
tax_data.update( |
|||
{ |
|||
tax.id: { |
|||
"id": tax.id, |
|||
"name": tax.name, |
|||
"tax_group_id": tax.tax_group_id.id, |
|||
"type_tax_use": tax.type_tax_use, |
|||
"amount_type": tax.amount_type, |
|||
"tags_ids": tax.invoice_repartition_line_ids.tag_ids.ids, |
|||
} |
|||
} |
|||
) |
|||
return tax_data |
|||
from odoo import api, fields, models |
|||
|
|||
@api.model |
|||
def _get_tax_report_domain(self, company_id, date_from, date_to, only_posted_moves): |
|||
domain = [ |
|||
("company_id", "=", company_id), |
|||
("date", ">=", date_from), |
|||
("date", "<=", date_to), |
|||
("tax_line_id", "!=", False), |
|||
("tax_exigible", "=", True), |
|||
] |
|||
if only_posted_moves: |
|||
domain += [("move_id.state", "=", "posted")] |
|||
return domain |
|||
|
|||
class VATReport(models.TransientModel): |
|||
_name = "report_vat_report" |
|||
_description = "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", |
|||
string="Taxes", |
|||
) |
|||
|
|||
|
|||
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, string="Tax ID",) |
|||
|
|||
# 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" |
|||
|
|||
def print_report(self, report_type="qweb"): |
|||
self.ensure_one() |
|||
if report_type == "xlsx": |
|||
report_name = "a_f_r.report_vat_report_xlsx" |
|||
else: |
|||
report_name = "account_financial_report.report_vat_report_qweb" |
|||
context = dict(self.env.context) |
|||
action = self.env["ir.actions.report"].search( |
|||
[("report_name", "=", report_name), ("report_type", "=", report_type)], |
|||
limit=1, |
|||
) |
|||
return action.with_context(context).report_action(self, config=False) |
|||
|
|||
def _get_html(self): |
|||
result = {} |
|||
rcontext = {} |
|||
context = dict(self.env.context) |
|||
report = self.browse(context.get("active_id")) |
|||
if report: |
|||
rcontext["o"] = report |
|||
result["html"] = self.env.ref( |
|||
"account_financial_report.report_vat_report" |
|||
).render(rcontext) |
|||
return result |
|||
|
|||
@api.model |
|||
def _get_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")] |
|||
return domain |
|||
|
|||
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 |
|||
def get_html(self, given_context=None): |
|||
return self.with_context(given_context)._get_html() |
|||
|
|||
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 |
|||
) |
|||
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, |
|||
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, |
|||
) |
|||
net_domain = self._get_net_report_domain( |
|||
company_id, date_from, date_to, only_posted_moves |
|||
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, |
|||
) |
|||
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 |
|||
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 |
|||
) |
|||
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, |
|||
"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) |
|||
|
|||
def _inject_tax_taxgroups_values(self): |
|||
""" Inject report values for report_vat_report_tax. """ |
|||
# pylint: disable=sql-injection |
|||
query_inject_tax = """ |
|||
WITH |
|||
taxtags_tax AS |
|||
( |
|||
SELECT |
|||
taxtag.id AS report_tax_id, ' ' AS code, |
|||
tax.name, tax.id, |
|||
coalesce(sum(movetax.tax_base_amount), 0.00) AS net, |
|||
coalesce(sum(movetax.balance), 0.00) AS tax |
|||
FROM |
|||
report_vat_report_taxtag AS taxtag |
|||
INNER JOIN account_tax AS tax |
|||
ON tax.tax_group_id = taxtag.taxgroup_id |
|||
INNER JOIN account_move_line AS movetax |
|||
ON movetax.tax_line_id = tax.id |
|||
INNER JOIN account_move AS move |
|||
ON move.id = movetax.move_id |
|||
WHERE taxtag.id is not null AND movetax.tax_exigible |
|||
AND taxtag.report_id = %s AND move.company_id = %s |
|||
AND move.date >= %s AND move.date <= %s |
|||
AND move.state = 'posted' |
|||
GROUP BY taxtag.id, tax.id |
|||
ORDER BY tax.name |
|||
) |
|||
INSERT INTO |
|||
report_vat_report_tax |
|||
( |
|||
report_tax_id, |
|||
create_uid, |
|||
create_date, |
|||
tax_id, |
|||
name, |
|||
net, |
|||
tax |
|||
) |
|||
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,444 @@ |
|||
# Author: Julien Coux |
|||
# Copyright 2016 Camptocamp SA |
|||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). |
|||
|
|||
import logging |
|||
|
|||
from odoo.tests import common |
|||
from odoo.tools import test_reports |
|||
|
|||
_logger = logging.getLogger(__name__) |
|||
|
|||
|
|||
class AbstractTest(common.TransactionCase): |
|||
"""Common technical tests for all reports.""" |
|||
|
|||
at_install = False |
|||
post_install = True |
|||
|
|||
accounts = {} |
|||
|
|||
def with_context(self, *args, **kwargs): |
|||
context = dict(args[0] if args else self.env.context, **kwargs) |
|||
self.env = self.env(context=context) |
|||
return self |
|||
|
|||
def _chart_template_create(self): |
|||
transfer_account_id = self.env["account.account.template"].create( |
|||
{ |
|||
"code": "000", |
|||
"name": "Liquidity Transfers", |
|||
"reconcile": True, |
|||
"user_type_id": self.ref("account.data_account_type_current_assets"), |
|||
} |
|||
) |
|||
self.chart = self.env["account.chart.template"].create( |
|||
{ |
|||
"name": "Test COA", |
|||
"code_digits": 4, |
|||
"bank_account_code_prefix": 1014, |
|||
"cash_account_code_prefix": 1014, |
|||
"currency_id": self.ref("base.USD"), |
|||
"transfer_account_code_prefix": "000", |
|||
} |
|||
) |
|||
transfer_account_id.update( |
|||
{"chart_template_id": self.chart.id,} |
|||
) |
|||
self.env["ir.model.data"].create( |
|||
{ |
|||
"res_id": transfer_account_id.id, |
|||
"model": transfer_account_id._name, |
|||
"name": "Liquidity Transfers", |
|||
} |
|||
) |
|||
act = self.env["account.account.template"].create( |
|||
{ |
|||
"code": "001", |
|||
"name": "Expenses", |
|||
"user_type_id": self.ref("account.data_account_type_expenses"), |
|||
"chart_template_id": self.chart.id, |
|||
"reconcile": True, |
|||
} |
|||
) |
|||
self.env["ir.model.data"].create( |
|||
{"res_id": act.id, "model": act._name, "name": "expenses",} |
|||
) |
|||
act = self.env["account.account.template"].create( |
|||
{ |
|||
"code": "002", |
|||
"name": "Product Sales", |
|||
"user_type_id": self.ref("account.data_account_type_revenue"), |
|||
"chart_template_id": self.chart.id, |
|||
"reconcile": True, |
|||
} |
|||
) |
|||
self.env["ir.model.data"].create( |
|||
{"res_id": act.id, "model": act._name, "name": "sales",} |
|||
) |
|||
act = self.env["account.account.template"].create( |
|||
{ |
|||
"code": "003", |
|||
"name": "Account Receivable", |
|||
"user_type_id": self.ref("account.data_account_type_receivable"), |
|||
"chart_template_id": self.chart.id, |
|||
"reconcile": True, |
|||
} |
|||
) |
|||
self.env["ir.model.data"].create( |
|||
{"res_id": act.id, "model": act._name, "name": "receivable",} |
|||
) |
|||
act = self.env["account.account.template"].create( |
|||
{ |
|||
"code": "004", |
|||
"name": "Account Payable", |
|||
"user_type_id": self.ref("account.data_account_type_payable"), |
|||
"chart_template_id": self.chart.id, |
|||
"reconcile": True, |
|||
} |
|||
) |
|||
self.env["ir.model.data"].create( |
|||
{"res_id": act.id, "model": act._name, "name": "payable",} |
|||
) |
|||
|
|||
def _add_chart_of_accounts(self): |
|||
self.company = self.env["res.company"].create({"name": "Spanish test company",}) |
|||
self.env.ref("base.group_multi_company").write( |
|||
{"users": [(4, self.env.uid)],} |
|||
) |
|||
self.env.user.write( |
|||
{"company_ids": [(4, self.company.id)], "company_id": self.company.id,} |
|||
) |
|||
self.with_context(company_id=self.company.id, force_company=self.company.id) |
|||
self.chart.try_loading_for_current_company() |
|||
self.revenue = self.env["account.account"].search( |
|||
[("user_type_id", "=", self.ref("account.data_account_type_revenue"))], |
|||
limit=1, |
|||
) |
|||
self.expense = self.env["account.account"].search( |
|||
[("user_type_id", "=", self.ref("account.data_account_type_expenses"))], |
|||
limit=1, |
|||
) |
|||
self.receivable = self.env["account.account"].search( |
|||
[("user_type_id", "=", self.ref("account.data_account_type_receivable"))], |
|||
limit=1, |
|||
) |
|||
self.payable = self.env["account.account"].search( |
|||
[("user_type_id", "=", self.ref("account.data_account_type_payable"))], |
|||
limit=1, |
|||
) |
|||
return True |
|||
|
|||
def _journals_create(self): |
|||
self.journal_sale = self.env["account.journal"].create( |
|||
{ |
|||
"company_id": self.company.id, |
|||
"name": "Test journal for sale", |
|||
"type": "sale", |
|||
"code": "TSALE", |
|||
"default_debit_account_id": self.revenue.id, |
|||
"default_credit_account_id": self.revenue.id, |
|||
} |
|||
) |
|||
self.journal_purchase = self.env["account.journal"].create( |
|||
{ |
|||
"company_id": self.company.id, |
|||
"name": "Test journal for purchase", |
|||
"type": "purchase", |
|||
"code": "TPUR", |
|||
"default_debit_account_id": self.expense.id, |
|||
"default_credit_account_id": self.expense.id, |
|||
} |
|||
) |
|||
return True |
|||
|
|||
def _invoice_create(self): |
|||
self.partner = self.env["res.partner"].create( |
|||
{ |
|||
"name": "Test partner", |
|||
"company_id": self.company.id, |
|||
"property_account_receivable_id": self.receivable.id, |
|||
"property_account_payable_id": self.payable.id, |
|||
} |
|||
) |
|||
|
|||
# customer invoice |
|||
customer_invoice_lines = [ |
|||
( |
|||
0, |
|||
False, |
|||
{ |
|||
"name": "Test description #1", |
|||
"account_id": self.revenue.id, |
|||
"quantity": 1.0, |
|||
"price_unit": 100.0, |
|||
}, |
|||
), |
|||
( |
|||
0, |
|||
False, |
|||
{ |
|||
"name": "Test description #2", |
|||
"account_id": self.revenue.id, |
|||
"quantity": 2.0, |
|||
"price_unit": 25.0, |
|||
}, |
|||
), |
|||
] |
|||
self.invoice_out = self.env["account.invoice"].create( |
|||
{ |
|||
"partner_id": self.partner.id, |
|||
"type": "out_invoice", |
|||
"invoice_line_ids": customer_invoice_lines, |
|||
"account_id": self.partner.property_account_receivable_id.id, |
|||
"journal_id": self.journal_sale.id, |
|||
} |
|||
) |
|||
self.invoice_out.action_invoice_open() |
|||
|
|||
# vendor bill |
|||
vendor_invoice_lines = [ |
|||
( |
|||
0, |
|||
False, |
|||
{ |
|||
"name": "Test description #1", |
|||
"account_id": self.revenue.id, |
|||
"quantity": 1.0, |
|||
"price_unit": 100.0, |
|||
}, |
|||
), |
|||
( |
|||
0, |
|||
False, |
|||
{ |
|||
"name": "Test description #2", |
|||
"account_id": self.revenue.id, |
|||
"quantity": 2.0, |
|||
"price_unit": 25.0, |
|||
}, |
|||
), |
|||
] |
|||
self.invoice_in = self.env["account.invoice"].create( |
|||
{ |
|||
"partner_id": self.partner.id, |
|||
"type": "in_invoice", |
|||
"invoice_line_ids": vendor_invoice_lines, |
|||
"account_id": self.partner.property_account_payable_id.id, |
|||
"journal_id": self.journal_purchase.id, |
|||
} |
|||
) |
|||
self.invoice_in.action_invoice_open() |
|||
|
|||
def setUp(self): |
|||
super(AbstractTest, self).setUp() |
|||
|
|||
self.with_context() |
|||
self._chart_template_create() |
|||
self._add_chart_of_accounts() |
|||
self._journals_create() |
|||
self._invoice_create() |
|||
|
|||
self.model = self._getReportModel() |
|||
|
|||
self.qweb_report_name = self._getQwebReportName() |
|||
self.xlsx_report_name = self._getXlsxReportName() |
|||
self.xlsx_action_name = self._getXlsxReportActionName() |
|||
|
|||
self.report_title = self._getReportTitle() |
|||
|
|||
self.base_filters = self._getBaseFilters() |
|||
self.additional_filters = self._getAdditionalFiltersToBeTested() |
|||
|
|||
self.report = self.model.create(self.base_filters) |
|||
self.report.compute_data_for_report() |
|||
|
|||
def test_html(self): |
|||
test_reports.try_report( |
|||
self.env.cr, |
|||
self.env.uid, |
|||
self.qweb_report_name, |
|||
[self.report.id], |
|||
report_type="qweb-html", |
|||
) |
|||
|
|||
def test_qweb(self): |
|||
test_reports.try_report( |
|||
self.env.cr, |
|||
self.env.uid, |
|||
self.qweb_report_name, |
|||
[self.report.id], |
|||
report_type="qweb-pdf", |
|||
) |
|||
|
|||
def test_xlsx(self): |
|||
test_reports.try_report( |
|||
self.env.cr, |
|||
self.env.uid, |
|||
self.xlsx_report_name, |
|||
[self.report.id], |
|||
report_type="xlsx", |
|||
) |
|||
|
|||
def test_print(self): |
|||
self.report.print_report("qweb") |
|||
self.report.print_report("xlsx") |
|||
|
|||
def test_02_generation_report_html(self): |
|||
"""Check if report HTML is correctly generated""" |
|||
|
|||
# Check if returned report action is correct |
|||
report_type = "qweb-html" |
|||
report_action = self.report.print_report(report_type) |
|||
self.assertDictContainsSubset( |
|||
{ |
|||
"type": "ir.actions.report", |
|||
"report_name": self.qweb_report_name, |
|||
"report_type": "qweb-html", |
|||
}, |
|||
report_action, |
|||
) |
|||
|
|||
# Check if report template is correct |
|||
report = self.env["ir.actions.report"].search( |
|||
[ |
|||
("report_name", "=", self.qweb_report_name), |
|||
("report_type", "=", report_type), |
|||
], |
|||
limit=1, |
|||
) |
|||
self.assertEqual(report.report_type, "qweb-html") |
|||
|
|||
rep = report.render(self.report.ids, {}) |
|||
|
|||
self.assertTrue(self.report_title.encode("utf8") in rep[0]) |
|||
self.assertTrue(self.report.account_ids[0].name.encode("utf8") in rep[0]) |
|||
|
|||
def test_04_compute_data(self): |
|||
"""Check that the SQL queries work with all filters options""" |
|||
|
|||
for filters in [{}] + self.additional_filters: |
|||
current_filter = self.base_filters.copy() |
|||
current_filter.update(filters) |
|||
|
|||
report = self.model.create(current_filter) |
|||
report.compute_data_for_report() |
|||
|
|||
self.assertGreaterEqual(len(report.account_ids), 1) |
|||
|
|||
# Same filters with only one account |
|||
current_filter = self.base_filters.copy() |
|||
current_filter.update(filters) |
|||
report_accounts = report.account_ids.filtered("account_id") |
|||
current_filter.update( |
|||
{"filter_account_ids": [(6, 0, report_accounts[0].account_id.ids)],} |
|||
) |
|||
|
|||
report2 = self.model.create(current_filter) |
|||
report2.compute_data_for_report() |
|||
|
|||
self.assertEqual(len(report2.account_ids), 1) |
|||
self.assertEqual(report2.account_ids.name, report_accounts[0].name) |
|||
|
|||
if self._partner_test_is_possible(filters): |
|||
# Same filters with only one partner |
|||
report_partner_ids = report.account_ids.mapped("partner_ids") |
|||
partner_ids = report_partner_ids.mapped("partner_id") |
|||
|
|||
current_filter = self.base_filters.copy() |
|||
current_filter.update(filters) |
|||
current_filter.update( |
|||
{"filter_partner_ids": [(6, 0, partner_ids[0].ids)],} |
|||
) |
|||
|
|||
report3 = self.model.create(current_filter) |
|||
report3.compute_data_for_report() |
|||
|
|||
self.assertGreaterEqual(len(report3.account_ids), 1) |
|||
|
|||
report_partner_ids3 = report3.account_ids.mapped("partner_ids") |
|||
partner_ids3 = report_partner_ids3.mapped("partner_id") |
|||
|
|||
self.assertEqual(len(partner_ids3), 1) |
|||
self.assertEqual(partner_ids3.name, partner_ids[0].name) |
|||
|
|||
# Same filters with only one partner and one account |
|||
report_partner_ids = report3.account_ids.mapped("partner_ids") |
|||
report_account_id = report_partner_ids.filtered(lambda p: p.partner_id)[ |
|||
0 |
|||
].report_account_id |
|||
|
|||
current_filter = self.base_filters.copy() |
|||
current_filter.update(filters) |
|||
current_filter.update( |
|||
{ |
|||
"filter_account_ids": [ |
|||
(6, 0, report_account_id.account_id.ids) |
|||
], |
|||
"filter_partner_ids": [(6, 0, partner_ids[0].ids)], |
|||
} |
|||
) |
|||
|
|||
report4 = self.model.create(current_filter) |
|||
report4.compute_data_for_report() |
|||
|
|||
self.assertEqual(len(report4.account_ids), 1) |
|||
self.assertEqual( |
|||
report4.account_ids.name, report_account_id.account_id.name |
|||
) |
|||
|
|||
report_partner_ids4 = report4.account_ids.mapped("partner_ids") |
|||
partner_ids4 = report_partner_ids4.mapped("partner_id") |
|||
|
|||
self.assertEqual(len(partner_ids4), 1) |
|||
self.assertEqual(partner_ids4.name, partner_ids[0].name) |
|||
|
|||
def _partner_test_is_possible(self, filters): |
|||
""" |
|||
:return: |
|||
a boolean to indicate if partner test is possible |
|||
with current filters |
|||
""" |
|||
return True |
|||
|
|||
def _getReportModel(self): |
|||
""" |
|||
:return: the report model name |
|||
""" |
|||
raise NotImplementedError() |
|||
|
|||
def _getQwebReportName(self): |
|||
""" |
|||
:return: the qweb report name |
|||
""" |
|||
raise NotImplementedError() |
|||
|
|||
def _getXlsxReportName(self): |
|||
""" |
|||
:return: the xlsx report name |
|||
""" |
|||
raise NotImplementedError() |
|||
|
|||
def _getXlsxReportActionName(self): |
|||
""" |
|||
:return: the xlsx report action name |
|||
""" |
|||
raise NotImplementedError() |
|||
|
|||
def _getReportTitle(self): |
|||
""" |
|||
:return: the report title displayed into the report |
|||
""" |
|||
raise NotImplementedError() |
|||
|
|||
def _getBaseFilters(self): |
|||
""" |
|||
:return: the minimum required filters to generate report |
|||
""" |
|||
raise NotImplementedError() |
|||
|
|||
def _getAdditionalFiltersToBeTested(self): |
|||
""" |
|||
:return: the additional filters to generate report variants |
|||
""" |
|||
raise NotImplementedError() |
@ -0,0 +1,94 @@ |
|||
# 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,89 @@ |
|||
# 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). |
|||
|
|||
from datetime import date |
|||
|
|||
from . import abstract_test |
|||
|
|||
|
|||
class TestAgedPartnerBalance(abstract_test.AbstractTest): |
|||
""" |
|||
Technical tests for Aged Partner Balance Report. |
|||
""" |
|||
|
|||
def _getReportModel(self): |
|||
return self.env["report_aged_partner_balance"] |
|||
|
|||
def _getQwebReportName(self): |
|||
return "account_financial_report.report_aged_partner_balance_qweb" |
|||
|
|||
def _getXlsxReportName(self): |
|||
return "a_f_r.report_aged_partner_balance_xlsx" |
|||
|
|||
def _getXlsxReportActionName(self): |
|||
return "account_financial_report." "action_report_aged_partner_balance_xlsx" |
|||
|
|||
def _getReportTitle(self): |
|||
return "Odoo" |
|||
|
|||
def _getBaseFilters(self): |
|||
return { |
|||
"date_at": date(date.today().year, 12, 31), |
|||
"company_id": self.company.id, |
|||
} |
|||
|
|||
def _getAdditionalFiltersToBeTested(self): |
|||
return [ |
|||
{"only_posted_moves": True}, |
|||
{"show_move_line_details": True}, |
|||
{"only_posted_moves": True, "show_move_line_details": True}, |
|||
] |
770
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
Write
Preview
Loading…
Cancel
Save
Reference in new issue