1
This commit is contained in:
@@ -9,6 +9,7 @@ import com.ruoyi.jarvis.config.JarvisGoofishProperties;
|
|||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLog;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLog;
|
||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLogQuery;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLogQuery;
|
||||||
|
import com.ruoyi.jarvis.dto.GoofishShipPreviewVo;
|
||||||
import com.ruoyi.jarvis.service.IErpGoofishOrderService;
|
import com.ruoyi.jarvis.service.IErpGoofishOrderService;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -47,6 +48,13 @@ public class ErpGoofishOrderController extends BaseController {
|
|||||||
return getDataTable(list);
|
return getDataTable(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PreAuthorize("@ss.hasPermi('jarvis:erpGoofishOrder:query')")
|
||||||
|
@GetMapping("/shipPreview/{id}")
|
||||||
|
public AjaxResult shipPreview(@PathVariable Long id) {
|
||||||
|
GoofishShipPreviewVo vo = erpGoofishOrderService.shipPreview(id);
|
||||||
|
return AjaxResult.success(vo);
|
||||||
|
}
|
||||||
|
|
||||||
@PreAuthorize("@ss.hasPermi('jarvis:erpGoofishOrder:query')")
|
@PreAuthorize("@ss.hasPermi('jarvis:erpGoofishOrder:query')")
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public AjaxResult getInfo(@PathVariable Long id) {
|
public AjaxResult getInfo(@PathVariable Long id) {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.ruoyi.jarvis.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 闲管家订单发货预览:闲鱼订单侧收件信息 vs 拟提交开放平台发货参数(可含京东兜底)
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class GoofishShipPreviewVo {
|
||||||
|
|
||||||
|
private String orderNo;
|
||||||
|
|
||||||
|
/** 管家 goods.title(表或详情) */
|
||||||
|
private String goodsTitle;
|
||||||
|
|
||||||
|
/** 关联京东单的型号 */
|
||||||
|
private String jdModelNumber;
|
||||||
|
|
||||||
|
/** 关联京东单的整段收件地址快照 */
|
||||||
|
private String jdAddressFull;
|
||||||
|
|
||||||
|
/** 仅从闲鱼开放平台落库的收件人姓名 */
|
||||||
|
private String goofishOrderReceiverName;
|
||||||
|
|
||||||
|
private String goofishOrderReceiverMobile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 闲鱼订单侧完整收件串:省市区镇 + detail(与发货流水线中 receiverFieldsToShipParts 一致,不含京东)
|
||||||
|
*/
|
||||||
|
private String goofishOrderFullAddress;
|
||||||
|
|
||||||
|
/** 拟调用发货接口使用的收件人(可能由京东兜底补姓名) */
|
||||||
|
private String shipReceiverName;
|
||||||
|
|
||||||
|
private String shipReceiverMobile;
|
||||||
|
|
||||||
|
/** 拟提交的发货详情地址字符串 */
|
||||||
|
private String shipFullAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发货收件地址是否与「闲鱼订单侧」归一化后一致(订单侧任一字段为空时为 null)
|
||||||
|
*/
|
||||||
|
private Boolean receiverAddressMatchesGoofish;
|
||||||
|
|
||||||
|
/** 是否与京东整段地址归一化后一致(无视京东或未维护京东地址时为 null) */
|
||||||
|
private Boolean receiverAddressMatchesJd;
|
||||||
|
|
||||||
|
/** 简短说明比对结论或数据来源 */
|
||||||
|
private String compareHint;
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSONObject;
|
|||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLog;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLog;
|
||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLogQuery;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLogQuery;
|
||||||
|
import com.ruoyi.jarvis.dto.GoofishShipPreviewVo;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -31,6 +32,11 @@ public interface IErpGoofishOrderService {
|
|||||||
|
|
||||||
void refreshDetail(Long id);
|
void refreshDetail(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发货预览:闲鱼订单收件串 vs 即将提交开放平台地址(可与京东快照比对)。
|
||||||
|
*/
|
||||||
|
GoofishShipPreviewVo shipPreview(Long id);
|
||||||
|
|
||||||
void retryShip(Long id);
|
void retryShip(Long id);
|
||||||
|
|
||||||
int syncWaybillAndTryShipBatch(int limit);
|
int syncWaybillAndTryShipBatch(int limit);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.ruoyi.jarvis.config.JarvisGoofishProperties;
|
|||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
||||||
import com.ruoyi.jarvis.domain.ErpOpenConfig;
|
import com.ruoyi.jarvis.domain.ErpOpenConfig;
|
||||||
import com.ruoyi.jarvis.domain.JDOrder;
|
import com.ruoyi.jarvis.domain.JDOrder;
|
||||||
|
import com.ruoyi.jarvis.dto.GoofishShipPreviewVo;
|
||||||
import com.ruoyi.jarvis.mapper.ErpGoofishOrderMapper;
|
import com.ruoyi.jarvis.mapper.ErpGoofishOrderMapper;
|
||||||
import com.ruoyi.jarvis.service.IJDOrderService;
|
import com.ruoyi.jarvis.service.IJDOrderService;
|
||||||
import com.ruoyi.jarvis.service.IErpOpenConfigService;
|
import com.ruoyi.jarvis.service.IErpOpenConfigService;
|
||||||
@@ -310,6 +311,10 @@ public class GoofishOrderPipeline {
|
|||||||
patch.setReceiverAddress(recv.getString("address"));
|
patch.setReceiverAddress(recv.getString("address"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 开放平台常拆分为省市区 + 明文 detail;明细列为空时用行政区拼接兜底,便于列表与发货解析
|
||||||
|
if (StringUtils.isEmpty(patch.getReceiverAddress()) && StringUtils.isNotEmpty(regionJoined)) {
|
||||||
|
patch.setReceiverAddress(regionJoined.trim());
|
||||||
|
}
|
||||||
Integer os = firstInt(data, "order_status", "orderStatus");
|
Integer os = firstInt(data, "order_status", "orderStatus");
|
||||||
if (os != null) {
|
if (os != null) {
|
||||||
patch.setOrderStatus(os);
|
patch.setOrderStatus(os);
|
||||||
@@ -527,25 +532,7 @@ public class GoofishOrderPipeline {
|
|||||||
row.getAppKey(), row.getOrderNo());
|
row.getAppKey(), row.getOrderNo());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ShipAddressParts addr = parseShipAddress(row.getDetailJson());
|
ShipAddressParts addr = resolveShippingAddressParts(row);
|
||||||
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)
|
if (StringUtils.isEmpty(addr.shipName) || StringUtils.isEmpty(addr.shipMobile)
|
||||||
|| StringUtils.isEmpty(addr.shipAddress)) {
|
|| StringUtils.isEmpty(addr.shipAddress)) {
|
||||||
patchShipError(row, "缺少收货人/手机/地址:详情无字段时请关联京东单并维护地址,或等平台返回收货字段");
|
patchShipError(row, "缺少收货人/手机/地址:详情无字段时请关联京东单并维护地址,或等平台返回收货字段");
|
||||||
@@ -704,9 +691,6 @@ public class GoofishOrderPipeline {
|
|||||||
p.shipCityName = firstNonEmpty(data, "ship_city_name", "receiver_city", "city", "city_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");
|
p.shipAreaName = firstNonEmpty(data, "ship_area_name", "receiver_area", "area", "district", "area_name");
|
||||||
String shipTown = firstNonEmpty(data, "town_name", "ship_town_name", "receiver_town");
|
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");
|
JSONObject recv = data.getJSONObject("receiver");
|
||||||
if (recv != null) {
|
if (recv != null) {
|
||||||
if (StringUtils.isEmpty(p.shipName)) {
|
if (StringUtils.isEmpty(p.shipName)) {
|
||||||
@@ -722,9 +706,135 @@ public class GoofishOrderPipeline {
|
|||||||
p.shipAddress = recv.getString("address");
|
p.shipAddress = recv.getString("address");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mergeRegionIntoShipAddress(p, shipTown);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与列表/落库拆分字段对齐:开放平台若只给省市区镇 + detail,拼成单行供发货调用。
|
||||||
|
* 已在 detail 中包含省名开头或与整段行政区一致时不重复前缀。
|
||||||
|
*/
|
||||||
|
private static void mergeRegionIntoShipAddress(ShipAddressParts p, String shipTownName) {
|
||||||
|
if (p == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String regionLine = joinWithSpace(p.shipProvName, p.shipCityName, p.shipAreaName, shipTownName);
|
||||||
|
if (StringUtils.isEmpty(regionLine)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String detail = p.shipAddress;
|
||||||
|
if (StringUtils.isEmpty(detail)) {
|
||||||
|
p.shipAddress = regionLine;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
detail = detail.trim();
|
||||||
|
String prov = StringUtils.isNotEmpty(p.shipProvName) ? p.shipProvName.trim() : "";
|
||||||
|
if (StringUtils.isNotEmpty(prov) && detail.startsWith(prov)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (detail.length() >= regionLine.length() && detail.startsWith(regionLine.trim())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p.shipAddress = regionLine + " " + detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与 {@link #tryAutoShip(ErpGoofishOrder, boolean)} 对齐:detail_json → 京东兜底 → 列表/库字段补全。
|
||||||
|
*/
|
||||||
|
private ShipAddressParts resolveShippingAddressParts(ErpGoofishOrder row) {
|
||||||
|
ShipAddressParts addr = parseShipAddress(row != null ? row.getDetailJson() : null);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 管理端发货预览:闲鱼收件串 vs 实际将提交开放平台地址(可对齐运单回填前自检)。
|
||||||
|
*/
|
||||||
|
public GoofishShipPreviewVo buildShipPreview(ErpGoofishOrder row) {
|
||||||
|
GoofishShipPreviewVo vo = new GoofishShipPreviewVo();
|
||||||
|
if (row == null) {
|
||||||
|
vo.setCompareHint("订单不存在");
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
vo.setOrderNo(row.getOrderNo());
|
||||||
|
vo.setGoodsTitle(row.getGoodsTitle());
|
||||||
|
vo.setJdModelNumber(row.getJdModelNumber());
|
||||||
|
vo.setJdAddressFull(row.getJdAddress());
|
||||||
|
|
||||||
|
ShipAddressParts orderSide = receiverFieldsToShipParts(row);
|
||||||
|
if (orderSide != null) {
|
||||||
|
vo.setGoofishOrderReceiverName(orderSide.shipName);
|
||||||
|
vo.setGoofishOrderReceiverMobile(orderSide.shipMobile);
|
||||||
|
vo.setGoofishOrderFullAddress(orderSide.shipAddress != null ? orderSide.shipAddress.trim() : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
ShipAddressParts ship = resolveShippingAddressParts(row);
|
||||||
|
vo.setShipReceiverName(ship.shipName);
|
||||||
|
vo.setShipReceiverMobile(ship.shipMobile);
|
||||||
|
vo.setShipFullAddress(StringUtils.isNotEmpty(ship.shipAddress) ? ship.shipAddress.trim() : "");
|
||||||
|
|
||||||
|
String nGoofishAddr = normalizeAddrComparable(vo.getGoofishOrderFullAddress());
|
||||||
|
String nShipAddr = normalizeAddrComparable(vo.getShipFullAddress());
|
||||||
|
|
||||||
|
boolean goofishHasAddr = StringUtils.isNotEmpty(nGoofishAddr);
|
||||||
|
boolean goofishHasContact = StringUtils.isNotEmpty(vo.getGoofishOrderReceiverName())
|
||||||
|
|| StringUtils.isNotEmpty(vo.getGoofishOrderReceiverMobile());
|
||||||
|
vo.setReceiverAddressMatchesGoofish(goofishHasAddr ? Objects.equals(nGoofishAddr, nShipAddr) : null);
|
||||||
|
|
||||||
|
String nJd = normalizeAddrComparable(vo.getJdAddressFull());
|
||||||
|
boolean jdHasAddr = StringUtils.isNotEmpty(nJd);
|
||||||
|
vo.setReceiverAddressMatchesJd(jdHasAddr ? Objects.equals(nJd, nShipAddr) : null);
|
||||||
|
|
||||||
|
StringBuilder hint = new StringBuilder();
|
||||||
|
if (!goofishHasAddr && StringUtils.isNotEmpty(vo.getShipFullAddress())) {
|
||||||
|
hint.append("闲鱼侧未合并到收件地址文本,发货参数可能仅靠详情解析或京东补全");
|
||||||
|
}
|
||||||
|
if (jdHasAddr && Boolean.FALSE.equals(vo.getReceiverAddressMatchesJd())
|
||||||
|
&& StringUtils.isNotEmpty(vo.getShipFullAddress())) {
|
||||||
|
if (hint.length() > 0) {
|
||||||
|
hint.append(';');
|
||||||
|
}
|
||||||
|
hint.append("与京东单整段地址不完全一致(请核对)");
|
||||||
|
}
|
||||||
|
if (Boolean.FALSE.equals(vo.getReceiverAddressMatchesGoofish())
|
||||||
|
&& goofishHasAddr && StringUtils.isNotEmpty(vo.getShipFullAddress())) {
|
||||||
|
if (hint.length() > 0) {
|
||||||
|
hint.append(';');
|
||||||
|
}
|
||||||
|
hint.append("与闲鱼订单收件串不完全一致(可能已用京东补全或未刷新详情)");
|
||||||
|
}
|
||||||
|
if (hint.length() == 0) {
|
||||||
|
hint.append(goofishHasContact || goofishHasAddr ? "可对照下方两项文本核对收件信息" : "暂无闲鱼收件信息,请先刷新详情或关联京东单");
|
||||||
|
}
|
||||||
|
vo.setCompareHint(hint.toString());
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalizeAddrComparable(String addr) {
|
||||||
|
if (addr == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return addr.trim().replaceAll("\\s+", " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** 开放平台 goods.images 首元素,或其它常见单图字段 */
|
/** 开放平台 goods.images 首元素,或其它常见单图字段 */
|
||||||
private static String firstGoodsCoverUrl(JSONObject goods) {
|
private static String firstGoodsCoverUrl(JSONObject goods) {
|
||||||
if (goods == null) {
|
if (goods == null) {
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import com.ruoyi.jarvis.config.JarvisGoofishProperties;
|
|||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrder;
|
||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLog;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLog;
|
||||||
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLogQuery;
|
import com.ruoyi.jarvis.domain.ErpGoofishOrderEventLogQuery;
|
||||||
import com.ruoyi.jarvis.domain.ErpOpenConfig;
|
|
||||||
import com.ruoyi.jarvis.domain.JDOrder;
|
|
||||||
import com.ruoyi.jarvis.dto.GoofishNotifyMessage;
|
import com.ruoyi.jarvis.dto.GoofishNotifyMessage;
|
||||||
|
import com.ruoyi.jarvis.dto.GoofishShipPreviewVo;
|
||||||
import com.ruoyi.jarvis.mapper.ErpGoofishOrderEventLogMapper;
|
import com.ruoyi.jarvis.mapper.ErpGoofishOrderEventLogMapper;
|
||||||
import com.ruoyi.jarvis.mapper.ErpGoofishOrderMapper;
|
import com.ruoyi.jarvis.mapper.ErpGoofishOrderMapper;
|
||||||
import com.ruoyi.jarvis.service.IErpGoofishOrderService;
|
import com.ruoyi.jarvis.service.IErpGoofishOrderService;
|
||||||
@@ -142,6 +141,17 @@ public class ErpGoofishOrderServiceImpl implements IErpGoofishOrderService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GoofishShipPreviewVo shipPreview(Long id) {
|
||||||
|
ErpGoofishOrder row = erpGoofishOrderMapper.selectById(id);
|
||||||
|
if (row == null) {
|
||||||
|
GoofishShipPreviewVo empty = new GoofishShipPreviewVo();
|
||||||
|
empty.setCompareHint("订单不存在");
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
return goofishOrderPipeline.buildShipPreview(row);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void retryShip(Long id) {
|
public void retryShip(Long id) {
|
||||||
erpGoofishOrderMapper.resetShipForRetry(id);
|
erpGoofishOrderMapper.resetShipForRetry(id);
|
||||||
|
|||||||
Reference in New Issue
Block a user