修正快手行业电子凭证核销参数
This commit is contained in:
@@ -104,11 +104,12 @@ export async function reverseAdminKuaishouIndustryVoucher(input: JsonObject = {}
|
|||||||
export async function consumeAdminKuaishouIndustryVoucherByCode(input: JsonObject = {}) {
|
export async function consumeAdminKuaishouIndustryVoucherByCode(input: JsonObject = {}) {
|
||||||
const voucher = await resolveRequiredVoucher(input)
|
const voucher = await resolveRequiredVoucher(input)
|
||||||
const task = voucher.task_id ? await getTaskById(voucher.task_id) : null
|
const task = voucher.task_id ? await getTaskById(voucher.task_id) : null
|
||||||
|
const consumeType = String(input.consumeType || '').trim()
|
||||||
const consumeInput: Parameters<typeof consumeKuaishouIndustryVoucher>[1] = {
|
const consumeInput: Parameters<typeof consumeKuaishouIndustryVoucher>[1] = {
|
||||||
source: 'admin_tool_manual_consume',
|
source: 'admin_tool_manual_consume',
|
||||||
token: String(input.token || voucher.token || '').trim(),
|
token: String(input.token || voucher.token || '').trim(),
|
||||||
consumeType: String(input.consumeType || 'delivery').trim() || 'delivery',
|
|
||||||
consumeTime: Date.now(),
|
consumeTime: Date.now(),
|
||||||
|
...(consumeType ? { consumeType } : {}),
|
||||||
...(input.serialNum ? { serialNum: String(input.serialNum).trim() } : {}),
|
...(input.serialNum ? { serialNum: String(input.serialNum).trim() } : {}),
|
||||||
...(input.eticketType ? { eticketType: String(input.eticketType).trim() } : {}),
|
...(input.eticketType ? { eticketType: String(input.eticketType).trim() } : {}),
|
||||||
...(input.storeName ? { storeName: String(input.storeName).trim() } : {}),
|
...(input.storeName ? { storeName: String(input.storeName).trim() } : {}),
|
||||||
|
|||||||
@@ -857,12 +857,13 @@ export async function consumeAdminTaskKuaishouIndustryVoucher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const voucher = await getRequiredIndustryVoucherForTask(task)
|
const voucher = await getRequiredIndustryVoucherForTask(task)
|
||||||
|
const consumeType = String(payload.consumeType || '').trim()
|
||||||
const result = await consumeKuaishouIndustryVoucher(voucher, {
|
const result = await consumeKuaishouIndustryVoucher(voucher, {
|
||||||
source: 'admin_manual_consume',
|
source: 'admin_manual_consume',
|
||||||
task,
|
task,
|
||||||
token: voucher.token,
|
token: voucher.token,
|
||||||
consumeType: String(payload.consumeType || 'delivery').trim() || 'delivery',
|
|
||||||
consumeTime: Date.now(),
|
consumeTime: Date.now(),
|
||||||
|
...(consumeType ? { consumeType } : {}),
|
||||||
...(payload.storeName ? { storeName: payload.storeName } : {}),
|
...(payload.storeName ? { storeName: payload.storeName } : {}),
|
||||||
...(payload.storeAddress ? { storeAddress: payload.storeAddress } : {}),
|
...(payload.storeAddress ? { storeAddress: payload.storeAddress } : {}),
|
||||||
...(payload.expressCode ? { expressCode: payload.expressCode } : {}),
|
...(payload.expressCode ? { expressCode: payload.expressCode } : {}),
|
||||||
|
|||||||
@@ -817,7 +817,6 @@ export async function returnKuaishouCloudFulfillmentTask(
|
|||||||
? await consumeKuaishouIndustryVouchersForTask(task, {
|
? await consumeKuaishouIndustryVouchersForTask(task, {
|
||||||
source: String(options.source || "system_auto_finalize").trim() || "system_auto_finalize",
|
source: String(options.source || "system_auto_finalize").trim() || "system_auto_finalize",
|
||||||
token: String(taskContext.kuaishouIndustryVoucher?.token || "").trim(),
|
token: String(taskContext.kuaishouIndustryVoucher?.token || "").trim(),
|
||||||
consumeType: "delivery",
|
|
||||||
consumeTime: Date.now(),
|
consumeTime: Date.now(),
|
||||||
})
|
})
|
||||||
: { ok: true, consumed: [], failed: [] };
|
: { ok: true, consumed: [], failed: [] };
|
||||||
|
|||||||
@@ -146,7 +146,6 @@ export async function syncKuaishouFeifeiTaskStatus(task: TaskRow) {
|
|||||||
if (order.rechargeStatus === 30) {
|
if (order.rechargeStatus === 30) {
|
||||||
const consumeResult = await consumeKuaishouIndustryVouchersForTask(task, {
|
const consumeResult = await consumeKuaishouIndustryVouchersForTask(task, {
|
||||||
source: 'kuaishou_feifei_completed',
|
source: 'kuaishou_feifei_completed',
|
||||||
consumeType: 'delivery',
|
|
||||||
consumeTime: Date.now(),
|
consumeTime: Date.now(),
|
||||||
})
|
})
|
||||||
const consumedVoucher = consumeResult.consumed[0] || null
|
const consumedVoucher = consumeResult.consumed[0] || null
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
import test from 'node:test'
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
|
||||||
|
import { buildConsumeCallbackBizParams } from './consume-callback-service.js'
|
||||||
|
|
||||||
|
test('buildConsumeCallbackBizParams omits eticket status', () => {
|
||||||
|
const bizParams = buildConsumeCallbackBizParams({
|
||||||
|
oid: '2619000086068982',
|
||||||
|
etickets: [{
|
||||||
|
id: 'KSVASXT6Q955WT4SS36',
|
||||||
|
num: 1,
|
||||||
|
status: 'CONSUMED',
|
||||||
|
} as any],
|
||||||
|
status: 'CONSUMED',
|
||||||
|
consumeType: 'consume',
|
||||||
|
consumeTime: 1783596649024,
|
||||||
|
token: 'ticket-token',
|
||||||
|
seriallNum: 'CONSUME-KSVASXT6Q955WT4SS36',
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.deepEqual(bizParams.etickets, [{
|
||||||
|
id: 'KSVASXT6Q955WT4SS36',
|
||||||
|
num: 1,
|
||||||
|
}])
|
||||||
|
assert.equal(bizParams.consumeType, 'consume')
|
||||||
|
})
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { logInfo, logWarn } from '../../../utils/logger.js'
|
import { logInfo, logWarn } from '../../../utils/logger.js'
|
||||||
import { requestKuaishouIndustryOpenApi, type JsonObject } from './openapi-client.js'
|
import { requestKuaishouIndustryOpenApi, type JsonObject } from './openapi-client.js'
|
||||||
|
|
||||||
type ConsumeCallbackInput = {
|
export type ConsumeCallbackInput = {
|
||||||
oid: string
|
oid: string
|
||||||
sellerId?: string
|
sellerId?: string
|
||||||
etickets: Array<{
|
etickets: Array<{
|
||||||
@@ -9,7 +9,6 @@ type ConsumeCallbackInput = {
|
|||||||
code?: string
|
code?: string
|
||||||
num: number
|
num: number
|
||||||
goodsValue?: number
|
goodsValue?: number
|
||||||
status?: string
|
|
||||||
}>
|
}>
|
||||||
status: string
|
status: string
|
||||||
consumeType: string
|
consumeType: string
|
||||||
@@ -29,30 +28,7 @@ type ConsumeCallbackInput = {
|
|||||||
export async function consumeCallback(
|
export async function consumeCallback(
|
||||||
input: ConsumeCallbackInput,
|
input: ConsumeCallbackInput,
|
||||||
): Promise<{ success: boolean; response?: JsonObject; error?: string }> {
|
): Promise<{ success: boolean; response?: JsonObject; error?: string }> {
|
||||||
const bizParams: JsonObject = {
|
const bizParams = buildConsumeCallbackBizParams(input)
|
||||||
oid: input.oid,
|
|
||||||
etickets: input.etickets.map((e) => {
|
|
||||||
const item: JsonObject = { id: e.id, num: e.num }
|
|
||||||
if (e.code) item.code = e.code
|
|
||||||
if (e.goodsValue != null) item.goodsValue = e.goodsValue
|
|
||||||
if (e.status) item.status = e.status
|
|
||||||
return item
|
|
||||||
}),
|
|
||||||
status: input.status,
|
|
||||||
consumeType: input.consumeType,
|
|
||||||
token: input.token,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (input.consumeTime != null) bizParams.consumeTime = input.consumeTime
|
|
||||||
if (input.storeName) bizParams.storeName = input.storeName
|
|
||||||
if (input.storeAddress) bizParams.storeAddress = input.storeAddress
|
|
||||||
if (input.expressNo) bizParams.expressNo = input.expressNo
|
|
||||||
if (input.expressCode) bizParams.expressCode = input.expressCode
|
|
||||||
if (input.appointmentTime) bizParams.appointmentTime = input.appointmentTime
|
|
||||||
if (input.eticketType) bizParams.eticketType = input.eticketType
|
|
||||||
if (input.ext) bizParams.ext = input.ext
|
|
||||||
if (input.seriallNum) bizParams.seriallNum = input.seriallNum
|
|
||||||
if (input.consumePoiId != null) bizParams.consumePoiId = input.consumePoiId
|
|
||||||
|
|
||||||
const result = await requestKuaishouIndustryOpenApi({
|
const result = await requestKuaishouIndustryOpenApi({
|
||||||
apiMethod: 'integration.callback.virtual.eticket.consume',
|
apiMethod: 'integration.callback.virtual.eticket.consume',
|
||||||
@@ -115,3 +91,31 @@ export async function consumeCallback(
|
|||||||
...(result.error ? { error: result.error } : {}),
|
...(result.error ? { error: result.error } : {}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildConsumeCallbackBizParams(input: ConsumeCallbackInput): JsonObject {
|
||||||
|
const bizParams: JsonObject = {
|
||||||
|
oid: input.oid,
|
||||||
|
etickets: input.etickets.map((e) => {
|
||||||
|
const item: JsonObject = { id: e.id, num: e.num }
|
||||||
|
if (e.code) item.code = e.code
|
||||||
|
if (e.goodsValue != null) item.goodsValue = e.goodsValue
|
||||||
|
return item
|
||||||
|
}),
|
||||||
|
status: input.status,
|
||||||
|
consumeType: input.consumeType,
|
||||||
|
token: input.token,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.consumeTime != null) bizParams.consumeTime = input.consumeTime
|
||||||
|
if (input.storeName) bizParams.storeName = input.storeName
|
||||||
|
if (input.storeAddress) bizParams.storeAddress = input.storeAddress
|
||||||
|
if (input.expressNo) bizParams.expressNo = input.expressNo
|
||||||
|
if (input.expressCode) bizParams.expressCode = input.expressCode
|
||||||
|
if (input.appointmentTime) bizParams.appointmentTime = input.appointmentTime
|
||||||
|
if (input.eticketType) bizParams.eticketType = input.eticketType
|
||||||
|
if (input.ext) bizParams.ext = input.ext
|
||||||
|
if (input.seriallNum) bizParams.seriallNum = input.seriallNum
|
||||||
|
if (input.consumePoiId != null) bizParams.consumePoiId = input.consumePoiId
|
||||||
|
|
||||||
|
return bizParams
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { generateKuaishouIndustryVoucherCode } from '../../../repositories/kuais
|
|||||||
import { buildKuaishouIndustryVoucherContext } from './voucher-binding-service.js'
|
import { buildKuaishouIndustryVoucherContext } from './voucher-binding-service.js'
|
||||||
import {
|
import {
|
||||||
buildKuaishouIndustryEticketFromVoucher,
|
buildKuaishouIndustryEticketFromVoucher,
|
||||||
|
normalizeKuaishouIndustryConsumeType,
|
||||||
resolveKuaishouIndustryVoucherValidity,
|
resolveKuaishouIndustryVoucherValidity,
|
||||||
} from './voucher-service.js'
|
} from './voucher-service.js'
|
||||||
|
|
||||||
@@ -62,6 +63,12 @@ test('resolveKuaishouIndustryVoucherValidity prefers actual certificate time ran
|
|||||||
assert.equal(validity.validEndTime, 5000)
|
assert.equal(validity.validEndTime, 5000)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('normalizeKuaishouIndustryConsumeType defaults to consume', () => {
|
||||||
|
assert.equal(normalizeKuaishouIndustryConsumeType(undefined), 'consume')
|
||||||
|
assert.equal(normalizeKuaishouIndustryConsumeType(''), 'consume')
|
||||||
|
assert.equal(normalizeKuaishouIndustryConsumeType(' pickup '), 'pickup')
|
||||||
|
})
|
||||||
|
|
||||||
test('buildKuaishouIndustryEticketFromVoucher mirrors voucher code into id and code', () => {
|
test('buildKuaishouIndustryEticketFromVoucher mirrors voucher code into id and code', () => {
|
||||||
const eticket = buildKuaishouIndustryEticketFromVoucher({
|
const eticket = buildKuaishouIndustryEticketFromVoucher({
|
||||||
voucher_code: 'KSV15K821FDHPMTX1ST',
|
voucher_code: 'KSV15K821FDHPMTX1ST',
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export const KUAISHOU_INDUSTRY_SEND_CALLBACK_STATUS = {
|
|||||||
SUCCESS: 'success',
|
SUCCESS: 'success',
|
||||||
FAILED: 'failed',
|
FAILED: 'failed',
|
||||||
} as const
|
} as const
|
||||||
|
export const KUAISHOU_INDUSTRY_DEFAULT_CONSUME_TYPE = 'consume'
|
||||||
|
|
||||||
export function resolveKuaishouIndustryVoucherValidity(
|
export function resolveKuaishouIndustryVoucherValidity(
|
||||||
input: {
|
input: {
|
||||||
@@ -124,7 +125,7 @@ export async function consumeKuaishouIndustryVouchersForTask(
|
|||||||
for (const voucher of vouchers) {
|
for (const voucher of vouchers) {
|
||||||
const consumeInput: Parameters<typeof consumeKuaishouIndustryVoucher>[1] = {
|
const consumeInput: Parameters<typeof consumeKuaishouIndustryVoucher>[1] = {
|
||||||
source: input.source || 'fulfillment_completed',
|
source: input.source || 'fulfillment_completed',
|
||||||
consumeType: input.consumeType || 'delivery',
|
consumeType: normalizeKuaishouIndustryConsumeType(input.consumeType),
|
||||||
consumeTime: input.consumeTime || Date.now(),
|
consumeTime: input.consumeTime || Date.now(),
|
||||||
task,
|
task,
|
||||||
}
|
}
|
||||||
@@ -202,7 +203,7 @@ export async function consumeKuaishouIndustryVoucher(
|
|||||||
|
|
||||||
const now = new Date().toISOString()
|
const now = new Date().toISOString()
|
||||||
const consumeTime = Number(input.consumeTime || Date.now()) || Date.now()
|
const consumeTime = Number(input.consumeTime || Date.now()) || Date.now()
|
||||||
const consumeType = String(input.consumeType || 'delivery').trim() || 'delivery'
|
const consumeType = normalizeKuaishouIndustryConsumeType(input.consumeType)
|
||||||
const serialNum = String(input.serialNum || voucher.consume_serial_num || `CONSUME-${voucher.voucher_code}`).trim()
|
const serialNum = String(input.serialNum || voucher.consume_serial_num || `CONSUME-${voucher.voucher_code}`).trim()
|
||||||
const token = String(input.token || voucher.token || '').trim()
|
const token = String(input.token || voucher.token || '').trim()
|
||||||
const consumeDetail = {
|
const consumeDetail = {
|
||||||
@@ -224,7 +225,6 @@ export async function consumeKuaishouIndustryVoucher(
|
|||||||
etickets: [{
|
etickets: [{
|
||||||
id: voucher.voucher_code,
|
id: voucher.voucher_code,
|
||||||
num: 1,
|
num: 1,
|
||||||
status: 'CONSUMED',
|
|
||||||
}],
|
}],
|
||||||
status: 'CONSUMED',
|
status: 'CONSUMED',
|
||||||
consumeType,
|
consumeType,
|
||||||
@@ -317,7 +317,7 @@ function resolveVoucherConsumeDetails(voucher: KuaishouIndustryVoucherRow): Json
|
|||||||
|
|
||||||
return [{
|
return [{
|
||||||
serialNum: voucher.consume_serial_num,
|
serialNum: voucher.consume_serial_num,
|
||||||
consumeType: 'delivery',
|
consumeType: KUAISHOU_INDUSTRY_DEFAULT_CONSUME_TYPE,
|
||||||
consumeTime: voucher.consumed_at ? Date.parse(voucher.consumed_at) : 0,
|
consumeTime: voucher.consumed_at ? Date.parse(voucher.consumed_at) : 0,
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
@@ -340,6 +340,11 @@ function normalizeVoucherStatus(value: unknown): string {
|
|||||||
return 'UNUSED'
|
return 'UNUSED'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function normalizeKuaishouIndustryConsumeType(value: unknown): string {
|
||||||
|
return String(value || KUAISHOU_INDUSTRY_DEFAULT_CONSUME_TYPE).trim() ||
|
||||||
|
KUAISHOU_INDUSTRY_DEFAULT_CONSUME_TYPE
|
||||||
|
}
|
||||||
|
|
||||||
function normalizePositiveTimestamp(value: unknown): number {
|
function normalizePositiveTimestamp(value: unknown): number {
|
||||||
const parsed = Number(value)
|
const parsed = Number(value)
|
||||||
return Number.isFinite(parsed) && parsed > 0 ? Math.trunc(parsed) : 0
|
return Number.isFinite(parsed) && parsed > 0 ? Math.trunc(parsed) : 0
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ export default function AdminKuaishouIndustryPage() {
|
|||||||
})
|
})
|
||||||
const [toolForm, setToolForm] = useState<AdminKuaishouIndustryVoucherToolPayload>({
|
const [toolForm, setToolForm] = useState<AdminKuaishouIndustryVoucherToolPayload>({
|
||||||
eticketType: DEFAULT_ETICKET_TYPE,
|
eticketType: DEFAULT_ETICKET_TYPE,
|
||||||
consumeType: 'delivery',
|
consumeType: 'consume',
|
||||||
})
|
})
|
||||||
const [refundDateRange, setRefundDateRange] = useState<DateRangeValue>(() => [
|
const [refundDateRange, setRefundDateRange] = useState<DateRangeValue>(() => [
|
||||||
dayjs().subtract(1, 'day'),
|
dayjs().subtract(1, 'day'),
|
||||||
|
|||||||
Reference in New Issue
Block a user