feat:咖啡机订单优化

This commit is contained in:
dzc committed 2026-09-23 10:50:56 +08:00
1 parent 9d6949a860
commit 40fb0d2191
5 files changed
+96 -30

No files matched your search

@@ -1,17 +1,28 @@
package com.bsd.pjcloud.hard.api.vo.coffee;
import com.bsd.pjcloud.admin.api.dto.user.SysUserStudentDto;
import com.bsd.pjcloud.admin.api.dto.user.SysUserTeacherDto;
import com.bsd.pjcloud.admin.api.vo.base.BaseUserDeptInterface;
import com.bsd.pjcloud.admin.api.vo.base.BaseUserIdentityInterface;
import com.bsd.pjcloud.hard.api.entity.coffee.HardCoffeeOrderEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;
import java.util.List;
/**
* 咖啡机订单管理端分页/详情
* 咖啡机订单管理端分页/详情,含用户主资料与身份展示资料
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class HardCoffeeOrderVo extends HardCoffeeOrderEntity {
public class HardCoffeeOrderVo extends HardCoffeeOrderEntity
implements BaseUserDeptInterface, BaseUserIdentityInterface {
/**
* 支付用户主键(hard_order.user_id),用于批量回填用户与身份资料
*/
private Long userId;
/**
* 设备名称
@@ -19,9 +30,54 @@ public class HardCoffeeOrderVo extends HardCoffeeOrderEntity {
private String hardName;
/**
* 支付人姓名
* 用户姓名,历史字段承载,供 UserInfoCell 组件展示
*/
private String userName;
private String username;
/**
* 用户手机号(历史字段)
*/
private String userMobile;
/**
* 用户标准手机号字段,供统一身份组件展示;与历史 userMobile 字段并存
*/
private String phone;
/**
* 用户头像
*/
private String userAvatar;
/**
* 用户当前部门主键
*/
private Long userDeptId;
/**
* 用户当前部门名称
*/
private String userDeptName;
/**
* 用户部门名称(标准字段)
*/
private String deptName;
/**
* 用户身份协议编码集合;没有身份时为空集合或空值
*/
private List<String> identityTypes;
/**
* 学生身份扩展资料;没有学生身份时为空
*/
private SysUserStudentDto studentInfo;
/**
* 老师身份扩展资料;没有老师身份时为空
*/
private SysUserTeacherDto teacherInfo;
/**
* 本地订单状态
@@ -14,9 +14,9 @@ import org.springframework.stereotype.Component;
public class CoffeeConf {
/**
* 厂商接口域名,测试环境 https://test.wulicoffee.com,生产环境 https://www.wulicoffee.com
* 厂商接口域名,测试环境 https://cafe.soudaoni.com,生产环境 https://www.wulicoffee.com
*/
private String baseUrl = "https://test.wulicoffee.com";
private String baseUrl = "https://cafe.soudaoni.com";
/**
* HTTP 超时时间(毫秒)
@@ -7,10 +7,8 @@ import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.admin.api.dto.UserInfo;
import com.bsd.pjcloud.admin.api.entity.SysUser;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.tenant.TenantBroker;
import com.bsd.pjcloud.common.data.tenant.TenantContextHolder;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
@@ -44,6 +42,7 @@ import com.bsd.pjcloud.hard.service.HardCoffeeService;
import com.bsd.pjcloud.hard.service.HardManagerService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.hard.service.impl.coffee.WuliCoffeeClient.WuliCallContext;
import com.bsd.pjcloud.hard.support.HardUserIdentitySupport;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
@@ -131,6 +130,7 @@ public class HardCoffeeServiceImpl implements HardCoffeeService {
private final HardCoffeeLogService coffeeLogService;
private final HardManagerService hardManagerService;
private final HardOrderService hardOrderService;
private final HardUserIdentitySupport userIdentitySupport;
private final WuliCoffeeClient wuliCoffeeClient;
private final RemoteMchService remoteMchService;
@@ -586,7 +586,7 @@ public class HardCoffeeServiceImpl implements HardCoffeeService {
}
/**
* 管理端咖啡机订单分页(当前租户),补齐订单状态/支付人/设备名
* 管理端咖啡机订单分页(当前租户),补齐订单状态/支付人/设备名及用户身份资料
*/
@Override
public Page<HardCoffeeOrderVo> orderPage(Page page, HardCoffeeOrderDto dto) {
@@ -604,15 +604,7 @@ public class HardCoffeeServiceImpl implements HardCoffeeService {
records.stream().map(HardCoffeeOrderEntity::getHardId).filter(Objects::nonNull).collect(Collectors.toList()),
ids -> hardManagerService.listByIds(ids).stream()
.collect(Collectors.toMap(HardManagerEntity::getId, HardManagerEntity::getName, (a, b) -> a)));
Map<Long, String> userNameMap = listByIdsMap(
orderMap.values().stream().map(HardOrderEntity::getUserId).filter(id -> id != null && id > 0).collect(Collectors.toList()),
ids -> {
R<List<SysUser>> userResult = remoteUserService.getInnerUserById(ids);
List<SysUser> users = userResult != null && userResult.isOk() && ObjectUtil.isNotEmpty(userResult.getData())
? userResult.getData() : List.of();
return users.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getName, (a, b) -> a));
});
voPage.setRecords(records.stream().map(entity -> {
List<HardCoffeeOrderVo> voRecords = records.stream().map(entity -> {
HardCoffeeOrderVo vo = BeanUtil.toBean(entity, HardCoffeeOrderVo.class);
HardOrderEntity order = orderMap.get(entity.getOrderId());
if (ObjectUtil.isNotEmpty(order)) {
@@ -622,17 +614,26 @@ public class HardCoffeeServiceImpl implements HardCoffeeService {
vo.setRefundPrice(order.getRefundPrice());
vo.setRefundStatus(order.getRefundStatus());
if (order.getUserId() != null && order.getUserId() > 0) {
vo.setUserName(userNameMap.get(order.getUserId()));
vo.setUserId(order.getUserId());
}
}
if (entity.getHardId() != null) {
vo.setHardName(hardNameMap.get(entity.getHardId()));
}
return vo;
}).collect(Collectors.toList()));
}).collect(Collectors.toList());
fillOrderUserInfo(voRecords);
voPage.setRecords(voRecords);
return voPage;
}
/**
* 批量补齐支付用户的姓名、手机、部门与身份资料
*/
private void fillOrderUserInfo(List<HardCoffeeOrderVo> voRecords) {
userIdentitySupport.fillUserInfo(voRecords, true);
}
private LambdaQueryWrapper<HardCoffeeOrderEntity> buildOrderWrapper(HardCoffeeOrderDto dto) {
LambdaQueryWrapper<HardCoffeeOrderEntity> wrapper = new LambdaQueryWrapper<>();
if (dto == null) {
@@ -709,10 +710,7 @@ public class HardCoffeeServiceImpl implements HardCoffeeService {
vo.setRefundPrice(order.getRefundPrice());
vo.setRefundStatus(order.getRefundStatus());
if (order.getUserId() != null && order.getUserId() > 0) {
R<List<SysUser>> userResult = remoteUserService.getInnerUserById(List.of(order.getUserId()));
if (userResult != null && userResult.isOk() && ObjectUtil.isNotEmpty(userResult.getData())) {
vo.setUserName(userResult.getData().get(0).getName());
}
vo.setUserId(order.getUserId());
}
}
if (coffeeOrder.getHardId() != null) {
@@ -721,6 +719,7 @@ public class HardCoffeeServiceImpl implements HardCoffeeService {
vo.setHardName(hard.getName());
}
}
fillOrderUserInfo(List.of(vo));
HardCoffeeOrderDetailVo detail = new HardCoffeeOrderDetailVo();
detail.setOrder(vo);
detail.setLogs(coffeeLogService.list(new LambdaQueryWrapper<HardCoffeeLogEntity>()
@@ -22,6 +22,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.security.SecureRandom;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
@@ -286,6 +287,7 @@ public class WuliCoffeeClient {
try {
String url = StrUtil.removeSuffix(coffeeConf.getBaseUrl(), "/") + "/api/order/" + action;
String res = cn.hutool.http.HttpUtil.createPost(url)
.charset(StandardCharsets.UTF_8)
.form(form)
.timeout(coffeeConf.getTimeoutMillis())
.execute()
@@ -307,7 +309,8 @@ public class WuliCoffeeClient {
/**
* 读取屋里咖啡密钥配置,本地缓存5分钟(空值同样缓存)。
* 匿名扫码场景无租户上下文,密钥按平台级全局唯一维护,由thirdparty跨租户查询
* 匿名扫码场景无租户上下文,密钥按平台级全局唯一维护,由thirdparty跨租户查询。
* 读取时去除前后空格,避免管理端录入带空格导致厂商侧appid校验失败
*/
private ThirdKeyManageEntity getKeyConfig(ThirdKeyTypeEnum type) {
KeyCacheEntry cached = keyCache.get(type.getType());
@@ -318,8 +321,10 @@ public class WuliCoffeeClient {
ThirdKeyManageEntity entity = null;
try {
R<ThirdKeyManageEntity> result = thirdKeyManageService.getByBizType(type.getType());
if (result != null && result.isOk()) {
if (result != null && result.isOk() && ObjectUtil.isNotEmpty(result.getData())) {
entity = result.getData();
entity.setAppKey(StrUtil.trim(entity.getAppKey()));
entity.setAppSecret(StrUtil.trim(entity.getAppSecret()));
}
} catch (Exception e) {
log.error("|{}|读取third_key_manage失败,bizType:{}", TAG, type.getType(), e);
@@ -329,12 +334,18 @@ public class WuliCoffeeClient {
}
/**
* 读取必填密钥配置,未配置时直接抛错阻断调用
* 读取必填密钥配置,未配置或格式不符时抛出带字段映射说明的错误,便于联调排查。
* 映射关系: app_key=厂商appid,app_secret=厂商appkey;文档要求两者均为16位大小写字母或数字
*/
private ThirdKeyManageEntity requireKeyConfig(ThirdKeyTypeEnum type) {
ThirdKeyManageEntity keyConfig = getKeyConfig(type);
if (ObjectUtil.isEmpty(keyConfig) || StrUtil.hasBlank(keyConfig.getAppKey(), keyConfig.getAppSecret())) {
throw new RuntimeException("屋里咖啡密钥未配置,请在third_key_manage维护bizType=" + type.getType());
throw new RuntimeException("屋里咖啡密钥未配置,请在third_key_manage维护bizType=" + type.getType()
+ ",注意字段映射:app_key填厂商appid,app_secret填厂商appkey");
}
if (!keyConfig.getAppKey().matches("[A-Za-z0-9]{16}") || !keyConfig.getAppSecret().matches("[A-Za-z0-9]{16}")) {
throw new RuntimeException("屋里咖啡密钥格式错误(应为16位大小写字母或数字),请检查third_key_manage bizType="
+ type.getType() + ",注意字段映射:app_key填厂商appid,app_secret填厂商appkey");
}
return keyConfig;
}
@@ -60,9 +60,9 @@ yyx:
template: 购买成功总金额${price}元
# 屋里咖啡咖啡机对接:密钥在 thirdparty 服务 third_key_manage 表维护(bizType=11 我方调厂商、12 厂商调我方查单)。
# 测试环境 base-url https://test.wulicoffee.com,生产环境 https://www.wulicoffee.com。
# 测试环境 base-url https://cafe.soudaoni.com,生产环境 https://www.wulicoffee.com。
coffee:
base-url: https://test.wulicoffee.com
base-url: https://cafe.soudaoni.com
timeout-millis: 10000
#yyx: