Files
RRBEC-LocalServer/rrbec_server/internal/models/models.go
Welton Moura 936aad779b feat: RRBEC Local Server - Go backend with Django sync
- Implement local-first architecture with SQLite
- Add bidirectional sync with Django via ChangeLog
- JWT authentication with auto-refresh token
- REST API for products, orders, commands, payments
- Stock management with automatic deduction
2026-04-04 17:38:40 -03:00

178 lines
4.6 KiB
Go

package models
import (
"strconv"
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
// Custom type to handle Price as string or float from JSON
type Price float64
func (p *Price) UnmarshalJSON(data []byte) error {
if len(data) == 0 {
return nil
}
s := string(data)
// Remove quotes if it's a string
if s[0] == '"' {
s = s[1 : len(s)-1]
}
f, err := strconv.ParseFloat(s, 64)
if err != nil {
return err
}
*p = Price(f)
return nil
}
// Base model with UUID and sync fields
type Base struct {
ID uint `gorm:"primaryKey" json:"id"`
UUID string `gorm:"uniqueIndex" json:"uuid"`
Sincronizado bool `gorm:"default:false" json:"sincronizado"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (b *Base) BeforeCreate(tx *gorm.DB) (err error) {
if b.UUID == "" {
b.UUID = uuid.New().String()
}
return
}
type Mesa struct {
Base
Name string `json:"name"`
Location string `json:"location"`
Active bool `gorm:"default:false" json:"active"`
}
type Client struct {
Base
Name string `json:"name"`
Debt Price `gorm:"default:0" json:"debt"`
CreatedAt time.Time `json:"created_at"`
Active bool `gorm:"default:true" json:"active"`
Contact string `json:"contact"`
}
type Category struct {
Base
Name string `json:"name"`
Active bool `gorm:"default:true" json:"active"`
}
type Product struct {
Base
Name string `json:"name"`
Description string `json:"description"`
Image string `json:"image"` // URL or Path
Price Price `json:"price"`
Quantity int `gorm:"default:0" json:"quantity"`
CategoryID uint `gorm:"column:category" json:"category"`
Cuisine bool `gorm:"default:false" json:"cuisine"`
Active bool `gorm:"default:true" json:"active"`
UnitOfMeasure *uint `gorm:"column:unit_of_measure" json:"unit_of_measure"`
}
type ProductComponent struct {
Base
CompositeProductID uint `json:"composite_product"`
ComponentProductID uint `json:"component_product"`
QuantityRequired float64 `json:"quantity_required"`
}
type Comanda struct {
Base
MesaID uint `json:"mesa"`
UserID uint `json:"user"`
TypePayID *uint `json:"type_pay"`
ClientID *uint `json:"client"`
Name string `json:"name"`
Status string `json:"status"` // OPEN, CLOSED, FIADO
DtOpen time.Time `json:"dt_open"`
DtClose *time.Time `json:"dt_close"`
// Nested items from Django (not stored in coma nda table)
Items []ProductComanda `gorm:"-" json:"items"`
}
type ProductComanda struct {
Base
ComandaID uint `json:"comanda"`
ProductID uint `json:"product"`
ProductName string `gorm:"-" json:"product_name"` // Read-only
ProductPrice Price `gorm:"-" json:"product_price"` // Read-only
DateTime time.Time `json:"data_time"`
Applicant string `json:"applicant"`
Obs string `gorm:"-" json:"obs"` // From Order
}
type Order struct {
Base
ProductComandaID *uint `json:"productComanda"`
ProductID uint `json:"id_product"`
ComandaID uint `json:"id_comanda"`
Obs string `json:"obs"`
Queue time.Time `json:"queue"`
Preparing *time.Time `json:"preparing"`
Finished *time.Time `json:"finished"`
Delivered *time.Time `json:"delivered"`
Canceled *time.Time `json:"canceled"`
}
func (o *Order) BeforeCreate(tx *gorm.DB) (err error) {
// Call Base.BeforeCreate to generate UUID
if err := o.Base.BeforeCreate(tx); err != nil {
return err
}
if o.Queue.IsZero() {
o.Queue = time.Now()
}
return
}
type TypePay struct {
Base
Name string `json:"name"`
Active bool `gorm:"default:true" json:"active"`
}
type Payment struct {
Base
Value Price `json:"value"`
TypePayID uint `json:"type_pay"`
ComandaID uint `json:"comanda"`
ClientID *uint `json:"client"`
Description string `json:"description"`
DateTime time.Time `json:"datetime"`
}
type User struct {
Base
Username string `gorm:"uniqueIndex" json:"username"`
Password string `json:"password"`
Email string `json:"email"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
IsStaff bool `json:"is_staff"`
IsActive bool `json:"is_active"`
}
type SyncState struct {
ID uint `gorm:"primaryKey"`
LastSyncID int `gorm:"default:0"`
}
type ChangeLog struct {
ID int `json:"id"`
ModelName string `json:"model_name"`
ObjectID uint `json:"object_id"`
Action string `json:"action"` // SAVE or DELETE
Timestamp time.Time `json:"timestamp"`
}