fix(syb): reduce parse status to success or failed (#272)
This commit is contained in:
@@ -455,7 +455,7 @@ func (product *ShopeeProduct) BeforeCreate(_ *gorm.DB) error {
|
||||
// Parse status for a SYBProduct's productSpec extraction. See sybimport.Parse.
|
||||
const (
|
||||
SYBParseStatusSuccess = "success"
|
||||
SYBParseStatusUncertain = "uncertain"
|
||||
SYBParseStatusUncertain = "uncertain" // legacy input only; persistence normalizes to failed
|
||||
SYBParseStatusFailed = "failed"
|
||||
)
|
||||
|
||||
|
||||
@@ -84,6 +84,9 @@ func ApplyDetail(ctx context.Context, db *gorm.DB, order OrderInput, detail Deta
|
||||
}
|
||||
|
||||
parsed := Parse(detail.ProductSpec)
|
||||
if parsed.Status == models.SYBParseStatusUncertain {
|
||||
parsed.Status = models.SYBParseStatusFailed
|
||||
}
|
||||
rawJSON, err := normalizeRaw(detail.Raw)
|
||||
if err != nil {
|
||||
return ApplyResult{}, err
|
||||
|
||||
@@ -77,6 +77,9 @@ func Reparse(ctx context.Context, db *gorm.DB, sybProductID uint64, force bool)
|
||||
return fmt.Errorf("syb product %d: stored raw json is not decodable: %w", record.ID, err)
|
||||
}
|
||||
parsed := Parse(raw.ProductSpec)
|
||||
if parsed.Status == models.SYBParseStatusUncertain {
|
||||
parsed.Status = models.SYBParseStatusFailed
|
||||
}
|
||||
outcome.NewStatus = parsed.Status
|
||||
|
||||
if parsed.Color == record.TargetColor && parsed.Size == record.TargetSize && parsed.Status == record.ParseStatus {
|
||||
|
||||
@@ -42,6 +42,9 @@ func RepairReversedSpecRoles(ctx context.Context, db *gorm.DB) (SpecRoleRepairRe
|
||||
continue
|
||||
}
|
||||
parsed := Parse(raw.ProductSpec)
|
||||
if parsed.Status == models.SYBParseStatusUncertain {
|
||||
parsed.Status = models.SYBParseStatusFailed
|
||||
}
|
||||
if parsed.Status == models.SYBParseStatusFailed || parsed.Color == record.TargetColor ||
|
||||
parsed.Color != record.TargetSize || parsed.Size != record.TargetColor {
|
||||
continue
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package version_local
|
||||
|
||||
import (
|
||||
"go-admin/app/goauto/models"
|
||||
"go-admin/cmd/migrate/migration"
|
||||
common "go-admin/common/models"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func init() { migration.Migrate.SetVersion("1789200000000", migrateSYBParseStatusBinary) }
|
||||
|
||||
// migrateSYBParseStatusBinary folds legacy uncertain rows into failed and
|
||||
// narrows the check constraint to the two supported states (#272).
|
||||
func migrateSYBParseStatusBinary(db *gorm.DB, version string) error {
|
||||
if err := db.Model(&models.SYBProduct{}).Where("parse_status = ?", "uncertain").Update("parse_status", models.SYBParseStatusFailed).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if db.Dialector.Name() == "mysql" {
|
||||
if err := db.Exec("ALTER TABLE syb_product DROP CHECK ck_syb_product_parse_status").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := db.Exec("ALTER TABLE syb_product ADD CONSTRAINT ck_syb_product_parse_status CHECK (parse_status IN ('success','failed'))").Error; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return db.Create(&common.Migration{Version: version}).Error
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
</el-autocomplete>
|
||||
</el-form-item>
|
||||
<el-form-item label="订单号"><el-input v-model="query.orderCodesText" type="textarea" :autosize="{ minRows: 1, maxRows: 4 }" resize="none" class="order-codes-input" placeholder="每行一个订单号,最多 100 个" @keydown.ctrl.enter.prevent="search" /></el-form-item>
|
||||
<el-form-item label="解析状态"><el-select v-model="query.parseStatus" clearable placeholder="全部" style="width: 110px"><el-option label="成功" value="success" /><el-option label="存疑" value="uncertain" /><el-option label="失败" value="failed" /></el-select></el-form-item>
|
||||
<el-form-item label="解析状态"><el-select v-model="query.parseStatus" clearable placeholder="全部" style="width: 110px"><el-option label="成功" value="success" /><el-option label="失败" value="failed" /></el-select></el-form-item>
|
||||
<el-form-item label="处理阶段"><el-select v-model="query.processStage" clearable placeholder="全部" style="width: 132px"><el-option v-for="item in processStageOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item>
|
||||
<el-form-item class="toolbar-actions"><el-button type="primary" :icon="Search" @click="search">查询</el-button><el-button :icon="RefreshLeft" @click="reset">重置</el-button><el-tooltip v-if="canPurchase" :content="aiMatchButtonReason" :disabled="!aiMatchButtonReason" placement="top"><span class="action-button-wrap"><el-button :loading="specMatchLoading" :disabled="purchaseReadinessLoading || specMatchLoading || aiMatchCandidates.length === 0" @click="runBatchSpecMatch">AI 匹配<span class="action-count">{{ aiMatchCandidates.length }}</span></el-button></span></el-tooltip><el-button v-if="canPurchase" type="primary" :loading="purchaseReadinessLoading" :disabled="purchaseReadinessLoading || specMatchLoading || purchaseCandidates.length === 0" @click="openPurchaseBatch">创建采购<span class="action-count action-count-primary">{{ purchaseCandidates.length }}</span></el-button><el-button v-if="canPurchase" type="primary" :loading="purchaseReadinessLoading" :disabled="purchaseReadinessLoading || specMatchLoading || collectionCandidates.length === 0" @click="openCollectionBatch">创建采集<span class="action-count action-count-primary">{{ collectionCandidates.length }}</span></el-button></el-form-item>
|
||||
</el-form>
|
||||
@@ -160,8 +160,8 @@
|
||||
<el-drawer v-model="detail.open" title="SYB 商品明细详情" size="960px">
|
||||
<div v-loading="detail.loading" class="drawer-body">
|
||||
<template v-if="detail.item">
|
||||
<el-alert v-if="detail.item.parseStatus !== 'success'" :title="detail.item.parseStatus === 'failed' ? '解析失败:' + detail.item.parseNote : '解析存疑:' + detail.item.parseNote" :type="detail.item.parseStatus === 'failed' ? 'error' : 'warning'" :closable="false" show-icon class="notice" />
|
||||
<p class="muted purchase-note">存疑不阻断采购:采购时由服务端 AI 拿 SYB 原始颜色尺码匹配 PDD 实际规格,不经过虾皮档案映射表。人工修正可提高匹配准确度,但不是采购的前置条件;失败必须处理,否则采购会明确失败。</p>
|
||||
<el-alert v-if="detail.item.parseStatus !== 'success'" :title="'解析失败:' + detail.item.parseNote" type="error" :closable="false" show-icon class="notice" />
|
||||
<p class="muted purchase-note">解析失败时由服务端 AI 根据 SYB 原始颜色尺码匹配 PDD 实际规格;解析失败不会自动写入虾皮档案映射。</p>
|
||||
|
||||
<div class="split">
|
||||
<div class="split-col">
|
||||
@@ -358,7 +358,7 @@ export default {
|
||||
}
|
||||
},
|
||||
priceText(row) { if (row.unitPriceCent === null || row.unitPriceCent === undefined) return '—'; return `¥${(row.unitPriceCent / 100).toFixed(2)}` },
|
||||
parseMeta(status) { return { success: { label: '成功', type: 'success' }, uncertain: { label: '存疑', type: 'warning' }, failed: { label: '失败', type: 'danger' }}[status] || { label: status || '-', type: 'info' } },
|
||||
parseMeta(status) { return { success: { label: '成功', type: 'success' }, failed: { label: '失败', type: 'danger' }}[status] || { label: status || '-', type: 'info' } },
|
||||
openShopeeDetail(shopeeProductId, targetColor = '', action = '') {
|
||||
if (!shopeeProductId) { ElMessage.warning('该明细尚未关联虾皮商品'); return }
|
||||
this.shopeeDetail = { open: true, productId: Number(shopeeProductId), targetColor: String(targetColor || '').trim(), action: String(action || '') }
|
||||
|
||||
Reference in New Issue
Block a user