Files
order_site/apps/backend/src/repositories/order-repo.ts
T

237 lines
5.5 KiB
TypeScript

import { query } from '../db/client.js'
import type {
OrderCreateInput,
OrderListQueryInput,
OrderUpdateInput,
} from '../types/repository/inputs.js'
import type { OrderListQueryResult, OrderListRow, OrderRow } from '../types/repository/rows.js'
type OrderPlatformLookupInput = {
provider?: string
platform: string
shopId?: string
platformOrderId: string
}
export async function findOrderByPlatformOrderId({
provider = '91kaquan',
platform,
shopId = '',
platformOrderId,
}: OrderPlatformLookupInput): Promise<OrderRow | null> {
const result = await query<OrderRow>(
`
SELECT *
FROM orders
WHERE provider = $1 AND platform = $2 AND shop_id = $3 AND platform_order_id = $4
LIMIT 1
`,
[provider, platform, shopId, platformOrderId],
)
return result.rows[0] || null
}
export async function findLatestOrderByPlatformOrderId({
provider = '91kaquan',
platform,
platformOrderId,
}: Omit<OrderPlatformLookupInput, 'shopId'>): Promise<OrderRow | null> {
const result = await query<OrderRow>(
`
SELECT *
FROM orders
WHERE provider = $1 AND platform = $2 AND platform_order_id = $3
ORDER BY id DESC
LIMIT 1
`,
[provider, platform, platformOrderId],
)
return result.rows[0] || null
}
export async function findLatestOrderByAnyPlatformOrderId(
platformOrderId: string,
): Promise<OrderRow | null> {
const result = await query<OrderRow>(
`
SELECT *
FROM orders
WHERE platform_order_id = $1
ORDER BY id DESC
LIMIT 1
`,
[String(platformOrderId || '').trim()],
)
return result.rows[0] || null
}
export async function createOrder(input: OrderCreateInput): Promise<OrderRow | null> {
const result = await query<OrderRow>(
`
INSERT INTO orders (
provider,
platform,
shop_id,
shop_name,
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 ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13::jsonb, $14, $15, $16)
RETURNING *
`,
[
input.provider,
input.platform,
input.shopId,
input.shopName,
input.platformOrderId,
input.orderStatus,
input.payStatus,
input.buyerId,
input.buyerName,
input.receiverContact,
input.totalAmount,
input.currency,
input.rawPayloadJson || '{}',
input.paidAt || null,
input.createdAt,
input.updatedAt,
],
)
return result.rows[0] || null
}
export async function updateOrder(
orderId: number | string,
input: OrderUpdateInput,
): Promise<OrderRow | null> {
const result = await query<OrderRow>(
`
UPDATE orders
SET
provider = $1,
platform = $2,
shop_id = $3,
shop_name = $4,
order_status = $5,
pay_status = $6,
buyer_id = $7,
buyer_name = $8,
receiver_contact = $9,
total_amount = $10,
currency = $11,
raw_payload_json = $12::jsonb,
paid_at = $13,
updated_at = $14
WHERE id = $15
RETURNING *
`,
[
input.provider,
input.platform,
input.shopId,
input.shopName,
input.orderStatus,
input.payStatus,
input.buyerId,
input.buyerName,
input.receiverContact,
input.totalAmount,
input.currency,
input.rawPayloadJson || '{}',
input.paidAt || null,
input.updatedAt,
Number(orderId),
],
)
return result.rows[0] || null
}
export async function getOrderById(orderId: number | string): Promise<OrderRow | null> {
const result = await query<OrderRow>('SELECT * FROM orders WHERE id = $1 LIMIT 1', [
Number(orderId),
])
return result.rows[0] || null
}
export async function listOrders({
page = 1,
pageSize = 20,
platformOrderId = '',
payStatus = '',
skuCode = '',
dateFrom = '',
dateTo = '',
}: OrderListQueryInput = {}): Promise<OrderListQueryResult> {
const offset = (page - 1) * pageSize
const filters: string[] = []
const params: unknown[] = []
if (platformOrderId) {
params.push(`%${platformOrderId}%`)
filters.push(`o.platform_order_id ILIKE $${params.length}`)
}
if (payStatus) {
params.push(payStatus)
filters.push(`o.pay_status = $${params.length}`)
}
if (skuCode) {
params.push(skuCode)
filters.push(
`EXISTS (SELECT 1 FROM order_items oi WHERE oi.order_id = o.id AND oi.sku_code = $${params.length})`,
)
}
if (dateFrom) {
params.push(dateFrom)
filters.push(`o.created_at >= $${params.length}`)
}
if (dateTo) {
params.push(dateTo)
filters.push(`o.created_at <= $${params.length}`)
}
const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : ''
const totalResult = await query<{ [column: string]: unknown; total: number }>(
`SELECT COUNT(*)::int AS total FROM orders o ${whereClause}`,
params,
)
params.push(pageSize)
params.push(offset)
const itemsResult = await query<OrderListRow>(
`
SELECT
o.*,
(SELECT COUNT(*)::int FROM fulfillment_tasks ft WHERE ft.order_id = o.id) AS task_count
FROM orders o
${whereClause}
ORDER BY o.id DESC
LIMIT $${params.length - 1} OFFSET $${params.length}
`,
params,
)
return {
items: itemsResult.rows,
total: Number(totalResult.rows[0]?.total || 0),
}
}