Browse Source

availability

portowyi 1 year ago
parent
commit
c736148e42
6 changed files with 147 additions and 11 deletions
  1. 5 1
      .env
  2. 28 0
      controller/availability.go
  3. 11 3
      controller/cdn.go
  4. 42 3
      cron-job/cronJobs.go
  5. 12 4
      main.go
  6. 49 0
      model/availability.go

+ 5 - 1
.env

@@ -12,4 +12,8 @@ JWT_PRIVATE_KEY="Kq4NZSrtRkyD5NqzjkeHlw"
 # pgAdmin4 Credentials for Docker Compose
 PGADMIN_DEFAULT_EMAIL=admin@admin.com
 PGADMIN_DEFAULT_PASSWORD=password123
-PGADMIN_LISTEN_PORT=80
+PGADMIN_LISTEN_PORT=80
+
+# cron
+CRON_XML_FEED=@every 6h
+CRON_CSV_DELTA=@every 20m

+ 28 - 0
controller/availability.go

@@ -0,0 +1,28 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"kng_feed_api/model"
+	"net/http"
+)
+
+func LoadAvailabilityInfo(context *gin.Context) {
+	var availabilityArray model.AvailabilityArray
+	err := context.ShouldBindJSON(&availabilityArray)
+
+	if err != nil {
+		context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
+		return
+	}
+
+	for _, av := range availabilityArray.AvailabilityArray {
+		product := model.Availability{
+			CodeCarCaDe: av.CodeCarCaDe,
+			Available:   av.Available,
+		}
+		product.CreateOrUpdate()
+	}
+
+	context.JSON(http.StatusCreated, gin.H{"ok": "Saved"})
+
+}

+ 11 - 3
controller/cdn.go

@@ -9,8 +9,16 @@ import (
 	"github.com/gin-gonic/gin"
 )
 
