彻底重构-4

This commit is contained in:
yml
2026-04-09 15:51:24 +08:00
parent 60054adcc4
commit 4c395103a9
28 changed files with 1917 additions and 404 deletions
@@ -1,12 +1,11 @@
import { query, withTransaction } from '../db/client.js'
const CDK_SELECT = `
const INVENTORY_ITEM_SELECT = `
SELECT
ii.id,
ii.sku_code,
ii.batch_no,
ii.credential_type,
ii.display_value AS cdk_code,
ii.display_value,
ii.status,
ii.invalid_reason,
@@ -27,9 +26,9 @@ const CDK_SELECT = `
LEFT JOIN fulfillment_tasks ft ON ft.id = tib.task_id
`
export async function findFirstAvailableCdkBySkuCode(skuCode, credentialType = 'tencent_code') {
export async function findFirstAvailableInventoryItemBySkuCode(skuCode, credentialType = 'tencent_code') {
const result = await query(
`${CDK_SELECT}
`${INVENTORY_ITEM_SELECT}
WHERE ii.sku_code = $1 AND ii.credential_type = $2 AND ii.status = 'available'
ORDER BY ii.id ASC
LIMIT 1`,
@@ -39,7 +38,7 @@ export async function findFirstAvailableCdkBySkuCode(skuCode, credentialType = '
return result.rows[0] || null
}
export async function assignReservedCdk(cdkId, taskId, updatedAt, roleKey = 'primary_code') {
export async function assignReservedInventoryItem(inventoryItemId, taskId, updatedAt, roleKey = 'primary_code') {
return withTransaction(async (client) => {
const inventoryResult = await client.query(
`
@@ -48,11 +47,11 @@ export async function assignReservedCdk(cdkId, taskId, updatedAt, roleKey = 'pri
WHERE id = $2 AND status = 'available'
RETURNING id
`,
[updatedAt, Number(cdkId)],
[updatedAt, Number(inventoryItemId)],
)
if (!inventoryResult.rows[0]) {
return getCdkById(cdkId)
return getInventoryItemById(inventoryItemId)
}
await client.query(
@@ -70,25 +69,25 @@ export async function assignReservedCdk(cdkId, taskId, updatedAt, roleKey = 'pri
ON CONFLICT (task_id, role_key, inventory_item_id) DO UPDATE
SET binding_status = 'reserved', updated_at = EXCLUDED.updated_at, released_at = NULL
`,
[Number(taskId), Number(cdkId), roleKey, updatedAt],
[Number(taskId), Number(inventoryItemId), roleKey, updatedAt],
)
return getCdkById(cdkId)
return getInventoryItemById(inventoryItemId)
})
}
export async function getCdkById(cdkId) {
export async function getInventoryItemById(inventoryItemId) {
const result = await query(
`${CDK_SELECT}
`${INVENTORY_ITEM_SELECT}
WHERE ii.id = $1
LIMIT 1`,
[Number(cdkId)],
[Number(inventoryItemId)],
)
return result.rows[0] || null
}
export async function markCdkDelivered(cdkId, deliveredAt) {
export async function markInventoryItemDelivered(inventoryItemId, deliveredAt) {
return withTransaction(async (client) => {
await client.query(
`
@@ -96,7 +95,7 @@ export async function markCdkDelivered(cdkId, deliveredAt) {
SET status = 'consumed', consumed_at = $1, updated_at = $1
WHERE id = $2
`,
[deliveredAt, Number(cdkId)],
[deliveredAt, Number(inventoryItemId)],
)
await client.query(
@@ -105,14 +104,14 @@ export async function markCdkDelivered(cdkId, deliveredAt) {
SET binding_status = 'consumed', consumed_at = $1, updated_at = $1
WHERE inventory_item_id = $2 AND binding_status = 'reserved'
`,
[deliveredAt, Number(cdkId)],
[deliveredAt, Number(inventoryItemId)],
)
return getCdkById(cdkId)
return getInventoryItemById(inventoryItemId)
})
}
export async function listCdks({
export async function listInventoryItems({
page = 1,
pageSize = 20,
skuCode = '',
@@ -147,7 +146,7 @@ export async function listCdks({
params.push(pageSize)
params.push(offset)
const itemsResult = await query(
`${CDK_SELECT}
`${INVENTORY_ITEM_SELECT}
${whereClause}
ORDER BY ii.id DESC
LIMIT $${params.length - 1} OFFSET $${params.length}`,
@@ -160,12 +159,12 @@ export async function listCdks({
}
}
export async function createCdks(rows) {
export async function createInventoryItems(rows) {
let created = 0
for (const row of rows) {
const payloadJson = JSON.stringify(row.payload || { code: row.cdkCode })
const displayValue = String(row.cdkCode || row.displayValue || '').trim()
const payloadJson = JSON.stringify(row.payload || { code: row.displayValue })
const displayValue = String(row.displayValue || '').trim()
const result = await query(
`
INSERT INTO inventory_items (
@@ -203,7 +202,7 @@ export async function createCdks(rows) {
return created
}
export async function releaseReservedCdk(cdkId, updatedAt) {
export async function releaseReservedInventoryItem(inventoryItemId, updatedAt) {
return withTransaction(async (client) => {
await client.query(
`
@@ -211,7 +210,7 @@ export async function releaseReservedCdk(cdkId, updatedAt) {
SET binding_status = 'released', released_at = $1, updated_at = $1
WHERE inventory_item_id = $2 AND binding_status = 'reserved'
`,
[updatedAt, Number(cdkId)],
[updatedAt, Number(inventoryItemId)],
)
await client.query(
@@ -220,14 +219,14 @@ export async function releaseReservedCdk(cdkId, updatedAt) {
SET status = 'available', updated_at = $1
WHERE id = $2 AND status = 'reserved'
`,
[updatedAt, Number(cdkId)],
[updatedAt, Number(inventoryItemId)],
)
return getCdkById(cdkId)
return getInventoryItemById(inventoryItemId)
})
}
export async function invalidateCdk(cdkId, invalidReason, updatedAt) {
export async function invalidateInventoryItem(inventoryItemId, invalidReason, updatedAt) {
const result = await query(
`
UPDATE inventory_items
@@ -235,12 +234,12 @@ export async function invalidateCdk(cdkId, invalidReason, updatedAt) {
WHERE id = $3 AND status = 'available'
RETURNING id
`,
[invalidReason, updatedAt, Number(cdkId)],
[invalidReason, updatedAt, Number(inventoryItemId)],
)
if (!result.rows[0]) {
return getCdkById(cdkId)
return getInventoryItemById(inventoryItemId)
}
return getCdkById(cdkId)
return getInventoryItemById(inventoryItemId)
}
@@ -0,0 +1,38 @@
import { query } from '../db/client.js'
export async function createTaskEvent(taskId, eventType, payload = {}, createdAt) {
const result = await query(
`
INSERT INTO task_events (
task_id,
event_type,
payload_json,
created_at
) VALUES ($1, $2, $3::jsonb, $4)
RETURNING *
`,
[
Number(taskId),
String(eventType || '').trim(),
JSON.stringify(payload || {}),
createdAt,
],
)
return result.rows[0] || null
}
export async function listTaskEventsByTaskId(taskId, { limit = 20 } = {}) {
const result = await query(
`
SELECT *
FROM task_events
WHERE task_id = $1
ORDER BY created_at DESC, id DESC
LIMIT $2
`,
[Number(taskId), Math.max(1, Number(limit || 20))],
)
return result.rows
}
@@ -0,0 +1,93 @@
import { query } from '../db/client.js'
export async function listTaskInventoryBindingsByTaskId(taskId) {
const result = await query(
`
SELECT
tib.id,
tib.task_id,
tib.inventory_item_id,
tib.role_key,
tib.quantity,
tib.binding_status,
tib.consumed_at,
tib.released_at,
tib.metadata_json,
tib.created_at,
tib.updated_at,
ii.sku_code,
ii.batch_no,
ii.credential_type,
ii.display_value,
ii.status AS inventory_item_status,
ii.invalid_reason
FROM task_inventory_bindings tib
JOIN inventory_items ii ON ii.id = tib.inventory_item_id
WHERE tib.task_id = $1
ORDER BY tib.id ASC
`,
[Number(taskId)],
)
return result.rows
}
export async function getTaskInventoryBindingById(bindingId) {
const result = await query(
`
SELECT
tib.id,
tib.task_id,
tib.inventory_item_id,
tib.role_key,
tib.quantity,
tib.binding_status,
tib.consumed_at,
tib.released_at,
tib.metadata_json,
tib.created_at,
tib.updated_at,
ii.sku_code,
ii.batch_no,
ii.credential_type,
ii.display_value,
ii.status AS inventory_item_status,
ii.invalid_reason
FROM task_inventory_bindings tib
JOIN inventory_items ii ON ii.id = tib.inventory_item_id
WHERE tib.id = $1
LIMIT 1
`,
[Number(bindingId)],
)
return result.rows[0] || null
}
export async function listTaskInventoryBindingSummariesByTaskIds(taskIds = []) {
const normalizedTaskIds = Array.from(new Set((Array.isArray(taskIds) ? taskIds : [])
.map((value) => Number(value))
.filter((value) => Number.isFinite(value) && value > 0)))
if (normalizedTaskIds.length === 0) {
return []
}
const result = await query(
`
SELECT
tib.task_id,
COUNT(*)::int AS total_binding_count,
COUNT(*) FILTER (WHERE tib.binding_status = 'reserved')::int AS reserved_binding_count,
COUNT(*) FILTER (WHERE tib.binding_status = 'consumed')::int AS consumed_binding_count,
COUNT(*) FILTER (WHERE tib.binding_status = 'released')::int AS released_binding_count,
ARRAY_AGG(DISTINCT tib.role_key ORDER BY tib.role_key) AS role_keys
FROM task_inventory_bindings tib
WHERE tib.task_id = ANY($1::bigint[])
GROUP BY tib.task_id
`,
[normalizedTaskIds],
)
return result.rows
}
+13 -9
View File
@@ -129,7 +129,7 @@ export async function createTask(input) {
await upsertTencentBrowserContextWithClient(client, taskId, input.tencentContext, input.createdAt)
}
return getTaskById(taskId)
return getTaskByIdWithExecutor(client.query.bind(client), taskId)
})
}
@@ -202,18 +202,12 @@ export async function updateTask(taskId, patch) {
}, patch.updated_at || current.updated_at)
}
return getTaskById(taskId)
return getTaskByIdWithExecutor(client.query.bind(client), taskId)
})
}
export async function getTaskById(taskId) {
const result = await query(
`${buildTaskSelect()}
WHERE ft.id = $1
LIMIT 1`,
[Number(taskId)],
)
return result.rows[0] || null
return getTaskByIdWithExecutor(query, taskId)
}
export async function findTaskByClaimTokenId(claimTokenId) {
@@ -399,6 +393,16 @@ async function upsertTencentBrowserContextWithClient(client, taskId, patch = {},
)
}
async function getTaskByIdWithExecutor(executor, taskId) {
const result = await executor(
`${buildTaskSelect()}
WHERE ft.id = $1
LIMIT 1`,
[Number(taskId)],
)
return result.rows[0] || null
}
function containsTencentPatch(patch = {}) {
return [
'browser_session_id',