fix: 修复顺运宝采集任务孤儿状态 (#165)
This commit is contained in:
@@ -379,8 +379,14 @@ func taskFilterClause(filter TaskFilter) (string, []any) {
|
||||
if kw := strings.TrimSpace(filter.Keyword); kw != "" {
|
||||
pattern := "%" + escapeLike(kw) + "%"
|
||||
clauses = append(clauses,
|
||||
"(t.task_id LIKE ? ESCAPE '!' OR t.order_no LIKE ? ESCAPE '!' OR t.pdd_goods_id LIKE ? ESCAPE '!')")
|
||||
args = append(args, pattern, pattern, pattern)
|
||||
`(t.task_id LIKE ? ESCAPE '!' OR t.order_no LIKE ? ESCAPE '!' OR t.pdd_goods_id LIKE ? ESCAPE '!'
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM task_syb_sources tss
|
||||
JOIN syb_orders so ON so.syb_id=tss.syb_id
|
||||
WHERE tss.task_id=t.task_id
|
||||
AND (tss.syb_id LIKE ? ESCAPE '!' OR so.order_no LIKE ? ESCAPE '!')
|
||||
))`)
|
||||
args = append(args, pattern, pattern, pattern, pattern, pattern)
|
||||
}
|
||||
if filter.VisibleUserID != "" {
|
||||
clauses = append(clauses, "t.created_by_user_id = ?")
|
||||
@@ -529,6 +535,59 @@ func DeleteTasksInScope(q Execer, taskIDs []string, visibleUserID string) (int64
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
// ListCollectTaskGoodsIDsInScope 在删除前找出受影响的 PDD 商品。
|
||||
// 调用方必须和删除使用同一事务、同一可见范围,避免越权数据影响状态回收。
|
||||
func ListCollectTaskGoodsIDsInScope(q Execer, taskIDs []string, visibleUserID string) ([]string, error) {
|
||||
if len(taskIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
placeholders := strings.TrimSuffix(strings.Repeat("?,", len(taskIDs)), ",")
|
||||
args := make([]any, 0, len(taskIDs)+1)
|
||||
for _, id := range taskIDs {
|
||||
args = append(args, id)
|
||||
}
|
||||
where := `task_id IN (` + placeholders + `) AND task_type='collect' AND pdd_goods_id IS NOT NULL`
|
||||
if visibleUserID != "" {
|
||||
where += ` AND created_by_user_id = ?`
|
||||
args = append(args, visibleUserID)
|
||||
}
|
||||
rows, err := q.Query(`SELECT DISTINCT pdd_goods_id FROM tasks WHERE `+where, args...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("查询待删除采集任务的 PDD 商品失败: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
var goodsIDs []string
|
||||
for rows.Next() {
|
||||
var goodsID string
|
||||
if err := rows.Scan(&goodsID); err != nil {
|
||||
return nil, fmt.Errorf("读取待删除采集任务的 PDD 商品失败: %w", err)
|
||||
}
|
||||
goodsIDs = append(goodsIDs, goodsID)
|
||||
}
|
||||
return goodsIDs, rows.Err()
|
||||
}
|
||||
|
||||
// ResetCollectingIfNoActiveTask 把没有有效采集任务的孤儿状态回收到待采集。
|
||||
// 条件判断和更新在一条 SQL 内完成,避免并发建任务时误覆盖 collecting。
|
||||
func ResetCollectingIfNoActiveTask(q Execer, goodsID string) (bool, error) {
|
||||
result, err := q.Exec(`UPDATE pdd_products AS pp
|
||||
SET collect_status='pending', collect_msg=NULL, updated_at=?
|
||||
WHERE pp.goods_id=? AND pp.collect_status='collecting'
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM tasks t
|
||||
WHERE t.task_type='collect' AND t.pdd_goods_id=pp.goods_id
|
||||
AND t.status IN ('pending','assigned','claimed')
|
||||
)`, model.NowISO(), goodsID)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("回收商品 %s 的孤立采集中状态失败: %w", goodsID, err)
|
||||
}
|
||||
n, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("确认商品 %s 的采集状态回收结果失败: %w", goodsID, err)
|
||||
}
|
||||
return n == 1, nil
|
||||
}
|
||||
|
||||
// InsertCollectTask 建一条不指定客户端的采集任务。
|
||||
// 保留这个入口给蝦皮、顺运宝等现有流程使用,避免它们被 PDD 页的新选项影响。
|
||||
func InsertCollectTask(q Execer, taskID, goodsID, goodsURL string) error {
|
||||
@@ -567,6 +626,31 @@ func InsertCollectTaskForClientAndUser(q Execer, taskID, goodsID, goodsURL, assi
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertCollectTaskSybSources 保存一条采集任务对应的全部顺运宝明细来源。
|
||||
// 同一个 PDD 商品可能由多条明细共同发起,来源不能压成 tasks 上的单列。
|
||||
func InsertCollectTaskSybSources(q Execer, taskID string, sybIDs []string) error {
|
||||
taskID = strings.TrimSpace(taskID)
|
||||
if taskID == "" {
|
||||
return fmt.Errorf("采集任务编号不能为空")
|
||||
}
|
||||
seen := make(map[string]struct{}, len(sybIDs))
|
||||
for _, raw := range sybIDs {
|
||||
sybID := strings.TrimSpace(raw)
|
||||
if sybID == "" {
|
||||
return fmt.Errorf("顺运宝明细编号不能为空")
|
||||
}
|
||||
if _, ok := seen[sybID]; ok {
|
||||
continue
|
||||
}
|
||||
seen[sybID] = struct{}{}
|
||||
if _, err := q.Exec(`INSERT INTO task_syb_sources(task_id,syb_id,created_at)
|
||||
VALUES(?,?,?) ON DUPLICATE KEY UPDATE created_at=created_at`, taskID, sybID, model.NowISO()); err != nil {
|
||||
return fmt.Errorf("保存采集任务 %s 的顺运宝来源 %s 失败: %w", taskID, sybID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasActivePurchaseTask 判断顺运宝明细是否已有尚未结束的采购任务。
|
||||
func HasActivePurchaseTask(q Execer, sybID string) (bool, error) {
|
||||
var count int
|
||||
|
||||
Reference in New Issue
Block a user