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.

@@ -7,26 +7,28 @@ from collections import defaultdict
7
7
  from dataclasses import dataclass
8
8
  from functools import lru_cache
9
9
  from pathlib import Path
10
- from typing import Any, TYPE_CHECKING, cast
10
+ from typing import Any, TYPE_CHECKING, cast, Iterable
11
11
 
12
12
  import regex as re
13
- from lxml.etree import _Comment, _ElementTree, _Entity, _ProcessingInstruction
13
+ from lxml.etree import _Comment, _ElementTree, _Entity, _ProcessingInstruction, _Element
14
14
 
15
+ from arelle import XbrlConst
15
16
  from arelle.FunctionIxt import ixtNamespaces
16
- from arelle import ModelDocument as ModelDocumentFile
17
- from arelle.ModelDocument import ModelDocument
17
+ from arelle.ModelDocument import ModelDocument, Type as ModelDocumentType
18
+ from arelle.ModelDtsObject import ModelConcept
18
19
  from arelle.ModelInstanceObject import ModelContext, ModelFact, ModelInlineFootnote, ModelUnit, ModelInlineFact
19
20
  from arelle.ModelObject import ModelObject
20
- from arelle.ModelValue import QName
21
+ from arelle.ModelValue import QName, qname
21
22
  from arelle.ModelXbrl import ModelXbrl
22
23
  from arelle.typing import assert_type
23
24
  from arelle.utils.PluginData import PluginData
24
25
  from arelle.utils.validate.ValidationUtil import etreeIterWithDepth
25
- from arelle.ValidateXbrl import ValidateXbrl
26
26
  from arelle.XbrlConst import ixbrl11, xhtmlBaseIdentifier, xmlBaseIdentifier
27
27
  from arelle.XmlValidate import lexicalPatterns
28
28
  from arelle.XmlValidateConst import VALID
29
+ from .LinkbaseType import LinkbaseType
29
30
 
31
+ DEFAULT_MEMBER_ROLE_URI = 'https://www.nltaxonomie.nl/kvk/role/axis-defaults'
30
32
  XBRLI_IDENTIFIER_PATTERN = re.compile(r"^(?!00)\d{8}$")
31
33
  XBRLI_IDENTIFIER_SCHEMA = 'http://www.kvk.nl/kvk-id'
32
34
  MAX_REPORT_PACKAGE_SIZE_MBS = 100
@@ -57,11 +59,51 @@ ALLOWABLE_LANGUAGES = frozenset((
57
59
  'fr'
58
60
  ))
59
61
 
60
- EFFECTIVE_TAXONOMY_URLS = frozenset((
62
+ EFFECTIVE_KVK_GAAP_IFRS_ENTRYPOINT_FILES = frozenset((
61
63
  'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd',
62
64
  'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd',
63
65
  ))
64
66
 
67
+ EFFECTIVE_KVK_GAAP_OTHER_ENTRYPOINT_FILES = frozenset((
68
+ 'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-other-gaap.xsd',
69
+ ))
70
+
71
+ TAXONOMY_URLS_BY_YEAR = {
72
+ '2024': {
73
+ 'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-nlgaap-ext.xsd',
74
+ 'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-ifrs-ext.xsd',
75
+ 'https://www.nltaxonomie.nl/kvk/2024-12-31/kvk-annual-report-other-gaap.xsd',
76
+ }
77
+ }
78
+
79
+ STANDARD_TAXONOMY_URLS = frozenset((
80
+ 'http://www.nltaxonomie.nl/ifrs/20',
81
+ 'https://www.nltaxonomie.nl/ifrs/20',
82
+ 'http://www.nltaxonomie.nl/',
83
+ 'https://www.nltaxonomie.nl/',
84
+ 'http://www.xbrl.org/taxonomy/int/lei/',
85
+ 'https://www.xbrl.org/taxonomy/int/lei/',
86
+ 'http://www.xbrl.org/20',
87
+ 'https://www.xbrl.org/20',
88
+ 'http://www.xbrl.org/lrr/',
89
+ 'https://www.xbrl.org/lrr/',
90
+ 'http://xbrl.org/20',
91
+ 'https://xbrl.org/20',
92
+ 'http://xbrl.ifrs.org/',
93
+ 'https://xbrl.ifrs.org/',
94
+ 'http://www.xbrl.org/dtr/',
95
+ 'https://www.xbrl.org/dtr/',
96
+ 'http://xbrl.org/2020/extensible-enumerations-2.0',
97
+ 'https://xbrl.org/2020/extensible-enumerations-2.0',
98
+ 'http://www.w3.org/1999/xlink',
99
+ 'https://www.w3.org/1999/xlink'
100
+ ))
101
+
102
+ QN_DOMAIN_ITEM_TYPES = frozenset((
103
+ qname("{http://www.xbrl.org/dtr/type/2022-03-31}nonnum:domainItemType"),
104
+ ))
105
+
106
+
65
107
  @dataclass(frozen=True)
66
108
  class ContextData:
67
109
  contextsWithImproperContent: list[ModelContext | None]
@@ -69,6 +111,48 @@ class ContextData:
69
111
  contextsWithPeriodTimeZone: list[ModelContext | None]
70
112
  contextsWithSegments: list[ModelContext | None]
71
113
 
114
+
115
+ @dataclass(frozen=True)
116
+ class ExtensionData:
117
+ extensionConcepts: list[ModelConcept]
118
+ extensionDocuments: dict[ModelDocument, ExtensionDocumentData]
119
+ extensionImportedUrls: frozenset[str]
120
+
121
+
122
+ @dataclass(frozen=True)
123
+ class ExtensionDocumentData:
124
+ basename: str
125
+ hrefXlinkRole: str | None
126
+ linkbases: list[LinkbaseData]
127
+
128
+ def iterArcsByType(
129
+ self,
130
+ linkbaseType: LinkbaseType,
131
+ includeArcroles: set[str] | None = None,
132
+ excludeArcroles: set[str] | None = None,
133
+ ) -> Iterable[_Element]:
134
+ """
135
+ Returns a list of LinkbaseData objects for the specified LinkbaseType.
136
+ """
137
+ for linkbase in self.iterLinkbasesByType(linkbaseType):
138
+ for arc in linkbase.arcs:
139
+ if includeArcroles is not None:
140
+ if arc.get(XbrlConst.qnXlinkArcRole.clarkNotation) not in includeArcroles:
141
+ continue
142
+ if excludeArcroles is not None:
143
+ if arc.get(XbrlConst.qnXlinkArcRole.clarkNotation) in excludeArcroles:
144
+ continue
145
+ yield arc
146
+
147
+ def iterLinkbasesByType(self, linkbaseType: LinkbaseType) -> Iterable[LinkbaseData]:
148
+ """
149
+ Returns a list of LinkbaseData objects for the specified LinkbaseType.
150
+ """
151
+ for linkbase in self.linkbases:
152
+ if linkbase.linkbaseType == linkbaseType:
153
+ yield linkbase
154
+
155
+
72
156
  @dataclass(frozen=True)
73
157
  class HiddenElementsData:
74
158
  cssHiddenFacts: set[ModelInlineFact]
@@ -76,6 +160,7 @@ class HiddenElementsData:
76
160
  hiddenFactsOutsideHiddenSection: set[ModelInlineFact]
77
161
  requiredToDisplayFacts: set[ModelInlineFact]
78
162
 
163
+
79
164
  @dataclass(frozen=True)
80
165
  class InlineHTMLData:
81
166
  baseElements: set[Any]
@@ -85,6 +170,19 @@ class InlineHTMLData:
85
170
  factLangFootnotes: dict[ModelInlineFootnote, set[str]]
86
171
  fractionElements: set[Any]
87
172
 
173
+
174
+ @dataclass(frozen=True)
175
+ class LinkbaseData:
176
+ arcs: list[_Element]
177
+ basename: str
178
+ element: _Element
179
+ linkbaseType: LinkbaseType | None
180
+
181
+ @property
182
+ def hasArcs(self) -> bool:
183
+ return len(self.arcs) > 0
184
+
185
+
88
186
  @dataclass
89
187
  class PluginValidationDataExtension(PluginData):
90
188
  chamberOfCommerceRegistrationNumberQn: QName
@@ -93,6 +191,7 @@ class PluginValidationDataExtension(PluginData):
93
191
  documentResubmissionUnsurmountableInaccuraciesQn: QName
94
192
  entrypointRoot: str
95
193
  entrypoints: set[str]
194
+ financialReportingPeriodQn: QName
96
195
  financialReportingPeriodCurrentStartDateQn: QName
97
196
  financialReportingPeriodCurrentEndDateQn: QName
98
197
  financialReportingPeriodPreviousStartDateQn: QName
@@ -105,6 +204,12 @@ class PluginValidationDataExtension(PluginData):
105
204
  def __hash__(self) -> int:
106
205
  return id(self)
107
206
 
207
+ def addDomMbrs(self, modelXbrl: ModelXbrl, sourceDomMbr: ModelConcept, ELR: str, membersSet: set[ModelConcept]) -> None:
208
+ if isinstance(sourceDomMbr, ModelConcept) and sourceDomMbr not in membersSet:
209
+ membersSet.add(sourceDomMbr)
210
+ for domMbrRel in modelXbrl.relationshipSet(XbrlConst.domainMember, ELR).fromModelObject(sourceDomMbr):
211
+ self.addDomMbrs(modelXbrl, domMbrRel.toModelObject, domMbrRel.consecutiveLinkrole, membersSet)
212
+
108
213
  @lru_cache(1)
109
214
  def contextsByDocument(self, modelXbrl: ModelXbrl) -> dict[str, list[ModelContext]]:
110
215
  contextsByDocument = defaultdict(list)
@@ -144,21 +249,6 @@ class PluginValidationDataExtension(PluginData):
144
249
  contextsWithSegments=contextsWithSegments,
145
250
  )
146
251
 
147
- def checkFilingDTS(
148
- self,
149
- val: ValidateXbrl,
150
- modelDocument: ModelDocument,
151
- visited: list[ModelDocument]
152
- ) -> None:
153
- visited.append(modelDocument)
154
- for referencedDocument, modelDocumentReference in modelDocument.referencesDocument.items():
155
- if referencedDocument not in visited and referencedDocument.inDTS:
156
- self.checkFilingDTS(val, referencedDocument, visited)
157
- if modelDocument.type == ModelDocumentFile.Type.SCHEMA:
158
- for doc, docRef in modelDocument.referencesDocument.items():
159
- if "import" in docRef.referenceTypes:
160
- val.extensionImportedUrls.add(doc.uri)
161
-
162
252
  @lru_cache(1)
163
253
  def checkHiddenElements(self, modelXbrl: ModelXbrl) -> HiddenElementsData:
164
254
  cssHiddenFacts = set()
@@ -169,7 +259,7 @@ class PluginValidationDataExtension(PluginData):
169
259
  presentedHiddenEltIds = defaultdict(list)
170
260
  requiredToDisplayFacts = set()
171
261
  for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
172
- ixNStag = getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11)
262
+ ixNStag = str(getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11))
173
263
  for ixHiddenElt in ixdsHtmlRootElt.iterdescendants(tag=ixNStag + "hidden"):
