# Dragonfly project backend ### PridokReferral This is how Pridok referral wil likely look like ```json= { "JournalGuid": "240b54a7-8c2a-4c3c-80a4-0bc63e2c9493", "PID": "13116900216", "FormatId": http://ehelse.no/xmlstds/henvisning/2017-11-30 "MessageTimestamp": "2022-11-08T22:51:10.1127156Z", "Firstname": "Line", "Lastname": "Danser", "Email": "line.danser@example.com",//hopefully ariving "PhoneNumber": "+4712345678" } ``` What does it mean for our model: - we gonna have to add SSN to our User model Whenever we receive referral: - we must fetch or create user - we must create a DigimedBooking (previously I thought a separate model DigimedReferral would be necessary, but now i think not) ### The High Castle - ConsultationResult model * Encrypted ICPC_2 (ICPC-2** code as sanitized string value) * Encrypted outcome (string value, from list of possible outcomes, eg. "Referred GP", "Helped", "Unable" etc) * Encrypted patient_ssn (if different from user SSN, in case of minor) * Encrypted patient_job_description (same as on bookings) ----- - contents gets piped to IF (reporting) - highly sensitive, we as a DevTeam should not have access. This is, technically, medical record. - it's security must be elevated, no time right now to get this done in a decent fashion - needs to be a scope of little sub-project ## ER Diagram ```plantuml @startuml class ConsultationResult { # (ALL ATTRIBUTES ENCRYPTED) - icpc2:string # crude - outcome:string # from list enum mby? - patient_ssn - patient_job_description - author_sp_id - notes:text - policy_number: bigint } class DigimedBooking { # flow_identifier() // returns 'referral' if referral present; else 'direct' - user - digimed_referral FK - assigned_at: datetime - starts_at: datetime // not sure - \nshould be equal to begins_at which should reflect factual state - ends_at - service_providers // bookings have many, in this\n case it will always be 1 - category: string (hardcoded to `insurance`) - v2_line_item -> order -> customer - enabled_channels: int[] - primary_channel : int - options: jsonb # is_insurance? --> checks if the deal \nis tagged as insurance # we don't have to know whether insurance or not. } class V2LineItem {} class V2Order {} class Organization { # IF Insurances } class DigimedReferral { # create_booking() - journal_uuid:, - user_id - data: jsonb // original webhook payload - partner : // OrganizationID of IF - deal_id: // DealID of IF DIGIMED - supervisor_sp_id // the one who calls the patient } BookingBase --> DigimedBooking ConsultationResult -- DigimedBooking DigimedBooking -- V2LineItem V2LineItem -- V2Order V2Order -- Organization DigimedReferral -- DigimedBooking @enduml ``` #### DigimedBooking - parameter definitions - created_at -> contractual time to serve the booking starts ticking - assigned_at -> time in which either SP picks up the booking as his/hers or Supervisor assigns some SP to it. - starts_at -> (same as responded at) the moment SP actually starts a booking and SP and patient get in contact. treatment begins. **WAITING_TIME** = booking.starts_at - booking.created_at **TREATMENT_DURATION** = booking.ends_at - booking.starts_at ## Referral Flow - Architectural sequence of events ```plantuml @startuml boundary Pridok as prid actor Patient as pat actor Doctor as doc actor Secretary as sec entity Backend as back database DB as db === 1. HL Receives referral in EPJ == prid -> back : sends a webhook (needs to contain SSN, email, phone_no) back -> back : receives and parses webhook, checks auth back -> db : creates a User (user somehow must be tagged\nthat is from IF, no marketing bs sent) back -> db : creates a Booking \n (different from normal referrals) === 2. Secretary creates booking from EPJ == note over back Secretary (SP Supervisor) screens the Bookings and calls patients. If they require Digimed help, secretary clicks "create booking" button. end note sec -> back : UI lists DigimedBookings sec -> back : creates Booking back -> db : creates DigimedBooking obj === 3. Booking placed in the queue == sec -> back : Secretary or ServiceProvider queries backend for list of DigiMedBookings open === 4. Doctor pulls booking from the queue and calls patient == doc -> back : BookingBase is now ongoing and started (started_at is now NON_NULL) back -> back : backend configures chat & video sessions back -> pat : backend sends Patient link to participate in the Booking note over back quite possibly, SP should be able to do several user related things 1) pull his data 2) his history of booking 3) book a rebooking end note === 5. Doctor completes consultation, adds ICPC-2 == note over back doctor clicks button, Booking ends_at becomes filled Doc is presented with a Report Form Patient is redirected to the Review page or sth end note back -> db : ConsultationResult record is created @enduml ``` #### What we ended up with ... ConsultationType ```ruby class Consultation < ApplicationRecord has_many :service_providers has_many :patients enum state: %i[ready_for_pickup pending_sp in_progress completed cancelled] belongs_to :user belongs_to :order has_one :video_room has_one :chat_room # .... end ``` - obviously new classes have to be introduced Consultation ConsultationServiceProvider DigimedEntry VideoRoom ChatRoom - New mailer/communication classes ( at least we should send sth onConsultationCompletion) etc. - Order recalculator has to account for discounts and LineItem should probably get a new column discount:decimal - New jobs/service introduced - ConsultationCreator SO (set up order, set up it's line items, configure new consultation, setup chat/video) - ConsultationUpdater SO - ConsultationCanceller SO - ConsultationReportGeneratorJob (likely some Excel file generator, I'm guessing) - GQL endpoints Consultations (index) createConsultation pickConsultation updateConsultation finishConsultation - GQL subscriptions consultations