# 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