---
# System prepended metadata

title: Patients and ContactPerson as an STI (after discussion)

---

# Patients and ContactPerson as an STI (after discussion)


### Business objectives

- retain information about patient-to-contact-person relationship
- retain info about what type of contact-person is it? Legal guardian? Ordinary fella of convenience?

## Solution

```plantuml
@startuml

class ContactLink {
  + person
  + contact
  + legal_guardian: bool
}

class Person <<Abstract>> {}

package Contacts #0F0 {
  class Patient {
    + contacts[]
  }

  class ContactPerson {
    + phone_number
  }

  Person o-- ContactPerson
  Person o-- Patient
}


Person }|--|| ContactLink
note left on link
<b>Join table</b>
ContactPerson should not 
have contact_links,
only Patient can have contact_links :-) 
end note

Patient ||--|{ ContactLink

note top of Person #0F0: STI

@enduml
```


Validatin

## Todos

- [ ] 1. Create Person as an STI with ContactPerson, and Patient subclasses
    - [ ] Migration
        - [x] rename `patients` table to `persons`
        - [x] add non-null type column and prefill with `Person` val for compatibility
        - [ ] backfill/mass create ContactPersons from Bookings already in DB
    - [ ] Models & Validations
- [x] 2. Create JOIN table `contact_links` table
  - [x] adjust associations
- [ ] 3. controllers/services
    - [ ] pass contact persons to Views to populate dropdown and stuff
    - [ ] on form submit
        - [ ] create contact persons when applicable
        - [ ] store patient-contact-person associations

```ruby =
class CreateContactLinks < ActiveRecord::Migration[6.0]
  def change
      create_table :contact_links do |t|
          t.references :person_id, foreign_key: { to_table: 'persons' }
          t.references :contact_id, foreign_key: { to_table: 'persons' }
          t.boolean :legal_guardian
         end
      end
  end
  # add_reference :contact_links, :persons, foreign_key: true
end
```


```ruby=
class Person < ActiveRecord::Base
  include SanitizePhoneNumber
  
end

class Patient < Person
  validates :national_id, length: {is: 11, message: :wrong_length_digit}, allow_blank: true

  has_many :contact_links
  has_many :contacts, through :contact_links # better name appreciated! [ContactPerson, Patient]
  
  scope :
  
  # all that was already
  has_one :user
  has_many :pat_links
  has_many :users, through: :pat_links, source: :pat_linkable, source_type: 'User'
  has_many :referrals, through: :pat_links, source: :pat_linkable, source_type: 'Referral'
  has_many :booking_bases, class_name: 'BookingBase', through: :pat_links, source: :pat_linkable, source_type: 'BookingBase'
  encrypts :national_id
  
  before_validation do
    self.independent = !contacts.legal_guardians.any?
  end
  
  # sync independent|dependent state on_create,on_update
  
  # validate_dependency_state # not a priority, likely many PROD DB records invalid in that regard
  
#   scope :independent, -> { joins(:responsible_contacts).where(responsible_contacts: {legal_guardians: true})}
  
#   scope :dependent, -> { joins(:responsible_contacts).where(responsible_contacts: {legal_guardians: false})}
  
#   def independent?
#     responsible_contacts.legal_guardians.any?
#   end
  
#   def dependent?
#     !independent?
#   end
end

class ContactLink < ActiveRecord::Base
  belongs_to :patient
  belongs_to :contact
  
  scope :legal_guardians, -> { where(legal_guardian: true) }
  
  # handle destroy case on both ends
end

class ContactPerson < Person
  has_many :contact_links
  has_many :contact_linkees, through: :contact_links  # better name appreciated!
end
```


