complete news and catalog
parent
9937d8df67
commit
d7b1f65805
|
@ -1,35 +1,75 @@
|
|||
package endpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"relynolli-server/models"
|
||||
"relynolli-server/services"
|
||||
"strconv"
|
||||
"relynolli-server/status"
|
||||
"relynolli-server/storage"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type getCartItemsRequest struct {
|
||||
FuserId int64 `form:"fuserId"`
|
||||
}
|
||||
|
||||
func (h *handlers) GetCartItems(c *gin.Context) {
|
||||
ctx := context.Background()
|
||||
query := new(getCartItemsRequest)
|
||||
meta := models.Meta{
|
||||
RequestStarted: time.Now().Unix(),
|
||||
}
|
||||
|
||||
fuserId := c.Query("fuserId")
|
||||
if fuserId == "" {
|
||||
c.JSON(400, models.Response{Status: 400, Info: "\"fuserId\" should be provided"})
|
||||
err := c.ShouldBindQuery(query)
|
||||
if err != nil || query.FuserId == 0 {
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
c.JSON(400, models.Response{
|
||||
Status: status.STATUS_BAD_REQUEST,
|
||||
Info: "\"fuserId\" should be provided and be integer number",
|
||||
Meta: &meta})
|
||||
return
|
||||
}
|
||||
|
||||
idx, err := strconv.Atoi(fuserId)
|
||||
s := storage.NewStorageCart()
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, models.Response{Status: 400, Info: "\"fuserId should be an integer number\""})
|
||||
return
|
||||
}
|
||||
items, _ := s.GetCartItems(ctx, query.FuserId)
|
||||
|
||||
c.JSON(200, services.GetCartItems(idx))
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
c.JSON(200, models.Response{
|
||||
Status: status.STATUS_OK,
|
||||
Data: &items,
|
||||
Meta: &meta,
|
||||
})
|
||||
}
|
||||
|
||||
func (h *handlers) CreateFUser(c *gin.Context) {
|
||||
lastInsertId := services.CreateFuser()
|
||||
s := storage.NewStorageCart()
|
||||
ctx := context.Background()
|
||||
meta := models.Meta{
|
||||
RequestStarted: time.Now().Unix(),
|
||||
}
|
||||
|
||||
c.JSON(201, gin.H{
|
||||
"fuserId": lastInsertId,
|
||||
fuserId, fuser, err := s.CreateFuser(ctx)
|
||||
if err != nil {
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
c.JSON(500, models.Response{
|
||||
Status: status.STATUS_SERVER_ERROR,
|
||||
Info: fmt.Sprintf("Error: %s", err.Error()),
|
||||
Meta: &meta,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
c.JSON(201, models.Response{
|
||||
Status: status.STATUS_OK,
|
||||
Info: "New Fuser has created",
|
||||
Data: &gin.H{
|
||||
"fuserId": fuserId,
|
||||
"fuser": &fuser,
|
||||
},
|
||||
Meta: &meta,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -7,10 +7,10 @@ type handlers struct{}
|
|||
type Handlers interface {
|
||||
GetCartItems(c *gin.Context)
|
||||
CreateFUser(c *gin.Context)
|
||||
|
||||
CreateCartItem(c *gin.Context)
|
||||
UpdateCartItem(c *gin.Context)
|
||||
DeleteCartItem(c *gin.Context)
|
||||
//
|
||||
//CreateCartItem(c *gin.Context)
|
||||
//UpdateCartItem(c *gin.Context)
|
||||
//DeleteCartItem(c *gin.Context)
|
||||
}
|
||||
|
||||
func GetHandlers() Handlers {
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
package endpoints
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"relynolli-server/models"
|
||||
"relynolli-server/services"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type createCartItemRequest struct {
|
||||
FuserId int `json:"fuserId"`
|
||||
PriceTypeId int `json:"priceTypeId,omitempty"`
|
||||
|
@ -27,50 +18,50 @@ type deleteCartRequest struct {
|
|||
ProductId int `json:"productId"`
|
||||
}
|
||||
|
||||
func (h *handlers) CreateCartItem(c *gin.Context) {
|
||||
req := createCartItemRequest{}
|
||||
err := c.ShouldBindJSON(&req)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
return
|
||||
}
|
||||
services.AddItemToCart(req.FuserId, req.ProductId)
|
||||
|
||||
c.JSON(http.StatusCreated, models.Response{Status: http.StatusCreated, Info: fmt.Sprintf("Item %d has added to cart", req.ProductId)})
|
||||
}
|
||||
|
||||
func (h *handlers) UpdateCartItem(c *gin.Context) {
|
||||
req := updateCartRequest{}
|
||||
err := c.ShouldBindJSON(&req)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
err = services.UpdateCartItem(req.FuserId, req.ProductId, req.Quantity)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, models.Response{Status: http.StatusOK})
|
||||
|
||||
}
|
||||
|
||||
func (h *handlers) DeleteCartItem(c *gin.Context) {
|
||||
|
||||
req := deleteCartRequest{}
|
||||
err := c.ShouldBindJSON(&req)
|
||||
|
||||
if err != nil {
|
||||
c.JSON(400, models.Response{Status: 400, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
return
|
||||
}
|
||||
|
||||
services.DeleteCartItem(req.FuserId, req.ProductId)
|
||||
|
||||
c.JSON(http.StatusNoContent, models.Response{Status: http.StatusNoContent})
|
||||
}
|
||||
//func (h *handlers) CreateCartItem(c *gin.Context) {
|
||||
// req := createCartItemRequest{}
|
||||
// err := c.ShouldBindJSON(&req)
|
||||
//
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
// return
|
||||
// }
|
||||
// services.AddItemToCart(req.FuserId, req.ProductId)
|
||||
//
|
||||
// c.JSON(http.StatusCreated, models.Response{Status: http.StatusCreated, Info: fmt.Sprintf("Item %d has added to cart", req.ProductId)})
|
||||
//}
|
||||
//
|
||||
//func (h *handlers) UpdateCartItem(c *gin.Context) {
|
||||
// req := updateCartRequest{}
|
||||
// err := c.ShouldBindJSON(&req)
|
||||
//
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// err = services.UpdateCartItem(req.FuserId, req.ProductId, req.Quantity)
|
||||
//
|
||||
// if err != nil {
|
||||
// c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// c.JSON(http.StatusOK, models.Response{Status: http.StatusOK})
|
||||
//
|
||||
//}
|
||||
//
|
||||
//func (h *handlers) DeleteCartItem(c *gin.Context) {
|
||||
//
|
||||
// req := deleteCartRequest{}
|
||||
// err := c.ShouldBindJSON(&req)
|
||||
//
|
||||
// if err != nil {
|
||||
// c.JSON(400, models.Response{Status: 400, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// services.DeleteCartItem(req.FuserId, req.ProductId)
|
||||
//
|
||||
// c.JSON(http.StatusNoContent, models.Response{Status: http.StatusNoContent})
|
||||
//}
|
||||
|
|
|
@ -8,15 +8,15 @@ import (
|
|||
func HandleRoutes(parent *gin.RouterGroup) {
|
||||
h := endpoints.GetHandlers()
|
||||
cart := parent.Group("/cart")
|
||||
itemRouter := cart.Group("/item")
|
||||
//itemRouter := cart.Group("/item")
|
||||
{
|
||||
cart.GET("", h.GetCartItems)
|
||||
cart.POST("", h.CreateFUser)
|
||||
}
|
||||
|
||||
{
|
||||
itemRouter.POST("", h.CreateCartItem)
|
||||
itemRouter.PATCH("", h.UpdateCartItem)
|
||||
itemRouter.DELETE("", h.DeleteCartItem)
|
||||
}
|
||||
//{
|
||||
// itemRouter.POST("", h.CreateCartItem)
|
||||
// itemRouter.PATCH("", h.UpdateCartItem)
|
||||
// itemRouter.DELETE("", h.DeleteCartItem)
|
||||
//}
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@ package endpoints
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
cmap "github.com/orcaman/concurrent-map/v2"
|
||||
"relynolli-server/models"
|
||||
"relynolli-server/status"
|
||||
"relynolli-server/storage"
|
||||
"time"
|
||||
|
||||
cmap "github.com/orcaman/concurrent-map/v2"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
// "relynolli-server/models"
|
||||
// "relynolli-server/services"
|
||||
|
@ -74,5 +75,43 @@ func (h *handlers) GetCatalogItems(c *gin.Context) {
|
|||
|
||||
}
|
||||
|
||||
func (h *handlers) GetCatalogItem(c *gin.Context) {
|
||||
type catalogItemReq struct {
|
||||
Code string `uri:"code"`
|
||||
}
|
||||
|
||||
func (h *handlers) GetCatalogItem(c *gin.Context) {
|
||||
ctx := context.Background()
|
||||
meta := models.Meta{
|
||||
RequestStarted: time.Now().Unix(),
|
||||
}
|
||||
s := storage.NewStorageCatalog()
|
||||
path := new(catalogItemReq)
|
||||
|
||||
var err error = nil
|
||||
var statusCode int = 200
|
||||
var response models.Response = models.Response{
|
||||
Status: status.STATUS_OK,
|
||||
Meta: &meta,
|
||||
}
|
||||
|
||||
err = c.ShouldBindUri(path)
|
||||
if err != nil {
|
||||
response.Info = fmt.Sprintf("Error: %s", err.Error())
|
||||
response.Status = status.STATUS_BAD_REQUEST
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
statusCode = 400
|
||||
c.JSON(statusCode, response)
|
||||
return
|
||||
}
|
||||
|
||||
data, err := s.GetCatalogItemByCode(ctx, path.Code)
|
||||
|
||||
response.Data = data
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
if data == nil {
|
||||
statusCode = 404
|
||||
response.Status = status.STATUS_NOT_FOUND
|
||||
}
|
||||
|
||||
c.JSON(statusCode, response)
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ type handlers struct{}
|
|||
type Handlers interface {
|
||||
GetFilters(c *gin.Context)
|
||||
GetCatalogItems(c *gin.Context)
|
||||
GetCatalogItem(c *gin.Context)
|
||||
}
|
||||
|
||||
func GetHandlers() Handlers {
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package catalog
|
||||
|
||||
import (
|
||||
"github.com/gin-contrib/cache"
|
||||
"os"
|
||||
"relynolli-server/handlers/catalog/endpoints"
|
||||
"relynolli-server/internal"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/cache"
|
||||
|
||||
// "relynolli-server/internal"
|
||||
// "time"
|
||||
|
||||
|
@ -22,9 +23,11 @@ func HandleRoutes(parent *gin.RouterGroup) {
|
|||
// Caching for production usage
|
||||
catalog.GET("", cache.CachePage(cacheStore, 15*time.Minute, h.GetCatalogItems))
|
||||
catalog.GET("/filters", cache.CachePage(cacheStore, 15*time.Minute, h.GetFilters))
|
||||
catalog.GET("/:code", cache.CachePage(cacheStore, 15*time.Minute, h.GetCatalogItem))
|
||||
}
|
||||
|
||||
catalog.GET("", h.GetCatalogItems)
|
||||
catalog.GET("/:code", h.GetCatalogItem)
|
||||
catalog.GET("/filters", h.GetFilters)
|
||||
|
||||
// catalog.GET("/filters", cache.CachePage(cacheStore, 15, h.GetFilters))
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
package endpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"relynolli-server/models"
|
||||
"relynolli-server/status"
|
||||
"relynolli-server/storage"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type handlers struct{}
|
||||
|
||||
type Handlers interface {
|
||||
GetNews(c *gin.Context)
|
||||
RetrieveNews(c *gin.Context)
|
||||
}
|
||||
|
||||
func GetHandlers() Handlers {
|
||||
return &handlers{}
|
||||
}
|
||||
|
||||
type ListNewsRequest struct {
|
||||
Limit int `form:"limit" `
|
||||
Page int `form:"page"`
|
||||
}
|
||||
|
||||
func (h *handlers) GetNews(c *gin.Context) {
|
||||
ctx := context.Background()
|
||||
meta := models.Meta{
|
||||
RequestStarted: time.Now().Unix(),
|
||||
}
|
||||
|
||||
query := ListNewsRequest{
|
||||
Limit: 10,
|
||||
Page: 1,
|
||||
}
|
||||
|
||||
err := c.ShouldBindQuery(&query)
|
||||
if err != nil {
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
c.JSON(400, models.Response{
|
||||
Status: status.STATUS_BAD_REQUEST,
|
||||
Info: fmt.Sprintf("Error: %s", err.Error()),
|
||||
Meta: &meta,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
s := storage.NewStorageNews()
|
||||
count, resp, err := s.GetNews(ctx, int64(query.Limit), int64(query.Limit * (query.Page - 1)))
|
||||
if err != nil {
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
c.JSON(500, models.Response{
|
||||
Status: status.STATUS_SERVER_ERROR,
|
||||
Info: fmt.Sprintf("Error: %s", err.Error()),
|
||||
Meta: &meta,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
meta.Count = count
|
||||
meta.Limit = query.Limit
|
||||
meta.Page = query.Page
|
||||
c.JSON(200, models.Response{
|
||||
Status: status.STATUS_OK,
|
||||
Data: resp,
|
||||
Meta: &meta,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
type retireveNewsReq struct {
|
||||
Code string `uri:"code" binding:"required"`
|
||||
}
|
||||
|
||||
func (h *handlers) RetrieveNews(c *gin.Context) {
|
||||
ctx := context.Background()
|
||||
meta := models.Meta {
|
||||
RequestStarted: time.Now().Unix(),
|
||||
}
|
||||
query := new(retireveNewsReq)
|
||||
|
||||
err := c.ShouldBindUri(query)
|
||||
if err != nil {
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
c.JSON(400, models.Response{
|
||||
Status: status.STATUS_BAD_REQUEST,
|
||||
Info: fmt.Sprintf("Error: %s", err.Error()),
|
||||
Meta: &meta,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
s := storage.NewStorageNews()
|
||||
resp, _ := s.RetrieveNews(ctx, query.Code)
|
||||
meta.RequestFinished = time.Now().Unix()
|
||||
|
||||
statusResult := status.STATUS_OK
|
||||
responseCode := 200
|
||||
if resp == nil {
|
||||
statusResult = status.STATUS_NOT_FOUND
|
||||
responseCode = 404
|
||||
}
|
||||
|
||||
c.JSON(responseCode, models.Response{
|
||||
Status: statusResult,
|
||||
Data: resp,
|
||||
Meta: &meta,
|
||||
})
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package news
|
||||
|
||||
import (
|
||||
"os"
|
||||
"relynolli-server/handlers/news/endpoints"
|
||||
"relynolli-server/internal"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/cache"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func HandleRoutes(parent *gin.RouterGroup) {
|
||||
h := endpoints.GetHandlers()
|
||||
cacheStore := internal.InitCacheStore()
|
||||
catalog := parent.Group("/news")
|
||||
if os.Getenv("IS_PROD") == "1" {
|
||||
// Caching for production usage
|
||||
catalog.GET("", cache.CachePage(cacheStore, 15*time.Minute, h.GetNews))
|
||||
catalog.GET("/:code", cache.CachePage(cacheStore, 15*time.Minute, h.RetrieveNews))
|
||||
}
|
||||
|
||||
catalog.GET("", h.GetNews)
|
||||
catalog.GET("/:code", h.RetrieveNews)
|
||||
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"relynolli-server/handlers/cart"
|
||||
"relynolli-server/handlers/news"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
// "relynolli-server/handlers/cart"
|
||||
"relynolli-server/handlers/catalog"
|
||||
// "relynolli-server/handlers/order"
|
||||
|
@ -11,7 +15,8 @@ import (
|
|||
func InitializeRouter(router *gin.Engine) {
|
||||
APIV1Router := router.Group("/api/v1")
|
||||
catalog.HandleRoutes(APIV1Router)
|
||||
// cart.HandleRoutes(APIV1Router)
|
||||
cart.HandleRoutes(APIV1Router)
|
||||
news.HandleRoutes(APIV1Router)
|
||||
// order.HandleRoutes(APIV1Router)
|
||||
// validate.HandleRoutes(APIV1Router)
|
||||
}
|
||||
|
|
|
@ -13,20 +13,20 @@ import (
|
|||
|
||||
var (
|
||||
redisInstance *redis.Client = nil
|
||||
cacheStore *persistence.RedisStore
|
||||
cacheStore *persistence.RedisStore
|
||||
)
|
||||
|
||||
type Cache interface {
|
||||
}
|
||||
|
||||
func InitRedis() (*redis.Client) {
|
||||
func InitRedis() *redis.Client {
|
||||
|
||||
if redisInstance == nil {
|
||||
redis_db_num, err := strconv.Atoi(os.Getenv("REDIS_DATABASE"))
|
||||
if err != nil {
|
||||
log.Fatalln("REDIS_DATABASE should be integer")
|
||||
}
|
||||
redisInstance = redis.NewClient(&redis.Options{Addr: os.Getenv("REDIS_ADDRESS"), Password: os.Getenv("REDIS_PASSWORD"), DB: redis_db_num})
|
||||
redisInstance = redis.NewClient(&redis.Options{Addr: os.Getenv("REDIS_ADDRESS"), Password: os.Getenv("REDIS_PASSWORD"), DB: redis_db_num, Username: os.Getenv("REDIS_USERNAME")})
|
||||
|
||||
_, conError := redisInstance.Ping(context.Background()).Result()
|
||||
if conError != nil {
|
||||
|
@ -36,9 +36,9 @@ func InitRedis() (*redis.Client) {
|
|||
return redisInstance
|
||||
}
|
||||
|
||||
func InitCacheStore() *persistence.RedisStore{
|
||||
func InitCacheStore() *persistence.RedisStore {
|
||||
if cacheStore == nil {
|
||||
cacheStore = persistence.NewRedisCache(os.Getenv("REDIS_ADDRESS"), os.Getenv("REDIS_PASSWORD"), 15 * time.Minute)
|
||||
cacheStore = persistence.NewRedisCache(os.Getenv("REDIS_ADDRESS"), os.Getenv("REDIS_PASSWORD"), 15*time.Minute)
|
||||
}
|
||||
return cacheStore
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
package article
|
|
@ -0,0 +1,27 @@
|
|||
package cart
|
||||
|
||||
import (
|
||||
"github.com/uptrace/bun"
|
||||
"relynolli-server/models/catalog"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DBFuser struct {
|
||||
bun.BaseModel `bun:"table:b_sale_fuser"`
|
||||
Id int64 `bun:"ID,pk" json:"id"`
|
||||
Code string `bun:"CODE,default:md5(now())" json:"code" json:"code"`
|
||||
UserId int64 `bun:"USER_ID,nullzero" json:"userId"`
|
||||
DateInserted time.Time `bun:"DATE_INSERT" json:"dateInserted"`
|
||||
DateUpdated time.Time `bun:"DATE_UPDATE" json:"dateUpdated"`
|
||||
}
|
||||
|
||||
type DBCart struct {
|
||||
bun.BaseModel `bun:"table:api_cart"`
|
||||
Id int64 `bun:"id,pk" json:"id"`
|
||||
FuserId int64 `bun:"fuser_id" json:"fuserId"`
|
||||
ProductId int64 `bun:"product_id" json:"productId"`
|
||||
PriceTypeId int64 `bun:"price_type_id" json:"priceTypeId"`
|
||||
Quantity int64 `bun:"quantity" json:"quantity"`
|
||||
Fuser *DBFuser `bun:"rel:belongs-to,join:fuser_id=ID" json:"fuser"`
|
||||
Product *catalog.DBCatalog `bun:"rel:belongs-to,join:product_id=id" json:"product"`
|
||||
}
|
|
@ -4,7 +4,7 @@ import "github.com/uptrace/bun"
|
|||
|
||||
type DBCatalog struct {
|
||||
bun.BaseModel `bun:"select:api_catalog"`
|
||||
Id int64 `bun:"id" json:"id"`
|
||||
Id int64 `bun:"id,pk" json:"id"`
|
||||
Code string `bun:"code" json:"code"`
|
||||
Name string `bun:"name" json:"name"`
|
||||
IsActive bool `bun:"is_active,type:integer" json:"isActive"`
|
||||
|
|
|
@ -1,13 +1 @@
|
|||
package catalog
|
||||
|
||||
type DomainCatalog struct {
|
||||
// bun.BaseModel `bun:"select:api_catalog"`
|
||||
Id int64
|
||||
Code string
|
||||
Name string
|
||||
IsActive bool `bun:"is_active,type:integer"`
|
||||
Properties string `bun:"properties"`
|
||||
DetailText string `bun:"detailText"`
|
||||
Price string `bun:"price"`
|
||||
AvailableQunatity int64 `bun:"available_quantity"`
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package news
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type DBNews struct {
|
||||
bun.BaseModel `bun:"select:api_news"`
|
||||
ID int64 `bun:"id" json:"id"`
|
||||
IsActive bool `bun:"is_active" json:"isActive"`
|
||||
Sort int64 `bun:"sort" json:"sort"`
|
||||
Name string `bun:"name" json:"name"`
|
||||
Content string `bun:"content" json:"content"`
|
||||
Code string `bun:"code" json:"code"`
|
||||
Picture string `bun:"picture" json:"picture"`
|
||||
Date time.Time `bun:"date" json:"date"`
|
||||
}
|
108
services/cart.go
108
services/cart.go
|
@ -1,109 +1 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"relynolli-server/internal"
|
||||
"relynolli-server/models"
|
||||
)
|
||||
|
||||
func GetCartItems(fuserId int) []models.CatalogWithQuantityWeb {
|
||||
rdb := internal.InitRedis()
|
||||
keys, _ := rdb.Keys(context.Background(), fmt.Sprintf("api.api_cart.%d.*", fuserId)).Result()
|
||||
|
||||
result := []models.CatalogWithQuantityWeb{}
|
||||
|
||||
for _, key := range keys {
|
||||
str, _ := rdb.Get(context.Background(), key).Result()
|
||||
item := models.CatalogWithQuantityWeb{}
|
||||
json.Unmarshal([]byte(str), &item)
|
||||
result = append(result, item)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func CreateFuser() int64 {
|
||||
stmt := "insert into b_sale_fuser (DATE_INSERT, DATE_UPDATE, CODE) values (now(), now(), md5(rand()));"
|
||||
|
||||
db := internal.InitDatabase()
|
||||
result := db.Execute(stmt)
|
||||
lastInsertId, _ := result.LastInsertId()
|
||||
return lastInsertId
|
||||
}
|
||||
|
||||
func AddItemToCart(fuserId int, productId int) {
|
||||
|
||||
rdb := internal.InitRedis()
|
||||
item, _ := GetCatalogItemById(productId)
|
||||
|
||||
itemWithQuantity := models.CatalogWithQuantityWeb{
|
||||
Id: item.Id,
|
||||
Code: item.Code,
|
||||
Name: item.Name,
|
||||
IsActive: item.IsActive,
|
||||
Properties: item.Properties,
|
||||
DetailText: item.DetailText,
|
||||
Price: item.Price,
|
||||
Quantity: 1,
|
||||
AvailableQuantity: item.AvailableQuantity,
|
||||
}
|
||||
|
||||
marshaled, _ := json.Marshal(itemWithQuantity)
|
||||
|
||||
err := rdb.Set(context.Background(), fmt.Sprintf("api.api_cart.%d.%d", fuserId, productId), string(marshaled), 0).Err()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateCartItem(fuserId int, productId int, quantity int) error {
|
||||
if quantity <= 0 {
|
||||
DeleteCartItem(fuserId, productId)
|
||||
return nil
|
||||
}
|
||||
|
||||
item, _ := GetCatalogItemById(productId)
|
||||
if item.AvailableQuantity < quantity {
|
||||
return fmt.Errorf("Available quantity is less than requested. Available %d, requested %d", item.AvailableQuantity, quantity)
|
||||
}
|
||||
|
||||
itemWithQuantity := models.CatalogWithQuantityWeb{
|
||||
Id: item.Id,
|
||||
Code: item.Code,
|
||||
Name: item.Name,
|
||||
IsActive: item.IsActive,
|
||||
Properties: item.Properties,
|
||||
DetailText: item.DetailText,
|
||||
Price: item.Price,
|
||||
Quantity: quantity,
|
||||
AvailableQuantity: item.AvailableQuantity,
|
||||
}
|
||||
|
||||
marshaled, _ := json.Marshal(itemWithQuantity)
|
||||
|
||||
rdb := internal.InitRedis()
|
||||
|
||||
rdb.Set(context.Background(), fmt.Sprintf("api.api_cart.%d.%d", fuserId, productId), string(marshaled), 0)
|
||||
return nil
|
||||
|
||||
//var availableQunatity int
|
||||
//stmtQuantity := fmt.Sprintf("select QUANTITY as q from b_catalog_product where ID = %d;", productId)
|
||||
//updateStmt := fmt.Sprintf("update api_cart set quantity = %d where product_id = %d and fuser_id = %d", quantity, productId, fuserId)
|
||||
|
||||
//db := internal.InitDatabase()
|
||||
//rows := db.Query(stmtQuantity)
|
||||
//rows.Next()
|
||||
//rows.Scan(&availableQunatity)
|
||||
//if quantity > availableQunatity {
|
||||
// return fmt.Errorf("Available quantity is less than requested. Available %d, requested %d", availableQunatity, quantity)
|
||||
//}
|
||||
//db.Execute(updateStmt)
|
||||
//return nil
|
||||
}
|
||||
|
||||
func DeleteCartItem(fuserId int, productId int) {
|
||||
rdb := internal.InitRedis()
|
||||
rdb.Del(context.Background(), fmt.Sprintf("api.api_cart.%d.%d", fuserId, productId)).Err()
|
||||
}
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"relynolli-server/internal"
|
||||
"relynolli-server/models"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func retrieveItems(stmt string, structure interface{}) {
|
||||
db := internal.InitDatabase()
|
||||
db.FetchRows(stmt, structure)
|
||||
}
|
||||
|
||||
func retrieveCatalogItems(stmt string) []models.CatalogStructWeb {
|
||||
var catalogList []models.CatalogStruct
|
||||
var returnedList []models.CatalogStructWeb
|
||||
|
||||
retrieveItems(stmt, &catalogList)
|
||||
for _, item := range catalogList {
|
||||
itemProd := models.CatalogStructWeb{
|
||||
Id: item.Id,
|
||||
Code: item.Code,
|
||||
Name: item.Name,
|
||||
IsActive: item.IsActive,
|
||||
DetailText: item.DetailText,
|
||||
AvailableQuantity: item.AvailableQuantity,
|
||||
}
|
||||
json.Unmarshal(item.Price, &itemProd.Price)
|
||||
json.Unmarshal(item.Properties, &itemProd.Properties)
|
||||
returnedList = append(returnedList, itemProd)
|
||||
}
|
||||
return returnedList
|
||||
}
|
||||
|
||||
func GetCatalogItemsCount() int {
|
||||
stmt := "select count(id) from api_catalog where available_quantity > 0 and is_active = 1;"
|
||||
var count int
|
||||
db := internal.InitDatabase()
|
||||
rows := db.Query(stmt)
|
||||
rows.Next()
|
||||
rows.Scan(&count)
|
||||
return count
|
||||
}
|
||||
|
||||
func GetCatalogItems(limit int, offset int) []models.CatalogStructWeb {
|
||||
stmt := fmt.Sprintf("select * from api_catalog where available_quantity > 0 and is_active = 1 order by code limit %d offset %d;", limit, offset)
|
||||
return retrieveCatalogItems(stmt)
|
||||
}
|
||||
|
||||
func GetCatalogItem(code string) (models.CatalogStructWeb, error) {
|
||||
stmt := fmt.Sprintf("select * from api_catalog where code = '%s';", code)
|
||||
items := retrieveCatalogItems(stmt)
|
||||
if len(items) == 0 {
|
||||
return models.CatalogStructWeb{}, fmt.Errorf("Not founded catalog item with given code")
|
||||
}
|
||||
return retrieveCatalogItems(stmt)[0], nil
|
||||
}
|
||||
|
||||
func GetCatalogItemById(id int) (models.CatalogStructWeb, error) {
|
||||
stmt := fmt.Sprintf("select * from api_catalog where id = %d;", id)
|
||||
items := retrieveCatalogItems(stmt)
|
||||
if len(items) == 0 {
|
||||
return models.CatalogStructWeb{}, fmt.Errorf("Not founded catalog item with given code")
|
||||
}
|
||||
return retrieveCatalogItems(stmt)[0], nil
|
||||
}
|
||||
|
||||
func FilterCatalogItems(filters map[string][]string, limit int, offset int) []models.CatalogStructWeb {
|
||||
// Generate stmt
|
||||
propertiesSubStmt := "properties->>'$.%s' = '%s'"
|
||||
|
||||
stmt := "select * from api_catalog where %s"
|
||||
|
||||
sample := "(%s)"
|
||||
|
||||
filterList := [][]string{}
|
||||
|
||||
for key, filter := range filters {
|
||||
if key == "isFilter" {
|
||||
continue
|
||||
}
|
||||
if key == "limit" {
|
||||
continue
|
||||
}
|
||||
if key == "page" {
|
||||
continue
|
||||
}
|
||||
|
||||
subFilterArr := []string{}
|
||||
values := strings.Split(filter[0], ",")
|
||||
for _, val := range values {
|
||||
subFilterArr = append(subFilterArr, fmt.Sprintf(propertiesSubStmt, key, val))
|
||||
}
|
||||
filterList = append(filterList, subFilterArr)
|
||||
}
|
||||
|
||||
samples := []string{}
|
||||
|
||||
for _, arr := range filterList {
|
||||
samples = append(samples, fmt.Sprintf(sample, strings.Join(arr, " or ")))
|
||||
}
|
||||
|
||||
stmt = fmt.Sprintf(stmt, strings.Join(samples, " and "))
|
||||
print("\n" + stmt + "\n")
|
||||
return retrieveCatalogItems(stmt + fmt.Sprintf("and is_active = 1 and available_quantity > 0;"))
|
||||
}
|
|
@ -1,147 +1,131 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"relynolli-server/external/bitrix"
|
||||
"relynolli-server/external/kassa"
|
||||
"relynolli-server/external/kassa/Measure"
|
||||
"relynolli-server/external/kassa/PaymentMode"
|
||||
"relynolli-server/external/kassa/PaymentSubject"
|
||||
"relynolli-server/external/kassa/VatCodes"
|
||||
"relynolli-server/internal"
|
||||
"relynolli-server/models"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetTotal(fuserId int) float64 {
|
||||
rdb := internal.InitRedis()
|
||||
keys, _ := rdb.Keys(context.Background(), fmt.Sprintf("api.api_cart.%d.*", fuserId)).Result()
|
||||
|
||||
result := []models.CatalogWithQuantityWeb{}
|
||||
|
||||
for _, key := range keys {
|
||||
str, _ := rdb.Get(context.Background(), key).Result()
|
||||
item := models.CatalogWithQuantityWeb{}
|
||||
|
||||
json.Unmarshal([]byte(str), &item)
|
||||
result = append(result, item)
|
||||
}
|
||||
|
||||
sum := float64(0)
|
||||
|
||||
for _, catalogItem := range result {
|
||||
sum = sum + catalogItem.Price["BASE"].(float64)*float64(catalogItem.Quantity)
|
||||
}
|
||||
|
||||
return sum
|
||||
}
|
||||
|
||||
type addProductsToOrderReq struct {
|
||||
ProductId int `db:"product_id"`
|
||||
PriceTypeId int `db:"price_type_id"`
|
||||
Quantity int `db:"quantity"`
|
||||
Price float64 `db:"price"`
|
||||
}
|
||||
|
||||
func addProductsToOrder(api bitrix.Bitrix, fuserId int, orderId int) error {
|
||||
//Получаем данные из корзины
|
||||
|
||||
cartItems := GetCartItems(fuserId)
|
||||
|
||||
rdb := internal.InitRedis()
|
||||
rdb.Keys(context.Background(), "")
|
||||
|
||||
for _, product := range cartItems {
|
||||
err := api.AddProductToOrder(orderId, product.Id, product.Price["BASE"].(float64), product.Quantity)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func MakeOrder(fuserId int, email string, fullName string, phone string) (map[string]interface{}, error) {
|
||||
|
||||
// Инициализируем api
|
||||
|
||||
api := bitrix.Initialize()
|
||||
|
||||
// 1. Создаем анонимного пользователя
|
||||
|
||||
userId, _ := api.CreateAnonymousUser()
|
||||
|
||||
// 2. Создаем заказ
|
||||
orderId, _ := api.CreateOrder(userId)
|
||||
|
||||
// --- обновляем контакт пользователя
|
||||
order, orderErr := api.GetOrderInfo(orderId)
|
||||
if orderErr != nil {
|
||||
return nil, orderErr
|
||||
}
|
||||
clientId, _ := strconv.Atoi(order.Clients[0].EntityId)
|
||||
api.UpdateContact(clientId, email, fullName, phone)
|
||||
|
||||
// 3. Добавляем элементы в корзину
|
||||
addProductErr := addProductsToOrder(api, fuserId, orderId)
|
||||
if addProductErr != nil {
|
||||
return nil, addProductErr
|
||||
}
|
||||
|
||||
// 4. Получаем обновленный ресурс заказа
|
||||
order, _ = api.GetOrderInfo(orderId)
|
||||
|
||||
// 5. Добавляем способ оплаты товара
|
||||
createPaymentError := api.CreatePayment(orderId, order.Price)
|
||||
|
||||
if createPaymentError != nil {
|
||||
return nil, createPaymentError
|
||||
}
|
||||
|
||||
// 6. Получаем ресурс оплаты и url для нее
|
||||
paymentData, _ := kassa.CreatePayment(orderId, order.Price, fullName, email, phone, getItemsForPayment(order))
|
||||
|
||||
insPaymentDataStmt := fmt.Sprintf(`
|
||||
insert into api_youkassa_payment (payment_id, order_id, link, status)
|
||||
values ('%s',
|
||||
'%s',
|
||||
'%s',
|
||||
'%s');
|
||||
`, paymentData["id"].(string),
|
||||
orderId,
|
||||
paymentData["confirmation"].(map[string]interface{})["confirmation_url"].(string),
|
||||
paymentData["status"].(string),
|
||||
)
|
||||
|
||||
db := internal.InitDatabase()
|
||||
|
||||
db.Execute(insPaymentDataStmt)
|
||||
|
||||
return paymentData, nil
|
||||
}
|
||||
|
||||
func getItemsForPayment(order *bitrix.OrderResource) []kassa.KassaReceiptItems {
|
||||
result := []kassa.KassaReceiptItems{}
|
||||
|
||||
for _, basketItem := range order.BasketItems {
|
||||
quantity, _ := strconv.Atoi(strings.Split(basketItem.Quantity, ".")[0])
|
||||
item := kassa.KassaReceiptItems{
|
||||
Description: basketItem.Name,
|
||||
Amount: kassa.KassaAmount{
|
||||
Value: fmt.Sprintf("%f", basketItem.Price),
|
||||
Currency: "RUB",
|
||||
},
|
||||
VatCode: VatCodes.NDS_20,
|
||||
Quantity: fmt.Sprintf("%d", quantity),
|
||||
Measure: Measure.PIECE,
|
||||
PaymentSubject: PaymentSubject.COMMODITY,
|
||||
PaymentMode: PaymentMode.FULL_PAYMENT,
|
||||
}
|
||||
result = append(result, item)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
//func GetTotal(fuserId int) float64 {
|
||||
// rdb := internal.InitRedis()
|
||||
// keys, _ := rdb.Keys(context.Background(), fmt.Sprintf("api.api_cart.%d.*", fuserId)).Result()
|
||||
//
|
||||
// result := []models.CatalogWithQuantityWeb{}
|
||||
//
|
||||
// for _, key := range keys {
|
||||
// str, _ := rdb.Get(context.Background(), key).Result()
|
||||
// item := models.CatalogWithQuantityWeb{}
|
||||
//
|
||||
// json.Unmarshal([]byte(str), &item)
|
||||
// result = append(result, item)
|
||||
// }
|
||||
//
|
||||
// sum := float64(0)
|
||||
//
|
||||
// for _, catalogItem := range result {
|
||||
// sum = sum + catalogItem.Price["BASE"].(float64)*float64(catalogItem.Quantity)
|
||||
// }
|
||||
//
|
||||
// return sum
|
||||
//}
|
||||
//
|
||||
//type addProductsToOrderReq struct {
|
||||
// ProductId int `db:"product_id"`
|
||||
// PriceTypeId int `db:"price_type_id"`
|
||||
// Quantity int `db:"quantity"`
|
||||
// Price float64 `db:"price"`
|
||||
//}
|
||||
//
|
||||
//func addProductsToOrder(api bitrix.Bitrix, fuserId int, orderId int) error {
|
||||
// //Получаем данные из корзины
|
||||
//
|
||||
// cartItems := GetCartItems(fuserId)
|
||||
//
|
||||
// rdb := internal.InitRedis()
|
||||
// rdb.Keys(context.Background(), "")
|
||||
//
|
||||
// for _, product := range cartItems {
|
||||
// err := api.AddProductToOrder(orderId, product.Id, product.Price["BASE"].(float64), product.Quantity)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// return nil
|
||||
//
|
||||
//}
|
||||
//
|
||||
//func MakeOrder(fuserId int, email string, fullName string, phone string) (map[string]interface{}, error) {
|
||||
//
|
||||
// // Инициализируем api
|
||||
//
|
||||
// api := bitrix.Initialize()
|
||||
//
|
||||
// // 1. Создаем анонимного пользователя
|
||||
//
|
||||
// userId, _ := api.CreateAnonymousUser()
|
||||
//
|
||||
// // 2. Создаем заказ
|
||||
// orderId, _ := api.CreateOrder(userId)
|
||||
//
|
||||
// // --- обновляем контакт пользователя
|
||||
// order, orderErr := api.GetOrderInfo(orderId)
|
||||
// if orderErr != nil {
|
||||
// return nil, orderErr
|
||||
// }
|
||||
// clientId, _ := strconv.Atoi(order.Clients[0].EntityId)
|
||||
// api.UpdateContact(clientId, email, fullName, phone)
|
||||
//
|
||||
// // 3. Добавляем элементы в корзину
|
||||
// addProductErr := addProductsToOrder(api, fuserId, orderId)
|
||||
// if addProductErr != nil {
|
||||
// return nil, addProductErr
|
||||
// }
|
||||
//
|
||||
// // 4. Получаем обновленный ресурс заказа
|
||||
// order, _ = api.GetOrderInfo(orderId)
|
||||
//
|
||||
// // 5. Добавляем способ оплаты товара
|
||||
// createPaymentError := api.CreatePayment(orderId, order.Price)
|
||||
//
|
||||
// if createPaymentError != nil {
|
||||
// return nil, createPaymentError
|
||||
// }
|
||||
//
|
||||
// // 6. Получаем ресурс оплаты и url для нее
|
||||
// paymentData, _ := kassa.CreatePayment(orderId, order.Price, fullName, email, phone, getItemsForPayment(order))
|
||||
//
|
||||
// insPaymentDataStmt := fmt.Sprintf(`
|
||||
// insert into api_youkassa_payment (payment_id, order_id, link, status)
|
||||
// values ('%s',
|
||||
// '%s',
|
||||
// '%s',
|
||||
// '%s');
|
||||
// `, paymentData["id"].(string),
|
||||
// orderId,
|
||||
// paymentData["confirmation"].(map[string]interface{})["confirmation_url"].(string),
|
||||
// paymentData["status"].(string),
|
||||
// )
|
||||
//
|
||||
// db := internal.InitDatabase()
|
||||
//
|
||||
// db.Execute(insPaymentDataStmt)
|
||||
//
|
||||
// return paymentData, nil
|
||||
//}
|
||||
//
|
||||
//func getItemsForPayment(order *bitrix.OrderResource) []kassa.KassaReceiptItems {
|
||||
// result := []kassa.KassaReceiptItems{}
|
||||
//
|
||||
// for _, basketItem := range order.BasketItems {
|
||||
// quantity, _ := strconv.Atoi(strings.Split(basketItem.Quantity, ".")[0])
|
||||
// item := kassa.KassaReceiptItems{
|
||||
// Description: basketItem.Name,
|
||||
// Amount: kassa.KassaAmount{
|
||||
// Value: fmt.Sprintf("%f", basketItem.Price),
|
||||
// Currency: "RUB",
|
||||
// },
|
||||
// VatCode: VatCodes.NDS_20,
|
||||
// Quantity: fmt.Sprintf("%d", quantity),
|
||||
// Measure: Measure.PIECE,
|
||||
// PaymentSubject: PaymentSubject.COMMODITY,
|
||||
// PaymentMode: PaymentMode.FULL_PAYMENT,
|
||||
// }
|
||||
// result = append(result, item)
|
||||
// }
|
||||
//
|
||||
// return result
|
||||
//}
|
||||
|
|
|
@ -1,32 +1,27 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"relynolli-server/external/bitrix"
|
||||
"relynolli-server/internal"
|
||||
)
|
||||
|
||||
func YookassaValidate(paymentId string, status string) {
|
||||
stmt := fmt.Sprintf(`select t1.order_id as order_id, t2.ID as payment_id from api_youkassa_payment t1 join b_sale_order_payment t2 on t1.order_id = t2.ORDER_ID where t1.payment_id = '%s';`, paymentId)
|
||||
db := internal.InitDatabase()
|
||||
rows := db.Query(stmt)
|
||||
|
||||
var (
|
||||
orderId int
|
||||
paymentIdBitrix int
|
||||
)
|
||||
|
||||
rows.Next()
|
||||
rows.Scan(&orderId, &paymentIdBitrix)
|
||||
|
||||
api := bitrix.Initialize()
|
||||
if status == "succeeded" {
|
||||
api.ApprovePayment(paymentIdBitrix, 8)
|
||||
return
|
||||
}
|
||||
if status == "canceled" {
|
||||
api.CancelOrder(orderId)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
//
|
||||
//func YookassaValidate(paymentId string, status string) {
|
||||
// stmt := fmt.Sprintf(`select t1.order_id as order_id, t2.ID as payment_id from api_youkassa_payment t1 join b_sale_order_payment t2 on t1.order_id = t2.ORDER_ID where t1.payment_id = '%s';`, paymentId)
|
||||
// db := internal.InitDatabase()
|
||||
// rows := db.Query(stmt)
|
||||
//
|
||||
// var (
|
||||
// orderId int
|
||||
// paymentIdBitrix int
|
||||
// )
|
||||
//
|
||||
// rows.Next()
|
||||
// rows.Scan(&orderId, &paymentIdBitrix)
|
||||
//
|
||||
// api := bitrix.Initialize()
|
||||
// if status == "succeeded" {
|
||||
// api.ApprovePayment(paymentIdBitrix, 8)
|
||||
// return
|
||||
// }
|
||||
// if status == "canceled" {
|
||||
// api.CancelOrder(orderId)
|
||||
// return
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
package storage
|
122
storage/cart.go
122
storage/cart.go
|
@ -1,15 +1,127 @@
|
|||
package storage
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"relynolli-server/internal"
|
||||
"relynolli-server/models/cart"
|
||||
"time"
|
||||
)
|
||||
|
||||
type StorageCart interface {
|
||||
|
||||
CreateFuser(ctx context.Context) (int64, *cart.DBFuser, error)
|
||||
GetCartItems(ctx context.Context, fuserId int64) (*[]cart.DBCart, error)
|
||||
GetCartItem(ctx context.Context, fuserId, productId int64) (*cart.DBCart, error)
|
||||
AddItemToCart(ctx context.Context, fuserId, productId int64) error
|
||||
UpdateCartItem(ctx context.Context, fuserId, productId, quantity int64) error
|
||||
DeleteCartItem(ctx context.Context, fuserId, productId int64) error
|
||||
}
|
||||
|
||||
func (s *storage) GetCartItem(ctx context.Context) {
|
||||
|
||||
func NewStorageCart() StorageCart {
|
||||
if instance == nil {
|
||||
instance = &storage{
|
||||
db: internal.InitDatabase().GetInstance(),
|
||||
rdb: internal.InitRedis(),
|
||||
}
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
func (s *storage) GetCartItems(ctx context.Context) {
|
||||
func (s *storage) CreateFuser(ctx context.Context) (int64, *cart.DBFuser, error) {
|
||||
//stmt := "insert into b_sale_fuser (DATE_INSERT, DATE_UPDATE, CODE) values (now(), now(), md5(rand()));"
|
||||
hash := md5.Sum([]byte(fmt.Sprintf("%d", time.Now().Unix())))
|
||||
|
||||
model := &cart.DBFuser{
|
||||
Code: hex.EncodeToString(hash[:]),
|
||||
DateInserted: time.Now().UTC(),
|
||||
DateUpdated: time.Now().UTC(),
|
||||
}
|
||||
|
||||
res, err := s.db.NewInsert().Model(model).Exec(ctx)
|
||||
id, _ := res.LastInsertId()
|
||||
|
||||
s.db.NewSelect().Model(model).Where("id = ?", id).Scan(ctx)
|
||||
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return model.Id, model, nil
|
||||
}
|
||||
|
||||
func (s *storage) GetCartItems(ctx context.Context, fuserId int64) (*[]cart.DBCart, error) {
|
||||
result := new([]cart.DBCart)
|
||||
err := s.db.NewSelect().Model(result).Relation("Product").Relation("Fuser").Where("fuser_id = ?", fuserId).Scan(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *storage) GetCartItem(ctx context.Context, fuserId, productId int64) (*cart.DBCart, error) {
|
||||
result := new(cart.DBCart)
|
||||
err := s.db.NewSelect().Model(result).Relation("Product").Relation("Fuser").Where("fuser_id = ?", fuserId).Where("product_id = ?", productId).Scan(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s *storage) AddItemToCart(ctx context.Context, fuserId, productId int64) error {
|
||||
|
||||
item, _ := s.GetCatalogItem(ctx, &productId)
|
||||
isExists, err := s.db.NewSelect().Model((*cart.DBCart)(nil)).Where("fuser_id = ?", fuserId).Where("product_id = ?", productId).Exists(ctx)
|
||||
|
||||
if isExists || item.AvailableQuantity < 1 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
newItem := &cart.DBCart{
|
||||
FuserId: fuserId,
|
||||
ProductId: productId,
|
||||
PriceTypeId: 1,
|
||||
Quantity: 1,
|
||||
}
|
||||
|
||||
_, err = s.db.NewInsert().Model(newItem).Exec(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *storage) UpdateCartItem(ctx context.Context, fuserId, productId, quantity int64) error {
|
||||
if quantity <= 0 {
|
||||
// TODO Implement
|
||||
return nil
|
||||
}
|
||||
|
||||
item, _ := s.GetCartItem(ctx, fuserId, productId)
|
||||
|
||||
if item.Product.AvailableQuantity < quantity {
|
||||
return fmt.Errorf("Available quantity is less than requested. Available %d, requested %d", item.Product.AvailableQuantity, quantity)
|
||||
}
|
||||
|
||||
item.Quantity = quantity
|
||||
|
||||
s.db.NewUpdate().Model(item).Where("id = ?", item.Id).Exec(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *storage) DeleteCartItem(ctx context.Context, fuserId, productId int64) error {
|
||||
_, err := s.db.NewDelete().Model((*cart.DBCart)(nil)).Where("fuser_id = ?", fuserId).Where("product_id = ?", productId).Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ import (
|
|||
|
||||
type StorageCatalog interface {
|
||||
GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCatalog, error)
|
||||
GetCatalogItemByCode(ctx context.Context, code string) (*catalog.DBCatalog, error)
|
||||
|
||||
GetCatalogItems(ctx context.Context, filters cmap.ConcurrentMap[string, []string], limit int, offset int) (int, *[]catalog.DBCatalog, error)
|
||||
GetFilters(ctx context.Context) (int, *[]filters2.DBFilter, error)
|
||||
}
|
||||
|
@ -21,17 +23,17 @@ type StorageCatalog interface {
|
|||
func NewStorageCatalog() StorageCatalog {
|
||||
if instance == nil {
|
||||
instance = &storage{
|
||||
db: internal.InitDatabase().GetInstance(),
|
||||
db: internal.InitDatabase().GetInstance(),
|
||||
rdb: internal.InitRedis(),
|
||||
}
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
func (s *storage) GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCatalog, error) {
|
||||
db := internal.InitDatabase().GetInstance()
|
||||
func (s *storage) GetCatalogItemByCode(ctx context.Context, code string) (*catalog.DBCatalog, error) {
|
||||
model := new(catalog.DBCatalog)
|
||||
|
||||
err := db.NewSelect().Model(model).Where("id = ?", id).Where("available_quantity > 0").Where("is_available = 1").Scan(ctx)
|
||||
err := s.db.NewSelect().Model(model).Where("code = ?", code).Where("available_quantity > 0").Where("is_active = 1").Scan(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -39,12 +41,22 @@ func (s *storage) GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCat
|
|||
return model, nil
|
||||
}
|
||||
|
||||
func buildFilterGroup(ctx context.Context, q *bun.SelectQuery, filters *cmap.ConcurrentMap[string, []string]) *bun.SelectQuery {
|
||||
db := internal.InitDatabase().GetInstance()
|
||||
func (s *storage) GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCatalog, error) {
|
||||
model := new(catalog.DBCatalog)
|
||||
|
||||
err := s.db.NewSelect().Model(model).Where("id = ?", id).Where("available_quantity > 0").Where("is_available = 1").Scan(ctx)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return model, nil
|
||||
}
|
||||
|
||||
func (s *storage) buildFilterGroup(ctx context.Context, q *bun.SelectQuery, filters *cmap.ConcurrentMap[string, []string]) *bun.SelectQuery {
|
||||
availableFilters := new([]filters2.DBFilter)
|
||||
|
||||
//Get filters
|
||||
db.NewSelect().Model(availableFilters).Scan(ctx)
|
||||
s.db.NewSelect().Model(availableFilters).Scan(ctx)
|
||||
|
||||
for _, filter := range filters.Keys() {
|
||||
filter = filter[0 : len(filter)-2]
|
||||
|
@ -66,18 +78,16 @@ func buildFilterGroup(ctx context.Context, q *bun.SelectQuery, filters *cmap.Con
|
|||
}
|
||||
|
||||
func (s *storage) GetCatalogItems(ctx context.Context, filters cmap.ConcurrentMap[string, []string], limit int, offset int) (int, *[]catalog.DBCatalog, error) {
|
||||
db := internal.InitDatabase().GetInstance()
|
||||
model := new([]catalog.DBCatalog)
|
||||
filterQuery := db.NewSelect().Model(model).Where("is_active = 1").Where("available_quantity > 0")
|
||||
count, _ := buildFilterGroup(ctx, filterQuery, &filters).Limit(limit).Offset(offset).Order("code").ScanAndCount(ctx)
|
||||
filterQuery := s.db.NewSelect().Model(model).Where("is_active = 1").Where("available_quantity > 0")
|
||||
count, _ := s.buildFilterGroup(ctx, filterQuery, &filters).Limit(limit).Offset(offset).Order("code").ScanAndCount(ctx)
|
||||
|
||||
return count, model, nil
|
||||
}
|
||||
|
||||
func (s *storage) GetFilters(ctx context.Context) (int, *[]filters2.DBFilter, error) {
|
||||
models := new([]filters2.DBFilter)
|
||||
db := internal.InitDatabase().GetInstance()
|
||||
count, err := db.NewSelect().Model(models).ScanAndCount(ctx)
|
||||
count, err := s.db.NewSelect().Model(models).ScanAndCount(ctx)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"relynolli-server/internal"
|
||||
"relynolli-server/models/news"
|
||||
)
|
||||
|
||||
type StorageNews interface {
|
||||
GetNews (ctx context.Context, limit, offset int64) (int, *[]news.DBNews, error)
|
||||
RetrieveNews(ctx context.Context, code string) (*news.DBNews, error)
|
||||
}
|
||||
|
||||
|
||||
func NewStorageNews() StorageNews {
|
||||
if instance == nil {
|
||||
instance = &storage{
|
||||
db: internal.InitDatabase().GetInstance(),
|
||||
rdb: internal.InitRedis(),
|
||||
}
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
func (s *storage) GetNews (ctx context.Context, limit, offset int64) (int, *[]news.DBNews, error) {
|
||||
model := new([]news.DBNews)
|
||||
stmt := s.db.NewSelect().Model(model).Where("is_active = 1").OrderExpr("sort ASC, date DESC").Limit(int(limit)).Offset(int(offset))
|
||||
count, err := stmt.ScanAndCount(ctx)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return count, model, nil
|
||||
}
|
||||
|
||||
|
||||
func (s *storage) RetrieveNews(ctx context.Context, code string) (*news.DBNews, error) {
|
||||
model := new(news.DBNews)
|
||||
stmt := s.db.NewSelect().Model(model).Where("code = ?", code).Where("is_active = 1")
|
||||
err := stmt.Scan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return model, nil
|
||||
}
|
|
@ -1,11 +1,13 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type storage struct {
|
||||
db *bun.DB
|
||||
db *bun.DB
|
||||
rdb *redis.Client
|
||||
}
|
||||
|
||||
var instance *storage = nil
|
||||
|
|
Loading…
Reference in New Issue