中性化库存凭据类型

This commit is contained in:
yml
2026-05-25 22:11:30 +08:00
parent 8ce16d9a36
commit 2103416c7b
14 changed files with 42 additions and 28 deletions
@@ -0,0 +1,16 @@
UPDATE inventory_items
SET credential_type = 'claim_code'
WHERE credential_type = 'tencent_code';
UPDATE fulfillment_profile_requirements
SET credential_type = 'claim_code'
WHERE credential_type = 'tencent_code';
UPDATE fulfillment_tasks
SET context_json = jsonb_set(
context_json,
'{primaryRequirement,credentialType}',
'"claim_code"'::jsonb,
false
)
WHERE context_json #>> '{primaryRequirement,credentialType}' = 'tencent_code';
@@ -46,7 +46,7 @@ const INVENTORY_ITEM_SELECT = `
export async function findFirstAvailableInventoryItemBySkuCode( export async function findFirstAvailableInventoryItemBySkuCode(
skuCode: string, skuCode: string,
credentialType = 'tencent_code', credentialType = 'claim_code',
inventoryGroupCodes: InventoryGroupCodesInput = null, inventoryGroupCodes: InventoryGroupCodesInput = null,
): Promise<InventoryItemRow | null> { ): Promise<InventoryItemRow | null> {
const normalizedInventoryGroupCodes = normalizeInventoryGroupCodes(inventoryGroupCodes) const normalizedInventoryGroupCodes = normalizeInventoryGroupCodes(inventoryGroupCodes)
@@ -360,7 +360,7 @@ export async function createInventoryItems(rows: InventoryCreateItemInput[]): Pr
[ [
row.batchNo || '', row.batchNo || '',
row.skuCode, row.skuCode,
row.credentialType || 'tencent_code', row.credentialType || 'claim_code',
inventoryGroupCode, inventoryGroupCode,
displayValue, displayValue,
payloadJson, payloadJson,
@@ -16,7 +16,7 @@ export async function mapAdminInventoryListItem(item: InventoryItemRow): Promise
inventoryItemId: item.id, inventoryItemId: item.id,
skuCode: item.sku_code, skuCode: item.sku_code,
batchNo: item.batch_no, batchNo: item.batch_no,
credentialType: item.credential_type || 'tencent_code', credentialType: item.credential_type || 'claim_code',
inventoryGroupCode: String(item.inventory_group_code || '').trim(), inventoryGroupCode: String(item.inventory_group_code || '').trim(),
displayValue: item.display_value, displayValue: item.display_value,
status: item.status, status: item.status,
@@ -258,7 +258,7 @@ export async function getAdminTaskDetail(
inventoryItemId: inventoryItem.id, inventoryItemId: inventoryItem.id,
skuCode: inventoryItem.sku_code, skuCode: inventoryItem.sku_code,
batchNo: inventoryItem.batch_no, batchNo: inventoryItem.batch_no,
credentialType: inventoryItem.credential_type || 'tencent_code', credentialType: inventoryItem.credential_type || 'claim_code',
displayValue: viewerContext.canViewSensitiveTaskData ? inventoryItem.display_value : '', displayValue: viewerContext.canViewSensitiveTaskData ? inventoryItem.display_value : '',
status: inventoryItem.status, status: inventoryItem.status,
} }
@@ -367,7 +367,7 @@ export async function getAdminInventorySkuSuggestions(
return { return {
items: items.map((item) => ({ items: items.map((item) => ({
skuCode: String(item.sku_code || '').trim(), skuCode: String(item.sku_code || '').trim(),
credentialType: String(item.credential_type || '').trim() || 'tencent_code', credentialType: String(item.credential_type || '').trim() || 'claim_code',
inventoryGroupCode: String(item.inventory_group_code || '').trim(), inventoryGroupCode: String(item.inventory_group_code || '').trim(),
totalCount: Number(item.total_count || 0), totalCount: Number(item.total_count || 0),
availableCount: Number(item.available_count || 0), availableCount: Number(item.available_count || 0),
@@ -221,7 +221,7 @@ export function mapAdminTaskInventoryBinding(
inventoryStatus: String(binding.inventory_item_status || '').trim(), inventoryStatus: String(binding.inventory_item_status || '').trim(),
skuCode: String(binding.sku_code || '').trim(), skuCode: String(binding.sku_code || '').trim(),
batchNo: String(binding.batch_no || '').trim(), batchNo: String(binding.batch_no || '').trim(),
credentialType: String(binding.credential_type || 'tencent_code').trim() || 'tencent_code', credentialType: String(binding.credential_type || 'claim_code').trim() || 'claim_code',
displayValue: viewerContext.canViewSensitiveTaskData ? String(binding.display_value || '').trim() : '', displayValue: viewerContext.canViewSensitiveTaskData ? String(binding.display_value || '').trim() : '',
invalidReason: String(binding.invalid_reason || '').trim(), invalidReason: String(binding.invalid_reason || '').trim(),
consumedAt: binding.consumed_at || null, consumedAt: binding.consumed_at || null,
@@ -35,7 +35,7 @@ export async function createAdminInventoryItem(
const skuCode = String(payload.skuCode || '').trim() const skuCode = String(payload.skuCode || '').trim()
const displayValue = String(payload.displayValue || '').trim() const displayValue = String(payload.displayValue || '').trim()
const batchNo = String(payload.batchNo || '').trim() const batchNo = String(payload.batchNo || '').trim()
const credentialType = String(payload.credentialType || 'tencent_code').trim() || 'tencent_code' const credentialType = String(payload.credentialType || 'claim_code').trim() || 'claim_code'
const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim() const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim()
if (!skuCode || !displayValue) { if (!skuCode || !displayValue) {
@@ -160,7 +160,7 @@ function normalizeInventoryImportRows(payload: AdminInventoryImportInput): Norma
const skuCode = String(row?.skuCode || '').trim() const skuCode = String(row?.skuCode || '').trim()
const displayValue = String(row?.displayValue || '').trim() const displayValue = String(row?.displayValue || '').trim()
const batchNo = String(row?.batchNo || '').trim() const batchNo = String(row?.batchNo || '').trim()
const credentialType = String(row?.credentialType || payload.credentialType || 'tencent_code').trim() || 'tencent_code' const credentialType = String(row?.credentialType || payload.credentialType || 'claim_code').trim() || 'claim_code'
const inventoryGroupCode = String(row?.inventoryGroupCode || payload.inventoryGroupCode || '').trim() const inventoryGroupCode = String(row?.inventoryGroupCode || payload.inventoryGroupCode || '').trim()
if (!skuCode || !displayValue) { if (!skuCode || !displayValue) {
@@ -174,7 +174,7 @@ function normalizeInventoryImportRows(payload: AdminInventoryImportInput): Norma
if (bulkCodes.length > 0) { if (bulkCodes.length > 0) {
const skuCode = String(payload.skuCode || '').trim() const skuCode = String(payload.skuCode || '').trim()
const batchNo = String(payload.batchNo || '').trim() const batchNo = String(payload.batchNo || '').trim()
const credentialType = String(payload.credentialType || 'tencent_code').trim() || 'tencent_code' const credentialType = String(payload.credentialType || 'claim_code').trim() || 'claim_code'
const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim() const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim()
if (!skuCode) { if (!skuCode) {
@@ -201,7 +201,7 @@ function dedupeRows(rows: NormalizedInventoryImportRow[]): NormalizedInventoryIm
const output: NormalizedInventoryImportRow[] = [] const output: NormalizedInventoryImportRow[] = []
for (const row of rows) { for (const row of rows) {
const key = `${row.skuCode}::${row.credentialType || 'tencent_code'}::${row.displayValue}` const key = `${row.skuCode}::${row.credentialType || 'claim_code'}::${row.displayValue}`
if (seen.has(key)) { if (seen.has(key)) {
continue continue
} }
@@ -37,7 +37,7 @@ function createTaskFixture(patch = {}) {
inventorySkuCode: 'dnf-cdk-a', inventorySkuCode: 'dnf-cdk-a',
primaryRequirement: { primaryRequirement: {
roleKey: 'primary_code', roleKey: 'primary_code',
credentialType: 'tencent_code', credentialType: 'claim_code',
}, },
}), }),
...patch, ...patch,
@@ -65,7 +65,7 @@ test('syncDeliveryTasksForOrderWithDeps moves paid claim task to waiting invento
{ {
skuCode: 'dnf-cdk-a', skuCode: 'dnf-cdk-a',
taskId: 30, taskId: 30,
credentialType: 'tencent_code', credentialType: 'claim_code',
roleKey: 'primary_code', roleKey: 'primary_code',
}, },
]) ])
@@ -201,7 +201,7 @@ export async function syncDeliveryTasksForOrderWithDeps(
primaryRequirement: primaryRequirement primaryRequirement: primaryRequirement
? { ? {
roleKey: String(primaryRequirement.role_key || primaryRequirement.roleKey || 'primary_code'), roleKey: String(primaryRequirement.role_key || primaryRequirement.roleKey || 'primary_code'),
credentialType: String(primaryRequirement.credential_type || primaryRequirement.credentialType || 'tencent_code'), credentialType: String(primaryRequirement.credential_type || primaryRequirement.credentialType || 'claim_code'),
} }
: null, : null,
kuaishouCloudFulfillment: isKuaishouCloudExecutor(profile.executor_key) kuaishouCloudFulfillment: isKuaishouCloudExecutor(profile.executor_key)
@@ -41,7 +41,7 @@ test('reserveInventoryForTaskWithDeps reserves first available inventory item wi
) )
assert.deepEqual(calls, [ assert.deepEqual(calls, [
['find', 'dnf-cdk-a', 'tencent_code', null], ['find', 'dnf-cdk-a', 'claim_code', null],
['assign', 321, 88, '2026-04-14T12:00:00.000Z', 'primary_code'], ['assign', 321, 88, '2026-04-14T12:00:00.000Z', 'primary_code'],
]) ])
assert.equal(result?.id, 321) assert.equal(result?.id, 321)
@@ -64,7 +64,7 @@ test('reserveInventoryForTaskWithDeps forwards inventory group filters', async (
) )
assert.deepEqual(calls, [ assert.deepEqual(calls, [
['find', 'dnf-cdk-a', 'tencent_code', ['A组', 'B组']], ['find', 'dnf-cdk-a', 'claim_code', ['A组', 'B组']],
]) ])
}) })
@@ -42,7 +42,7 @@ type ReleaseReservedInventoryItemsDeps = {
export async function reserveInventoryForTask({ export async function reserveInventoryForTask({
skuCode, skuCode,
taskId, taskId,
credentialType = 'tencent_code', credentialType = 'claim_code',
roleKey = 'primary_code', roleKey = 'primary_code',
inventoryGroupCodes = null, inventoryGroupCodes = null,
}: ReserveInventoryForTaskInput): Promise<InventoryItemRow | null> { }: ReserveInventoryForTaskInput): Promise<InventoryItemRow | null> {
@@ -60,7 +60,7 @@ export async function reserveInventoryForTaskWithDeps(
{ {
skuCode, skuCode,
taskId, taskId,
credentialType = 'tencent_code', credentialType = 'claim_code',
roleKey = 'primary_code', roleKey = 'primary_code',
inventoryGroupCodes = null, inventoryGroupCodes = null,
}: ReserveInventoryForTaskInput, }: ReserveInventoryForTaskInput,
-2
View File
@@ -25,7 +25,6 @@ declare module 'vue' {
ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
ElDescriptions: typeof import('element-plus/es')['ElDescriptions'] ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem'] ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDropdown: typeof import('element-plus/es')['ElDropdown'] ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
@@ -33,7 +32,6 @@ declare module 'vue' {
ElForm: typeof import('element-plus/es')['ElForm'] ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon'] ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenu: typeof import('element-plus/es')['ElMenu']
+1 -1
View File
@@ -34,7 +34,7 @@ export const adminInventoryStatusOptions = [
export const adminInventoryCredentialTypeOptions = [ export const adminInventoryCredentialTypeOptions = [
{ label: '全部凭据类型', value: '' }, { label: '全部凭据类型', value: '' },
{ label: '兑换码(领取链路)', value: 'tencent_code' }, { label: '兑换码(领取链路)', value: 'claim_code' },
{ label: '卡号卡密', value: 'card_password' }, { label: '卡号卡密', value: 'card_password' },
{ label: '账号密码', value: 'account_password' }, { label: '账号密码', value: 'account_password' },
{ label: '激活链接', value: 'activation_link' }, { label: '激活链接', value: 'activation_link' },
@@ -142,7 +142,7 @@ function handleSkuSuggestionSelect(item: Record<string, unknown>) {
class="bulk-input" class="bulk-input"
/> />
<p class="helper-text helper-text--spaced"> <p class="helper-text helper-text--spaced">
示例sjz_hdl_test01|tencent_code|sjz-20260412|A组|DJQFf7HgXXXXXXXXXX 示例sjz_hdl_test01|claim_code|sjz-20260412|A组|DJQFf7HgXXXXXXXXXX
</p> </p>
<div class="action-row"> <div class="action-row">
@@ -34,7 +34,7 @@ export function useAdminInventory() {
const filterInventoryGroupCode = ref('') const filterInventoryGroupCode = ref('')
const entrySkuCode = ref('') const entrySkuCode = ref('')
const entryCredentialType = ref('tencent_code') const entryCredentialType = ref('claim_code')
const entryBatchNo = ref('') const entryBatchNo = ref('')
const entryInventoryGroupCode = ref('') const entryInventoryGroupCode = ref('')
const singleDisplayValue = ref('') const singleDisplayValue = ref('')
@@ -75,10 +75,10 @@ export function useAdminInventory() {
>() >()
for (const item of items.value) { for (const item of items.value) {
const key = `${item.skuCode}::${item.credentialType || 'tencent_code'}::${item.inventoryGroupCode || ''}` const key = `${item.skuCode}::${item.credentialType || 'claim_code'}::${item.inventoryGroupCode || ''}`
const current = groupMap.get(key) || { const current = groupMap.get(key) || {
skuCode: item.skuCode, skuCode: item.skuCode,
credentialType: item.credentialType || 'tencent_code', credentialType: item.credentialType || 'claim_code',
inventoryGroupCode: item.inventoryGroupCode || '', inventoryGroupCode: item.inventoryGroupCode || '',
totalCount: 0, totalCount: 0,
availableCount: 0, availableCount: 0,
@@ -147,7 +147,7 @@ export function useAdminInventory() {
function getCredentialTypeHint(value: string) { function getCredentialTypeHint(value: string) {
const normalized = String(value || '').trim() const normalized = String(value || '').trim()
if (normalized === 'tencent_code') if (normalized === 'claim_code')
return '当前领取链路会优先预占这一类兑换码,快手云履约等场景可按内部 SKU 统一匹配。' return '当前领取链路会优先预占这一类兑换码,快手云履约等场景可按内部 SKU 统一匹配。'
if (normalized === 'card_password') return '适合卡号 / 卡密一体的库存项。' if (normalized === 'card_password') return '适合卡号 / 卡密一体的库存项。'
if (normalized === 'account_password') return '适合账号密码、账号令牌等组合凭据。' if (normalized === 'account_password') return '适合账号密码、账号令牌等组合凭据。'
@@ -210,7 +210,7 @@ export function useAdminInventory() {
.filter(Boolean) .filter(Boolean)
const rows: InventoryImportRow[] = [] const rows: InventoryImportRow[] = []
const defaultSkuCode = entrySkuCode.value.trim() const defaultSkuCode = entrySkuCode.value.trim()
const defaultCredentialType = entryCredentialType.value.trim() || 'tencent_code' const defaultCredentialType = entryCredentialType.value.trim() || 'claim_code'
const defaultBatchNo = entryBatchNo.value.trim() const defaultBatchNo = entryBatchNo.value.trim()
for (let index = 0; index < lines.length; index += 1) { for (let index = 0; index < lines.length; index += 1) {
@@ -272,7 +272,7 @@ export function useAdminInventory() {
skuSuggestionsLoading.value = true skuSuggestionsLoading.value = true
try { try {
const response = await fetchAdminInventorySkuSuggestions({ const response = await fetchAdminInventorySkuSuggestions({
credentialType: entryCredentialType.value.trim() || 'tencent_code', credentialType: entryCredentialType.value.trim() || 'claim_code',
inventoryGroupCode: entryInventoryGroupCode.value.trim(), inventoryGroupCode: entryInventoryGroupCode.value.trim(),
limit: 50, limit: 50,
}) })
@@ -302,7 +302,7 @@ export function useAdminInventory() {
try { try {
await createAdminInventoryItem({ await createAdminInventoryItem({
skuCode: entrySkuCode.value.trim(), skuCode: entrySkuCode.value.trim(),
credentialType: entryCredentialType.value.trim() || 'tencent_code', credentialType: entryCredentialType.value.trim() || 'claim_code',
batchNo: entryBatchNo.value.trim(), batchNo: entryBatchNo.value.trim(),
inventoryGroupCode: entryInventoryGroupCode.value.trim(), inventoryGroupCode: entryInventoryGroupCode.value.trim(),
displayValue: singleDisplayValue.value.trim(), displayValue: singleDisplayValue.value.trim(),