arelle-release 2.37.21__py3-none-any.whl → 2.37.23__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of arelle-release might be problematic. Click here for more details.
- arelle/ModelRelationshipSet.py +3 -0
- arelle/ValidateDuplicateFacts.py +13 -7
- arelle/XbrlConst.py +3 -0
- arelle/_version.py +2 -2
- arelle/api/Session.py +88 -58
- arelle/plugin/validate/DBA/rules/fr.py +10 -10
- arelle/plugin/validate/DBA/rules/th.py +1 -1
- arelle/plugin/validate/ESEF/ESEF_Current/ValidateXbrlFinally.py +21 -20
- arelle/plugin/validate/NL/DisclosureSystems.py +14 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +167 -3
- arelle/plugin/validate/NL/ValidationPluginExtension.py +10 -1
- arelle/plugin/validate/NL/resources/config.xml +12 -1
- arelle/plugin/validate/NL/rules/fr_kvk.py +1 -1
- arelle/plugin/validate/NL/rules/nl_kvk.py +680 -155
- arelle/utils/validate/DetectScriptsInXhtml.py +1 -4
- arelle/utils/validate/ESEFImage.py +274 -0
- {arelle_release-2.37.21.dist-info → arelle_release-2.37.23.dist-info}/METADATA +1 -1
- {arelle_release-2.37.21.dist-info → arelle_release-2.37.23.dist-info}/RECORD +27 -26
- tests/integration_tests/validation/conformance_suite_configs.py +2 -0
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +30 -43
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024_gaap_other.py +244 -0
- tests/integration_tests/validation/discover_tests.py +2 -2
- tests/unit_tests/arelle/plugin/validate/ESEF/ESEF_Current/test_validate_css_url.py +10 -2
- arelle/plugin/validate/ESEF/ESEF_Current/Image.py +0 -213
- {arelle_release-2.37.21.dist-info → arelle_release-2.37.23.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.21.dist-info → arelle_release-2.37.23.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.21.dist-info → arelle_release-2.37.23.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.21.dist-info → arelle_release-2.37.23.dist-info}/top_level.txt +0 -0
|
@@ -3,29 +3,50 @@ See COPYRIGHT.md for copyright information.
|
|
|
3
3
|
"""
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
+
from collections import defaultdict
|
|
7
|
+
from collections.abc import Iterable
|
|
6
8
|
from datetime import date
|
|
9
|
+
from typing import Any, cast, TYPE_CHECKING
|
|
10
|
+
|
|
7
11
|
import zipfile
|
|
8
12
|
|
|
13
|
+
from lxml.etree import Element
|
|
14
|
+
|
|
15
|
+
from arelle.ModelDtsObject import ModelLink, ModelResource, ModelType
|
|
9
16
|
from arelle.ModelInstanceObject import ModelInlineFact
|
|
17
|
+
from arelle.ModelObject import ModelObject
|
|
18
|
+
from arelle.PrototypeDtsObject import PrototypeObject
|
|
10
19
|
from arelle.ValidateDuplicateFacts import getDuplicateFactSets
|
|
11
20
|
from arelle.XmlValidateConst import VALID
|
|
12
|
-
from collections.abc import Iterable
|
|
13
|
-
from typing import Any, cast, TYPE_CHECKING
|
|
14
21
|
|
|
15
|
-
from arelle import
|
|
22
|
+
from arelle import XbrlConst, XmlUtil
|
|
16
23
|
from arelle.ValidateXbrl import ValidateXbrl
|
|
17
24
|
from arelle.typing import TypeGetText
|
|
18
25
|
from arelle.utils.PluginHooks import ValidationHook
|
|
19
26
|
from arelle.utils.validate.Decorator import validation
|
|
27
|
+
from arelle.utils.validate.DetectScriptsInXhtml import containsScriptMarkers
|
|
28
|
+
from arelle.utils.validate.ESEFImage import ImageValidationParameters, validateImage
|
|
20
29
|
from arelle.utils.validate.Validation import Validation
|
|
21
30
|
from arelle.ValidateDuplicateFacts import getHashEquivalentFactGroups, getAspectEqualFacts
|
|
22
31
|
from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
|
|
23
|
-
from ..DisclosureSystems import
|
|
32
|
+
from ..DisclosureSystems import (ALL_NL_INLINE_DISCLOSURE_SYSTEMS, NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
33
|
+
NL_INLINE_GAAP_OTHER_DISCLOSURE_SYSTEMS)
|
|
24
34
|
from ..LinkbaseType import LinkbaseType
|
|
25
|
-
from ..PluginValidationDataExtension import (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
from ..PluginValidationDataExtension import (
|
|
36
|
+
PluginValidationDataExtension,
|
|
37
|
+
ALLOWABLE_LANGUAGES,
|
|
38
|
+
DEFAULT_MEMBER_ROLE_URI,
|
|
39
|
+
DISALLOWED_IXT_NAMESPACES,
|
|
40
|
+
EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES,
|
|
41
|
+
EFFECTIVE_KVK_GAAP_OTHER_ENTRYPOINT_FILES,
|
|
42
|
+
MAX_REPORT_PACKAGE_SIZE_MBS,
|
|
43
|
+
NON_DIMENSIONALIZED_LINE_ITEM_LINKROLES,
|
|
44
|
+
QN_DOMAIN_ITEM_TYPES,
|
|
45
|
+
SUPPORTED_IMAGE_TYPES_BY_IS_FILE,
|
|
46
|
+
TAXONOMY_URLS_BY_YEAR,
|
|
47
|
+
XBRLI_IDENTIFIER_PATTERN,
|
|
48
|
+
XBRLI_IDENTIFIER_SCHEMA,
|
|
49
|
+
)
|
|
29
50
|
|
|
30
51
|
if TYPE_CHECKING:
|
|
31
52
|
from arelle.ModelXbrl import ModelXbrl
|
|
@@ -45,9 +66,7 @@ def _getReportingPeriodDateValue(modelXbrl: ModelXbrl, qname: QName) -> date | N
|
|
|
45
66
|
|
|
46
67
|
@validation(
|
|
47
68
|
hook=ValidationHook.XBRL_FINALLY,
|
|
48
|
-
disclosureSystems=
|
|
49
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
50
|
-
],
|
|
69
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
51
70
|
)
|
|
52
71
|
def rule_nl_kvk_3_1_1_1(
|
|
53
72
|
pluginData: PluginValidationDataExtension,
|
|
@@ -64,7 +83,7 @@ def rule_nl_kvk_3_1_1_1(
|
|
|
64
83
|
if not XBRLI_IDENTIFIER_PATTERN.match(entityId[1]):
|
|
65
84
|
yield Validation.error(
|
|
66
85
|
codes='NL.NL-KVK-RTS_Annex_IV_Par_2_G3-1-1_1.invalidIdentifierFormat',
|
|
67
|
-
msg=_('xbrli:identifier content to match KVK number format that must consist of 8 consecutive digits.'
|
|
86
|
+
msg=_('xbrli:identifier content to match KVK number format that must consist of 8 consecutive digits. '
|
|
68
87
|
'Additionally the first two digits must not be "00".'),
|
|
69
88
|
modelObject = val.modelXbrl
|
|
70
89
|
)
|
|
@@ -73,9 +92,7 @@ def rule_nl_kvk_3_1_1_1(
|
|
|
73
92
|
|
|
74
93
|
@validation(
|
|
75
94
|
hook=ValidationHook.XBRL_FINALLY,
|
|
76
|
-
disclosureSystems=
|
|
77
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
78
|
-
],
|
|
95
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
79
96
|
)
|
|
80
97
|
def rule_nl_kvk_3_1_1_2(
|
|
81
98
|
pluginData: PluginValidationDataExtension,
|
|
@@ -91,7 +108,7 @@ def rule_nl_kvk_3_1_1_2(
|
|
|
91
108
|
if XBRLI_IDENTIFIER_SCHEMA != entityId[0]:
|
|
92
109
|
yield Validation.error(
|
|
93
110
|
codes='NL.NL-KVK-RTS_Annex_IV_Par_2_G3-1-1_2.invalidIdentifier',
|
|
94
|
-
msg=_('The scheme attribute of the xbrli:identifier does not match the required content.'
|
|
111
|
+
msg=_('The scheme attribute of the xbrli:identifier does not match the required content. '
|
|
95
112
|
'This should be "http://www.kvk.nl/kvk-id".'),
|
|
96
113
|
modelObject = val.modelXbrl
|
|
97
114
|
)
|
|
@@ -100,9 +117,7 @@ def rule_nl_kvk_3_1_1_2(
|
|
|
100
117
|
|
|
101
118
|
@validation(
|
|
102
119
|
hook=ValidationHook.XBRL_FINALLY,
|
|
103
|
-
disclosureSystems=
|
|
104
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
105
|
-
],
|
|
120
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
106
121
|
)
|
|
107
122
|
def rule_nl_kvk_3_1_2_1(
|
|
108
123
|
pluginData: PluginValidationDataExtension,
|
|
@@ -124,9 +139,7 @@ def rule_nl_kvk_3_1_2_1(
|
|
|
124
139
|
|
|
125
140
|
@validation(
|
|
126
141
|
hook=ValidationHook.XBRL_FINALLY,
|
|
127
|
-
disclosureSystems=
|
|
128
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
129
|
-
],
|
|
142
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
130
143
|
)
|
|
131
144
|
def rule_nl_kvk_3_1_2_2(
|
|
132
145
|
pluginData: PluginValidationDataExtension,
|
|
@@ -148,9 +161,7 @@ def rule_nl_kvk_3_1_2_2(
|
|
|
148
161
|
|
|
149
162
|
@validation(
|
|
150
163
|
hook=ValidationHook.XBRL_FINALLY,
|
|
151
|
-
disclosureSystems=
|
|
152
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
153
|
-
],
|
|
164
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
154
165
|
)
|
|
155
166
|
def rule_nl_kvk_3_1_3_1 (
|
|
156
167
|
pluginData: PluginValidationDataExtension,
|
|
@@ -172,9 +183,7 @@ def rule_nl_kvk_3_1_3_1 (
|
|
|
172
183
|
|
|
173
184
|
@validation(
|
|
174
185
|
hook=ValidationHook.XBRL_FINALLY,
|
|
175
|
-
disclosureSystems=
|
|
176
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
177
|
-
],
|
|
186
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
178
187
|
)
|
|
179
188
|
def rule_nl_kvk_3_1_3_2 (
|
|
180
189
|
pluginData: PluginValidationDataExtension,
|
|
@@ -196,9 +205,7 @@ def rule_nl_kvk_3_1_3_2 (
|
|
|
196
205
|
|
|
197
206
|
@validation(
|
|
198
207
|
hook=ValidationHook.XBRL_FINALLY,
|
|
199
|
-
disclosureSystems=
|
|
200
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
201
|
-
],
|
|
208
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
202
209
|
)
|
|
203
210
|
def rule_nl_kvk_3_1_4_1 (
|
|
204
211
|
pluginData: PluginValidationDataExtension,
|
|
@@ -221,9 +228,7 @@ def rule_nl_kvk_3_1_4_1 (
|
|
|
221
228
|
|
|
222
229
|
@validation(
|
|
223
230
|
hook=ValidationHook.XBRL_FINALLY,
|
|
224
|
-
disclosureSystems=
|
|
225
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
226
|
-
],
|
|
231
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
227
232
|
)
|
|
228
233
|
def rule_nl_kvk_3_1_4_2 (
|
|
229
234
|
pluginData: PluginValidationDataExtension,
|
|
@@ -250,9 +255,7 @@ def rule_nl_kvk_3_1_4_2 (
|
|
|
250
255
|
|
|
251
256
|
@validation(
|
|
252
257
|
hook=ValidationHook.XBRL_FINALLY,
|
|
253
|
-
disclosureSystems=
|
|
254
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
255
|
-
],
|
|
258
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
256
259
|
)
|
|
257
260
|
def rule_nl_kvk_3_2_1_1 (
|
|
258
261
|
pluginData: PluginValidationDataExtension,
|
|
@@ -277,9 +280,7 @@ def rule_nl_kvk_3_2_1_1 (
|
|
|
277
280
|
|
|
278
281
|
@validation(
|
|
279
282
|
hook=ValidationHook.XBRL_FINALLY,
|
|
280
|
-
disclosureSystems=
|
|
281
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
282
|
-
],
|
|
283
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
283
284
|
)
|
|
284
285
|
def rule_nl_kvk_3_2_3_1 (
|
|
285
286
|
pluginData: PluginValidationDataExtension,
|
|
@@ -305,9 +306,7 @@ def rule_nl_kvk_3_2_3_1 (
|
|
|
305
306
|
|
|
306
307
|
@validation(
|
|
307
308
|
hook=ValidationHook.XBRL_FINALLY,
|
|
308
|
-
disclosureSystems=
|
|
309
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
310
|
-
],
|
|
309
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
311
310
|
)
|
|
312
311
|
def rule_nl_kvk_3_2_4_1 (
|
|
313
312
|
pluginData: PluginValidationDataExtension,
|
|
@@ -335,9 +334,7 @@ def rule_nl_kvk_3_2_4_1 (
|
|
|
335
334
|
|
|
336
335
|
@validation(
|
|
337
336
|
hook=ValidationHook.XBRL_FINALLY,
|
|
338
|
-
disclosureSystems=
|
|
339
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
340
|
-
],
|
|
337
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
341
338
|
)
|
|
342
339
|
def rule_nl_kvk_3_2_4_2 (
|
|
343
340
|
pluginData: PluginValidationDataExtension,
|
|
@@ -365,9 +362,7 @@ def rule_nl_kvk_3_2_4_2 (
|
|
|
365
362
|
|
|
366
363
|
@validation(
|
|
367
364
|
hook=ValidationHook.XBRL_FINALLY,
|
|
368
|
-
disclosureSystems=
|
|
369
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
370
|
-
],
|
|
365
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
371
366
|
)
|
|
372
367
|
def rule_nl_kvk_3_2_7_1 (
|
|
373
368
|
pluginData: PluginValidationDataExtension,
|
|
@@ -386,7 +381,7 @@ def rule_nl_kvk_3_2_7_1 (
|
|
|
386
381
|
if len(improperlyEscapedFacts) >0:
|
|
387
382
|
yield Validation.error(
|
|
388
383
|
codes='NL.NL-KVK.3.2.7.1.improperApplicationOfEscapeAttribute',
|
|
389
|
-
msg=_('Ensure that any block-tagged facts of type textBlockItemType are assigned @escape="true",'
|
|
384
|
+
msg=_('Ensure that any block-tagged facts of type textBlockItemType are assigned @escape="true", '
|
|
390
385
|
'while other data types (e.g., xbrli:stringItemType) are assigned @escape="false".'),
|
|
391
386
|
modelObject = improperlyEscapedFacts
|
|
392
387
|
)
|
|
@@ -394,9 +389,29 @@ def rule_nl_kvk_3_2_7_1 (
|
|
|
394
389
|
|
|
395
390
|
@validation(
|
|
396
391
|
hook=ValidationHook.XBRL_FINALLY,
|
|
397
|
-
disclosureSystems=
|
|
398
|
-
|
|
399
|
-
|
|
392
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
393
|
+
)
|
|
394
|
+
def rule_nl_kvk_3_2_8_1(
|
|
395
|
+
pluginData: PluginValidationDataExtension,
|
|
396
|
+
val: ValidateXbrl,
|
|
397
|
+
*args: Any,
|
|
398
|
+
**kwargs: Any,
|
|
399
|
+
) -> Iterable[Validation]:
|
|
400
|
+
"""
|
|
401
|
+
NL-KVK.3.2.8.1: Include unique @id attribute for each tagged fact
|
|
402
|
+
"""
|
|
403
|
+
errors = {fact for fact in val.modelXbrl.facts if not fact.id}
|
|
404
|
+
if len(errors) > 0:
|
|
405
|
+
yield Validation.warning(
|
|
406
|
+
codes='NL.NL-KVK.3.2.8.1',
|
|
407
|
+
msg=_('All facts should include an id attribute'),
|
|
408
|
+
modelObject=errors
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
@validation(
|
|
413
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
414
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
400
415
|
)
|
|
401
416
|
def rule_nl_kvk_3_3_1_1 (
|
|
402
417
|
pluginData: PluginValidationDataExtension,
|
|
@@ -417,9 +432,7 @@ def rule_nl_kvk_3_3_1_1 (
|
|
|
417
432
|
|
|
418
433
|
@validation(
|
|
419
434
|
hook=ValidationHook.XBRL_FINALLY,
|
|
420
|
-
disclosureSystems=
|
|
421
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
422
|
-
],
|
|
435
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
423
436
|
)
|
|
424
437
|
def rule_nl_kvk_3_3_1_2 (
|
|
425
438
|
pluginData: PluginValidationDataExtension,
|
|
@@ -441,9 +454,7 @@ def rule_nl_kvk_3_3_1_2 (
|
|
|
441
454
|
|
|
442
455
|
@validation(
|
|
443
456
|
hook=ValidationHook.XBRL_FINALLY,
|
|
444
|
-
disclosureSystems=
|
|
445
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
446
|
-
],
|
|
457
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
447
458
|
)
|
|
448
459
|
def rule_nl_kvk_3_3_1_3 (
|
|
449
460
|
pluginData: PluginValidationDataExtension,
|
|
@@ -467,9 +478,7 @@ def rule_nl_kvk_3_3_1_3 (
|
|
|
467
478
|
|
|
468
479
|
@validation(
|
|
469
480
|
hook=ValidationHook.XBRL_FINALLY,
|
|
470
|
-
disclosureSystems=
|
|
471
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
472
|
-
],
|
|
481
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
473
482
|
)
|
|
474
483
|
def rule_nl_kvk_3_4_1_1 (
|
|
475
484
|
pluginData: PluginValidationDataExtension,
|
|
@@ -491,9 +500,7 @@ def rule_nl_kvk_3_4_1_1 (
|
|
|
491
500
|
|
|
492
501
|
@validation(
|
|
493
502
|
hook=ValidationHook.XBRL_FINALLY,
|
|
494
|
-
disclosureSystems=
|
|
495
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
496
|
-
],
|
|
503
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
497
504
|
)
|
|
498
505
|
def rule_nl_kvk_3_4_1_2 (
|
|
499
506
|
pluginData: PluginValidationDataExtension,
|
|
@@ -515,9 +522,7 @@ def rule_nl_kvk_3_4_1_2 (
|
|
|
515
522
|
|
|
516
523
|
@validation(
|
|
517
524
|
hook=ValidationHook.XBRL_FINALLY,
|
|
518
|
-
disclosureSystems=
|
|
519
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
520
|
-
],
|
|
525
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
521
526
|
)
|
|
522
527
|
def rule_nl_kvk_3_4_1_3 (
|
|
523
528
|
pluginData: PluginValidationDataExtension,
|
|
@@ -541,9 +546,7 @@ def rule_nl_kvk_3_4_1_3 (
|
|
|
541
546
|
|
|
542
547
|
@validation(
|
|
543
548
|
hook=ValidationHook.XBRL_FINALLY,
|
|
544
|
-
disclosureSystems=
|
|
545
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
546
|
-
],
|
|
549
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
547
550
|
)
|
|
548
551
|
def rule_nl_kvk_3_4_1_4 (
|
|
549
552
|
pluginData: PluginValidationDataExtension,
|
|
@@ -565,9 +568,7 @@ def rule_nl_kvk_3_4_1_4 (
|
|
|
565
568
|
|
|
566
569
|
@validation(
|
|
567
570
|
hook=ValidationHook.XBRL_FINALLY,
|
|
568
|
-
disclosureSystems=
|
|
569
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
570
|
-
],
|
|
571
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
571
572
|
)
|
|
572
573
|
def rule_nl_kvk_3_4_1_5 (
|
|
573
574
|
pluginData: PluginValidationDataExtension,
|
|
@@ -589,9 +590,7 @@ def rule_nl_kvk_3_4_1_5 (
|
|
|
589
590
|
|
|
590
591
|
@validation(
|
|
591
592
|
hook=ValidationHook.XBRL_FINALLY,
|
|
592
|
-
disclosureSystems=
|
|
593
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
594
|
-
],
|
|
593
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
595
594
|
)
|
|
596
595
|
def rule_nl_kvk_3_4_2_1 (
|
|
597
596
|
pluginData: PluginValidationDataExtension,
|
|
@@ -613,9 +612,73 @@ def rule_nl_kvk_3_4_2_1 (
|
|
|
613
612
|
|
|
614
613
|
@validation(
|
|
615
614
|
hook=ValidationHook.XBRL_FINALLY,
|
|
616
|
-
disclosureSystems=
|
|
617
|
-
|
|
618
|
-
|
|
615
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
616
|
+
)
|
|
617
|
+
def rule_nl_kvk_3_5_1_1_non_img (
|
|
618
|
+
pluginData: PluginValidationDataExtension,
|
|
619
|
+
val: ValidateXbrl,
|
|
620
|
+
*args: Any,
|
|
621
|
+
**kwargs: Any,
|
|
622
|
+
) -> Iterable[Validation]:
|
|
623
|
+
"""
|
|
624
|
+
NL-KVK.3.5.1.1: Resources embedded or referenced by the XHTML document and its inline XBRL MUST NOT contain executable code.
|
|
625
|
+
"""
|
|
626
|
+
|
|
627
|
+
executableElements = []
|
|
628
|
+
for ixdsHtmlRootElt in val.modelXbrl.ixdsHtmlElements:
|
|
629
|
+
for elt in ixdsHtmlRootElt.iter(Element):
|
|
630
|
+
if containsScriptMarkers(elt):
|
|
631
|
+
executableElements.append(elt)
|
|
632
|
+
if executableElements:
|
|
633
|
+
yield Validation.error(
|
|
634
|
+
codes='NL.NL-KVK.3.5.1.1.executableCodePresent',
|
|
635
|
+
msg=_("Resources embedded or referenced by the XHTML document and its inline XBRL MUST NOT contain executable code."),
|
|
636
|
+
modelObject=executableElements,
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
@validation(
|
|
641
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
642
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
643
|
+
)
|
|
644
|
+
def rule_nl_kvk_3_5_1_img (
|
|
645
|
+
pluginData: PluginValidationDataExtension,
|
|
646
|
+
val: ValidateXbrl,
|
|
647
|
+
*args: Any,
|
|
648
|
+
**kwargs: Any,
|
|
649
|
+
) -> Iterable[Validation]:
|
|
650
|
+
"""
|
|
651
|
+
NL-KVK.3.5.1.1: Inline XBRL images MUST NOT contain executable code.
|
|
652
|
+
NL-KVK.3.5.1.2: Images included in the XHTML document MUST be saved with MIME type specifying PNG, GIF, SVG or JPG/JPEG formats.
|
|
653
|
+
NL-KVK.3.5.1.3: File type inferred from file signature does not match the data URL media subtype (MIME subtype).
|
|
654
|
+
NL-KVK.3.5.1.4: File type inferred from file signature does not match the file extension.
|
|
655
|
+
NL-KVK.3.5.1.5: Images included in the XHTML document MUST be saved in PNG, GIF, SVG or JPG/JPEG formats.
|
|
656
|
+
"""
|
|
657
|
+
|
|
658
|
+
imageValidationParameters = ImageValidationParameters.from_non_esef(
|
|
659
|
+
checkMinExternalResourceSize=False,
|
|
660
|
+
missingMimeTypeIsIncorrect=False,
|
|
661
|
+
recommendBase64EncodingEmbeddedImages=False,
|
|
662
|
+
supportedImgTypes=SUPPORTED_IMAGE_TYPES_BY_IS_FILE,
|
|
663
|
+
)
|
|
664
|
+
for ixdsHtmlRootElt in val.modelXbrl.ixdsHtmlElements:
|
|
665
|
+
for elt in ixdsHtmlRootElt.iter((f'{{{XbrlConst.xhtml}}}img', '{http://www.w3.org/2000/svg}svg')):
|
|
666
|
+
src = elt.get('src', '').strip()
|
|
667
|
+
evaluatedMsg = _('On line {line}, "alt" attribute value: "{alt}"').format(line=elt.sourceline, alt=elt.get('alt'))
|
|
668
|
+
yield from validateImage(
|
|
669
|
+
elt.modelDocument.baseForElement(elt),
|
|
670
|
+
src,
|
|
671
|
+
val.modelXbrl,
|
|
672
|
+
val,
|
|
673
|
+
elt,
|
|
674
|
+
evaluatedMsg,
|
|
675
|
+
imageValidationParameters,
|
|
676
|
+
)
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
@validation(
|
|
680
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
681
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
619
682
|
)
|
|
620
683
|
def rule_nl_kvk_3_5_2_1(
|
|
621
684
|
pluginData: PluginValidationDataExtension,
|
|
@@ -624,7 +687,7 @@ def rule_nl_kvk_3_5_2_1(
|
|
|
624
687
|
**kwargs: Any,
|
|
625
688
|
) -> Iterable[Validation]:
|
|
626
689
|
"""
|
|
627
|
-
NL-KVK.3.5.2.1: Each tagged text fact MUST have the
|
|
690
|
+
NL-KVK.3.5.2.1: Each tagged text fact MUST have the 'xml:lang' attribute assigned or inherited.
|
|
628
691
|
"""
|
|
629
692
|
factsWithoutLang = []
|
|
630
693
|
for fact in val.modelXbrl.facts:
|
|
@@ -637,16 +700,14 @@ def rule_nl_kvk_3_5_2_1(
|
|
|
637
700
|
if len(factsWithoutLang) > 0:
|
|
638
701
|
yield Validation.error(
|
|
639
702
|
codes='NL.NL-KVK.3.5.2.1.undefinedLanguageForTextFact',
|
|
640
|
-
msg=_(
|
|
703
|
+
msg=_("Each tagged text fact MUST have the 'xml:lang' attribute assigned or inherited."),
|
|
641
704
|
modelObject=factsWithoutLang
|
|
642
705
|
)
|
|
643
706
|
|
|
644
707
|
|
|
645
708
|
@validation(
|
|
646
709
|
hook=ValidationHook.XBRL_FINALLY,
|
|
647
|
-
disclosureSystems=
|
|
648
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
649
|
-
],
|
|
710
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
650
711
|
)
|
|
651
712
|
def rule_nl_kvk_3_5_2_2(
|
|
652
713
|
pluginData: PluginValidationDataExtension,
|
|
@@ -675,9 +736,7 @@ def rule_nl_kvk_3_5_2_2(
|
|
|
675
736
|
|
|
676
737
|
@validation(
|
|
677
738
|
hook=ValidationHook.XBRL_FINALLY,
|
|
678
|
-
disclosureSystems=
|
|
679
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
680
|
-
],
|
|
739
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
681
740
|
)
|
|
682
741
|
def rule_nl_kvk_3_5_2_3(
|
|
683
742
|
pluginData: PluginValidationDataExtension,
|
|
@@ -706,9 +765,7 @@ def rule_nl_kvk_3_5_2_3(
|
|
|
706
765
|
|
|
707
766
|
@validation(
|
|
708
767
|
hook=ValidationHook.XBRL_FINALLY,
|
|
709
|
-
disclosureSystems=
|
|
710
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
711
|
-
],
|
|
768
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
712
769
|
)
|
|
713
770
|
def rule_nl_kvk_3_5_3_1(
|
|
714
771
|
pluginData: PluginValidationDataExtension,
|
|
@@ -730,9 +787,7 @@ def rule_nl_kvk_3_5_3_1(
|
|
|
730
787
|
|
|
731
788
|
@validation(
|
|
732
789
|
hook=ValidationHook.XBRL_FINALLY,
|
|
733
|
-
disclosureSystems=
|
|
734
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
735
|
-
],
|
|
790
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
736
791
|
)
|
|
737
792
|
def rule_nl_kvk_3_5_4_1 (
|
|
738
793
|
pluginData: PluginValidationDataExtension,
|
|
@@ -755,9 +810,7 @@ def rule_nl_kvk_3_5_4_1 (
|
|
|
755
810
|
|
|
756
811
|
@validation(
|
|
757
812
|
hook=ValidationHook.XBRL_FINALLY,
|
|
758
|
-
disclosureSystems=
|
|
759
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
760
|
-
],
|
|
813
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
761
814
|
)
|
|
762
815
|
def rule_nl_kvk_3_6_3_1(
|
|
763
816
|
pluginData: PluginValidationDataExtension,
|
|
@@ -788,9 +841,7 @@ def rule_nl_kvk_3_6_3_1(
|
|
|
788
841
|
|
|
789
842
|
@validation(
|
|
790
843
|
hook=ValidationHook.XBRL_FINALLY,
|
|
791
|
-
disclosureSystems=
|
|
792
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
793
|
-
],
|
|
844
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
794
845
|
)
|
|
795
846
|
def rule_nl_kvk_3_6_3_2(
|
|
796
847
|
pluginData: PluginValidationDataExtension,
|
|
@@ -820,9 +871,7 @@ def rule_nl_kvk_3_6_3_2(
|
|
|
820
871
|
|
|
821
872
|
@validation(
|
|
822
873
|
hook=ValidationHook.XBRL_FINALLY,
|
|
823
|
-
disclosureSystems=
|
|
824
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
825
|
-
],
|
|
874
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
826
875
|
)
|
|
827
876
|
def rule_nl_kvk_3_6_3_3(
|
|
828
877
|
pluginData: PluginValidationDataExtension,
|
|
@@ -850,9 +899,7 @@ def rule_nl_kvk_3_6_3_3(
|
|
|
850
899
|
|
|
851
900
|
@validation(
|
|
852
901
|
hook=ValidationHook.FINALLY,
|
|
853
|
-
disclosureSystems=
|
|
854
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
855
|
-
],
|
|
902
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
856
903
|
)
|
|
857
904
|
def rule_nl_kvk_3_7_1_1(
|
|
858
905
|
pluginData: PluginValidationDataExtension,
|
|
@@ -880,9 +927,7 @@ def rule_nl_kvk_3_7_1_1(
|
|
|
880
927
|
|
|
881
928
|
@validation(
|
|
882
929
|
hook=ValidationHook.FINALLY,
|
|
883
|
-
disclosureSystems=
|
|
884
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
885
|
-
],
|
|
930
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
886
931
|
)
|
|
887
932
|
def rule_nl_kvk_3_7_1_2(
|
|
888
933
|
pluginData: PluginValidationDataExtension,
|
|
@@ -910,9 +955,7 @@ def rule_nl_kvk_3_7_1_2(
|
|
|
910
955
|
|
|
911
956
|
@validation(
|
|
912
957
|
hook=ValidationHook.XBRL_FINALLY,
|
|
913
|
-
disclosureSystems=
|
|
914
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
915
|
-
],
|
|
958
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
916
959
|
)
|
|
917
960
|
def rule_nl_kvk_4_1_1_1(
|
|
918
961
|
pluginData: PluginValidationDataExtension,
|
|
@@ -963,9 +1006,7 @@ def rule_nl_kvk_4_1_1_1(
|
|
|
963
1006
|
|
|
964
1007
|
@validation(
|
|
965
1008
|
hook=ValidationHook.XBRL_FINALLY,
|
|
966
|
-
disclosureSystems=
|
|
967
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
968
|
-
],
|
|
1009
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
969
1010
|
)
|
|
970
1011
|
def rule_nl_kvk_4_1_1_2(
|
|
971
1012
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1000,9 +1041,7 @@ def rule_nl_kvk_4_1_1_2(
|
|
|
1000
1041
|
|
|
1001
1042
|
@validation(
|
|
1002
1043
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1003
|
-
disclosureSystems=
|
|
1004
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1005
|
-
],
|
|
1044
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1006
1045
|
)
|
|
1007
1046
|
def rule_nl_kvk_4_1_2_1(
|
|
1008
1047
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1027,9 +1066,7 @@ def rule_nl_kvk_4_1_2_1(
|
|
|
1027
1066
|
|
|
1028
1067
|
@validation(
|
|
1029
1068
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1030
|
-
disclosureSystems=
|
|
1031
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1032
|
-
],
|
|
1069
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1033
1070
|
)
|
|
1034
1071
|
def rule_nl_kvk_4_1_2_2(
|
|
1035
1072
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1038,7 +1075,7 @@ def rule_nl_kvk_4_1_2_2(
|
|
|
1038
1075
|
**kwargs: Any,
|
|
1039
1076
|
) -> Iterable[Validation]:
|
|
1040
1077
|
"""
|
|
1041
|
-
NL-KVK.4.1.2.2: The legal entity
|
|
1078
|
+
NL-KVK.4.1.2.2: The legal entity's extension taxonomy MUST import the applicable version of
|
|
1042
1079
|
the taxonomy files prepared by KVK.
|
|
1043
1080
|
"""
|
|
1044
1081
|
reportingPeriod = pluginData.getReportingPeriod(val.modelXbrl)
|
|
@@ -1048,16 +1085,15 @@ def rule_nl_kvk_4_1_2_2(
|
|
|
1048
1085
|
yield Validation.error(
|
|
1049
1086
|
codes='NL.NL-KVK.4.1.2.2.incorrectKvkTaxonomyVersionUsed',
|
|
1050
1087
|
msg=_('The extension taxonomy MUST import the applicable version of the taxonomy files prepared by KVK '
|
|
1051
|
-
'for the reported financial reporting period
|
|
1088
|
+
'for the reported financial reporting period. Verify the taxonomy version and make sure '
|
|
1089
|
+
'that FinancialReportingPeriod are tagged correctly.'),
|
|
1052
1090
|
modelObject=val.modelXbrl.modelDocument
|
|
1053
1091
|
)
|
|
1054
1092
|
|
|
1055
1093
|
|
|
1056
1094
|
@validation(
|
|
1057
1095
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1058
|
-
disclosureSystems=
|
|
1059
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1060
|
-
],
|
|
1096
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1061
1097
|
)
|
|
1062
1098
|
def rule_nl_kvk_4_1_5_1(
|
|
1063
1099
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1089,9 +1125,7 @@ def rule_nl_kvk_4_1_5_1(
|
|
|
1089
1125
|
|
|
1090
1126
|
@validation(
|
|
1091
1127
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1092
|
-
disclosureSystems=
|
|
1093
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1094
|
-
],
|
|
1128
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1095
1129
|
)
|
|
1096
1130
|
def rule_nl_kvk_4_1_5_2(
|
|
1097
1131
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1122,9 +1156,7 @@ def rule_nl_kvk_4_1_5_2(
|
|
|
1122
1156
|
|
|
1123
1157
|
@validation(
|
|
1124
1158
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1125
|
-
disclosureSystems=
|
|
1126
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1127
|
-
],
|
|
1159
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1128
1160
|
)
|
|
1129
1161
|
def rule_nl_kvk_4_2_0_1(
|
|
1130
1162
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1148,9 +1180,7 @@ def rule_nl_kvk_4_2_0_1(
|
|
|
1148
1180
|
|
|
1149
1181
|
@validation(
|
|
1150
1182
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1151
|
-
disclosureSystems=
|
|
1152
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1153
|
-
],
|
|
1183
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1154
1184
|
)
|
|
1155
1185
|
def rule_nl_kvk_4_2_0_2(
|
|
1156
1186
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1174,9 +1204,7 @@ def rule_nl_kvk_4_2_0_2(
|
|
|
1174
1204
|
|
|
1175
1205
|
@validation(
|
|
1176
1206
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1177
|
-
disclosureSystems=
|
|
1178
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1179
|
-
],
|
|
1207
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1180
1208
|
)
|
|
1181
1209
|
def rule_nl_kvk_4_2_1_1(
|
|
1182
1210
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1205,9 +1233,127 @@ def rule_nl_kvk_4_2_1_1(
|
|
|
1205
1233
|
|
|
1206
1234
|
@validation(
|
|
1207
1235
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1208
|
-
disclosureSystems=
|
|
1209
|
-
|
|
1210
|
-
|
|
1236
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1237
|
+
)
|
|
1238
|
+
def rule_nl_kvk_4_2_2_2(
|
|
1239
|
+
pluginData: PluginValidationDataExtension,
|
|
1240
|
+
val: ValidateXbrl,
|
|
1241
|
+
*args: Any,
|
|
1242
|
+
**kwargs: Any,
|
|
1243
|
+
) -> Iterable[Validation]:
|
|
1244
|
+
"""
|
|
1245
|
+
NL-KVK.4.2.2.2: Domain members MUST have domainItemType data type as defined in https://www.xbrl.org/dtr/type/2022-03-31/types.xsd.
|
|
1246
|
+
"""
|
|
1247
|
+
domainMembersWrongType = []
|
|
1248
|
+
domainMembers = pluginData.getDimensionalData(val.modelXbrl).domainMembers
|
|
1249
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1250
|
+
for concept in extensionData.extensionConcepts:
|
|
1251
|
+
if concept.isDomainMember and concept in domainMembers and concept.typeQname not in QN_DOMAIN_ITEM_TYPES:
|
|
1252
|
+
domainMembersWrongType.append(concept)
|
|
1253
|
+
if len(domainMembersWrongType) > 0:
|
|
1254
|
+
yield Validation.error(
|
|
1255
|
+
codes='NL.NL-KVK.4.2.2.2.domainMemberWrongDataType',
|
|
1256
|
+
modelObject=domainMembersWrongType,
|
|
1257
|
+
msg=_('Domain members must have domainItemType data type as defined in "https://www.xbrl.org/dtr/type/2022-03-31/types.xsd".'
|
|
1258
|
+
'Update to follow appropriate Data Type Registry. '))
|
|
1259
|
+
|
|
1260
|
+
|
|
1261
|
+
@validation(
|
|
1262
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1263
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1264
|
+
)
|
|
1265
|
+
def rule_nl_kvk_4_2_3_1(
|
|
1266
|
+
pluginData: PluginValidationDataExtension,
|
|
1267
|
+
val: ValidateXbrl,
|
|
1268
|
+
*args: Any,
|
|
1269
|
+
**kwargs: Any,
|
|
1270
|
+
) -> Iterable[Validation]:
|
|
1271
|
+
"""
|
|
1272
|
+
NL-KVK.4.2.3.1: Extension taxonomy MUST NOT define typed dimensions.
|
|
1273
|
+
"""
|
|
1274
|
+
typedDims = []
|
|
1275
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1276
|
+
for concept in extensionData.extensionConcepts:
|
|
1277
|
+
if concept.isTypedDimension:
|
|
1278
|
+
typedDims.append(concept)
|
|
1279
|
+
if len(typedDims) > 0:
|
|
1280
|
+
yield Validation.error(
|
|
1281
|
+
codes='NL.NL-KVK.4.2.3.1.typedDimensionDefinitionInExtensionTaxonomy',
|
|
1282
|
+
modelObject=typedDims,
|
|
1283
|
+
msg=_('Typed dimensions are not allowed in the extension taxonomy. Update to remove the typed dimension.'))
|
|
1284
|
+
|
|
1285
|
+
|
|
1286
|
+
@validation(
|
|
1287
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1288
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
1289
|
+
)
|
|
1290
|
+
def rule_nl_kvk_4_3_1_1(
|
|
1291
|
+
pluginData: PluginValidationDataExtension,
|
|
1292
|
+
val: ValidateXbrl,
|
|
1293
|
+
*args: Any,
|
|
1294
|
+
**kwargs: Any,
|
|
1295
|
+
) -> Iterable[Validation]:
|
|
1296
|
+
"""
|
|
1297
|
+
NL-KVK.4.3.1.1: Anchoring relationships for elements other than concepts MUST not
|
|
1298
|
+
use 'http://www.esma.europa.eu/xbrl/esef/arcrole/wider-narrower' arcrole
|
|
1299
|
+
"""
|
|
1300
|
+
anchorData = pluginData.getAnchorData(val.modelXbrl)
|
|
1301
|
+
if len(anchorData.extLineItemsWronglyAnchored) > 0:
|
|
1302
|
+
yield Validation.error(
|
|
1303
|
+
codes='NL.NL-KVK.4.3.1.1.unexpectedAnchoringRelationshipsDefinedUsingWiderNarrowerArcrole',
|
|
1304
|
+
modelObject=anchorData.extLineItemsWronglyAnchored,
|
|
1305
|
+
msg=_('A custom element that is not a line item concept is using the wider-narrower arcrole. '
|
|
1306
|
+
'Only line item concepts should use this arcrole. '
|
|
1307
|
+
'Update the extension to no longer include this arcole.')
|
|
1308
|
+
)
|
|
1309
|
+
for anchor in anchorData.anchorsWithDomainItem:
|
|
1310
|
+
yield Validation.error(
|
|
1311
|
+
codes="NL.NL-KVK.4.3.1.1.unexpectedAnchoringRelationshipsDefinedUsingWiderNarrowerArcrole",
|
|
1312
|
+
msg=_("Anchoring relationships MUST be from and to concepts, from %(qname1)s to %(qname2)s"),
|
|
1313
|
+
modelObject=(anchor, anchor.fromModelObject, anchor.toModelObject),
|
|
1314
|
+
qname1=anchor.fromModelObject.qname,
|
|
1315
|
+
qname2=anchor.toModelObject.qname
|
|
1316
|
+
)
|
|
1317
|
+
for anchor in anchorData.anchorsWithDimensionItem:
|
|
1318
|
+
yield Validation.error(
|
|
1319
|
+
codes="NL.NL-KVK.4.3.1.1.unexpectedAnchoringRelationshipsDefinedUsingWiderNarrowerArcrole",
|
|
1320
|
+
msg=_("Anchoring relationships MUST be from and to concepts, from %(qname1)s to %(qname2)s"),
|
|
1321
|
+
modelObject=(anchor, anchor.fromModelObject, anchor.toModelObject),
|
|
1322
|
+
qname1=anchor.fromModelObject.qname,
|
|
1323
|
+
qname2=anchor.toModelObject.qname
|
|
1324
|
+
)
|
|
1325
|
+
|
|
1326
|
+
|
|
1327
|
+
@validation(
|
|
1328
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1329
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
1330
|
+
)
|
|
1331
|
+
def rule_nl_kvk_4_3_2_1(
|
|
1332
|
+
pluginData: PluginValidationDataExtension,
|
|
1333
|
+
val: ValidateXbrl,
|
|
1334
|
+
*args: Any,
|
|
1335
|
+
**kwargs: Any,
|
|
1336
|
+
) -> Iterable[Validation]:
|
|
1337
|
+
"""
|
|
1338
|
+
NL-KVK.4.3.2.1: Anchoring relationships for concepts MUST be defined in a dedicated
|
|
1339
|
+
extended link role (or roles if needed to properly represent the relationships),
|
|
1340
|
+
e.g. http://{default pattern for roles}/Anchoring.
|
|
1341
|
+
"""
|
|
1342
|
+
anchorData = pluginData.getAnchorData(val.modelXbrl)
|
|
1343
|
+
for elr, rels in anchorData.anchorsInDimensionalElrs.items():
|
|
1344
|
+
yield Validation.error(
|
|
1345
|
+
codes="NL.NL-KVK.4.3.2.1.anchoringRelationshipsForConceptsDefinedInElrContainingDimensionalRelationships",
|
|
1346
|
+
msg=_("Anchoring relationships for concepts MUST be defined in a dedicated extended link role "
|
|
1347
|
+
"(or roles if needed to properly represent the relationships), e.g. "
|
|
1348
|
+
"http://{issuer default pattern for roles}/Anchoring. %(anchoringDimensionalELR)s"),
|
|
1349
|
+
modelObject=rels,
|
|
1350
|
+
anchoringDimensionalELR=elr
|
|
1351
|
+
)
|
|
1352
|
+
|
|
1353
|
+
|
|
1354
|
+
@validation(
|
|
1355
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1356
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1211
1357
|
)
|
|
1212
1358
|
def rule_nl_kvk_4_4_1_1(
|
|
1213
1359
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1235,9 +1381,7 @@ def rule_nl_kvk_4_4_1_1(
|
|
|
1235
1381
|
|
|
1236
1382
|
@validation(
|
|
1237
1383
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1238
|
-
disclosureSystems=
|
|
1239
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1240
|
-
],
|
|
1384
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1241
1385
|
)
|
|
1242
1386
|
def rule_nl_kvk_4_4_2_1(
|
|
1243
1387
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1264,9 +1408,7 @@ def rule_nl_kvk_4_4_2_1(
|
|
|
1264
1408
|
|
|
1265
1409
|
@validation(
|
|
1266
1410
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1267
|
-
disclosureSystems=
|
|
1268
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1269
|
-
],
|
|
1411
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1270
1412
|
)
|
|
1271
1413
|
def rule_nl_kvk_4_4_2_2(
|
|
1272
1414
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1276,7 +1418,7 @@ def rule_nl_kvk_4_4_2_2(
|
|
|
1276
1418
|
) -> Iterable[Validation]:
|
|
1277
1419
|
"""
|
|
1278
1420
|
NL-KVK.4.4.2.2: Hypercubes appearing as target of definition arc with
|
|
1279
|
-
http://xbrl.org/int/dim/arcrole/all arcrole MUST have xbrldt:closed attribute set to
|
|
1421
|
+
http://xbrl.org/int/dim/arcrole/all arcrole MUST have xbrldt:closed attribute set to "true".
|
|
1280
1422
|
"""
|
|
1281
1423
|
errors = []
|
|
1282
1424
|
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
@@ -1294,9 +1436,7 @@ def rule_nl_kvk_4_4_2_2(
|
|
|
1294
1436
|
|
|
1295
1437
|
@validation(
|
|
1296
1438
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1297
|
-
disclosureSystems=
|
|
1298
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
1299
|
-
],
|
|
1439
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1300
1440
|
)
|
|
1301
1441
|
def rule_nl_kvk_4_4_2_3(
|
|
1302
1442
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1306,7 +1446,7 @@ def rule_nl_kvk_4_4_2_3(
|
|
|
1306
1446
|
) -> Iterable[Validation]:
|
|
1307
1447
|
"""
|
|
1308
1448
|
NL-KVK.4.4.2.3: Hypercubes appearing as target of definition arc with
|
|
1309
|
-
http://xbrl.org/int/dim/arcrole/notAll arcrole MUST have xbrldt:closed attribute set to
|
|
1449
|
+
http://xbrl.org/int/dim/arcrole/notAll arcrole MUST have xbrldt:closed attribute set to "false".
|
|
1310
1450
|
"""
|
|
1311
1451
|
errors = []
|
|
1312
1452
|
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
@@ -1324,9 +1464,308 @@ def rule_nl_kvk_4_4_2_3(
|
|
|
1324
1464
|
|
|
1325
1465
|
@validation(
|
|
1326
1466
|
hook=ValidationHook.XBRL_FINALLY,
|
|
1327
|
-
disclosureSystems=
|
|
1328
|
-
|
|
1329
|
-
|
|
1467
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1468
|
+
)
|
|
1469
|
+
def rule_nl_kvk_4_4_2_4(
|
|
1470
|
+
pluginData: PluginValidationDataExtension,
|
|
1471
|
+
val: ValidateXbrl,
|
|
1472
|
+
*args: Any,
|
|
1473
|
+
**kwargs: Any,
|
|
1474
|
+
) -> Iterable[Validation]:
|
|
1475
|
+
"""
|
|
1476
|
+
NL-KVK.4.4.2.4: Line items that do not require any dimensional information to tag data MUST be linked to the hypercube in the dedicated
|
|
1477
|
+
extended link role
|
|
1478
|
+
"""
|
|
1479
|
+
elrPrimaryItems = pluginData.getDimensionalData(val.modelXbrl).elrPrimaryItems
|
|
1480
|
+
errors = set(concept
|
|
1481
|
+
for qn, facts in val.modelXbrl.factsByQname.items()
|
|
1482
|
+
if any(not f.context.qnameDims for f in facts if f.context is not None)
|
|
1483
|
+
for concept in (val.modelXbrl.qnameConcepts.get(qn),)
|
|
1484
|
+
if concept is not None and
|
|
1485
|
+
not any(concept in elrPrimaryItems.get(lr, set()) for lr in NON_DIMENSIONALIZED_LINE_ITEM_LINKROLES) and
|
|
1486
|
+
concept not in elrPrimaryItems.get("*", set()))
|
|
1487
|
+
for error in errors:
|
|
1488
|
+
yield Validation.error(
|
|
1489
|
+
codes='NL.NL-KVK.4.4.2.4.extensionTaxonomyLineItemNotLinkedToAnyHypercube',
|
|
1490
|
+
modelObject=error,
|
|
1491
|
+
msg=_('A non-dimensional concept was not associated to a hypercube. Update relationship so concept is linked to a hypercube.'),
|
|
1492
|
+
)
|
|
1493
|
+
|
|
1494
|
+
@validation(
|
|
1495
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1496
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1497
|
+
)
|
|
1498
|
+
def rule_nl_kvk_4_4_3_1(
|
|
1499
|
+
pluginData: PluginValidationDataExtension,
|
|
1500
|
+
val: ValidateXbrl,
|
|
1501
|
+
*args: Any,
|
|
1502
|
+
**kwargs: Any,
|
|
1503
|
+
) -> Iterable[Validation]:
|
|
1504
|
+
"""
|
|
1505
|
+
NL-KVK.4.4.3.1: The extension taxonomy MUST not modify (prohibit and/or override) default members assigned to dimensions by the KVK taxonomy
|
|
1506
|
+
"""
|
|
1507
|
+
for modelLink in cast(list[ModelLink], val.modelXbrl.baseSets[XbrlConst.dimensionDefault, None, None, None]):
|
|
1508
|
+
if not pluginData.isExtensionUri(modelLink.modelDocument.uri, val.modelXbrl):
|
|
1509
|
+
continue
|
|
1510
|
+
for linkChild in modelLink:
|
|
1511
|
+
if (
|
|
1512
|
+
isinstance(linkChild,(ModelObject,PrototypeObject))
|
|
1513
|
+
and linkChild.get(XbrlConst.qnXlinkType.clarkNotation) == "arc"
|
|
1514
|
+
and linkChild.get(XbrlConst.qnXlinkArcRole.clarkNotation) == XbrlConst.dimensionDefault
|
|
1515
|
+
):
|
|
1516
|
+
fromLabel = linkChild.get(XbrlConst.qnXlinkFrom.clarkNotation)
|
|
1517
|
+
for fromResource in modelLink.labeledResources[fromLabel]:
|
|
1518
|
+
if not pluginData.isExtensionUri(fromResource.modelDocument.uri, val.modelXbrl):
|
|
1519
|
+
yield Validation.error(
|
|
1520
|
+
codes='NL.NL-KVK.4.4.3.1.extensionTaxonomyOverridesDefaultMembers',
|
|
1521
|
+
msg=_('A default member does not match the default member settings of the taxonomy. '
|
|
1522
|
+
'Update the default member to taxonomy defaults.'
|
|
1523
|
+
),
|
|
1524
|
+
modelObject=linkChild
|
|
1525
|
+
)
|
|
1526
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1527
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1528
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.dimensionDefault}):
|
|
1529
|
+
if arc.get("use") == "prohibited":
|
|
1530
|
+
yield Validation.error(
|
|
1531
|
+
codes='NL.NL-KVK.4.4.3.1.extensionTaxonomyOverridesDefaultMembers',
|
|
1532
|
+
msg=_('A default member is forbidden in the extension taxonomy. '
|
|
1533
|
+
'Update the default member to taxonomy defaults.'
|
|
1534
|
+
),
|
|
1535
|
+
modelObject=arc
|
|
1536
|
+
)
|
|
1537
|
+
|
|
1538
|
+
|
|
1539
|
+
@validation(
|
|
1540
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1541
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1542
|
+
)
|
|
1543
|
+
def rule_nl_kvk_4_4_3_2(
|
|
1544
|
+
pluginData: PluginValidationDataExtension,
|
|
1545
|
+
val: ValidateXbrl,
|
|
1546
|
+
*args: Any,
|
|
1547
|
+
**kwargs: Any,
|
|
1548
|
+
) -> Iterable[Validation]:
|
|
1549
|
+
"""
|
|
1550
|
+
NL-KVK.4.4.3.2: Each dimension in an extension taxonomy MUST be assigned to a default member in the ELR with role URI https://www.nltaxonomie.nl/kvk/role/axis-defaults.
|
|
1551
|
+
"""
|
|
1552
|
+
dimensionDefaults =val.modelXbrl.relationshipSet(XbrlConst.dimensionDefault, DEFAULT_MEMBER_ROLE_URI)
|
|
1553
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1554
|
+
for modelConcept in extensionData.extensionConcepts:
|
|
1555
|
+
if modelConcept.isExplicitDimension and not dimensionDefaults.fromModelObject(modelConcept):
|
|
1556
|
+
yield Validation.error(
|
|
1557
|
+
codes='NL.NL-KVK.4.4.2.3.extensionTaxonomyDimensionNotAssignedDefaultMemberInDedicatedPlaceholder',
|
|
1558
|
+
modelObject=modelConcept,
|
|
1559
|
+
msg=_('Axis is missing a default member or the default member does not match the taxonomy defaults. '
|
|
1560
|
+
'Update to set default member based on taxonomy defaults.'
|
|
1561
|
+
),
|
|
1562
|
+
)
|
|
1563
|
+
|
|
1564
|
+
|
|
1565
|
+
@validation(
|
|
1566
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1567
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1568
|
+
)
|
|
1569
|
+
def rule_nl_kvk_4_4_4_1(
|
|
1570
|
+
pluginData: PluginValidationDataExtension,
|
|
1571
|
+
val: ValidateXbrl,
|
|
1572
|
+
*args: Any,
|
|
1573
|
+
**kwargs: Any,
|
|
1574
|
+
) -> Iterable[Validation]:
|
|
1575
|
+
"""
|
|
1576
|
+
NL-KVK.4.4.5.1: Custom labels roles SHOULD NOT be used.
|
|
1577
|
+
"""
|
|
1578
|
+
warnings = set()
|
|
1579
|
+
for ELR in val.modelXbrl.relationshipSet(XbrlConst.parentChild).linkRoleUris:
|
|
1580
|
+
relSet = val.modelXbrl.relationshipSet(XbrlConst.parentChild, ELR)
|
|
1581
|
+
for rootConcept in relSet.rootConcepts:
|
|
1582
|
+
warnings = pluginData.checkLabels(set(), val.modelXbrl , rootConcept, relSet, None, set())
|
|
1583
|
+
if len(warnings) > 0:
|
|
1584
|
+
yield Validation.warning(
|
|
1585
|
+
codes='NL.NL-KVK.4.4.4.1.missingPreferredLabelRole',
|
|
1586
|
+
modelObject=warnings,
|
|
1587
|
+
msg=_('Multiple concepts exist in the presentation with the same label role. '
|
|
1588
|
+
'Review presentation if duplicate concepts should exist or separate preferred label roles should be set.'),
|
|
1589
|
+
)
|
|
1590
|
+
|
|
1591
|
+
|
|
1592
|
+
@validation(
|
|
1593
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1594
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1595
|
+
)
|
|
1596
|
+
def rule_nl_kvk_4_4_5_1(
|
|
1597
|
+
pluginData: PluginValidationDataExtension,
|
|
1598
|
+
val: ValidateXbrl,
|
|
1599
|
+
*args: Any,
|
|
1600
|
+
**kwargs: Any,
|
|
1601
|
+
) -> Iterable[Validation]:
|
|
1602
|
+
"""
|
|
1603
|
+
NL-KVK.4.4.5.1: Custom labels roles SHOULD NOT be used.
|
|
1604
|
+
"""
|
|
1605
|
+
warnings = []
|
|
1606
|
+
labelsRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
|
|
1607
|
+
if not labelsRelationshipSet:
|
|
1608
|
+
return
|
|
1609
|
+
for labelRels in labelsRelationshipSet.fromModelObjects().values():
|
|
1610
|
+
for labelRel in labelRels:
|
|
1611
|
+
label = cast(ModelResource, labelRel.toModelObject)
|
|
1612
|
+
if label.role in XbrlConst.standardLabelRoles:
|
|
1613
|
+
continue
|
|
1614
|
+
roleType = val.modelXbrl.roleTypes.get(label.role)
|
|
1615
|
+
if roleType is not None and \
|
|
1616
|
+
roleType[0].modelDocument.uri.startswith("http://www.xbrl.org/lrr"):
|
|
1617
|
+
continue
|
|
1618
|
+
warnings.append(label)
|
|
1619
|
+
if len(warnings) > 0:
|
|
1620
|
+
yield Validation.warning(
|
|
1621
|
+
codes='NL.NL-KVK.4.4.5.1.taxonomyElementLabelCustomRole',
|
|
1622
|
+
modelObject=warnings,
|
|
1623
|
+
msg=_('A custom label role has been used. Update to label role to non-custom.'),
|
|
1624
|
+
)
|
|
1625
|
+
|
|
1626
|
+
|
|
1627
|
+
@validation(
|
|
1628
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1629
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
1630
|
+
)
|
|
1631
|
+
def rule_nl_kvk_4_4_5_2(
|
|
1632
|
+
pluginData: PluginValidationDataExtension,
|
|
1633
|
+
val: ValidateXbrl,
|
|
1634
|
+
*args: Any,
|
|
1635
|
+
**kwargs: Any,
|
|
1636
|
+
) -> Iterable[Validation]:
|
|
1637
|
+
"""
|
|
1638
|
+
NL-KVK.4.4.5.2: Extension taxonomy elements SHOULD be assigned with at most one label for any combination of role and language.
|
|
1639
|
+
Additionally, extension taxonomies shall not override or replace standard labels of elements referenced in the KVK taxonomy.
|
|
1640
|
+
"""
|
|
1641
|
+
labelsRelationshipSet = val.modelXbrl.relationshipSet(XbrlConst.conceptLabel)
|
|
1642
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1643
|
+
extensionConcepts = extensionData.extensionConcepts
|
|
1644
|
+
for concept in val.modelXbrl.qnameConcepts.values():
|
|
1645
|
+
conceptLangRoleLabels = defaultdict(list)
|
|
1646
|
+
labelRels = labelsRelationshipSet.fromModelObject(concept)
|
|
1647
|
+
for labelRel in labelRels:
|
|
1648
|
+
label = cast(ModelResource, labelRel.toModelObject)
|
|
1649
|
+
conceptLangRoleLabels[(label.xmlLang, label.role)].append(labelRel.toModelObject)
|
|
1650
|
+
for (lang, labelRole), labels in conceptLangRoleLabels.items():
|
|
1651
|
+
if concept in extensionConcepts and len(labels) > 1:
|
|
1652
|
+
yield Validation.error(
|
|
1653
|
+
codes='NL.NL-KVK.4.4.5.2.taxonomyElementDuplicateLabels',
|
|
1654
|
+
msg=_('A concept was found with more than one label role for related language. '
|
|
1655
|
+
'Update to only one combination. Language: %(lang)s, Role: %(labelRole)s, Concept: %(concept)s.'),
|
|
1656
|
+
modelObject=[concept]+labels, concept=concept.qname, lang=lang, labelRole=labelRole,
|
|
1657
|
+
)
|
|
1658
|
+
elif labelRole == XbrlConst.standardLabel:
|
|
1659
|
+
hasCoreLabel = False
|
|
1660
|
+
hasExtensionLabel = False
|
|
1661
|
+
for label in labels:
|
|
1662
|
+
if pluginData.isExtensionUri(label.modelDocument.uri, val.modelXbrl):
|
|
1663
|
+
hasExtensionLabel = True
|
|
1664
|
+
else:
|
|
1665
|
+
hasCoreLabel = True
|
|
1666
|
+
if hasCoreLabel and hasExtensionLabel:
|
|
1667
|
+
labels_files = ['"%s": %s' % (l.text, l.modelDocument.basename) for l in labels]
|
|
1668
|
+
yield Validation.error(
|
|
1669
|
+
codes='NL.NL-KVK.4.4.5.2.taxonomyElementDuplicateLabels',
|
|
1670
|
+
msg=_("An extension taxonomy defines a standard label for a concept "
|
|
1671
|
+
"already labeled by the base taxonomy. Language: %(lang)s, "
|
|
1672
|
+
"Role: %(labelRole)s, Concept: %(concept)s, Labels: %(labels)s"),
|
|
1673
|
+
modelObject=[concept]+labels, concept=concept.qname, lang=lang,
|
|
1674
|
+
labelRole=labelRole, labels=", ".join(labels_files),
|
|
1675
|
+
)
|
|
1676
|
+
|
|
1677
|
+
|
|
1678
|
+
@validation(
|
|
1679
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1680
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1681
|
+
)
|
|
1682
|
+
def rule_nl_kvk_4_4_6_1(
|
|
1683
|
+
pluginData: PluginValidationDataExtension,
|
|
1684
|
+
val: ValidateXbrl,
|
|
1685
|
+
*args: Any,
|
|
1686
|
+
**kwargs: Any,
|
|
1687
|
+
) -> Iterable[Validation]:
|
|
1688
|
+
"""
|
|
1689
|
+
NL-KVK.4.4.6.1: All usable concepts in extension taxonomy relationships SHOULD be applied by tagged facts.
|
|
1690
|
+
"""
|
|
1691
|
+
conceptsUsed = {f.concept for f in val.modelXbrl.facts}
|
|
1692
|
+
unreportedLbLocs = set()
|
|
1693
|
+
for arcrole in (XbrlConst.parentChild, XbrlConst.summationItems, XbrlConst.all, XbrlConst.dimensionDomain, XbrlConst.domainMember):
|
|
1694
|
+
for rel in val.modelXbrl.relationshipSet(arcrole).modelRelationships:
|
|
1695
|
+
for object in (rel.fromModelObject, rel.toModelObject):
|
|
1696
|
+
if (object is None or
|
|
1697
|
+
object.isAbstract or
|
|
1698
|
+
object in conceptsUsed or
|
|
1699
|
+
not pluginData.isExtensionUri(rel.modelDocument.uri, val.modelXbrl)):
|
|
1700
|
+
continue
|
|
1701
|
+
if arcrole in (XbrlConst.parentChild, XbrlConst.summationItems):
|
|
1702
|
+
unreportedLbLocs.add(rel.fromLocator)
|
|
1703
|
+
elif object.type is not None and rel.isUsable and not object.type.isDomainItemType:
|
|
1704
|
+
unreportedLbLocs.add(rel.fromLocator)
|
|
1705
|
+
if len(unreportedLbLocs) > 0:
|
|
1706
|
+
yield Validation.warning(
|
|
1707
|
+
# Subtitle is capitalized inconsistently here because is tmatches the conformance suite. This may change in the future.
|
|
1708
|
+
codes='NL.NL-KVK.4.4.6.1.UsableConceptsNotAppliedByTaggedFacts',
|
|
1709
|
+
modelObject=unreportedLbLocs,
|
|
1710
|
+
msg=_('Axis is missing a default member or the default member does not match the taxonomy defaults. '
|
|
1711
|
+
'Update to set default member based on taxonomy defaults.')
|
|
1712
|
+
)
|
|
1713
|
+
|
|
1714
|
+
|
|
1715
|
+
@validation(
|
|
1716
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1717
|
+
disclosureSystems=NL_INLINE_GAAP_OTHER_DISCLOSURE_SYSTEMS,
|
|
1718
|
+
)
|
|
1719
|
+
def rule_nl_kvk_5_1_3_1(
|
|
1720
|
+
pluginData: PluginValidationDataExtension,
|
|
1721
|
+
val: ValidateXbrl,
|
|
1722
|
+
*args: Any,
|
|
1723
|
+
**kwargs: Any,
|
|
1724
|
+
) -> Iterable[Validation]:
|
|
1725
|
+
"""
|
|
1726
|
+
NL-KVK.5.1.3.1: Validate that the imported taxonomy matches the KVK-specified entry point.
|
|
1727
|
+
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-other-gaap.xsd
|
|
1728
|
+
"""
|
|
1729
|
+
uris = {doc[0].uri for doc in val.modelXbrl.namespaceDocs.values()}
|
|
1730
|
+
matches = uris & EFFECTIVE_KVK_GAAP_OTHER_ENTRYPOINT_FILES
|
|
1731
|
+
if not matches:
|
|
1732
|
+
yield Validation.error(
|
|
1733
|
+
codes='NL.NL-KVK.5.1.3.1.requiredEntryPointOtherGaapNotReferenced',
|
|
1734
|
+
msg=_('The extension taxonomy must import the entry point of the taxonomy files prepared by KVK.'),
|
|
1735
|
+
modelObject=val.modelXbrl.modelDocument
|
|
1736
|
+
)
|
|
1737
|
+
|
|
1738
|
+
|
|
1739
|
+
@validation(
|
|
1740
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1741
|
+
disclosureSystems=NL_INLINE_GAAP_OTHER_DISCLOSURE_SYSTEMS,
|
|
1742
|
+
)
|
|
1743
|
+
def rule_nl_kvk_5_1_3_2(
|
|
1744
|
+
pluginData: PluginValidationDataExtension,
|
|
1745
|
+
val: ValidateXbrl,
|
|
1746
|
+
*args: Any,
|
|
1747
|
+
**kwargs: Any,
|
|
1748
|
+
) -> Iterable[Validation]:
|
|
1749
|
+
"""
|
|
1750
|
+
NL-KVK.5.1.3.2: The legal entity's report MUST import the applicable version of
|
|
1751
|
+
the taxonomy files prepared by KVK.
|
|
1752
|
+
"""
|
|
1753
|
+
reportingPeriod = pluginData.getReportingPeriod(val.modelXbrl)
|
|
1754
|
+
uris = {doc[0].uri for doc in val.modelXbrl.namespaceDocs.values()}
|
|
1755
|
+
matches = uris & TAXONOMY_URLS_BY_YEAR.get(reportingPeriod or '', set())
|
|
1756
|
+
if not reportingPeriod or not matches:
|
|
1757
|
+
yield Validation.error(
|
|
1758
|
+
codes='NL.NL-KVK.5.1.3.2.incorrectVersionEntryPointOtherGaapReferenced',
|
|
1759
|
+
msg=_('The report MUST import the applicable version of the taxonomy files prepared by KVK '
|
|
1760
|
+
'for the reported financial reporting period. Verify the taxonomy version and make sure '
|
|
1761
|
+
'that FinancialReportingPeriod are tagged correctly.'),
|
|
1762
|
+
modelObject=val.modelXbrl.modelDocument
|
|
1763
|
+
)
|
|
1764
|
+
|
|
1765
|
+
|
|
1766
|
+
@validation(
|
|
1767
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1768
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
1330
1769
|
)
|
|
1331
1770
|
def rule_nl_kvk_6_1_1_1(
|
|
1332
1771
|
pluginData: PluginValidationDataExtension,
|
|
@@ -1348,3 +1787,89 @@ def rule_nl_kvk_6_1_1_1(
|
|
|
1348
1787
|
msg=_('The size of the report package must not exceed %(maxSize)s MBs, size is %(size)s MBs.'),
|
|
1349
1788
|
modelObject=val.modelXbrl, maxSize=MAX_REPORT_PACKAGE_SIZE_MBS, size=int(_size/1000000)
|
|
1350
1789
|
)
|
|
1790
|
+
|
|
1791
|
+
|
|
1792
|
+
@validation(
|
|
1793
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1794
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1795
|
+
)
|
|
1796
|
+
def rule_nl_kvk_RTS_Annex_IV_Par_11_G4_2_2_1(
|
|
1797
|
+
pluginData: PluginValidationDataExtension,
|
|
1798
|
+
val: ValidateXbrl,
|
|
1799
|
+
*args: Any,
|
|
1800
|
+
**kwargs: Any,
|
|
1801
|
+
) -> Iterable[Validation]:
|
|
1802
|
+
"""
|
|
1803
|
+
NL-KVK.RTS_Annex_IV_Par_11_G4-2-2_1: Extension taxonomy MUST NOT define a custom type if a matching
|
|
1804
|
+
type is defined by the XBRL 2.1 specification or in the XBRL Data Types Registry.
|
|
1805
|
+
Similar to ESEF.RTS.Annex.IV.Par.11.customDataTypeDuplicatingXbrlOrDtrEntry
|
|
1806
|
+
"""
|
|
1807
|
+
errors = []
|
|
1808
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1809
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1810
|
+
for modelType in modelDocument.xmlRootElement.iterdescendants(tag=XbrlConst.qnXsdComplexType.clarkNotation):
|
|
1811
|
+
if isinstance(modelType, ModelType) and \
|
|
1812
|
+
modelType.typeDerivedFrom is not None and \
|
|
1813
|
+
modelType.typeDerivedFrom.qname.namespaceURI == XbrlConst.xbrli and \
|
|
1814
|
+
not modelType.particlesList:
|
|
1815
|
+
errors.append(modelType)
|
|
1816
|
+
if len(errors) > 0:
|
|
1817
|
+
yield Validation.error(
|
|
1818
|
+
codes='NL.NL-KVK.RTS_Annex_IV_Par_11_G4-2-2_1.customTypeAlreadyDefinedByXbrl',
|
|
1819
|
+
msg=_('A custom data type is being used that matches a standard data type from the XBRL Data Type Registry. '
|
|
1820
|
+
'Update to remove duplicate data types and leverage the standard where appropriate.'),
|
|
1821
|
+
modelObject=errors
|
|
1822
|
+
)
|
|
1823
|
+
|
|
1824
|
+
|
|
1825
|
+
@validation(
|
|
1826
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1827
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1828
|
+
)
|
|
1829
|
+
def rule_nl_kvk_RTS_Annex_IV_Par_4_2(
|
|
1830
|
+
pluginData: PluginValidationDataExtension,
|
|
1831
|
+
val: ValidateXbrl,
|
|
1832
|
+
*args: Any,
|
|
1833
|
+
**kwargs: Any,
|
|
1834
|
+
) -> Iterable[Validation]:
|
|
1835
|
+
"""
|
|
1836
|
+
NL-KVK.RTS_Annex_IV_Par_4_2: Extension elements must be equipped with an appropriate balance attribute.
|
|
1837
|
+
"""
|
|
1838
|
+
errors = []
|
|
1839
|
+
for concept in pluginData.getExtensionConcepts(val.modelXbrl):
|
|
1840
|
+
if concept.isMonetary and concept.balance is None:
|
|
1841
|
+
errors.append(concept)
|
|
1842
|
+
if len(errors) > 0:
|
|
1843
|
+
yield Validation.error(
|
|
1844
|
+
codes='NL.NL-KVK.RTS_Annex_IV_Par_4_2.monetaryConceptWithoutBalance',
|
|
1845
|
+
msg=_('Extension elements must have an appropriate balance attribute.'),
|
|
1846
|
+
modelObject=errors
|
|
1847
|
+
)
|
|
1848
|
+
|
|
1849
|
+
|
|
1850
|
+
@validation(
|
|
1851
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1852
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1853
|
+
)
|
|
1854
|
+
def rule_nl_kvk_RTS_Annex_IV_Par_6(
|
|
1855
|
+
pluginData: PluginValidationDataExtension,
|
|
1856
|
+
val: ValidateXbrl,
|
|
1857
|
+
*args: Any,
|
|
1858
|
+
**kwargs: Any,
|
|
1859
|
+
) -> Iterable[Validation]:
|
|
1860
|
+
"""
|
|
1861
|
+
NL-KVK.RTS_Annex_IV_Par_6: Each NL-GAAP or IFRS financial statements structure MUST be equipped with
|
|
1862
|
+
a calculation linkbase
|
|
1863
|
+
"""
|
|
1864
|
+
hasCalcLinkbase = False
|
|
1865
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1866
|
+
for modelDoc, extensionDoc in extensionData.extensionDocuments.items():
|
|
1867
|
+
for linkbase in extensionDoc.linkbases:
|
|
1868
|
+
if linkbase.linkbaseType == LinkbaseType.CALCULATION:
|
|
1869
|
+
hasCalcLinkbase = True
|
|
1870
|
+
if not hasCalcLinkbase:
|
|
1871
|
+
yield Validation.error(
|
|
1872
|
+
codes='NL.NL-KVK.RTS_Annex_IV_Par_6.extensionTaxonomyWrongFilesStructure',
|
|
1873
|
+
msg=_('The filing package must include a calculation linkbase.'),
|
|
1874
|
+
modelObject=val.modelXbrl.modelDocument
|
|
1875
|
+
)
|