feat(M08-D): 补后台订单运营
This commit is contained in:
@@ -32,29 +32,31 @@ export async function registerOrderQueryRoutes(
|
||||
app: FastifyInstance,
|
||||
options: OrderQueryRouteOptions
|
||||
) {
|
||||
app.get('/app-api/orders', async (request, reply) => {
|
||||
const auth = await authenticate(request.headers.authorization, options);
|
||||
const query = listSchema.safeParse(request.query);
|
||||
if (!auth) return unauthorized(reply, request.traceId);
|
||||
if (!query.success) return invalid(reply, request.traceId);
|
||||
return {
|
||||
code: 0,
|
||||
data: await options.repository.listMine({ ...auth, ...query.data }),
|
||||
traceId: request.traceId
|
||||
};
|
||||
});
|
||||
for (const prefix of ['/app-api/orders', '/admin-api/orders', '/app-api/management/orders']) {
|
||||
app.get(prefix, async (request, reply) => {
|
||||
const auth = await authenticate(request.headers.authorization, options);
|
||||
const query = listSchema.safeParse(request.query);
|
||||
if (!auth) return unauthorized(reply, request.traceId);
|
||||
if (!query.success) return invalid(reply, request.traceId);
|
||||
return {
|
||||
code: 0,
|
||||
data: await options.repository.listMine({ ...auth, ...query.data }),
|
||||
traceId: request.traceId
|
||||
};
|
||||
});
|
||||
|
||||
app.get('/app-api/orders/:orderId', async (request, reply) => {
|
||||
const auth = await authenticate(request.headers.authorization, options);
|
||||
const params = paramsSchema.safeParse(request.params);
|
||||
if (!auth) return unauthorized(reply, request.traceId);
|
||||
if (!params.success) return invalid(reply, request.traceId);
|
||||
return handle(reply, request.traceId, async () => ({
|
||||
code: 0,
|
||||
data: await options.repository.getMine({ ...auth, orderId: params.data.orderId }),
|
||||
traceId: request.traceId
|
||||
}));
|
||||
});
|
||||
app.get(`${prefix}/:orderId`, async (request, reply) => {
|
||||
const auth = await authenticate(request.headers.authorization, options);
|
||||
const params = paramsSchema.safeParse(request.params);
|
||||
if (!auth) return unauthorized(reply, request.traceId);
|
||||
if (!params.success) return invalid(reply, request.traceId);
|
||||
return handle(reply, request.traceId, async () => ({
|
||||
code: 0,
|
||||
data: await options.repository.getMine({ ...auth, orderId: params.data.orderId }),
|
||||
traceId: request.traceId
|
||||
}));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function authenticate(
|
||||
|
||||
@@ -27,19 +27,25 @@ export interface OrderStateRouteOptions {
|
||||
export async function registerOrderStateRoutes(
|
||||
app: FastifyInstance, options: OrderStateRouteOptions
|
||||
) {
|
||||
app.get('/app-api/orders/:orderId/history', async (request, reply) => {
|
||||
const auth = await authenticate(request.headers.authorization, options);
|
||||
const params = paramsSchema.safeParse(request.params);
|
||||
if (!auth) return unauthorized(reply, request.traceId);
|
||||
if (!params.success) return invalid(reply, request.traceId);
|
||||
return handle(reply, request.traceId, async () => ({
|
||||
code: 0,
|
||||
data: await options.repository.history(
|
||||
auth.tenantId, auth.userId, params.data.orderId, auth.access
|
||||
),
|
||||
traceId: request.traceId
|
||||
}));
|
||||
});
|
||||
for (const path of [
|
||||
'/app-api/orders/:orderId/history',
|
||||
'/admin-api/orders/:orderId/history',
|
||||
'/app-api/management/orders/:orderId/history'
|
||||
]) {
|
||||
app.get(path, async (request, reply) => {
|
||||
const auth = await authenticate(request.headers.authorization, options);
|
||||
const params = paramsSchema.safeParse(request.params);
|
||||
if (!auth) return unauthorized(reply, request.traceId);
|
||||
if (!params.success) return invalid(reply, request.traceId);
|
||||
return handle(reply, request.traceId, async () => ({
|
||||
code: 0,
|
||||
data: await options.repository.history(
|
||||
auth.tenantId, auth.userId, params.data.orderId, auth.access
|
||||
),
|
||||
traceId: request.traceId
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
app.post('/app-api/orders/:orderId/cancel', async (request, reply) => {
|
||||
const auth = await authenticate(request.headers.authorization, options);
|
||||
|
||||
@@ -89,6 +89,14 @@ assert.equal(listInput.pageSize, 5);
|
||||
assert.equal(listInput.status, 'PENDING_PAYMENT');
|
||||
assert.equal(listInput.storeId, '18');
|
||||
|
||||
const adminListed = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/admin-api/orders?page=1&pageSize=20&storeId=18',
|
||||
headers: { authorization: `Bearer ${token}` }
|
||||
});
|
||||
assert.equal(adminListed.statusCode, 200);
|
||||
assert.equal(listInput.storeId, '18');
|
||||
|
||||
const detail = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/app-api/orders/31',
|
||||
@@ -97,6 +105,13 @@ const detail = await app.inject({
|
||||
assert.equal(detail.statusCode, 200);
|
||||
assert.equal(detailInput.orderId, '31');
|
||||
|
||||
const adminDetail = await app.inject({
|
||||
method: 'GET', url: '/admin-api/orders/31',
|
||||
headers: { authorization: `Bearer ${token}` }
|
||||
});
|
||||
assert.equal(adminDetail.statusCode, 200);
|
||||
assert.equal(detailInput.orderId, '31');
|
||||
|
||||
const unauthenticated = await app.inject({
|
||||
method: 'GET',
|
||||
url: '/app-api/orders'
|
||||
|
||||
@@ -8,6 +8,7 @@ const token = signAccessToken({
|
||||
tid: '7', aid: '9', rv: 1
|
||||
}, secret, 900);
|
||||
let transitionInput;
|
||||
let historyInput;
|
||||
const options = {
|
||||
jwtSecret: secret,
|
||||
authRepository: {
|
||||
@@ -33,7 +34,10 @@ const options = {
|
||||
transitionInput = { actor, orderId, action, reason };
|
||||
return { orderId, status: action === 'CANCEL' ? 'CANCELLED' : 'PAID' };
|
||||
},
|
||||
async history() { return []; }
|
||||
async history(tenantId, userId, orderId, access) {
|
||||
historyInput = { tenantId, userId, orderId, access };
|
||||
return [{ id: '1', fromStatus: null, toStatus: 'DRAFT', action: 'CREATED' }];
|
||||
}
|
||||
}
|
||||
};
|
||||
const app = await buildApp({ orderState: options });
|
||||
@@ -76,6 +80,15 @@ assert.equal(transitionInput.action, 'START');
|
||||
assert.equal(transitionInput.actor.source, 'ADMIN');
|
||||
assert.equal(transitionInput.actor.traceId, 'm08c-route-transition');
|
||||
|
||||
const adminHistory = await app.inject({
|
||||
method: 'GET', url: '/admin-api/orders/31/history',
|
||||
headers: { authorization: `Bearer ${token}` }
|
||||
});
|
||||
assert.equal(adminHistory.statusCode, 200);
|
||||
assert.equal(adminHistory.json().data[0].action, 'CREATED');
|
||||
assert.equal(historyInput.orderId, '31');
|
||||
assert.equal(historyInput.access.roles[0], 'TENANT_ADMIN');
|
||||
|
||||
const cancelled = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/app-api/orders/31/cancel',
|
||||
|
||||
Reference in New Issue
Block a user