174
264
  for tag in (ixNStag + "nonNumeric", ixNStag+"nonFraction"):
175
265
  for ixElt in ixHiddenElt.iterdescendants(tag=tag):
@@ -218,7 +308,7 @@ class PluginValidationDataExtension(PluginData):
218
308
  tupleElements = set()
219
309
  orphanedFootnotes = set()
220
310
  for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
221
- ixNStag = getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11)
311
+ ixNStag = str(getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11))
222
312
  ixTupleTag = ixNStag + "tuple"
223
313
  ixFractionTag = ixNStag + "fraction"
224
314
  for elts in modelXbrl.ixdsEltById.values(): # type: ignore[attr-defined]
@@ -291,6 +381,49 @@ class PluginValidationDataExtension(PluginData):
291
381
  def getContextsWithSegments(self, modelXbrl: ModelXbrl) -> list[ModelContext | None]:
292
382
  return self.checkContexts(modelXbrl).contextsWithSegments
293
383
 
384
+ @lru_cache(1)
385
+ def getDocumentsInDts(self, modelXbrl: ModelXbrl) -> dict[ModelDocument, str | None]:
386
+ modelDocuments: dict[ModelDocument, str | None] = {}
387
+ if modelXbrl.modelDocument is None:
388
+ return modelDocuments
389
+
390
+ def _getDocumentsInDts(modelDocument: ModelDocument) -> None:
391
+ for referencedDocument, modelDocumentReference in modelDocument.referencesDocument.items():
392
+ if referencedDocument in modelDocuments:
393
+ continue
394
+ if referencedDocument.inDTS:
395
+ modelDocuments[referencedDocument] = modelDocumentReference.referringXlinkRole
396
+ _getDocumentsInDts(referencedDocument)
397
+
398
+ modelDocuments[modelXbrl.modelDocument] = None
399
+ _getDocumentsInDts(modelXbrl.modelDocument)
400
+ return modelDocuments
401
+
402
+ def getDomainMembers(self, modelXbrl: ModelXbrl) -> set[ModelConcept]:
403
+ domainMembers = set() # concepts which are dimension domain members
404
+ hcPrimaryItems: set[ModelConcept] = set()
405
+ hcMembers: set[Any] = set()
406
+ for hasHypercubeArcrole in (XbrlConst.all, XbrlConst.notAll):
407
+ hasHypercubeRelationships = modelXbrl.relationshipSet(hasHypercubeArcrole).fromModelObjects()
408
+ for hasHcRels in hasHypercubeRelationships.values():
409
+ for hasHcRel in hasHcRels:
410
+ sourceConcept: ModelConcept = hasHcRel.fromModelObject
411
+ hcPrimaryItems.add(sourceConcept)
412
+ # find associated primary items to source concept
413
+ for domMbrRel in modelXbrl.relationshipSet(XbrlConst.domainMember).fromModelObject(sourceConcept):
414
+ if domMbrRel.consecutiveLinkrole == hasHcRel.linkrole: # only those related to this hc
415
+ self.addDomMbrs(modelXbrl, domMbrRel.toModelObject, domMbrRel.consecutiveLinkrole, hcPrimaryItems)
416
+ hc = hasHcRel.toModelObject
417
+ for hcDimRel in modelXbrl.relationshipSet(XbrlConst.hypercubeDimension, hasHcRel.consecutiveLinkrole).fromModelObject(hc):
418
+ dim = hcDimRel.toModelObject
419
+ if isinstance(dim, ModelConcept):
420
+ for dimDomRel in modelXbrl.relationshipSet(XbrlConst.dimensionDomain, hcDimRel.consecutiveLinkrole).fromModelObject(dim):
421
+ dom = dimDomRel.toModelObject
422
+ if isinstance(dom, ModelConcept):
423
+ self.addDomMbrs(modelXbrl, dom, dimDomRel.consecutiveLinkrole, hcMembers)
424
+ domainMembers.update(hcMembers)
425
+ return domainMembers
426
+
294
427
  def getEligibleForTransformHiddenFacts(self, modelXbrl: ModelXbrl) -> set[ModelInlineFact]:
295
428
  return self.checkHiddenElements(modelXbrl).eligibleForTransformHiddenFacts
296
429
 
@@ -321,8 +454,19 @@ class PluginValidationDataExtension(PluginData):
321
454
  )
322
455
 
323
456
  @lru_cache(1)
324
- def getFilenameParts(self, filename: str) -> dict[str, Any] | None:
325
- match = self.getFilenameFormatPattern().match(filename)
457
+ def getExtensionFilenameFormatPattern(self) -> re.Pattern[str]:
458
+ return re.compile(
459
+ r"^(?<base>[^-]*)"
460
+ r"-(?<year>\d{4})-(?<month>0[1-9]|1[012])-(?<day>0?[1-9]|[12][0-9]|3[01])"
461
+ r"(?<suffix>[_pre|_cal|_lab|_def]*)"
462
+ r"(?<lang>-*[^-]*)"
463
+ r"\.(?<extension>xsd|xml)$",
464
+ flags=re.ASCII
465
+ )
466
+
467
+ @lru_cache(1)
468
+ def getFilenameParts(self, filename: str, filenamePattern: re.Pattern[str]) -> dict[str, Any] | None:
469
+ match = filenamePattern.match(filename)
326
470
  if match:
327
471
  return match.groupdict()
328
472
  return None
