Merge branch '0.8.X' of https://gitee.com/hdka/klp-oa into 0.8.X

This commit is contained in:
砂糖
2025-08-13 14:02:04 +08:00
14 changed files with 424 additions and 14 deletions

View File

@@ -56,5 +56,11 @@
<artifactId>kfpt-sdk</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.jd</groupId>
<artifactId>jd-sdk</artifactId>
<version>1.2.89</version>
<classifier>RELEASE</classifier>
</dependency>
</dependencies>
</project>

View File

@@ -80,5 +80,9 @@ public class WmsPayableVo {
@ExcelProperty(value = "备注")
private String remark;
/**
* 供应商名称
*/
@ExcelProperty(value = "供应商名称")
private String supplierName;
}

View File

@@ -80,5 +80,9 @@ public class WmsReceivableVo {
@ExcelProperty(value = "备注")
private String remark;
/**
* 客户名称
*/
@ExcelProperty(value = "客户名称")
private String customerName;
}

View File

@@ -4,6 +4,8 @@ import com.klp.domain.WmsJournal;
import com.klp.domain.vo.WmsJournalVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import java.math.BigDecimal;
/**
* 资金日记账Mapper接口
*
@@ -12,4 +14,8 @@ import com.klp.common.core.mapper.BaseMapperPlus;
*/
public interface WmsJournalMapper extends BaseMapperPlus<WmsJournalMapper, WmsJournal, WmsJournalVo> {
/**
* 获取最后一条记录的余额 (用于新增记录时计算余额)
*/
BigDecimal getLastBalance();
}

View File

@@ -1,8 +1,11 @@
package com.klp.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.domain.WmsPayable;
import com.klp.domain.vo.WmsPayableVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
/**
* 应付款管理宽松版Mapper接口
@@ -12,4 +15,5 @@ import com.klp.common.core.mapper.BaseMapperPlus;
*/
public interface WmsPayableMapper extends BaseMapperPlus<WmsPayableMapper, WmsPayable, WmsPayableVo> {
Page<WmsPayableVo> selectVoPagePlus(Page<Object> build, @Param("ew") QueryWrapper<WmsPayable> lqw);
}

View File

@@ -1,8 +1,11 @@
package com.klp.mapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.klp.domain.WmsReceivable;
import com.klp.domain.vo.WmsReceivableVo;
import com.klp.common.core.mapper.BaseMapperPlus;
import org.apache.ibatis.annotations.Param;
/**
* 应收款管理宽松版Mapper接口
@@ -12,4 +15,5 @@ import com.klp.common.core.mapper.BaseMapperPlus;
*/
public interface WmsReceivableMapper extends BaseMapperPlus<WmsReceivableMapper, WmsReceivable, WmsReceivableVo> {
Page<WmsReceivableVo> selectVoPagePlus(Page<Object> build, @Param("ew") QueryWrapper<WmsReceivable> lqw);
}

View File

@@ -238,6 +238,15 @@ public class WmsExpressServiceImpl implements IWmsExpressService {
WmsExpressVo.setLastStatus(stoVo.getFirstStatusName());
}
}
if (expressType.equals("SXJD") && WmsExpressVo.getStatus() == 1L) {
// 顺心捷达快递轨迹查询
String result = SxjdRouteQueryUtil.queryRoute(WmsExpressVo.getExpressCode());
WmsExpressVo sxjdVo = SxjdRouteQueryUtil.parseData(result);
if (sxjdVo != null) {
WmsExpressVo.setLastUpdateTime(sxjdVo.getLastUpdateTime());
WmsExpressVo.setLastStatus(sxjdVo.getLastStatus());
}
}
WmsExpress add = BeanUtil.toBean(WmsExpressVo, WmsExpress.class);
baseMapper.updateById(add);;
}

View File

