Compare commits

...

31 Commits

Author SHA1 Message Date
dzq 460d34457e feat(商品): 添加获取商品列表接口及格口库存管理功能
添加获取商品列表的非分页查询接口
新增格口商品库存配置、调整和清空功能
2025-06-14 08:09:06 +08:00
dzq 4e4c4876b6 feat(店铺/智能柜): 增加按店铺ID和模式筛选功能
修改店铺列表接口,支持传入mode参数进行筛选
智能柜详情接口改为按shopId查询相关数据
2025-06-13 15:40:31 +08:00
dzq ad1d764991 feat(shop): 添加根据ID获取商店详情的接口
新增获取商店详情的功能,包括领域层服务方法和控制器接口
```

```msg
feat(cabinet): 新增10口机柜模板枚举值

在CabinetTemplateEnum中添加CABINET_10枚举值,用于支持10口机柜配置
```

```msg
feat(cabinet): 拆分智能柜列表接口为分页和非分页版本

将原智能柜列表接口拆分为getSmartCabinetPage和getSmartCabinetList
分别用于分页查询和普通列表查询
```

```msg
refactor(mqtt): 优化MQTT连接日志信息

在MQTT连接和消息发送日志中添加主题信息,便于调试和问题排查
2025-06-13 11:51:45 +08:00
dzq 9cc755f83c feat(approval): 添加审批码字段及相关功能
- 在return_approval表中添加code字段用于存储审批码
- 在审批相关DTO、Entity、Query中添加code字段支持
- 修改商品详情查询SQL,添加店铺名称字段
- 移除资产申请时的库存校验逻辑
2025-06-13 09:00:18 +08:00
dzq 2c4ccc4dfd feat(shop): 添加店铺运行模式、借呗支付和封面图功能
- 在ShopDTO、ShopEntity和SearchShopQuery中添加mode、balanceEnable和coverImg字段
- 修改ShopServiceImpl的getShopListByCorpid方法,过滤mode为4的店铺
- 更新数据库表结构,添加mode、balance_enable和cover_img字段
2025-06-12 16:14:57 +08:00
dzq 84157ed63e fix: 将资产消费接口地址改为线上 2025-06-12 08:59:54 +08:00
dzq d7f85485db refactor(QywxScheduleJob): 优化用户同步逻辑避免重复添加
将多个import语句合并为使用java.util.*
使用stream过滤避免重复添加微信用户
使用Set优化用户ID存在性检查
2025-06-11 17:16:18 +08:00
dzq 74cc7f3201 feat(审批流程): 添加申请人和审批人企业UserID字段
在退货审批流程中新增apply_userid和audit_userid字段,用于记录申请人和审批人的企业微信UserID
修改相关DTO、Entity、Service及查询类,支持新字段的存储和查询
调整固资通服务调用参数,使用新字段进行用户标识
2025-06-11 16:25:17 +08:00
dzq 353fe774d8 feat(shop): 添加归属类型字段并实现固资通出库功能
为shop表添加belong_type字段用于区分归属类型(0-借还柜 1-固资通)
在退货审批通过时调用固资通服务的出库接口,同步出库信息
新增ConsumeOutputRequest和ConsumeOutputResponse用于出库接口交互
2025-06-11 15:53:54 +08:00
dzq 0e0eeba3a3 fix(退款): 修复旧订单退款商户不一致问题
检查订单创建时间以确定使用新旧商户进行退款。旧订单需使用旧商户退款,若失败则尝试新商户退款。
2025-06-11 10:19:52 +08:00
dzq 40e062933d feat(支付): 添加旧业务ID支持并增强退款错误处理
添加old_biz_id常量以支持旧支付系统
根据订单创建时间选择支付业务ID
在退款异常时添加详细错误日志并尝试新系统
改进异常信息包含请求参数和响应结果
2025-06-11 10:03:08 +08:00
dzq 7f45b1cf79 feat(qywx): 添加根据appid和corpid查询企业授权信息接口
添加selectByAppidAndCorpid方法用于精确查询企业授权信息
优化getBalance接口逻辑,直接使用传入的corpid参数
修复AssetApplicationService中monthlyPurchaseLimit的判断条件
2025-06-10 17:12:54 +08:00
dzq cf5e5fa673 feat(shop): 添加根据企业ID获取店铺列表功能并修正限购数量类型
- 在ShopService接口和实现类中添加getShopListByCorpid方法
- 在ShopApplicationService中实现业务逻辑
- 在ShopController中新增/list接口
- 将monthlyPurchaseLimit字段类型从String改为Integer
2025-06-10 11:16:05 +08:00
dzq a4f79e3e28 feat(订单): 添加corpid字段支持企业微信相关功能
在订单创建和退货审批流程中添加corpid字段,用于支持企业微信相关的用户查询和余额操作
2025-06-10 10:12:07 +08:00
dzq 6313299722 fix: 更新SQL脚本并优化商品查询SQL
更新多个表的corpid字段值为统一值,确保数据一致性
优化商品查询SQL,明确指定查询字段避免潜在问题
2025-06-10 09:40:48 +08:00
dzq 848f9d9606 feat(商品): 添加belongType字段并优化审批流程
在SearchGoodsWithCabinetDO中添加belongType字段以支持商品分类
优化ReturnApprovalApplicationService中的审批流程,添加订单商品校验和状态更新
简化ShopGoodsMapper中的SQL查询语句
重构OrderApplicationService中的submitAssetApproval方法,使用完整命令对象
2025-06-09 17:38:54 +08:00
dzq 4da0d35be4 feat(订单): 添加审批支付类型支持
在订单服务中添加审批支付类型处理逻辑,包括:
1. 修改QyUserService接口及相关实现,支持按企业ID查询管理员
2. 扩展支付方式描述和订单提交参数
3. 实现审批支付流程,包括创建审批记录和发送企业微信通知
2025-06-09 16:45:35 +08:00
dzq 59d8ff188a feat(approval): 实现资产退货申请的审批通过逻辑
添加approveAssetApproval方法实现资产退货审批通过功能,包括:
- 检查商品和格口库存是否充足
- 更新审批状态和审批人信息
- 更新商品和格口库存
- 更新关联订单商品状态
2025-06-09 16:18:21 +08:00
dzq b96fd06aea feat(approval): 添加审批相关功能及每月限购数量字段
- 新增审批ID字段和根据审批ID查询订单商品接口
- 添加商品每月限购数量字段及相关DTO映射
- 实现审批处理逻辑和获取审批订单商品列表功能
- 修复审批流程中corpid硬编码问题
2025-06-09 15:23:35 +08:00
dzq 909f61fdd5 feat(shop/order): 添加企业微信id字段到店铺和订单相关实体
在店铺和订单相关的DTO、Entity及查询类中添加corpid字段,用于存储企业微信id信息
同时更新数据库表结构,为shop、shop_order和shop_order_goods表添加corpid字段
2025-06-09 08:23:13 +08:00
dzq 72fdac0083 fix(asset): 添加柜格库存检查逻辑以防止库存不足
在资产审批流程中增加对柜格库存的检查,当商品库存或柜格库存不足时抛出异常。这避免了审批通过后实际库存不足的问题。
2025-06-07 15:00:55 +08:00
dzq d451a93a4e refactor(asset): 重构资产审批流程,分离审批商品信息
将审批商品信息从审批流程中分离出来,使用单独的模型和表进行存储
更新测试数据以匹配新的商品ID和名称
2025-06-07 10:39:47 +08:00
dzq 163dfeb3e8 feat(shop): 新增申请领用商品功能模块
添加申请领用商品相关功能,包括:
- 实体类ApprovalGoodsEntity及Mapper/Service实现
- 新增/修改命令对象AddApprovalGoodsCommand/UpdateApprovalGoodsCommand
- 查询对象SearchApprovalGoodsQuery
- 数据传输对象ApprovalGoodsDTO
- 业务模型ApprovalGoodsModel及工厂类
- 应用服务ApprovalGoodsApplicationService
- 控制器ApprovalGoodsController
2025-06-07 10:21:47 +08:00
dzq 043c0e8cb9 feat(asset): 支持多商品审批流程
重构资产审批流程,将单个商品审批改为支持多商品审批
- 新增ApprovalGoodsInfo类存储商品信息
- 修改审批逻辑处理多个商品
- 更新数据库表结构
- 调整审批通知消息格式
2025-06-07 09:53:34 +08:00
dzq 02dad5beab feat(asset): 新增企业微信资产管理和审批功能
添加企业微信相关字段支持,包括corpid等标识
实现资产商品推送接口,支持批量处理商品信息
新增资产审批功能,包含审批通知和库存检查
重构商品和审批相关DTO及实体类,添加企业微信字段
更新数据库结构,添加相关字段和索引
2025-06-06 17:21:56 +08:00
dzq aefb4366dc fix(shop-goods): 修复商品查询条件及优化SQL查询字段
1. 在SearchShopGoodsQuery中增加externalGoodsId的非空判断,避免当参数为null时生成无效查询条件
2. 简化ShopGoodsMapper中的SQL查询字段,使用g.*替代具体字段列表,同时保持聚合字段不变
2025-06-05 17:30:29 +08:00
dzq 3b80c87f52 feat(asset): 添加外部商品推送功能及相关字段
- 在shop_goods表中新增belong_type和external_goods_id字段
- 实现AssetApiController接收外部商品推送接口
- 添加AssetApplicationService处理商品创建/更新逻辑
- 扩展ShopGoodsDTO、SearchShopGoodsQuery等支持新字段
- 新增PostAssetGoodsCommand和PostAssetGoodsBody数据传输对象
- 添加单元测试验证接口功能
2025-06-05 16:24:41 +08:00
dzq 1b057f6615 feat(用户绑定): 添加企业微信用户与汇邦云用户绑定功能
- 在QyLoginDTO中新增qyUserId和ab98User字段,用于存储绑定信息
- 修改bindQyUser方法返回Ab98UserEntity以便前端展示
- 新增WxLoginController中的bindQyUser接口用于处理绑定请求
- 在PaymentController中完善登录返回信息,包含绑定用户数据
2025-06-04 09:18:50 +08:00
dzq 695e70e7a5 fix: 修复用户信息查询和订单查询的问题
1. 在QyUserApplicationService中添加对ab98UserId为null的判断,避免空指针异常
2. 在ShopGoodsMapper的SQL查询中增加goods_detail和usage_instruction字段
3. 在SearchShopOrderQuery中添加goodsId查询条件,支持按商品ID筛选订单
2025-06-03 17:34:00 +08:00
dzq 4cdabe3db3 feat(用户管理): 实现汇邦云用户与企业微信用户的绑定功能
新增BindQyUserCommand类用于绑定操作
在Ab98UserController中添加绑定接口
完善Ab98UserApplicationService中的绑定逻辑
修改TokenDTO以包含企业微信用户信息
调整相关服务类方法以支持双向关联查询
2025-06-03 16:25:37 +08:00
dzq b65106402e feat(智能柜): 新增运行模式和借呗支付字段及相关功能
- 在smart_cabinet表中添加mode和balance_enable字段
- 在DTO、Entity和Query中新增对应字段
- 修改CabinetCellMapper中参数命名从cabinet_id改为cabinetId
- 在SmartCabinetApplicationService中添加计算已用和可用格口数的逻辑
- 为SmartCabinetEntity中的usedCells和availableCells添加@TableField(exist = false)注解
2025-06-02 16:54:10 +08:00
91 changed files with 2555 additions and 147 deletions

View File

@ -5,6 +5,9 @@ import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.ab98.user.command.BindQyUserCommand;
import com.agileboot.domain.ab98.user.dto.Ab98UserDetailDTO;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.ab98.user.Ab98UserApplicationService;
@ -17,6 +20,7 @@ import io.swagger.v3.oas.annotations.Operation;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@ -73,4 +77,15 @@ public class Ab98UserController extends BaseController {
userApplicationService.deleteUser(new BulkOperationCommand<>(ids));
return ResponseDTO.ok();
}
@Operation(summary = "绑定汇邦云")
@AccessLog(title = "ab98用户管理", businessType = BusinessTypeEnum.MODIFY)
@PostMapping("/bindQyUser")
public ResponseDTO<Void> bindQyUser(@RequestBody BindQyUserCommand command) {
if (command == null || command.getQyUserId() == null || StringUtils.isBlank(command.getName()) || StringUtils.isBlank(command.getIdNum())) {
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "参数错误"));
}
userApplicationService.bindQyUser(command);
return ResponseDTO.ok();
}
}

View File

