diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/server/__tests__/issues.test.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/server/__tests__/issues.test.ts new file mode 100644 index 0000000000..1e924f7e69 --- /dev/null +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/server/__tests__/issues.test.ts @@ -0,0 +1,67 @@ +/** + * This file is part of the NocoBase (R) project. + * Copyright (c) 2020-2024 NocoBase Co., Ltd. + * Authors: NocoBase Team. + * + * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. + * For more information, please refer to: https://www.nocobase.com/agreement. + */ + +import { Database, Repository } from '@nocobase/database'; +import { MockServer, createMockServer } from '@nocobase/test'; +import compose from 'koa-compose'; +import { parseFieldAndAssociations, queryData } from '../actions/query'; +import { createQueryParser } from '../query-parser'; + +describe('api', () => { + let app: MockServer; + let db: Database; + + beforeAll(async () => { + app = await createMockServer({ + plugins: ['users', 'auth', 'data-visualization', 'data-source-manager', 'acl', 'error-handler'], + }); + db = app.db; + }); + + afterAll(async () => { + await app.destroy(); + }); + + test('query with nested m2m filter', async () => { + const ctx = { + app, + db, + action: { + params: { + values: { + collection: 'users', + measures: [ + { + field: ['id'], + aggregation: 'count', + alias: 'id', + }, + ], + filter: { + $and: [ + { + createdBy: { + roles: { + name: { + $includes: 'member', + }, + }, + }, + }, + ], + }, + }, + }, + }, + } as any; + const queryParser = createQueryParser(db); + await compose([parseFieldAndAssociations, queryParser.parse(), queryData])(ctx, async () => {}); + expect(ctx.action.params.values.data).toBeDefined(); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/server/__tests__/query.test.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/server/__tests__/query.test.ts index 2c4070679c..e61035a14a 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/src/server/__tests__/query.test.ts +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/server/__tests__/query.test.ts @@ -18,9 +18,7 @@ import { postProcess, } from '../actions/query'; import { Database } from '@nocobase/database'; -import * as formatter from '../formatter'; import { createQueryParser } from '../query-parser'; -import { QueryParser } from '../query-parser/query-parser'; describe('query', () => { describe('parseBuilder', () => { diff --git a/packages/plugins/@nocobase/plugin-data-visualization/src/server/actions/query.ts b/packages/plugins/@nocobase/plugin-data-visualization/src/server/actions/query.ts index 631937a59a..51a76aac47 100644 --- a/packages/plugins/@nocobase/plugin-data-visualization/src/server/actions/query.ts +++ b/packages/plugins/@nocobase/plugin-data-visualization/src/server/actions/query.ts @@ -149,20 +149,26 @@ export const parseFieldAndAssociations = async (ctx: Context, next: Next) => { collection, }); const { where, include: filterInclude } = filterParser.toSequelizeParams(); - const parsedFilterInclude = filterInclude?.map((item) => { - if (fields.get(item.association)?.type === 'belongsToMany') { - item.through = { attributes: [] }; + if (filterInclude) { + // Remove attributes from through table + const stack = [...filterInclude]; + while (stack.length) { + const item = stack.pop(); + if (fields.get(item.association)?.type === 'belongsToMany') { + item.through = { attributes: [] }; + } + if (item.include) { + stack.push(...item.include); + } } - return item; - }); - + } ctx.action.params.values = { ...ctx.action.params.values, where, measures: parsedMeasures, dimensions: parsedDimensions, orders: parsedOrders, - include: [...include, ...(parsedFilterInclude || [])], + include: [...include, ...(filterInclude || [])], }; await next(); };