Compare commits
No commits in common. "99bd7009ccc7ce406fb305ada02473a7aae02104" and "edd91185a11239a77f6f897557f32cf3231b58a2" have entirely different histories.
99bd7009cc
...
edd91185a1
|
|
@ -132,7 +132,7 @@ export class ShopyyAdapter implements ISiteAdapter {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
shopyyOrderStatusMap = {//订单状态 100 未完成;110 待处理;180 已完成(确认收货); 190 取消;
|
shopyyOrderAutoNextStatusMap = {//订单状态 100 未完成;110 待处理;180 已完成(确认收货); 190 取消;
|
||||||
[100]: OrderStatus.PENDING, // 100 未完成 转为 pending
|
[100]: OrderStatus.PENDING, // 100 未完成 转为 pending
|
||||||
[110]: OrderStatus.PROCESSING, // 110 待处理 转为 processing
|
[110]: OrderStatus.PROCESSING, // 110 待处理 转为 processing
|
||||||
[180]: OrderStatus.COMPLETED, // 180 已完成(确认收货) 转为 completed
|
[180]: OrderStatus.COMPLETED, // 180 已完成(确认收货) 转为 completed
|
||||||
|
|
@ -244,13 +244,13 @@ export class ShopyyAdapter implements ISiteAdapter {
|
||||||
'SGD': 'S$'
|
'SGD': 'S$'
|
||||||
// 可以根据需要添加更多货币代码和符号
|
// 可以根据需要添加更多货币代码和符号
|
||||||
};
|
};
|
||||||
// 映射订单状态,如果不存在则默认 pending
|
const originStatus = item.status;
|
||||||
const status = this.shopyyOrderStatusMap[item.status?? item.order_status] || OrderStatus.PENDING;
|
item.status = this.shopyyOrderAutoNextStatusMap[originStatus];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: item.id || item.order_id,
|
id: item.id || item.order_id,
|
||||||
number: item.order_number || item.order_sn,
|
number: item.order_number || item.order_sn,
|
||||||
status,
|
status: String(item.status || item.order_status),
|
||||||
currency: item.currency_code || item.currency,
|
currency: item.currency_code || item.currency,
|
||||||
total: String(item.total_price ?? item.total_amount ?? ''),
|
total: String(item.total_price ?? item.total_amount ?? ''),
|
||||||
customer_id: item.customer_id || item.user_id,
|
customer_id: item.customer_id || item.user_id,
|
||||||
|
|
@ -427,37 +427,15 @@ export class ShopyyAdapter implements ISiteAdapter {
|
||||||
): Promise<any> {
|
): Promise<any> {
|
||||||
return await this.shopyyService.batchProcessProducts(this.site, data);
|
return await this.shopyyService.batchProcessProducts(this.site, data);
|
||||||
}
|
}
|
||||||
mapUnifiedOrderQueryToShopyyQuery(params:UnifiedSearchParamsDTO ){
|
|
||||||
const {where={} as any, ...restParams} = params|| {}
|
|
||||||
const statusMap = {
|
|
||||||
'pending': '100', // 100 未完成
|
|
||||||
'processing': '110', // 110 待处理
|
|
||||||
'completed': "180", // 180 已完成(确认收货)
|
|
||||||
'cancelled': '190', // 190 取消
|
|
||||||
}
|
|
||||||
const normalizedParams:any= {
|
|
||||||
...restParams,
|
|
||||||
}
|
|
||||||
if(where){
|
|
||||||
normalizedParams.where = {
|
|
||||||
...where,
|
|
||||||
}
|
|
||||||
if(where.status){
|
|
||||||
normalizedParams.where.status = statusMap[where.status];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return normalizedParams
|
|
||||||
}
|
|
||||||
|
|
||||||
async getOrders(
|
async getOrders(
|
||||||
params: UnifiedSearchParamsDTO
|
params: UnifiedSearchParamsDTO
|
||||||
): Promise<UnifiedPaginationDTO<UnifiedOrderDTO>> {
|
): Promise<UnifiedPaginationDTO<UnifiedOrderDTO>> {
|
||||||
const normalizedParams = this.mapUnifiedOrderQueryToShopyyQuery(params);
|
|
||||||
const { items, total, totalPages, page, per_page } =
|
const { items, total, totalPages, page, per_page } =
|
||||||
await this.shopyyService.fetchResourcePaged<any>(
|
await this.shopyyService.fetchResourcePaged<any>(
|
||||||
this.site,
|
this.site,
|
||||||
'orders',
|
'orders',
|
||||||
normalizedParams
|
params
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
items: items.map(this.mapOrder.bind(this)),
|
items: items.map(this.mapOrder.bind(this)),
|
||||||
|
|
|
||||||
|
|
@ -481,7 +481,6 @@ export class WooCommerceAdapter implements ISiteAdapter {
|
||||||
...li,
|
...li,
|
||||||
productId: li.product_id,
|
productId: li.product_id,
|
||||||
})),
|
})),
|
||||||
customer_ip_address: item.customer_ip_address ?? '',
|
|
||||||
date_paid: item.date_paid ?? '',
|
date_paid: item.date_paid ?? '',
|
||||||
utm_source: item?.meta_data?.find(el => el.key === '_wc_order_attribution_utm_source')?.value || '',
|
utm_source: item?.meta_data?.find(el => el.key === '_wc_order_attribution_utm_source')?.value || '',
|
||||||
device_type: item?.meta_data?.find(el => el.key === '_wc_order_attribution_device_type')?.value || '',
|
device_type: item?.meta_data?.find(el => el.key === '_wc_order_attribution_device_type')?.value || '',
|
||||||
|
|
|
||||||
|
|
@ -663,7 +663,8 @@ export class SiteApiController {
|
||||||
this.logger.info(`[Site API] 获取订单列表开始, siteId: ${siteId}, query: ${JSON.stringify(query)}`);
|
this.logger.info(`[Site API] 获取订单列表开始, siteId: ${siteId}, query: ${JSON.stringify(query)}`);
|
||||||
try {
|
try {
|
||||||
const adapter = await this.siteApiService.getAdapter(siteId);
|
const adapter = await this.siteApiService.getAdapter(siteId);
|
||||||
const data = await adapter.getOrders(query);
|
const where = { ...(query.where || {}) };
|
||||||
|
const data = await adapter.getOrders({ ...query, where });
|
||||||
this.logger.info(`[Site API] 获取订单列表成功, siteId: ${siteId}, 共获取到 ${data.total} 个订单`);
|
this.logger.info(`[Site API] 获取订单列表成功, siteId: ${siteId}, 共获取到 ${data.total} 个订单`);
|
||||||
return successResponse(data);
|
return successResponse(data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,12 @@ export class WebhookController {
|
||||||
return 'webhook';
|
return 'webhook';
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO 这里得检查一下是否对 SHOPYY有效,否则得另外书写
|
|
||||||
@Post('/woocommerce')
|
@Post('/woocommerce')
|
||||||
async handleWooWebhook(
|
async handleWooWebhook(
|
||||||
@Body() body: any,
|
@Body() body: any,
|
||||||
@Query('siteId') siteIdStr: string,
|
@Query('siteId') siteIdStr: string,
|
||||||
@Headers() header: any
|
@Headers() header: any
|
||||||
) {
|
) {
|
||||||
console.log(`webhook woocommerce`, siteIdStr, body,header)
|
|
||||||
const signature = header['x-wc-webhook-signature'];
|
const signature = header['x-wc-webhook-signature'];
|
||||||
const topic = header['x-wc-webhook-topic'];
|
const topic = header['x-wc-webhook-topic'];
|
||||||
const source = header['x-wc-webhook-source'];
|
const source = header['x-wc-webhook-source'];
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ export class CreateCustomerDTO {
|
||||||
site_id: number;
|
site_id: number;
|
||||||
|
|
||||||
@ApiProperty({ description: '原始ID', required: false })
|
@ApiProperty({ description: '原始ID', required: false })
|
||||||
origin_id?: string;
|
origin_id?: number;
|
||||||
|
|
||||||
@ApiProperty({ description: '邮箱' })
|
@ApiProperty({ description: '邮箱' })
|
||||||
email: string;
|
email: string;
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,7 @@ import { ApiProperty } from '@midwayjs/swagger';
|
||||||
import {
|
import {
|
||||||
UnifiedPaginationDTO,
|
UnifiedPaginationDTO,
|
||||||
} from './api.dto';
|
} from './api.dto';
|
||||||
// export class UnifiedOrderWhere{
|
|
||||||
// []
|
|
||||||
// }
|
|
||||||
export class UnifiedTagDTO {
|
export class UnifiedTagDTO {
|
||||||
// 标签DTO用于承载统一标签数据
|
// 标签DTO用于承载统一标签数据
|
||||||
@ApiProperty({ description: '标签ID' })
|
@ApiProperty({ description: '标签ID' })
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ export class CustomerService {
|
||||||
site_id: siteId, // 使用站点ID而不是客户ID
|
site_id: siteId, // 使用站点ID而不是客户ID
|
||||||
site_created_at: this.parseDate(siteCustomer.date_created),
|
site_created_at: this.parseDate(siteCustomer.date_created),
|
||||||
site_updated_at: this.parseDate(siteCustomer.date_modified),
|
site_updated_at: this.parseDate(siteCustomer.date_modified),
|
||||||
origin_id: String(siteCustomer.id),
|
origin_id: Number(siteCustomer.id),
|
||||||
email: siteCustomer.email,
|
email: siteCustomer.email,
|
||||||
first_name: siteCustomer.first_name,
|
first_name: siteCustomer.first_name,
|
||||||
last_name: siteCustomer.last_name,
|
last_name: siteCustomer.last_name,
|
||||||
|
|
@ -171,7 +171,10 @@ export class CustomerService {
|
||||||
// 第二步:将站点客户数据转换为客户实体数据
|
// 第二步:将站点客户数据转换为客户实体数据
|
||||||
const customersData = siteCustomers.map(siteCustomer => {
|
const customersData = siteCustomers.map(siteCustomer => {
|
||||||
return this.mapSiteCustomerToCustomer(siteCustomer, siteId);
|
return this.mapSiteCustomerToCustomer(siteCustomer, siteId);
|
||||||
})
|
}).map(customer => ({
|
||||||
|
...customer,
|
||||||
|
origin_id: String(customer.origin_id),
|
||||||
|
}));
|
||||||
|
|
||||||
// 第三步:批量upsert客户数据
|
// 第三步:批量upsert客户数据
|
||||||
const upsertResult = await this.upsertManyCustomers(customersData);
|
const upsertResult = await this.upsertManyCustomers(customersData);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Inject, Logger, Provide } from '@midwayjs/core';
|
import { Inject, Provide } from '@midwayjs/core';
|
||||||
import { WPService } from './wp.service';
|
import { WPService } from './wp.service';
|
||||||
import { Order } from '../entity/order.entity';
|
import { Order } from '../entity/order.entity';
|
||||||
import { In, Like, Repository } from 'typeorm';
|
import { In, Like, Repository } from 'typeorm';
|
||||||
|
|
@ -37,7 +37,6 @@ import * as fs from 'fs';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import { UnifiedOrderDTO } from '../dto/site-api.dto';
|
import { UnifiedOrderDTO } from '../dto/site-api.dto';
|
||||||
import { CustomerService } from './customer.service';
|
|
||||||
@Provide()
|
@Provide()
|
||||||
export class OrderService {
|
export class OrderService {
|
||||||
|
|
||||||
|
|
@ -98,15 +97,9 @@ export class OrderService {
|
||||||
@Inject()
|
@Inject()
|
||||||
siteService: SiteService;
|
siteService: SiteService;
|
||||||
|
|
||||||
@Inject()
|
@Inject()
|
||||||
siteApiService: SiteApiService;
|
siteApiService: SiteApiService;
|
||||||
|
|
||||||
@Inject()
|
|
||||||
customerService: CustomerService;
|
|
||||||
|
|
||||||
@Logger()
|
|
||||||
logger; // 注入 Logger 实例
|
|
||||||
|
|
||||||
async syncOrders(siteId: number, params: Record<string, any> = {}): Promise<SyncOperationResult> {
|
async syncOrders(siteId: number, params: Record<string, any> = {}): Promise<SyncOperationResult> {
|
||||||
// 调用 WooCommerce API 获取订单
|
// 调用 WooCommerce API 获取订单
|
||||||
const result = await (await this.siteApiService.getAdapter(siteId)).getAllOrders(params);
|
const result = await (await this.siteApiService.getAdapter(siteId)).getAllOrders(params);
|
||||||
|
|
@ -151,7 +144,7 @@ export class OrderService {
|
||||||
syncResult.processed++;
|
syncResult.processed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.logger.debug('syncOrders result', syncResult)
|
|
||||||
return syncResult;
|
return syncResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,7 +202,7 @@ export class OrderService {
|
||||||
|
|
||||||
// 由于 wordpress 订单状态和 我们的订单状态 不一致,需要做转换
|
// 由于 wordpress 订单状态和 我们的订单状态 不一致,需要做转换
|
||||||
async autoUpdateOrderStatus(siteId: number, order: any) {
|
async autoUpdateOrderStatus(siteId: number, order: any) {
|
||||||
// console.log('更新订单状态', order.status, '=>', this.orderAutoNextStatusMap[order.status])
|
console.log('更新订单状态', order.status, '=>', this.orderAutoNextStatusMap[order.status])
|
||||||
// 其他状态保持不变
|
// 其他状态保持不变
|
||||||
const originStatus = order.status;
|
const originStatus = order.status;
|
||||||
// 如果有值就赋值
|
// 如果有值就赋值
|
||||||
|
|
@ -293,7 +286,7 @@ export class OrderService {
|
||||||
externalOrderId,
|
externalOrderId,
|
||||||
coupon_lines,
|
coupon_lines,
|
||||||
});
|
});
|
||||||
// console.log('同步进单个订单2')
|
console.log('同步进单个订单2')
|
||||||
await this.saveOrderShipping({
|
await this.saveOrderShipping({
|
||||||
siteId,
|
siteId,
|
||||||
orderId,
|
orderId,
|
||||||
|
|
@ -347,33 +340,16 @@ export class OrderService {
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
entity.orderStatus = this.mapOrderStatus(entity.status);
|
entity.orderStatus = this.mapOrderStatus(entity.status);
|
||||||
await this.customerService.upsertCustomer({
|
const customer = await this.customerModel.findOne({
|
||||||
email: order.customer_email,
|
where: { email: order.customer_email },
|
||||||
site_id: siteId,
|
|
||||||
origin_id: String(order.customer_id),
|
|
||||||
billing: order.billing,
|
|
||||||
shipping: order.shipping,
|
|
||||||
first_name: order?.billing?.first_name || order?.shipping?.first_name,
|
|
||||||
last_name: order?.billing?.last_name || order?.shipping?.last_name,
|
|
||||||
fullname: order?.billing?.fullname || order?.shipping?.fullname,
|
|
||||||
phone: order?.billing?.phone || order?.shipping?.phone,
|
|
||||||
|
|
||||||
// tags:['fromOrder']
|
|
||||||
});
|
});
|
||||||
// const customer = await this.customerModel.findOne({
|
if (!customer) {
|
||||||
// where: { email: order.customer_email },
|
await this.customerModel.save({
|
||||||
// });
|
email: order.customer_email,
|
||||||
// if (!customer) {
|
site_id: siteId,
|
||||||
// // 这里用 customer create
|
origin_id: String(order.customer_id),
|
||||||
// await this.customerModel.save({
|
});
|
||||||
// email: order.customer_email,
|
}
|
||||||
// site_id: siteId,
|
|
||||||
// origin_id: String(order.customer_id),
|
|
||||||
// billing: order.billing,
|
|
||||||
// shipping: order.shipping,
|
|
||||||
// phone: order?.billing?.phone || order?.shipping?.phone,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
return await this.orderModel.save(entity);
|
return await this.orderModel.save(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,7 +394,7 @@ export class OrderService {
|
||||||
externalOrderId: string;
|
externalOrderId: string;
|
||||||
orderItems: Record<string, any>[];
|
orderItems: Record<string, any>[];
|
||||||
}) {
|
}) {
|
||||||
// console.log('saveOrderItems params',params)
|
console.log('saveOrderItems params',params)
|
||||||
const { siteId, orderId, externalOrderId, orderItems } = params;
|
const { siteId, orderId, externalOrderId, orderItems } = params;
|
||||||
const currentOrderItems = await this.orderItemModel.find({
|
const currentOrderItems = await this.orderItemModel.find({
|
||||||
where: { siteId, externalOrderId: externalOrderId },
|
where: { siteId, externalOrderId: externalOrderId },
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { ILogger, Inject, Provide } from '@midwayjs/core';
|
import { Inject, Provide } from '@midwayjs/core';
|
||||||
import axios, { AxiosRequestConfig } from 'axios';
|
import axios, { AxiosRequestConfig } from 'axios';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as FormData from 'form-data';
|
import * as FormData from 'form-data';
|
||||||
|
|
@ -13,8 +13,6 @@ import { UnifiedSearchParamsDTO } from '../dto/api.dto';
|
||||||
*/
|
*/
|
||||||
@Provide()
|
@Provide()
|
||||||
export class ShopyyService {
|
export class ShopyyService {
|
||||||
@Inject()
|
|
||||||
logger:ILogger;
|
|
||||||
/**
|
/**
|
||||||
* 获取ShopYY评论列表
|
* 获取ShopYY评论列表
|
||||||
* @param site 站点配置
|
* @param site 站点配置
|
||||||
|
|
@ -203,12 +201,10 @@ export class ShopyyService {
|
||||||
page,
|
page,
|
||||||
limit
|
limit
|
||||||
};
|
};
|
||||||
this.logger.debug('ShopYY API请求分页参数:'+ JSON.stringify(requestParams));
|
|
||||||
const response = await this.request(site, endpoint, 'GET', null, requestParams);
|
const response = await this.request(site, endpoint, 'GET', null, requestParams);
|
||||||
if (response?.code !== 0) {
|
if (response?.code !== 0) {
|
||||||
throw new Error(response?.msg)
|
throw new Error(response?.msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items: (response.data.list || []) as T[],
|
items: (response.data.list || []) as T[],
|
||||||
total: response.data?.paginate?.total || 0,
|
total: response.data?.paginate?.total || 0,
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,7 @@ export class SiteService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 save 方法保存实体及其关联关系
|
// 使用 save 方法保存实体及其关联关系
|
||||||
const result = await this.siteModel.save(newSite);
|
await this.siteModel.save(newSite);
|
||||||
console.log('result create siteId',result)
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,7 +97,7 @@ export class SiteService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用 save 方法保存实体及其更新后的关联关系
|
// 使用 save 方法保存实体及其更新后的关联关系
|
||||||
await this.siteModel.save(siteToUpdate);
|
await this.siteModel.save(siteToUpdate);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue