a363078d6f
- Added a new Type field to the CMS entity to differentiate between Company and Organization types, improving data categorization. - Updated the CMSForm to include validation for the Type field, ensuring proper input handling. - Modified the ToResponse method to include the Type field in the CMSResponse, enhancing the API response structure. - Adjusted the copyFormToEntity method in the CMS service to handle the new Type field, maintaining data integrity based on the selected type. - Enhanced Swagger documentation to reflect the changes in the CMS API, providing clear examples for the new Type field.
350 lines
8.9 KiB
Go
350 lines
8.9 KiB
Go
package cms
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"tm/pkg/logger"
|
|
orm "tm/pkg/mongo"
|
|
"tm/pkg/response"
|
|
)
|
|
|
|
// Service defines the interface for CMS business operations
|
|
type Service interface {
|
|
// Create creates a new CMS entry
|
|
Create(ctx context.Context, form *CMSForm) (*CMSResponse, error)
|
|
|
|
// GetByID retrieves a CMS entry by ID
|
|
GetByID(ctx context.Context, id string) (*CMSResponse, error)
|
|
|
|
// GetByKey retrieves a CMS entry by key
|
|
GetByKey(ctx context.Context, key string) (*CMSResponse, error)
|
|
|
|
// Update updates a CMS entry
|
|
Update(ctx context.Context, id string, form *CMSForm) (*CMSResponse, error)
|
|
|
|
// Delete deletes a CMS entry by ID
|
|
Delete(ctx context.Context, id string) error
|
|
|
|
// Search searches CMS entries with filters and pagination
|
|
Search(ctx context.Context, form *SearchCMSForm, pagination *response.Pagination) (*CMSListResponse, error)
|
|
}
|
|
|
|
// cmsService implements Service interface
|
|
type cmsService struct {
|
|
repo Repository
|
|
logger logger.Logger
|
|
}
|
|
|
|
// NewService creates a new CMS service
|
|
func NewService(repo Repository, logger logger.Logger) Service {
|
|
return &cmsService{
|
|
repo: repo,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
// Create creates a new CMS entry
|
|
func (s *cmsService) Create(ctx context.Context, form *CMSForm) (*CMSResponse, error) {
|
|
s.logger.Info("Creating new CMS entry", map[string]interface{}{
|
|
"key": form.Key,
|
|
})
|
|
|
|
// Check if CMS with this key already exists
|
|
existing, err := s.repo.GetByKey(ctx, form.Key)
|
|
if err == nil && existing != nil {
|
|
s.logger.Warn("CMS with this key already exists", map[string]interface{}{
|
|
"key": form.Key,
|
|
})
|
|
return nil, ErrCMSKeyExists
|
|
}
|
|
|
|
// Create CMS entity
|
|
cms := &CMS{
|
|
Key: form.Key,
|
|
}
|
|
|
|
// Copy form data to entity
|
|
s.copyFormToEntity(form, cms)
|
|
|
|
// Save to database
|
|
if err := s.repo.Create(ctx, cms); err != nil {
|
|
s.logger.Error("Failed to create CMS", map[string]interface{}{
|
|
"key": form.Key,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, fmt.Errorf("failed to create CMS: %w", err)
|
|
}
|
|
|
|
s.logger.Info("CMS entry created successfully", map[string]interface{}{
|
|
"id": cms.GetID(),
|
|
"key": form.Key,
|
|
})
|
|
|
|
return cms.ToResponse(), nil
|
|
}
|
|
|
|
// GetByID retrieves a CMS entry by ID
|
|
func (s *cmsService) GetByID(ctx context.Context, id string) (*CMSResponse, error) {
|
|
s.logger.Debug("Retrieving CMS by ID", map[string]interface{}{
|
|
"id": id,
|
|
})
|
|
|
|
cms, err := s.repo.GetByID(ctx, id)
|
|
if err != nil {
|
|
s.logger.Error("Failed to get CMS by ID", map[string]interface{}{
|
|
"id": id,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, fmt.Errorf("failed to get CMS: %w", err)
|
|
}
|
|
|
|
return cms.ToResponse(), nil
|
|
}
|
|
|
|
// GetByKey retrieves a CMS entry by key
|
|
func (s *cmsService) GetByKey(ctx context.Context, key string) (*CMSResponse, error) {
|
|
s.logger.Debug("Retrieving CMS by key", map[string]interface{}{
|
|
"key": key,
|
|
})
|
|
|
|
cms, err := s.repo.GetByKey(ctx, key)
|
|
if err != nil {
|
|
s.logger.Error("Failed to get CMS by key", map[string]interface{}{
|
|
"key": key,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, fmt.Errorf("failed to get CMS: %w", err)
|
|
}
|
|
|
|
return cms.ToResponse(), nil
|
|
}
|
|
|
|
// Update updates a CMS entry
|
|
func (s *cmsService) Update(ctx context.Context, id string, form *CMSForm) (*CMSResponse, error) {
|
|
s.logger.Info("Updating CMS entry", map[string]interface{}{
|
|
"id": id,
|
|
"key": form.Key,
|
|
})
|
|
|
|
// Get existing CMS
|
|
cms, err := s.repo.GetByID(ctx, id)
|
|
if err != nil {
|
|
s.logger.Error("Failed to get existing CMS for update", map[string]interface{}{
|
|
"id": id,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, fmt.Errorf("failed to get CMS for update: %w", err)
|
|
}
|
|
|
|
// Check if key is being changed and if new key already exists
|
|
if cms.Key != form.Key {
|
|
existing, err := s.repo.GetByKey(ctx, form.Key)
|
|
if err == nil && existing != nil && existing.GetID() != id {
|
|
s.logger.Warn("CMS with this key already exists", map[string]interface{}{
|
|
"key": form.Key,
|
|
})
|
|
return nil, ErrCMSKeyExists
|
|
}
|
|
cms.Key = form.Key
|
|
}
|
|
|
|
// Copy form data to entity
|
|
s.copyFormToEntity(form, cms)
|
|
|
|
// Update in database
|
|
if err := s.repo.Update(ctx, cms); err != nil {
|
|
s.logger.Error("Failed to update CMS", map[string]interface{}{
|
|
"id": id,
|
|
"key": form.Key,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, fmt.Errorf("failed to update CMS: %w", err)
|
|
}
|
|
|
|
s.logger.Info("CMS entry updated successfully", map[string]interface{}{
|
|
"id": id,
|
|
"key": form.Key,
|
|
})
|
|
|
|
return cms.ToResponse(), nil
|
|
}
|
|
|
|
// Delete deletes a CMS entry by ID
|
|
func (s *cmsService) Delete(ctx context.Context, id string) error {
|
|
s.logger.Info("Deleting CMS entry", map[string]interface{}{
|
|
"id": id,
|
|
})
|
|
|
|
if err := s.repo.Delete(ctx, id); err != nil {
|
|
s.logger.Error("Failed to delete CMS", map[string]interface{}{
|
|
"id": id,
|
|
"error": err.Error(),
|
|
})
|
|
return fmt.Errorf("failed to delete CMS: %w", err)
|
|
}
|
|
|
|
s.logger.Info("CMS entry deleted successfully", map[string]interface{}{
|
|
"id": id,
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// Search searches CMS entries with filters and pagination
|
|
func (s *cmsService) Search(ctx context.Context, form *SearchCMSForm, pagination *response.Pagination) (*CMSListResponse, error) {
|
|
s.logger.Debug("Searching CMS entries", map[string]interface{}{
|
|
"filters": form,
|
|
"pagination": pagination,
|
|
})
|
|
|
|
// Convert response.Pagination to orm.Pagination
|
|
ormPagination := orm.Pagination{
|
|
Limit: pagination.Limit,
|
|
Skip: pagination.Offset,
|
|
SortField: pagination.SortBy,
|
|
SortOrder: 1, // Default ascending
|
|
}
|
|
if pagination.SortOrder == "desc" {
|
|
ormPagination.SortOrder = -1
|
|
}
|
|
|
|
result, err := s.repo.Search(ctx, form, ormPagination)
|
|
if err != nil {
|
|
s.logger.Error("Failed to search CMS entries", map[string]interface{}{
|
|
"filters": form,
|
|
"error": err.Error(),
|
|
})
|
|
return nil, fmt.Errorf("failed to search CMS entries: %w", err)
|
|
}
|
|
|
|
// Convert to response format
|
|
cmsResponses := make([]*CMSResponse, len(result.Items))
|
|
for i, cms := range result.Items {
|
|
cmsResponses[i] = cms.ToResponse()
|
|
}
|
|
|
|
s.logger.Info("CMS search completed", map[string]interface{}{
|
|
"total_count": result.TotalCount,
|
|
"items_count": len(result.Items),
|
|
})
|
|
|
|
return &CMSListResponse{
|
|
CMS: cmsResponses,
|
|
Meta: pagination.Response(result.TotalCount),
|
|
}, nil
|
|
}
|
|
|
|
// copyFormToEntity copies data from form to entity
|
|
func (s *cmsService) copyFormToEntity(form *CMSForm, cms *CMS) {
|
|
if form.Type != "" {
|
|
cms.Type = CMSType(form.Type)
|
|
}
|
|
|
|
switch cms.Type {
|
|
case CMSTypeCompany:
|
|
if form.Language != "" {
|
|
cms.Language = form.Language
|
|
}
|
|
if form.CompanyName != "" {
|
|
cms.CompanyName = form.CompanyName
|
|
}
|
|
if form.Country != "" {
|
|
cms.Country = form.Country
|
|
}
|
|
case CMSTypeOrganization:
|
|
cms.Language = ""
|
|
cms.CompanyName = ""
|
|
cms.Country = ""
|
|
}
|
|
|
|
// Hero section
|
|
if form.Hero.Title != "" {
|
|
cms.Hero.Title = form.Hero.Title
|
|
}
|
|
if form.Hero.Description != "" {
|
|
cms.Hero.Description = form.Hero.Description
|
|
}
|
|
if form.Hero.ButtonText != "" {
|
|
cms.Hero.ButtonText = form.Hero.ButtonText
|
|
}
|
|
if form.Hero.ButtonLink != "" {
|
|
cms.Hero.ButtonLink = form.Hero.ButtonLink
|
|
}
|
|
if form.Hero.GifFile != "" {
|
|
cms.Hero.GifFile = form.Hero.GifFile
|
|
}
|
|
|
|
// Chart section
|
|
if form.Chart.Title != "" {
|
|
cms.Chart.Title = form.Chart.Title
|
|
}
|
|
if form.Chart.MissedAmount != "" {
|
|
cms.Chart.MissedAmount = form.Chart.MissedAmount
|
|
}
|
|
if len(form.Chart.Data) > 0 {
|
|
cms.Chart.Data = make([]chartPoint, len(form.Chart.Data))
|
|
for i, point := range form.Chart.Data {
|
|
cms.Chart.Data[i] = chartPoint(point)
|
|
}
|
|
}
|
|
|
|
// Features section
|
|
s.copyCardSectionForm(&form.Features, &cms.Features)
|
|
|
|
// Challenges section
|
|
s.copyCardSectionForm(&form.Challenges, &cms.Challenges)
|
|
|
|
// Advantages section
|
|
s.copyCardSectionForm(&form.Advantages, &cms.Advantages)
|
|
|
|
// Contact section
|
|
if form.Contact.Title != "" {
|
|
cms.Contact.Title = form.Contact.Title
|
|
}
|
|
if form.Contact.Description != "" {
|
|
cms.Contact.Description = form.Contact.Description
|
|
}
|
|
if form.Contact.SubmitButtonText != "" {
|
|
cms.Contact.SubmitButtonText = form.Contact.SubmitButtonText
|
|
}
|
|
if len(form.Contact.Fields) > 0 {
|
|
cms.Contact.Fields = make([]formField, len(form.Contact.Fields))
|
|
for i, field := range form.Contact.Fields {
|
|
cms.Contact.Fields[i] = formField(field)
|
|
}
|
|
}
|
|
|
|
// Footer section
|
|
if form.Footer.Email != "" {
|
|
cms.Footer.Email = form.Footer.Email
|
|
}
|
|
if form.Footer.Phone != "" {
|
|
cms.Footer.Phone = form.Footer.Phone
|
|
}
|
|
if form.Footer.Location != "" {
|
|
cms.Footer.Location = form.Footer.Location
|
|
}
|
|
if form.Footer.Tagline != "" {
|
|
cms.Footer.Tagline = form.Footer.Tagline
|
|
}
|
|
if form.Footer.Copyright != "" {
|
|
cms.Footer.Copyright = form.Footer.Copyright
|
|
}
|
|
}
|
|
|
|
// copyCardSectionForm copies card section form data to entity
|
|
func (s *cmsService) copyCardSectionForm(formSection *cardSectionForm, entitySection *cardSection) {
|
|
if formSection.Title != "" {
|
|
entitySection.Title = formSection.Title
|
|
}
|
|
if formSection.Description != "" {
|
|
entitySection.Description = formSection.Description
|
|
}
|
|
if len(formSection.Cards) > 0 {
|
|
entitySection.Cards = make([]card, len(formSection.Cards))
|
|
for i, cardForm := range formSection.Cards {
|
|
entitySection.Cards[i] = card(cardForm)
|
|
}
|
|
}
|
|
}
|