FirelyTeam / firely-validator-api

Firely's official FHIR validator API for validating HL7 FHIR resources against profiles.
Other
7 stars 2 forks source link

ElementSchemaConverter incorrectly complaining about putting a pattern[x], fixed[x] or binding on an element that isn't the discriminator #322

Closed mmsmits closed 2 months ago

mmsmits commented 3 months ago

We have an ExplanationOfBenefit profile with the following slice defined:

<element id="ExplanationOfBenefit.item.adjudication">
        <path value="ExplanationOfBenefit.item.adjudication" />
        <slicing>
          <discriminator>
            <type value="pattern" />
            <path value="category" />
          </discriminator>
          <rules value="open" />
        </slicing>
        <mustSupport value="true" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication.category">
        <path value="ExplanationOfBenefit.item.adjudication.category" />
        <binding>
          <strength value="required" />
          <valueSet value="http://hl7.org/fhir/us/carin-bb/ValueSet/C4BBAdjudicationCategoryDiscriminator" />
        </binding>
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:adjudicationamounttype">
        <path value="ExplanationOfBenefit.item.adjudication" />
        <sliceName value="adjudicationamounttype" />
        <comment value="Describes the various amount fields used when payers receive and adjudicate a claim. (187)" />
        <mustSupport value="true" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:adjudicationamounttype.id">
        <path value="ExplanationOfBenefit.item.adjudication.id" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:adjudicationamounttype.category">
        <path value="ExplanationOfBenefit.item.adjudication.category" />
        <isSummary value="false" />
        <binding>
          <strength value="required" />
          <valueSet value="http://hl7.org/fhir/us/carin-bb/ValueSet/C4BBAdjudication" />
        </binding>
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:adjudicationamounttype.reason">
        <path value="ExplanationOfBenefit.item.adjudication.reason" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:adjudicationamounttype.amount">
        <path value="ExplanationOfBenefit.item.adjudication.amount" />
        <min value="1" />
        <mustSupport value="true" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:adjudicationamounttype.value">
        <path value="ExplanationOfBenefit.item.adjudication.value" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:denialreason">
        <path value="ExplanationOfBenefit.item.adjudication" />
        <sliceName value="denialreason" />
        <comment value="Reason codes used to interpret the Non-Covered Amount that are provided to the Provider. (92)" />
        <mustSupport value="true" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:denialreason.id">
        <path value="ExplanationOfBenefit.item.adjudication.id" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:denialreason.category">
        <path value="ExplanationOfBenefit.item.adjudication.category" />
        <patternCodeableConcept>
          <coding>
            <system value="http://hl7.org/fhir/us/carin-bb/CodeSystem/C4BBAdjudicationDiscriminator" />
            <code value="denialreason" />
          </coding>
        </patternCodeableConcept>
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:denialreason.reason">
        <path value="ExplanationOfBenefit.item.adjudication.reason" />
        <min value="1" />
        <mustSupport value="true" />
        <isSummary value="false" />
        <binding>
          <strength value="required" />
          <valueSet value="http://hl7.org/fhir/us/carin-bb/ValueSet/X12ClaimAdjustmentReasonCodesCMSRemittanceAdviceRemarkCodes" />
        </binding>
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:denialreason.amount">
        <path value="ExplanationOfBenefit.item.adjudication.amount" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:denialreason.value">
        <path value="ExplanationOfBenefit.item.adjudication.value" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:allowedunits">
        <path value="ExplanationOfBenefit.item.adjudication" />
        <sliceName value="allowedunits" />
        <comment value="The quantity of units, times, days, visits, services, or treatments allowed for the service described by the procedure code, submitted by the provider. (149)" />
        <max value="1" />
        <mustSupport value="true" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:allowedunits.id">
        <path value="ExplanationOfBenefit.item.adjudication.id" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:allowedunits.category">
        <path value="ExplanationOfBenefit.item.adjudication.category" />
        <patternCodeableConcept>
          <coding>
            <system value="http://hl7.org/fhir/us/carin-bb/CodeSystem/C4BBAdjudicationDiscriminator" />
            <code value="allowedunits" />
          </coding>
        </patternCodeableConcept>
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:allowedunits.reason">
        <path value="ExplanationOfBenefit.item.adjudication.reason" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:allowedunits.amount">
        <path value="ExplanationOfBenefit.item.adjudication.amount" />
        <isSummary value="false" />
      </element>
      <element id="ExplanationOfBenefit.item.adjudication:allowedunits.value">
        <path value="ExplanationOfBenefit.item.adjudication.value" />
        <min value="1" />
        <mustSupport value="true" />
        <isSummary value="false" />
      </element>

and it cannot convert this StructureDefinition to ElementSchema. The converter throws: " Failed to convert ElementDefinition at ExplanationOfBenefit.item.adjudication:adjudicationamounttype in profile XXX: The pattern discriminator should have a 'fixed[x]', 'pattern[x]' or binding element set on 'Money.value'

This is strange, because the discriminator is on 'category' and should not look at Money at all.

See https://firelyteam.slack.com/archives/C011XD1TKL0/p1716221527870179 for the full conversation.

ewoutkramer commented 2 months ago

I did see that the base profile is pretty weird, e.g. this structure for EOB.profile looks incomplete:

  <element id="ExplanationOfBenefit.meta.profile">
            <path value="ExplanationOfBenefit.meta.profile" />
            <slicing>
                <discriminator>
                    <type value="pattern" />
                    <path value="$this" />
                </discriminator>
                <description value="Slice based on value" />
                <ordered value="false" />
                <rules value="open" />
            </slicing>
            <comment value="meta.profile is required as a matter of convenience of receiving systems. The meta.profile should be used by the Server to hint/assert/declare that this instance conforms to one (or more) stated profiles (with business versions). meta.profile does not capture any business logic, processing directives, or semantics (for example, inpatient or outpatient). Clients should not assume that the Server will exhaustively indicate all profiles with all versions that this instance conforms to. Clients can (and should) perform their own validation of conformance to the indicated profile(s) and to any other profiles of interest. CPCDS data element (190)" />
            <min value="1" />
        </element>
        <element id="ExplanationOfBenefit.meta.profile:supportedProfile">
            <path value="ExplanationOfBenefit.meta.profile" />
            <sliceName value="supportedProfile" />
            <min value="1" />
            <max value="1" />
        </element>

as it declares a slice on $this, but does not provide an actual pattern[x] in the slice that follows. This means a sub-profile must override the slice otherwise you will get an error just like the OP of this bug found. It could therefore be that this Carin profile has more of these "incomplete" slices, which would cause errors when the author of a sub-profile forgets to override them. But that's just theory.

For now, I cannot reproduce this issue, but will push it to our repo under branch issue-322.

mmsmits commented 2 months ago

@wardweistra FYI