diff --git a/scripts/chatPaymentSettlementUpdater.js b/scripts/chatPaymentSettlementUpdater.js new file mode 100644 index 00000000..76e43682 --- /dev/null +++ b/scripts/chatPaymentSettlementUpdater.js @@ -0,0 +1,34 @@ +// Issue #449-1을 해결하기 위한 DB 마이그레이션 스크립트입니다. +// chat type 중 settlement와 payment를 서로 교체합니다. +// https://github.com/sparcs-kaist/taxi-back/issues/449 + +const { MongoClient } = require("mongodb"); +const { mongo: mongoUrl } = require("../loadenv"); + +const client = new MongoClient(mongoUrl); +const db = client.db("taxi"); +const chats = db.collection("chats"); + +async function run() { + try { + for await (const doc of chats.find()) { + if (doc.type === "settlement" || doc.type === "payment") { + await chats.findOneAndUpdate( + { _id: doc._id }, + { + $set: { + type: doc.type === "settlement" ? "payment" : "settlement", + }, + } + ); + } + } + } catch (err) { + console.log(err); + } finally { + await client.close(); + } +} +run().then(() => { + console.log("Done!"); +}); diff --git a/src/lottery/modules/contracts.js b/src/lottery/modules/contracts.js index 87a24a84..72a62deb 100644 --- a/src/lottery/modules/contracts.js +++ b/src/lottery/modules/contracts.js @@ -127,7 +127,7 @@ const completeFirstLoginQuest = async (userId, timestamp) => { * @param {Date} roomObject.time - 출발 시각입니다. * @returns {Promise} * @description 정산 요청 또는 송금이 이루어질 때마다 호출해 주세요. - * @usage rooms - commitPaymentHandler, rooms - settlementHandler + * @usage rooms - commitSettlementHandler, rooms - commitPaymentHandler */ const completePayingAndSendingQuest = async (userId, timestamp, roomObject) => { logger.info( @@ -167,7 +167,7 @@ const completeFirstRoomCreationQuest = async (userId, timestamp) => { * @param {Date} roomObject.time - 출발 시각입니다. * @returns {Promise} * @description 정산 요청이 이루어질 때마다 호출해 주세요. - * @usage rooms - commitPaymentHandler + * @usage rooms - commitSettlementHandler */ const completePayingQuest = async (userId, timestamp, roomObject) => { logger.info( @@ -195,7 +195,7 @@ const completePayingQuest = async (userId, timestamp, roomObject) => { * @param {Date} roomObject.time - 출발 시각입니다. * @returns {Promise} * @description 송금이 이루어질 때마다 호출해 주세요. - * @usage rooms - settlementHandler + * @usage rooms - commitPaymentHandler */ const completeSendingQuest = async (userId, timestamp, roomObject) => { logger.info( diff --git a/src/modules/socket.js b/src/modules/socket.js index c238ce64..9cda8991 100644 --- a/src/modules/socket.js +++ b/src/modules/socket.js @@ -82,11 +82,11 @@ const getMessageBody = (type, nickname = "", content = "") => { const suffix = "님이 퇴장하였습니다"; return `${ellipsisedNickname} ${suffix}`; } - case "payment": { + case "settlement": { const suffix = "님이 정산을 시작하였습니다"; return `${ellipsisedNickname} ${suffix}`; } - case "settlement": { + case "payment": { const suffix = "님이 송금을 완료하였습니다"; return `${ellipsisedNickname} ${suffix}`; } diff --git a/src/routes/docs/chats.js b/src/routes/docs/chats.js index 0aaa1c6d..f9107201 100644 --- a/src/routes/docs/chats.js +++ b/src/routes/docs/chats.js @@ -211,7 +211,7 @@ chatsDocs[`${apiPrefix}/send`] = { Chat { roomId: ObjectId, //방의 objectId - type: String, // 메시지 종류 ("text": 일반 메시지, "s3img": S3에 업로드된 이미지, "in": 입장 메시지, "out": 퇴장 메시지, "payment": 결제 메시지, "settlement": 정산 완료 메시지, "account": 계좌 전송 메시지) + type: String, // 메시지 종류 ("text": 일반 메시지, "s3img": S3에 업로드된 이미지, "in": 입장 메시지, "out": 퇴장 메시지, "settlement": 정산 메시지, "payment": 송금 메시지, "account": 계좌 전송 메시지) authorId: ObejctId, //작성자의 objectId content: String, // 메시지 내용 (메시지 종류에 따라 포맷이 상이함) time: String(ISO 8601), // ex) 2024-01-08T01:52:00.000Z diff --git a/src/routes/docs/rooms.js b/src/routes/docs/rooms.js index 710bf649..87488b11 100644 --- a/src/routes/docs/rooms.js +++ b/src/routes/docs/rooms.js @@ -683,11 +683,11 @@ roomsDocs[`${apiPrefix}/searchByUser`] = { }, }; -roomsDocs[`${apiPrefix}/commitPayment`] = { +roomsDocs[`${apiPrefix}/commitSettlement`] = { post: { tags: [tag], - summary: "방 결제 처리", - description: `해당 방에 요청을 보낸 유저를 결제자로 처리합니다.
+ summary: "방 정산 요청 처리", + description: `해당 방에 요청을 보낸 유저를 결제자로 처리하여, 다른 유저들에게 정산을 요청합니다.
이미 출발한 방에 대해서만 요청을 처리합니다.
방의 \`part\` 배열에서 요청을 보낸 유저의 \`isSettlement\` 속성은 \`paid\`로 설정됩니다.
나머지 유저들의 \`isSettlement\` 속성을 \`send-required\`로 설정합니다.`, @@ -731,7 +731,7 @@ roomsDocs[`${apiPrefix}/commitPayment`] = { }, }, example: { - error: "Rooms/:id/commitPayment : cannot find settlement info", + error: "Rooms/:id/commitSettlement : cannot find settlement info", }, }, }, @@ -749,7 +749,7 @@ roomsDocs[`${apiPrefix}/commitPayment`] = { }, }, example: { - error: "Rooms/:id/commitPayment : internal server error", + error: "Rooms/:id/commitSettlement : internal server error", }, }, }, @@ -758,11 +758,11 @@ roomsDocs[`${apiPrefix}/commitPayment`] = { }, }; -roomsDocs[`${apiPrefix}/commitSettlement`] = { +roomsDocs[`${apiPrefix}/commitPayment`] = { post: { tags: [tag], - summary: "방 정산 완료 처리", - description: `해당 방에 요청을 보낸 유저를 정산 완료로 처리합니다.
+ summary: "방 송금 처리", + description: `해당 방에 요청을 보낸 유저를 송금을 완료한 정산 완료로 처리합니다.
방의 \`part\` 배열에서 요청을 보낸 유저의 \`isSettlement\` 속성은 \`send-required\`에서 \`sent\`로 변경합니다.
방의 참여한 유저들이 모두 정산완료를 하면 방의 \`isOver\` 속성이 \`true\`로 변경되며, 과거 방으로 취급됩니다.`, requestBody: { @@ -805,7 +805,7 @@ roomsDocs[`${apiPrefix}/commitSettlement`] = { }, }, example: { - error: "Rooms/:id/settlement : cannot find settlement info", + error: "Rooms/:id/commitPayment : cannot find settlement info", }, }, }, @@ -823,7 +823,7 @@ roomsDocs[`${apiPrefix}/commitSettlement`] = { }, }, example: { - error: "Rooms/:id/settlement : internal server error", + error: "Rooms/:id/commitPayment : internal server error", }, }, }, diff --git a/src/routes/docs/schemas/roomsSchema.js b/src/routes/docs/schemas/roomsSchema.js index 39dcd8bf..a0af753e 100644 --- a/src/routes/docs/schemas/roomsSchema.js +++ b/src/routes/docs/schemas/roomsSchema.js @@ -31,6 +31,14 @@ roomsZod["room"] = z }) .partial({ settlementTotal: true, isOver: true }); +roomsZod["commitSettlement"] = z.object({ + roomId: z.string().regex(objectId), +}); + +roomsZod["commitPayment"] = z.object({ + roomId: z.string().regex(objectId), +}); + const roomsSchema = zodToSchemaObject(roomsZod); module.exports = { roomsSchema, roomsZod }; diff --git a/src/routes/rooms.js b/src/routes/rooms.js index 6334136d..6345fa6f 100644 --- a/src/routes/rooms.js +++ b/src/routes/rooms.js @@ -1,5 +1,7 @@ const express = require("express"); const { query, body } = require("express-validator"); +const { validateBody } = require("../middlewares/zod"); +const { roomsZod } = require("./docs/schemas/roomsSchema"); const router = express.Router(); const roomHandlers = require("../services/rooms"); @@ -91,19 +93,18 @@ router.post( // 로그인된 사용자의 모든 방들을 반환한다. router.get("/searchByUser", roomHandlers.searchByUserHandler); +// 해당 방에 요청을 보낸 유저의 정산을 처리한다. router.post( - "/commitPayment", - body("roomId").isMongoId(), - validator, - roomHandlers.commitPaymentHandler + "/commitSettlement", + validateBody(roomsZod.commitSettlement), + roomHandlers.commitSettlementHandler ); -// 해당 룸의 요청을 보낸 유저의 정산을 완료로 처리한다. +// 해당 방에 요청을 보낸 유저의 송금을 처리한다. router.post( - "/commitSettlement", - body("roomId").isMongoId(), - validator, - roomHandlers.settlementHandler + "/commitPayment", + validateBody(roomsZod.commitPayment), + roomHandlers.commitPaymentHandler ); // json으로 수정할 값들을 받아 방의 정보를 수정합니다. diff --git a/src/services/rooms.js b/src/services/rooms.js index cf8b6e9e..a1a61913 100644 --- a/src/services/rooms.js +++ b/src/services/rooms.js @@ -559,7 +559,7 @@ const searchByUserHandler = async (req, res) => { } }; -const commitPaymentHandler = async (req, res) => { +const commitSettlementHandler = async (req, res) => { try { const user = await userModel.findOne({ id: req.userId }); const { roomId } = req.body; @@ -593,7 +593,7 @@ const commitPaymentHandler = async (req, res) => { if (!roomObject) { return res.status(404).json({ - error: "Rooms/:id/commitPayment : cannot find settlement info", + error: "Rooms/:id/commitSettlement : cannot find settlement info", }); } @@ -606,17 +606,17 @@ const commitPaymentHandler = async (req, res) => { if (userOngoingRoomIndex === -1) { await user.save(); return res.status(500).json({ - error: "Rooms/:id/settlement : internal server error", + error: "Rooms/:id/commitSettlement : internal server error", }); } user.ongoingRoom.splice(userOngoingRoomIndex, 1); await user.save(); - // 결제 채팅을 보냅니다. + // 정산 채팅을 보냅니다. await emitChatEvent(req.app.get("io"), { roomId, - type: "payment", + type: "settlement", content: user.id, authorId: user._id, }); @@ -638,12 +638,12 @@ const commitPaymentHandler = async (req, res) => { } catch (err) { logger.error(err); res.status(500).json({ - error: "Rooms/:id/commitPayment : internal server error", + error: "Rooms/:id/commitSettlement : internal server error", }); } }; -const settlementHandler = async (req, res) => { +const commitPaymentHandler = async (req, res) => { try { const { roomId } = req.body; const user = await userModel.findOne({ id: req.userId }); @@ -671,7 +671,7 @@ const settlementHandler = async (req, res) => { if (!roomObject) { return res.status(404).json({ - error: "Rooms/:id/settlement : cannot find settlement info", + error: "Rooms/:id/commitPayment : cannot find settlement info", }); } @@ -684,17 +684,17 @@ const settlementHandler = async (req, res) => { if (userOngoingRoomIndex === -1) { await user.save(); return res.status(500).json({ - error: "Rooms/:id/settlement : internal server error", + error: "Rooms/:id/commitPayment : internal server error", }); } user.ongoingRoom.splice(userOngoingRoomIndex, 1); await user.save(); - // 정산 채팅을 보냅니다. + // 송금 채팅을 보냅니다. await emitChatEvent(req.app.get("io"), { roomId, - type: "settlement", + type: "payment", content: user.id, authorId: user._id, }); @@ -716,7 +716,7 @@ const settlementHandler = async (req, res) => { } catch (err) { logger.error(err); res.status(500).json({ - error: "Rooms/:id/settlement : internal server error", + error: "Rooms/:id/commitPayment : internal server error", }); } }; @@ -811,6 +811,6 @@ module.exports = { searchHandler, searchByUserHandler, commitPaymentHandler, - settlementHandler, + commitSettlementHandler, // editHandler, }; diff --git a/test/services/rooms.js b/test/services/rooms.js index e17ae6af..4e948ad1 100644 --- a/test/services/rooms.js +++ b/test/services/rooms.js @@ -141,8 +141,8 @@ describe("[rooms] 6.searchByUserHandler", () => { }); // 7. 1분이 지난 후, 정산 정보를 불러옴. 예상과 같은 정보를 불러오는지 확인 -describe("[rooms] 7.commitPaymentHandler", () => { - it("should return information of room and commit payment", async () => { +describe("[rooms] 7.commitSettlementHandler", () => { + it("should return information of room and commit settlement", async () => { const testUser1 = await userModel.findOne({ id: "test1" }); const testRoom = await roomModel.findOne({ name: "test-room" }); let req = httpMocks.createRequest({ @@ -152,7 +152,7 @@ describe("[rooms] 7.commitPaymentHandler", () => { app, }); let res = httpMocks.createResponse(); - await roomsHandlers.commitPaymentHandler(req, res); + await roomsHandlers.commitSettlementHandler(req, res); const resData = res._getData(); expect(resData).to.has.property("name", "test-room"); @@ -161,9 +161,9 @@ describe("[rooms] 7.commitPaymentHandler", () => { }); }); -// 8. 도착 정보를 불러옴. 예상과 같은 정보를 불러오는지 확인 -describe("[rooms] 8.settlementHandler", () => { - it("should return information of room and set settlement", async () => { +// 8. 송금 후 정산 정보를 불러옴. 예상과 같은 정보를 불러오는지 확인 +describe("[rooms] 8.commitPaymentHandler", () => { + it("should return information of room and commit payment", async () => { const testUser2 = await userModel.findOne({ id: "test2" }); const testRoom = await roomModel.findOne({ name: "test-room" }); let req = httpMocks.createRequest({ @@ -172,7 +172,7 @@ describe("[rooms] 8.settlementHandler", () => { app, }); let res = httpMocks.createResponse(); - await roomsHandlers.settlementHandler(req, res); + await roomsHandlers.commitPaymentHandler(req, res); const resData = res._getData(); expect(resData).to.has.property("name", "test-room");