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.
Merge pull request rapidpro#486 from nyaruka/topics
Ticket Topics
- Loading branch information
Showing
17 changed files
with
230 additions
and
25 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
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
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
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
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
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
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,107 @@ | ||
package models | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
"database/sql/driver" | ||
"time" | ||
|
||
"github.com/jmoiron/sqlx" | ||
"github.com/nyaruka/gocommon/dates" | ||
"github.com/nyaruka/goflow/assets" | ||
"github.com/nyaruka/mailroom/utils/dbutil" | ||
"github.com/nyaruka/null" | ||
"github.com/pkg/errors" | ||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
type TopicID null.Int | ||
|
||
const NilTopicID = TopicID(0) | ||
|
||
type Topic struct { | ||
t struct { | ||
ID TopicID `json:"id"` | ||
UUID assets.TopicUUID `json:"uuid"` | ||
OrgID OrgID `json:"org_id"` | ||
Name string `json:"name"` | ||
IsDefault bool `json:"is_default"` | ||
} | ||
} | ||
|
||
// ID returns the ID | ||
func (t *Topic) ID() TopicID { return t.t.ID } | ||
|
||
// UUID returns the UUID | ||
func (t *Topic) UUID() assets.TopicUUID { return t.t.UUID } | ||
|
||
// OrgID returns the org ID | ||
func (t *Topic) OrgID() OrgID { return t.t.OrgID } | ||
|
||
// Name returns the name | ||
func (t *Topic) Name() string { return t.t.Name } | ||
|
||
// Type returns the type | ||
func (t *Topic) IsDefault() bool { return t.t.IsDefault } | ||
|
||
const selectOrgTopicsSQL = ` | ||
SELECT ROW_TO_JSON(r) FROM (SELECT | ||
t.id as id, | ||
t.uuid as uuid, | ||
t.org_id as org_id, | ||
t.name as name, | ||
t.is_default as is_default | ||
FROM | ||
tickets_topic t | ||
WHERE | ||
t.org_id = $1 AND | ||
t.is_active = TRUE | ||
ORDER BY | ||
t.is_default DESC, t.created_on ASC | ||
) r; | ||
` | ||
|
||
// loadTopics loads all the topics for the passed in org | ||
func loadTopics(ctx context.Context, db sqlx.Queryer, orgID OrgID) ([]assets.Topic, error) { | ||
start := dates.Now() | ||
|
||
rows, err := db.Queryx(selectOrgTopicsSQL, orgID) | ||
if err != nil && err != sql.ErrNoRows { | ||
return nil, errors.Wrapf(err, "error querying topics for org: %d", orgID) | ||
} | ||
defer rows.Close() | ||
|
||
topics := make([]assets.Topic, 0, 2) | ||
for rows.Next() { | ||
topic := &Topic{} | ||
err := dbutil.ReadJSONRow(rows, &topic.t) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "error unmarshalling topic") | ||
} | ||
topics = append(topics, topic) | ||
} | ||
|
||
logrus.WithField("elapsed", time.Since(start)).WithField("org_id", orgID).WithField("count", len(topics)).Debug("loaded topics") | ||
|
||
return topics, nil | ||
} | ||
|
||
// MarshalJSON marshals into JSON. 0 values will become null | ||
func (i TopicID) MarshalJSON() ([]byte, error) { | ||
return null.Int(i).MarshalJSON() | ||
} | ||
|
||
// UnmarshalJSON unmarshals from JSON. null values become 0 | ||
func (i *TopicID) UnmarshalJSON(b []byte) error { | ||
return null.UnmarshalInt(b, (*null.Int)(i)) | ||
} | ||
|
||
// Value returns the db value, null is returned for 0 | ||
func (i TopicID) Value() (driver.Value, error) { | ||
return null.Int(i).Value() | ||
} | ||
|
||
// Scan scans from the db value. null values become 0 | ||
func (i *TopicID) Scan(value interface{}) error { | ||
return null.ScanInt(value, (*null.Int)(i)) | ||
} |
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,33 @@ | ||
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/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestTopics(t *testing.T) { | ||
ctx, _, db, _ := testsuite.Get() | ||
|
||
oa, err := models.GetOrgAssetsWithRefresh(ctx, db, testdata.Org1.ID, models.RefreshTopics) | ||
require.NoError(t, err) | ||
|
||
topics, err := oa.Topics() | ||
require.NoError(t, err) | ||
|
||
assert.Equal(t, 3, len(topics)) | ||
assert.Equal(t, testdata.DefaultTopic.UUID, topics[0].UUID()) | ||
assert.Equal(t, "General", topics[0].Name()) | ||
assert.Equal(t, testdata.SalesTopic.UUID, topics[1].UUID()) | ||
assert.Equal(t, "Sales", topics[1].Name()) | ||
assert.Equal(t, testdata.SupportTopic.UUID, topics[2].UUID()) | ||
assert.Equal(t, "Support", topics[2].Name()) | ||
|
||
assert.Equal(t, topics[1], oa.TopicByID(testdata.SalesTopic.ID)) | ||
assert.Equal(t, topics[2], oa.TopicByUUID(testdata.SupportTopic.UUID)) | ||
} |
Binary file not shown.
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
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
Oops, something went wrong.