feat(shop): 添加归属类型字段并实现固资通出库功能

为shop表添加belong_type字段用于区分归属类型(0-借还柜 1-固资通)
在退货审批通过时调用固资通服务的出库接口,同步出库信息
新增ConsumeOutputRequest和ConsumeOutputResponse用于出库接口交互
This commit is contained in:
dzq 2025-06-11 15:53:54 +08:00
parent 0e0eeba3a3
commit 353fe774d8
9 changed files with 199 additions and 3 deletions

View File

@ -3,6 +3,8 @@ package com.agileboot.api.controller;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.constant.OpenApiConstants;
import com.agileboot.domain.asset.api.request.ConsumeOutputRequest;
import com.agileboot.domain.asset.api.response.ConsumeOutputResponse;
import com.agileboot.domain.asset.command.PostAssetApprovalCommand;
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
import com.agileboot.domain.shop.payment.SignUtils;
@ -13,6 +15,7 @@ import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@ -113,4 +116,49 @@ public class AssetApiControllerTest {
log.info("接口响应: {}", res);
}
@Test
public void testConsumeOutput() throws UnsupportedEncodingException {
// 1.构建测试数据
ConsumeOutputRequest request = new ConsumeOutputRequest();
request.setCorpid("wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw");
request.setOutUserid("woZ1ZrEgAAV9AEdRt1MGQxSg-KDJrDlA");
request.setOutDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
request.setApproveUserid("woZ1ZrEgAAV9AEdRt1MGQxSg-KDJrDlA");
request.setRemark("测试出库单");
request.setState("2");
List<ConsumeOutputRequest.ConsumeOutDetailParam> details = new ArrayList<>();
ConsumeOutputRequest.ConsumeOutDetailParam detail1 = new ConsumeOutputRequest.ConsumeOutDetailParam();
detail1.setConsumeId(1900L);
detail1.setOutNum(2);
detail1.setOutPrice(BigDecimal.valueOf(116.50));
detail1.setOutAmount(detail1.getOutPrice().multiply(BigDecimal.valueOf(detail1.getOutNum())));
details.add(detail1);
ConsumeOutputRequest.ConsumeOutDetailParam detail2 = new ConsumeOutputRequest.ConsumeOutDetailParam();
detail2.setConsumeId(1896L);
detail2.setOutNum(1);
detail2.setOutPrice(BigDecimal.valueOf(9.60));
detail2.setOutAmount(detail2.getOutPrice().multiply(BigDecimal.valueOf(detail2.getOutNum())));
details.add(detail2);
request.setConsumeOutDetailParams(details);
request.setMaterialNum(details.stream().map(ConsumeOutputRequest.ConsumeOutDetailParam::getOutNum).reduce(0, Integer::sum));
request.setTotalAmount(details.stream().map(ConsumeOutputRequest.ConsumeOutDetailParam::getOutAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
// 2.发送POST请求
log.info("请求参数: {}", JSONUtil.toJsonStr(request));
String res = HttpUtil.post("http://192.168.8.33:8090/api/receive/cabinet/consume/output", JSONUtil.toJsonStr(request));
log.info("接口响应: {}", res);
ConsumeOutputResponse response = JSONUtil.toBean(res, ConsumeOutputResponse.class);
if (response != null && response.getCode() == 0) {
log.info("出库单创建成功,出库单: {}", JSONUtil.toJsonStr(response.getData()));
} else {
log.error("出库单创建失败,错误信息: {}", response.getMessage());
}
}
}

View File

@ -1,7 +1,10 @@
package com.agileboot.domain.asset;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.constant.WeixinConstants;
import com.agileboot.domain.asset.api.request.ConsumeOutputRequest;
import com.agileboot.domain.asset.api.response.ConsumeOutputResponse;
import com.agileboot.domain.asset.command.PostAssetApprovalCommand;
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
import com.agileboot.domain.cabinet.cell.db.CabinetCellEntity;
@ -23,14 +26,16 @@ import com.agileboot.domain.shop.goods.db.ShopGoodsEntity;
import com.agileboot.domain.shop.goods.db.ShopGoodsService;
import com.agileboot.domain.shop.goods.model.GoodsModel;
import com.agileboot.domain.shop.goods.model.GoodsModelFactory;
import com.agileboot.domain.shop.order.db.ShopOrderGoodsEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@Service
@ -200,4 +205,70 @@ public class AssetApplicationService {
log.error("发送退货审核通知失败", e);
}
}
public void consumeOutput(String corpid, String outUserid, String approveUserid,
ReturnApprovalModel returnApprovalModel,
List<ShopOrderGoodsEntity> shopOrderGoodsList,
List<GoodsModel> goodsModelList) {
ConsumeOutputRequest request = new ConsumeOutputRequest();
request.setCorpid(corpid);
request.setOutUserid(outUserid);
request.setOutDate(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
request.setApproveUserid(approveUserid);
request.setRemark(returnApprovalModel.getAuditRemark());
request.setState("2");
List<ConsumeOutputRequest.ConsumeOutDetailParam> details = new ArrayList<>();
for (ShopOrderGoodsEntity shopOrderGoods : shopOrderGoodsList) {
GoodsModel goodsModel = goodsModelList.stream()
.filter(g -> g.getGoodsId().equals(shopOrderGoods.getGoodsId()))
.findFirst().orElse(null);
if (goodsModel == null) {
throw new IllegalArgumentException("GoodsModel not found");
}
ConsumeOutputRequest.ConsumeOutDetailParam detail = new ConsumeOutputRequest.ConsumeOutDetailParam();
detail.setConsumeId(goodsModel.getExternalGoodsId());
detail.setOutNum(shopOrderGoods.getQuantity());
detail.setOutPrice(shopOrderGoods.getPrice());
detail.setOutAmount(shopOrderGoods.getTotalAmount());
details.add(detail);
}
request.setConsumeOutDetailParams(details);
request.setMaterialNum(details.stream().map(ConsumeOutputRequest.ConsumeOutDetailParam::getOutNum).reduce(0, Integer::sum));
request.setTotalAmount(details.stream().map(ConsumeOutputRequest.ConsumeOutDetailParam::getOutAmount).reduce(BigDecimal.ZERO, BigDecimal::add));
// 2.发送POST请求
log.info("consumeOutput 请求参数: {}", JSONUtil.toJsonStr(request));
String res = HttpUtil.post("http://192.168.8.33:8090/api/receive/cabinet/consume/output", JSONUtil.toJsonStr(request));
log.info("consumeOutput 接口响应: {}", res);
ConsumeOutputResponse response = JSONUtil.toBean(res, ConsumeOutputResponse.class);
if (response != null && response.getCode() == 0) {
log.info("出库单创建成功,出库单: {}", JSONUtil.toJsonStr(response.getData()));
List<Map<String, Integer>> consumeOutDetail = response.getData();
Map<String, Integer> consumeOutDetailMap = new HashMap<>();
consumeOutDetail.forEach(consumeOutDetailMap::putAll);
for (ShopOrderGoodsEntity shopOrderGoods : shopOrderGoodsList) {
GoodsModel goodsModel = goodsModelList.stream()
.filter(g -> g.getGoodsId().equals(shopOrderGoods.getGoodsId()))
.findFirst().orElse(null);
if (goodsModel == null) {
throw new IllegalArgumentException("GoodsModel not found");
}
if (!consumeOutDetailMap.containsKey(String.valueOf(goodsModel.getExternalGoodsId()))) {
throw new IllegalArgumentException("ConsumeOutDetail not found");
}
if (!consumeOutDetailMap.get(String.valueOf(goodsModel.getExternalGoodsId())).equals(shopOrderGoods.getQuantity())) {
throw new IllegalArgumentException("Insufficient stock");
}
}
} else {
log.error("出库单创建失败,错误信息: {}", response.getMessage());
throw new RuntimeException("出库单创建失败");
}
}
}

