-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
496 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import {MigrationInterface, QueryRunner} from "typeorm"; | ||
|
||
export class Lead1617026957510 implements MigrationInterface { | ||
name = 'Lead1617026957510' | ||
|
||
public async up(queryRunner: QueryRunner): Promise<void> { | ||
await queryRunner.query(`CREATE TABLE "lead" ("id" uuid NOT NULL DEFAULT uuid_generate_v4(), "reference" character varying NOT NULL, "name" character varying NOT NULL, "address" character varying NOT NULL, "zipCode" character varying NOT NULL, "city" character varying NOT NULL, "phoneNumber" character varying NOT NULL, "email" character varying NOT NULL, "numberOfStudents" integer DEFAULT 0, "createdAt" TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "PK_ca96c1888f7dcfccab72b72fffa" PRIMARY KEY ("id"))`); | ||
} | ||
|
||
public async down(queryRunner: QueryRunner): Promise<void> { | ||
await queryRunner.query(`DROP TABLE "lead"`); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { IQuery } from 'src/Application/IQuery'; | ||
|
||
export class GetLeadsQuery implements IQuery { | ||
constructor( | ||
public readonly page: number, | ||
) {} | ||
} |
71 changes: 71 additions & 0 deletions
71
api/src/Application/Lead/Query/GetLeadsQueryHandler.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { mock, instance, when, verify } from 'ts-mockito'; | ||
import { GetLeadsQueryHandler } from 'src/Application/Lead/Query/GetLeadsQueryHandler'; | ||
import { LeadRepository } from 'src/Infrastructure/Lead/Repository/LeadRepository'; | ||
import { GetLeadsQuery } from 'src/Application/Lead/Query/GetLeadsQuery'; | ||
import { Lead } from 'src/Domain/Lead/Lead.entity'; | ||
import { LeadView } from 'src/Application/Lead/View/LeadView'; | ||
import { Pagination } from 'src/Application/Common/Pagination'; | ||
|
||
describe('GetLeadsQueryHandler', () => { | ||
it('testGetLeads', async () => { | ||
const leadRepository = mock(LeadRepository); | ||
|
||
const lead1 = mock(Lead); | ||
when(lead1.getId()).thenReturn('eb9e1d9b-dce2-48a9-b64f-f0872f3157d2'); | ||
when(lead1.getName()).thenReturn('Ecole élementaire Belliard'); | ||
when(lead1.getReference()).thenReturn('xLKJSs'); | ||
when(lead1.getAddress()).thenReturn('127 Rue Belliard'); | ||
when(lead1.getCity()).thenReturn('Paris'); | ||
when(lead1.getZipCode()).thenReturn('75010'); | ||
when(lead1.getEmail()).thenReturn('email@email.com'); | ||
when(lead1.getPhoneNumber()).thenReturn('0102030405'); | ||
when(lead1.getNumberOfStudents()).thenReturn(200); | ||
|
||
const lead2 = mock(Lead); | ||
when(lead2.getId()).thenReturn('d54f15d6-1a1d-47e8-8672-9f46018f9960'); | ||
when(lead2.getName()).thenReturn('Ecole Primaire les Landes'); | ||
when(lead2.getReference()).thenReturn('abcDes'); | ||
when(lead2.getAddress()).thenReturn('12 Rue des Lampes'); | ||
when(lead2.getCity()).thenReturn('Paris'); | ||
when(lead2.getZipCode()).thenReturn('75018'); | ||
when(lead2.getEmail()).thenReturn('email2@email.com'); | ||
when(lead2.getPhoneNumber()).thenReturn('0102030406'); | ||
|
||
when(leadRepository.findLeads(1)).thenResolve([ | ||
[instance(lead2), instance(lead1)], | ||
2 | ||
]); | ||
|
||
const queryHandler = new GetLeadsQueryHandler(instance(leadRepository)); | ||
const expectedResult = new Pagination<LeadView>( | ||
[ | ||
new LeadView( | ||
'd54f15d6-1a1d-47e8-8672-9f46018f9960', | ||
'Ecole Primaire les Landes', | ||
'abcDes', | ||
'12 Rue des Lampes', | ||
'Paris', | ||
'75018', | ||
'email2@email.com', | ||
'0102030406', | ||
null | ||
), | ||
new LeadView( | ||
'eb9e1d9b-dce2-48a9-b64f-f0872f3157d2', | ||
'Ecole élementaire Belliard', | ||
'xLKJSs', | ||
'127 Rue Belliard', | ||
'Paris', | ||
'75010', | ||
'email@email.com', | ||
'0102030405', | ||
200 | ||
) | ||
], | ||
2 | ||
); | ||
|
||
expect(await queryHandler.execute(new GetLeadsQuery(1))).toMatchObject(expectedResult); | ||
verify(leadRepository.findLeads(1)).once(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { QueryHandler } from '@nestjs/cqrs'; | ||
import { Inject } from '@nestjs/common'; | ||
import { GetLeadsQuery } from './GetLeadsQuery'; | ||
import { Pagination } from 'src/Application/Common/Pagination'; | ||
import { ILeadRepository } from 'src/Domain/Lead/Repository/ILeadRepository'; | ||
import { LeadView } from '../View/LeadView'; | ||
|
||
@QueryHandler(GetLeadsQuery) | ||
export class GetLeadsQueryHandler { | ||
constructor( | ||
@Inject('ILeadRepository') | ||
private readonly leadRepository: ILeadRepository | ||
) {} | ||
|
||
public async execute(query: GetLeadsQuery): Promise<Pagination<LeadView>> { | ||
const { page } = query; | ||
const leadViews: LeadView[] = []; | ||
const [ leads, total ] = await this.leadRepository.findLeads(page); | ||
|
||
for (const lead of leads) { | ||
leadViews.push( | ||
new LeadView( | ||
lead.getId(), | ||
lead.getName(), | ||
lead.getReference(), | ||
lead.getAddress(), | ||
lead.getCity(), | ||
lead.getZipCode(), | ||
lead.getEmail(), | ||
lead.getPhoneNumber(), | ||
lead.getNumberOfStudents(), | ||
) | ||
); | ||
} | ||
|
||
return new Pagination<LeadView>(leadViews, total); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export class LeadView { | ||
constructor( | ||
public readonly id: string, | ||
public readonly reference: string, | ||
public readonly name: string, | ||
public readonly address: string, | ||
public readonly zipCode: string, | ||
public readonly city: string, | ||
public readonly email: string, | ||
public readonly phoneNumber: string, | ||
public readonly numberOfStudents?: number, | ||
) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Lead } from './Lead.entity'; | ||
|
||
describe('Lead', () => { | ||
it('testGetters', () => { | ||
const lead = new Lead( | ||
'LM120I', | ||
'Belliard', | ||
'127 Rue Belliard', | ||
'75018', | ||
'Paris', | ||
'test@test.com', | ||
'010101010101', | ||
200 | ||
); | ||
expect(lead.getId()).toBeUndefined(); | ||
expect(lead.getName()).toBe('Belliard'); | ||
expect(lead.getReference()).toBe('LM120I'); | ||
expect(lead.getCity()).toBe('Paris'); | ||
expect(lead.getZipCode()).toBe('75018'); | ||
expect(lead.getAddress()).toBe('127 Rue Belliard'); | ||
expect(lead.getPhoneNumber()).toBe('010101010101'); | ||
expect(lead.getEmail()).toBe('test@test.com'); | ||
expect(lead.getNumberOfStudents()).toBe(200); | ||
expect(lead.getCreatedAt()).toBeUndefined(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; | ||
|
||
@Entity() | ||
export class Lead { | ||
@PrimaryGeneratedColumn('uuid') | ||
private id: string; | ||
|
||
@Column({ type: 'varchar', nullable: false }) | ||
private reference: string; | ||
|
||
@Column({ type: 'varchar', nullable: false }) | ||
private name: string; | ||
|
||
@Column({ type: 'varchar', nullable: false }) | ||
private address: string; | ||
|
||
@Column({ type: 'varchar', nullable: false }) | ||
private zipCode: string; | ||
|
||
@Column({ type: 'varchar', nullable: false }) | ||
private city: string; | ||
|
||
@Column({ type: 'varchar', nullable: false }) | ||
private phoneNumber: string; | ||
|
||
@Column({ type: 'varchar', nullable: false }) | ||
private email: string; | ||
|
||
@Column({ type: 'integer', nullable: true, default: 0 }) | ||
private numberOfStudents: number; | ||
|
||
@Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' }) | ||
private createdAt: number; | ||
|
||
constructor( | ||
reference: string, | ||
name: string, | ||
address: string, | ||
zipCode: string, | ||
city: string, | ||
email: string, | ||
phoneNumber: string, | ||
numberOfStudents?: number, | ||
) { | ||
this.reference = reference; | ||
this.name = name; | ||
this.address = address; | ||
this.zipCode = zipCode; | ||
this.city = city; | ||
this.email = email; | ||
this.phoneNumber = phoneNumber; | ||
this.numberOfStudents = numberOfStudents; | ||
} | ||
|
||
public getId(): string { | ||
return this.id; | ||
} | ||
|
||
public getReference(): string { | ||
return this.reference; | ||
} | ||
|
||
public getName(): string { | ||
return this.name; | ||
} | ||
|
||
public getZipCode(): string { | ||
return this.zipCode; | ||
} | ||
|
||
public getAddress(): string { | ||
return this.address; | ||
} | ||
|
||
public getCity(): string { | ||
return this.city; | ||
} | ||
|
||
public getEmail(): string { | ||
return this.email; | ||
} | ||
|
||
public getPhoneNumber(): string { | ||
return this.phoneNumber; | ||
} | ||
|
||
public getNumberOfStudents(): number { | ||
return this.numberOfStudents; | ||
} | ||
|
||
public getCreatedAt(): number { | ||
return this.createdAt; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { Lead } from '../Lead.entity'; | ||
|
||
export interface ILeadRepository { | ||
save(lead: Lead): Promise<Lead>; | ||
findLeads(page: number): Promise<[Lead[], number]>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { Controller, Inject, UseGuards, Get, Query } from '@nestjs/common'; | ||
import { AuthGuard } from '@nestjs/passport'; | ||
import { ApiTags, ApiBearerAuth, ApiOperation } from '@nestjs/swagger'; | ||
import { LeadView } from 'src/Application/Lead/View/LeadView'; | ||
import { IQueryBus } from 'src/Application/IQueryBus'; | ||
import { GetLeadsQuery } from 'src/Application/Lead/Query/GetLeadsQuery'; | ||
import { Pagination } from 'src/Application/Common/Pagination'; | ||
import { PaginationDTO } from 'src/Infrastructure/Common/DTO/PaginationDTO'; | ||
import { RolesGuard } from 'src/Infrastructure/User/Security/RolesGuard'; | ||
import { Roles } from 'src/Infrastructure/User/Decorator/Roles'; | ||
import { UserRole } from 'src/Domain/User/User.entity'; | ||
|
||
@Controller('leads') | ||
@ApiTags('Lead') | ||
@ApiBearerAuth() | ||
@UseGuards(AuthGuard('bearer'), RolesGuard) | ||
export class GetLeadsAction { | ||
constructor( | ||
@Inject('IQueryBus') | ||
private readonly queryBus: IQueryBus | ||
) {} | ||
|
||
@Get() | ||
@Roles(UserRole.PHOTOGRAPHER) | ||
@ApiOperation({summary: 'Get all leads'}) | ||
public async index( | ||
@Query() { page }: PaginationDTO, | ||
): Promise<Pagination<LeadView>> { | ||
return await this.queryBus.execute(new GetLeadsQuery(page)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { Repository } from 'typeorm'; | ||
import { InjectRepository } from '@nestjs/typeorm'; | ||
import { Lead } from 'src/Domain/Lead/Lead.entity'; | ||
import { ILeadRepository } from 'src/Domain/Lead/Repository/ILeadRepository'; | ||
import { MAX_ITEMS_PER_PAGE } from 'src/Application/Common/Pagination'; | ||
|
||
@Injectable() | ||
export class LeadRepository implements ILeadRepository { | ||
constructor( | ||
@InjectRepository(Lead) | ||
private readonly repository: Repository<Lead> | ||
) {} | ||
|
||
public save(lead: Lead): Promise<Lead> { | ||
return this.repository.save(lead); | ||
} | ||
|
||
public findLeads(page = 1): Promise<[Lead[], number]> { | ||
return this.repository | ||
.createQueryBuilder('lead') | ||
.select([ | ||
'lead.id', | ||
'lead.name', | ||
'lead.reference', | ||
'lead.address', | ||
'lead.city', | ||
'lead.zipCode', | ||
'lead.email', | ||
'lead.phoneNumber', | ||
'lead.numberOfStudents' | ||
]) | ||
.orderBy('lead.createdAt', 'DESC') | ||
.limit(MAX_ITEMS_PER_PAGE) | ||
.offset((page - 1) * MAX_ITEMS_PER_PAGE) | ||
.getManyAndCount(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { TypeOrmModule } from '@nestjs/typeorm'; | ||
import { GetLeadsQueryHandler } from 'src/Application/Lead/Query/GetLeadsQueryHandler'; | ||
import { Lead } from 'src/Domain/Lead/Lead.entity'; | ||
import { BusModule } from '../bus.module'; | ||
import { GetLeadsAction } from './Action/GetSchoolsAction'; | ||
import { LeadRepository } from './Repository/LeadRepository'; | ||
|
||
@Module({ | ||
imports: [ | ||
BusModule, | ||
TypeOrmModule.forFeature([ | ||
Lead | ||
]) | ||
], | ||
controllers: [ | ||
GetLeadsAction | ||
], | ||
providers: [ | ||
{ provide: 'ILeadRepository', useClass: LeadRepository }, | ||
GetLeadsQueryHandler | ||
] | ||
}) | ||
export class LeadModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.