API/src/service/site-api.service.ts

200 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Inject, Provide } from '@midwayjs/core';
import { ShopyyAdapter } from '../adapter/shopyy.adapter';
import { WooCommerceAdapter } from '../adapter/woocommerce.adapter';
import { ISiteAdapter } from '../interface/site-adapter.interface';
import { ShopyyService } from './shopyy.service';
import { SiteService } from './site.service';
import { WPService } from './wp.service';
import { ProductService } from './product.service';
import { UnifiedProductDTO } from '../dto/site-api.dto';
@Provide()
export class SiteApiService {
@Inject()
siteService: SiteService;
@Inject()
wpService: WPService;
@Inject()
shopyyService: ShopyyService;
@Inject()
productService: ProductService;
async getAdapter(siteId: number): Promise<ISiteAdapter> {
const site = await this.siteService.get(siteId, true);
if (!site) {
throw new Error(`Site ${siteId} not found`);
}
if (site.type === 'woocommerce') {
if (!site?.consumerKey || !site.consumerSecret || !site.apiUrl) {
throw new Error('站点配置缺少 consumerKey/consumerSecret/apiUrl');
}
return new WooCommerceAdapter(site, this.wpService);
} else if (site.type === 'shopyy') {
if (!site?.token) {
throw new Error('站点配置缺少 token');
}
return new ShopyyAdapter(site, this.shopyyService);
}
throw new Error(`Unsupported site type: ${site.type}`);
}
/**
* 获取站点商品并关联ERP产品信息
* @param siteId 站点ID
* @param siteProduct 站点商品信息
* @returns 包含ERP产品信息的站点商品
*/
async enrichSiteProductWithErpInfo(siteId: number, siteProduct: any): Promise<any> {
if (!siteProduct || !siteProduct.sku) {
return siteProduct;
}
try {
// 使用站点SKU查询对应的ERP产品
const erpProduct = await this.productService.findProductBySiteSku(siteProduct.sku);
// 将ERP产品信息合并到站点商品中
return {
...siteProduct,
erpProduct: {
id: erpProduct.id,
sku: erpProduct.sku,
name: erpProduct.name,
nameCn: erpProduct.nameCn,
category: erpProduct.category,
attributes: erpProduct.attributes,
components: erpProduct.components,
price: erpProduct.price,
promotionPrice: erpProduct.promotionPrice,
// 可以根据需要添加更多ERP产品字段
}
};
} catch (error) {
// 如果找不到对应的ERP产品返回原始站点商品
console.warn(`未找到站点SKU ${siteProduct.sku} 对应的ERP产品: ${error.message}`);
return siteProduct;
}
}
/**
* 批量获取站点商品并关联ERP产品信息
* @param siteId 站点ID
* @param siteProducts 站点商品列表
* @returns 包含ERP产品信息的站点商品列表
*/
async enrichSiteProductsWithErpInfo(siteId: number, siteProducts: any[]): Promise<any[]> {
if (!siteProducts || !siteProducts.length) {
return siteProducts;
}
// 并行处理所有商品
const enrichedProducts = await Promise.all(
siteProducts.map(product => this.enrichSiteProductWithErpInfo(siteId, product))
);
return enrichedProducts;
}
/**
* 更新或创建产品
* @param siteId 站点ID
* @param product 产品数据
* @returns 更新或创建后的产品
*/
async upsertProduct(siteId: number, product: Partial<UnifiedProductDTO>): Promise<any> {
const adapter = await this.getAdapter(siteId);
// 首先尝试查找产品
if (product.sku) {
// 如果没有提供ID但提供了SKU尝试通过SKU查找产品
try {
// 尝试搜索具有相同SKU的产品
const existingProduct = await adapter.getProduct( { sku: product.sku });
if (existingProduct) {
// 找到现有产品,更新它
return await adapter.updateProduct({ id: existingProduct.id }, product);
}
// 产品不存在,执行创建
return await adapter.createProduct(product);
} catch (error) {
// 搜索失败,继续执行创建逻辑
console.log(`通过SKU搜索产品失败:`, error.message);
}
}
}
/**
* 批量更新或创建产品
* @param siteId 站点ID
* @param products 产品数据数组
* @returns 批量操作结果
*/
async batchUpsertProduct(siteId: number, products: Partial<UnifiedProductDTO>[]): Promise<{ created: any[], updated: any[], errors: any[] }> {
const results = {
created: [],
updated: [],
errors: []
};
for (const product of products) {
try {
const result = await this.upsertProduct(siteId, product);
// 判断是创建还是更新
if (result && result.id) {
// 简单判断如果产品原本没有ID而现在有了说明是创建的
if (!product.id || !product.id.toString().trim()) {
results.created.push(result);
} else {
results.updated.push(result);
}
}
} catch (error) {
results.errors.push({
product: product,
error: error.message
});
}
}
return results;
}
/**
* 从站点获取产品
* @param siteId 站点ID
* @param params 查询参数
* @returns 站点产品列表
*/
async getProductsFromSite(siteId: number, params?: any): Promise<any> {
const adapter = await this.getAdapter(siteId);
return await adapter.getProducts(params);
}
/**
* 从站点获取单个产品
* @param siteId 站点ID
* @param productId 产品ID
* @returns 站点产品
*/
async getProductFromSite(siteId: number, productId: string | number): Promise<any> {
const adapter = await this.getAdapter(siteId);
return await adapter.getProduct({ id: productId });
}
/**
* 从站点获取所有产品
* @param siteId 站点ID
* @param params 查询参数
* @returns 站点产品列表
*/
async getAllProductsFromSite(siteId: number, params?: any): Promise<any[]> {
const adapter = await this.getAdapter(siteId);
return await adapter.getAllProducts(params);
}
}