View File

@ -0,0 +1,42 @@
package com.agileboot.domain.asset.api.request;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.List;
@EqualsAndHashCode
@Data
public class ConsumeOutputRequest {
/** 企业corpid必填 */
private String corpid;
/** 申领用户企业微信id必填 */
private String outUserid;
/** 申领出库单日期,不传默认当天 */
private String outDate;
/** 出库总耗材数,必填 */
private Integer materialNum;
/** 出库总金额,必填 */
private BigDecimal totalAmount;
/** 审核用户企业微信id必填 */
private String approveUserid;
/** 审批备注 */
private String remark;
/** 审批状态("2"通过,"3"拒绝),必填 */
private String state;
/** 耗材明细,必填 */
private List<ConsumeOutDetailParam> consumeOutDetailParams;
@Data
public static class ConsumeOutDetailParam {
/** 耗材id必填 */
private Long consumeId;
/** 出库数量,必填 */
private Integer outNum;
/** 出库单价,必填 */
private BigDecimal outPrice;
/** 出库金额,必填 */
private BigDecimal outAmount;
}
}

View File

@ -0,0 +1,14 @@
package com.agileboot.domain.asset.api.response;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
import java.util.Map;
@EqualsAndHashCode
@Data
public class ConsumeOutputResponse {
private Integer code;
private String message;
private List<Map<String, Integer>> data;
}

