Files
cmautobuy/admin/service/shopee_pdd.go
T

160 lines
5.5 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 service
import (
"database/sql"
"errors"
"fmt"
"strings"
"cmautobuy/admin/model"
"cmautobuy/admin/repository"
)
// ErrPddAssociationReplaceRequired 表示当前蝦皮商品已经关联了另一个 PDD 商品。
var ErrPddAssociationReplaceRequired = errors.New("更换 PDD 商品需要明确确认")
const canonicalPddGoodsURL = "https://mobile.yangkeduo.com/goods.html?goods_id="
// normalizeSybPddReference 只在顺运宝详情入口兼容纯商品 ID。
// 其他入口仍沿用完整 PDD 链接校验,避免无意扩大已经确认的输入范围。
func normalizeSybPddReference(raw string) (string, error) {
value := strings.TrimSpace(raw)
if value == "" {
return "", fmt.Errorf("%w: PDD 商品链接或商品 ID 不能为空", ErrBadPddURL)
}
if isGoodsID(value) {
return canonicalPddGoodsURL + value, nil
}
if isASCIIDigits(value) {
return "", fmt.Errorf("%w: PDD 商品 ID 必须是 6~24 位纯数字", ErrBadPddURL)
}
if !strings.Contains(value, "://") {
return "", fmt.Errorf("%w: 请输入带 goods_id 的完整拼多多链接,或 6~24 位纯数字商品 ID", ErrBadPddURL)
}
return value, nil
}
func isASCIIDigits(value string) bool {
for _, char := range value {
if char < '0' || char > '9' {
return false
}
}
return true
}
// AssociateShopeePdd 把蝦皮商品关联到 PDD 商品档案。
// 解析、建档/复活和关联更新在同一事务内完成,任一步失败都不留下半成品。
func AssociateShopeePdd(db *sql.DB, shopeeGoodsID, rawURL string, confirmReplace bool) (string, error) {
shopeeGoodsID = strings.TrimSpace(shopeeGoodsID)
rawURL = strings.TrimSpace(rawURL)
pddGoodsID, err := ParsePddGoodsID(rawURL)
if err != nil {
return "", err
}
tx, err := db.Begin()
if err != nil {
return "", fmt.Errorf("开始关联 PDD 商品事务失败: %w", err)
}
defer tx.Rollback()
product, err := repository.GetShopeeProductByGoodsID(tx, shopeeGoodsID)
if err != nil {
return "", err
}
if product == nil {
return "", fmt.Errorf("蝦皮商品 %s 不存在", shopeeGoodsID)
}
if product.PddGoodsID != "" && product.PddGoodsID != pddGoodsID && !confirmReplace {
return "", fmt.Errorf("%w:当前是 %s,新链接解析为 %s",
ErrPddAssociationReplaceRequired, product.PddGoodsID, pddGoodsID)
}
if _, err := repository.EnsurePddProduct(tx, pddGoodsID, rawURL); err != nil {
return "", err
}
if err := repository.UpdateShopeePddLink(tx, shopeeGoodsID, pddGoodsID, rawURL); err != nil {
return "", err
}
if err := tx.Commit(); err != nil {
return "", fmt.Errorf("提交 PDD 商品关联失败: %w", err)
}
return pddGoodsID, nil
}
// CreateShopeePddCollectTask 按蝦皮商品当前关联创建采集任务,避免相信表单里的 PDD ID。
func CreateShopeePddCollectTask(db *sql.DB, shopeeGoodsID string) (CollectTaskResult, error) {
product, err := repository.GetShopeeProductByGoodsID(db, strings.TrimSpace(shopeeGoodsID))
if err != nil {
return CollectTaskResult{}, err
}
if product == nil {
return CollectTaskResult{}, fmt.Errorf("蝦皮商品不存在")
}
if product.PddGoodsID == "" {
return CollectTaskResult{}, fmt.Errorf("请先关联 PDD 商品")
}
return CreatePddCollectTasks(db, []string{product.PddGoodsID})
}
// CreateShopeePddCollectTaskForUser 为网页登录入口记录任务创建人。
func CreateShopeePddCollectTaskForUser(db *sql.DB, actor *model.User, shopeeGoodsID string) (CollectTaskResult, error) {
product, err := repository.GetShopeeProductByGoodsID(db, strings.TrimSpace(shopeeGoodsID))
if err != nil {
return CollectTaskResult{}, err
}
if product == nil {
return CollectTaskResult{}, fmt.Errorf("蝦皮商品不存在")
}
if product.PddGoodsID == "" {
return CollectTaskResult{}, fmt.Errorf("请先关联 PDD 商品")
}
return CreatePddCollectTasksForUser(db, actor, []string{product.PddGoodsID}, "")
}
// AssociateSybPdd 从顺运宝明细解析出可信的蝦皮商品,再复用统一关联逻辑。
func AssociateSybPdd(db *sql.DB, sybID, rawURL string, confirmReplace bool) (string, error) {
context, err := repository.GetSybOrderContext(db, strings.TrimSpace(sybID))
if err != nil {
return "", err
}
if context == nil {
return "", fmt.Errorf("顺运宝明细不存在")
}
if context.Order.ShopeeGoodsID == "" {
return "", fmt.Errorf("顺运宝未提供蝦皮商品 ID")
}
if context.Order.SpecKey == "" {
return "", fmt.Errorf("顺运宝未提供规格,不能进入采购流程")
}
normalizedURL, err := normalizeSybPddReference(rawURL)
if err != nil {
return "", err
}
return AssociateShopeePdd(db, context.Order.ShopeeGoodsID, normalizedURL, confirmReplace)
}
// CreateSybPddCollectTask 按顺运宝明细当前关联创建采集任务。
func CreateSybPddCollectTask(db *sql.DB, sybID string) (CollectTaskResult, error) {
context, err := repository.GetSybOrderContext(db, strings.TrimSpace(sybID))
if err != nil {
return CollectTaskResult{}, err
}
if context == nil {
return CollectTaskResult{}, fmt.Errorf("顺运宝明细不存在")
}
return CreateShopeePddCollectTask(db, context.Order.ShopeeGoodsID)
}
// CreateSybPddCollectTaskForUser 为网页登录入口记录任务创建人。
func CreateSybPddCollectTaskForUser(db *sql.DB, actor *model.User, sybID string) (CollectTaskResult, error) {
context, err := repository.GetSybOrderContext(db, strings.TrimSpace(sybID))
if err != nil {
return CollectTaskResult{}, err
}
if context == nil {
return CollectTaskResult{}, fmt.Errorf("顺运宝明细不存在")
}
return CreateShopeePddCollectTaskForUser(db, actor, context.Order.ShopeeGoodsID)
}