Elaborazione Prodotti E-commerce
Il sistema di elaborazione prodotti gestisce l'estrazione, l'elaborazione e la generazione di embedding per prodotti e-commerce tramite WooCommerce REST API.
Architettura del Sistema
WooCommerce Integration
- API REST: Integrazione completa con WooCommerce
- Autenticazione: Consumer Key e Consumer Secret
- Rate Limiting: Gestione limiti API WooCommerce
- Paginazione: Elaborazione batch per grandi cataloghi
Products Embedding Service
/src/services/productsEmbeddingService.ts
// Servizio principale per prodotti
class ProductsEmbeddingService {
private websiteUrl: string
private collectionName: string
private resourceUuid: string
private woocommerce: WooCommerceAPI
constructor(config: ProductsConfig) {
this.websiteUrl = config.websiteUrl
this.collectionName = config.collectionName
this.resourceUuid = config.resourceUuid
this.woocommerce = new WooCommerceAPI(config.woocommerce)
}
}
Tipi di Dati Elaborati
1. Prodotti
- Informazioni Base: Nome, descrizione, SKU, prezzo
- Categorie: Gerarchia categorie e tag
- Varianti: Attributi, opzioni, prezzi
- Immagini: URL immagini e metadati
- SEO: Meta title, description, slug
2. Categorie
- Gerarchia: Categorie padre e figlie
- Metadati: Nome, descrizione, slug
- Immagini: Icone e banner categoria
- SEO: Meta informazioni
3. Attributi
- Attributi Globali: Colore, taglia, materiale
- Termini Attributo: Valori specifici (Rosso, L, Cotone)
- Configurazione: Tipo, ordinamento, visibilità
Processo di Elaborazione
1. Inizializzazione
/src/services/productsEmbeddingService.ts
// Inizializzazione servizio prodotti
const init = async (agentUuid: string): Promise<void> => {
// Verifica connessione WooCommerce
await this.woocommerce.testConnection()
// Caricamento configurazione agente
const agentConfig = await this.loadAgentConfig(agentUuid)
// Setup collection Qdrant
await this.setupCollection()
}
2. Estrazione Prodotti
/src/services/productsEmbeddingService.ts
// Estrazione prodotti con paginazione
const extractProducts = async (): Promise<Product[]> => {
const products: Product[] = []
let page = 1
const perPage = 100
while (true) {
const response = await this.woocommerce.getProducts({
page,
per_page: perPage,
status: 'publish',
})
if (response.data.length === 0) break
products.push(...response.data)
page++
// Rate limiting
await this.delay(100)
}
return products
}
3. Elaborazione Prodotti
/src/services/productsEmbeddingService.ts
// Elaborazione singolo prodotto
const processProduct = async (product: WooCommerceProduct): Promise<LoaderResult> => {
// Estrazione dati base
const productData = this.extractProductData(product)
// Generazione contenuto per embedding
const content = this.generateProductContent(productData)
// Creazione metadati strutturati
const metadata = this.createProductMetadata(productData)
return {
content: content,
metadata: metadata,
resourceUuid: this.resourceUuid,
collectionName: this.collectionName,
}
}
4. Generazione Contenuto
/src/services/productsEmbeddingService.ts
// Generazione contenuto per ricerca semantica
const generateProductContent = (product: ProductData): string => {
const sections = [
`Nome: ${product.name}`,
`Descrizione: ${product.description}`,
`SKU: ${product.sku}`,
`Prezzo: ${product.price} ${product.currency}`,
`Categorie: ${product.categories.join(', ')}`,
`Tag: ${product.tags.join(', ')}`,
`Attributi: ${this.formatAttributes(product.attributes)}`,
`Varianti: ${this.formatVariants(product.variants)}`,
]
return sections.filter(section => section).join('\n\n')
}
Metadati Strutturati
Product Metadata
/src/types/embeddingsTypes.ts
interface ProductQdrantMetadata extends BaseQdrantMetadata<BaseQdrantMetadataType.PRODUCT> {
product_id: number | string
slug: string
sku: string
name: string
price: number
currency: string
categories: string[]
tags: string[]
variants: {
attributes: {
[attribute_slug: string]: string
}[]
}[]
images: string[]
seo_title?: string
seo_description?: string
stock_status: 'instock' | 'outofstock' | 'onbackorder'
featured: boolean
date_created: string
date_modified: string
}
Category Metadata
/src/types/embeddingsTypes.ts
interface CategoryQdrantMetadata extends BaseQdrantMetadata<BaseQdrantMetadataType.CATEGORY> {
category_id: number
name: string
slug: string
description?: string
parent_id?: number
image?: string
count: number
seo_title?: string
seo_description?: string
}
Attribute Metadata
/src/types/embeddingsTypes.ts
interface AttributeQdrantMetadata extends BaseQdrantMetadata<BaseQdrantMetadataType.ATTRIBUTE> {
attribute_id: number
name: string
slug: string
type: 'select' | 'color' | 'button' | 'variation'
order_by: 'menu_order' | 'name' | 'name_num' | 'id'
has_archives: boolean
terms: AttributeTermMetadata[]
}
Gestione Varianti
Elaborazione Varianti
/src/services/productsEmbeddingService.ts
// Elaborazione varianti prodotto
const processVariants = async (productId: number): Promise<Variant[]> => {
const variations = await this.woocommerce.getProductVariations(productId)
return variations.map(variation => ({
id: variation.id,
sku: variation.sku,
price: variation.price,
regular_price: variation.regular_price,
sale_price: variation.sale_price,
attributes: this.extractVariationAttributes(variation.attributes),
image: variation.image,
stock_quantity: variation.stock_quantity,
stock_status: variation.stock_status,
}))
}
Attributi Varianti
/src/services/productsEmbeddingService.ts
// Estrazione attributi varianti
const extractVariationAttributes = (attributes: any): Record<string, string> => {
const variantAttributes: Record<string, string> = {}
Object.entries(attributes).forEach(([key, value]) => {
if (value && typeof value === 'string') {
variantAttributes[key] = value
}
})
return variantAttributes
}
Gestione Categorie
Estrazione Gerarchia Categorie
/src/services/productsEmbeddingService.ts
// Estrazione categorie con gerarchia
const extractCategories = async (): Promise<Category[]> => {
const categories: Category[] = []
let page = 1
const perPage = 100
while (true) {
const response = await this.woocommerce.getCategories({
page,
per_page: perPage,
hide_empty: false,
})
if (response.data.length === 0) break
categories.push(...response.data)
page++
await this.delay(100)
}
return this.buildCategoryHierarchy(categories)
}
Costruzione Gerarchia
/src/services/productsEmbeddingService.ts
// Costruzione gerarchia categorie
const buildCategoryHierarchy = (categories: WooCommerceCategory[]): Category[] => {
const categoryMap = new Map<number, Category>()
const rootCategories: Category[] = []
// Prima passata: creazione mappa
categories.forEach(cat => {
categoryMap.set(cat.id, {
...cat,
children: [],
parent: undefined,
})
})
// Seconda passata: costruzione gerarchia
categories.forEach(cat => {
const category = categoryMap.get(cat.id)!
if (cat.parent === 0) {
rootCategories.push(category)
} else {
const parent = categoryMap.get(cat.parent)
if (parent) {
parent.children.push(category)
category.parent = parent
}
}
})
return rootCategories
}
Gestione Attributi
Estrazione Attributi Globali
/src/services/productsEmbeddingService.ts
// Estrazione attributi globali
const extractAttributes = async (): Promise<Attribute[]> => {
const attributes: Attribute[] = []
let page = 1
const perPage = 100
while (true) {
const response = await this.woocommerce.getAttributes({
page,
per_page: perPage,
})
if (response.data.length === 0) break
// Estrazione termini per ogni attributo
for (const attr of response.data) {
const terms = await this.extractAttributeTerms(attr.id)
attributes.push({
...attr,
terms,
})
}
page++
await this.delay(100)
}
return attributes
}
Estrazione Termini Attributo
/src/services/productsEmbeddingService.ts
// Estrazione termini attributo
const extractAttributeTerms = async (attributeId: number): Promise<AttributeTerm[]> => {
const terms: AttributeTerm[] = []
let page = 1
const perPage = 100
while (true) {
const response = await this.woocommerce.getAttributeTerms(attributeId, {
page,
per_page: perPage,
})
if (response.data.length === 0) break
terms.push(...response.data)
page++
await this.delay(50)
}
return terms
}
Rate Limiting e Performance
Gestione Rate Limiting
/src/services/productsEmbeddingService.ts
// Rate limiting per API WooCommerce
const RATE_LIMITS = {
requestsPerMinute: 60,
delayBetweenRequests: 1000,
maxConcurrentRequests: 3,
}
const delay = (ms: number): Promise<void> => {
return new Promise(resolve => setTimeout(resolve, ms))
}
Elaborazione Batch
/src/services/productsEmbeddingService.ts
// Elaborazione batch prodotti
const processProductsBatch = async (products: WooCommerceProduct[]): Promise<LoaderResult[]> => {
const batchSize = 10
const results: LoaderResult[] = []
for (let i = 0; i < products.length; i += batchSize) {
const batch = products.slice(i, i + batchSize)
const batchPromises = batch.map(product => this.processProduct(product))
const batchResults = await Promise.all(batchPromises)
results.push(...batchResults)
// Pausa tra batch
await this.delay(2000)
}
return results
}
Configurazione
WooCommerce API Config
/src/types/woocommerceTypes.ts
// Configurazione API WooCommerce
interface WooCommerceConfig {
url: string
consumerKey: string
consumerSecret: string
version: 'wc/v3'
timeout: number
retry: {
maxRetries: 3
backoff: {
initialDelay: 1000
maxDelay: 10000
factor: 2
}
}
}
Products Processing Config
/src/types/woocommerceTypes.ts
// Configurazione elaborazione prodotti
interface ProductsConfig {
websiteUrl: string
collectionName: string
resourceUuid: string
woocommerce: WooCommerceConfig
processing: {
batchSize: number
maxProducts: number
includeVariants: boolean
includeCategories: boolean
includeAttributes: boolean
}
}
Monitoraggio e Logging
Metriche Prodotti
- Products Processed: Numero prodotti elaborati
- Categories Processed: Numero categorie elaborate
- Attributes Processed: Numero attributi elaborati
- Variants Processed: Numero varianti elaborate
- API Calls: Numero chiamate API WooCommerce
- Error Rate: Percentuale errori per tipo
Logging Dettagliato
/src/utilities/loggerUtility.ts
// Log per elaborazione prodotti
logInfo(ctx, 'Product processing started', {
productId: product.id,
productName: product.name,
sku: product.sku,
})
logInfo(ctx, 'Product content generated', {
productId: product.id,
contentLength: content.length,
categoriesCount: product.categories.length,
variantsCount: product.variants.length,
})
Gestione Errori
Errori API WooCommerce
/src/services/productsEmbeddingService.ts
// Gestione errori API
try {
const products = await this.woocommerce.getProducts()
} catch (error) {
if (error.response?.status === 401) {
throw new Error('WooCommerce authentication failed')
} else if (error.response?.status === 429) {
// Rate limit exceeded, wait and retry
await this.delay(60000)
return this.retryRequest()
} else if (error.response?.status >= 500) {
throw new Error('WooCommerce server error')
}
throw new Error(`WooCommerce API error: ${error.message}`)
}
Errori Elaborazione
/src/services/productsEmbeddingService.ts
// Gestione errori elaborazione
const processProductWithErrorHandling = async (
product: WooCommerceProduct
): Promise<LoaderResult | null> => {
try {
return await this.processProduct(product)
} catch (error) {
logError(ctx, 'Product processing failed', {
productId: product.id,
productName: product.name,
error: error.message,
})
// Ritorna null per prodotti che non possono essere elaborati
return null
}
}