package server import ( "context" _ "embed" "encoding/json" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" "perler-beads-server/internal/domain" "time" ) //go:embed migrations/001_initial.sql var migration string func (s *Server) put(ctx context.Context, kind, id, store, owner string, v any) error { b, e := json.Marshal(v) if e != nil { return e } _, e = s.DB.Exec(ctx, `INSERT INTO documents(kind,id,store_id,owner_id,body) VALUES($1,$2,$3,$4,$5) ON CONFLICT(kind,id) DO UPDATE SET body=EXCLUDED.body,store_id=EXCLUDED.store_id,owner_id=EXCLUDED.owner_id`, kind, id, store, owner, b) return e } func (s *Server) get(ctx context.Context, kind, id string, v any) error { var b []byte e := s.DB.QueryRow(ctx, `SELECT body FROM documents WHERE kind=$1 AND id=$2`, kind, id).Scan(&b) if e != nil { return e } return json.Unmarshal(b, v) } func getTx(ctx context.Context, tx pgx.Tx, kind, id string, v any) error { var b []byte if err := tx.QueryRow(ctx, `SELECT body FROM documents WHERE kind=$1 AND id=$2`, kind, id).Scan(&b); err != nil { return err } return json.Unmarshal(b, v) } func rollback(tx pgx.Tx) { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() _ = tx.Rollback(ctx) } func (s *Server) list(ctx context.Context, kind string) ([]json.RawMessage, error) { rows, e := s.DB.Query(ctx, `SELECT body FROM documents WHERE kind=$1 ORDER BY id`, kind) if e != nil { return nil, e } defer rows.Close() out := []json.RawMessage{} for rows.Next() { var b []byte if e = rows.Scan(&b); e != nil { return nil, e } out = append(out, b) } return out, rows.Err() } func Migrate(ctx context.Context, db *pgxpool.Pool) error { _, e := db.Exec(ctx, migration); return e } func (s *Server) Seed(ctx context.Context) error { var n int if e := s.DB.QueryRow(ctx, `SELECT count(*) FROM documents WHERE kind='store'`).Scan(&n); e != nil { return e } if n > 0 { return nil } store := domain.Store{ID: "store-001", Name: "拼豆体验店(演示)", Address: "请在后台配置真实地址", Hours: "10:00–20:00(演示)", Notice: "演示色板非品牌真实色号"} cs := demoColors() if e := s.put(ctx, "store", store.ID, store.ID, "", store); e != nil { return e } if e := s.put(ctx, "palette", store.ID, store.ID, "", cs); e != nil { return e } if e := s.put(ctx, "tables", store.ID, store.ID, "", []domain.Table{{Code: "T01", Label: "1 号桌(演示)", Enabled: true}, {Code: "T02", Label: "2 号桌(演示)", Enabled: true}}); e != nil { return e } for _, p := range demoPatterns(store.ID, cs) { if e := s.put(ctx, "pattern", p.ID, p.StoreID, "", p); e != nil { return e } } return nil }