mirror of
https://github.com/bringout/oca-ocb-report.git
synced 2026-04-21 18:21:59 +02:00
19.0 vanilla
This commit is contained in:
parent
62d197ac8b
commit
184bb0e321
667 changed files with 691406 additions and 239886 deletions
|
|
@ -2,3 +2,8 @@
|
|||
|
||||
from . import test_currency
|
||||
from . import test_currency_rate
|
||||
from . import test_display_names
|
||||
from . import test_ir_model
|
||||
from . import test_locale
|
||||
from . import test_session_info
|
||||
from . import test_utils
|
||||
|
|
|
|||
|
|
@ -28,38 +28,6 @@ class TestCurrencyRates(TransactionCase):
|
|||
cls.env.user.company_id = eur_company
|
||||
cls.usd_company_id = usd_company.id
|
||||
|
||||
def test_get_currencies_for_spreadsheet(self):
|
||||
self.assertEqual(
|
||||
self.env["res.currency"].get_currencies_for_spreadsheet(["MC1", "MC2"]),
|
||||
[
|
||||
{
|
||||
"code": "MC1",
|
||||
"symbol": ":D",
|
||||
"decimalPlaces": 3,
|
||||
"position": "after",
|
||||
},
|
||||
{
|
||||
"code": "MC2",
|
||||
"symbol": "§",
|
||||
"decimalPlaces": 2,
|
||||
"position": "after",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
self.env["res.currency"].get_currencies_for_spreadsheet(["ProbablyNotACurrencyName?", "MC2"]),
|
||||
[
|
||||
None,
|
||||
{
|
||||
"code": "MC2",
|
||||
"symbol": "§",
|
||||
"decimalPlaces": 2,
|
||||
"position": "after",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
def test_get_company_currency_for_spreadsheet(self):
|
||||
self.assertEqual(
|
||||
self.env["res.currency"].get_company_currency_for_spreadsheet(),
|
||||
|
|
|
|||
|
|
@ -50,33 +50,33 @@ class TestCurrencyRates(TransactionCase):
|
|||
)
|
||||
|
||||
def test_currency_without_date(self):
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet("USD", "EUR"),
|
||||
CURRENT_EUR / CURRENT_USD,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet("EUR", "USD"),
|
||||
CURRENT_USD,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet("USD", "CAD"),
|
||||
CURRENT_CAD / CURRENT_USD,
|
||||
)
|
||||
|
||||
def test_currency_with_date(self):
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet(
|
||||
"USD", "EUR", "2021-11-11"
|
||||
),
|
||||
CURRENT_EUR / USD_11,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet(
|
||||
"EUR", "USD", "2021-11-11"
|
||||
),
|
||||
USD_11,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet(
|
||||
"USD", "CAD", "2021-11-11"
|
||||
),
|
||||
|
|
@ -109,8 +109,11 @@ class TestCurrencyRates(TransactionCase):
|
|||
|
||||
@freeze_time(fake_now_utc)
|
||||
def test_rate_by_tz(self):
|
||||
# after setting a timezone, reset the transaction to recomput env.tz
|
||||
cad = self.env.ref("base.CAD")
|
||||
self.env.user.tz = "UTC"
|
||||
self.env.flush_all()
|
||||
self.env.transaction.reset()
|
||||
self.env["res.currency.rate"].create(
|
||||
{
|
||||
"currency_id": cad.id,
|
||||
|
|
@ -118,19 +121,60 @@ class TestCurrencyRates(TransactionCase):
|
|||
}
|
||||
)
|
||||
self.env.user.tz = "Australia/Sydney"
|
||||
self.env.flush_all()
|
||||
self.env.transaction.reset()
|
||||
self.env["res.currency.rate"].create(
|
||||
{
|
||||
"currency_id": cad.id,
|
||||
"rate": CAD_AUS,
|
||||
}
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet("CAD", "EUR"),
|
||||
CURRENT_EUR / CAD_AUS,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]
|
||||
.with_context(tz="UTC")
|
||||
._get_rate_for_spreadsheet("CAD", "EUR"),
|
||||
CURRENT_EUR / CAD_UTC,
|
||||
)
|
||||
|
||||
def test_currency_with_company_id(self):
|
||||
usd = self.env.ref("base.USD")
|
||||
cad = self.env.ref("base.CAD")
|
||||
company_eur = self.env["res.company"].create({"currency_id": usd.id, "name": "EUR"})
|
||||
company_cad = self.env["res.company"].create({"currency_id": cad.id, "name": "GBP"})
|
||||
self.env["res.currency.rate"].create(
|
||||
[
|
||||
{
|
||||
"currency_id": usd.id,
|
||||
"rate": 0.5,
|
||||
"company_id": company_eur.id,
|
||||
},
|
||||
{
|
||||
"currency_id": usd.id,
|
||||
"rate": 0.8,
|
||||
"company_id": company_cad.id,
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"].with_company(company_eur)._get_rate_for_spreadsheet(
|
||||
"USD", "EUR", None, None
|
||||
),
|
||||
CURRENT_EUR / 0.5,
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet(
|
||||
"USD", "EUR", None, company_eur.id
|
||||
),
|
||||
CURRENT_EUR / 0.5,
|
||||
)
|
||||
self.assertAlmostEqual(
|
||||
self.env["res.currency.rate"]._get_rate_for_spreadsheet(
|
||||
"USD", "CAD", None, company_cad.id
|
||||
),
|
||||
CURRENT_EUR / 0.8,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
from odoo.tests.common import TransactionCase, new_test_user
|
||||
|
||||
|
||||
class TestDisplayNames(TransactionCase):
|
||||
|
||||
def test_get_single_display_name(self):
|
||||
bob = self.env["res.partner"].create({"name": "Bob"})
|
||||
display_name = self.env["spreadsheet.mixin"].get_display_names_for_spreadsheet([{"model": "res.partner", "id": bob.id}])
|
||||
self.assertEqual(display_name, ["Bob"])
|
||||
|
||||
def test_get_archived_record_display_name(self):
|
||||
bob = self.env["res.partner"].create({"name": "Bob", "active": False})
|
||||
display_name = self.env["spreadsheet.mixin"].get_display_names_for_spreadsheet([{"model": "res.partner", "id": bob.id}])
|
||||
self.assertEqual(display_name, ["Bob"])
|
||||
|
||||
def test_two_single_display_name(self):
|
||||
alice = self.env["res.partner"].create({"name": "Alice"})
|
||||
bob = self.env["res.partner"].create({"name": "Bob"})
|
||||
display_name = self.env["spreadsheet.mixin"].get_display_names_for_spreadsheet([
|
||||
{"model": "res.partner", "id": alice.id},
|
||||
{"model": "res.partner", "id": bob.id}
|
||||
])
|
||||
self.assertEqual(display_name, ["Alice", "Bob"])
|
||||
|
||||
def test_get_missing_id_display_name(self):
|
||||
self.assertFalse(self.env["res.partner"].browse(9999).exists())
|
||||
display_name = self.env["spreadsheet.mixin"].get_display_names_for_spreadsheet([
|
||||
{"model": "res.partner", "id": 9999}
|
||||
])
|
||||
self.assertEqual(display_name, [None])
|
||||
|
||||
def test_get_mix_missing_correct_ids_display_name(self):
|
||||
bob = self.env["res.partner"].create({"name": "Bob"})
|
||||
display_name = self.env["spreadsheet.mixin"].get_display_names_for_spreadsheet([
|
||||
{"model": "res.partner", "id": bob.id},
|
||||
{"model": "res.partner", "id": 9999},
|
||||
])
|
||||
self.assertEqual(display_name, ["Bob", None])
|
||||
|
||||
def test_mixed_model_display_name(self):
|
||||
alice = new_test_user(self.env, login="alice", name="Alice")
|
||||
bob = self.env["res.partner"].create({"name": "Bob"})
|
||||
display_name = self.env["spreadsheet.mixin"].get_display_names_for_spreadsheet([
|
||||
{"model": "res.users", "id": alice.id},
|
||||
{"model": "res.partner", "id": bob.id}
|
||||
])
|
||||
self.assertEqual(display_name, ["Alice", "Bob"])
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
|
||||
class SpreadsheetIrModel(TransactionCase):
|
||||
|
||||
def test_has_searchable_parent_not_stored(self):
|
||||
self.assertEqual(self.env['ir.model'].has_searchable_parent_relation(['res.users']), {'res.users': False})
|
||||
|
||||
def test_has_searchable_parent_stored(self):
|
||||
self.assertEqual(self.env['ir.model'].has_searchable_parent_relation(['ir.ui.menu']), {'ir.ui.menu': True})
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
from odoo.tests.common import TransactionCase
|
||||
from odoo.addons.spreadsheet.utils.formatting import (
|
||||
strftime_format_to_spreadsheet_time_format,
|
||||
strftime_format_to_spreadsheet_date_format,
|
||||
)
|
||||
|
||||
|
||||
class TestLocale(TransactionCase):
|
||||
def test_time_format_conversion(self):
|
||||
# Simple format
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%H:%M:%S"), "hh:mm:ss")
|
||||
|
||||
# AM/PM
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%I:%M:%S"), "hh:mm:ss a")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%H:%M:%S %p"), "hh:mm:ss a")
|
||||
|
||||
# Separator
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%H %M %S"), "hh mm ss")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%H %M:%S"), "hh mm ss")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%H-%M-%S"), "hh:mm:ss")
|
||||
|
||||
# Escaped characters are ignored
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%H시 %M분 %S초"), "hh mm ss")
|
||||
|
||||
# Unsupported format code are ignored
|
||||
self.assertEqual(strftime_format_to_spreadsheet_time_format("%H:%M:%S %f %z"), "hh:mm:ss")
|
||||
|
||||
def test_date_format_conversion(self):
|
||||
# Simple format
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%m/%d/%Y"), "mm/dd/yyyy")
|
||||
|
||||
# Various formats code
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%b/%a/%y"), "mmm/ddd/yy")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%B/%A/%Y"), "mmmm/dddd/yyyy")
|
||||
|
||||
# Separator
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%m %d %Y"), "mm dd yyyy")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%m-%d-%Y"), "mm-dd-yyyy")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%m/%d/%Y"), "mm/dd/yyyy")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%m-%d/%Y"), "mm-dd-yyyy")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%m.%d.%Y"), "mm/dd/yyyy")
|
||||
|
||||
# Escaped characters are ignored
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%a, %Y.eko %bren %da"), "ddd yyyy mmm dd")
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%Y년 %m월 %d일"), "yyyy mm dd")
|
||||
|
||||
# Unsupported format code are ignored
|
||||
self.assertEqual(strftime_format_to_spreadsheet_date_format("%w %x %Z %j %m %d %Y"), "mm dd yyyy")
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
import json
|
||||
from uuid import uuid4
|
||||
|
||||
from odoo.tests import common
|
||||
|
||||
|
||||
class TestSessionInfo(common.HttpCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.user_password = "password"
|
||||
cls.user = common.new_test_user(
|
||||
cls.env,
|
||||
"user",
|
||||
email="user@in.fo",
|
||||
password=cls.user_password,
|
||||
tz="UTC")
|
||||
|
||||
cls.payload = json.dumps(
|
||||
dict(jsonrpc="2.0", method="call", id=str(uuid4())))
|
||||
cls.headers = {
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
def test_session_info(self):
|
||||
"""
|
||||
Checks that the session_info['can_insert_in_spreadsheet'] structure
|
||||
correspond to what is expected
|
||||
"""
|
||||
self.authenticate(self.user.login, self.user_password)
|
||||
response = self.url_open(
|
||||
"/web/session/get_session_info", data=self.payload, headers=self.headers)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
data = response.json()
|
||||
session_info = data["result"]
|
||||
|
||||
self.assertEqual(
|
||||
session_info["can_insert_in_spreadsheet"],
|
||||
False,
|
||||
"The session_info['can_insert_in_spreadsheet'] should be False")
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import datetime
|
||||
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
from odoo.addons.spreadsheet.utils.formatting import (
|
||||
date_to_spreadsheet_date_number,
|
||||
datetime_to_spreadsheet_date_number,
|
||||
)
|
||||
from odoo.addons.spreadsheet.utils.json import extend_serialized_json
|
||||
|
||||
|
||||
class TestSpreadsheetUtils(TransactionCase):
|
||||
|
||||
def test_extend_serialized_json(self):
|
||||
self.assertEqual(extend_serialized_json('{}', []), '{}')
|
||||
self.assertEqual(extend_serialized_json('{}', [('key', '{}')]), '{"key":{}}')
|
||||
self.assertEqual(extend_serialized_json('{}', [('key', '[]')]), '{"key":[]}')
|
||||
self.assertEqual(
|
||||
extend_serialized_json('{}', [('key', '"value"')]),
|
||||
'{"key":"value"}'
|
||||
)
|
||||
self.assertEqual(
|
||||
extend_serialized_json('{"a": 1}', [('key', '"value"')]),
|
||||
'{"a": 1,"key":"value"}'
|
||||
)
|
||||
self.assertEqual(
|
||||
extend_serialized_json('{"a": 1}', [('key', '{"b": 2}')]),
|
||||
'{"a": 1,"key":{"b": 2}}'
|
||||
)
|
||||
self.assertEqual(
|
||||
extend_serialized_json('{"a": {}}', [('key', '{"b": 2}')]),
|
||||
'{"a": {},"key":{"b": 2}}'
|
||||
)
|
||||
self.assertEqual(
|
||||
extend_serialized_json('{"a": 1}', [('key', '[]')]),
|
||||
'{"a": 1,"key":[]}'
|
||||
)
|
||||
self.assertEqual(
|
||||
extend_serialized_json('{"a": []}', [('key', '[]')]),
|
||||
'{"a": [],"key":[]}'
|
||||
)
|
||||
self.assertEqual(
|
||||
extend_serialized_json('{}', [('key1', '1'), ('key2', '2')]),
|
||||
'{"key1":1,"key2":2}'
|
||||
)
|
||||
|
||||
def test_date_to_spreadsheet_date_number(self):
|
||||
d = datetime.date(1899, 12, 30)
|
||||
self.assertEqual(date_to_spreadsheet_date_number(d), 0)
|
||||
|
||||
d = datetime.date(2023, 10, 1)
|
||||
self.assertEqual(date_to_spreadsheet_date_number(d), 45200)
|
||||
|
||||
def test_datetime_to_spreadsheet_date_number(self):
|
||||
test_tz_offset = 8 / 24 # Etc/GMT-8 is UTC+8
|
||||
dt = datetime.datetime(1899, 12, 30, 0, 0, 0)
|
||||
self.assertEqual(datetime_to_spreadsheet_date_number(dt, 'UTC'), 0)
|
||||
|
||||
dt = datetime.datetime(1899, 12, 30, 0, 0, 0)
|
||||
self.assertEqual(datetime_to_spreadsheet_date_number(dt, 'Etc/GMT-8'), test_tz_offset)
|
||||
|
||||
dt = datetime.datetime(2023, 10, 1, 12, 0, 0)
|
||||
self.assertEqual(datetime_to_spreadsheet_date_number(dt, 'UTC'), 45200.5)
|
||||
|
||||
dt = datetime.datetime(2023, 10, 1, 12, 0, 0)
|
||||
self.assertEqual(datetime_to_spreadsheet_date_number(dt, 'Etc/GMT-8'), 45200.5 + test_tz_offset)
|
||||
|
|
@ -1,218 +0,0 @@
|
|||
from collections import defaultdict
|
||||
from itertools import chain
|
||||
import json
|
||||
import re
|
||||
from odoo.tests.common import TransactionCase
|
||||
|
||||
markdown_link_regex = r"^\[([^\[]+)\]\((.+)\)$"
|
||||
|
||||
xml_id_url_prefix = "odoo://ir_menu_xml_id/"
|
||||
|
||||
odoo_view_link_prefix = "odoo://view/"
|
||||
|
||||
|
||||
def odoo_charts(data):
|
||||
"""return all odoo chart definition in the spreadsheet"""
|
||||
figures = []
|
||||
for sheet in data["sheets"]:
|
||||
figures += [
|
||||
dict(figure["data"], id=figure["id"])
|
||||
for figure in sheet["figures"]
|
||||
if figure["tag"] == "chart" and figure["data"]["type"].startswith("odoo_")
|
||||
]
|
||||
return figures
|
||||
|
||||
|
||||
def links_urls(data):
|
||||
"""return all markdown links in cells"""
|
||||
urls = []
|
||||
link_prefix = "odoo://view/"
|
||||
for sheet in data["sheets"]:
|
||||
for cell in sheet["cells"].values():
|
||||
content = cell.get("content", "")
|
||||
match = re.match(markdown_link_regex, content)
|
||||
if match and match.group(2).startswith(link_prefix):
|
||||
urls.append(match.group(2))
|
||||
return urls
|
||||
|
||||
|
||||
def odoo_view_links(data):
|
||||
"""return all view definitions embedded in link cells.
|
||||
urls looks like odoo://view/{... view data...}
|
||||
"""
|
||||
return [
|
||||
json.loads(url[len(odoo_view_link_prefix):])
|
||||
for url in links_urls(data)
|
||||
if url.startswith(odoo_view_link_prefix)
|
||||
]
|
||||
|
||||
|
||||
def remove_group_operator(field_name):
|
||||
"""remove the group operator
|
||||
>>> remove_group_operator("amount:sum")
|
||||
>>> "amount"
|
||||
"""
|
||||
return field_name.split(":")[0]
|
||||
|
||||
|
||||
def domain_fields(domain):
|
||||
"""return all field names used in the domain"""
|
||||
fields = []
|
||||
for leaf in domain:
|
||||
if len(leaf) == 3:
|
||||
fields.append(leaf[0])
|
||||
return fields
|
||||
|
||||
|
||||
def pivot_measure_fields(pivot):
|
||||
return [
|
||||
measure["field"]
|
||||
for measure in pivot["measures"]
|
||||
if measure["field"] != "__count"
|
||||
]
|
||||
|
||||
|
||||
def pivot_fields(pivot):
|
||||
"""return all field names used in a pivot definition"""
|
||||
model = pivot["model"]
|
||||
fields = set(
|
||||
pivot["colGroupBys"]
|
||||
+ pivot["rowGroupBys"]
|
||||
+ pivot_measure_fields(pivot)
|
||||
+ domain_fields(pivot["domain"])
|
||||
)
|
||||
measure = pivot.get("sortedColumn") and pivot["sortedColumn"]["measure"]
|
||||
if measure and measure != "__count":
|
||||
fields.add(measure)
|
||||
return model, fields
|
||||
|
||||
|
||||
def list_order_fields(list_definition):
|
||||
return [order["name"] for order in list_definition["orderBy"]]
|
||||
|
||||
|
||||
def list_fields(list_definition):
|
||||
"""return all field names used in a list definitions"""
|
||||
model = list_definition["model"]
|
||||
fields = set(
|
||||
list_definition["columns"]
|
||||
+ list_order_fields(list_definition)
|
||||
+ domain_fields(list_definition["domain"])
|
||||
)
|
||||
return model, fields
|
||||
|
||||
|
||||
def chart_fields(chart):
|
||||
"""return all field names used in a chart definitions"""
|
||||
model = chart["metaData"]["resModel"]
|
||||
fields = set(
|
||||
chart["metaData"]["groupBy"]
|
||||
+ chart["searchParams"]["groupBy"]
|
||||
+ domain_fields(chart["searchParams"]["domain"])
|
||||
)
|
||||
measure = chart["metaData"]["measure"]
|
||||
if measure != "__count":
|
||||
fields.add(measure)
|
||||
return model, fields
|
||||
|
||||
|
||||
def filter_fields(data):
|
||||
"""return all field names used in global filter definitions"""
|
||||
fields_by_model = defaultdict(set)
|
||||
charts = odoo_charts(data)
|
||||
odoo_version = data.get("odooVersion", 1)
|
||||
if odoo_version < 5:
|
||||
for filter_definition in data.get("globalFilters", []):
|
||||
for pivot_id, matching in filter_definition.get("pivotFields", dict()).items():
|
||||
model = data["pivots"][pivot_id]["model"]
|
||||
fields_by_model[model].add(matching["field"])
|
||||
for list_id, matching in filter_definition.get("listFields", dict()).items():
|
||||
model = data["lists"][list_id]["model"]
|
||||
fields_by_model[model].add(matching["field"])
|
||||
for chart_id, matching in filter_definition.get("graphFields", dict()).items():
|
||||
chart = next((chart for chart in charts if chart["id"] == chart_id), None)
|
||||
model = chart["metaData"]["resModel"]
|
||||
fields_by_model[model].add(matching["field"])
|
||||
else:
|
||||
for pivot in data["pivots"].values():
|
||||
model = pivot.model
|
||||
field = pivot.get("fieldMatching", {}).get("chain")
|
||||
if field:
|
||||
fields_by_model[model].add(field)
|
||||
for _list in data["lists"].values():
|
||||
model = _list.model
|
||||
field = _list.get("fieldMatching", {}).get("chain")
|
||||
if field:
|
||||
fields_by_model[model].add(field)
|
||||
for chart in charts:
|
||||
model = chart["metaData"]["resModel"]
|
||||
field = chart.get("fieldMatching", {}).get("chain")
|
||||
if field:
|
||||
fields_by_model[model].add(field)
|
||||
|
||||
return dict(fields_by_model)
|
||||
|
||||
|
||||
def odoo_view_fields(view):
|
||||
return view["action"]["modelName"], set(domain_fields(view["action"]["domain"]))
|
||||
|
||||
|
||||
def extract_fields(extract_fn, items):
|
||||
fields_by_model = defaultdict(set)
|
||||
for item in items:
|
||||
model, fields = extract_fn(item)
|
||||
fields_by_model[model] |= {remove_group_operator(field) for field in fields}
|
||||
return dict(fields_by_model)
|
||||
|
||||
|
||||
def fields_in_spreadsheet(data):
|
||||
"""return all fields, grouped by model, used in the spreadsheet"""
|
||||
all_fields = chain(
|
||||
extract_fields(list_fields, data.get("lists", dict()).values()).items(),
|
||||
extract_fields(pivot_fields, data.get("pivots", dict()).values()).items(),
|
||||
extract_fields(chart_fields, odoo_charts(data)).items(),
|
||||
extract_fields(odoo_view_fields, odoo_view_links(data)).items(),
|
||||
filter_fields(data).items(),
|
||||
)
|
||||
fields_by_model = defaultdict(set)
|
||||
for model, fields in all_fields:
|
||||
fields_by_model[model] |= fields
|
||||
return dict(fields_by_model)
|
||||
|
||||
|
||||
def xml_ids_in_spreadsheet(data):
|
||||
|
||||
return set(data.get("chartOdooMenusReferences", {}).values()) | {
|
||||
url[len(xml_id_url_prefix):]
|
||||
for url in links_urls(data)
|
||||
if url.startswith(xml_id_url_prefix)
|
||||
}
|
||||
|
||||
|
||||
class ValidateSpreadsheetData(TransactionCase):
|
||||
def validate_spreadsheet_data(self, stringified_data, spreadsheet_name):
|
||||
data = json.loads(stringified_data)
|
||||
for model, fields in fields_in_spreadsheet(data).items():
|
||||
if model not in self.env:
|
||||
raise AssertionError(
|
||||
f"model '{model}' used in '{spreadsheet_name}' does not exist"
|
||||
)
|
||||
for field_chain in fields:
|
||||
field_model = model
|
||||
for fname in field_chain.split(
|
||||
"."
|
||||
): # field chain 'product_id.channel_ids'
|
||||
if fname not in self.env[field_model]._fields:
|
||||
raise AssertionError(
|
||||
f"field '{fname}' used in spreadsheet '{spreadsheet_name}' does not exist on model '{field_model}'"
|
||||
)
|
||||
field = self.env[field_model]._fields[fname]
|
||||
if field.relational:
|
||||
field_model = field.comodel_name
|
||||
|
||||
for xml_id in xml_ids_in_spreadsheet(data):
|
||||
record = self.env.ref(xml_id, raise_if_not_found=False)
|
||||
if not record:
|
||||
raise AssertionError(
|
||||
f"xml id '{xml_id}' used in spreadsheet '{spreadsheet_name}' does not exist"
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue