feat: 积分商城-供应商
This commit is contained in:
@@ -23,6 +23,13 @@ export const merchantOrderListController = withErrorBoundary(async (request: Req
|
||||
return toHttpResponse(await merchantService.listOrders(await readJson<MerchantOrderListInput>(request)))
|
||||
})
|
||||
|
||||
export const merchantSupplierListController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return toHttpResponse(await merchantService.listSuppliers())
|
||||
})
|
||||
|
||||
export const merchantOrderShipController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
@@ -14,7 +14,11 @@ import { orderActionService } from '../services/order-action.service.js'
|
||||
import { orderCreateService, type CheckoutGoods } from '../services/order-create.service.js'
|
||||
import { orderListService } from '../services/order-list.service.js'
|
||||
import { orderPushEventService, type OrderPushEventInput } from '../services/order-push-event.service.js'
|
||||
import { supplierOpenOrderService, type SupplierOrderQueryRequest } from '../services/supplier-open-order.service.js'
|
||||
import {
|
||||
supplierOpenOrderService,
|
||||
type SupplierOrderQueryRequest,
|
||||
type SupplierReconciliationQueryRequest
|
||||
} from '../services/supplier-open-order.service.js'
|
||||
import { toHttpResponse } from './controller-response.js'
|
||||
|
||||
type OrderListRequest = {
|
||||
@@ -239,3 +243,21 @@ export const supplierOrderInfoController = withErrorBoundary(async (request: Req
|
||||
|
||||
return Response.json(await supplierOpenOrderService.queryOrderInfo(body))
|
||||
})
|
||||
|
||||
export const supplierReconciliationInfoController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
let body: SupplierReconciliationQueryRequest
|
||||
try {
|
||||
body = supplierOpenOrderService.parseBody(await readJson<SupplierReconciliationQueryRequest>(request))
|
||||
} catch (error) {
|
||||
return Response.json({
|
||||
resultCode: 400,
|
||||
message: error instanceof Error ? error.message : '请求参数解密失败',
|
||||
orderInfos: []
|
||||
})
|
||||
}
|
||||
|
||||
return Response.json(await supplierOpenOrderService.queryReconciliationInfo(body))
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { Context } from '../utils/handler.js'
|
||||
import { guardMethod } from '../utils/method.js'
|
||||
import { readJson } from '../utils/request.js'
|
||||
import { withErrorBoundary } from '../utils/handler.js'
|
||||
import { productService } from '../services/product.service.js'
|
||||
import { toHttpResponse } from './controller-response.js'
|
||||
@@ -25,3 +26,28 @@ export const productDetailController = withErrorBoundary(async (request: Request
|
||||
|
||||
return toHttpResponse(await productService.getProductDetail(id, sku))
|
||||
})
|
||||
|
||||
export const merchantProductListController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
const body = await readJson<{ keyword?: string; categoryId?: string }>(request)
|
||||
return toHttpResponse(await productService.listManageProducts(String(body.keyword || '').trim(), String(body.categoryId || '').trim()))
|
||||
})
|
||||
|
||||
export const merchantProductSaveController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return toHttpResponse(await productService.saveManageProduct(
|
||||
await readJson<Parameters<typeof productService.saveManageProduct>[0]>(request)
|
||||
))
|
||||
})
|
||||
|
||||
export const merchantProductDeleteController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
const body = await readJson<{ id?: number }>(request)
|
||||
return toHttpResponse(await productService.deleteManageProduct(Number(body.id || 0)))
|
||||
})
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import type { Context } from '../utils/handler.js'
|
||||
import { withErrorBoundary } from '../utils/handler.js'
|
||||
import { guardMethod } from '../utils/method.js'
|
||||
import { readJson } from '../utils/request.js'
|
||||
import { toHttpResponse } from './controller-response.js'
|
||||
import { supplierOpenOrderService } from '../services/supplier-open-order.service.js'
|
||||
import {
|
||||
reconciliationResultService,
|
||||
type ReconciliationResultCallbackInput,
|
||||
type ReconciliationResultListInput,
|
||||
type ReconciliationResultUpdateInput
|
||||
} from '../services/reconciliation-result.service.js'
|
||||
|
||||
type UnReconciledMsgInput = {
|
||||
supplierId?: string
|
||||
token?: string
|
||||
timestamp?: number
|
||||
orderIds?: string
|
||||
unReconciledType?: number
|
||||
unReconciledMsg?: string
|
||||
uniqueSeqNo?: string
|
||||
AplParmObjct?: string
|
||||
}
|
||||
|
||||
export const supplierReconciliationResultController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
let body: ReconciliationResultCallbackInput
|
||||
try {
|
||||
body = supplierOpenOrderService.parseBody(await readJson<ReconciliationResultCallbackInput>(request)) as ReconciliationResultCallbackInput
|
||||
} catch (error) {
|
||||
return Response.json({ resultCode: 400, message: error instanceof Error ? error.message : '请求参数解密失败' })
|
||||
}
|
||||
return Response.json(await reconciliationResultService.receiveCallback(body))
|
||||
})
|
||||
|
||||
export const supplierUnReconciledMsgController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
let body: UnReconciledMsgInput
|
||||
try {
|
||||
body = supplierOpenOrderService.parseBody(await readJson<UnReconciledMsgInput>(request)) as UnReconciledMsgInput
|
||||
} catch (error) {
|
||||
return Response.json({ resultCode: 400, message: error instanceof Error ? error.message : '请求参数解密失败' })
|
||||
}
|
||||
const reconciliationResults = String(body.orderIds || '').split(',').map(orderId => orderId.trim()).filter(Boolean).map(orderId => ({
|
||||
orderId,
|
||||
reconciliationStatus: 2,
|
||||
diffType: body.unReconciledType === undefined ? undefined : Number(body.unReconciledType),
|
||||
diffReason: body.unReconciledMsg
|
||||
}))
|
||||
return Response.json(await reconciliationResultService.receiveCallback({
|
||||
supplierId: body.supplierId,
|
||||
token: body.token,
|
||||
timestamp: body.timestamp,
|
||||
reconciliationBatchNo: body.uniqueSeqNo,
|
||||
reconciliationResults
|
||||
}))
|
||||
})
|
||||
|
||||
export const merchantReconciliationListController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return toHttpResponse(await reconciliationResultService.list(await readJson<ReconciliationResultListInput>(request)))
|
||||
})
|
||||
|
||||
export const merchantReconciliationUpdateController = withErrorBoundary(async (request: Request, _context: Context) => {
|
||||
const methodResponse = guardMethod(request, ['POST'])
|
||||
if (methodResponse) return methodResponse
|
||||
|
||||
return toHttpResponse(await reconciliationResultService.update(await readJson<ReconciliationResultUpdateInput>(request)))
|
||||
})
|
||||
@@ -137,12 +137,38 @@ export const orderDao = {
|
||||
})
|
||||
},
|
||||
|
||||
findMerchantSubOrders(supplierId: string, orderState?: number) {
|
||||
findOpenApiReconciliationSubOrders(supplierId: string, orderIds: string[], startDate?: Date, endDate?: Date, orderState?: number) {
|
||||
return prisma.supplierOrderSub.findMany({
|
||||
where: {
|
||||
supplierId,
|
||||
deleted: 0,
|
||||
...(Number.isInteger(orderState) ? { orderState } : {})
|
||||
...(Number.isInteger(orderState) ? { orderState } : {}),
|
||||
...(orderIds.length ? { orderId: { in: orderIds } } : {}),
|
||||
...(startDate || endDate ? {
|
||||
completeTime: {
|
||||
...(startDate ? { gte: startDate } : {}),
|
||||
...(endDate ? { lte: endDate } : {})
|
||||
}
|
||||
} : {})
|
||||
},
|
||||
include: {
|
||||
products: {
|
||||
where: { deleted: 0 },
|
||||
orderBy: { createAt: 'asc' }
|
||||
}
|
||||
},
|
||||
orderBy: { createAt: 'asc' }
|
||||
})
|
||||
},
|
||||
|
||||
findMerchantSubOrders(supplierId: string, orderState?: number, orderId?: string, userId?: string) {
|
||||
return prisma.supplierOrderSub.findMany({
|
||||
where: {
|
||||
supplierId,
|
||||
deleted: 0,
|
||||
...(Number.isInteger(orderState) ? { orderState } : {}),
|
||||
...(orderId ? { OR: [{ orderId: { contains: orderId } }, { orderNumberId: { contains: orderId } }] } : {}),
|
||||
...(userId ? { userId: { contains: userId } } : {})
|
||||
},
|
||||
include: {
|
||||
products: {
|
||||
|
||||
@@ -33,5 +33,31 @@ export const productDao = {
|
||||
]
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
findManageProducts(keyword: string, categoryId: string) {
|
||||
return prisma.supplierProduct.findMany({
|
||||
where: {
|
||||
deleted: 0,
|
||||
...(keyword ? { OR: [{ name: { contains: keyword } }, { sku: { contains: keyword } }] } : {}),
|
||||
...(categoryId ? { categoryId } : {})
|
||||
},
|
||||
orderBy: [
|
||||
{ sortOrder: 'asc' },
|
||||
{ createdAt: 'desc' }
|
||||
]
|
||||
})
|
||||
},
|
||||
|
||||
createProduct(data: Parameters<typeof prisma.supplierProduct.create>[0]['data']) {
|
||||
return prisma.supplierProduct.create({ data })
|
||||
},
|
||||
|
||||
updateProduct(id: number, data: Parameters<typeof prisma.supplierProduct.update>[0]['data']) {
|
||||
return prisma.supplierProduct.update({ where: { id }, data })
|
||||
},
|
||||
|
||||
findManageProduct(id: number) {
|
||||
return prisma.supplierProduct.findFirst({ where: { id, deleted: 0 } })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,5 +11,13 @@ export const supplierDao = {
|
||||
return prisma.supplierInfo.findFirst({
|
||||
where: { supplierId, deleted: 0 }
|
||||
})
|
||||
},
|
||||
|
||||
findActiveSuppliers() {
|
||||
return prisma.supplierInfo.findMany({
|
||||
where: { deleted: 0 },
|
||||
select: { supplierId: true, supplierName: true },
|
||||
orderBy: { supplierName: 'asc' }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,15 @@ import {
|
||||
orderPayController,
|
||||
orderPushEventController,
|
||||
orderShipController,
|
||||
supplierOrderInfoController
|
||||
supplierOrderInfoController,
|
||||
supplierReconciliationInfoController
|
||||
} from './controllers/order.controller.js'
|
||||
import {
|
||||
merchantReconciliationListController,
|
||||
merchantReconciliationUpdateController,
|
||||
supplierReconciliationResultController,
|
||||
supplierUnReconciledMsgController
|
||||
} from './controllers/reconciliation.controller.js'
|
||||
import {
|
||||
merchantAfterSaleAuditController,
|
||||
merchantAfterSaleDetailController,
|
||||
@@ -42,9 +49,16 @@ import {
|
||||
merchantAfterSaleReceiveController,
|
||||
merchantAfterSaleShipController,
|
||||
merchantOrderListController,
|
||||
merchantOrderShipController
|
||||
merchantOrderShipController,
|
||||
merchantSupplierListController
|
||||
} from './controllers/merchant.controller.js'
|
||||
import { productDetailController, productListController } from './controllers/product.controller.js'
|
||||
import {
|
||||
merchantProductDeleteController,
|
||||
merchantProductListController,
|
||||
merchantProductSaveController,
|
||||
productDetailController,
|
||||
productListController
|
||||
} from './controllers/product.controller.js'
|
||||
import {
|
||||
supplierDebugTokensController,
|
||||
supplierInfoController,
|
||||
@@ -75,6 +89,7 @@ const handlers: Record<string, FunctionHandler> = {
|
||||
'merchant-after-sale-ship': merchantAfterSaleShipController,
|
||||
'merchant-order-list': merchantOrderListController,
|
||||
'merchant-order-ship': merchantOrderShipController,
|
||||
'merchant-supplier-list': merchantSupplierListController,
|
||||
'order-cancel-main': orderCancelMainController,
|
||||
'order-cancel-paid-main': orderCancelPaidMainController,
|
||||
'order-cancel-sub': orderCancelSubController,
|
||||
@@ -87,9 +102,17 @@ const handlers: Record<string, FunctionHandler> = {
|
||||
'order-ship': orderShipController,
|
||||
'product-detail': productDetailController,
|
||||
'product-list': productListController,
|
||||
'merchant-product-list': merchantProductListController,
|
||||
'merchant-product-save': merchantProductSaveController,
|
||||
'merchant-product-delete': merchantProductDeleteController,
|
||||
'supplier-debug-tokens': supplierDebugTokensController,
|
||||
'supplier-info': supplierInfoController,
|
||||
'supplier-order-info': supplierOrderInfoController,
|
||||
'supplier-reconciliation-info': supplierReconciliationInfoController,
|
||||
'supplier-reconciliation-result': supplierReconciliationResultController,
|
||||
'supplier-unreconciled-msg': supplierUnReconciledMsgController,
|
||||
'merchant-reconciliation-list': merchantReconciliationListController,
|
||||
'merchant-reconciliation-update': merchantReconciliationUpdateController,
|
||||
'supplier-points': supplierPointsController,
|
||||
'supplier-token': supplierTokenController,
|
||||
upload: uploadController,
|
||||
@@ -174,7 +197,11 @@ router.delete('/api/supplier-logs', ctx => {
|
||||
}
|
||||
})
|
||||
router.all('/api/:name', async ctx => dispatch(ctx.params.name)(ctx))
|
||||
router.all('/api/admin/:name', async ctx => dispatch(ctx.params.name)(ctx))
|
||||
router.post('/supplierOpenApi/pointOrder/queryOrderInfo', dispatch('supplier-order-info'))
|
||||
router.post('/supplierOpenApi/pointOrder/queryReconciliationInfo', dispatch('supplier-reconciliation-info'))
|
||||
router.post('/supplierOpenApi/pointOrder/reconciliationResult', dispatch('supplier-reconciliation-result'))
|
||||
router.post('/supplierOpenApi/pointOrder/unReconciledMsg', dispatch('supplier-unreconciled-msg'))
|
||||
router.post('/supplierOpenApi/debug/tokens', dispatch('supplier-debug-tokens'))
|
||||
|
||||
app.use(router.routes())
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
ORDER_STATE
|
||||
} from '../constants/order.js'
|
||||
import { orderDao } from '../dao/order.dao.js'
|
||||
import { supplierDao } from '../dao/supplier.dao.js'
|
||||
import { afterSaleService, type AfterSaleAuditInput, type AfterSaleLogisticsInput } from './after-sale.service.js'
|
||||
import { orderActionService } from './order-action.service.js'
|
||||
import { logger } from '../utils/logger.js'
|
||||
@@ -13,6 +14,8 @@ import { serviceFail, serviceOk } from '../types/service-result.js'
|
||||
export type MerchantOrderListInput = {
|
||||
supplierId?: string
|
||||
orderState?: number
|
||||
orderId?: string
|
||||
userId?: string
|
||||
}
|
||||
|
||||
export type MerchantShipInput = {
|
||||
@@ -105,14 +108,16 @@ const isOrderSigned = (orderState?: number | null) => signedOrderStates.has(Numb
|
||||
export const merchantService = {
|
||||
async listOrders(input: MerchantOrderListInput) {
|
||||
const supplierId = String(input.supplierId || '').trim()
|
||||
const orderState = Number(input.orderState ?? ORDER_STATE.FINISH_PAY)
|
||||
const orderState = input.orderState === undefined ? undefined : Number(input.orderState)
|
||||
const orderId = String(input.orderId || '').trim()
|
||||
const userId = String(input.userId || '').trim()
|
||||
logger.info('merchant order list query', { supplierId, orderState })
|
||||
|
||||
if (!supplierId) {
|
||||
return serviceFail('供应商不能为空')
|
||||
}
|
||||
|
||||
const orders = await orderDao.findMerchantSubOrders(supplierId, orderState)
|
||||
const orders = await orderDao.findMerchantSubOrders(supplierId, orderState, orderId, userId)
|
||||
const afterSales = await orderDao.findMerchantAfterSales(supplierId, pendingShipExcludeAfterSaleStates)
|
||||
const afterSaleSubOrderIds = new Set(afterSales.map(item => item.subOrderId).filter(Boolean))
|
||||
const orderItems = orders.filter(order => !afterSaleSubOrderIds.has(order.orderId)).map(order => ({
|
||||
@@ -139,6 +144,11 @@ export const merchantService = {
|
||||
return serviceOk({ orderItems })
|
||||
},
|
||||
|
||||
async listSuppliers() {
|
||||
const suppliers = await supplierDao.findActiveSuppliers()
|
||||
return serviceOk({ suppliers })
|
||||
},
|
||||
|
||||
shipOrder(input: MerchantShipInput) {
|
||||
return orderActionService.shipOrder({
|
||||
supplierId: String(input.supplierId || '').trim(),
|
||||
|
||||
@@ -35,7 +35,9 @@ const toProductItem = (product: ProductRecord) => {
|
||||
category: product.category || '',
|
||||
tag: product.tag || '',
|
||||
sales: product.sales || '',
|
||||
stock: product.stock
|
||||
stock: product.stock,
|
||||
sortOrder: product.sortOrder,
|
||||
enabled: product.enabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,5 +66,67 @@ export const productService = {
|
||||
}
|
||||
|
||||
return serviceOk(toProductItem(product))
|
||||
},
|
||||
|
||||
async listManageProducts(keyword: string, categoryId: string) {
|
||||
const products = await productDao.findManageProducts(keyword, categoryId)
|
||||
return serviceOk({ categories, products: products.map(toProductItem) })
|
||||
},
|
||||
|
||||
async saveManageProduct(input: {
|
||||
id?: number
|
||||
sku?: string
|
||||
name?: string
|
||||
price?: number
|
||||
number?: number
|
||||
stock?: number
|
||||
taxRate?: number
|
||||
categoryId?: string
|
||||
category?: string
|
||||
imageUrl?: string
|
||||
description?: string
|
||||
detail?: string
|
||||
originPrice?: number
|
||||
tag?: string
|
||||
sales?: string
|
||||
sortOrder?: number
|
||||
enabled?: boolean
|
||||
}) {
|
||||
const sku = String(input.sku || '').trim()
|
||||
const name = String(input.name || '').trim()
|
||||
const price = Number(input.price)
|
||||
if (!sku || !name || Number.isNaN(price) || price < 0) {
|
||||
return serviceFail('商品SKU、名称和价格不能为空')
|
||||
}
|
||||
|
||||
const data = {
|
||||
sku,
|
||||
name,
|
||||
price,
|
||||
number: Math.max(Number(input.number || 0), 0),
|
||||
stock: Math.max(Number(input.stock || 0), 0),
|
||||
taxRate: Number(input.taxRate ?? 0.13),
|
||||
categoryId: String(input.categoryId || '').trim() || null,
|
||||
category: String(input.category || '').trim() || null,
|
||||
imageUrl: String(input.imageUrl || '').trim() || null,
|
||||
description: String(input.description || '').trim() || null,
|
||||
detail: String(input.detail || '').trim() || null,
|
||||
originPrice: input.originPrice === undefined || input.originPrice === null ? null : Number(input.originPrice),
|
||||
tag: String(input.tag || '').trim() || null,
|
||||
sales: String(input.sales || '').trim() || null,
|
||||
sortOrder: Math.max(Number(input.sortOrder || 0), 0),
|
||||
enabled: input.enabled !== false
|
||||
}
|
||||
const id = Number(input.id || 0)
|
||||
const product = id > 0 ? await productDao.updateProduct(id, data) : await productDao.createProduct(data)
|
||||
return serviceOk(toProductItem(product))
|
||||
},
|
||||
|
||||
async deleteManageProduct(id: number) {
|
||||
if (!Number.isInteger(id) || id <= 0) return serviceFail('商品ID不正确')
|
||||
const product = await productDao.findManageProduct(id)
|
||||
if (!product) return serviceFail('商品不存在')
|
||||
await productDao.updateProduct(id, { deleted: 1 })
|
||||
return serviceOk({})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
import type { Prisma } from '@prisma/client'
|
||||
import { prisma } from '../utils/prisma.js'
|
||||
import { supplierDao } from '../dao/supplier.dao.js'
|
||||
import { verifySupplierOpenSignature } from '../utils/supplier-open-crypto.js'
|
||||
import { serviceFail, serviceOk } from '../types/service-result.js'
|
||||
|
||||
export type ReconciliationResultItem = {
|
||||
orderId?: string
|
||||
mainOrderId?: string
|
||||
userId?: string
|
||||
reconciliationStatus?: number
|
||||
diffType?: number
|
||||
diffReason?: string
|
||||
platformTotalPrice?: number
|
||||
platformCashAmount?: number
|
||||
platformPointsPrice?: number
|
||||
platformRefundPrice?: number
|
||||
supplierTotalPrice?: number
|
||||
supplierCashAmount?: number
|
||||
supplierPointsPrice?: number
|
||||
supplierRefundPrice?: number
|
||||
}
|
||||
|
||||
export type ReconciliationResultCallbackInput = {
|
||||
supplierId?: string
|
||||
token?: string
|
||||
timestamp?: number
|
||||
reconciliationBatchNo?: string
|
||||
reconciliationTime?: string
|
||||
reconciliationResults?: ReconciliationResultItem[]
|
||||
AplParmObjct?: string
|
||||
}
|
||||
|
||||
export type ReconciliationResultListInput = {
|
||||
supplierId?: string
|
||||
reconciliationStatus?: number
|
||||
orderId?: string
|
||||
}
|
||||
|
||||
export type ReconciliationResultUpdateInput = {
|
||||
supplierId?: string
|
||||
orderId?: string
|
||||
reconciliationStatus?: number
|
||||
diffType?: number
|
||||
diffReason?: string
|
||||
}
|
||||
|
||||
const toNumber = (value?: number) => value === undefined || value === null ? null : Number(value)
|
||||
|
||||
const toTime = (value?: string) => {
|
||||
if (!value) return new Date()
|
||||
const time = new Date(value)
|
||||
return Number.isNaN(time.getTime()) ? new Date() : time
|
||||
}
|
||||
|
||||
const resultItem = (record: Awaited<ReturnType<typeof prisma.supplierReconciliationOrder.findMany>>[number]) => ({
|
||||
supplierId: record.supplierId,
|
||||
orderId: record.orderId,
|
||||
mainOrderId: record.mainOrderId || '',
|
||||
userId: record.userId || '',
|
||||
reconciliationStatus: record.reconciliationStatus,
|
||||
diffType: record.diffType,
|
||||
diffReason: record.diffReason || '',
|
||||
platformTotalPrice: record.platformTotalPrice?.toFixed(2) || '',
|
||||
platformCashAmount: record.platformCashAmount?.toFixed(2) || '',
|
||||
platformPointsPrice: record.platformPointsPrice?.toFixed(2) || '',
|
||||
platformRefundPrice: record.platformRefundPrice?.toFixed(2) || '',
|
||||
supplierTotalPrice: record.supplierTotalPrice?.toFixed(2) || '',
|
||||
supplierCashAmount: record.supplierCashAmount?.toFixed(2) || '',
|
||||
supplierPointsPrice: record.supplierPointsPrice?.toFixed(2) || '',
|
||||
supplierRefundPrice: record.supplierRefundPrice?.toFixed(2) || '',
|
||||
reconciliationBatchNo: record.reconciliationBatchNo || '',
|
||||
reconciliationTime: record.reconciliationTime,
|
||||
updateAt: record.updateAt
|
||||
})
|
||||
|
||||
export const reconciliationResultService = {
|
||||
async receiveCallback(input: ReconciliationResultCallbackInput) {
|
||||
const supplierId = String(input.supplierId || '').trim()
|
||||
const token = String(input.token || '').trim()
|
||||
const timestamp = Number(input.timestamp || 0)
|
||||
const records = Array.isArray(input.reconciliationResults) ? input.reconciliationResults : []
|
||||
if (!supplierId || !token || !timestamp || !records.length) {
|
||||
return { resultCode: 400, message: '供应商、签名或对账结果不能为空' }
|
||||
}
|
||||
|
||||
const supplier = await supplierDao.findActiveBySupplierId(supplierId)
|
||||
if (!supplier) return { resultCode: 404, message: '供应商信息不存在' }
|
||||
if (!verifySupplierOpenSignature(supplier.supplierId, supplier.clientId, timestamp, token)) {
|
||||
return { resultCode: 401, message: '签名无效或已过期' }
|
||||
}
|
||||
|
||||
const reconciliationTime = toTime(input.reconciliationTime)
|
||||
for (const record of records) {
|
||||
const orderId = String(record.orderId || '').trim()
|
||||
const status = Number(record.reconciliationStatus)
|
||||
if (!orderId || ![0, 1, 2].includes(status)) {
|
||||
return { resultCode: 400, message: '子订单ID或对账状态不正确' }
|
||||
}
|
||||
}
|
||||
|
||||
await prisma.$transaction(records.map(record => {
|
||||
const orderId = String(record.orderId || '').trim()
|
||||
const data = {
|
||||
mainOrderId: String(record.mainOrderId || '').trim() || null,
|
||||
userId: String(record.userId || '').trim() || null,
|
||||
reconciliationStatus: Number(record.reconciliationStatus),
|
||||
diffType: record.diffType === undefined || record.diffType === null ? null : Number(record.diffType),
|
||||
diffReason: String(record.diffReason || '').trim() || null,
|
||||
platformTotalPrice: toNumber(record.platformTotalPrice),
|
||||
platformCashAmount: toNumber(record.platformCashAmount),
|
||||
platformPointsPrice: toNumber(record.platformPointsPrice),
|
||||
platformRefundPrice: toNumber(record.platformRefundPrice),
|
||||
supplierTotalPrice: toNumber(record.supplierTotalPrice),
|
||||
supplierCashAmount: toNumber(record.supplierCashAmount),
|
||||
supplierPointsPrice: toNumber(record.supplierPointsPrice),
|
||||
supplierRefundPrice: toNumber(record.supplierRefundPrice),
|
||||
reconciliationBatchNo: String(input.reconciliationBatchNo || '').trim() || null,
|
||||
reconciliationTime,
|
||||
resultPayload: record as Prisma.InputJsonValue,
|
||||
deleted: 0
|
||||
}
|
||||
return prisma.supplierReconciliationOrder.upsert({
|
||||
where: { supplierId_orderId: { supplierId, orderId } },
|
||||
update: data,
|
||||
create: { supplierId, orderId, ...data }
|
||||
})
|
||||
}))
|
||||
|
||||
return { resultCode: 0, message: '成功' }
|
||||
},
|
||||
|
||||
async list(input: ReconciliationResultListInput) {
|
||||
const supplierId = String(input.supplierId || '').trim()
|
||||
if (!supplierId) return serviceFail('供应商不能为空')
|
||||
const reconciliationStatus = input.reconciliationStatus === undefined ? undefined : Number(input.reconciliationStatus)
|
||||
if (reconciliationStatus !== undefined && ![0, 1, 2].includes(reconciliationStatus)) {
|
||||
return serviceFail('对账状态不正确')
|
||||
}
|
||||
|
||||
const records = await prisma.supplierReconciliationOrder.findMany({
|
||||
where: {
|
||||
supplierId,
|
||||
deleted: 0,
|
||||
...(reconciliationStatus === undefined ? {} : { reconciliationStatus }),
|
||||
...(String(input.orderId || '').trim() ? { orderId: { contains: String(input.orderId).trim() } } : {})
|
||||
},
|
||||
orderBy: { updateAt: 'desc' }
|
||||
})
|
||||
return serviceOk({ reconciliationItems: records.map(resultItem) })
|
||||
},
|
||||
|
||||
async update(input: ReconciliationResultUpdateInput) {
|
||||
const supplierId = String(input.supplierId || '').trim()
|
||||
const orderId = String(input.orderId || '').trim()
|
||||
const reconciliationStatus = Number(input.reconciliationStatus)
|
||||
if (!supplierId || !orderId || ![0, 1, 2].includes(reconciliationStatus)) {
|
||||
return serviceFail('供应商、子订单或对账状态不正确')
|
||||
}
|
||||
|
||||
const record = await prisma.supplierReconciliationOrder.findUnique({
|
||||
where: { supplierId_orderId: { supplierId, orderId } }
|
||||
})
|
||||
if (!record || record.deleted !== 0) return serviceFail('对账结果不存在')
|
||||
|
||||
await prisma.supplierReconciliationOrder.update({
|
||||
where: { supplierId_orderId: { supplierId, orderId } },
|
||||
data: {
|
||||
reconciliationStatus,
|
||||
diffType: input.diffType === undefined || input.diffType === null ? null : Number(input.diffType),
|
||||
diffReason: String(input.diffReason || '').trim() || null
|
||||
}
|
||||
})
|
||||
return serviceOk({})
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,19 @@ export type SupplierOrderQueryRequest = {
|
||||
AplParmObjct?: string
|
||||
}
|
||||
|
||||
export type SupplierReconciliationQueryRequest = {
|
||||
supplierId?: string
|
||||
token?: string
|
||||
reconciliationType?: number
|
||||
orderId?: string
|
||||
startDate?: string
|
||||
endDate?: string
|
||||
page?: number
|
||||
pageSize?: number
|
||||
timestamp?: number
|
||||
AplParmObjct?: string
|
||||
}
|
||||
|
||||
const parseBody = (body: SupplierOrderQueryRequest) => {
|
||||
if (!body.AplParmObjct) return body
|
||||
|
||||
@@ -149,5 +162,66 @@ export const supplierOpenOrderService = {
|
||||
}))
|
||||
|
||||
return { resultCode: 0, message: '成功', orderInfo }
|
||||
},
|
||||
|
||||
async queryReconciliationInfo(body: SupplierReconciliationQueryRequest) {
|
||||
const supplierId = String(body.supplierId || '').trim()
|
||||
const token = String(body.token || '').trim()
|
||||
const reconciliationType = Number(body.reconciliationType || 0)
|
||||
const orderIds = String(body.orderId || '')
|
||||
.split(',')
|
||||
.map(item => item.trim())
|
||||
.filter(Boolean)
|
||||
const timestamp = Number(body.timestamp || 0)
|
||||
|
||||
if (!supplierId || !token || !timestamp) {
|
||||
return { resultCode: 400, message: '供应商或签名信息不能为空', orderInfos: [] }
|
||||
}
|
||||
if (reconciliationType === 1 && !body.startDate) {
|
||||
return { resultCode: 400, message: '请选择开始日期', orderInfos: [] }
|
||||
}
|
||||
if (reconciliationType === 2 && !orderIds.length) {
|
||||
return { resultCode: 400, message: '订单号不能为空', orderInfos: [] }
|
||||
}
|
||||
if (![1, 2].includes(reconciliationType)) {
|
||||
return { resultCode: 400, message: '对账类型不正确', orderInfos: [] }
|
||||
}
|
||||
|
||||
const supplier = await supplierDao.findActiveBySupplierId(supplierId)
|
||||
if (!supplier) {
|
||||
return { resultCode: 404, message: '供应商信息不存在', orderInfos: [] }
|
||||
}
|
||||
if (!verifySupplierOpenSignature(supplier.supplierId, supplier.clientId, timestamp, token)) {
|
||||
return { resultCode: 401, message: '签名无效或已过期', orderInfos: [] }
|
||||
}
|
||||
|
||||
const startDate = body.startDate ? new Date(`${body.startDate}T00:00:00`) : undefined
|
||||
const endDate = body.endDate ? new Date(`${body.endDate}T23:59:59`) : undefined
|
||||
if ((startDate && Number.isNaN(startDate.getTime())) || (endDate && Number.isNaN(endDate.getTime()))) {
|
||||
return { resultCode: 400, message: '对账日期格式不正确', orderInfos: [] }
|
||||
}
|
||||
|
||||
const orders = await orderDao.findOpenApiReconciliationSubOrders(
|
||||
supplierId,
|
||||
orderIds,
|
||||
startDate,
|
||||
endDate,
|
||||
reconciliationType === 1 ? ORDER_STATE.COMPLETED : undefined
|
||||
)
|
||||
const page = Math.max(Number(body.page || 1), 1)
|
||||
const pageSize = Math.max(Number(body.pageSize || 100), 1)
|
||||
const totalPage = Math.max(Math.ceil(orders.length / pageSize), 1)
|
||||
const pagedOrders = orders.slice((page - 1) * pageSize, page * pageSize)
|
||||
const orderInfos = pagedOrders.map(order => ({
|
||||
orderId: order.orderId,
|
||||
supplierId: order.supplierId,
|
||||
totalPrice: toMoney(order.totalPrice),
|
||||
pointsPrice: toMoney(order.pointsPrice),
|
||||
wPayOrAPay: toMoney(order.wPayOrAPay),
|
||||
invoiceNakedPrice: toMoney(order.totalPrice),
|
||||
orderProInfos: toOrderProductInfo(order)
|
||||
}))
|
||||
|
||||
return { resultCode: 0, message: '成功', totalPage, currentPage: page, orderInfos }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user