Skip to content

Commit 068198c

Browse files
authored
Merge pull request #54 from PBTP/test/pet-unit
2 parents 2e7b44e + 793ac24 commit 068198c

41 files changed

Lines changed: 1922 additions & 307 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

k6/script/stress.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import http from 'k6/http';
21
import { check } from 'k6';
2+
import http from 'k6/http';
33

44
const host = 'http://host.docker.internal:3000';
55

src/auth/presentation/user.dto.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import { ApiProperty } from '@nestjs/swagger';
2+
import { Builder } from 'builder-pattern';
13
import { IsIn, IsNotEmpty, IsOptional } from 'class-validator';
24
import { CrudGroup } from '../../common/validation/validation.data';
3-
import { ApiProperty } from '@nestjs/swagger';
45
import { Customer } from '../../customer/customer.domain';
5-
import { Builder } from 'builder-pattern';
66

77
// 고객, 업체, 기사 공통 사용 DTO
88
export type UserType = 'customer' | 'driver' | 'business';

src/customer/customer.domain.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { AuthProvider, UserDto } from '../auth/presentation/user.dto';
33
import { Favorite } from '../schemas/favorites.entity';
44
import { Review } from '../schemas/reviews.entity';
55
import { Appointment } from '../schemas/appointments.entity';
6-
import { Pet } from '../schemas/pets.entity';
6+
import { PetEntity } from '../schemas/pets.entity';
77
import { CustomerChatRoom } from '../schemas/customer-chat-room.entity';
88
import { AuthDto } from '../auth/presentation/auth.dto';
99
import { CustomerDto } from './presentation/customer.dto';
@@ -25,7 +25,7 @@ export interface ICustomer extends AuthDto {
2525
favorites?: Favorite[];
2626
reviews?: Review[];
2727
appointments?: Appointment[];
28-
pets?: Pet[];
28+
pets?: PetEntity[];
2929
chatRooms?: CustomerChatRoom[];
3030
createdAt?: Date;
3131
modifiedAt?: Date;
@@ -45,7 +45,7 @@ export class Customer implements ICustomer, UserDto {
4545
favorites?: Favorite[];
4646
reviews?: Review[];
4747
appointments?: Appointment[];
48-
pets?: Pet[];
48+
pets?: PetEntity[];
4949
chatRooms?: CustomerChatRoom[];
5050
createdAt?: Date;
5151
modifiedAt?: Date;

src/pet/application/pet.checklist.service.spec.ts

Lines changed: 0 additions & 24 deletions
This file was deleted.

src/pet/application/pet.service.spec.ts

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/pet/application/pet.service.ts

Lines changed: 88 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,72 @@
1+
import { ForbiddenException, Inject, Injectable } from '@nestjs/common';
2+
import { BadRequestException } from '@nestjs/common/exceptions';
3+
import { Builder } from 'builder-pattern';
4+
import { DATE_HOLDER, DateHolder } from '../../common/holder/date.holder';
5+
import { UUID_HOLDER, UUIDHolder } from '../../common/holder/uuid.holders';
6+
import { ICustomer } from '../../customer/customer.domain';
7+
import {
8+
ChecklistType,
9+
PetChecklistCategory,
10+
} from '../../schemas/pet-checklist.entity';
11+
import { PetEntity } from '../../schemas/pets.entity';
12+
import { PetChecklistAnswer } from '../pet.checklist-answer.domain';
13+
import { PetChecklistChoiceAnswer } from '../pet.checklist-choice-answer.domain';
14+
import { Pet } from '../pet.domain';
15+
import { BREED_REPOSITORY, IBreedRepository } from '../port/bree.repository';
16+
import {
17+
IPetChecklistAnswerRepository,
18+
PET_CHECKLIST_ANSWER_REPOSITORY,
19+
} from '../port/pet.checklist-answer.repository';
20+
import { IPetChecklistChoiceAnswerRepository } from '../port/pet.checklist-choice-answer.repository';
21+
import { PET_CHECKLIST_CHOICE_REPOSITORY } from '../port/pet.checklist-choice.repository';
122
import {
2-
ForbiddenException,
3-
Injectable,
4-
NotFoundException,
5-
} from '@nestjs/common';
6-
import { InjectRepository } from '@nestjs/typeorm';
7-
import { In, Repository } from 'typeorm';
8-
import { Pet } from '../../schemas/pets.entity';
9-
import { Breed } from '../../schemas/breed.entity';
23+
IPetChecklistRepository,
24+
PET_CHECKLIST_REPOSITORY,
25+
} from '../port/pet.checklist.repository';
26+
import { IPetRepository, PET_REPOSITORY } from '../port/pet.repository';
1027
import {
1128
PetChecklistAnswerDto,
1229
PetChecklistChoiceDto,
1330
PetChecklistDto,
1431
PetDto,
1532
} from '../presentation/pet.dto';
16-
import {
17-
ChecklistType,
18-
PetChecklist,
19-
PetChecklistCategory,
20-
} from '../../schemas/pet-checklist.entity';
21-
import { PetChecklistChoice } from '../../schemas/pet-checklist-chocie.entity';
22-
import { PetChecklistAnswer } from '../../schemas/pet-checklist-answer.entity';
23-
import { PetChecklistChoiceAnswer } from '../../schemas/pet-checklist-chocie-answer.entity';
24-
import { Builder } from 'builder-pattern';
25-
import { CustomerService } from '../../customer/application/customer.service';
26-
import { BadRequestException } from '@nestjs/common/exceptions';
27-
import { ICustomer } from '../../customer/customer.domain';
2833

2934
@Injectable()
3035
export class PetService {
3136
constructor(
32-
private customerService: CustomerService,
33-
@InjectRepository(Pet)
34-
private petRepository: Repository<Pet>,
35-
@InjectRepository(PetChecklist)
36-
private petChecklistRepository: Repository<PetChecklist>,
37-
@InjectRepository(PetChecklistAnswer)
38-
private petChecklistAnswerRepository: Repository<PetChecklistAnswer>,
39-
@InjectRepository(PetChecklistChoiceAnswer)
40-
private petChecklistChoiceAnswerRepository: Repository<PetChecklistChoiceAnswer>,
41-
@InjectRepository(Breed)
42-
private breedRepository: Repository<Breed>,
37+
@Inject(UUID_HOLDER)
38+
private uuidHolder: UUIDHolder,
39+
@Inject(DATE_HOLDER)
40+
private dateHolder: DateHolder,
41+
@Inject(PET_REPOSITORY)
42+
private petRepository: IPetRepository,
43+
@Inject(PET_CHECKLIST_REPOSITORY)
44+
private petChecklistRepository: IPetChecklistRepository,
45+
@Inject(PET_CHECKLIST_ANSWER_REPOSITORY)
46+
private petChecklistAnswerRepository: IPetChecklistAnswerRepository,
47+
@Inject(PET_CHECKLIST_CHOICE_REPOSITORY)
48+
private petChecklistChoiceAnswerRepository: IPetChecklistChoiceAnswerRepository,
49+
@Inject(BREED_REPOSITORY)
50+
private breedRepository: IBreedRepository,
4351
) {}
4452

4553
async create(dto: PetDto, customer: ICustomer): Promise<Pet> {
46-
const breed = await this.breedRepository.findOneOrFail({
47-
where: { breedId: dto.breedId },
48-
});
49-
50-
if (!breed) {
51-
throw new NotFoundException('견종을 찾을 수 없습니다.');
52-
}
54+
const breed = await this.breedRepository.getBreed(dto.breedId);
5355

54-
const newPet = this.petRepository.create({
55-
...dto,
56-
breed,
56+
return await this.petRepository.create(
57+
Pet.create(dto, breed, customer, this.uuidHolder, this.dateHolder),
5758
customer,
58-
});
59-
60-
return await this.petRepository.save(newPet);
59+
this.dateHolder,
60+
this.uuidHolder,
61+
);
6162
}
6263

63-
async findAll(customer: ICustomer): Promise<Pet[]> {
64-
return await this.petRepository.find({
65-
where: { customer: { customerId: customer.customerId } },
66-
relations: ['breed'],
67-
});
64+
async findAll(customer: ICustomer): Promise<PetEntity[]> {
65+
return await this.petRepository.findAllByCustomer(customer);
6866
}
69-
async findOne(id: number, customer: ICustomer): Promise<Pet> {
70-
const pet = await this.petRepository.findOneOrFail({
71-
where: { petId: id },
72-
relations: ['breed', 'customer'],
73-
});
67+
68+
async getOne(id: number, customer: ICustomer): Promise<PetEntity> {
69+
const pet = await this.petRepository.getOne(id);
7470

7571
if (pet.customer.customerId !== customer.customerId) {
7672
throw new ForbiddenException('해당 반려동물에 접근할 수 없습니다.');
@@ -84,12 +80,10 @@ export class PetService {
8480
dto: Partial<PetDto>,
8581
customer: ICustomer,
8682
): Promise<Pet> {
87-
const pet = await this.findOne(id, customer);
83+
const pet = await this.getOne(id, customer);
8884

8985
if (dto.breedId && dto.breedId !== pet.breed.breedId) {
90-
pet.breed = await this.breedRepository.findOneOrFail({
91-
where: { breedId: dto.breedId },
92-
});
86+
pet.breed = await this.breedRepository.getBreed(dto.breedId);
9387
}
9488

9589
pet.petName = dto.petName ?? pet.petName;
@@ -100,59 +94,26 @@ export class PetService {
10094
pet.vaccinationStatus = dto.vaccinationStatus ?? pet.vaccinationStatus;
10195
pet.petGender = dto.petGender ?? pet.petGender;
10296

103-
return await this.petRepository.save(pet);
97+
return await this.petRepository.update(pet, this.dateHolder);
10498
}
10599

106100
async delete(id: number, customer: ICustomer): Promise<void> {
107-
const pet = await this.findOne(id, customer);
101+
const pet = await this.getOne(id, customer);
108102

109-
await this.petRepository.softDelete(pet.petId);
103+
await this.petRepository.delete(pet);
110104
}
111105

112106
async findCheckList(
113107
category: PetChecklistCategory,
114108
type: ChecklistType,
115109
petId: number | null,
116-
customer: ICustomer,
117110
): Promise<PetChecklistDto[]> {
118-
let query = this.petChecklistRepository
119-
.createQueryBuilder('PC')
120-
.leftJoinAndMapMany(
121-
'PC.petChecklistChoices',
122-
PetChecklistChoice,
123-
'PCC',
124-
'PC.pet_checklist_id = PCC.pet_checklist_id',
125-
);
126-
127-
if (petId) {
128-
await this.findOne(petId, customer);
129-
130-
query = query
131-
.leftJoinAndMapOne(
132-
'PCC.petChecklistChoiceAnswers',
133-
PetChecklistChoiceAnswer,
134-
'PCCA',
135-
`PCC.pet_checklist_id = PCCA.pet_checklist_id
136-
AND PCC.pet_checklist_choice_id = PCCA.pet_checklist_choice_id
137-
AND PCCA.pet_id = :petId`,
138-
{ petId },
139-
)
140-
.leftJoinAndMapMany(
141-
'PC.petChecklistAnswers',
142-
PetChecklistAnswer,
143-
'PCA',
144-
'PC.pet_checklist_id = PCA.pet_checklist_id AND PCA.pet_id = :petId',
145-
{ petId },
146-
);
147-
}
148-
149-
type && query.andWhere('PC.pet_checklist_type = :type', { type });
150-
category &&
151-
query.andWhere('PC.pet_checklist_category = :category', { category });
152-
153-
query.orderBy('PC.pet_checklist_id');
111+
const data = await this.petChecklistRepository.findCheckList(
112+
category,
113+
type,
114+
petId,
115+
);
154116

155-
const data = await query.getMany();
156117
return data.map((checklist) => {
157118
const dto = Builder<PetChecklistDto>()
158119
.petChecklistId(checklist.petChecklistId)
@@ -190,46 +151,49 @@ export class PetService {
190151
dto: PetChecklistAnswerDto[],
191152
customer: ICustomer,
192153
) {
193-
const pet = await this.findOne(petId, customer);
154+
const pet = await this.getOne(petId, customer);
194155

195-
const checklist = await this.petChecklistRepository.find({
196-
where: {
197-
petChecklistId: In(dto.map((v) => v.petChecklistId)),
198-
},
199-
});
156+
const checklists = await this.petChecklistRepository.findByIds(
157+
dto.map((v) => v.petChecklistId),
158+
);
200159

201-
for (const v of checklist) {
202-
const answer = dto.find((d) => d.petChecklistId === v.petChecklistId);
160+
for (const checklist of checklists) {
161+
const answer = dto.find(
162+
(d) => d.petChecklistId === checklist.petChecklistId,
163+
);
203164

204-
if (v.petChecklistType === ChecklistType.ANSWER) {
165+
if (checklist.petChecklistType === ChecklistType.ANSWER) {
205166
if (!answer?.petChecklistAnswer) {
206167
throw new BadRequestException('답변을 적어주세요');
207168
}
208-
209-
await this.petChecklistAnswerRepository.save({
210-
pet,
211-
petChecklistId: v.petChecklistId,
212-
petChecklistAnswer: answer?.petChecklistAnswer,
213-
});
169+
await this.petChecklistAnswerRepository.create(
170+
Builder(PetChecklistAnswer)
171+
.petId(pet.petId)
172+
.petChecklistId(checklist.petChecklistId)
173+
.petChecklistAnswer(answer.petChecklistAnswer)
174+
.build(),
175+
);
214176
} else {
215177
if (!answer?.petChecklistChoiceId) {
216178
throw new BadRequestException('선택지를 선택해주세요');
217179
}
218180

181+
const petChecklistChoiceAnswer = Builder(PetChecklistChoiceAnswer)
182+
.petId(pet.petId)
183+
.petChecklistId(checklist.petChecklistId)
184+
.petChecklistChoiceId(answer.petChecklistChoiceId)
185+
.build();
186+
219187
if (answer.checked) {
220-
await this.petChecklistChoiceAnswerRepository.save({
221-
petId,
222-
petChecklistId: v.petChecklistId,
223-
petChecklistChoiceId: answer.petChecklistChoiceId,
224-
});
188+
await this.petChecklistChoiceAnswerRepository.create(
189+
petChecklistChoiceAnswer,
190+
);
225191
return;
226192
}
227193

228-
await this.petChecklistChoiceAnswerRepository.delete({
229-
petId,
230-
petChecklistId: v.petChecklistId,
231-
petChecklistChoiceId: answer.petChecklistChoiceId,
232-
});
194+
await this.petChecklistChoiceAnswerRepository.delete(
195+
petChecklistChoiceAnswer,
196+
);
233197
}
234198
}
235199
}

src/pet/bred.domain.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Builder } from 'builder-pattern';
2+
import { BreedEntity } from '../schemas/breed.entity';
3+
4+
export class Breed {
5+
uuid: string;
6+
breedId: number;
7+
breedName: string;
8+
breedDescription: string;
9+
10+
static from(entity: BreedEntity): Breed {
11+
return Builder(Breed)
12+
.breedId(entity.breedId)
13+
.breedName(entity.breedName)
14+
.breedDescription(entity.breedDescription)
15+
.build();
16+
}
17+
}

0 commit comments

Comments
 (0)