@@ -331,6 +475,56 @@ class PluginValidationDataExtension(PluginData):
331
475
  def getIxdsDocBasenames(self, modelXbrl: ModelXbrl) -> set[str]:
332
476
  return set(Path(url).name for url in getattr(modelXbrl, "ixdsDocUrls", []))
333
477
 
478
+ def getExtensionConcepts(self, modelXbrl: ModelXbrl) -> list[ModelConcept]:
479
+ """
480
+ Returns a list of extension concepts in the DTS.
481
+ """
482
+ extensionConcepts = []
483
+ for concepts in modelXbrl.nameConcepts.values():
484
+ for concept in concepts:
485
+ if self.isExtensionUri(concept.qname.namespaceURI, modelXbrl):
486
+ extensionConcepts.append(concept)
487
+ return extensionConcepts
488
+
489
+ @lru_cache(1)
490
+ def getExtensionData(self, modelXbrl: ModelXbrl) -> ExtensionData:
491
+ extensionDocuments = {}
492
+ extensionImportedUrls = set()
493
+ documentsInDts = self.getDocumentsInDts(modelXbrl)
494
+ for modelDocument, hrefXlinkRole in documentsInDts.items():
495
+ if not self.isExtensionUri(modelDocument.uri, modelDocument.modelXbrl):
496
+ # Skip non-extension documents
497
+ continue
498
+ if modelDocument.type in (ModelDocumentType.LINKBASE, ModelDocumentType.SCHEMA):
499
+ extensionDocuments[modelDocument] = ExtensionDocumentData(
500
+ basename=modelDocument.basename,
501
+ hrefXlinkRole=hrefXlinkRole,
502
+ linkbases=self.getLinkbaseData(modelDocument),
503
+ )
504
+ if modelDocument.type == ModelDocumentType.SCHEMA:
505
+ for doc, docRef in modelDocument.referencesDocument.items():
506
+ if "import" in docRef.referenceTypes:
507
+ extensionImportedUrls.add(doc.uri)
508
+ return ExtensionData(
509
+ extensionConcepts=self.getExtensionConcepts(modelXbrl),
510
+ extensionDocuments=extensionDocuments,
511
+ extensionImportedUrls=frozenset(sorted(extensionImportedUrls)),
512
+ )
513
+
514
+ def getLinkbaseData(self, modelDocument: ModelDocument) -> list[LinkbaseData]:
515
+ linkbases = []
516
+ for linkbaseType in LinkbaseType:
517
+ for linkElt in modelDocument.xmlRootElement.iterdescendants(tag=linkbaseType.getLinkQn().clarkNotation):
518
+ arcQn = linkbaseType.getArcQn()
519
+ arcs = list(linkElt.iterdescendants(tag=arcQn.clarkNotation))
520
+ linkbases.append(LinkbaseData(
521
+ arcs=arcs,
522
+ basename=modelDocument.basename,
523
+ element=linkElt,
524
+ linkbaseType=linkbaseType,
525
+ ))
526
+ return linkbases
527
+
334
528
  def getNoMatchLangFootnotes(self, modelXbrl: ModelXbrl) -> set[ModelInlineFootnote]:
