From 0291eb4ba406c0e65a3f9dfa3fd73955b3537559 Mon Sep 17 00:00:00 2001 From: ChengLei Shao Date: Wed, 17 Apr 2024 19:26:43 +0800 Subject: [PATCH] fix: load with source field (#4075) * test: belongs to a view collection * fix: load with source field --- .../server/__tests__/collection-load.test.ts | 192 ++++++++++++++++++ .../repositories/collection-repository.ts | 10 +- 2 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/collection-load.test.ts diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/collection-load.test.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/collection-load.test.ts new file mode 100644 index 0000000000..199d39622b --- /dev/null +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/server/__tests__/collection-load.test.ts @@ -0,0 +1,192 @@ +import Database, { Repository } from '@nocobase/database'; +import Application from '@nocobase/server'; +import { createApp } from './index'; +import { uid } from '@nocobase/utils'; + +describe('load collections', function () { + let db: Database; + let app: Application; + + let collectionRepository: Repository; + + let fieldsRepository: Repository; + + beforeEach(async () => { + app = await createApp({ + database: { + tablePrefix: '', + }, + }); + + db = app.db; + + collectionRepository = db.getCollection('collections').repository; + fieldsRepository = db.getCollection('fields').repository; + }); + + afterEach(async () => { + await app.destroy(); + }); + + it('should load belongs to view collection', async () => { + await collectionRepository.create({ + values: { + name: 'groups', + fields: [ + { name: 'id', type: 'bigInt', primaryKey: true, autoIncrement: true }, + { name: 'name', type: 'string' }, + ], + }, + context: {}, + }); + + await collectionRepository.create({ + values: { + name: 'users', + fields: [ + { name: 'id', type: 'bigInt', primaryKey: true, autoIncrement: true }, + { name: 'name', type: 'string' }, + { type: 'belongsTo', name: 'group', foreignKey: 'groupId' }, + ], + }, + context: {}, + }); + + await db.getCollection('users').repository.create({ + values: { + name: '张三', + group: { + name: '技术部', + }, + }, + }); + + const viewName = `test_view_${uid(6)}`; + // create view from users + const createSQL = `CREATE VIEW ${viewName} AS SELECT * FROM ${db.getCollection('groups').quotedTableName()}`; + + await db.sequelize.query(createSQL); + + await collectionRepository.create({ + values: { + name: viewName, + view: true, + fields: [ + { name: 'id', source: 'groups.id', type: 'bigInt' }, + { name: 'name', source: 'groups.name', type: 'string' }, + ], + schema: db.inDialect('postgres') ? 'public' : undefined, + }, + context: {}, + }); + + // create belongsTo relation in groups + await fieldsRepository.create({ + values: { + name: 'groupAlias', + type: 'belongsTo', + collectionName: 'users', + target: viewName, + foreignKey: 'groupId', + targetKey: 'id', + }, + context: {}, + }); + + await app.runCommand('restart'); + + db = app.db; + + const User = db.getCollection('users'); + + expect(User.model.associations.groupAlias).toBeTruthy(); + const users = await db.getRepository('users').find({ + appends: ['groupAlias'], + }); + + expect(users[0].groupAlias.name).toBe('技术部'); + }); + + it('should load collections has many to view collection', async () => { + await collectionRepository.create({ + values: { + name: 'groups', + fields: [{ name: 'name', type: 'string' }], + }, + context: {}, + }); + + await collectionRepository.create({ + values: { + name: 'users', + fields: [ + { name: 'id', type: 'bigInt', primaryKey: true, autoIncrement: true }, + { name: 'name', type: 'string' }, + { type: 'belongsTo', name: 'group', foreignKey: 'groupId' }, + ], + }, + context: {}, + }); + + await db.getCollection('users').repository.create({ + values: { + name: '张三', + group: { + name: '技术部', + }, + }, + }); + + const User = db.getCollection('users'); + + const viewName = `test_view_${uid(6)}`; + const assoc = User.model.associations.group; + const foreignKey = assoc.foreignKey; + const foreignField = User.model.rawAttributes[foreignKey].field; + + // create view from users + const createSQL = `CREATE VIEW ${viewName} AS SELECT * FROM ${db.getCollection('users').quotedTableName()}`; + + await db.sequelize.query(createSQL); + + await collectionRepository.create({ + values: { + name: viewName, + view: true, + fields: [ + { name: 'id', source: 'users.id', type: 'bigInt' }, + { name: 'groupId', source: 'users.groupId', type: 'bigInt' }, + { name: 'name', source: 'users.name', type: 'string' }, + ], + schema: db.inDialect('postgres') ? 'public' : undefined, + }, + context: {}, + }); + + // create hasMany relation in groups + await fieldsRepository.create({ + values: { + name: 'users', + type: 'hasMany', + collectionName: 'groups', + target: viewName, + foreignKey: 'groupId', + targetKey: 'id', + }, + context: {}, + }); + + await app.runCommand('restart'); + + db = app.db; + + const group = db.getCollection('groups'); + expect(group.getField('users')).toBeTruthy(); + + const groups = await db.getRepository('groups').find({ + appends: ['users'], + }); + + expect(groups[0].users.length).toBe(1); + }); +}); diff --git a/packages/plugins/@nocobase/plugin-collection-manager/src/server/repositories/collection-repository.ts b/packages/plugins/@nocobase/plugin-collection-manager/src/server/repositories/collection-repository.ts index 44d9547789..f98025e116 100644 --- a/packages/plugins/@nocobase/plugin-collection-manager/src/server/repositories/collection-repository.ts +++ b/packages/plugins/@nocobase/plugin-collection-manager/src/server/repositories/collection-repository.ts @@ -110,7 +110,15 @@ export class CollectionRepository extends Repository { const skipField = (() => { const fields = nameMap[viewCollectionName].get('fields'); - return fields.filter((field) => field.options?.source).map((field) => field.get('name')); + return fields + .filter((field) => { + if (field.options?.source && (field['type'] === 'belongsTo' || field['type'] === 'belongsToMany')) { + return true; + } + + return false; + }) + .map((field) => field.get('name')); })(); this.app.setMaintainingMessage(`load ${viewCollectionName} collection fields`);