View File

@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
import com.agileboot.common.constant.PayApiConstants;
import com.agileboot.common.constant.WeixinConstants;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.asset.AssetApplicationService;
import com.agileboot.domain.cabinet.cell.model.CabinetCellModel;
import com.agileboot.domain.cabinet.cell.model.CabinetCellModelFactory;
import com.agileboot.domain.common.command.BulkOperationCommand;
@ -70,6 +71,7 @@ public class ReturnApprovalApplicationService {
private final CabinetCellModelFactory cabinetCellModelFactory;
private final QyUserService userService;
private final PaymentOperationLogApplicationService paymentOperationLogApplicationService;
private final AssetApplicationService assetApplicationService;
/**
* 获取退货审批列表
@ -329,6 +331,12 @@ public class ReturnApprovalApplicationService {
model.setAuditImages(command.getAuditImages());
model.setAuditRemark(command.getAuditRemark());
model.setApprovalTime(new Date());
// 调用固资通服务的出库方法
assetApplicationService.consumeOutput(model.getCorpid(), model.getUserid(), command.getUserid(),
model, shopOrderGoodsList, goodsModelList);
// 开始执行数据库操作
model.setStatus(2); // 2表示审核通过状态
model.updateById();
@ -344,7 +352,6 @@ public class ReturnApprovalApplicationService {
// 批量更新格口库存
cabinetCellModelList.forEach(CabinetCellModel::updateById);
OrderModel orderModel = orderModelFactory.loadById(shopOrderGoodsList.get(0).getOrderId());
orderModel.setStatus(2);
orderModel.setPayStatus(2);

View File

@ -39,6 +39,10 @@ public class ShopEntity extends BaseEntity<ShopEntity> {
@TableField("corpid")
private String corpid;
@ApiModelProperty("归属类型0-借还柜 1-固资通)")
@TableField("belong_type")
private Integer belongType;
@Override
public Serializable pkVal() {
return this.shopId;

View File

@ -6,6 +6,8 @@ import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.domain.common.cache.CacheCenter;
import com.agileboot.domain.shop.shop.db.ShopEntity;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ExcelSheet(name = "商店列表")
@ -26,4 +28,7 @@ public class ShopDTO {
@ExcelColumn(name = "企业微信id")
private String corpid;
@ExcelColumn(name = "归属类型0-借还柜 1-固资通)")
private Integer belongType;
}

View File

@ -16,6 +16,7 @@ public class SearchShopQuery<T> extends AbstractPageQuery<T> {
private Date startTime;
private Date endTime;
private String corpid;
private Integer belongType;
@Override
public QueryWrapper<T> addQueryCondition() {
@ -25,6 +26,7 @@ public class SearchShopQuery<T> extends AbstractPageQuery<T> {
.like(StrUtil.isNotEmpty(shopName), "shop_name", shopName)
.eq(StrUtil.isNotEmpty(enable), "enable", enable)
.eq(StrUtil.isNotEmpty(corpid), "corpid", corpid)
.eq(belongType != null, "belong_type", belongType)
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
this.timeRangeColumn = "create_time";

3
sql/20250611.sql Normal file
View File

@ -0,0 +1,3 @@
ALTER TABLE `shop`
ADD COLUMN `belong_type` tinyint NOT NULL DEFAULT 0 COMMENT '归属类型0-借还柜 1-固资通)'
AFTER `corpid`;