feat: Implement notification service and integrate with user interactions
- Added notification service to handle sending and listing notifications. - Integrated notification sending on user follow and order payment events. - Updated user service to include fetching followed tenants. - Enhanced content service to manage access control for content assets. - Implemented logic for listing content topics based on genre. - Updated creator service to manage content updates and pricing. - Improved order service to include detailed order information and notifications. - Added tests for notification CRUD operations and order details.
This commit is contained in:
@@ -118,9 +118,13 @@ func (s *ContentTestSuite) Test_Get() {
|
||||
ContentID: content.ID,
|
||||
AssetID: asset.ID,
|
||||
Sort: 1,
|
||||
Role: consts.ContentAssetRoleMain, // Explicitly set role
|
||||
}
|
||||
models.ContentAssetQuery.WithContext(ctx).Create(ca)
|
||||
|
||||
// Set context to author
|
||||
ctx = context.WithValue(ctx, consts.CtxKeyUser, author.ID)
|
||||
|
||||
Convey("should get detail with assets", func() {
|
||||
detail, err := Content.Get(ctx, cast.ToString(content.ID))
|
||||
So(err, ShouldBeNil)
|
||||
@@ -259,3 +263,96 @@ func (s *ContentTestSuite) Test_Interact() {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *ContentTestSuite) Test_ListTopics() {
|
||||
Convey("ListTopics", s.T(), func() {
|
||||
ctx := s.T().Context()
|
||||
database.Truncate(ctx, s.DB, models.TableNameContent, models.TableNameUser)
|
||||
|
||||
u := &models.User{Username: "user_t", Phone: "13900000005"}
|
||||
models.UserQuery.WithContext(ctx).Create(u)
|
||||
|
||||
// Create Contents: 2 video, 1 audio
|
||||
models.ContentQuery.WithContext(ctx).Create(
|
||||
&models.Content{TenantID: 1, UserID: u.ID, Title: "V1", Genre: "video", Status: consts.ContentStatusPublished},
|
||||
&models.Content{TenantID: 1, UserID: u.ID, Title: "V2", Genre: "video", Status: consts.ContentStatusPublished},
|
||||
&models.Content{TenantID: 1, UserID: u.ID, Title: "A1", Genre: "audio", Status: consts.ContentStatusPublished},
|
||||
&models.Content{TenantID: 1, UserID: u.ID, Title: "D1", Genre: "draft", Status: consts.ContentStatusDraft}, // Should ignore
|
||||
)
|
||||
|
||||
Convey("should aggregate topics", func() {
|
||||
topics, err := Content.ListTopics(ctx)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(topics), ShouldBeGreaterThanOrEqualTo, 2)
|
||||
|
||||
var videoCount, audioCount int
|
||||
for _, t := range topics {
|
||||
if t.Tag == "video" {
|
||||
videoCount = t.Count
|
||||
}
|
||||
if t.Tag == "audio" {
|
||||
audioCount = t.Count
|
||||
}
|
||||
}
|
||||
So(videoCount, ShouldEqual, 2)
|
||||
So(audioCount, ShouldEqual, 1)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func (s *ContentTestSuite) Test_PreviewLogic() {
|
||||
Convey("Preview Logic", s.T(), func() {
|
||||
ctx := s.T().Context()
|
||||
database.Truncate(ctx, s.DB, models.TableNameContent, models.TableNameContentAsset, models.TableNameContentAccess, models.TableNameUser, models.TableNameMediaAsset)
|
||||
|
||||
author := &models.User{Username: "author_p", Phone: "13900000006"}
|
||||
models.UserQuery.WithContext(ctx).Create(author)
|
||||
|
||||
c := &models.Content{TenantID: 1, UserID: author.ID, Title: "Premium", Status: consts.ContentStatusPublished}
|
||||
models.ContentQuery.WithContext(ctx).Create(c)
|
||||
|
||||
assetMain := &models.MediaAsset{ObjectKey: "main.mp4", Type: consts.MediaAssetTypeVideo}
|
||||
assetPrev := &models.MediaAsset{ObjectKey: "preview.mp4", Type: consts.MediaAssetTypeVideo}
|
||||
models.MediaAssetQuery.WithContext(ctx).Create(assetMain, assetPrev)
|
||||
|
||||
models.ContentAssetQuery.WithContext(ctx).Create(
|
||||
&models.ContentAsset{ContentID: c.ID, AssetID: assetMain.ID, Role: consts.ContentAssetRoleMain},
|
||||
&models.ContentAsset{ContentID: c.ID, AssetID: assetPrev.ID, Role: consts.ContentAssetRolePreview},
|
||||
)
|
||||
|
||||
Convey("guest should see preview only", func() {
|
||||
guest := &models.User{Username: "guest", Phone: "13900000007"}
|
||||
models.UserQuery.WithContext(ctx).Create(guest)
|
||||
guestCtx := context.WithValue(ctx, consts.CtxKeyUser, guest.ID)
|
||||
|
||||
detail, err := Content.Get(guestCtx, cast.ToString(c.ID))
|
||||
So(err, ShouldBeNil)
|
||||
So(len(detail.MediaUrls), ShouldEqual, 1)
|
||||
So(detail.MediaUrls[0].URL, ShouldEndWith, "preview.mp4")
|
||||
So(detail.IsPurchased, ShouldBeFalse)
|
||||
})
|
||||
|
||||
Convey("owner should see all", func() {
|
||||
ownerCtx := context.WithValue(ctx, consts.CtxKeyUser, author.ID)
|
||||
detail, err := Content.Get(ownerCtx, cast.ToString(c.ID))
|
||||
So(err, ShouldBeNil)
|
||||
So(len(detail.MediaUrls), ShouldEqual, 2)
|
||||
So(detail.IsPurchased, ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("buyer should see all", func() {
|
||||
buyer := &models.User{Username: "buyer_p", Phone: "13900000008"}
|
||||
models.UserQuery.WithContext(ctx).Create(buyer)
|
||||
buyerCtx := context.WithValue(ctx, consts.CtxKeyUser, buyer.ID)
|
||||
|
||||
models.ContentAccessQuery.WithContext(ctx).Create(&models.ContentAccess{
|
||||
UserID: buyer.ID, ContentID: c.ID, Status: consts.ContentAccessStatusActive,
|
||||
})
|
||||
|
||||
detail, err := Content.Get(buyerCtx, cast.ToString(c.ID))
|
||||
So(err, ShouldBeNil)
|
||||
So(len(detail.MediaUrls), ShouldEqual, 2)
|
||||
So(detail.IsPurchased, ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user