Skip to content

Commit

Permalink
Record daily assignment counts when tickets are being assigned
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanseymour committed May 9, 2022
1 parent 114e510 commit 3a362e6
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 15 deletions.
43 changes: 38 additions & 5 deletions core/models/tickets.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,18 +345,30 @@ func InsertTickets(ctx context.Context, tx Queryer, oa *OrgAssets, tickets []*Ti
return nil
}

openingCounts := map[string]int{scopeOrg(oa): len(tickets)} // all new tickets are open
assignmentCounts := make(map[string]int)

ts := make([]interface{}, len(tickets))
for i := range tickets {
ts[i] = &tickets[i].t
for i, t := range tickets {
ts[i] = &t.t

if t.AssigneeID() != NilUserID {
assignmentCounts[scopeUser(oa, t.AssigneeID())]++
}
}

if err := BulkQuery(ctx, "inserted tickets", tx, sqlInsertTicket, ts); err != nil {
return err
}

return insertTicketDailyCounts(ctx, tx, TicketDailyCountOpening, oa.Org().Timezone(), map[string]int{
fmt.Sprintf("o:%d", oa.OrgID()): len(tickets),
})
if err := insertTicketDailyCounts(ctx, tx, TicketDailyCountOpening, oa.Org().Timezone(), openingCounts); err != nil {
return err
}
if err := insertTicketDailyCounts(ctx, tx, TicketDailyCountAssignment, oa.Org().Timezone(), assignmentCounts); err != nil {
return err
}

return nil
}

const sqlInsertTicketDailyCount = `
Expand Down Expand Up @@ -430,8 +442,16 @@ func TicketsAssign(ctx context.Context, db Queryer, oa *OrgAssets, userID UserID
eventsByTicket := make(map[*Ticket]*TicketEvent, len(tickets))
now := dates.Now()

assignmentCounts := make(map[string]int)

for _, ticket := range tickets {
if ticket.AssigneeID() != assigneeID {

// if this is an initial assignment record count for user
if ticket.AssigneeID() == NilUserID && assigneeID != NilUserID {
assignmentCounts[scopeUser(oa, assigneeID)]++
}

ids = append(ids, ticket.ID())
t := &ticket.t
t.AssigneeID = assigneeID
Expand Down Expand Up @@ -460,6 +480,11 @@ func TicketsAssign(ctx context.Context, db Queryer, oa *OrgAssets, userID UserID
return nil, errors.Wrap(err, "error inserting notifications")
}

err = insertTicketDailyCounts(ctx, db, TicketDailyCountAssignment, oa.Org().Timezone(), assignmentCounts)
if err != nil {
return nil, errors.Wrap(err, "error inserting assignment counts")
}

return eventsByTicket, nil
}

Expand Down Expand Up @@ -869,3 +894,11 @@ func (i TicketerID) Value() (driver.Value, error) {
func (i *TicketerID) Scan(value interface{}) error {
return null.ScanInt(value, (*null.Int)(i))
}

func scopeOrg(oa *OrgAssets) string {
return fmt.Sprintf("o:%d", oa.OrgID())
}

func scopeUser(oa *OrgAssets, uid UserID) string {
return fmt.Sprintf("o:%d:u:%d", oa.OrgID(), uid)
}
39 changes: 30 additions & 9 deletions core/models/tickets_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package models_test

import (
"fmt"
"testing"
"time"

"github.com/jmoiron/sqlx"
"github.com/nyaruka/gocommon/dates"
"github.com/nyaruka/gocommon/dbutil/assertdb"
"github.com/nyaruka/gocommon/httpx"
Expand Down Expand Up @@ -90,13 +92,13 @@ func TestTickets(t *testing.T) {
)
ticket3 := models.NewTicket(
"28ef8ddc-b221-42f3-aeae-ee406fc9d716",
testdata.Org2.ID,
testdata.Org1.ID,
testdata.Alexandria.ID,
testdata.Zendesk.ID,
"EX6677",
testdata.SupportTopic.ID,
"Where are my pants?",
testdata.Org2Admin.ID,
testdata.Admin.ID,
nil,
)

Expand All @@ -116,8 +118,11 @@ func TestTickets(t *testing.T) {
// check all tickets were created
assertdb.Query(t, db, `SELECT count(*) FROM tickets_ticket WHERE status = 'O' AND closed_on IS NULL`).Returns(3)

// check the opened count was added
assertdb.Query(t, db, `SELECT SUM(count) FROM tickets_ticketdailycount WHERE count_type = 'O' AND scope = CONCAT('o:', $1::text)`, testdata.Org1.ID).Returns(3)
// check counts were added
assertTicketDailyCount(t, db, models.TicketDailyCountOpening, fmt.Sprintf("o:%d", testdata.Org1.ID), 3)
assertTicketDailyCount(t, db, models.TicketDailyCountOpening, fmt.Sprintf("o:%d", testdata.Org2.ID), 0)
assertTicketDailyCount(t, db, models.TicketDailyCountAssignment, fmt.Sprintf("o:%d:u:%d", testdata.Org1.ID, testdata.Admin.ID), 2)
assertTicketDailyCount(t, db, models.TicketDailyCountAssignment, fmt.Sprintf("o:%d:u:%d", testdata.Org1.ID, testdata.Editor.ID), 0)

// can lookup a ticket by UUID
tk1, err := models.LookupTicketByUUID(ctx, db, "2ef57efc-d85f-4291-b330-e4afe68af5fe")
Expand Down Expand Up @@ -196,22 +201,31 @@ func TestTicketsAssign(t *testing.T) {
ticket2 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Where my pants", "234", nil)
modelTicket2 := ticket2.Load(db)

// create ticket already assigned to a user
ticket3 := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Zendesk, testdata.DefaultTopic, "Where my glasses", "", testdata.Admin)
modelTicket3 := ticket3.Load(db)

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")
evts, err := models.TicketsAssign(ctx, db, oa, testdata.Admin.ID, []*models.Ticket{modelTicket1, modelTicket2, modelTicket3}, testdata.Agent.ID, "please handle these")
require.NoError(t, err)
assert.Equal(t, 2, len(evts))
assert.Equal(t, 3, len(evts))
assert.Equal(t, models.TicketEventTypeAssigned, evts[modelTicket1].EventType())
assert.Equal(t, models.TicketEventTypeAssigned, evts[modelTicket2].EventType())
assert.Equal(t, models.TicketEventTypeAssigned, evts[modelTicket3].EventType())

// check tickets are now assigned
assertdb.Query(t, db, `SELECT assignee_id FROM tickets_ticket WHERE id = $1`, ticket1.ID).Columns(map[string]interface{}{"assignee_id": int64(testdata.Agent.ID)})
assertdb.Query(t, db, `SELECT assignee_id FROM tickets_ticket WHERE id = $1`, ticket2.ID).Columns(map[string]interface{}{"assignee_id": int64(testdata.Agent.ID)})
assertdb.Query(t, db, `SELECT assignee_id FROM tickets_ticket WHERE id = $1`, ticket3.ID).Columns(map[string]interface{}{"assignee_id": int64(testdata.Agent.ID)})

// and there are new assigned events
assertdb.Query(t, db, `SELECT count(*) FROM tickets_ticketevent WHERE event_type = 'A' AND note = 'please handle these'`).Returns(2)

// and there are new assigned events with notifications
assertdb.Query(t, db, `SELECT count(*) FROM tickets_ticketevent WHERE event_type = 'A' AND note = 'please handle these'`).Returns(3)
assertdb.Query(t, db, `SELECT count(*) FROM notifications_notification WHERE user_id = $1 AND notification_type = 'tickets:activity'`, testdata.Agent.ID).Returns(1)

// and daily counts (we only count first assignments of a ticket)
assertTicketDailyCount(t, db, models.TicketDailyCountAssignment, fmt.Sprintf("o:%d:u:%d", testdata.Org1.ID, testdata.Agent.ID), 2)
assertTicketDailyCount(t, db, models.TicketDailyCountAssignment, fmt.Sprintf("o:%d:u:%d", testdata.Org1.ID, testdata.Admin.ID), 0)
}

func TestTicketsAddNote(t *testing.T) {
Expand Down Expand Up @@ -391,4 +405,11 @@ func TestReopenTickets(t *testing.T) {
assert.Equal(t, 2, len(cathy.Groups().All()))
assert.Equal(t, "Doctors", cathy.Groups().All()[0].Name())
assert.Equal(t, "Open Tickets", cathy.Groups().All()[1].Name())

// reopening doesn't change opening daily counts
assertTicketDailyCount(t, db, models.TicketDailyCountOpening, fmt.Sprintf("o:%d", testdata.Org1.ID), 0)
}

func assertTicketDailyCount(t *testing.T, db *sqlx.DB, countType models.TicketDailyCountType, scope string, expected int) {
assertdb.Query(t, db, `SELECT COALESCE(SUM(count), 0) FROM tickets_ticketdailycount WHERE count_type = $1 AND scope = $2`, countType, scope).Returns(expected)
}
2 changes: 1 addition & 1 deletion services/tickets/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,5 +186,5 @@ func TestCloseTicket(t *testing.T) {
require.NoError(t, err)

testsuite.AssertContactTasks(t, 1, testdata.Cathy.ID,
[]string{`{"type":"ticket_closed","org_id":1,"task":{"id":1,"org_id":1,"contact_id":10000,"ticket_id":1,"event_type":"C","created_on":"2021-06-08T16:40:32Z"},"queued_on":"2021-06-08T16:40:35Z"}`})
[]string{`{"type":"ticket_closed","org_id":1,"task":{"id":1,"org_id":1,"contact_id":10000,"ticket_id":1,"event_type":"C","created_on":"2021-06-08T16:40:34Z"},"queued_on":"2021-06-08T16:40:37Z"}`})
}

0 comments on commit 3a362e6

Please sign in to comment.