feat(advertising): implement advertising service with CRUD operations and validation
- Added advertising.go for managing advertising entries with Create and List functionalities. - Implemented CreateAdvertisingParams with validation for name, email, and status. - Created migrations for advertising table structure. - Added tests for advertising parameters validation. feat(promo): introduce promo management with validation and CRUD operations - Added promo.go for managing promotional entries with Create, Update, and List functionalities. - Implemented CreatePromoParams and UpdatePromoParams with validation for position, section, and weeks. - Created migrations for promo table structure. - Added tests for promo parameters validation. feat(images): add image management service with upload and retrieval - Added images.go for managing image uploads and retrieval from storage. - Implemented SaveImageParams with validation for image description and data. - Created migrations for images table structure. - Added tests for image parameters validation and data parsing.
This commit is contained in:
154
advertising/advertising.go
Normal file
154
advertising/advertising.go
Normal file
@@ -0,0 +1,154 @@
|
||||
// Service advertising gestisce l'elenco delle inserzioni pubblicitarie (Advertising Directory).
|
||||
package advertising
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/mail"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"encore.dev/beta/errs"
|
||||
"encore.dev/storage/sqldb"
|
||||
"encore.dev/types/uuid"
|
||||
)
|
||||
|
||||
var db = sqldb.NewDatabase("advertising", sqldb.DatabaseConfig{
|
||||
Migrations: "./migrations",
|
||||
})
|
||||
|
||||
type Status string
|
||||
|
||||
const (
|
||||
StatusActive Status = "active"
|
||||
StatusInactive Status = "inactive"
|
||||
)
|
||||
|
||||
type Advertising struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Nome string `json:"nome"`
|
||||
Email string `json:"email"`
|
||||
Status Status `json:"status"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type CreateAdvertisingParams struct {
|
||||
Nome string `json:"nome"`
|
||||
Email string `json:"email"`
|
||||
Status Status `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (p *CreateAdvertisingParams) Validate() error {
|
||||
if p == nil {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "i parametri di creazione sono obbligatori"}
|
||||
}
|
||||
|
||||
email, err := normalizeEmailValue(p.Email)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Email = email
|
||||
|
||||
nome := normalizeText(p.Nome)
|
||||
if nome == "" {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "il nome è obbligatorio"}
|
||||
}
|
||||
p.Nome = nome
|
||||
|
||||
if p.Status == "" {
|
||||
p.Status = StatusActive
|
||||
} else if p.Status != StatusActive && p.Status != StatusInactive {
|
||||
return &errs.Error{Code: errs.InvalidArgument, Message: "lo status deve essere 'active' o 'inactive'"}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeEmailValue(email string) (string, error) {
|
||||
email = strings.TrimSpace(strings.ToLower(email))
|
||||
if email == "" {
|
||||
return "", &errs.Error{Code: errs.InvalidArgument, Message: "l'email è obbligatoria"}
|
||||
}
|
||||
parsed, err := mail.ParseAddress(email)
|
||||
if err != nil || !strings.Contains(parsed.Address, "@") || !strings.Contains(parsed.Address, ".") {
|
||||
return "", &errs.Error{Code: errs.InvalidArgument, Message: "indirizzo email non valido"}
|
||||
}
|
||||
return strings.TrimSpace(strings.ToLower(parsed.Address)), nil
|
||||
}
|
||||
|
||||
func normalizeText(value string) string {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" {
|
||||
return ""
|
||||
}
|
||||
parts := strings.Fields(value)
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
type ListAdvertisingResponse struct {
|
||||
Advertising []*Advertising `json:"advertising"`
|
||||
}
|
||||
|
||||
// List ritorna l'intera lista delle pubblicità ordinate per data di creazione.
|
||||
//
|
||||
//encore:api public method=GET path=/advertising
|
||||
func List(ctx context.Context) (*ListAdvertisingResponse, error) {
|
||||
rows, err := db.Query(ctx, `
|
||||
SELECT id, nome, email, status, created_at
|
||||
FROM advertising
|
||||
ORDER BY created_at DESC
|
||||
`)
|
||||
if err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "errore durante il recupero delle pubblicità")
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var list []*Advertising
|
||||
for rows.Next() {
|
||||
var a Advertising
|
||||
if err := rows.Scan(&a.ID, &a.Nome, &a.Email, &a.Status, &a.CreatedAt); err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "errore durante la lettura del record pubblicità")
|
||||
}
|
||||
list = append(list, &a)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "errore durante l'iterazione delle pubblicità")
|
||||
}
|
||||
|
||||
if list == nil {
|
||||
list = []*Advertising{}
|
||||
}
|
||||
|
||||
return &ListAdvertisingResponse{Advertising: list}, nil
|
||||
}
|
||||
|
||||
// Create crea un nuovo cliente/pubblicità con validazione dell'email e dei campi.
|
||||
//
|
||||
//encore:api public method=POST path=/advertising
|
||||
func Create(ctx context.Context, p *CreateAdvertisingParams) (*Advertising, error) {
|
||||
if err := p.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "impossibile generare l'identificativo UUID")
|
||||
}
|
||||
|
||||
item := Advertising{
|
||||
ID: id,
|
||||
Nome: p.Nome,
|
||||
Email: p.Email,
|
||||
Status: p.Status,
|
||||
}
|
||||
|
||||
err = db.QueryRow(ctx, `
|
||||
INSERT INTO advertising (id, nome, email, status)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
RETURNING created_at
|
||||
`, id, p.Nome, p.Email, p.Status).Scan(&item.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, errs.WrapCode(err, errs.Internal, "impossibile creare la pubblicità")
|
||||
}
|
||||
|
||||
return &item, nil
|
||||
}
|
||||
Reference in New Issue
Block a user