Skip to content

Commit e541fc0

Browse files
authored
Merge pull request #537 from sparcs-kaist/#536-2024-chuseok-event
#536 2024 추석 이벤트
2 parents 5ca7315 + 05126ee commit e541fc0

31 files changed

+999
-800
lines changed

loadenv.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,18 @@ module.exports = {
4343
slackWebhookUrl: {
4444
report: process.env.SLACK_REPORT_WEBHOOK_URL || "", // optional
4545
},
46-
eventConfig: process.env.EVENT_CONFIG && JSON.parse(process.env.EVENT_CONFIG), // optional
46+
eventConfig: (process.env.EVENT_CONFIG &&
47+
JSON.parse(process.env.EVENT_CONFIG)) || {
48+
mode: "2024fall",
49+
credit: {
50+
name: "송편코인",
51+
initialAmount: 0,
52+
},
53+
period: {
54+
startAt: new Date("2024-09-07T00:00:00+09:00"),
55+
endAt: new Date("2024-09-24T00:00:00+09:00"),
56+
},
57+
}, // optional
4758
naverMap: {
4859
apiId: process.env.NAVER_MAP_API_ID, // optional
4960
apiKey: process.env.NAVER_MAP_API_KEY, //optional

src/lottery/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ lotteryRouter.use(require("../middlewares/originValidator"));
2828

2929
// [Router] APIs
3030
lotteryRouter.use("/globalState", require("./routes/globalState"));
31-
lotteryRouter.use("/invite", require("./routes/invite"));
31+
lotteryRouter.use("/invites", require("./routes/invites"));
3232
lotteryRouter.use("/transactions", require("./routes/transactions"));
3333
lotteryRouter.use("/items", require("./routes/items"));
34-
lotteryRouter.use("/publicNotice", require("./routes/publicNotice"));
34+
// lotteryRouter.use("/publicNotice", require("./routes/publicNotice"));
3535
lotteryRouter.use("/quests", require("./routes/quests"));
3636

3737
// [AdminJS] AdminJS에 표시할 Resource 생성

src/lottery/modules/contracts.js

Lines changed: 58 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,44 @@ const quests = buildQuests({
1313
firstLogin: {
1414
name: "첫 발걸음",
1515
description:
16-
"로그인만 해도 넙죽코인을 얻을 수 있다고?? 이벤트 기간에 처음으로 SPARCS Taxi 서비스에 로그인하여 넙죽코인을 받아보세요.",
16+
"이벤트 참여만 해도 송편코인을 얻을 수 있다고?? 이벤트 참여에 동의하고 송편코인을 받아 보세요.",
1717
imageUrl:
1818
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_firstLogin.png",
19-
reward: 50,
20-
},
21-
payingAndSending: {
22-
name: "함께하는 택시의 여정",
23-
description:
24-
"2명 이상과 함께 택시를 타고 정산/송금까지 완료해보세요. 최대 3번까지 넙죽코인을 받을 수 있어요. 정산/송금 버튼은 채팅 페이지 좌측 하단의 <b>+버튼</b>을 눌러 확인할 수 있어요.",
25-
imageUrl:
26-
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_payingAndSending.png",
27-
reward: 150,
28-
maxCount: 0,
19+
reward: 200,
2920
},
3021
firstRoomCreation: {
3122
name: "첫 방 개설",
3223
description:
3324
"원하는 택시팟을 찾을 수 없다면? 원하는 조건으로 <b>방 개설 페이지</b>에서 방을 직접 개설해보세요.",
3425
imageUrl:
3526
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_firstRoomCreation.png",
36-
reward: 50,
27+
reward: 500,
3728
},
3829
roomSharing: {
39-
name: "너 T야? Taxi",
30+
name: "이 택시팟은 진짜 유명한 택시팟임",
4031
description:
41-
"방을 공유해 친구들을 택시에 초대해보세요. 채팅창 상단의 햄버거(☰) 버튼을 누르면 <b>공유하기</b> 버튼을 찾을 수 있어요.",
32+
"방을 공유해 친구들을 택시팟에 초대해 보세요. 채팅창 상단의 햄버거(☰) 버튼을 누르면 <b>공유하기 버튼</b> 찾을 수 있어요.",
4233
imageUrl:
4334
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_roomSharing.png",
44-
reward: 50,
35+
reward: 500,
4536
isApiRequired: true,
4637
},
47-
paying: {
48-
name: "정산해요 택시의 숲",
38+
fareSettlement: {
39+
name: "정산의 신, 신팍스",
4940
description:
50-
"2명 이상과 함께 택시를 타고 택시비를 결제한 후 정산하기를 요청해보세요. 정산하기 버튼은 채팅 페이지 좌측 하단의 <b>+버튼</b>을 눌러 확인할 수 있어요.",
41+
"2명 이상과 함께 택시를 타고 택시비를 결제한 후 정산을 요청해 보세요. 정산하기 버튼은 채팅 페이지 좌측 하단의 <b>+ 버튼</b>을 눌러 찾을 수 있어요.",
5142
imageUrl:
5243
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_paying.png",
53-
reward: 100,
44+
reward: 2000,
5445
maxCount: 0,
5546
},
56-
sending: {
47+
farePayment: {
5748
name: "송금 완료면 I am 신뢰에요",
5849
description:
5950
"2명 이상과 함께 택시를 타고 택시비를 결제한 분께 송금해주세요. 송금하기 버튼은 채팅 페이지 좌측 하단의 <b>+버튼</b>을 눌러 확인할 수 있어요.",
6051
imageUrl:
6152
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_sending.png",
62-
reward: 50,
53+
reward: 2000,
6354
maxCount: 0,
6455
},
6556
nicknameChanging: {
@@ -68,41 +59,46 @@ const quests = buildQuests({
6859
"닉네임을 변경하여 자신을 표현하세요. <b>마이페이지</b>의 <b>수정하기</b> 버튼을 눌러 닉네임을 수정할 수 있어요.",
6960
imageUrl:
7061
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_nicknameChanging.png",
71-
reward: 50,
62+
reward: 500,
7263
},
7364
accountChanging: {
7465
name: "계좌 등록을 해야 능률이 올라갑니다",
7566
description:
7667
"정산하기 기능을 더욱 빠르고 이용할 수 있다고? 계좌번호를 등록하면 정산하기를 할 때 계좌가 자동으로 입력돼요. <b>마이페이지</b>의 <b>수정하기</b> 버튼을 눌러 계좌번호를 등록 또는 수정할 수 있어요.",
7768
imageUrl:
7869
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_accountChanging.png",
79-
reward: 50,
70+
reward: 500,
8071
},
8172
adPushAgreement: {
8273
name: "Taxi의 소울메이트",
8374
description:
8475
"Taxi 서비스를 잊지 않도록 가끔 찾아갈게요! 광고성 푸시 알림 수신 동의를 해주시면 방이 많이 모이는 시즌, 주변에 택시앱 사용자가 있을 때 알려드릴 수 있어요.",
8576
imageUrl:
8677
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_adPushAgreement.png",
87-
reward: 50,
78+
reward: 500,
8879
},
8980
eventSharing: {
90-
name: "너 나랑 ㅌ태태택 (1명)",
91-
description:
92-
"내가 초대한 사람이 Taxi에 가입하여 이벤트에 참여하면 넙죽코인을 드려요. 내가 초대한 사람도 넙죽코인을 받아요. 이벤트 안내 페이지의 <b>이벤트 공유하기</b> 버튼을 통해 카카오톡으로 초대 문자를 보낼 수 있어요!",
81+
name: "Taxi를 아십니까",
82+
description: "내가 초대한 사람이 이벤트에 참여하면 송편코인을 드려요.",
9383
imageUrl:
9484
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_eventSharing.png",
95-
reward: 50,
85+
reward: 700,
9686
maxCount: 0,
9787
},
98-
eventSharing5: {
99-
name: "너 나랑 ㅌ태태택 (5명)",
88+
dailyAttendance: {
89+
name: "하루 한 번 Taxi!",
10090
description:
101-
"내가 초대한 사람이 5명이 Taxi에 가입하여 이벤트에 참여하면 넙죽코인을 드려요. 내가 초대한 사람도 넙죽코인을 받아요. 이벤트 안내 페이지의 <b>이벤트 공유하기</b> 버튼을 통해 카카오톡으로 초대 문자를 보낼 수 있어요!",
102-
imageUrl:
103-
"https://sparcs-taxi-prod.s3.ap-northeast-2.amazonaws.com/assets/event-2024spring/quest_eventSharing.png",
104-
reward: 250,
105-
maxCount: 0,
91+
"매일 Taxi에 접속하여 출석 체크를 하면 송편코인을 드려요! 하루에 한 번, 택시팟도 둘러보고 송편코인도 받아 가세요. 송편코인을 얻으려면 출석 체크 페이지에서 <b>출석 버튼</b>을 눌러야 해요.",
92+
imageUrl: "",
93+
reward: 700,
94+
maxCount: 17,
95+
isApiRequired: true,
96+
},
97+
itemPurchase: {
98+
name: "itemPurchase",
99+
description: "itemPurchase",
100+
imageUrl: "",
101+
reward: 500,
106102
},
107103
});
108104

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

120-
/**
121-
* payingAndSending 퀘스트의 완료를 요청합니다. 방의 참가자 수가 2명 미만이면 요청하지 않습니다.
122-
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
123-
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
124-
* @param {Object} roomObject - 방의 정보입니다.
125-
* @param {mongoose.Types.ObjectId} roomObject._id - 방의 ObjectId입니다.
126-
* @param {Array<{ user: mongoose.Types.ObjectId }>} roomObject.part - 참여자 목록입니다.
127-
* @param {Date} roomObject.time - 출발 시각입니다.
128-
* @returns {Promise}
129-
* @description 정산 요청 또는 송금이 이루어질 때마다 호출해 주세요.
130-
* @usage rooms - commitSettlementHandler, rooms - commitPaymentHandler
131-
*/
132-
const completePayingAndSendingQuest = async (userId, timestamp, roomObject) => {
133-
logger.info(
134-
`User ${userId} requested to complete payingAndSendingQuest in Room ${roomObject._id}`
135-
);
136-
137-
if (roomObject.part.length < 2) return null;
138-
if (
139-
!eventPeriod ||
140-
roomObject.time >= eventPeriod.endAt ||
141-
roomObject.time < eventPeriod.startAt
142-
)
143-
return null; // 택시 출발 시각이 이벤트 기간 내에 포함되지 않는 경우 퀘스트 완료 요청을 하지 않습니다.
144-
145-
return await completeQuest(userId, timestamp, quests.payingAndSending);
146-
};
147-
148116
/**
149117
* firstRoomCreation 퀘스트의 완료를 요청합니다.
150118
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
@@ -158,7 +126,7 @@ const completeFirstRoomCreationQuest = async (userId, timestamp) => {
158126
};
159127

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

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

185-
return await completeQuest(userId, timestamp, quests.paying);
153+
return await completeQuest(userId, timestamp, quests.fareSettlement);
186154
};
187155

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

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

213-
return await completeQuest(userId, timestamp, quests.sending);
181+
return await completeQuest(userId, timestamp, quests.farePayment);
214182
};
215183

216184
/**
@@ -241,13 +209,13 @@ const completeAccountChangingQuest = async (userId, timestamp, newAccount) => {
241209
};
242210

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

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

278-
const eventSharing5Result = await completeQuest(
279-
userId,
280-
timestamp,
281-
quests.eventSharing5
282-
);
283-
return [eventSharingResult, eventSharing5Result];
241+
/**
242+
* itemPurchase 퀘스트의 완료를 요청합니다.
243+
* @param {string|mongoose.Types.ObjectId} userId - 퀘스트를 완료한 사용자의 ObjectId입니다.
244+
* @param {number|Date} timestamp - 퀘스트 완료를 요청한 시각입니다.
245+
* @returns {Promise}
246+
* @description 상품을 구입할 때마다 호출해 주세요.
247+
*/
248+
const completeItemPurchaseQuest = async (userId, timestamp) => {
249+
return await completeQuest(userId, timestamp, quests.itemPurchase);
284250
};
285251

286252
module.exports = {
287253
quests,
288254
completeFirstLoginQuest,
289-
completePayingAndSendingQuest,
290255
completeFirstRoomCreationQuest,
291-
completePayingQuest,
292-
completeSendingQuest,
256+
completeFareSettlementQuest,
257+
completeFarePaymentQuest,
293258
completeNicknameChangingQuest,
294259
completeAccountChangingQuest,
295260
completeAdPushAgreementQuest,
296261
completeEventSharingQuest,
262+
completeItemPurchaseQuest,
297263
};

src/lottery/modules/populates/transactions.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
const transactionPopulateOption = [
22
{
3-
path: "item",
4-
select:
5-
"name imageUrl instagramStoryStickerImageUrl price description isDisabled stock itemType",
3+
path: "itemId",
4+
select: "name imageUrl",
65
},
76
];
87

src/lottery/modules/quests.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const eventPeriod = eventConfig && {
1414
};
1515

1616
const requiredQuestFields = ["name", "description", "imageUrl", "reward"];
17+
1718
const buildQuests = (quests) => {
1819
for (const [id, quest] of Object.entries(quests)) {
1920
// quest에 필수 필드가 모두 포함되어 있는지 확인합니다.
@@ -61,7 +62,7 @@ const buildQuests = (quests) => {
6162
* @param {number} quest.reward.credit - 퀘스트의 완료 보상 중 재화의 양입니다.
6263
* @param {number} quest.reward.ticket1 - 퀘스트의 완료 보상 중 일반 티켓의 개수입니다.
6364
* @param {number} quest.maxCount - 퀘스트의 최대 완료 가능 횟수입니다.
64-
* @returns {Object|null} 성공한 경우 Object를, 실패한 경우 null을 반환합니다. 이미 최대 완료 횟수에 도달했거나, 퀘스트가 원격으로 비활성화 된 경우에도 실패로 처리됩니다.
65+
* @returns {Object|null} 성공한 경우 Object를, 실패한 경우 null을 반환합니다. 이미 최대 완료 횟수에 도달했거나, 퀘스트가 원격으로 비활성화된 경우에도 실패로 처리됩니다.
6566
*/
6667
const completeQuest = async (userId, timestamp, quest) => {
6768
try {
@@ -118,7 +119,10 @@ const completeQuest = async (userId, timestamp, quest) => {
118119
ticket1Amount: quest.reward.ticket1,
119120
},
120121
$push: {
121-
completedQuests: quest.id,
122+
completedQuests: {
123+
questId: quest.id,
124+
completedAt: timestamp,
125+
},
122126
},
123127
}
124128
);
@@ -143,7 +147,7 @@ const completeQuest = async (userId, timestamp, quest) => {
143147
amount: 0,
144148
userId,
145149
questId: quest.id,
146-
item: ticket1._id,
150+
itemId: ticket1._id,
147151
comment: `"${quest.name}" 퀘스트를 완료해 "${ticket1.name}" ${quest.reward.ticket1}개를 획득했습니다.`,
148152
});
149153
await transaction.save();

0 commit comments

Comments
 (0)