1
This commit is contained in:
@@ -64,6 +64,30 @@ public class ErpGoofishOrderController extends BaseController {
|
||||
return AjaxResult.success(data);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('jarvis:erpGoofishOrder:edit')")
|
||||
@Log(title = "闲管家历史全量拉单", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/pull/{appKey}/full")
|
||||
public AjaxResult pullOneFull(@PathVariable String appKey) {
|
||||
int n = erpGoofishOrderService.pullOrdersForAppKeyFullHistory(appKey);
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("processedItems", n);
|
||||
data.put("pullFullHistoryDays", goofishProperties.getPullFullHistoryDays());
|
||||
data.put("pullTimeChunkSeconds", goofishProperties.getPullTimeChunkSeconds());
|
||||
return AjaxResult.success(data);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('jarvis:erpGoofishOrder:edit')")
|
||||
@Log(title = "闲管家全账号历史全量拉单", businessType = BusinessType.OTHER)
|
||||
@PostMapping("/pullAll/full")
|
||||
public AjaxResult pullAllFull() {
|
||||
int n = erpGoofishOrderService.pullAllEnabledFullHistory();
|
||||
Map<String, Object> data = new LinkedHashMap<>();
|
||||
data.put("processedItems", n);
|
||||
data.put("pullFullHistoryDays", goofishProperties.getPullFullHistoryDays());
|
||||
data.put("pullTimeChunkSeconds", goofishProperties.getPullTimeChunkSeconds());
|
||||
return AjaxResult.success(data);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('jarvis:erpGoofishOrder:edit')")
|
||||
@Log(title = "闲管家订单详情刷新", businessType = BusinessType.UPDATE)
|
||||
@PostMapping("/refreshDetail/{id}")
|
||||
|
||||
@@ -268,7 +268,14 @@ jarvis:
|
||||
pull-lookback-hours: 72
|
||||
pull-cron: "0 0/15 * * * ?"
|
||||
auto-ship-cron: "0 2/10 * * * ?"
|
||||
pull-max-pages-per-shop: 30
|
||||
# 订单列表:每页条数(最大 100)
|
||||
pull-page-size: 100
|
||||
# 每授权单次最大页数(最大 100;与 page_size 乘积勿超 10000)
|
||||
pull-max-pages-per-shop: 100
|
||||
# 全量拉单按 update_time 分段(秒),默认 7 天
|
||||
pull-time-chunk-seconds: 604800
|
||||
# 全量拉单起点:距今多少天(默认约 3 年)
|
||||
pull-full-history-days: 1095
|
||||
auto-ship-batch-size: 20
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,21 @@ CREATE TABLE IF NOT EXISTS erp_goofish_order (
|
||||
modify_time bigint(20) DEFAULT NULL COMMENT '订单更新时间(秒)',
|
||||
product_id bigint(20) DEFAULT NULL COMMENT '管家商品ID',
|
||||
item_id bigint(20) DEFAULT NULL COMMENT '闲鱼商品ID',
|
||||
goods_title varchar(512) DEFAULT NULL COMMENT '商品标题(详情 goods.title)',
|
||||
goods_image_url varchar(1024) DEFAULT NULL COMMENT '商品主图 URL(goods.images 首图)',
|
||||
buyer_nick varchar(256) DEFAULT NULL COMMENT '买家昵称(详情 buyer_nick)',
|
||||
pay_amount bigint(20) DEFAULT NULL COMMENT '实付金额(分) pay_amount',
|
||||
detail_waybill_no varchar(128) DEFAULT NULL COMMENT '闲管家详情回传运单号 waybill_no',
|
||||
detail_express_code varchar(64) DEFAULT NULL COMMENT '详情快递编码 express_code',
|
||||
detail_express_name varchar(128) DEFAULT NULL COMMENT '详情快递名称 express_name',
|
||||
receiver_name varchar(128) DEFAULT NULL COMMENT '收货人(详情有则落库)',
|
||||
receiver_mobile varchar(64) DEFAULT NULL COMMENT '收货手机',
|
||||
receiver_address varchar(1000) DEFAULT NULL COMMENT '收货详细地址(address)',
|
||||
receiver_region varchar(256) DEFAULT NULL COMMENT '省市区街道等拼接展示',
|
||||
recv_prov_name varchar(64) DEFAULT NULL COMMENT 'prov_name',
|
||||
recv_city_name varchar(64) DEFAULT NULL COMMENT 'city_name',
|
||||
recv_area_name varchar(64) DEFAULT NULL COMMENT 'area_name',
|
||||
recv_town_name varchar(128) DEFAULT NULL COMMENT 'town_name',
|
||||
detail_json longtext COMMENT '订单详情接口全量 JSON',
|
||||
last_notify_json longtext COMMENT '最近一次推送原文 JSON',
|
||||
jd_order_id bigint(20) DEFAULT NULL COMMENT '关联 jd_order.id(第三方单号=闲鱼单号)',
|
||||
@@ -61,3 +76,22 @@ CREATE TABLE IF NOT EXISTS erp_goofish_order (
|
||||
-- 按钮权限示例:
|
||||
-- jarvis:erpOpenConfig:list,query,add,edit,remove
|
||||
-- jarvis:erpGoofishOrder:list,query,edit
|
||||
|
||||
-- —— 已建表升级:详情摘要字段(若列已存在会报错,可逐条执行并忽略)——
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN goods_title varchar(512) NULL COMMENT '商品标题' AFTER item_id;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN goods_image_url varchar(1024) NULL COMMENT '商品主图URL' AFTER goods_title;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN buyer_nick varchar(256) NULL COMMENT '买家昵称' AFTER goods_image_url;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN pay_amount bigint(20) NULL COMMENT '实付金额(分)' AFTER buyer_nick;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN detail_waybill_no varchar(128) NULL COMMENT '详情运单号' AFTER pay_amount;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN detail_express_code varchar(64) NULL COMMENT '详情快递编码' AFTER detail_waybill_no;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN detail_express_name varchar(128) NULL COMMENT '详情快递名称' AFTER detail_express_code;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN receiver_name varchar(128) NULL COMMENT '收货人' AFTER detail_express_name;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN receiver_mobile varchar(64) NULL COMMENT '收货手机' AFTER receiver_name;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN receiver_address varchar(1000) NULL COMMENT '收货地址' AFTER receiver_mobile;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN receiver_region varchar(256) NULL COMMENT '省市区' AFTER receiver_address;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN recv_prov_name varchar(64) NULL COMMENT 'prov_name' AFTER receiver_region;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN recv_city_name varchar(64) NULL COMMENT 'city_name' AFTER recv_prov_name;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN recv_area_name varchar(64) NULL COMMENT 'area_name' AFTER recv_city_name;
|
||||
-- ALTER TABLE erp_goofish_order ADD COLUMN recv_town_name varchar(128) NULL COMMENT 'town_name' AFTER recv_area_name;
|
||||
|
||||
-- 已建库一键升级(可重复执行、自动判存):请使用同目录 erp_goofish_upgrade.sql
|
||||
|
||||
195
ruoyi-admin/src/main/resources/sql/erp_goofish_upgrade.sql
Normal file
195
ruoyi-admin/src/main/resources/sql/erp_goofish_upgrade.sql
Normal file
@@ -0,0 +1,195 @@
|
||||
-- =============================================================================
|
||||
-- 闲管家 ERP:erp_open_config / erp_goofish_order 一键升级脚本
|
||||
-- =============================================================================
|
||||
-- 用法:
|
||||
-- 1. 先备份数据库;连接目标库后执行(或在文件开头加 USE your_database;)
|
||||
-- 2. 可重复执行:已存在的列/索引会自动跳过
|
||||
-- 3. ADD COLUMN 一律不指定 AFTER,避免旧表缺中间列时升级失败(新列落在表尾,不影响业务)
|
||||
-- 环境:MySQL 5.7+ / 8.x(MariaDB 未逐项验证)
|
||||
-- =============================================================================
|
||||
|
||||
SET @schema := DATABASE();
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 1) 表不存在时创建完整结构(与 erp_goofish_init.sql 一致)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS erp_open_config (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
app_key varchar(64) NOT NULL COMMENT '开放平台 AppKey(appid)',
|
||||
app_secret varchar(128) NOT NULL COMMENT '开放平台 AppSecret',
|
||||
xy_user_name varchar(128) DEFAULT NULL COMMENT '默认闲鱼会员名(展示)',
|
||||
express_code varchar(64) DEFAULT NULL COMMENT '发货用快递公司编码(日日顺物流在官方列表中为 rrs)',
|
||||
express_name varchar(64) DEFAULT NULL COMMENT '快递公司名称(展示)',
|
||||
status char(1) NOT NULL DEFAULT '0' COMMENT '0正常 1停用',
|
||||
order_num int(11) NOT NULL DEFAULT 0 COMMENT '排序(小优先)',
|
||||
create_by varchar(64) DEFAULT '',
|
||||
create_time datetime DEFAULT NULL,
|
||||
update_by varchar(64) DEFAULT '',
|
||||
update_time datetime DEFAULT NULL,
|
||||
remark varchar(500) DEFAULT NULL COMMENT '备注',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_app_key (app_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='闲管家开放平台应用配置';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS erp_goofish_order (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
app_key varchar(64) NOT NULL COMMENT 'AppKey',
|
||||
seller_id bigint(20) DEFAULT NULL COMMENT '商家ID',
|
||||
user_name varchar(128) DEFAULT NULL COMMENT '闲鱼会员名',
|
||||
order_no varchar(64) NOT NULL COMMENT '闲鱼订单号',
|
||||
order_type int(11) DEFAULT NULL COMMENT '订单类型',
|
||||
order_status int(11) DEFAULT NULL COMMENT '订单状态(推送/列表)',
|
||||
refund_status int(11) DEFAULT NULL COMMENT '退款状态',
|
||||
modify_time bigint(20) DEFAULT NULL COMMENT '订单更新时间(秒)',
|
||||
product_id bigint(20) DEFAULT NULL COMMENT '管家商品ID',
|
||||
item_id bigint(20) DEFAULT NULL COMMENT '闲鱼商品ID',
|
||||
goods_title varchar(512) DEFAULT NULL COMMENT '商品标题(详情 goods.title)',
|
||||
goods_image_url varchar(1024) DEFAULT NULL COMMENT '商品主图 URL(goods.images 首图)',
|
||||
buyer_nick varchar(256) DEFAULT NULL COMMENT '买家昵称(详情 buyer_nick)',
|
||||
pay_amount bigint(20) DEFAULT NULL COMMENT '实付金额(分) pay_amount',
|
||||
detail_waybill_no varchar(128) DEFAULT NULL COMMENT '闲管家详情回传运单号 waybill_no',
|
||||
detail_express_code varchar(64) DEFAULT NULL COMMENT '详情快递编码 express_code',
|
||||
detail_express_name varchar(128) DEFAULT NULL COMMENT '详情快递名称 express_name',
|
||||
receiver_name varchar(128) DEFAULT NULL COMMENT '收货人(详情有则落库)',
|
||||
receiver_mobile varchar(64) DEFAULT NULL COMMENT '收货手机',
|
||||
receiver_address varchar(1000) DEFAULT NULL COMMENT '收货详细地址(address)',
|
||||
receiver_region varchar(256) DEFAULT NULL COMMENT '省市区街道等拼接展示',
|
||||
recv_prov_name varchar(64) DEFAULT NULL COMMENT 'prov_name',
|
||||
recv_city_name varchar(64) DEFAULT NULL COMMENT 'city_name',
|
||||
recv_area_name varchar(64) DEFAULT NULL COMMENT 'area_name',
|
||||
recv_town_name varchar(128) DEFAULT NULL COMMENT 'town_name',
|
||||
detail_json longtext COMMENT '订单详情接口全量 JSON',
|
||||
last_notify_json longtext COMMENT '最近一次推送原文 JSON',
|
||||
jd_order_id bigint(20) DEFAULT NULL COMMENT '关联 jd_order.id(第三方单号=闲鱼单号)',
|
||||
local_waybill_no varchar(128) DEFAULT NULL COMMENT '本地物流扫描得到的运单号',
|
||||
ship_status tinyint(4) NOT NULL DEFAULT '0' COMMENT '0未发货 1已调用发货成功 2发货失败',
|
||||
ship_error varchar(500) DEFAULT NULL COMMENT '发货失败原因',
|
||||
ship_time datetime DEFAULT NULL COMMENT '发货调用成功时间',
|
||||
ship_express_code varchar(64) DEFAULT NULL COMMENT '实际发货使用的快递编码',
|
||||
create_time datetime DEFAULT NULL,
|
||||
update_time datetime DEFAULT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_app_order (app_key, order_no),
|
||||
KEY idx_jd_order (jd_order_id),
|
||||
KEY idx_order_status (order_status),
|
||||
KEY idx_modify_time (modify_time)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='闲管家 ERP 订单(全量跟踪)';
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 2) 存储过程:列不存在则 ADD
|
||||
-- -----------------------------------------------------------------------------
|
||||
DROP PROCEDURE IF EXISTS jarvis_erp_goofish_add_column;
|
||||
DROP PROCEDURE IF EXISTS jarvis_erp_goofish_add_index;
|
||||
|
||||
DELIMITER $$
|
||||
|
||||
CREATE PROCEDURE jarvis_erp_goofish_add_column(
|
||||
IN p_table VARCHAR(64),
|
||||
IN p_column VARCHAR(64),
|
||||
IN p_ddl TEXT
|
||||
)
|
||||
BEGIN
|
||||
DECLARE col_exists INT DEFAULT 0;
|
||||
SELECT COUNT(*) INTO col_exists
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @schema
|
||||
AND TABLE_NAME = p_table
|
||||
AND COLUMN_NAME = p_column;
|
||||
IF col_exists = 0 THEN
|
||||
SET @stmt := CONCAT('ALTER TABLE `', p_table, '` ADD COLUMN `', p_column, '` ', p_ddl);
|
||||
PREPARE ps FROM @stmt;
|
||||
EXECUTE ps;
|
||||
DEALLOCATE PREPARE ps;
|
||||
END IF;
|
||||
END$$
|
||||
|
||||
CREATE PROCEDURE jarvis_erp_goofish_add_index(
|
||||
IN p_table VARCHAR(64),
|
||||
IN p_index VARCHAR(64),
|
||||
IN p_columns VARCHAR(200)
|
||||
)
|
||||
BEGIN
|
||||
DECLARE idx_exists INT DEFAULT 0;
|
||||
SELECT COUNT(*) INTO idx_exists
|
||||
FROM information_schema.statistics
|
||||
WHERE TABLE_SCHEMA = @schema
|
||||
AND TABLE_NAME = p_table
|
||||
AND INDEX_NAME = p_index;
|
||||
IF idx_exists = 0 THEN
|
||||
SET @stmt := CONCAT('ALTER TABLE `', p_table, '` ADD INDEX `', p_index, '` (', p_columns, ')');
|
||||
PREPARE ps FROM @stmt;
|
||||
EXECUTE ps;
|
||||
DEALLOCATE PREPARE ps;
|
||||
END IF;
|
||||
END$$
|
||||
|
||||
DELIMITER ;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 3) erp_goofish_order:补齐缺列(与当前 Java 实体 / erp_goofish_init.sql 一致)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'seller_id', 'bigint(20) NULL COMMENT ''商家ID''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'user_name', 'varchar(128) NULL COMMENT ''闲鱼会员名''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'order_type', 'int(11) NULL COMMENT ''订单类型''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'order_status', 'int(11) NULL COMMENT ''订单状态(推送/列表)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'refund_status', 'int(11) NULL COMMENT ''退款状态''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'modify_time', 'bigint(20) NULL COMMENT ''订单更新时间(秒)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'product_id', 'bigint(20) NULL COMMENT ''管家商品ID''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'item_id', 'bigint(20) NULL COMMENT ''闲鱼商品ID''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'goods_title', 'varchar(512) NULL COMMENT ''商品标题(详情 goods.title)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'goods_image_url', 'varchar(1024) NULL COMMENT ''商品主图 URL(goods.images 首图)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'buyer_nick', 'varchar(256) NULL COMMENT ''买家昵称(详情 buyer_nick)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'pay_amount', 'bigint(20) NULL COMMENT ''实付金额(分) pay_amount''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'detail_waybill_no', 'varchar(128) NULL COMMENT ''闲管家详情回传运单号 waybill_no''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'detail_express_code', 'varchar(64) NULL COMMENT ''详情快递编码 express_code''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'detail_express_name', 'varchar(128) NULL COMMENT ''详情快递名称 express_name''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'receiver_name', 'varchar(128) NULL COMMENT ''收货人(详情有则落库)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'receiver_mobile', 'varchar(64) NULL COMMENT ''收货手机''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'receiver_address', 'varchar(1000) NULL COMMENT ''收货详细地址(address)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'receiver_region', 'varchar(256) NULL COMMENT ''省市区街道等拼接展示''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'recv_prov_name', 'varchar(64) NULL COMMENT ''prov_name''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'recv_city_name', 'varchar(64) NULL COMMENT ''city_name''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'recv_area_name', 'varchar(64) NULL COMMENT ''area_name''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'recv_town_name', 'varchar(128) NULL COMMENT ''town_name''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'detail_json', 'longtext NULL COMMENT ''订单详情接口全量 JSON''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'last_notify_json', 'longtext NULL COMMENT ''最近一次推送原文 JSON''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'jd_order_id', 'bigint(20) NULL COMMENT ''关联 jd_order.id(第三方单号=闲鱼单号)''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'local_waybill_no', 'varchar(128) NULL COMMENT ''本地物流扫描得到的运单号''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'ship_status', 'tinyint(4) NOT NULL DEFAULT 0 COMMENT ''0未发货 1已调用发货成功 2发货失败''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'ship_error', 'varchar(500) NULL COMMENT ''发货失败原因''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'ship_time', 'datetime NULL COMMENT ''发货调用成功时间''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'ship_express_code', 'varchar(64) NULL COMMENT ''实际发货使用的快递编码''');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'create_time', 'datetime NULL');
|
||||
CALL jarvis_erp_goofish_add_column('erp_goofish_order', 'update_time', 'datetime NULL');
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 4) 索引(手工建表可能缺)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CALL jarvis_erp_goofish_add_index('erp_goofish_order', 'idx_jd_order', '`jd_order_id`');
|
||||
CALL jarvis_erp_goofish_add_index('erp_goofish_order', 'idx_order_status', '`order_status`');
|
||||
CALL jarvis_erp_goofish_add_index('erp_goofish_order', 'idx_modify_time', '`modify_time`');
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 5) 唯一键 uk_app_order
|
||||
-- 若已存在同名约束则跳过;若 (app_key,order_no) 有重复行会报错,需先清洗数据。
|
||||
-- 若已通过其它名称建了 (app_key,order_no) 唯一索引,请勿重复执行本节(可能报 Duplicate key)。
|
||||
-- -----------------------------------------------------------------------------
|
||||
SET @uk := (
|
||||
SELECT COUNT(*) FROM information_schema.table_constraints
|
||||
WHERE table_schema = @schema AND table_name = 'erp_goofish_order'
|
||||
AND constraint_name = 'uk_app_order' AND constraint_type = 'UNIQUE'
|
||||
);
|
||||
SET @sql_uk := IF(@uk = 0,
|
||||
'ALTER TABLE erp_goofish_order ADD UNIQUE KEY uk_app_order (app_key, order_no)',
|
||||
'SELECT ''uk_app_order 已存在,跳过'' AS note');
|
||||
PREPARE puk FROM @sql_uk;
|
||||
EXECUTE puk;
|
||||
DEALLOCATE PREPARE puk;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 6) 清理存储过程
|
||||
-- -----------------------------------------------------------------------------
|
||||
DROP PROCEDURE IF EXISTS jarvis_erp_goofish_add_column;
|
||||
DROP PROCEDURE IF EXISTS jarvis_erp_goofish_add_index;
|
||||
|
||||
SELECT 'erp_goofish_upgrade.sql 执行结束' AS message;
|
||||
@@ -17,7 +17,7 @@ public class JarvisGoofishProperties {
|
||||
|
||||
private String consumerGroup = "jarvis-goofish-order-consumer";
|
||||
|
||||
/** 回溯拉单小时数 */
|
||||
/** 回溯拉单小时数(定时/增量) */
|
||||
private int pullLookbackHours = 72;
|
||||
|
||||
/** 拉单定时 cron */
|
||||
@@ -26,8 +26,25 @@ public class JarvisGoofishProperties {
|
||||
/** 同步运单 + 自动发货 cron */
|
||||
private String autoShipCron = "0 2/10 * * * ?";
|
||||
|
||||
/** 单次拉单每店最大页数防护 */
|
||||
private int pullMaxPagesPerShop = 30;
|
||||
/**
|
||||
* 订单列表 page_size(开放平台最大 100)
|
||||
*/
|
||||
private int pullPageSize = 100;
|
||||
|
||||
/**
|
||||
* 单次拉单每授权最大页数(开放平台 page_no 最大 100;page_no×page_size 勿超过 10000)
|
||||
*/
|
||||
private int pullMaxPagesPerShop = 100;
|
||||
|
||||
/**
|
||||
* 全量/长历史拉单时,按 update_time 切片的窗口长度(秒),避免单窗内订单量过大触发平台限制
|
||||
*/
|
||||
private int pullTimeChunkSeconds = 604800;
|
||||
|
||||
/**
|
||||
* 全量拉单从「当前时间」往前推多少天作为起点(仅 full 接口;可自行改大)
|
||||
*/
|
||||
private int pullFullHistoryDays = 1095;
|
||||
|
||||
private int autoShipBatchSize = 20;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,27 @@ public class ErpGoofishOrder {
|
||||
private Long modifyTime;
|
||||
private Long productId;
|
||||
private Long itemId;
|
||||
/** 详情 goods.title */
|
||||
private String goodsTitle;
|
||||
/** goods.images 首张或其它单图字段 */
|
||||
private String goodsImageUrl;
|
||||
private String buyerNick;
|
||||
/** 开放平台 pay_amount,单位:分 */
|
||||
private Long payAmount;
|
||||
/** 闲管家详情 waybill_no */
|
||||
private String detailWaybillNo;
|
||||
private String detailExpressCode;
|
||||
private String detailExpressName;
|
||||
private String receiverName;
|
||||
private String receiverMobile;
|
||||
private String receiverAddress;
|
||||
/** 省市区拼接 */
|
||||
private String receiverRegion;
|
||||
/** 待发货等状态下开放平台返回的分级地址(与 prov_name/city_name/area_name/town_name 一致) */
|
||||
private String recvProvName;
|
||||
private String recvCityName;
|
||||
private String recvAreaName;
|
||||
private String recvTownName;
|
||||
private String detailJson;
|
||||
private String lastNotifyJson;
|
||||
private Long jdOrderId;
|
||||
@@ -41,4 +62,6 @@ public class ErpGoofishOrder {
|
||||
private String jdThirdPartyOrderNo;
|
||||
/** 联查:内部备注单号 */
|
||||
private String jdRemark;
|
||||
/** 联查:本地京东单收件地址 jd_order.address(闲鱼详情常不返回明文地址) */
|
||||
private String jdAddress;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,11 @@ public interface IErpGoofishOrderService {
|
||||
|
||||
int pullAllEnabled(int lookbackHours);
|
||||
|
||||
/** 按配置的起始天数 + 时间分段,尽量拉全历史订单(update_time) */
|
||||
int pullOrdersForAppKeyFullHistory(String appKey);
|
||||
|
||||
int pullAllEnabledFullHistory();
|
||||
|
||||
void refreshDetail(Long id);
|
||||
|
||||
void retryShip(Long id);
|
||||
|
||||
@@ -53,6 +53,7 @@ public class GoofishOrderPipeline {
|
||||
try {
|
||||
ErpGoofishOrder row = upsertFromNotify(appid, notifyBody, notifyBody.toJSONString());
|
||||
tryLinkJdOrder(row);
|
||||
mergeSummaryFromOrderDetailShape(row, notifyBody);
|
||||
refreshDetail(row);
|
||||
syncWaybillFromRedis(row);
|
||||
tryAutoShip(row);
|
||||
@@ -67,6 +68,7 @@ public class GoofishOrderPipeline {
|
||||
}
|
||||
ErpGoofishOrder row = upsertFromNotify(appKey, item, lastNotifyJson);
|
||||
tryLinkJdOrder(row);
|
||||
mergeSummaryFromOrderDetailShape(row, item);
|
||||
refreshDetail(row);
|
||||
syncWaybillFromRedis(row);
|
||||
tryAutoShip(row);
|
||||
@@ -151,7 +153,7 @@ public class GoofishOrderPipeline {
|
||||
if (jo != null && jo.getIntValue("code") == 0) {
|
||||
JSONObject data = jo.getJSONObject("data");
|
||||
if (data != null) {
|
||||
mergeSummaryFromDetail(row, data);
|
||||
mergeSummaryFromOrderDetailShape(row, data);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
@@ -159,34 +161,212 @@ public class GoofishOrderPipeline {
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeSummaryFromDetail(ErpGoofishOrder row, JSONObject data) {
|
||||
/**
|
||||
* 合并「订单详情 / 订单列表 / 推送」等同一 schema(order_detail)上的展示与发货摘要字段。
|
||||
* 列表与推送含 prov_name、city_name、area_name、town_name、address,详情接口常不含明文地址。
|
||||
*/
|
||||
private void mergeSummaryFromOrderDetailShape(ErpGoofishOrder row, JSONObject data) {
|
||||
if (row == null || row.getId() == null || data == null) {
|
||||
return;
|
||||
}
|
||||
ErpGoofishOrder patch = new ErpGoofishOrder();
|
||||
patch.setId(row.getId());
|
||||
boolean any = false;
|
||||
JSONObject goods = data.getJSONObject("goods");
|
||||
if (goods != null) {
|
||||
String title = goods.getString("title");
|
||||
if (StringUtils.isNotEmpty(title)) {
|
||||
patch.setGoodsTitle(title.trim());
|
||||
}
|
||||
String cover = firstGoodsCoverUrl(goods);
|
||||
if (StringUtils.isNotEmpty(cover)) {
|
||||
patch.setGoodsImageUrl(cover);
|
||||
}
|
||||
Long gPid = goods.getLong("product_id");
|
||||
if (gPid != null) {
|
||||
patch.setProductId(gPid);
|
||||
}
|
||||
Long gIid = goods.getLong("item_id");
|
||||
if (gIid != null) {
|
||||
patch.setItemId(gIid);
|
||||
}
|
||||
}
|
||||
String wb = data.getString("waybill_no");
|
||||
if (StringUtils.isNotEmpty(wb)) {
|
||||
patch.setDetailWaybillNo(wb.trim());
|
||||
}
|
||||
String dec = data.getString("express_code");
|
||||
if (StringUtils.isNotEmpty(dec)) {
|
||||
patch.setDetailExpressCode(dec.trim());
|
||||
}
|
||||
String den = data.getString("express_name");
|
||||
if (StringUtils.isNotEmpty(den)) {
|
||||
patch.setDetailExpressName(den.trim());
|
||||
}
|
||||
String bn = data.getString("buyer_nick");
|
||||
if (StringUtils.isNotEmpty(bn)) {
|
||||
patch.setBuyerNick(bn.trim());
|
||||
}
|
||||
Long payFen = data.getLong("pay_amount");
|
||||
if (payFen != null) {
|
||||
patch.setPayAmount(payFen);
|
||||
}
|
||||
String seller = data.getString("seller_name");
|
||||
if (StringUtils.isEmpty(row.getUserName()) && StringUtils.isNotEmpty(seller)) {
|
||||
patch.setUserName(seller.trim());
|
||||
}
|
||||
patch.setReceiverName(firstNonEmpty(data, "receiver_name", "ship_name", "consignee_name", "contact_name"));
|
||||
patch.setReceiverMobile(firstNonEmpty(data, "receiver_mobile", "ship_mobile", "receiver_phone", "contact_mobile"));
|
||||
patch.setReceiverAddress(firstNonEmpty(data, "receiver_address", "ship_address", "detail_address",
|
||||
"full_address", "address"));
|
||||
String prov = firstNonEmpty(data, "receiver_province", "ship_prov_name", "prov", "prov_name");
|
||||
String city = firstNonEmpty(data, "receiver_city", "ship_city_name", "city", "city_name");
|
||||
String area = firstNonEmpty(data, "receiver_district", "receiver_area", "ship_area_name", "district", "area_name");
|
||||
String town = firstNonEmpty(data, "town_name", "receiver_town", "ship_town_name", "street_name");
|
||||
String regionJoined = joinWithSpace(prov, city, area, town);
|
||||
if (StringUtils.isNotEmpty(regionJoined)) {
|
||||
patch.setReceiverRegion(regionJoined);
|
||||
}
|
||||
if (StringUtils.isNotEmpty(prov)) {
|
||||
patch.setRecvProvName(prov.trim());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(city)) {
|
||||
patch.setRecvCityName(city.trim());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(area)) {
|
||||
patch.setRecvAreaName(area.trim());
|
||||
}
|
||||
if (StringUtils.isNotEmpty(town)) {
|
||||
patch.setRecvTownName(town.trim());
|
||||
}
|
||||
JSONObject recv = data.getJSONObject("receiver");
|
||||
if (recv != null) {
|
||||
if (StringUtils.isEmpty(patch.getReceiverName())) {
|
||||
patch.setReceiverName(recv.getString("name"));
|
||||
}
|
||||
if (StringUtils.isEmpty(patch.getReceiverMobile())) {
|
||||
String m = recv.getString("mobile");
|
||||
if (StringUtils.isEmpty(m)) {
|
||||
m = recv.getString("phone");
|
||||
}
|
||||
patch.setReceiverMobile(m);
|
||||
}
|
||||
if (StringUtils.isEmpty(patch.getReceiverAddress())) {
|
||||
patch.setReceiverAddress(recv.getString("address"));
|
||||
}
|
||||
}
|
||||
Integer os = data.getInteger("order_status");
|
||||
if (os != null) {
|
||||
patch.setOrderStatus(os);
|
||||
row.setOrderStatus(os);
|
||||
any = true;
|
||||
}
|
||||
Integer rs = data.getInteger("refund_status");
|
||||
if (rs != null) {
|
||||
patch.setRefundStatus(rs);
|
||||
row.setRefundStatus(rs);
|
||||
any = true;
|
||||
}
|
||||
Long mt = data.getLong("modify_time");
|
||||
if (mt == null) {
|
||||
mt = data.getLong("order_modify_time");
|
||||
}
|
||||
if (mt == null) {
|
||||
mt = data.getLong("update_time");
|
||||
}
|
||||
if (mt != null) {
|
||||
patch.setModifyTime(mt);
|
||||
row.setModifyTime(mt);
|
||||
any = true;
|
||||
}
|
||||
if (any) {
|
||||
fillReceiverFromJdOrder(patch, row);
|
||||
patch.setUpdateTime(DateUtils.getNowDate());
|
||||
erpGoofishOrderMapper.update(patch);
|
||||
applySummaryPatchToRow(row, patch);
|
||||
}
|
||||
|
||||
/** 闲鱼详情常不返回明文地址:用已关联的 jd_order.address 兜底;平台已回收货人/分级地址时不覆盖姓名 */
|
||||
private void fillReceiverFromJdOrder(ErpGoofishOrder patch, ErpGoofishOrder row) {
|
||||
if (row.getJdOrderId() == null) {
|
||||
return;
|
||||
}
|
||||
boolean platformCare = StringUtils.isNotEmpty(patch.getReceiverName())
|
||||
|| StringUtils.isNotEmpty(patch.getReceiverMobile())
|
||||
|| StringUtils.isNotEmpty(patch.getRecvProvName())
|
||||
|| StringUtils.isNotEmpty(patch.getRecvCityName())
|
||||
|| StringUtils.isNotEmpty(patch.getRecvAreaName())
|
||||
|| StringUtils.isNotEmpty(patch.getRecvTownName());
|
||||
JDOrder jd = jdOrderService.selectJDOrderById(row.getJdOrderId());
|
||||
if (jd == null) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(patch.getReceiverAddress()) && StringUtils.isNotEmpty(jd.getAddress())) {
|
||||
patch.setReceiverAddress(jd.getAddress().trim());
|
||||
}
|
||||
if (platformCare) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(patch.getReceiverName()) && StringUtils.isNotEmpty(jd.getBuyer())) {
|
||||
patch.setReceiverName(jd.getBuyer().trim());
|
||||
}
|
||||
}
|
||||
|
||||
private void applySummaryPatchToRow(ErpGoofishOrder row, ErpGoofishOrder patch) {
|
||||
if (patch.getGoodsTitle() != null) {
|
||||
row.setGoodsTitle(patch.getGoodsTitle());
|
||||
}
|
||||
if (patch.getGoodsImageUrl() != null) {
|
||||
row.setGoodsImageUrl(patch.getGoodsImageUrl());
|
||||
}
|
||||
if (patch.getBuyerNick() != null) {
|
||||
row.setBuyerNick(patch.getBuyerNick());
|
||||
}
|
||||
if (patch.getPayAmount() != null) {
|
||||
row.setPayAmount(patch.getPayAmount());
|
||||
}
|
||||
if (patch.getDetailWaybillNo() != null) {
|
||||
row.setDetailWaybillNo(patch.getDetailWaybillNo());
|
||||
}
|
||||
if (patch.getDetailExpressCode() != null) {
|
||||
row.setDetailExpressCode(patch.getDetailExpressCode());
|
||||
}
|
||||
if (patch.getDetailExpressName() != null) {
|
||||
row.setDetailExpressName(patch.getDetailExpressName());
|
||||
}
|
||||
if (patch.getReceiverName() != null) {
|
||||
row.setReceiverName(patch.getReceiverName());
|
||||
}
|
||||
if (patch.getReceiverMobile() != null) {
|
||||
row.setReceiverMobile(patch.getReceiverMobile());
|
||||
}
|
||||
if (patch.getReceiverAddress() != null) {
|
||||
row.setReceiverAddress(patch.getReceiverAddress());
|
||||
}
|
||||
if (patch.getReceiverRegion() != null) {
|
||||
row.setReceiverRegion(patch.getReceiverRegion());
|
||||
}
|
||||
if (patch.getRecvProvName() != null) {
|
||||
row.setRecvProvName(patch.getRecvProvName());
|
||||
}
|
||||
if (patch.getRecvCityName() != null) {
|
||||
row.setRecvCityName(patch.getRecvCityName());
|
||||
}
|
||||
if (patch.getRecvAreaName() != null) {
|
||||
row.setRecvAreaName(patch.getRecvAreaName());
|
||||
}
|
||||
if (patch.getRecvTownName() != null) {
|
||||
row.setRecvTownName(patch.getRecvTownName());
|
||||
}
|
||||
if (patch.getUserName() != null) {
|
||||
row.setUserName(patch.getUserName());
|
||||
}
|
||||
if (patch.getOrderStatus() != null) {
|
||||
row.setOrderStatus(patch.getOrderStatus());
|
||||
}
|
||||
if (patch.getRefundStatus() != null) {
|
||||
row.setRefundStatus(patch.getRefundStatus());
|
||||
}
|
||||
if (patch.getModifyTime() != null) {
|
||||
row.setModifyTime(patch.getModifyTime());
|
||||
}
|
||||
if (patch.getProductId() != null) {
|
||||
row.setProductId(patch.getProductId());
|
||||
}
|
||||
if (patch.getItemId() != null) {
|
||||
row.setItemId(patch.getItemId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,7 +403,11 @@ public class GoofishOrderPipeline {
|
||||
if (row.getShipStatus() != null && row.getShipStatus() == 1) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(row.getLocalWaybillNo())) {
|
||||
String waybill = row.getLocalWaybillNo();
|
||||
if (StringUtils.isEmpty(waybill)) {
|
||||
waybill = row.getDetailWaybillNo();
|
||||
}
|
||||
if (StringUtils.isEmpty(waybill)) {
|
||||
return;
|
||||
}
|
||||
ErpOpenConfig cfg = erpOpenConfigService.selectByAppKey(row.getAppKey());
|
||||
@@ -234,9 +418,27 @@ public class GoofishOrderPipeline {
|
||||
return;
|
||||
}
|
||||
ShipAddressParts addr = parseShipAddress(row.getDetailJson());
|
||||
if (addr == null || StringUtils.isEmpty(addr.shipName) || StringUtils.isEmpty(addr.shipMobile)
|
||||
if (addr == null) {
|
||||
addr = new ShipAddressParts();
|
||||
}
|
||||
enrichShipAddressFromJd(row, addr);
|
||||
if (StringUtils.isEmpty(addr.shipAddress)) {
|
||||
ShipAddressParts fromRow = receiverFieldsToShipParts(row);
|
||||
if (fromRow != null) {
|
||||
if (StringUtils.isEmpty(addr.shipName)) {
|
||||
addr.shipName = fromRow.shipName;
|
||||
}
|
||||
if (StringUtils.isEmpty(addr.shipMobile)) {
|
||||
addr.shipMobile = fromRow.shipMobile;
|
||||
}
|
||||
if (StringUtils.isEmpty(addr.shipAddress)) {
|
||||
addr.shipAddress = fromRow.shipAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(addr.shipName) || StringUtils.isEmpty(addr.shipMobile)
|
||||
|| StringUtils.isEmpty(addr.shipAddress)) {
|
||||
patchShipError(row, "详情中缺少收货人/手机/地址,请核对开放平台订单详情 JSON 字段");
|
||||
patchShipError(row, "缺少收货人/手机/地址:详情无字段时请关联京东单并维护地址,或等平台返回收货字段");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -258,7 +460,7 @@ public class GoofishOrderPipeline {
|
||||
if (StringUtils.isNotEmpty(addr.shipAreaName)) {
|
||||
ship.setShipAreaName(addr.shipAreaName);
|
||||
}
|
||||
ship.setWaybillNo(row.getLocalWaybillNo());
|
||||
ship.setWaybillNo(waybill.trim());
|
||||
ship.setExpressCode(expressCode);
|
||||
ship.setExpressName(expressName);
|
||||
String resp = ship.getResponseBody();
|
||||
@@ -308,6 +510,47 @@ public class GoofishOrderPipeline {
|
||||
String shipAreaName;
|
||||
}
|
||||
|
||||
private void enrichShipAddressFromJd(ErpGoofishOrder row, ShipAddressParts p) {
|
||||
if (row == null || p == null || row.getJdOrderId() == null) {
|
||||
return;
|
||||
}
|
||||
JDOrder jd = jdOrderService.selectJDOrderById(row.getJdOrderId());
|
||||
if (jd == null) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isEmpty(p.shipAddress) && StringUtils.isNotEmpty(jd.getAddress())) {
|
||||
p.shipAddress = jd.getAddress().trim();
|
||||
}
|
||||
if (StringUtils.isEmpty(p.shipName) && StringUtils.isNotEmpty(jd.getBuyer())) {
|
||||
p.shipName = jd.getBuyer().trim();
|
||||
}
|
||||
}
|
||||
|
||||
private ShipAddressParts receiverFieldsToShipParts(ErpGoofishOrder row) {
|
||||
if (row == null) {
|
||||
return null;
|
||||
}
|
||||
String regionLine = row.getReceiverRegion();
|
||||
if (StringUtils.isEmpty(regionLine)) {
|
||||
regionLine = joinWithSpace(row.getRecvProvName(), row.getRecvCityName(), row.getRecvAreaName(), row.getRecvTownName());
|
||||
}
|
||||
if (StringUtils.isEmpty(row.getReceiverAddress()) && StringUtils.isEmpty(regionLine)) {
|
||||
return null;
|
||||
}
|
||||
ShipAddressParts p = new ShipAddressParts();
|
||||
p.shipName = row.getReceiverName();
|
||||
p.shipMobile = row.getReceiverMobile();
|
||||
p.shipAddress = row.getReceiverAddress();
|
||||
if (StringUtils.isNotEmpty(regionLine)) {
|
||||
if (StringUtils.isNotEmpty(p.shipAddress)) {
|
||||
p.shipAddress = regionLine + " " + p.shipAddress;
|
||||
} else {
|
||||
p.shipAddress = regionLine;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
private ShipAddressParts parseShipAddress(String detailJson) {
|
||||
if (StringUtils.isEmpty(detailJson)) {
|
||||
return null;
|
||||
@@ -323,11 +566,15 @@ public class GoofishOrderPipeline {
|
||||
ShipAddressParts p = new ShipAddressParts();
|
||||
p.shipName = firstNonEmpty(data, "ship_name", "receiver_name", "consignee", "contact_name");
|
||||
p.shipMobile = firstNonEmpty(data, "ship_mobile", "receiver_mobile", "receiver_phone", "contact_mobile");
|
||||
p.shipAddress = firstNonEmpty(data, "ship_address", "receiver_address", "detail_address");
|
||||
p.shipAddress = firstNonEmpty(data, "ship_address", "receiver_address", "detail_address", "address");
|
||||
p.shipDistrictId = firstInt(data, "ship_district_id", "receiver_district_id");
|
||||
p.shipProvName = firstNonEmpty(data, "ship_prov_name", "receiver_province", "prov");
|
||||
p.shipCityName = firstNonEmpty(data, "ship_city_name", "receiver_city", "city");
|
||||
p.shipAreaName = firstNonEmpty(data, "ship_area_name", "receiver_area", "area", "district");
|
||||
p.shipProvName = firstNonEmpty(data, "ship_prov_name", "receiver_province", "prov", "prov_name");
|
||||
p.shipCityName = firstNonEmpty(data, "ship_city_name", "receiver_city", "city", "city_name");
|
||||
p.shipAreaName = firstNonEmpty(data, "ship_area_name", "receiver_area", "area", "district", "area_name");
|
||||
String shipTown = firstNonEmpty(data, "town_name", "ship_town_name", "receiver_town");
|
||||
if (StringUtils.isNotEmpty(shipTown) && StringUtils.isEmpty(p.shipAddress)) {
|
||||
p.shipAddress = shipTown;
|
||||
}
|
||||
JSONObject recv = data.getJSONObject("receiver");
|
||||
if (recv != null) {
|
||||
if (StringUtils.isEmpty(p.shipName)) {
|
||||
@@ -346,6 +593,43 @@ public class GoofishOrderPipeline {
|
||||
return p;
|
||||
}
|
||||
|
||||
/** 开放平台 goods.images 首元素,或其它常见单图字段 */
|
||||
private static String firstGoodsCoverUrl(JSONObject goods) {
|
||||
if (goods == null) {
|
||||
return null;
|
||||
}
|
||||
for (String k : new String[]{"image", "pic", "cover", "main_image", "img", "item_pic"}) {
|
||||
String v = goods.getString(k);
|
||||
if (StringUtils.isNotEmpty(v)) {
|
||||
return v.trim();
|
||||
}
|
||||
}
|
||||
JSONArray images = goods.getJSONArray("images");
|
||||
if (images == null || images.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Object first = images.get(0);
|
||||
if (first == null) {
|
||||
return null;
|
||||
}
|
||||
String u = first.toString().trim();
|
||||
return StringUtils.isNotEmpty(u) ? u : null;
|
||||
}
|
||||
|
||||
/** 省、市、区、街道等与列表接口 prov_name/city_name/area_name/town_name 对齐拼接 */
|
||||
private static String joinWithSpace(String... parts) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String p : parts) {
|
||||
if (StringUtils.isNotEmpty(p)) {
|
||||
if (sb.length() > 0) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(p.trim());
|
||||
}
|
||||
}
|
||||
return sb.length() == 0 ? null : sb.toString();
|
||||
}
|
||||
|
||||
private static String firstNonEmpty(JSONObject o, String... keys) {
|
||||
if (o == null) {
|
||||
return null;
|
||||
@@ -372,23 +656,76 @@ public class GoofishOrderPipeline {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 增量拉单:按 update_time ∈ [now−lookbackHours, now]
|
||||
*/
|
||||
public int pullForAppKey(String appKey, int lookbackHours) {
|
||||
if (StringUtils.isEmpty(appKey)) {
|
||||
return 0;
|
||||
}
|
||||
IERPAccount cred = erpAccountResolver.resolve(appKey);
|
||||
long now = System.currentTimeMillis() / 1000;
|
||||
long start = now - (long) lookbackHours * 3600L;
|
||||
return pullForAppKeyUpdateTimeRange(appKey, start, now);
|
||||
}
|
||||
|
||||
/**
|
||||
* 长历史全量:从「当前时间 − pullFullHistoryDays」起,按 pullTimeChunkSeconds 切 update_time 窗口逐段拉取;
|
||||
* 每段内 page_size、page_no 与开放平台上限对齐,降低 page_no×page_size 超 1 万的风险。
|
||||
*/
|
||||
public int pullForAppKeyFullHistory(String appKey) {
|
||||
if (StringUtils.isEmpty(appKey)) {
|
||||
return 0;
|
||||
}
|
||||
long now = System.currentTimeMillis() / 1000;
|
||||
int days = goofishProperties.getPullFullHistoryDays();
|
||||
if (days < 1) {
|
||||
days = 1;
|
||||
}
|
||||
long start = now - (long) days * 86400L;
|
||||
int chunk = goofishProperties.getPullTimeChunkSeconds();
|
||||
if (chunk < 3600) {
|
||||
chunk = 86400;
|
||||
}
|
||||
int total = 0;
|
||||
for (long t = start; t <= now; t += chunk) {
|
||||
long end = Math.min(t + chunk - 1, now);
|
||||
if (end < t) {
|
||||
break;
|
||||
}
|
||||
total += pullForAppKeyUpdateTimeRange(appKey, t, end);
|
||||
try {
|
||||
Thread.sleep(150);
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按开放平台「订单列表」接口,限定 update_time 时间戳区间(秒,闭区间)拉取并落库。
|
||||
*/
|
||||
public int pullForAppKeyUpdateTimeRange(String appKey, long updateTimeStartSec, long updateTimeEndSec) {
|
||||
if (StringUtils.isEmpty(appKey) || updateTimeEndSec < updateTimeStartSec) {
|
||||
return 0;
|
||||
}
|
||||
IERPAccount cred = erpAccountResolver.resolve(appKey);
|
||||
List<Long> authorizeIds = fetchAuthorizeIds(cred);
|
||||
int pageSize = Math.min(100, Math.max(1, goofishProperties.getPullPageSize()));
|
||||
int maxPages = Math.min(100, Math.max(1, goofishProperties.getPullMaxPagesPerShop()));
|
||||
if ((long) maxPages * pageSize > 10000L) {
|
||||
maxPages = 10000 / pageSize;
|
||||
log.warn("闲管家拉单: pull-max-pages 与 pull-page-size 乘积超过 10000,已收敛 maxPages={}", maxPages);
|
||||
}
|
||||
int saved = 0;
|
||||
int maxPages = goofishProperties.getPullMaxPagesPerShop();
|
||||
for (Long aid : authorizeIds) {
|
||||
int page = 1;
|
||||
while (page <= maxPages) {
|
||||
OrderListQueryRequest q = new OrderListQueryRequest(cred);
|
||||
q.setAuthorizeId(aid);
|
||||
q.setUpdateTime(start, now);
|
||||
q.setPage(page, 20);
|
||||
q.setUpdateTime(updateTimeStartSec, updateTimeEndSec);
|
||||
q.setPage(page, pageSize);
|
||||
String resp;
|
||||
try {
|
||||
resp = q.getResponseBody();
|
||||
@@ -411,7 +748,12 @@ public class GoofishOrderPipeline {
|
||||
applyListOrNotifyItem(appKey, item, item.toJSONString());
|
||||
saved++;
|
||||
}
|
||||
if (list.size() < 20) {
|
||||
if (list.size() < pageSize) {
|
||||
break;
|
||||
}
|
||||
if (page == maxPages) {
|
||||
log.warn("闲管家拉单已达最大页数 appKey={} aid={} 区间[{},{}];若订单更多请缩小 pull-time-chunk-seconds",
|
||||
appKey, aid, updateTimeStartSec, updateTimeEndSec);
|
||||
break;
|
||||
}
|
||||
page++;
|
||||
|
||||
@@ -90,6 +90,27 @@ public class ErpGoofishOrderServiceImpl implements IErpGoofishOrderService {
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int pullOrdersForAppKeyFullHistory(String appKey) {
|
||||
return goofishOrderPipeline.pullForAppKeyFullHistory(appKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int pullAllEnabledFullHistory() {
|
||||
int total = 0;
|
||||
List<ErpOpenConfig> cfgs = erpOpenConfigService.selectEnabledOrderBySort();
|
||||
if (cfgs == null) {
|
||||
return 0;
|
||||
}
|
||||
for (ErpOpenConfig c : cfgs) {
|
||||
if (c.getAppKey() == null) {
|
||||
continue;
|
||||
}
|
||||
total += goofishOrderPipeline.pullForAppKeyFullHistory(c.getAppKey());
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshDetail(Long id) {
|
||||
ErpGoofishOrder row = erpGoofishOrderMapper.selectById(id);
|
||||
|
||||
@@ -14,6 +14,21 @@
|
||||
<result property="modifyTime" column="modify_time"/>
|
||||
<result property="productId" column="product_id"/>
|
||||
<result property="itemId" column="item_id"/>
|
||||
<result property="goodsTitle" column="goods_title"/>
|
||||
<result property="goodsImageUrl" column="goods_image_url"/>
|
||||
<result property="buyerNick" column="buyer_nick"/>
|
||||
<result property="payAmount" column="pay_amount"/>
|
||||
<result property="detailWaybillNo" column="detail_waybill_no"/>
|
||||
<result property="detailExpressCode" column="detail_express_code"/>
|
||||
<result property="detailExpressName" column="detail_express_name"/>
|
||||
<result property="receiverName" column="receiver_name"/>
|
||||
<result property="receiverMobile" column="receiver_mobile"/>
|
||||
<result property="receiverAddress" column="receiver_address"/>
|
||||
<result property="receiverRegion" column="receiver_region"/>
|
||||
<result property="recvProvName" column="recv_prov_name"/>
|
||||
<result property="recvCityName" column="recv_city_name"/>
|
||||
<result property="recvAreaName" column="recv_area_name"/>
|
||||
<result property="recvTownName" column="recv_town_name"/>
|
||||
<result property="detailJson" column="detail_json"/>
|
||||
<result property="lastNotifyJson" column="last_notify_json"/>
|
||||
<result property="jdOrderId" column="jd_order_id"/>
|
||||
@@ -26,13 +41,17 @@
|
||||
<result property="updateTime" column="update_time"/>
|
||||
<result property="jdThirdPartyOrderNo" column="jd_third_party_order_no"/>
|
||||
<result property="jdRemark" column="jd_remark"/>
|
||||
<result property="jdAddress" column="jd_address"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="selectJoinVo">
|
||||
select e.id, e.app_key, e.seller_id, e.user_name, e.order_no, e.order_type, e.order_status, e.refund_status,
|
||||
e.modify_time, e.product_id, e.item_id, e.detail_json, e.last_notify_json, e.jd_order_id, e.local_waybill_no,
|
||||
e.modify_time, e.product_id, e.item_id, e.goods_title, e.goods_image_url, e.buyer_nick, e.pay_amount, e.detail_waybill_no,
|
||||
e.detail_express_code, e.detail_express_name, e.receiver_name, e.receiver_mobile, e.receiver_address,
|
||||
e.receiver_region, e.recv_prov_name, e.recv_city_name, e.recv_area_name, e.recv_town_name,
|
||||
e.detail_json, e.last_notify_json, e.jd_order_id, e.local_waybill_no,
|
||||
e.ship_status, e.ship_error, e.ship_time, e.ship_express_code, e.create_time, e.update_time,
|
||||
o.third_party_order_no as jd_third_party_order_no, o.remark as jd_remark
|
||||
o.third_party_order_no as jd_third_party_order_no, o.remark as jd_remark, o.address as jd_address
|
||||
from erp_goofish_order e
|
||||
left join jd_order o on e.jd_order_id = o.id
|
||||
</sql>
|
||||
@@ -68,10 +87,16 @@
|
||||
<insert id="insert" parameterType="com.ruoyi.jarvis.domain.ErpGoofishOrder" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into erp_goofish_order
|
||||
(app_key, seller_id, user_name, order_no, order_type, order_status, refund_status, modify_time, product_id, item_id,
|
||||
goods_title, goods_image_url, buyer_nick, pay_amount, detail_waybill_no, detail_express_code, detail_express_name,
|
||||
receiver_name, receiver_mobile, receiver_address, receiver_region,
|
||||
recv_prov_name, recv_city_name, recv_area_name, recv_town_name,
|
||||
detail_json, last_notify_json, jd_order_id, local_waybill_no, ship_status, ship_error, ship_time, ship_express_code,
|
||||
create_time, update_time)
|
||||
values
|
||||
(#{appKey}, #{sellerId}, #{userName}, #{orderNo}, #{orderType}, #{orderStatus}, #{refundStatus}, #{modifyTime}, #{productId}, #{itemId},
|
||||
#{goodsTitle}, #{goodsImageUrl}, #{buyerNick}, #{payAmount}, #{detailWaybillNo}, #{detailExpressCode}, #{detailExpressName},
|
||||
#{receiverName}, #{receiverMobile}, #{receiverAddress}, #{receiverRegion},
|
||||
#{recvProvName}, #{recvCityName}, #{recvAreaName}, #{recvTownName},
|
||||
#{detailJson}, #{lastNotifyJson}, #{jdOrderId}, #{localWaybillNo}, #{shipStatus}, #{shipError}, #{shipTime}, #{shipExpressCode},
|
||||
#{createTime}, #{updateTime})
|
||||
</insert>
|
||||
@@ -87,6 +112,21 @@
|
||||
<if test="modifyTime != null">modify_time = #{modifyTime},</if>
|
||||
<if test="productId != null">product_id = #{productId},</if>
|
||||
<if test="itemId != null">item_id = #{itemId},</if>
|
||||
<if test="goodsTitle != null">goods_title = #{goodsTitle},</if>
|
||||
<if test="goodsImageUrl != null">goods_image_url = #{goodsImageUrl},</if>
|
||||
<if test="buyerNick != null">buyer_nick = #{buyerNick},</if>
|
||||
<if test="payAmount != null">pay_amount = #{payAmount},</if>
|
||||
<if test="detailWaybillNo != null">detail_waybill_no = #{detailWaybillNo},</if>
|
||||
<if test="detailExpressCode != null">detail_express_code = #{detailExpressCode},</if>
|
||||
<if test="detailExpressName != null">detail_express_name = #{detailExpressName},</if>
|
||||
<if test="receiverName != null">receiver_name = #{receiverName},</if>
|
||||
<if test="receiverMobile != null">receiver_mobile = #{receiverMobile},</if>
|
||||
<if test="receiverAddress != null">receiver_address = #{receiverAddress},</if>
|
||||
<if test="receiverRegion != null">receiver_region = #{receiverRegion},</if>
|
||||
<if test="recvProvName != null">recv_prov_name = #{recvProvName},</if>
|
||||
<if test="recvCityName != null">recv_city_name = #{recvCityName},</if>
|
||||
<if test="recvAreaName != null">recv_area_name = #{recvAreaName},</if>
|
||||
<if test="recvTownName != null">recv_town_name = #{recvTownName},</if>
|
||||
<if test="detailJson != null">detail_json = #{detailJson},</if>
|
||||
<if test="lastNotifyJson != null">last_notify_json = #{lastNotifyJson},</if>
|
||||
<if test="jdOrderId != null">jd_order_id = #{jdOrderId},</if>
|
||||
|
||||
Reference in New Issue
Block a user