458 lines
14 KiB
Go
458 lines
14 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"time"
|
|
|
|
dbgen "Yimaru-Backend/gen/db"
|
|
"Yimaru-Backend/internal/domain"
|
|
"Yimaru-Backend/internal/ports"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
func NewTeamStore(s *Store) ports.TeamStore { return s }
|
|
|
|
func (s *Store) CreateTeamMember(ctx context.Context, member domain.TeamMember) (domain.TeamMember, error) {
|
|
var permissionsJSON []byte
|
|
if len(member.Permissions) > 0 {
|
|
var err error
|
|
permissionsJSON, err = json.Marshal(member.Permissions)
|
|
if err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
}
|
|
|
|
var hireDate pgtype.Date
|
|
if member.HireDate != nil {
|
|
hireDate = pgtype.Date{Time: *member.HireDate, Valid: true}
|
|
}
|
|
|
|
var createdBy pgtype.Int8
|
|
if member.CreatedBy != nil {
|
|
createdBy = pgtype.Int8{Int64: *member.CreatedBy, Valid: true}
|
|
}
|
|
|
|
res, err := s.queries.CreateTeamMember(ctx, dbgen.CreateTeamMemberParams{
|
|
FirstName: member.FirstName,
|
|
LastName: member.LastName,
|
|
Email: member.Email,
|
|
PhoneNumber: pgtype.Text{String: member.PhoneNumber, Valid: member.PhoneNumber != ""},
|
|
Password: member.Password,
|
|
TeamRole: string(member.TeamRole),
|
|
Department: pgtype.Text{String: member.Department, Valid: member.Department != ""},
|
|
JobTitle: pgtype.Text{String: member.JobTitle, Valid: member.JobTitle != ""},
|
|
EmploymentType: pgtype.Text{String: string(member.EmploymentType), Valid: member.EmploymentType != ""},
|
|
HireDate: hireDate,
|
|
ProfilePictureUrl: pgtype.Text{String: member.ProfilePictureURL, Valid: member.ProfilePictureURL != ""},
|
|
Bio: pgtype.Text{String: member.Bio, Valid: member.Bio != ""},
|
|
WorkPhone: pgtype.Text{String: member.WorkPhone, Valid: member.WorkPhone != ""},
|
|
EmergencyContact: pgtype.Text{String: member.EmergencyContact, Valid: member.EmergencyContact != ""},
|
|
Status: string(member.Status),
|
|
EmailVerified: member.EmailVerified,
|
|
Permissions: permissionsJSON,
|
|
CreatedBy: createdBy,
|
|
})
|
|
if err != nil {
|
|
return domain.TeamMember{}, err
|
|
}
|
|
|
|
return mapDBTeamMember(res), nil
|
|
}
|
|
|
|
func (s *Store) GetTeamMemberByID(ctx context.Context, id int64) (domain.TeamMember, error) {
|
|
res, err := s.queries.GetTeamMemberByID(ctx, id)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return domain.TeamMember{}, domain.ErrTeamMemberNotFound
|
|
}
|
|
return domain.TeamMember{}, err
|
|
}
|
|
return mapDBTeamMember(res), nil
|
|
}
|
|
|
|
func (s *Store) GetTeamMemberByEmail(ctx context.Context, email string) (domain.TeamMember, error) {
|
|
res, err := s.queries.GetTeamMemberByEmail(ctx, email)
|
|
if err != nil {
|
|
if errors.Is(err, pgx.ErrNoRows) {
|
|
return domain.TeamMember{}, domain.ErrTeamMemberNotFound
|
|
}
|
|
return domain.TeamMember{}, err
|
|
}
|
|
return mapDBTeamMember(res), nil
|
|
}
|
|
|
|
func (s *Store) GetAllTeamMembers(
|
|
ctx context.Context,
|
|
teamRole, department, status *string,
|
|
limit, offset int32,
|
|
) ([]domain.TeamMember, int64, error) {
|
|
var teamRoleParam, departmentParam, statusParam pgtype.Text
|
|
if teamRole != nil {
|
|
teamRoleParam = pgtype.Text{String: *teamRole, Valid: true}
|
|
}
|
|
if department != nil {
|
|
departmentParam = pgtype.Text{String: *department, Valid: true}
|
|
}
|
|
if status != nil {
|
|
statusParam = pgtype.Text{String: *status, Valid: true}
|
|
}
|
|
|
|
rows, err := s.queries.GetAllTeamMembers(ctx, dbgen.GetAllTeamMembersParams{
|
|
TeamRole: teamRoleParam,
|
|
Department: departmentParam,
|
|
Status: statusParam,
|
|
Limit: pgtype.Int4{Int32: limit, Valid: true},
|
|
Offset: pgtype.Int4{Int32: offset, Valid: true},
|
|
})
|
|
if err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
if len(rows) == 0 {
|
|
return []domain.TeamMember{}, 0, nil
|
|
}
|
|
|
|
var totalCount int64
|
|
members := make([]domain.TeamMember, len(rows))
|
|
for i, row := range rows {
|
|
if i == 0 {
|
|
totalCount = row.TotalCount
|
|
}
|
|
members[i] = mapGetAllTeamMembersRow(row)
|
|
}
|
|
|
|
return members, totalCount, nil
|
|
}
|
|
|
|
func (s *Store) SearchTeamMembers(
|
|
ctx context.Context,
|
|
search string,
|
|
teamRole, status *string,
|
|
) ([]domain.TeamMember, error) {
|
|
var teamRoleParam, statusParam pgtype.Text
|
|
if teamRole != nil {
|
|
teamRoleParam = pgtype.Text{String: *teamRole, Valid: true}
|
|
}
|
|
if status != nil {
|
|
statusParam = pgtype.Text{String: *status, Valid: true}
|
|
}
|
|
|
|
rows, err := s.queries.SearchTeamMembers(ctx, dbgen.SearchTeamMembersParams{
|
|
Column1: pgtype.Text{String: search, Valid: true},
|
|
TeamRole: teamRoleParam,
|
|
Status: statusParam,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
members := make([]domain.TeamMember, len(rows))
|
|
for i, row := range rows {
|
|
members[i] = mapSearchTeamMembersRow(row)
|
|
}
|
|
|
|
return members, nil
|
|
}
|
|
|
|
func (s *Store) UpdateTeamMember(ctx context.Context, req domain.UpdateTeamMemberReq) error {
|
|
var permissionsJSON []byte
|
|
if len(req.Permissions) > 0 {
|
|
var err error
|
|
permissionsJSON, err = json.Marshal(req.Permissions)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
var hireDate pgtype.Date
|
|
if req.HireDate != "" {
|
|
t, err := parseDate(req.HireDate)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
hireDate = pgtype.Date{Time: t, Valid: true}
|
|
}
|
|
|
|
return s.queries.UpdateTeamMember(ctx, dbgen.UpdateTeamMemberParams{
|
|
FirstName: req.FirstName,
|
|
LastName: req.LastName,
|
|
PhoneNumber: pgtype.Text{String: req.PhoneNumber, Valid: req.PhoneNumber != ""},
|
|
TeamRole: req.TeamRole,
|
|
Department: pgtype.Text{String: req.Department, Valid: req.Department != ""},
|
|
JobTitle: pgtype.Text{String: req.JobTitle, Valid: req.JobTitle != ""},
|
|
EmploymentType: pgtype.Text{String: req.EmploymentType, Valid: req.EmploymentType != ""},
|
|
HireDate: hireDate,
|
|
ProfilePictureUrl: pgtype.Text{String: req.ProfilePictureURL, Valid: req.ProfilePictureURL != ""},
|
|
Bio: pgtype.Text{String: req.Bio, Valid: req.Bio != ""},
|
|
WorkPhone: pgtype.Text{String: req.WorkPhone, Valid: req.WorkPhone != ""},
|
|
EmergencyContact: pgtype.Text{String: req.EmergencyContact, Valid: req.EmergencyContact != ""},
|
|
Permissions: permissionsJSON,
|
|
UpdatedBy: pgtype.Int8{Int64: req.UpdatedBy, Valid: req.UpdatedBy > 0},
|
|
ID: req.TeamMemberID,
|
|
})
|
|
}
|
|
|
|
func (s *Store) UpdateTeamMemberStatus(ctx context.Context, req domain.UpdateTeamMemberStatusReq) error {
|
|
return s.queries.UpdateTeamMemberStatus(ctx, dbgen.UpdateTeamMemberStatusParams{
|
|
Status: req.Status,
|
|
UpdatedBy: pgtype.Int8{Int64: req.UpdatedBy, Valid: req.UpdatedBy > 0},
|
|
ID: req.TeamMemberID,
|
|
})
|
|
}
|
|
|
|
func (s *Store) UpdateTeamMemberPassword(ctx context.Context, memberID int64, password string) error {
|
|
return s.queries.UpdateTeamMemberPassword(ctx, dbgen.UpdateTeamMemberPasswordParams{
|
|
Password: []byte(password),
|
|
ID: memberID,
|
|
})
|
|
}
|
|
|
|
func (s *Store) UpdateTeamMemberLastLogin(ctx context.Context, memberID int64) error {
|
|
return s.queries.UpdateTeamMemberLastLogin(ctx, memberID)
|
|
}
|
|
|
|
func (s *Store) DeleteTeamMember(ctx context.Context, memberID int64) error {
|
|
return s.queries.DeleteTeamMember(ctx, memberID)
|
|
}
|
|
|
|
func (s *Store) CheckTeamMemberEmailExists(ctx context.Context, email string) (bool, error) {
|
|
return s.queries.CheckTeamMemberEmailExists(ctx, email)
|
|
}
|
|
|
|
func (s *Store) GetTeamMembersByDepartment(ctx context.Context, department string) ([]domain.TeamMember, error) {
|
|
rows, err := s.queries.GetTeamMembersByDepartment(ctx, pgtype.Text{String: department, Valid: true})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
members := make([]domain.TeamMember, len(rows))
|
|
for i, row := range rows {
|
|
members[i] = mapGetTeamMembersByDepartmentRow(row)
|
|
}
|
|
|
|
return members, nil
|
|
}
|
|
|
|
func (s *Store) GetTeamMembersByRole(ctx context.Context, role string) ([]domain.TeamMember, error) {
|
|
rows, err := s.queries.GetTeamMembersByRole(ctx, role)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
members := make([]domain.TeamMember, len(rows))
|
|
for i, row := range rows {
|
|
members[i] = mapGetTeamMembersByRoleRow(row)
|
|
}
|
|
|
|
return members, nil
|
|
}
|
|
|
|
func (s *Store) CountTeamMembersByStatus(ctx context.Context) (domain.TeamMemberStats, error) {
|
|
res, err := s.queries.CountTeamMembersByStatus(ctx)
|
|
if err != nil {
|
|
return domain.TeamMemberStats{}, err
|
|
}
|
|
|
|
return domain.TeamMemberStats{
|
|
ActiveCount: res.ActiveCount,
|
|
InactiveCount: res.InactiveCount,
|
|
SuspendedCount: res.SuspendedCount,
|
|
TerminatedCount: res.TerminatedCount,
|
|
TotalCount: res.TotalCount,
|
|
}, nil
|
|
}
|
|
|
|
func (s *Store) UpdateTeamMemberEmailVerified(ctx context.Context, memberID int64, verified bool) error {
|
|
return s.queries.UpdateTeamMemberEmailVerified(ctx, dbgen.UpdateTeamMemberEmailVerifiedParams{
|
|
EmailVerified: verified,
|
|
ID: memberID,
|
|
})
|
|
}
|
|
|
|
func mapDBTeamMember(m dbgen.TeamMember) domain.TeamMember {
|
|
var permissions []string
|
|
if len(m.Permissions) > 0 {
|
|
_ = json.Unmarshal(m.Permissions, &permissions)
|
|
}
|
|
|
|
var hireDate *time.Time
|
|
if m.HireDate.Valid {
|
|
hireDate = &m.HireDate.Time
|
|
}
|
|
|
|
var lastLogin *time.Time
|
|
if m.LastLogin.Valid {
|
|
lastLogin = &m.LastLogin.Time
|
|
}
|
|
|
|
var createdBy *int64
|
|
if m.CreatedBy.Valid {
|
|
createdBy = &m.CreatedBy.Int64
|
|
}
|
|
|
|
var updatedBy *int64
|
|
if m.UpdatedBy.Valid {
|
|
updatedBy = &m.UpdatedBy.Int64
|
|
}
|
|
|
|
var updatedAt *time.Time
|
|
if m.UpdatedAt.Valid {
|
|
updatedAt = &m.UpdatedAt.Time
|
|
}
|
|
|
|
return domain.TeamMember{
|
|
ID: m.ID,
|
|
FirstName: m.FirstName,
|
|
LastName: m.LastName,
|
|
Email: m.Email,
|
|
PhoneNumber: m.PhoneNumber.String,
|
|
Password: m.Password,
|
|
TeamRole: domain.TeamRole(m.TeamRole),
|
|
Department: m.Department.String,
|
|
JobTitle: m.JobTitle.String,
|
|
EmploymentType: domain.EmploymentType(m.EmploymentType.String),
|
|
HireDate: hireDate,
|
|
ProfilePictureURL: m.ProfilePictureUrl.String,
|
|
Bio: m.Bio.String,
|
|
WorkPhone: m.WorkPhone.String,
|
|
EmergencyContact: m.EmergencyContact.String,
|
|
Status: domain.TeamMemberStatus(m.Status),
|
|
EmailVerified: m.EmailVerified,
|
|
Permissions: permissions,
|
|
LastLogin: lastLogin,
|
|
CreatedBy: createdBy,
|
|
UpdatedBy: updatedBy,
|
|
CreatedAt: m.CreatedAt.Time,
|
|
UpdatedAt: updatedAt,
|
|
}
|
|
}
|
|
|
|
func mapGetAllTeamMembersRow(row dbgen.GetAllTeamMembersRow) domain.TeamMember {
|
|
var permissions []string
|
|
if len(row.Permissions) > 0 {
|
|
_ = json.Unmarshal(row.Permissions, &permissions)
|
|
}
|
|
|
|
var hireDate *time.Time
|
|
if row.HireDate.Valid {
|
|
hireDate = &row.HireDate.Time
|
|
}
|
|
|
|
var lastLogin *time.Time
|
|
if row.LastLogin.Valid {
|
|
lastLogin = &row.LastLogin.Time
|
|
}
|
|
|
|
var updatedAt *time.Time
|
|
if row.UpdatedAt.Valid {
|
|
updatedAt = &row.UpdatedAt.Time
|
|
}
|
|
|
|
return domain.TeamMember{
|
|
ID: row.ID,
|
|
FirstName: row.FirstName,
|
|
LastName: row.LastName,
|
|
Email: row.Email,
|
|
PhoneNumber: row.PhoneNumber.String,
|
|
TeamRole: domain.TeamRole(row.TeamRole),
|
|
Department: row.Department.String,
|
|
JobTitle: row.JobTitle.String,
|
|
EmploymentType: domain.EmploymentType(row.EmploymentType.String),
|
|
HireDate: hireDate,
|
|
ProfilePictureURL: row.ProfilePictureUrl.String,
|
|
Bio: row.Bio.String,
|
|
WorkPhone: row.WorkPhone.String,
|
|
Status: domain.TeamMemberStatus(row.Status),
|
|
EmailVerified: row.EmailVerified,
|
|
Permissions: permissions,
|
|
LastLogin: lastLogin,
|
|
CreatedAt: row.CreatedAt.Time,
|
|
UpdatedAt: updatedAt,
|
|
}
|
|
}
|
|
|
|
func mapSearchTeamMembersRow(row dbgen.SearchTeamMembersRow) domain.TeamMember {
|
|
var permissions []string
|
|
if len(row.Permissions) > 0 {
|
|
_ = json.Unmarshal(row.Permissions, &permissions)
|
|
}
|
|
|
|
var hireDate *time.Time
|
|
if row.HireDate.Valid {
|
|
hireDate = &row.HireDate.Time
|
|
}
|
|
|
|
var lastLogin *time.Time
|
|
if row.LastLogin.Valid {
|
|
lastLogin = &row.LastLogin.Time
|
|
}
|
|
|
|
var updatedAt *time.Time
|
|
if row.UpdatedAt.Valid {
|
|
updatedAt = &row.UpdatedAt.Time
|
|
}
|
|
|
|
return domain.TeamMember{
|
|
ID: row.ID,
|
|
FirstName: row.FirstName,
|
|
LastName: row.LastName,
|
|
Email: row.Email,
|
|
PhoneNumber: row.PhoneNumber.String,
|
|
TeamRole: domain.TeamRole(row.TeamRole),
|
|
Department: row.Department.String,
|
|
JobTitle: row.JobTitle.String,
|
|
EmploymentType: domain.EmploymentType(row.EmploymentType.String),
|
|
HireDate: hireDate,
|
|
ProfilePictureURL: row.ProfilePictureUrl.String,
|
|
Bio: row.Bio.String,
|
|
Status: domain.TeamMemberStatus(row.Status),
|
|
EmailVerified: row.EmailVerified,
|
|
Permissions: permissions,
|
|
LastLogin: lastLogin,
|
|
CreatedAt: row.CreatedAt.Time,
|
|
UpdatedAt: updatedAt,
|
|
}
|
|
}
|
|
|
|
func mapGetTeamMembersByDepartmentRow(row dbgen.GetTeamMembersByDepartmentRow) domain.TeamMember {
|
|
return domain.TeamMember{
|
|
ID: row.ID,
|
|
FirstName: row.FirstName,
|
|
LastName: row.LastName,
|
|
Email: row.Email,
|
|
PhoneNumber: row.PhoneNumber.String,
|
|
TeamRole: domain.TeamRole(row.TeamRole),
|
|
Department: row.Department.String,
|
|
JobTitle: row.JobTitle.String,
|
|
EmploymentType: domain.EmploymentType(row.EmploymentType.String),
|
|
ProfilePictureURL: row.ProfilePictureUrl.String,
|
|
Status: domain.TeamMemberStatus(row.Status),
|
|
CreatedAt: row.CreatedAt.Time,
|
|
}
|
|
}
|
|
|
|
func mapGetTeamMembersByRoleRow(row dbgen.GetTeamMembersByRoleRow) domain.TeamMember {
|
|
return domain.TeamMember{
|
|
ID: row.ID,
|
|
FirstName: row.FirstName,
|
|
LastName: row.LastName,
|
|
Email: row.Email,
|
|
PhoneNumber: row.PhoneNumber.String,
|
|
TeamRole: domain.TeamRole(row.TeamRole),
|
|
Department: row.Department.String,
|
|
JobTitle: row.JobTitle.String,
|
|
EmploymentType: domain.EmploymentType(row.EmploymentType.String),
|
|
ProfilePictureURL: row.ProfilePictureUrl.String,
|
|
Status: domain.TeamMemberStatus(row.Status),
|
|
CreatedAt: row.CreatedAt.Time,
|
|
}
|
|
}
|
|
|
|
func parseDate(dateStr string) (time.Time, error) {
|
|
return time.Parse("2006-01-02", dateStr)
|
|
}
|