feat(订单): 添加获取订单总数功能
实现订单总数统计接口,包括: 1. 在ISiteAdapter接口添加countOrders方法 2. 在WooCommerce和Shopyy适配器中实现该方法 3. 添加控制器端点暴露该功能 4. 优化订单查询参数映射逻辑 refactor(Shopyy): 重构搜索参数映射逻辑 将通用的搜索参数映射逻辑提取为独立方法,提高代码复用性
This commit is contained in:
parent
0f81499ccc
commit
acfee35e73
|
|
@ -27,8 +27,10 @@ import {
|
|||
ShopyyCustomer,
|
||||
ShopyyOrder,
|
||||
ShopyyOrderQuery,
|
||||
ShopyyOrderQuery,
|
||||
ShopyyProduct,
|
||||
ShopyyProductQuery,
|
||||
ShopyyProductQuery,
|
||||
ShopyyVariant,
|
||||
ShopyyWebhook,
|
||||
} from '../dto/shopyy.dto';
|
||||
|
|
@ -56,45 +58,51 @@ export class ShopyyAdapter implements ISiteAdapter {
|
|||
// this.mapPlatformToUnifiedSubscription = this.mapPlatformToUnifiedSubscription.bind(this);
|
||||
}
|
||||
|
||||
// ========== 客户映射方法 ==========
|
||||
mapPlatformToUnifiedCustomer(item: ShopyyCustomer): UnifiedCustomerDTO {
|
||||
// 处理多地址结构
|
||||
const addresses = item.addresses || [];
|
||||
const defaultAddress = item.default_address || (addresses.length > 0 ? addresses[0] : {});
|
||||
|
||||
// 尝试从地址列表中获取billing和shipping
|
||||
// 如果没有明确区分,默认使用默认地址或第一个地址
|
||||
const billingAddress = defaultAddress;
|
||||
const shippingAddress = defaultAddress;
|
||||
|
||||
const billing = {
|
||||
first_name: billingAddress.first_name || item.first_name || '',
|
||||
last_name: billingAddress.last_name || item.last_name || '',
|
||||
fullname: billingAddress.name || `${billingAddress.first_name || item.first_name || ''} ${billingAddress.last_name || item.last_name || ''}`.trim(),
|
||||
company: billingAddress.company || '',
|
||||
email: item.email || '',
|
||||
phone: billingAddress.phone || item.contact || '',
|
||||
address_1: billingAddress.address1 || '',
|
||||
address_2: billingAddress.address2 || '',
|
||||
city: billingAddress.city || '',
|
||||
state: billingAddress.province || '',
|
||||
postcode: billingAddress.zip || '',
|
||||
country: billingAddress.country_name || billingAddress.country_code || item.country?.country_name || ''
|
||||
private mapMedia(item: any): UnifiedMediaDTO {
|
||||
// 映射媒体项目
|
||||
return {
|
||||
id: item.id,
|
||||
date_created: item.created_at,
|
||||
date_modified: item.updated_at,
|
||||
source_url: item.src,
|
||||
title: item.alt || '',
|
||||
media_type: '', // Shopyy API未提供,暂时留空
|
||||
mime_type: '', // Shopyy API未提供,暂时留空
|
||||
};
|
||||
}
|
||||
|
||||
const shipping = {
|
||||
first_name: shippingAddress.first_name || item.first_name || '',
|
||||
last_name: shippingAddress.last_name || item.last_name || '',
|
||||
fullname: shippingAddress.name || `${shippingAddress.first_name || item.first_name || ''} ${shippingAddress.last_name || item.last_name || ''}`.trim(),
|
||||
company: shippingAddress.company || '',
|
||||
address_1: shippingAddress.address1 || '',
|
||||
address_2: shippingAddress.address2 || '',
|
||||
city: shippingAddress.city || '',
|
||||
state: shippingAddress.province || '',
|
||||
postcode: shippingAddress.zip || '',
|
||||
country: shippingAddress.country_name || shippingAddress.country_code || item.country?.country_name || ''
|
||||
};
|
||||
private mapMediaSearchParams(params: UnifiedSearchParamsDTO): any {
|
||||
return this.mapSearchParams(params)
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用搜索参数转换方法,处理 where 和 orderBy 的转换
|
||||
* 将统一的搜索参数转换为 ShopYY API 所需的参数格式
|
||||
*/
|
||||
private mapSearchParams(params: UnifiedSearchParamsDTO): any {
|
||||
// 处理分页参数
|
||||
const page = Number(params.page || 1);
|
||||
const limit = Number(params.per_page ?? 20);
|
||||
|
||||
// 处理 where 条件
|
||||
const query: any = {
|
||||
...(params.where || {}),
|
||||
page,
|
||||
limit,
|
||||
}
|
||||
if(params.orderBy){
|
||||
const [field, dir] = Object.entries(params.orderBy)[0];
|
||||
query.order_by = dir === 'desc' ? 'desc' : 'asc';
|
||||
query.order_field = field
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
private mapProduct(item: ShopyyProduct & { permalink?: string }): UnifiedProductDTO {
|
||||
// 映射产品状态
|
||||
function mapProductStatus(status: number) {
|
||||
return status === 1 ? 'publish' : 'draft';
|
||||
}
|
||||
return {
|
||||
id: item.id || item.customer_id,
|
||||
orders: Number(item.orders_count ?? item.order_count ?? item.orders ?? 0),
|
||||
|
|
@ -394,153 +402,198 @@ export class ShopyyAdapter implements ISiteAdapter {
|
|||
raw: item,
|
||||
};
|
||||
}
|
||||
|
||||
mapUnifiedToPlatformOrder(data: Partial<UnifiedOrderDTO>) {
|
||||
return data
|
||||
shopyyFulfillmentStatusMap = {
|
||||
// 未发货
|
||||
'300': OrderFulfillmentStatus.PENDING,
|
||||
// 部分发货
|
||||
'310': OrderFulfillmentStatus.PARTIALLY_FULFILLED,
|
||||
// 已发货
|
||||
'320': OrderFulfillmentStatus.FULFILLED,
|
||||
// 已取消
|
||||
'330': OrderFulfillmentStatus.CANCELLED,
|
||||
// 确认发货
|
||||
}
|
||||
|
||||
mapCreateOrderParams(data: Partial<UnifiedOrderDTO>): any {
|
||||
return data
|
||||
}
|
||||
private mapCustomer(item: ShopyyCustomer): UnifiedCustomerDTO {
|
||||
// 处理多地址结构
|
||||
const addresses = item.addresses || [];
|
||||
const defaultAddress = item.default_address || (addresses.length > 0 ? addresses[0] : {});
|
||||
|
||||
mapUpdateOrderParams(data: Partial<UnifiedOrderDTO>): any {
|
||||
// 构建 ShopYY 订单更新参数(仅包含传入的字段)
|
||||
const params: any = {};
|
||||
// 尝试从地址列表中获取billing和shipping
|
||||
// 如果没有明确区分,默认使用默认地址或第一个地址
|
||||
const billingAddress = defaultAddress;
|
||||
const shippingAddress = defaultAddress;
|
||||
|
||||
// 仅当字段存在时才添加到更新参数中
|
||||
if (data.status !== undefined) {
|
||||
// 映射订单状态
|
||||
const statusMap = {
|
||||
[OrderStatus.PENDING]: 100, // pending -> 100 未完成
|
||||
[OrderStatus.PROCESSING]: 110, // processing -> 110 待处理
|
||||
[OrderStatus.COMPLETED]: 180, // completed -> 180 已完成
|
||||
[OrderStatus.CANCEL]: 190 // cancel -> 190 取消
|
||||
const billing = {
|
||||
first_name: billingAddress.first_name || item.first_name || '',
|
||||
last_name: billingAddress.last_name || item.last_name || '',
|
||||
fullname: billingAddress.name || `${billingAddress.first_name || item.first_name || ''} ${billingAddress.last_name || item.last_name || ''}`.trim(),
|
||||
company: billingAddress.company || '',
|
||||
email: item.email || '',
|
||||
phone: billingAddress.phone || item.contact || '',
|
||||
address_1: billingAddress.address1 || '',
|
||||
address_2: billingAddress.address2 || '',
|
||||
city: billingAddress.city || '',
|
||||
state: billingAddress.province || '',
|
||||
postcode: billingAddress.zip || '',
|
||||
country: billingAddress.country_name || billingAddress.country_code || item.country?.country_name || ''
|
||||
};
|
||||
params.status = statusMap[data.status] || 100;
|
||||
|
||||
const shipping = {
|
||||
first_name: shippingAddress.first_name || item.first_name || '',
|
||||
last_name: shippingAddress.last_name || item.last_name || '',
|
||||
fullname: shippingAddress.name || `${shippingAddress.first_name || item.first_name || ''} ${shippingAddress.last_name || item.last_name || ''}`.trim(),
|
||||
company: shippingAddress.company || '',
|
||||
address_1: shippingAddress.address1 || '',
|
||||
address_2: shippingAddress.address2 || '',
|
||||
city: shippingAddress.city || '',
|
||||
state: shippingAddress.province || '',
|
||||
postcode: shippingAddress.zip || '',
|
||||
country: shippingAddress.country_name || shippingAddress.country_code || item.country?.country_name || ''
|
||||
};
|
||||
|
||||
return {
|
||||
id: item.id || item.customer_id,
|
||||
orders: Number(item.orders_count ?? item.order_count ?? item.orders ?? 0),
|
||||
total_spend: Number(item.total_spent ?? item.total_spend_amount ?? item.total_spend_money ?? 0),
|
||||
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,
|
||||
shipping,
|
||||
date_created:
|
||||
typeof item.created_at === 'number'
|
||||
? new Date(item.created_at * 1000).toISOString()
|
||||
: (typeof item.created_at === 'string' ? item.created_at : item.date_added || ''),
|
||||
date_modified:
|
||||
typeof item.updated_at === 'number'
|
||||
? new Date(item.updated_at * 1000).toISOString()
|
||||
: (typeof item.updated_at === 'string' ? item.updated_at : item.date_updated || ''),
|
||||
raw: item,
|
||||
};
|
||||
}
|
||||
mapProductQuery(query: UnifiedSearchParamsDTO): ShopyyProductQuery {
|
||||
return this.mapSearchParams(query)
|
||||
}
|
||||
|
||||
if (data.payment_method !== undefined) {
|
||||
params.payment_method = data.payment_method;
|
||||
async getProducts(
|
||||
params: UnifiedSearchParamsDTO
|
||||
): Promise<UnifiedPaginationDTO<UnifiedProductDTO>> {
|
||||
// 转换搜索参数
|
||||
const requestParams = this.mapProductQuery(params);
|
||||
const response = await this.shopyyService.fetchResourcePaged<ShopyyProduct>(
|
||||
this.site,
|
||||
'products/list',
|
||||
requestParams
|
||||
);
|
||||
const { items = [], total, totalPages, page, per_page } = response;
|
||||
const finalItems = items.map((item) => ({
|
||||
...item,
|
||||
permalink: `${this.site.websiteUrl}/products/${item.handle}`,
|
||||
})).map(this.mapProduct.bind(this))
|
||||
return {
|
||||
items: finalItems as UnifiedProductDTO[],
|
||||
total,
|
||||
totalPages,
|
||||
page,
|
||||
per_page,
|
||||
};
|
||||
}
|
||||
|
||||
if (data.billing) {
|
||||
// 更新客户信息
|
||||
if (data.billing.first_name !== undefined) {
|
||||
params.firstname = data.billing.first_name;
|
||||
}
|
||||
if (data.billing.last_name !== undefined) {
|
||||
params.lastname = data.billing.last_name;
|
||||
}
|
||||
if (data.billing.email !== undefined) {
|
||||
params.email = data.billing.email;
|
||||
}
|
||||
if (data.billing.phone !== undefined) {
|
||||
params.phone = data.billing.phone;
|
||||
async getAllProducts(params?: UnifiedSearchParamsDTO): Promise<UnifiedProductDTO[]> {
|
||||
// Shopyy getAllProducts 暂未实现
|
||||
throw new Error('Shopyy getAllProducts 暂未实现');
|
||||
}
|
||||
|
||||
// 更新账单地址
|
||||
params.billing_address = params.billing_address || {};
|
||||
if (data.billing.first_name !== undefined) {
|
||||
params.billing_address.first_name = data.billing.first_name;
|
||||
async getProduct(id: string | number): Promise<UnifiedProductDTO> {
|
||||
// 使用ShopyyService获取单个产品
|
||||
const product = await this.shopyyService.getProduct(this.site, id);
|
||||
return this.mapProduct(product);
|
||||
}
|
||||
if (data.billing.last_name !== undefined) {
|
||||
params.billing_address.last_name = data.billing.last_name;
|
||||
|
||||
async createProduct(data: Partial<UnifiedProductDTO>): Promise<UnifiedProductDTO> {
|
||||
const res = await this.shopyyService.createProduct(this.site, data);
|
||||
return this.mapProduct(res);
|
||||
}
|
||||
if (data.billing.company !== undefined) {
|
||||
params.billing_address.company = data.billing.company;
|
||||
async updateProduct(id: string | number, data: Partial<UnifiedProductDTO>): Promise<boolean> {
|
||||
// Shopyy update returns boolean?
|
||||
// shopyyService.updateProduct returns boolean.
|
||||
// So I can't return the updated product.
|
||||
// I have to fetch it again or return empty/input.
|
||||
// Since getProduct is missing, I'll return input data as UnifiedProductDTO (mock).
|
||||
await this.shopyyService.updateProduct(this.site, String(id), data);
|
||||
return true;
|
||||
}
|
||||
if (data.billing.address_1 !== undefined) {
|
||||
params.billing_address.address1 = data.billing.address_1;
|
||||
|
||||
async updateVariation(productId: string | number, variationId: string | number, data: any): Promise<any> {
|
||||
await this.shopyyService.updateVariation(this.site, String(productId), String(variationId), data);
|
||||
return { ...data, id: variationId };
|
||||
}
|
||||
if (data.billing.address_2 !== undefined) {
|
||||
params.billing_address.address2 = data.billing.address_2;
|
||||
|
||||
async getOrderNotes(orderId: string | number): Promise<any[]> {
|
||||
return await this.shopyyService.getOrderNotes(this.site, orderId);
|
||||
}
|
||||
if (data.billing.city !== undefined) {
|
||||
params.billing_address.city = data.billing.city;
|
||||
|
||||
async createOrderNote(orderId: string | number, data: any): Promise<any> {
|
||||
return await this.shopyyService.createOrderNote(this.site, orderId, data);
|
||||
}
|
||||
if (data.billing.state !== undefined) {
|
||||
params.billing_address.province = data.billing.state;
|
||||
|
||||
async deleteProduct(id: string | number): Promise<boolean> {
|
||||
// Use batch delete
|
||||
await this.shopyyService.batchProcessProducts(this.site, { delete: [id] });
|
||||
return true;
|
||||
}
|
||||
if (data.billing.postcode !== undefined) {
|
||||
params.billing_address.zip = data.billing.postcode;
|
||||
|
||||
async batchProcessProducts(
|
||||
data: { create?: any[]; update?: any[]; delete?: Array<string | number> }
|
||||
): Promise<any> {
|
||||
return await this.shopyyService.batchProcessProducts(this.site, data);
|
||||
}
|
||||
if (data.billing.country !== undefined) {
|
||||
params.billing_address.country_code = data.billing.country;
|
||||
/**
|
||||
* 将统一的订单查询参数转换为 ShopYY 订单查询参数
|
||||
* 包含状态映射等特殊处理
|
||||
*/
|
||||
private mapOrderSearchParams(params: UnifiedSearchParamsDTO): Partial<ShopyyOrderQuery> {
|
||||
// 首先使用通用参数转换
|
||||
const baseParams = this.mapSearchParams(params);
|
||||
|
||||
// 订单状态映射
|
||||
const statusMap = {
|
||||
'pending': '100', // 100 未完成
|
||||
'processing': '110', // 110 待处理
|
||||
'completed': "180", // 180 已完成(确认收货)
|
||||
'cancelled': '190', // 190 取消
|
||||
};
|
||||
|
||||
// 如果有状态参数,进行特殊映射
|
||||
if (baseParams.status) {
|
||||
const unifiedStatus = baseParams.status
|
||||
if (statusMap[unifiedStatus]) {
|
||||
baseParams.status = statusMap[unifiedStatus];
|
||||
}
|
||||
}
|
||||
|
||||
if (data.shipping) {
|
||||
// 更新送货地址
|
||||
params.shipping_address = params.shipping_address || {};
|
||||
if (data.shipping.first_name !== undefined) {
|
||||
params.shipping_address.first_name = data.shipping.first_name;
|
||||
}
|
||||
if (data.shipping.last_name !== undefined) {
|
||||
params.shipping_address.last_name = data.shipping.last_name;
|
||||
}
|
||||
if (data.shipping.company !== undefined) {
|
||||
params.shipping_address.company = data.shipping.company;
|
||||
}
|
||||
if (data.shipping.address_1 !== undefined) {
|
||||
params.shipping_address.address1 = data.shipping.address_1;
|
||||
}
|
||||
if (data.shipping.address_2 !== undefined) {
|
||||
params.shipping_address.address2 = data.shipping.address_2;
|
||||
}
|
||||
if (data.shipping.city !== undefined) {
|
||||
params.shipping_address.city = data.shipping.city;
|
||||
}
|
||||
if (data.shipping.state !== undefined) {
|
||||
params.shipping_address.province = data.shipping.state;
|
||||
}
|
||||
if (data.shipping.postcode !== undefined) {
|
||||
params.shipping_address.zip = data.shipping.postcode;
|
||||
}
|
||||
if (data.shipping.country !== undefined) {
|
||||
params.shipping_address.country_code = data.shipping.country;
|
||||
}
|
||||
if (data.shipping.phone !== undefined) {
|
||||
params.shipping_address.phone = data.shipping.phone;
|
||||
}
|
||||
// 处理ID参数
|
||||
if (baseParams.id) {
|
||||
baseParams.ids = baseParams.id;
|
||||
delete baseParams.id;
|
||||
}
|
||||
|
||||
// 更新订单项
|
||||
if (data.line_items && data.line_items.length > 0) {
|
||||
params.products = data.line_items.map((item: UnifiedOrderLineItemDTO) => ({
|
||||
product_id: item.product_id,
|
||||
quantity: item.quantity,
|
||||
// price: item.price || '0.00',
|
||||
sku: item.sku || '',
|
||||
}));
|
||||
}
|
||||
|
||||
// 更新物流信息
|
||||
if (data.shipping_lines && data.shipping_lines.length > 0) {
|
||||
const shippingLine = data.shipping_lines[0];
|
||||
if (shippingLine.method_title !== undefined) {
|
||||
params.shipping_method = shippingLine.method_title;
|
||||
}
|
||||
if (shippingLine.total !== undefined) {
|
||||
params.shipping_price = shippingLine.total;
|
||||
}
|
||||
}
|
||||
|
||||
// // 更新备注信息
|
||||
// if (data.note !== undefined) {
|
||||
// params.note = data.note;
|
||||
// }
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
async getOrder(where: {id: string | number}): Promise<UnifiedOrderDTO> {
|
||||
const data = await this.shopyyService.getOrder(this.site.id, String(where.id));
|
||||
return this.mapPlatformToUnifiedOrder(data);
|
||||
return baseParams;
|
||||
}
|
||||
|
||||
async getOrders(
|
||||
params: UnifiedSearchParamsDTO
|
||||
): Promise<UnifiedPaginationDTO<UnifiedOrderDTO>> {
|
||||
// 转换订单查询参数
|
||||
const normalizedParams = this.mapOrderSearchParams(params);
|
||||
const { items, total, totalPages, page, per_page } = await this.shopyyService.fetchResourcePaged<any>(
|
||||
this.site,
|
||||
'orders',
|
||||
normalizedParams
|
||||
);
|
||||
// 转换订单查询参数
|
||||
const normalizedParams = this.mapOrderSearchParams(params);
|
||||
const { items, total, totalPages, page, per_page } = await this.shopyyService.fetchResourcePaged<any>(
|
||||
|
|
@ -557,6 +610,17 @@ export class ShopyyAdapter implements ISiteAdapter {
|
|||
};
|
||||
}
|
||||
|
||||
async countOrders(where: Record<string,any>): Promise<number> {
|
||||
// 使用最小分页只获取总数
|
||||
const searchParams = {
|
||||
where,
|
||||
page: 1,
|
||||
per_page: 1,
|
||||
}
|
||||
const data = await this.getOrders(searchParams);
|
||||
return data.total || 0;
|
||||
}
|
||||
|
||||
async getAllOrders(params?: UnifiedSearchParamsDTO): Promise<UnifiedOrderDTO[]> {
|
||||
const data = await this.shopyyService.getAllOrders(this.site.id, params);
|
||||
return data.map(this.mapPlatformToUnifiedOrder.bind(this));
|
||||
|
|
@ -882,7 +946,7 @@ export class ShopyyAdapter implements ISiteAdapter {
|
|||
const requestParams = this.mapProductQuery(params);
|
||||
const response = await this.shopyyService.fetchResourcePaged<ShopyyProduct>(
|
||||
this.site,
|
||||
'products/list',
|
||||
'media', // Shopyy的媒体API端点可能需要调整
|
||||
requestParams
|
||||
);
|
||||
const { items = [], total, totalPages, page, per_page } = response;
|
||||
|
|
|
|||
|
|
@ -890,10 +890,87 @@ export class WooCommerceAdapter implements ISiteAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
// ========== 评论映射方法 ==========
|
||||
async batchProcessProducts(
|
||||
data: { create?: any[]; update?: any[]; delete?: Array<string | number> }
|
||||
): Promise<any> {
|
||||
// 批量处理产品增删改
|
||||
return await this.wpService.batchProcessProducts(this.site, data);
|
||||
}
|
||||
|
||||
mapUnifiedToPlatformReview(data: Partial<UnifiedReviewDTO>) {
|
||||
return data;
|
||||
async getOrders(
|
||||
params: UnifiedSearchParamsDTO
|
||||
): Promise<UnifiedPaginationDTO<UnifiedOrderDTO>> {
|
||||
const requestParams = this.mapOrderSearchParams(params);
|
||||
const { items, total, totalPages, page, per_page } =
|
||||
await this.wpService.fetchResourcePaged<any>(this.site, 'orders', requestParams);
|
||||
|
||||
// 并行获取所有订单的履行信息
|
||||
const ordersWithFulfillments = await Promise.all(
|
||||
items.map(async (order: any) => {
|
||||
try {
|
||||
// 获取订单的履行信息
|
||||
const fulfillments = await this.getOrderFulfillments(order.id);
|
||||
// 将履行信息添加到订单对象中
|
||||
return {
|
||||
...order,
|
||||
fulfillments: fulfillments || []
|
||||
};
|
||||
} catch (error) {
|
||||
// 如果获取履行信息失败,仍然返回订单,只是履行信息为空数组
|
||||
console.error(`获取订单 ${order.id} 的履行信息失败:`, error);
|
||||
return {
|
||||
...order,
|
||||
fulfillments: []
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
return {
|
||||
items: ordersWithFulfillments.map(this.mapOrder),
|
||||
total,
|
||||
totalPages,
|
||||
page,
|
||||
per_page,
|
||||
};
|
||||
}
|
||||
|
||||
async countOrders(where: Record<string,any>): Promise<number> {
|
||||
// 使用最小分页只获取总数
|
||||
const searchParams: UnifiedSearchParamsDTO = {
|
||||
where,
|
||||
page: 1,
|
||||
per_page: 1,
|
||||
};
|
||||
const requestParams = this.mapOrderSearchParams(searchParams);
|
||||
const { total } = await this.wpService.fetchResourcePaged<any>(this.site, 'orders', requestParams);
|
||||
return total || 0;
|
||||
}
|
||||
|
||||
async getOrder(id: string | number): Promise<UnifiedOrderDTO> {
|
||||
// 获取单个订单详情
|
||||
const api = (this.wpService as any).createApi(this.site, 'wc/v3');
|
||||
const res = await api.get(`orders/${id}`);
|
||||
return this.mapOrder(res.data);
|
||||
}
|
||||
|
||||
async getAllOrders(params?: UnifiedSearchParamsDTO): Promise<UnifiedOrderDTO[]> {
|
||||
// 使用sdkGetAll获取所有订单数据,不受分页限制
|
||||
const api = (this.wpService as any).createApi(this.site, 'wc/v3');
|
||||
const orders = await this.wpService.sdkGetAll(api, 'orders', params);
|
||||
return orders.map((order: any) => this.mapOrder(order));
|
||||
}
|
||||
|
||||
async createOrder(data: Partial<UnifiedOrderDTO>): Promise<UnifiedOrderDTO> {
|
||||
// 创建订单并返回统一订单DTO
|
||||
const api = (this.wpService as any).createApi(this.site, 'wc/v3');
|
||||
const res = await api.post('orders', data);
|
||||
return this.mapOrder(res.data);
|
||||
}
|
||||
|
||||
async updateOrder(id: string | number, data: Partial<UnifiedOrderDTO>): Promise<boolean> {
|
||||
// 更新订单并返回布尔结果
|
||||
return await this.wpService.updateOrder(this.site, String(id), data as any);
|
||||
}
|
||||
|
||||
mapCreateReviewParams(data: CreateReviewDTO) {
|
||||
|
|
@ -1239,142 +1316,4 @@ export class WooCommerceAdapter implements ISiteAdapter {
|
|||
throw new Error(`删除产品变体失败: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 网络钩子映射方法 ==========
|
||||
mapUnifiedToPlatformWebhook(data: Partial<UnifiedWebhookDTO>) {
|
||||
return data;
|
||||
}
|
||||
|
||||
mapCreateWebhookParams(data: CreateWebhookDTO) {
|
||||
return data;
|
||||
}
|
||||
mapUpdateWebhookParams(data: UpdateWebhookDTO) {
|
||||
return data;
|
||||
}
|
||||
|
||||
// 映射 WooCommerce webhook 到统一格式
|
||||
mapPlatformToUnifiedWebhook(webhook: WooWebhook): UnifiedWebhookDTO {
|
||||
return {
|
||||
id: webhook.id.toString(),
|
||||
name: webhook.name,
|
||||
status: webhook.status,
|
||||
topic: webhook.topic,
|
||||
delivery_url: webhook.delivery_url,
|
||||
secret: webhook.secret,
|
||||
api_version: webhook.api_version,
|
||||
date_created: webhook.date_created,
|
||||
date_modified: webhook.date_modified,
|
||||
// metadata: webhook.meta_data || [],
|
||||
};
|
||||
}
|
||||
|
||||
// 网络钩子操作方法
|
||||
// 获取站点的 webhooks 列表
|
||||
async getWebhooks(params: UnifiedSearchParamsDTO): Promise<UnifiedWebhookPaginationDTO> {
|
||||
try {
|
||||
const result = await this.wpService.getWebhooks(this.site, params);
|
||||
|
||||
return {
|
||||
items: (result.items as WooWebhook[]).map(this.mapPlatformToUnifiedWebhook),
|
||||
total: result.total,
|
||||
page: Number(params.page || 1),
|
||||
per_page: Number(params.per_page || 20),
|
||||
totalPages: result.totalPages,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to get webhooks: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取所有webhooks
|
||||
async getAllWebhooks(params?: UnifiedSearchParamsDTO): Promise<UnifiedWebhookDTO[]> {
|
||||
try {
|
||||
const api = (this.wpService as any).createApi(this.site, 'wc/v3');
|
||||
const webhooks = await this.wpService.sdkGetAll(api, 'webhooks', params);
|
||||
return webhooks.map((webhook: any) => this.mapPlatformToUnifiedWebhook(webhook));
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to get all webhooks: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取单个 webhook 详情
|
||||
async getWebhook(where: {id: string | number}): Promise<UnifiedWebhookDTO> {
|
||||
try {
|
||||
const result = await this.wpService.getWebhook(this.site, where.id);
|
||||
return this.mapPlatformToUnifiedWebhook(result as WooWebhook);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to get webhook: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的 webhook
|
||||
async createWebhook(data: CreateWebhookDTO): Promise<UnifiedWebhookDTO> {
|
||||
try {
|
||||
const params = {
|
||||
name: data.name,
|
||||
status: 'active', // 默认状态为活跃
|
||||
topic: data.topic,
|
||||
delivery_url: data.delivery_url,
|
||||
secret: data.secret,
|
||||
api_version: data.api_version || 'wp/v2',
|
||||
};
|
||||
const result = await this.wpService.createWebhook(this.site, params);
|
||||
return this.mapPlatformToUnifiedWebhook(result as WooWebhook);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to create webhook: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新现有的 webhook
|
||||
async updateWebhook(where: Partial<Pick<UnifiedWebhookDTO, 'id'>>, data: UpdateWebhookDTO): Promise<UnifiedWebhookDTO> {
|
||||
try {
|
||||
const params = {
|
||||
...(data.name ? { name: data.name } : {}),
|
||||
...(data.status ? { status: data.status } : {}),
|
||||
...(data.topic ? { topic: data.topic } : {}),
|
||||
...(data.delivery_url ? { delivery_url: data.delivery_url } : {}),
|
||||
...(data.secret ? { secret: data.secret } : {}),
|
||||
...(data.api_version ? { api_version: data.api_version } : {}),
|
||||
};
|
||||
const result = await this.wpService.updateWebhook(this.site, where.id, params);
|
||||
return this.mapPlatformToUnifiedWebhook(result as WooWebhook);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to update webhook: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除指定的 webhook
|
||||
async deleteWebhook(where: Partial<Pick<UnifiedWebhookDTO, 'id'>>): Promise<boolean> {
|
||||
try {
|
||||
await this.wpService.deleteWebhook(this.site, where.id);
|
||||
return true;
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to delete webhook: ${error instanceof Error ? error.message : String(error)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 其他方法 ==========
|
||||
async getLinks(): Promise<Array<{ title: string, url: string }>> {
|
||||
const baseUrl = this.site.apiUrl;
|
||||
const links = [
|
||||
{ title: '访问网站', url: baseUrl },
|
||||
{ title: '管理后台', url: `${baseUrl}/wp-admin/` },
|
||||
{ title: '订单管理', url: `${baseUrl}/wp-admin/edit.php?post_type=shop_order` },
|
||||
{ title: '产品管理', url: `${baseUrl}/wp-admin/edit.php?post_type=product` },
|
||||
{ title: '客户管理', url: `${baseUrl}/wp-admin/users.php` },
|
||||
{ title: '插件管理', url: `${baseUrl}/wp-admin/plugins.php` },
|
||||
{ title: '主题管理', url: `${baseUrl}/wp-admin/themes.php` },
|
||||
{ title: 'WooCommerce设置', url: `${baseUrl}/wp-admin/admin.php?page=wc-settings` },
|
||||
{ title: 'WooCommerce报告', url: `${baseUrl}/wp-admin/admin.php?page=wc-reports` },
|
||||
];
|
||||
return links;
|
||||
}
|
||||
|
||||
batchProcessOrders?(data: { create?: any[]; update?: any[]; delete?: Array<string | number>; }): Promise<any> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
|
||||
batchProcessCustomers?(data: { create?: any[]; update?: any[]; delete?: Array<string | number>; }): Promise<any> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,12 @@ export interface ISiteAdapter {
|
|||
/**
|
||||
* 获取客户列表
|
||||
*/
|
||||
getCustomers(params: UnifiedSearchParamsDTO): Promise<UnifiedPaginationDTO<UnifiedCustomerDTO>>;
|
||||
getOrders(params: UnifiedSearchParamsDTO): Promise<UnifiedPaginationDTO<UnifiedOrderDTO>>;
|
||||
|
||||
/**
|
||||
* 获取订单总数
|
||||
*/
|
||||
countOrders(params: Record<string,any>): Promise<number>;
|
||||
|
||||
/**
|
||||
* 获取所有客户
|
||||
|
|
|
|||
Loading…
Reference in New Issue