{
  "resourceType": "StructureDefinition",
  "id": "gap-related-person-profile",
  "url": "http://akinox.com/fhir/StructureDefinition/gap-related-person-profile",
  "version": "1.0.0",
  "name": "GapRelatedPerson",
  "title": "GAP Related Person Profile",
  "status": "draft",
  "description": "A FHIR RelatedPerson profile for GAP requests. Communication (preferred language) is optional as not all source systems can provide this information.",
  "fhirVersion": "4.0.1",
  "kind": "resource",
  "abstract": false,
  "type": "RelatedPerson",
  "baseDefinition": "http://hl7.org/fhir/StructureDefinition/RelatedPerson",
  "derivation": "constraint",
  "differential": {
    "element": [
      {
        "id": "RelatedPerson",
        "path": "RelatedPerson",
        "constraint": [
          {
            "key": "gap-related-person-at-least-one-telecom",
            "severity": "error",
            "human": "At least one of phone or email must be present.",
            "expression": "telecom.where(system='phone').exists() or telecom.where(system='email').exists()",
            "source": "http://akinox.com/fhir/StructureDefinition/gap-related-person-profile"
          },
          {
            "key": "gap-related-person-no-sms-telecom",
            "severity": "error",
            "human": "SMS is not a permitted telecom system. Only phone and email are allowed.",
            "expression": "telecom.where(system='sms').empty()",
            "source": "http://akinox.com/fhir/StructureDefinition/gap-related-person-profile"
          },
          {
            "key": "gap-related-person-phone-number-format",
            "severity": "error",
            "human": "Phone number must contain exactly 10 digits.",
            "expression": "telecom.where(system='phone').all(value.matches('^[0-9]{10}$'))",
            "source": "http://akinox.com/fhir/StructureDefinition/gap-related-person-profile"
          },
          {
            "key": "gap-related-person-email-format",
            "severity": "error",
            "human": "Email must follow a strict valid email format without consecutive dots, leading/trailing hyphens in domain parts, or other invalid patterns.",
            "expression": "telecom.where(system='email').all(value.matches('^[a-zA-Z0-9][a-zA-Z0-9._%+-]*[a-zA-Z0-9]@[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\\\\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\\\\.[a-zA-Z]{2,}$') or value.matches('^[a-zA-Z0-9]@[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\\\\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*\\\\.[a-zA-Z]{2,}$'))",
            "source": "http://akinox.com/fhir/StructureDefinition/gap-related-person-profile"
          }
        ]
      },
      {
        "id": "RelatedPerson.relationship",
        "path": "RelatedPerson.relationship",
        "slicing": {
          "discriminator": [
            {
              "type": "value",
              "path": "coding.system"
            }
          ],
          "rules": "open"
        },
        "min": 1,
        "max": "2"
      },
      {
        "id": "RelatedPerson.relationship:roleCode",
        "path": "RelatedPerson.relationship",
        "sliceName": "roleCode",
        "min": 1,
        "max": "2"
      },
      {
        "id": "RelatedPerson.relationship:roleCode.coding.system",
        "path": "RelatedPerson.relationship.coding.system",
        "min": 1,
        "patternUri": "http://terminology.hl7.org/CodeSystem/v3-RoleCode"
      },
      {
        "id": "RelatedPerson.relationship:roleCode.coding.code",
        "path": "RelatedPerson.relationship.coding.code",
        "min": 1,
        "binding": {
          "strength": "required",
          "valueSet": "http://akinox.com/fhir/ValueSet/gap-relatedperson-role-valueset"
        }
      },
      {
        "id": "RelatedPerson.name",
        "path": "RelatedPerson.name",
        "min": 1,
        "max": "1"
      },
      {
        "id": "RelatedPerson.name.family",
        "path": "RelatedPerson.name.family",
        "min": 1
      },
      {
        "id": "RelatedPerson.name.given",
        "path": "RelatedPerson.name.given",
        "min": 1,
        "max": "1"
      },
      {
        "id": "RelatedPerson.telecom",
        "path": "RelatedPerson.telecom",
        "slicing": {
          "discriminator": [
            {
              "type": "value",
              "path": "system"
            }
          ],
          "rules": "open"
        },
        "min": 1
      },
      {
        "id": "RelatedPerson.telecom:phone",
        "path": "RelatedPerson.telecom",
        "sliceName": "phone",
        "min": 0,
        "max": "1"
      },
      {
        "id": "RelatedPerson.telecom:phone.system",
        "path": "RelatedPerson.telecom.system",
        "min": 1,
        "patternCode": "phone"
      },
      {
        "id": "RelatedPerson.telecom:phone.value",
        "path": "RelatedPerson.telecom.value",
        "min": 1
      },
      {
        "id": "RelatedPerson.telecom:phone.use",
        "path": "RelatedPerson.telecom.use",
        "min": 1,
        "binding": {
          "strength": "required",
          "valueSet": "http://akinox.com/fhir/ValueSet/gap-phone-telecom-use-valueset"
        }
      },
      {
        "id": "RelatedPerson.telecom:phone.rank",
        "path": "RelatedPerson.telecom.rank",
        "min": 1
      },
      {
        "id": "RelatedPerson.telecom:email",
        "path": "RelatedPerson.telecom",
        "sliceName": "email",
        "min": 0,
        "max": "1"
      },
      {
        "id": "RelatedPerson.telecom:email.system",
        "path": "RelatedPerson.telecom.system",
        "min": 1,
        "patternCode": "email"
      },
      {
        "id": "RelatedPerson.telecom:email.use",
        "path": "RelatedPerson.telecom.use",
        "min": 1,
        "binding": {
          "strength": "required",
          "valueSet": "http://akinox.com/fhir/ValueSet/gap-email-telecom-use-valueset"
        }
      },
      {
        "id": "RelatedPerson.telecom:email.rank",
        "path": "RelatedPerson.telecom.rank",
        "min": 1
      },
      {
        "id": "RelatedPerson.communication.language",
        "path": "RelatedPerson.communication.language",
        "binding": {
          "strength": "required",
          "valueSet": "http://akinox.com/fhir/ValueSet/gap-language-valueset"
        }
      },
      {
        "id": "RelatedPerson.communication.preferred",
        "path": "RelatedPerson.communication.preferred",
        "min": 1,
        "patternBoolean": true
      }
    ]
  }
}