335
529
  return self.checkInlineHTMLElements(modelXbrl).noMatchLangFootnotes
336
530
 
@@ -346,6 +540,14 @@ class PluginValidationDataExtension(PluginData):
346
540
  def getTupleElements(self, modelXbrl: ModelXbrl) -> set[tuple[Any]]:
347
541
  return self.checkInlineHTMLElements(modelXbrl).tupleElements
348
542
 
543
+ @lru_cache(1)
544
+ def getReportingPeriod(self, modelXbrl: ModelXbrl) -> str | None:
545
+ reportingPeriodFacts = modelXbrl.factsByQname.get(self.financialReportingPeriodQn, set())
546
+ for fact in reportingPeriodFacts:
547
+ if fact.xValid >= VALID:
548
+ return cast(str, fact.xValue)
549
+ return None
550
+
349
551
  @lru_cache(1)
350
552
  def getReportXmlLang(self, modelXbrl: ModelXbrl) -> str | None:
351
553
  reportXmlLang = None
@@ -365,13 +567,20 @@ class PluginValidationDataExtension(PluginData):
365
567
  def getTargetElements(self, modelXbrl: ModelXbrl) -> list[Any]:
366
568
  targetElements = []
367
569
  for ixdsHtmlRootElt in modelXbrl.ixdsHtmlElements:
368
- ixNStag = getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11)
570
+ ixNStag = str(getattr(ixdsHtmlRootElt.modelDocument, "ixNStag", ixbrl11))
369
571
  ixTags = set(ixNStag + ln for ln in ("nonNumeric", "nonFraction", "references", "relationship"))
370
572
  for elt, depth in etreeIterWithDepth(ixdsHtmlRootElt):
371
573
  if elt.tag in ixTags and elt.get("target"):
372
574
  targetElements.append(elt)
373
575
  return targetElements
374
576
 
577
+ def isExtensionUri(self, uri: str, modelXbrl: ModelXbrl) -> bool:
578
+ if uri.startswith(modelXbrl.uriDir):
579
+ return True
580
+ if not any(uri.startswith(taxonomyUri) for taxonomyUri in STANDARD_TAXONOMY_URLS):
581
+ return True
582
+ return False
583
+
375
584
  @lru_cache(1)
376
585
  def isFilenameValidCharacters(self, filename: str) -> bool:
377
586
  match = self.getFilenameAllowedCharactersPattern().match(filename)
@@ -10,7 +10,9 @@ from arelle.ModelXbrl import ModelXbrl
10
10
  from arelle.ValidateXbrl import ValidateXbrl
11
11
  from arelle.typing import TypeGetText
12
12
  from arelle.utils.validate.ValidationPlugin import ValidationPlugin
13
- from .DisclosureSystems import DISCLOSURE_SYSTEM_NT16, DISCLOSURE_SYSTEM_NT17, DISCLOSURE_SYSTEM_NT18, DISCLOSURE_SYSTEM_NT19, DISCLOSURE_SYSTEM_NL_INLINE_2024
13
+ from .DisclosureSystems import (DISCLOSURE_SYSTEM_NT16, DISCLOSURE_SYSTEM_NT17, DISCLOSURE_SYSTEM_NT18,
14
+ DISCLOSURE_SYSTEM_NT19, DISCLOSURE_SYSTEM_NL_INLINE_2024,
15
+ DISCLOSURE_SYSTEM_NL_INLINE_2024_GAAP_OTHER)
14
16
  from .PluginValidationDataExtension import PluginValidationDataExtension
