Passa al contenuto principale

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
}
}