Files
QuoteForge/internal/handlers/partnumber_books.go
2026-03-15 16:28:32 +03:00

107 lines
2.9 KiB
Go

package handlers
import (
"net/http"
"strconv"
"strings"
"git.mchus.pro/mchus/quoteforge/internal/localdb"
"git.mchus.pro/mchus/quoteforge/internal/repository"
"github.com/gin-gonic/gin"
)
// PartnumberBooksHandler provides read-only access to local partnumber book snapshots.
type PartnumberBooksHandler struct {
localDB *localdb.LocalDB
}
func NewPartnumberBooksHandler(localDB *localdb.LocalDB) *PartnumberBooksHandler {
return &PartnumberBooksHandler{localDB: localDB}
}
// List returns all local partnumber book snapshots.
// GET /api/partnumber-books
func (h *PartnumberBooksHandler) List(c *gin.Context) {
bookRepo := repository.NewPartnumberBookRepository(h.localDB.DB())
books, err := bookRepo.ListBooks()
if err != nil {
RespondError(c, http.StatusInternalServerError, "internal server error", err)
return
}
type bookSummary struct {
ID uint `json:"id"`
ServerID int `json:"server_id"`
Version string `json:"version"`
CreatedAt string `json:"created_at"`
IsActive bool `json:"is_active"`
ItemCount int64 `json:"item_count"`
}
summaries := make([]bookSummary, 0, len(books))
for _, b := range books {
summaries = append(summaries, bookSummary{
ID: b.ID,
ServerID: b.ServerID,
Version: b.Version,
CreatedAt: b.CreatedAt.Format("2006-01-02"),
IsActive: b.IsActive,
ItemCount: bookRepo.CountBookItems(b.ID),
})
}
c.JSON(http.StatusOK, gin.H{
"books": summaries,
"total": len(summaries),
})
}
// GetItems returns items for a partnumber book by server ID.
// GET /api/partnumber-books/:id
func (h *PartnumberBooksHandler) GetItems(c *gin.Context) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid book ID"})
return
}
bookRepo := repository.NewPartnumberBookRepository(h.localDB.DB())
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
perPage, _ := strconv.Atoi(c.DefaultQuery("per_page", "100"))
search := strings.TrimSpace(c.Query("search"))
if page < 1 {
page = 1
}
if perPage < 1 || perPage > 500 {
perPage = 100
}
// Find local book by server_id
var book localdb.LocalPartnumberBook
if err := h.localDB.DB().Where("server_id = ?", id).First(&book).Error; err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "partnumber book not found"})
return
}
items, total, err := bookRepo.GetBookItemsPage(book.ID, search, page, perPage)
if err != nil {
RespondError(c, http.StatusInternalServerError, "internal server error", err)
return
}
c.JSON(http.StatusOK, gin.H{
"book_id": book.ServerID,
"version": book.Version,
"is_active": book.IsActive,
"partnumbers": book.PartnumbersJSON,
"items": items,
"total": total,
"page": page,
"per_page": perPage,
"search": search,
"book_total": bookRepo.CountBookItems(book.ID),
"lot_count": bookRepo.CountDistinctLots(book.ID),
})
}