15
17
 
16
18
  _: TypeGetText
@@ -174,6 +176,13 @@ class ValidationPluginExtension(ValidationPlugin):
174
176
  entrypoints = {entrypointRoot + e for e in [
175
177
  'kvk-annual-report-ifrs-ext.xsd',
176
178
  'kvk-annual-report-nlgaap-ext.xsd',
179
+ ]}
180
+ elif disclosureSystem == DISCLOSURE_SYSTEM_NL_INLINE_2024_GAAP_OTHER:
181
+ jenvNamespace = 'https://www.nltaxonomie.nl/bw2-titel9/2024-12-31/bw2-titel9-cor'
182
+ kvkINamespace = None
183
+ nlTypesNamespace = None
184
+ entrypointRoot = 'http://www.nltaxonomie.nl/kvk/2024-12-31/'
185
+ entrypoints = {entrypointRoot + e for e in [
177
186
  'kvk-annual-report-other-gaap.xsd',
178
187
  ]}
179
188
  else:
@@ -186,6 +195,7 @@ class ValidationPluginExtension(ValidationPlugin):
186
195
  documentResubmissionUnsurmountableInaccuraciesQn=qname(f'{{{kvkINamespace}}}DocumentResubmissionDueToUnsurmountableInaccuracies'),
187
196
  entrypointRoot=entrypointRoot,
188
197
  entrypoints=entrypoints,
198
+ financialReportingPeriodQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriod'),
189
199
  financialReportingPeriodCurrentStartDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodCurrentStartDate'),
190
200
  financialReportingPeriodCurrentEndDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodCurrentEndDate'),
191
201
  financialReportingPeriodPreviousStartDateQn=qname(f'{{{jenvNamespace}}}FinancialReportingPeriodPreviousStartDate'),
@@ -46,9 +46,6 @@ def modelXbrlLoadComplete(*args: Any, **kwargs: Any) -> ModelDocument | LoadingE
46
46
  def validateFinally(*args: Any, **kwargs: Any) -> None:
47
47
  return validationPlugin.validateFinally(*args, **kwargs)
48
48
 
49
- def validateXbrlStart(val: ValidateXbrl, parameters: dict[Any, Any], *args: Any, **kwargs: Any) -> None:
50
- val.extensionImportedUrls = set()
51
-
52
49
  def validateXbrlFinally(*args: Any, **kwargs: Any) -> None:
53
50
  return validationPlugin.validateXbrlFinally(*args, **kwargs)
54
51
 
@@ -64,7 +61,6 @@ __pluginInfo__ = {
64
61
  "DisclosureSystem.Types": disclosureSystemTypes,
65
62
  "DisclosureSystem.ConfigURL": disclosureSystemConfigURL,
66
63
  "ModelXbrl.LoadComplete": modelXbrlLoadComplete,
67
- "Validate.XBRL.Start": validateXbrlStart,
68
64
  "Validate.XBRL.Finally": validateXbrlFinally,
69
65
  "ValidateFormula.Finished": validateFinally,
70
66
  }
@@ -5,7 +5,12 @@
5
5
  <!-- see arelle/config/disclosuresystems.xml for full comments -->
6
6
  <DisclosureSystem
7
7
  names="NL-INLINE-2024|nl-inline-2024|kvk-inline-2024-preview"
8
- description="Checks for NL INLINE 2024"
8
+ description="Checks for NL INLINE 2024. For use with NL GAAP and NL IFRS"
9
+ validationType="NL"
10
+ />
11
+ <DisclosureSystem
12
+ names="NL-INLINE-2024-GAAP-OTHER|nl-inline-2024-gaap-other|kvk-inline-2024-gaap-other-preview"
13
+ description="Checks for NL INLINE 2024. For use with other GAAP."
9
14
  validationType="NL"
10
15
  />
11
16
  <DisclosureSystem