Initial commit: Supermarket scraper MVP
This commit is contained in:
84
src/services/parser/ProductParser.ts
Normal file
84
src/services/parser/ProductParser.ts
Normal 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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user