作者 linmadan

添加消息通知接口

正在显示 29 个修改的文件 包含 1118 行增加0 行删除
... ... @@ -43,6 +43,7 @@ func (customerValueService *CustomerValueService) CreateCustomerValue(createCust
}
if count, _, err := customerValueRepository.Find(map[string]interface{}{
"customerValueName": createCustomerValueCommand.CustomerValueName,
"companyId": createCustomerValueCommand.CompanyId,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
... ... @@ -129,6 +130,7 @@ func (customerValueService *CustomerValueService) UpdateCustomerValue(updateCust
}
if count, customerValues, err := customerValueRepository.Find(map[string]interface{}{
"customerValueName": updateCustomerValueCommand.CustomerValueName,
"companyId": customerValue.CompanyId,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
... ...
... ... @@ -20,3 +20,11 @@ func CreateEmployeeDao(options map[string]interface{}) (*dao.EmployeeDao, error)
}
return dao.NewEmployeeDao(transactionContext)
}
func CreateNotificationDao(options map[string]interface{}) (*dao.NotificationDao, error) {
var transactionContext *pg.TransactionContext
if value, ok := options["transactionContext"]; ok {
transactionContext = value.(*pg.TransactionContext)
}
return dao.NewNotificationDao(transactionContext)
}
... ...
... ... @@ -6,6 +6,22 @@ import (
domainService "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/domain_service"
)
func CreateReadSentNotificationService(options map[string]interface{}) (service.ReadSentNotificationService, error) {
var transactionContext *pgTransaction.TransactionContext
if value, ok := options["transactionContext"]; ok {
transactionContext = value.(*pgTransaction.TransactionContext)
}
return domainService.NewReadSentNotificationService(transactionContext)
}
func CreateReadAllUnReadSentNotificationService(options map[string]interface{}) (service.ReadAllUnReadSentNotificationService, error) {
var transactionContext *pgTransaction.TransactionContext
if value, ok := options["transactionContext"]; ok {
transactionContext = value.(*pgTransaction.TransactionContext)
}
return domainService.NewReadAllUnReadSentNotificationService(transactionContext)
}
func CreateOperationSuMoneyService(options map[string]interface{}) (service.OperationSuMoneyService, error) {
var transactionContext *pgTransaction.TransactionContext
if value, ok := options["transactionContext"]; ok {
... ...
... ... @@ -69,3 +69,19 @@ func CreateRejectTaskRecordRepository(options map[string]interface{}) (domain.Re
}
return repository.NewRejectTaskRecordRepository(transactionContext)
}
func CreateNotificationRepository(options map[string]interface{}) (domain.NotificationRepository, error) {
var transactionContext *pg.TransactionContext
if value, ok := options["transactionContext"]; ok {
transactionContext = value.(*pg.TransactionContext)
}
return repository.NewNotificationRepository(transactionContext)
}
func CreateSentNotificationRepository(options map[string]interface{}) (domain.SentNotificationRepository, error) {
var transactionContext *pg.TransactionContext
if value, ok := options["transactionContext"]; ok {
transactionContext = value.(*pg.TransactionContext)
}
return repository.NewSentNotificationRepository(transactionContext)
}
... ...
package command
import (
"fmt"
"github.com/astaxie/beego/validation"
)
type ReadAllUnReadSentNotificationCommand struct {
// 通知接收者Uid
ReceiverId int64 `json:"receiverId" valid:"Required"`
}
func (readAllUnReadSentNotificationCommand *ReadAllUnReadSentNotificationCommand) ValidateCommand() error {
valid := validation.Validation{}
b, err := valid.Valid(readAllUnReadSentNotificationCommand)
if err != nil {
return err
}
if !b {
for _, validErr := range valid.Errors {
return fmt.Errorf("%s %s", validErr.Key, validErr.Message)
}
}
return nil
}
... ...
package command
import (
"fmt"
"github.com/astaxie/beego/validation"
)
type ReadSentNotificationCommand struct {
// 发送出的通知ID
SentNotificationId int64 `json:"sentNotificationId" valid:"Required"`
}
func (readSentNotificationCommand *ReadSentNotificationCommand) ValidateCommand() error {
valid := validation.Validation{}
b, err := valid.Valid(readSentNotificationCommand)
if err != nil {
return err
}
if !b {
for _, validErr := range valid.Errors {
return fmt.Errorf("%s %s", validErr.Key, validErr.Message)
}
}
return nil
}
... ...
package query
import (
"fmt"
"github.com/astaxie/beego/validation"
)
type ListSentNotificationQuery struct {
// 通知接收者Uid
ReceiverId int64 `json:"receiverId" valid:"Required"`
// 通知类型
NotificationType int `json:"notificationType,omitempty"`
// 查询偏离量
Offset int `json:"offset,omitempty"`
// 查询限制
Limit int `json:"limit,omitempty"`
}
func (listSentNotificationQuery *ListSentNotificationQuery) ValidateQuery() error {
valid := validation.Validation{}
b, err := valid.Valid(listSentNotificationQuery)
if err != nil {
return err
}
if !b {
for _, validErr := range valid.Errors {
return fmt.Errorf("%s %s", validErr.Key, validErr.Message)
}
}
return nil
}
... ...
package service
import (
"github.com/linmadan/egglib-go/core/application"
"github.com/linmadan/egglib-go/utils/tool_funs"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/application/factory"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/application/notification/command"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/application/notification/query"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain/service"
)
// 通知服务
type NotificationService struct {
}
// 读取发送出的通知
func (notificationService *NotificationService) ReadSentNotification(readSentNotificationCommand *command.ReadSentNotificationCommand) (interface{}, error) {
if err := readSentNotificationCommand.ValidateCommand(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
var readSentNotificationService service.ReadSentNotificationService
if value, err := factory.CreateReadSentNotificationService(map[string]interface{}{
"transactionContext": transactionContext,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
readSentNotificationService = value
}
if sentNotification, err := readSentNotificationService.Read(readSentNotificationCommand.SentNotificationId); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return sentNotification, nil
}
}
// 读取全部未读取的发送出的通知
func (notificationService *NotificationService) ReadAllUnReadSentNotification(readAllUnReadSentNotificationCommand *command.ReadAllUnReadSentNotificationCommand) (interface{}, error) {
if err := readAllUnReadSentNotificationCommand.ValidateCommand(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
var readAllUnReadSentNotificationService service.ReadAllUnReadSentNotificationService
if value, err := factory.CreateReadAllUnReadSentNotificationService(map[string]interface{}{
"transactionContext": transactionContext,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
readAllUnReadSentNotificationService = value
}
if readCount, err := readAllUnReadSentNotificationService.ReadAll(readAllUnReadSentNotificationCommand.ReceiverId); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return readCount, nil
}
}
// 返回发送出的通知列表
func (notificationService *NotificationService) ListSentNotification(listSentNotificationQuery *query.ListSentNotificationQuery) (interface{}, error) {
if err := listSentNotificationQuery.ValidateQuery(); err != nil {
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
}
transactionContext, err := factory.CreateTransactionContext(nil)
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
if err := transactionContext.StartTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
defer func() {
transactionContext.RollbackTransaction()
}()
var sentNotificationRepository domain.SentNotificationRepository
if value, err := factory.CreateSentNotificationRepository(map[string]interface{}{
"transactionContext": transactionContext,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
sentNotificationRepository = value
}
if count, sentNotifications, err := sentNotificationRepository.Find(tool_funs.SimpleStructToMap(listSentNotificationQuery)); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
return map[string]interface{}{
"count": count,
"sentNotifications": sentNotifications,
}, nil
}
}
func NewNotificationService(options map[string]interface{}) *NotificationService {
newNotificationService := &NotificationService{}
return newNotificationService
}
... ...
... ... @@ -43,6 +43,7 @@ func (projectBelongService *ProjectBelongService) CreateProjectBelong(createProj
}
if count, _, err := projectBelongRepository.Find(map[string]interface{}{
"projectBelongName": createProjectBelongCommand.ProjectBelongName,
"companyId": createProjectBelongCommand.CompanyId,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
... ... @@ -129,6 +130,7 @@ func (projectBelongService *ProjectBelongService) UpdateProjectBelong(updateProj
}
if count, projectBelongs, err := projectBelongRepository.Find(map[string]interface{}{
"projectBelongName": updateProjectBelongCommand.ProjectBelongName,
"companyId": projectBelong.CompanyId,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
... ...
... ... @@ -43,6 +43,7 @@ func (taskNatureService *TaskNatureService) CreateTaskNature(createTaskNatureCom
}
if count, _, err := taskNatureRepository.Find(map[string]interface{}{
"taskNatureName": createTaskNatureCommand.TaskNatureName,
"companyId": createTaskNatureCommand.CompanyId,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
... ... @@ -129,6 +130,7 @@ func (taskNatureService *TaskNatureService) UpdateTaskNature(updateTaskNatureCom
}
if count, taskNatures, err := taskNatureRepository.Find(map[string]interface{}{
"taskNatureName": updateTaskNatureCommand.TaskNatureName,
"companyId": taskNature.CompanyId,
}); err != nil {
return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
} else {
... ...
package domain
import "time"
const (
NOTIFICATION_TYPE_SYSTEM = iota + 1 //系统通知
NOTIFICATION_TYPE_INTERACTION //互动通知
)
const (
EXTERNAL_RESOURCE_TYPE_TASK = iota + 1 //任务
EXTERNAL_RESOURCE_TYPE_REJECT_TASK_RECORD //驳回任务记录
)
// 通知
type Notification struct {
// 通知ID
NotificationId int64 `json:"notificationId"`
// 通知类型
NotificationType int `json:"notificationType"`
// 通知标题
NotificationTitle string `json:"notificationTitle"`
// 通知内容
NotificationContent string `json:"notificationContent"`
// 通知时间
NotificationTime time.Time `json:"notificationTime"`
// 外部资源引用类型(1任务2驳回任务记录)
ExternalResourceType int `json:"externalResourceType"`
// 外部资源引用
ExternalResource int64 `json:"externalResource"`
}
type NotificationRepository interface {
Save(notification *Notification) (*Notification, error)
Remove(notification *Notification) (*Notification, error)
FindOne(queryOptions map[string]interface{}) (*Notification, error)
Find(queryOptions map[string]interface{}) (int64, []*Notification, error)
}
func (notification *Notification) Identify() interface{} {
if notification.NotificationId == 0 {
return nil
}
return notification.NotificationId
}
... ...
package domain
import "time"
// 发送出的通知
type SentNotification struct {
// 发送出的通知ID
SentNotificationId int64 `json:"sentNotificationId"`
// 通知
Notification *Notification `json:"notification"`
// 通知接收者
Receiver *EmployeeInfo `json:"receiver"`
// 是否已读
IsRead bool `json:"isRead"`
// 通知读取时间
ReadTime time.Time `json:"readTime"`
}
type SentNotificationRepository interface {
Save(sentNotification *SentNotification) (*SentNotification, error)
Remove(sentNotification *SentNotification) (*SentNotification, error)
FindOne(queryOptions map[string]interface{}) (*SentNotification, error)
Find(queryOptions map[string]interface{}) (int64, []*SentNotification, error)
}
func (sentNotification *SentNotification) Identify() interface{} {
if sentNotification.SentNotificationId == 0 {
return nil
}
return sentNotification.SentNotificationId
}
func (sentNotification *SentNotification) Read() error {
sentNotification.IsRead = true
if sentNotification.ReadTime.IsZero() {
sentNotification.ReadTime = time.Now()
}
return nil
}
... ...
package service
import (
coreDomain "github.com/linmadan/egglib-go/core/domain"
)
type ReadAllUnReadSentNotificationService interface {
coreDomain.DomainEventPublisher
ReadAll(receiverUid int64) (int, error)
}
... ...
package service
import (
coreDomain "github.com/linmadan/egglib-go/core/domain"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
)
type ReadSentNotificationService interface {
coreDomain.DomainEventPublisher
Read(sentNotificationId int64) (*domain.SentNotification, error)
}
... ...
package dao
import (
"fmt"
"github.com/go-pg/pg"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"time"
)
type NotificationDao struct {
transactionContext *pgTransaction.TransactionContext
}
func (dao *NotificationDao) ReadAllUnReadSentNotification(receiverId int64) (int, error) {
tx := dao.transactionContext.PgTx
result, err := tx.Query(
pg.Scan(),
`UPDATE sent_notifications SET is_read=?, read_time=? WHERE receiver @> '{"uid":?}'`,
true, time.Now(), receiverId)
if err != nil {
return 0, err
} else {
return result.RowsAffected(), nil
}
}
func NewNotificationDao(transactionContext *pgTransaction.TransactionContext) (*NotificationDao, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &NotificationDao{
transactionContext: transactionContext,
}, nil
}
}
... ...
package domain_service
import (
"fmt"
coreDomain "github.com/linmadan/egglib-go/core/domain"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/dao"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/repository"
)
type ReadAllUnReadSentNotificationService struct {
coreDomain.BaseEventPublisher
transactionContext *pgTransaction.TransactionContext
}
func (service *ReadAllUnReadSentNotificationService) ReadAll(receiverUid int64) (int, error) {
var employeeRepository domain.EmployeeRepository
var notificationDao *dao.NotificationDao
if repository, err := repository.NewEmployeeRepository(service.transactionContext); err != nil {
return 0, err
} else {
employeeRepository = repository
}
if dao, err := dao.NewNotificationDao(service.transactionContext); err != nil {
return 0, err
} else {
notificationDao = dao
}
receiver, err := employeeRepository.FindOne(map[string]interface{}{
"uid": receiverUid,
})
if err != nil {
return 0, err
}
if receiver == nil {
return 0, fmt.Errorf("无效的通知接收者")
}
readCount, err := notificationDao.ReadAllUnReadSentNotification(receiverUid)
if err != nil {
return 0, err
} else {
return readCount, nil
}
}
func NewReadAllUnReadSentNotificationService(transactionContext *pgTransaction.TransactionContext) (*ReadAllUnReadSentNotificationService, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &ReadAllUnReadSentNotificationService{
transactionContext: transactionContext,
}, nil
}
}
... ...
package domain_service
import (
"fmt"
coreDomain "github.com/linmadan/egglib-go/core/domain"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/repository"
)
type ReadSentNotificationService struct {
coreDomain.BaseEventPublisher
transactionContext *pgTransaction.TransactionContext
}
func (service *ReadSentNotificationService) Read(sentNotificationId int64) (*domain.SentNotification, error) {
var sentNotificationRepository domain.SentNotificationRepository
if repository, err := repository.NewSentNotificationRepository(service.transactionContext); err != nil {
return nil, err
} else {
sentNotificationRepository = repository
}
sentNotification, err := sentNotificationRepository.FindOne(map[string]interface{}{
"sentNotificationId": sentNotificationId,
})
if err != nil {
return nil, err
}
if sentNotification == nil {
return nil, fmt.Errorf("无效的任务")
}
if err := sentNotification.Read(); err != nil {
return nil, err
}
if sentNotification, err := sentNotificationRepository.Save(sentNotification); err != nil {
return nil, err
} else {
return sentNotification, nil
}
}
func NewReadSentNotificationService(transactionContext *pgTransaction.TransactionContext) (*ReadSentNotificationService, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &ReadSentNotificationService{
transactionContext: transactionContext,
}, nil
}
}
... ...
... ... @@ -34,6 +34,8 @@ func init() {
(*models.TaskNature)(nil),
(*models.ProjectBelong)(nil),
(*models.RejectTaskRecord)(nil),
(*models.Notification)(nil),
(*models.SentNotification)(nil),
} {
err := DB.CreateTable(model, &orm.CreateTableOptions{
Temp: false,
... ...
package models
import "time"
type Notification struct {
TableName string `pg:"notifications,alias:notification"`
// 通知ID
Id int64
// 通知类型
NotificationType int
// 通知标题
NotificationTitle string
// 通知内容
NotificationContent string
// 通知时间
NotificationTime time.Time
// 外部资源引用类型(1任务)
ExternalResourceType int
// 外部资源引用
ExternalResource int64
}
... ...
package models
import (
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"time"
)
type SentNotification struct {
TableName string `pg:"sent_notifications,alias:sent_notification"`
// 发送出的通知ID
Id int64
NotificationId int64
// 通知
Notification *Notification
// 通知接收者
Receiver *domain.EmployeeInfo
// 是否已读
IsRead bool
// 通知读取时间
ReadTime time.Time
}
... ...
package repository
import (
"fmt"
"github.com/linmadan/egglib-go/utils/snowflake"
"github.com/go-pg/pg"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg/models"
)
type NotificationRepository struct {
transactionContext *pgTransaction.TransactionContext
}
func (repository *NotificationRepository) nextIdentify() (int64, error) {
IdWorker, err := snowflake.NewIdWorker(2)
if err != nil {
return 0, err
}
id, err := IdWorker.NextId()
return id, err
}
func (repository *NotificationRepository) Save(notification *domain.Notification) (*domain.Notification, error) {
tx := repository.transactionContext.PgTx
if notification.Identify() == nil {
if nextId, err := repository.nextIdentify(); err != nil {
return notification, err
} else {
notification.NotificationId = nextId
}
if _, err := tx.QueryOne(
pg.Scan(&notification.NotificationId, &notification.NotificationType, &notification.NotificationTitle, &notification.NotificationContent, &notification.NotificationTime, &notification.ExternalResourceType, &notification.ExternalResource),
"INSERT INTO notifications (id, notification_type, notification_title, notification_content, notification_time, external_resource_type, external_resource) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING id, notification_type, notification_title, notification_content, notification_time, external_resource_type, external_resource",
notification.NotificationId, notification.NotificationType, notification.NotificationTitle, notification.NotificationContent, notification.NotificationTime, notification.ExternalResourceType, notification.ExternalResource); err != nil {
return notification, err
}
} else {
if _, err := tx.QueryOne(
pg.Scan(&notification.NotificationType, &notification.NotificationTitle, &notification.NotificationContent, &notification.NotificationTime, &notification.ExternalResourceType, &notification.ExternalResource),
"UPDATE notifications SET notification_type=?, notification_title=?, notification_content=?, notification_time=?, external_resource_type=?, external_resource=? WHERE id=? RETURNING notification_type, notification_title, notification_content, notification_time, external_resource_type, external_resource",
notification.NotificationType, notification.NotificationTitle, notification.NotificationContent, notification.NotificationTime, notification.ExternalResourceType, notification.ExternalResource, notification.Identify()); err != nil {
return notification, err
}
}
return notification, nil
}
func (repository *NotificationRepository) Remove(notification *domain.Notification) (*domain.Notification, error) {
tx := repository.transactionContext.PgTx
notificationModel := new(models.Notification)
notificationModel.Id = notification.Identify().(int64)
if _, err := tx.Model(notificationModel).WherePK().Delete(); err != nil {
return notification, err
}
return notification, nil
}
func (repository *NotificationRepository) FindOne(queryOptions map[string]interface{}) (*domain.Notification, error) {
tx := repository.transactionContext.PgTx
notificationModel := new(models.Notification)
query := tx.Model(notificationModel)
if notificationId, ok := queryOptions["notificationId"]; ok {
query = query.Where("notification.id = ?", notificationId)
}
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
return nil, fmt.Errorf("没有此资源")
} else {
return nil, err
}
}
if notificationModel.Id == 0 {
return nil, nil
} else {
return repository.transformPgModelToDomainModel(notificationModel)
}
}
func (repository *NotificationRepository) Find(queryOptions map[string]interface{}) (int64, []*domain.Notification, error) {
tx := repository.transactionContext.PgTx
var notificationModels []*models.Notification
notifications := make([]*domain.Notification, 0)
query := tx.Model(&notificationModels)
if offset, ok := queryOptions["offset"]; ok {
offset := offset.(int)
if offset > -1 {
query = query.Offset(offset)
}
} else {
query = query.Offset(0)
}
if limit, ok := queryOptions["limit"]; ok {
limit := limit.(int)
if limit > -1 {
query = query.Limit(limit)
}
} else {
query = query.Limit(20)
}
if count, err := query.Order("id DESC").SelectAndCount(); err != nil {
return 0, notifications, err
} else {
for _, notificationModel := range notificationModels {
if notification, err := repository.transformPgModelToDomainModel(notificationModel); err != nil {
return 0, notifications, err
} else {
notifications = append(notifications, notification)
}
}
return int64(count), notifications, nil
}
}
func (repository *NotificationRepository) transformPgModelToDomainModel(notificationModel *models.Notification) (*domain.Notification, error) {
return &domain.Notification{
NotificationId: notificationModel.Id,
NotificationType: notificationModel.NotificationType,
NotificationTitle: notificationModel.NotificationTitle,
NotificationContent: notificationModel.NotificationContent,
NotificationTime: notificationModel.NotificationTime,
ExternalResourceType: notificationModel.ExternalResourceType,
ExternalResource: notificationModel.ExternalResource,
}, nil
}
func NewNotificationRepository(transactionContext *pgTransaction.TransactionContext) (*NotificationRepository, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &NotificationRepository{
transactionContext: transactionContext,
}, nil
}
}
... ...
package repository
import (
"fmt"
"github.com/linmadan/egglib-go/utils/snowflake"
"github.com/go-pg/pg"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg/models"
)
type SentNotificationRepository struct {
transactionContext *pgTransaction.TransactionContext
}
func (repository *SentNotificationRepository) nextIdentify() (int64, error) {
IdWorker, err := snowflake.NewIdWorker(3)
if err != nil {
return 0, err
}
id, err := IdWorker.NextId()
return id, err
}
func (repository *SentNotificationRepository) Save(sentNotification *domain.SentNotification) (*domain.SentNotification, error) {
tx := repository.transactionContext.PgTx
if sentNotification.Identify() == nil {
if nextId, err := repository.nextIdentify(); err != nil {
return sentNotification, err
} else {
sentNotification.SentNotificationId = nextId
}
if _, err := tx.QueryOne(
pg.Scan(&sentNotification.SentNotificationId, &sentNotification.Notification.NotificationId, &sentNotification.Receiver, &sentNotification.IsRead, &sentNotification.ReadTime),
"INSERT INTO sent_notifications (id, notification_id, receiver, is_read, read_time) VALUES (?, ?, ?, ?, ?) RETURNING id, notification_id, receiver, is_read, read_time",
sentNotification.SentNotificationId, sentNotification.Notification.NotificationId, sentNotification.Receiver, sentNotification.IsRead, sentNotification.ReadTime); err != nil {
return sentNotification, err
}
} else {
if _, err := tx.QueryOne(
pg.Scan(&sentNotification.SentNotificationId, &sentNotification.Notification.NotificationId, &sentNotification.Receiver, &sentNotification.IsRead, &sentNotification.ReadTime),
"UPDATE sent_notifications SET notification_id=?, receiver=?, is_read=?, read_time=? WHERE id=? RETURNING id, notification_id, receiver, is_read, read_time",
sentNotification.Notification.NotificationId, sentNotification.Receiver, sentNotification.IsRead, sentNotification.ReadTime, sentNotification.Identify()); err != nil {
return sentNotification, err
}
}
return sentNotification, nil
}
func (repository *SentNotificationRepository) Remove(sentNotification *domain.SentNotification) (*domain.SentNotification, error) {
tx := repository.transactionContext.PgTx
sentNotificationModel := new(models.SentNotification)
sentNotificationModel.Id = sentNotification.Identify().(int64)
if _, err := tx.Model(sentNotificationModel).WherePK().Delete(); err != nil {
return sentNotification, err
}
return sentNotification, nil
}
func (repository *SentNotificationRepository) FindOne(queryOptions map[string]interface{}) (*domain.SentNotification, error) {
tx := repository.transactionContext.PgTx
sentNotificationModel := new(models.SentNotification)
query := tx.Model(sentNotificationModel).Relation("Notification")
if sentNotificationId, ok := queryOptions["sentNotificationId"]; ok {
query = query.Where("sent_notification.id = ?", sentNotificationId)
}
if err := query.First(); err != nil {
if err.Error() == "pg: no rows in result set" {
return nil, fmt.Errorf("没有此资源")
} else {
return nil, err
}
}
if sentNotificationModel.Id == 0 {
return nil, nil
} else {
return repository.transformPgModelToDomainModel(sentNotificationModel)
}
}
func (repository *SentNotificationRepository) Find(queryOptions map[string]interface{}) (int64, []*domain.SentNotification, error) {
tx := repository.transactionContext.PgTx
var sentNotificationModels []*models.SentNotification
sentNotifications := make([]*domain.SentNotification, 0)
query := tx.Model(&sentNotificationModels).Relation("Notification")
if receiver, ok := queryOptions["receiver"]; ok && (receiver != int64(0)) {
query = query.Where(`sent_notification.receiver @> '{"uid":?}'`, receiver)
}
if notificationType, ok := queryOptions["notificationType"]; ok && (notificationType != int(0)) {
query = query.Where("notification.notification_type = ?", notificationType)
}
if offset, ok := queryOptions["offset"]; ok {
offset := offset.(int)
if offset > -1 {
query = query.Offset(offset)
}
} else {
query = query.Offset(0)
}
if limit, ok := queryOptions["limit"]; ok {
limit := limit.(int)
if limit > -1 {
query = query.Limit(limit)
}
} else {
query = query.Limit(20)
}
if count, err := query.Order("id DESC").SelectAndCount(); err != nil {
return 0, sentNotifications, err
} else {
for _, sentNotificationModel := range sentNotificationModels {
if sentNotification, err := repository.transformPgModelToDomainModel(sentNotificationModel); err != nil {
return 0, sentNotifications, err
} else {
sentNotifications = append(sentNotifications, sentNotification)
}
}
return int64(count), sentNotifications, nil
}
}
func (repository *SentNotificationRepository) transformPgModelToDomainModel(sentNotificationModel *models.SentNotification) (*domain.SentNotification, error) {
var notification *domain.Notification
if sentNotificationModel.Notification == nil {
notification = nil
} else {
notification = &domain.Notification{
NotificationId: sentNotificationModel.Notification.Id,
NotificationType: sentNotificationModel.Notification.NotificationType,
NotificationTitle: sentNotificationModel.Notification.NotificationTitle,
NotificationContent: sentNotificationModel.Notification.NotificationContent,
NotificationTime: sentNotificationModel.Notification.NotificationTime,
ExternalResourceType: sentNotificationModel.Notification.ExternalResourceType,
ExternalResource: sentNotificationModel.Notification.ExternalResource,
}
}
return &domain.SentNotification{
SentNotificationId: sentNotificationModel.Id,
Notification: notification,
Receiver: sentNotificationModel.Receiver,
IsRead: sentNotificationModel.IsRead,
ReadTime: sentNotificationModel.ReadTime,
}, nil
}
func NewSentNotificationRepository(transactionContext *pgTransaction.TransactionContext) (*SentNotificationRepository, error) {
if transactionContext == nil {
return nil, fmt.Errorf("transactionContext参数不能为nil")
} else {
return &SentNotificationRepository{
transactionContext: transactionContext,
}, nil
}
}
... ...
... ... @@ -23,6 +23,7 @@ func (repository *TaskRepository) nextIdentify() (int64, error) {
id, err := IdWorker.NextId()
return id, err
}
func (repository *TaskRepository) Save(task *domain.Task) (*domain.Task, error) {
tx := repository.transactionContext.PgTx
if task.Identify() == nil {
... ...
package controllers
import (
"encoding/json"
"github.com/astaxie/beego"
"github.com/linmadan/egglib-go/web/beego/utils"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/application/notification/command"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/application/notification/query"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/application/notification/service"
)
type NotificationController struct {
beego.Controller
}
func (controller *NotificationController) ReadSentNotification() {
notificationService := service.NewNotificationService(nil)
readSentNotificationCommand := &command.ReadSentNotificationCommand{}
json.Unmarshal(controller.Ctx.Input.GetData("requestBody").([]byte), readSentNotificationCommand)
data, err := notificationService.ReadSentNotification(readSentNotificationCommand)
var response utils.JsonResponse
if err != nil {
response = utils.ResponseError(controller.Ctx, err)
} else {
response = utils.ResponseData(controller.Ctx, data)
}
controller.Data["json"] = response
controller.ServeJSON()
}
func (controller *NotificationController) ReadAllUnReadSentNotification() {
notificationService := service.NewNotificationService(nil)
readAllUnReadSentNotificationCommand := &command.ReadAllUnReadSentNotificationCommand{}
json.Unmarshal(controller.Ctx.Input.GetData("requestBody").([]byte), readAllUnReadSentNotificationCommand)
data, err := notificationService.ReadAllUnReadSentNotification(readAllUnReadSentNotificationCommand)
var response utils.JsonResponse
if err != nil {
response = utils.ResponseError(controller.Ctx, err)
} else {
response = utils.ResponseData(controller.Ctx, data)
}
controller.Data["json"] = response
controller.ServeJSON()
}
func (controller *NotificationController) ListSentNotification() {
notificationService := service.NewNotificationService(nil)
listSentNotificationQuery := &query.ListSentNotificationQuery{}
receiverId, _ := controller.GetInt64("receiverId")
listSentNotificationQuery.ReceiverId = receiverId
notificationType, _ := controller.GetInt("notificationType")
listSentNotificationQuery.NotificationType = notificationType
offset, _ := controller.GetInt("offset")
listSentNotificationQuery.Offset = offset
limit, _ := controller.GetInt("limit")
listSentNotificationQuery.Limit = limit
data, err := notificationService.ListSentNotification(listSentNotificationQuery)
var response utils.JsonResponse
if err != nil {
response = utils.ResponseError(controller.Ctx, err)
} else {
response = utils.ResponseData(controller.Ctx, data)
}
controller.Data["json"] = response
controller.ServeJSON()
}
... ...
package routers
import (
"github.com/astaxie/beego"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/port/beego/controllers"
)
func init() {
beego.Router("/notifications/read", &controllers.NotificationController{}, "Post:ReadSentNotification")
beego.Router("/notifications/read-all", &controllers.NotificationController{}, "Post:ReadAllUnReadSentNotification")
beego.Router("/notifications/", &controllers.NotificationController{}, "Get:ListSentNotification")
}
... ...
package notification
import (
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"net/http"
"time"
"github.com/gavv/httpexpect"
"github.com/go-pg/pg"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
pG "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg"
)
var _ = Describe("返回发送出的通知列表", func() {
var notificationId int64
var sentNotificationId int64
BeforeEach(func() {
_, err := pG.DB.QueryOne(
pg.Scan(&notificationId),
"INSERT INTO notifications (id, notification_type, notification_title, notification_content, notification_time, external_resource_type, external_resource) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING id",
1, 1, "testNotificationTitle", "testNotificationContent", time.Now(), 1, 1)
Expect(err).NotTo(HaveOccurred())
_, err1 := pG.DB.QueryOne(
pg.Scan(&sentNotificationId),
"INSERT INTO sent_notifications (id, notification_id, receiver, is_read, read_time) VALUES (?, ?, ?, ?, ?) RETURNING id",
1, notificationId, &domain.EmployeeInfo{
Uid: 2499036607974745088,
}, false, time.Time{})
Expect(err1).NotTo(HaveOccurred())
_, err2 := pG.DB.QueryOne(
pg.Scan(),
"INSERT INTO employees (id, company_id, uid, employee_name, employee_account, su_money) VALUES (?, ?, ?, ?, ?, ?)",
1, 101, 2499036607974745088, "testEmployeeName", "testEmployeeAccount", 0)
Expect(err2).NotTo(HaveOccurred())
})
Describe("返回发送出的通知列表", func() {
Context("", func() {
It("", func() {
httpExpect := httpexpect.New(GinkgoT(), server.URL)
httpExpect.GET("/notifications").
WithQuery("receiverId", 2499036607974745088).
WithQuery("notificationType", 1).
WithQuery("offset", 0).
WithQuery("limit", 20).
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "ok").
ContainsKey("data").Value("data").Object()
})
})
})
AfterEach(func() {
_, err := pG.DB.Exec("DELETE FROM sent_notifications WHERE true")
Expect(err).NotTo(HaveOccurred())
_, err1 := pG.DB.Exec("DELETE FROM notifications WHERE true")
Expect(err1).NotTo(HaveOccurred())
_, err2 := pG.DB.Exec("DELETE FROM employees WHERE true")
Expect(err2).NotTo(HaveOccurred())
})
})
... ...
package notification
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/astaxie/beego"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
_ "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg"
_ "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/port/beego"
)
func TestNotification(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Beego Port Notification Correlations Test Case Suite")
}
var handler http.Handler
var server *httptest.Server
var _ = BeforeSuite(func() {
handler = beego.BeeApp.Handlers
server = httptest.NewServer(handler)
})
var _ = AfterSuite(func() {
server.Close()
})
... ...
package notification
import (
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
"net/http"
"time"
"github.com/gavv/httpexpect"
"github.com/go-pg/pg"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
pG "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg"
)
var _ = Describe("读取全部未读取的发送出的通知", func() {
var notificationId int64
var sentNotificationId int64
BeforeEach(func() {
_, err := pG.DB.QueryOne(
pg.Scan(&notificationId),
"INSERT INTO notifications (id, notification_type, notification_title, notification_content, notification_time, external_resource_type, external_resource) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING id",
1, 1, "testNotificationTitle", "testNotificationContent", time.Now(), 1, 1)
Expect(err).NotTo(HaveOccurred())
_, err1 := pG.DB.QueryOne(
pg.Scan(&sentNotificationId),
"INSERT INTO sent_notifications (id, notification_id, receiver, is_read, read_time) VALUES (?, ?, ?, ?, ?) RETURNING id",
1, notificationId, &domain.EmployeeInfo{
Uid: 2499036607974745088,
}, false, time.Time{})
Expect(err1).NotTo(HaveOccurred())
_, err2 := pG.DB.QueryOne(
pg.Scan(),
"INSERT INTO employees (id, company_id, uid, employee_name, employee_account, su_money) VALUES (?, ?, ?, ?, ?, ?)",
1, 101, 2499036607974745088, "testEmployeeName", "testEmployeeAccount", 0)
Expect(err2).NotTo(HaveOccurred())
})
Describe("读取全部未读取的发送出的通知", func() {
Context("读取通知接收者全部未读取的发送出的通知", func() {
It("读取成功", func() {
httpExpect := httpexpect.New(GinkgoT(), server.URL)
body := map[string]interface{}{
"receiverId": 2499036607974745088,
}
httpExpect.POST("/notifications/read-all").
WithJSON(body).
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "ok").
ContainsKey("data").ValueEqual("data", 1)
})
})
})
AfterEach(func() {
_, err := pG.DB.Exec("DELETE FROM sent_notifications WHERE true")
Expect(err).NotTo(HaveOccurred())
_, err1 := pG.DB.Exec("DELETE FROM notifications WHERE true")
Expect(err1).NotTo(HaveOccurred())
_, err2 := pG.DB.Exec("DELETE FROM employees WHERE true")
Expect(err2).NotTo(HaveOccurred())
})
})
... ...
package notification
import (
"github.com/gavv/httpexpect"
"github.com/go-pg/pg"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/domain"
pG "gitlab.fjmaimaimai.com/linmadan/mmm-worth/pkg/infrastructure/pg"
"net/http"
"time"
)
var _ = Describe("读取发送出的通知", func() {
var notificationId int64
var sentNotificationId int64
BeforeEach(func() {
_, err := pG.DB.QueryOne(
pg.Scan(&notificationId),
"INSERT INTO notifications (id, notification_type, notification_title, notification_content, notification_time, external_resource_type, external_resource) VALUES (?, ?, ?, ?, ?, ?, ?) RETURNING id",
1, 1, "testNotificationTitle", "testNotificationContent", time.Now(), 1, 1)
Expect(err).NotTo(HaveOccurred())
_, err1 := pG.DB.QueryOne(
pg.Scan(&sentNotificationId),
"INSERT INTO sent_notifications (id, notification_id, receiver, is_read, read_time) VALUES (?, ?, ?, ?, ?) RETURNING id",
1, notificationId, &domain.EmployeeInfo{
Uid: 2499036607974745088,
}, false, time.Time{})
Expect(err1).NotTo(HaveOccurred())
})
Describe("读取发送出的通知", func() {
Context("读取正确sentNotificationId的发送出的通知", func() {
It("读取成功", func() {
httpExpect := httpexpect.New(GinkgoT(), server.URL)
body := map[string]interface{}{
"sentNotificationId": sentNotificationId,
}
httpExpect.POST("/notifications/read").
WithJSON(body).
Expect().
Status(http.StatusOK).
JSON().
Object().
ContainsKey("code").ValueEqual("code", 0).
ContainsKey("msg").ValueEqual("msg", "ok").
ContainsKey("data").Value("data").Object().
ContainsKey("isRead").ValueEqual("isRead", true)
})
})
})
AfterEach(func() {
_, err := pG.DB.Exec("DELETE FROM sent_notifications WHERE true")
Expect(err).NotTo(HaveOccurred())
_, err1 := pG.DB.Exec("DELETE FROM notifications WHERE true")
Expect(err1).NotTo(HaveOccurred())
})
})
... ...