initial commit
This commit is contained in:
72
internal/application/profile/converter.go
Normal file
72
internal/application/profile/converter.go
Normal file
@@ -0,0 +1,72 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"base/internal/domain/profile"
|
||||
"base/internal/dto"
|
||||
)
|
||||
|
||||
// DomainProfileToProfileResponse converts a domain profile to ProfileResponse.
|
||||
// Used by specialist overview and other consumers that have a domain profile.
|
||||
func DomainProfileToProfileResponse(p *profile.Profile) *dto.ProfileResponse {
|
||||
if p == nil {
|
||||
return nil
|
||||
}
|
||||
roleLevel := ""
|
||||
if p.Hero.Role != nil {
|
||||
roleLevel = p.Hero.Role.Level
|
||||
}
|
||||
resp := &dto.ProfileResponse{
|
||||
ID: p.ID,
|
||||
Handle: p.Handle,
|
||||
PageSectionOrder: p.PageSectionOrder,
|
||||
Hero: dto.HeroDTO{
|
||||
RoleLevel: roleLevel,
|
||||
FirstName: p.Hero.FirstName,
|
||||
LastName: p.Hero.LastName,
|
||||
Company: p.Hero.Company,
|
||||
ShortDescription: p.Hero.ShortDescription,
|
||||
ResumeLink: p.Hero.ResumeLink,
|
||||
CTAEnabled: p.Hero.CTAEnabled,
|
||||
Avatar: p.Hero.Avatar,
|
||||
},
|
||||
About: dto.AboutDTO{
|
||||
ProfilePicture: p.About.ProfilePicture,
|
||||
About: p.About.About,
|
||||
},
|
||||
Contact: dto.ContactDTO{
|
||||
Email: p.Contact.Email,
|
||||
Phone: p.Contact.Phone,
|
||||
},
|
||||
PageSetting: dto.PageSettingDTO{
|
||||
VisibilityLevel: p.PageSetting.VisibilityLevel,
|
||||
},
|
||||
}
|
||||
|
||||
if p.Hero.Role != nil {
|
||||
resp.Hero.RoleID = &p.Hero.Role.ID
|
||||
}
|
||||
|
||||
for _, skill := range p.Skills {
|
||||
resp.Skills = append(resp.Skills, dto.SkillDTO{
|
||||
SkillName: skill.SkillName,
|
||||
Level: skill.Level,
|
||||
})
|
||||
}
|
||||
|
||||
for _, achievement := range p.About.Achievements {
|
||||
resp.About.Achievements = append(resp.About.Achievements, dto.AchievementDTO{
|
||||
Title: achievement.Title,
|
||||
Value: achievement.Value,
|
||||
Enabled: achievement.Enabled,
|
||||
})
|
||||
}
|
||||
|
||||
for _, sl := range p.Contact.SocialLinks {
|
||||
resp.Contact.SocialLinks = append(resp.Contact.SocialLinks, dto.SocialLinkDTO{
|
||||
LinkType: sl.LinkType,
|
||||
Link: sl.Link,
|
||||
})
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
315
internal/application/profile/service.go
Normal file
315
internal/application/profile/service.go
Normal file
@@ -0,0 +1,315 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/samber/lo"
|
||||
"go.uber.org/fx"
|
||||
|
||||
"base/internal/domain/profile"
|
||||
"base/internal/dto"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
Create(ctx context.Context, req dto.CreateProfileRequest) (*dto.ProfileResponse, error)
|
||||
Update(ctx context.Context, req dto.UpdateProfileRequest) (*dto.ProfileResponse, error)
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*dto.ProfileResponse, error)
|
||||
GetByHandle(ctx context.Context, handle string) (*dto.ProfileResponse, error)
|
||||
List(ctx context.Context, req dto.ListProfilesRequest) (*dto.ListProfilesResponse, error)
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
|
||||
type service struct {
|
||||
logger zerolog.Logger
|
||||
profileRepo profile.Repository
|
||||
}
|
||||
|
||||
type Param struct {
|
||||
Logger zerolog.Logger
|
||||
ProfileRepo profile.Repository
|
||||
|
||||
fx.In
|
||||
}
|
||||
|
||||
func New(param Param) Service {
|
||||
return &service{
|
||||
logger: param.Logger,
|
||||
profileRepo: param.ProfileRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) Create(ctx context.Context, req dto.CreateProfileRequest) (*dto.ProfileResponse, error) {
|
||||
domainProfile := &profile.Profile{
|
||||
ID: uuid.New(),
|
||||
Handle: req.Handle,
|
||||
PageSectionOrder: req.PageSectionOrder,
|
||||
Hero: profile.Hero{
|
||||
Role: &profile.Role{
|
||||
ID: lo.FromPtr(req.Hero.RoleID),
|
||||
Level: req.Hero.RoleLevel,
|
||||
},
|
||||
FirstName: req.Hero.FirstName,
|
||||
LastName: req.Hero.LastName,
|
||||
Company: req.Hero.Company,
|
||||
ShortDescription: req.Hero.ShortDescription,
|
||||
ResumeLink: req.Hero.ResumeLink,
|
||||
CTAEnabled: req.Hero.CTAEnabled,
|
||||
Avatar: req.Hero.Avatar,
|
||||
},
|
||||
About: profile.About{
|
||||
ProfilePicture: req.About.ProfilePicture,
|
||||
About: req.About.About,
|
||||
},
|
||||
Contact: profile.Contact{
|
||||
Email: req.Contact.Email,
|
||||
Phone: req.Contact.Phone,
|
||||
},
|
||||
PageSetting: profile.PageSetting{
|
||||
VisibilityLevel: req.PageSetting.VisibilityLevel,
|
||||
},
|
||||
}
|
||||
|
||||
if req.Hero.RoleID != nil {
|
||||
domainProfile.Hero.Role = &profile.Role{
|
||||
ID: *req.Hero.RoleID,
|
||||
}
|
||||
}
|
||||
|
||||
for _, skill := range req.Skills {
|
||||
domainProfile.Skills = append(domainProfile.Skills, profile.Skill{
|
||||
SkillName: skill.SkillName,
|
||||
Level: skill.Level,
|
||||
})
|
||||
}
|
||||
|
||||
for _, achievement := range req.About.Achievements {
|
||||
domainProfile.About.Achievements = append(domainProfile.About.Achievements, profile.Achievement{
|
||||
Title: achievement.Title,
|
||||
Value: achievement.Value,
|
||||
Enabled: achievement.Enabled,
|
||||
})
|
||||
}
|
||||
|
||||
for _, socialLink := range req.Contact.SocialLinks {
|
||||
domainProfile.Contact.SocialLinks = append(domainProfile.Contact.SocialLinks, profile.SocialLink{
|
||||
LinkType: socialLink.LinkType,
|
||||
Link: socialLink.Link,
|
||||
})
|
||||
}
|
||||
|
||||
if err := s.profileRepo.Create(ctx, domainProfile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.toProfileResponse(domainProfile), nil
|
||||
}
|
||||
|
||||
func (s *service) Update(ctx context.Context, req dto.UpdateProfileRequest) (*dto.ProfileResponse, error) {
|
||||
id, err := uuid.Parse(req.ID)
|
||||
if err != nil {
|
||||
return nil, profile.ErrProfileNotFound
|
||||
}
|
||||
|
||||
// First, get the existing profile to ensure it exists
|
||||
existingProfile, err := s.profileRepo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, profile.ErrProfileNotFound
|
||||
}
|
||||
|
||||
domainProfile := &profile.Profile{
|
||||
ID: id,
|
||||
Handle: req.Handle,
|
||||
PageSectionOrder: req.PageSectionOrder,
|
||||
Hero: profile.Hero{
|
||||
FirstName: req.Hero.FirstName,
|
||||
Role: &profile.Role{
|
||||
ID: lo.FromPtr(req.Hero.RoleID),
|
||||
Level: req.Hero.RoleLevel,
|
||||
},
|
||||
LastName: req.Hero.LastName,
|
||||
Company: req.Hero.Company,
|
||||
ShortDescription: req.Hero.ShortDescription,
|
||||
ResumeLink: req.Hero.ResumeLink,
|
||||
CTAEnabled: req.Hero.CTAEnabled,
|
||||
Avatar: req.Hero.Avatar,
|
||||
},
|
||||
About: profile.About{
|
||||
ProfilePicture: req.About.ProfilePicture,
|
||||
About: req.About.About,
|
||||
},
|
||||
Contact: profile.Contact{
|
||||
Email: req.Contact.Email,
|
||||
Phone: req.Contact.Phone,
|
||||
},
|
||||
PageSetting: profile.PageSetting{
|
||||
VisibilityLevel: req.PageSetting.VisibilityLevel,
|
||||
},
|
||||
}
|
||||
|
||||
if req.Hero.RoleID != nil {
|
||||
domainProfile.Hero.Role = &profile.Role{
|
||||
ID: *req.Hero.RoleID,
|
||||
}
|
||||
} else if existingProfile != nil && existingProfile.Hero.Role != nil {
|
||||
domainProfile.Hero.Role = existingProfile.Hero.Role
|
||||
}
|
||||
|
||||
if req.Hero.RoleLevel == "" && existingProfile != nil {
|
||||
domainProfile.Hero.Role.Level = existingProfile.Hero.Role.Level
|
||||
}
|
||||
|
||||
for _, skill := range req.Skills {
|
||||
domainProfile.Skills = append(domainProfile.Skills, profile.Skill{
|
||||
SkillName: skill.SkillName,
|
||||
Level: skill.Level,
|
||||
})
|
||||
}
|
||||
|
||||
for _, achievement := range req.About.Achievements {
|
||||
domainProfile.About.Achievements = append(domainProfile.About.Achievements, profile.Achievement{
|
||||
Title: achievement.Title,
|
||||
Value: achievement.Value,
|
||||
Enabled: achievement.Enabled,
|
||||
})
|
||||
}
|
||||
|
||||
for _, socialLink := range req.Contact.SocialLinks {
|
||||
domainProfile.Contact.SocialLinks = append(domainProfile.Contact.SocialLinks, profile.SocialLink{
|
||||
LinkType: socialLink.LinkType,
|
||||
Link: socialLink.Link,
|
||||
})
|
||||
}
|
||||
|
||||
if err := s.profileRepo.Update(ctx, domainProfile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.toProfileResponse(domainProfile), nil
|
||||
}
|
||||
|
||||
func (s *service) GetByID(ctx context.Context, id uuid.UUID) (*dto.ProfileResponse, error) {
|
||||
profileData, err := s.profileRepo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
return nil, profile.ErrProfileNotFound
|
||||
}
|
||||
|
||||
return s.toProfileResponse(profileData), nil
|
||||
}
|
||||
|
||||
func (s *service) GetByHandle(ctx context.Context, handle string) (*dto.ProfileResponse, error) {
|
||||
profileData, err := s.profileRepo.FindByHandle(ctx, handle)
|
||||
if err != nil {
|
||||
return nil, profile.ErrProfileNotFound
|
||||
}
|
||||
|
||||
return s.toProfileResponse(profileData), nil
|
||||
}
|
||||
|
||||
func (s *service) List(ctx context.Context, req dto.ListProfilesRequest) (*dto.ListProfilesResponse, error) {
|
||||
filter := profile.Filter{
|
||||
FirstName: req.FirstName,
|
||||
LastName: req.LastName,
|
||||
Company: req.Company,
|
||||
SkillName: req.SkillName,
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
SortedBy: req.SortedBy,
|
||||
Ascending: req.Ascending,
|
||||
}
|
||||
|
||||
if req.Page == 0 {
|
||||
filter.Page = 1
|
||||
}
|
||||
if req.PageSize == 0 {
|
||||
filter.PageSize = 10
|
||||
}
|
||||
|
||||
if req.RoleID != nil {
|
||||
filter.RoleID = *req.RoleID
|
||||
}
|
||||
|
||||
profiles, total, err := s.profileRepo.FindAll(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response := &dto.ListProfilesResponse{
|
||||
Profiles: make([]dto.ProfileResponse, len(profiles)),
|
||||
Total: total,
|
||||
Page: filter.Page,
|
||||
PageSize: filter.PageSize,
|
||||
}
|
||||
|
||||
for i, p := range profiles {
|
||||
response.Profiles[i] = *s.toProfileResponse(p)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *service) Delete(ctx context.Context, id uuid.UUID) error {
|
||||
// Get profile first to ensure it exists
|
||||
profileData, err := s.profileRepo.FindByID(ctx, id)
|
||||
if err != nil {
|
||||
return profile.ErrProfileNotFound
|
||||
}
|
||||
|
||||
return s.profileRepo.Delete(ctx, profileData)
|
||||
}
|
||||
|
||||
func (s *service) toProfileResponse(p *profile.Profile) *dto.ProfileResponse {
|
||||
resp := &dto.ProfileResponse{
|
||||
ID: p.ID,
|
||||
Handle: p.Handle,
|
||||
PageSectionOrder: p.PageSectionOrder,
|
||||
Hero: dto.HeroDTO{
|
||||
FirstName: p.Hero.FirstName,
|
||||
LastName: p.Hero.LastName,
|
||||
Company: p.Hero.Company,
|
||||
ShortDescription: p.Hero.ShortDescription,
|
||||
ResumeLink: p.Hero.ResumeLink,
|
||||
CTAEnabled: p.Hero.CTAEnabled,
|
||||
Avatar: p.Hero.Avatar,
|
||||
},
|
||||
About: dto.AboutDTO{
|
||||
ProfilePicture: p.About.ProfilePicture,
|
||||
About: p.About.About,
|
||||
},
|
||||
Contact: dto.ContactDTO{
|
||||
Email: p.Contact.Email,
|
||||
Phone: p.Contact.Phone,
|
||||
},
|
||||
PageSetting: dto.PageSettingDTO{
|
||||
VisibilityLevel: p.PageSetting.VisibilityLevel,
|
||||
},
|
||||
}
|
||||
|
||||
if p.Hero.Role != nil {
|
||||
resp.Hero.RoleID = &p.Hero.Role.ID
|
||||
}
|
||||
|
||||
for _, skill := range p.Skills {
|
||||
resp.Skills = append(resp.Skills, dto.SkillDTO{
|
||||
SkillName: skill.SkillName,
|
||||
Level: skill.Level,
|
||||
})
|
||||
}
|
||||
|
||||
for _, achievement := range p.About.Achievements {
|
||||
resp.About.Achievements = append(resp.About.Achievements, dto.AchievementDTO{
|
||||
Title: achievement.Title,
|
||||
Value: achievement.Value,
|
||||
Enabled: achievement.Enabled,
|
||||
})
|
||||
}
|
||||
|
||||
for _, socialLink := range p.Contact.SocialLinks {
|
||||
resp.Contact.SocialLinks = append(resp.Contact.SocialLinks, dto.SocialLinkDTO{
|
||||
LinkType: socialLink.LinkType,
|
||||
Link: socialLink.Link,
|
||||
})
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
Reference in New Issue
Block a user