diff --git a/app/database/migrations/20240625083758_insert_teammembers_for_all_org_owners_without_team_member/migration.sql b/app/database/migrations/20240625083758_insert_teammembers_for_all_org_owners_without_team_member/migration.sql new file mode 100644 index 000000000..488559bf7 --- /dev/null +++ b/app/database/migrations/20240625083758_insert_teammembers_for_all_org_owners_without_team_member/migration.sql @@ -0,0 +1,16 @@ +-- It is used to insert team members for all organization owners who do not have a team member record. +-- To test if the migration works, you can run the same query without the first line (INSERT INTO "TeamMember" ...) and check the results. +INSERT INTO "TeamMember" (id, name, "organizationId", "userId", "createdAt", "updatedAt") +SELECT + 'c' || md5(random()::text || clock_timestamp()::text)::uuid, -- Simulates cuid generation + COALESCE(u."firstName", '') || ' ' || COALESCE(u."lastName", ''), -- Combines first name and last name, replacing NULL with empty string + o.id, -- Organization ID + o."userId", -- User ID + NOW(), -- Current timestamp for createdAt + NOW() -- Current timestamp for updatedAt +FROM + "Organization" o + LEFT JOIN "TeamMember" tm ON o.id = tm."organizationId" AND o."userId" = tm."userId" + JOIN "User" u ON o."userId" = u.id +WHERE + tm.id IS NULL; diff --git a/app/modules/asset/service.server.ts b/app/modules/asset/service.server.ts index 03932d0bb..d367bdcf0 100644 --- a/app/modules/asset/service.server.ts +++ b/app/modules/asset/service.server.ts @@ -1840,6 +1840,7 @@ export async function createAssetsFromContentImport({ customFieldsValues, }); } catch (error) { + // eslint-disable-next-line no-console console.error("Error processing asset", error); // Handle the error as needed } diff --git a/app/modules/organization/service.server.ts b/app/modules/organization/service.server.ts index c620e6b3f..3cd3dac29 100644 --- a/app/modules/organization/service.server.ts +++ b/app/modules/organization/service.server.ts @@ -114,6 +114,8 @@ export async function createOrganization({ image: File | null; }) { try { + const owner = await db.user.findFirstOrThrow({ where: { id: userId } }); + const data = { name, currency, @@ -132,7 +134,17 @@ export async function createOrganization({ id: userId, }, }, - }; + /** + * Creating a teamMember when a new organization/workspace is created + * so that the owner appear in the list by default + */ + members: { + create: { + name: `${owner.firstName} ${owner.lastName} (Owner)`, + user: { connect: { id: owner.id } }, + }, + }, + } satisfies Prisma.OrganizationCreateInput; const org = await db.organization.create({ data }); diff --git a/app/modules/team-member/service.server.ts b/app/modules/team-member/service.server.ts index 099aebc98..909079b16 100644 --- a/app/modules/team-member/service.server.ts +++ b/app/modules/team-member/service.server.ts @@ -212,59 +212,36 @@ export async function getTeamMemberForCustodianFilter({ getAll?: boolean; }) { try { - const [ - teamMemberExcludedSelected, - teamMembersSelected, - totalTeamMembers, - org, - ] = await Promise.all([ - db.teamMember.findMany({ - where: { - organizationId, - id: { notIn: selectedTeamMembers }, - deletedAt: null, - }, - include: { - user: { - select: { - firstName: true, - lastName: true, - email: true, + const [teamMemberExcludedSelected, teamMembersSelected, totalTeamMembers] = + await Promise.all([ + db.teamMember.findMany({ + where: { + organizationId, + id: { notIn: selectedTeamMembers }, + deletedAt: null, + }, + include: { + user: { + select: { + firstName: true, + lastName: true, + email: true, + }, }, }, - }, - take: getAll ? undefined : 12, - }), - db.teamMember.findMany({ - where: { organizationId, id: { in: selectedTeamMembers } }, - }), - db.teamMember.count({ where: { organizationId, deletedAt: null } }), - db.organization.findUnique({ - where: { id: organizationId }, - select: { owner: true }, - }), - ]); + take: getAll ? undefined : 12, + }), + db.teamMember.findMany({ + where: { organizationId, id: { in: selectedTeamMembers } }, + }), + db.teamMember.count({ where: { organizationId, deletedAt: null } }), + ]); const allTeamMembers = [ ...teamMembersSelected, ...teamMemberExcludedSelected, ]; - /** - * Owners can be assigned in bookings so have to add it to the list - */ - if (org?.owner && typeof org.owner.id === "string") { - allTeamMembers.push({ - id: "owner", - name: `${org.owner.firstName} ${org.owner.lastName} (Owner)`, - userId: org.owner.id, - organizationId, - createdAt: new Date(), - updatedAt: new Date(), - deletedAt: null, - }); - } - /** * If teamMember has a user associated then we have to use that user's id * otherwise we have to use teamMember's id diff --git a/app/modules/user/service.server.test.ts b/app/modules/user/service.server.test.ts index dccb15ea4..5117bb1fd 100644 --- a/app/modules/user/service.server.test.ts +++ b/app/modules/user/service.server.test.ts @@ -242,6 +242,12 @@ describe(createUserAccountForTesting.name, () => { userId: USER_ID, })), }, + members: { + create: { + name: `${undefined} ${undefined} (Owner)`, + user: { connect: { id: USER_ID } }, + }, + }, }, ], }, diff --git a/app/modules/user/service.server.ts b/app/modules/user/service.server.ts index 5e31702ae..003caee65 100644 --- a/app/modules/user/service.server.ts +++ b/app/modules/user/service.server.ts @@ -445,6 +445,11 @@ export async function createUser( username, firstName, lastName, + roles: { + connect: { + name: Roles["USER"], + }, + }, ...(!isSSO && { organizations: { create: [ @@ -456,15 +461,20 @@ export async function createUser( userId, })), }, + /** + * Creating a teamMember when a new organization/workspace is created + * so that the owner appear in the list by default + */ + members: { + create: { + name: `${firstName} ${lastName} (Owner)`, + user: { connect: { id: userId } }, + }, + }, }, ], }, }), - roles: { - connect: { - name: Roles["USER"], - }, - }, ...(isSSO && { // When user is coming from SSO, we set them as onboarded as we already have their first and last name and they dont need a password. onboarded: true, @@ -477,7 +487,8 @@ export async function createUser( }, }); - /** Create user organization association + /** + * Creating an organization for the user * 1. For the personal org * 2. For the org that the user is being attached to */