Skip to content

Commit

Permalink
Notifications (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanseymour committed Aug 31, 2021
1 parent 36984ab commit b6859ff
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 0 deletions.
101 changes: 101 additions & 0 deletions core/models/notifications.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package models

import (
"context"

"github.com/nyaruka/mailroom/utils/dbutil"
"github.com/pkg/errors"
)

// LogID is our type for log ids
type LogID int

type LogType string

const (
LogTypeBroadcastStarted LogType = "bcast:started"
LogTypeBroadcastCompleted LogType = "bcast:completed"
LogTypeChannelAlert LogType = "channel:alert"
LogTypeExportStarted LogType = "export:started"
LogTypeExportCompleted LogType = "export:completed"
LogTypeFlowStartStarted LogType = "start:started"
LogTypeFlowStartCompleted LogType = "start:completed"
LogTypeImportStarted LogType = "import:started"
LogTypeImportCompleted LogType = "import:completed"
LogTypeTicketOpened LogType = "ticket:opened"
LogTypeTicketNewMsgs LogType = "ticket:msgs"
LogTypeTicketAssignment LogType = "ticket:assign"
LogTypeTicketNote LogType = "ticket:note"
)

type Log struct {
ID LogID `db:"id"`
OrgID OrgID `db:"org_id"`
LogType LogType `db:"log_type"`
CreatedByID UserID `db:"created_by_id"`

BroadcastID BroadcastID `db:"broadcast_id"`
FlowStartID StartID `db:"flow_start_id"`
TicketID TicketID `db:"ticket_id"`
}

type Notification struct {
ID LogID `db:"id"`
OrgID OrgID `db:"org_id"`
UserID UserID `db:"user_id"`
LogID LogID `db:"log_id"`
}

func LogTicketOpened(ctx context.Context, db Queryer, oa *OrgAssets, ticket *Ticket) error {
log := &Log{OrgID: ticket.OrgID(), LogType: LogTypeTicketOpened, TicketID: ticket.ID()}
return logAndNotify(ctx, db, oa, log, []UserRole{UserRoleAdministrator, UserRoleEditor, UserRoleAgent}, false)
}

const insertLogSQL = `
INSERT INTO notifications_log(org_id, log_type, created_on, created_by_id, broadcast_id, flow_start_id, ticket_id)
VALUES(:org_id, :log_type, NOW(), :created_by_id, :broadcast_id, :flow_start_id, :ticket_id)
RETURNING id`

const insertNotificationSQL = `
INSERT INTO notifications_notification(org_id, user_id, log_id, is_seen)
VALUES(:org_id, :user_id, :log_id, FALSE)`

func logAndNotify(ctx context.Context, db Queryer, oa *OrgAssets, log *Log, notifyRoles []UserRole, notifyUser bool) error {
// TODO use a more efficient simple Exec
err := dbutil.BulkQuery(ctx, db, insertLogSQL, []interface{}{log})
if err != nil {
return errors.Wrapf(err, "error inserting %s log", log.LogType)
}

notifyUsers := getUsersToNotify(oa, notifyRoles, notifyUser, log.CreatedByID)

var notifications []interface{}
for _, user := range notifyUsers {
notifications = append(notifications, &Notification{OrgID: oa.OrgID(), UserID: user.ID(), LogID: log.ID})
}

err = dbutil.BulkQuery(ctx, db, insertNotificationSQL, notifications)

return errors.Wrap(err, "error inserting notifications")
}

func getUsersToNotify(oa *OrgAssets, notifyRoles []UserRole, notifyUser bool, logUserID UserID) []*User {
var users []*User

for _, u := range oa.users {
user := u.(*User)

if !notifyUser && logUserID == user.ID() {
continue
}

for _, r := range notifyRoles {
if user.Role() == r {
users = append(users, user)
break
}
}
}

return users
}
28 changes: 28 additions & 0 deletions core/models/notifications_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package models_test

import (
"testing"

"github.com/nyaruka/mailroom/core/models"
"github.com/nyaruka/mailroom/testsuite"
"github.com/nyaruka/mailroom/testsuite/testdata"
"github.com/stretchr/testify/require"
)

func TestNotifications(t *testing.T) {
ctx, _, db, _ := testsuite.Reset()

oa, err := models.GetOrgAssets(ctx, db, testdata.Org1.ID)
require.NoError(t, err)

ticket := testdata.InsertOpenTicket(db, testdata.Org1, testdata.Cathy, testdata.Internal, testdata.SupportTopic, "", "Where my pants", "", nil)
modelTicket := ticket.Load(db)

err = models.LogTicketOpened(ctx, db, oa, modelTicket)
require.NoError(t, err)

testsuite.AssertQuery(t, db, `SELECT org_id, log_type, ticket_id FROM notifications_log`).
Columns(map[string]interface{}{"org_id": int64(testdata.Org1.ID), "log_type": "ticket:opened", "ticket_id": int64(modelTicket.ID())})

testsuite.AssertQuery(t, db, `SELECT count(*) FROM notifications_notification`).Returns(3)
}
Binary file modified mailroom_test.dump
Binary file not shown.

0 comments on commit b6859ff

Please sign in to comment.