Skip to content

Commit

Permalink
Add ability to send connection invites for multiple providers
Browse files Browse the repository at this point in the history
  • Loading branch information
toddkazakov committed Oct 18, 2024
1 parent 2d79552 commit 8b46d39
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 49 deletions.
56 changes: 34 additions & 22 deletions patients/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ func (p *PatientCDCConsumer) handleCDCEvent(event PatientCDCEvent) error {
return err
}

// Only send invite email if patient does not have a pending dexcom connect request, which also
// Only send invite email if patient does not have a pending connection request, which also
// sends an email that provides a pathway towards claiming the account
if !event.PatientHasPendingDexcomConnection() {
if !event.PatientHasPendingConnection() {
if err := p.applyInviteUpdate(event); err != nil {
return err
}
Expand Down Expand Up @@ -177,16 +177,17 @@ func (p *PatientCDCConsumer) handleCDCEvent(event PatientCDCEvent) error {
return p.sendUploadReminder(*event.FullDocument.UserId)
}

if event.IsRequestDexcomConnectEvent() {
p.logger.Infow("processing dexcom connect email", "event", event)
connectionRequests := event.UpdateDescription.UpdatedFields.GetUpdatedConnectionRequests()
if len(connectionRequests) > 0 {
p.logger.Infow("processing connection requests", "event", event)

if event.FullDocument.IsCustodial() {
invite := confirmations.UpsertAccountSignupConfirmationJSONRequestBody{
ClinicId: (*confirmations.ClinicId)(&event.FullDocument.ClinicId.Value),
InvitedBy: (*confirmations.TidepoolUserId)(event.FullDocument.InvitedBy),
ClinicId: &event.FullDocument.ClinicId.Value,
InvitedBy: event.FullDocument.InvitedBy,
}

response, err := p.confirmations.UpsertAccountSignupConfirmationWithResponse(ctx, confirmations.UserId(*event.FullDocument.UserId), invite)
response, err := p.confirmations.UpsertAccountSignupConfirmationWithResponse(ctx, *event.FullDocument.UserId, invite)
if err != nil {
return fmt.Errorf("unable to upsert confirmation: %v", err)
}
Expand All @@ -198,26 +199,37 @@ func (p *PatientCDCConsumer) handleCDCEvent(event PatientCDCEvent) error {
}
}

templateName := "request_dexcom_connect"

if event.FullDocument.IsCustodial() {
templateName = "request_dexcom_connect_custodial"
providers := map[string]struct{}{}
for _, r := range connectionRequests {
providers[r.ProviderName] = struct{}{}
}

if event.FullDocument.DataSources != nil {
for _, source := range *event.FullDocument.DataSources {
if *source.ProviderName == DexcomDataSourceProviderName && *source.State == string(clinics.DataSourceStatePendingReconnect) {
templateName = "request_dexcom_reconnect"
errs := make([]error, 0, len(providers))
for providerName, _ := range providers {
templatePrefix := fmt.Sprintf("request_%s_", providerName)
action := "connect"
if event.FullDocument.IsCustodial() {
action = "connect_custodial"
}
if event.FullDocument.DataSources != nil {
for _, source := range *event.FullDocument.DataSources {
if *source.ProviderName == providerName && *source.State == string(clinics.DataSourceStatePendingReconnect) {
action = "reconnect"
}
}
}
}

return p.sendDexcomConnectEmail(
*event.FullDocument.UserId,
event.FullDocument.ClinicId.Value,
*event.FullDocument.FullName,
templateName,
)
templateName := templatePrefix + action
errs = append(errs, p.sendDexcomConnectEmail(
*event.FullDocument.UserId,
event.FullDocument.ClinicId.Value,
*event.FullDocument.FullName,
templateName,
))
}
if err := errors.Join(errs...); err != nil {
return err
}
}

return nil
Expand Down
77 changes: 50 additions & 27 deletions patients/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,6 @@ func (p PatientCDCEvent) IsUploadReminderEvent() bool {
return lastUploadReminderTime != nil && lastUploadReminderTime.Value > 0
}

func (p PatientCDCEvent) IsRequestDexcomConnectEvent() bool {
if p.OperationType != cdc.OperationTypeUpdate && p.OperationType != cdc.OperationTypeReplace {
return false
}
if p.FullDocument.UserId == nil || p.UpdateDescription.UpdatedFields.LastRequestedDexcomConnectTime == nil {
return false
}
return p.UpdateDescription.UpdatedFields.LastRequestedDexcomConnectTime.Value > 0
}

func (p PatientCDCEvent) IsProfileUpdateEvent() bool {
if p.OperationType != cdc.OperationTypeInsert && p.OperationType != cdc.OperationTypeUpdate && p.OperationType != cdc.OperationTypeReplace {
return false
Expand All @@ -55,10 +45,10 @@ func (p PatientCDCEvent) IsPatientCreateFromExistingUserEvent() bool {
return p.OperationType == cdc.OperationTypeInsert && !p.FullDocument.IsCustodial()
}

func (p PatientCDCEvent) PatientHasPendingDexcomConnection() bool {
func (p PatientCDCEvent) PatientHasPendingConnection() bool {
if p.FullDocument.DataSources != nil {
for _, dataSource := range *p.FullDocument.DataSources {
if *dataSource.ProviderName == DexcomDataSourceProviderName && *dataSource.State == string(clinics.DataSourceStatePending) {
if *dataSource.State == string(clinics.DataSourceStatePending) {
return true
}
}
Expand Down Expand Up @@ -110,21 +100,31 @@ type CDCSummary struct {
}

type Patient struct {
Id *cdc.ObjectId `json:"_id" bson:"_id"`
ClinicId *cdc.ObjectId `json:"clinicId" bson:"clinicId"`
UserId *string `json:"userId" bson:"userId"`
BirthDate *string `json:"birthDate" bson:"birthDate"`
Email *string `json:"email" bson:"email"`
FullName *string `json:"fullName" bson:"fullName"`
Mrn *string `json:"mrn" bson:"mrn"`
TargetDevices *[]string `json:"targetDevices" bson:"targetDevices"`
DataSources *[]PatientDataSource `json:"dataSources" bson:"dataSources"`
Permissions *Permissions `json:"permissions" bson:"permissions"`
IsMigrated bool `json:"isMigrated" bson:"isMigrated"`
InvitedBy *string `json:"invitedBy" bson:"invitedBy"`
LastRequestedDexcomConnectTime *cdc.Date `json:"lastRequestedDexcomConnectTime" bson:"lastRequestedDexcomConnectTime"`
LastUploadReminderTime *cdc.Date `json:"lastUploadReminderTime" bson:"lastUploadReminderTime"`
Summary *CDCSummary `json:"summary" bson:"summary"`
Id *cdc.ObjectId `json:"_id" bson:"_id"`
ClinicId *cdc.ObjectId `json:"clinicId" bson:"clinicId"`
UserId *string `json:"userId" bson:"userId"`
BirthDate *string `json:"birthDate" bson:"birthDate"`
Email *string `json:"email" bson:"email"`
FullName *string `json:"fullName" bson:"fullName"`
Mrn *string `json:"mrn" bson:"mrn"`
TargetDevices *[]string `json:"targetDevices" bson:"targetDevices"`
DataSources *[]PatientDataSource `json:"dataSources" bson:"dataSources"`
Permissions *Permissions `json:"permissions" bson:"permissions"`
IsMigrated bool `json:"isMigrated" bson:"isMigrated"`
InvitedBy *string `json:"invitedBy" bson:"invitedBy"`
LastRequestedDexcomConnectTime *cdc.Date `json:"lastRequestedDexcomConnectTime" bson:"lastRequestedDexcomConnectTime"`
LastUploadReminderTime *cdc.Date `json:"lastUploadReminderTime" bson:"lastUploadReminderTime"`
Summary *CDCSummary `json:"summary" bson:"summary"`
ProviderConnectionRequests ProviderConnectionRequests `json:"providerConnectionRequests" bson:"providerConnectionRequests"`
}

type ProviderConnectionRequests map[string]ConnectionRequests

type ConnectionRequests []ConnectionRequest

type ConnectionRequest struct {
ProviderName string `json:"providerName" bson:"providerName"`
CreatedTime cdc.Date `json:"createdTime" bson:"createdTime"`
}

func (p PatientCDCEvent) CreateDataSourceBody(source clients.DataSource) clinics.DataSource {
Expand Down Expand Up @@ -170,4 +170,27 @@ func (u UpdateDescription) applyUpdatesToExistingProfile(profile map[string]inte

type UpdatedFields struct {
Patient

// Partial updates to nested fields are encoded using dot notation in CDC events
ProviderConnectionRequestsDexcom ConnectionRequests `bson:"providerConnectionRequests.dexcom"`
ProviderConnectionRequestsTwiist ConnectionRequests `bson:"providerConnectionRequests.twiist"`
}

func (u UpdatedFields) GetUpdatedConnectionRequests() ConnectionRequests {
var requests ConnectionRequests
if u.ProviderConnectionRequests != nil {
for _, r := range u.ProviderConnectionRequests {
for _, v := range r {
requests = append(requests, v)
}
}
}
for _, v := range u.ProviderConnectionRequestsDexcom {
requests = append(requests, v)
}
for _, v := range u.ProviderConnectionRequestsTwiist {
requests = append(requests, v)
}
return requests
}

0 comments on commit 8b46d39

Please sign in to comment.