diff --git a/src/routes/docs/rooms.js b/src/routes/docs/rooms.js
new file mode 100644
index 00000000..3292b127
--- /dev/null
+++ b/src/routes/docs/rooms.js
@@ -0,0 +1,830 @@
+const { roomsSchema } = require("./roomsSchema");
+const { objectIdPattern, roomsPattern } = require("./utils");
+
+const tag = "rooms";
+const apiPrefix = "/rooms";
+
+const roomsDocs = {};
+
+roomsDocs[`${apiPrefix}/create`] = {
+ post: {
+ tags: [tag],
+ summary: "방 생성",
+ description: `방을 생성합니다. 한 유저당 최대 5개의 진행중인 방에 참여할 수 있습니다.
`,
+ requestBody: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ name: {
+ type: "string",
+ pattern: roomsPattern.rooms.name,
+ description: `방 이름
+ 1~50 글자로 구성되며 영어 대소문자, 숫자, 한글, 특정 특수기호("-", ",", ".", "?", "!", "_")만 가능`,
+ },
+ from: {
+ type: "string",
+ pattern: roomsPattern.rooms.from,
+ description: "출발지 location Document의 ObjectId",
+ },
+ to: {
+ type: "string",
+ pattern: roomsPattern.rooms.to,
+ description: "도착지 location Document의 ObjectId",
+ },
+ time: {
+ type: "string",
+ format: "date-time",
+ description: "방 출발 시각. 현재 이후여야 함.",
+ },
+ maxPartLength: {
+ type: "integer",
+ minimum: 2,
+ maximum: 4,
+ description: "방의 최대 인원 수",
+ },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: "생성 완성된 방 목록",
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ 400: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ examples: {
+ "출발지와 도착지가 같음": {
+ value: {
+ error: "Room/create : locations are same",
+ },
+ },
+ "현재로부터 2주일보다 이후의 방을 생성": {
+ value: {
+ error:
+ "Room/create : cannot over 2 weeks on the basis of current Date",
+ },
+ },
+ "존재하지 않는 location Document를 입력": {
+ value: {
+ error: "Rooms/create : no corresponding locations",
+ },
+ },
+ "사용자가 참여하는 진행 중 방이 5개 이상": {
+ value: {
+ error: "Rooms/create : participating in too many rooms",
+ },
+ },
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/create : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/publicInfo`] = {
+ get: {
+ tags: [tag],
+ summary: "정산 정보를 제외한 방 세부 사항 반환",
+ description:
+ "특정 id 방의 정산 정보를 제외한 세부사항을 반환합니다. 로그인을 하지 않아도 접근 가능합니다.",
+ parameters: [
+ {
+ in: "query",
+ name: "id",
+ schema: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ description: "찾고 싶은 방의 Object id",
+ },
+ ],
+ responses: {
+ 200: {
+ description: "방의 세부 정보가 담긴 room Object",
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ 404: {
+ description: "해당 id가 존재하지 않음",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/publicInfo : id does not exist",
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/publicInfo : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/info`] = {
+ get: {
+ tags: [tag],
+ summary: "방 세부 사항 반환",
+ description: "유저가 참여한 방의 세부사항을 반환합니다.",
+ parameters: [
+ {
+ in: "query",
+ name: "id",
+ schema: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ description: "찾고 싶은 방의 Object id",
+ },
+ ],
+ responses: {
+ 200: {
+ description: "방의 세부 정보가 담긴 room Object",
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ 404: {
+ description: "해당 id가 존재하지 않음",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/info : id does not exist",
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/info : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/join`] = {
+ post: {
+ tags: [tag],
+ summary: "진행 중인 방에 참여",
+ description: `room의 ID를 받아 해당 room의 참가자 목록에 요청을 보낸 사용자를 추가합니다.
+ 하나의 User는 최대 5개의 진행중인 방에 참여할 수 있습니다.
+ 아직 정원이 차지 않은 방과 아직 출발하지 않은 방에만 참여할 수 있습니다.`,
+ requestBody: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ roomId: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: "방의 세부 정보가 담긴 room Object",
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ 400: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ examples: {
+ "사용자가 참여하는 진행 중 방이 5개 이상": {
+ value: {
+ error: "Rooms/join : participating in too many rooms",
+ },
+ },
+ "입력한 시간의 방이 이미 출발함": {
+ value: {
+ error: "Room/join : The room has already departed",
+ },
+ },
+ "방의 인원이 모두 찼음": {
+ value: {
+ error: "Room/join : The room is already full",
+ },
+ },
+ },
+ },
+ },
+ },
+ 404: {
+ description: "해당 id를 가진 방이 존재하지 않음",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/join : no corresponding room",
+ },
+ },
+ },
+ },
+ 409: {
+ description: "사용자가 이미 참여중임",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/join : {userID} Already in room",
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "text/html": {
+ example: "Rooms/join : internal server error",
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/abort`] = {
+ post: {
+ tags: [tag],
+ summary: "참여 중인 방에서 퇴장",
+ description: `room의 ID를 받아 해당 room의 참가자 목록에서 요청을 보낸 사용자를 삭제합니다.
+ 출발했지만 정산이 완료되지 않은 방에서는 나갈 수 없습니다.`,
+ requestBody: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ roomId: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ 400: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ examples: {
+ "잘못된 userId를 포함한 요청임": {
+ value: {
+ error: "Rooms/abort : Bad request",
+ },
+ },
+ "정산이 되지 않은 출발한 방은 나갈 수 없음": {
+ value: {
+ error:
+ "Rooms/abort : cannot exit room. Settlement is not done",
+ },
+ },
+ },
+ },
+ },
+ },
+ 403: {
+ description: "사용자가 해당 방의 구성원이 아님",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/abort : did not joined the room",
+ },
+ },
+ },
+ },
+ 404: {
+ description: "해당 id를 가진 방이 존재하지 않음",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/abort : no corresponding room",
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/abort : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/search`] = {
+ get: {
+ tags: [tag],
+ summary: "방 검색",
+ description: `출발지/도착지/날짜를 받아 조건에 맞는 방을 검색합니다.
+ 조건에 맞는 방이 있을 경우, 방들의 정보를 반환하고 없다면 빈 배열을 반환합니다.
+ 로그인을 하지 않아도 접근 가능합니다.`,
+ parameters: [
+ {
+ in: "query",
+ name: "name",
+ schema: {
+ type: "string",
+ },
+ description: `검색할 방의 이름
+ 주어진 경우 해당 텍스트가 방의 이름에 포함된 방들만 반환.
+ 주어지지 않은 경우 임의의 이름을 가지는 방들을 검색.`,
+ },
+ {
+ in: "query",
+ name: "from",
+ schema: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ description: `출발지 Document의 ObjectId
+ 주어진 경우 출발지가 일치하는 방들만 반환.
+ 주어지지 않은 경우 임의의 출발지를 가지는 방들을 검색.`,
+ },
+ {
+ in: "query",
+ name: "to",
+ schema: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ description: `도착지 Document의 ObjectId
+ 주어진 경우 도착지가 일치하는 방들만 반환.
+ 주어지지 않은 경우 임의의 도착지를 가지는 방들을 검색.`,
+ },
+ {
+ in: "query",
+ name: "time",
+ schema: {
+ type: "string",
+ format: "date-time",
+ },
+ description: `출발 시각
+ 주어진 경우 주어진 시간부터 주어진 시간부터 그 다음에 찾아오는 오전 5시 전에 출발하는 방들만 반환.
+ 주어지지 않은 경우 현재 시각부터 그 다음으로 찾아오는 오전 5시 전까지의 방들을 반환.`,
+ },
+ {
+ in: "query",
+ name: "withTime",
+ schema: {
+ type: "boolean",
+ },
+ description: `검색 옵션에 시간 옵션이 포함되어 있는지 여부.
+ false이고 검색하는 날짜가 오늘 이후인 경우 검색하는 시간을 0시 0분 0초로 설정함.`,
+ },
+ {
+ in: "query",
+ name: "maxPartLength",
+ schema: {
+ type: "integer",
+ },
+ description: ` 방의 최대 인원 수.
+ 주어진 경우 최대 인원 수가 일치하는 방들만 반환.
+ 주어지지 않은 경우 임의의 최대 인원 수를 가지는 방들을 검색.`,
+ },
+ {
+ in: "query",
+ name: "isHome",
+ schema: {
+ type: "boolean",
+ },
+ description: `홈 페이지 검색인지 여부
+ true인 경우 검색 날짜 범위를 7일로 설정.
+ false인 경우 검색 날짜 범위를 14일로 설정.
`,
+ },
+ ],
+ responses: {
+ 200: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "array",
+ items: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ },
+ 400: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ examples: {
+ "출발지와 도착지가 같음": {
+ value: {
+ error: "Room/search : Bad request",
+ },
+ },
+ "출발/도착지가 존재하지 않는 장소": {
+ value: {
+ error: "Room/search : no corresponding locations",
+ },
+ },
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/search : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/searchByUser`] = {
+ get: {
+ tags: [tag],
+ summary: "사용자가 참여 중인 방 검색",
+ description: `로그인 된 사용자가 참여 중인 방을 검색합니다.
+ 정산 완료 여부 기준으로 진행 중인 방과 완료된 방을 \`ongoing\`과 \`done\`으로 각각 분리하여 응답을 전송합니다.
+ (\`ongoing\`은 \`isOver\`이 flase인 방, \`done\`은 \`isOver\`이 true인 방을 의미합니다.)`,
+ parameters: {},
+ responses: {
+ 200: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ ongoing: {
+ type: "array",
+ items: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ done: {
+ type: "array",
+ items: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/searchByUser : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/commitPayment`] = {
+ post: {
+ tags: [tag],
+ summary: "방 결제 처리",
+ description: `해당 방에 요청을 보낸 유저를 결제자로 처리합니다.
+ 이미 출발한 방에 대해서만 요청을 처리합니다.
+ 방의 \`part\` 배열에서 요청을 보낸 유저의 \`isSettlement\` 속성은 \`paid\`로 설정됩니다.
+ 나머지 유저들의 \`isSettlement\` 속성을 \`send-required\`로 설정합니다.`,
+ requestBody: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ roomId: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: "결제 정보가 수정된 방의 세부 정보가 담긴 room Object",
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ 404: {
+ description: `잘못된 방 요청
+ (사용자가 참여 중인 방이 아니거나, 이미 다른 사람이 결제자이거나, 아직 방이 출발하지 않은 경우)`,
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/:id/commitPayment : cannot find settlement info",
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/:id/commitPayment : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+roomsDocs[`${apiPrefix}/commitSettlement`] = {
+ post: {
+ tags: [tag],
+ summary: "방 정산 완료 처리",
+ description: `해당 방에 요청을 보낸 유저를 정산 완료로 처리합니다.
+ 방의 \`part\` 배열에서 요청을 보낸 유저의 \`isSettlement\` 속성은 \`send-required\`에서 \`sent\`로 변경합니다.
+ 방의 참여한 유저들이 모두 정산완료를 하면 방의 \`isOver\` 속성이 \`true\`로 변경되며, 과거 방으로 취급됩니다.`,
+ requestBody: {
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ roomId: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ },
+ },
+ },
+ },
+ },
+ responses: {
+ 200: {
+ description: "결제 정보가 수정된 방의 세부 정보가 담긴 room Object",
+ content: {
+ "application/json": {
+ schema: {
+ $ref: "#/components/schemas/room",
+ },
+ },
+ },
+ },
+ 404: {
+ description: `잘못된 방 요청
+ (사용자가 참여 중인 방이 아니거나, 사용자가 결제를 했거나 이미 정산한 경우)`,
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/:id/settlement : cannot find settlement info",
+ },
+ },
+ },
+ },
+ 500: {
+ description: "내부 서버 오류",
+ content: {
+ "application/json": {
+ schema: {
+ type: "object",
+ properties: {
+ error: {
+ type: "string",
+ },
+ },
+ },
+ example: {
+ error: "Rooms/:id/settlement : internal server error",
+ },
+ },
+ },
+ },
+ },
+ },
+};
+
+module.exports = roomsDocs;
diff --git a/src/routes/docs/rooms.md b/src/routes/docs/rooms.md
deleted file mode 100755
index 3346d753..00000000
--- a/src/routes/docs/rooms.md
+++ /dev/null
@@ -1,367 +0,0 @@
-# `/rooms` API
-
-## Table of contents
-
-- [`/rooms` API](#rooms-api)
- - [Table of contents](#table-of-contents)
- - [Description](#description)
- - [Available endpoints](#available-endpoints)
- - [`/publicInfo` **(GET)**](#publicinfo-get)
- - [URL parameters](#url-parameters)
- - [Response](#response)
- - [Errors](#errors)
- - [`/info` **(GET)**](#info-get)
- - [URL parameters](#url-parameters-1)
- - [Response](#response-1)
- - [Errors](#errors-1)
- - [`/create` **(POST)**](#create-post)
- - [POST request form](#post-request-form)
- - [Errors](#errors-2)
- - [Response](#response-2)
- - [`/join` (POST)](#join-post)
- - [request JSON form](#request-json-form)
- - [Errors](#errors-3)
- - [`/abort` (POST)](#abort-post)
- - [request JSON form](#request-json-form-1)
- - [Errors](#errors-4)
- - [`/search` **(GET)**](#search-get)
- - [URL parameters](#url-parameters-2)
- - [Response](#response-3)
- - [Errors](#errors-5)
- - [`/searchByUser` **(GET)**](#searchbyuser-get)
- - [URL parameters](#url-parameters-3)
- - [Response](#response-4)
- - [Errors](#errors-6)
- - [`/commitPayment` **(POST)**](#commitpayment-post)
- - [Request Body](#request-body)
- - [Response](#response-5)
- - [Errors](#errors-7)
- - [`/commitSettlement/` **(POST)**](#commitsettlement-post)
- - [Request Body](#request-body-1)
- - [Response](#response-6)
- - [Errors](#errors-8)
- - [`/edit/` **(POST)** **(for dev)**](#edit-post-for-dev)
- - [POST request form](#post-request-form-1)
- - [Response](#response-7)
- - [Errors](#errors-9)
- - [`/getAllRoom` **(GET)** (for dev)](#getallroom-get-for-dev)
- - [`/removeAllRoom` **(GET)** (for dev)](#removeallroom-get-for-dev)
- - [`/:id/delete/` **(GET)** **(for dev)**](#iddelete-get-for-dev)
- - [URL Parameters](#url-parameters-4)
- - [Response](#response-8)
- - [Errors](#errors-10)
-
-## Description
-
-- 방 생성/수정/삭제/조회 기능을 지원하는 API.
-- `/publicInfo`, `/search`를 제외한 endpoint는 로그인된 상태에서만 접근 가능
-- Request form에서 요구하는 property 이름에 ? 이 붙은 경우 필수가 아니라는 뜻
-- 방을 반환할 경우 그 type은 다음과 같다.
-
-```javascript
-Room {
- _id: ObjectId, //ObjectID
- name: String, // 1~50글자로 구성되며 영어 대소문자, 숫자, 한글, "-", ",", ".", "?", "!", "_"로만 이루어져야 함.
- from: {
- _id: ObjectId, // 출발지 document의 ObjectId
- koName: String, // 출발지의 한국어 명칭
- enName: String, // 출발지의 영어 명칭
- },
- to: {
- _id: ObjectId, // 도착지 document의 ObjectId
- koName: String, // 도착지의 한국어 명칭
- enName: String, // 도착지의 영어 명칭
- },
- time: String(ISO 8601), // ex) 방 출발 시각. '2022-01-12T13:58:20.180Z'
- isDeparted: Boolean, // 이미 출발한 택시인지 여부 (출발했으면 true)
- part: [
- {
- _id: ObjectId, // part의 ObjectId
- user: {
- _id: ObjectId, // 참여 중인 사용자 Document의 ObjectId
- name: String, // 참여 중인 사용자 이름
- nickname: String, // 참여 중인 사용자 닉네임
- profileImageUrl: String, // 프로필 사진 url
- isSettlement: String || undefined, //해당 사용자의 정산 상태 (주의: "/publicInfo"와 "/search"에서는 isSettlement 속성이 undefined로 설정됨).
- },
- }
- ],
- maxPartLength: Number(2~4), //방의 최대 인원 수
- madeat: String(ISO 8601), // ex) 방 생성 시각. '2022-01-12T13:58:20.180Z'
- settlementTotal: Number(2~4), // 정산이 완료된 사용자 수 (주의: "/publicInfo"와 "/search"에서는 settlementTotal 속성이 undefined로 설정됨).
- isOver: Boolean, // 요청을 보낸 사용자가 해당 방의 정산을 완료됐는지 여부(완료 시 true) (주의: rooms/search에서는 isOver 속성을 반환하지 않고 undefined를 반환함).
- __v: Number, // 문서 버전. mongoDB 내부적으로 사용됨.
-}
-```
-
-`settlementStatus` 속성은 아래 네 가지 값들 중 하나를 가진다.
-
-1. `"not-departed"` : 아무도 결제/정산하지 않은 상태
-2. `"paid"` : 택시비를 결제한 참가가 "결제하기" 버튼을 누르면 해당 참가자에게 설정되는 정산 상태.
-3. `"send-required"` : 특정 참가자가 "결제하기" 버튼을 눌렀을 때 그 방의 나머지 참가자에게 설정되는 정산 상태.
-4. `"sent"` : 정산 상태가`"send-required"`인 사용자가 "정산하기" 버튼을 눌렀을 때 그 사용자에게 설정되는 정산 상태.
-
-## Available endpoints
-
-### `/publicInfo` **(GET)**
-
-ID를 parameter로 받아 해당 ID의 room의 정보 출력
-
-#### URL parameters
-
-- id : 조회할 room의 ID
-
-#### Response
-
-- 해당 방의 정보
-- 각 참여자의 isSettlement 속성과 방의 settlementTotal 속성은 undefined로 설정됨.
-
-#### Errors
-
-- 404 "id does not exist"
-- 500 "internal server error"
-
-### `/info` **(GET)**
-
-ID를 parameter로 받아 해당 ID의 room의 정보 출력
-
-#### URL parameters
-
-- id : 조회할 room의 ID
-
-#### Response
-
-- 해당 방의 정보
-
-#### Errors
-
-- 403 "not logged in"
-- 403 "did not joined the room"
-- 404 "id does not exist"
-- 500 "internal server error"
-
-### `/create` **(POST)**
-
-요청을 받아 room을 생성
-하나의 User는 최대 5개의 진행중인 방에 참여할 수 있다.
-
-#### POST request form
-
-`Request body`
-
-```javascript
-{
- name : String, // 방 이름. 문서 상단에 명시된 규칙을 만족시켜야 함
- from : ObjectId, // 출발지 Document의 ObjectId
- to : ObjectId, // 도착지 Document의 ObjectId
- time : Date, // 방 출발 시각. 현재 이후여야 함.
- part? : String[], // 방 사람들의 ObjectId. 따라서 빈 배열로 요청하시면 됩니다.
- maxPartLength: Number(2~4), //방의 최대 인원 수
-}
-```
-
-#### Errors
-
-- 400 "bad request"
-- 400 "participating in too many rooms"
-- 400 "locations are same"
-- 400 "no corresponding locations"
-- 500 "internal server error"
-
-#### Response
-
-- 새로이 만들어진 방
-
-### `/join` (POST)
-
-room의 ID를 받아 해당 room의 참가자 목록에 요청을 보낸 사용자를 추가한다.
-하나의 User는 최대 5개의 진행중인 방에 참여할 수 있다.
-아직 정원이 차지 않은 방과 아직 출발하지 않은 방에만 참여할 수 있다.
-
-#### request JSON form
-
-```javascript
-{
- roomId : ObjectId, // 초대 혹은 참여하려는 방 Document의 ObjectId
-}
-```
-
-#### Errors
-
-- 400 "Bad request"
-- 400 "participating in too many rooms"
-- 400 "The room is full"
-- 400 "The room has already departed"
-- 404 "no corresponding room"
-- 409 "{userID} Already in room"
-- 500 "internal server error"
-
-### `/abort` (POST)
-
-room의 ID를 받아 해당 room의 참가자 목록에서 요청을 보낸 사용자를 삭제한다.
-출발했지만 정산이 완료되지 않은 방에서는 나갈 수 없다.
-
-#### request JSON form
-
-```javascript
-{
- roomId : ObjectId, // 초대 혹은 참여하려는 방 Document의 ObjectId
-}
-```
-
-#### Errors
-
-- 400 "Bad request"
-- 400 "cannot exit room. Settlement is not done"
-- 404 "no corresponding room"
-- 500 "internal server error"
-
-
-### `/search` **(GET)**
-
-출발지/도착지/날짜를 받아 해당하는 room들을 반환한다.
-
-#### URL parameters
-
-- name?: String, // 검색할 방의 이름. 주어진 경우 해당 텍스트가 방의 이름에 포함된 방들만 반환. 주어지지 않은 경우 임의의 이름을 가지는 방들을 검색.
-- from? : ObjectId, // 출발지 Document의 ObjectId. 주어진 경우 출발지가 일치하는 방들만 반환. 주어지지 않은 경우 임의의 출발지를 가지는 방들을 검색.
-- to? : ObjectId, // 도착지 Document의 ObjectId. 주어진 경우 도착지가 일치하는 방들만 반환. 주어지지 않은 경우 임의의 도착지를 가지는 방들을 검색.
-- time? : Date, // 출발 시각. 주어진 경우 주어진 시간부터 주어진 시간부터 그 다음에 찾아오는 오전 5시 전에 출발하는 방들만 반환. 주어지지 않은 경우 현재 시각부터 그 다음으로 찾아오는 오전 5시 전까지의 방들을 반환.
-- withTime? : Boolean, // 검색 옵션에 시간 옵션이 포함되어 있는지 여부. false이고 검색하는 날짜가 오늘 이후인 경우 검색하는 시간을 0시 0분 0초로 설정함.
-- maxPartLength?: Number(2~4), // 방의 최대 인원 수. 주어진 경우 최대 인원 수가 일치하는 방들만 반환. 주어지지 않은 경우 임의의 최대 인원 수를 가지는 방들을 검색.
-
-
-#### Response
-
-조건에 맞는 방**들**의 정보: `Room[]`
-조건에 일치하는 방이 없더라도 빈 배열을 반환함.
-
-#### Errors
-
-- 400 "Bad request"
-- 400 "no corresponding locations"
-- 500 "Internal server error"
-
-### `/searchByUser` **(GET)**
-
-로그인된 사용자가 참여 중인 room들을 반환한다.
-
-#### URL parameters
-
-없음.
-
-#### Response
-
-```javascript
-{
- ongoing: [Room], // 정산이 완료되지 않은 방 (방의 isOver 속성이 false인 방)
- done: [Room], // 정산이 완료된 방 (방의 isOver 속성이 true인 방)
-}
-```
-
-#### Errors
-
-- 403 "not logged in"
-- 500 "internal server error"
-
-
-### `/commitPayment` **(POST)**
-
-- ID를 받아 해당 방에 요청을 보낸 유저를 결제자로 처리
-- 이미 출발한 방(현재 시각이 출발 시각 이후인 경우)에 대해서만 요청을 처리함
-- 방의 part 배열에서 요청을 보낸 유저의 isSettlement 속성을 `paid`로 설정하고, 나머지 유저들의 isSettlement 속성을 `"send-required"`로 설정함.
-
-#### Request Body
-
-- roomId : 정산할 room의 ID
-
-#### Response
-
-- 멤버들의 정산정보가 반영된 방의 정보
-
-#### Errors
-
-- 400 "Bad request": 로그인이 되어있지 않은 경우
-- 404 "cannot find settlement info": 사용자가 참여 중인 방이 아니거나, 이미 다른 사람이 결제자이거나, 아직 방이 출발하지 않은 경우
-- 500 "internal server error"
-
-
-
-### `/commitSettlement/` **(POST)**
-
-- ID를 받아 해당 방에 요청을 보낸 유저의 정산을 완료로 처리
-- 방의 part 배열에서 요청을 보낸 유저의 isSettlement 속성을 `send-required`에서 `"sent"`로 변경함.
-- 방에 참여한 멤버들이 모두 정산완료를 하면 방의 `isOver` 속성이 `true`로 변경되며, 과거 방으로 취급됨
-
-#### Request Body
-
-- roomId : 정산할 room의 ID
-
-#### Response
-
-- 멤버들의 정산정보가 반영된 방의 정보
-
-#### Errors
-
-- 400 "Bad request" : 로그인이 되어있지 않은 경우
-- 404 "cannot find settlement info": 사용자가 참여중인 방이 아니거나, 사용자가 결제를 했거나 이미 정산한 경우
-- 500 "internal server error"
-
-### `/edit/` **(POST)** **(for dev)**
-
-- ID와 수정할 데이터를 JSON으로 받아 해당 ID의 room을 수정
-- 방에 참여중인 사용자만 정보를 수정할 수 있음.
-- 프론트엔드에서 쓰일 일은 없어 보임.
-
-#### POST request form
-
-```javascript
-{
- roomId : String, // 수정할 room의 ID
- name? : String, // 방 이름. 문서 상단에 명시된 규칙을 만족시켜야 함
- from? : ObjectId, // 출발지 Document의 ObjectId
- to? : ObjectId, // 도착지 Document의 ObjectId
- time? : Date, // 방 출발 시각. 현재 이후여야 함.
- maxPartLength?: Number(2~4), // 방의 최대 인원 수. 현재 참여 인원수보다 크거나 같은 값이어야 함.
-}
-```
-
-#### Response
-
-- 변경된 방의 정보
-
-#### Errors
-
-- 400 "Bad request"
-- 404 "id does not exist"
-- 500 "internal server error"
-
-### `/getAllRoom` **(GET)** (for dev)
-
-모든 방 가져옴
-
-### `/removeAllRoom` **(GET)** (for dev)
-
-모든 방 삭제
-
-### `/:id/delete/` **(GET)** **(for dev)**
-
-ID를 받아 해당 ID의 room을 제거
-
-#### URL Parameters
-
-- id : 삭제할 room의 ID
-
-#### Response
-
-```javascript
-{
- id: ObjectId, // 삭제할 방 Document의 ObjectId
- isDeleted: true
-}
-```
-
-#### Errors
-
-- 404 "ID does not exist"
-- 500 "Internal server error"
\ No newline at end of file
diff --git a/src/routes/docs/roomsSchema.js b/src/routes/docs/roomsSchema.js
new file mode 100644
index 00000000..e256c5dd
--- /dev/null
+++ b/src/routes/docs/roomsSchema.js
@@ -0,0 +1,90 @@
+const { objectIdPattern, roomsPattern } = require("./utils");
+
+const participantSchema = {
+ part: {
+ type: "object",
+ required: ["_id", "name", "nickname", "profileImageUrl", "readAt"],
+ properties: {
+ _id: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ name: {
+ type: "string",
+ },
+ nickname: {
+ type: "string",
+ },
+ profileImageUrl: {
+ type: "string",
+ },
+ isSettlement: {
+ type: "string",
+ enum: ["not-departed", "paid", "send-required", "sent"],
+ default: "not-departed",
+ },
+ readAt: {
+ type: "string",
+ format: "date-time",
+ },
+ },
+ },
+};
+
+const roomsSchema = {
+ room: {
+ type: "object",
+ required: [
+ "name",
+ "from",
+ "to",
+ "time",
+ "part",
+ "madeat",
+ "maxPartLength",
+ "isDeparted",
+ ],
+ properties: {
+ name: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ from: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ to: {
+ type: "string",
+ pattern: objectIdPattern,
+ },
+ time: {
+ type: "string",
+ format: "date-time",
+ },
+ part: {
+ type: "array",
+ items: participantSchema["part"],
+ },
+ madeat: {
+ type: "string",
+ format: "date-time",
+ },
+ maxPartLength: {
+ type: "integer",
+ default: 4,
+ },
+ settlementTotal: {
+ type: "integer",
+ default: 0,
+ },
+ isOver: {
+ type: "boolean",
+ },
+ isDeparted: {
+ type: "boolean",
+ },
+ },
+ },
+};
+
+module.exports = { roomsSchema, participantSchema };
diff --git a/src/routes/docs/swaggerDocs.js b/src/routes/docs/swaggerDocs.js
index c0b474b4..a6dab17a 100644
--- a/src/routes/docs/swaggerDocs.js
+++ b/src/routes/docs/swaggerDocs.js
@@ -1,9 +1,11 @@
const reportsSchema = require("./reportsSchema");
+const { participantSchema, roomsSchema } = require("./roomsSchema");
const reportsDocs = require("./reports");
const logininfoDocs = require("./logininfo");
const locationsDocs = require("./locations");
const authDocs = require("./auth");
const usersDocs = require("./users");
+const roomsDocs = require("./rooms");
const chatsDocs = require("./chats");
const { port, nodeEnv } = require("../../../loadenv");
@@ -57,6 +59,10 @@ const swaggerDocs = {
name: "users",
description: "유저 계정 정보 수정 및 조회",
},
+ {
+ name: "rooms",
+ description: "방 생성/수정/삭제/조회 및 관리 지원",
+ },
{
name: "chats",
description: "채팅 시 발생하는 이벤트 정리",
@@ -71,10 +77,13 @@ const swaggerDocs = {
...usersDocs,
...authDocs,
...chatsDocs,
+ ...roomsDocs,
},
components: {
schemas: {
...reportsSchema,
+ ...participantSchema,
+ ...roomsSchema,
},
},
};
diff --git a/src/routes/docs/utils.js b/src/routes/docs/utils.js
index b435476b..8181ceac 100644
--- a/src/routes/docs/utils.js
+++ b/src/routes/docs/utils.js
@@ -1,3 +1,12 @@
const objectIdPattern = `^[a-fA-F\d]{24}$`;
+const roomsPattern = {
+ rooms: {
+ name: RegExp(
+ "^[A-Za-z0-9가-힣ㄱ-ㅎㅏ-ㅣ,.?! _~/#'\\\\@=\"\\-\\^()+*<>{}[\\]]{1,50}$"
+ ),
+ from: RegExp("^[A-Za-z0-9가-힣 -]{1,20}$"),
+ to: RegExp("^[A-Za-z0-9가-힣 -]{1,20}$"),
+ },
+};
-module.exports = { objectIdPattern };
+module.exports = { objectIdPattern, roomsPattern };
diff --git a/src/services/rooms.js b/src/services/rooms.js
index d4b7557e..a2562c67 100644
--- a/src/services/rooms.js
+++ b/src/services/rooms.js
@@ -110,13 +110,13 @@ const publicInfoHandler = async (req, res) => {
res.send(formatSettlement(roomObject, { includeSettlement: false }));
} else {
res.status(404).json({
- error: "Rooms/info : id does not exist",
+ error: "Rooms/publicInfo : id does not exist",
});
}
} catch (err) {
logger.error(err);
res.status(500).json({
- error: "Rooms/info : internal server error",
+ error: "Rooms/publicInfo : internal server error",
});
}
};
@@ -153,7 +153,7 @@ const joinHandler = async (req, res) => {
// 사용자의 참여중인 진행중인 방이 5개 이상이면 오류를 반환합니다.
if (user.ongoingRoom.length >= 5) {
return res.status(400).json({
- error: "Rooms/create : participating in too many rooms",
+ error: "Rooms/join : participating in too many rooms",
});
}
@@ -244,7 +244,7 @@ const abortHandler = async (req, res) => {
.indexOf(user._id.toString());
if (roomPartIndex === -1) {
return res.status(403).json({
- error: "Rooms/info : did not joined the room",
+ error: "Rooms/abort : did not joined the room",
});
}
@@ -254,7 +254,7 @@ const abortHandler = async (req, res) => {
// 방의 출발시간이 지나고 정산이 되지 않으면 나갈 수 없음
if (isOvertime(room, req.timestamp) && userOngoingRoomIndex !== -1) {
return res.status(400).json({
- error: "Rooms/info : cannot exit room. Settlement is not done",
+ error: "Rooms/abort : cannot exit room. Settlement is not done",
});
}
@@ -377,7 +377,6 @@ const searchHandler = async (req, res) => {
.limit(1000)
.populate(roomPopulateOption)
.lean();
-
res.json(
rooms.map((room) => formatSettlement(room, { includeSettlement: false }))
);