diff --git a/services/tickets/zendesk/service.go b/services/tickets/zendesk/service.go index 20f4c5e25..de9a0e7c9 100644 --- a/services/tickets/zendesk/service.go +++ b/services/tickets/zendesk/service.go @@ -80,23 +80,27 @@ func NewService(rtCfg *runtime.Config, httpClient *http.Client, httpRetries *htt // Open opens a ticket which for mailgun means just sending an initial email func (s *service) Open(session flows.Session, topic *flows.Topic, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { ticket := flows.OpenTicket(s.ticketer, topic, body, assignee) + + contact := session.Contact() + if contact == nil { + return nil, fmt.Errorf("session contact is nil") + } + contactDisplay := session.Contact().Format(session.Environment()) contactUUID := string(session.Contact().UUID()) + var trace *httpx.Trace var phoneNumber string - urn := session.Contact().PreferredURN().URN() - if urn.Scheme() == "whatsapp" { - phoneNumber = string(session.Contact().PreferredURN().URN().Path()) + preferredURN := contact.PreferredURN() + if preferredURN != nil && preferredURN.URN().Scheme() == "whatsapp" { + phoneNumber = string(preferredURN.URN().Path()) } - user, trace, err := s.restClient.SearchUser(contactUUID) - if trace != nil { - logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor)) - } - if err != nil && trace.Response.StatusCode != http.StatusNotFound { + user, err := s.searchUserWithIdentities(contactUUID, phoneNumber, logHTTP) + if err != nil && user == nil { return nil, err } - if trace.Response.StatusCode == http.StatusNotFound || user == nil { + if user == nil { newUser := &User{ Name: contactDisplay, ExternalID: contactUUID, @@ -197,16 +201,18 @@ func (s *service) Open(session flows.Session, topic *flows.Topic, body string, a if trace != nil { logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor)) } - if err != nil && trace.Response.StatusCode != http.StatusNotFound { + if err != nil { return nil, err } - _, trace, err = s.restClient.MergeUser(user.ID, unmergedUser.ID) - if trace != nil { - logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor)) - } - if err != nil && trace.Response.StatusCode != http.StatusNotFound { - return nil, err + if unmergedUser != nil { + _, trace, err = s.restClient.MergeUser(user.ID, unmergedUser.ID) + if trace != nil { + logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor)) + } + if err != nil { + return nil, err + } } return ticket, nil @@ -402,3 +408,49 @@ func (s *service) convertAttachments(attachments []utils.Attachment) ([]string, } return fileURLs, nil } + +func (s *service) searchUserWithIdentities(contactUUID string, phoneNumber string, logHTTP flows.HTTPLogCallback) (*User, error) { + fetchUser := func(identifier string) (*User, error) { + if identifier == "" { + return nil, nil + } + user, trace, err := s.restClient.SearchUser(identifier) + if trace != nil { + logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor)) + } + if err != nil && trace.Response.StatusCode != http.StatusNotFound { + return nil, err + } + return user, nil + } + + userContactUUID, err := fetchUser(contactUUID) + if err != nil { + return nil, err + } + + userPhoneNumber, err := fetchUser(phoneNumber) + if err != nil { + return nil, err + } + + switch { + case userContactUUID == nil && userPhoneNumber == nil: + return nil, nil + case userContactUUID != nil && userPhoneNumber == nil: + return userContactUUID, nil + case userPhoneNumber != nil && userContactUUID == nil: + return userPhoneNumber, nil + case userContactUUID.ID == userPhoneNumber.ID: + return userContactUUID, nil + default: + mergedUser, trace, err := s.restClient.MergeUser(userContactUUID.ID, userPhoneNumber.ID) + if trace != nil { + logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor)) + } + if err != nil && trace.Response.StatusCode != http.StatusNotFound { + return nil, err + } + return mergedUser, nil + } +}