282 lines
9.6 KiB
Go
282 lines
9.6 KiB
Go
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))
|
||
}
|