diff --git a/package.json b/package.json index 2620068..6f59353 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "license": "UNLICENSED", "scripts": { "build": "nest build", + "generate-schema": "ts-node scripts/generate-schema.ts", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", "start:dev": "nest start --watch", diff --git a/schema.gql b/schema.gql index 6f93c1c..cc3e094 100644 --- a/schema.gql +++ b/schema.gql @@ -1,58 +1,50 @@ -# ------------------------------------------------------ -# THIS FILE WAS AUTOMATICALLY GENERATED (DO NOT MODIFY) -# ------------------------------------------------------ - -"""Case comment""" -type Comment { - author: String - comment: String! - timestamp: String! -} - """KYC Customer""" type Customer { - countryOfResidence: String! - dateOfBirth: String! name: String! -} - -input CustomerInput { - countryOfResidence: String! dateOfBirth: String! - name: String! + countryOfResidence: String! } """KYC Document""" type Document { + id: ID! name: String! path: String! } -"""greeting""" -type Greeting { - greeting: String! +"""Case comment""" +type Comment { + id: ID! + comment: String! + timestamp: String! + author: String } """KYC Case""" type KycCase { - comments: [Comment!]! + id: ID! + status: String! customer: Customer! documents: [Document!]! - id: String! - status: String! + comments: [Comment!]! +} + +type Query { + listCases: [KycCase!]! + getCase(id: ID!): KycCase! } type Mutation { - addDocumentToCase(documentName: String!, documentPath: String!, id: ID!): KycCase! - approveCase(comment: String!, id: ID!): KycCase! createCase(customer: CustomerInput!): KycCase! - reviewCase(comment: String!, id: ID!): KycCase! + addDocumentToCase(caseId: ID!, documentName: String!, documentPath: String!): KycCase! + reviewCase(caseId: ID!, comment: String, timestamp: String, author: String): KycCase! + approveCase(caseId: ID!, comment: String, timestamp: String, author: String): KycCase! } -type Query { - getCase(id: ID!): KycCase! - helloWorld: Greeting! - listCases: [KycCase!]! +input CustomerInput { + name: String! + dateOfBirth: String! + countryOfResidence: String! } type Subscription { diff --git a/scripts/generate-schema.ts b/scripts/generate-schema.ts new file mode 100644 index 0000000..5a8deca --- /dev/null +++ b/scripts/generate-schema.ts @@ -0,0 +1,20 @@ +import {NestFactory} from "@nestjs/core"; +import {GraphQLSchemaBuilderModule, GraphQLSchemaFactory} from "@nestjs/graphql"; +import {printSchema} from "graphql/utilities"; +import {promises} from 'fs'; + +import {KycCaseResolver} from "../src/resolvers/kyc-case"; + +const generateSchema = async (file: string) => { + const app = await NestFactory.create(GraphQLSchemaBuilderModule); + await app.init(); + + const gqlSchemaFactory = app.get(GraphQLSchemaFactory); + const schema = await gqlSchemaFactory.create([KycCaseResolver]); + + if (file) { + await promises.writeFile(file, printSchema(schema)) + } +} + +generateSchema('schema.gql').catch(err => console.error('Unable to generate schema: ', err)); diff --git a/src/app.module.ts b/src/app.module.ts index 1a2b598..6893054 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,11 +1,10 @@ -import { Module } from '@nestjs/common'; +import {Module} from '@nestjs/common'; import {GraphQLModule} from "@nestjs/graphql"; import {ApolloDriver, ApolloDriverConfig} from "@nestjs/apollo"; -import {join} from 'path'; -import { controllers } from './controllers'; -import {ServiceModule} from "./services"; +import {controllers} from './controllers'; import {ResolverModule} from "./resolvers"; +import {ServiceModule} from "./services"; const imports = [ GraphQLModule.forRoot({ @@ -13,7 +12,7 @@ const imports = [ autoSchemaFile: 'schema.gql', sortSchema: true, subscriptions: { - 'graphql-ws': true + 'graphql-ws': true, }, }), ServiceModule, diff --git a/src/graphql-types/kyc-case.graphql.ts b/src/graphql-types/kyc-case.graphql.ts index 1bb2a03..f2466e2 100644 --- a/src/graphql-types/kyc-case.graphql.ts +++ b/src/graphql-types/kyc-case.graphql.ts @@ -1,4 +1,4 @@ -import {Field, InputType, ObjectType} from "@nestjs/graphql"; +import {Field, ID, InputType, ObjectType} from "@nestjs/graphql"; import { CommentModel, CustomerModel, @@ -20,6 +20,8 @@ export class Customer implements CustomerModel { @ObjectType({ description: 'KYC Document' }) export class Document implements DocumentModel { + @Field(() => ID) + id: string; @Field() name: string; @Field() @@ -40,6 +42,8 @@ export class CustomerRiskAssessment implements CustomerRiskAssessmentModel { @ObjectType({description: 'Case comment'}) export class Comment implements CommentModel { + @Field(() => ID) + id: string; @Field() comment: string; @Field() @@ -50,7 +54,7 @@ export class Comment implements CommentModel { @ObjectType({ description: 'KYC Case' }) export class KycCase implements KycCaseModel { - @Field() + @Field(() => ID) id: string; @Field() status: string; diff --git a/src/models/kyc-case.model.ts b/src/models/kyc-case.model.ts index 19a8047..bd4a254 100644 --- a/src/models/kyc-case.model.ts +++ b/src/models/kyc-case.model.ts @@ -9,6 +9,7 @@ export interface KycCaseModel { } export interface CommentModel { + id: string; comment: string; timestamp: string; author?: string; @@ -21,6 +22,7 @@ export interface CustomerModel { } export interface DocumentModel { + id: string; name: string; path: string; } diff --git a/src/resolvers/kyc-case/kyc-case.resolver.ts b/src/resolvers/kyc-case/kyc-case.resolver.ts index 921dd0e..d32db45 100644 --- a/src/resolvers/kyc-case/kyc-case.resolver.ts +++ b/src/resolvers/kyc-case/kyc-case.resolver.ts @@ -42,7 +42,7 @@ export class KycCaseResolver { @Mutation(() => KycCase) async addDocumentToCase( - @Args('id', { type: () => ID }) caseId: string, + @Args('caseId', { type: () => ID }) caseId: string, @Args('documentName', { type: () => String }) documentName: string, @Args('documentPath', { type: () => String }) documentPath: string, ): Promise { @@ -51,17 +51,21 @@ export class KycCaseResolver { @Mutation(() => KycCase) async reviewCase( - @Args('id', { type: () => ID }) caseId: string, - @Args('comment', { type: () => String }) comment: string + @Args('caseId', { type: () => ID }) caseId: string, + @Args('comment', { type: () => String, nullable: true }) comment?: string, + @Args('timestamp', { type: () => String, nullable: true }) timestamp?: string, + @Args('author', { type: () => String, nullable: true }) author?: string, ): Promise { - return this.service.reviewCase(caseId, comment); + return this.service.reviewCase(caseId, comment, timestamp, author); } @Mutation(() => KycCase) async approveCase( - @Args('id', { type: () => ID }) caseId: string, - @Args('comment', { type: () => String }) comment: string + @Args('caseId', { type: () => ID }) caseId: string, + @Args('comment', { type: () => String, nullable: true }) comment?: string, + @Args('timestamp', { type: () => String, nullable: true }) timestamp?: string, + @Args('author', { type: () => String, nullable: true }) author?: string, ): Promise { - return this.service.approveCase(caseId, comment); + return this.service.approveCase(caseId, comment, timestamp, author); } } diff --git a/src/services/kyc-case/kyc-case-management.mock.ts b/src/services/kyc-case/kyc-case-management.mock.ts index 37668b4..15515e1 100644 --- a/src/services/kyc-case/kyc-case-management.mock.ts +++ b/src/services/kyc-case/kyc-case-management.mock.ts @@ -67,12 +67,14 @@ export class KycCaseManagementMock implements KycCaseManagementApi { return newCase; } - async addDocumentToCase(id: string, documentName: string, documentPath: string): Promise { - const currentCase = await this.getCase(id); + async addDocumentToCase(caseId: string, documentName: string, documentPath: string): Promise { + const currentCase = await this.getCase(caseId); currentCase.status = 'Pending'; - currentCase.documents.push({name: documentName, path: documentPath}); + const id = '' + (currentCase.documents.length + 1); + + currentCase.documents.push({id: `${caseId}-${id}`, name: documentName, path: documentPath}); this.subject.next(this.subject.value); @@ -85,24 +87,29 @@ export class KycCaseManagementMock implements KycCaseManagementApi { currentCase.status = 'Pending'; - if (comment) { - currentCase.comments.push(Object.assign({comment, timestamp}, author ? {author} : {})) - } + this.addComment(currentCase, comment, timestamp, author); this.subject.next(this.subject.value); return currentCase; } + addComment(currentCase: KycCaseModel, comment?: string, timestamp?: string, author?: string) { + if (comment) { + const caseId = currentCase.id; + const commentId = '' + (currentCase.comments.length + 1) + + currentCase.comments.push(Object.assign({id: `${caseId}-${commentId}`, comment, timestamp}, author ? {author} : {})) + } + } + async approveCase(id: string, comment?: string, timestamp: string = new Date().toISOString(), author?: string): Promise { const currentCase = first(this.subject.value.filter(c => c.id === id)) .orElseThrow(() => new CaseNotFound(id)) currentCase.status = 'Closed'; - if (comment) { - currentCase.comments.push(Object.assign({comment, timestamp}, author ? {author} : {})) - } + this.addComment(currentCase, comment, timestamp, author); this.subject.next(this.subject.value);