@ -42,8 +42,15 @@ public class SmartCabinetController extends BaseController {
@Operation(summary = "智能柜列表")
@GetMapping
public ResponseDTO<PageDTO<SmartCabinetDTO>> list(SearchSmartCabinetQuery<SmartCabinetEntity> query) {
PageDTO<SmartCabinetDTO> page = smartCabinetApplicationService.getSmartCabinetList(query);
public ResponseDTO<PageDTO<SmartCabinetDTO>> page(SearchSmartCabinetQuery<SmartCabinetEntity> query) {
PageDTO<SmartCabinetDTO> page = smartCabinetApplicationService.getSmartCabinetPage(query);
return ResponseDTO.ok(page);
}
@Operation(summary = "智能柜列表")
@GetMapping("/list")
public ResponseDTO<List<SmartCabinetDTO>> list(SearchSmartCabinetQuery<SmartCabinetEntity> query) {
List<SmartCabinetDTO> page = smartCabinetApplicationService.getSmartCabinetList(query);
return ResponseDTO.ok(page);
}

View File

@ -13,6 +13,10 @@ import com.agileboot.domain.common.dto.CurrentLoginUserDTO;
import com.agileboot.domain.common.dto.TokenDTO;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
import com.agileboot.domain.qywx.user.QyUserApplicationService;
import com.agileboot.domain.qywx.user.dto.QyUserDTO;
import com.agileboot.domain.qywx.userQySys.SysUserQyUserApplicationService;
import com.agileboot.domain.qywx.userQySys.db.SysUserQyUserEntity;
import com.agileboot.domain.system.menu.MenuApplicationService;
import com.agileboot.domain.system.menu.dto.RouterDTO;
import com.agileboot.domain.system.user.UserApplicationService;
@ -63,6 +67,10 @@ public class LoginController {
private final AccessTokenApplicationService accessTokenApplicationService;
private final SysUserQyUserApplicationService sysUserQyUserApplicationService;
private final QyUserApplicationService qyUserApplicationService;
/**
* 访问首页提示语
*/
@ -114,7 +122,13 @@ public class LoginController {
SystemLoginUser loginUser = AuthenticationUtils.getSystemLoginUser();
CurrentLoginUserDTO currentUserDTO = userApplicationService.getLoginUserInfo(loginUser);
return ResponseDTO.ok(new TokenDTO(token, currentUserDTO));
SysUserQyUserEntity sysUserQyUser = sysUserQyUserApplicationService.getBySysUserId(loginUser.getUserId());
QyUserDTO qyUserDTO = null;
if (sysUserQyUser != null) {
qyUserDTO = qyUserApplicationService.getQyUserDetail(Long.valueOf(sysUserQyUser.getQyUserId()));
}
return ResponseDTO.ok(new TokenDTO(token, currentUserDTO, qyUserDTO));
}
/**

View File

@ -0,0 +1,68 @@
package com.agileboot.admin.controller.shop;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.shop.approvalGoods.ApprovalGoodsApplicationService;
import com.agileboot.domain.shop.approvalGoods.command.AddApprovalGoodsCommand;
import com.agileboot.domain.shop.approvalGoods.command.UpdateApprovalGoodsCommand;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsEntity;
import com.agileboot.domain.shop.approvalGoods.dto.ApprovalGoodsDTO;
import com.agileboot.domain.shop.approvalGoods.query.SearchApprovalGoodsQuery;
import io.swagger.v3.oas.annotations.Operation;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/shop/approvalGoods")
@RequiredArgsConstructor
@Validated
public class ApprovalGoodsController extends BaseController {
private final ApprovalGoodsApplicationService approvalGoodsApplicationService;
@Operation(summary = "申请领用商品列表")
@GetMapping
public ResponseDTO<PageDTO<ApprovalGoodsDTO>> list(SearchApprovalGoodsQuery<ApprovalGoodsEntity> query) {
PageDTO<ApprovalGoodsDTO> page = approvalGoodsApplicationService.getApprovalGoodsList(query);
return ResponseDTO.ok(page);
}
@Operation(summary = "新增申请领用商品")
@AccessLog(title = "申请领用商品管理", businessType = BusinessTypeEnum.ADD)
@PostMapping
public ResponseDTO<Void> add(@Validated @RequestBody AddApprovalGoodsCommand command) {
approvalGoodsApplicationService.addApprovalGoods(command);
return ResponseDTO.ok();
}
@Operation(summary = "修改申请领用商品")
@AccessLog(title = "申请领用商品管理", businessType = BusinessTypeEnum.MODIFY)
@PutMapping("/{id}")
public ResponseDTO<Void> edit(@PathVariable Long id, @Validated @RequestBody UpdateApprovalGoodsCommand command) {
command.setApprovalGoodsId(id);
approvalGoodsApplicationService.updateApprovalGoods(command);
return ResponseDTO.ok();
}
@Operation(summary = "删除申请领用商品")
@AccessLog(title = "申请领用商品管理", businessType = BusinessTypeEnum.DELETE)
@DeleteMapping("/{ids}")
public ResponseDTO<Void> remove(@PathVariable @NotNull List<Long> ids) {
approvalGoodsApplicationService.deleteApprovalGoods(new BulkOperationCommand<>(ids));
return ResponseDTO.ok();
}
}

View File

@ -107,6 +107,13 @@ public class ShopController extends BaseController {
return ResponseDTO.ok(page);
}
@Operation(summary = "获取商店详情")
@GetMapping("/{id}")
public ResponseDTO<ShopDTO> getShopById(@PathVariable Long id) {
ShopDTO shopDTO = shopApplicationService.getShopById(id);
return ResponseDTO.ok(shopDTO);
}
@Operation(summary = "新增商店")
@AccessLog(title = "商店管理", businessType = BusinessTypeEnum.ADD)
@PostMapping

View File

@ -80,7 +80,7 @@ public class ShopGoodsController extends BaseController {
/**
* 获取单个商品信息
*/
@Operation(summary = "商品列表")
@Operation(summary = "商品详情")
// @PreAuthorize("@permission.has('shop:goods:list')")
@GetMapping("/getGoodsInfo")
public ResponseDTO<ShopGoodsDTO> getGoodsInfo(@RequestParam Long goodsId) {

View File

@ -26,11 +26,7 @@ import com.agileboot.domain.qywx.template.command.UpdateTemplateCommand;
import com.agileboot.domain.qywx.template.db.QyTemplateEntity;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -435,7 +431,9 @@ public class QywxScheduleJob {
List<UserListResponse.UserInfo> wxUsersList = userList.getUserlist();
if (wxUsersList != null) {
wxUsers.addAll(wxUsersList);
wxUsers.addAll(wxUsersList.stream()
.filter(u -> wxUsers.stream().noneMatch(wu -> wu.getUserid().equals(u.getUserid())))
.collect(Collectors.toList()));
}
}
@ -451,9 +449,11 @@ public class QywxScheduleJob {
.collect(Collectors.toList());
// 识别需要新增的用户
List<QyUserEntity> finalQyUserList = qyUserList;
Set<String> existingUserIds = qyUserList.stream()
.map(QyUserEntity::getUserid)
.collect(Collectors.toSet());
List<UserListResponse.UserInfo> toAdd = wxUsers.stream()
.filter(wxUser -> finalQyUserList.stream().noneMatch(u -> u.getUserid().equals(wxUser.getUserid())))
.filter(wxUser -> !existingUserIds.contains(wxUser.getUserid()))
.collect(Collectors.toList());
log.info("syncUserInfo toAdd: {}", JSONUtil.toJsonStr(toAdd));

View File

@ -24,6 +24,7 @@ import org.apache.commons.lang3.StringUtils;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 审批请求控制器
@ -80,6 +81,32 @@ public class ApprovalApiController {
}
}
@PostMapping("/handle/asset")
@ApiOperation(value = "处理审批操作")
public ResponseDTO<String> handleAssetApproval(@Valid @RequestBody UpdateReturnApprovalCommand command) {
if (command.getApprovalId() == null) {
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "审批ID不能为空"));
}
if (command.getStatus() == null) {
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "操作状态不能为空"));
}
try {
if (command.getStatus() == 2) {
approvalApplicationService.approveAssetApproval(command);
} else if (command.getStatus() == 3) {
approvalApplicationService.rejectApproval(command);
} else {
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "无效的操作状态"));
}
return ResponseDTO.ok("操作成功");
} catch (Exception e) {
log.error("审批操作失败", e);
return ResponseDTO.fail(new ApiException(ErrorCode.Internal.INTERNAL_ERROR, e.getMessage()));
}
}
/**
* 提交退货审批申请
*
@ -117,4 +144,11 @@ public class ApprovalApiController {
PageDTO<ReturnApprovalEntity> page = approvalApplicationService.getApprovalWithGoodsInfo(query);
return ResponseDTO.ok(page);
}
@GetMapping("/getApprovalOrderGoods")
@ApiOperation(value = "审批列表")
public ResponseDTO<List<ShopOrderGoodsEntity>> getApprovalOrderGoods(Long approvalId) {
List<ShopOrderGoodsEntity> list = approvalApplicationService.getApprovalOrderGoods(approvalId);
return ResponseDTO.ok(list);
}
}

View File

@ -3,8 +3,10 @@ package com.agileboot.api.controller;
import cn.hutool.json.JSONUtil;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.cabinet.cell.CabinetCellApplicationService;
import com.agileboot.domain.cabinet.cell.model.CabinetCellModel;
import com.agileboot.domain.cabinet.cell.model.CabinetCellModelFactory;
import com.agileboot.domain.cabinet.mainboard.model.CabinetMainboardModel;
@ -19,6 +21,7 @@ import com.agileboot.domain.cabinet.smartCabinet.model.SmartCabinetModelFactory;
import com.agileboot.domain.mqtt.MqttService;
import com.agileboot.domain.shop.goods.model.GoodsModel;
import com.agileboot.domain.shop.goods.model.GoodsModelFactory;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@ -39,12 +42,40 @@ public class CabinetCellController {
private final GoodsModelFactory goodsModelFactory;
private final SmartCabinetModelFactory smartCabinetModelFactory;
private final CabinetMainboardModelFactory cabinetMainboardModelFactory;
private final CabinetCellApplicationService cabinetCellApplicationService;
@GetMapping("/detail")
public ResponseDTO<List<CabinetDetailDTO>> getCabinetDetail() {
return ResponseDTO.ok(smartCabinetApplicationService.getCabinetDetail());
public ResponseDTO<List<CabinetDetailDTO>> getCabinetDetail(@RequestParam Long shopId) {
return ResponseDTO.ok(smartCabinetApplicationService.getCabinetDetail(shopId));
}
@Operation(summary = "配置格口商品库存")
@PutMapping("/configureGoodsCellsStock/{cellId}/{goodsId}/{stock}")
public ResponseDTO<Void> configureGoodsCellsStock(@PathVariable Long cellId, @PathVariable Long goodsId, @PathVariable Integer stock) {
cabinetCellApplicationService.configureGoodsCellsStock(cellId, goodsId, stock);
return ResponseDTO.ok();
}
@Operation(summary = "调整格口商品库存")
@PutMapping("/changeGoodsCellsStock/{cellId}/{stock}")
public ResponseDTO<Void> changeGoodsCellsStock(@PathVariable Long cellId, @PathVariable Integer stock) {
if (stock < 0) {
log.error("调整格口商品库存,库存不能小于0");
return ResponseDTO.fail();
}
cabinetCellApplicationService.changeGoodsCellsStock(cellId, stock);
return ResponseDTO.ok();
}
@Operation(summary = "清空格口商品")
@PutMapping("/clearGoodsCells/{cellId}")
public ResponseDTO<Void> clearGoodsCells(@PathVariable Long cellId) {
cabinetCellApplicationService.clearGoodsCells(cellId);
return ResponseDTO.ok();
}
@PostMapping("/openCabinet/{cabinetId}/{pinNo}")
public ResponseDTO<?> openCabinet(@PathVariable Long cabinetId, @PathVariable Integer pinNo,
@RequestBody AddCabinetCellOperationCommand operationCommand) {

View File

@ -10,6 +10,8 @@ import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.common.exception.error.ErrorCode.Client;
import com.agileboot.common.utils.OpenSignUtil;
import com.agileboot.domain.ab98.user.Ab98UserApplicationService;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.common.dto.QyLoginDTO;
import com.agileboot.domain.qywx.accessToken.AccessTokenApplicationService;
import com.agileboot.domain.qywx.accessToken.db.QyAccessTokenEntity;
@ -68,6 +70,7 @@ public class PaymentController {
private final MenuApplicationService menuApplicationService;
private final PaymentApplicationService paymentApplicationService;
private final PaymentOperationLogApplicationService paymentOperationLogApplicationService;
private final Ab98UserApplicationService ab98UserApplicationService;
// 新增回调接口
/**
@ -198,9 +201,16 @@ public class PaymentController {
OpenidResponse openidResponse = QywxApiUtil.convertToOpenid(qyAccessToken.getAccessToken(), userid);
QyUserEntity qyUserEntity = qyUserApplicationService.getUserByUserId(userid, corpid);
QyUserEntity qyUserEntity = qyUserApplicationService.getUserByUserIdAndCorpid(userid, corpid);
Ab98UserEntity ab98User = null;
if (qyUserEntity != null && qyUserEntity.getAb98UserId() != null) {
ab98User = ab98UserApplicationService.getByAb98UserId(qyUserEntity.getAb98UserId());
}
return ResponseDTO.ok(new QyLoginDTO(userid, openidResponse.getOpenid(), isCabinetAdmin, qyUserEntity.getName()));
return ResponseDTO.ok(new QyLoginDTO(userid, openidResponse.getOpenid(), isCabinetAdmin,
qyUserEntity == null ? 0 : qyUserEntity.getId(),
qyUserEntity == null ? "" : qyUserEntity.getName(),
ab98User));
} catch (RestClientException e) {
log.error("qyLogin失败", e);
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "微信服务调用失败"));
@ -235,43 +245,23 @@ public class PaymentController {
* 3. 返回余额最大的用户信息
*/
@GetMapping("/getBalance")
public ResponseDTO<GetBalanceResponse> getBalance(@RequestParam String openid) {
public ResponseDTO<GetBalanceResponse> getBalance(@RequestParam String corpid, @RequestParam String openid) {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> qyAuthCorpInfoEntityList = authCorpInfoApplicationService.getByAppid(appid);
List<QyUserEntity> qyUserEntityList = new ArrayList<>();
for (QyAuthCorpInfoEntity qyAuthCorpInfoEntity : qyAuthCorpInfoEntityList) {
String corpid = qyAuthCorpInfoEntity.getCorpid();
if (!corpid.equals(WeixinConstants.corpid)) {
continue;
}
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, corpid);
UserIdResponse userIdResponse = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), openid);
QyUserEntity qyUser = qyUserApplicationService.getUserByUserId(userIdResponse.getUserid(), corpid);
if (qyUser == null) {
continue;
}
qyUserEntityList.add(qyUser);
}
if (qyUserEntityList.isEmpty()) {
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的openid参数"));
}
// 找出余额最大的用户
QyUserEntity maxBalanceUser = qyUserEntityList.stream()
.filter(user -> user.getBalance() != null)
.max(Comparator.comparing(QyUserEntity::getBalance))
.orElse(null);
if (maxBalanceUser == null) {
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "未找到有效余额信息"));
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, corpid);
UserIdResponse userIdResponse = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), openid);
QyUserEntity qyUser = qyUserApplicationService.getUserByUserIdAndCorpid(userIdResponse.getUserid(), corpid);
if (qyUser == null) {
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的openid参数"));
}
// 创建响应对象假设GetBalanceResponse包含balance字段
GetBalanceResponse response = new GetBalanceResponse(
maxBalanceUser.getUserid(),
maxBalanceUser.getCorpid(),
BigDecimal.ZERO,
BigDecimal.ZERO,
BigDecimal.ZERO);
qyUser.getUserid(),
qyUser.getCorpid(),
qyUser.getBalance(),
qyUser.getUseBalance(),
qyUser.getBalanceLimit());
return ResponseDTO.ok(response);
}
@ -283,7 +273,7 @@ public class PaymentController {
*/
@GetMapping("/getBalanceByQyUserid")
public ResponseDTO<GetBalanceResponse> getBalanceByQyUserid(@RequestParam String corpid, @RequestParam String userid) {
QyUserEntity qyUser = qyUserApplicationService.getUserByUserId(userid, corpid);
QyUserEntity qyUser = qyUserApplicationService.getUserByUserIdAndCorpid(userid, corpid);
// 创建响应对象假设GetBalanceResponse包含balance字段
GetBalanceResponse response = new GetBalanceResponse(

View File

@ -10,6 +10,7 @@ import com.agileboot.domain.shop.category.CategoryApplicationService;
import com.agileboot.domain.shop.category.db.ShopCategoryEntity;
import com.agileboot.domain.shop.category.dto.ShopCategoryDTO;
import com.agileboot.domain.shop.goods.GoodsApplicationService;
import com.agileboot.domain.shop.goods.db.SearchGoodsDO;
import com.agileboot.domain.shop.goods.db.SearchGoodsWithCabinetDO;
import com.agileboot.domain.shop.goods.db.ShopGoodsEntity;
@ -20,6 +21,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import com.agileboot.domain.shop.goods.query.SearchShopGoodsQuery;
import com.agileboot.domain.shop.shop.ShopApplicationService;
import com.agileboot.domain.shop.shop.db.ShopEntity;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
@ -34,10 +38,36 @@ import org.springframework.web.util.UriComponentsBuilder;
@Slf4j
@RequiredArgsConstructor
public class ShopController {
private final ShopApplicationService shopApplicationService;
private final GoodsApplicationService goodsApplicationService;
private final CategoryApplicationService categoryApplicationService;
@GetMapping("/list")
public ResponseDTO<List<ShopEntity>> getShopList(@RequestParam(required = false) String corpid,
@RequestParam(required = false) Long mode) {
List<ShopEntity> shopList;
Long modeValue = mode != null ? mode : 4L;
if (StringUtils.isNotBlank(corpid)) {
shopList = shopApplicationService.getShopListByCorpid(corpid, modeValue);
} else {
shopList = shopApplicationService.getShopListByCorpid(WeixinConstants.corpid, modeValue);
}
return ResponseDTO.ok(shopList);
}
@GetMapping("/goods/list")
public ResponseDTO<List<SearchGoodsDO>> getShopGoodsList(SearchShopGoodsQuery<SearchGoodsDO> query) {
if (StringUtils.isBlank(query.getCorpid())) {
query.setCorpid(WeixinConstants.corpid);
}
if (query.getBelongType() == null) {
query.setBelongType(0);
}
List<SearchGoodsDO> goodsList = goodsApplicationService.selectGoodsList(query);
return ResponseDTO.ok(goodsList);
}
@GetMapping("/goods")
public ResponseDTO<ShopGoodsResponse> getShopGoodsInfo(@RequestParam(required = false) Long shopId) {
/*// 获取商品列表

View File

@ -5,11 +5,14 @@ import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.ab98.api.SsoLoginUserinfo;
import com.agileboot.domain.ab98.user.Ab98UserApplicationService;
import com.agileboot.domain.ab98.user.command.BindQyUserCommand;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.qywx.user.QyUserApplicationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import com.agileboot.domain.ab98.api.Ab98ApiUtil;
@ -25,6 +28,7 @@ import java.util.Map;
public class WxLoginController {
private final QyUserApplicationService qyUserApplicationService;
private final Ab98UserApplicationService ab98UserApplicationService;
private final Ab98UserApplicationService userApplicationService;
@PostMapping("/logout")
@ApiOperation(value = "用户退出登录")
@ -98,16 +102,17 @@ public class WxLoginController {
data.setRegistered(loginResponse.getOutputData().isRegistered());
data.setTel(loginResponse.getOutputData().getTel());
Long ab98UserId = null;
try {
qyUserApplicationService.saveQyUserInfoByAb98(userid, loginResponse.getOutputData(), null);
ab98UserId = ab98UserApplicationService.saveAb98User(openid, loginResponse.getOutputData());
} catch (Exception e) {
log.error("保存汇邦云用户信息到企业用户失败: ", e);
log.error("保存汇邦云用户信息失败: ", e);
}
try {
ab98UserApplicationService.saveAb98User(openid, loginResponse.getOutputData());
qyUserApplicationService.saveQyUserInfoByAb98(ab98UserId, userid, loginResponse.getOutputData(), null);
} catch (Exception e) {
log.error("保存汇邦云用户信息失败: ", e);
log.error("保存汇邦云用户信息到企业用户失败: ", e);
}
return ResponseDTO.ok(data);
@ -136,18 +141,29 @@ public class WxLoginController {
data.setRegistered(true);
data.setTel(loginUserinfo.getPhone());
Long ab98UserId = null;
try {
qyUserApplicationService.saveQyUserInfoByAb98(userid, null, loginUserinfo);
} catch (Exception e) {
log.error("保存汇邦云用户信息到企业用户失败: ", e);
}
try {
ab98UserApplicationService.saveAb98UserByToken(openid, loginUserinfo);
ab98UserId = ab98UserApplicationService.saveAb98UserByToken(openid, loginUserinfo);
} catch (Exception e) {
log.error("保存汇邦云用户信息失败: ", e);
}
try {
qyUserApplicationService.saveQyUserInfoByAb98(ab98UserId, userid, null, loginUserinfo);
} catch (Exception e) {
log.error("保存汇邦云用户信息到企业用户失败: ", e);
}
return ResponseDTO.ok(data);
}
@PostMapping("/bindQyUser")
@ApiOperation(value = "绑定汇邦云", notes = "通过姓名身份证绑定汇邦云")
public ResponseDTO<Ab98UserEntity> bindQyUser(@RequestBody BindQyUserCommand command) {
if (command == null || command.getQyUserId() == null || StringUtils.isBlank(command.getName()) || StringUtils.isBlank(command.getIdNum())) {
return ResponseDTO.fail(new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "参数错误"));
}
Ab98UserEntity ab98User = userApplicationService.bindQyUser(command);
return ResponseDTO.ok(ab98User);
}
}

View File

@ -0,0 +1,55 @@
package com.agileboot.api.controller.asset;
import com.agileboot.common.constant.OpenApiConstants;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.asset.AssetApplicationService;
import com.agileboot.domain.asset.command.PostAssetApprovalCommand;
import com.agileboot.domain.asset.command.PostAssetGoodsCommand;
import com.agileboot.domain.shop.payment.SignUtils;
import com.agileboot.domain.shop.payment.dto.CommonRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import java.io.UnsupportedEncodingException;
@Slf4j
@RestController
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RequiredArgsConstructor
@RequestMapping("/api/asset")
public class AssetApiController {
private final AssetApplicationService assetApplicationService;
@PostMapping("/pushExternalGoods")
public ResponseDTO<Void> pushExternalGoods(@RequestBody String body) {
CommonRequest<PostAssetGoodsCommand> notifyRequest = CommonRequest.build(body, PostAssetGoodsCommand.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.pushExternalGoods(notifyRequest.getBizContent());
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();
}
}

View File

@ -0,0 +1,164 @@
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;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
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
public class AssetApiControllerTest {
@Test
public void testPushExternalGoods() throws UnsupportedEncodingException {
// 1.构建测试商品数据
PostAssetGoodsCommand.GoodsInfo goodsInfo = new PostAssetGoodsCommand.GoodsInfo();
goodsInfo.setExternalGoodsId(1004L);
goodsInfo.setGoodsName("测试笔记本电脑4");
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();
goods.setCorpid("wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw");
goods.setGoodsInfoList(new ArrayList<>());
goods.getGoodsInfoList().add(goodsInfo);
// 2.构造请求体
Map<String, String> params = new HashMap<>();
params.put("timestamp", String.valueOf(System.currentTimeMillis()));
params.put("biz_content", URLEncoder.encode(JSONUtil.toJsonStr(goods), 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/pushExternalGoods", sb.toString());
log.info("接口响应: {}", res);
}
@Test
public void testPostAssetApproval() throws UnsupportedEncodingException {
// 1.构建测试商品数据
PostAssetApprovalCommand approvalCommand = new PostAssetApprovalCommand();
approvalCommand.setCorpid("wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw");
approvalCommand.setExternalApprovalId(1L);
approvalCommand.setApprovalType(1);
approvalCommand.setApplyRemark("申请说明");
approvalCommand.setMobile("12345678901");
approvalCommand.setUserid("123");
approvalCommand.setName("姓名");
approvalCommand.setIsInternal(2);
approvalCommand.setGoodsInfoList(new ArrayList<>());
PostAssetApprovalCommand.ApprovalGoodsInfo goodsInfo = new PostAssetApprovalCommand.ApprovalGoodsInfo();
goodsInfo.setExternalGoodsId(1003L);
goodsInfo.setApplyQuantity(2);
approvalCommand.getGoodsInfoList().add(goodsInfo);
goodsInfo = new PostAssetApprovalCommand.ApprovalGoodsInfo();
goodsInfo.setExternalGoodsId(1004L);
goodsInfo.setApplyQuantity(5);
approvalCommand.getGoodsInfoList().add(goodsInfo);
// 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);
}
@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

@ -2,6 +2,7 @@ package com.agileboot.common.constant;
public class PayApiConstants {
public static final String biz_id = "wxshop";
public static final String old_biz_id = "wxshop_old";
public static final String appkey = "wxshop202503081132";
public static final String pay_url = "http://222.218.10.217:7890/open/trade/wx/jsapi/precreate";
public static final String pay_callback_url = "http://wxshop.ab98.cn/shop-api/api/payment/callback";

View File

@ -179,6 +179,40 @@ public class Ab98ApiUtil {
return null;
}
/**
* 拉取用户信息
* @param appname
* @param appsecret
* @param idnum
* @return
*/
public static Ab98UserDto pullUserInfoByIdnum(String appname,
String appsecret,
String idnum) {
String sign = DigestUtils.md5Hex(String.format("app=%s&idnum=%s&name=&tel=%s", appname, idnum, appsecret));
String url = String.format("https://www.ab98.cn/api/pull?idnum=%s&app=%s&sign=%s"
,idnum
,appname
,sign);
String res = HttpUtil.get(url);
try {
JSONObject o = JSONUtil.parseObj(res);
String state = o.getStr("state");
if (StringUtils.equalsIgnoreCase(state, "ok")) {
return o.get("user", Ab98UserDto.class);
}
} catch (Exception e) {
log.error("获取登录用户信息失败", e);
}
return null;
}
public static void main(String[] args) {
Ab98UserDto userDto = pullUserInfoByIdnum("wxshop", "34164e41f0c6694be6bbbba0dc50c14a", "450981199505186050");
log.info("拉取用户信息: {}", JSONUtil.toJsonStr(userDto));
}
// 基础响应对象
@Data
public static class BaseResponse {

View File

@ -0,0 +1,133 @@
package com.agileboot.domain.ab98.api;
import lombok.Data;
@Data
public class Ab98UserDto {
/**
* 统一系统的记录ID
*/
private String ssoUid;
/**
* 真实姓名
*/
private String realName;
/**
* 性别
*/
private String sex;
/**
* 手机号码
*/
private String phone;
/**
* 在统一登录平台绑定的药小云公众号openid
*/
private String openid;
/**
* 微信昵称
*/
private String nickname;
/**
* 微信头像
*/
private String headimage;
/**
* 身份证地址
*/
private String idCardAddress;
/**
* 身份证号
*/
private String idCardNo;
/**
* 签发机关
*/
private String authority;
/**
* 有效期
*/
private String validdate;
/**
* 身份证正面图像链接
*/
private String idCardFront;
/**
* 身份证背面图像链接
*/
private String idCardBack;
/**
* 人脸图像链接
*/
private String facePicture;
/**
* 营业执照图片链接
*/
private String businessLicense;
/**
* 统一社会信用代码三合一之前为注册号
*/
private String regNum;
/**
* 公司名称
*/
private String companyName;
/**
* 注册资本
*/
private String capital;
/**
* 法定代表人
*/
private String person;
/**
* 注册地址
*/
private String address;
/**
* 民族
*/
private String nation;
/**
* 经营范围
*/
private String business;
/**
* 主体类型
*/
private String type;
/**
* 营业期限
*/
private String period;
/**
* 组成形式
*/
private String composingForm;
/**
* 成立日期
*/
private String setDate;
/**
* 门店图片链接
*/
private String shopPicture;
/**
* 门店环境图片链接
*/
private String environmentPicture;
/**
* 当前系统的门店老板的账号ID此字段不为空时表示门店老板添加员工
*/
private String parentUserId;
/**
* 人脸特征的base64字符串
*/
private String faceFeatureBase64;
/**
* 人员角色:0-超级管理员 1-普通管理员 2-普通用户
*/
private Integer role;
}

View File

@ -1,8 +1,12 @@
package com.agileboot.domain.ab98.user;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.ab98.api.Ab98ApiUtil;
import com.agileboot.domain.ab98.api.Ab98UserDto;
import com.agileboot.domain.ab98.api.SsoLoginUserinfo;
import com.agileboot.domain.ab98.user.command.BindQyUserCommand;
import com.agileboot.domain.ab98.user.dto.Ab98UserDetailDTO;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.ab98.user.command.AddAb98UserCommand;
@ -13,12 +17,21 @@ import com.agileboot.domain.ab98.user.dto.Ab98UserDTO;
import com.agileboot.domain.ab98.user.model.Ab98UserModel;
import com.agileboot.domain.ab98.user.model.Ab98UserModelFactory;
import com.agileboot.domain.ab98.user.query.SearchAb98UserQuery;
import com.agileboot.domain.qywx.user.db.QyUserEntity;
import com.agileboot.domain.qywx.user.db.QyUserService;
import com.agileboot.domain.qywx.userQySys.db.SysUserQyUserEntity;
import com.agileboot.domain.qywx.userQySys.db.SysUserQyUserService;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.agileboot.domain.system.user.db.SysUserService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
@Service
@ -27,6 +40,9 @@ import org.springframework.stereotype.Service;
public class Ab98UserApplicationService {
private final Ab98UserService userService;
private final Ab98UserModelFactory userModelFactory;
private final QyUserService qyUserService;
private final SysUserQyUserService sysUserQyUserService;
private final SysUserService sysUserService;
public PageDTO<Ab98UserDTO> getUserList(SearchAb98UserQuery<Ab98UserEntity> query) {
Page<Ab98UserEntity> page = userService.getUserListWithTagFilter(query);
@ -74,8 +90,12 @@ public class Ab98UserApplicationService {
}
public void saveAb98User(String openid, Ab98ApiUtil.LoginData loginData) {
Ab98UserEntity ab98UserEntity = userService.selectByOpenidAndUserid(openid, loginData.getUserid());
public Long saveAb98User(String openid, Ab98ApiUtil.LoginData loginData) {
// Ab98UserEntity ab98UserEntity = userService.selectByOpenidAndUserid(openid, loginData.getUserid());
if (loginData == null || StringUtils.isBlank(loginData.getIdnum())) {
return null;
}
Ab98UserEntity ab98UserEntity = userService.getByIdnum(loginData.getIdnum());
if (ab98UserEntity != null &&
StringUtils.equals(loginData.getName(), ab98UserEntity.getName())
) {
@ -90,6 +110,7 @@ public class Ab98UserApplicationService {
command.setAddress(loginData.getAddress());
command.setRegistered(loginData.isRegistered());
updateUser(command);
return ab98UserEntity.getAb98UserId();
} else {
AddAb98UserCommand command = new AddAb98UserCommand();
command.setOpenid(openid);
@ -103,13 +124,22 @@ public class Ab98UserApplicationService {
command.setFaceImg(loginData.getFace_img());
command.setAddress(loginData.getAddress());
command.setRegistered(loginData.isRegistered());
addUser(command);
command.initBaseEntity();
Ab98UserModel model = userModelFactory.create();
model.loadAddCommand(command);
model.insert();
return model.getAb98UserId();
}
}
public void saveAb98UserByToken(String openid, SsoLoginUserinfo loginUserinfo) {
Ab98UserEntity ab98UserEntity = userService.selectByOpenidAndUserid(openid, String.valueOf(loginUserinfo.getId()));
public Long saveAb98UserByToken(String openid, SsoLoginUserinfo loginUserinfo) {
if (loginUserinfo == null || StringUtils.isBlank(loginUserinfo.getIdCardNo())) {
return null;
}
// Ab98UserEntity ab98UserEntity = userService.selectByOpenidAndUserid(openid, String.valueOf(loginUserinfo.getId()));
Ab98UserEntity ab98UserEntity = userService.getByIdnum(loginUserinfo.getIdCardNo());
if (ab98UserEntity != null &&
StringUtils.equals(loginUserinfo.getName(), ab98UserEntity.getName())
) {
@ -124,6 +154,7 @@ public class Ab98UserApplicationService {
command.setAddress(loginUserinfo.getAddress());
command.setRegistered(true);
updateUser(command);
return ab98UserEntity.getAb98UserId();
} else {
AddAb98UserCommand command = new AddAb98UserCommand();
command.setOpenid(openid);
@ -137,7 +168,79 @@ public class Ab98UserApplicationService {
command.setFaceImg(loginUserinfo.getFace());
command.setAddress(loginUserinfo.getAddress());
command.setRegistered(true);
addUser(command);
command.initBaseEntity();
Ab98UserModel model = userModelFactory.create();
model.loadAddCommand(command);
model.insert();
return model.getAb98UserId();
}
}
public Ab98UserEntity bindQyUser(BindQyUserCommand bindQyUserCommand) {
QyUserEntity qyUser = qyUserService.getById(bindQyUserCommand.getQyUserId());
if (qyUser == null) {
throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "企业微信用户不存在");
}
Ab98UserEntity ab98UserEntity = userService.getByIdnum(bindQyUserCommand.getIdNum());
if (ab98UserEntity != null && StringUtils.equals(ab98UserEntity.getName(), bindQyUserCommand.getName())) {
saveQyUserInfoByAb98(qyUser, ab98UserEntity);
return ab98UserEntity;
}
Ab98UserDto ab98UserDto = Ab98ApiUtil.pullUserInfoByIdnum("wxshop", "34164e41f0c6694be6bbbba0dc50c14a", bindQyUserCommand.getIdNum());
if (ab98UserDto == null) {
throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "Ab98用户不存在");
}
if (!StringUtils.equals(ab98UserDto.getRealName(), bindQyUserCommand.getName())) {
throw new ApiException(ErrorCode.Internal.INTERNAL_ERROR, "姓名不匹配");
}
AddAb98UserCommand addAb98UserCommand = getAddAb98UserCommand(ab98UserDto);
Ab98UserModel model = userModelFactory.create();
model.loadAddCommand(addAb98UserCommand);
model.insert();
ab98UserEntity = model.selectById();
saveQyUserInfoByAb98(qyUser, ab98UserEntity);
return ab98UserEntity;
}
@NotNull
private static AddAb98UserCommand getAddAb98UserCommand(Ab98UserDto ab98UserDto) {
AddAb98UserCommand addAb98UserCommand = new AddAb98UserCommand();
addAb98UserCommand.setOpenid(ab98UserDto.getOpenid());
addAb98UserCommand.setUserid(ab98UserDto.getSsoUid());
addAb98UserCommand.setName(ab98UserDto.getRealName());
addAb98UserCommand.setTel(ab98UserDto.getPhone());
addAb98UserCommand.setSex(ab98UserDto.getSex());
addAb98UserCommand.setIdnum(ab98UserDto.getIdCardNo());
addAb98UserCommand.setIdcardFront(ab98UserDto.getIdCardFront());
addAb98UserCommand.setIdcardBack(ab98UserDto.getIdCardBack());
addAb98UserCommand.setFaceImg(ab98UserDto.getFacePicture());
addAb98UserCommand.setAddress(ab98UserDto.getAddress());
addAb98UserCommand.setRegistered(true);
addAb98UserCommand.initBaseEntity();
return addAb98UserCommand;
}
public void saveQyUserInfoByAb98(QyUserEntity qyUser, Ab98UserEntity ab98UserEntity) {
SysUserQyUserEntity sysUserQyUser = sysUserQyUserService.getByQyUserId(qyUser.getId());
SysUserEntity sysUser = null;
if (sysUserQyUser != null) {
sysUser = sysUserService.getById(sysUserQyUser.getSysUserId());
}
qyUser.setAb98UserId(ab98UserEntity.getAb98UserId());
qyUser.setAvatar(ab98UserEntity.getFaceImg());
qyUser.setGender(ab98UserEntity.getSex());
qyUser.setMobile(ab98UserEntity.getTel());
qyUser.updateById();
if (sysUser!= null) {
sysUser.setAvatar(ab98UserEntity.getFaceImg());
sysUser.setSex(ab98UserEntity.getSex().contains("") ? 0 : 1);
sysUser.setPhoneNumber(ab98UserEntity.getTel());
sysUser.updateById();
}
}
}

View File

@ -0,0 +1,13 @@
package com.agileboot.domain.ab98.user.command;
import lombok.Data;
@Data
public class BindQyUserCommand {
private Long qyUserId;
private String name;
private String idNum;
}

View File

@ -26,5 +26,7 @@ public interface Ab98UserService extends IService<Ab98UserEntity> {
Ab98UserEntity getByUserid(String userid);
Ab98UserEntity getByIdnum(String idnum);
Ab98UserEntity selectByOpenidAndUserid(String openid, String userid);
}

View File

@ -2,6 +2,7 @@ package com.agileboot.domain.ab98.user.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@ -40,6 +41,14 @@ public class Ab98UserServiceImpl extends ServiceImpl<Ab98UserMapper, Ab98UserEnt
return baseMapper.selectByUserid(userid);
}
@Override
public Ab98UserEntity getByIdnum(String idnum) {
QueryWrapper<Ab98UserEntity> wrapper = new QueryWrapper<Ab98UserEntity>();
wrapper.eq("idnum", idnum)
.last("LIMIT 1");
return this.getOne(wrapper);
}
@Override
public Ab98UserEntity selectByOpenidAndUserid(String openid, String userid) {
return baseMapper.selectByOpenidAndUserid(openid, userid);

View File

@ -0,0 +1,274 @@
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;
import com.agileboot.domain.cabinet.cell.db.CabinetCellService;
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.approvalGoods.command.AddApprovalGoodsCommand;
import com.agileboot.domain.shop.approvalGoods.model.ApprovalGoodsModel;
import com.agileboot.domain.shop.approvalGoods.model.ApprovalGoodsModelFactory;
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.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
@Service
@RequiredArgsConstructor
public class AssetApplicationService {
private final ShopGoodsService shopGoodsService;
private final GoodsModelFactory goodsModelFactory;
private final ReturnApprovalModelFactory returnApprovalModelFactory;
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
private final AccessTokenApplicationService accessTokenApplicationService;
private final QyUserService qyUserService;
private final ApprovalGoodsModelFactory approvalGoodsModelFactory;
private final CabinetCellService cabinetCellService;
public void pushExternalGoods(PostAssetGoodsCommand postAssetGoodsCommand) {
log.info("postAssetGoodsCommand: {}", JSONUtil.toJsonStr(postAssetGoodsCommand));
if (postAssetGoodsCommand == null || postAssetGoodsCommand.getGoodsInfoList() == null || postAssetGoodsCommand.getGoodsInfoList().isEmpty()) {
throw new IllegalArgumentException("GoodsInfoList cannot be null or empty");
}
if (postAssetGoodsCommand.getCorpid() == null) {
throw new IllegalArgumentException("Corpid cannot be null");
}
for (PostAssetGoodsCommand.GoodsInfo command : postAssetGoodsCommand.getGoodsInfoList()) {
if (command == null || command.getExternalGoodsId() == null) {
throw new IllegalArgumentException("ExternalGoodsId cannot be null");
}
ShopGoodsEntity shopGoodsEntity = shopGoodsService.getGoodsByExternalGoodsId(postAssetGoodsCommand.getCorpid(), command.getExternalGoodsId());
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.getMonthlyPurchaseLimit() != null) {
shopGoodsEntity.setMonthlyPurchaseLimit(command.getMonthlyPurchaseLimit());
}
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.setMonthlyPurchaseLimit(command.getMonthlyPurchaseLimit());
goodsModel.initBaseEntity();
goodsModel.setCategoryId(0L);
goodsModel.setStatus(1);
goodsModel.insert();
}
}
}
public void postAssetApprovalCommand(PostAssetApprovalCommand postAssetApprovalCommand) {
if (postAssetApprovalCommand == null || postAssetApprovalCommand.getGoodsInfoList() == null || postAssetApprovalCommand.getGoodsInfoList().isEmpty()) {
throw new IllegalArgumentException("ExternalGoodsId cannot be null");
}
if (StringUtils.isBlank(postAssetApprovalCommand.getCorpid())) {
throw new IllegalArgumentException("Corpid cannot be null");
}
AddReturnApprovalCommand returnApprovalCommand = new AddReturnApprovalCommand();
BeanUtils.copyProperties(postAssetApprovalCommand, returnApprovalCommand);
if (returnApprovalCommand.getApprovalType() == null) {
returnApprovalCommand.setApprovalType(1);
}
ReturnApprovalModel returnApprovalModel = returnApprovalModelFactory.create();
returnApprovalModel.initBaseEntity();
returnApprovalModel.loadAddCommand(returnApprovalCommand);
List<ApprovalGoodsModel> approvalGoodsModels = new ArrayList<>();
for (PostAssetApprovalCommand.ApprovalGoodsInfo command : postAssetApprovalCommand.getGoodsInfoList()) {
if (command.getApplyQuantity() == null || command.getApplyQuantity() <= 0) {
throw new IllegalArgumentException("ApplyQuantity must be greater than 0");
}
ShopGoodsEntity shopGoodsEntity = shopGoodsService.getGoodsByExternalGoodsId(postAssetApprovalCommand.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");
}
/*List<CabinetCellEntity> cabinetCellEntities = cabinetCellService.selectByGoodsId(shopGoodsEntity.getGoodsId());
if (cabinetCellEntities == null || cabinetCellEntities.isEmpty()) {
throw new IllegalArgumentException("No cabinet cells found for the goods");
}
Integer totalStock = cabinetCellEntities.stream().map(CabinetCellEntity::getStock).reduce(0, Integer::sum);
if (totalStock < command.getApplyQuantity()) {
throw new IllegalArgumentException("Insufficient stock in cabinet cells");
}*/
AddApprovalGoodsCommand approvalGoodsCommand = new AddApprovalGoodsCommand();
approvalGoodsCommand.initBaseEntity();
BeanUtils.copyProperties(postAssetApprovalCommand, approvalGoodsCommand);
BeanUtils.copyProperties(command, approvalGoodsCommand);
BeanUtils.copyProperties(shopGoodsEntity, approvalGoodsCommand);
ApprovalGoodsModel approvalGoodsModel = approvalGoodsModelFactory.create();
approvalGoodsModel.loadAddCommand(approvalGoodsCommand);
approvalGoodsModels.add(approvalGoodsModel);
}
returnApprovalModel.insert();
approvalGoodsModels.stream()
.peek(approvalGoodsModel -> approvalGoodsModel.setApprovalId(returnApprovalModel.getApprovalId()))
.forEach(ApprovalGoodsModel::insert);
ShopGoodsEntity firstGoods = shopGoodsService.getGoodsByExternalGoodsId(postAssetApprovalCommand.getCorpid(), postAssetApprovalCommand.getGoodsInfoList().get(0).getExternalGoodsId());
// 发送审核消息
try {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
.filter(a -> postAssetApprovalCommand.getCorpid().equals(a.getCorpid()))
.findFirst().orElse(null);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, postAssetApprovalCommand.getCorpid());
// 获取用户ID
List<String> adminUserIds = qyUserService.selectAdminUserIds(postAssetApprovalCommand.getCorpid());
String toUser = String.join("|", adminUserIds);
String toparty = "";
String totag = "";
List<NewsArticle> articles = new ArrayList<>();
NewsArticle article = new NewsArticle();
article.setTitle("耗材领用审核通知");
if (postAssetApprovalCommand.getGoodsInfoList().size() > 1) {
article.setDescription(postAssetApprovalCommand.getName() + " 申请领用" + firstGoods.getGoodsName() + "" + postAssetApprovalCommand.getGoodsInfoList().size() + "件商品");
} else {
article.setDescription(postAssetApprovalCommand.getName() + " 申请领用" + firstGoods.getGoodsName());
}
article.setPicurl(firstGoods.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);
}
}
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("https://kvkk.cn/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

@ -0,0 +1,51 @@
package com.agileboot.domain.asset.command;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
@EqualsAndHashCode
@Data
public class PostAssetApprovalCommand {
@ApiModelProperty("企业微信id")
private String corpid;
@ApiModelProperty("外部归属类型的审批ID")
private Long externalApprovalId;
@ApiModelProperty("审批类型0为借还柜 1为固资通")
private Integer approvalType;
@ApiModelProperty("申请说明")
private String applyRemark;
@ApiModelProperty("核销码")
private String code;
@ApiModelProperty("手机号码")
private String mobile;
@ApiModelProperty("企业微信用户ID或汇邦云用户ID")
private String userid;
@ApiModelProperty("用户姓名")
private String name;
@ApiModelProperty("是否内部用户0否 1汇邦云用户 2企业微信用户")
private Integer isInternal;
@ApiModelProperty("审批信息列表")
private List<ApprovalGoodsInfo> goodsInfoList;
@Data
public static class ApprovalGoodsInfo {
@ApiModelProperty("外部归属类型的商品ID")
private Long externalGoodsId;
@ApiModelProperty("申请数量")
private Integer applyQuantity;
}
}

View File

@ -0,0 +1,56 @@
package com.agileboot.domain.asset.command;
import com.agileboot.common.annotation.ExcelColumn;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.List;
@EqualsAndHashCode
@Data
public class PostAssetGoodsCommand {
@ApiModelProperty("企业微信id")
private String corpid;
@ApiModelProperty("商品信息列表")
private List<GoodsInfo> goodsInfoList;
@Data
public static class GoodsInfo {
@ApiModelProperty("外部归属类型的商品ID")
private Long externalGoodsId;
@ApiModelProperty("商品名称")
private String goodsName;
@ApiModelProperty("销售价格")
private BigDecimal price;
@ApiModelProperty("库存数量")
private Integer stock;
@ApiModelProperty("免审批0否 1是")
private Integer autoApproval;
@ApiModelProperty("封面图URL")
private String coverImg;
@ApiModelProperty("商品详情支持2000汉字+10个图片链接")
private String goodsDetail;
@ApiModelProperty("商品使用说明")
private String usageInstruction;
@ApiModelProperty("归属类型0-借还柜 1-固资通)")
private Integer belongType;
@ApiModelProperty("每人每月限购数量")
private Integer monthlyPurchaseLimit;
}
}

View File

@ -71,7 +71,7 @@ public interface CabinetCellMapper extends BaseMapper<CabinetCellEntity> {
@Select("SELECT * " +
"FROM cabinet_cell " +
"WHERE cabinet_id = #{cabinet_id} AND deleted = 0 " +
"WHERE cabinet_id = #{cabinetId} AND deleted = 0 " +
"ORDER BY cell_id ASC")
List<CabinetCellDO> selectCabinetCellDOList(@Param("cabinetId") Long cabinetId);
}

View File

@ -22,7 +22,9 @@ public enum CabinetTemplateEnum {
/** 120口机柜模板(6X20)6块主板每块主板20个单元格 */
CABINET_120(8, "cabinet_120.jpg", "120口机柜", 6, 20),
/** 4口机柜模板1块主板每块主板4个单元格 */
CABINET_4(9, "cabinet_4.jpg","4口机柜", 1, 4);
CABINET_4(9, "cabinet_4.jpg","4口机柜", 1, 4),
/** 10口机柜模板1块主板每块主板10个单元格 */
CABINET_10(1, "cabinet_16.jpg", "10口机柜", 1, 10);
/** 模板代码 */
private final int code;

View File

@ -2,6 +2,7 @@ package com.agileboot.domain.cabinet.smartCabinet;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.cabinet.cell.command.AddCabinetCellCommand;
import com.agileboot.domain.cabinet.cell.db.CabinetCellDO;
import com.agileboot.domain.cabinet.cell.db.CabinetCellEntity;
import com.agileboot.domain.cabinet.cell.db.CabinetCellService;
import com.agileboot.domain.cabinet.cell.model.CabinetCellModel;
@ -29,6 +30,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -44,7 +46,7 @@ public class SmartCabinetApplicationService {
private final CabinetMainboardModelFactory cabinetMainboardModelFactory;
private final CabinetCellModelFactory cabinetCellModelFactory;
public PageDTO<SmartCabinetDTO> getSmartCabinetList(SearchSmartCabinetQuery<SmartCabinetEntity> query) {
public PageDTO<SmartCabinetDTO> getSmartCabinetPage(SearchSmartCabinetQuery<SmartCabinetEntity> query) {
List<ShopEntity> shopEntities = shopService.selectAll();
Page<SmartCabinetEntity> page = smartCabinetService.getCabinetList(query);
@ -63,10 +65,36 @@ public class SmartCabinetApplicationService {
return new PageDTO<>(dtoList, page.getTotal());
}
public List<SmartCabinetDTO> getSmartCabinetList(SearchSmartCabinetQuery<SmartCabinetEntity> query) {
List<ShopEntity> shopEntities = shopService.selectAll();
List<SmartCabinetDTO> dtoList = smartCabinetService.list(query.toQueryWrapper()).stream()
.map(SmartCabinetDTO::new)
.collect(Collectors.toList());
dtoList.forEach(dto ->
dto.setShopName(
shopEntities.stream()
.filter(shop -> shop.getShopId().equals(dto.getShopId()))
.findFirst()
.map(ShopEntity::getShopName)
.orElse(""))
);
return dtoList;
}
public SmartCabinetDTO getSmartCabinetById(Long cabinetId) {
SmartCabinetEntity cabinet = smartCabinetService.getById(cabinetId);
SmartCabinetDTO dto = new SmartCabinetDTO(cabinet);
List<CabinetCellDO> cabinetCellDOS = cabinetCellService.selectCabinetCellDOList(cabinetId);
dto.setUsedCells(Math.toIntExact(cabinetCellDOS.stream()
.filter(cell -> cell.getUsageStatus().equals(2))
.count()));
dto.setAvailableCells(Math.toIntExact(cabinetCellDOS.stream()
.filter(cell -> cell.getUsageStatus().equals(1))
.count()));
List<ShopEntity> shopEntities = shopService.selectAll();
dto.setShopName(
shopEntities.stream()
@ -119,11 +147,32 @@ public class SmartCabinetApplicationService {
* 获取所有智能柜的详细信息
* @return 包含柜体信息单元格信息和商品信息的列表
*/
public List<CabinetDetailDTO> getCabinetDetail() {
public List<CabinetDetailDTO> getCabinetDetail(Long shopId) {
// 获取所有智能柜单元格和商品的基础数据
List<SmartCabinetEntity> smartCabinets = smartCabinetService.selectAll();
List<CabinetCellEntity> cabinetCells = cabinetCellService.selectAll();
List<ShopGoodsEntity> goodsList = shopGoodsService.selectAll();
QueryWrapper<SmartCabinetEntity> smartCabinetEntityQueryWrapper = new QueryWrapper<>();
smartCabinetEntityQueryWrapper.eq("shop_id", shopId)
.eq("deleted", false);
List<SmartCabinetEntity> smartCabinets = smartCabinetService.list(smartCabinetEntityQueryWrapper);
QueryWrapper<CabinetCellEntity> cabinetCellEntityQueryWrapper = new QueryWrapper<>();
cabinetCellEntityQueryWrapper.in("cabinet_id",
smartCabinets.stream()
.map(SmartCabinetEntity::getCabinetId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList()))
.eq("deleted", false);
List<CabinetCellEntity> cabinetCells = cabinetCellService.list(cabinetCellEntityQueryWrapper);
QueryWrapper<ShopGoodsEntity> shopGoodsEntityQueryWrapper = new QueryWrapper<>();
shopGoodsEntityQueryWrapper.in("goods_id",
cabinetCells.stream()
.map(CabinetCellEntity::getGoodsId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList()))
.eq("deleted", false);
List<ShopGoodsEntity> goodsList = shopGoodsService.list(shopGoodsEntityQueryWrapper);
List<CabinetDetailDTO> result = new ArrayList<>();
// 遍历每个智能柜构建详细信息

View File

@ -43,6 +43,14 @@ public class SmartCabinetEntity extends BaseEntity<SmartCabinetEntity> {
@TableField("main_cabinet")
private Long mainCabinet;
@ApiModelProperty("运行模式0-支付模式 1-审批模式 2-借还模式 3-会员模式)")
@TableField("mode")
private Integer mode;
@ApiModelProperty("借呗支付1-正常使用 0-禁止使用)")
@TableField("balance_enable")
private Integer balanceEnable;
@ApiModelProperty("归属类型0-借还柜 1-固资通)")
@TableField("belong_type")
private Integer belongType;
@ -72,9 +80,11 @@ public class SmartCabinetEntity extends BaseEntity<SmartCabinetEntity> {
private Integer location;
@ApiModelProperty("已用格口数")
@TableField(exist = false)
private Integer usedCells;
@ApiModelProperty("未用格口数")
@TableField(exist = false)
private Integer availableCells;
@Override

View File

@ -32,6 +32,12 @@ public class SmartCabinetDTO {
@ExcelColumn(name = "归属主柜ID")
private Long mainCabinet;
@ExcelColumn(name = "运行模式0-支付模式 1-审批模式 2-借还模式 3-会员模式)")
private Integer mode;
@ExcelColumn(name = "借呗支付1-正常使用 0-禁止使用)")
private Integer balanceEnable;
@ExcelColumn(name = "归属类型0-借还柜 1-固资通)")
private Integer belongType;

View File

@ -20,6 +20,8 @@ public class SearchSmartCabinetQuery<T> extends AbstractPageQuery<T> {
private Long shopId;
private Integer belongType;
private Integer mode;
private Integer balanceEnable;
@Override
public QueryWrapper<T> addQueryCondition() {
@ -31,6 +33,8 @@ public class SearchSmartCabinetQuery<T> extends AbstractPageQuery<T> {
.eq(mqttServerId!= null, "sc.mqtt_server_id", mqttServerId)
.eq(shopId!= null, "sc.shop_id", shopId)
.eq(belongType!= null, "sc.belong_type", belongType)
.eq(mode != null, "sc.mode", mode)
.eq(balanceEnable != null, "sc.balance_enable", balanceEnable)
.eq(StrUtil.isNotEmpty(templateNo), "sc.template_no", templateNo)
.eq("sc.deleted", false)
.between(startTime != null && endTime != null, "sc.create_time", startTime, endTime)

View File

@ -1,5 +1,6 @@
package com.agileboot.domain.common.dto;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -10,5 +11,8 @@ public class QyLoginDTO {
private String userid;
private String openid;
private Integer isCabinetAdmin;
private Integer qyUserId;
private String name;
private Ab98UserEntity ab98User;
}

View File

@ -1,5 +1,6 @@
package com.agileboot.domain.common.dto;
import com.agileboot.domain.qywx.user.dto.QyUserDTO;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -14,4 +15,5 @@ public class TokenDTO {
private CurrentLoginUserDTO currentUser;
private QyUserDTO qyUser;
}

View File

@ -66,7 +66,7 @@ public class MqttService implements MqttCallback {
if (existingConfig != null) {
existingConfig.client.subscribe(config.getTopicFilter());
clientConfigs.add(new ClientConfig(existingConfig.client, config));
log.info("复用已有MQTT连接{} 账号:{}", config.getServerUrl(), config.getUsername());
log.info("复用已有MQTT连接{} 账号:{} 主题:{}", config.getServerUrl(), config.getUsername(), config.getPublishTopic());
continue;
}
@ -88,7 +88,7 @@ public class MqttService implements MqttCallback {
client.connect(options);
client.subscribe(config.getTopicFilter());
clientConfigs.add(new ClientConfig(client, config));
log.info("成功连接MQTT服务器{} 账号:{}", config.getServerUrl(), config.getUsername());
log.info("成功连接MQTT服务器{} 账号:{} 主题:{}", config.getServerUrl(), config.getUsername(), config.getPublishTopic());
}
}
@ -104,6 +104,7 @@ public class MqttService implements MqttCallback {
.filter(cc -> cc.config.getMqttServerId().equals(mqttServerId))
.forEach(cc -> {
try {
log.info("发送消息到主题:{} 消息:{}", cc.config.getPublishTopic(), data + bcc);
cc.client.publish(cc.config.getPublishTopic(), message);
} catch (MqttException e) {
log.error("消息发送失败", e);

View File

@ -54,4 +54,8 @@ public class AuthCorpInfoApplicationService {
public List<QyAuthCorpInfoEntity> getByAppid(String appid) {
return authCorpInfoService.getByAppid(appid);
}
public QyAuthCorpInfoEntity selectByAppidAndCorpid(String appid, String corpid) {
return authCorpInfoService.selectByAppidAndCorpid(appid, corpid);
}
}

View File

@ -34,4 +34,8 @@ public interface QyAuthCorpInfoMapper extends BaseMapper<QyAuthCorpInfoEntity> {
@Select("SELECT * FROM qy_auth_corp_info WHERE appid = #{appid}")
List<QyAuthCorpInfoEntity> selectByAppid(@Param("appid")String appid);
@Select("SELECT * FROM qy_auth_corp_info WHERE appid = #{appid} AND corpid = #{corpid} LIMIT 1")
QyAuthCorpInfoEntity selectByAppidAndCorpid(@Param("appid")String appid, @Param("corpid")String corpid);
}

View File

@ -3,6 +3,8 @@ package com.agileboot.domain.qywx.authCorpInfo.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
@ -20,4 +22,6 @@ public interface QyAuthCorpInfoService extends IService<QyAuthCorpInfoEntity> {
List<QyAuthCorpInfoEntity> selectAll();
List<QyAuthCorpInfoEntity> getByAppid(String appid);
QyAuthCorpInfoEntity selectByAppidAndCorpid(String appid, String corpid);
}

View File

@ -33,4 +33,9 @@ public class QyAuthCorpInfoServiceImpl extends ServiceImpl<QyAuthCorpInfoMapper,
public List<QyAuthCorpInfoEntity> getByAppid(String appid) {
return baseMapper.selectByAppid(appid);
}
@Override
public QyAuthCorpInfoEntity selectByAppidAndCorpid(String appid, String corpid) {
return baseMapper.selectByAppidAndCorpid(appid, corpid);
}
}

View File

@ -4,6 +4,9 @@ import com.agileboot.common.constant.WeixinConstants;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.ab98.api.Ab98ApiUtil;
import com.agileboot.domain.ab98.api.SsoLoginUserinfo;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
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.qywx.user.command.AddQyUserCommand;
import com.agileboot.domain.qywx.user.command.UpdateQyUserCommand;
@ -39,6 +42,9 @@ public class QyUserApplicationService {
private final SysUserQyUserService sysUserQyUserService;
private final SysUserService sysUserService;
private final SysRoleService sysRoleService;
private final Ab98UserService ab98UserService;
private final RedisCacheService redisCache;
public PageDTO<QyUserDTO> getUserList(SearchQyUserQuery<QyUserEntity> query) {
Page<QyUserEntity> page = userService.getUserList(query);
@ -60,6 +66,12 @@ public class QyUserApplicationService {
dto.setRoleName(sysRole.getRoleName());
}
}
if (user.getAb98UserId() != null) {
Ab98UserEntity ab98User = ab98UserService.getById(user.getAb98UserId());
if (ab98User != null) {
dto.setOpenid(ab98User.getOpenid());
}
}
return dto;
}
@ -70,6 +82,7 @@ public class QyUserApplicationService {
public void addUser(AddQyUserCommand command) {
UserModel model = qyUserModelFactory.create();
model.loadAddCommand(command);
model.initBaseEntity();
model.insert();
}
@ -79,6 +92,7 @@ public class QyUserApplicationService {
command.setBalance(command.getBalanceLimit().subtract(model.getUseBalance()));
}
model.loadUpdateCommand(command);
model.setUpdaterId(0L);
model.updateById();
if (command.getRoleId() == null) {
@ -88,7 +102,9 @@ public class QyUserApplicationService {
if (sysUserQyUser != null) {
SysUserEntity sysUser = sysUserService.getById(sysUserQyUser.getSysUserId());
sysUser.setRoleId(command.getRoleId() > 0 ? command.getRoleId() : null);
sysUserService.updateById(sysUser);
sysUser.updateById();
redisCache.userCache.delete(sysUser.getUserId());
}
}
@ -99,43 +115,50 @@ public class QyUserApplicationService {
}
}
public QyUserEntity getUserByUserId(String userid, String corpid) {
return userService.getUserByUserId(userid, corpid);
public List<QyUserEntity> getUserByUserId(String userid) {
return userService.getUserByUserId(userid);
}
public void saveQyUserInfoByAb98(String userid, Ab98ApiUtil.LoginData data, SsoLoginUserinfo loginUserinfo) {
QyUserEntity qyUser = getUserByUserId(userid, WeixinConstants.corpid);
if (qyUser == null) {
public QyUserEntity getUserByUserIdAndCorpid(String userid, String corpid) {
return userService.getUserByUserIdAndCorpid(userid, corpid);
}
public void saveQyUserInfoByAb98(Long ab98UserId, String userid, Ab98ApiUtil.LoginData data, SsoLoginUserinfo loginUserinfo) {
List<QyUserEntity> qyUserList = getUserByUserId(userid);
if (qyUserList == null || qyUserList.isEmpty()) {
log.error("saveQyUserInfoByAb98: user not found for userid: {}", userid);
return;
}
SysUserQyUserEntity sysUserQyUser = sysUserQyUserService.getByQyUserId(qyUser.getId());
SysUserEntity sysUser = null;
if (sysUserQyUser != null) {
sysUser = sysUserService.getById(sysUserQyUser.getSysUserId());
}
if (data != null) {
qyUser.setAvatar(data.getFace_img());
qyUser.setGender(data.getSex());
qyUser.setMobile(data.getTel());
qyUser.updateById();
if (sysUser!= null) {
sysUser.setAvatar(data.getFace_img());
sysUser.setSex(data.getSex().contains("") ? 0 : 1);
sysUser.setPhoneNumber(data.getTel());
sysUser.updateById();
for (QyUserEntity qyUser : qyUserList) {
SysUserQyUserEntity sysUserQyUser = sysUserQyUserService.getByQyUserId(qyUser.getId());
SysUserEntity sysUser = null;
if (sysUserQyUser != null) {
sysUser = sysUserService.getById(sysUserQyUser.getSysUserId());
}
} else if (loginUserinfo != null) {
qyUser.setAvatar(loginUserinfo.getFace());
qyUser.setGender(loginUserinfo.getSex());
qyUser.setMobile(loginUserinfo.getPhone());
qyUser.updateById();
if (sysUser!= null) {
sysUser.setAvatar(loginUserinfo.getFace());
sysUser.setSex(loginUserinfo.getSex().contains("")? 0 : 1);
sysUser.setPhoneNumber(loginUserinfo.getPhone());
sysUser.updateById();
qyUser.setAb98UserId(ab98UserId);
if (data != null) {
qyUser.setAvatar(data.getFace_img());
qyUser.setGender(data.getSex());
qyUser.setMobile(data.getTel());
qyUser.updateById();
if (sysUser!= null) {
sysUser.setAvatar(data.getFace_img());
sysUser.setSex(data.getSex().contains("") ? 0 : 1);
sysUser.setPhoneNumber(data.getTel());
sysUser.updateById();
}
} else if (loginUserinfo != null) {
qyUser.setAvatar(loginUserinfo.getFace());
qyUser.setGender(loginUserinfo.getSex());
qyUser.setMobile(loginUserinfo.getPhone());
qyUser.updateById();
if (sysUser!= null) {
sysUser.setAvatar(loginUserinfo.getFace());
sysUser.setSex(loginUserinfo.getSex().contains("")? 0 : 1);
sysUser.setPhoneNumber(loginUserinfo.getPhone());
sysUser.updateById();
}
}
}
}

View File

@ -45,6 +45,10 @@ public class QyUserEntity extends BaseEntity<QyUserEntity> {
@TableField("userid")
private String userid;
@ApiModelProperty("汇邦云用户id")
@TableField("ab98_user_id")
private Long ab98UserId;
@ApiModelProperty("成员名称")
@TableField("`name`")
private String name;

View File

@ -31,7 +31,14 @@ public interface QyUserMapper extends BaseMapper<QyUserEntity> {
"AND corpid = #{corpid}" +
"AND enable = '1'" +
"AND deleted = 0")
QyUserEntity selectByUserid(@Param("userid") String userid, @Param("corpid") String corpid);
QyUserEntity selectByUseridAndCorpid(@Param("userid") String userid, @Param("corpid") String corpid);
@Select("SELECT * " +
"FROM qy_user " +
"WHERE userid = #{userid} " +
"AND enable = '1'" +
"AND deleted = 0")
List<QyUserEntity> selectByUserid(@Param("userid") String userid);
@Select("SELECT DISTINCT qu.userid " +
"FROM qy_user qu " +
@ -39,11 +46,12 @@ public interface QyUserMapper extends BaseMapper<QyUserEntity> {
"LEFT JOIN sys_user su ON suqy.sys_user_id = su.user_id " +
"LEFT JOIN sys_role sr ON su.role_id = sr.role_id " +
"WHERE qu.deleted = 0 " +
"AND qu.corpid = #{corpid}" +
"AND suqy.deleted = 0 " +
"AND su.deleted = 0 " +
"AND sr.deleted = 0 " +
"AND sr.role_key = 'admin'")
List<String> selectAdminUserIds();
List<String> selectAdminUserIds(@Param("corpid") String corpid);
@Select("SELECT SUM(balance) AS balance, SUM(use_balance) AS useBalance, SUM(balance_limit) AS balanceLimit " +
"FROM qy_user " +

View File

@ -1,6 +1,7 @@
package com.agileboot.domain.qywx.user.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.qywx.user.dto.QyUserStatsDTO;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
@ -22,9 +23,11 @@ public interface QyUserService extends IService<QyUserEntity> {
List<QyUserEntity> selectAll();
QyUserEntity getUserByUserId(String userid, String corpid);
List<QyUserEntity> getUserByUserId(String userid);
List<String> selectAdminUserIds();
QyUserEntity getUserByUserIdAndCorpid(String userid, String corpid);
List<String> selectAdminUserIds(String corpid);
QyUserStatsDTO selectTotalBalance(String corpid);
}

View File

@ -1,8 +1,16 @@
package com.agileboot.domain.qywx.user.db;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.ab98.user.db.Ab98UserEntity;
import com.agileboot.domain.qywx.user.dto.QyUserStatsDTO;
import com.agileboot.domain.qywx.userQySys.db.SysUserQyUserEntity;
import com.agileboot.domain.qywx.userQySys.db.SysUserQyUserMapper;
import com.agileboot.domain.system.user.db.SysUserEntity;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
@ -38,13 +46,18 @@ public class QyUserServiceImpl extends ServiceImpl<QyUserMapper, QyUserEntity> i
}
@Override
public QyUserEntity getUserByUserId(String userid, String corpid) {
return baseMapper.selectByUserid(userid, corpid);
public List<QyUserEntity> getUserByUserId(String userid) {
return baseMapper.selectByUserid(userid);
}
@Override
public List<String> selectAdminUserIds() {
return baseMapper.selectAdminUserIds();
public QyUserEntity getUserByUserIdAndCorpid(String userid, String corpid) {
return baseMapper.selectByUseridAndCorpid(userid, corpid);
}
@Override
public List<String> selectAdminUserIds(String corpid) {
return baseMapper.selectAdminUserIds(corpid);
}
@Override

View File

@ -43,6 +43,12 @@ public class QyUserDTO {
@ExcelColumn(name = "企业用户ID")
private String userid;
@ExcelColumn(name = "汇邦云用户ID")
private Long ab98UserId;
@ExcelColumn(name = "微信openid")
private String openid;
@ExcelColumn(name = "用户姓名")
private String name;

View File

@ -1,9 +1,11 @@
package com.agileboot.domain.shop.approval;
import cn.hutool.core.date.DateUtil;
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;
@ -26,6 +28,7 @@ import com.agileboot.domain.shop.approval.query.SearchReturnApprovalQuery;
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 com.agileboot.domain.shop.order.db.ShopOrderGoodsService;
import com.agileboot.domain.shop.order.model.OrderGoodsModel;
import com.agileboot.domain.shop.order.model.OrderGoodsModelFactory;
import com.agileboot.domain.shop.order.model.OrderModel;
@ -38,15 +41,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
/**
@ -59,6 +60,7 @@ public class ReturnApprovalApplicationService {
private final ReturnApprovalService approvalService;
private final ReturnApprovalModelFactory modelFactory;
private final ShopOrderGoodsService shopOrderGoodsService;
private final OrderGoodsModelFactory orderGoodsModelFactory;
private final OrderModelFactory orderModelFactory;
private final PaymentApplicationService paymentApplicationService;
@ -69,6 +71,7 @@ public class ReturnApprovalApplicationService {
private final CabinetCellModelFactory cabinetCellModelFactory;
private final QyUserService userService;
private final PaymentOperationLogApplicationService paymentOperationLogApplicationService;
private final AssetApplicationService assetApplicationService;
/**
* 获取退货审批列表
@ -158,10 +161,37 @@ public class ReturnApprovalApplicationService {
// 微信退款
RefundVO refundVO = null;
try {
refundVO = paymentApplicationService.refund(
PayApiConstants.biz_id, PayApiConstants.appkey,
orderModel.getBizOrderId(), orderModel.getUcid(),
"退还", returnAmount.intValue());
/* 检查订单创建时间是否在2025年6月10日11:05之前
之前的旧订单收款商户和新订单收款商户不一致需要使用旧订单收款商户进行退款
*/
Date cutoffDate = DateUtil.parse("2025-06-10 11:05:00", "yyyy-MM-dd HH:mm:ss");
if (orderModel.getCreateTime().after(cutoffDate)) {
refundVO = paymentApplicationService.refund(
PayApiConstants.biz_id, PayApiConstants.appkey,
orderModel.getBizOrderId(), orderModel.getUcid(),
"退还", returnAmount.intValue());
} else {
try {
refundVO = paymentApplicationService.refund(
PayApiConstants.old_biz_id, PayApiConstants.appkey,
orderModel.getBizOrderId(), orderModel.getUcid(),
"退还", returnAmount.intValue());
} catch (Exception e) {
AddPaymentOperationLogCommand paymentOperationLogCommand = new AddPaymentOperationLogCommand();
paymentOperationLogCommand.setParams(JSONUtil.toJsonStr(command));
paymentOperationLogCommand.setOperationType("refund");
paymentOperationLogCommand.setStatus(3);
paymentOperationLogCommand.setRemark(ExceptionUtils.getStackTrace(e));
paymentOperationLogCommand.initBaseEntity();
paymentOperationLogApplicationService.addPaymentOperationLog(paymentOperationLogCommand);
// 若还是失败使用新订单收款商户进行退款
refundVO = paymentApplicationService.refund(
PayApiConstants.biz_id, PayApiConstants.appkey,
orderModel.getBizOrderId(), orderModel.getUcid(),
"退还", returnAmount.intValue());
}
}
AddPaymentOperationLogCommand paymentOperationLogCommand = new AddPaymentOperationLogCommand();
paymentOperationLogCommand.setParams(JSONUtil.toJsonStr(command));
@ -187,9 +217,9 @@ public class ReturnApprovalApplicationService {
} else if (Objects.equals(orderModel.getPaymentMethod(), "balance")) {
// 余额退款
try {
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", WeixinConstants.corpid);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid("QWTONG_YS_WXSHOP", model.getCorpid());
String userid = QywxApiUtil.convertToUserid(accessToken.getAccessToken(), orderModel.getOpenid()).getUserid();
QyUserEntity qyUser = userService.getUserByUserId(userid, WeixinConstants.corpid);
QyUserEntity qyUser = userService.getUserByUserIdAndCorpid(userid, model.getCorpid());
if (null != qyUser) {
qyUser.setBalance(qyUser.getBalance().add(command.getReturnAmount()));
qyUser.setUseBalance(qyUser.getUseBalance().subtract(command.getReturnAmount()));
@ -204,7 +234,7 @@ public class ReturnApprovalApplicationService {
if (StringUtils.isNotBlank(command.getAuditName())) {
model.setAuditName(command.getAuditName());
} else if (StringUtils.isNotBlank(command.getUserid())) {
QyUserEntity qyUserEntity = qyUserService.getUserByUserId(command.getUserid(), WeixinConstants.corpid);
QyUserEntity qyUserEntity = qyUserService.getUserByUserIdAndCorpid(command.getUserid(), model.getCorpid());
if (null != qyUserEntity) {
model.setAuditName(qyUserEntity.getName());
}
@ -215,6 +245,7 @@ public class ReturnApprovalApplicationService {
model.setAuditImages(command.getAuditImages());
model.setAuditRemark(command.getAuditRemark());
model.setReturnAmount(command.getReturnAmount());
model.setAuditUserid(command.getAuditUserid());
model.setApprovalTime(new Date());
model.setStatus(2); // 2表示审核通过状态
model.updateById();
@ -234,6 +265,103 @@ public class ReturnApprovalApplicationService {
cabinetCellModel.updateById();
}
/**
* 审批通过资产退货申请
* @param command 更新退货审批命令包含审批ID审批人信息等
* @throws RuntimeException 如果商品库存不足
*/
public void approveAssetApproval(UpdateReturnApprovalCommand command) {
// 加载退货审批模型
ReturnApprovalModel model = modelFactory.loadById(command.getApprovalId());
// 获取关联的订单商品列表
List<ShopOrderGoodsEntity> shopOrderGoodsList = shopOrderGoodsService.selectOrderGoodsByApprovalId(model.getApprovalId());
if (shopOrderGoodsList == null || shopOrderGoodsList.isEmpty()) {
throw new RuntimeException("未找到关联的订单商品");
}
// 设置审批人信息
if (StringUtils.isNotBlank(command.getAuditName())) {
model.setAuditName(command.getAuditName());
} else if (StringUtils.isNotBlank(command.getUserid())) {
QyUserEntity qyUserEntity = qyUserService.getUserByUserIdAndCorpid(command.getUserid(), model.getCorpid());
if (null != qyUserEntity) {
model.setAuditName(qyUserEntity.getName());
}
}
// 初始化商品和格口模型列表
List<GoodsModel> goodsModelList = new ArrayList<>();
List<CabinetCellModel> cabinetCellModelList = new ArrayList<>();
// 遍历订单商品检查并更新库存
for (ShopOrderGoodsEntity shopOrderGoods : shopOrderGoodsList) {
// 获取或创建商品模型
GoodsModel goodsModel = goodsModelList.stream()
.filter(g -> g.getGoodsId().equals(shopOrderGoods.getGoodsId()))
.findFirst().orElse(null);
if (goodsModel == null) {
goodsModel = goodsModelFactory.loadById(shopOrderGoods.getGoodsId());
goodsModelList.add(goodsModel);
}
// 获取或创建格口模型
CabinetCellModel cabinetCellModel = cabinetCellModelList.stream()
.filter(c -> c.getCellId().equals(shopOrderGoods.getCellId()))
.findFirst().orElse(null);
if (cabinetCellModel == null) {
cabinetCellModel = cabinetCellModelFactory.loadById(shopOrderGoods.getCellId());
cabinetCellModelList.add(cabinetCellModel);
}
// 检查商品和格口库存是否充足
if (goodsModel.getStock().compareTo(shopOrderGoods.getQuantity()) < 0 ||
cabinetCellModel.getStock().compareTo(shopOrderGoods.getQuantity()) < 0) {
throw new RuntimeException("商品库存不足");
}
// 更新商品和格口库存
goodsModel.setStock(goodsModel.getStock() - shopOrderGoods.getQuantity());
cabinetCellModel.setStock(cabinetCellModel.getStock() - shopOrderGoods.getQuantity());
}
// 更新审批状态为通过
model.validateApprovalStatus();
model.setAuditImages(command.getAuditImages());
model.setAuditRemark(command.getAuditRemark());
model.setAuditUserid(command.getAuditUserid());
model.setApprovalTime(new Date());
// 调用固资通服务的出库方法
assetApplicationService.consumeOutput(model.getCorpid(), model.getApplyUserid(), model.getAuditUserid(),
model, shopOrderGoodsList, goodsModelList);
// 开始执行数据库操作
model.setStatus(2); // 2表示审核通过状态
model.updateById();
// 更新关联订单商品状态为已完成退货
shopOrderGoodsList.forEach(shopOrderGoods -> {
shopOrderGoods.setStatus(4); // 4表示已完成退货
shopOrderGoods.updateById();
});
// 批量更新商品库存
goodsModelList.forEach(GoodsModel::updateById);
// 批量更新格口库存
cabinetCellModelList.forEach(CabinetCellModel::updateById);
OrderModel orderModel = orderModelFactory.loadById(shopOrderGoodsList.get(0).getOrderId());
orderModel.setStatus(2);
orderModel.setPayStatus(2);
orderModel.setPayTime(new Date());
orderModel.setIsDeductStock(1);
orderModel.updateById();
}
/**
* 提交退货审批申请
* @param command 添加退货审批命令
@ -245,8 +373,6 @@ public class ReturnApprovalApplicationService {
command.setGoodsId(orderGoods.getGoodsId());
command.setOrderId(orderGoods.getOrderId());
command.setGoodsPrice(orderGoods.getTotalAmount());
command.setReturnImages(command.getReturnImages());
command.setReturnRemark(command.getReturnRemark());
command.setStatus(1);
command.setCreatorId(0L);
command.setCreateTime(new Date());
@ -266,6 +392,7 @@ public class ReturnApprovalApplicationService {
// 如果商品免审批则自动审批
if (goodsModel.getAutoApproval().equals(1)) {
UpdateReturnApprovalCommand approveCommand = new UpdateReturnApprovalCommand();
approveCommand.setCorpid(command.getCorpid());
approveCommand.setApprovalId(returnApprovalModel.getApprovalId());
approveCommand.setReturnAmount(orderGoods.getTotalAmount());
approveCommand.setAuditName("自动审批");
@ -278,11 +405,11 @@ public class ReturnApprovalApplicationService {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
.filter(a -> WeixinConstants.corpid.equals(a.getCorpid()))
.filter(a -> command.getCorpid().equals(a.getCorpid()))
.findFirst().orElse(null);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, authCorpInfo.getCorpid());
// 获取用户ID
List<String> adminUserIds = qyUserService.selectAdminUserIds();
List<String> adminUserIds = qyUserService.selectAdminUserIds(command.getCorpid());
String toUser = String.join("|", adminUserIds);
String toparty = "";
String totag = "";
@ -308,6 +435,10 @@ public class ReturnApprovalApplicationService {
return new PageDTO<>(page.getRecords(), page.getTotal());
}
public List<ShopOrderGoodsEntity> getApprovalOrderGoods(Long approvalId) {
return shopOrderGoodsService.selectOrderGoodsByApprovalId(approvalId);
}
/**
* 审批驳回退货申请
* @param command 更新退货审批命令包含驳回原因
@ -318,7 +449,7 @@ public class ReturnApprovalApplicationService {
// 审批人信息
if (StringUtils.isNotBlank(command.getUserid())) {
QyUserEntity qyUserEntity = qyUserService.getUserByUserId(command.getUserid(), WeixinConstants.corpid);
QyUserEntity qyUserEntity = qyUserService.getUserByUserIdAndCorpid(command.getUserid(), command.getCorpid());
if (null != qyUserEntity) {
model.setAuditName(qyUserEntity.getName());
}

View File

@ -46,6 +46,42 @@ public class ReturnApprovalEntity extends BaseEntity<ReturnApprovalEntity> {
@TableField("order_goods_id")
private Long orderGoodsId;
@ApiModelProperty("外部归属类型的商品ID")
@TableField("external_goods_id")
private Long externalGoodsId;
@ApiModelProperty("外部归属类型的审批ID")
@TableField("external_approval_id")
private Long externalApprovalId;
@ApiModelProperty("审批码")
@TableField("code")
private String code;
@ApiModelProperty("企业微信id")
@TableField("corpid")
private String corpid;
@ApiModelProperty("申请人企业UserID")
@TableField("apply_userid")
private String applyUserid;
@ApiModelProperty("审批人企业UserID")
@TableField("audit_userid")
private String auditUserid;
@ApiModelProperty("申请数量")
@TableField("apply_quantity")
private Integer applyQuantity;
@ApiModelProperty("审批类型0为借还柜 1为固资通")
@TableField("approval_type")
private Integer approvalType;
@ApiModelProperty("申请说明")
@TableField("apply_remark")
private String applyRemark;
@ApiModelProperty("归还数量")
@TableField("return_quantity")
private Integer returnQuantity;

View File

@ -44,6 +44,33 @@ public class ReturnApprovalDTO {
@ExcelColumn(name = "关联订单商品ID")
private Long orderGoodsId;
@ExcelColumn(name = "外部归属类型的商品ID")
private Long externalGoodsId;
@ExcelColumn(name = "外部归属类型的审批ID")
private Long externalApprovalId;
@ExcelColumn(name = "审批码")
private String code;
@ExcelColumn(name = "企业微信id")
private String corpid;
@ExcelColumn(name = "申请人企业UserID")
private String applyUserid;
@ExcelColumn(name = "审批人企业UserID")
private String auditUserid;
@ExcelColumn(name = "申请数量")
private Integer applyQuantity;
@ExcelColumn(name = "审批类型")
private Integer approvalType;
@ExcelColumn(name = "申请说明")
private String applyRemark;
@ExcelColumn(name = "归还数量")
private Integer returnQuantity;

View File

@ -16,6 +16,15 @@ public class SearchApiReturnApprovalQuery<T> extends AbstractPageQuery<T> {
private Long goodsId;
private String goodsName;
private Integer status;
private Long externalGoodsId;
private Long externalApprovalId;
private String code;
private String corpid;
private String applyUserid;
private String auditUserid;
private Integer applyQuantity;
private Integer approvalType;
private String applyRemark;
private String returnRemark;
private String auditRemark;
private Date startTime;
@ -30,6 +39,13 @@ public class SearchApiReturnApprovalQuery<T> extends AbstractPageQuery<T> {
.eq(orderId != null, "ra.order_id", orderId)
.eq(goodsId != null, "ra.goods_id", goodsId)
.eq(status != null, "ra.status", status)
.eq(externalGoodsId != null, "ra.external_goods_id", externalGoodsId)
.eq(externalApprovalId != null, "ra.external_approval_id", externalApprovalId)
.eq(StrUtil.isNotEmpty(code), "ra.code", code)
.eq(approvalType != null, "ra.approval_type", approvalType)
.eq(StrUtil.isNotEmpty(corpid), "ra.corpid", corpid)
.eq(StrUtil.isNotEmpty(applyUserid), "ra.apply_userid", applyUserid)
.eq(StrUtil.isNotEmpty(auditUserid), "ra.audit_userid", auditUserid)
.like(StrUtil.isNotEmpty(goodsName), "sog.goods_name", goodsName)
.between(startTime != null && endTime != null, "ra.create_time", startTime, endTime)
.orderByDesc("ra.approval_id");

View File

@ -16,6 +16,15 @@ public class SearchReturnApprovalQuery<T> extends AbstractPageQuery<T> {
private Long orderId;
private Long goodsId;
private Integer status;
private Long externalGoodsId;
private Long externalApprovalId;
private String code;
private String corpid;
private String applyUserid;
private String auditUserid;
private Integer applyQuantity;
private Integer approvalType;
private String applyRemark;
private String returnRemark;
private String auditRemark;
private Date startTime;
@ -32,6 +41,13 @@ public class SearchReturnApprovalQuery<T> extends AbstractPageQuery<T> {
.eq(orderId != null, "ra.order_id", orderId)
.eq(goodsId != null, "ra.goods_id", goodsId)
.eq(status != null, "ra.status", status)
.eq(externalGoodsId != null, "ra.external_goods_id", externalGoodsId)
.eq(externalApprovalId != null, "ra.external_approval_id", externalApprovalId)
.eq(StrUtil.isNotEmpty(code), "ra.code", code)
.eq(approvalType != null, "ra.approval_type", approvalType)
.eq(StrUtil.isNotEmpty(corpid), "ra.corpid", corpid)
.eq(StrUtil.isNotEmpty(applyUserid), "ra.apply_userid", applyUserid)
.eq(StrUtil.isNotEmpty(auditUserid), "ra.audit_userid", auditUserid)
.like(StrUtil.isNotEmpty(returnRemark), "ra.return_remark", returnRemark)
.like(StrUtil.isNotEmpty(auditRemark), "ra.audit_remark", auditRemark)
.like(StrUtil.isNotEmpty(paymentMethod), "so.payment_method", paymentMethod)

View File

@ -0,0 +1,74 @@
package com.agileboot.domain.shop.approvalGoods;
import cn.hutool.json.JSONObject;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.shop.approvalGoods.command.AddApprovalGoodsCommand;
import com.agileboot.domain.shop.approvalGoods.command.UpdateApprovalGoodsCommand;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsEntity;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsService;
import com.agileboot.domain.shop.approvalGoods.dto.ApprovalGoodsDTO;
import com.agileboot.domain.shop.approvalGoods.model.ApprovalGoodsModel;
import com.agileboot.domain.shop.approvalGoods.model.ApprovalGoodsModelFactory;
import com.agileboot.domain.shop.approvalGoods.query.SearchApprovalGoodsQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
@Service
@Slf4j
@RequiredArgsConstructor
public class ApprovalGoodsApplicationService {
private final ApprovalGoodsService approvalGoodsService;
private final ApprovalGoodsModelFactory approvalGoodsModelFactory;
public PageDTO<ApprovalGoodsDTO> getApprovalGoodsList(SearchApprovalGoodsQuery<ApprovalGoodsEntity> query) {
Page<ApprovalGoodsEntity> page = approvalGoodsService.getApprovalGoodsList(query);
List<ApprovalGoodsDTO> dtoList = page.getRecords().stream()
.map(ApprovalGoodsDTO::new)
.collect(Collectors.toList());
return new PageDTO<>(dtoList, page.getTotal());
}
public void addApprovalGoods(AddApprovalGoodsCommand command) {
ApprovalGoodsModel model = approvalGoodsModelFactory.create();
model.loadAddCommand(command);
model.insert();
}
public void updateApprovalGoods(UpdateApprovalGoodsCommand command) {
ApprovalGoodsModel model = approvalGoodsModelFactory.loadById(command.getApprovalGoodsId());
model.loadUpdateCommand(command);
model.updateById();
}
public void deleteApprovalGoods(BulkOperationCommand<Long> command) {
for (Long id : command.getIds()) {
ApprovalGoodsModel model = approvalGoodsModelFactory.loadById(id);
model.deleteById();
}
}
public ApprovalGoodsEntity getFirstEnabledApprovalGoods() {
return approvalGoodsService.selectLatest();
}
public ApprovalGoodsEntity getByApprovalId(Long approvalId) {
return approvalGoodsService.selectByApprovalId(approvalId);
}
public ApprovalGoodsEntity getByGoodsId(Long goodsId) {
return approvalGoodsService.selectByGoodsId(goodsId);
}
}

View File

@ -0,0 +1,11 @@
package com.agileboot.domain.shop.approvalGoods.command;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class AddApprovalGoodsCommand extends ApprovalGoodsEntity {
}

View File

@ -0,0 +1,16 @@
package com.agileboot.domain.shop.approvalGoods.command;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class UpdateApprovalGoodsCommand extends AddApprovalGoodsCommand {
@NotNull
@PositiveOrZero
private Long approvalGoodsId;
}

View File

@ -0,0 +1,77 @@
package com.agileboot.domain.shop.approvalGoods.db;
import com.agileboot.common.core.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 申请领用商品信息表
* </p>
*
* @author valarchie
* @since 2025-06-07
*/
@Getter
@Setter
@TableName("approval_goods")
@ApiModel(value = "ApprovalGoodsEntity对象", description = "申请领用商品信息表")
public class ApprovalGoodsEntity extends BaseEntity<ApprovalGoodsEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("主键ID")
@TableId(value = "approval_goods_id", type = IdType.AUTO)
private Long approvalGoodsId;
@ApiModelProperty("审批ID")
@TableField("approval_id")
private Long approvalId;
@ApiModelProperty("商品名称")
@TableField("goods_name")
private String goodsName;
@ApiModelProperty("关联商品ID")
@TableField("goods_id")
private Long goodsId;
@ApiModelProperty("外部归属类型的商品ID")
@TableField("external_goods_id")
private Long externalGoodsId;
@ApiModelProperty("企业微信id")
@TableField("corpid")
private String corpid;
@ApiModelProperty("归属类型0-借还柜 1-固资通)")
@TableField("belong_type")
private Integer belongType;
@ApiModelProperty("销售价格")
@TableField("price")
private BigDecimal price;
@ApiModelProperty("申请数量")
@TableField("apply_quantity")
private Integer applyQuantity;
@ApiModelProperty("封面图URL")
@TableField("cover_img")
private String coverImg;
@Override
public Serializable pkVal() {
return this.approvalGoodsId;
}
}

View File

@ -0,0 +1,44 @@
package com.agileboot.domain.shop.approvalGoods.db;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* <p>
* 申请领用商品信息表 Mapper 接口
* </p>
*
* @author valarchie
* @since 2025-06-07
*/
public interface ApprovalGoodsMapper extends BaseMapper<ApprovalGoodsEntity> {
@Select("SELECT * " +
"FROM approval_goods " +
"${ew.customSqlSegment}")
Page<ApprovalGoodsEntity> getApprovalGoodsList(
Page<ApprovalGoodsEntity> page,
@Param(Constants.WRAPPER) Wrapper<ApprovalGoodsEntity> queryWrapper
);
@Select("SELECT * " +
"FROM approval_goods " +
"ORDER BY approval_goods_id DESC " +
"LIMIT 1")
ApprovalGoodsEntity selectLatest();
@Select("SELECT * " +
"FROM approval_goods " +
"ORDER BY approval_goods_id DESC")
List<ApprovalGoodsEntity> selectAll();
@Select("SELECT * FROM approval_goods WHERE approval_id = #{approvalId} LIMIT 1")
ApprovalGoodsEntity selectByApprovalId(Long approvalId);
@Select("SELECT * FROM approval_goods WHERE goods_id = #{goodsId} LIMIT 1")
ApprovalGoodsEntity selectByGoodsId(Long goodsId);
}

View File

@ -0,0 +1,27 @@
package com.agileboot.domain.shop.approvalGoods.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 申请领用商品信息表 服务类
* </p>
*
* @author valarchie
* @since 2025-06-07
*/
public interface ApprovalGoodsService extends IService<ApprovalGoodsEntity> {
Page<ApprovalGoodsEntity> getApprovalGoodsList(AbstractPageQuery<ApprovalGoodsEntity> query);
List<ApprovalGoodsEntity> selectAll();
ApprovalGoodsEntity selectLatest();
ApprovalGoodsEntity selectByApprovalId(Long approvalId);
ApprovalGoodsEntity selectByGoodsId(Long goodsId);
}

View File

@ -0,0 +1,45 @@
package com.agileboot.domain.shop.approvalGoods.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 申请领用商品信息表 服务实现类
* </p>
*
* @author valarchie
* @since 2025-06-07
*/
@Service
public class ApprovalGoodsServiceImpl extends ServiceImpl<ApprovalGoodsMapper, ApprovalGoodsEntity> implements ApprovalGoodsService {
@Override
public Page<ApprovalGoodsEntity> getApprovalGoodsList(AbstractPageQuery<ApprovalGoodsEntity> query) {
return this.page(query.toPage(), query.toQueryWrapper());
}
@Override
public List<ApprovalGoodsEntity> selectAll() {
return baseMapper.selectAll();
}
@Override
public ApprovalGoodsEntity selectLatest() {
return baseMapper.selectLatest();
}
@Override
public ApprovalGoodsEntity selectByApprovalId(Long approvalId) {
return baseMapper.selectByApprovalId(approvalId);
}
@Override
public ApprovalGoodsEntity selectByGoodsId(Long goodsId) {
return baseMapper.selectByGoodsId(goodsId);
}
}

View File

@ -0,0 +1,51 @@
package com.agileboot.domain.shop.approvalGoods.dto;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.agileboot.common.annotation.ExcelColumn;
import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsEntity;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
@ExcelSheet(name = "申请领用商品信息列表")
@Data
public class ApprovalGoodsDTO {
public ApprovalGoodsDTO(ApprovalGoodsEntity entity) {
if (entity != null) {
BeanUtil.copyProperties(entity, this);
}
}
@ExcelColumn(name = "主键ID")
private Long approvalGoodsId;
@ExcelColumn(name = "审批ID")
private Long approvalId;
@ExcelColumn(name = "商品名称")
private String goodsName;
@ExcelColumn(name = "关联商品ID")
private Long goodsId;
@ExcelColumn(name = "外部归属类型的商品ID")
private Long externalGoodsId;
@ExcelColumn(name = "企业微信id")
private String corpid;
@ExcelColumn(name = "归属类型0-借还柜 1-固资通)")
private Integer belongType;
@ExcelColumn(name = "销售价格")
private BigDecimal price;
@ExcelColumn(name = "申请数量")
private Integer applyQuantity;
@ExcelColumn(name = "封面图URL")
private String coverImg;
}

View File

@ -0,0 +1,41 @@
package com.agileboot.domain.shop.approvalGoods.model;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.shop.approvalGoods.command.AddApprovalGoodsCommand;
import com.agileboot.domain.shop.approvalGoods.command.UpdateApprovalGoodsCommand;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsEntity;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsService;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ApprovalGoodsModel extends ApprovalGoodsEntity {
private ApprovalGoodsService approvalGoodsService;
public ApprovalGoodsModel(ApprovalGoodsEntity entity, ApprovalGoodsService approvalGoodsService) {
this(approvalGoodsService);
if (entity != null) {
BeanUtil.copyProperties(entity, this);
}
}
public ApprovalGoodsModel(ApprovalGoodsService approvalGoodsService) {
this.approvalGoodsService = approvalGoodsService;
}
public void loadAddCommand(AddApprovalGoodsCommand command) {
if (command != null) {
BeanUtil.copyProperties(command, this, "id");
}
}
public void loadUpdateCommand(UpdateApprovalGoodsCommand command) {
if (command != null) {
loadAddCommand(command);
}
}
}

View File

@ -0,0 +1,27 @@
package com.agileboot.domain.shop.approvalGoods.model;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsEntity;
import com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class ApprovalGoodsModelFactory {
private final ApprovalGoodsService approvalGoodsService;
public ApprovalGoodsModel loadById(Long approvalGoodsId) {
ApprovalGoodsEntity entity = approvalGoodsService.getById(approvalGoodsId);
if (entity == null) {
throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, approvalGoodsId, "申请领用商品");
}
return new ApprovalGoodsModel(entity, approvalGoodsService);
}
public ApprovalGoodsModel create() {
return new ApprovalGoodsModel(approvalGoodsService);
}
}

View File

@ -0,0 +1,50 @@
package com.agileboot.domain.shop.approvalGoods.query;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.math.BigDecimal;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class SearchApprovalGoodsQuery<T> extends AbstractPageQuery<T> {
private Long approvalGoodsId;
private Long approvalId;
private String goodsName;
private Long goodsId;
private Long externalGoodsId;
private String corpid;
private Integer belongType;
private BigDecimal price;
private Integer applyQuantity;
private String coverImg;
private Date startTime;
private Date endTime;
@Override
public QueryWrapper<T> addQueryCondition() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper
.eq(approvalGoodsId != null, "approval_goods_id", approvalGoodsId)
.eq(approvalId != null, "approval_id", approvalId)
.eq(StrUtil.isNotEmpty(goodsName), "goods_name", goodsName)
.eq(goodsId != null, "goods_id", goodsId)
.eq(externalGoodsId != null, "external_goods_id", externalGoodsId)
.eq(StrUtil.isNotEmpty(corpid), "corpid", corpid)
.eq(belongType != null, "belong_type", belongType)
.eq(price != null, "price", price)
.eq(applyQuantity != null, "apply_quantity", applyQuantity)
.eq(StrUtil.isNotEmpty(coverImg), "cover_img", coverImg)
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
this.timeRangeColumn = "create_time";
return queryWrapper;
}
}

View File

@ -12,6 +12,7 @@ import com.agileboot.domain.shop.goods.dto.ShopGoodsDTO;
import com.agileboot.domain.shop.goods.model.GoodsModel;
import com.agileboot.domain.shop.goods.model.GoodsModelFactory;
import com.agileboot.domain.shop.goods.query.SearchShopGoodsQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.math.BigDecimal;
@ -32,6 +33,10 @@ public class GoodsApplicationService {
return new PageDTO<>(goodsDTOList, goodsPage.getTotal());
}
public List<SearchGoodsDO> selectGoodsList(SearchShopGoodsQuery<SearchGoodsDO> query) {
return shopGoodsService.selectGoodsList(query);
}
public void addGoods(AddGoodsCommand command) {
GoodsModel model = goodsModelFactory.create();
model.loadAddGoodsCommand(command);

View File

@ -16,6 +16,8 @@ public class SearchGoodsDO extends ShopGoodsEntity {
private Long cabinetId;
@TableField("cabinet_name")
private String cabinetName;
@TableField("shop_name_str")
private String shopNameStr;
@TableField("cell_no")
private Integer cellNo;
@TableField("cell_no_str")

View File

@ -22,6 +22,7 @@ public class SearchGoodsWithCabinetDO extends BaseEntity<SearchGoodsWithCabinetD
private String goodsDetail;
private String usageInstruction;
private String remark;
private Integer belongType;
@TableField("sc.cabinet_id")
private Long cabinetId;

View File

@ -40,6 +40,18 @@ public class ShopGoodsEntity extends BaseEntity<ShopGoodsEntity> {
@TableField("category_id")
private Long categoryId;
@ApiModelProperty("外部归属类型的商品ID")
@TableField("external_goods_id")
private Long externalGoodsId;
@ApiModelProperty("企业微信id")
@TableField("corpid")
private String corpid;
@ApiModelProperty("每人每月限购数量")
@TableField("monthly_purchase_limit")
private Integer monthlyPurchaseLimit;
@ApiModelProperty("销售价格")
@TableField("price")
private BigDecimal price;
@ -72,6 +84,10 @@ public class ShopGoodsEntity extends BaseEntity<ShopGoodsEntity> {
@TableField("usage_instruction")
private String usageInstruction;
@ApiModelProperty("归属类型0-借还柜 1-固资通)")
@TableField("belong_type")
private Integer belongType;
@Override
public Serializable pkVal() {
return this.goodsId;

View File

@ -50,6 +50,19 @@ public interface ShopGoodsMapper extends BaseMapper<ShopGoodsEntity> {
@Param(Constants.WRAPPER) Wrapper<SearchGoodsDO> queryWrapper
);
@Select("SELECT g.goods_id, g.goods_name, g.category_id, g.price, " +
"g.stock, g.status, g.auto_approval, g.cover_img, g.usage_instruction, SUM(cc.stock) AS total_stock, " +
"GROUP_CONCAT(DISTINCT cc.cell_no) AS cell_no_str, " +
"GROUP_CONCAT(DISTINCT sc.cabinet_name) AS cabinet_name " +
"FROM shop_goods g " +
"LEFT JOIN cabinet_cell cc ON g.goods_id = cc.goods_id AND cc.deleted = 0 " +
"LEFT JOIN smart_cabinet sc ON cc.cabinet_id = sc.cabinet_id AND sc.deleted = 0 " +
"${ew.customSqlSegment} ")
List<SearchGoodsDO> getGoodsListQuery(
@Param(Constants.WRAPPER) Wrapper<SearchGoodsDO> queryWrapper
);
/**
* 查询所有商品未删除的
* @return 商品列表
@ -65,32 +78,34 @@ public interface ShopGoodsMapper extends BaseMapper<ShopGoodsEntity> {
* @return 商品列表
*/
@Select("SELECT g.goods_id, g.goods_name, g.category_id, g.price, " +
"g.status, g.cover_img, g.goods_detail, g.usage_instruction, " +
"g.status, g.cover_img, g.goods_detail, g.usage_instruction, g.belong_type, " +
"g.creator_id, g.create_time, g.updater_id, g.update_time, g.remark, g.deleted, " +
"sc.cabinet_id, sc.cabinet_name, cc.stock, cc.cell_id " +
"FROM shop_goods g " +
"LEFT JOIN cabinet_cell cc ON g.goods_id = cc.goods_id " +
"LEFT JOIN smart_cabinet sc ON cc.cabinet_id = sc.cabinet_id " +
"WHERE g.deleted = 0 AND sc.deleted = 0 AND cc.deleted = 0 AND cc.goods_id IS NOT NULL ")
"WHERE g.deleted = 0 AND g.belong_type = 0 AND sc.deleted = 0 AND cc.deleted = 0 AND cc.goods_id IS NOT NULL ")
List<SearchGoodsWithCabinetDO> getGoodsWithCabinetList();
@Select("SELECT g.goods_id, g.goods_name, g.category_id, g.price, " +
"g.status, g.cover_img, g.goods_detail, g.usage_instruction, " +
"g.status, g.cover_img, g.goods_detail, g.usage_instruction, g.belong_type, " +
"g.creator_id, g.create_time, g.updater_id, g.update_time, g.remark, g.deleted, " +
"sc.cabinet_id, sc.cabinet_name, sc.shop_id, cc.stock, cc.cell_id " +
"FROM shop_goods g " +
"LEFT JOIN cabinet_cell cc ON g.goods_id = cc.goods_id " +
"LEFT JOIN smart_cabinet sc ON cc.cabinet_id = sc.cabinet_id " +
"WHERE g.deleted = 0 AND sc.deleted = 0 AND sc.shop_id = #{shopId} AND cc.deleted = 0 AND cc.goods_id IS NOT NULL ")
"WHERE g.deleted = 0 AND g.belong_type = 0 AND sc.deleted = 0 AND sc.shop_id = #{shopId} AND cc.deleted = 0 AND cc.goods_id IS NOT NULL ")
List<SearchGoodsWithCabinetDO> getGoodsWithCabinetListByShopId(@Param("shopId")Long shopId);
@Select("SELECT g.goods_id, g.goods_name, g.category_id, g.price, " +
"g.stock, g.status, g.auto_approval, g.cover_img, SUM(cc.stock) AS total_stock, " +
@Select("SELECT g.*, " +
"SUM(cc.stock) AS total_stock, " +
"GROUP_CONCAT(DISTINCT cc.cell_no) AS cell_no_str, " +
"GROUP_CONCAT(DISTINCT sc.cabinet_name) AS cabinet_name " +
"GROUP_CONCAT(DISTINCT sc.cabinet_name) AS cabinet_name, " +
"GROUP_CONCAT(DISTINCT s.shop_name) AS shop_name_str " +
"FROM shop_goods g " +
"LEFT JOIN cabinet_cell cc ON g.goods_id = cc.goods_id AND cc.deleted = 0 " +
"LEFT JOIN smart_cabinet sc ON cc.cabinet_id = sc.cabinet_id AND sc.deleted = 0 " +
"LEFT JOIN shop s ON s.shop_id = sc.shop_id AND s.deleted = 0 " +
"WHERE g.goods_id = #{goodsId} ")
SearchGoodsDO getGoodsInfo(@Param("goodsId") Long goodsId);

View File

@ -18,6 +18,8 @@ import java.util.List;
public interface ShopGoodsService extends IService<ShopGoodsEntity> {
Page<SearchGoodsDO> getGoodsList(AbstractPageQuery<SearchGoodsDO> query);
List<SearchGoodsDO> selectGoodsList(AbstractPageQuery<SearchGoodsDO> query);
List<ShopGoodsEntity> selectAll();
List<SearchGoodsWithCabinetDO> getGoodsWithCabinetList(Long shopId);
@ -27,4 +29,6 @@ public interface ShopGoodsService extends IService<ShopGoodsEntity> {
Long countAllRecord();
BigDecimal calculateTotalAmount();
ShopGoodsEntity getGoodsByExternalGoodsId(String corpid, Long externalGoodsId);
}

View File

@ -29,6 +29,12 @@ public class ShopGoodsServiceImpl extends ServiceImpl<ShopGoodsMapper, ShopGoods
return baseMapper.getGoodsList(query.toPage(), wrapper);
}
@Override
public List<SearchGoodsDO> selectGoodsList(AbstractPageQuery<SearchGoodsDO> query) {
QueryWrapper<SearchGoodsDO> wrapper = query.toQueryWrapper();
return baseMapper.getGoodsListQuery(wrapper);
}
@Override
public List<ShopGoodsEntity> selectAll() {
return baseMapper.selectAll();
@ -57,4 +63,14 @@ public class ShopGoodsServiceImpl extends ServiceImpl<ShopGoodsMapper, ShopGoods
public BigDecimal calculateTotalAmount() {
return baseMapper.calculateTotalAmount();
}
@Override
public ShopGoodsEntity getGoodsByExternalGoodsId(String corpid, Long externalGoodsId) {
QueryWrapper<ShopGoodsEntity> wrapper = new QueryWrapper<>();
wrapper.eq("external_goods_id", externalGoodsId)
.eq("corpid", corpid)
.eq("deleted", 0)
.last("LIMIT 1");
return baseMapper.selectOne(wrapper);
}
}

View File

@ -9,6 +9,9 @@ import com.agileboot.domain.shop.goods.db.SearchGoodsDO;
import com.agileboot.domain.system.user.db.SysUserEntity;
import java.math.BigDecimal;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ExcelSheet(name = "商品列表")
@ -48,9 +51,18 @@ public class ShopGoodsDTO {
@ExcelColumn(name = "分类ID")
private Long categoryId;
@ExcelColumn(name = "外部商品ID")
private Long externalGoodsId;
@ExcelColumn(name = "企业微信id")
private String corpid;
@ExcelColumn(name = "分类名称")
private String categoryName;
@ExcelColumn(name = "归属类型0-借还柜 1-固资通)")
private Long belongType;
@ExcelColumn(name = "销售价格")
private BigDecimal price;
@ -87,6 +99,12 @@ public class ShopGoodsDTO {
@ExcelColumn(name = "已分配库存")
private Integer totalStock;
@ExcelColumn(name = "地址名称")
private String shopNameStr;
@ExcelColumn(name = "商品使用说明")
private String usageInstruction;
@ExcelColumn(name = "每人每月限购数量")
private Integer monthlyPurchaseLimit;
}

View File

@ -13,10 +13,13 @@ public class SearchShopGoodsQuery<T> extends AbstractPageQuery<T> {
protected String goodsName;
protected Long categoryId;
protected Long externalGoodsId;
protected String corpid;
protected Integer status;
protected Integer autoApproval;
protected BigDecimal minPrice;
protected BigDecimal maxPrice;
protected Integer belongType;
@Override
public QueryWrapper<T> addQueryCondition() {
@ -29,6 +32,9 @@ public class SearchShopGoodsQuery<T> extends AbstractPageQuery<T> {
.eq(autoApproval != null, "g.auto_approval", autoApproval)
.ge(minPrice != null, "g.price", minPrice)
.le(maxPrice != null, "g.price", maxPrice)
.eq(belongType != null, "g.belong_type", belongType)
.eq(externalGoodsId != null, "g.external_goods_id", externalGoodsId)
.eq(StrUtil.isNotEmpty(corpid), "g.corpid", corpid)
.eq("g.deleted", 0)
.groupBy("g.goods_id");

View File

@ -17,10 +17,21 @@ import com.agileboot.domain.cabinet.smartCabinet.db.SmartCabinetEntity;
import com.agileboot.domain.cabinet.smartCabinet.db.SmartCabinetService;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.mqtt.MqttService;
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.QyUserEntity;
import com.agileboot.domain.qywx.user.db.QyUserService;
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand;
import com.agileboot.domain.shop.approval.command.UpdateReturnApprovalCommand;
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.ShopGoodsService;
import com.agileboot.domain.shop.goods.model.GoodsModel;
import com.agileboot.domain.shop.order.command.SubmitOrderCommand;
import com.agileboot.domain.shop.order.db.*;
import com.agileboot.domain.shop.order.db.dto.OrderWithGoodsDTO;
@ -41,6 +52,7 @@ import com.agileboot.domain.shop.paymentOperationLog.command.AddPaymentOperation
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@ -50,6 +62,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -71,6 +84,10 @@ public class OrderApplicationService {
private final CabinetCellOperationModelFactory cabinetCellOperationModelFactory;
private final PaymentOperationLogApplicationService paymentOperationLogApplicationService;
private final CabinetMainboardService cabinetMainboardService;
private final ReturnApprovalModelFactory modelFactory;
private final AuthCorpInfoApplicationService authCorpInfoApplicationService;
private final AccessTokenApplicationService accessTokenApplicationService;
private final QyUserService qyUserService;
public PageDTO<OrderWithGoodsDTO> getOrderList(SearchShopOrderQuery<OrderWithGoodsDTO> query) {
Page<OrderWithGoodsDTO> page = orderService.getOrderList(query);
@ -146,6 +163,7 @@ public class OrderApplicationService {
OrderModel orderModel = orderModelFactory.create();
orderModel.setOpenid(command.getOpenid());
orderModel.setCorpid(command.getCorpid());
orderModel.setCreatorId(1L);
orderModel.setCreateTime(new Date());
orderModel.setUpdaterId(1L);
@ -162,6 +180,9 @@ public class OrderApplicationService {
orderModel.setIsDeductStock(0);
orderModel.insert();
goodsList.forEach(goods -> {
goods.setCorpid(command.getCorpid());
});
processOrderGoods(orderModel, goodsList);
if (Objects.equals(command.getPaymentType(), "wechat")) {
@ -179,7 +200,7 @@ public class OrderApplicationService {
return new CreateOrderResult(orderModel.getOrderId(), orderModel.getTotalAmount(), paymentResponse, BigDecimal.valueOf(0));
} else if (Objects.equals(command.getPaymentType(), "balance")) {
QyUserEntity qyUser = userService.getUserByUserId(command.getUserid(), command.getCorpid());
QyUserEntity qyUser = userService.getUserByUserIdAndCorpid(command.getUserid(), command.getCorpid());
// 余额不足
if (qyUser.getBalance().compareTo(orderModel.getTotalAmount()) < 0) {
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "余额不足");
@ -195,8 +216,77 @@ public class OrderApplicationService {
handlePaymentSuccess(orderModel.getOrderId(), Integer.valueOf(amountInFen.toPlainString()),
"balance-" + orderModel.getOrderId(), DateUtil.formatDateTime(new Date()));
return new CreateOrderResult(orderModel.getOrderId(), orderModel.getTotalAmount(), null, qyUser.getBalance());
} else if (Objects.equals(command.getPaymentType(), "approval")) {
submitAssetApproval(orderModel, goodsList, command);
return new CreateOrderResult(orderModel.getOrderId(), orderModel.getTotalAmount(), null, BigDecimal.valueOf(0));
}else {
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的支付类型");
}
}
private void submitAssetApproval(OrderModel orderModel, List<ShopOrderGoodsEntity> orderGoodsList, SubmitOrderCommand submitOrderCommand) {
ShopOrderGoodsEntity firstOrderGoods = orderGoodsList.get(0);
// 设置商品价格并初始化审批状态
AddReturnApprovalCommand command = new AddReturnApprovalCommand();
command.initBaseEntity();
command.setCorpid(submitOrderCommand.getCorpid());
command.setGoodsId(firstOrderGoods.getGoodsId());
command.setOrderId(orderModel.getOrderId());
command.setApplyUserid(orderModel.getUserid());
command.setApplyRemark(submitOrderCommand.getApplyRemark());
command.setApprovalType(1);
command.setStatus(1);
command.setCreatorId(0L);
command.setCreateTime(new Date());
command.setUpdaterId(0L);
command.setUpdateTime(new Date());
command.setDeleted(false);
// 执行业务逻辑
ReturnApprovalModel returnApprovalModel = modelFactory.create();
returnApprovalModel.loadAddCommand(command);
returnApprovalModel.insert();
// 更新订单商品状态
orderGoodsList.forEach(orderGoods -> {
orderGoods.setStatus(5);
orderGoods.setApprovalId(returnApprovalModel.getApprovalId());
orderGoodsService.updateById(orderGoods);
});
// 如果商品免审批则自动审批
// 发送审核消息
try {
String appid = "QWTONG_YS_WXSHOP";
List<QyAuthCorpInfoEntity> authCorpInfoList = authCorpInfoApplicationService.getByAppid(appid);
QyAuthCorpInfoEntity authCorpInfo = authCorpInfoList.stream()
.filter(a -> command.getCorpid().equals(a.getCorpid()))
.findFirst().orElse(null);
QyAccessTokenEntity accessToken = accessTokenApplicationService.getByAppid(appid, authCorpInfo.getCorpid());
// 获取用户ID
List<String> adminUserIds = qyUserService.selectAdminUserIds(submitOrderCommand.getCorpid());
String toUser = String.join("|", adminUserIds);
String toparty = "";
String totag = "";
List<NewsArticle> articles = new ArrayList<>();
NewsArticle article = new NewsArticle();
article.setTitle("耗材领用申请通知");
article.setDescription("领用商品:" + firstOrderGoods.getGoodsName());
if (orderGoodsList.size() > 1) {
article.setDescription(submitOrderCommand.getName() + " 申请领用" + firstOrderGoods.getGoodsName() + "" + orderGoodsList.size() + "件商品");
} else {
article.setDescription(submitOrderCommand.getName() + " 申请领用" + firstOrderGoods.getGoodsName());
}
article.setPicurl(firstOrderGoods.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);
}
throw new ApiException(ErrorCode.Client.COMMON_REQUEST_PARAMETERS_INVALID, "无效的支付类型");
}
private WxJsApiPreCreateRequest buildPaymentRequest(OrderModel orderModel) {
@ -242,6 +332,7 @@ public class OrderApplicationService {
// 保存订单商品
goodsModel.insert();
BeanUtils.copyProperties(goodsModel, goods);
// 扣减库存
// 改为收到支付成功后扣减库存

View File

@ -19,9 +19,12 @@ public class SubmitOrderCommand {
@ApiModelProperty("订单主体信息")
private ShopOrderEntity order;
@ApiModelProperty("支付类型 wechat:微信 balance:余额")
@ApiModelProperty("支付类型 wechat:微信 balance:余额 approval:审批")
private String paymentType;
@ApiModelProperty("领用说明")
private String applyRemark;
@ApiModelProperty("订单商品明细列表")
private List<ShopOrderGoodsEntity> goodsList;

View File

@ -65,6 +65,10 @@ public class ShopOrderEntity extends BaseEntity<ShopOrderEntity> {
@TableField("biz_order_id")
private String bizOrderId;
@ApiModelProperty("企业微信id")
@TableField("corpid")
private String corpid;
@ApiModelProperty("订单总金额")
@TableField("total_amount")
private BigDecimal totalAmount;
@ -81,7 +85,7 @@ public class ShopOrderEntity extends BaseEntity<ShopOrderEntity> {
@TableField("is_deduct_stock")
private Integer isDeductStock;
@ApiModelProperty("支付方式")
@ApiModelProperty("支付方式 wechat:微信 balance:余额 approval:审批")
@TableField("payment_method")
private String paymentMethod;

View File

@ -36,6 +36,10 @@ public class ShopOrderGoodsEntity extends BaseEntity<ShopOrderGoodsEntity> {
@TableField("order_id")
private Long orderId;
@ApiModelProperty("审批ID")
@TableField("approval_id")
private Long approvalId;
@ApiModelProperty("关联商品ID")
@TableField("goods_id")
private Long goodsId;
@ -68,6 +72,9 @@ public class ShopOrderGoodsEntity extends BaseEntity<ShopOrderGoodsEntity> {
@TableField("`status`")
private Integer status;
@ApiModelProperty("企业微信id")
@TableField("corpid")
private String corpid;
@Override
public Serializable pkVal() {

View File

@ -24,4 +24,6 @@ public interface ShopOrderGoodsService extends IService<ShopOrderGoodsEntity> {
List<TodayLatestOrderGoodsDTO> selectTodayLatestOrderGoods();
List<ShopOrderGoodsEntity> selectUnReturnOrderGoods();
List<ShopOrderGoodsEntity> selectOrderGoodsByApprovalId(Long approvalId);
}

View File

@ -1,6 +1,7 @@
package com.agileboot.domain.shop.order.db;
import com.agileboot.domain.shop.order.dto.TopGoodsDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@ -42,4 +43,12 @@ public class ShopOrderGoodsServiceImpl extends ServiceImpl<ShopOrderGoodsMapper,
return baseMapper.selectUnReturnOrderGoods();
}
@Override
public List<ShopOrderGoodsEntity> selectOrderGoodsByApprovalId(Long approvalId) {
QueryWrapper<ShopOrderGoodsEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("approval_id", approvalId)
.eq("deleted", 0);
return this.list(queryWrapper);
}
}

View File

@ -54,4 +54,7 @@ public class ShopOrderDTO {
private Integer isInternal;
@ApiModelProperty("业务系统订单ID对接外部系统")
private String bizOrderId;
@ApiModelProperty("企业微信id")
private String corpid;
}

View File

@ -18,12 +18,14 @@ public class SearchShopOrderQuery<T> extends AbstractPageQuery<T> {
private String userid;
private Long cellId;
private Long cabinetId;
private Long goodsId;
private Integer status;
private Integer payStatus;
private Date startTime;
private Date endTime;
private Date payTime;
private String paymentMethod;
private String corpid;
@Override
public QueryWrapper<T> addQueryCondition() {
@ -32,12 +34,18 @@ public class SearchShopOrderQuery<T> extends AbstractPageQuery<T> {
queryWrapper
.eq(orderId != null, "o.order_id", orderId)
.eq(cellId != null, "og.cell_id", cellId)
.eq(StrUtil.isNotBlank(openid), "o.openid", StringUtils.trim(openid))
.eq(StrUtil.isNotBlank(userid), "o.userid", StringUtils.trim(userid))
.eq(StrUtil.isNotBlank(openid) && StrUtil.isBlank(userid), "o.openid", StringUtils.trim(openid))
.eq(StrUtil.isNotBlank(userid) && StrUtil.isBlank(openid), "o.userid", StringUtils.trim(userid))
.or(StrUtil.isNotBlank(userid) && StrUtil.isNotBlank(openid),
qw -> qw.eq("o.openid", StringUtils.trim(openid))
.or()
.eq("o.userid", StringUtils.trim(userid)))
.eq(cabinetId != null, "cc.cabinet_id", cabinetId)
.eq(goodsId!= null, "og.goods_id", goodsId)
.eq(status != null, "o.status", status)
.eq(payStatus != null, "o.pay_status", payStatus)
.eq(StrUtil.isNotEmpty(paymentMethod), "o.payment_method", paymentMethod)
.eq(StrUtil.isNotBlank(corpid), "o.corpid", corpid)
.between(startTime != null && endTime != null, "o.create_time", startTime, endTime)
.between(payTime != null, "o.pay_time",
payTime == null ? null : DateUtil.beginOfDay(payTime).toJdkDate(),

View File

@ -156,7 +156,7 @@ public class PaymentApplicationService {
String result = HttpUtil.post(url, sb.toString());
CommonResponse<RefundVO> res = JSONUtil.toBean(result, new TypeReference<CommonResponse<RefundVO>>(){}, true);
if (res.getCode() != CommonErrorCode.OK.getErrorCode()) {
throw new Exception(res.getMsg());
throw new Exception(res.getMsg() + ",请求参数:" + JSONUtil.toJsonStr(params) + ",响应结果:" + result);
}
return res.getData();
}

View File

@ -32,6 +32,15 @@ public class ShopApplicationService {
return new PageDTO<>(dtoList, page.getTotal());
}
public ShopDTO getShopById(Long shopId) {
ShopEntity shopEntity = shopService.getById(shopId);
return new ShopDTO(shopEntity);
}
public List<ShopEntity> getShopListByCorpid(String corpid, Long mode) {
return shopService.getShopListByCorpid(corpid, mode);
}
public void addShop(AddShopCommand command) {
ShopModel model = shopModelFactory.create();
model.loadAddCommand(command);

View File

@ -35,6 +35,25 @@ public class ShopEntity extends BaseEntity<ShopEntity> {
@TableField("shop_name")
private String shopName;
@ApiModelProperty("企业微信id")
@TableField("corpid")
private String corpid;
@ApiModelProperty("归属类型0-借还柜 1-固资通)")
@TableField("belong_type")
private Integer belongType;
@ApiModelProperty("运行模式0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式)")
@TableField("mode")
private Integer mode;
@ApiModelProperty("借呗支付1-正常使用 0-禁止使用)")
@TableField("balance_enable")
private Integer balanceEnable;
@ApiModelProperty("封面图URL")
@TableField("cover_img")
private String coverImg;
@Override
public Serializable pkVal() {

View File

@ -27,4 +27,6 @@ public interface ShopService extends IService<ShopEntity> {
ShopEntity selectByShopName(String shopName);
Long countAllRecord();
List<ShopEntity> getShopListByCorpid(String corpid, Long mode);
}

View File

@ -1,6 +1,7 @@
package com.agileboot.domain.shop.shop.db;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@ -47,4 +48,13 @@ public class ShopServiceImpl extends ServiceImpl<ShopMapper, ShopEntity> impleme
public Long countAllRecord() {
return baseMapper.countAllRecord();
}
@Override
public List<ShopEntity> getShopListByCorpid(String corpid, Long mode) {
QueryWrapper<ShopEntity> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("corpid", corpid)
.ne("mode", mode)
.eq("deleted", 0);
return this.list(queryWrapper);
}
}

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 = "商店列表")
@ -24,4 +26,18 @@ public class ShopDTO {
@ExcelColumn(name = "商店名称")
private String shopName;
@ExcelColumn(name = "企业微信id")
private String corpid;
@ExcelColumn(name = "归属类型0-借还柜 1-固资通)")
private Integer belongType;
@ExcelColumn(name = "运行模式0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式)")
private Integer mode;
@ExcelColumn(name = "借呗支付1-正常使用 0-禁止使用)")
private Integer balanceEnable;
@ExcelColumn(name = "封面图URL")
private String coverImg;
}

View File

@ -15,6 +15,10 @@ public class SearchShopQuery<T> extends AbstractPageQuery<T> {
private String enable;
private Date startTime;
private Date endTime;
private String corpid;
private Integer belongType;
private Integer mode;
private Integer balanceEnable;
@Override
public QueryWrapper<T> addQueryCondition() {
@ -23,6 +27,10 @@ public class SearchShopQuery<T> extends AbstractPageQuery<T> {
queryWrapper
.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)
.eq(mode != null, "mode", mode)
.eq(balanceEnable != null, "balance_enable", balanceEnable)
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
this.timeRangeColumn = "create_time";

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.agileboot.domain.shop.approvalGoods.db.ApprovalGoodsMapper">
</mapper>

View File

@ -61,7 +61,7 @@ public class CodeGenerator {
//生成的类 放在orm子模块下的/target/generated-code目录底下
.module("/agileboot-orm/target/generated-code")
.parentPackage("com.agileboot")
.tableName("ab98_user_tag")
.tableName("approval_goods")
// 决定是否继承基类
.isExtendsFromBaseEntity(true)
.build();

View File

@ -13,3 +13,11 @@ AFTER `balance`;
ALTER TABLE `qy_user`
ADD COLUMN `balance_limit` DECIMAL(15,2) NOT NULL DEFAULT '0.00' COMMENT '余额额度'
AFTER `use_balance`;
ALTER TABLE `qy_user`
ADD COLUMN `ab98_user_id` bigint NULL COMMENT '汇邦云用户id'
AFTER `userid`;
ALTER TABLE `ab98_user`
ADD COLUMN `qy_user_id` bigint NULL COMMENT '企业用户id'
AFTER `userid`;

View File

@ -18,3 +18,11 @@ CREATE TABLE `ab98_user_tag` (
ALTER TABLE `smart_cabinet`
ADD COLUMN `belong_type` TINYINT NOT NULL DEFAULT 0 COMMENT '归属类型0-借还柜 1-固资通)'
AFTER `main_cabinet`;
ALTER TABLE `smart_cabinet`
ADD COLUMN `mode` TINYINT NOT NULL DEFAULT 0 COMMENT '运行模式0-支付模式 1-审批模式 2-借还模式 3-会员模式)'
AFTER `main_cabinet`;
ALTER TABLE `smart_cabinet`
ADD COLUMN `balance_enable` TINYINT NOT NULL DEFAULT 1 COMMENT '借呗支付1-正常使用 0-禁止使用)'
AFTER `main_cabinet`;

82
sql/20250605.sql Normal file
View File

@ -0,0 +1,82 @@
ALTER TABLE `shop_goods`
ADD COLUMN `belong_type` TINYINT NOT NULL DEFAULT 0 COMMENT '归属类型0-借还柜 1-固资通)'
AFTER `category_id`;
ALTER TABLE `shop_goods`
ADD COLUMN `external_goods_id` BIGINT NULL COMMENT '外部归属类型的商品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`);
CREATE TABLE `approval_goods` (
`approval_goods_id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`approval_id` bigint NOT NULL COMMENT '审批ID',
`goods_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品名称',
`goods_id` bigint NOT NULL COMMENT '关联商品ID',
`external_goods_id` bigint DEFAULT NULL COMMENT '外部归属类型的商品ID',
`corpid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业微信id',
`belong_type` tinyint NOT NULL DEFAULT '0' COMMENT '归属类型0-借还柜 1-固资通)',
`price` decimal(15,2) NOT NULL DEFAULT '0.00' COMMENT '销售价格',
`apply_quantity` int DEFAULT NULL COMMENT '申请数量',
`cover_img` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '封面图URL',
`creator_id` bigint NULL DEFAULT '0' COMMENT '创建者ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater_id` bigint NULL DEFAULT '0' COMMENT '更新者ID',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '删除标志0存在 1删除',
PRIMARY KEY (`approval_goods_id`),
KEY `idx_approval_id` (`approval_id`),
KEY `idx_goods_id` (`goods_id`),
KEY `idx_external_goods_id` (`external_goods_id`),
KEY `idx_corpid` (`corpid`),
KEY `idx_update_time` (`update_time`)
) ENGINE=InnoDB AUTO_INCREMENT=87 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='申请领用商品信息表';
ALTER TABLE `shop`
ADD COLUMN `corpid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业微信id'
AFTER `shop_name`;
ALTER TABLE `shop_order`
ADD COLUMN `corpid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业微信id';
ALTER TABLE `shop_order_goods`
ADD COLUMN `corpid` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '企业微信id';
ALTER TABLE `shop_goods`
ADD COLUMN `monthly_purchase_limit` INT DEFAULT NULL COMMENT '每人每月限购数量'
AFTER `corpid`;
ALTER TABLE `shop_order_goods`
ADD COLUMN `approval_id` bigint NULL COMMENT '审批ID'
AFTER `order_id`;
UPDATE shop_goods SET corpid = 'wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw';
UPDATE return_approval SET corpid = 'wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw';
UPDATE shop SET corpid = 'wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw';
UPDATE shop_order SET corpid = 'wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw';
UPDATE shop_order_goods SET corpid = 'wpZ1ZrEgAA2QTxIRcB4cMtY7hQbTcPAw';

27
sql/20250611.sql Normal file
View File

@ -0,0 +1,27 @@
ALTER TABLE `shop`
ADD COLUMN `belong_type` tinyint NOT NULL DEFAULT 0 COMMENT '归属类型0-借还柜 1-固资通)'
AFTER `corpid`;
ALTER TABLE `return_approval`
ADD COLUMN `apply_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '申请人企业UserID'
AFTER `corpid`;
ALTER TABLE `return_approval`
ADD COLUMN `audit_userid` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '审批人企业UserID'
AFTER `corpid`;
ALTER TABLE `shop`
ADD COLUMN `mode` TINYINT NOT NULL DEFAULT 0 COMMENT '运行模式0-支付模式 1-审批模式 2-借还模式 3-会员模式 4-耗材模式)'
AFTER `belong_type`;
ALTER TABLE `shop`
ADD COLUMN `balance_enable` TINYINT NOT NULL DEFAULT 1 COMMENT '借呗支付1-正常使用 0-禁止使用)'
AFTER `mode`;
ALTER TABLE `shop`
ADD COLUMN `cover_img` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '封面图URL'
AFTER `balance_enable`;
ALTER TABLE `return_approval`
ADD COLUMN `code` varchar(32) DEFAULT NULL COMMENT '审批码'
AFTER `external_approval_id`;