forked from rapidpro/mailroom
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
36984ab
commit b6859ff
Showing
3 changed files
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 not shown.