-func SendFileToClient(context *gin.Context) {
-	var fileName = filepath.Join(helper.RootDir(), "feed.xml")
+func SendXmlFeedToClient(context *gin.Context) {
+	sendFile(context, "feed.xml")
+}
+
+func SendCsvDeltaToClient(context *gin.Context) {
+	sendFile(context, "delta.csv")
+}
+
+func sendFile(context *gin.Context, fileMark string) {
+	var fileName = filepath.Join(helper.RootDir(), fileMark)
 	_, err := os.Stat(fileName)
 	if err != nil {
 		if os.IsNotExist(err) {
@@ -31,6 +39,6 @@ func SendFileToClient(context *gin.Context) {
 			return
 		}
 	}
-	context.FileAttachment(fileName, "feed.xml")
+	context.FileAttachment(fileName, fileMark)
 	context.Status(http.StatusOK)
 }

+ 42 - 3
cron-job/cronJobs.go

@@ -1,10 +1,12 @@
 package cronjob
 
 import (
+	"encoding/csv"
 	"encoding/xml"
 	"fmt"
 	"kng_feed_api/helper"
 	"kng_feed_api/model"
+	"log"
 	"os"
 	"path/filepath"
 	"strconv"
@@ -67,7 +69,7 @@ func CreateXMLFeed() {
 	yml_catalog.Date = time_now.Format("2006-01-02 15:04")
 
 	var shop = &Shop{}
-	shop.Name = "ООО \"Княгиня\""
+	shop.Name = "ООО КНЯГИНЯ"
 	shop.URL = "https://b2bn.kngnn.ru"
 
 	for _, value := range categoryRows {
@@ -165,8 +167,45 @@ func CreateXMLFeed() {
 		fmt.Printf("error: %v\n", err)
 	} else {
 		var Header = `<?xml version="1.0" encoding="UTF-8"?>` + "\n"
-		var byteXmlText_withHeasder = []byte(Header + string(byteXmlText))
+		var byteXmlTextWithHeader = []byte(Header + string(byteXmlText))
 
-		os.WriteFile(filepath.Join(helper.RootDir(), "feed.xml"), byteXmlText_withHeasder, 0666)
+		os.WriteFile(filepath.Join(helper.RootDir(), "feed.xml"), byteXmlTextWithHeader, 0666)
+	}
+}
+
+func CreateCSVDeltaFeed() {
+	rows, err := model.GetAllAvailability()
+	if err != nil {
+		log.Printf("Не удалось получить данные для формирования дельта-фида из базы по причине [%s]", err)
+		return
+	}
+
+	file, err := os.Create(filepath.Join(helper.RootDir(), "delta.csv"))
+	if err != nil {
+		log.Printf("Не удалось сформировать пустой файл дельта-фида по причине [%s]", err)
+		return
+	}
+	defer file.Close()
+
+	csvWriter := csv.NewWriter(file)
+	csvWriter.Comma = ';'
+
+	defer csvWriter.Flush()
+
+	var records [][]string
+
+	for _, row := range rows {
+		var record []string
+		record = append(record, row.CodeCarCaDe)
+		record = append(record, "0")
+		record = append(record, strconv.Itoa(row.Available))
+
+		records = append(records, record)
+	}
+
+	writeError := csvWriter.WriteAll(records)
+	if writeError != nil {
+		log.Printf("Не удалось сохранить файл дельта-фида на диск по причине [%s]", writeError)
+		return
 	}
 }

+ 12 - 4
main.go

@@ -7,6 +7,7 @@ import (
 	"kng_feed_api/database"
 	"kng_feed_api/model"
 	"log"
+	"os"
 
 	"github.com/gin-gonic/gin"
 	"github.com/joho/godotenv"
@@ -22,7 +23,8 @@ func main() {
 
 func startCronJob() {
 	cron := cron.New()
-	cron.AddFunc("@every 6h", cronjob.CreateXMLFeed)
+	cron.AddFunc(os.Getenv("CRON_XML_FEED"), cronjob.CreateXMLFeed)
+	cron.AddFunc(os.Getenv("CRON_CSV_DELTA"), cronjob.CreateCSVDeltaFeed)
 	cron.Start()
 }
 
@@ -43,7 +45,8 @@ func loadEnv() {
 func serveApplication() {
 	router := gin.Default()
 
-	router.StaticFile("/feed.xml", "./feed.xml") //filepath.Join(helper.RootDir()))
+	router.StaticFile("/feed.xml", "./feed.xml")   //filepath.Join(helper.RootDir()))
+	router.StaticFile("/delta.csv", "./delta.csv") //filepath.Join(helper.RootDir()))
 
 	publicRoutes := router.Group("/auth")
 	publicRoutes.POST("/register", controller.Register)
@@ -52,8 +55,13 @@ func serveApplication() {
 	feedRoutes := router.Group("/feed")
 	feedRoutes.POST("/products", controller.LoadProductsInfo)
 	feedRoutes.POST("/categories", controller.CreateUpdateCategories)
-	feedRoutes.GET("/", controller.SendFileToClient)
+
+	feedRoutes.GET("/", controller.SendXmlFeedToClient)
+
+	deltaRoutes := router.Group("/delta")
+	deltaRoutes.POST("/availability", controller.LoadAvailabilityInfo)
+	deltaRoutes.GET("/", controller.SendCsvDeltaToClient)
 
 	router.Run(":3005")
-	fmt.Println("Server running on port 8000")
+	fmt.Println("Server running on port 3005")
 }

+ 49 - 0
model/availability.go

@@ -0,0 +1,49 @@
+package model
+
+import (
+	"database/sql"
+	"errors"
+	"fmt"
+	"gorm.io/gorm"
+	"kng_feed_api/database"
+)
+
+type Availability struct {
+	CodeCarCaDe string `gorm:"size:11;not null; unique; index; primaryKey" json:"code_carcade"`
+	Available   int    `gorm:"default=0" json:"available"`
+}
+
+type AvailabilityArray struct {
+	AvailabilityArray []Availability `binding:"dive" json:"items"`
+}
+
+func (availability *Availability) CreateOrUpdate() {
+	database.Database.Exec(
+		`UPDATE public.availability SET available = @available WHERE code_car_ca_de = @code;
+				INSERT INTO public.availability (code_car_ca_de, available) 
+				SELECT @code, @available 
+				WHERE NOT EXISTS (SELECT 1 FROM public.availability WHERE code_car_ca_de = @code);`,
+		sql.Named("available", availability.Available),
+		sql.Named("code", availability.CodeCarCaDe))
+}
+
+func GetAllAvailability() ([]Availability, error) {
+	var availability []Availability
+	result := database.Database.Find(&availability)
+	if result.Error != nil {
+		return availability, result.Error
+	}
+	return availability, nil
+}
+
+func GetOneAvailability(code string) (Availability, error) {
+	var av Availability
+	err := database.Database.First(&av, code).Error
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return av, errors.New(fmt.Sprintf("Объект с кодом %s не найден", code))
+		}
+		return av, err
+	}
+	return av, nil
+}