@@ -15,9 +15,11 @@ import com.klp.domain.WmsJournal;
import com.klp.mapper.WmsJournalMapper;
import com.klp.service.IWmsJournalService;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Optional;
/**
* 资金日记账Service业务层处理
@@ -76,11 +78,21 @@ public class WmsJournalServiceImpl implements IWmsJournalService {
*/
@Override
public Boolean insertByBo(WmsJournalBo bo) {
WmsJournal add = BeanUtil.toBean(bo, WmsJournal.class);
validEntityBeforeSave(add);
boolean flag = baseMapper.insert(add) > 0;
WmsJournal journal = BeanUtil.toBean(bo, WmsJournal.class);
validEntityBeforeSave(journal);
// 计算新的余额
BigDecimal lastBalance = baseMapper.getLastBalance();
if (lastBalance == null) {
lastBalance = BigDecimal.ZERO;
}
BigDecimal newBalance = lastBalance
.add(Optional.ofNullable(journal.getIncomeAmount()).orElse(BigDecimal.ZERO))
.subtract(Optional.ofNullable(journal.getExpenseAmount()).orElse(BigDecimal.ZERO));
journal.setBalanceAmount(newBalance);
boolean flag = baseMapper.insert(journal) > 0;
if (flag) {
bo.setJournalId(add.getJournalId());
bo.setJournalId(journal.getJournalId());
}
return flag;
}

View File

@@ -1,6 +1,7 @@
package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -16,7 +17,6 @@ import com.klp.mapper.WmsPayableMapper;
import com.klp.service.IWmsPayableService;
import java.util.List;
import java.util.Map;
import java.util.Collection;
/**
@@ -44,11 +44,24 @@ public class WmsPayableServiceImpl implements IWmsPayableService {
*/
@Override
public TableDataInfo<WmsPayableVo> queryPageList(WmsPayableBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsPayable> lqw = buildQueryWrapper(bo);
Page<WmsPayableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
QueryWrapper<WmsPayable> lqw = buildQueryWrapperPlus(bo);
Page<WmsPayableVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
private QueryWrapper<WmsPayable> buildQueryWrapperPlus(WmsPayableBo bo) {
QueryWrapper<WmsPayable> lqw = Wrappers.query();
lqw.eq("p.del_flag", 0);
lqw.eq(bo.getSupplierId() != null, "p.supplier_id", bo.getSupplierId());
lqw.eq(bo.getOrderId() != null, "p.order_id", bo.getOrderId());
lqw.eq(bo.getDueDate() != null, "p.due_date", bo.getDueDate());
lqw.eq(bo.getAmount() != null, "p.amount", bo.getAmount());
lqw.eq(bo.getPaidAmount() != null, "p.paid_amount", bo.getPaidAmount());
lqw.eq(bo.getBalanceAmount() != null, "p.balance_amount", bo.getBalanceAmount());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), "p.status", bo.getStatus());
return lqw;
}
/**
* 查询应付款管理(宽松版)列表
*/
@@ -59,14 +72,13 @@ public class WmsPayableServiceImpl implements IWmsPayableService {
}
private LambdaQueryWrapper<WmsPayable> buildQueryWrapper(WmsPayableBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<WmsPayable> lqw = Wrappers.lambdaQuery();
lqw.eq(bo.getSupplierId() != null, WmsPayable::getSupplierId, bo.getSupplierId());
lqw.eq(bo.getOrderId() != null, WmsPayable::getOrderId, bo.getOrderId());
lqw.eq(bo.getDueDate() != null, WmsPayable::getDueDate, bo.getDueDate());
lqw.eq(bo.getSupplierId() != null, WmsPayable::getSupplierId, bo.getSupplierId());
lqw.eq(bo.getAmount() != null, WmsPayable::getAmount, bo.getAmount());
lqw.eq(bo.getPaidAmount() != null, WmsPayable::getPaidAmount, bo.getPaidAmount());
lqw.eq(bo.getBalanceAmount() != null, WmsPayable::getBalanceAmount, bo.getBalanceAmount());
lqw.eq(bo.getPaidAmount() != null, WmsPayable::getPaidAmount, bo.getPaidAmount());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), WmsPayable::getStatus, bo.getStatus());
return lqw;
}

View File

