Initial commit: Supermarket scraper MVP

This commit is contained in:
2025-12-28 23:29:30 +05:00
commit 19c0426cdc
30 changed files with 4839 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import { ProductItem } from '../../scrapers/api/magnit/types.js';
import { CreateProductData } from '../product/ProductService.js';
export class ProductParser {
/**
* Конвертация цены из копеек в рубли
*/
private static priceFromKopecks(kopecks: number): number {
return kopecks / 100;
}
/**
* Парсинг даты из строки
*/
private static parseDate(dateString?: string): Date | undefined {
if (!dateString) return undefined;
try {
return new Date(dateString);
} catch {
return undefined;
}
}
/**
* Преобразование массива бейджей в JSON строку
*/
private static badgesToJson(badges: Array<{ text: string; backgroundColor: string }>): string | undefined {
if (!badges || badges.length === 0) return undefined;
return JSON.stringify(badges);
}
/**
* Преобразование ProductItem из API в CreateProductData для БД
*/
static parseProductItem(
item: ProductItem,
storeId: number,
categoryId?: number
): CreateProductData {
return {
externalId: item.productId,
storeId,
categoryId,
name: item.name,
description: item.description,
url: item.url,
imageUrl: item.gallery && item.gallery.length > 0 ? item.gallery[0].url : undefined,
currentPrice: this.priceFromKopecks(item.price),
unit: item.unit,
weight: item.weight,
brand: item.brand,
oldPrice: item.promotion?.oldPrice
? this.priceFromKopecks(item.promotion.oldPrice)
: undefined,
discountPercent: item.promotion?.discountPercent
? item.promotion.discountPercent
: undefined,
promotionEndDate: this.parseDate(item.promotion?.endDate),
rating: item.ratings?.rating,
scoresCount: item.ratings?.scoresCount,
commentsCount: item.ratings?.commentsCount,
quantity: item.quantity,
badges: this.badgesToJson(item.badges),
};
}
/**
* Парсинг массива товаров
*/
static parseProductItems(
items: ProductItem[],
storeId: number,
categoryMap: Map<number, number> // Map<externalCategoryId, categoryId>
): CreateProductData[] {
return items.map(item => {
const categoryId = item.category?.id
? categoryMap.get(item.category.id)
: undefined;
return this.parseProductItem(item, storeId, categoryId);
});
}
}