diff --git a/src/repositories/partRepository.js b/src/repositories/partRepository.js index 4e453fa900d1ff186583ff4448ae11f0a7531d62..e93675b0b1622862b74bdc5ce5544fa7ee5d13b7 100644 --- a/src/repositories/partRepository.js +++ b/src/repositories/partRepository.js @@ -57,6 +57,36 @@ const PartRepository = { const result = await pool.query(query, queryValues); return result.rows; }, + + async getAllCombinations() { + const query = ` + SELECT array_agg(r.part_id) AS partIds + FROM combinations c + LEFT JOIN relations r ON c.id = r.combination_id + GROUP BY c.id; + `; + + const result = await pool.query(query); + return result.rows; + }, + + async getFilteredCombinations(queryValues) { + const query = ` + SELECT + c.id AS combination_id, + array_agg(r.part_id) AS partIds + FROM combinations c + LEFT JOIN relations r ON c.id = r.combination_id + WHERE r.combination_id IN ( + SELECT DISTINCT combination_id + FROM relations + WHERE part_id = ANY($1::int[]) + ) + GROUP BY c.id; + `; + const result = await pool.query(query, queryValues); + return result.rows; + }, }; export default PartRepository; diff --git a/src/routes/parts.js b/src/routes/parts.js index b995962256ae13284f72da104caa89c9ac183a32..f8d6d9ac1f616986ac636b76b9abab7a8ddd5c2e 100644 --- a/src/routes/parts.js +++ b/src/routes/parts.js @@ -33,4 +33,23 @@ partRouter.get( }) ); +partRouter.get( + '/combination/all', + wrapAsync(async (req, res) => { + const allCombinations = await PartService.getCombinations(); + res.sendResponse('', 200, { combination: allCombinations }); + }) +); + +partRouter.get( + '/combination/filtered', + wrapAsync(async (req, res) => { + const filters = req.query; + const filteredCombinations = + await PartService.getFilteredCombinations(filters); + + res.sendResponse('', 200, { combination: filteredCombinations }); + }) +); + export default partRouter; diff --git a/src/services/partService.js b/src/services/partService.js index 0fa797d00b0ffacff33cdbc4a8364ca6643054ed..e85f690c5a73cf3beac90701b449752d9d789e0f 100644 --- a/src/services/partService.js +++ b/src/services/partService.js @@ -74,6 +74,38 @@ const PartService = { ); return parts; }, + + async getCombinations() { + const allCombinations = await PartRepository.getAllCombinations(); + return allCombinations; + }, + + async getFilteredCombinations(filters) { + if (typeof filters.partId === 'string') { + filters.partId = filters.partId.split(',').map((id) => id.trim()); + } + + if ( + !filters || + !Array.isArray(filters.partId) || + filters.partId.length === 0 + ) { + throw new ReportableError(400, '유효한 partId 값이 필요합니다.'); + } + + const validFilters = filters.partId.filter((value) => value != null); + if (validFilters.length === 0) { + throw new ReportableError(400, '유효한 partId 값이 없습니다.'); + } + + const queryValues = [validFilters]; + const filteredCombinations = + await PartRepository.getFilteredCombinations(queryValues); + + return filteredCombinations.map((combination) => ({ + partIds: combination.partids, + })); + }, }; export default PartService;