@@ -1,6 +1,7 @@
package com.klp.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.klp.common.core.page.TableDataInfo;
import com.klp.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -44,11 +45,24 @@ public class WmsReceivableServiceImpl implements IWmsReceivableService {
*/
@Override
public TableDataInfo<WmsReceivableVo> queryPageList(WmsReceivableBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<WmsReceivable> lqw = buildQueryWrapper(bo);
Page<WmsReceivableVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
QueryWrapper<WmsReceivable> lqw = buildQueryWrapperPlus(bo);
Page<WmsReceivableVo> result = baseMapper.selectVoPagePlus(pageQuery.build(), lqw);
return TableDataInfo.build(result);
}
private QueryWrapper<WmsReceivable> buildQueryWrapperPlus(WmsReceivableBo bo) {
QueryWrapper<WmsReceivable> lqw = Wrappers.query();
lqw.eq("r.del_flag", 0);
lqw.eq(bo.getCustomerId() != null, "r.customer_id", bo.getCustomerId());
lqw.eq(bo.getOrderId() != null, "r.order_id", bo.getOrderId());
lqw.eq(bo.getDueDate() != null, "r.due_date", bo.getDueDate());
lqw.eq(bo.getAmount() != null, "r.amount", bo.getAmount());
lqw.eq(bo.getPaidAmount() != null, "r.paid_amount", bo.getPaidAmount());
lqw.eq(bo.getBalanceAmount() != null, "r.balance_amount", bo.getBalanceAmount());
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), "r.status", bo.getStatus());
return lqw;
}
/**
* 查询应收款管理(宽松版)列表
*/

View File

