mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
dev day #65
This commit is contained in:
@@ -0,0 +1,297 @@
|
||||
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")
|
||||
}
|
||||
Reference in New Issue
Block a user