优化接单模板匹配
This commit is contained in:
@@ -0,0 +1,8 @@
|
|||||||
|
-- 035_worker_product_match_sku_mode.sql —— SKU 系列匹配方式。
|
||||||
|
|
||||||
|
ALTER TABLE work_product_rule_mappings
|
||||||
|
ADD COLUMN IF NOT EXISTS sku_match_mode TEXT NOT NULL DEFAULT 'fuzzy'
|
||||||
|
CHECK (sku_match_mode IN ('fuzzy', 'exact'));
|
||||||
|
|
||||||
|
COMMENT ON COLUMN work_product_rule_mappings.sku_match_mode
|
||||||
|
IS 'SKU 数量系列匹配方式:fuzzy 兼容密钥/秘钥与附加文案,exact 仅完整系列名匹配';
|
||||||
@@ -49,6 +49,7 @@ export async function upsertWorkProductRuleMapping(input: {
|
|||||||
itemTitle: string
|
itemTitle: string
|
||||||
relSkuId: string
|
relSkuId: string
|
||||||
skuNick: string
|
skuNick: string
|
||||||
|
skuMatchMode: 'fuzzy' | 'exact'
|
||||||
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
now: string
|
now: string
|
||||||
@@ -64,9 +65,10 @@ export async function upsertWorkProductRuleMapping(input: {
|
|||||||
item_title = $5,
|
item_title = $5,
|
||||||
rel_sku_id = $6,
|
rel_sku_id = $6,
|
||||||
sku_nick = $7,
|
sku_nick = $7,
|
||||||
mapping_type = $8,
|
sku_match_mode = $8,
|
||||||
enabled = $9,
|
mapping_type = $9,
|
||||||
updated_at = $10
|
enabled = $10,
|
||||||
|
updated_at = $11
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
RETURNING *
|
RETURNING *
|
||||||
`,
|
`,
|
||||||
@@ -78,6 +80,7 @@ export async function upsertWorkProductRuleMapping(input: {
|
|||||||
input.itemTitle,
|
input.itemTitle,
|
||||||
input.relSkuId,
|
input.relSkuId,
|
||||||
input.skuNick,
|
input.skuNick,
|
||||||
|
input.skuMatchMode,
|
||||||
input.mappingType,
|
input.mappingType,
|
||||||
input.enabled,
|
input.enabled,
|
||||||
input.now,
|
input.now,
|
||||||
@@ -90,8 +93,8 @@ export async function upsertWorkProductRuleMapping(input: {
|
|||||||
`
|
`
|
||||||
INSERT INTO work_product_rule_mappings (
|
INSERT INTO work_product_rule_mappings (
|
||||||
rule_id, seller_ids_json, rel_item_id, item_title, rel_sku_id, sku_nick,
|
rule_id, seller_ids_json, rel_item_id, item_title, rel_sku_id, sku_nick,
|
||||||
mapping_type, enabled, created_at, updated_at
|
sku_match_mode, mapping_type, enabled, created_at, updated_at
|
||||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $9)
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $10)
|
||||||
RETURNING *
|
RETURNING *
|
||||||
`,
|
`,
|
||||||
[
|
[
|
||||||
@@ -101,6 +104,7 @@ export async function upsertWorkProductRuleMapping(input: {
|
|||||||
input.itemTitle,
|
input.itemTitle,
|
||||||
input.relSkuId,
|
input.relSkuId,
|
||||||
input.skuNick,
|
input.skuNick,
|
||||||
|
input.skuMatchMode,
|
||||||
input.mappingType,
|
input.mappingType,
|
||||||
input.enabled,
|
input.enabled,
|
||||||
input.now,
|
input.now,
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ export type WorkProductRuleMappingRow = {
|
|||||||
item_title: string
|
item_title: string
|
||||||
rel_sku_id: string
|
rel_sku_id: string
|
||||||
sku_nick: string
|
sku_nick: string
|
||||||
|
sku_match_mode: 'fuzzy' | 'exact' | string
|
||||||
mapping_type: 'product_default' | 'sku_exact' | 'sku_series' | string
|
mapping_type: 'product_default' | 'sku_exact' | 'sku_series' | string
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
created_at: string
|
created_at: string
|
||||||
|
|||||||
@@ -680,6 +680,16 @@ export async function getWorkProductRuleByKey(ruleKey: string): Promise<WorkProd
|
|||||||
return result.rows[0] || null
|
return result.rows[0] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getWorkProductRuleById(
|
||||||
|
ruleId: number | string,
|
||||||
|
): Promise<WorkProductRuleRow | null> {
|
||||||
|
const result = await query<WorkProductRuleRow>(
|
||||||
|
`${WORK_PRODUCT_RULE_SELECT} WHERE wpr.id = $1 LIMIT 1`,
|
||||||
|
[Number(ruleId)],
|
||||||
|
)
|
||||||
|
return result.rows[0] || null
|
||||||
|
}
|
||||||
|
|
||||||
export async function deleteWorkProductRule(
|
export async function deleteWorkProductRule(
|
||||||
ruleId: number | string,
|
ruleId: number | string,
|
||||||
): Promise<{ deleted: boolean }> {
|
): Promise<{ deleted: boolean }> {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import {
|
|||||||
getWorkerUserById,
|
getWorkerUserById,
|
||||||
getWorkOrderStatistics,
|
getWorkOrderStatistics,
|
||||||
getWorkOrderByOrderItemId,
|
getWorkOrderByOrderItemId,
|
||||||
getWorkProductRuleByKey,
|
getWorkProductRuleById,
|
||||||
listAllWorkCategories,
|
listAllWorkCategories,
|
||||||
listWorkerFinanceRequests,
|
listWorkerFinanceRequests,
|
||||||
listWorkOrders,
|
listWorkOrders,
|
||||||
@@ -306,6 +306,11 @@ export async function saveAdminWorkProductRuleMapping(payload: JsonObject = {})
|
|||||||
mappingType === 'product_default'
|
mappingType === 'product_default'
|
||||||
? ''
|
? ''
|
||||||
: String(payload.skuNick ?? payload.sku_nick ?? '').trim()
|
: String(payload.skuNick ?? payload.sku_nick ?? '').trim()
|
||||||
|
const skuMatchMode =
|
||||||
|
mappingType === 'sku_series' &&
|
||||||
|
String(payload.skuMatchMode ?? payload.sku_match_mode ?? '').trim() === 'exact'
|
||||||
|
? 'exact'
|
||||||
|
: 'fuzzy'
|
||||||
const requiresProductScope = mappingType === 'product_default'
|
const requiresProductScope = mappingType === 'product_default'
|
||||||
if (
|
if (
|
||||||
!ruleId ||
|
!ruleId ||
|
||||||
@@ -357,6 +362,7 @@ export async function saveAdminWorkProductRuleMapping(payload: JsonObject = {})
|
|||||||
itemTitle,
|
itemTitle,
|
||||||
relSkuId,
|
relSkuId,
|
||||||
skuNick,
|
skuNick,
|
||||||
|
skuMatchMode,
|
||||||
mappingType,
|
mappingType,
|
||||||
enabled: normalizeBoolean(payload.enabled, true),
|
enabled: normalizeBoolean(payload.enabled, true),
|
||||||
now: nowIso(),
|
now: nowIso(),
|
||||||
@@ -488,6 +494,7 @@ function mapWorkProductRuleMapping(mapping: WorkProductRuleMappingRow) {
|
|||||||
itemTitle: String(mapping.item_title || ''),
|
itemTitle: String(mapping.item_title || ''),
|
||||||
relSkuId: String(mapping.rel_sku_id || ''),
|
relSkuId: String(mapping.rel_sku_id || ''),
|
||||||
skuNick: String(mapping.sku_nick || ''),
|
skuNick: String(mapping.sku_nick || ''),
|
||||||
|
skuMatchMode: mapping.sku_match_mode === 'exact' ? 'exact' : 'fuzzy',
|
||||||
mappingType:
|
mappingType:
|
||||||
mapping.mapping_type === 'sku_series'
|
mapping.mapping_type === 'sku_series'
|
||||||
? 'sku_series'
|
? 'sku_series'
|
||||||
@@ -622,18 +629,16 @@ export async function saveAdminWorkProductRule(payload: JsonObject = {}) {
|
|||||||
}
|
}
|
||||||
const finalRewardAmount = sharingEnabled ? resolvedSharingTotalAmount : rewardAmount
|
const finalRewardAmount = sharingEnabled ? resolvedSharingTotalAmount : rewardAmount
|
||||||
|
|
||||||
const fields = normalizeRequirementFieldsFromPayload(payload)
|
|
||||||
const ruleKey = normalizeSlugKey(
|
|
||||||
payload.ruleKey || payload.rule_key || skuCode || productName || matchedProductName,
|
|
||||||
`rule-${Date.now()}`,
|
|
||||||
)
|
|
||||||
const ruleId = normalizeOptionalId(payload.ruleId ?? payload.rule_id)
|
const ruleId = normalizeOptionalId(payload.ruleId ?? payload.rule_id)
|
||||||
if (!ruleId && (await getWorkProductRuleByKey(ruleKey))) {
|
const existingRule = ruleId ? await getWorkProductRuleById(ruleId) : null
|
||||||
throw createHttpError('规则标识已存在,请更换后重试', {
|
if (ruleId && !existingRule) {
|
||||||
statusCode: 409,
|
throw createHttpError('接单模板不存在', {
|
||||||
errorCode: 'work_product_rule_key_taken',
|
statusCode: 404,
|
||||||
|
errorCode: 'work_product_rule_not_found',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const fields = normalizeRequirementFieldsFromPayload(payload)
|
||||||
|
const ruleKey = existingRule?.rule_key || randomId('rule-')
|
||||||
const rule = await upsertWorkProductRule({
|
const rule = await upsertWorkProductRule({
|
||||||
ruleKey,
|
ruleKey,
|
||||||
provider: String(payload.provider || '').trim(),
|
provider: String(payload.provider || '').trim(),
|
||||||
|
|||||||
@@ -760,9 +760,8 @@ function scoreWorkProductRuleMapping(
|
|||||||
if (skuNickMatched) score += 200
|
if (skuNickMatched) score += 200
|
||||||
}
|
}
|
||||||
if (mappingType === 'sku_series') {
|
if (mappingType === 'sku_series') {
|
||||||
const mappedSeries = normalizeSkuSeriesName(mapping.sku_nick)
|
const skuMatchMode = mapping.sku_match_mode === 'exact' ? 'exact' : 'fuzzy'
|
||||||
const actualSeries = normalizeSkuSeriesName(context.skuNick)
|
if (!matchSkuSeriesName(context.skuNick, mapping.sku_nick, skuMatchMode)) return null
|
||||||
if (!mappedSeries || !actualSeries || actualSeries !== mappedSeries) return null
|
|
||||||
score += 200
|
score += 200
|
||||||
}
|
}
|
||||||
return { rule, score, mappingId: Number(mapping.id) }
|
return { rule, score, mappingId: Number(mapping.id) }
|
||||||
@@ -917,6 +916,21 @@ function normalizeSkuSeriesName(value: unknown) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function matchSkuSeriesName(actual: unknown, expected: unknown, matchMode: 'fuzzy' | 'exact') {
|
||||||
|
const normalizedActual = normalizeSkuSeriesName(actual)
|
||||||
|
const normalizedExpected = normalizeSkuSeriesName(expected)
|
||||||
|
if (!normalizedActual || !normalizedExpected) return false
|
||||||
|
if (matchMode === 'exact') return normalizedActual === normalizedExpected
|
||||||
|
|
||||||
|
const fuzzyActual = normalizeFuzzySkuSeriesName(normalizedActual)
|
||||||
|
const fuzzyExpected = normalizeFuzzySkuSeriesName(normalizedExpected)
|
||||||
|
return fuzzyActual.includes(fuzzyExpected) || fuzzyExpected.includes(fuzzyActual)
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeFuzzySkuSeriesName(value: string) {
|
||||||
|
return value.replace(/秘钥|密匙|秘匙/g, '密钥')
|
||||||
|
}
|
||||||
|
|
||||||
export function normalizeWorkProductRuleMatch(payload: JsonObject): JsonObject {
|
export function normalizeWorkProductRuleMatch(payload: JsonObject): JsonObject {
|
||||||
const match =
|
const match =
|
||||||
payload.match && typeof payload.match === 'object' && !Array.isArray(payload.match)
|
payload.match && typeof payload.match === 'object' && !Array.isArray(payload.match)
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ function buildProductMapping(
|
|||||||
item_title: '和平精英密钥指挥官特种兵侦察兵密钥',
|
item_title: '和平精英密钥指挥官特种兵侦察兵密钥',
|
||||||
rel_sku_id: '',
|
rel_sku_id: '',
|
||||||
sku_nick: '',
|
sku_nick: '',
|
||||||
|
sku_match_mode: 'fuzzy',
|
||||||
mapping_type: 'product_default',
|
mapping_type: 'product_default',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
created_at: '2026-08-18T00:00:00.000Z',
|
created_at: '2026-08-18T00:00:00.000Z',
|
||||||
@@ -253,6 +254,55 @@ test('SKU 数量系列可覆盖多店铺的前后数量规格', () => {
|
|||||||
assert.equal(decision.rule?.rule_key, 'commander-series')
|
assert.equal(decision.rule?.rule_key, 'commander-series')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('SKU 数量系列默认模糊匹配密钥和秘钥', () => {
|
||||||
|
const item = buildOrderItemRow()
|
||||||
|
item.item_snapshot_json = {
|
||||||
|
kuaishouSendCode: {
|
||||||
|
...item.item_snapshot_json.kuaishouSendCode,
|
||||||
|
skuNick: '指挥官秘钥8个',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const rule = buildProductRule({ product_name: '' })
|
||||||
|
const decision = resolveMatchingProductRuleDecision(
|
||||||
|
buildOrderRow(),
|
||||||
|
item,
|
||||||
|
[rule],
|
||||||
|
[
|
||||||
|
buildProductMapping({
|
||||||
|
mapping_type: 'sku_series',
|
||||||
|
sku_nick: '指挥官密钥',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(decision.reason, 'matched')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('SKU 数量系列精确匹配不兼容密钥和秘钥', () => {
|
||||||
|
const item = buildOrderItemRow()
|
||||||
|
item.item_snapshot_json = {
|
||||||
|
kuaishouSendCode: {
|
||||||
|
...item.item_snapshot_json.kuaishouSendCode,
|
||||||
|
skuNick: '指挥官秘钥8个',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
const rule = buildProductRule({ product_name: '' })
|
||||||
|
const decision = resolveMatchingProductRuleDecision(
|
||||||
|
buildOrderRow(),
|
||||||
|
item,
|
||||||
|
[rule],
|
||||||
|
[
|
||||||
|
buildProductMapping({
|
||||||
|
mapping_type: 'sku_series',
|
||||||
|
sku_nick: '指挥官密钥',
|
||||||
|
sku_match_mode: 'exact',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.equal(decision.reason, 'unmatched')
|
||||||
|
})
|
||||||
|
|
||||||
test('商品默认映射支持用逗号填写多个关联商品 ID', () => {
|
test('商品默认映射支持用逗号填写多个关联商品 ID', () => {
|
||||||
const item = buildOrderItemRow()
|
const item = buildOrderItemRow()
|
||||||
item.item_snapshot_json = {
|
item.item_snapshot_json = {
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ type MappingFormValues = {
|
|||||||
itemTitle?: string
|
itemTitle?: string
|
||||||
relSkuId?: string
|
relSkuId?: string
|
||||||
skuNick?: string
|
skuNick?: string
|
||||||
|
skuMatchMode: 'fuzzy' | 'exact'
|
||||||
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
}
|
}
|
||||||
@@ -109,6 +110,7 @@ export default function ProductMatchPanel() {
|
|||||||
mappingForm.setFieldsValue({
|
mappingForm.setFieldsValue({
|
||||||
mappingType: 'product_default',
|
mappingType: 'product_default',
|
||||||
productScope: 'selected_products',
|
productScope: 'selected_products',
|
||||||
|
skuMatchMode: 'fuzzy',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -130,6 +132,7 @@ export default function ProductMatchPanel() {
|
|||||||
: mappingType === 'sku_series'
|
: mappingType === 'sku_series'
|
||||||
? normalizeSkuSeriesName(source.skuNick)
|
? normalizeSkuSeriesName(source.skuNick)
|
||||||
: source.skuNick,
|
: source.skuNick,
|
||||||
|
skuMatchMode: 'fuzzy',
|
||||||
mappingType,
|
mappingType,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
})
|
})
|
||||||
@@ -145,6 +148,7 @@ export default function ProductMatchPanel() {
|
|||||||
itemTitle: mapping.itemTitle,
|
itemTitle: mapping.itemTitle,
|
||||||
relSkuId: mapping.relSkuId,
|
relSkuId: mapping.relSkuId,
|
||||||
skuNick: mapping.skuNick,
|
skuNick: mapping.skuNick,
|
||||||
|
skuMatchMode: mapping.skuMatchMode,
|
||||||
mappingType: mapping.mappingType,
|
mappingType: mapping.mappingType,
|
||||||
enabled: mapping.enabled,
|
enabled: mapping.enabled,
|
||||||
})
|
})
|
||||||
@@ -224,6 +228,9 @@ export default function ProductMatchPanel() {
|
|||||||
{row.mappingType !== 'product_default' ? (
|
{row.mappingType !== 'product_default' ? (
|
||||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||||
{row.mappingType === 'sku_series' ? 'SKU 系列' : 'SKU'} {row.skuNick || row.relSkuId}
|
{row.mappingType === 'sku_series' ? 'SKU 系列' : 'SKU'} {row.skuNick || row.relSkuId}
|
||||||
|
{row.mappingType === 'sku_series'
|
||||||
|
? ` · ${row.skuMatchMode === 'exact' ? '精确' : '模糊'}`
|
||||||
|
: ''}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
@@ -405,6 +412,7 @@ export default function ProductMatchPanel() {
|
|||||||
initialValues={{
|
initialValues={{
|
||||||
mappingType: 'product_default',
|
mappingType: 'product_default',
|
||||||
productScope: 'selected_products',
|
productScope: 'selected_products',
|
||||||
|
skuMatchMode: 'fuzzy',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
}}
|
}}
|
||||||
onValuesChange={handleMappingValuesChange}
|
onValuesChange={handleMappingValuesChange}
|
||||||
@@ -492,9 +500,19 @@ export default function ProductMatchPanel() {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
) : mappingType === 'sku_series' ? (
|
) : mappingType === 'sku_series' ? (
|
||||||
|
<>
|
||||||
|
<Form.Item label="SKU 匹配方式" name="skuMatchMode">
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{ value: 'fuzzy', label: '模糊匹配(默认)' },
|
||||||
|
{ value: 'exact', label: '精确匹配' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item label="SKU 系列名称" name="skuNick">
|
<Form.Item label="SKU 系列名称" name="skuNick">
|
||||||
<Input placeholder="例如:指挥官密钥;自动覆盖 1个、10个等数量规格" />
|
<Input placeholder="例如:指挥官密钥;自动覆盖 1个、10个等数量规格" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ export default function ProductRulesPanel() {
|
|||||||
function editRule(rule: WorkProductRule) {
|
function editRule(rule: WorkProductRule) {
|
||||||
setEditingRule(rule)
|
setEditingRule(rule)
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
ruleKey: rule.ruleKey,
|
|
||||||
provider: rule.provider,
|
provider: rule.provider,
|
||||||
platform: rule.platform,
|
platform: rule.platform,
|
||||||
shopId: rule.shopId,
|
shopId: rule.shopId,
|
||||||
@@ -122,7 +121,7 @@ export default function ProductRulesPanel() {
|
|||||||
|
|
||||||
async function saveRule(values: {
|
async function saveRule(values: {
|
||||||
ruleId?: number
|
ruleId?: number
|
||||||
ruleKey: string
|
ruleKey?: string
|
||||||
provider?: string
|
provider?: string
|
||||||
platform?: string
|
platform?: string
|
||||||
shopId?: string
|
shopId?: string
|
||||||
@@ -159,6 +158,7 @@ export default function ProductRulesPanel() {
|
|||||||
await saveAdminWorkProductRule({
|
await saveAdminWorkProductRule({
|
||||||
...payload,
|
...payload,
|
||||||
ruleId: editingRule?.ruleId,
|
ruleId: editingRule?.ruleId,
|
||||||
|
ruleKey: editingRule?.ruleKey || '',
|
||||||
match: editingRule?.match,
|
match: editingRule?.match,
|
||||||
unitPrice: unitMode ? Number(values.unitPrice || 0) : 0,
|
unitPrice: unitMode ? Number(values.unitPrice || 0) : 0,
|
||||||
})
|
})
|
||||||
@@ -472,14 +472,6 @@ export default function ProductRulesPanel() {
|
|||||||
onFinish={saveRule}
|
onFinish={saveRule}
|
||||||
>
|
>
|
||||||
<div className="rule-form-grid-2col">
|
<div className="rule-form-grid-2col">
|
||||||
<Form.Item
|
|
||||||
label="规则标识"
|
|
||||||
name="ruleKey"
|
|
||||||
rules={[{ required: true, message: '请输入规则标识' }]}
|
|
||||||
>
|
|
||||||
<Input placeholder="skin-training" disabled={Boolean(editingRule)} />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item label="来源" name="provider">
|
<Form.Item label="来源" name="provider">
|
||||||
<Input placeholder="如 91kaquan" />
|
<Input placeholder="如 91kaquan" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ export function saveAdminWorkProductRuleMapping(payload: {
|
|||||||
itemTitle?: string
|
itemTitle?: string
|
||||||
relSkuId?: string
|
relSkuId?: string
|
||||||
skuNick?: string
|
skuNick?: string
|
||||||
|
skuMatchMode?: 'fuzzy' | 'exact'
|
||||||
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
||||||
enabled?: boolean
|
enabled?: boolean
|
||||||
}) {
|
}) {
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ export type WorkProductRuleMapping = {
|
|||||||
itemTitle: string
|
itemTitle: string
|
||||||
relSkuId: string
|
relSkuId: string
|
||||||
skuNick: string
|
skuNick: string
|
||||||
|
skuMatchMode: 'fuzzy' | 'exact'
|
||||||
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
mappingType: 'product_default' | 'sku_exact' | 'sku_series'
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
createdAt: string
|
createdAt: string
|
||||||
|
|||||||
Reference in New Issue
Block a user