@@ -0,0 +1,287 @@
package com.klp.utils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.klp.domain.vo.WmsCustomerVo;
import com.klp.domain.vo.WmsExpressVo;
import com.sf.fop.sxjd.oms.open.platform.*;
import com.sf.fop.sxjd.oms.open.platform.api.bean.SX_EWB_ORDER_SAVE.EwbOrderSaveRequest;
import com.sf.fop.sxjd.oms.open.platform.api.bean.SX_EWB_ORDER_SAVE.EwbOrderSaveResponse;
import com.sf.fop.sxjd.oms.open.platform.api.bean.SX_ORDER_STATUS_NOTIFY.OrderStatusNotifyRequest;
import com.sf.fop.sxjd.oms.open.platform.api.bean.SX_QUERY_TRACK.QueryTrackRequest;
import com.sf.fop.sxjd.oms.open.platform.api.bean.SX_QUERY_TRACK.QueryTrackResponse;
import com.sf.fop.sxjd.oms.open.platform.api.bean.SdkReceiveRequest;
import com.sf.fop.sxjd.oms.open.platform.api.bean.SendResponse;
import org.apache.commons.codec.binary.Base64;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Date;
import java.util.logging.Level;
/**
* 顺心捷达路由查询工具类
*
* @author ruoyi
*/
public class SxjdRouteQueryUtil {
private static final ClientAccount clientAccount;
private static final SdkClient sdkClient;
private static final OpenPlatformLogger logger;
private static final SxOrderStatusNotifyListener sxOrderStatusNotifyListener = new SxOrderStatusNotifyListener();
// 应用信息
private static final String APP_KEY = "3587488e38f3ebc6334d285cce34d979";
private static final String APP_SECRET = "b1f971b834a6db28f71310862dd3af83";
private static final String APP_CODE = "000469";
private static final String SX_CUSTOMER_CODE = "C20002014"; // 测试联调环境
private static final String REQUEST_URL = "https://oms.sit.sf-express.com:9010/api/gateway/service";
static {
// 初始化客户端账户信息
clientAccount = new ClientAccount();
clientAccount.setAppKey(APP_KEY);
clientAccount.setAppCode(APP_CODE);
clientAccount.setAppSecret(APP_SECRET);
clientAccount.setSxCustomerCode(SX_CUSTOMER_CODE);
clientAccount.setRequestUrl(REQUEST_URL);
// 初始化SDK客户端
sdkClient = new SdkClient(clientAccount);
// 注册监听器
sdkClient.registerReceiveListener(OpenApiType.SX_ORDER_STATUS_NOTIFY, sxOrderStatusNotifyListener);
// 设置日志级别
logger = sdkClient.getLogger();
logger.setLoggerLevel(Level.ALL);
}
/**
* 创建电子运单
*
* @param request 电子运单请求对象
* @return 电子运单响应
*/
public static SendResponse<EwbOrderSaveResponse> createEwbOrder(EwbOrderSaveRequest request) {
SendResponse<EwbOrderSaveResponse> sendResponse = sdkClient.send(OpenApiType.SX_EWB_ORDER_SAVE, request, EwbOrderSaveResponse.class);
logger.info("下单返回参数=" + JSON.toJSONString(sendResponse));
return sendResponse;
}
/**
* 创建电子运单使用JSON字符串
*
* @param requestStr JSON格式的请求字符串
* @return 电子运单响应
*/
public static SendResponse<EwbOrderSaveResponse> createEwbOrderByJson(String requestStr) {
EwbOrderSaveRequest ewbOrderSaveRequest = JSON.parseObject(requestStr, EwbOrderSaveRequest.class);
return createEwbOrder(ewbOrderSaveRequest);
}
/**
* 查询货物轨迹(与其他快递工具类接口保持一致)
*
* @param expressCode 运单号
* @return 查询结果JSON字符串
*/
public static String queryRoute(String expressCode) {
return queryTrackByHttp(expressCode);
}
/**
* 查询货物轨迹
*
* @param waybillId 运单号
* @return 查询结果
*/
public static SendResponse<QueryTrackResponse> queryTrack(String waybillId) {
QueryTrackRequest request = new QueryTrackRequest();
request.setWaybillId(waybillId);
SendResponse<QueryTrackResponse> response = sdkClient.send(OpenApiType.SX_QUERY_TRACK, request, QueryTrackResponse.class);
logger.info("轨迹查询返回参数=" + JSON.toJSONString(response));
return response;
}
/**
* 解析顺心捷达返回数据转为WmsExpressVo
*
* @param result 查询结果JSON字符串
* @return WmsExpressVo对象
*/
public static WmsExpressVo parseData(String result) {
if (result == null || result.trim().isEmpty()) {
return null;
}
try {
JSONObject json = JSON.parseObject(result);
if (!json.getBooleanValue("success")) {
return null;
}
JSONObject data = json.getJSONObject("data");
if (data == null) {
return null;
}
JSONArray trackInfoList = data.getJSONArray("trackInfoList");
if (trackInfoList == null || trackInfoList.isEmpty()) {
return null;
}
// 获取最新的一条轨迹记录
JSONObject lastTrack = trackInfoList.getJSONObject(0);
WmsExpressVo vo = new WmsExpressVo();
vo.setExpressCode(lastTrack.getString("waybillId"));
// 设置时间
Long opTime = lastTrack.getLong("operationTime");
if (opTime != null) {
vo.setLastUpdateTime(new Date(opTime));
vo.setAcceptTime(new Date(opTime));
}
// 设置状态
String step = lastTrack.getString("step");
String trackDesc = lastTrack.getString("trackDesc");
vo.setLastStatus(trackDesc);
vo.setFirstStatusName(step);
return vo;
} catch (Exception e) {
logger.info("解析顺心捷达轨迹数据异常: " + e.getMessage());
e.printStackTrace();
}
return null;
}
/**
* 使用HTTP方式查询货物轨迹
*
* @param waybillId 运单号
* @return 查询结果JSON字符串
*/
public static String queryTrackByHttp(String waybillId) {
try {
// 构建请求数据
String data = "{\"waybillId\":\"" + waybillId + "\"}";
String timestamp = System.currentTimeMillis() + "";
String dataDigest = md5Encode(data + timestamp + APP_SECRET);
// 构建请求体
StringBuilder body = new StringBuilder();
body.append("apiType=SX_QUERY_TRACK");
body.append("&appKey=").append(APP_KEY);
body.append("&sxCustomerCode=").append(SX_CUSTOMER_CODE);
body.append("&timestamp=").append(timestamp);
body.append("&dataDigest=").append(dataDigest);
body.append("&data=").append(data);
// 发送请求
URL url = new URL(REQUEST_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
// 写入请求体
OutputStream out = conn.getOutputStream();
out.write(body.toString().getBytes(StandardCharsets.UTF_8));
out.flush();
out.close();
// 处理响应
StringBuilder sbResult = new StringBuilder();
if (200 == conn.getResponseCode()) {
BufferedReader responseReader = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String readLine;
while ((readLine = responseReader.readLine()) != null) {
sbResult.append(readLine).append("\n");
}
responseReader.close();
String result = sbResult.toString();
logger.info("HTTP轨迹查询返回参数=" + result);
return result;
}
} catch (IOException e) {
logger.info("HTTP轨迹查询异常: " + e.getMessage());
}
return null;
}
/**
* MD5加密并Base64编码
*
* @param str 待加密字符串
* @return 加密后的字符串
*/
public static String md5Encode(String str) {
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(str.getBytes(StandardCharsets.UTF_8));
byte[] digest = md.digest();
return new String(Base64.encodeBase64URLSafe(digest), StandardCharsets.UTF_8);
} catch (Exception e) {
logger.setLogEnable(("MD5加密异常: " + e.getMessage()).isEmpty());
}
return null;
}
/**
* 顺心订单状态通知监听器
*/
public static class SxOrderStatusNotifyListener implements ReceiveListener<OrderStatusNotifyRequest, Void> {
@Override
public OpenApiType getApiType() {
return OpenApiType.SX_ORDER_STATUS_NOTIFY;
}
@Override
public Void execute(SdkReceiveRequest<OrderStatusNotifyRequest, Void> sdkReceiveRequest) throws OpenPlatformException {
OrderStatusNotifyRequest request = sdkReceiveRequest.getRequestData();
String print = JSON.toJSONString(request);
logger.info("接收参数={}" + print);
return null;
}
}
/**
* 测试方法
*/
public static void main(String[] args) {
try {
String data = "{ \"customerOrderNo\":\"QW2315464601\", \"orderChannelNo\":\"SE1231322\", \"orderType\":1,\"whetherEwb\":true,\"senderCompany\":\"测试公司890\", \"senderName\":\"测试收\", \"senderMobile\":\"12345667634\", \"senderTel\":\"0755-8658521\", \"senderProv\":\"广东省\", \"senderCity\":\"广州市\", \"senderArea\":\"越秀区\", \"senderAddress\":\"白云街道102号筒子巷\", \"receiverCompany\":\"绿色公司\", \"receiverName\":\"大师傅\", \"receiverTel\":\"021-85685452\", \"receiverMobile\":\"12313213213\", \"receiverProv\":\"广东省\", \"receiverCity\":\"广州市\", \"receiverArea\":\"海珠区\", \"receiverAddress\":\"华洲街道\", \"cargoName\":\"装修物品\", \"totalPackages\":3, \"totalWeight\":12, \"totalVolume\":15, \"pickupWay\":\"送货(不含上楼)\", \"backSignBill\":\"电子回单\", \"remark\":\"客户接入sxCustomerCode必填\", \"insuranceValue\":800, \"codAmount\":1024, \"fcodAmount\":620, \"getGoodMode\":\"上门接货\", \"orderSource\":\"PDD\",\"productName\":\"顺心包裹\",\"payType\":\"现付\",\"subMailNos\":\"20220426013,20220426014,20220426015\"}";
SendResponse<EwbOrderSaveResponse> response = createEwbOrderByJson(data);
System.out.println("下单测试结果: " + JSON.toJSONString(response));
// 测试轨迹查询
String waybillId = "S60201493742";
String trackResult = queryTrackByHttp(waybillId);
System.out.println("轨迹查询测试结果: " + trackResult);
// 测试MD5加密
String timestamp = System.currentTimeMillis() + "";
String appSecret = "b1f971b834a6db28f71310862dd3af83";
String dataDigest = md5Encode(data + timestamp + appSecret);
System.out.println("MD5加密结果: " + dataDigest);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -20,6 +20,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
</resultMap>
<select id="getLastBalance" resultType="java.math.BigDecimal">
SELECT balance_amount
FROM wms_journal
WHERE del_flag = 0
ORDER BY create_time DESC
LIMIT 1
</select>
</mapper>

View File

@@ -20,6 +20,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateTime" column="update_time"/>
<result property="updateBy" column="update_by"/>
</resultMap>
<select id="selectVoPagePlus" resultType="com.klp.domain.vo.WmsPayableVo">
select p.payable_id,
p.supplier_id,
s.name as supplierName,
p.order_id,
p.due_date,
p.amount,
p.paid_amount,
p.balance_amount,
p.status,
p.del_flag,
p.remark,
p.create_time,
p.create_by,
p.update_time,
p.update_by
from wms_payable p
left join wms_supplier s on p.supplier_id = s.supplier_id
${ew.customSqlSegment}
</select>
</mapper>

View File

@@ -21,5 +21,26 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by"/>
</resultMap>
<select id="selectVoPagePlus" resultType="com.klp.domain.vo.WmsReceivableVo">
select r.receivable_id,
r.customer_id,
r.order_id,
r.due_date,
r.amount,
r.paid_amount,
r.balance_amount,
r.status,
r.del_flag,
r.remark,
r.create_time,
r.create_by,
r.update_time,
r.update_by,
c.name as customerName
from wms_receivable r
left join wms_customer c on r.customer_id = c.customer_id
${ew.customSqlSegment}
</select>
</mapper>