+17
-13
@@ -18,6 +18,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -553,21 +554,22 @@ func RunSybSync(ctx context.Context, db *sql.DB, client *syb.Client, cfg config.
|
||||
// 局部历史补拉只 upsert 数据、不动游标,否则会让未覆盖的订单永久漏掉。
|
||||
func RunSybSyncWithOptions(ctx context.Context, db *sql.DB, client *syb.Client, cfg config.SybConfig, now time.Time, options SybSyncOptions) SyncReport {
|
||||
report := SyncReport{StartedAt: now, Specified: options.IsSpecified()}
|
||||
allowedNames, err := repository.ListEnabledSybShopNames(db)
|
||||
allowedShops, err := repository.ListEnabledSybShopMappings(db)
|
||||
if err != nil {
|
||||
report.Err = fmt.Errorf("读取顺运宝允许店铺失败: %w", err)
|
||||
report.FinishedAt = time.Now().UTC()
|
||||
return report
|
||||
}
|
||||
if len(allowedNames) == 0 {
|
||||
report.Err = fmt.Errorf("没有启用的顺运宝同步店铺,请先由管理员在“同步店铺”中配置并启用至少一个店铺")
|
||||
if len(allowedShops) == 0 {
|
||||
report.Err = fmt.Errorf("没有启用的顺运宝同步店铺,请先由管理员在“店铺管理”中配置并启用至少一个 SYB 店铺")
|
||||
report.FinishedAt = time.Now().UTC()
|
||||
return report
|
||||
}
|
||||
allowedShops := make(map[string]struct{}, len(allowedNames))
|
||||
for _, name := range allowedNames {
|
||||
allowedShops[name] = struct{}{}
|
||||
allowedNames := make([]string, 0, len(allowedShops))
|
||||
for name := range allowedShops {
|
||||
allowedNames = append(allowedNames, name)
|
||||
}
|
||||
sort.Strings(allowedNames)
|
||||
report.ShopFilterHash = fmt.Sprintf("%x", sha256.Sum256([]byte(strings.Join(allowedNames, "\x00"))))
|
||||
|
||||
pageSize := cfg.PageSize
|
||||
@@ -754,7 +756,7 @@ func RunSybSyncWithOptions(ctx context.Context, db *sql.DB, client *syb.Client,
|
||||
report.StockCount += len(rawIDs)
|
||||
orderedIDs := make([]int64, 0, len(rawIDs))
|
||||
for _, id := range rawIDs {
|
||||
if !sybShopAllowed(allowedShops, stockByID[id].Raw, nil) {
|
||||
if _, ok := sybShopID(allowedShops, stockByID[id].Raw, nil); !ok {
|
||||
report.ShopSkipped++
|
||||
continue
|
||||
}
|
||||
@@ -782,12 +784,13 @@ func RunSybSyncWithOptions(ctx context.Context, db *sql.DB, client *syb.Client,
|
||||
}
|
||||
for _, d := range details {
|
||||
stockRow := stockByID[d.ID]
|
||||
if !sybShopAllowed(allowedShops, stockRow.Raw, d.Raw) {
|
||||
shopID, ok := sybShopID(allowedShops, stockRow.Raw, d.Raw)
|
||||
if !ok {
|
||||
report.AcceptedCount--
|
||||
report.ShopSkipped++
|
||||
continue
|
||||
}
|
||||
if err := writeStockDetail(db, cfg.BaseURL, stockRow, d, &report); err != nil {
|
||||
if err := writeStockDetail(db, cfg.BaseURL, shopID, stockRow, d, &report); err != nil {
|
||||
report.Err = fmt.Errorf("写入货运单 %s(id=%d)失败(本次同步整体作废,"+
|
||||
"已写入的数据保留): %w", d.Code, d.ID, err)
|
||||
report.FinishedAt = time.Now().UTC()
|
||||
@@ -820,10 +823,10 @@ func RunSybSyncWithOptions(ctx context.Context, db *sql.DB, client *syb.Client,
|
||||
|
||||
// sybShopAllowed 用明细字段覆盖列表字段后再核对,防止列表通过但明细在同步
|
||||
// 期间已变成其他店铺。detail 为空时只检查列表快照。
|
||||
func sybShopAllowed(allowed map[string]struct{}, listRaw, detailRaw map[string]any) bool {
|
||||
func sybShopID(allowed map[string]string, listRaw, detailRaw map[string]any) (string, bool) {
|
||||
name := trimmedStringField(mergeRaw(listRaw, detailRaw), "shopName")
|
||||
_, ok := allowed[name]
|
||||
return ok
|
||||
shopID, ok := allowed[name]
|
||||
return shopID, ok
|
||||
}
|
||||
|
||||
// validateDetailBatch 确认批量明细响应与请求 ID 一一对应。任何缺失、重复、
|
||||
@@ -856,7 +859,7 @@ func validateDetailBatch(requested []int64, details []syb.StockDetail) error {
|
||||
|
||||
// writeStockDetail 把一张货运单的全部商品明细写进 syb_orders,
|
||||
// 一张货运单一个事务(工单 #46「按货运单为单位提交」)。
|
||||
func writeStockDetail(db *sql.DB, baseURL string, stockRow syb.StockRow, detail syb.StockDetail, report *SyncReport) error {
|
||||
func writeStockDetail(db *sql.DB, baseURL, shopID string, stockRow syb.StockRow, detail syb.StockDetail, report *SyncReport) error {
|
||||
if len(detail.Details) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -888,6 +891,7 @@ func writeStockDetail(db *sql.DB, baseURL string, stockRow syb.StockRow, detail
|
||||
order := model.SybOrder{
|
||||
SybID: sybID,
|
||||
OrderNo: detail.Code,
|
||||
ShopID: shopID,
|
||||
ShopName: trimmedStringField(stockRaw, "shopName"),
|
||||
Title: item.ProductTitle,
|
||||
ProductSpec: item.ProductSpec,
|
||||
|
||||
Reference in New Issue
Block a user