forked from yoone/API
1
0
Fork 0

refactor(service): 统一使用site.apiUrl并优化产品同步逻辑

移除对wpApiUrl的兼容处理,统一使用apiUrl
修复产品同步查询的分页问题,使用Infinity获取全部数据
优化代码格式和缩进
This commit is contained in:
tikkhun 2025-11-24 09:24:55 +08:00
parent c7480ccc8a
commit a64e611294
3 changed files with 43 additions and 44 deletions

View File

@ -52,7 +52,7 @@ export class SiteService {
const { consumerKey, consumerSecret, emailPswd, ...rest } = s as any; const { consumerKey, consumerSecret, emailPswd, ...rest } = s as any;
return rest; return rest;
} }
async list(param: { current?: number; pageSize?: number; keyword?: string; isDisabled?: boolean; ids?: string }, includeSecret = false) { async list(param: { current?: number; pageSize?: number; keyword?: string; isDisabled?: boolean; ids?: string }, includeSecret = false) {
const { current = 1, pageSize = 10, keyword, isDisabled, ids } = (param || {}) as any; const { current = 1, pageSize = 10, keyword, isDisabled, ids } = (param || {}) as any;
const where: any = {}; const where: any = {};

View File

@ -36,9 +36,8 @@ export class WPService {
* @param namespace API wc/v3 wcs/v1 * @param namespace API wc/v3 wcs/v1
*/ */
private createApi(site: any, namespace: WooCommerceRestApiVersion = 'wc/v3') { private createApi(site: any, namespace: WooCommerceRestApiVersion = 'wc/v3') {
const url = site.wpApiUrl ?? site.apiUrl; // 中文注释:兼容数据库 Site 与 WpSite 结构
return new WooCommerceRestApi({ return new WooCommerceRestApi({
url, url: site.apiUrl,
consumerKey: site.consumerKey, consumerKey: site.consumerKey,
consumerSecret: site.consumerSecret, consumerSecret: site.consumerSecret,
version: namespace, version: namespace,
@ -86,7 +85,7 @@ export class WPService {
param: Record<string, any> = {} param: Record<string, any> = {}
): Promise<T> { ): Promise<T> {
try { try {
const apiUrl = site.wpApiUrl ?? site.apiUrl; const apiUrl = site.apiUrl;
const { consumerKey, consumerSecret } = site; const { consumerKey, consumerSecret } = site;
// 构建 URL规避多/或少/问题 // 构建 URL规避多/或少/问题
const url = this.buildURL(apiUrl, '/wp-json', endpoint); const url = this.buildURL(apiUrl, '/wp-json', endpoint);
@ -247,7 +246,7 @@ export class WPService {
site: any, site: any,
data: Record<string, any> data: Record<string, any>
): Promise<Boolean> { ): Promise<Boolean> {
const apiUrl = site.wpApiUrl ?? site.apiUrl; const apiUrl = site.apiUrl;
const { consumerKey, consumerSecret } = site; const { consumerKey, consumerSecret } = site;
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString( const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
'base64' 'base64'
@ -347,7 +346,7 @@ export class WPService {
orderId: string, orderId: string,
data: Record<string, any> data: Record<string, any>
) { ) {
const apiUrl = site.wpApiUrl ?? site.apiUrl; const apiUrl = site.apiUrl;
const { consumerKey, consumerSecret } = site; const { consumerKey, consumerSecret } = site;
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString( const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
'base64' 'base64'
@ -375,7 +374,7 @@ export class WPService {
orderId: string, orderId: string,
trackingId: string, trackingId: string,
): Promise<Boolean> { ): Promise<Boolean> {
const apiUrl = site.wpApiUrl ?? site.apiUrl; const apiUrl = site.apiUrl;
const { consumerKey, consumerSecret } = site; const { consumerKey, consumerSecret } = site;
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString( const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
'base64' 'base64'

View File

@ -33,7 +33,7 @@ export class WpProductService {
async syncAllSites() { async syncAllSites() {
// 中文注释:从数据库获取所有启用的站点,并逐站点同步产品与变体 // 中文注释:从数据库获取所有启用的站点,并逐站点同步产品与变体
const { items } = await this.siteService.list({ current: 1, pageSize: 1000, isDisabled: false }, true); const { items } = await this.siteService.list({ current: 1, pageSize: Infinity, isDisabled: false }, true);
for (const s of items as any[]) { for (const s of items as any[]) {
const site: WpSite = { const site: WpSite = {
id: String(s.id), id: String(s.id),
@ -54,49 +54,49 @@ export class WpProductService {
} }
} }
} }
// 同步一个网站
async syncSite(siteId: string) { async syncSite(siteId: string) {
// 中文注释:通过数据库获取站点并转换为 WpSite用于后续 WooCommerce 同步 // 中文注释:通过数据库获取站点并转换为 WpSite用于后续 WooCommerce 同步
const site = await this.siteService.get(Number(siteId), true); const site = await this.siteService.get(Number(siteId), true);
const externalProductIds = this.wpProductModel.createQueryBuilder('wp_product') const externalProductIds = this.wpProductModel.createQueryBuilder('wp_product')
.select([ .select([
'wp_product.id ', 'wp_product.id ',
'wp_product.externalProductId ', 'wp_product.externalProductId ',
]) ])
.where('wp_product.siteId = :siteIds ', { .where('wp_product.siteId = :siteIds ', {
siteIds: siteId, siteIds: siteId,
}) })
const rawResult = await externalProductIds.getRawMany(); const rawResult = await externalProductIds.getRawMany();
const externalIds = rawResult.map(item => item.externalProductId); const externalIds = rawResult.map(item => item.externalProductId);
const excludeValues = []; const excludeValues = [];
const products = await this.wpApiService.getProducts(site); const products = await this.wpApiService.getProducts(site);
for (const product of products) { for (const product of products) {
excludeValues.push(String(product.id)); excludeValues.push(String(product.id));
const variations = const variations =
product.type === 'variable' product.type === 'variable'
? await this.wpApiService.getVariations(site, product.id) ? await this.wpApiService.getVariations(site, product.id)
: []; : [];
await this.syncProductAndVariations(site.id, product, variations); await this.syncProductAndVariations(site.id, product, variations);
} }
const filteredIds = externalIds.filter(id => !excludeValues.includes(id)); const filteredIds = externalIds.filter(id => !excludeValues.includes(id));
if(filteredIds.length!=0){ if (filteredIds.length != 0) {
await this.variationModel.createQueryBuilder('variation') await this.variationModel.createQueryBuilder('variation')
.update() .update()
.set({ on_delete: true }) .set({ on_delete: true })
.where(" variation.externalProductId in (:...filteredId) ",{filteredId:filteredIds}) .where(" variation.externalProductId in (:...filteredId) ", { filteredId: filteredIds })
.execute(); .execute();
this.wpProductModel.createQueryBuilder('wp_product') this.wpProductModel.createQueryBuilder('wp_product')
.update() .update()
.set({ on_delete: true }) .set({ on_delete: true })
.where(" wp_product.externalProductId in (:...filteredId) ",{filteredId:filteredIds}) .where(" wp_product.externalProductId in (:...filteredId) ", { filteredId: filteredIds })
.execute(); .execute();
} }
} }
// 控制产品上下架 // 控制产品上下架
@ -105,7 +105,7 @@ const excludeValues = [];
const site = await this.siteService.get(Number(wpProduct.siteId), true); const site = await this.siteService.get(Number(wpProduct.siteId), true);
wpProduct.status = status; wpProduct.status = status;
wpProduct.stockStatus = stock_status; wpProduct.stockStatus = stock_status;
const res = await this.wpApiService.updateProductStatus(site, wpProduct.externalProductId, status, stock_status); const res = await this.wpApiService.updateProductStatus(site, wpProduct.externalProductId, status, stock_status);
if (res === true) { if (res === true) {
this.wpProductModel.save(wpProduct); this.wpProductModel.save(wpProduct);
return true; return true;
@ -321,8 +321,8 @@ const excludeValues = [];
if (status) { if (status) {
where.status = status; where.status = status;
} }
where.on_delete = false; where.on_delete = false;
const products = await this.wpProductModel.find({ const products = await this.wpProductModel.find({
where, where,
skip: (current - 1) * pageSize, skip: (current - 1) * pageSize,
@ -503,16 +503,16 @@ const excludeValues = [];
if (!product) throw new Error('未找到该商品'); if (!product) throw new Error('未找到该商品');
await this.variationModel.createQueryBuilder('variation') await this.variationModel.createQueryBuilder('variation')
.update() .update()
.set({ on_delete: true }) .set({ on_delete: true })
.where(" variation.externalProductId = :externalProductId ",{externalProductId:productId}) .where(" variation.externalProductId = :externalProductId ", { externalProductId: productId })
.execute(); .execute();
const sums= await this.wpProductModel.createQueryBuilder('wp_product') const sums = await this.wpProductModel.createQueryBuilder('wp_product')
.update() .update()
.set({ on_delete: true }) .set({ on_delete: true })
.where(" wp_product.externalProductId = :externalProductId ",{externalProductId:productId}) .where(" wp_product.externalProductId = :externalProductId ", { externalProductId: productId })
.execute(); .execute();
console.log(sums); console.log(sums);
//await this.variationModel.delete({ siteId, externalProductId: productId }); //await this.variationModel.delete({ siteId, externalProductId: productId });
@ -520,7 +520,7 @@ const excludeValues = [];
} }
async findProductsByName(name: string): Promise<WpProduct[]> { async findProductsByName(name: string): Promise<WpProduct[]> {
const nameFilter = name ? name.split(' ').filter(Boolean) : []; const nameFilter = name ? name.split(' ').filter(Boolean) : [];
const query = this.wpProductModel.createQueryBuilder('product'); const query = this.wpProductModel.createQueryBuilder('product');
@ -553,7 +553,7 @@ const excludeValues = [];
} }
query.take(50); query.take(50);
return await query.getMany(); return await query.getMany();
} }
} }