Files
MyClub/internal/controllers/example_usage_controller.go
T
Tomas Dvorak 9ccca365b3 dev day #65
2025-10-19 18:09:28 +02:00

298 lines
8.3 KiB
Go

package controllers
import (
"fotbal-club/internal/models"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// ExampleUsageController demonstrates how to use the new utility controllers
type ExampleUsageController struct {
DB *gorm.DB
}
// NewExampleUsageController creates a new ExampleUsageController instance
func NewExampleUsageController(db *gorm.DB) *ExampleUsageController {
return &ExampleUsageController{DB: db}
}
// ===== EXAMPLE 1: Simple List with Pagination =====
// GET /api/v1/articles?page=1&page_size=20
func (euc *ExampleUsageController) ListArticlesWithPagination(c *gin.Context) {
query := euc.DB.Model(&models.Article{}).Where("published = ?", true)
var articles []models.Article
meta, err := Paginator.Paginate(c, query, &articles)
if err != nil {
Respond.InternalError(c, "Failed to retrieve articles")
return
}
Respond.SuccessWithMeta(c, articles, meta, "Articles retrieved successfully")
}
// ===== EXAMPLE 2: List with Search, Sort, and Pagination =====
// GET /api/v1/articles?search=football&sort=created_at:desc&page=1&page_size=20
func (euc *ExampleUsageController) ListArticlesWithFilters(c *gin.Context) {
query := QueryParser.BuildQueryChain(c, euc.DB.Model(&models.Article{})).
WithSearch("title", "content").
WithSort("created_at", "desc").
Build()
var articles []models.Article
meta, err := Paginator.PaginateWithPreload(c, query, &articles, "Author", "Category")
if err != nil {
Respond.InternalError(c, "Failed to retrieve articles")
return
}
Respond.SuccessWithMeta(c, articles, meta, "Articles retrieved successfully")
}
// ===== EXAMPLE 3: Create with Validation =====
func (euc *ExampleUsageController) CreateArticleWithValidation(c *gin.Context) {
var req struct {
Title string `json:"title" validate:"required,min=3,max=200"`
Content string `json:"content" validate:"required,min=10"`
Slug string `json:"slug" validate:"omitempty,slug"`
}
if err := c.ShouldBindJSON(&req); err != nil {
Respond.BadRequest(c, "Invalid JSON: "+err.Error())
return
}
// Validate using our helper
if !Validator.ValidateAndRespond(c, req) {
return // Response already sent
}
// Sanitize inputs
req.Title = Validator.SanitizeString(req.Title)
req.Slug = Validator.SanitizeSlug(req.Slug)
article := models.Article{
Title: req.Title,
Content: req.Content,
Slug: req.Slug,
}
if err := euc.DB.Create(&article).Error; err != nil {
Respond.InternalError(c, "Failed to create article")
return
}
// Log the creation
if AuditLogger != nil {
_ = AuditLogger.LogCreate(c, "Article", article.ID, "Article created: "+article.Title)
}
Respond.Created(c, article, "Article created successfully")
}
// ===== EXAMPLE 4: Update with Audit Logging =====
func (euc *ExampleUsageController) UpdateArticleWithAudit(c *gin.Context) {
id := c.Param("id")
var article models.Article
if err := euc.DB.First(&article, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
Respond.NotFound(c, "Article not found")
return
}
Respond.InternalError(c, "Failed to retrieve article")
return
}
// Store old values for audit
oldTitle := article.Title
oldPublished := article.Published
var req struct {
Title string `json:"title" validate:"omitempty,min=3,max=200"`
Published *bool `json:"published"`
}
if err := c.ShouldBindJSON(&req); err != nil {
Respond.BadRequest(c, "Invalid JSON: "+err.Error())
return
}
if !Validator.ValidateAndRespond(c, req) {
return
}
// Apply updates
if req.Title != "" {
article.Title = Validator.SanitizeString(req.Title)
}
if req.Published != nil {
article.Published = *req.Published
}
if err := euc.DB.Save(&article).Error; err != nil {
Respond.InternalError(c, "Failed to update article")
return
}
// Log the update with changes
if AuditLogger != nil {
before := map[string]interface{}{
"title": oldTitle,
"published": oldPublished,
}
after := map[string]interface{}{
"title": article.Title,
"published": article.Published,
}
_ = AuditLogger.LogUpdate(c, "Article", article.ID, "Article updated", before, after)
}
Respond.Success(c, article, "Article updated successfully")
}
// ===== EXAMPLE 5: Batch Delete =====
// POST /api/v1/articles/batch-delete
// Body: {"ids": [1, 2, 3]}
func (euc *ExampleUsageController) BatchDeleteArticles(c *gin.Context) {
if BatchOps == nil {
BatchOps = NewBatchOperationsController(euc.DB)
}
BatchOps.BatchDelete(c, &models.Article{}, "articles")
}
// ===== EXAMPLE 6: Advanced Filtering =====
// GET /api/v1/articles?published=true&category_ids=1,2,3&from=2024-01-01&to=2024-12-31
func (euc *ExampleUsageController) ListArticlesAdvanced(c *gin.Context) {
query := QueryParser.BuildQueryChain(c, euc.DB.Model(&models.Article{})).
WithSearch("title", "content").
WithSort("created_at", "desc").
WithBoolFilter("published", "published").
WithBoolFilter("featured", "featured").
WithIDsFilter("category_ids", "category_id").
WithDateRange("created_at").
Build()
var articles []models.Article
meta, err := Paginator.PaginateWithPreload(c, query, &articles, "Author", "Category")
if err != nil {
Respond.InternalError(c, "Failed to retrieve articles")
return
}
Respond.SuccessWithMeta(c, articles, meta, "Articles retrieved successfully")
}
// ===== EXAMPLE 7: Batch Publish/Unpublish =====
// POST /api/v1/articles/batch-publish
// Body: {"ids": [1, 2, 3]}
func (euc *ExampleUsageController) BatchPublishArticles(c *gin.Context) {
if BatchOps == nil {
BatchOps = NewBatchOperationsController(euc.DB)
}
BatchOps.BatchPublish(c, &models.Article{}, "articles", true)
}
func (euc *ExampleUsageController) BatchUnpublishArticles(c *gin.Context) {
if BatchOps == nil {
BatchOps = NewBatchOperationsController(euc.DB)
}
BatchOps.BatchPublish(c, &models.Article{}, "articles", false)
}
// ===== EXAMPLE 8: Get Entity with Standard Response =====
func (euc *ExampleUsageController) GetArticle(c *gin.Context) {
id := c.Param("id")
var article models.Article
if err := euc.DB.Preload("Author").Preload("Category").First(&article, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
Respond.NotFound(c, "Article not found")
return
}
Respond.InternalError(c, "Failed to retrieve article")
return
}
Respond.Success(c, article, "Article retrieved successfully")
}
// ===== EXAMPLE 9: Delete with Audit =====
func (euc *ExampleUsageController) DeleteArticleWithAudit(c *gin.Context) {
id := c.Param("id")
var article models.Article
if err := euc.DB.First(&article, id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
Respond.NotFound(c, "Article not found")
return
}
Respond.InternalError(c, "Failed to retrieve article")
return
}
title := article.Title
articleID := article.ID
if err := euc.DB.Delete(&article).Error; err != nil {
Respond.InternalError(c, "Failed to delete article")
return
}
// Log the deletion
if AuditLogger != nil {
_ = AuditLogger.LogDelete(c, "Article", articleID, "Article deleted: "+title)
}
Respond.NoContent(c)
}
// ===== EXAMPLE 10: Complex Query with Multiple Filters =====
func (euc *ExampleUsageController) SearchArticlesComplex(c *gin.Context) {
// Start with base query
query := euc.DB.Model(&models.Article{})
// Get search term
searchTerm := QueryParser.GetSearchQuery(c)
if searchTerm != "" {
query = QueryParser.ApplySearch(query, searchTerm, "title", "content", "seo_description")
}
// Apply boolean filters
if published := QueryParser.GetBoolQuery(c, "published"); published != nil {
query = query.Where("published = ?", *published)
}
if featured := QueryParser.GetBoolQuery(c, "featured"); featured != nil {
query = query.Where("featured = ?", *featured)
}
// Apply category filter
if categoryID := c.Query("category_id"); categoryID != "" {
query = query.Where("category_id = ?", categoryID)
}
// Apply date range
from, to := QueryParser.GetDateRange(c)
if from != "" {
query = query.Where("created_at >= ?", from)
}
if to != "" {
query = query.Where("created_at <= ?", to)
}
// Apply sorting
query = QueryParser.ApplySortFromContext(c, query, "created_at", "desc")
// Execute with pagination
var articles []models.Article
meta, err := Paginator.PaginateWithPreload(c, query, &articles, "Author", "Category")
if err != nil {
Respond.InternalError(c, "Failed to search articles")
return
}
Respond.SuccessWithMeta(c, articles, meta, "Search completed successfully")
}