complete news and catalog
parent
9937d8df67
commit
d7b1f65805
|
@ -1,35 +1,75 @@
|
||||||
package endpoints
|
package endpoints
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
"relynolli-server/models"
|
"relynolli-server/models"
|
||||||
"relynolli-server/services"
|
"relynolli-server/status"
|
||||||
"strconv"
|
"relynolli-server/storage"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type getCartItemsRequest struct {
|
||||||
|
FuserId int64 `form:"fuserId"`
|
||||||
|
}
|
||||||
|
|
||||||
func (h *handlers) GetCartItems(c *gin.Context) {
|
func (h *handlers) GetCartItems(c *gin.Context) {
|
||||||
|
ctx := context.Background()
|
||||||
|
query := new(getCartItemsRequest)
|
||||||
|
meta := models.Meta{
|
||||||
|
RequestStarted: time.Now().Unix(),
|
||||||
|
}
|
||||||
|
|
||||||
fuserId := c.Query("fuserId")
|
err := c.ShouldBindQuery(query)
|
||||||
if fuserId == "" {
|
if err != nil || query.FuserId == 0 {
|
||||||
c.JSON(400, models.Response{Status: 400, Info: "\"fuserId\" should be provided"})
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
idx, err := strconv.Atoi(fuserId)
|
s := storage.NewStorageCart()
|
||||||
|
|
||||||
if err != nil {
|
items, _ := s.GetCartItems(ctx, query.FuserId)
|
||||||
c.JSON(400, models.Response{Status: 400, Info: "\"fuserId should be an integer number\""})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
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, fuser, err := s.CreateFuser(ctx)
|
||||||
"fuserId": lastInsertId,
|
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 {
|
type Handlers interface {
|
||||||
GetCartItems(c *gin.Context)
|
GetCartItems(c *gin.Context)
|
||||||
CreateFUser(c *gin.Context)
|
CreateFUser(c *gin.Context)
|
||||||
|
//
|
||||||
CreateCartItem(c *gin.Context)
|
//CreateCartItem(c *gin.Context)
|
||||||
UpdateCartItem(c *gin.Context)
|
//UpdateCartItem(c *gin.Context)
|
||||||
DeleteCartItem(c *gin.Context)
|
//DeleteCartItem(c *gin.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHandlers() Handlers {
|
func GetHandlers() Handlers {
|
||||||
|
|
|
@ -1,14 +1,5 @@
|
||||||
package endpoints
|
package endpoints
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"relynolli-server/models"
|
|
||||||
"relynolli-server/services"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type createCartItemRequest struct {
|
type createCartItemRequest struct {
|
||||||
FuserId int `json:"fuserId"`
|
FuserId int `json:"fuserId"`
|
||||||
PriceTypeId int `json:"priceTypeId,omitempty"`
|
PriceTypeId int `json:"priceTypeId,omitempty"`
|
||||||
|
@ -27,50 +18,50 @@ type deleteCartRequest struct {
|
||||||
ProductId int `json:"productId"`
|
ProductId int `json:"productId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handlers) CreateCartItem(c *gin.Context) {
|
//func (h *handlers) CreateCartItem(c *gin.Context) {
|
||||||
req := createCartItemRequest{}
|
// req := createCartItemRequest{}
|
||||||
err := c.ShouldBindJSON(&req)
|
// err := c.ShouldBindJSON(&req)
|
||||||
|
//
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
// c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
services.AddItemToCart(req.FuserId, req.ProductId)
|
// 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)})
|
// 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) {
|
//func (h *handlers) UpdateCartItem(c *gin.Context) {
|
||||||
req := updateCartRequest{}
|
// req := updateCartRequest{}
|
||||||
err := c.ShouldBindJSON(&req)
|
// err := c.ShouldBindJSON(&req)
|
||||||
|
//
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
// c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
err = services.UpdateCartItem(req.FuserId, req.ProductId, req.Quantity)
|
// err = services.UpdateCartItem(req.FuserId, req.ProductId, req.Quantity)
|
||||||
|
//
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
// c.JSON(http.StatusBadRequest, models.Response{Status: http.StatusBadRequest, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
c.JSON(http.StatusOK, models.Response{Status: http.StatusOK})
|
// c.JSON(http.StatusOK, models.Response{Status: http.StatusOK})
|
||||||
|
//
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
func (h *handlers) DeleteCartItem(c *gin.Context) {
|
//func (h *handlers) DeleteCartItem(c *gin.Context) {
|
||||||
|
//
|
||||||
req := deleteCartRequest{}
|
// req := deleteCartRequest{}
|
||||||
err := c.ShouldBindJSON(&req)
|
// err := c.ShouldBindJSON(&req)
|
||||||
|
//
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
c.JSON(400, models.Response{Status: 400, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
// c.JSON(400, models.Response{Status: 400, Info: fmt.Sprintf("Bad request. Error info: %s", err.Error())})
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
services.DeleteCartItem(req.FuserId, req.ProductId)
|
// services.DeleteCartItem(req.FuserId, req.ProductId)
|
||||||
|
//
|
||||||
c.JSON(http.StatusNoContent, models.Response{Status: http.StatusNoContent})
|
// c.JSON(http.StatusNoContent, models.Response{Status: http.StatusNoContent})
|
||||||
}
|
//}
|
||||||
|
|
|
@ -8,15 +8,15 @@ import (
|
||||||
func HandleRoutes(parent *gin.RouterGroup) {
|
func HandleRoutes(parent *gin.RouterGroup) {
|
||||||
h := endpoints.GetHandlers()
|
h := endpoints.GetHandlers()
|
||||||
cart := parent.Group("/cart")
|
cart := parent.Group("/cart")
|
||||||
itemRouter := cart.Group("/item")
|
//itemRouter := cart.Group("/item")
|
||||||
{
|
{
|
||||||
cart.GET("", h.GetCartItems)
|
cart.GET("", h.GetCartItems)
|
||||||
cart.POST("", h.CreateFUser)
|
cart.POST("", h.CreateFUser)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
//{
|
||||||
itemRouter.POST("", h.CreateCartItem)
|
// itemRouter.POST("", h.CreateCartItem)
|
||||||
itemRouter.PATCH("", h.UpdateCartItem)
|
// itemRouter.PATCH("", h.UpdateCartItem)
|
||||||
itemRouter.DELETE("", h.DeleteCartItem)
|
// itemRouter.DELETE("", h.DeleteCartItem)
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,13 @@ package endpoints
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
cmap "github.com/orcaman/concurrent-map/v2"
|
|
||||||
"relynolli-server/models"
|
"relynolli-server/models"
|
||||||
"relynolli-server/status"
|
"relynolli-server/status"
|
||||||
"relynolli-server/storage"
|
"relynolli-server/storage"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
cmap "github.com/orcaman/concurrent-map/v2"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
// "relynolli-server/models"
|
// "relynolli-server/models"
|
||||||
// "relynolli-server/services"
|
// "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 {
|
type Handlers interface {
|
||||||
GetFilters(c *gin.Context)
|
GetFilters(c *gin.Context)
|
||||||
GetCatalogItems(c *gin.Context)
|
GetCatalogItems(c *gin.Context)
|
||||||
|
GetCatalogItem(c *gin.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHandlers() Handlers {
|
func GetHandlers() Handlers {
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
package catalog
|
package catalog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-contrib/cache"
|
|
||||||
"os"
|
"os"
|
||||||
"relynolli-server/handlers/catalog/endpoints"
|
"relynolli-server/handlers/catalog/endpoints"
|
||||||
"relynolli-server/internal"
|
"relynolli-server/internal"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/cache"
|
||||||
|
|
||||||
// "relynolli-server/internal"
|
// "relynolli-server/internal"
|
||||||
// "time"
|
// "time"
|
||||||
|
|
||||||
|
@ -22,9 +23,11 @@ func HandleRoutes(parent *gin.RouterGroup) {
|
||||||
// Caching for production usage
|
// Caching for production usage
|
||||||
catalog.GET("", cache.CachePage(cacheStore, 15*time.Minute, h.GetCatalogItems))
|
catalog.GET("", cache.CachePage(cacheStore, 15*time.Minute, h.GetCatalogItems))
|
||||||
catalog.GET("/filters", cache.CachePage(cacheStore, 15*time.Minute, h.GetFilters))
|
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("", h.GetCatalogItems)
|
||||||
|
catalog.GET("/:code", h.GetCatalogItem)
|
||||||
catalog.GET("/filters", h.GetFilters)
|
catalog.GET("/filters", h.GetFilters)
|
||||||
|
|
||||||
// catalog.GET("/filters", cache.CachePage(cacheStore, 15, 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
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"relynolli-server/handlers/cart"
|
||||||
|
"relynolli-server/handlers/news"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
// "relynolli-server/handlers/cart"
|
// "relynolli-server/handlers/cart"
|
||||||
"relynolli-server/handlers/catalog"
|
"relynolli-server/handlers/catalog"
|
||||||
// "relynolli-server/handlers/order"
|
// "relynolli-server/handlers/order"
|
||||||
|
@ -11,7 +15,8 @@ import (
|
||||||
func InitializeRouter(router *gin.Engine) {
|
func InitializeRouter(router *gin.Engine) {
|
||||||
APIV1Router := router.Group("/api/v1")
|
APIV1Router := router.Group("/api/v1")
|
||||||
catalog.HandleRoutes(APIV1Router)
|
catalog.HandleRoutes(APIV1Router)
|
||||||
// cart.HandleRoutes(APIV1Router)
|
cart.HandleRoutes(APIV1Router)
|
||||||
|
news.HandleRoutes(APIV1Router)
|
||||||
// order.HandleRoutes(APIV1Router)
|
// order.HandleRoutes(APIV1Router)
|
||||||
// validate.HandleRoutes(APIV1Router)
|
// validate.HandleRoutes(APIV1Router)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,20 +13,20 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
redisInstance *redis.Client = nil
|
redisInstance *redis.Client = nil
|
||||||
cacheStore *persistence.RedisStore
|
cacheStore *persistence.RedisStore
|
||||||
)
|
)
|
||||||
|
|
||||||
type Cache interface {
|
type Cache interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitRedis() (*redis.Client) {
|
func InitRedis() *redis.Client {
|
||||||
|
|
||||||
if redisInstance == nil {
|
if redisInstance == nil {
|
||||||
redis_db_num, err := strconv.Atoi(os.Getenv("REDIS_DATABASE"))
|
redis_db_num, err := strconv.Atoi(os.Getenv("REDIS_DATABASE"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("REDIS_DATABASE should be integer")
|
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()
|
_, conError := redisInstance.Ping(context.Background()).Result()
|
||||||
if conError != nil {
|
if conError != nil {
|
||||||
|
@ -36,9 +36,9 @@ func InitRedis() (*redis.Client) {
|
||||||
return redisInstance
|
return redisInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitCacheStore() *persistence.RedisStore{
|
func InitCacheStore() *persistence.RedisStore {
|
||||||
if cacheStore == nil {
|
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
|
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 {
|
type DBCatalog struct {
|
||||||
bun.BaseModel `bun:"select:api_catalog"`
|
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"`
|
Code string `bun:"code" json:"code"`
|
||||||
Name string `bun:"name" json:"name"`
|
Name string `bun:"name" json:"name"`
|
||||||
IsActive bool `bun:"is_active,type:integer" json:"isActive"`
|
IsActive bool `bun:"is_active,type:integer" json:"isActive"`
|
||||||
|
|
|
@ -1,13 +1 @@
|
||||||
package catalog
|
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
|
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
|
package services
|
||||||
|
|
||||||
import (
|
//func GetTotal(fuserId int) float64 {
|
||||||
"context"
|
// rdb := internal.InitRedis()
|
||||||
"encoding/json"
|
// keys, _ := rdb.Keys(context.Background(), fmt.Sprintf("api.api_cart.%d.*", fuserId)).Result()
|
||||||
"fmt"
|
//
|
||||||
"relynolli-server/external/bitrix"
|
// result := []models.CatalogWithQuantityWeb{}
|
||||||
"relynolli-server/external/kassa"
|
//
|
||||||
"relynolli-server/external/kassa/Measure"
|
// for _, key := range keys {
|
||||||
"relynolli-server/external/kassa/PaymentMode"
|
// str, _ := rdb.Get(context.Background(), key).Result()
|
||||||
"relynolli-server/external/kassa/PaymentSubject"
|
// item := models.CatalogWithQuantityWeb{}
|
||||||
"relynolli-server/external/kassa/VatCodes"
|
//
|
||||||
"relynolli-server/internal"
|
// json.Unmarshal([]byte(str), &item)
|
||||||
"relynolli-server/models"
|
// result = append(result, item)
|
||||||
"strconv"
|
// }
|
||||||
"strings"
|
//
|
||||||
)
|
// sum := float64(0)
|
||||||
|
//
|
||||||
func GetTotal(fuserId int) float64 {
|
// for _, catalogItem := range result {
|
||||||
rdb := internal.InitRedis()
|
// sum = sum + catalogItem.Price["BASE"].(float64)*float64(catalogItem.Quantity)
|
||||||
keys, _ := rdb.Keys(context.Background(), fmt.Sprintf("api.api_cart.%d.*", fuserId)).Result()
|
// }
|
||||||
|
//
|
||||||
result := []models.CatalogWithQuantityWeb{}
|
// return sum
|
||||||
|
//}
|
||||||
for _, key := range keys {
|
//
|
||||||
str, _ := rdb.Get(context.Background(), key).Result()
|
//type addProductsToOrderReq struct {
|
||||||
item := models.CatalogWithQuantityWeb{}
|
// ProductId int `db:"product_id"`
|
||||||
|
// PriceTypeId int `db:"price_type_id"`
|
||||||
json.Unmarshal([]byte(str), &item)
|
// Quantity int `db:"quantity"`
|
||||||
result = append(result, item)
|
// Price float64 `db:"price"`
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
sum := float64(0)
|
//func addProductsToOrder(api bitrix.Bitrix, fuserId int, orderId int) error {
|
||||||
|
// //Получаем данные из корзины
|
||||||
for _, catalogItem := range result {
|
//
|
||||||
sum = sum + catalogItem.Price["BASE"].(float64)*float64(catalogItem.Quantity)
|
// cartItems := GetCartItems(fuserId)
|
||||||
}
|
//
|
||||||
|
// rdb := internal.InitRedis()
|
||||||
return sum
|
// rdb.Keys(context.Background(), "")
|
||||||
}
|
//
|
||||||
|
// for _, product := range cartItems {
|
||||||
type addProductsToOrderReq struct {
|
// err := api.AddProductToOrder(orderId, product.Id, product.Price["BASE"].(float64), product.Quantity)
|
||||||
ProductId int `db:"product_id"`
|
// if err != nil {
|
||||||
PriceTypeId int `db:"price_type_id"`
|
// return err
|
||||||
Quantity int `db:"quantity"`
|
// }
|
||||||
Price float64 `db:"price"`
|
// }
|
||||||
}
|
// return nil
|
||||||
|
//
|
||||||
func addProductsToOrder(api bitrix.Bitrix, fuserId int, orderId int) error {
|
//}
|
||||||
//Получаем данные из корзины
|
//
|
||||||
|
//func MakeOrder(fuserId int, email string, fullName string, phone string) (map[string]interface{}, error) {
|
||||||
cartItems := GetCartItems(fuserId)
|
//
|
||||||
|
// // Инициализируем api
|
||||||
rdb := internal.InitRedis()
|
//
|
||||||
rdb.Keys(context.Background(), "")
|
// api := bitrix.Initialize()
|
||||||
|
//
|
||||||
for _, product := range cartItems {
|
// // 1. Создаем анонимного пользователя
|
||||||
err := api.AddProductToOrder(orderId, product.Id, product.Price["BASE"].(float64), product.Quantity)
|
//
|
||||||
if err != nil {
|
// userId, _ := api.CreateAnonymousUser()
|
||||||
return err
|
//
|
||||||
}
|
// // 2. Создаем заказ
|
||||||
}
|
// orderId, _ := api.CreateOrder(userId)
|
||||||
return nil
|
//
|
||||||
|
// // --- обновляем контакт пользователя
|
||||||
}
|
// order, orderErr := api.GetOrderInfo(orderId)
|
||||||
|
// if orderErr != nil {
|
||||||
func MakeOrder(fuserId int, email string, fullName string, phone string) (map[string]interface{}, error) {
|
// return nil, orderErr
|
||||||
|
// }
|
||||||
// Инициализируем api
|
// clientId, _ := strconv.Atoi(order.Clients[0].EntityId)
|
||||||
|
// api.UpdateContact(clientId, email, fullName, phone)
|
||||||
api := bitrix.Initialize()
|
//
|
||||||
|
// // 3. Добавляем элементы в корзину
|
||||||
// 1. Создаем анонимного пользователя
|
// addProductErr := addProductsToOrder(api, fuserId, orderId)
|
||||||
|
// if addProductErr != nil {
|
||||||
userId, _ := api.CreateAnonymousUser()
|
// return nil, addProductErr
|
||||||
|
// }
|
||||||
// 2. Создаем заказ
|
//
|
||||||
orderId, _ := api.CreateOrder(userId)
|
// // 4. Получаем обновленный ресурс заказа
|
||||||
|
// order, _ = api.GetOrderInfo(orderId)
|
||||||
// --- обновляем контакт пользователя
|
//
|
||||||
order, orderErr := api.GetOrderInfo(orderId)
|
// // 5. Добавляем способ оплаты товара
|
||||||
if orderErr != nil {
|
// createPaymentError := api.CreatePayment(orderId, order.Price)
|
||||||
return nil, orderErr
|
//
|
||||||
}
|
// if createPaymentError != nil {
|
||||||
clientId, _ := strconv.Atoi(order.Clients[0].EntityId)
|
// return nil, createPaymentError
|
||||||
api.UpdateContact(clientId, email, fullName, phone)
|
// }
|
||||||
|
//
|
||||||
// 3. Добавляем элементы в корзину
|
// // 6. Получаем ресурс оплаты и url для нее
|
||||||
addProductErr := addProductsToOrder(api, fuserId, orderId)
|
// paymentData, _ := kassa.CreatePayment(orderId, order.Price, fullName, email, phone, getItemsForPayment(order))
|
||||||
if addProductErr != nil {
|
//
|
||||||
return nil, addProductErr
|
// insPaymentDataStmt := fmt.Sprintf(`
|
||||||
}
|
// insert into api_youkassa_payment (payment_id, order_id, link, status)
|
||||||
|
// values ('%s',
|
||||||
// 4. Получаем обновленный ресурс заказа
|
// '%s',
|
||||||
order, _ = api.GetOrderInfo(orderId)
|
// '%s',
|
||||||
|
// '%s');
|
||||||
// 5. Добавляем способ оплаты товара
|
// `, paymentData["id"].(string),
|
||||||
createPaymentError := api.CreatePayment(orderId, order.Price)
|
// orderId,
|
||||||
|
// paymentData["confirmation"].(map[string]interface{})["confirmation_url"].(string),
|
||||||
if createPaymentError != nil {
|
// paymentData["status"].(string),
|
||||||
return nil, createPaymentError
|
// )
|
||||||
}
|
//
|
||||||
|
// db := internal.InitDatabase()
|
||||||
// 6. Получаем ресурс оплаты и url для нее
|
//
|
||||||
paymentData, _ := kassa.CreatePayment(orderId, order.Price, fullName, email, phone, getItemsForPayment(order))
|
// db.Execute(insPaymentDataStmt)
|
||||||
|
//
|
||||||
insPaymentDataStmt := fmt.Sprintf(`
|
// return paymentData, nil
|
||||||
insert into api_youkassa_payment (payment_id, order_id, link, status)
|
//}
|
||||||
values ('%s',
|
//
|
||||||
'%s',
|
//func getItemsForPayment(order *bitrix.OrderResource) []kassa.KassaReceiptItems {
|
||||||
'%s',
|
// result := []kassa.KassaReceiptItems{}
|
||||||
'%s');
|
//
|
||||||
`, paymentData["id"].(string),
|
// for _, basketItem := range order.BasketItems {
|
||||||
orderId,
|
// quantity, _ := strconv.Atoi(strings.Split(basketItem.Quantity, ".")[0])
|
||||||
paymentData["confirmation"].(map[string]interface{})["confirmation_url"].(string),
|
// item := kassa.KassaReceiptItems{
|
||||||
paymentData["status"].(string),
|
// Description: basketItem.Name,
|
||||||
)
|
// Amount: kassa.KassaAmount{
|
||||||
|
// Value: fmt.Sprintf("%f", basketItem.Price),
|
||||||
db := internal.InitDatabase()
|
// Currency: "RUB",
|
||||||
|
// },
|
||||||
db.Execute(insPaymentDataStmt)
|
// VatCode: VatCodes.NDS_20,
|
||||||
|
// Quantity: fmt.Sprintf("%d", quantity),
|
||||||
return paymentData, nil
|
// Measure: Measure.PIECE,
|
||||||
}
|
// PaymentSubject: PaymentSubject.COMMODITY,
|
||||||
|
// PaymentMode: PaymentMode.FULL_PAYMENT,
|
||||||
func getItemsForPayment(order *bitrix.OrderResource) []kassa.KassaReceiptItems {
|
// }
|
||||||
result := []kassa.KassaReceiptItems{}
|
// result = append(result, item)
|
||||||
|
// }
|
||||||
for _, basketItem := range order.BasketItems {
|
//
|
||||||
quantity, _ := strconv.Atoi(strings.Split(basketItem.Quantity, ".")[0])
|
// return result
|
||||||
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
|
package services
|
||||||
|
|
||||||
import (
|
//
|
||||||
"fmt"
|
//func YookassaValidate(paymentId string, status string) {
|
||||||
"relynolli-server/external/bitrix"
|
// 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)
|
||||||
"relynolli-server/internal"
|
// db := internal.InitDatabase()
|
||||||
)
|
// rows := db.Query(stmt)
|
||||||
|
//
|
||||||
func YookassaValidate(paymentId string, status string) {
|
// var (
|
||||||
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)
|
// orderId int
|
||||||
db := internal.InitDatabase()
|
// paymentIdBitrix int
|
||||||
rows := db.Query(stmt)
|
// )
|
||||||
|
//
|
||||||
var (
|
// rows.Next()
|
||||||
orderId int
|
// rows.Scan(&orderId, &paymentIdBitrix)
|
||||||
paymentIdBitrix int
|
//
|
||||||
)
|
// api := bitrix.Initialize()
|
||||||
|
// if status == "succeeded" {
|
||||||
rows.Next()
|
// api.ApprovePayment(paymentIdBitrix, 8)
|
||||||
rows.Scan(&orderId, &paymentIdBitrix)
|
// return
|
||||||
|
// }
|
||||||
api := bitrix.Initialize()
|
// if status == "canceled" {
|
||||||
if status == "succeeded" {
|
// api.CancelOrder(orderId)
|
||||||
api.ApprovePayment(paymentIdBitrix, 8)
|
// return
|
||||||
return
|
// }
|
||||||
}
|
// 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
|
package storage
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"relynolli-server/internal"
|
||||||
|
"relynolli-server/models/cart"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type StorageCart interface {
|
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 {
|
type StorageCatalog interface {
|
||||||
GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCatalog, error)
|
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)
|
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)
|
GetFilters(ctx context.Context) (int, *[]filters2.DBFilter, error)
|
||||||
}
|
}
|
||||||
|
@ -21,17 +23,17 @@ type StorageCatalog interface {
|
||||||
func NewStorageCatalog() StorageCatalog {
|
func NewStorageCatalog() StorageCatalog {
|
||||||
if instance == nil {
|
if instance == nil {
|
||||||
instance = &storage{
|
instance = &storage{
|
||||||
db: internal.InitDatabase().GetInstance(),
|
db: internal.InitDatabase().GetInstance(),
|
||||||
|
rdb: internal.InitRedis(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return instance
|
return instance
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCatalog, error) {
|
func (s *storage) GetCatalogItemByCode(ctx context.Context, code string) (*catalog.DBCatalog, error) {
|
||||||
db := internal.InitDatabase().GetInstance()
|
|
||||||
model := new(catalog.DBCatalog)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -39,12 +41,22 @@ func (s *storage) GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCat
|
||||||
return model, nil
|
return model, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildFilterGroup(ctx context.Context, q *bun.SelectQuery, filters *cmap.ConcurrentMap[string, []string]) *bun.SelectQuery {
|
func (s *storage) GetCatalogItem(ctx context.Context, id *int64) (*catalog.DBCatalog, error) {
|
||||||
db := internal.InitDatabase().GetInstance()
|
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)
|
availableFilters := new([]filters2.DBFilter)
|
||||||
|
|
||||||
//Get filters
|
//Get filters
|
||||||
db.NewSelect().Model(availableFilters).Scan(ctx)
|
s.db.NewSelect().Model(availableFilters).Scan(ctx)
|
||||||
|
|
||||||
for _, filter := range filters.Keys() {
|
for _, filter := range filters.Keys() {
|
||||||
filter = filter[0 : len(filter)-2]
|
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) {
|
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)
|
model := new([]catalog.DBCatalog)
|
||||||
filterQuery := db.NewSelect().Model(model).Where("is_active = 1").Where("available_quantity > 0")
|
filterQuery := s.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)
|
count, _ := s.buildFilterGroup(ctx, filterQuery, &filters).Limit(limit).Offset(offset).Order("code").ScanAndCount(ctx)
|
||||||
|
|
||||||
return count, model, nil
|
return count, model, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) GetFilters(ctx context.Context) (int, *[]filters2.DBFilter, error) {
|
func (s *storage) GetFilters(ctx context.Context) (int, *[]filters2.DBFilter, error) {
|
||||||
models := new([]filters2.DBFilter)
|
models := new([]filters2.DBFilter)
|
||||||
db := internal.InitDatabase().GetInstance()
|
count, err := s.db.NewSelect().Model(models).ScanAndCount(ctx)
|
||||||
count, err := db.NewSelect().Model(models).ScanAndCount(ctx)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, nil, err
|
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
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
"github.com/uptrace/bun"
|
"github.com/uptrace/bun"
|
||||||
)
|
)
|
||||||
|
|
||||||
type storage struct {
|
type storage struct {
|
||||||
db *bun.DB
|
db *bun.DB
|
||||||
|
rdb *redis.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
var instance *storage = nil
|
var instance *storage = nil
|
||||||
|
|
Loading…
Reference in New Issue