Skip to content

Commit 3e25c01

Browse files
authored
[Fix] 낱말 카드 반복 버그 수정 및 카테고리 아이디 통일 확인 (moduwa-aac#96)
2 parents eccd696 + ae9a358 commit 3e25c01

4 files changed

Lines changed: 27 additions & 28 deletions

File tree

src/category/category.service.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,21 @@ export const getCategoryListService = async ({ userId }) => {
7575
});
7676

7777
categories = await listUserCategories({ userId });
78-
}
7978

80-
// 기본 UserCategory 생성 후, 각 카테고리별 Word를 UserWord로 복사
79+
// 기본 UserCategory 생성 직후에만 복사
8180
const wordsRepo = (await import("../words/repositories/words.repository.js")).default;
8281
for (const userCategory of categories.filter(c => c.isDefault)) {
83-
// 기본 카테고리 이름으로 Category 찾기
8482
const category = await prisma.category.findFirst({
8583
where: {
8684
categoryName: userCategory.categoryName,
8785
isDefault: true
8886
}
8987
});
9088
if (category) {
91-
// 해당 Category의 Word를 UserWord로 복사
9289
await wordsRepo.createSnapshotFromWords(userId, userCategory.id);
9390
}
9491
}
92+
}
9593

9694
return Promise.all(
9795
categories.map(async (c) => {

src/words/controllers/words.controller.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export class WordsController {
1111
async getWords(req, res, next) {
1212
try {
1313
const userId = req.user?.userId;
14+
const accountType = req.user?.accountType;
1415

1516
const queryDto = new GetWordsQueryDto({
1617
categoryId: req.query.categoryId,
@@ -19,6 +20,7 @@ export class WordsController {
1920

2021
const result = await wordsService.getWords(
2122
userId,
23+
accountType,
2224
queryDto.categoryId,
2325
queryDto.onlyFavorite
2426
);

src/words/routes/words.route.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ const router = express.Router();
1616
* get:
1717
* summary: 낱말 카드 조회
1818
* description: |
19-
* 낱말 카드 목록을 조회합니다.
20-
* 토큰이 있으면 사용자별 낱말(즐겨찾기/개인화 포함), 없으면 기본 낱말만 반환합니다.
21-
* categoryId가 있으면 data.category(카테고리 이름)도 함께 반환됩니다.
19+
* 낱말 카드 목록을 조회합니다.
20+
* 토큰이 있으면 게스트/소셜 계정 모두 사용자별 낱말(즐겨찾기/개인화 포함)을 조회합니다.
21+
* 토큰이 없으면 기본 낱말만 반환합니다.
22+
* categoryId가 있으면 data.category(카테고리 이름)도 함께 반환됩니다.
2223
* tags: [Words]
2324
* parameters:
2425
* - in: query

src/words/services/words.service.js

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ export class WordsService {
99
/**
1010
* 내부용: 전체 낱말 카드 목록 생성 (categoryId 없이)
1111
*/
12-
async _getAllWordCards(userId, onlyFavorite = false) {
12+
async _getAllWordCards(userId, accountType, onlyFavorite = false) {
1313
const wordCards = [];
1414
let categoryNameToUserCategoryIdMap = new Map();
1515
let categoryNameToCategoryIdMap = new Map();
1616
let hasUserCategories = false;
1717

18-
if (userId) {
18+
if (userId && accountType !== 'GUEST') {
1919
const userCategories = await wordsRepository.findAllUserCategories(userId);
2020
if (userCategories.length > 0) {
2121
hasUserCategories = true;
@@ -44,17 +44,14 @@ export class WordsService {
4444
});
4545
}
4646

47-
// 소셜 로그인(유저가 존재) 시에는 기본 Word를 반환하지 않고 UserWord만 반환
48-
// 게스트(유저 없음)일 때만 기본 Word 반환
49-
if (!onlyFavorite && !userId) {
50-
const words = await wordsRepository.findWords(null, userId);
47+
// 소셜/게스트 로그인(유저가 존재) 시에는 UserWord 기반, 비회원(토큰 없음)만 기본 Word 반환
48+
if (!onlyFavorite && !userId && !accountType) {
49+
const words = await wordsRepository.findWords();
5150
words.forEach((word, index) => {
52-
const wordCategoryName = word.category?.categoryName;
53-
let mappedCategoryId = categoryNameToCategoryIdMap.get(wordCategoryName) || word.categoryId;
5451
wordCards.push(new WordCardResponseDto({
5552
cardId: word.id,
56-
categoryId: mappedCategoryId,
57-
categoryName: wordCategoryName,
53+
categoryId: word.categoryId,
54+
categoryName: word.category?.categoryName,
5855
partOfSpeech: word.partOfSpeech,
5956
word: word.word,
6057
imageUrl: word.imageUrl,
@@ -101,20 +98,20 @@ export class WordsService {
10198
/**
10299
* 다음 displayOrder 계산 (기본 Word + UserWord 모두 고려)
103100
* @param {string} userId
101+
* @param {string} accountType
104102
* @param {string} categoryId
105103
* @returns {Promise<number>}
106104
*/
107-
async getNextDisplayOrder(userId, categoryId) {
105+
async getNextDisplayOrder(userId, accountType, categoryId) {
108106
// 1. UserWord 조회 (삭제된 것 제외)
109-
const userWords = await wordsRepository.findUserWords(userId, categoryId, false, false);
110-
111-
// 2. UserWord가 있으면 최대값 + 1 반환
112-
if (userWords.length > 0) {
113-
const maxOrder = Math.max(...userWords.map(w => w.displayOrder));
114-
return maxOrder + 1;
107+
if (accountType !== 'GUEST') {
108+
const userWords = await wordsRepository.findUserWords(userId, categoryId, false, false);
109+
if (userWords.length > 0) {
110+
const maxOrder = Math.max(...userWords.map(w => w.displayOrder));
111+
return maxOrder + 1;
112+
}
115113
}
116-
117-
// 3. UserWord가 없으면 기본 Word 개수 반환
114+
// 게스트이거나 UserWord가 없으면 기본 Word 개수 반환
118115
const words = await wordsRepository.findWords(categoryId, userId);
119116
return words.length;
120117
}
@@ -124,13 +121,14 @@ export class WordsService {
124121
* 기본 낱말(Word) + 개인 낱말(UserWord) 통합 반환
125122
*
126123
* @param {string} userId
124+
* @param {string} accountType
127125
* @param {string|null} categoryId - Category.id 또는 UserCategory.id
128126
* @param {boolean} onlyFavorite
129127
* @returns {Promise<Object>} { category, words }
130128
*/
131-
async getWords(userId, categoryId = null, onlyFavorite = false) {
129+
async getWords(userId, accountType, categoryId = null, onlyFavorite = false) {
132130
// 1. 전체 낱말 목록 생성 (categoryId 없이)
133-
const allWords = await this._getAllWordCards(userId, onlyFavorite);
131+
const allWords = await this._getAllWordCards(userId, accountType, onlyFavorite);
134132

135133
// 2. categoryId가 없으면 전체 반환
136134
if (!categoryId) {

0 commit comments

Comments
 (0)