package repository import ( "database/sql" "errors" "fmt" "cmautobuy/admin/model" ) // InnerCodeImportOutcome 说明幂等导入是新增还是更新。 type InnerCodeImportOutcome string const ( InnerCodeImportCreated InnerCodeImportOutcome = "created" InnerCodeImportUpdated InnerCodeImportOutcome = "updated" ) // UpsertInnerCodeImportRow 按已确认业务键写入一行。 // 必须在事务中调用;先锁定业务键,避免另一个唯一键冲突时更新错行。 func UpsertInnerCodeImportRow(tx *sql.Tx, row model.InnerCodeImportRow, now string) (InnerCodeImportOutcome, error) { var id int64 err := tx.QueryRow(` SELECT id FROM syb_inner_code_records WHERE business_date=? AND order_number=? AND stall=? AND spec_key=? FOR UPDATE`, row.BusinessDate, row.OrderNumber, row.Stall, row.SpecKey).Scan(&id) if err != nil && !errors.Is(err, sql.ErrNoRows) { return "", fmt.Errorf("锁定档口入库码业务键失败: %w", err) } if errors.Is(err, sql.ErrNoRows) { _, err = tx.Exec(` INSERT INTO syb_inner_code_records ( business_date,source_row,print_sequence,order_number,shop_name,stall, spec_raw,spec_key,inner_code,source_duplicate_count,status, created_by_user_id,created_at,updated_at ) VALUES (?,?,?,?,?,?,?,?,?,?,'pending',?,?,?)`, row.BusinessDate, row.SourceRow, nullablePositiveInt(row.PrintSequence), row.OrderNumber, nullableString(row.ShopName), row.Stall, row.SpecRaw, row.SpecKey, row.InnerCode, row.SourceDuplicateCount, row.CreatedByUserID, now, now) if err != nil { return "", fmt.Errorf("新增档口入库码记录失败: %w", err) } return InnerCodeImportCreated, nil } _, err = tx.Exec(` UPDATE syb_inner_code_records SET source_row=?,print_sequence=?,shop_name=?,spec_raw=?,inner_code=?, source_duplicate_count=?, status=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN status ELSE 'pending' END, stock_id=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN stock_id ELSE NULL END, detail_id=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN detail_id ELSE NULL END, syb_spec=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN syb_spec ELSE NULL END, syb_sku=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN syb_sku ELSE NULL END, syb_variation_sku=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN syb_variation_sku ELSE NULL END, purchase_platform=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN purchase_platform ELSE NULL END, purchase_code=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN purchase_code ELSE NULL END, remote_inner_code=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN remote_inner_code ELSE NULL END, result_message=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN result_message ELSE NULL END, planned_at=CASE WHEN status IN ('updated','already_filled','applying','needs_check') THEN planned_at ELSE NULL END, updated_at=? WHERE id=?`, row.SourceRow, nullablePositiveInt(row.PrintSequence), nullableString(row.ShopName), row.SpecRaw, row.InnerCode, row.SourceDuplicateCount, now, id) if err != nil { return "", fmt.Errorf("更新档口入库码导入记录失败: %w", err) } return InnerCodeImportUpdated, nil } func nullablePositiveInt(value int) any { if value <= 0 { return nil } return value } func nullableString(value string) any { if value == "" { return nil } return value }