The database requirements have been added, as well as the service/repo architecture. A few small functions have been created, but the system is not complete by any means. More work is required to mark this task complete.
154 lines
4.4 KiB
Go
154 lines
4.4 KiB
Go
package repository
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"time"
|
|
|
|
domain "github.com/haydenhargreaves/Potion/internal/domain/engagement"
|
|
_ "github.com/lib/pq"
|
|
)
|
|
|
|
type EngagementRepository struct {
|
|
db *sql.DB
|
|
}
|
|
|
|
// Compile-time check to ensure the EngagementRepository implements domain.EngagementRepository
|
|
var _ domain.EngagementRepository = (*EngagementRepository)(nil)
|
|
|
|
// NewUserRepository creates a user repository object which is used by the user service to access
|
|
// the database. Any user related database operations will take place in this repository.
|
|
func NewEngagementRepository(db *sql.DB) domain.EngagementRepository {
|
|
return &EngagementRepository{db: db}
|
|
}
|
|
|
|
// AddUserEngagement creates an engagement record in the database with the user ID provided. This
|
|
// function does not accept an entity ID as it should be used when there is no need to reference
|
|
// an entity. The message should be provided, but a blank string ("") is acceptable. The engagement
|
|
// type parameter determines the labeling of the engagement in the database. Any errors will be
|
|
// bubbled to the caller.
|
|
func (r *EngagementRepository) AddUserEngagement(userId int, message string, engagementType domain.EngagementType) (domain.Engagement, error) {
|
|
tx, err := r.db.Begin()
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return domain.Engagement{}, err
|
|
}
|
|
|
|
query := `
|
|
INSERT INTO Engagements (
|
|
type, message, entity, userid, created
|
|
) VALUES (
|
|
$1, $2, NULL, $3, $4
|
|
) RETURNING *;
|
|
`
|
|
|
|
var engagement domain.Engagement
|
|
if err := tx.QueryRow(query, engagementType, message, userId, time.Now()).Scan(
|
|
&engagement.Id,
|
|
&engagement.Type,
|
|
&engagement.Message,
|
|
&engagement.Entity,
|
|
&engagement.UserId,
|
|
&engagement.Created,
|
|
); err != nil {
|
|
tx.Rollback()
|
|
return domain.Engagement{}, fmt.Errorf("Failed to insert engagement into database. %s", err.Error())
|
|
}
|
|
|
|
if err := tx.Commit(); err != nil {
|
|
tx.Rollback()
|
|
return domain.Engagement{}, err
|
|
}
|
|
|
|
return engagement, nil
|
|
}
|
|
|
|
// AddUserEngagement creates an engagement record in the database with the user ID provided. This
|
|
// function requires an entity ID as it should be used when there is a reference to external an
|
|
// entity. The message should be provided, but a blank string ("") is acceptable. The engagement
|
|
// type parameter determines the labeling of the engagement in the database. Any errors will be
|
|
// bubbled to the caller.
|
|
func (r *EngagementRepository) AddUserEntityEngagement(userId, entityId int, message string, engagementType domain.EngagementType) (domain.Engagement, error) {
|
|
tx, err := r.db.Begin()
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return domain.Engagement{}, err
|
|
}
|
|
|
|
query := `
|
|
INSERT INTO Engagements (
|
|
type, message, entity, userid, created
|
|
) VALUES (
|
|
$1, $2, $3, $4, $5
|
|
) RETURNING *;
|
|
`
|
|
|
|
var engagement domain.Engagement
|
|
if err := tx.QueryRow(query, engagementType, message, entityId, userId, time.Now()).Scan(
|
|
&engagement.Id,
|
|
&engagement.Type,
|
|
&engagement.Message,
|
|
&engagement.Entity,
|
|
&engagement.UserId,
|
|
&engagement.Created,
|
|
); err != nil {
|
|
tx.Rollback()
|
|
return domain.Engagement{}, fmt.Errorf("Failed to insert engagement into database. %s", err.Error())
|
|
}
|
|
|
|
if err := tx.Commit(); err != nil {
|
|
tx.Rollback()
|
|
return domain.Engagement{}, err
|
|
}
|
|
|
|
return engagement, nil
|
|
}
|
|
|
|
// GetUserEngagement returns a list of the users most recent engagement entries. The number of records
|
|
// is determined by the limit passed into this function. The results are sorted, newest-to-oldest.
|
|
func (r *EngagementRepository) GetUserEngagement(userId, limit int) ([]domain.Engagement, error) {
|
|
tx, err := r.db.Begin()
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return []domain.Engagement{}, err
|
|
}
|
|
|
|
query := `
|
|
SELECT * FROM Engagements
|
|
WHERE Userid = $1
|
|
ORDER BY created DESC LIMIT $2;
|
|
`
|
|
|
|
rows, err := tx.Query(query, userId, limit)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return []domain.Engagement{}, fmt.Errorf("Failed to get user engagements. %s", err.Error())
|
|
}
|
|
defer rows.Close()
|
|
|
|
var engagements []domain.Engagement
|
|
for rows.Next() {
|
|
var engagement domain.Engagement
|
|
if err := rows.Scan(
|
|
&engagement.Id,
|
|
&engagement.Type,
|
|
&engagement.Message,
|
|
&engagement.Entity,
|
|
&engagement.UserId,
|
|
&engagement.Created,
|
|
); err != nil {
|
|
tx.Rollback()
|
|
return []domain.Engagement{}, fmt.Errorf("Failed to scan user engagement. %s", err.Error())
|
|
}
|
|
|
|
engagements = append(engagements, engagement)
|
|
}
|
|
|
|
if err := tx.Commit(); err != nil {
|
|
tx.Rollback()
|
|
return []domain.Engagement{}, err
|
|
}
|
|
|
|
return engagements, err
|
|
}
|