# frozen_string_literal: true require 'roqua/healthy/a19/name_parser' require 'roqua/healthy/a19/epic_name_parser' require 'roqua/healthy/a19/cdis_name_parser' require 'roqua/healthy/a19/impulse_name_parser' require 'roqua/healthy/a19/address_parser' require 'roqua/healthy/a19/phone_validator' require 'roqua/healthy/a19/phone_parser' require 'active_support/core_ext/hash' module Roqua module Healthy module A19 class Transformer attr_reader :message def initialize(message) raise ::Roqua::Healthy::PatientNotFound unless message['PID'].present? message['PID']['PID.3'] = [message.fetch('PID').fetch('PID.3')].flatten.compact message['PID']['PID.5'] = [message.fetch('PID').fetch('PID.5')].flatten.compact message['PID']['PID.11'] = [message.fetch('PID').fetch('PID.11')].flatten.compact message['PID']['PID.13'] = [message.fetch('PID').fetch('PID.13')].flatten.compact @message = MessageCleaner.new(message).message end # rubocop:disable Metrics/AbcSize, Metrics/MethodLength def to_patient { status: status, source: source, identities: identities, firstname: name.firstname, initials: name.initials, lastname: name.lastname, display_name: name.display_name, nickname: name.nickname, email: email, address_type: address.address_type, street: address.street, city: address.city, zipcode: address.zipcode, country: address.country, birthdate: birthdate, gender: gender, phone_cell: phone_cell, medoq_data: medoq_data, deceased: deceased } end # rubocop:enable Metrics/AbcSize, Metrics/MethodLength def status 'SUCCESS' end def source message.fetch('MSH').fetch('MSH.4').fetch('MSH.4.1') end def identities @identities ||= message.fetch('PID').fetch('PID.3').map do |identity| next if identity.fetch('PID.3.1').blank? authority = identity.fetch('PID.3.5') # medoq sends all its (possibly identifying) metadata in 1 json encoded identity # non medoq hl7 clients could fake being medoq, so do not add any trusted behavior # to medoq identities beyond what a regular hl7 field would enable if authority == 'MEDOQ' parsed_medoq_data = JSON.parse(identity.fetch('PID.3.1')).with_indifferent_access {ident: parsed_medoq_data[:epd_id], research_number: parsed_medoq_data[:research_number], metadata: parsed_medoq_data[:metadata], authority: authority} else {ident: identity.fetch('PID.3.1'), authority: authority} end end.compact end def medoq_data identities.find do |identity| identity[:authority] == 'MEDOQ' end || {} end def birthdate birthdate_details = message.fetch('PID').fetch('PID.7') birthdate_details&.fetch('PID.7.1') end def email email_record = message.fetch('PID').fetch('PID.13').find do |record| record.fetch('PID.13.2', :unknown_type_of_phone_record) == 'NET' end return nil unless email_record email_address = email_record.fetch('PID.13.1', "") email_address = email_record.fetch('PID.13.4', "") if email_address.blank? email_address end def phone_cell PhoneParser.new(message).to_s end def gender message.dig('PID', 'PID.8', 'PID.8.1') end def deceased case message.dig('PID', 'PID.30', 'PID.30.1') when 'Y' then true when 'N' then false end end private def name case source when "CLOVDMZA", "CLOVDMZP" EpicNameParser.new(message) when "UMCG" # UMCG is actually ggzwnb impersonating old umcg CdisNameParser.new(message) when "IMPULSE" ImpulseNameParser.new(message) else NameParser.new(message) end end def address AddressParser.new(message) end end end end end