---
# System prepended metadata

title: Dragonfly project backend

---

# 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


