diff --git a/agileboot-api/src/test/java/com/agileboot/api/controller/AssetApiControllerTest.java b/agileboot-api/src/test/java/com/agileboot/api/controller/AssetApiControllerTest.java index ba4351d..49fb29b 100644 --- a/agileboot-api/src/test/java/com/agileboot/api/controller/AssetApiControllerTest.java +++ b/agileboot-api/src/test/java/com/agileboot/api/controller/AssetApiControllerTest.java @@ -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 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()); + } + } } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/asset/AssetApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/asset/AssetApplicationService.java index eebf21f..f1277a5 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/asset/AssetApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/asset/AssetApplicationService.java @@ -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 shopOrderGoodsList, + List 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 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> consumeOutDetail = response.getData(); + Map 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("出库单创建失败"); + } + } } diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/asset/api/request/ConsumeOutputRequest.java b/agileboot-domain/src/main/java/com/agileboot/domain/asset/api/request/ConsumeOutputRequest.java new file mode 100644 index 0000000..a351833 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/asset/api/request/ConsumeOutputRequest.java @@ -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 consumeOutDetailParams; + + @Data + public static class ConsumeOutDetailParam { + /** 耗材id,必填 */ + private Long consumeId; + /** 出库数量,必填 */ + private Integer outNum; + /** 出库单价,必填 */ + private BigDecimal outPrice; + /** 出库金额,必填 */ + private BigDecimal outAmount; + } +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/asset/api/response/ConsumeOutputResponse.java b/agileboot-domain/src/main/java/com/agileboot/domain/asset/api/response/ConsumeOutputResponse.java new file mode 100644 index 0000000..02e0933 --- /dev/null +++ b/agileboot-domain/src/main/java/com/agileboot/domain/asset/api/response/ConsumeOutputResponse.java @@ -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> data; +} diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java index 137fead..e9b4ffe 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/approval/ReturnApprovalApplicationService.java @@ -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); diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/db/ShopEntity.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/db/ShopEntity.java index a780df5..e19cf94 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/db/ShopEntity.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/db/ShopEntity.java @@ -39,6 +39,10 @@ public class ShopEntity extends BaseEntity { @TableField("corpid") private String corpid; + @ApiModelProperty("归属类型(0-借还柜 1-固资通)") + @TableField("belong_type") + private Integer belongType; + @Override public Serializable pkVal() { return this.shopId; diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/dto/ShopDTO.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/dto/ShopDTO.java index 587f10f..dc6193d 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/dto/ShopDTO.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/dto/ShopDTO.java @@ -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; } \ No newline at end of file diff --git a/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/query/SearchShopQuery.java b/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/query/SearchShopQuery.java index 9bc882e..3d2d942 100644 --- a/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/query/SearchShopQuery.java +++ b/agileboot-domain/src/main/java/com/agileboot/domain/shop/shop/query/SearchShopQuery.java @@ -16,6 +16,7 @@ public class SearchShopQuery extends AbstractPageQuery { private Date startTime; private Date endTime; private String corpid; + private Integer belongType; @Override public QueryWrapper addQueryCondition() { @@ -25,6 +26,7 @@ public class SearchShopQuery extends AbstractPageQuery { .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"; diff --git a/sql/20250611.sql b/sql/20250611.sql new file mode 100644 index 0000000..3bd73d4 --- /dev/null +++ b/sql/20250611.sql @@ -0,0 +1,3 @@ +ALTER TABLE `shop` +ADD COLUMN `belong_type` tinyint NOT NULL DEFAULT 0 COMMENT '归属类型(0-借还柜 1-固资通)' +AFTER `corpid`; \ No newline at end of file