arelle-release 2.37.20__py3-none-any.whl → 2.37.22__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/CntlrCmdLine.py +8 -0
- arelle/RuntimeOptions.py +0 -6
- arelle/XbrlConst.py +4 -0
- arelle/_version.py +2 -2
- arelle/api/Session.py +92 -60
- arelle/plugin/validate/NL/DisclosureSystems.py +14 -0
- arelle/plugin/validate/NL/LinkbaseType.py +77 -0
- arelle/plugin/validate/NL/PluginValidationDataExtension.py +236 -27
- arelle/plugin/validate/NL/ValidationPluginExtension.py +11 -1
- arelle/plugin/validate/NL/__init__.py +0 -4
- arelle/plugin/validate/NL/resources/config.xml +6 -1
- arelle/plugin/validate/NL/rules/nl_kvk.py +596 -118
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.22.dist-info}/METADATA +1 -1
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.22.dist-info}/RECORD +23 -21
- tests/integration_tests/validation/conformance_suite_configs.py +2 -0
- tests/integration_tests/validation/conformance_suite_configurations/nl_inline_2024.py +16 -31
- 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/test_runtimeoptions.py +0 -13
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.22.dist-info}/WHEEL +0 -0
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.22.dist-info}/entry_points.txt +0 -0
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.22.dist-info}/licenses/LICENSE.md +0 -0
- {arelle_release-2.37.20.dist-info → arelle_release-2.37.22.dist-info}/top_level.txt +0 -0
|
@@ -6,13 +6,16 @@ from __future__ import annotations
|
|
|
6
6
|
from datetime import date
|
|
7
7
|
import zipfile
|
|
8
8
|
|
|
9
|
+
from arelle.ModelDtsObject import ModelLink
|
|
9
10
|
from arelle.ModelInstanceObject import ModelInlineFact
|
|
11
|
+
from arelle.ModelObject import ModelObject
|
|
12
|
+
from arelle.PrototypeDtsObject import PrototypeObject
|
|
10
13
|
from arelle.ValidateDuplicateFacts import getDuplicateFactSets
|
|
11
14
|
from arelle.XmlValidateConst import VALID
|
|
12
15
|
from collections.abc import Iterable
|
|
13
16
|
from typing import Any, cast, TYPE_CHECKING
|
|
14
17
|
|
|
15
|
-
from arelle import XmlUtil
|
|
18
|
+
from arelle import XmlUtil, XbrlConst, ModelDocument
|
|
16
19
|
from arelle.ValidateXbrl import ValidateXbrl
|
|
17
20
|
from arelle.typing import TypeGetText
|
|
18
21
|
from arelle.utils.PluginHooks import ValidationHook
|
|
@@ -20,11 +23,16 @@ from arelle.utils.validate.Decorator import validation
|
|
|
20
23
|
from arelle.utils.validate.Validation import Validation
|
|
21
24
|
from arelle.ValidateDuplicateFacts import getHashEquivalentFactGroups, getAspectEqualFacts
|
|
22
25
|
from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
|
|
23
|
-
from ..DisclosureSystems import
|
|
26
|
+
from ..DisclosureSystems import (ALL_NL_INLINE_DISCLOSURE_SYSTEMS, NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
27
|
+
NL_INLINE_GAAP_OTHER_DISCLOSURE_SYSTEMS)
|
|
28
|
+
from ..LinkbaseType import LinkbaseType
|
|
24
29
|
from ..PluginValidationDataExtension import (PluginValidationDataExtension, ALLOWABLE_LANGUAGES,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
30
|
+
DEFAULT_MEMBER_ROLE_URI, DISALLOWED_IXT_NAMESPACES,
|
|
31
|
+
EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES,
|
|
32
|
+
EFFECTIVE_KVK_GAAP_OTHER_ENTRYPOINT_FILES,
|
|
33
|
+
MAX_REPORT_PACKAGE_SIZE_MBS, TAXONOMY_URLS_BY_YEAR,
|
|
34
|
+
XBRLI_IDENTIFIER_PATTERN, XBRLI_IDENTIFIER_SCHEMA,
|
|
35
|
+
QN_DOMAIN_ITEM_TYPES)
|
|
28
36
|
|
|
29
37
|
if TYPE_CHECKING:
|
|
30
38
|
from arelle.ModelXbrl import ModelXbrl
|
|
@@ -44,9 +52,7 @@ def _getReportingPeriodDateValue(modelXbrl: ModelXbrl, qname: QName) -> date | N
|
|
|
44
52
|
|
|
45
53
|
@validation(
|
|
46
54
|
hook=ValidationHook.XBRL_FINALLY,
|
|
47
|
-
disclosureSystems=
|
|
48
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
49
|
-
],
|
|
55
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
50
56
|
)
|
|
51
57
|
def rule_nl_kvk_3_1_1_1(
|
|
52
58
|
pluginData: PluginValidationDataExtension,
|
|
@@ -72,9 +78,7 @@ def rule_nl_kvk_3_1_1_1(
|
|
|
72
78
|
|
|
73
79
|
@validation(
|
|
74
80
|
hook=ValidationHook.XBRL_FINALLY,
|
|
75
|
-
disclosureSystems=
|
|
76
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
77
|
-
],
|
|
81
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
78
82
|
)
|
|
79
83
|
def rule_nl_kvk_3_1_1_2(
|
|
80
84
|
pluginData: PluginValidationDataExtension,
|
|
@@ -99,9 +103,7 @@ def rule_nl_kvk_3_1_1_2(
|
|
|
99
103
|
|
|
100
104
|
@validation(
|
|
101
105
|
hook=ValidationHook.XBRL_FINALLY,
|
|
102
|
-
disclosureSystems=
|
|
103
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
104
|
-
],
|
|
106
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
105
107
|
)
|
|
106
108
|
def rule_nl_kvk_3_1_2_1(
|
|
107
109
|
pluginData: PluginValidationDataExtension,
|
|
@@ -123,9 +125,7 @@ def rule_nl_kvk_3_1_2_1(
|
|
|
123
125
|
|
|
124
126
|
@validation(
|
|
125
127
|
hook=ValidationHook.XBRL_FINALLY,
|
|
126
|
-
disclosureSystems=
|
|
127
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
128
|
-
],
|
|
128
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
129
129
|
)
|
|
130
130
|
def rule_nl_kvk_3_1_2_2(
|
|
131
131
|
pluginData: PluginValidationDataExtension,
|
|
@@ -147,9 +147,7 @@ def rule_nl_kvk_3_1_2_2(
|
|
|
147
147
|
|
|
148
148
|
@validation(
|
|
149
149
|
hook=ValidationHook.XBRL_FINALLY,
|
|
150
|
-
disclosureSystems=
|
|
151
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
152
|
-
],
|
|
150
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
153
151
|
)
|
|
154
152
|
def rule_nl_kvk_3_1_3_1 (
|
|
155
153
|
pluginData: PluginValidationDataExtension,
|
|
@@ -171,9 +169,7 @@ def rule_nl_kvk_3_1_3_1 (
|
|
|
171
169
|
|
|
172
170
|
@validation(
|
|
173
171
|
hook=ValidationHook.XBRL_FINALLY,
|
|
174
|
-
disclosureSystems=
|
|
175
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
176
|
-
],
|
|
172
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
177
173
|
)
|
|
178
174
|
def rule_nl_kvk_3_1_3_2 (
|
|
179
175
|
pluginData: PluginValidationDataExtension,
|
|
@@ -195,9 +191,7 @@ def rule_nl_kvk_3_1_3_2 (
|
|
|
195
191
|
|
|
196
192
|
@validation(
|
|
197
193
|
hook=ValidationHook.XBRL_FINALLY,
|
|
198
|
-
disclosureSystems=
|
|
199
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
200
|
-
],
|
|
194
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
201
195
|
)
|
|
202
196
|
def rule_nl_kvk_3_1_4_1 (
|
|
203
197
|
pluginData: PluginValidationDataExtension,
|
|
@@ -220,9 +214,7 @@ def rule_nl_kvk_3_1_4_1 (
|
|
|
220
214
|
|
|
221
215
|
@validation(
|
|
222
216
|
hook=ValidationHook.XBRL_FINALLY,
|
|
223
|
-
disclosureSystems=
|
|
224
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
225
|
-
],
|
|
217
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
226
218
|
)
|
|
227
219
|
def rule_nl_kvk_3_1_4_2 (
|
|
228
220
|
pluginData: PluginValidationDataExtension,
|
|
@@ -249,9 +241,7 @@ def rule_nl_kvk_3_1_4_2 (
|
|
|
249
241
|
|
|
250
242
|
@validation(
|
|
251
243
|
hook=ValidationHook.XBRL_FINALLY,
|
|
252
|
-
disclosureSystems=
|
|
253
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
254
|
-
],
|
|
244
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
255
245
|
)
|
|
256
246
|
def rule_nl_kvk_3_2_1_1 (
|
|
257
247
|
pluginData: PluginValidationDataExtension,
|
|
@@ -276,9 +266,7 @@ def rule_nl_kvk_3_2_1_1 (
|
|
|
276
266
|
|
|
277
267
|
@validation(
|
|
278
268
|
hook=ValidationHook.XBRL_FINALLY,
|
|
279
|
-
disclosureSystems=
|
|
280
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
281
|
-
],
|
|
269
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
282
270
|
)
|
|
283
271
|
def rule_nl_kvk_3_2_3_1 (
|
|
284
272
|
pluginData: PluginValidationDataExtension,
|
|
@@ -304,9 +292,7 @@ def rule_nl_kvk_3_2_3_1 (
|
|
|
304
292
|
|
|
305
293
|
@validation(
|
|
306
294
|
hook=ValidationHook.XBRL_FINALLY,
|
|
307
|
-
disclosureSystems=
|
|
308
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
309
|
-
],
|
|
295
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
310
296
|
)
|
|
311
297
|
def rule_nl_kvk_3_2_4_1 (
|
|
312
298
|
pluginData: PluginValidationDataExtension,
|
|
@@ -334,9 +320,7 @@ def rule_nl_kvk_3_2_4_1 (
|
|
|
334
320
|
|
|
335
321
|
@validation(
|
|
336
322
|
hook=ValidationHook.XBRL_FINALLY,
|
|
337
|
-
disclosureSystems=
|
|
338
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
339
|
-
],
|
|
323
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
340
324
|
)
|
|
341
325
|
def rule_nl_kvk_3_2_4_2 (
|
|
342
326
|
pluginData: PluginValidationDataExtension,
|
|
@@ -364,9 +348,7 @@ def rule_nl_kvk_3_2_4_2 (
|
|
|
364
348
|
|
|
365
349
|
@validation(
|
|
366
350
|
hook=ValidationHook.XBRL_FINALLY,
|
|
367
|
-
disclosureSystems=
|
|
368
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
369
|
-
],
|
|
351
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
370
352
|
)
|
|
371
353
|
def rule_nl_kvk_3_2_7_1 (
|
|
372
354
|
pluginData: PluginValidationDataExtension,
|
|
@@ -393,9 +375,7 @@ def rule_nl_kvk_3_2_7_1 (
|
|
|
393
375
|
|
|
394
376
|
@validation(
|
|
395
377
|
hook=ValidationHook.XBRL_FINALLY,
|
|
396
|
-
disclosureSystems=
|
|
397
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
398
|
-
],
|
|
378
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
399
379
|
)
|
|
400
380
|
def rule_nl_kvk_3_3_1_1 (
|
|
401
381
|
pluginData: PluginValidationDataExtension,
|
|
@@ -416,9 +396,7 @@ def rule_nl_kvk_3_3_1_1 (
|
|
|
416
396
|
|
|
417
397
|
@validation(
|
|
418
398
|
hook=ValidationHook.XBRL_FINALLY,
|
|
419
|
-
disclosureSystems=
|
|
420
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
421
|
-
],
|
|
399
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
422
400
|
)
|
|
423
401
|
def rule_nl_kvk_3_3_1_2 (
|
|
424
402
|
pluginData: PluginValidationDataExtension,
|
|
@@ -440,9 +418,7 @@ def rule_nl_kvk_3_3_1_2 (
|
|
|
440
418
|
|
|
441
419
|
@validation(
|
|
442
420
|
hook=ValidationHook.XBRL_FINALLY,
|
|
443
|
-
disclosureSystems=
|
|
444
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
445
|
-
],
|
|
421
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
446
422
|
)
|
|
447
423
|
def rule_nl_kvk_3_3_1_3 (
|
|
448
424
|
pluginData: PluginValidationDataExtension,
|
|
@@ -466,9 +442,7 @@ def rule_nl_kvk_3_3_1_3 (
|
|
|
466
442
|
|
|
467
443
|
@validation(
|
|
468
444
|
hook=ValidationHook.XBRL_FINALLY,
|
|
469
|
-
disclosureSystems=
|
|
470
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
471
|
-
],
|
|
445
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
472
446
|
)
|
|
473
447
|
def rule_nl_kvk_3_4_1_1 (
|
|
474
448
|
pluginData: PluginValidationDataExtension,
|
|
@@ -490,9 +464,7 @@ def rule_nl_kvk_3_4_1_1 (
|
|
|
490
464
|
|
|
491
465
|
@validation(
|
|
492
466
|
hook=ValidationHook.XBRL_FINALLY,
|
|
493
|
-
disclosureSystems=
|
|
494
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
495
|
-
],
|
|
467
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
496
468
|
)
|
|
497
469
|
def rule_nl_kvk_3_4_1_2 (
|
|
498
470
|
pluginData: PluginValidationDataExtension,
|
|
@@ -514,9 +486,7 @@ def rule_nl_kvk_3_4_1_2 (
|
|
|
514
486
|
|
|
515
487
|
@validation(
|
|
516
488
|
hook=ValidationHook.XBRL_FINALLY,
|
|
517
|
-
disclosureSystems=
|
|
518
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
519
|
-
],
|
|
489
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
520
490
|
)
|
|
521
491
|
def rule_nl_kvk_3_4_1_3 (
|
|
522
492
|
pluginData: PluginValidationDataExtension,
|
|
@@ -532,7 +502,7 @@ def rule_nl_kvk_3_4_1_3 (
|
|
|
532
502
|
if len(facts) > 0:
|
|
533
503
|
yield Validation.error(
|
|
534
504
|
codes='NL.NL-KVK.3.4.1.3.transformableElementIncludedInHiddenSection',
|
|
535
|
-
msg=_('The ix:hidden section should not include elements that are eligible for transformation'
|
|
505
|
+
msg=_('The ix:hidden section should not include elements that are eligible for transformation '
|
|
536
506
|
'according to the latest recommended Transformation Rules Registry.'),
|
|
537
507
|
modelObject=facts
|
|
538
508
|
)
|
|
@@ -540,9 +510,7 @@ def rule_nl_kvk_3_4_1_3 (
|
|
|
540
510
|
|
|
541
511
|
@validation(
|
|
542
512
|
hook=ValidationHook.XBRL_FINALLY,
|
|
543
|
-
disclosureSystems=
|
|
544
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
545
|
-
],
|
|
513
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
546
514
|
)
|
|
547
515
|
def rule_nl_kvk_3_4_1_4 (
|
|
548
516
|
pluginData: PluginValidationDataExtension,
|
|
@@ -564,9 +532,7 @@ def rule_nl_kvk_3_4_1_4 (
|
|
|
564
532
|
|
|
565
533
|
@validation(
|
|
566
534
|
hook=ValidationHook.XBRL_FINALLY,
|
|
567
|
-
disclosureSystems=
|
|
568
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
569
|
-
],
|
|
535
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
570
536
|
)
|
|
571
537
|
def rule_nl_kvk_3_4_1_5 (
|
|
572
538
|
pluginData: PluginValidationDataExtension,
|
|
@@ -588,9 +554,7 @@ def rule_nl_kvk_3_4_1_5 (
|
|
|
588
554
|
|
|
589
555
|
@validation(
|
|
590
556
|
hook=ValidationHook.XBRL_FINALLY,
|
|
591
|
-
disclosureSystems=
|
|
592
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
593
|
-
],
|
|
557
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
594
558
|
)
|
|
595
559
|
def rule_nl_kvk_3_4_2_1 (
|
|
596
560
|
pluginData: PluginValidationDataExtension,
|
|
@@ -612,9 +576,7 @@ def rule_nl_kvk_3_4_2_1 (
|
|
|
612
576
|
|
|
613
577
|
@validation(
|
|
614
578
|
hook=ValidationHook.XBRL_FINALLY,
|
|
615
|
-
disclosureSystems=
|
|
616
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
617
|
-
],
|
|
579
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
618
580
|
)
|
|
619
581
|
def rule_nl_kvk_3_5_2_1(
|
|
620
582
|
pluginData: PluginValidationDataExtension,
|
|
@@ -643,9 +605,7 @@ def rule_nl_kvk_3_5_2_1(
|
|
|
643
605
|
|
|
644
606
|
@validation(
|
|
645
607
|
hook=ValidationHook.XBRL_FINALLY,
|
|
646
|
-
disclosureSystems=
|
|
647
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
648
|
-
],
|
|
608
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
649
609
|
)
|
|
650
610
|
def rule_nl_kvk_3_5_2_2(
|
|
651
611
|
pluginData: PluginValidationDataExtension,
|
|
@@ -674,9 +634,7 @@ def rule_nl_kvk_3_5_2_2(
|
|
|
674
634
|
|
|
675
635
|
@validation(
|
|
676
636
|
hook=ValidationHook.XBRL_FINALLY,
|
|
677
|
-
disclosureSystems=
|
|
678
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
679
|
-
],
|
|
637
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
680
638
|
)
|
|
681
639
|
def rule_nl_kvk_3_5_2_3(
|
|
682
640
|
pluginData: PluginValidationDataExtension,
|
|
@@ -705,9 +663,7 @@ def rule_nl_kvk_3_5_2_3(
|
|
|
705
663
|
|
|
706
664
|
@validation(
|
|
707
665
|
hook=ValidationHook.XBRL_FINALLY,
|
|
708
|
-
disclosureSystems=
|
|
709
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
710
|
-
],
|
|
666
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
711
667
|
)
|
|
712
668
|
def rule_nl_kvk_3_5_3_1(
|
|
713
669
|
pluginData: PluginValidationDataExtension,
|
|
@@ -729,9 +685,7 @@ def rule_nl_kvk_3_5_3_1(
|
|
|
729
685
|
|
|
730
686
|
@validation(
|
|
731
687
|
hook=ValidationHook.XBRL_FINALLY,
|
|
732
|
-
disclosureSystems=
|
|
733
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
734
|
-
],
|
|
688
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
735
689
|
)
|
|
736
690
|
def rule_nl_kvk_3_5_4_1 (
|
|
737
691
|
pluginData: PluginValidationDataExtension,
|
|
@@ -754,9 +708,7 @@ def rule_nl_kvk_3_5_4_1 (
|
|
|
754
708
|
|
|
755
709
|
@validation(
|
|
756
710
|
hook=ValidationHook.XBRL_FINALLY,
|
|
757
|
-
disclosureSystems=
|
|
758
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
759
|
-
],
|
|
711
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
760
712
|
)
|
|
761
713
|
def rule_nl_kvk_3_6_3_1(
|
|
762
714
|
pluginData: PluginValidationDataExtension,
|
|
@@ -770,7 +722,7 @@ def rule_nl_kvk_3_6_3_1(
|
|
|
770
722
|
"""
|
|
771
723
|
invalidBasenames = []
|
|
772
724
|
for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
|
|
773
|
-
filenameParts = pluginData.getFilenameParts(basename)
|
|
725
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
|
|
774
726
|
if not filenameParts:
|
|
775
727
|
continue # Filename is not formatted correctly enough to determine {base}
|
|
776
728
|
if len(filenameParts.get('base', '')) > 20:
|
|
@@ -787,9 +739,7 @@ def rule_nl_kvk_3_6_3_1(
|
|
|
787
739
|
|
|
788
740
|
@validation(
|
|
789
741
|
hook=ValidationHook.XBRL_FINALLY,
|
|
790
|
-
disclosureSystems=
|
|
791
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
792
|
-
],
|
|
742
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
793
743
|
)
|
|
794
744
|
def rule_nl_kvk_3_6_3_2(
|
|
795
745
|
pluginData: PluginValidationDataExtension,
|
|
@@ -803,7 +753,7 @@ def rule_nl_kvk_3_6_3_2(
|
|
|
803
753
|
"""
|
|
804
754
|
invalidBasenames = []
|
|
805
755
|
for basename in pluginData.getIxdsDocBasenames(val.modelXbrl):
|
|
806
|
-
filenameParts = pluginData.getFilenameParts(basename)
|
|
756
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getFilenameFormatPattern())
|
|
807
757
|
if not filenameParts:
|
|
808
758
|
invalidBasenames.append(basename)
|
|
809
759
|
if len(invalidBasenames) > 0:
|
|
@@ -819,9 +769,7 @@ def rule_nl_kvk_3_6_3_2(
|
|
|
819
769
|
|
|
820
770
|
@validation(
|
|
821
771
|
hook=ValidationHook.XBRL_FINALLY,
|
|
822
|
-
disclosureSystems=
|
|
823
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
824
|
-
],
|
|
772
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
825
773
|
)
|
|
826
774
|
def rule_nl_kvk_3_6_3_3(
|
|
827
775
|
pluginData: PluginValidationDataExtension,
|
|
@@ -849,9 +797,7 @@ def rule_nl_kvk_3_6_3_3(
|
|
|
849
797
|
|
|
850
798
|
@validation(
|
|
851
799
|
hook=ValidationHook.FINALLY,
|
|
852
|
-
disclosureSystems=
|
|
853
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
854
|
-
],
|
|
800
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
855
801
|
)
|
|
856
802
|
def rule_nl_kvk_3_7_1_1(
|
|
857
803
|
pluginData: PluginValidationDataExtension,
|
|
@@ -879,9 +825,7 @@ def rule_nl_kvk_3_7_1_1(
|
|
|
879
825
|
|
|
880
826
|
@validation(
|
|
881
827
|
hook=ValidationHook.FINALLY,
|
|
882
|
-
disclosureSystems=
|
|
883
|
-
DISCLOSURE_SYSTEM_NL_INLINE_2024
|
|
884
|
-
],
|
|
828
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
885
829
|
)
|
|
886
830
|
def rule_nl_kvk_3_7_1_2(
|
|
887
831
|
pluginData: PluginValidationDataExtension,
|
|
@@ -909,9 +853,93 @@ def rule_nl_kvk_3_7_1_2(
|
|
|
909
853
|
|
|
910
854
|
@validation(
|
|
911
855
|
hook=ValidationHook.XBRL_FINALLY,
|
|
912
|
-
disclosureSystems=
|
|
913
|
-
|
|
914
|
-
|
|
856
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
857
|
+
)
|
|
858
|
+
def rule_nl_kvk_4_1_1_1(
|
|
859
|
+
pluginData: PluginValidationDataExtension,
|
|
860
|
+
val: ValidateXbrl,
|
|
861
|
+
*args: Any,
|
|
862
|
+
**kwargs: Any,
|
|
863
|
+
) -> Iterable[Validation]:
|
|
864
|
+
"""
|
|
865
|
+
NL-KVK.4.1.1.1: Extension taxonomies MUST consist of at least a schema file and presentation,
|
|
866
|
+
calculation and definition linkbases.
|
|
867
|
+
A label linkbase is also required if extension elements are present.
|
|
868
|
+
"""
|
|
869
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
870
|
+
linkbaseIsMissing = {
|
|
871
|
+
LinkbaseType.CALCULATION: True,
|
|
872
|
+
LinkbaseType.DEFINITION: True,
|
|
873
|
+
LinkbaseType.LABEL: len(extensionData.extensionConcepts) > 0,
|
|
874
|
+
LinkbaseType.PRESENTATION: True,
|
|
875
|
+
}
|
|
876
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
877
|
+
hasArcs = False
|
|
878
|
+
linkbaseType = LinkbaseType.fromRefUri(extensionDocumentData.hrefXlinkRole)
|
|
879
|
+
for linkbaseData in extensionDocumentData.linkbases:
|
|
880
|
+
if linkbaseType is not None:
|
|
881
|
+
if linkbaseType == linkbaseData.linkbaseType:
|
|
882
|
+
if linkbaseData.hasArcs:
|
|
883
|
+
hasArcs = True
|
|
884
|
+
break
|
|
885
|
+
elif linkbaseData.hasArcs:
|
|
886
|
+
linkbaseType = linkbaseData.linkbaseType
|
|
887
|
+
hasArcs = True
|
|
888
|
+
break
|
|
889
|
+
if linkbaseType is None:
|
|
890
|
+
continue
|
|
891
|
+
if hasArcs and linkbaseIsMissing.get(linkbaseType, False):
|
|
892
|
+
linkbaseIsMissing[linkbaseType] = False
|
|
893
|
+
missingFiles = set(linkbaseType.getLowerName() for linkbaseType, isMissing in linkbaseIsMissing.items() if isMissing)
|
|
894
|
+
if len(missingFiles) > 0:
|
|
895
|
+
yield Validation.error(
|
|
896
|
+
codes='NL.NL-KVK.4.1.1.1.extensionTaxonomyWrongFilesStructure',
|
|
897
|
+
msg=_('The extension taxonomy is missing one or more required components: %(missingFiles)s '
|
|
898
|
+
'Review to ensure that the schema file, presentation, calculation, '
|
|
899
|
+
'and definition linkbases are included and not empty. '
|
|
900
|
+
'A label linkbase is also required if extension elements are present.'),
|
|
901
|
+
modelObject=val.modelXbrl, missingFiles=", ".join(missingFiles)
|
|
902
|
+
)
|
|
903
|
+
|
|
904
|
+
|
|
905
|
+
@validation(
|
|
906
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
907
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
908
|
+
)
|
|
909
|
+
def rule_nl_kvk_4_1_1_2(
|
|
910
|
+
pluginData: PluginValidationDataExtension,
|
|
911
|
+
val: ValidateXbrl,
|
|
912
|
+
*args: Any,
|
|
913
|
+
**kwargs: Any,
|
|
914
|
+
) -> Iterable[Validation]:
|
|
915
|
+
"""
|
|
916
|
+
NL-KVK.4.1.1.2: Each linkbase type MUST be provided in a separate linkbase file.
|
|
917
|
+
"""
|
|
918
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
919
|
+
errors = []
|
|
920
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
921
|
+
linkbasesFound = set(
|
|
922
|
+
linkbase.linkbaseType.getLowerName()
|
|
923
|
+
for linkbase in extensionDocumentData.linkbases
|
|
924
|
+
if linkbase.linkbaseType is not None
|
|
925
|
+
)
|
|
926
|
+
if len(linkbasesFound) > 1:
|
|
927
|
+
errors.append((modelDocument, linkbasesFound))
|
|
928
|
+
for modelDocument, linkbasesFound in errors:
|
|
929
|
+
yield Validation.error(
|
|
930
|
+
codes='NL.NL-KVK.4.1.1.2.linkbasesNotSeparateFiles',
|
|
931
|
+
msg=_('Linkbase types are not stored in separate files. '
|
|
932
|
+
'Review linkbase files and ensure they are provided as individual files. '
|
|
933
|
+
'Found: %(linkbasesFound)s. in %(basename)s.'),
|
|
934
|
+
modelObject=modelDocument.xmlRootElement,
|
|
935
|
+
basename=modelDocument.basename,
|
|
936
|
+
linkbasesFound=", ".join(sorted(linkbasesFound))
|
|
937
|
+
)
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
@validation(
|
|
941
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
942
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
915
943
|
)
|
|
916
944
|
def rule_nl_kvk_4_1_2_1(
|
|
917
945
|
pluginData: PluginValidationDataExtension,
|
|
@@ -921,24 +949,474 @@ def rule_nl_kvk_4_1_2_1(
|
|
|
921
949
|
) -> Iterable[Validation]:
|
|
922
950
|
"""
|
|
923
951
|
NL-KVK.4.1.2.1: Validate that the imported taxonomy matches the KVK-specified entry point.
|
|
924
|
-
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd
|
|
925
|
-
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd
|
|
952
|
+
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd
|
|
953
|
+
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd
|
|
954
|
+
"""
|
|
955
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
956
|
+
matches = extensionData.extensionImportedUrls & EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES
|
|
957
|
+
if not matches:
|
|
958
|
+
yield Validation.error(
|
|
959
|
+
codes='NL.NL-KVK.4.1.2.1.requiredEntryPointNotImported',
|
|
960
|
+
msg=_('The extension taxonomy must import the entry point of the taxonomy files prepared by KVK.'),
|
|
961
|
+
modelObject=val.modelXbrl.modelDocument
|
|
962
|
+
)
|
|
963
|
+
|
|
964
|
+
|
|
965
|
+
@validation(
|
|
966
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
967
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
968
|
+
)
|
|
969
|
+
def rule_nl_kvk_4_1_2_2(
|
|
970
|
+
pluginData: PluginValidationDataExtension,
|
|
971
|
+
val: ValidateXbrl,
|
|
972
|
+
*args: Any,
|
|
973
|
+
**kwargs: Any,
|
|
974
|
+
) -> Iterable[Validation]:
|
|
975
|
+
"""
|
|
976
|
+
NL-KVK.4.1.2.2: The legal entity’s extension taxonomy MUST import the applicable version of
|
|
977
|
+
the taxonomy files prepared by KVK.
|
|
978
|
+
"""
|
|
979
|
+
reportingPeriod = pluginData.getReportingPeriod(val.modelXbrl)
|
|
980
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
981
|
+
matches = extensionData.extensionImportedUrls & TAXONOMY_URLS_BY_YEAR.get(reportingPeriod or '', set())
|
|
982
|
+
if not reportingPeriod or not matches:
|
|
983
|
+
yield Validation.error(
|
|
984
|
+
codes='NL.NL-KVK.4.1.2.2.incorrectKvkTaxonomyVersionUsed',
|
|
985
|
+
msg=_('The extension taxonomy MUST import the applicable version of the taxonomy files prepared by KVK '
|
|
986
|
+
'for the reported financial reporting period. Verify the taxonomy version and make sure '
|
|
987
|
+
'that FinancialReportingPeriod are tagged correctly.'),
|
|
988
|
+
modelObject=val.modelXbrl.modelDocument
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
@validation(
|
|
993
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
994
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
995
|
+
)
|
|
996
|
+
def rule_nl_kvk_4_1_5_1(
|
|
997
|
+
pluginData: PluginValidationDataExtension,
|
|
998
|
+
val: ValidateXbrl,
|
|
999
|
+
*args: Any,
|
|
1000
|
+
**kwargs: Any,
|
|
1001
|
+
) -> Iterable[Validation]:
|
|
1002
|
+
"""
|
|
1003
|
+
NL-KVK.4.1.5.1: The `{base}` component of the extension document filename SHOULD not exceed twenty characters.
|
|
1004
|
+
"""
|
|
1005
|
+
invalidBasenames = []
|
|
1006
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1007
|
+
for extensionDocument in extensionData.extensionDocuments.values():
|
|
1008
|
+
basename = extensionDocument.basename
|
|
1009
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getExtensionFilenameFormatPattern())
|
|
1010
|
+
if not filenameParts:
|
|
1011
|
+
continue # Filename is not formatted correctly enough to determine {base}
|
|
1012
|
+
if len(filenameParts.get('base', '')) > 20:
|
|
1013
|
+
invalidBasenames.append(basename)
|
|
1014
|
+
if len(invalidBasenames) > 0:
|
|
1015
|
+
yield Validation.warning(
|
|
1016
|
+
codes='NL.NL-KVK.4.1.5.1.baseComponentInNameOfTaxonomyFileExceedsTwentyCharacters',
|
|
1017
|
+
invalidBasenames=', '.join(invalidBasenames),
|
|
1018
|
+
msg=_('The {base} component of the extension document filename is greater than twenty characters. '
|
|
1019
|
+
'The {base} component can either be the KVK number or the legal entity\'s name. '
|
|
1020
|
+
'If the legal entity\'s name has been utilized, review to shorten the name to twenty characters or less. '
|
|
1021
|
+
'Invalid filenames: %(invalidBasenames)s'))
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
@validation(
|
|
1025
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1026
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1027
|
+
)
|
|
1028
|
+
def rule_nl_kvk_4_1_5_2(
|
|
1029
|
+
pluginData: PluginValidationDataExtension,
|
|
1030
|
+
val: ValidateXbrl,
|
|
1031
|
+
*args: Any,
|
|
1032
|
+
**kwargs: Any,
|
|
1033
|
+
) -> Iterable[Validation]:
|
|
1034
|
+
"""
|
|
1035
|
+
NL-KVK.4.1.5.2: Extension document filename SHOULD match the {base}-{date}_{suffix}-{lang}.{extension} pattern.
|
|
1036
|
+
"""
|
|
1037
|
+
invalidBasenames = []
|
|
1038
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1039
|
+
for extensionDocument in extensionData.extensionDocuments.values():
|
|
1040
|
+
basename = extensionDocument.basename
|
|
1041
|
+
filenameParts = pluginData.getFilenameParts(basename, pluginData.getExtensionFilenameFormatPattern())
|
|
1042
|
+
if not filenameParts:
|
|
1043
|
+
invalidBasenames.append(basename)
|
|
1044
|
+
if len(invalidBasenames) > 0:
|
|
1045
|
+
yield Validation.warning(
|
|
1046
|
+
codes='NL.NL-KVK.4.1.5.2.extensionTaxonomyDocumentNameDoesNotFollowNamingConvention',
|
|
1047
|
+
invalidBasenames=', '.join(invalidBasenames),
|
|
1048
|
+
msg=_('The extension document filename does not match the naming convention outlined by the KVK. '
|
|
1049
|
+
'It is recommended to be in the {base}-{date}_{suffix}-{lang}.{extension} format. '
|
|
1050
|
+
'{extension} must be one of the following: html, htm, xhtml. '
|
|
1051
|
+
'Review formatting and update as appropriate. '
|
|
1052
|
+
'Invalid filenames: %(invalidBasenames)s'))
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
@validation(
|
|
1056
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1057
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1058
|
+
)
|
|
1059
|
+
def rule_nl_kvk_4_2_0_1(
|
|
1060
|
+
pluginData: PluginValidationDataExtension,
|
|
1061
|
+
val: ValidateXbrl,
|
|
1062
|
+
*args: Any,
|
|
1063
|
+
**kwargs: Any,
|
|
1064
|
+
) -> Iterable[Validation]:
|
|
926
1065
|
"""
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1066
|
+
NL-KVK.4.2.0.1: Tuples MUST NOT be defined in extension taxonomy.
|
|
1067
|
+
"""
|
|
1068
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1069
|
+
tupleConcepts = [
|
|
1070
|
+
concept for concept in extensionData.extensionConcepts if concept.isTuple
|
|
1071
|
+
]
|
|
1072
|
+
if len(tupleConcepts) > 0:
|
|
1073
|
+
yield Validation.error(
|
|
1074
|
+
codes='NL.NL-KVK.4.2.0.1.tupleElementUsed',
|
|
1075
|
+
modelObject=tupleConcepts,
|
|
1076
|
+
msg=_('The extension taxonomy must not define tuple concepts.'))
|
|
1077
|
+
|
|
1078
|
+
|
|
1079
|
+
@validation(
|
|
1080
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1081
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1082
|
+
)
|
|
1083
|
+
def rule_nl_kvk_4_2_0_2(
|
|
1084
|
+
pluginData: PluginValidationDataExtension,
|
|
1085
|
+
val: ValidateXbrl,
|
|
1086
|
+
*args: Any,
|
|
1087
|
+
**kwargs: Any,
|
|
1088
|
+
) -> Iterable[Validation]:
|
|
1089
|
+
"""
|
|
1090
|
+
NL-KVK.4.2.0.2: Items with xbrli:fractionItemType data type MUST NOT be defined in extension taxonomy
|
|
1091
|
+
"""
|
|
1092
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1093
|
+
fractionConcepts = [
|
|
1094
|
+
concept for concept in extensionData.extensionConcepts if concept.isFraction
|
|
1095
|
+
]
|
|
1096
|
+
if len(fractionConcepts) > 0:
|
|
1097
|
+
yield Validation.error(
|
|
1098
|
+
codes='NL.NL-KVK.4.2.0.2.fractionElementUsed',
|
|
1099
|
+
modelObject=fractionConcepts,
|
|
1100
|
+
msg=_('The extension taxonomy must not define fraction concepts.'))
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
@validation(
|
|
1104
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1105
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1106
|
+
)
|
|
1107
|
+
def rule_nl_kvk_4_2_1_1(
|
|
1108
|
+
pluginData: PluginValidationDataExtension,
|
|
1109
|
+
val: ValidateXbrl,
|
|
1110
|
+
*args: Any,
|
|
1111
|
+
**kwargs: Any,
|
|
1112
|
+
) -> Iterable[Validation]:
|
|
1113
|
+
"""
|
|
1114
|
+
NL-KVK.4.2.1.1: Extension taxonomy MUST set xbrli:scenario as context element on definition arcs with
|
|
1115
|
+
http://xbrl.org/int/dim/arcrole/all and http://xbrl.org/int/dim/arcrole/notAll arcroles.
|
|
1116
|
+
"""
|
|
1117
|
+
errors = []
|
|
1118
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1119
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1120
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.all, XbrlConst.notAll}):
|
|
1121
|
+
if arc.get(XbrlConst.qnXbrldtContextElement.clarkNotation) != "scenario":
|
|
1122
|
+
errors.append(arc)
|
|
1123
|
+
if len(errors) > 0:
|
|
1124
|
+
yield Validation.error(
|
|
1125
|
+
codes='NL.NL-KVK.4.2.1.1.scenarioNotUsedInExtensionTaxonomy',
|
|
1126
|
+
modelObject=errors,
|
|
1127
|
+
msg=_('The definition linkbase is missing xbrli:scenario in extension taxonomy. '
|
|
1128
|
+
'Review definition linkbase and update as appropriate.'),
|
|
1129
|
+
)
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
@validation(
|
|
1133
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1134
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1135
|
+
)
|
|
1136
|
+
def rule_nl_kvk_4_2_2_2(
|
|
1137
|
+
pluginData: PluginValidationDataExtension,
|
|
1138
|
+
val: ValidateXbrl,
|
|
1139
|
+
*args: Any,
|
|
1140
|
+
**kwargs: Any,
|
|
1141
|
+
) -> Iterable[Validation]:
|
|
1142
|
+
"""
|
|
1143
|
+
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.
|
|
1144
|
+
"""
|
|
1145
|
+
domainMembersWrongType = []
|
|
1146
|
+
domainMembers = pluginData.getDomainMembers(val.modelXbrl)
|
|
1147
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1148
|
+
for concept in extensionData.extensionConcepts:
|
|
1149
|
+
if concept.isDomainMember and concept in domainMembers and concept.typeQname not in QN_DOMAIN_ITEM_TYPES:
|
|
1150
|
+
domainMembersWrongType.append(concept)
|
|
1151
|
+
if len(domainMembersWrongType) > 0:
|
|
1152
|
+
yield Validation.error(
|
|
1153
|
+
codes='NL.NL-KVK.4.2.2.2.domainMemberWrongDataType',
|
|
1154
|
+
modelObject=domainMembersWrongType,
|
|
1155
|
+
msg=_('Domain members must have domainItemType data type as defined in "https://www.xbrl.org/dtr/type/2022-03-31/types.xsd".'
|
|
1156
|
+
'Update to follow appropriate Data Type Registry. '))
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
@validation(
|
|
1160
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1161
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1162
|
+
)
|
|
1163
|
+
def rule_nl_kvk_4_2_3_1(
|
|
1164
|
+
pluginData: PluginValidationDataExtension,
|
|
1165
|
+
val: ValidateXbrl,
|
|
1166
|
+
*args: Any,
|
|
1167
|
+
**kwargs: Any,
|
|
1168
|
+
) -> Iterable[Validation]:
|
|
1169
|
+
"""
|
|
1170
|
+
NL-KVK.4.2.3.1: Extension taxonomy MUST NOT define typed dimensions.
|
|
1171
|
+
"""
|
|
1172
|
+
typedDims = []
|
|
1173
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1174
|
+
for concept in extensionData.extensionConcepts:
|
|
1175
|
+
if concept.isTypedDimension:
|
|
1176
|
+
typedDims.append(concept)
|
|
1177
|
+
if len(typedDims) > 0:
|
|
1178
|
+
yield Validation.error(
|
|
1179
|
+
codes='NL.NL-KVK.4.3.2.1.typedDimensionDefinitionInExtensionTaxonomy',
|
|
1180
|
+
modelObject=typedDims,
|
|
1181
|
+
msg=_('Typed dimensions are not allowed in the extension taxonomy. Update to remove the typed dimension.'))
|
|
1182
|
+
|
|
1183
|
+
|
|
1184
|
+
@validation(
|
|
1185
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1186
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1187
|
+
)
|
|
1188
|
+
def rule_nl_kvk_4_4_1_1(
|
|
1189
|
+
pluginData: PluginValidationDataExtension,
|
|
1190
|
+
val: ValidateXbrl,
|
|
1191
|
+
*args: Any,
|
|
1192
|
+
**kwargs: Any,
|
|
1193
|
+
) -> Iterable[Validation]:
|
|
1194
|
+
"""
|
|
1195
|
+
NL-KVK.4.4.1.1: Arithmetical relationships defined in the calculation linkbase of an extension taxonomy
|
|
1196
|
+
MUST use the https://xbrl.org/2023/arcrole/summation-item arcrole as defined in Calculation 1.1 specification.
|
|
1197
|
+
"""
|
|
1198
|
+
errors = []
|
|
1199
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1200
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1201
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.CALCULATION, excludeArcroles={XbrlConst.summationItem11}):
|
|
1202
|
+
errors.append(arc)
|
|
1203
|
+
if len(errors) > 0:
|
|
1204
|
+
yield Validation.error(
|
|
1205
|
+
codes='NL.NL-KVK.4.4.1.1.incorrectSummationItemArcroleUsed',
|
|
1206
|
+
modelObject=errors,
|
|
1207
|
+
msg=_('Calculation relationships should follow the requirements of the Calculation 1.1 specification. '
|
|
1208
|
+
'Update to ensure use of summation-item arcrole in the calculation linkbase.'),
|
|
1209
|
+
)
|
|
1210
|
+
|
|
1211
|
+
|
|
1212
|
+
@validation(
|
|
1213
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1214
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1215
|
+
)
|
|
1216
|
+
def rule_nl_kvk_4_4_2_1(
|
|
1217
|
+
pluginData: PluginValidationDataExtension,
|
|
1218
|
+
val: ValidateXbrl,
|
|
1219
|
+
*args: Any,
|
|
1220
|
+
**kwargs: Any,
|
|
1221
|
+
) -> Iterable[Validation]:
|
|
1222
|
+
"""
|
|
1223
|
+
NL-KVK.4.4.2.1: Extension taxonomies MUST NOT define definition arcs
|
|
1224
|
+
with http://xbrl.org/int/dim/arcrole/notAll arcrole.
|
|
1225
|
+
"""
|
|
1226
|
+
errors = []
|
|
1227
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1228
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1229
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.notAll}):
|
|
1230
|
+
errors.append(arc)
|
|
1231
|
+
if len(errors) > 0:
|
|
1232
|
+
yield Validation.error(
|
|
1233
|
+
codes='NL.NL-KVK.4.4.2.1.notAllArcroleUsedInDefinitionLinkbase',
|
|
1234
|
+
modelObject=errors,
|
|
1235
|
+
msg=_('Incorrect hypercube settings are found. Ensure that positive hypercubes are in use.'),
|
|
1236
|
+
)
|
|
1237
|
+
|
|
1238
|
+
|
|
1239
|
+
@validation(
|
|
1240
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1241
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1242
|
+
)
|
|
1243
|
+
def rule_nl_kvk_4_4_2_2(
|
|
1244
|
+
pluginData: PluginValidationDataExtension,
|
|
1245
|
+
val: ValidateXbrl,
|
|
1246
|
+
*args: Any,
|
|
1247
|
+
**kwargs: Any,
|
|
1248
|
+
) -> Iterable[Validation]:
|
|
1249
|
+
"""
|
|
1250
|
+
NL-KVK.4.4.2.2: Hypercubes appearing as target of definition arc with
|
|
1251
|
+
http://xbrl.org/int/dim/arcrole/all arcrole MUST have xbrldt:closed attribute set to “true”.
|
|
1252
|
+
"""
|
|
1253
|
+
errors = []
|
|
1254
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1255
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1256
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.all}):
|
|
1257
|
+
if arc.get(XbrlConst.qnXbrldtClosed.clarkNotation, "false") != "true":
|
|
1258
|
+
errors.append(arc)
|
|
1259
|
+
if len(errors) > 0:
|
|
1260
|
+
yield Validation.error(
|
|
1261
|
+
codes='NL.NL-KVK.4.4.2.2.openPositiveHypercubeInDefinitionLinkbase',
|
|
1262
|
+
modelObject=errors,
|
|
1263
|
+
msg=_('Incorrect hypercube settings are found. Ensure that positive hypercubes are closed.'),
|
|
1264
|
+
)
|
|
1265
|
+
|
|
1266
|
+
|
|
1267
|
+
@validation(
|
|
1268
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1269
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1270
|
+
)
|
|
1271
|
+
def rule_nl_kvk_4_4_2_3(
|
|
1272
|
+
pluginData: PluginValidationDataExtension,
|
|
1273
|
+
val: ValidateXbrl,
|
|
1274
|
+
*args: Any,
|
|
1275
|
+
**kwargs: Any,
|
|
1276
|
+
) -> Iterable[Validation]:
|
|
1277
|
+
"""
|
|
1278
|
+
NL-KVK.4.4.2.3: Hypercubes appearing as target of definition arc with
|
|
1279
|
+
http://xbrl.org/int/dim/arcrole/notAll arcrole MUST have xbrldt:closed attribute set to “false”.
|
|
1280
|
+
"""
|
|
1281
|
+
errors = []
|
|
1282
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1283
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1284
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.notAll}):
|
|
1285
|
+
if arc.get(XbrlConst.qnXbrldtClosed.clarkNotation, "true") != "false":
|
|
1286
|
+
errors.append(arc)
|
|
1287
|
+
if len(errors) > 0:
|
|
1288
|
+
yield Validation.error(
|
|
1289
|
+
codes='NL.NL-KVK.4.4.2.3.closedNegativeHypercubeInDefinitionLinkbase',
|
|
1290
|
+
modelObject=errors,
|
|
1291
|
+
msg=_('Incorrect hypercube settings are found. Ensure that negative hypercubes are not closed.'),
|
|
1292
|
+
)
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
@validation(
|
|
1296
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1297
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1298
|
+
)
|
|
1299
|
+
def rule_nl_kvk_4_4_3_1(
|
|
1300
|
+
pluginData: PluginValidationDataExtension,
|
|
1301
|
+
val: ValidateXbrl,
|
|
1302
|
+
*args: Any,
|
|
1303
|
+
**kwargs: Any,
|
|
1304
|
+
) -> Iterable[Validation]:
|
|
1305
|
+
"""
|
|
1306
|
+
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
|
|
1307
|
+
"""
|
|
1308
|
+
for modelLink in cast(list[ModelLink], val.modelXbrl.baseSets[XbrlConst.dimensionDefault, None, None, None]):
|
|
1309
|
+
if not pluginData.isExtensionUri(modelLink.modelDocument.uri, val.modelXbrl):
|
|
1310
|
+
continue
|
|
1311
|
+
for linkChild in modelLink:
|
|
1312
|
+
if (
|
|
1313
|
+
isinstance(linkChild,(ModelObject,PrototypeObject))
|
|
1314
|
+
and linkChild.get(XbrlConst.qnXlinkType.clarkNotation) == "arc"
|
|
1315
|
+
and linkChild.get(XbrlConst.qnXlinkArcRole.clarkNotation) == XbrlConst.dimensionDefault
|
|
1316
|
+
):
|
|
1317
|
+
fromLabel = linkChild.get(XbrlConst.qnXlinkFrom.clarkNotation)
|
|
1318
|
+
for fromResource in modelLink.labeledResources[fromLabel]:
|
|
1319
|
+
if not pluginData.isExtensionUri(fromResource.modelDocument.uri, val.modelXbrl):
|
|
1320
|
+
yield Validation.error(
|
|
1321
|
+
codes='NL.NL-KVK.4.4.3.1.extensionTaxonomyOverridesDefaultMembers',
|
|
1322
|
+
msg=_('A default member does not match the default member settings of the taxonomy. '
|
|
1323
|
+
'Update the default member to taxonomy defaults.'
|
|
1324
|
+
),
|
|
1325
|
+
modelObject=linkChild
|
|
1326
|
+
)
|
|
1327
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1328
|
+
for modelDocument, extensionDocumentData in extensionData.extensionDocuments.items():
|
|
1329
|
+
for arc in extensionDocumentData.iterArcsByType(LinkbaseType.DEFINITION, includeArcroles={XbrlConst.dimensionDefault}):
|
|
1330
|
+
if arc.get("use") == "prohibited":
|
|
1331
|
+
yield Validation.error(
|
|
1332
|
+
codes='NL.NL-KVK.4.4.3.1.extensionTaxonomyOverridesDefaultMembers',
|
|
1333
|
+
msg=_('A default member is forbidden in the extension taxonomy. '
|
|
1334
|
+
'Update the default member to taxonomy defaults.'
|
|
1335
|
+
),
|
|
1336
|
+
modelObject=arc
|
|
1337
|
+
)
|
|
1338
|
+
|
|
1339
|
+
|
|
1340
|
+
@validation(
|
|
1341
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1342
|
+
disclosureSystems=NL_INLINE_GAAP_IFRS_DISCLOSURE_SYSTEMS,
|
|
1343
|
+
)
|
|
1344
|
+
def rule_nl_kvk_4_4_3_2(
|
|
1345
|
+
pluginData: PluginValidationDataExtension,
|
|
1346
|
+
val: ValidateXbrl,
|
|
1347
|
+
*args: Any,
|
|
1348
|
+
**kwargs: Any,
|
|
1349
|
+
) -> Iterable[Validation]:
|
|
1350
|
+
"""
|
|
1351
|
+
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.
|
|
1352
|
+
"""
|
|
1353
|
+
dimensionDefaults =val.modelXbrl.relationshipSet(XbrlConst.dimensionDefault, DEFAULT_MEMBER_ROLE_URI)
|
|
1354
|
+
extensionData = pluginData.getExtensionData(val.modelXbrl)
|
|
1355
|
+
for modelConcept in extensionData.extensionConcepts:
|
|
1356
|
+
if modelConcept.isExplicitDimension and not dimensionDefaults.fromModelObject(modelConcept):
|
|
930
1357
|
yield Validation.error(
|
|
931
|
-
codes='NL.NL-KVK.4.
|
|
932
|
-
|
|
933
|
-
|
|
1358
|
+
codes='NL.NL-KVK.4.4.2.3.extensionTaxonomyDimensionNotAssignedDefaultMemberInDedicatedPlaceholder',
|
|
1359
|
+
modelObject=modelConcept,
|
|
1360
|
+
msg=_('Axis is missing a default member or the default member does not match the taxonomy defaults. '
|
|
1361
|
+
'Update to set default member based on taxonomy defaults.'
|
|
1362
|
+
),
|
|
934
1363
|
)
|
|
935
1364
|
|
|
936
1365
|
|
|
937
1366
|
@validation(
|
|
938
1367
|
hook=ValidationHook.XBRL_FINALLY,
|
|
939
|
-
disclosureSystems=
|
|
940
|
-
|
|
941
|
-
|
|
1368
|
+
disclosureSystems=NL_INLINE_GAAP_OTHER_DISCLOSURE_SYSTEMS,
|
|
1369
|
+
)
|
|
1370
|
+
def rule_nl_kvk_5_1_3_1(
|
|
1371
|
+
pluginData: PluginValidationDataExtension,
|
|
1372
|
+
val: ValidateXbrl,
|
|
1373
|
+
*args: Any,
|
|
1374
|
+
**kwargs: Any,
|
|
1375
|
+
) -> Iterable[Validation]:
|
|
1376
|
+
"""
|
|
1377
|
+
NL-KVK.5.1.3.1: Validate that the imported taxonomy matches the KVK-specified entry point.
|
|
1378
|
+
- https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-other-gaap.xsd
|
|
1379
|
+
"""
|
|
1380
|
+
uris = {doc[0].uri for doc in val.modelXbrl.namespaceDocs.values()}
|
|
1381
|
+
matches = uris & EFFECTIVE_KVK_GAAP_OTHER_ENTRYPOINT_FILES
|
|
1382
|
+
if not matches:
|
|
1383
|
+
yield Validation.error(
|
|
1384
|
+
codes='NL.NL-KVK.5.1.3.1.requiredEntryPointOtherGaapNotReferenced',
|
|
1385
|
+
msg=_('The extension taxonomy must import the entry point of the taxonomy files prepared by KVK.'),
|
|
1386
|
+
modelObject=val.modelXbrl.modelDocument
|
|
1387
|
+
)
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
@validation(
|
|
1391
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1392
|
+
disclosureSystems=NL_INLINE_GAAP_OTHER_DISCLOSURE_SYSTEMS,
|
|
1393
|
+
)
|
|
1394
|
+
def rule_nl_kvk_5_1_3_2(
|
|
1395
|
+
pluginData: PluginValidationDataExtension,
|
|
1396
|
+
val: ValidateXbrl,
|
|
1397
|
+
*args: Any,
|
|
1398
|
+
**kwargs: Any,
|
|
1399
|
+
) -> Iterable[Validation]:
|
|
1400
|
+
"""
|
|
1401
|
+
NL-KVK.5.1.3.2: The legal entity’s report MUST import the applicable version of
|
|
1402
|
+
the taxonomy files prepared by KVK.
|
|
1403
|
+
"""
|
|
1404
|
+
reportingPeriod = pluginData.getReportingPeriod(val.modelXbrl)
|
|
1405
|
+
uris = {doc[0].uri for doc in val.modelXbrl.namespaceDocs.values()}
|
|
1406
|
+
matches = uris & TAXONOMY_URLS_BY_YEAR.get(reportingPeriod or '', set())
|
|
1407
|
+
if not reportingPeriod or not matches:
|
|
1408
|
+
yield Validation.error(
|
|
1409
|
+
codes='NL.NL-KVK.5.1.3.2.incorrectVersionEntryPointOtherGaapReferenced',
|
|
1410
|
+
msg=_('The report MUST import the applicable version of the taxonomy files prepared by KVK '
|
|
1411
|
+
'for the reported financial reporting period. Verify the taxonomy version and make sure '
|
|
1412
|
+
'that FinancialReportingPeriod are tagged correctly.'),
|
|
1413
|
+
modelObject=val.modelXbrl.modelDocument
|
|
1414
|
+
)
|
|
1415
|
+
|
|
1416
|
+
|
|
1417
|
+
@validation(
|
|
1418
|
+
hook=ValidationHook.XBRL_FINALLY,
|
|
1419
|
+
disclosureSystems=ALL_NL_INLINE_DISCLOSURE_SYSTEMS,
|
|
942
1420
|
)
|
|
943
1421
|
def rule_nl_kvk_6_1_1_1(
|
|
944
1422
|
pluginData: PluginValidationDataExtension,
|