init
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function createAdminAuditLog(input) {
|
||||
const result = getDb().prepare(`
|
||||
INSERT INTO admin_audit_logs (
|
||||
actor_user_id,
|
||||
actor_username,
|
||||
actor_role,
|
||||
action,
|
||||
target_type,
|
||||
target_id,
|
||||
payload_json,
|
||||
created_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
input.actorUserId,
|
||||
input.actorUsername,
|
||||
input.actorRole,
|
||||
input.action,
|
||||
input.targetType,
|
||||
input.targetId,
|
||||
input.payloadJson,
|
||||
input.createdAt,
|
||||
)
|
||||
|
||||
return getAdminAuditLogById(Number(result.lastInsertRowid))
|
||||
}
|
||||
|
||||
export function getAdminAuditLogById(logId) {
|
||||
return getDb().prepare('SELECT * FROM admin_audit_logs WHERE id = ? LIMIT 1').get(logId) || null
|
||||
}
|
||||
|
||||
export function listAdminAuditLogs(query = {}) {
|
||||
const conditions = []
|
||||
const values = []
|
||||
|
||||
if (query.actorUsername) {
|
||||
conditions.push('actor_username = ?')
|
||||
values.push(query.actorUsername)
|
||||
}
|
||||
|
||||
if (query.action) {
|
||||
conditions.push('action = ?')
|
||||
values.push(query.action)
|
||||
}
|
||||
|
||||
if (query.targetType) {
|
||||
conditions.push('target_type = ?')
|
||||
values.push(query.targetType)
|
||||
}
|
||||
|
||||
if (query.dateFrom) {
|
||||
conditions.push('created_at >= ?')
|
||||
values.push(query.dateFrom)
|
||||
}
|
||||
|
||||
if (query.dateTo) {
|
||||
conditions.push('created_at <= ?')
|
||||
values.push(query.dateTo)
|
||||
}
|
||||
|
||||
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''
|
||||
const page = Number(query.page) || 1
|
||||
const pageSize = Number(query.pageSize) || 20
|
||||
const offset = (page - 1) * pageSize
|
||||
const db = getDb()
|
||||
|
||||
const items = db.prepare(`
|
||||
SELECT *
|
||||
FROM admin_audit_logs
|
||||
${whereClause}
|
||||
ORDER BY id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`).all(...values, pageSize, offset)
|
||||
|
||||
const totalRow = db.prepare(`
|
||||
SELECT COUNT(*) AS total
|
||||
FROM admin_audit_logs
|
||||
${whereClause}
|
||||
`).get(...values)
|
||||
|
||||
return {
|
||||
items,
|
||||
total: Number(totalRow?.total || 0),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function getAdminUserByUsername(username) {
|
||||
return getDb().prepare('SELECT * FROM admin_users WHERE username = ? LIMIT 1').get(username) || null
|
||||
}
|
||||
|
||||
export function getAdminUserById(userId) {
|
||||
return getDb().prepare('SELECT * FROM admin_users WHERE id = ? LIMIT 1').get(userId) || null
|
||||
}
|
||||
|
||||
export function createAdminUser(input) {
|
||||
const result = getDb().prepare(`
|
||||
INSERT INTO admin_users (
|
||||
username,
|
||||
password_hash,
|
||||
role,
|
||||
status,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
input.username,
|
||||
input.passwordHash,
|
||||
input.role,
|
||||
input.status,
|
||||
input.createdAt,
|
||||
input.updatedAt,
|
||||
)
|
||||
|
||||
return getAdminUserById(Number(result.lastInsertRowid))
|
||||
}
|
||||
|
||||
export function listAdminUsers(query = {}) {
|
||||
const conditions = []
|
||||
const values = []
|
||||
|
||||
if (query.username) {
|
||||
conditions.push('username LIKE ?')
|
||||
values.push(`%${query.username}%`)
|
||||
}
|
||||
|
||||
if (query.role) {
|
||||
conditions.push('role = ?')
|
||||
values.push(query.role)
|
||||
}
|
||||
|
||||
if (query.status) {
|
||||
conditions.push('status = ?')
|
||||
values.push(query.status)
|
||||
}
|
||||
|
||||
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : ''
|
||||
const page = Number(query.page) || 1
|
||||
const pageSize = Number(query.pageSize) || 20
|
||||
const offset = (page - 1) * pageSize
|
||||
const db = getDb()
|
||||
|
||||
const items = db.prepare(`
|
||||
SELECT *
|
||||
FROM admin_users
|
||||
${whereClause}
|
||||
ORDER BY id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`).all(...values, pageSize, offset)
|
||||
|
||||
const totalRow = db.prepare(`
|
||||
SELECT COUNT(*) AS total
|
||||
FROM admin_users
|
||||
${whereClause}
|
||||
`).get(...values)
|
||||
|
||||
return {
|
||||
items,
|
||||
total: Number(totalRow?.total || 0),
|
||||
}
|
||||
}
|
||||
|
||||
export function updateAdminUser(userId, patch = {}) {
|
||||
const current = getAdminUserById(userId)
|
||||
|
||||
if (!current) {
|
||||
return null
|
||||
}
|
||||
|
||||
const next = {
|
||||
username: Object.prototype.hasOwnProperty.call(patch, 'username') ? patch.username : current.username,
|
||||
password_hash: Object.prototype.hasOwnProperty.call(patch, 'password_hash') ? patch.password_hash : current.password_hash,
|
||||
role: Object.prototype.hasOwnProperty.call(patch, 'role') ? patch.role : current.role,
|
||||
status: Object.prototype.hasOwnProperty.call(patch, 'status') ? patch.status : current.status,
|
||||
updated_at: Object.prototype.hasOwnProperty.call(patch, 'updated_at') ? patch.updated_at : current.updated_at,
|
||||
}
|
||||
|
||||
getDb().prepare(`
|
||||
UPDATE admin_users
|
||||
SET username = ?, password_hash = ?, role = ?, status = ?, updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
next.username,
|
||||
next.password_hash,
|
||||
next.role,
|
||||
next.status,
|
||||
next.updated_at,
|
||||
userId,
|
||||
)
|
||||
|
||||
return getAdminUserById(userId)
|
||||
}
|
||||
|
||||
export function countActiveAdminUsers() {
|
||||
const row = getDb().prepare(`
|
||||
SELECT COUNT(*) AS total
|
||||
FROM admin_users
|
||||
WHERE role = 'admin' AND status = 'active'
|
||||
`).get()
|
||||
|
||||
return Number(row?.total || 0)
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function findFirstAvailableCdkBySkuCode(skuCode) {
|
||||
return getDb().prepare(`
|
||||
SELECT *
|
||||
FROM cdk_inventory
|
||||
WHERE sku_code = ? AND status = 'available'
|
||||
ORDER BY id ASC
|
||||
LIMIT 1
|
||||
`).get(skuCode) || null
|
||||
}
|
||||
|
||||
export function assignReservedCdk(cdkId, taskId, updatedAt) {
|
||||
getDb().prepare(`
|
||||
UPDATE cdk_inventory
|
||||
SET
|
||||
status = 'reserved',
|
||||
reserved_by_task_id = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ? AND status = 'available'
|
||||
`).run(taskId, updatedAt, cdkId)
|
||||
|
||||
return getCdkById(cdkId)
|
||||
}
|
||||
|
||||
export function getCdkById(cdkId) {
|
||||
return getDb().prepare('SELECT * FROM cdk_inventory WHERE id = ? LIMIT 1').get(cdkId) || null
|
||||
}
|
||||
|
||||
export function markCdkDelivered(cdkId, deliveredAt) {
|
||||
getDb().prepare(`
|
||||
UPDATE cdk_inventory
|
||||
SET
|
||||
status = 'delivered',
|
||||
delivered_at = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(deliveredAt, deliveredAt, cdkId)
|
||||
|
||||
return getCdkById(cdkId)
|
||||
}
|
||||
|
||||
export function listCdks({
|
||||
page = 1,
|
||||
pageSize = 20,
|
||||
skuCode = '',
|
||||
status = '',
|
||||
batchNo = '',
|
||||
} = {}) {
|
||||
const offset = (page - 1) * pageSize
|
||||
const filters = []
|
||||
const params = []
|
||||
|
||||
if (skuCode) {
|
||||
filters.push('sku_code = ?')
|
||||
params.push(skuCode)
|
||||
}
|
||||
|
||||
if (status) {
|
||||
filters.push('status = ?')
|
||||
params.push(status)
|
||||
}
|
||||
|
||||
if (batchNo) {
|
||||
filters.push('batch_no LIKE ?')
|
||||
params.push(`%${batchNo}%`)
|
||||
}
|
||||
|
||||
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
|
||||
const db = getDb()
|
||||
const totalRow = db.prepare(`
|
||||
SELECT COUNT(*) AS total
|
||||
FROM cdk_inventory
|
||||
${whereClause}
|
||||
`).get(...params)
|
||||
|
||||
const items = db.prepare(`
|
||||
SELECT *
|
||||
FROM cdk_inventory
|
||||
${whereClause}
|
||||
ORDER BY id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`).all(...params, pageSize, offset)
|
||||
|
||||
return {
|
||||
items,
|
||||
total: Number(totalRow?.total || 0),
|
||||
}
|
||||
}
|
||||
|
||||
export function createCdks(rows) {
|
||||
const db = getDb()
|
||||
const stmt = db.prepare(`
|
||||
INSERT OR IGNORE INTO cdk_inventory (
|
||||
batch_no,
|
||||
sku_code,
|
||||
cdk_code,
|
||||
status,
|
||||
reserved_by_task_id,
|
||||
invalid_reason,
|
||||
delivered_at,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, 'available', NULL, '', NULL, ?, ?)
|
||||
`)
|
||||
|
||||
let created = 0
|
||||
|
||||
for (const row of rows) {
|
||||
const result = stmt.run(row.batchNo, row.skuCode, row.cdkCode, row.createdAt, row.updatedAt)
|
||||
if (Number(result.changes || 0) > 0) {
|
||||
created += 1
|
||||
}
|
||||
}
|
||||
|
||||
return created
|
||||
}
|
||||
|
||||
export function releaseReservedCdk(cdkId, updatedAt) {
|
||||
getDb().prepare(`
|
||||
UPDATE cdk_inventory
|
||||
SET
|
||||
status = 'available',
|
||||
reserved_by_task_id = NULL,
|
||||
updated_at = ?
|
||||
WHERE id = ? AND status = 'reserved'
|
||||
`).run(updatedAt, cdkId)
|
||||
|
||||
return getCdkById(cdkId)
|
||||
}
|
||||
|
||||
export function invalidateCdk(cdkId, invalidReason, updatedAt) {
|
||||
getDb().prepare(`
|
||||
UPDATE cdk_inventory
|
||||
SET
|
||||
status = 'invalid',
|
||||
invalid_reason = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ? AND status = 'available'
|
||||
`).run(invalidReason, updatedAt, cdkId)
|
||||
|
||||
return getCdkById(cdkId)
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function createClaimToken(input) {
|
||||
const result = getDb().prepare(`
|
||||
INSERT INTO claim_tokens (
|
||||
task_id,
|
||||
token,
|
||||
status,
|
||||
expired_at,
|
||||
used_at,
|
||||
max_use_count,
|
||||
used_count,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
input.taskId,
|
||||
input.token,
|
||||
input.status,
|
||||
input.expiredAt,
|
||||
input.usedAt,
|
||||
input.maxUseCount,
|
||||
input.usedCount,
|
||||
input.createdAt,
|
||||
input.updatedAt,
|
||||
)
|
||||
|
||||
return getClaimTokenById(Number(result.lastInsertRowid))
|
||||
}
|
||||
|
||||
export function getClaimTokenById(tokenId) {
|
||||
return getDb().prepare('SELECT * FROM claim_tokens WHERE id = ? LIMIT 1').get(tokenId) || null
|
||||
}
|
||||
|
||||
export function findClaimTokenByToken(token) {
|
||||
return getDb().prepare('SELECT * FROM claim_tokens WHERE token = ? LIMIT 1').get(token) || null
|
||||
}
|
||||
|
||||
export function updateClaimToken(tokenId, patch) {
|
||||
const current = getClaimTokenById(tokenId)
|
||||
|
||||
if (!current) {
|
||||
return null
|
||||
}
|
||||
|
||||
const next = { ...current, ...patch }
|
||||
|
||||
getDb().prepare(`
|
||||
UPDATE claim_tokens
|
||||
SET
|
||||
status = ?,
|
||||
expired_at = ?,
|
||||
used_at = ?,
|
||||
max_use_count = ?,
|
||||
used_count = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
next.status,
|
||||
next.expired_at,
|
||||
next.used_at,
|
||||
next.max_use_count,
|
||||
next.used_count,
|
||||
next.updated_at,
|
||||
tokenId,
|
||||
)
|
||||
|
||||
return getClaimTokenById(tokenId)
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function createMessageDelivery(input) {
|
||||
const result = getDb().prepare(`
|
||||
INSERT INTO message_deliveries (
|
||||
platform,
|
||||
channel,
|
||||
order_id,
|
||||
task_id,
|
||||
platform_order_id,
|
||||
recipient_key,
|
||||
message_content,
|
||||
claim_url,
|
||||
status,
|
||||
request_url,
|
||||
request_headers_json,
|
||||
request_body_json,
|
||||
response_status,
|
||||
response_json,
|
||||
error_message,
|
||||
sent_at,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
input.platform,
|
||||
input.channel,
|
||||
input.orderId,
|
||||
input.taskId,
|
||||
input.platformOrderId,
|
||||
input.recipientKey,
|
||||
input.messageContent,
|
||||
input.claimUrl,
|
||||
input.status,
|
||||
input.requestUrl,
|
||||
input.requestHeadersJson,
|
||||
input.requestBodyJson,
|
||||
input.responseStatus,
|
||||
input.responseJson,
|
||||
input.errorMessage,
|
||||
input.sentAt,
|
||||
input.createdAt,
|
||||
input.updatedAt,
|
||||
)
|
||||
|
||||
return getMessageDeliveryById(Number(result.lastInsertRowid))
|
||||
}
|
||||
|
||||
export function getMessageDeliveryById(deliveryId) {
|
||||
return getDb().prepare('SELECT * FROM message_deliveries WHERE id = ? LIMIT 1').get(deliveryId) || null
|
||||
}
|
||||
|
||||
export function updateMessageDelivery(deliveryId, patch = {}) {
|
||||
const current = getMessageDeliveryById(deliveryId)
|
||||
|
||||
if (!current) {
|
||||
return null
|
||||
}
|
||||
|
||||
const next = { ...current, ...patch }
|
||||
|
||||
getDb().prepare(`
|
||||
UPDATE message_deliveries
|
||||
SET
|
||||
status = ?,
|
||||
request_url = ?,
|
||||
request_headers_json = ?,
|
||||
request_body_json = ?,
|
||||
response_status = ?,
|
||||
response_json = ?,
|
||||
error_message = ?,
|
||||
sent_at = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
next.status,
|
||||
next.request_url,
|
||||
next.request_headers_json,
|
||||
next.request_body_json,
|
||||
next.response_status,
|
||||
next.response_json,
|
||||
next.error_message,
|
||||
next.sent_at,
|
||||
next.updated_at,
|
||||
deliveryId,
|
||||
)
|
||||
|
||||
return getMessageDeliveryById(deliveryId)
|
||||
}
|
||||
|
||||
export function findLatestSuccessfulMessageDeliveryByTask(taskId, channel) {
|
||||
return getDb().prepare(`
|
||||
SELECT *
|
||||
FROM message_deliveries
|
||||
WHERE task_id = ? AND channel = ? AND status = 'success'
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
`).get(taskId, channel) || null
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function listOrderItemsByOrderId(orderId) {
|
||||
return getDb().prepare(`
|
||||
SELECT *
|
||||
FROM order_items
|
||||
WHERE order_id = ?
|
||||
ORDER BY id ASC
|
||||
`).all(orderId)
|
||||
}
|
||||
|
||||
export function replaceOrderItems(orderId, items) {
|
||||
const db = getDb()
|
||||
const existingItems = listOrderItemsByOrderId(orderId)
|
||||
const updateStatement = db.prepare(`
|
||||
UPDATE order_items
|
||||
SET
|
||||
sku_code = ?,
|
||||
sku_name = ?,
|
||||
quantity = ?,
|
||||
spec_json = ?,
|
||||
delivery_mode = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
`)
|
||||
const insertStatement = db.prepare(`
|
||||
INSERT INTO order_items (
|
||||
order_id,
|
||||
sku_code,
|
||||
sku_name,
|
||||
quantity,
|
||||
spec_json,
|
||||
delivery_mode,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`)
|
||||
|
||||
for (let index = 0; index < items.length; index += 1) {
|
||||
const item = items[index]
|
||||
const existingItem = existingItems[index] || null
|
||||
|
||||
if (existingItem) {
|
||||
updateStatement.run(
|
||||
item.skuCode,
|
||||
item.skuName,
|
||||
item.quantity,
|
||||
item.specJson,
|
||||
item.deliveryMode,
|
||||
item.updatedAt,
|
||||
existingItem.id,
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
insertStatement.run(
|
||||
orderId,
|
||||
item.skuCode,
|
||||
item.skuName,
|
||||
item.quantity,
|
||||
item.specJson,
|
||||
item.deliveryMode,
|
||||
item.createdAt,
|
||||
item.updatedAt,
|
||||
)
|
||||
}
|
||||
|
||||
if (existingItems.length > items.length) {
|
||||
const redundantIds = existingItems.slice(items.length).map((item) => item.id)
|
||||
const placeholders = redundantIds.map(() => '?').join(', ')
|
||||
|
||||
db.prepare(`DELETE FROM order_items WHERE order_id = ? AND id IN (${placeholders})`).run(orderId, ...redundantIds)
|
||||
}
|
||||
|
||||
return listOrderItemsByOrderId(orderId)
|
||||
}
|
||||
|
||||
export function getOrderItemById(orderItemId) {
|
||||
return getDb().prepare('SELECT * FROM order_items WHERE id = ? LIMIT 1').get(orderItemId) || null
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function findOrderByPlatformOrderId(platform, platformOrderId) {
|
||||
return getDb().prepare(`
|
||||
SELECT *
|
||||
FROM orders
|
||||
WHERE platform = ? AND platform_order_id = ?
|
||||
LIMIT 1
|
||||
`).get(platform, platformOrderId) || null
|
||||
}
|
||||
|
||||
export function createOrder(input) {
|
||||
const result = getDb().prepare(`
|
||||
INSERT INTO orders (
|
||||
platform,
|
||||
platform_order_id,
|
||||
order_status,
|
||||
pay_status,
|
||||
buyer_id,
|
||||
buyer_name,
|
||||
receiver_contact,
|
||||
total_amount,
|
||||
currency,
|
||||
raw_payload_json,
|
||||
paid_at,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
input.platform,
|
||||
input.platformOrderId,
|
||||
input.orderStatus,
|
||||
input.payStatus,
|
||||
input.buyerId,
|
||||
input.buyerName,
|
||||
input.receiverContact,
|
||||
input.totalAmount,
|
||||
input.currency,
|
||||
input.rawPayloadJson,
|
||||
input.paidAt,
|
||||
input.createdAt,
|
||||
input.updatedAt,
|
||||
)
|
||||
|
||||
return getOrderById(Number(result.lastInsertRowid))
|
||||
}
|
||||
|
||||
export function updateOrder(orderId, input) {
|
||||
getDb().prepare(`
|
||||
UPDATE orders
|
||||
SET
|
||||
order_status = ?,
|
||||
pay_status = ?,
|
||||
buyer_id = ?,
|
||||
buyer_name = ?,
|
||||
receiver_contact = ?,
|
||||
total_amount = ?,
|
||||
currency = ?,
|
||||
raw_payload_json = ?,
|
||||
paid_at = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
input.orderStatus,
|
||||
input.payStatus,
|
||||
input.buyerId,
|
||||
input.buyerName,
|
||||
input.receiverContact,
|
||||
input.totalAmount,
|
||||
input.currency,
|
||||
input.rawPayloadJson,
|
||||
input.paidAt,
|
||||
input.updatedAt,
|
||||
orderId,
|
||||
)
|
||||
|
||||
return getOrderById(orderId)
|
||||
}
|
||||
|
||||
export function getOrderById(orderId) {
|
||||
return getDb().prepare('SELECT * FROM orders WHERE id = ? LIMIT 1').get(orderId) || null
|
||||
}
|
||||
|
||||
export function listOrders({
|
||||
page = 1,
|
||||
pageSize = 20,
|
||||
platformOrderId = '',
|
||||
payStatus = '',
|
||||
skuCode = '',
|
||||
dateFrom = '',
|
||||
dateTo = '',
|
||||
} = {}) {
|
||||
const offset = (page - 1) * pageSize
|
||||
const filters = []
|
||||
const params = []
|
||||
|
||||
if (platformOrderId) {
|
||||
filters.push('o.platform_order_id LIKE ?')
|
||||
params.push(`%${platformOrderId}%`)
|
||||
}
|
||||
|
||||
if (payStatus) {
|
||||
filters.push('o.pay_status = ?')
|
||||
params.push(payStatus)
|
||||
}
|
||||
|
||||
if (skuCode) {
|
||||
filters.push('EXISTS (SELECT 1 FROM order_items oi WHERE oi.order_id = o.id AND oi.sku_code = ?)')
|
||||
params.push(skuCode)
|
||||
}
|
||||
|
||||
if (dateFrom) {
|
||||
filters.push('o.created_at >= ?')
|
||||
params.push(dateFrom)
|
||||
}
|
||||
|
||||
if (dateTo) {
|
||||
filters.push('o.created_at <= ?')
|
||||
params.push(dateTo)
|
||||
}
|
||||
|
||||
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
|
||||
const db = getDb()
|
||||
const totalRow = db.prepare(`
|
||||
SELECT COUNT(*) AS total
|
||||
FROM orders o
|
||||
${whereClause}
|
||||
`).get(...params)
|
||||
|
||||
const items = db.prepare(`
|
||||
SELECT
|
||||
o.*,
|
||||
(SELECT COUNT(*) FROM delivery_tasks dt WHERE dt.order_id = o.id) AS task_count
|
||||
FROM orders o
|
||||
${whereClause}
|
||||
ORDER BY o.id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`).all(...params, pageSize, offset)
|
||||
|
||||
return {
|
||||
items,
|
||||
total: Number(totalRow?.total || 0),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function listTasksByOrderId(orderId) {
|
||||
return getDb().prepare(`
|
||||
SELECT *
|
||||
FROM delivery_tasks
|
||||
WHERE order_id = ?
|
||||
ORDER BY id ASC
|
||||
`).all(orderId)
|
||||
}
|
||||
|
||||
export function createTask(input) {
|
||||
const result = getDb().prepare(`
|
||||
INSERT INTO delivery_tasks (
|
||||
order_id,
|
||||
order_item_id,
|
||||
platform_order_id,
|
||||
task_no,
|
||||
task_status,
|
||||
login_type,
|
||||
claim_token_id,
|
||||
reserved_cdk_id,
|
||||
browser_session_id,
|
||||
nickname,
|
||||
role_id,
|
||||
role_name,
|
||||
area,
|
||||
partition_name,
|
||||
result_code,
|
||||
result_message,
|
||||
screenshot_path,
|
||||
artifacts_json,
|
||||
last_error,
|
||||
retry_count,
|
||||
expires_at,
|
||||
claimed_at,
|
||||
role_confirmed_at,
|
||||
redeemed_at,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
input.orderId,
|
||||
input.orderItemId,
|
||||
input.platformOrderId,
|
||||
input.taskNo,
|
||||
input.taskStatus,
|
||||
input.loginType,
|
||||
input.claimTokenId,
|
||||
input.reservedCdkId,
|
||||
input.browserSessionId,
|
||||
input.nickname,
|
||||
input.roleId,
|
||||
input.roleName,
|
||||
input.area,
|
||||
input.partitionName,
|
||||
input.resultCode,
|
||||
input.resultMessage,
|
||||
input.screenshotPath,
|
||||
input.artifactsJson,
|
||||
input.lastError,
|
||||
input.retryCount,
|
||||
input.expiresAt,
|
||||
input.claimedAt,
|
||||
input.roleConfirmedAt,
|
||||
input.redeemedAt,
|
||||
input.createdAt,
|
||||
input.updatedAt,
|
||||
)
|
||||
|
||||
return getTaskById(Number(result.lastInsertRowid))
|
||||
}
|
||||
|
||||
export function updateTask(taskId, patch) {
|
||||
const current = getTaskById(taskId)
|
||||
|
||||
if (!current) {
|
||||
return null
|
||||
}
|
||||
|
||||
const next = { ...current, ...patch }
|
||||
|
||||
getDb().prepare(`
|
||||
UPDATE delivery_tasks
|
||||
SET
|
||||
task_status = ?,
|
||||
login_type = ?,
|
||||
claim_token_id = ?,
|
||||
reserved_cdk_id = ?,
|
||||
browser_session_id = ?,
|
||||
nickname = ?,
|
||||
role_id = ?,
|
||||
role_name = ?,
|
||||
area = ?,
|
||||
partition_name = ?,
|
||||
result_code = ?,
|
||||
result_message = ?,
|
||||
screenshot_path = ?,
|
||||
artifacts_json = ?,
|
||||
last_error = ?,
|
||||
retry_count = ?,
|
||||
expires_at = ?,
|
||||
claimed_at = ?,
|
||||
role_confirmed_at = ?,
|
||||
redeemed_at = ?,
|
||||
updated_at = ?
|
||||
WHERE id = ?
|
||||
`).run(
|
||||
next.task_status,
|
||||
next.login_type,
|
||||
next.claim_token_id,
|
||||
next.reserved_cdk_id,
|
||||
next.browser_session_id,
|
||||
next.nickname,
|
||||
next.role_id,
|
||||
next.role_name,
|
||||
next.area,
|
||||
next.partition_name,
|
||||
next.result_code,
|
||||
next.result_message,
|
||||
next.screenshot_path,
|
||||
next.artifacts_json,
|
||||
next.last_error,
|
||||
next.retry_count,
|
||||
next.expires_at,
|
||||
next.claimed_at,
|
||||
next.role_confirmed_at,
|
||||
next.redeemed_at,
|
||||
next.updated_at,
|
||||
taskId,
|
||||
)
|
||||
|
||||
return getTaskById(taskId)
|
||||
}
|
||||
|
||||
export function getTaskById(taskId) {
|
||||
return getDb().prepare('SELECT * FROM delivery_tasks WHERE id = ? LIMIT 1').get(taskId) || null
|
||||
}
|
||||
|
||||
export function findTaskByClaimTokenId(claimTokenId) {
|
||||
return getDb().prepare(`
|
||||
SELECT *
|
||||
FROM delivery_tasks
|
||||
WHERE claim_token_id = ?
|
||||
LIMIT 1
|
||||
`).get(claimTokenId) || null
|
||||
}
|
||||
|
||||
export function listTasks({
|
||||
page = 1,
|
||||
pageSize = 20,
|
||||
status = '',
|
||||
platformOrderId = '',
|
||||
taskNo = '',
|
||||
skuCode = '',
|
||||
roleId = '',
|
||||
dateFrom = '',
|
||||
dateTo = '',
|
||||
} = {}) {
|
||||
const offset = (page - 1) * pageSize
|
||||
const filters = []
|
||||
const params = []
|
||||
|
||||
if (status) {
|
||||
filters.push('dt.task_status = ?')
|
||||
params.push(status)
|
||||
}
|
||||
|
||||
if (platformOrderId) {
|
||||
filters.push('dt.platform_order_id LIKE ?')
|
||||
params.push(`%${platformOrderId}%`)
|
||||
}
|
||||
|
||||
if (taskNo) {
|
||||
filters.push('dt.task_no LIKE ?')
|
||||
params.push(`%${taskNo}%`)
|
||||
}
|
||||
|
||||
if (skuCode) {
|
||||
filters.push('oi.sku_code = ?')
|
||||
params.push(skuCode)
|
||||
}
|
||||
|
||||
if (roleId) {
|
||||
filters.push('dt.role_id LIKE ?')
|
||||
params.push(`%${roleId}%`)
|
||||
}
|
||||
|
||||
if (dateFrom) {
|
||||
filters.push('dt.created_at >= ?')
|
||||
params.push(dateFrom)
|
||||
}
|
||||
|
||||
if (dateTo) {
|
||||
filters.push('dt.created_at <= ?')
|
||||
params.push(dateTo)
|
||||
}
|
||||
|
||||
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
|
||||
const db = getDb()
|
||||
const totalRow = db.prepare(`
|
||||
SELECT COUNT(*) AS total
|
||||
FROM delivery_tasks dt
|
||||
LEFT JOIN order_items oi ON oi.id = dt.order_item_id
|
||||
${whereClause}
|
||||
`).get(...params)
|
||||
|
||||
const items = db.prepare(`
|
||||
SELECT
|
||||
dt.*,
|
||||
oi.sku_code,
|
||||
oi.sku_name,
|
||||
ci.cdk_code,
|
||||
ct.token AS claim_token
|
||||
FROM delivery_tasks dt
|
||||
LEFT JOIN order_items oi ON oi.id = dt.order_item_id
|
||||
LEFT JOIN cdk_inventory ci ON ci.id = dt.reserved_cdk_id
|
||||
LEFT JOIN claim_tokens ct ON ct.id = dt.claim_token_id
|
||||
${whereClause}
|
||||
ORDER BY dt.id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`).all(...params, pageSize, offset)
|
||||
|
||||
return {
|
||||
items,
|
||||
total: Number(totalRow?.total || 0),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import { getDb } from '../db/client.js'
|
||||
|
||||
export function createWebhookEvent(input) {
|
||||
const result = getDb().prepare(`
|
||||
INSERT INTO webhook_events (
|
||||
platform,
|
||||
event_type,
|
||||
event_key,
|
||||
signature_valid,
|
||||
headers_json,
|
||||
query_json,
|
||||
body_json,
|
||||
processed,
|
||||
process_error,
|
||||
related_order_id,
|
||||
created_at
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(
|
||||
input.platform,
|
||||
input.eventType,
|
||||
input.eventKey,
|
||||
input.signatureValid ? 1 : 0,
|
||||
input.headersJson,
|
||||
input.queryJson,
|
||||
input.bodyJson,
|
||||
input.processed ? 1 : 0,
|
||||
input.processError,
|
||||
input.relatedOrderId,
|
||||
input.createdAt,
|
||||
)
|
||||
|
||||
return getWebhookEventById(Number(result.lastInsertRowid))
|
||||
}
|
||||
|
||||
export function updateWebhookEvent(eventId, patch) {
|
||||
const current = getWebhookEventById(eventId)
|
||||
|
||||
if (!current) {
|
||||
return null
|
||||
}
|
||||
|
||||
const next = { ...current, ...patch }
|
||||
|
||||
getDb().prepare(`
|
||||
UPDATE webhook_events
|
||||
SET
|
||||
processed = ?,
|
||||
process_error = ?,
|
||||
related_order_id = ?
|
||||
WHERE id = ?
|
||||
`).run(next.processed ? 1 : 0, next.process_error, next.related_order_id, eventId)
|
||||
|
||||
return getWebhookEventById(eventId)
|
||||
}
|
||||
|
||||
export function getWebhookEventById(eventId) {
|
||||
return getDb().prepare('SELECT * FROM webhook_events WHERE id = ? LIMIT 1').get(eventId) || null
|
||||
}
|
||||
|
||||
export function listWebhookEvents({
|
||||
page = 1,
|
||||
pageSize = 20,
|
||||
platform = '',
|
||||
processed = '',
|
||||
relatedOrderId = '',
|
||||
dateFrom = '',
|
||||
dateTo = '',
|
||||
} = {}) {
|
||||
const offset = (page - 1) * pageSize
|
||||
const filters = []
|
||||
const params = []
|
||||
|
||||
if (platform) {
|
||||
filters.push('platform = ?')
|
||||
params.push(platform)
|
||||
}
|
||||
|
||||
if (processed === '0' || processed === '1') {
|
||||
filters.push('processed = ?')
|
||||
params.push(Number(processed))
|
||||
}
|
||||
|
||||
if (relatedOrderId) {
|
||||
filters.push('related_order_id = ?')
|
||||
params.push(Number(relatedOrderId))
|
||||
}
|
||||
|
||||
if (dateFrom) {
|
||||
filters.push('created_at >= ?')
|
||||
params.push(dateFrom)
|
||||
}
|
||||
|
||||
if (dateTo) {
|
||||
filters.push('created_at <= ?')
|
||||
params.push(dateTo)
|
||||
}
|
||||
|
||||
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
|
||||
const db = getDb()
|
||||
const totalRow = db.prepare(`
|
||||
SELECT COUNT(*) AS total
|
||||
FROM webhook_events
|
||||
${whereClause}
|
||||
`).get(...params)
|
||||
|
||||
const items = db.prepare(`
|
||||
SELECT *
|
||||
FROM webhook_events
|
||||
${whereClause}
|
||||
ORDER BY id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`).all(...params, pageSize, offset)
|
||||
|
||||
return {
|
||||
items,
|
||||
total: Number(totalRow?.total || 0),
|
||||
}
|
||||
}
|
||||
|
||||
export function listWebhookEventsByOrderId(orderId) {
|
||||
return getDb().prepare(`
|
||||
SELECT *
|
||||
FROM webhook_events
|
||||
WHERE related_order_id = ?
|
||||
ORDER BY id DESC
|
||||
`).all(orderId)
|
||||
}
|
||||
Reference in New Issue
Block a user