perf: add pagination, filters, and fix Django sync pagination
This commit is contained in:
@@ -4,9 +4,131 @@ import (
|
||||
"fmt"
|
||||
"gorm.io/gorm"
|
||||
"log"
|
||||
"math"
|
||||
"rrbec_server/internal/models"
|
||||
"time"
|
||||
)
|
||||
|
||||
type PaginationParams struct {
|
||||
Page int
|
||||
Limit int
|
||||
Sort string
|
||||
Filters map[string]interface{}
|
||||
}
|
||||
|
||||
type PaginatedResponse struct {
|
||||
Data interface{} `json:"data"`
|
||||
Total int64 `json:"total"`
|
||||
Page int `json:"page"`
|
||||
Limit int `json:"limit"`
|
||||
TotalPages int `json:"total_pages"`
|
||||
}
|
||||
|
||||
func (p *PaginationParams) Apply(db *gorm.DB, model interface{}) (*gorm.DB, int64, error) {
|
||||
if p.Page <= 0 {
|
||||
p.Page = 1
|
||||
}
|
||||
if p.Limit <= 0 {
|
||||
p.Limit = 50
|
||||
}
|
||||
if p.Limit > 200 {
|
||||
p.Limit = 200
|
||||
}
|
||||
|
||||
query := db.Model(model)
|
||||
|
||||
for key, value := range p.Filters {
|
||||
if key == "status" {
|
||||
if s, ok := value.(string); ok && s != "" {
|
||||
query = query.Where("status = ?", s)
|
||||
}
|
||||
} else if key == "active" {
|
||||
if b, ok := value.(bool); ok {
|
||||
query = query.Where("active = ?", b)
|
||||
}
|
||||
} else if key == "category" {
|
||||
if c, ok := value.(uint); ok && c > 0 {
|
||||
query = query.Where("category = ?", c)
|
||||
}
|
||||
} else if key == "cuisine" {
|
||||
if b, ok := value.(bool); ok {
|
||||
query = query.Where("cuisine = ?", b)
|
||||
}
|
||||
} else if key == "date_from" {
|
||||
if t, ok := value.(time.Time); ok {
|
||||
query = query.Where("date_time >= ? OR dt_open >= ? OR created_at >= ?", t, t, t)
|
||||
}
|
||||
} else if key == "date_to" {
|
||||
if t, ok := value.(time.Time); ok {
|
||||
query = query.Where("date_time <= ? OR dt_open <= ? OR created_at <= ?", t, t, t)
|
||||
}
|
||||
} else if key == "comanda_id" {
|
||||
if c, ok := value.(uint); ok && c > 0 {
|
||||
query = query.Where("comanda_id = ?", c)
|
||||
}
|
||||
} else if key == "name" {
|
||||
if n, ok := value.(string); ok && n != "" {
|
||||
query = query.Where("name LIKE ?", "%"+n+"%")
|
||||
}
|
||||
} else if key == "canceled" {
|
||||
if v, ok := value.(bool); ok {
|
||||
if v {
|
||||
query = query.Where("canceled IS NOT NULL")
|
||||
} else {
|
||||
query = query.Where("canceled IS NULL")
|
||||
}
|
||||
}
|
||||
} else if key == "delivered" {
|
||||
if v, ok := value.(bool); ok {
|
||||
if v {
|
||||
query = query.Where("delivered IS NOT NULL")
|
||||
} else {
|
||||
query = query.Where("delivered IS NULL")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
sort := "id ASC"
|
||||
if p.Sort != "" {
|
||||
sort = p.Sort
|
||||
}
|
||||
|
||||
offset := (p.Page - 1) * p.Limit
|
||||
query = query.Order(sort).Offset(offset).Limit(p.Limit)
|
||||
|
||||
return query, total, nil
|
||||
}
|
||||
|
||||
func (p *PaginationParams) Paginate(db *gorm.DB, model interface{}, result interface{}) (*PaginatedResponse, error) {
|
||||
query, total, err := p.Apply(db, model)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := query.Find(result).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
totalPages := int(math.Ceil(float64(total) / float64(p.Limit)))
|
||||
if totalPages == 0 {
|
||||
totalPages = 1
|
||||
}
|
||||
|
||||
return &PaginatedResponse{
|
||||
Data: result,
|
||||
Total: total,
|
||||
Page: p.Page,
|
||||
Limit: p.Limit,
|
||||
TotalPages: totalPages,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
@@ -16,10 +138,9 @@ func NewRepository(db *gorm.DB) *Repository {
|
||||
}
|
||||
|
||||
// Mesa
|
||||
func (r *Repository) GetMesas() ([]models.Mesa, error) {
|
||||
func (r *Repository) GetMesas(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var mesas []models.Mesa
|
||||
err := r.db.Find(&mesas).Error
|
||||
return mesas, err
|
||||
return params.Paginate(r.db, &models.Mesa{}, &mesas)
|
||||
}
|
||||
|
||||
func (r *Repository) CreateMesa(mesa *models.Mesa) error {
|
||||
@@ -31,10 +152,9 @@ func (r *Repository) SaveMesa(mesa *models.Mesa) error {
|
||||
}
|
||||
|
||||
// Client
|
||||
func (r *Repository) GetClients() ([]models.Client, error) {
|
||||
func (r *Repository) GetClients(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var clients []models.Client
|
||||
err := r.db.Find(&clients).Error
|
||||
return clients, err
|
||||
return params.Paginate(r.db, &models.Client{}, &clients)
|
||||
}
|
||||
|
||||
func (r *Repository) CreateClient(client *models.Client) error {
|
||||
@@ -46,10 +166,13 @@ func (r *Repository) SaveClient(client *models.Client) error {
|
||||
}
|
||||
|
||||
// Product
|
||||
func (r *Repository) GetProducts() ([]models.Product, error) {
|
||||
func (r *Repository) GetProducts(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var products []models.Product
|
||||
err := r.db.Find(&products).Error
|
||||
return products, err
|
||||
return params.Paginate(r.db, &models.Product{}, &products)
|
||||
}
|
||||
|
||||
func (r *Repository) GetProductsAll(products *[]models.Product) error {
|
||||
return r.db.Find(products).Error
|
||||
}
|
||||
|
||||
func (r *Repository) SaveProduct(product *models.Product) error {
|
||||
@@ -88,20 +211,33 @@ func (r *Repository) CreateProduct(product *models.Product) error {
|
||||
}
|
||||
|
||||
// Comanda
|
||||
func (r *Repository) GetComandas() ([]models.Comanda, error) {
|
||||
func (r *Repository) GetComandas(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var comandas []models.Comanda
|
||||
if err := r.db.Find(&comandas).Error; err != nil {
|
||||
if params == nil {
|
||||
params = &PaginationParams{Page: 1, Limit: 50}
|
||||
}
|
||||
|
||||
query, total, err := params.Apply(r.db, &models.Comanda{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// For each comanda, load its items
|
||||
for i := range comandas {
|
||||
var items []models.ProductComanda
|
||||
r.db.Where("comanda_id = ?", comandas[i].ID).Find(&items)
|
||||
comandas[i].Items = items
|
||||
if err := query.Preload("Items").Find(&comandas).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return comandas, nil
|
||||
totalPages := int(math.Ceil(float64(total) / float64(params.Limit)))
|
||||
if totalPages == 0 {
|
||||
totalPages = 1
|
||||
}
|
||||
|
||||
return &PaginatedResponse{
|
||||
Data: comandas,
|
||||
Total: total,
|
||||
Page: params.Page,
|
||||
Limit: params.Limit,
|
||||
TotalPages: totalPages,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *Repository) CreateComanda(comanda *models.Comanda) error {
|
||||
@@ -128,16 +264,14 @@ func (r *Repository) SaveTypePay(tp *models.TypePay) error {
|
||||
return r.db.Save(tp).Error
|
||||
}
|
||||
|
||||
func (r *Repository) GetCategories() ([]models.Category, error) {
|
||||
func (r *Repository) GetCategories(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var categories []models.Category
|
||||
err := r.db.Find(&categories).Error
|
||||
return categories, err
|
||||
return params.Paginate(r.db, &models.Category{}, &categories)
|
||||
}
|
||||
|
||||
func (r *Repository) GetTypePayments() ([]models.TypePay, error) {
|
||||
func (r *Repository) GetTypePayments(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var types []models.TypePay
|
||||
err := r.db.Find(&types).Error
|
||||
return types, err
|
||||
return params.Paginate(r.db, &models.TypePay{}, &types)
|
||||
}
|
||||
|
||||
func (r *Repository) GetComandaByID(id uint) (*models.Comanda, error) {
|
||||
@@ -172,10 +306,9 @@ func (r *Repository) DeleteItem(itemID uint) error {
|
||||
return r.db.Delete(&models.ProductComanda{}, itemID).Error
|
||||
}
|
||||
|
||||
func (r *Repository) GetOrders() ([]models.Order, error) {
|
||||
func (r *Repository) GetOrders(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var orders []models.Order
|
||||
err := r.db.Find(&orders).Error
|
||||
return orders, err
|
||||
return params.Paginate(r.db, &models.Order{}, &orders)
|
||||
}
|
||||
|
||||
func (r *Repository) SaveOrder(order *models.Order) error {
|
||||
@@ -216,10 +349,9 @@ func (r *Repository) UpdateOrderFields(id uint, updates map[string]interface{})
|
||||
return r.db.Model(&models.Order{}).Where("id = ?", id).Updates(mappedUpdates).Error
|
||||
}
|
||||
|
||||
func (r *Repository) GetPayments() ([]models.Payment, error) {
|
||||
func (r *Repository) GetPayments(params *PaginationParams) (*PaginatedResponse, error) {
|
||||
var payments []models.Payment
|
||||
err := r.db.Find(&payments).Error
|
||||
return payments, err
|
||||
return params.Paginate(r.db, &models.Payment{}, &payments)
|
||||
}
|
||||
|
||||
func (r *Repository) CreatePayment(payment *models.Payment) error {
|
||||
|
||||
Reference in New Issue
Block a user