feat(M09-D4): 完成商品选购与运营工作台
This commit is contained in:
@@ -113,8 +113,10 @@ function adminAccess(access: AccessProfile) {
|
||||
const storeRead = tenant || access.capabilities.includes('store.operation.read');
|
||||
const menus = [
|
||||
...(storeRead ? ['overview', 'stores', 'orders', 'thirdParty'] : []),
|
||||
...(tenant || access.capabilities.includes('product.catalog.read')
|
||||
|| access.capabilities.includes('inventory.read') ? ['products'] : []),
|
||||
...(tenant || access.capabilities.some((capability) => [
|
||||
'product.catalog.read', 'product.catalog.write', 'inventory.read', 'inventory.adjust',
|
||||
'goods.order.read', 'goods.order.manage', 'goods.storage.read', 'goods.storage.manage'
|
||||
].includes(capability)) ? ['products'] : []),
|
||||
...(tenant ? ['platformApps', 'content', 'franchise', 'system', 'payments', 'people'] : []),
|
||||
...(tenant || access.capabilities.includes('device.read') ? ['devices'] : []),
|
||||
...(tenant || access.capabilities.includes('cleaning.task.read') ? ['cleaning'] : [])
|
||||
|
||||
@@ -119,13 +119,34 @@ export interface ProductRouteOptions {
|
||||
| 'listProducts' | 'createProduct' | 'updateProduct' | 'archiveProduct'
|
||||
| 'listSkus' | 'createSku' | 'updateSku' | 'archiveSku'
|
||||
| 'listListings' | 'putListing' | 'archiveListing'
|
||||
| 'getStoreSettings' | 'putStoreSettings'>;
|
||||
| 'getStoreSettings' | 'putStoreSettings' | 'listStoreCatalog'>;
|
||||
authRepository: Pick<AuthRepository, 'validateSession'>;
|
||||
accessControl: { getAccessProfile(tenantId: string, userId: string): Promise<AccessProfile> };
|
||||
jwtSecret: string;
|
||||
}
|
||||
|
||||
export async function registerProductRoutes(app: FastifyInstance, options: ProductRouteOptions) {
|
||||
app.get('/app-api/stores/:storeId/product-catalog', async (request, reply) => {
|
||||
const auth = await authenticateAccessToken(
|
||||
request.headers.authorization, options.authRepository, options.jwtSecret
|
||||
);
|
||||
const params = storeParamsSchema.safeParse(request.params);
|
||||
if (!auth) {
|
||||
reply.status(401).send({
|
||||
code: 'AUTH_SESSION_INVALID', message: 'Authentication required.', traceId: request.traceId
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!params.success) return invalid(reply, request.traceId);
|
||||
return handle(reply, request.traceId, async () => ({
|
||||
code: 0,
|
||||
data: await options.repository.listStoreCatalog({
|
||||
tenantId: auth.session.tenantId, storeId: params.data.storeId
|
||||
}),
|
||||
traceId: request.traceId
|
||||
}));
|
||||
});
|
||||
|
||||
for (const path of [
|
||||
'/admin-api/stores/:storeId/product-categories',
|
||||
'/app-api/management/stores/:storeId/product-categories'
|
||||
|
||||
@@ -24,6 +24,9 @@ const record = (method, result) => async (...args) => {
|
||||
return typeof result === 'function' ? result(...args) : result;
|
||||
};
|
||||
const repository = {
|
||||
listStoreCatalog: record('listStoreCatalog', {
|
||||
storeId: '11', salesOpen: true, categories: []
|
||||
}),
|
||||
listCategories: record('listCategories', []),
|
||||
createCategory: record('createCategory', { categoryId: '31', version: 1 }),
|
||||
updateCategory: record('updateCategory', { categoryId: '31', version: 2 }),
|
||||
@@ -79,6 +82,18 @@ const unauthorized = await app.inject({
|
||||
assert.equal(unauthorized.statusCode, 401);
|
||||
assert.equal(unauthorized.json().code, 'AUTH_SESSION_INVALID');
|
||||
|
||||
assert.equal((await app.inject({
|
||||
method: 'GET', url: '/app-api/stores/11/product-catalog'
|
||||
})).statusCode, 401);
|
||||
const customerCatalog = await app.inject({
|
||||
method: 'GET', url: '/app-api/stores/11/product-catalog',
|
||||
headers: { authorization: `Bearer ${token}` }
|
||||
});
|
||||
assert.equal(customerCatalog.statusCode, 200);
|
||||
assert.deepEqual(calls.find((call) => call.method === 'listStoreCatalog').args[0], {
|
||||
tenantId: '7', storeId: '11'
|
||||
});
|
||||
|
||||
currentAccess = { roles: ['STAFF'], capabilities: [], storeIds: ['11'] };
|
||||
const forbidden = await app.inject({
|
||||
method: 'GET', url: '/admin-api/products', headers: { authorization: `Bearer ${token}` }
|
||||
|
||||
Reference in New Issue
Block a user