narasiahli-be/app/module/chat/service/chat_schedule.service.go

312 lines
9.8 KiB
Go
Raw Normal View History

2025-09-22 18:47:06 +00:00
package service
import (
"errors"
"narasi-ahli-be/app/database/entity"
"narasi-ahli-be/app/module/chat/mapper"
"narasi-ahli-be/app/module/chat/repository"
"narasi-ahli-be/app/module/chat/request"
usersRepository "narasi-ahli-be/app/module/users/repository"
"narasi-ahli-be/utils/paginator"
utilSvc "narasi-ahli-be/utils/service"
"time"
"github.com/rs/zerolog"
)
type chatScheduleService struct {
chatScheduleRepository repository.ChatScheduleRepository
chatRepository repository.ChatRepository
2025-09-23 22:21:47 +00:00
chatService ChatService
2025-09-22 18:47:06 +00:00
chatScheduleMapper *mapper.ChatScheduleMapper
Log zerolog.Logger
UsersRepo usersRepository.UsersRepository
}
type ChatScheduleService interface {
// Chat Schedule CRUD operations
CreateChatSchedule(authToken string, req request.ChatScheduleCreateRequest) (dataResult *mapper.ChatScheduleResponse, err error)
GetAllChatSchedules(authToken string, req request.ChatScheduleQueryRequest) (schedules []*mapper.ChatScheduleResponse, paging paginator.Pagination, err error)
GetChatScheduleByID(authToken string, id uint) (schedule *mapper.ChatScheduleResponse, err error)
UpdateChatSchedule(authToken string, id uint, req request.ChatScheduleUpdateRequest) (err error)
DeleteChatSchedule(authToken string, id uint) (err error)
// Additional schedule operations
GetUpcomingSchedules(authToken string, limit int) (schedules []*mapper.ChatScheduleResponse, err error)
GetSchedulesByStatus(authToken string, status string) (schedules []*mapper.ChatScheduleResponse, err error)
SendScheduleReminder(authToken string, scheduleID uint) (err error)
}
func NewChatScheduleService(
chatScheduleRepository repository.ChatScheduleRepository,
chatRepository repository.ChatRepository,
2025-09-23 22:21:47 +00:00
chatService ChatService,
2025-09-22 18:47:06 +00:00
log zerolog.Logger,
usersRepo usersRepository.UsersRepository,
) ChatScheduleService {
return &chatScheduleService{
chatScheduleRepository: chatScheduleRepository,
chatRepository: chatRepository,
2025-09-23 22:21:47 +00:00
chatService: chatService,
2025-09-22 18:47:06 +00:00
chatScheduleMapper: mapper.NewChatScheduleMapper(),
Log: log,
UsersRepo: usersRepo,
}
}
// CreateChatSchedule - Create a new chat schedule
func (_i *chatScheduleService) CreateChatSchedule(authToken string, req request.ChatScheduleCreateRequest) (dataResult *mapper.ChatScheduleResponse, err error) {
userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if userInfo == nil {
return nil, errors.New("user not found")
}
userID := userInfo.ID
// Validate that the scheduled time is in the future
if req.ScheduledAt.Before(time.Now()) {
return nil, errors.New("scheduled time must be in the future")
}
2025-09-23 22:21:47 +00:00
var chatSessionID uint
// If ChatSessionID is not provided, create a new chat session
if req.ChatSessionID == nil {
// Create a new personal chat session for the schedule
chatSessionReq := request.ChatSessionCreateRequest{
Name: &req.Title, // Use schedule title as chat session name
Type: "group", // Default to group chat for schedules
UserIDs: []uint{}, // Empty for now, can be populated later
}
chatSession, err := _i.chatService.CreateChatSession(authToken, chatSessionReq)
if err != nil {
return nil, errors.New("failed to create chat session: " + err.Error())
}
chatSessionID = chatSession.ID
} else {
chatSessionID = *req.ChatSessionID
// Check if user is participant in the existing chat session
isParticipant, err := _i.chatRepository.CheckUserInChatSession(userID, chatSessionID)
if err != nil {
return nil, err
}
2025-09-22 18:47:06 +00:00
2025-09-23 22:21:47 +00:00
if !isParticipant {
return nil, errors.New("user is not a participant in this chat session")
}
2025-09-22 18:47:06 +00:00
}
// Convert request to entity
schedule := _i.chatScheduleMapper.ToEntity(req)
2025-09-23 22:21:47 +00:00
schedule.ChatSessionID = chatSessionID
2025-09-22 18:47:06 +00:00
schedule.CreatedBy = userID
// Create schedule
result, err := _i.chatScheduleRepository.CreateChatSchedule(schedule)
if err != nil {
return nil, err
}
// Convert to response
dataResult = _i.chatScheduleMapper.ToResponse(result)
return
}
// GetAllChatSchedules - Get all chat schedules for a user
func (_i *chatScheduleService) GetAllChatSchedules(authToken string, req request.ChatScheduleQueryRequest) (schedules []*mapper.ChatScheduleResponse, paging paginator.Pagination, err error) {
userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if userInfo == nil {
return nil, paginator.Pagination{}, errors.New("user not found")
}
userID := userInfo.ID
// Get schedules from repository
scheduleEntities, paging, err := _i.chatScheduleRepository.GetAllChatSchedules(userID, req)
if err != nil {
return nil, paginator.Pagination{}, err
}
// Convert to response
schedules = _i.chatScheduleMapper.ToResponseList(scheduleEntities)
return
}
// GetChatScheduleByID - Get a specific chat schedule
func (_i *chatScheduleService) GetChatScheduleByID(authToken string, id uint) (schedule *mapper.ChatScheduleResponse, err error) {
// Get schedule from repository
scheduleEntity, err := _i.chatScheduleRepository.GetChatScheduleByID(id)
if err != nil {
return nil, err
}
// Convert to response
schedule = _i.chatScheduleMapper.ToResponse(scheduleEntity)
return
}
// UpdateChatSchedule - Update a chat schedule
func (_i *chatScheduleService) UpdateChatSchedule(authToken string, id uint, req request.ChatScheduleUpdateRequest) (err error) {
userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if userInfo == nil {
return errors.New("user not found")
}
userID := userInfo.ID
// Check if user is participant in the chat session
isParticipant, err := _i.chatScheduleRepository.CheckUserInChatSchedule(userID, id)
if err != nil {
return err
}
if !isParticipant {
return errors.New("user is not a participant in this chat session")
}
// Get existing schedule to check if user is the creator
existingSchedule, err := _i.chatScheduleRepository.GetChatScheduleByID(id)
if err != nil {
return err
}
// Only creator can update the schedule
if existingSchedule.CreatedBy != userID {
return errors.New("only the creator can update this schedule")
}
// Validate scheduled time if provided
if !req.ScheduledAt.IsZero() && req.ScheduledAt.Before(time.Now()) {
return errors.New("scheduled time must be in the future")
}
// Convert request to entity
schedule := _i.chatScheduleMapper.ToUpdateEntity(req)
// Update schedule
err = _i.chatScheduleRepository.UpdateChatSchedule(id, schedule)
return
}
// DeleteChatSchedule - Delete a chat schedule
func (_i *chatScheduleService) DeleteChatSchedule(authToken string, id uint) (err error) {
userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if userInfo == nil {
return errors.New("user not found")
}
userID := userInfo.ID
// Get existing schedule to check if user is the creator
existingSchedule, err := _i.chatScheduleRepository.GetChatScheduleByID(id)
if err != nil {
return err
}
// Only creator can delete the schedule
if existingSchedule.CreatedBy != userID {
return errors.New("only the creator can delete this schedule")
}
// Delete schedule
err = _i.chatScheduleRepository.DeleteChatSchedule(id)
return
}
// GetUpcomingSchedules - Get upcoming schedules for a user
func (_i *chatScheduleService) GetUpcomingSchedules(authToken string, limit int) (schedules []*mapper.ChatScheduleResponse, err error) {
userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if userInfo == nil {
return nil, errors.New("user not found")
}
userID := userInfo.ID
// Get upcoming schedules from repository
scheduleEntities, err := _i.chatScheduleRepository.GetUpcomingSchedules(userID, limit)
if err != nil {
return nil, err
}
// Convert to response
schedules = _i.chatScheduleMapper.ToResponseList(scheduleEntities)
return
}
// GetSchedulesByStatus - Get schedules by status
func (_i *chatScheduleService) GetSchedulesByStatus(authToken string, status string) (schedules []*mapper.ChatScheduleResponse, err error) {
userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if userInfo == nil {
return nil, errors.New("user not found")
}
userID := userInfo.ID
// Validate status
validStatuses := []string{"scheduled", "ongoing", "completed", "cancelled"}
isValidStatus := false
for _, validStatus := range validStatuses {
if status == validStatus {
isValidStatus = true
break
}
}
if !isValidStatus {
return nil, errors.New("invalid status")
}
// Get schedules by status from repository
scheduleEntities, err := _i.chatScheduleRepository.GetSchedulesByStatus(status)
if err != nil {
return nil, err
}
// Filter by user participation
var userSchedules []*entity.ChatSchedules
for _, schedule := range scheduleEntities {
isParticipant, err := _i.chatScheduleRepository.CheckUserInChatSchedule(userID, schedule.ID)
if err != nil {
continue
}
if isParticipant {
userSchedules = append(userSchedules, schedule)
}
}
// Convert to response
schedules = _i.chatScheduleMapper.ToResponseList(userSchedules)
return
}
// SendScheduleReminder - Send reminder for a schedule
func (_i *chatScheduleService) SendScheduleReminder(authToken string, scheduleID uint) (err error) {
userInfo := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
if userInfo == nil {
return errors.New("user not found")
}
userID := userInfo.ID
// Get schedule
schedule, err := _i.chatScheduleRepository.GetChatScheduleByID(scheduleID)
if err != nil {
return err
}
// Only creator can send reminders
if schedule.CreatedBy != userID {
return errors.New("only the creator can send reminders")
}
// Check if reminder was already sent
if schedule.IsReminderSent {
return errors.New("reminder has already been sent")
}
// TODO: Implement actual reminder sending logic (email, push notification, etc.)
// For now, just update the reminder status
now := time.Now()
schedule.IsReminderSent = true
schedule.ReminderSentAt = &now
err = _i.chatScheduleRepository.UpdateChatSchedule(scheduleID, schedule)
return
}