Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main branch update from Dev branch #543

Merged
merged 40 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b679c03
Add: create/join feature restriction
TaehyeonPark Aug 12, 2024
5f4a9b9
Add: BanSchema
TaehyeonPark Aug 12, 2024
89cc169
Add: Swagger docs
TaehyeonPark Aug 12, 2024
2c280c8
Refactor: unnecessary code deletion
TaehyeonPark Aug 12, 2024
ca70330
Add: default value for eventConfig
kmc7468 Aug 26, 2024
097ec2a
Add: completedQuestSchema
kmc7468 Aug 28, 2024
e5d7674
Refactor: quest list
kmc7468 Aug 28, 2024
5c00f4e
Refactor: update globalState router for 2024 fall event
kmc7468 Aug 28, 2024
8f4c58a
Refactor: update invites router for 2024 fall event
kmc7468 Aug 28, 2024
61e4b07
Refactor: update quests router for 2024 fall event
kmc7468 Aug 28, 2024
14f13ca
Refactor: update transactions router for 2024 fall event
kmc7468 Aug 28, 2024
f2f6103
Add: item leaderboard
kmc7468 Aug 29, 2024
c1ea322
Refactor: exclude banned user from item leaderboards
kmc7468 Aug 31, 2024
f25c646
Add: credit random box
kmc7468 Aug 31, 2024
4fe74d0
Docs: lottery module
kmc7468 Aug 31, 2024
6f9a434
Remove: disable publicNotice router
kmc7468 Aug 31, 2024
d7e742d
Fix: invalid format of completedQuests element
kmc7468 Sep 1, 2024
4a1f9af
Fix: invalid eventStatus.inviter value
kmc7468 Sep 1, 2024
e7ef57b
Fix: dailyAttendance can be completed infinitely
kmc7468 Sep 1, 2024
05126ee
Add: totalAmount, totalUser field into item leaderboard
kmc7468 Sep 1, 2024
e541fc0
Merge pull request #537 from sparcs-kaist/#536-2024-chuseok-event
kmc7468 Sep 1, 2024
1f52f5c
Add: ban user by sso id
TaehyeonPark Sep 2, 2024
6bb6fe0
Merge branch 'dev' into #520-ban-여부에-따른-서비스-이용-제한
TaehyeonPark Sep 2, 2024
f6c49ae
Add: pull origin dev
TaehyeonPark Sep 2, 2024
c381eff
Merge branch 'dev' of https://github.com/sparcs-kaist/taxi-back into …
TaehyeonPark Sep 2, 2024
a8c35ef
Merge branch '#520-ban-여부에-따른-서비스-이용-제한' of https://github.com/sparcs…
TaehyeonPark Sep 2, 2024
56bd968
Add: modulize validation of service ban
TaehyeonPark Sep 2, 2024
7eceae0
Add: resolve comments
TaehyeonPark Sep 3, 2024
eecc5f6
Add: resolve comments
TaehyeonPark Sep 3, 2024
9151693
feat: add item handler
Sep 3, 2024
ab69625
Add: resolve comments
TaehyeonPark Sep 3, 2024
9d47b87
feat: unused field remove && update doc
Sep 3, 2024
dde8965
fix: minor doc update
Sep 3, 2024
4d487c6
fix: minor doc fix
Sep 3, 2024
f3f41e0
Merge pull request #538 from sparcs-kaist/2024fall-item
xMHW Sep 3, 2024
b341a33
Add: ban middleware
TaehyeonPark Sep 3, 2024
074d357
Add: resolve comments
TaehyeonPark Sep 4, 2024
8da0c4a
Add: resolve comments
TaehyeonPark Sep 4, 2024
0729f66
Remove: unnecessary require
kmc7468 Sep 4, 2024
30ff291
Merge pull request #530 from sparcs-kaist/#520-ban-여부에-따른-서비스-이용-제한
TaehyeonPark Sep 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion loadenv.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,18 @@ module.exports = {
slackWebhookUrl: {
report: process.env.SLACK_REPORT_WEBHOOK_URL || "", // optional
},
eventConfig: process.env.EVENT_CONFIG && JSON.parse(process.env.EVENT_CONFIG), // optional
eventConfig: (process.env.EVENT_CONFIG &&
JSON.parse(process.env.EVENT_CONFIG)) || {
mode: "2024fall",
credit: {
name: "송편코인",
initialAmount: 0,
},
period: {
startAt: new Date("2024-09-07T00:00:00+09:00"),
endAt: new Date("2024-09-24T00:00:00+09:00"),
},
}, // optional
naverMap: {
apiId: process.env.NAVER_MAP_API_ID, // optional
apiKey: process.env.NAVER_MAP_API_KEY, //optional
Expand Down
4 changes: 2 additions & 2 deletions src/lottery/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ lotteryRouter.use(require("../middlewares/originValidator"));

// [Router] APIs
lotteryRouter.use("/globalState", require("./routes/globalState"));
lotteryRouter.use("/invite", require("./routes/invite"));
lotteryRouter.use("/invites", require("./routes/invites"));
lotteryRouter.use("/transactions", require("./routes/transactions"));
lotteryRouter.use("/items", require("./routes/items"));
lotteryRouter.use("/publicNotice", require("./routes/publicNotice"));
// lotteryRouter.use("/publicNotice", require("./routes/publicNotice"));
lotteryRouter.use("/quests", require("./routes/quests"));

// [AdminJS] AdminJS에 표시할 Resource 생성
Expand Down
150 changes: 58 additions & 92 deletions src/lottery/modules/contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,53 +13,44 @@ const quests = buildQuests({
firstLogin: {
name: "첫 발걸음",
description:
"로그인만 해도 넙죽코인을 얻을 수 있다고?? 이벤트 기간에 처음으로 SPARCS Taxi 서비스에 로그인하여 넙죽코인을 받아보세요.",
"이벤트 참여만 해도 송편코인을 얻을 수 있다고?? 이벤트 참여에 동의하고 송편코인을 받아 보세요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_firstLogin.png",
reward: 50,
},
payingAndSending: {
name: "함께하는 택시의 여정",
description:
"2명 이상과 함께 택시를 타고 정산/송금까지 완료해보세요. 최대 3번까지 넙죽코인을 받을 수 있어요. 정산/송금 버튼은 채팅 페이지 좌측 하단의 <b>+버튼</b>을 눌러 확인할 수 있어요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_payingAndSending.png",
reward: 150,
maxCount: 0,
reward: 200,
},
firstRoomCreation: {
name: "첫 방 개설",
description:
"원하는 택시팟을 찾을 수 없다면? 원하는 조건으로 <b>방 개설 페이지</b>에서 방을 직접 개설해보세요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_firstRoomCreation.png",
reward: 50,
reward: 500,
},
roomSharing: {
name: "너 T야? Taxi",
name: "이 택시팟은 진짜 유명한 택시팟임",
description:
"방을 공유해 친구들을 택시에 초대해보세요. 채팅창 상단의 햄버거(☰) 버튼을 누르면 <b>공유하기</b> 버튼을 찾을 수 있어요.",
"방을 공유해 친구들을 택시팟에 초대해 보세요. 채팅창 상단의 햄버거(☰) 버튼을 누르면 <b>공유하기 버튼</b> 찾을 수 있어요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_roomSharing.png",
reward: 50,
reward: 500,
isApiRequired: true,
},
paying: {
name: "정산해요 택시의 숲",
fareSettlement: {
name: "정산의 신, 신팍스",
description:
"2명 이상과 함께 택시를 타고 택시비를 결제한 후 정산하기를 요청해보세요. 정산하기 버튼은 채팅 페이지 좌측 하단의 <b>+버튼</b>을 눌러 확인할 수 있어요.",
"2명 이상과 함께 택시를 타고 택시비를 결제한 후 정산을 요청해 보세요. 정산하기 버튼은 채팅 페이지 좌측 하단의 <b>+ 버튼</b>을 눌러 찾을 수 있어요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_paying.png",
reward: 100,
reward: 2000,
maxCount: 0,
},
sending: {
farePayment: {
name: "송금 완료면 I am 신뢰에요",
description:
"2명 이상과 함께 택시를 타고 택시비를 결제한 분께 송금해주세요. 송금하기 버튼은 채팅 페이지 좌측 하단의 <b>+버튼</b>을 눌러 확인할 수 있어요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_sending.png",
reward: 50,
reward: 2000,
maxCount: 0,
},
nicknameChanging: {
Expand All @@ -68,41 +59,46 @@ const quests = buildQuests({
"닉네임을 변경하여 자신을 표현하세요. <b>마이페이지</b>의 <b>수정하기</b> 버튼을 눌러 닉네임을 수정할 수 있어요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_nicknameChanging.png",
reward: 50,
reward: 500,
},
accountChanging: {
name: "계좌 등록을 해야 능률이 올라갑니다",
description:
"정산하기 기능을 더욱 빠르고 이용할 수 있다고? 계좌번호를 등록하면 정산하기를 할 때 계좌가 자동으로 입력돼요. <b>마이페이지</b>의 <b>수정하기</b> 버튼을 눌러 계좌번호를 등록 또는 수정할 수 있어요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_accountChanging.png",
reward: 50,
reward: 500,
},
adPushAgreement: {
name: "Taxi의 소울메이트",
description:
"Taxi 서비스를 잊지 않도록 가끔 찾아갈게요! 광고성 푸시 알림 수신 동의를 해주시면 방이 많이 모이는 시즌, 주변에 택시앱 사용자가 있을 때 알려드릴 수 있어요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_adPushAgreement.png",
reward: 50,
reward: 500,
},
eventSharing: {
name: "너 나랑 ㅌ태태택 (1명)",
description:
"내가 초대한 사람이 Taxi에 가입하여 이벤트에 참여하면 넙죽코인을 드려요. 내가 초대한 사람도 넙죽코인을 받아요. 이벤트 안내 페이지의 <b>이벤트 공유하기</b> 버튼을 통해 카카오톡으로 초대 문자를 보낼 수 있어요!",
name: "Taxi를 아십니까",
description: "내가 초대한 사람이 이벤트에 참여하면 송편코인을 드려요.",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_eventSharing.png",
reward: 50,
reward: 700,
maxCount: 0,
},
eventSharing5: {
name: "너 나랑 ㅌ태태택 (5명)",
dailyAttendance: {
name: "하루 한 번 Taxi!",
description:
"내가 초대한 사람이 5명이 Taxi에 가입하여 이벤트에 참여하면 넙죽코인을 드려요. 내가 초대한 사람도 넙죽코인을 받아요. 이벤트 안내 페이지의 <b>이벤트 공유하기</b> 버튼을 통해 카카오톡으로 초대 문자를 보낼 수 있어요!",
imageUrl:
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_eventSharing.png",
reward: 250,
maxCount: 0,
"매일 Taxi에 접속하여 출석 체크를 하면 송편코인을 드려요! 하루에 한 번, 택시팟도 둘러보고 송편코인도 받아 가세요. 송편코인을 얻으려면 출석 체크 페이지에서 <b>출석 버튼</b>을 눌러야 해요.",
imageUrl: "",
reward: 700,
maxCount: 17,
isApiRequired: true,
},
itemPurchase: {
name: "itemPurchase",
description: "itemPurchase",
imageUrl: "",
reward: 500,
},
});

Expand All @@ -111,40 +107,12 @@ const quests = buildQuests({
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
* @returns {Promise}
* @usage lottery/globalState/createUserGlobalStateHandler
* @usage lottery/globalState - createUserGlobalStateHandler
*/
const completeFirstLoginQuest = async (userId, timestamp) => {
return await completeQuest(userId, timestamp, quests.firstLogin);
};

/**
* payingAndSending 퀘스트의 완료를 요청합니다. 방의 참가자 수가 2명 미만이면 요청하지 않습니다.
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
* @param {Object} roomObject - 방의 정보입니다.
* @param {mongoose.Types.ObjectId} roomObject._id - 방의 ObjectId입니다.
* @param {Array<{ user: mongoose.Types.ObjectId }>} roomObject.part - 참여자 목록입니다.
* @param {Date} roomObject.time - 출발 시각입니다.
* @returns {Promise}
* @description 정산 요청 또는 송금이 이루어질 때마다 호출해 주세요.
* @usage rooms - commitSettlementHandler, rooms - commitPaymentHandler
*/
const completePayingAndSendingQuest = async (userId, timestamp, roomObject) => {
logger.info(
`User ${userId} requested to complete payingAndSendingQuest in Room ${roomObject._id}`
);

if (roomObject.part.length < 2) return null;
if (
!eventPeriod ||
roomObject.time >= eventPeriod.endAt ||
roomObject.time < eventPeriod.startAt
)
return null; // 택시 출발 시각이 이벤트 기간 내에 포함되지 않는 경우 퀘스트 완료 요청을 하지 않습니다.

return await completeQuest(userId, timestamp, quests.payingAndSending);
};

/**
* firstRoomCreation 퀘스트의 완료를 요청합니다.
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
Expand All @@ -158,7 +126,7 @@ const completeFirstRoomCreationQuest = async (userId, timestamp) => {
};

/**
* paying 퀘스트의 완료를 요청합니다. 방의 참가자 수가 2명 미만이면 요청하지 않습니다.
* fareSettlement 퀘스트의 완료를 요청합니다. 방의 참가자 수가 2명 미만이면 요청하지 않습니다.
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
* @param {Object} roomObject - 방의 정보입니다.
Expand All @@ -169,9 +137,9 @@ const completeFirstRoomCreationQuest = async (userId, timestamp) => {
* @description 정산 요청이 이루어질 때마다 호출해 주세요.
* @usage rooms - commitSettlementHandler
*/
const completePayingQuest = async (userId, timestamp, roomObject) => {
const completeFareSettlementQuest = async (userId, timestamp, roomObject) => {
logger.info(
`User ${userId} requested to complete payingQuest in Room ${roomObject._id}`
`User ${userId} requested to complete fareSettlementQuest in Room ${roomObject._id}`
);

if (roomObject.part.length < 2) return null;
Expand All @@ -182,11 +150,11 @@ const completePayingQuest = async (userId, timestamp, roomObject) => {
)
return null; // 택시 출발 시각이 이벤트 기간 내에 포함되지 않는 경우 퀘스트 완료 요청을 하지 않습니다.

return await completeQuest(userId, timestamp, quests.paying);
return await completeQuest(userId, timestamp, quests.fareSettlement);
};

/**
* sending 퀘스트의 완료를 요청합니다. 방의 참가자 수가 2명 미만이면 요청하지 않습니다.
* farePayment 퀘스트의 완료를 요청합니다. 방의 참가자 수가 2명 미만이면 요청하지 않습니다.
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
* @param {Object} roomObject - 방의 정보입니다.
Expand All @@ -197,9 +165,9 @@ const completePayingQuest = async (userId, timestamp, roomObject) => {
* @description 송금이 이루어질 때마다 호출해 주세요.
* @usage rooms - commitPaymentHandler
*/
const completeSendingQuest = async (userId, timestamp, roomObject) => {
const completeFarePaymentQuest = async (userId, timestamp, roomObject) => {
logger.info(
`User ${userId} requested to complete sendingQuest in Room ${roomObject._id}`
`User ${userId} requested to complete farePaymentQuest in Room ${roomObject._id}`
);

if (roomObject.part.length < 2) return null;
Expand All @@ -210,7 +178,7 @@ const completeSendingQuest = async (userId, timestamp, roomObject) => {
)
return null; // 택시 출발 시각이 이벤트 기간 내에 포함되지 않는 경우 퀘스트 완료 요청을 하지 않습니다.

return await completeQuest(userId, timestamp, quests.sending);
return await completeQuest(userId, timestamp, quests.farePayment);
};

/**
Expand Down Expand Up @@ -241,13 +209,13 @@ const completeAccountChangingQuest = async (userId, timestamp, newAccount) => {
};

/**
* adPushAgreementQuest 퀘스트의 완료를 요청합니다.
* adPushAgreement 퀘스트의 완료를 요청합니다.
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
* @param {boolean} advertisement - 변경된 광고성 알림 수신 동의 여부입니다.
* @returns {Promise}
* @description 알림 옵션을 변경할 때마다 호출해 주세요.
* @usage notifications/editOptionsHandler
* @usage notifications - editOptionsHandler
*/
const completeAdPushAgreementQuest = async (
userId,
Expand All @@ -260,38 +228,36 @@ const completeAdPushAgreementQuest = async (
};

/**
* eventSharing, eventSharing5 퀘스트의 완료를 요청합니다.
* eventSharing 퀘스트의 완료를 요청합니다.
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
* @returns {Promise}
* @description 초대 링크를 통해 사용자가 이벤트에 참여할 때마다, 초대한 사용자 및 초대받은 사용자에 대해 각각 호출해 주세요.
* @usage lottery/globalState - createUserGlobalStateHandler
*/
const completeEventSharingQuest = async (userId, timestamp) => {
const eventSharingResult = await completeQuest(
userId,
timestamp,
quests.eventSharing
);
if (!eventSharingResult || eventSharingResult.questCount % 5 !== 0)
return [eventSharingResult, null];
return await completeQuest(userId, timestamp, quests.eventSharing);
};

const eventSharing5Result = await completeQuest(
userId,
timestamp,
quests.eventSharing5
);
return [eventSharingResult, eventSharing5Result];
/**
* itemPurchase 퀘스트의 완료를 요청합니다.
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
* @returns {Promise}
* @description 상품을 구입할 때마다 호출해 주세요.
*/
const completeItemPurchaseQuest = async (userId, timestamp) => {
return await completeQuest(userId, timestamp, quests.itemPurchase);
};

module.exports = {
quests,
completeFirstLoginQuest,
completePayingAndSendingQuest,
completeFirstRoomCreationQuest,
completePayingQuest,
completeSendingQuest,
completeFareSettlementQuest,
completeFarePaymentQuest,
completeNicknameChangingQuest,
completeAccountChangingQuest,
completeAdPushAgreementQuest,
completeEventSharingQuest,
completeItemPurchaseQuest,
};
5 changes: 2 additions & 3 deletions src/lottery/modules/populates/transactions.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const transactionPopulateOption = [
{
path: "item",
select:
"name imageUrl instagramStoryStickerImageUrl price description isDisabled stock itemType",
path: "itemId",
select: "name imageUrl",
},
];

Expand Down
10 changes: 7 additions & 3 deletions src/lottery/modules/quests.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const eventPeriod = eventConfig && {
};

const requiredQuestFields = ["name", "description", "imageUrl", "reward"];

const buildQuests = (quests) => {
for (const [id, quest] of Object.entries(quests)) {
// quest에 필수 필드가 모두 포함되어 있는지 확인합니다.
Expand Down Expand Up @@ -61,7 +62,7 @@ const buildQuests = (quests) => {
* @param {number} quest.reward.credit - 퀘스트의 완료 보상 중 재화의 양입니다.
* @param {number} quest.reward.ticket1 - 퀘스트의 완료 보상 중 일반 티켓의 개수입니다.
* @param {number} quest.maxCount - 퀘스트의 최대 완료 가능 횟수입니다.
* @returns {Object|null} 성공한 경우 Object를, 실패한 경우 null을 반환합니다. 이미 최대 완료 횟수에 도달했거나, 퀘스트가 원격으로 비활성화 된 경우에도 실패로 처리됩니다.
* @returns {Object|null} 성공한 경우 Object를, 실패한 경우 null을 반환합니다. 이미 최대 완료 횟수에 도달했거나, 퀘스트가 원격으로 비활성화된 경우에도 실패로 처리됩니다.
*/
const completeQuest = async (userId, timestamp, quest) => {
try {
Expand Down Expand Up @@ -118,7 +119,10 @@ const completeQuest = async (userId, timestamp, quest) => {
ticket1Amount: quest.reward.ticket1,
},
$push: {
completedQuests: quest.id,
completedQuests: {
questId: quest.id,
completedAt: timestamp,
},
},
}
);
Expand All @@ -143,7 +147,7 @@ const completeQuest = async (userId, timestamp, quest) => {
amount: 0,
userId,
questId: quest.id,
item: ticket1._id,
itemId: ticket1._id,
comment: `"${quest.name}" 퀘스트를 완료해 "${ticket1.name}" ${quest.reward.ticket1}개를 획득했습니다.`,
});
await transaction.save();
Expand Down
Loading
Loading