feat(订单): 添加同步结果计数和完整地址信息
在订单服务中添加成功和失败计数返回 为订单DTO添加账单和收货地址全称字段 统一各服务的同步结果返回格式 优化地址格式化逻辑和映射处理
This commit is contained in:
parent
50317abff3
commit
87b4039a67
|
|
@ -60,86 +60,129 @@ export class ShopyyAdapter implements ISiteAdapter {
|
|||
}
|
||||
|
||||
private mapOrder(item: any): UnifiedOrderDTO {
|
||||
const billing = item.billing_address || {};
|
||||
const shipping = item.shipping_address || {};
|
||||
|
||||
const billingObj = {
|
||||
first_name: billing.first_name || item.firstname || '',
|
||||
last_name: billing.last_name || item.lastname || '',
|
||||
fullname: billing.name || `${item.firstname} ${item.lastname}`.trim(),
|
||||
company: billing.company || '',
|
||||
email: item.customer_email || item.email || '',
|
||||
phone: billing.phone || item.telephone || '',
|
||||
address_1: billing.address1 || item.payment_address || '',
|
||||
address_2: billing.address2 || '',
|
||||
city: billing.city || item.payment_city || '',
|
||||
state: billing.province || item.payment_zone || '',
|
||||
postcode: billing.zip || item.payment_postcode || '',
|
||||
country: billing.country_name || billing.country_code || item.payment_country || ''
|
||||
};
|
||||
|
||||
const shippingObj = {
|
||||
first_name: shipping.first_name || item.firstname || '',
|
||||
last_name: shipping.last_name || item.lastname || '',
|
||||
fullname: shipping.name || '',
|
||||
company: shipping.company || '',
|
||||
address_1: shipping.address1 || item.shipping_address || '',
|
||||
address_2: shipping.address2 || '',
|
||||
city: shipping.city || item.shipping_city || '',
|
||||
state: shipping.province || item.shipping_zone || '',
|
||||
postcode: shipping.zip || item.shipping_postcode || '',
|
||||
country: shipping.country_name || shipping.country_code || item.shipping_country || ''
|
||||
};
|
||||
|
||||
const formatAddress = (addr: any) => {
|
||||
return [
|
||||
addr.fullname,
|
||||
addr.company,
|
||||
addr.address_1,
|
||||
addr.address_2,
|
||||
addr.city,
|
||||
addr.state,
|
||||
addr.postcode,
|
||||
addr.country,
|
||||
addr.phone
|
||||
].filter(Boolean).join(', ');
|
||||
};
|
||||
|
||||
return {
|
||||
id: item.order_id,
|
||||
number: item.order_sn,
|
||||
status: item.order_status,
|
||||
currency: item.currency,
|
||||
total: item.total_amount,
|
||||
customer_id: item.user_id,
|
||||
customer_name: `${item.firstname} ${item.lastname}`.trim(),
|
||||
email: item.email,
|
||||
id: item.id || item.order_id,
|
||||
number: item.order_number || item.order_sn,
|
||||
status: String(item.status || item.order_status),
|
||||
currency: item.currency_code || item.currency,
|
||||
total: String(item.total_price || item.total_amount),
|
||||
customer_id: item.customer_id || item.user_id,
|
||||
customer_name: item.customer_name || `${item.firstname} ${item.lastname}`.trim(),
|
||||
email: item.customer_email || item.email,
|
||||
line_items: (item.products || []).map((p: any) => ({
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
name: p.product_title || p.name,
|
||||
product_id: p.product_id,
|
||||
quantity: p.quantity,
|
||||
total: p.price,
|
||||
sku: p.sku
|
||||
total: String(p.price),
|
||||
sku: p.sku || p.sku_code || ''
|
||||
})),
|
||||
sales: (item.products || []).map((p: any) => ({
|
||||
id: p.id,
|
||||
name: p.name,
|
||||
name: p.product_title || p.name,
|
||||
product_id: p.product_id,
|
||||
productId: p.product_id,
|
||||
quantity: p.quantity,
|
||||
total: p.price,
|
||||
sku: p.sku
|
||||
total: String(p.price),
|
||||
sku: p.sku || p.sku_code || ''
|
||||
})),
|
||||
billing: {
|
||||
first_name: item.firstname,
|
||||
last_name: item.lastname,
|
||||
email: item.email,
|
||||
phone: item.telephone,
|
||||
address_1: item.payment_address,
|
||||
city: item.payment_city,
|
||||
state: item.payment_zone,
|
||||
postcode: item.payment_postcode,
|
||||
country: item.payment_country
|
||||
},
|
||||
shipping: {
|
||||
first_name: item.firstname,
|
||||
last_name: item.lastname,
|
||||
address_1: item.shipping_address,
|
||||
city: item.shipping_city,
|
||||
state: item.shipping_zone,
|
||||
postcode: item.shipping_postcode,
|
||||
country: item.shipping_country
|
||||
},
|
||||
billing: billingObj,
|
||||
shipping: shippingObj,
|
||||
billing_full_address: formatAddress(billingObj),
|
||||
shipping_full_address: formatAddress(shippingObj),
|
||||
payment_method: item.payment_method,
|
||||
date_created: item.date_added,
|
||||
date_created: item.created_at ? new Date(item.created_at * 1000).toISOString() : item.date_added,
|
||||
raw: item,
|
||||
};
|
||||
}
|
||||
|
||||
private mapCustomer(item: any): UnifiedCustomerDTO {
|
||||
// 处理多地址结构
|
||||
const addresses = item.addresses || [];
|
||||
const defaultAddress = item.default_address || (addresses.length > 0 ? addresses[0] : {});
|
||||
|
||||
// 尝试从地址列表中获取billing和shipping
|
||||
// 如果没有明确区分,默认使用默认地址或第一个地址
|
||||
const billing = defaultAddress;
|
||||
const shipping = defaultAddress;
|
||||
|
||||
return {
|
||||
id: item.customer_id,
|
||||
first_name: item.firstname,
|
||||
last_name: item.lastname,
|
||||
fullname: item.customer_name,
|
||||
email: item.customer_email,
|
||||
phone: item.phone || '',
|
||||
id: item.id || item.customer_id,
|
||||
first_name: item.first_name || item.firstname || '',
|
||||
last_name: item.last_name || item.lastname || '',
|
||||
fullname: item.fullname || item.customer_name || `${item.first_name || item.firstname || ''} ${item.last_name || item.lastname || ''}`.trim(),
|
||||
email: item.email || item.customer_email || '',
|
||||
phone: item.contact || billing.phone || item.phone || '',
|
||||
billing: {
|
||||
first_name: item.first_name,
|
||||
last_name: item.last_name,
|
||||
fullname: item.name,
|
||||
email: item.email,
|
||||
phone: item.phone || '',
|
||||
address_1: item.address_1 || '',
|
||||
city: item.city || '',
|
||||
state: item.zone || '',
|
||||
postcode: item.postcode || '',
|
||||
country: item.country || ''
|
||||
first_name: billing.first_name || item.first_name || '',
|
||||
last_name: billing.last_name || item.last_name || '',
|
||||
fullname: billing.name || `${billing.first_name || ''} ${billing.last_name || ''}`.trim(),
|
||||
company: billing.company || '',
|
||||
email: item.email || '',
|
||||
phone: billing.phone || item.contact || '',
|
||||
address_1: billing.address1 || '',
|
||||
address_2: billing.address2 || '',
|
||||
city: billing.city || '',
|
||||
state: billing.province || '',
|
||||
postcode: billing.zip || '',
|
||||
country: billing.country_name || billing.country_code || item.country?.country_name || ''
|
||||
},
|
||||
shipping: {
|
||||
first_name: item.firstname,
|
||||
last_name: item.lastname,
|
||||
address_1: item.address_1 || '',
|
||||
city: item.city || '',
|
||||
state: item.zone || '',
|
||||
postcode: item.postcode || '',
|
||||
country: item.country || ''
|
||||
first_name: shipping.first_name || item.first_name || '',
|
||||
last_name: shipping.last_name || item.last_name || '',
|
||||
fullname: shipping.name || `${shipping.first_name || ''} ${shipping.last_name || ''}`.trim(),
|
||||
company: shipping.company || '',
|
||||
address_1: shipping.address1 || '',
|
||||
address_2: shipping.address2 || '',
|
||||
city: shipping.city || '',
|
||||
state: shipping.province || '',
|
||||
postcode: shipping.zip || '',
|
||||
country: shipping.country_name || shipping.country_code || item.country?.country_name || ''
|
||||
},
|
||||
raw: item,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -40,6 +40,22 @@ export class WooCommerceAdapter implements ISiteAdapter {
|
|||
}
|
||||
|
||||
private mapOrder(item: any): UnifiedOrderDTO {
|
||||
const formatAddress = (addr: any) => {
|
||||
if (!addr) return '';
|
||||
const name = addr.fullname || `${addr.first_name || ''} ${addr.last_name || ''}`.trim();
|
||||
return [
|
||||
name,
|
||||
addr.company,
|
||||
addr.address_1,
|
||||
addr.address_2,
|
||||
addr.city,
|
||||
addr.state,
|
||||
addr.postcode,
|
||||
addr.country,
|
||||
addr.phone
|
||||
].filter(Boolean).join(', ');
|
||||
};
|
||||
|
||||
return {
|
||||
id: item.id,
|
||||
number: item.number,
|
||||
|
|
@ -59,6 +75,8 @@ export class WooCommerceAdapter implements ISiteAdapter {
|
|||
})),
|
||||
billing: item.billing,
|
||||
shipping: item.shipping,
|
||||
billing_full_address: formatAddress(item.billing),
|
||||
shipping_full_address: formatAddress(item.shipping),
|
||||
payment_method: item.payment_method_title,
|
||||
date_created: item.date_created,
|
||||
raw: item,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,264 @@
|
|||
import { ApiProperty } from '@midwayjs/swagger';
|
||||
|
||||
export class UnifiedPaginationDTO<T> {
|
||||
@ApiProperty({ description: '列表数据' })
|
||||
items: T[];
|
||||
|
||||
@ApiProperty({ description: '总数', example: 100 })
|
||||
total: number;
|
||||
|
||||
@ApiProperty({ description: '当前页', example: 1 })
|
||||
page: number;
|
||||
|
||||
@ApiProperty({ description: '每页数量', example: 20 })
|
||||
per_page: number;
|
||||
|
||||
@ApiProperty({ description: '总页数', example: 5 })
|
||||
totalPages: number;
|
||||
}
|
||||
|
||||
export class UnifiedImageDTO {
|
||||
@ApiProperty({ description: '图片ID' })
|
||||
id: number | string;
|
||||
|
||||
@ApiProperty({ description: '图片URL' })
|
||||
src: string;
|
||||
|
||||
@ApiProperty({ description: '图片名称' })
|
||||
name?: string;
|
||||
|
||||
@ApiProperty({ description: '替代文本' })
|
||||
alt?: string;
|
||||
}
|
||||
|
||||
export class UnifiedProductDTO {
|
||||
@ApiProperty({ description: '产品ID' })
|
||||
id: string | number;
|
||||
|
||||
@ApiProperty({ description: '产品名称' })
|
||||
name: string;
|
||||
|
||||
@ApiProperty({ description: '产品类型' })
|
||||
type: string;
|
||||
|
||||
@ApiProperty({ description: '产品状态' })
|
||||
status: string;
|
||||
|
||||
@ApiProperty({ description: '产品SKU' })
|
||||
sku: string;
|
||||
|
||||
@ApiProperty({ description: '常规价格' })
|
||||
regular_price: string;
|
||||
|
||||
@ApiProperty({ description: '销售价格' })
|
||||
sale_price: string;
|
||||
|
||||
@ApiProperty({ description: '当前价格' })
|
||||
price: string;
|
||||
|
||||
@ApiProperty({ description: '库存状态' })
|
||||
stock_status: string;
|
||||
|
||||
@ApiProperty({ description: '库存数量' })
|
||||
stock_quantity: number;
|
||||
|
||||
@ApiProperty({ description: '产品图片', type: [UnifiedImageDTO] })
|
||||
images: UnifiedImageDTO[];
|
||||
|
||||
@ApiProperty({ description: '产品标签', type: 'json' })
|
||||
tags?: string[];
|
||||
|
||||
@ApiProperty({ description: '产品属性', type: 'json' })
|
||||
attributes: any[];
|
||||
|
||||
@ApiProperty({ description: '产品变体', type: 'json' })
|
||||
variations?: any[];
|
||||
|
||||
@ApiProperty({ description: '创建时间' })
|
||||
date_created: string;
|
||||
|
||||
@ApiProperty({ description: '更新时间' })
|
||||
date_modified: string;
|
||||
|
||||
@ApiProperty({ description: '原始数据(保留备用)', type: 'json' })
|
||||
raw?: any;
|
||||
}
|
||||
|
||||
export class UnifiedOrderDTO {
|
||||
@ApiProperty({ description: '订单ID' })
|
||||
id: string | number;
|
||||
|
||||
@ApiProperty({ description: '订单号' })
|
||||
number: string;
|
||||
|
||||
@ApiProperty({ description: '订单状态' })
|
||||
status: string;
|
||||
|
||||
@ApiProperty({ description: '货币' })
|
||||
currency: string;
|
||||
|
||||
@ApiProperty({ description: '总金额' })
|
||||
total: string;
|
||||
|
||||
@ApiProperty({ description: '客户ID' })
|
||||
customer_id: number;
|
||||
|
||||
@ApiProperty({ description: '客户姓名' })
|
||||
customer_name: string;
|
||||
|
||||
@ApiProperty({ description: '客户邮箱' })
|
||||
email: string;
|
||||
|
||||
@ApiProperty({ description: '订单项', type: 'json' })
|
||||
line_items: any[];
|
||||
|
||||
@ApiProperty({ description: '销售项(兼容前端)', type: 'json' })
|
||||
sales?: any[];
|
||||
|
||||
@ApiProperty({ description: '账单地址', type: 'json' })
|
||||
billing: any;
|
||||
|
||||
@ApiProperty({ description: '收货地址', type: 'json' })
|
||||
shipping: any;
|
||||
|
||||
@ApiProperty({ description: '账单地址全称' })
|
||||
billing_full_address?: string;
|
||||
|
||||
@ApiProperty({ description: '收货地址全称' })
|
||||
shipping_full_address?: string;
|
||||
|
||||
@ApiProperty({ description: '支付方式' })
|
||||
payment_method: string;
|
||||
|
||||
@ApiProperty({ description: '创建时间' })
|
||||
date_created: string;
|
||||
|
||||
@ApiProperty({ description: '原始数据', type: 'json' })
|
||||
raw?: any;
|
||||
}
|
||||
|
||||
export class UnifiedCustomerDTO {
|
||||
@ApiProperty({ description: '客户ID' })
|
||||
id: string | number;
|
||||
|
||||
@ApiProperty({ description: '邮箱' })
|
||||
email: string;
|
||||
|
||||
@ApiProperty({ description: '名' })
|
||||
first_name?: string;
|
||||
|
||||
@ApiProperty({ description: '姓' })
|
||||
last_name?: string;
|
||||
|
||||
@ApiProperty({ description: '名字' })
|
||||
fullname?: string;
|
||||
|
||||
@ApiProperty({ description: '用户名' })
|
||||
username?: string;
|
||||
|
||||
@ApiProperty({ description: '电话' })
|
||||
phone?: string;
|
||||
|
||||
@ApiProperty({ description: '账单地址', type: 'json' })
|
||||
billing?: any;
|
||||
|
||||
@ApiProperty({ description: '收货地址', type: 'json' })
|
||||
shipping?: any;
|
||||
|
||||
@ApiProperty({ description: '原始数据', type: 'json' })
|
||||
raw?: any;
|
||||
}
|
||||
|
||||
export class UnifiedSubscriptionDTO {
|
||||
@ApiProperty({ description: '订阅ID' })
|
||||
id: string | number;
|
||||
|
||||
@ApiProperty({ description: '订阅状态' })
|
||||
status: string;
|
||||
|
||||
@ApiProperty({ description: '客户ID' })
|
||||
customer_id: number;
|
||||
|
||||
@ApiProperty({ description: '计费周期' })
|
||||
billing_period: string;
|
||||
|
||||
@ApiProperty({ description: '计费间隔' })
|
||||
billing_interval: number;
|
||||
|
||||
@ApiProperty({ description: '开始时间' })
|
||||
start_date: string;
|
||||
|
||||
@ApiProperty({ description: '下次支付时间' })
|
||||
next_payment_date: string;
|
||||
|
||||
@ApiProperty({ description: '订单项', type: 'json' })
|
||||
line_items: any[];
|
||||
|
||||
@ApiProperty({ description: '原始数据', type: 'json' })
|
||||
raw?: any;
|
||||
}
|
||||
|
||||
export class UnifiedMediaDTO {
|
||||
@ApiProperty({ description: '媒体ID' })
|
||||
id: number;
|
||||
|
||||
@ApiProperty({ description: '标题' })
|
||||
title: string;
|
||||
|
||||
@ApiProperty({ description: '媒体类型' })
|
||||
media_type: string;
|
||||
|
||||
@ApiProperty({ description: 'MIME类型' })
|
||||
mime_type: string;
|
||||
|
||||
@ApiProperty({ description: '源URL' })
|
||||
source_url: string;
|
||||
|
||||
@ApiProperty({ description: '创建时间' })
|
||||
date_created: string;
|
||||
}
|
||||
|
||||
export class UnifiedProductPaginationDTO extends UnifiedPaginationDTO<UnifiedProductDTO> {
|
||||
@ApiProperty({ description: '列表数据', type: [UnifiedProductDTO] })
|
||||
items: UnifiedProductDTO[];
|
||||
}
|
||||
|
||||
export class UnifiedOrderPaginationDTO extends UnifiedPaginationDTO<UnifiedOrderDTO> {
|
||||
@ApiProperty({ description: '列表数据', type: [UnifiedOrderDTO] })
|
||||
items: UnifiedOrderDTO[];
|
||||
}
|
||||
|
||||
export class UnifiedCustomerPaginationDTO extends UnifiedPaginationDTO<UnifiedCustomerDTO> {
|
||||
@ApiProperty({ description: '列表数据', type: [UnifiedCustomerDTO] })
|
||||
items: UnifiedCustomerDTO[];
|
||||
}
|
||||
|
||||
export class UnifiedSubscriptionPaginationDTO extends UnifiedPaginationDTO<UnifiedSubscriptionDTO> {
|
||||
@ApiProperty({ description: '列表数据', type: [UnifiedSubscriptionDTO] })
|
||||
items: UnifiedSubscriptionDTO[];
|
||||
}
|
||||
|
||||
export class UnifiedMediaPaginationDTO extends UnifiedPaginationDTO<UnifiedMediaDTO> {
|
||||
@ApiProperty({ description: '列表数据', type: [UnifiedMediaDTO] })
|
||||
items: UnifiedMediaDTO[];
|
||||
}
|
||||
|
||||
export class UnifiedSearchParamsDTO {
|
||||
@ApiProperty({ description: '页码', example: 1 })
|
||||
page?: number;
|
||||
|
||||
@ApiProperty({ description: '每页数量', example: 20 })
|
||||
per_page?: number;
|
||||
|
||||
@ApiProperty({ description: '搜索关键词' })
|
||||
search?: string;
|
||||
|
||||
@ApiProperty({ description: '状态' })
|
||||
status?: string;
|
||||
|
||||
@ApiProperty({ description: '排序字段' })
|
||||
orderby?: string;
|
||||
|
||||
@ApiProperty({ description: '排序方式' })
|
||||
order?: string;
|
||||
}
|
||||
|
|
@ -121,6 +121,12 @@ export class UnifiedOrderDTO {
|
|||
@ApiProperty({ description: '收货地址', type: 'json' })
|
||||
shipping: any;
|
||||
|
||||
@ApiProperty({ description: '账单地址全称' })
|
||||
billing_full_address?: string;
|
||||
|
||||
@ApiProperty({ description: '收货地址全称' })
|
||||
shipping_full_address?: string;
|
||||
|
||||
@ApiProperty({ description: '支付方式' })
|
||||
payment_method: string;
|
||||
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ export class OrderService {
|
|||
}
|
||||
return {
|
||||
success: failureCount === 0,
|
||||
successCount,
|
||||
failureCount,
|
||||
message: `同步完成: 成功 ${successCount}, 失败 ${failureCount}`,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export class ShopyyService implements IPlatformService {
|
|||
* @returns 请求头
|
||||
*/
|
||||
private buildHeaders(site: Site): Record<string, string> {
|
||||
if(!site?.token){
|
||||
if (!site?.token) {
|
||||
throw new Error(`获取站点${site?.name}数据,但失败,因为未设置站点令牌配置`)
|
||||
}
|
||||
return {
|
||||
|
|
@ -81,11 +81,11 @@ export class ShopyyService implements IPlatformService {
|
|||
limit: params.per_page || 20
|
||||
};
|
||||
const response = await this.request(site, endpoint, 'GET', null, requestParams);
|
||||
if(response?.code !== 0){
|
||||
if (response?.code !== 0) {
|
||||
throw new Error(response?.msg)
|
||||
}
|
||||
return {
|
||||
items: response.data.list || [],
|
||||
items: (response.data.list || []) as T,
|
||||
total: response.data?.paginate?.total || 0,
|
||||
totalPages: response.data?.paginate?.pageTotal || 0,
|
||||
page: response.data?.paginate?.current || requestParams.page,
|
||||
|
|
@ -426,7 +426,7 @@ export class ShopyyService implements IPlatformService {
|
|||
async fetchCustomersPaged(site: any, params: any): Promise<any> {
|
||||
// ShopYY API: GET /customers
|
||||
const { items, total, totalPages, page, per_page } =
|
||||
await this.fetchResourcePaged<any>(site, 'customers', params);
|
||||
await this.fetchResourcePaged<any>(site, 'customers/list', params);
|
||||
return {
|
||||
items,
|
||||
total,
|
||||
|
|
|
|||
|
|
@ -35,11 +35,13 @@ export class SubscriptionService {
|
|||
}
|
||||
return {
|
||||
success: failureCount === 0,
|
||||
successCount,
|
||||
failureCount,
|
||||
message: `同步完成: 成功 ${successCount}, 失败 ${failureCount}`,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('同步订阅失败:', error);
|
||||
return { success: false, message: `同步失败: ${error.message}` };
|
||||
return { success: false, successCount: 0, failureCount: 0, message: `同步失败: ${error.message}` };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -606,11 +606,13 @@ export class WpProductService {
|
|||
}
|
||||
return {
|
||||
success: failureCount === 0,
|
||||
successCount,
|
||||
failureCount,
|
||||
message: `同步完成: 成功 ${successCount}, 失败 ${failureCount}`,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('同步站点产品失败:', error);
|
||||
return { success: false, message: `同步失败: ${error.message}` };
|
||||
return { success: false, successCount: 0, failureCount: 0, message: `同步失败: ${error.message}` };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue