9037cb5917
- Updated the notification handling logic to utilize a new SDK for sending notifications, improving the flexibility and scalability of the notification system. - Introduced new methods in the notification service for sending notifications to users and customers based on various target audience types, enhancing the notification delivery capabilities. - Added a new endpoint to assign companies to a customer, improving customer management functionalities. - Refactored the customer entity and forms to replace 'CompanyIDs' with 'Companies', ensuring consistency across the data model. - Enhanced API documentation with Swagger comments for the new endpoint and updated notification structures, ensuring clarity for API consumers.
245 lines
6.6 KiB
Go
245 lines
6.6 KiB
Go
package notification
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"tm/internal/customer"
|
|
"tm/internal/user"
|
|
"tm/pkg/logger"
|
|
"tm/pkg/notification"
|
|
"tm/pkg/response"
|
|
)
|
|
|
|
// NotificationService defines the interface for notification business logic
|
|
type Service interface {
|
|
Send(ctx context.Context, req *NotificationRequest) error
|
|
getUsers(ctx context.Context, userIDs []string) ([]notificationRecipient, error)
|
|
getCustomers(ctx context.Context, values []string, target string) ([]notificationRecipient, error)
|
|
}
|
|
|
|
// notificationService implements NotificationService interface
|
|
type notificationService struct {
|
|
sdk notification.SDK
|
|
userService user.Service
|
|
customerService customer.Service
|
|
logger logger.Logger
|
|
}
|
|
|
|
// NewNotificationService creates a new notification service
|
|
func NewNotificationService(
|
|
sdk notification.SDK,
|
|
userService user.Service,
|
|
customerService customer.Service,
|
|
logger logger.Logger,
|
|
) Service {
|
|
return ¬ificationService{
|
|
sdk: sdk,
|
|
userService: userService,
|
|
customerService: customerService,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// Send sends a multiple notification
|
|
func (s *notificationService) Send(ctx context.Context, req *NotificationRequest) error {
|
|
s.logger.Info("Sending notification", map[string]interface{}{
|
|
"recipient": req.Recipient,
|
|
"type": req.Type,
|
|
"priority": req.Priority,
|
|
})
|
|
|
|
if req.Target == TargetAudienceAllUsers || req.Target == TargetAudienceSpecificUsers {
|
|
recipients, err := s.getUsers(ctx, req.Recipient)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, recipient := range recipients {
|
|
for _, v := range recipient.DeviceTokens {
|
|
s.sdk.SendNotification(ctx, ¬ification.NotificationRequest{
|
|
UserID: recipient.UserID,
|
|
Title: req.Title,
|
|
Message: req.Description,
|
|
Type: string(req.Type),
|
|
Priority: string(req.Priority),
|
|
EventType: notification.EventTypePush,
|
|
Metadata: map[string]any{
|
|
"tender": req.Tender,
|
|
},
|
|
Methods: notification.NotificationMethods{
|
|
Push: v,
|
|
},
|
|
|
|
ScheduledAt: req.ScheduleAt,
|
|
})
|
|
}
|
|
|
|
if recipient.Email != "" {
|
|
s.sdk.SendNotification(ctx, ¬ification.NotificationRequest{
|
|
UserID: recipient.UserID,
|
|
Title: req.Title,
|
|
Message: req.Description,
|
|
Type: string(req.Type),
|
|
Priority: string(req.Priority),
|
|
EventType: notification.EventTypeEmail,
|
|
Metadata: map[string]any{
|
|
"tender": req.Tender,
|
|
},
|
|
Methods: notification.NotificationMethods{
|
|
Email: recipient.Email,
|
|
},
|
|
ScheduledAt: req.ScheduleAt,
|
|
})
|
|
}
|
|
}
|
|
} else {
|
|
recipients, err := s.getCustomers(ctx, req.Recipient, string(req.Target))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, recipient := range recipients {
|
|
for _, v := range recipient.DeviceTokens {
|
|
s.sdk.SendNotification(ctx, ¬ification.NotificationRequest{
|
|
UserID: recipient.UserID,
|
|
Title: req.Title,
|
|
Message: req.Description,
|
|
Type: string(req.Type),
|
|
Priority: string(req.Priority),
|
|
EventType: notification.EventTypePush,
|
|
Methods: notification.NotificationMethods{
|
|
Push: v,
|
|
},
|
|
ScheduledAt: req.ScheduleAt,
|
|
})
|
|
}
|
|
|
|
if recipient.Email != "" {
|
|
s.sdk.SendNotification(ctx, ¬ification.NotificationRequest{
|
|
UserID: recipient.UserID,
|
|
Title: req.Title,
|
|
Message: req.Description,
|
|
Type: string(req.Type),
|
|
Priority: string(req.Priority),
|
|
EventType: notification.EventTypeEmail,
|
|
Methods: notification.NotificationMethods{
|
|
Email: recipient.Email,
|
|
},
|
|
ScheduledAt: req.ScheduleAt,
|
|
})
|
|
}
|
|
}
|
|
s.logger.Info("Notification sent", map[string]interface{}{
|
|
"recipient": req.Recipient,
|
|
"channels": req.Channels,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *notificationService) getUsers(ctx context.Context, userIDs []string) ([]notificationRecipient, error) {
|
|
recipients := make([]notificationRecipient, 0)
|
|
offset := 0
|
|
for {
|
|
var users *user.UserListResponse
|
|
var err error
|
|
if len(userIDs) > 0 {
|
|
users, err = s.userService.GetUsersByIDs(ctx, userIDs)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
users, err = s.userService.Search(ctx, &user.SearchUsersForm{}, &response.Pagination{Limit: 100, Offset: offset})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
offset += 100
|
|
if len(users.Users) == 0 {
|
|
break
|
|
}
|
|
}
|
|
|
|
for _, user := range users.Users {
|
|
recipients = append(recipients, notificationRecipient{
|
|
UserID: user.ID,
|
|
Email: user.Email,
|
|
DeviceTokens: user.DeviceToken,
|
|
})
|
|
}
|
|
|
|
if len(recipients) == 0 {
|
|
return nil, errors.New("no users found")
|
|
}
|
|
}
|
|
|
|
return recipients, nil
|
|
}
|
|
|
|
func (s *notificationService) getCustomers(ctx context.Context, values []string, target string) ([]notificationRecipient, error) {
|
|
recipients := make([]notificationRecipient, 0)
|
|
|
|
if target == string(TargetAudienceSpecificRole) {
|
|
customers, err := s.customerService.GetCustomersByRole(ctx, values[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, customer := range customers.Customers {
|
|
recipients = append(recipients, notificationRecipient{
|
|
UserID: customer.ID,
|
|
Email: customer.Email,
|
|
DeviceTokens: customer.DeviceToken,
|
|
})
|
|
}
|
|
} else if target == string(TargetAudienceSpecificCompany) {
|
|
customers, err := s.customerService.GetCustomersByCompanies(ctx, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, customer := range customers.Customers {
|
|
recipients = append(recipients, notificationRecipient{
|
|
UserID: customer.ID,
|
|
Email: customer.Email,
|
|
DeviceTokens: customer.DeviceToken,
|
|
})
|
|
}
|
|
} else if target == string(TargetAudienceSpecificCustomer) {
|
|
customers, err := s.customerService.GetCustomersByIDs(ctx, values)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, customer := range customers.Customers {
|
|
recipients = append(recipients, notificationRecipient{
|
|
UserID: customer.ID,
|
|
Email: customer.Email,
|
|
DeviceTokens: customer.DeviceToken,
|
|
})
|
|
}
|
|
} else {
|
|
offset := 0
|
|
for {
|
|
customers, err := s.customerService.Search(ctx, &customer.SearchCustomersForm{}, &response.Pagination{Limit: 100, Offset: offset})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, customer := range customers.Customers {
|
|
recipients = append(recipients, notificationRecipient{
|
|
UserID: customer.ID,
|
|
Email: customer.Email,
|
|
DeviceTokens: customer.DeviceToken,
|
|
})
|
|
}
|
|
offset += 100
|
|
if len(customers.Customers) == 0 {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(recipients) == 0 {
|
|
return nil, errors.New("no customers found")
|
|
}
|
|
|
|
return recipients, nil
|
|
}
|