Skip to content

Commit 4f3b610

Browse files
authored
Merge pull request #38 from codeit-moving/dev
Dev -> main 20241217 17:16 프론트 요청사항 및 유저 기능 수정
2 parents 315febd + e322e69 commit 4f3b610

File tree

8 files changed

+266
-50
lines changed

8 files changed

+266
-50
lines changed

src/controllers/authController.ts

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import { Router } from "express";
22
import authService from "../services/authService";
33
import { asyncHandle } from "../utils/asyncHandler";
44
import cookieConfig from "../config/cookie.config";
5-
import createToken from "../utils/token.utils";
5+
import createToken, { Payload } from "../utils/token.utils";
66
import upload from "../utils/multer";
7+
import passport from "passport";
78

89
const router = Router();
910

@@ -75,18 +76,19 @@ router.post(
7576
upload.single("imageUrl"),
7677
asyncHandle(async (req, res, next) => {
7778
try {
78-
const SignUpCustomer: SignUpCustomer = {
79+
const signUpCustomer: SignUpCustomer = {
7980
...req.body,
8081
imageUrl: req.file!,
8182
services: Array.isArray(req.body.services)
82-
? req.body.services
83-
: JSON.parse(req.body.services),
83+
? req.body.services.map(Number)
84+
: JSON.parse(req.body.services).map(Number),
8485
regions: Array.isArray(req.body.regions)
85-
? req.body.regions
86-
: JSON.parse(req.body.regions),
86+
? req.body.regions.map(Number)
87+
: JSON.parse(req.body.regions).map(Number),
8788
isOAuth: req.body.isOAuth === "true",
8889
};
89-
await authService.signUpCustomer(SignUpCustomer);
90+
91+
await authService.signUpCustomer(signUpCustomer);
9092
res.status(204).send();
9193
} catch (error) {
9294
next(error);
@@ -99,7 +101,18 @@ router.post(
99101
upload.single("imageUrl"),
100102
asyncHandle(async (req, res, next) => {
101103
try {
102-
const SignUpMover: SignUpMover = req.body;
104+
const SignUpMover: SignUpMover = {
105+
...req.body,
106+
imageUrl: req.file!,
107+
services: Array.isArray(req.body.services)
108+
? req.body.services.map(Number)
109+
: JSON.parse(req.body.services).map(Number),
110+
regions: Array.isArray(req.body.regions)
111+
? req.body.regions.map(Number)
112+
: JSON.parse(req.body.regions).map(Number),
113+
isOAuth: req.body.isOAuth === "true",
114+
career: Number(req.body.career),
115+
};
103116
await authService.signUpMover(SignUpMover);
104117
res.status(204).send();
105118
} catch (error) {
@@ -108,4 +121,32 @@ router.post(
108121
})
109122
);
110123

124+
router.post(
125+
"/validate",
126+
asyncHandle(async (req, res, next) => {
127+
try {
128+
const { email, phoneNumber } = req.body;
129+
await authService.validate(email, phoneNumber);
130+
res.status(204).send();
131+
} catch (error) {
132+
next(error);
133+
}
134+
})
135+
);
136+
137+
router.post(
138+
"/refresh",
139+
passport.authenticate("refresh-token", { session: false }),
140+
asyncHandle(async (req, res, next) => {
141+
try {
142+
const user = req.user as Payload;
143+
const accessToken = createToken(user, "access");
144+
res.cookie("accessToken", accessToken, cookieConfig.accessTokenOption);
145+
res.status(204).send();
146+
} catch (error) {
147+
next(error);
148+
}
149+
})
150+
);
151+
111152
export default router;

src/controllers/customerController.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,16 @@ router.post(
1717
const profile = {
1818
userId: userId,
1919
imageUrl: req.file!,
20-
services: Array.isArray(req.body.services)
21-
? req.body.services
22-
: JSON.parse(req.body.services),
23-
regions: Array.isArray(req.body.regions)
24-
? req.body.regions
25-
: JSON.parse(req.body.regions), //postman으로 테스트하였는데 문자 배열로 인식하는 것 같아 임시 코드 작성 수정예정
20+
regions: req.body.regions
21+
? Array.isArray(req.body.regions)
22+
? req.body.regions.map(Number)
23+
: JSON.parse(req.body.regions).map(Number)
24+
: [],
25+
services: req.body.services
26+
? Array.isArray(req.body.services)
27+
? req.body.services.map(Number)
28+
: JSON.parse(req.body.services).map(Number)
29+
: [],
2630
};
2731
await customerService.createCustomerProfile(profile);
2832
res.status(204).send();
@@ -39,7 +43,16 @@ router.patch(
3943
asyncHandle(async (req, res, next) => {
4044
try {
4145
const userId = (req.user as Payload).id;
42-
const profile = { ...req.body, imageUrl: req.file };
46+
const profile = {
47+
...req.body,
48+
imageUrl: req.file,
49+
regions: req.body.regions
50+
? JSON.parse(req.body.regions).map(Number)
51+
: [],
52+
services: req.body.services
53+
? JSON.parse(req.body.services).map(Number)
54+
: [],
55+
};
4356
await customerService.updateCustomerProfile(userId, profile);
4457
res.status(204).send();
4558
} catch (error) {

src/controllers/movingRequestController.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ const router = express.Router();
99

1010
//이사요청 목록 조회
1111
router.get(
12-
"/",
13-
// passport.authenticate("jwt", { session: false }),
12+
"/my-mover",
13+
passport.authenticate("jwt", { session: false }),
1414
asyncHandle(async (req, res, next) => {
1515
try {
16-
// const { customerId } = req.user as { customerId: number };
16+
const { moverId } = req.user as { moverId: number };
1717

1818
const {
1919
limit = "10",
@@ -24,17 +24,18 @@ router.get(
2424
houseMove = "false",
2525
officeMove = "false",
2626
orderBy = "resent",
27+
isQuoted = "false",
2728
} = req.query;
2829
const parseLimit = parseInt(limit as string);
2930
const parseCursor = parseInt(cursor as string);
3031
const parseIsDesignated = checkBoolean(isDesignated as string);
3132
const parseSmallMove = checkBoolean(smallMove as string);
3233
const parseHouseMove = checkBoolean(houseMove as string);
3334
const parseOfficeMove = checkBoolean(officeMove as string);
35+
const parseIsQuoted = checkBoolean(isQuoted as string);
3436

35-
const movingRequestList = await movingRequestService.getMovingRequestList(
36-
1,
37-
{
37+
const movingRequestList =
38+
await movingRequestService.getMovingRequestListByMover(moverId, {
3839
limit: parseLimit,
3940
isDesignated: parseIsDesignated,
4041
cursor: parseCursor,
@@ -43,8 +44,8 @@ router.get(
4344
houseMove: parseHouseMove || false,
4445
officeMove: parseOfficeMove || false,
4546
orderBy: orderBy as string,
46-
}
47-
);
47+
isQuoted: parseIsQuoted || false,
48+
});
4849
return res.status(200).send(movingRequestList);
4950
} catch (error) {
5051
next(error);

src/repositorys/movingRequestRepository.ts

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,72 @@ const getMovingRequestCountByCustomer = (customerId: number) => {
2626
});
2727
};
2828

29+
//이사요청 서비스별 카운트 조회
30+
const getMovingRequestCountByServices = async (where: WhereCondition) => {
31+
const counts = await prismaClient.movingRequest.groupBy({
32+
where,
33+
by: ["service"],
34+
_count: {
35+
service: true,
36+
},
37+
});
38+
39+
// 초기값 설정
40+
const result = {
41+
smallMove: 0, // service: 1
42+
houseMove: 0, // service: 2
43+
officeMove: 0, // service: 3
44+
};
45+
46+
// 각 서비스 타입별로 카운트 할당
47+
counts.forEach((count) => {
48+
switch (count.service) {
49+
case 1:
50+
result.smallMove = count._count.service;
51+
break;
52+
case 2:
53+
result.houseMove = count._count.service;
54+
break;
55+
case 3:
56+
result.officeMove = count._count.service;
57+
break;
58+
}
59+
});
60+
61+
return result;
62+
};
63+
64+
const getMovingRequestCountByDesignated = async (
65+
where: WhereCondition,
66+
moverId: number
67+
) => {
68+
return prismaClient.movingRequest.count({
69+
where: {
70+
...where,
71+
mover: {
72+
some: {
73+
id: moverId,
74+
},
75+
},
76+
},
77+
});
78+
};
79+
80+
const getTotalCount = async (where: WhereCondition) => {
81+
return prismaClient.movingRequest.count({
82+
where,
83+
});
84+
};
85+
2986
//이사요청 목록 조회
30-
const getMovingRequestList = (
31-
customerId: number,
87+
const getMovingRequestListByMover = (
3288
query: CursorQueryString,
3389
where: WhereCondition
3490
) => {
3591
const { limit, cursor, orderBy } = query;
3692

3793
return prismaClient.movingRequest.findMany({
38-
where: {
39-
customerId,
40-
...where,
41-
},
94+
where,
4295
orderBy,
4396
take: limit,
4497
skip: cursor ? 1 : 0, //커서 자신을 스킵하기 위함
@@ -263,7 +316,7 @@ const getActiveRequest = (customerId: number) => {
263316
};
264317

265318
export default {
266-
getMovingRequestList,
319+
getMovingRequestList: getMovingRequestListByMover,
267320
createMovingRequest,
268321
updateDesignated,
269322
updateDesignatedCancel,
@@ -272,4 +325,7 @@ export default {
272325
getMovingRequestById,
273326
getMovingRequestListByCustomer,
274327
getMovingRequestCountByCustomer,
328+
getMovingRequestCountByServices,
329+
getMovingRequestCountByDesignated,
330+
getTotalCount,
275331
};

src/schedules/notifications.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,32 @@ interface ConfirmedQuote {
2727
};
2828
}
2929

30+
const extractLocationInfo = (address: string) => {
31+
// 시/도와 시/군/구를 추출하는 정규식
32+
const match = address.match(/([-]+)\s([-]+[-]*)/);
33+
if (!match) return address;
34+
35+
const province = match[1]; // 첫 번째 그룹 (시/도)
36+
const city = match[2].replace(/.*$/, ""); // 두 번째 그룹에서 '시' 이후 제거
37+
38+
return `${province}(${city})`;
39+
};
40+
3041
const setMessage = async (confirmedQuote: ConfirmedQuote) => {
42+
const pickupLocation = extractLocationInfo(
43+
confirmedQuote.movingRequest.pickupAddress
44+
);
45+
const dropOffLocation = extractLocationInfo(
46+
confirmedQuote.movingRequest.dropOffAddress
47+
);
3148
return [
3249
{
33-
content: `내일은 ,${confirmedQuote.movingRequest.pickupAddress} -> ${confirmedQuote.movingRequest.dropOffAddress} 이사 예정일,이에요.`,
50+
content: `내일은 ,${pickupLocation} -> ${dropOffLocation} 이사 예정일,이에요.`,
3451
isRead: false,
3552
userId: confirmedQuote.mover.user.id,
3653
},
3754
{
38-
content: `내일은 ,${confirmedQuote.movingRequest.pickupAddress} -> ${confirmedQuote.movingRequest.dropOffAddress} 이사 예정일,이에요.`,
55+
content: `내일은 ,${pickupLocation} -> ${dropOffLocation} 이사 예정일,이에요.`,
3956
isRead: false,
4057
userId: confirmedQuote.customer.user.id,
4158
},

src/services/authService.ts

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,7 @@ const signIn = async ({ email, password }: SignInData) => {
4444
throw error;
4545
}
4646

47-
// const isPasswordValid = await bcrypt.compare(password, user.password!);
48-
49-
const isPasswordValid = password === user.password;
47+
const isPasswordValid = await bcrypt.compare(password, user.password!); //패스워드 검증
5048

5149
if (!isPasswordValid) {
5250
const error: CustomError = new Error("Unauthorized");
@@ -87,9 +85,12 @@ const signUpCustomer = async (customer: SignUpCustomer) => {
8785
}
8886
}
8987

88+
const hashedPassword = await bcrypt.hash(customer.password, 10);
89+
9090
const customerData = {
9191
...customer,
9292
imageUrl,
93+
password: hashedPassword,
9394
};
9495

9596
const result = await userRepository.createCustomer(customerData);
@@ -125,9 +126,12 @@ const signUpMover = async (mover: SignUpMover) => {
125126
}
126127
}
127128

129+
const hashedPassword = await bcrypt.hash(mover.password, 10);
130+
128131
const moverData = {
129132
...mover,
130133
imageUrl,
134+
password: hashedPassword,
131135
};
132136
const result = await userRepository.createMover(moverData);
133137

@@ -137,4 +141,28 @@ const signUpMover = async (mover: SignUpMover) => {
137141
}
138142
};
139143

140-
export default { signIn, signUpCustomer, signUpMover };
144+
const validate = async (email: string, phoneNumber: string) => {
145+
const user = await userRepository.existingUser(email, phoneNumber);
146+
147+
if (user) {
148+
const error: CustomError = new Error("Conflict");
149+
if (user.email === email) {
150+
error.status = 409;
151+
error.data = {
152+
message: "이미 존재하는 이메일입니다.",
153+
};
154+
throw error;
155+
}
156+
if (user.phoneNumber === phoneNumber) {
157+
error.status = 409;
158+
error.data = {
159+
message: "이미 존재하는 전화번호입니다.",
160+
};
161+
throw error;
162+
}
163+
}
164+
165+
return user;
166+
};
167+
168+
export default { signIn, signUpCustomer, signUpMover, validate };

0 commit comments

Comments
 (0)