diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d179e5c3..5b8d5f1c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +v6.5.28 +---------- + * Add warning log entry when task takes longer than 1 minute + +v6.5.27 +---------- + * Update to latest goflow (fixes word_slice) + +v6.5.26 +---------- + * Update to latest goflow + v6.5.25 ---------- * Add notifications for contact imports and set contact import status diff --git a/core/goflow/engine.go b/core/goflow/engine.go index 1979e5ce8..b4d90e383 100644 --- a/core/goflow/engine.go +++ b/core/goflow/engine.go @@ -108,8 +108,8 @@ type simulatorTicketService struct { ticketer *flows.Ticketer } -func (s *simulatorTicketService) Open(session flows.Session, topic *flows.Topic, subject, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { - return flows.OpenTicket(s.ticketer, topic, subject, body, assignee), nil +func (s *simulatorTicketService) Open(session flows.Session, topic *flows.Topic, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { + return flows.OpenTicket(s.ticketer, topic, body, assignee), nil } func simulatorAirtimeServiceFactory(session flows.Session) (flows.AirtimeService, error) { diff --git a/core/goflow/engine_test.go b/core/goflow/engine_test.go index be94e4446..3d6634a3c 100644 --- a/core/goflow/engine_test.go +++ b/core/goflow/engine_test.go @@ -68,10 +68,12 @@ func TestSimulatorTicket(t *testing.T) { svc, err := goflow.Simulator(rt.Config).Services().Ticket(nil, flows.NewTicketer(ticketer)) assert.NoError(t, err) - ticket, err := svc.Open(nil, nil, "New ticket", "Where are my cookies?", nil, nil) + oa, err := models.GetOrgAssets(ctx, db, testdata.Org1.ID) + require.NoError(t, err) + + ticket, err := svc.Open(nil, oa.SessionAssets().Topics().FindByName("General"), "Where are my cookies?", nil, nil) assert.NoError(t, err) assert.Equal(t, testdata.Mailgun.UUID, ticket.Ticketer().UUID()) - assert.Equal(t, "New ticket", ticket.Subject()) assert.Equal(t, "Where are my cookies?", ticket.Body()) } diff --git a/core/handlers/ticket_opened.go b/core/handlers/ticket_opened.go index a720e33d3..479f97340 100644 --- a/core/handlers/ticket_opened.go +++ b/core/handlers/ticket_opened.go @@ -53,7 +53,6 @@ func handleTicketOpened(ctx context.Context, tx *sqlx.Tx, rp *redis.Pool, oa *mo ticketer.ID(), event.Ticket.ExternalID, topicID, - event.Ticket.Subject, event.Ticket.Body, assigneeID, map[string]interface{}{ diff --git a/core/handlers/ticket_opened_test.go b/core/handlers/ticket_opened_test.go index 51fa7c50d..56898526a 100644 --- a/core/handlers/ticket_opened_test.go +++ b/core/handlers/ticket_opened_test.go @@ -45,7 +45,7 @@ func TestTicketOpened(t *testing.T) { })) // an existing ticket - cathyTicket := models.NewTicket(flows.TicketUUID(uuids.New()), testdata.Org1.ID, testdata.Cathy.ID, testdata.Mailgun.ID, "748363", testdata.DefaultTopic.ID, "Old Question", "Who?", models.NilUserID, nil) + cathyTicket := models.NewTicket(flows.TicketUUID(uuids.New()), testdata.Org1.ID, testdata.Cathy.ID, testdata.Mailgun.ID, "748363", testdata.DefaultTopic.ID, "Who?", models.NilUserID, nil) err := models.InsertTickets(ctx, db, []*models.Ticket{cathyTicket}) require.NoError(t, err) @@ -57,7 +57,6 @@ func TestTicketOpened(t *testing.T) { handlers.NewActionUUID(), assets.NewTicketerReference(testdata.Mailgun.UUID, "Mailgun (IT Support)"), assets.NewTopicReference(testdata.SupportTopic.UUID, "Support"), - "", "Where are my cookies?", assets.NewUserReference(testdata.Admin.Email, "Admin"), "Email Ticket", @@ -68,7 +67,6 @@ func TestTicketOpened(t *testing.T) { handlers.NewActionUUID(), assets.NewTicketerReference(testdata.Zendesk.UUID, "Zendesk (Nyaruka)"), nil, - "Interesting", "I've found some cookies", nil, "Zen Ticket", diff --git a/core/models/assets_test.go b/core/models/assets_test.go index 440449752..41b1c56e3 100644 --- a/core/models/assets_test.go +++ b/core/models/assets_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/nyaruka/goflow/assets" - "github.com/nyaruka/goflow/assets/static/types" + "github.com/nyaruka/goflow/assets/static" "github.com/nyaruka/mailroom/core/models" "github.com/nyaruka/mailroom/testsuite" "github.com/nyaruka/mailroom/testsuite/testdata" @@ -33,8 +33,8 @@ func TestCloneForSimulation(t *testing.T) { } testChannels := []assets.Channel{ - types.NewChannel("d7be3965-4c76-4abd-af78-ebc0b84ab621", "Test Channel 1", "1234567890", []string{"tel"}, nil, nil), - types.NewChannel("fd130d20-65f8-43fc-a3c5-a3fa4d1e4193", "Test Channel 2", "2345678901", []string{"tel"}, nil, nil), + static.NewChannel("d7be3965-4c76-4abd-af78-ebc0b84ab621", "Test Channel 1", "1234567890", []string{"tel"}, nil, nil), + static.NewChannel("fd130d20-65f8-43fc-a3c5-a3fa4d1e4193", "Test Channel 2", "2345678901", []string{"tel"}, nil, nil), } clone, err := oa.CloneForSimulation(ctx, db, newDefs, testChannels) diff --git a/core/models/contacts.go b/core/models/contacts.go index 9f4167897..ab75444f4 100644 --- a/core/models/contacts.go +++ b/core/models/contacts.go @@ -322,7 +322,7 @@ func LoadContacts(ctx context.Context, db Queryer, org *OrgAssets, ids []Contact for _, t := range e.Tickets { ticketer := org.TicketerByID(t.TicketerID) if ticketer != nil { - tickets = append(tickets, NewTicket(t.UUID, org.OrgID(), contact.ID(), ticketer.ID(), t.ExternalID, t.TopicID, t.Subject, t.Body, t.AssigneeID, nil)) + tickets = append(tickets, NewTicket(t.UUID, org.OrgID(), contact.ID(), ticketer.ID(), t.ExternalID, t.TopicID, t.Body, t.AssigneeID, nil)) } } contact.tickets = tickets diff --git a/core/models/contacts_test.go b/core/models/contacts_test.go index ab3f275f1..11d182d45 100644 --- a/core/models/contacts_test.go +++ b/core/models/contacts_test.go @@ -26,9 +26,9 @@ func TestContacts(t *testing.T) { defer testsuite.Reset() testdata.InsertContactURN(db, testdata.Org1, testdata.Bob, "whatsapp:250788373373", 999) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.SupportTopic, "Problem!", "Where are my shoes?", "1234", testdata.Agent) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.SalesTopic, "Another Problem!", "Where are my pants?", "2345", nil) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Bob, testdata.Mailgun, testdata.DefaultTopic, "Urgent", "His name is Bob", "", testdata.Editor) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.SupportTopic, "Where are my shoes?", "1234", testdata.Agent) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.SalesTopic, "Where are my pants?", "2345", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Bob, testdata.Mailgun, testdata.DefaultTopic, "His name is Bob", "", testdata.Editor) // delete mailgun ticketer db.MustExec(`UPDATE tickets_ticketer SET is_active = false WHERE id = $1`, testdata.Mailgun.ID) @@ -63,10 +63,8 @@ func TestContacts(t *testing.T) { assert.Equal(t, 2, cathy.Tickets().Count()) cathyTickets := cathy.Tickets().All() - assert.Equal(t, "Problem!", cathyTickets[0].Subject()) assert.Equal(t, "Support", cathyTickets[0].Topic().Name()) assert.Equal(t, "agent1@nyaruka.com", cathyTickets[0].Assignee().Email()) - assert.Equal(t, "Another Problem!", cathyTickets[1].Subject()) assert.Equal(t, "Sales", cathyTickets[1].Topic().Name()) assert.Nil(t, cathyTickets[1].Assignee()) diff --git a/core/models/msgs_test.go b/core/models/msgs_test.go index 8d49c0f40..b8ccf3d96 100644 --- a/core/models/msgs_test.go +++ b/core/models/msgs_test.go @@ -282,7 +282,7 @@ func TestNonPersistentBroadcasts(t *testing.T) { defer testsuite.ResetData(db) - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Bob, testdata.Mailgun, testdata.DefaultTopic, "Problem", "", "", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Bob, testdata.Mailgun, testdata.DefaultTopic, "", "", nil) modelTicket := ticket.Load(db) translations := map[envs.Language]*models.BroadcastTranslation{envs.Language("eng"): {Text: "Hi there"}} diff --git a/core/models/notifications_test.go b/core/models/notifications_test.go index 1895d0a28..e19be211c 100644 --- a/core/models/notifications_test.go +++ b/core/models/notifications_test.go @@ -147,7 +147,7 @@ func assertNotifications(t *testing.T, ctx context.Context, db *sqlx.DB, after t } func openTicket(t *testing.T, ctx context.Context, db *sqlx.DB, openedBy *testdata.User, assignee *testdata.User) (*models.Ticket, *models.TicketEvent) { - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.SupportTopic, "", "Where my pants", "", assignee) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.SupportTopic, "Where my pants", "", assignee) modelTicket := ticket.Load(db) openedEvent := models.NewTicketOpenedEvent(modelTicket, openedBy.SafeID(), assignee.SafeID()) diff --git a/core/models/ticket_events_test.go b/core/models/ticket_events_test.go index eddf33070..c2c663e03 100644 --- a/core/models/ticket_events_test.go +++ b/core/models/ticket_events_test.go @@ -19,7 +19,7 @@ func TestTicketEvents(t *testing.T) { db.MustExec(`DELETE FROM tickets_ticket`) }() - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "17", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Have you seen my cookies?", "17", nil) modelTicket := ticket.Load(db) e1 := models.NewTicketOpenedEvent(modelTicket, testdata.Admin.ID, testdata.Agent.ID) diff --git a/core/models/tickets.go b/core/models/tickets.go index 420f04c5e..b0de49346 100644 --- a/core/models/tickets.go +++ b/core/models/tickets.go @@ -76,7 +76,6 @@ type Ticket struct { ExternalID null.String `db:"external_id"` Status TicketStatus `db:"status"` TopicID TopicID `db:"topic_id"` - Subject string `db:"subject"` Body string `db:"body"` AssigneeID UserID `db:"assignee_id"` Config null.Map `db:"config"` @@ -88,7 +87,7 @@ type Ticket struct { } // NewTicket creates a new open ticket -func NewTicket(uuid flows.TicketUUID, orgID OrgID, contactID ContactID, ticketerID TicketerID, externalID string, topicID TopicID, subject, body string, assigneeID UserID, config map[string]interface{}) *Ticket { +func NewTicket(uuid flows.TicketUUID, orgID OrgID, contactID ContactID, ticketerID TicketerID, externalID string, topicID TopicID, body string, assigneeID UserID, config map[string]interface{}) *Ticket { t := &Ticket{} t.t.UUID = uuid t.t.OrgID = orgID @@ -97,7 +96,6 @@ func NewTicket(uuid flows.TicketUUID, orgID OrgID, contactID ContactID, ticketer t.t.ExternalID = null.String(externalID) t.t.Status = TicketStatusOpen t.t.TopicID = topicID - t.t.Subject = subject t.t.Body = body t.t.AssigneeID = assigneeID t.t.Config = null.NewMap(config) @@ -112,7 +110,6 @@ func (t *Ticket) TicketerID() TicketerID { return t.t.TicketerID } func (t *Ticket) ExternalID() null.String { return t.t.ExternalID } func (t *Ticket) Status() TicketStatus { return t.t.Status } func (t *Ticket) TopicID() TopicID { return t.t.TopicID } -func (t *Ticket) Subject() string { return t.t.Subject } func (t *Ticket) Body() string { return t.t.Body } func (t *Ticket) AssigneeID() UserID { return t.t.AssigneeID } func (t *Ticket) LastActivityOn() time.Time { return t.t.LastActivityOn } @@ -146,7 +143,6 @@ func (t *Ticket) FlowTicket(oa *OrgAssets) (*flows.Ticket, error) { t.UUID(), oa.SessionAssets().Ticketers().Get(modelTicketer.UUID()), topic, - t.Subject(), t.Body(), string(t.ExternalID()), assignee, @@ -183,7 +179,6 @@ SELECT t.external_id AS external_id, t.status AS status, t.topic_id AS topic_id, - t.subject AS subject, t.body AS body, t.assignee_id AS assignee_id, t.config AS config, @@ -213,7 +208,6 @@ SELECT t.external_id AS external_id, t.status AS status, t.topic_id AS topic_id, - t.subject AS subject, t.body AS body, t.assignee_id AS assignee_id, t.config AS config, @@ -262,7 +256,6 @@ SELECT t.external_id AS external_id, t.status AS status, t.topic_id AS topic_id, - t.subject AS subject, t.body AS body, t.assignee_id AS assignee_id, t.config AS config, @@ -291,7 +284,6 @@ SELECT t.external_id AS external_id, t.status AS status, t.topic_id AS topic_id, - t.subject AS subject, t.body AS body, t.assignee_id AS assignee_id, t.config AS config, @@ -333,8 +325,8 @@ func lookupTicket(ctx context.Context, db Queryer, query string, params ...inter const insertTicketSQL = ` INSERT INTO - tickets_ticket(uuid, org_id, contact_id, ticketer_id, external_id, status, topic_id, subject, body, assignee_id, config, opened_on, modified_on, last_activity_on) - VALUES( :uuid, :org_id, :contact_id, :ticketer_id, :external_id, :status, :topic_id, :subject, :body, :assignee_id, :config, NOW(), NOW() , NOW()) + tickets_ticket(uuid, org_id, contact_id, ticketer_id, external_id, status, topic_id, body, assignee_id, config, opened_on, modified_on, last_activity_on) + VALUES( :uuid, :org_id, :contact_id, :ticketer_id, :external_id, :status, :topic_id, :body, :assignee_id, :config, NOW(), NOW() , NOW()) RETURNING id ` diff --git a/core/models/tickets_test.go b/core/models/tickets_test.go index 087451f2b..73e5cfa47 100644 --- a/core/models/tickets_test.go +++ b/core/models/tickets_test.go @@ -66,7 +66,6 @@ func TestTickets(t *testing.T) { testdata.Mailgun.ID, "EX12345", testdata.DefaultTopic.ID, - "New Ticket", "Where are my cookies?", testdata.Admin.ID, map[string]interface{}{ @@ -80,7 +79,6 @@ func TestTickets(t *testing.T) { testdata.Zendesk.ID, "EX7869", testdata.SalesTopic.ID, - "New Zen Ticket", "Where are my trousers?", models.NilUserID, nil, @@ -92,7 +90,6 @@ func TestTickets(t *testing.T) { testdata.Zendesk.ID, "EX6677", models.NilTopicID, - "Other Org Ticket", "Where are my pants?", testdata.Org2Admin.ID, nil, @@ -104,7 +101,6 @@ func TestTickets(t *testing.T) { assert.Equal(t, testdata.Mailgun.ID, ticket1.TicketerID()) assert.Equal(t, null.String("EX12345"), ticket1.ExternalID()) assert.Equal(t, testdata.DefaultTopic.ID, ticket1.TopicID()) - assert.Equal(t, "New Ticket", ticket1.Subject()) assert.Equal(t, "Cathy", ticket1.Config("contact-display")) assert.Equal(t, testdata.Admin.ID, ticket1.AssigneeID()) assert.Equal(t, "", ticket1.Config("xyz")) @@ -118,12 +114,12 @@ func TestTickets(t *testing.T) { // can lookup a ticket by UUID tk1, err := models.LookupTicketByUUID(ctx, db, "2ef57efc-d85f-4291-b330-e4afe68af5fe") assert.NoError(t, err) - assert.Equal(t, "New Ticket", tk1.Subject()) + assert.Equal(t, "Where are my cookies?", tk1.Body()) // can lookup a ticket by external ID and ticketer tk2, err := models.LookupTicketByExternalID(ctx, db, testdata.Zendesk.ID, "EX7869") assert.NoError(t, err) - assert.Equal(t, "New Zen Ticket", tk2.Subject()) + assert.Equal(t, "Where are my trousers?", tk2.Body()) // can lookup open tickets by contact org1, _ := models.GetOrgAssets(ctx, db, testdata.Org1.ID) @@ -133,7 +129,7 @@ func TestTickets(t *testing.T) { tks, err := models.LoadOpenTicketsForContact(ctx, db, cathy) assert.NoError(t, err) assert.Equal(t, 1, len(tks)) - assert.Equal(t, "New Ticket", tks[0].Subject()) + assert.Equal(t, "Where are my cookies?", tks[0].Body()) } func TestUpdateTicketConfig(t *testing.T) { @@ -141,7 +137,7 @@ func TestUpdateTicketConfig(t *testing.T) { defer testsuite.ResetData(db) - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where my shoes", "123", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where my shoes", "123", nil) modelTicket := ticket.Load(db) // empty configs are null @@ -167,7 +163,7 @@ func TestUpdateTicketLastActivity(t *testing.T) { defer dates.SetNowSource(dates.DefaultNowSource) dates.SetNowSource(dates.NewFixedNowSource(now)) - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where my shoes", "123", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where my shoes", "123", nil) modelTicket := ticket.Load(db) models.UpdateTicketLastActivity(ctx, db, []*models.Ticket{modelTicket}) @@ -186,13 +182,13 @@ func TestTicketsAssign(t *testing.T) { oa, err := models.GetOrgAssetsWithRefresh(ctx, db, testdata.Org1.ID, models.RefreshTicketers) require.NoError(t, err) - ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where my shoes", "123", nil) + ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where my shoes", "123", nil) modelTicket1 := ticket1.Load(db) - ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Old Problem", "Where my pants", "234", nil) + ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Where my pants", "234", nil) modelTicket2 := ticket2.Load(db) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Ignore", "", "", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "", "", nil) evts, err := models.TicketsAssign(ctx, db, oa, testdata.Admin.ID, []*models.Ticket{modelTicket1, modelTicket2}, testdata.Agent.ID, "please handle these") require.NoError(t, err) @@ -218,13 +214,13 @@ func TestTicketsAddNote(t *testing.T) { oa, err := models.GetOrgAssetsWithRefresh(ctx, db, testdata.Org1.ID, models.RefreshTicketers) require.NoError(t, err) - ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where my shoes", "123", nil) + ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where my shoes", "123", nil) modelTicket1 := ticket1.Load(db) - ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Old Problem", "Where my pants", "234", testdata.Agent) + ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Where my pants", "234", testdata.Agent) modelTicket2 := ticket2.Load(db) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Ignore", "", "", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "", "", nil) evts, err := models.TicketsAddNote(ctx, db, oa, testdata.Admin.ID, []*models.Ticket{modelTicket1, modelTicket2}, "spam") require.NoError(t, err) @@ -246,16 +242,16 @@ func TestTicketsChangeTopic(t *testing.T) { oa, err := models.GetOrgAssetsWithRefresh(ctx, db, testdata.Org1.ID, models.RefreshTicketers) require.NoError(t, err) - ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.SalesTopic, "Problem", "Where my shoes", "123", nil) + ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.SalesTopic, "Where my shoes", "123", nil) modelTicket1 := ticket1.Load(db) - ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.SupportTopic, "Old Problem", "Where my pants", "234", nil) + ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.SupportTopic, "Where my pants", "234", nil) modelTicket2 := ticket2.Load(db) - ticket3 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "", "Where my pants", "345", nil) + ticket3 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Where my pants", "345", nil) modelTicket3 := ticket3.Load(db) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Ignore", "", "", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "", "", nil) evts, err := models.TicketsChangeTopic(ctx, db, oa, testdata.Admin.ID, []*models.Ticket{modelTicket1, modelTicket2, modelTicket3}, testdata.SupportTopic.ID) require.NoError(t, err) @@ -286,10 +282,10 @@ func TestCloseTickets(t *testing.T) { oa, err := models.GetOrgAssetsWithRefresh(ctx, db, testdata.Org1.ID, models.RefreshTicketers) require.NoError(t, err) - ticket1 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where my shoes", "123", nil) + ticket1 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where my shoes", "123", nil) modelTicket1 := ticket1.Load(db) - ticket2 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Old Problem", "Where my pants", "234", nil) + ticket2 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Where my pants", "234", nil) modelTicket2 := ticket2.Load(db) logger := &models.HTTPLogger{} @@ -314,7 +310,7 @@ func TestCloseTickets(t *testing.T) { testsuite.AssertQuery(t, db, `SELECT count(*) FROM tickets_ticketevent WHERE ticket_id = $1 AND event_type = 'C'`, ticket2.ID).Returns(0) // can close tickets without a user - ticket3 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where my shoes", "123", nil) + ticket3 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where my shoes", "123", nil) modelTicket3 := ticket3.Load(db) evts, err = models.CloseTickets(ctx, db, oa, models.NilUserID, []*models.Ticket{modelTicket3}, false, false, logger) @@ -343,10 +339,10 @@ func TestReopenTickets(t *testing.T) { oa, err := models.GetOrgAssetsWithRefresh(ctx, db, testdata.Org1.ID, models.RefreshTicketers) require.NoError(t, err) - ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where my shoes", "123", nil) + ticket1 := testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where my shoes", "123", nil) modelTicket1 := ticket1.Load(db) - ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Old Problem", "Where my pants", "234", nil) + ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Where my pants", "234", nil) modelTicket2 := ticket2.Load(db) logger := &models.HTTPLogger{} diff --git a/core/tasks/broadcasts/worker_test.go b/core/tasks/broadcasts/worker_test.go index db33ad52a..a5d30af51 100644 --- a/core/tasks/broadcasts/worker_test.go +++ b/core/tasks/broadcasts/worker_test.go @@ -129,7 +129,7 @@ func TestBroadcastTask(t *testing.T) { // insert a broadcast so we can check it is being set to sent legacyID := testdata.InsertBroadcast(db, testdata.Org1, "base", map[envs.Language]string{"base": "hi @(PROPER(contact.name)) legacy"}, models.NilScheduleID, nil, nil) - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "", "", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "", "", nil) modelTicket := ticket.Load(db) evaluated := map[envs.Language]*models.BroadcastTranslation{ diff --git a/core/tasks/handler/handler_test.go b/core/tasks/handler/handler_test.go index a6c6f12ca..97ccd5146 100644 --- a/core/tasks/handler/handler_test.go +++ b/core/tasks/handler/handler_test.go @@ -34,16 +34,16 @@ func TestMsgEvents(t *testing.T) { // give Cathy and Bob some tickets... openTickets := map[*testdata.Contact][]*testdata.Ticket{ testdata.Cathy: { - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Hi there", "Ok", "", nil), - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Hi again", "Ok", "", nil), + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Ok", "", nil), + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Ok", "", nil), }, } closedTickets := map[*testdata.Contact][]*testdata.Ticket{ testdata.Cathy: { - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Old", "", "", nil), + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "", "", nil), }, testdata.Bob: { - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Bob, testdata.Mailgun, testdata.DefaultTopic, "Hi there", "Ok", "", nil), + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Bob, testdata.Mailgun, testdata.DefaultTopic, "Ok", "", nil), }, } @@ -309,7 +309,7 @@ func TestTicketEvents(t *testing.T) { // add a ticket closed trigger testdata.InsertTicketClosedTrigger(rt.DB, testdata.Org1, testdata.Favorites) - ticket := testdata.InsertClosedTicket(rt.DB, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Problem", "Where are my shoes?", "", nil) + ticket := testdata.InsertClosedTicket(rt.DB, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Where are my shoes?", "", nil) modelTicket := ticket.Load(db) event := models.NewTicketClosedEvent(modelTicket, testdata.Admin.ID) diff --git a/go.mod b/go.mod index c77da6b86..9e95dd71e 100644 --- a/go.mod +++ b/go.mod @@ -18,8 +18,8 @@ require ( github.com/lib/pq v1.4.0 github.com/mattn/go-sqlite3 v1.10.0 // indirect github.com/nyaruka/ezconf v0.2.1 - github.com/nyaruka/gocommon v1.13.2 - github.com/nyaruka/goflow v0.133.1 + github.com/nyaruka/gocommon v1.14.0 + github.com/nyaruka/goflow v0.135.0 github.com/nyaruka/librato v1.0.0 github.com/nyaruka/logrus_sentry v0.8.2-0.20190129182604-c2962b80ba7d github.com/nyaruka/null v1.2.0 diff --git a/go.sum b/go.sum index 9ff4a4cda..0f73301f1 100644 --- a/go.sum +++ b/go.sum @@ -132,10 +132,10 @@ github.com/naoina/toml v0.1.1 h1:PT/lllxVVN0gzzSqSlHEmP8MJB4MY2U7STGxiouV4X8= github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/nyaruka/ezconf v0.2.1 h1:TDXWoqjqYya1uhou1mAJZg7rgFYL98EB0Tb3+BWtUh0= github.com/nyaruka/ezconf v0.2.1/go.mod h1:ey182kYkw2MIi4XiWe1FR/mzI33WCmTWuceDYYxgnQw= -github.com/nyaruka/gocommon v1.13.2 h1:dNe8nGDSeECC7zL6H/0vmx9yp6UG8HJFxjKcIQmiccY= -github.com/nyaruka/gocommon v1.13.2/go.mod h1:2DWgWcjsfdU/+29xEP75G9xnorxvrxxe1pSISzUcSgw= -github.com/nyaruka/goflow v0.133.1 h1:Q7+X3BpkBNHBkO48tK02Sa5eXKHKz0Wan9GkXMh8TTI= -github.com/nyaruka/goflow v0.133.1/go.mod h1:zD+hVUIhyhT5gH6sayKgA21gxlhdFdYslZgK+LrpuHc= +github.com/nyaruka/gocommon v1.14.0 h1:sZ0rsKy52GAHfEB6H74thj0cf7VIW9uRYpuFBe1iJ9Q= +github.com/nyaruka/gocommon v1.14.0/go.mod h1:J0BvHSsj8gjMp0oPW+PEb4x25oStupkNpHm7Y5OfNPo= +github.com/nyaruka/goflow v0.135.0 h1:CPrhJh1e2hLKJu4q9ae3oHJUtWi53hnheLC0bC7FBZA= +github.com/nyaruka/goflow v0.135.0/go.mod h1:kqvs8GzFkLjogLqLmNJmpuvEHFvlKsALlDWgC25AtGk= github.com/nyaruka/librato v1.0.0 h1:Vznj9WCeC1yZXbBYyYp40KnbmXLbEkjKmHesV/v2SR0= github.com/nyaruka/librato v1.0.0/go.mod h1:pkRNLFhFurOz0QqBz6/DuTFhHHxAubWxs4Jx+J7yUgg= github.com/nyaruka/logrus_sentry v0.8.2-0.20190129182604-c2962b80ba7d h1:hyp9u36KIwbTCo2JAJ+TuJcJBc+UZzEig7RI/S5Dvkc= diff --git a/services/tickets/intern/service.go b/services/tickets/intern/service.go index 85d01f0a4..e44709e78 100644 --- a/services/tickets/intern/service.go +++ b/services/tickets/intern/service.go @@ -28,8 +28,8 @@ func NewService(rtCfg *config.Config, httpClient *http.Client, httpRetries *http } // Open just returns a new ticket - no external service to notify -func (s *service) Open(session flows.Session, topic *flows.Topic, subject, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { - return flows.OpenTicket(s.ticketer, topic, subject, body, assignee), nil +func (s *service) Open(session flows.Session, topic *flows.Topic, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { + return flows.OpenTicket(s.ticketer, topic, body, assignee), nil } // Forward is a noop diff --git a/services/tickets/intern/service_test.go b/services/tickets/intern/service_test.go index 40614ba31..118e477f0 100644 --- a/services/tickets/intern/service_test.go +++ b/services/tickets/intern/service_test.go @@ -6,7 +6,7 @@ import ( "github.com/nyaruka/gocommon/uuids" "github.com/nyaruka/goflow/assets" - "github.com/nyaruka/goflow/assets/static/types" + "github.com/nyaruka/goflow/assets/static" "github.com/nyaruka/goflow/envs" "github.com/nyaruka/goflow/flows" "github.com/nyaruka/goflow/test" @@ -21,7 +21,7 @@ import ( ) func TestOpenAndForward(t *testing.T) { - _, rt, _, _ := testsuite.Get() + ctx, rt, _, _ := testsuite.Get() session, _, err := test.CreateTestSession("", envs.RedactionPolicyNone) require.NoError(t, err) @@ -29,7 +29,7 @@ func TestOpenAndForward(t *testing.T) { defer uuids.SetGenerator(uuids.DefaultGenerator) uuids.SetGenerator(uuids.NewSeededGenerator(12345)) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "internal")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "internal")) svc, err := intern.NewService( rt.Config, @@ -42,15 +42,19 @@ func TestOpenAndForward(t *testing.T) { logger := &flows.HTTPLogger{} - ticket, err := svc.Open(session, nil, "Need help", "Where are my cookies?", nil, logger.Log) + oa, err := models.GetOrgAssets(ctx, rt.DB, testdata.Org1.ID) + require.NoError(t, err) + defaultTopic := oa.SessionAssets().Topics().FindByName("General") + + ticket, err := svc.Open(session, defaultTopic, "Where are my cookies?", nil, logger.Log) assert.NoError(t, err) assert.Equal(t, flows.TicketUUID("e7187099-7d38-4f60-955c-325957214c42"), ticket.UUID()) - assert.Equal(t, "Need help", ticket.Subject()) + assert.Equal(t, "General", ticket.Topic().Name()) assert.Equal(t, "Where are my cookies?", ticket.Body()) assert.Equal(t, "", ticket.ExternalID()) assert.Equal(t, 0, len(logger.Logs)) - dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.Internal.ID, "", testdata.DefaultTopic.ID, "Need help", "Where are my cookies?", models.NilUserID, nil) + dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.Internal.ID, "", testdata.DefaultTopic.ID, "Where are my cookies?", models.NilUserID, nil) logger = &flows.HTTPLogger{} err = svc.Forward( @@ -72,13 +76,13 @@ func TestCloseAndReopen(t *testing.T) { defer uuids.SetGenerator(uuids.DefaultGenerator) uuids.SetGenerator(uuids.NewSeededGenerator(12345)) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "internal")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "internal")) svc, err := intern.NewService(rt.Config, http.DefaultClient, nil, ticketer, nil) require.NoError(t, err) logger := &flows.HTTPLogger{} - ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.Internal.ID, "12", testdata.DefaultTopic.ID, "New ticket", "Where my cookies?", models.NilUserID, nil) - ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.Internal.ID, "14", testdata.DefaultTopic.ID, "Second ticket", "Where my shoes?", models.NilUserID, nil) + ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.Internal.ID, "12", testdata.DefaultTopic.ID, "Where my cookies?", models.NilUserID, nil) + ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.Internal.ID, "14", testdata.DefaultTopic.ID, "Where my shoes?", models.NilUserID, nil) err = svc.Close([]*models.Ticket{ticket1, ticket2}, logger.Log) diff --git a/services/tickets/mailgun/service.go b/services/tickets/mailgun/service.go index f32ce4a28..09117d3fc 100644 --- a/services/tickets/mailgun/service.go +++ b/services/tickets/mailgun/service.go @@ -107,19 +107,15 @@ func NewService(rtCfg *config.Config, httpClient *http.Client, httpRetries *http } // Open opens a ticket which for mailgun means just sending an initial email -func (s *service) Open(session flows.Session, topic *flows.Topic, subject, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { - ticket := flows.OpenTicket(s.ticketer, topic, subject, body, assignee) +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) contactDisplay := tickets.GetContactDisplay(session.Environment(), session.Contact()) - if topic != nil { - subject = topic.Name() - } - from := s.ticketAddress(contactDisplay, ticket.UUID()) - context := s.templateContext(subject, body, "", string(session.Contact().UUID()), contactDisplay) + context := s.templateContext(body, "", string(session.Contact().UUID()), contactDisplay) fullBody := evaluateTemplate(openBodyTemplate, context) - msgID, trace, err := s.client.SendMessage(from, s.toAddress, subject, fullBody, nil, nil) + msgID, trace, err := s.client.SendMessage(from, s.toAddress, subjectFromBody(body), fullBody, nil, nil) if trace != nil { logHTTP(flows.NewHTTPLog(trace, flows.HTTPStatusFromCode, s.redactor)) } @@ -132,7 +128,7 @@ func (s *service) Open(session flows.Session, topic *flows.Topic, subject, body } func (s *service) Forward(ticket *models.Ticket, msgUUID flows.MsgUUID, text string, attachments []utils.Attachment, logHTTP flows.HTTPLogCallback) error { - context := s.templateContext(ticket.Subject(), ticket.Body(), text, ticket.Config(ticketConfigContactUUID), ticket.Config(ticketConfigContactDisplay)) + context := s.templateContext(ticket.Body(), text, ticket.Config(ticketConfigContactUUID), ticket.Config(ticketConfigContactDisplay)) body := evaluateTemplate(forwardBodyTemplate, context) _, err := s.sendInTicket(ticket, body, attachments, logHTTP) @@ -141,7 +137,7 @@ func (s *service) Forward(ticket *models.Ticket, msgUUID flows.MsgUUID, text str func (s *service) Close(tickets []*models.Ticket, logHTTP flows.HTTPLogCallback) error { for _, ticket := range tickets { - context := s.templateContext(ticket.Subject(), ticket.Body(), "", ticket.Config(ticketConfigContactUUID), ticket.Config(ticketConfigContactDisplay)) + context := s.templateContext(ticket.Body(), "", ticket.Config(ticketConfigContactUUID), ticket.Config(ticketConfigContactDisplay)) body := evaluateTemplate(closedBodyTemplate, context) _, err := s.sendInTicket(ticket, body, nil, logHTTP) @@ -154,7 +150,7 @@ func (s *service) Close(tickets []*models.Ticket, logHTTP flows.HTTPLogCallback) func (s *service) Reopen(tickets []*models.Ticket, logHTTP flows.HTTPLogCallback) error { for _, ticket := range tickets { - context := s.templateContext(ticket.Subject(), ticket.Body(), "", ticket.Config(ticketConfigContactUUID), ticket.Config(ticketConfigContactDisplay)) + context := s.templateContext(ticket.Body(), "", ticket.Config(ticketConfigContactUUID), ticket.Config(ticketConfigContactDisplay)) body := evaluateTemplate(reopenedBodyTemplate, context) _, err := s.sendInTicket(ticket, body, nil, logHTTP) @@ -178,7 +174,7 @@ func (s *service) sendInTicket(ticket *models.Ticket, text string, attachments [ } from := s.ticketAddress(contactDisplay, ticket.UUID()) - return s.send(from, s.toAddress, ticket.Subject(), text, attachments, headers, logHTTP) + return s.send(from, s.toAddress, subjectFromBody(ticket.Body()), text, attachments, headers, logHTTP) } func (s *service) send(from, to, subject, text string, attachments []utils.Attachment, headers map[string]string, logHTTP flows.HTTPLogCallback) (string, error) { @@ -212,10 +208,10 @@ func (s *service) noReplyAddress() string { return fmt.Sprintf("no-reply@%s", s.client.domain) } -func (s *service) templateContext(subject, body, message, contactUUID, contactDisplay string) map[string]string { +func (s *service) templateContext(body, message, contactUUID, contactDisplay string) map[string]string { return map[string]string{ "brand": s.brandName, // rapidpro brand - "subject": subject, // original ticket subject + "subject": subjectFromBody(body), // portion of body used as subject "body": body, // original ticket body "message": message, // new message if this is a forward "contact": contactDisplay, // display name contact @@ -232,3 +228,7 @@ func evaluateTemplate(t *template.Template, c map[string]string) string { t.Execute(b, c) return b.String() } + +func subjectFromBody(body string) string { + return utils.Truncate(strings.ReplaceAll(body, "\n", ""), 64) +} diff --git a/services/tickets/mailgun/service_test.go b/services/tickets/mailgun/service_test.go index ef162cfa1..573742fb2 100644 --- a/services/tickets/mailgun/service_test.go +++ b/services/tickets/mailgun/service_test.go @@ -9,7 +9,7 @@ import ( "github.com/nyaruka/gocommon/httpx" "github.com/nyaruka/gocommon/uuids" "github.com/nyaruka/goflow/assets" - "github.com/nyaruka/goflow/assets/static/types" + "github.com/nyaruka/goflow/assets/static" "github.com/nyaruka/goflow/envs" "github.com/nyaruka/goflow/flows" "github.com/nyaruka/goflow/test" @@ -24,7 +24,7 @@ import ( ) func TestOpenAndForward(t *testing.T) { - _, rt, _, _ := testsuite.Get() + ctx, rt, _, _ := testsuite.Get() session, _, err := test.CreateTestSession("", envs.RedactionPolicyNone) require.NoError(t, err) @@ -52,7 +52,7 @@ func TestOpenAndForward(t *testing.T) { }, })) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "mailgun")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "mailgun")) _, err = mailgun.NewService( rt.Config, @@ -80,21 +80,25 @@ func TestOpenAndForward(t *testing.T) { logger := &flows.HTTPLogger{} - _, err = svc.Open(session, nil, "Need help", "Where are my cookies?", nil, logger.Log) + oa, err := models.GetOrgAssets(ctx, rt.DB, testdata.Org1.ID) + require.NoError(t, err) + defaultTopic := oa.SessionAssets().Topics().FindByName("General") + + _, err = svc.Open(session, defaultTopic, "Where are my cookies?", nil, logger.Log) assert.EqualError(t, err, "error calling mailgun API: unable to connect to server") logger = &flows.HTTPLogger{} - ticket, err := svc.Open(session, nil, "Need help", "Where are my cookies?", nil, logger.Log) + ticket, err := svc.Open(session, defaultTopic, "Where are my cookies? Where are my cookies? Where are my cookies? Where are my cookies? Where are my cookies?", nil, logger.Log) assert.NoError(t, err) assert.Equal(t, flows.TicketUUID("9688d21d-95aa-4bed-afc7-f31b35731a3d"), ticket.UUID()) - assert.Equal(t, "Need help", ticket.Subject()) - assert.Equal(t, "Where are my cookies?", ticket.Body()) + assert.Equal(t, "General", ticket.Topic().Name()) + assert.Equal(t, "Where are my cookies? Where are my cookies? Where are my cookies? Where are my cookies? Where are my cookies?", ticket.Body()) assert.Equal(t, "<20200426161758.1.590432020254B2BF@tickets.rapidpro.io>", ticket.ExternalID()) assert.Equal(t, 1, len(logger.Logs)) test.AssertSnapshot(t, "open_ticket", logger.Logs[0].Request) - dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.Mailgun.ID, "", testdata.DefaultTopic.ID, "Need help", "Where are my cookies?", models.NilUserID, map[string]interface{}{ + dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.Mailgun.ID, "", testdata.DefaultTopic.ID, "Where are my cookies?", models.NilUserID, map[string]interface{}{ "contact-uuid": string(testdata.Cathy.UUID), "contact-display": "Cathy", }) @@ -137,7 +141,7 @@ func TestCloseAndReopen(t *testing.T) { }, })) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "mailgun")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "mailgun")) svc, err := mailgun.NewService( rt.Config, http.DefaultClient, @@ -154,8 +158,8 @@ func TestCloseAndReopen(t *testing.T) { require.NoError(t, err) logger := &flows.HTTPLogger{} - ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.Zendesk.ID, "12", testdata.DefaultTopic.ID, "New ticket", "Where my cookies?", models.NilUserID, nil) - ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.Zendesk.ID, "14", testdata.DefaultTopic.ID, "Second ticket", "Where my shoes?", models.NilUserID, nil) + ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.Zendesk.ID, "12", testdata.DefaultTopic.ID, "Where my cookies?", models.NilUserID, nil) + ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.Zendesk.ID, "14", testdata.DefaultTopic.ID, "Where my shoes?", models.NilUserID, nil) err = svc.Close([]*models.Ticket{ticket1, ticket2}, logger.Log) diff --git a/services/tickets/mailgun/testdata/TestCloseAndReopen_close_tickets.snap b/services/tickets/mailgun/testdata/TestCloseAndReopen_close_tickets.snap index 2e3eae820..a2468656e 100644 --- a/services/tickets/mailgun/testdata/TestCloseAndReopen_close_tickets.snap +++ b/services/tickets/mailgun/testdata/TestCloseAndReopen_close_tickets.snap @@ -1,7 +1,7 @@ POST /v3/tickets.rapidpro.io/messages HTTP/1.1 Host: api.mailgun.net User-Agent: Go-http-client/1.1 -Content-Length: 832 +Content-Length: 839 Authorization: Basic **************** Content-Type: multipart/form-data; boundary=e7187099-7d38-4f60-955c-325957214c42 Accept-Encoding: gzip @@ -17,7 +17,7 @@ bob@acme.com --e7187099-7d38-4f60-955c-325957214c42 Content-Disposition: form-data; name="subject" -New ticket +Where my cookies? --e7187099-7d38-4f60-955c-325957214c42 Content-Disposition: form-data; name="text" diff --git a/services/tickets/mailgun/testdata/TestCloseAndReopen_reopen_tickets.snap b/services/tickets/mailgun/testdata/TestCloseAndReopen_reopen_tickets.snap index a5ffa3196..bdc39eb3c 100644 --- a/services/tickets/mailgun/testdata/TestCloseAndReopen_reopen_tickets.snap +++ b/services/tickets/mailgun/testdata/TestCloseAndReopen_reopen_tickets.snap @@ -1,7 +1,7 @@ POST /v3/tickets.rapidpro.io/messages HTTP/1.1 Host: api.mailgun.net User-Agent: Go-http-client/1.1 -Content-Length: 835 +Content-Length: 837 Authorization: Basic **************** Content-Type: multipart/form-data; boundary=59d74b86-3e2f-4a93-aece-b05d2fdcde0c Accept-Encoding: gzip @@ -17,7 +17,7 @@ bob@acme.com --59d74b86-3e2f-4a93-aece-b05d2fdcde0c Content-Disposition: form-data; name="subject" -Second ticket +Where my shoes? --59d74b86-3e2f-4a93-aece-b05d2fdcde0c Content-Disposition: form-data; name="text" diff --git a/services/tickets/mailgun/testdata/TestOpenAndForward_forward_message.snap b/services/tickets/mailgun/testdata/TestOpenAndForward_forward_message.snap index 4bae135ad..e65f2b108 100644 --- a/services/tickets/mailgun/testdata/TestOpenAndForward_forward_message.snap +++ b/services/tickets/mailgun/testdata/TestOpenAndForward_forward_message.snap @@ -1,7 +1,7 @@ POST /v3/tickets.rapidpro.io/messages HTTP/1.1 Host: api.mailgun.net User-Agent: Go-http-client/1.1 -Content-Length: 1159 +Content-Length: 1171 Authorization: Basic **************** Content-Type: multipart/form-data; boundary=13e96d5a-4e65-4f07-9189-9d6270c6f3c0 Accept-Encoding: gzip @@ -17,7 +17,7 @@ bob@acme.com --13e96d5a-4e65-4f07-9189-9d6270c6f3c0 Content-Disposition: form-data; name="subject" -Need help +Where are my cookies? --13e96d5a-4e65-4f07-9189-9d6270c6f3c0 Content-Disposition: form-data; name="text" diff --git a/services/tickets/mailgun/testdata/TestOpenAndForward_open_ticket.snap b/services/tickets/mailgun/testdata/TestOpenAndForward_open_ticket.snap index 4a0e2f732..a28149086 100644 --- a/services/tickets/mailgun/testdata/TestOpenAndForward_open_ticket.snap +++ b/services/tickets/mailgun/testdata/TestOpenAndForward_open_ticket.snap @@ -1,7 +1,7 @@ POST /v3/tickets.rapidpro.io/messages HTTP/1.1 Host: api.mailgun.net User-Agent: Go-http-client/1.1 -Content-Length: 834 +Content-Length: 977 Authorization: Basic **************** Content-Type: multipart/form-data; boundary=297611a6-b583-45c3-8587-d4e530c948f0 Accept-Encoding: gzip @@ -17,14 +17,14 @@ bob@acme.com --297611a6-b583-45c3-8587-d4e530c948f0 Content-Disposition: form-data; name="subject" -Need help +Where are my cookies? Where are my cookies? Where are my cookies --297611a6-b583-45c3-8587-d4e530c948f0 Content-Disposition: form-data; name="text" New ticket opened ------------------------------------------------ -Where are my cookies? +Where are my cookies? Where are my cookies? Where are my cookies? Where are my cookies? Where are my cookies? ------------------------------------------------ * Reply to the contact by replying to this email diff --git a/services/tickets/mailgun/web_test.go b/services/tickets/mailgun/web_test.go index 4113ae873..d7d1b136c 100644 --- a/services/tickets/mailgun/web_test.go +++ b/services/tickets/mailgun/web_test.go @@ -14,7 +14,7 @@ func TestReceive(t *testing.T) { defer testsuite.ResetData(db) // create a mailgun ticket for Cathy - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Have you seen my cookies?", "", nil) web.RunWebTests(t, "testdata/receive.json", map[string]string{"cathy_ticket_uuid": string(ticket.UUID)}) } diff --git a/services/tickets/rocketchat/service.go b/services/tickets/rocketchat/service.go index a8f096c17..85180ec71 100644 --- a/services/tickets/rocketchat/service.go +++ b/services/tickets/rocketchat/service.go @@ -51,8 +51,8 @@ func NewService(rtCfg *config.Config, httpClient *http.Client, httpRetries *http type VisitorToken models.ContactID // Open opens a ticket which for RocketChat means open a room associated to a visitor user -func (s *service) Open(session flows.Session, topic *flows.Topic, subject, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { - ticket := flows.OpenTicket(s.ticketer, topic, subject, body, assignee) +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() email := "" phone := "" diff --git a/services/tickets/rocketchat/service_test.go b/services/tickets/rocketchat/service_test.go index dd3100555..d36990b96 100644 --- a/services/tickets/rocketchat/service_test.go +++ b/services/tickets/rocketchat/service_test.go @@ -9,7 +9,7 @@ import ( "github.com/nyaruka/gocommon/httpx" "github.com/nyaruka/gocommon/uuids" "github.com/nyaruka/goflow/assets" - "github.com/nyaruka/goflow/assets/static/types" + "github.com/nyaruka/goflow/assets/static" "github.com/nyaruka/goflow/envs" "github.com/nyaruka/goflow/flows" "github.com/nyaruka/goflow/test" @@ -24,7 +24,7 @@ import ( ) func TestOpenAndForward(t *testing.T) { - _, rt, _, _ := testsuite.Get() + ctx, rt, _, _ := testsuite.Get() defer dates.SetNowSource(dates.DefaultNowSource) dates.SetNowSource(dates.NewSequentialNowSource(time.Date(2019, 10, 7, 15, 21, 30, 0, time.UTC))) @@ -47,7 +47,7 @@ func TestOpenAndForward(t *testing.T) { }, })) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "rocketchat")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "rocketchat")) _, err = rocketchat.NewService( rt.Config, @@ -70,21 +70,25 @@ func TestOpenAndForward(t *testing.T) { ) assert.NoError(t, err) + oa, err := models.GetOrgAssets(ctx, rt.DB, testdata.Org1.ID) + require.NoError(t, err) + defaultTopic := oa.SessionAssets().Topics().FindByName("General") + logger := &flows.HTTPLogger{} - _, err = svc.Open(session, nil, "Need help", "Where are my cookies?", nil, logger.Log) + _, err = svc.Open(session, defaultTopic, "Where are my cookies?", nil, logger.Log) assert.EqualError(t, err, "error calling RocketChat: unable to connect to server") logger = &flows.HTTPLogger{} - ticket, err := svc.Open(session, nil, "Need help", "Where are my cookies?", nil, logger.Log) + ticket, err := svc.Open(session, defaultTopic, "Where are my cookies?", nil, logger.Log) assert.NoError(t, err) assert.Equal(t, flows.TicketUUID("59d74b86-3e2f-4a93-aece-b05d2fdcde0c"), ticket.UUID()) - assert.Equal(t, "Need help", ticket.Subject()) + assert.Equal(t, "General", ticket.Topic().Name()) assert.Equal(t, "Where are my cookies?", ticket.Body()) assert.Equal(t, "uiF7ybjsv7PSJGSw6", ticket.ExternalID()) assert.Equal(t, 1, len(logger.Logs)) test.AssertSnapshot(t, "open_ticket", logger.Logs[0].Request) - dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.RocketChat.ID, "", testdata.DefaultTopic.ID, "Need help", "Where are my cookies?", models.NilUserID, map[string]interface{}{ + dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.RocketChat.ID, "", testdata.DefaultTopic.ID, "Where are my cookies?", models.NilUserID, map[string]interface{}{ "contact-uuid": string(testdata.Cathy.UUID), "contact-display": "Cathy", }) @@ -119,7 +123,7 @@ func TestCloseAndReopen(t *testing.T) { }, })) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "rocketchat")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "rocketchat")) svc, err := rocketchat.NewService( rt.Config, http.DefaultClient, @@ -132,8 +136,8 @@ func TestCloseAndReopen(t *testing.T) { ) require.NoError(t, err) - ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.RocketChat.ID, "X5gwXeaxbnGDaq8Q3", testdata.DefaultTopic.ID, "New ticket", "Where my cookies?", models.NilUserID, nil) - ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.RocketChat.ID, "cq7AokJHKkGhAMoBK", testdata.DefaultTopic.ID, "Second ticket", "Where my shoes?", models.NilUserID, nil) + ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.RocketChat.ID, "X5gwXeaxbnGDaq8Q3", testdata.DefaultTopic.ID, "Where my cookies?", models.NilUserID, nil) + ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.RocketChat.ID, "cq7AokJHKkGhAMoBK", testdata.DefaultTopic.ID, "Where my shoes?", models.NilUserID, nil) logger := &flows.HTTPLogger{} err = svc.Close([]*models.Ticket{ticket1, ticket2}, logger.Log) diff --git a/services/tickets/rocketchat/web_test.go b/services/tickets/rocketchat/web_test.go index 9979c64a1..ee423f5b7 100644 --- a/services/tickets/rocketchat/web_test.go +++ b/services/tickets/rocketchat/web_test.go @@ -13,7 +13,7 @@ func TestEventCallback(t *testing.T) { db := testsuite.DB() // create a rocketchat ticket for Cathy - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.RocketChat, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "1234", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.RocketChat, testdata.DefaultTopic, "Have you seen my cookies?", "1234", nil) web.RunWebTests(t, "testdata/event_callback.json", map[string]string{"cathy_ticket_uuid": string(ticket.UUID)}) } diff --git a/services/tickets/utils_test.go b/services/tickets/utils_test.go index 0e9145b63..ce87ca199 100644 --- a/services/tickets/utils_test.go +++ b/services/tickets/utils_test.go @@ -52,8 +52,8 @@ func TestFromTicketUUID(t *testing.T) { defer testsuite.Reset() // create some tickets - ticket1 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "", nil) - ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Need help", "Have you seen my shoes?", "", nil) + ticket1 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Have you seen my cookies?", "", nil) + ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my shoes?", "", nil) // break mailgun configuration db.MustExec(`UPDATE tickets_ticketer SET config = '{"foo":"bar"}'::jsonb WHERE id = $1`, testdata.Mailgun.ID) @@ -130,7 +130,7 @@ func TestSendReply(t *testing.T) { image := &tickets.File{URL: "http://coolfiles.com/a.jpg", ContentType: "image/jpeg", Body: imageBody} // create a ticket - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Have you seen my cookies?", "", nil) modelTicket := ticket.Load(db) msg, err := tickets.SendReply(ctx, rt, modelTicket, "I'll get back to you", []*tickets.File{image}) @@ -173,7 +173,6 @@ func TestCloseTicket(t *testing.T) { testdata.Mailgun.ID, "EX12345", testdata.DefaultTopic.ID, - "", "Where are my cookies?", models.NilUserID, map[string]interface{}{ diff --git a/services/tickets/zendesk/service.go b/services/tickets/zendesk/service.go index 2af3126bb..03517d0a7 100644 --- a/services/tickets/zendesk/service.go +++ b/services/tickets/zendesk/service.go @@ -75,8 +75,8 @@ func NewService(rtCfg *config.Config, httpClient *http.Client, httpRetries *http } // Open opens a ticket which for mailgun means just sending an initial email -func (s *service) Open(session flows.Session, topic *flows.Topic, subject, body string, assignee *flows.User, logHTTP flows.HTTPLogCallback) (*flows.Ticket, error) { - ticket := flows.OpenTicket(s.ticketer, topic, subject, body, assignee) +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) contactDisplay := session.Contact().Format(session.Environment()) msg := &ExternalResource{ diff --git a/services/tickets/zendesk/service_test.go b/services/tickets/zendesk/service_test.go index 966b63caf..c17a1ab42 100644 --- a/services/tickets/zendesk/service_test.go +++ b/services/tickets/zendesk/service_test.go @@ -9,7 +9,7 @@ import ( "github.com/nyaruka/gocommon/httpx" "github.com/nyaruka/gocommon/uuids" "github.com/nyaruka/goflow/assets" - "github.com/nyaruka/goflow/assets/static/types" + "github.com/nyaruka/goflow/assets/static" "github.com/nyaruka/goflow/envs" "github.com/nyaruka/goflow/flows" "github.com/nyaruka/goflow/test" @@ -24,7 +24,7 @@ import ( ) func TestOpenAndForward(t *testing.T) { - _, rt, _, _ := testsuite.Get() + ctx, rt, _, _ := testsuite.Get() session, _, err := test.CreateTestSession("", envs.RedactionPolicyNone) require.NoError(t, err) @@ -57,7 +57,7 @@ func TestOpenAndForward(t *testing.T) { }, })) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "zendesk")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "zendesk")) _, err = zendesk.NewService( rt.Config, @@ -85,22 +85,26 @@ func TestOpenAndForward(t *testing.T) { logger := &flows.HTTPLogger{} + oa, err := models.GetOrgAssets(ctx, rt.DB, testdata.Org1.ID) + require.NoError(t, err) + defaultTopic := oa.SessionAssets().Topics().FindByName("General") + // try with connection failure - _, err = svc.Open(session, nil, "Need help", "Where are my cookies?", nil, logger.Log) + _, err = svc.Open(session, defaultTopic, "Where are my cookies?", nil, logger.Log) assert.EqualError(t, err, "error pushing message to zendesk: unable to connect to server") logger = &flows.HTTPLogger{} - ticket, err := svc.Open(session, nil, "Need help", "Where are my cookies?", nil, logger.Log) + ticket, err := svc.Open(session, defaultTopic, "Where are my cookies?", nil, logger.Log) assert.NoError(t, err) assert.Equal(t, flows.TicketUUID("59d74b86-3e2f-4a93-aece-b05d2fdcde0c"), ticket.UUID()) - assert.Equal(t, "Need help", ticket.Subject()) + assert.Equal(t, "General", ticket.Topic().Name()) assert.Equal(t, "Where are my cookies?", ticket.Body()) assert.Equal(t, "", ticket.ExternalID()) assert.Equal(t, 1, len(logger.Logs)) test.AssertSnapshot(t, "open_ticket", logger.Logs[0].Request) - dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.Zendesk.ID, "", testdata.DefaultTopic.ID, "Need help", "Where are my cookies?", models.NilUserID, map[string]interface{}{ + dbTicket := models.NewTicket(ticket.UUID(), testdata.Org1.ID, testdata.Cathy.ID, testdata.Zendesk.ID, "", testdata.DefaultTopic.ID, "Where are my cookies?", models.NilUserID, map[string]interface{}{ "contact-uuid": string(testdata.Cathy.UUID), "contact-display": "Cathy", }) @@ -144,7 +148,7 @@ func TestCloseAndReopen(t *testing.T) { }, })) - ticketer := flows.NewTicketer(types.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "zendesk")) + ticketer := flows.NewTicketer(static.NewTicketer(assets.TicketerUUID(uuids.New()), "Support", "zendesk")) svc, err := zendesk.NewService( rt.Config, http.DefaultClient, @@ -161,8 +165,8 @@ func TestCloseAndReopen(t *testing.T) { require.NoError(t, err) logger := &flows.HTTPLogger{} - ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.Zendesk.ID, "12", testdata.DefaultTopic.ID, "New ticket", "Where my cookies?", models.NilUserID, nil) - ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.Zendesk.ID, "14", testdata.DefaultTopic.ID, "Second ticket", "Where my shoes?", models.NilUserID, nil) + ticket1 := models.NewTicket("88bfa1dc-be33-45c2-b469-294ecb0eba90", testdata.Org1.ID, testdata.Cathy.ID, testdata.Zendesk.ID, "12", testdata.DefaultTopic.ID, "Where my cookies?", models.NilUserID, nil) + ticket2 := models.NewTicket("645eee60-7e84-4a9e-ade3-4fce01ae28f1", testdata.Org1.ID, testdata.Bob.ID, testdata.Zendesk.ID, "14", testdata.DefaultTopic.ID, "Where my shoes?", models.NilUserID, nil) err = svc.Close([]*models.Ticket{ticket1, ticket2}, logger.Log) diff --git a/services/tickets/zendesk/testdata/TestOpenAndForward_forward_message.snap b/services/tickets/zendesk/testdata/TestOpenAndForward_forward_message.snap index e8759ae66..6207acfcc 100644 --- a/services/tickets/zendesk/testdata/TestOpenAndForward_forward_message.snap +++ b/services/tickets/zendesk/testdata/TestOpenAndForward_forward_message.snap @@ -6,4 +6,4 @@ Authorization: Bearer **************** Content-Type: application/json Accept-Encoding: gzip -{"instance_push_id":"1234-abcd","request_id":"sesame:1570461699000000000","external_resources":[{"external_id":"ca5607f0-cba8-4c94-9cd5-c4fbc24aa767","message":"It's urgent","thread_id":"59d74b86-3e2f-4a93-aece-b05d2fdcde0c","created_at":"2019-10-07T15:21:38Z","author":{"external_id":"6393abc0-283d-4c9b-a1b3-641a035c34bf","name":"Cathy"},"allow_channelback":true,"file_urls":["file/0123/attachment1.jpg"]}]} \ No newline at end of file +{"instance_push_id":"1234-abcd","request_id":"sesame:1570461700000000000","external_resources":[{"external_id":"ca5607f0-cba8-4c94-9cd5-c4fbc24aa767","message":"It's urgent","thread_id":"59d74b86-3e2f-4a93-aece-b05d2fdcde0c","created_at":"2019-10-07T15:21:39Z","author":{"external_id":"6393abc0-283d-4c9b-a1b3-641a035c34bf","name":"Cathy"},"allow_channelback":true,"file_urls":["file/0123/attachment1.jpg"]}]} \ No newline at end of file diff --git a/services/tickets/zendesk/testdata/TestOpenAndForward_open_ticket.snap b/services/tickets/zendesk/testdata/TestOpenAndForward_open_ticket.snap index 537dce39e..c9c66feac 100644 --- a/services/tickets/zendesk/testdata/TestOpenAndForward_open_ticket.snap +++ b/services/tickets/zendesk/testdata/TestOpenAndForward_open_ticket.snap @@ -6,4 +6,4 @@ Authorization: Bearer **************** Content-Type: application/json Accept-Encoding: gzip -{"instance_push_id":"1234-abcd","request_id":"sesame:1570461695000000000","external_resources":[{"external_id":"59d74b86-3e2f-4a93-aece-b05d2fdcde0c","message":"Where are my cookies?","thread_id":"59d74b86-3e2f-4a93-aece-b05d2fdcde0c","created_at":"2019-10-07T15:21:34Z","author":{"external_id":"5d76d86b-3bb9-4d5a-b822-c9d86f5d8e4f","name":"Ryan Lewis"},"allow_channelback":true}]} \ No newline at end of file +{"instance_push_id":"1234-abcd","request_id":"sesame:1570461696000000000","external_resources":[{"external_id":"59d74b86-3e2f-4a93-aece-b05d2fdcde0c","message":"Where are my cookies?","thread_id":"59d74b86-3e2f-4a93-aece-b05d2fdcde0c","created_at":"2019-10-07T15:21:35Z","author":{"external_id":"5d76d86b-3bb9-4d5a-b822-c9d86f5d8e4f","name":"Ryan Lewis"},"allow_channelback":true}]} \ No newline at end of file diff --git a/services/tickets/zendesk/web_test.go b/services/tickets/zendesk/web_test.go index 4fe9015d9..8f9916889 100644 --- a/services/tickets/zendesk/web_test.go +++ b/services/tickets/zendesk/web_test.go @@ -14,7 +14,7 @@ func TestChannelback(t *testing.T) { defer testsuite.ResetData(db) // create a zendesk ticket for Cathy - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "1234", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "1234", nil) web.RunWebTests(t, "testdata/channelback.json", map[string]string{"cathy_ticket_uuid": string(ticket.UUID)}) } @@ -25,7 +25,7 @@ func TestEventCallback(t *testing.T) { defer testsuite.ResetData(db) // create a zendesk ticket for Cathy - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "1234", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "1234", nil) web.RunWebTests(t, "testdata/event_callback.json", map[string]string{"cathy_ticket_uuid": string(ticket.UUID)}) } @@ -36,7 +36,7 @@ func TestTarget(t *testing.T) { defer testsuite.ResetData(db) // create a zendesk ticket for Cathy - ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "1234", nil) + ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "1234", nil) web.RunWebTests(t, "testdata/target.json", map[string]string{"cathy_ticket_uuid": string(ticket.UUID)}) } diff --git a/testsuite/testdata/tickets.go b/testsuite/testdata/tickets.go index 76a2c1ae2..bf0bf0225 100644 --- a/testsuite/testdata/tickets.go +++ b/testsuite/testdata/tickets.go @@ -35,16 +35,16 @@ type Ticketer struct { } // InsertOpenTicket inserts an open ticket -func InsertOpenTicket(db *sqlx.DB, org *Org, contact *Contact, ticketer *Ticketer, topic *Topic, subject, body, externalID string, assignee *User) *Ticket { - return insertTicket(db, org, contact, ticketer, models.TicketStatusOpen, topic, subject, body, externalID, assignee) +func InsertOpenTicket(db *sqlx.DB, org *Org, contact *Contact, ticketer *Ticketer, topic *Topic, body, externalID string, assignee *User) *Ticket { + return insertTicket(db, org, contact, ticketer, models.TicketStatusOpen, topic, body, externalID, assignee) } // InsertClosedTicket inserts a closed ticket -func InsertClosedTicket(db *sqlx.DB, org *Org, contact *Contact, ticketer *Ticketer, topic *Topic, subject, body, externalID string, assignee *User) *Ticket { - return insertTicket(db, org, contact, ticketer, models.TicketStatusClosed, topic, subject, body, externalID, assignee) +func InsertClosedTicket(db *sqlx.DB, org *Org, contact *Contact, ticketer *Ticketer, topic *Topic, body, externalID string, assignee *User) *Ticket { + return insertTicket(db, org, contact, ticketer, models.TicketStatusClosed, topic, body, externalID, assignee) } -func insertTicket(db *sqlx.DB, org *Org, contact *Contact, ticketer *Ticketer, status models.TicketStatus, topic *Topic, subject, body, externalID string, assignee *User) *Ticket { +func insertTicket(db *sqlx.DB, org *Org, contact *Contact, ticketer *Ticketer, status models.TicketStatus, topic *Topic, body, externalID string, assignee *User) *Ticket { uuid := flows.TicketUUID(uuids.New()) var closedOn *time.Time if status == models.TicketStatusClosed { @@ -54,8 +54,8 @@ func insertTicket(db *sqlx.DB, org *Org, contact *Contact, ticketer *Ticketer, s var id models.TicketID must(db.Get(&id, - `INSERT INTO tickets_ticket(uuid, org_id, contact_id, ticketer_id, status, topic_id, subject, body, external_id, opened_on, modified_on, closed_on, last_activity_on, assignee_id) - VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), NOW(), $10, NOW(), $11) RETURNING id`, uuid, org.ID, contact.ID, ticketer.ID, status, topic.ID, subject, body, externalID, closedOn, assignee.SafeID(), + `INSERT INTO tickets_ticket(uuid, org_id, contact_id, ticketer_id, status, topic_id, body, external_id, opened_on, modified_on, closed_on, last_activity_on, assignee_id) + VALUES($1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW(), $9, NOW(), $10) RETURNING id`, uuid, org.ID, contact.ID, ticketer.ID, status, topic.ID, body, externalID, closedOn, assignee.SafeID(), )) return &Ticket{id, uuid} } diff --git a/utils/cron/cron.go b/utils/cron/cron.go index 6c9f68c5f..0b5b3d921 100644 --- a/utils/cron/cron.go +++ b/utils/cron/cron.go @@ -25,7 +25,7 @@ func StartCron(quit chan bool, rp *redis.Pool, name string, interval time.Durati log := logrus.WithField("cron", name).WithField("lockName", lockName) go func() { - defer log.Info("exiting") + defer log.Info("cron exiting") // we run expiration every minute on the minute for { @@ -64,7 +64,7 @@ func StartCron(quit chan bool, rp *redis.Pool, name string, interval time.Durati // calculate our next fire time nextFire := nextFire(lastFire, interval) - wait = nextFire.Sub(time.Now()) + wait = time.Until(nextFire) if wait < time.Duration(0) { wait = time.Duration(0) } diff --git a/web/simulation/simulation.go b/web/simulation/simulation.go index 4d6793a2c..de99fcfd8 100644 --- a/web/simulation/simulation.go +++ b/web/simulation/simulation.go @@ -7,7 +7,7 @@ import ( "github.com/nyaruka/gocommon/urns" "github.com/nyaruka/goflow/assets" - "github.com/nyaruka/goflow/assets/static/types" + "github.com/nyaruka/goflow/assets/static" "github.com/nyaruka/goflow/excellent/tools" xtypes "github.com/nyaruka/goflow/excellent/types" "github.com/nyaruka/goflow/flows" @@ -39,7 +39,7 @@ type sessionRequest struct { OrgID models.OrgID `json:"org_id" validate:"required"` Flows []flowDefinition `json:"flows"` Assets struct { - Channels []*types.Channel `json:"channels"` + Channels []*static.Channel `json:"channels"` } `json:"assets"` } diff --git a/web/ticket/base_test.go b/web/ticket/base_test.go index 2e25792d9..ae718c207 100644 --- a/web/ticket/base_test.go +++ b/web/ticket/base_test.go @@ -15,10 +15,10 @@ func TestTicketAssign(t *testing.T) { defer testsuite.ResetData(db) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "17", testdata.Admin) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "More help", "Have you seen my cookies?", "21", testdata.Agent) - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Old question", "Have you seen my cookies?", "34", nil) - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Bob, testdata.Internal, testdata.DefaultTopic, "Problem", "", "", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Have you seen my cookies?", "17", testdata.Admin) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Have you seen my cookies?", "21", testdata.Agent) + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Have you seen my cookies?", "34", nil) + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Bob, testdata.Internal, testdata.DefaultTopic, "", "", nil) web.RunWebTests(t, "testdata/assign.json", nil) } @@ -28,9 +28,9 @@ func TestTicketAddNote(t *testing.T) { defer testsuite.ResetData(db) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "17", testdata.Admin) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "More help", "Have you seen my cookies?", "21", testdata.Agent) - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Old question", "Have you seen my cookies?", "34", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Have you seen my cookies?", "17", testdata.Admin) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Have you seen my cookies?", "21", testdata.Agent) + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Have you seen my cookies?", "34", nil) web.RunWebTests(t, "testdata/add_note.json", nil) } @@ -40,9 +40,9 @@ func TestTicketChangeTopic(t *testing.T) { defer testsuite.ResetData(db) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "17", testdata.Admin) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.SupportTopic, "More help", "Have you seen my cookies?", "21", testdata.Agent) - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.SalesTopic, "Old question", "Have you seen my cookies?", "34", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.DefaultTopic, "Have you seen my cookies?", "17", testdata.Admin) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.SupportTopic, "Have you seen my cookies?", "21", testdata.Agent) + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.SalesTopic, "Have you seen my cookies?", "34", nil) web.RunWebTests(t, "testdata/change_topic.json", nil) } @@ -53,10 +53,10 @@ func TestTicketClose(t *testing.T) { defer testsuite.ResetData(db) // create 2 open tickets and 1 closed one for Cathy across two different ticketers - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "17", testdata.Admin) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "More help", "Have you seen my cookies?", "21", nil) - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Old question", "Have you seen my cookies?", "34", testdata.Editor) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "More help", "Have you seen my cookies?", "21", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Have you seen my cookies?", "17", testdata.Admin) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "21", nil) + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "34", testdata.Editor) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "21", nil) web.RunWebTests(t, "testdata/close.json", nil) } @@ -67,9 +67,9 @@ func TestTicketReopen(t *testing.T) { defer testsuite.ResetData(db) // create 2 closed tickets and 1 open one for Cathy - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Need help", "Have you seen my cookies?", "17", testdata.Admin) - testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "More help", "Have you seen my cookies?", "21", nil) - testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Old question", "Have you seen my cookies?", "34", testdata.Editor) + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Mailgun, testdata.DefaultTopic, "Have you seen my cookies?", "17", testdata.Admin) + testdata.InsertClosedTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "21", nil) + testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Have you seen my cookies?", "34", testdata.Editor) web.RunWebTests(t, "testdata/reopen.json", nil) } diff --git a/workers.go b/workers.go index 71591015b..e684ab070 100644 --- a/workers.go +++ b/workers.go @@ -54,7 +54,7 @@ func (f *Foreman) Stop() { worker.Stop() } close(f.quit) - logrus.WithField("comp", "foreman").WithField("state", "stopping").Info("foreman stopping") + logrus.WithField("comp", "foreman").WithField("queue", f.queue).WithField("state", "stopping").Info("foreman stopping") } // Assign is our main loop for the Foreman, it takes care of popping the next outgoing task from our @@ -62,7 +62,7 @@ func (f *Foreman) Stop() { func (f *Foreman) Assign() { f.wg.Add(1) defer f.wg.Done() - log := logrus.WithField("comp", "foreman") + log := logrus.WithField("comp", "foreman").WithField("queue", f.queue) log.WithFields(logrus.Fields{ "state": "started", @@ -185,11 +185,18 @@ func (w *Worker) handleTask(task *queue.Task) { if found { err := taskFunc(context.Background(), w.foreman.rt, task) if err != nil { - log.WithError(err).WithField("task", string(task.Task)).WithField("task_type", task.Type).WithField("org_id", task.OrgID).Error("error running task") + log.WithError(err).WithField("task", string(task.Task)).Error("error running task") } } else { log.Error("unable to find function for task type") } - log.WithField("elapsed", time.Since(start)).Info("task complete") + elapsed := time.Since(start) + + log.WithField("elapsed", elapsed).Info("task complete") + + // additionally if any task took longer than 1 minute, log as warning + if elapsed > time.Minute { + log.WithField("task", string(task.Task)).WithField("elapsed", elapsed).Warn("long running task") + } }