daShangDao_psiServer/controllers/process_sync.go

282 lines
9.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package controllers
import (
"encoding/json"
"fmt"
"strconv"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"gorm.io/datatypes"
"gorm.io/gorm"
"psi/constant"
"psi/database"
"psi/es"
"psi/models"
systemReq "psi/models/request"
systemRes "psi/models/response"
"psi/service"
"psi/utils"
"time"
)
type bookFieldData struct {
Fid int64
BookType int8
ISBN string
FISBN string
BookName string
FBookName string
Author string
Publishing string
PublicationTime int64
Binding string
PagesCount int64
WordsCount int64
Format int64
CatID datatypes.JSON
}
// defaultCatID 默认分类ID
func defaultCatID() datatypes.JSON {
return datatypes.JSON(`{"xian_yu_cat_id": "", "kong_fu_zi_cat_id": "", "pin_duo_duo_cat_id": ""}`)
}
// bookFieldsFromDB 从数据库中获取书籍信息
func bookFieldsFromDB(bi models.BookInfo) bookFieldData {
catID := bi.CatID
if catID == nil {
catID = defaultCatID()
}
return bookFieldData{
Fid: bi.Fid, BookType: bi.Type, ISBN: bi.ISBN, FISBN: bi.FISBN,
BookName: bi.BookName, FBookName: bi.FBookName, Author: bi.Author,
Publishing: bi.Publishing, PublicationTime: bi.PublicationTime,
Binding: bi.Binding, PagesCount: bi.PagesCount, WordsCount: bi.WordsCount,
Format: bi.Format, CatID: catID,
}
}
// bookFieldsFromES 从ES中获取书籍信息
func bookFieldsFromES(eb *systemRes.ESBook, isbn string) bookFieldData {
var bookType int8
if eb.IsSuit > 0 {
bookType = 2
}
var publicationTime int64
if eb.PublicationTime != "" {
if v, err := strconv.ParseInt(eb.PublicationTime, 10, 64); err == nil {
publicationTime = v
}
}
var pagesCount int64
if v, err := strconv.ParseInt(string(eb.PageCount), 10, 64); err == nil {
pagesCount = v
}
var wordsCount int64
if v, err := strconv.ParseInt(string(eb.WordCount), 10, 64); err == nil {
wordsCount = v
}
var formatVal int64
if v, err := strconv.ParseInt(string(eb.BookFormat), 10, 64); err == nil {
formatVal = v
}
catID := defaultCatID()
if catBytes, err := json.Marshal(eb.CatId); err == nil {
emptyCat := es.CatIdObject{}
if eb.CatId != emptyCat {
catID = catBytes
}
}
return bookFieldData{
Fid: eb.Fid, BookType: bookType, ISBN: isbn, FISBN: eb.FISBN,
BookName: eb.BookName.Value, FBookName: eb.FBookName.Value, Author: eb.Author,
Publishing: eb.Publisher, PublicationTime: publicationTime,
Binding: eb.BindingLayout, PagesCount: pagesCount, WordsCount: wordsCount,
Format: formatVal, CatID: catID,
}
}
// syncProductBookToMainDB 入库后同步商品信息到主库 product_book_xx 分表
func (r *ProcessApi) syncProductBookToMainDB(req systemReq.ReceivingSubmitRequest, userInfo utils.UserInfo, c *gin.Context) {
itemProductIDs := make([]int64, len(req.Items))
for i, item := range req.Items {
itemProductIDs[i] = item.ProductID
}
tenantDB, err := database.GetTenantDB(userInfo.AboutID)
if err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "获取租户数据库连接失败", err, c, gin.H{"about_id": userInfo.AboutID})
return
}
var receivingOrder models.ReceivingOrder
if err := tenantDB.Where("id = ? AND is_del = 0", req.ReceivingOrderID).First(&receivingOrder).Error; err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "查询入库单失败", err, c, gin.H{"receiving_order_id": req.ReceivingOrderID})
return
}
var warehouse models.Warehouse
if err := tenantDB.Where("id = ? AND is_del = 0", receivingOrder.WarehouseID).First(&warehouse).Error; err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "查询仓库失败", err, c, gin.H{"warehouse_id": receivingOrder.WarehouseID})
return
}
var products []models.Product
if err := tenantDB.Where("id IN ? AND is_del = 0", itemProductIDs).Find(&products).Error; err != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "查询商品列表失败", err, c, gin.H{"product_ids": itemProductIDs})
return
}
type locationInfo struct {
LocationID int64
Code string
}
locationMap := make(map[int64]locationInfo)
for _, product := range products {
var invDetail models.InventoryDetail
if err := tenantDB.Where("product_id = ? AND warehouse_id = ? AND is_del = 0", product.ID, receivingOrder.WarehouseID).First(&invDetail).Error; err == nil {
var loc models.Location
if err := tenantDB.Where("id = ? AND is_del = 0", invDetail.LocationID).First(&loc).Error; err == nil {
locationMap[product.ID] = locationInfo{LocationID: loc.ID, Code: loc.Code}
}
}
}
// 构建书籍信息有StandardProductID查book_info表否则查ES
bookSvc := service.BookService{}
dbBookMap := make(map[int64]models.BookInfo)
esBookMap := make(map[string]*systemRes.ESBook)
for _, product := range products {
if product.Barcode == "" {
continue
}
if product.StandardProductID > 0 {
if _, exists := dbBookMap[product.StandardProductID]; !exists {
var bookInfo models.BookInfo
if err := database.DB.Where("id = ?", product.StandardProductID).First(&bookInfo).Error; err == nil {
dbBookMap[product.StandardProductID] = bookInfo
continue
}
} else {
continue
}
}
isbn := product.Barcode
if _, exists := esBookMap[isbn]; !exists {
esBook, esErr := bookSvc.GetBookInfo(systemReq.BookRequest{Isbn: isbn})
if esErr != nil {
utils.ErrorLog(constant.LoggerChannelWork, logrus.Fields{
"source": "ES查询BookInfo失败", "isbn": isbn, "err_msg": esErr.Error(),
})
}
if esBook != nil {
esBookMap[isbn] = esBook
}
}
}
// 逐个写入分表
now := time.Now().Unix()
for _, product := range products {
isbn := product.Barcode
if isbn == "" {
continue
}
var fields bookFieldData
var hasBookInfo bool
if bi, exists := dbBookMap[product.StandardProductID]; product.StandardProductID > 0 && exists {
fields = bookFieldsFromDB(bi)
hasBookInfo = true
} else if eb, exists := esBookMap[isbn]; exists {
fields = bookFieldsFromES(eb, isbn)
hasBookInfo = true
}
if !hasBookInfo {
utils.ErrorLog(constant.LoggerChannelWork, logrus.Fields{
"source": "书籍信息未找到,跳过同步",
"product_id": product.ID,
"isbn": isbn,
"about_id": userInfo.AboutID,
})
continue
}
tableName := models.ProductBookTableName(isbn)
var locInfo locationInfo
if li, exists := locationMap[product.ID]; exists {
locInfo = li
}
liveImage := product.LiveImage
if liveImage == nil {
liveImage = datatypes.JSON("[]")
}
var existingBook models.ProductBook
err := database.DB.Table(tableName).Where("self_id = ? AND about_id = ? AND is_del = 0", product.ID, userInfo.AboutID).First(&existingBook).Error
if err != nil && err == gorm.ErrRecordNotFound {
bookRecord := models.ProductBook{
SelfID: product.ID, AboutId: userInfo.AboutID,
WarehouseID: warehouse.ID, WarehouseName: warehouse.Name,
LocationID: locInfo.LocationID, LocationName: locInfo.Code,
CategoryID: product.CategoryID, StandardProductID: product.StandardProductID,
Fid: fields.Fid, Type: fields.BookType, ISBN: isbn, FISBN: fields.FISBN,
BookName: fields.BookName, FBookName: fields.FBookName,
Author: fields.Author, Publishing: fields.Publishing,
PublicationTime: fields.PublicationTime, Binding: fields.Binding,
PagesCount: fields.PagesCount, WordsCount: fields.WordsCount,
Format: fields.Format, CatID: fields.CatID,
Name: product.Name, Appearance: product.Appearance,
Barcode: product.Barcode, Price: product.Price,
SalePrice: product.SalePrice, Cost: product.Cost,
LiveImage: liveImage, IsBatchManaged: product.IsBatchManaged,
IsShelfLifeManaged: product.IsShelfLifeManaged, Status: product.Status,
CreatedAt: now, UpdatedAt: now, IsDel: 0,
}
if createErr := database.DB.Table(tableName).Create(&bookRecord).Error; createErr != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "写入product_book分表失败", createErr, c, gin.H{
"product_id": product.ID, "isbn": isbn, "table_name": tableName,
})
return
}
} else if err == nil {
updateData := map[string]interface{}{
"warehouse_id": warehouse.ID, "warehouse_name": warehouse.Name,
"location_id": locInfo.LocationID, "location_name": locInfo.Code,
"category_id": product.CategoryID, "standard_product_id": product.StandardProductID,
"fid": fields.Fid, "type": fields.BookType,
"f_isbn": fields.FISBN, "book_name": fields.BookName,
"f_book_name": fields.FBookName, "author": fields.Author,
"publishing": fields.Publishing, "publication_time": fields.PublicationTime,
"binding": fields.Binding, "pages_count": fields.PagesCount,
"words_count": fields.WordsCount, "format": fields.Format, "cat_id": fields.CatID,
"name": product.Name, "appearance": product.Appearance,
"barcode": product.Barcode, "price": product.Price,
"sale_price": product.SalePrice, "cost": product.Cost,
"live_image": liveImage, "is_batch_managed": product.IsBatchManaged,
"is_shelf_life_managed": product.IsShelfLifeManaged, "status": product.Status,
"updated_at": now,
}
if updateErr := database.DB.Table(tableName).Model(&existingBook).Updates(updateData).Error; updateErr != nil {
utils.FailWithRequestLog(constant.LoggerChannelWork, "更新product_book分表失败", updateErr, c, gin.H{
"product_id": product.ID, "isbn": isbn, "table_name": tableName,
})
return
}
} else {
utils.FailWithRequestLog(constant.LoggerChannelWork, "查询product_book分表失败", err, c, gin.H{
"product_id": product.ID, "isbn": isbn, "table_name": tableName,
})
return
}
}
fmt.Printf("同步product_book完成, 入库单ID: %d, 商品数: %d\n", req.ReceivingOrderID, len(products))
}