178 lines
3.7 KiB
Go
178 lines
3.7 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/google/uuid"
|
|
"net/url"
|
|
"perler-beads-server/internal/domain"
|
|
)
|
|
|
|
func (s *Server) visitCreate(c *gin.Context) {
|
|
if !need(c, "") {
|
|
return
|
|
}
|
|
var in struct {
|
|
StoreID string `json:"storeId"`
|
|
TableCode string `json:"tableCode"`
|
|
}
|
|
if !bind(c, &in) {
|
|
return
|
|
}
|
|
var tables []domain.Table
|
|
if s.get(c, "tables", in.StoreID, &tables) != nil {
|
|
fail(c, errors.New("门店不存在"))
|
|
return
|
|
}
|
|
enabled := false
|
|
for _, t := range tables {
|
|
if t.Code == in.TableCode && t.Enabled {
|
|
enabled = true
|
|
}
|
|
}
|
|
if !enabled {
|
|
fail(c, errors.New("桌码未启用"))
|
|
return
|
|
}
|
|
v := domain.Visit{ID: uuid.NewString(), StoreID: in.StoreID, TableCode: in.TableCode, Status: "active"}
|
|
b, _ := json.Marshal(v)
|
|
if _, e := s.DB.Exec(c, `INSERT INTO visits(user_id,body) VALUES($1,$2) ON CONFLICT(user_id) DO UPDATE SET body=EXCLUDED.body`, user(c).ID, b); e != nil {
|
|
fail(c, e)
|
|
return
|
|
}
|
|
ok(c, v)
|
|
}
|
|
func (s *Server) visit(c *gin.Context) (domain.Visit, error) {
|
|
var b []byte
|
|
var v domain.Visit
|
|
e := s.DB.QueryRow(c, `SELECT body FROM visits WHERE user_id=$1`, user(c).ID).Scan(&b)
|
|
if e == nil {
|
|
e = json.Unmarshal(b, &v)
|
|
}
|
|
return v, e
|
|
}
|
|
func (s *Server) visitGet(c *gin.Context) {
|
|
if !need(c, "") {
|
|
return
|
|
}
|
|
v, e := s.visit(c)
|
|
if e != nil || v.Status != "active" {
|
|
ok(c, nil)
|
|
return
|
|
}
|
|
ok(c, v)
|
|
}
|
|
func (s *Server) visitClose(c *gin.Context) {
|
|
if !need(c, "") {
|
|
return
|
|
}
|
|
if _, e := s.DB.Exec(c, `DELETE FROM visits WHERE user_id=$1`, user(c).ID); e != nil {
|
|
fail(c, e)
|
|
return
|
|
}
|
|
ok(c, nil)
|
|
}
|
|
func (s *Server) tableList(c *gin.Context) {
|
|
if !need(c, "staff") {
|
|
return
|
|
}
|
|
if storeID(c) != user(c).StoreID {
|
|
reply(c, 401, "门店无权限", nil)
|
|
return
|
|
}
|
|
var v []domain.Table
|
|
if e := s.get(c, "tables", storeID(c), &v); e != nil {
|
|
fail(c, e)
|
|
return
|
|
}
|
|
ok(c, v)
|
|
}
|
|
func (s *Server) palettePut(c *gin.Context) {
|
|
if !need(c, "admin") {
|
|
return
|
|
}
|
|
var in struct {
|
|
StoreID string `json:"storeId"`
|
|
Colors []domain.Color `json:"colors"`
|
|
}
|
|
if !bind(c, &in) {
|
|
return
|
|
}
|
|
if in.StoreID != user(c).StoreID {
|
|
reply(c, 401, "门店无权限", nil)
|
|
return
|
|
}
|
|
if e := domain.ValidateColors(in.Colors); e != nil {
|
|
fail(c, e)
|
|
return
|
|
}
|
|
if e := s.put(c, "palette", in.StoreID, in.StoreID, "", in.Colors); e != nil {
|
|
fail(c, e)
|
|
return
|
|
}
|
|
ok(c, in.Colors)
|
|
}
|
|
func (s *Server) tablePut(c *gin.Context) {
|
|
if !need(c, "admin") {
|
|
return
|
|
}
|
|
var in struct {
|
|
StoreID string `json:"storeId"`
|
|
Tables []domain.Table `json:"tables"`
|
|
}
|
|
if !bind(c, &in) {
|
|
return
|
|
}
|
|
if in.StoreID != user(c).StoreID {
|
|
reply(c, 401, "门店无权限", nil)
|
|
return
|
|
}
|
|
seen := map[string]bool{}
|
|
if len(in.Tables) > 200 {
|
|
fail(c, errors.New("桌位超过限制"))
|
|
return
|
|
}
|
|
for _, t := range in.Tables {
|
|
if t.Code == "" || len(t.Code) > 64 || seen[t.Code] || t.Label == "" {
|
|
fail(c, errors.New("桌码或名称无效/重复"))
|
|
return
|
|
}
|
|
seen[t.Code] = true
|
|
}
|
|
if e := s.put(c, "tables", in.StoreID, in.StoreID, "", in.Tables); e != nil {
|
|
fail(c, e)
|
|
return
|
|
}
|
|
ok(c, in.Tables)
|
|
}
|
|
func endpointValid(v string) bool {
|
|
if v == "" {
|
|
return true
|
|
}
|
|
u, e := url.Parse(v)
|
|
return e == nil && u.Scheme == "https" && u.Host != "" && u.User == nil && u.RawQuery == "" && u.Fragment == ""
|
|
}
|
|
func (s *Server) storePut(c *gin.Context) {
|
|
if !need(c, "admin") {
|
|
return
|
|
}
|
|
var v domain.Store
|
|
if !bind(c, &v) {
|
|
return
|
|
}
|
|
if v.ID != user(c).StoreID {
|
|
reply(c, 401, "门店无权限", nil)
|
|
return
|
|
}
|
|
if v.Name == "" || !endpointValid(v.LocalBaseURL) || !endpointValid(v.PublicBaseURL) {
|
|
fail(c, errors.New("门店名称或 HTTPS 端点无效"))
|
|
return
|
|
}
|
|
if e := s.put(c, "store", v.ID, v.ID, "", v); e != nil {
|
|
fail(c, e)
|
|
return
|
|
}
|
|
ok(c, v)
|
|
}
|