diff --git a/server/src/core/pipeline/seed-data/pipeline-stages.json b/server/src/core/pipeline/seed-data/pipeline-stages.json new file mode 100644 index 000000000..851b8cd59 --- /dev/null +++ b/server/src/core/pipeline/seed-data/pipeline-stages.json @@ -0,0 +1,33 @@ +[ + { + "name": "New", + "color": "#B76796", + "index": 0, + "type": "open" + }, + { + "name": "Screening", + "color": "#CB912F", + "index": 1, + "type": "ongoing" + }, + { + "name": "Meeting", + "color": "#9065B0", + "index": 2, + "type": "ongoing" + }, + { + "name": "Proposal", + "color": "#337EA9", + "index": 3, + "type": "ongoing" + }, + { + "name": "Customer", + "color": "#079039", + "index": 4, + "type": "won" + } + ] + \ No newline at end of file diff --git a/server/src/core/pipeline/seed-data/sales-pipeline.json b/server/src/core/pipeline/seed-data/sales-pipeline.json new file mode 100644 index 000000000..8084910ad --- /dev/null +++ b/server/src/core/pipeline/seed-data/sales-pipeline.json @@ -0,0 +1,6 @@ +{ + "name": "Sales pipeline", + "icon": "💰", + "pipelineProgressableType": "Company" +} + diff --git a/server/src/core/pipeline/services/pipeline-stage.service.ts b/server/src/core/pipeline/services/pipeline-stage.service.ts index 8aaf352ce..c2fa64b0c 100644 --- a/server/src/core/pipeline/services/pipeline-stage.service.ts +++ b/server/src/core/pipeline/services/pipeline-stage.service.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from 'src/database/prisma.service'; +import seedPipelineStages from '../seed-data/pipeline-stages.json'; @Injectable() export class PipelineStageService { @@ -35,4 +36,22 @@ export class PipelineStageService { // GroupBy groupBy = this.prismaService.pipelineStage.groupBy; + + // Customs + async createDefaultPipelineStages({ + workspaceId, + pipelineId, + }: { + workspaceId: string; + pipelineId: string; + }) { + const pipelineStages = seedPipelineStages.map((pipelineStage) => ({ + ...pipelineStage, + workspaceId, + pipelineId, + })); + return this.createMany({ + data: pipelineStages, + }); + } } diff --git a/server/src/core/pipeline/services/pipeline.service.ts b/server/src/core/pipeline/services/pipeline.service.ts index 201be8f0b..713a5dbb6 100644 --- a/server/src/core/pipeline/services/pipeline.service.ts +++ b/server/src/core/pipeline/services/pipeline.service.ts @@ -1,5 +1,7 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from 'src/database/prisma.service'; +import seedSalesPipeline from '../seed-data/sales-pipeline.json'; +import { PipelineProgressableType } from '@prisma/client'; @Injectable() export class PipelineService { @@ -35,4 +37,18 @@ export class PipelineService { // GroupBy groupBy = this.prismaService.pipeline.groupBy; + + // Customs + async createDefaultPipeline({ workspaceId }: { workspaceId: string }) { + const pipeline = { + ...seedSalesPipeline, + pipelineProgressableType: + seedSalesPipeline.pipelineProgressableType as PipelineProgressableType, + workspaceId, + }; + + return this.create({ + data: pipeline, + }); + } } diff --git a/server/src/core/user/user.module.ts b/server/src/core/user/user.module.ts index d8f3b3b73..d70bc8ca7 100644 --- a/server/src/core/user/user.module.ts +++ b/server/src/core/user/user.module.ts @@ -2,9 +2,10 @@ import { Module } from '@nestjs/common'; import { UserService } from './user.service'; import { UserResolver } from './user.resolver'; import { FileModule } from '../file/file.module'; +import { WorkspaceModule } from '../workspace/workspace.module'; @Module({ - imports: [FileModule], + imports: [FileModule, WorkspaceModule], providers: [UserService, UserResolver], exports: [UserService], }) diff --git a/server/src/core/user/user.service.spec.ts b/server/src/core/user/user.service.spec.ts index 94fa79a48..e3d0f3546 100644 --- a/server/src/core/user/user.service.spec.ts +++ b/server/src/core/user/user.service.spec.ts @@ -2,6 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing'; import { UserService } from './user.service'; import { PrismaService } from 'src/database/prisma.service'; import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; +import { WorkspaceService } from '../workspace/services/workspace.service'; describe('UserService', () => { let service: UserService; @@ -14,6 +15,10 @@ describe('UserService', () => { provide: PrismaService, useValue: prismaMock, }, + { + provide: WorkspaceService, + useValue: {}, + }, ], }).compile(); diff --git a/server/src/core/user/user.service.ts b/server/src/core/user/user.service.ts index 7bb12d766..c3a075a90 100644 --- a/server/src/core/user/user.service.ts +++ b/server/src/core/user/user.service.ts @@ -2,6 +2,7 @@ import { BadRequestException, Injectable } from '@nestjs/common'; import { PrismaService } from 'src/database/prisma.service'; import { Prisma } from '@prisma/client'; import { assert } from 'src/utils/assert'; +import { WorkspaceService } from '../workspace/services/workspace.service'; export type UserPayload = { displayName: string | undefined | null; @@ -10,7 +11,10 @@ export type UserPayload = { @Injectable() export class UserService { - constructor(private readonly prismaService: PrismaService) {} + constructor( + private readonly prismaService: PrismaService, + private readonly workspaceService: WorkspaceService, + ) {} // Find findFirst = this.prismaService.user.findFirst; @@ -50,6 +54,18 @@ export class UserService { ): Promise> { assert(args.data.email, 'email is missing', BadRequestException); + // Create workspace if not exists + const workspace = workspaceId + ? await this.workspaceService.findUnique({ + where: { + id: workspaceId, + }, + }) + : await this.workspaceService.createDefaultWorkspace(); + + assert(workspace, 'workspace is missing', BadRequestException); + + // Create user const user = await this.prismaService.user.upsert({ where: { email: args.data.email, @@ -57,22 +73,13 @@ export class UserService { create: { ...(args.data as Prisma.UserCreateInput), - workspaceMember: workspaceId - ? { - create: { - workspace: { - connect: { id: workspaceId }, - }, - }, - } - : // Assign the user to a new workspace by default - { - create: { - workspace: { - create: {}, - }, - }, + workspaceMember: { + create: { + workspace: { + connect: { id: workspace.id }, }, + }, + }, locale: 'en', }, update: {}, diff --git a/server/src/core/workspace/services/workspace.service.spec.ts b/server/src/core/workspace/services/workspace.service.spec.ts index 965c60962..396767c42 100644 --- a/server/src/core/workspace/services/workspace.service.spec.ts +++ b/server/src/core/workspace/services/workspace.service.spec.ts @@ -2,6 +2,8 @@ import { Test, TestingModule } from '@nestjs/testing'; import { WorkspaceService } from './workspace.service'; import { PrismaService } from 'src/database/prisma.service'; import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; +import { PipelineService } from 'src/core/pipeline/services/pipeline.service'; +import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage.service'; describe('WorkspaceService', () => { let service: WorkspaceService; @@ -14,6 +16,14 @@ describe('WorkspaceService', () => { provide: PrismaService, useValue: prismaMock, }, + { + provide: PipelineService, + useValue: {}, + }, + { + provide: PipelineStageService, + useValue: {}, + }, ], }).compile(); diff --git a/server/src/core/workspace/services/workspace.service.ts b/server/src/core/workspace/services/workspace.service.ts index 75d1639f9..75ecd16f5 100644 --- a/server/src/core/workspace/services/workspace.service.ts +++ b/server/src/core/workspace/services/workspace.service.ts @@ -1,9 +1,15 @@ import { Injectable } from '@nestjs/common'; +import { PipelineStageService } from 'src/core/pipeline/services/pipeline-stage.service'; +import { PipelineService } from 'src/core/pipeline/services/pipeline.service'; import { PrismaService } from 'src/database/prisma.service'; @Injectable() export class WorkspaceService { - constructor(private readonly prismaService: PrismaService) {} + constructor( + private readonly prismaService: PrismaService, + private readonly pipelineService: PipelineService, + private readonly pipelineStageService: PipelineStageService, + ) {} // Find findFirst = this.prismaService.workspace.findFirst; @@ -35,4 +41,22 @@ export class WorkspaceService { // GroupBy groupBy = this.prismaService.workspace.groupBy; + + // Customs + async createDefaultWorkspace() { + const workspace = await this.create({ data: {} }); + + // Create default pipeline + const pipeline = await this.pipelineService.createDefaultPipeline({ + workspaceId: workspace.id, + }); + + // Create default stages + await this.pipelineStageService.createDefaultPipelineStages({ + pipelineId: pipeline.id, + workspaceId: workspace.id, + }); + + return workspace; + } } diff --git a/server/src/core/workspace/workspace.module.ts b/server/src/core/workspace/workspace.module.ts index 1492aa072..f3456f537 100644 --- a/server/src/core/workspace/workspace.module.ts +++ b/server/src/core/workspace/workspace.module.ts @@ -4,8 +4,10 @@ import { WorkspaceMemberService } from './services/workspace-member.service'; import { WorkspaceMemberResolver } from './resolvers/workspace-member.resolver'; import { WorkspaceResolver } from './resolvers/workspace.resolver'; import { FileUploadService } from '../file/services/file-upload.service'; +import { PipelineModule } from '../pipeline/pipeline.module'; @Module({ + imports: [PipelineModule], providers: [ WorkspaceService, FileUploadService,