- 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
178 lines
4.6 KiB
Go
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"`
|
|
}
|