彻底重构-4
This commit is contained in:
+28
-29
@@ -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
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user