/
aurora
/
test
Обзор
Документация
Войти
/
aurora
/
test
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
01_week/01_async/solution.js
167 строк
5 KB
auroraptor
refactoring
22 июн 2024, 11:22
22 июн 2024, 11:22
6295ff9
Код
Авторство
О чём код?
async function solution({ categoriesRepository, productsRepository, orders }) { class OrderResult { constructor() { this.status = "Successful Order"; this.totalPrice = 0; this.productsDetails = []; } addProductDetail(detail) { this.productsDetails.push(detail); } setStatus(status) { this.status = status; } addToTotalPrice(amount) { this.totalPrice += amount; } toString() { const productsString = this.productsDetails .map( (detail) => `${detail.productTitle} (${detail.categoryTitle}) - ${Math.min( detail.availableAmount, detail.requiredAmount )}/${detail.requiredAmount}` ) .join(", "); if (this.status === "Failed Order") { return `${this.status} // Products: ${productsString}`; } else { return `${this.status} // Total Price: $${this.totalPrice} // Products: ${productsString}`; } } } const retryUntilSuccessAsync = (fn) => { return new Promise((resolve, reject) => { const retryCallback = (err, result) => { if (err) { console.log("Retrying..."); fn(retryCallback); } else { resolve(result); } }; fn(retryCallback); }); }; // Сбор уникальных идентификаторов продуктов и категорий const productIds = new Set(); const categoryIds = new Set(); orders.forEach((order) => { order.forEach((product) => { productIds.add(product.id); }); }); // Параллельное получение данных продуктов и категорий const productsCache = new Map(); const categoriesCache = new Map(); const fetchProducts = Array.from(productIds).map(async (productId) => { const productData = await retryUntilSuccessAsync((cb) => productsRepository.getById({ id: productId }, cb) ); productsCache.set(productId, productData); categoryIds.add(productData.categoryId); }); await Promise.all(fetchProducts); const fetchCategories = Array.from(categoryIds).map(async (categoryId) => { const categoryData = await retryUntilSuccessAsync((cb) => categoriesRepository.getById({ id: categoryId }, cb) ); categoriesCache.set(categoryId, categoryData); }); await Promise.all(fetchCategories); // Обработка заказов с использованием кэша const processOrders = (orders, productsCache, categoriesCache) => { const answer = orders.map((order) => { const orderResult = new OrderResult(); order.forEach((product) => { const { id: productId, amount: requiredAmount } = product; let productStatus = "Unknown"; const productData = productsCache.get(productId); if (!productData) { orderResult.setStatus("Failed Order"); orderResult.addProductDetail({ productTitle: "Unknown", categoryTitle: "Unknown", availableAmount: 0, requiredAmount, productStatus, }); return; } const { categoryId, title: productTitle, amount: availableAmount, price, } = productData; const categoryData = categoriesCache.get(categoryId); const categoryTitle = categoryData ? categoryData.title : "Unknown"; if (availableAmount === 0) { productStatus = "Sold"; orderResult.setStatus("Partial Order"); } else { let orderedAmount; if (availableAmount < requiredAmount) { orderedAmount = availableAmount; orderResult.setStatus("Partial Order"); productStatus = "Partial"; } else { orderedAmount = requiredAmount; productStatus = "Fullfiled"; } productData.amount -= orderedAmount; orderResult.addToTotalPrice(price * orderedAmount); } orderResult.addProductDetail({ productTitle, categoryTitle, availableAmount, requiredAmount, productStatus, }); }); if ( orderResult.productsDetails.every( (detail) => detail.productStatus === "Sold" || detail.productStatus === "Unknown" ) ) { orderResult.setStatus("Failed Order"); } return orderResult.toString(); }); return answer; }; return await processOrders(orders, productsCache, categoriesCache); } module.exports = solution;