165 lines
4.9 KiB
Go
165 lines
4.9 KiB
Go
package team
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"Yimaru-Backend/internal/domain"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
const bcryptCost = 10
|
|
|
|
func (s *Service) CreateTeamMember(ctx context.Context, req domain.CreateTeamMemberReq, createdBy *int64) (domain.TeamMember, error) {
|
|
if !domain.TeamRole(req.TeamRole).IsValid() {
|
|
return domain.TeamMember{}, domain.ErrInvalidTeamRole
|
|
}
|
|
|
|
if req.EmploymentType != "" && !domain.EmploymentType(req.EmploymentType).IsValid() {
|
|
return domain.TeamMember{}, domain.ErrInvalidEmploymentType
|
|
}
|
|
|
|
exists, err := s.teamStore.CheckTeamMemberEmailExists(ctx, req.Email)
|
|
if err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
if exists {
|
|
return domain.TeamMember{}, domain.ErrTeamMemberEmailExists
|
|
}
|
|
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcryptCost)
|
|
if err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
|
|
var hireDate *time.Time
|
|
if req.HireDate != "" {
|
|
parsed, err := time.Parse("2006-01-02", req.HireDate)
|
|
if err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
hireDate = &parsed
|
|
}
|
|
|
|
member := domain.TeamMember{
|
|
FirstName: req.FirstName,
|
|
LastName: req.LastName,
|
|
Email: req.Email,
|
|
PhoneNumber: req.PhoneNumber,
|
|
Password: hashedPassword,
|
|
TeamRole: domain.TeamRole(req.TeamRole),
|
|
Department: req.Department,
|
|
JobTitle: req.JobTitle,
|
|
EmploymentType: domain.EmploymentType(req.EmploymentType),
|
|
HireDate: hireDate,
|
|
ProfilePictureURL: req.ProfilePictureURL,
|
|
Bio: req.Bio,
|
|
WorkPhone: req.WorkPhone,
|
|
EmergencyContact: req.EmergencyContact,
|
|
Status: domain.TeamMemberStatusActive,
|
|
Permissions: req.Permissions,
|
|
CreatedBy: createdBy,
|
|
}
|
|
|
|
return s.teamStore.CreateTeamMember(ctx, member)
|
|
}
|
|
|
|
func (s *Service) GetTeamMemberByID(ctx context.Context, id int64) (domain.TeamMember, error) {
|
|
return s.teamStore.GetTeamMemberByID(ctx, id)
|
|
}
|
|
|
|
func (s *Service) GetTeamMemberByEmail(ctx context.Context, email string) (domain.TeamMember, error) {
|
|
return s.teamStore.GetTeamMemberByEmail(ctx, email)
|
|
}
|
|
|
|
func (s *Service) GetAllTeamMembers(ctx context.Context, filter domain.TeamMemberFilter) ([]domain.TeamMember, int64, error) {
|
|
var limit int32 = 10
|
|
var offset int32 = 0
|
|
|
|
if filter.PageSize > 0 {
|
|
limit = int32(filter.PageSize)
|
|
}
|
|
if filter.Page > 0 && filter.PageSize > 0 {
|
|
offset = int32((filter.Page - 1) * filter.PageSize)
|
|
}
|
|
|
|
return s.teamStore.GetAllTeamMembers(ctx, filter.TeamRole, filter.Department, filter.Status, limit, offset)
|
|
}
|
|
|
|
func (s *Service) SearchTeamMembers(ctx context.Context, search string, teamRole, status *string) ([]domain.TeamMember, error) {
|
|
return s.teamStore.SearchTeamMembers(ctx, search, teamRole, status)
|
|
}
|
|
|
|
func (s *Service) UpdateTeamMember(ctx context.Context, req domain.UpdateTeamMemberReq) error {
|
|
if req.TeamRole != "" && !domain.TeamRole(req.TeamRole).IsValid() {
|
|
return domain.ErrInvalidTeamRole
|
|
}
|
|
|
|
if req.EmploymentType != "" && !domain.EmploymentType(req.EmploymentType).IsValid() {
|
|
return domain.ErrInvalidEmploymentType
|
|
}
|
|
|
|
return s.teamStore.UpdateTeamMember(ctx, req)
|
|
}
|
|
|
|
func (s *Service) UpdateTeamMemberStatus(ctx context.Context, req domain.UpdateTeamMemberStatusReq) error {
|
|
if !domain.TeamMemberStatus(req.Status).IsValid() {
|
|
return domain.ErrInvalidTeamMemberStatus
|
|
}
|
|
|
|
return s.teamStore.UpdateTeamMemberStatus(ctx, req)
|
|
}
|
|
|
|
func (s *Service) DeleteTeamMember(ctx context.Context, memberID int64) error {
|
|
return s.teamStore.DeleteTeamMember(ctx, memberID)
|
|
}
|
|
|
|
func (s *Service) GetTeamMemberStats(ctx context.Context) (domain.TeamMemberStats, error) {
|
|
return s.teamStore.CountTeamMembersByStatus(ctx)
|
|
}
|
|
|
|
func (s *Service) Login(ctx context.Context, req domain.TeamMemberLoginReq) (domain.TeamMember, error) {
|
|
member, err := s.teamStore.GetTeamMemberByEmail(ctx, req.Email)
|
|
if err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
|
|
if err := bcrypt.CompareHashAndPassword(member.Password, []byte(req.Password)); err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
|
|
if err := s.teamStore.UpdateTeamMemberLastLogin(ctx, member.ID); err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
|
|
return member, nil
|
|
}
|
|
|
|
func (s *Service) ChangePassword(ctx context.Context, memberID int64, currentPassword, newPassword string) error {
|
|
member, err := s.teamStore.GetTeamMemberByID(ctx, memberID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := bcrypt.CompareHashAndPassword(member.Password, []byte(currentPassword)); err != nil {
|
|
return err
|
|
}
|
|
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcryptCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return s.teamStore.UpdateTeamMemberPassword(ctx, memberID, string(hashedPassword))
|
|
}
|
|
|
|
func (s *Service) ResetPassword(ctx context.Context, memberID int64, newPassword string) error {
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcryptCost)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return s.teamStore.UpdateTeamMemberPassword(ctx, memberID, string(hashedPassword))
|
|
}
|