删除库存和旧回调管理
This commit is contained in:
@@ -1,213 +0,0 @@
|
||||
import {
|
||||
createInventoryItems,
|
||||
invalidateInventoryItem,
|
||||
listInventoryItems,
|
||||
releaseReservedInventoryItem,
|
||||
} from '../../../repositories/inventory-repo.js'
|
||||
import { createHttpError } from '../../../utils/http.js'
|
||||
import { nowIso } from '../../../utils/time.js'
|
||||
import {
|
||||
getRequiredInventoryItem,
|
||||
mapAdminInventoryListItem,
|
||||
} from '../admin-inventory-read-helpers.js'
|
||||
|
||||
import type { AdminEntityIdInput } from '../../../types/admin-read-inputs.js'
|
||||
import type {
|
||||
AdminInventoryCreateInput,
|
||||
AdminInventoryImportInput,
|
||||
AdminInventoryImportRowInput,
|
||||
AdminInventoryInvalidateInput,
|
||||
} from '../../../types/admin-write-inputs.js'
|
||||
import type {
|
||||
AdminInventoryImportResponse,
|
||||
AdminInventoryMutationResponse,
|
||||
} from '../../../types/admin-write-models.js'
|
||||
import type { InventoryItemRow } from '../../../types/repository-rows.js'
|
||||
|
||||
type NormalizedInventoryImportRow = Required<Pick<
|
||||
AdminInventoryImportRowInput,
|
||||
'skuCode' | 'displayValue' | 'batchNo' | 'credentialType' | 'inventoryGroupCode'
|
||||
>>
|
||||
|
||||
export async function createAdminInventoryItem(
|
||||
payload: AdminInventoryCreateInput = {},
|
||||
): Promise<AdminInventoryMutationResponse> {
|
||||
const skuCode = String(payload.skuCode || '').trim()
|
||||
const displayValue = String(payload.displayValue || '').trim()
|
||||
const batchNo = String(payload.batchNo || '').trim()
|
||||
const credentialType = String(payload.credentialType || 'claim_code').trim() || 'claim_code'
|
||||
const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim()
|
||||
|
||||
if (!skuCode || !displayValue) {
|
||||
throw createHttpError('缺少 skuCode 或 displayValue', {
|
||||
statusCode: 400,
|
||||
errorCode: 'admin_inventory_create_invalid',
|
||||
})
|
||||
}
|
||||
|
||||
const now = nowIso()
|
||||
const created = await createInventoryItems([
|
||||
{
|
||||
skuCode,
|
||||
displayValue,
|
||||
batchNo,
|
||||
credentialType,
|
||||
inventoryGroupCode,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
},
|
||||
])
|
||||
|
||||
if (created === 0) {
|
||||
throw createHttpError('库存凭据已存在,不能重复新增', {
|
||||
statusCode: 409,
|
||||
errorCode: 'admin_inventory_duplicate',
|
||||
})
|
||||
}
|
||||
|
||||
const { items } = await listInventoryItems({
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
skuCode,
|
||||
inventoryGroupCode,
|
||||
})
|
||||
const createdItem = items.find((item) => item.display_value === displayValue && item.inventory_group_code === inventoryGroupCode) || null
|
||||
|
||||
return {
|
||||
inventoryItem: createdItem ? await mapAdminInventoryListItem(createdItem) : null,
|
||||
}
|
||||
}
|
||||
|
||||
export async function importAdminInventoryItems(
|
||||
payload: AdminInventoryImportInput = {},
|
||||
): Promise<AdminInventoryImportResponse> {
|
||||
const rows = normalizeInventoryImportRows(payload)
|
||||
|
||||
if (rows.length === 0) {
|
||||
throw createHttpError('没有可导入的库存凭据数据', {
|
||||
statusCode: 400,
|
||||
errorCode: 'admin_inventory_import_empty',
|
||||
})
|
||||
}
|
||||
|
||||
const now = nowIso()
|
||||
const normalizedRows = rows.map((row) => ({
|
||||
skuCode: row.skuCode,
|
||||
batchNo: row.batchNo,
|
||||
displayValue: row.displayValue,
|
||||
credentialType: row.credentialType,
|
||||
inventoryGroupCode: row.inventoryGroupCode,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
}))
|
||||
|
||||
const created = await createInventoryItems(normalizedRows)
|
||||
|
||||
return {
|
||||
total: normalizedRows.length,
|
||||
created,
|
||||
duplicated: normalizedRows.length - created,
|
||||
}
|
||||
}
|
||||
|
||||
export async function releaseAdminInventoryItem(
|
||||
inventoryItemId: AdminEntityIdInput,
|
||||
): Promise<AdminInventoryMutationResponse> {
|
||||
const inventoryItem = await getRequiredInventoryItem(inventoryItemId)
|
||||
|
||||
if (inventoryItem.status !== 'reserved') {
|
||||
throw createHttpError('当前库存项不是预占状态,不能释放', {
|
||||
statusCode: 409,
|
||||
errorCode: 'admin_inventory_release_not_allowed',
|
||||
})
|
||||
}
|
||||
|
||||
const updated = await releaseReservedInventoryItem(inventoryItem.id, nowIso())
|
||||
|
||||
return {
|
||||
inventoryItem: await mapAdminInventoryListItem(updated as InventoryItemRow),
|
||||
}
|
||||
}
|
||||
|
||||
export async function invalidateAdminInventoryItem(
|
||||
inventoryItemId: AdminEntityIdInput,
|
||||
payload: AdminInventoryInvalidateInput = {},
|
||||
): Promise<AdminInventoryMutationResponse> {
|
||||
const inventoryItem = await getRequiredInventoryItem(inventoryItemId)
|
||||
|
||||
if (inventoryItem.status !== 'available') {
|
||||
throw createHttpError('只有可用库存项才能作废,请先释放预占', {
|
||||
statusCode: 409,
|
||||
errorCode: 'admin_inventory_invalidate_not_allowed',
|
||||
})
|
||||
}
|
||||
|
||||
const reason = String(payload.reason || '').trim() || '后台手动作废'
|
||||
const updated = await invalidateInventoryItem(inventoryItem.id, reason, nowIso())
|
||||
|
||||
return {
|
||||
inventoryItem: await mapAdminInventoryListItem(updated as InventoryItemRow),
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeInventoryImportRows(payload: AdminInventoryImportInput): NormalizedInventoryImportRow[] {
|
||||
const rows: NormalizedInventoryImportRow[] = []
|
||||
const directRows = Array.isArray(payload.rows) ? payload.rows : []
|
||||
const bulkCodes = Array.isArray(payload.codes) ? payload.codes : []
|
||||
|
||||
if (directRows.length > 0) {
|
||||
for (const row of directRows) {
|
||||
const skuCode = String(row?.skuCode || '').trim()
|
||||
const displayValue = String(row?.displayValue || '').trim()
|
||||
const batchNo = String(row?.batchNo || '').trim()
|
||||
const credentialType = String(row?.credentialType || payload.credentialType || 'claim_code').trim() || 'claim_code'
|
||||
const inventoryGroupCode = String(row?.inventoryGroupCode || payload.inventoryGroupCode || '').trim()
|
||||
|
||||
if (!skuCode || !displayValue) {
|
||||
continue
|
||||
}
|
||||
|
||||
rows.push({ skuCode, displayValue, batchNo, credentialType, inventoryGroupCode })
|
||||
}
|
||||
}
|
||||
|
||||
if (bulkCodes.length > 0) {
|
||||
const skuCode = String(payload.skuCode || '').trim()
|
||||
const batchNo = String(payload.batchNo || '').trim()
|
||||
const credentialType = String(payload.credentialType || 'claim_code').trim() || 'claim_code'
|
||||
const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim()
|
||||
|
||||
if (!skuCode) {
|
||||
throw createHttpError('批量导入时缺少 skuCode', {
|
||||
statusCode: 400,
|
||||
errorCode: 'admin_inventory_import_missing_sku',
|
||||
})
|
||||
}
|
||||
|
||||
for (const rawValue of bulkCodes) {
|
||||
const displayValue = String(rawValue || '').trim()
|
||||
if (!displayValue) {
|
||||
continue
|
||||
}
|
||||
rows.push({ skuCode, displayValue, batchNo, credentialType, inventoryGroupCode })
|
||||
}
|
||||
}
|
||||
|
||||
return dedupeRows(rows)
|
||||
}
|
||||
|
||||
function dedupeRows(rows: NormalizedInventoryImportRow[]): NormalizedInventoryImportRow[] {
|
||||
const seen = new Set<string>()
|
||||
const output: NormalizedInventoryImportRow[] = []
|
||||
|
||||
for (const row of rows) {
|
||||
const key = `${row.skuCode}::${row.credentialType || 'claim_code'}::${row.displayValue}`
|
||||
if (seen.has(key)) {
|
||||
continue
|
||||
}
|
||||
seen.add(key)
|
||||
output.push(row)
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
@@ -198,7 +198,6 @@ export async function prepareAdminTaskKuaishouCloudFulfillment(
|
||||
|
||||
const updatedTask = await updateTask(task.id, {
|
||||
task_status: 'waiting_binding',
|
||||
inventory_status: 'not_required',
|
||||
user_action_status: 'pending',
|
||||
claim_token: claimLinkState.token || task.claim_token || '',
|
||||
claim_expires_at: claimLinkState.expiredAt || getTaskClaimExpiresAt(task),
|
||||
|
||||
@@ -3,7 +3,6 @@ import {
|
||||
maskCode as maskCodeValue,
|
||||
maskPhone as maskPhoneValue,
|
||||
} from '../../../utils/masking.js'
|
||||
import { parseTaskContext } from '../admin-read-shared-helpers.js'
|
||||
|
||||
import type { TaskRow } from '../../../types/repository-rows.js'
|
||||
|
||||
@@ -26,12 +25,6 @@ export function maskCode(value: unknown): string {
|
||||
return maskCodeValue(value)
|
||||
}
|
||||
|
||||
export function resolveTaskInventoryGroupCodes(task: TaskRow): string[] | null {
|
||||
const taskContext = parseTaskContext(task)
|
||||
const inventoryGroupCode = String(taskContext?.inventoryGroupCode || '').trim()
|
||||
return inventoryGroupCode ? [inventoryGroupCode] : null
|
||||
}
|
||||
|
||||
export function isRecoverableTaskSessionCloseError(error: ErrorLike | null | undefined): boolean {
|
||||
const errorCode = String(error?.errorCode || error?.code || '').trim()
|
||||
return errorCode === 'session_not_found' || errorCode === 'session_closed'
|
||||
|
||||
Reference in New Issue
Block a user