feat(asset): 新增企业微信资产管理和审批功能
添加企业微信相关字段支持,包括corpid等标识 实现资产商品推送接口,支持批量处理商品信息 新增资产审批功能,包含审批通知和库存检查 重构商品和审批相关DTO及实体类,添加企业微信字段 更新数据库结构,添加相关字段和索引
This commit is contained in:
parent
aefb4366dc
commit
02dad5beab
|
@ -1,25 +1,20 @@
|
||||||
package com.agileboot.api.controller.asset;
|
package com.agileboot.api.controller.asset;
|
||||||
|
|
||||||
|
|
||||||
import cn.hutool.json.JSONUtil;
|
|
||||||
import com.agileboot.common.constant.OpenApiConstants;
|
import com.agileboot.common.constant.OpenApiConstants;
|
||||||
import com.agileboot.common.core.dto.ResponseDTO;
|
import com.agileboot.common.core.dto.ResponseDTO;
|
||||||
import com.agileboot.common.exception.ApiException;
|
import com.agileboot.common.exception.ApiException;
|
||||||
import com.agileboot.common.exception.error.ErrorCode;
|
import com.agileboot.common.exception.error.ErrorCode;
|
||||||
import com.agileboot.domain.asset.AssetApplicationService;
|
import com.agileboot.domain.asset.AssetApplicationService;
|
||||||
import com.agileboot.domain.asset.api.PostAssetGoodsBody;
|
import com.agileboot.domain.asset.command.PostAssetApprovalCommand;
|
||||||
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
|
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
|
||||||
import com.agileboot.domain.shop.payment.SignUtils;
|
import com.agileboot.domain.shop.payment.SignUtils;
|
||||||
import com.agileboot.domain.shop.payment.dto.CommonRequest;
|
import com.agileboot.domain.shop.payment.dto.CommonRequest;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
|
@ -30,7 +25,7 @@ public class AssetApiController {
|
||||||
private final AssetApplicationService assetApplicationService;
|
private final AssetApplicationService assetApplicationService;
|
||||||
|
|
||||||
@PostMapping("/pushExternalGoods")
|
@PostMapping("/pushExternalGoods")
|
||||||
public ResponseDTO<Void> pushExternalGoods(@RequestBody String body) throws UnsupportedEncodingException {
|
public ResponseDTO<Void> pushExternalGoods(@RequestBody String body) {
|
||||||
CommonRequest<PostAssetGoodsCommand> notifyRequest = CommonRequest.build(body, PostAssetGoodsCommand.class);
|
CommonRequest<PostAssetGoodsCommand> notifyRequest = CommonRequest.build(body, PostAssetGoodsCommand.class);
|
||||||
if (notifyRequest == null) {
|
if (notifyRequest == null) {
|
||||||
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "请求参数无效"));
|
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "请求参数无效"));
|
||||||
|
@ -42,4 +37,19 @@ public class AssetApiController {
|
||||||
assetApplicationService.pushExternalGoods(notifyRequest.getBizContent());
|
assetApplicationService.pushExternalGoods(notifyRequest.getBizContent());
|
||||||
return ResponseDTO.ok();
|
return ResponseDTO.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@PostMapping("/postAssetApproval")
|
||||||
|
public ResponseDTO<Void> postAssetApproval(@RequestBody String body) {
|
||||||
|
CommonRequest<PostAssetApprovalCommand> notifyRequest = CommonRequest.build(body, PostAssetApprovalCommand.class);
|
||||||
|
if (notifyRequest == null) {
|
||||||
|
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "请求参数无效"));
|
||||||
|
}
|
||||||
|
log.info("pushExternalGoods sign:{}, body:{}", notifyRequest.getSign(), body);
|
||||||
|
if (!SignUtils.checkOpenSign(OpenApiConstants.appKey, notifyRequest.getSign(), body)) {
|
||||||
|
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "sign校验失败"));
|
||||||
|
}
|
||||||
|
assetApplicationService.postAssetApprovalCommand(notifyRequest.getBizContent());
|
||||||
|
return ResponseDTO.ok();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@ package com.agileboot.api.controller;
|
||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.agileboot.common.constant.OpenApiConstants;
|
import com.agileboot.common.constant.OpenApiConstants;
|
||||||
import com.agileboot.common.core.dto.ResponseDTO;
|
import com.agileboot.domain.asset.command.PostAssetApprovalCommand;
|
||||||
import com.agileboot.domain.asset.api.PostAssetGoodsBody;
|
|
||||||
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
|
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
|
||||||
import com.agileboot.domain.shop.payment.SignUtils;
|
import com.agileboot.domain.shop.payment.SignUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -22,16 +21,21 @@ public class AssetApiControllerTest {
|
||||||
@Test
|
@Test
|
||||||
public void testPushExternalGoods() throws UnsupportedEncodingException {
|
public void testPushExternalGoods() throws UnsupportedEncodingException {
|
||||||
// 1.构建测试商品数据
|
// 1.构建测试商品数据
|
||||||
|
PostAssetGoodsCommand.GoodsInfo goodsInfo = new PostAssetGoodsCommand.GoodsInfo();
|
||||||
|
goodsInfo.setExternalGoodsId(1003L);
|
||||||
|
goodsInfo.setGoodsName("测试笔记本电脑3");
|
||||||
|
goodsInfo.setPrice(new BigDecimal("5999.00"));
|
||||||
|
goodsInfo.setStock(10);
|
||||||
|
goodsInfo.setAutoApproval(0);
|
||||||
|
goodsInfo.setCoverImg("https://example.com/laptop.jpg");
|
||||||
|
goodsInfo.setGoodsDetail("商品详情内容,支持2000汉字和10张图片链接");
|
||||||
|
goodsInfo.setUsageInstruction("1. 使用前请充电\n2. 避免液体接触\n3. 定期清理灰尘");
|
||||||
|
goodsInfo.setBelongType(1);
|
||||||
|
|
||||||
PostAssetGoodsCommand goods = new PostAssetGoodsCommand();
|
PostAssetGoodsCommand goods = new PostAssetGoodsCommand();
|
||||||
goods.setExternalGoodsId(1002L);
|
goods.setCorpid("wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw");
|
||||||
goods.setGoodsName("测试笔记本电脑");
|
goods.setGoodsInfoList(new ArrayList<>());
|
||||||
goods.setPrice(new BigDecimal("5999.00"));
|
goods.getGoodsInfoList().add(goodsInfo);
|
||||||
goods.setStock(10);
|
|
||||||
goods.setAutoApproval(1);
|
|
||||||
goods.setCoverImg("https://example.com/laptop.jpg");
|
|
||||||
goods.setGoodsDetail("商品详情内容,支持2000汉字和10张图片链接");
|
|
||||||
goods.setUsageInstruction("1. 使用前请充电\n2. 避免液体接触\n3. 定期清理灰尘");
|
|
||||||
goods.setBelongType(1);
|
|
||||||
|
|
||||||
// 2.构造请求体
|
// 2.构造请求体
|
||||||
Map<String, String> params = new HashMap<>();
|
Map<String, String> params = new HashMap<>();
|
||||||
|
@ -58,4 +62,46 @@ public class AssetApiControllerTest {
|
||||||
|
|
||||||
log.info("接口响应: {}", res);
|
log.info("接口响应: {}", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPostAssetApproval() throws UnsupportedEncodingException {
|
||||||
|
// 1.构建测试商品数据
|
||||||
|
PostAssetApprovalCommand approvalCommand = new PostAssetApprovalCommand();
|
||||||
|
approvalCommand.setCorpid("wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw");
|
||||||
|
approvalCommand.setExternalApprovalId(1L);
|
||||||
|
approvalCommand.setExternalGoodsId(1003L);
|
||||||
|
approvalCommand.setApplyQuantity(2);
|
||||||
|
approvalCommand.setApprovalType(1);
|
||||||
|
approvalCommand.setApplyRemark("申请说明");
|
||||||
|
approvalCommand.setMobile("12345678901");
|
||||||
|
approvalCommand.setUserid("123");
|
||||||
|
approvalCommand.setName("姓名");
|
||||||
|
approvalCommand.setIsInternal(2);
|
||||||
|
|
||||||
|
// 2.构造请求体
|
||||||
|
Map<String, String> params = new HashMap<>();
|
||||||
|
params.put("timestamp", String.valueOf(System.currentTimeMillis()));
|
||||||
|
params.put("biz_content", URLEncoder.encode(JSONUtil.toJsonStr(approvalCommand), StandardCharsets.UTF_8.toString()));
|
||||||
|
|
||||||
|
// 3.生成签名参数
|
||||||
|
|
||||||
|
String appKey = OpenApiConstants.appKey;
|
||||||
|
String sign = SignUtils.openSign(appKey, params);
|
||||||
|
params.put("sign", sign);
|
||||||
|
|
||||||
|
// 4.构造完整请求JSON
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (String key : params.keySet()) {
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
sb.append("&");
|
||||||
|
}
|
||||||
|
sb.append(key).append("=").append(params.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5.发送POST请求
|
||||||
|
String res = HttpUtil.post("http://localhost:8090/api/asset/postAssetApproval", sb.toString());
|
||||||
|
|
||||||
|
log.info("接口响应: {}", res);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,16 +1,29 @@
|
||||||
package com.agileboot.domain.asset;
|
package com.agileboot.domain.asset;
|
||||||
|
|
||||||
import cn.hutool.json.JSONUtil;
|
import com.agileboot.common.constant.WeixinConstants;
|
||||||
import com.agileboot.domain.asset.api.PostAssetGoodsBody;
|
import com.agileboot.domain.asset.command.PostAssetApprovalCommand;
|
||||||
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
|
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
|
||||||
|
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
|
||||||
|
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
|
||||||
|
import com.agileboot.domain.qywx.api.QywxApiUtil;
|
||||||
|
import com.agileboot.domain.qywx.api.response.NewsArticle;
|
||||||
|
import com.agileboot.domain.qywx.authCorpInfo.AuthCorpInfoApplicationService;
|
||||||
|
import com.agileboot.domain.qywx.authCorpInfo.db.QyAuthCorpInfoEntity;
|
||||||
|
import com.agileboot.domain.qywx.user.db.QyUserService;
|
||||||
|
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand;
|
||||||
|
import com.agileboot.domain.shop.approval.model.ReturnApprovalModel;
|
||||||
|
import com.agileboot.domain.shop.approval.model.ReturnApprovalModelFactory;
|
||||||
import com.agileboot.domain.shop.goods.db.ShopGoodsEntity;
|
import com.agileboot.domain.shop.goods.db.ShopGoodsEntity;
|
||||||
import com.agileboot.domain.shop.goods.db.ShopGoodsService;
|
import com.agileboot.domain.shop.goods.db.ShopGoodsService;
|
||||||
import com.agileboot.domain.shop.goods.model.GoodsModel;
|
import com.agileboot.domain.shop.goods.model.GoodsModel;
|
||||||
import com.agileboot.domain.shop.goods.model.GoodsModelFactory;
|
import com.agileboot.domain.shop.goods.model.GoodsModelFactory;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@ -19,55 +32,126 @@ import java.util.List;
|
||||||
public class AssetApplicationService {
|
public class AssetApplicationService {
|
||||||
private final ShopGoodsService shopGoodsService;
|
private final ShopGoodsService shopGoodsService;
|
||||||
private final GoodsModelFactory goodsModelFactory;
|
private final GoodsModelFactory goodsModelFactory;
|
||||||
|
private final ReturnApprovalModelFactory returnApprovalModelFactory;
|
||||||
|
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
|
||||||
|
private final AccessTokenApplicationService accessTokenApplicationService;
|
||||||
|
private final QyUserService qyUserService;
|
||||||
|
|
||||||
public void pushExternalGoods(PostAssetGoodsCommand command) {
|
public void pushExternalGoods(PostAssetGoodsCommand postAssetGoodsCommand) {
|
||||||
if (command == null || command.getExternalGoodsId() == null) {
|
if (postAssetGoodsCommand == null || postAssetGoodsCommand.getGoodsInfoList() == null || postAssetGoodsCommand.getGoodsInfoList().isEmpty()) {
|
||||||
throw new IllegalArgumentException("ExternalGoodsId cannot be null");
|
throw new IllegalArgumentException("GoodsInfoList cannot be null or empty");
|
||||||
}
|
}
|
||||||
ShopGoodsEntity shopGoodsEntity = shopGoodsService.getGoodsByExternalGoodsId(command.getExternalGoodsId());
|
if (postAssetGoodsCommand.getCorpid() == null) {
|
||||||
if (shopGoodsEntity != null) {
|
throw new IllegalArgumentException("Corpid cannot be null");
|
||||||
if (command.getGoodsName() != null) {
|
}
|
||||||
shopGoodsEntity.setGoodsName(command.getGoodsName());
|
|
||||||
|
for (PostAssetGoodsCommand.GoodsInfo command : postAssetGoodsCommand.getGoodsInfoList()) {
|
||||||
|
if (command == null || command.getExternalGoodsId() == null) {
|
||||||
|
throw new IllegalArgumentException("ExternalGoodsId cannot be null");
|
||||||
}
|
}
|
||||||
if (command.getPrice() != null) {
|
ShopGoodsEntity shopGoodsEntity = shopGoodsService.getGoodsByExternalGoodsId(postAssetGoodsCommand.getCorpid(), command.getExternalGoodsId());
|
||||||
shopGoodsEntity.setPrice(command.getPrice());
|
if (shopGoodsEntity != null) {
|
||||||
|
if (command.getGoodsName() != null) {
|
||||||
|
shopGoodsEntity.setGoodsName(command.getGoodsName());
|
||||||
|
}
|
||||||
|
if (command.getPrice() != null) {
|
||||||
|
shopGoodsEntity.setPrice(command.getPrice());
|
||||||
|
}
|
||||||
|
if (command.getStock() != null) {
|
||||||
|
shopGoodsEntity.setStock(command.getStock());
|
||||||
|
}
|
||||||
|
if (command.getAutoApproval() != null) {
|
||||||
|
shopGoodsEntity.setAutoApproval(command.getAutoApproval());
|
||||||
|
}
|
||||||
|
if (command.getCoverImg() != null) {
|
||||||
|
shopGoodsEntity.setCoverImg(command.getCoverImg());
|
||||||
|
}
|
||||||
|
if (command.getGoodsDetail() != null) {
|
||||||
|
shopGoodsEntity.setGoodsDetail(command.getGoodsDetail());
|
||||||
|
}
|
||||||
|
if (command.getUsageInstruction() != null) {
|
||||||
|
shopGoodsEntity.setUsageInstruction(command.getUsageInstruction());
|
||||||
|
}
|
||||||
|
if (command.getBelongType() != null) {
|
||||||
|
shopGoodsEntity.setBelongType(command.getBelongType());
|
||||||
|
}
|
||||||
|
shopGoodsEntity.updateById();
|
||||||
|
} else {
|
||||||
|
GoodsModel goodsModel = goodsModelFactory.create();
|
||||||
|
goodsModel.setCorpid(postAssetGoodsCommand.getCorpid());
|
||||||
|
goodsModel.setExternalGoodsId(command.getExternalGoodsId());
|
||||||
|
goodsModel.setGoodsName(command.getGoodsName());
|
||||||
|
goodsModel.setPrice(command.getPrice());
|
||||||
|
goodsModel.setStock(command.getStock());
|
||||||
|
goodsModel.setAutoApproval(command.getAutoApproval());
|
||||||
|
goodsModel.setCoverImg(command.getCoverImg());
|
||||||
|
goodsModel.setGoodsDetail(command.getGoodsDetail());
|
||||||
|
goodsModel.setUsageInstruction(command.getUsageInstruction());
|
||||||
|
goodsModel.setBelongType(command.getBelongType());
|
||||||
|
goodsModel.initBaseEntity();
|
||||||
|
goodsModel.setCategoryId(0L);
|
||||||
|
goodsModel.setStatus(1);
|
||||||
|
goodsModel.insert();
|
||||||
}
|
}
|
||||||
if (command.getStock() != null) {
|
|
||||||
shopGoodsEntity.setStock(command.getStock());
|
|
||||||
}
|
|
||||||
if (command.getAutoApproval() != null) {
|
|
||||||
shopGoodsEntity.setAutoApproval(command.getAutoApproval());
|
|
||||||
}
|
|
||||||
if (command.getCoverImg() != null) {
|
|
||||||
shopGoodsEntity.setCoverImg(command.getCoverImg());
|
|
||||||
}
|
|
||||||
if (command.getGoodsDetail() != null) {
|
|
||||||
shopGoodsEntity.setGoodsDetail(command.getGoodsDetail());
|
|
||||||
}
|
|
||||||
if (command.getUsageInstruction() != null) {
|
|
||||||
shopGoodsEntity.setUsageInstruction(command.getUsageInstruction());
|
|
||||||
}
|
|
||||||
if (command.getBelongType() != null) {
|
|
||||||
shopGoodsEntity.setBelongType(command.getBelongType());
|
|
||||||
}
|
|
||||||
shopGoodsEntity.updateById();
|
|
||||||
} else {
|
|
||||||
GoodsModel goodsModel = goodsModelFactory.create();
|
|
||||||
goodsModel.setExternalGoodsId(command.getExternalGoodsId());
|
|
||||||
goodsModel.setGoodsName(command.getGoodsName());
|
|
||||||
goodsModel.setPrice(command.getPrice());
|
|
||||||
goodsModel.setStock(command.getStock());
|
|
||||||
goodsModel.setAutoApproval(command.getAutoApproval());
|
|
||||||
goodsModel.setCoverImg(command.getCoverImg());
|
|
||||||
goodsModel.setGoodsDetail(command.getGoodsDetail());
|
|
||||||
goodsModel.setUsageInstruction(command.getUsageInstruction());
|
|
||||||
goodsModel.setBelongType(command.getBelongType());
|
|
||||||
goodsModel.initBaseEntity();
|
|
||||||
goodsModel.setCategoryId(0L);
|
|
||||||
goodsModel.setStatus(1);
|
|
||||||
goodsModel.insert();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void postAssetApprovalCommand(PostAssetApprovalCommand command) {
|
||||||
|
if (command == null || command.getExternalGoodsId() == null || StringUtils.isBlank(command.getCorpid())) {
|
||||||
|
throw new IllegalArgumentException("ExternalGoodsId cannot be null");
|
||||||
|
}
|
||||||
|
if (command.getApplyQuantity() == null || command.getApplyQuantity() <= 0) {
|
||||||
|
throw new IllegalArgumentException("ApplyQuantity must be greater than 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
ShopGoodsEntity shopGoodsEntity = shopGoodsService.getGoodsByExternalGoodsId(command.getCorpid(), command.getExternalGoodsId());
|
||||||
|
if (shopGoodsEntity == null) {
|
||||||
|
throw new IllegalArgumentException("ExternalGoodsId not found");
|
||||||
|
}
|
||||||
|
if (shopGoodsEntity.getStock() == null || shopGoodsEntity.getStock() < command.getApplyQuantity()) {
|
||||||
|
throw new IllegalArgumentException("Insufficient stock");
|
||||||
|
}
|
||||||
|
|
||||||
|
AddReturnApprovalCommand returnApprovalCommand = new AddReturnApprovalCommand();
|
||||||
|
BeanUtils.copyProperties(command, returnApprovalCommand);
|
||||||
|
returnApprovalCommand.setGoodsId(shopGoodsEntity.getGoodsId());
|
||||||
|
returnApprovalCommand.setGoodsPrice(shopGoodsEntity.getPrice());
|
||||||
|
if (returnApprovalCommand.getApprovalType() == null) {
|
||||||
|
returnApprovalCommand.setApprovalType(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnApprovalModel returnApprovalModel = returnApprovalModelFactory.create();
|
||||||
|
returnApprovalModel.initBaseEntity();
|
||||||
|
returnApprovalModel.loadAddCommand(returnApprovalCommand);
|
||||||
|
returnApprovalCommand.insert();
|
||||||
|
|
||||||
|
|
||||||
|
// 发送审核消息
|
||||||
|
try {
|
||||||
|
String appid = "QWTONG_YS_WXSHOP";
|
||||||
|
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
|
||||||
|
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
|
||||||
|
.filter(a -> WeixinConstants.corpid.equals(a.getCorpid()))
|
||||||
|
.findFirst().orElse(null);
|
||||||
|
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, authCorpInfo.getCorpid());
|
||||||
|
// 获取用户ID
|
||||||
|
List<String> adminUserIds = qyUserService.selectAdminUserIds();
|
||||||
|
String toUser = String.join("|", adminUserIds);
|
||||||
|
String toparty = "";
|
||||||
|
String totag = "";
|
||||||
|
List<NewsArticle> articles = new ArrayList<>();
|
||||||
|
NewsArticle article = new NewsArticle();
|
||||||
|
article.setTitle("耗材领用审核通知");
|
||||||
|
article.setDescription("申请领用商品:" + shopGoodsEntity.getGoodsName());
|
||||||
|
article.setPicurl(shopGoodsEntity.getCoverImg());
|
||||||
|
article.setUrl("http://wxshop.ab98.cn/shop-api/api/shop/qy/wechatAuth");
|
||||||
|
articles.add(article);
|
||||||
|
|
||||||
|
QywxApiUtil.sendNewsMessage(accessToken.getAccessToken(), Integer.valueOf(authCorpInfo.getAgentid()),
|
||||||
|
toUser, toparty, totag, articles);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("发送退货审核通知失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
package com.agileboot.domain.asset.api;
|
|
||||||
|
|
||||||
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@EqualsAndHashCode
|
|
||||||
@Data
|
|
||||||
public class PostAssetGoodsBody {
|
|
||||||
|
|
||||||
List<PostAssetGoodsCommand> goodsList;
|
|
||||||
}
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.agileboot.domain.asset.command;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@EqualsAndHashCode
|
||||||
|
@Data
|
||||||
|
public class PostAssetApprovalCommand {
|
||||||
|
@ApiModelProperty("企业微信id")
|
||||||
|
private String corpid;
|
||||||
|
|
||||||
|
@ApiModelProperty("外部归属类型的商品ID")
|
||||||
|
private Long externalGoodsId;
|
||||||
|
|
||||||
|
@ApiModelProperty("外部归属类型的审批ID")
|
||||||
|
private Long externalApprovalId;
|
||||||
|
|
||||||
|
@ApiModelProperty("申请数量")
|
||||||
|
private Integer applyQuantity;
|
||||||
|
|
||||||
|
@ApiModelProperty("审批类型(0为借还柜 1为固资通)")
|
||||||
|
private Integer approvalType;
|
||||||
|
|
||||||
|
@ApiModelProperty("申请说明")
|
||||||
|
private String applyRemark;
|
||||||
|
|
||||||
|
@ApiModelProperty("手机号码")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
@ApiModelProperty("企业微信用户ID或汇邦云用户ID")
|
||||||
|
private String userid;
|
||||||
|
|
||||||
|
@ApiModelProperty("用户姓名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty("是否内部用户(0否 1汇邦云用户 2企业微信用户)")
|
||||||
|
private Integer isInternal;
|
||||||
|
}
|
|
@ -8,34 +8,45 @@ import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@EqualsAndHashCode
|
@EqualsAndHashCode
|
||||||
@Data
|
@Data
|
||||||
public class PostAssetGoodsCommand {
|
public class PostAssetGoodsCommand {
|
||||||
@ApiModelProperty("外部归属类型的商品ID")
|
@ApiModelProperty("企业微信id")
|
||||||
private Long externalGoodsId;
|
private String corpid;
|
||||||
|
|
||||||
@ApiModelProperty("商品名称")
|
@ApiModelProperty("商品信息列表")
|
||||||
private String goodsName;
|
private List<GoodsInfo> goodsInfoList;
|
||||||
|
|
||||||
@ApiModelProperty("销售价格")
|
@Data
|
||||||
private BigDecimal price;
|
public static class GoodsInfo {
|
||||||
|
|
||||||
@ApiModelProperty("库存数量")
|
@ApiModelProperty("外部归属类型的商品ID")
|
||||||
private Integer stock;
|
private Long externalGoodsId;
|
||||||
|
|
||||||
@ApiModelProperty("免审批(0否 1是)")
|
@ApiModelProperty("商品名称")
|
||||||
private Integer autoApproval;
|
private String goodsName;
|
||||||
|
|
||||||
@ApiModelProperty("封面图URL")
|
@ApiModelProperty("销售价格")
|
||||||
private String coverImg;
|
private BigDecimal price;
|
||||||
|
|
||||||
@ApiModelProperty("商品详情(支持2000汉字+10个图片链接)")
|
@ApiModelProperty("库存数量")
|
||||||
private String goodsDetail;
|
private Integer stock;
|
||||||
|
|
||||||
@ApiModelProperty("商品使用说明")
|
@ApiModelProperty("免审批(0否 1是)")
|
||||||
private String usageInstruction;
|
private Integer autoApproval;
|
||||||
|
|
||||||
@ApiModelProperty("归属类型(0-借还柜 1-固资通)")
|
@ApiModelProperty("封面图URL")
|
||||||
private Integer belongType;
|
private String coverImg;
|
||||||
|
|
||||||
|
@ApiModelProperty("商品详情(支持2000汉字+10个图片链接)")
|
||||||
|
private String goodsDetail;
|
||||||
|
|
||||||
|
@ApiModelProperty("商品使用说明")
|
||||||
|
private String usageInstruction;
|
||||||
|
|
||||||
|
@ApiModelProperty("归属类型(0-借还柜 1-固资通)")
|
||||||
|
private Integer belongType;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import com.agileboot.domain.ab98.api.Ab98ApiUtil;
|
||||||
import com.agileboot.domain.ab98.api.SsoLoginUserinfo;
|
import com.agileboot.domain.ab98.api.SsoLoginUserinfo;
|
||||||
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
|
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
|
||||||
import com.agileboot.domain.ab98.user.db.Ab98UserService;
|
import com.agileboot.domain.ab98.user.db.Ab98UserService;
|
||||||
|
import com.agileboot.domain.common.cache.RedisCacheService;
|
||||||
import com.agileboot.domain.common.command.BulkOperationCommand;
|
import com.agileboot.domain.common.command.BulkOperationCommand;
|
||||||
import com.agileboot.domain.qywx.user.command.AddQyUserCommand;
|
import com.agileboot.domain.qywx.user.command.AddQyUserCommand;
|
||||||
import com.agileboot.domain.qywx.user.command.UpdateQyUserCommand;
|
import com.agileboot.domain.qywx.user.command.UpdateQyUserCommand;
|
||||||
|
@ -43,6 +44,8 @@ public class QyUserApplicationService {
|
||||||
private final SysRoleService sysRoleService;
|
private final SysRoleService sysRoleService;
|
||||||
private final Ab98UserService ab98UserService;
|
private final Ab98UserService ab98UserService;
|
||||||
|
|
||||||
|
private final RedisCacheService redisCache;
|
||||||
|
|
||||||
public PageDTO<QyUserDTO> getUserList(SearchQyUserQuery<QyUserEntity> query) {
|
public PageDTO<QyUserDTO> getUserList(SearchQyUserQuery<QyUserEntity> query) {
|
||||||
Page<QyUserEntity> page = userService.getUserList(query);
|
Page<QyUserEntity> page = userService.getUserList(query);
|
||||||
List<QyUserDTO> dtoList = page.getRecords().stream()
|
List<QyUserDTO> dtoList = page.getRecords().stream()
|
||||||
|
@ -79,6 +82,7 @@ public class QyUserApplicationService {
|
||||||
public void addUser(AddQyUserCommand command) {
|
public void addUser(AddQyUserCommand command) {
|
||||||
UserModel model = qyUserModelFactory.create();
|
UserModel model = qyUserModelFactory.create();
|
||||||
model.loadAddCommand(command);
|
model.loadAddCommand(command);
|
||||||
|
model.initBaseEntity();
|
||||||
model.insert();
|
model.insert();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +92,7 @@ public class QyUserApplicationService {
|
||||||
command.setBalance(command.getBalanceLimit().subtract(model.getUseBalance()));
|
command.setBalance(command.getBalanceLimit().subtract(model.getUseBalance()));
|
||||||
}
|
}
|
||||||
model.loadUpdateCommand(command);
|
model.loadUpdateCommand(command);
|
||||||
|
model.setUpdaterId(0L);
|
||||||
model.updateById();
|
model.updateById();
|
||||||
|
|
||||||
if (command.getRoleId() == null) {
|
if (command.getRoleId() == null) {
|
||||||
|
@ -97,7 +102,9 @@ public class QyUserApplicationService {
|
||||||
if (sysUserQyUser != null) {
|
if (sysUserQyUser != null) {
|
||||||
SysUserEntity sysUser = sysUserService.getById(sysUserQyUser.getSysUserId());
|
SysUserEntity sysUser = sysUserService.getById(sysUserQyUser.getSysUserId());
|
||||||
sysUser.setRoleId(command.getRoleId() > 0 ? command.getRoleId() : null);
|
sysUser.setRoleId(command.getRoleId() > 0 ? command.getRoleId() : null);
|
||||||
sysUserService.updateById(sysUser);
|
sysUser.updateById();
|
||||||
|
|
||||||
|
redisCache.userCache.delete(sysUser.getUserId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,30 @@ public class ReturnApprovalEntity extends BaseEntity<ReturnApprovalEntity> {
|
||||||
@TableField("order_goods_id")
|
@TableField("order_goods_id")
|
||||||
private Long orderGoodsId;
|
private Long orderGoodsId;
|
||||||
|
|
||||||
|
@ApiModelProperty("外部归属类型的商品ID")
|
||||||
|
@TableField("external_goods_id")
|
||||||
|
private Long externalGoodsId;
|
||||||
|
|
||||||
|
@ApiModelProperty("外部归属类型的审批ID")
|
||||||
|
@TableField("external_approval_id")
|
||||||
|
private Long externalApprovalId;
|
||||||
|
|
||||||
|
@ApiModelProperty("企业微信id")
|
||||||
|
@TableField("corpid")
|
||||||
|
private String corpid;
|
||||||
|
|
||||||
|
@ApiModelProperty("申请数量")
|
||||||
|
@TableField("apply_quantity")
|
||||||
|
private Integer applyQuantity;
|
||||||
|
|
||||||
|
@ApiModelProperty("审批类型(0为借还柜 1为固资通)")
|
||||||
|
@TableField("approval_type")
|
||||||
|
private Integer approvalType;
|
||||||
|
|
||||||
|
@ApiModelProperty("申请说明")
|
||||||
|
@TableField("apply_remark")
|
||||||
|
private String applyRemark;
|
||||||
|
|
||||||
@ApiModelProperty("归还数量")
|
@ApiModelProperty("归还数量")
|
||||||
@TableField("return_quantity")
|
@TableField("return_quantity")
|
||||||
private Integer returnQuantity;
|
private Integer returnQuantity;
|
||||||
|
|
|
@ -44,6 +44,24 @@ public class ReturnApprovalDTO {
|
||||||
@ExcelColumn(name = "关联订单商品ID")
|
@ExcelColumn(name = "关联订单商品ID")
|
||||||
private Long orderGoodsId;
|
private Long orderGoodsId;
|
||||||
|
|
||||||
|
@ExcelColumn(name = "外部归属类型的商品ID")
|
||||||
|
private Long externalGoodsId;
|
||||||
|
|
||||||
|
@ExcelColumn(name = "外部归属类型的审批ID")
|
||||||
|
private Long externalApprovalId;
|
||||||
|
|
||||||
|
@ExcelColumn(name = "企业微信id")
|
||||||
|
private String corpid;
|
||||||
|
|
||||||
|
@ExcelColumn(name = "申请数量")
|
||||||
|
private Integer applyQuantity;
|
||||||
|
|
||||||
|
@ExcelColumn(name = "审批类型")
|
||||||
|
private Integer approvalType;
|
||||||
|
|
||||||
|
@ExcelColumn(name = "申请说明")
|
||||||
|
private String applyRemark;
|
||||||
|
|
||||||
@ExcelColumn(name = "归还数量")
|
@ExcelColumn(name = "归还数量")
|
||||||
private Integer returnQuantity;
|
private Integer returnQuantity;
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,12 @@ public class SearchApiReturnApprovalQuery<T> extends AbstractPageQuery<T> {
|
||||||
private Long goodsId;
|
private Long goodsId;
|
||||||
private String goodsName;
|
private String goodsName;
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
private Long externalGoodsId;
|
||||||
|
private Long externalApprovalId;
|
||||||
|
private String corpid;
|
||||||
|
private Integer applyQuantity;
|
||||||
|
private Integer approvalType;
|
||||||
|
private String applyRemark;
|
||||||
private String returnRemark;
|
private String returnRemark;
|
||||||
private String auditRemark;
|
private String auditRemark;
|
||||||
private Date startTime;
|
private Date startTime;
|
||||||
|
@ -30,6 +36,10 @@ public class SearchApiReturnApprovalQuery<T> extends AbstractPageQuery<T> {
|
||||||
.eq(orderId != null, "ra.order_id", orderId)
|
.eq(orderId != null, "ra.order_id", orderId)
|
||||||
.eq(goodsId != null, "ra.goods_id", goodsId)
|
.eq(goodsId != null, "ra.goods_id", goodsId)
|
||||||
.eq(status != null, "ra.status", status)
|
.eq(status != null, "ra.status", status)
|
||||||
|
.eq(externalGoodsId != null, "ra.external_goods_id", externalGoodsId)
|
||||||
|
.eq(externalApprovalId != null, "ra.external_approval_id", externalApprovalId)
|
||||||
|
.eq(approvalType != null, "ra.approval_type", approvalType)
|
||||||
|
.eq(StrUtil.isNotEmpty(corpid), "ra.corpid", corpid)
|
||||||
.like(StrUtil.isNotEmpty(goodsName), "sog.goods_name", goodsName)
|
.like(StrUtil.isNotEmpty(goodsName), "sog.goods_name", goodsName)
|
||||||
.between(startTime != null && endTime != null, "ra.create_time", startTime, endTime)
|
.between(startTime != null && endTime != null, "ra.create_time", startTime, endTime)
|
||||||
.orderByDesc("ra.approval_id");
|
.orderByDesc("ra.approval_id");
|
||||||
|
|
|
@ -16,6 +16,12 @@ public class SearchReturnApprovalQuery<T> extends AbstractPageQuery<T> {
|
||||||
private Long orderId;
|
private Long orderId;
|
||||||
private Long goodsId;
|
private Long goodsId;
|
||||||
private Integer status;
|
private Integer status;
|
||||||
|
private Long externalGoodsId;
|
||||||
|
private Long externalApprovalId;
|
||||||
|
private String corpid;
|
||||||
|
private Integer applyQuantity;
|
||||||
|
private Integer approvalType;
|
||||||
|
private String applyRemark;
|
||||||
private String returnRemark;
|
private String returnRemark;
|
||||||
private String auditRemark;
|
private String auditRemark;
|
||||||
private Date startTime;
|
private Date startTime;
|
||||||
|
@ -32,6 +38,10 @@ public class SearchReturnApprovalQuery<T> extends AbstractPageQuery<T> {
|
||||||
.eq(orderId != null, "ra.order_id", orderId)
|
.eq(orderId != null, "ra.order_id", orderId)
|
||||||
.eq(goodsId != null, "ra.goods_id", goodsId)
|
.eq(goodsId != null, "ra.goods_id", goodsId)
|
||||||
.eq(status != null, "ra.status", status)
|
.eq(status != null, "ra.status", status)
|
||||||
|
.eq(externalGoodsId != null, "ra.external_goods_id", externalGoodsId)
|
||||||
|
.eq(externalApprovalId != null, "ra.external_approval_id", externalApprovalId)
|
||||||
|
.eq(approvalType != null, "ra.approval_type", approvalType)
|
||||||
|
.eq(StrUtil.isNotEmpty(corpid), "ra.corpid", corpid)
|
||||||
.like(StrUtil.isNotEmpty(returnRemark), "ra.return_remark", returnRemark)
|
.like(StrUtil.isNotEmpty(returnRemark), "ra.return_remark", returnRemark)
|
||||||
.like(StrUtil.isNotEmpty(auditRemark), "ra.audit_remark", auditRemark)
|
.like(StrUtil.isNotEmpty(auditRemark), "ra.audit_remark", auditRemark)
|
||||||
.like(StrUtil.isNotEmpty(paymentMethod), "so.payment_method", paymentMethod)
|
.like(StrUtil.isNotEmpty(paymentMethod), "so.payment_method", paymentMethod)
|
||||||
|
|
|
@ -44,6 +44,10 @@ public class ShopGoodsEntity extends BaseEntity<ShopGoodsEntity> {
|
||||||
@TableField("external_goods_id")
|
@TableField("external_goods_id")
|
||||||
private Long externalGoodsId;
|
private Long externalGoodsId;
|
||||||
|
|
||||||
|
@ApiModelProperty("企业微信id")
|
||||||
|
@TableField("corpid")
|
||||||
|
private String corpid;
|
||||||
|
|
||||||
@ApiModelProperty("销售价格")
|
@ApiModelProperty("销售价格")
|
||||||
@TableField("price")
|
@TableField("price")
|
||||||
private BigDecimal price;
|
private BigDecimal price;
|
||||||
|
|
|
@ -28,5 +28,5 @@ public interface ShopGoodsService extends IService<ShopGoodsEntity> {
|
||||||
|
|
||||||
BigDecimal calculateTotalAmount();
|
BigDecimal calculateTotalAmount();
|
||||||
|
|
||||||
ShopGoodsEntity getGoodsByExternalGoodsId(Long externalGoodsId);
|
ShopGoodsEntity getGoodsByExternalGoodsId(String corpid, Long externalGoodsId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,9 +59,10 @@ public class ShopGoodsServiceImpl extends ServiceImpl<ShopGoodsMapper, ShopGoods
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ShopGoodsEntity getGoodsByExternalGoodsId(Long externalGoodsId) {
|
public ShopGoodsEntity getGoodsByExternalGoodsId(String corpid, Long externalGoodsId) {
|
||||||
QueryWrapper<ShopGoodsEntity> wrapper = new QueryWrapper<>();
|
QueryWrapper<ShopGoodsEntity> wrapper = new QueryWrapper<>();
|
||||||
wrapper.eq("external_goods_id", externalGoodsId)
|
wrapper.eq("external_goods_id", externalGoodsId)
|
||||||
|
.eq("corpid", corpid)
|
||||||
.eq("deleted", 0)
|
.eq("deleted", 0)
|
||||||
.last("LIMIT 1");
|
.last("LIMIT 1");
|
||||||
return baseMapper.selectOne(wrapper);
|
return baseMapper.selectOne(wrapper);
|
||||||
|
|
|
@ -51,6 +51,9 @@ public class ShopGoodsDTO {
|
||||||
@ExcelColumn(name = "外部商品ID")
|
@ExcelColumn(name = "外部商品ID")
|
||||||
private Long externalGoodsId;
|
private Long externalGoodsId;
|
||||||
|
|
||||||
|
@ExcelColumn(name = "企业微信id")
|
||||||
|
private String corpid;
|
||||||
|
|
||||||
@ExcelColumn(name = "分类名称")
|
@ExcelColumn(name = "分类名称")
|
||||||
private String categoryName;
|
private String categoryName;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ public class SearchShopGoodsQuery<T> extends AbstractPageQuery<T> {
|
||||||
protected String goodsName;
|
protected String goodsName;
|
||||||
protected Long categoryId;
|
protected Long categoryId;
|
||||||
protected Long externalGoodsId;
|
protected Long externalGoodsId;
|
||||||
|
protected String corpid;
|
||||||
protected Integer status;
|
protected Integer status;
|
||||||
protected Integer autoApproval;
|
protected Integer autoApproval;
|
||||||
protected BigDecimal minPrice;
|
protected BigDecimal minPrice;
|
||||||
|
@ -33,6 +34,7 @@ public class SearchShopGoodsQuery<T> extends AbstractPageQuery<T> {
|
||||||
.le(maxPrice != null, "g.price", maxPrice)
|
.le(maxPrice != null, "g.price", maxPrice)
|
||||||
.eq(belongType != null, "g.belong_type", belongType)
|
.eq(belongType != null, "g.belong_type", belongType)
|
||||||
.eq(externalGoodsId != null, "g.external_goods_id", externalGoodsId)
|
.eq(externalGoodsId != null, "g.external_goods_id", externalGoodsId)
|
||||||
|
.eq(StrUtil.isNotEmpty(corpid), "g.corpid", corpid)
|
||||||
.eq("g.deleted", 0)
|
.eq("g.deleted", 0)
|
||||||
.groupBy("g.goods_id");
|
.groupBy("g.goods_id");
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,30 @@ AFTER `category_id`;
|
||||||
ALTER TABLE `shop_goods`
|
ALTER TABLE `shop_goods`
|
||||||
ADD COLUMN `external_goods_id` BIGINT NULL COMMENT '外部归属类型的商品ID'
|
ADD COLUMN `external_goods_id` BIGINT NULL COMMENT '外部归属类型的商品ID'
|
||||||
AFTER `category_id`;
|
AFTER `category_id`;
|
||||||
|
|
||||||
|
-- 添加缺失字段
|
||||||
|
ALTER TABLE `return_approval`
|
||||||
|
ADD COLUMN `external_goods_id` bigint DEFAULT NULL COMMENT '外部归属类型的商品ID' AFTER `order_goods_id`,
|
||||||
|
ADD COLUMN `apply_quantity` int DEFAULT NULL COMMENT '申请数量' AFTER `external_goods_id`,
|
||||||
|
ADD COLUMN `approval_type` TINYINT NOT NULL DEFAULT 0 COMMENT '审批类型(0为借还柜 1为固资通)' AFTER `order_goods_id`,
|
||||||
|
ADD COLUMN `apply_remark` varchar(1024) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '申请说明' AFTER `return_remark`;
|
||||||
|
|
||||||
|
-- 添加索引
|
||||||
|
ALTER TABLE `return_approval`
|
||||||
|
ADD INDEX `idx_external_goods_id` (`external_goods_id`),
|
||||||
|
ADD INDEX `idx_approval_type` (`approval_type`);
|
||||||
|
|
||||||
|
ALTER TABLE `shop_goods`
|
||||||
|
ADD COLUMN `corpid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业微信id'
|
||||||
|
AFTER `external_goods_id`;
|
||||||
|
|
||||||
|
ALTER TABLE `return_approval`
|
||||||
|
ADD COLUMN `corpid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业微信id'
|
||||||
|
AFTER `external_goods_id`;
|
||||||
|
|
||||||
|
|
||||||
|
ALTER TABLE `return_approval`
|
||||||
|
ADD COLUMN `external_approval_id` bigint DEFAULT NULL COMMENT '外部归属类型的审批ID'
|
||||||
|
AFTER `external_goods_id`;
|
||||||
|
ALTER TABLE `return_approval`
|
||||||
|
ADD INDEX `idx_external_approval_id` (`external_approval_id`);
|
Loading…
Reference in New Issue