Commit 8dee8e33 authored by 何金镒's avatar 何金镒

建发:共享空间优惠券预约

parent 38019317
......@@ -34,7 +34,16 @@
-
- 1、当用户提出在某个时间段要预约您管理的某个会所或房间时,请按照以下步骤回应用户的控制:
- 调用mcp函数getAppointmentTimeByRoomId查询可预约时间
- 调用mcp函数getUserCoupons获取可用优惠卷
- 若有可用优惠券,在这些优惠卷中如果其deductionTime大于等于用户预约的时间长度,且优惠卷的startTime和endTime在用户的预约时间内,
就可以使用该张优惠券,若有优惠卷符合条件,就需要把这些张优惠券的名称和抵扣时间、使用日期告知用户,且要询问用户是否使用该张优惠卷,
若有多张优惠卷符合条件,告知用户后,需要让用户选择使用哪张优惠券
- 若用户选择使用了某张优惠卷,则调用mcp函数bookingOrder使用优惠卷预订房间(会所)
- 若用户为使用优惠券,则直接回复:未使用优惠券,请自行支付购买
注意:
- 预约必须一个小时起,不能隔天
package com.ikonke.konkeaialibabamcp.aitools;
import cn.hutool.core.exceptions.StatefulException;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.ikonke.konkeaialibabamcp.service.cdc.spaces.SpacesService;
......@@ -18,32 +19,40 @@ public class CDCSpacesTools {
this.spacesService = spacesService;
}
@Tool(description = "根据房间ID和日期查询该日期可预约情况")
@Tool(description = "根据房间(会所)ID和日期查询该日期可预约情况")
public JSONObject getAppointmentTimeByRoomId(@ToolParam(description = "设备的sn号,如:00226DA86A12")String sn,
@ToolParam(description = "查询的日,如:2025-08-12")String date,
@ToolParam(description = "查询的日,如:2025-08-12")String date,
@ToolParam(description = "查询的房间ID")String roomId,
@ToolParam(description = "查询的房间的子空间ID,可省略")String subspaceId){
log.info("getAppointmentTimeByRoomId..获取预约时间..sn:{},time:{},roomId:{},roomSubspaceId:{}",sn,date,roomId,subspaceId);
@ToolParam(description = "查询的房间的子空间ID,可省略", required = false)String subspaceId){
log.info("mcp调用--->getAppointmentTimeByRoomId..获取预约时间..sn:{},time:{},roomId:{},roomSubspaceId:{}",sn,date,roomId,subspaceId);
return spacesService.getAppointmentTimeByRoomId(sn,date,roomId,subspaceId);
}
@Tool(description = "获取该房间ID下可使用的优惠卷")
public JSONArray getUserCoupons(@ToolParam(description = "设备的sn号,如:00226DA86A12")String sn,
@Tool(description = "获取该房间(会所)ID下可使用的优惠卷")
public JSONArray getUserSpacesCoupons(@ToolParam(description = "设备的sn号,如:00226DA86A12")String sn,
@ToolParam(description = "查询的房间ID")String roomId){
log.info("getUserCoupons..获取用户优惠券..sn:{},roomId:{}",sn,roomId);
log.info("mcp调用--->getUserCoupons..获取用户优惠券..sn:{},roomId:{}",sn,roomId);
return spacesService.getUserCoupons(sn,roomId);
}
@Tool(description = "使用优惠卷预订房间")
public boolean bookingOrder(@ToolParam(description = "设备的sn号,如:00226DA86A12")String sn,
@Tool(description = "使用优惠卷预订房间(会所)")
public String bookingSpaces(@ToolParam(description = "设备的sn号,如:00226DA86A12")String sn,
@ToolParam(description = "使用的开始时间,必须是30分钟的倍数且不能隔天预约,如:2025-08-12 09:00:00")String beginTime,
@ToolParam(description = "使用的结束时间,必须是30分钟的倍数且不能隔天预约,如:2025-08-12 10:30:00")String endTime,
@ToolParam(description = "预约的房间ID")String roomId,
@ToolParam(description = "预约的房间下的子空间ID")String subspaceId,
@ToolParam(description = "使用的人数,必须大于1")int userQuantity,
@ToolParam(description = "使用的优惠券ID,不能为空")String couponId){
log.info("bookingOrder..预约订单..sn:{},beginTime:{},endTime:{},roomId:{},roomSubspaceId:{},userQuantity:{},couponId:{}",
sn,beginTime,endTime,roomId,subspaceId,userQuantity,couponId);
return spacesService.bookingOrder(sn,beginTime,endTime,roomId,subspaceId,userQuantity,couponId);
@ToolParam(description = "预约的房间下的子空间ID,若不是预约子空间可省略", required = false)String subspaceId,
@ToolParam(description = "使用的人数,必须大于0")int userQuantity,
@ToolParam(description = "使用的优惠券ID,不能为空")String couponsId){
log.info("mcp调用--->bookingOrder..预约订单..sn:{},beginTime:{},endTime:{},roomId:{},roomSubspaceId:{},userQuantity:{},couponId:{}",
sn,beginTime,endTime,roomId,subspaceId,userQuantity,couponsId);
try {
if(spacesService.bookingOrder(sn,beginTime,endTime,roomId,subspaceId,userQuantity,couponsId)){
return "预约成功";
}else{
return "预约失败";
}
}catch (StatefulException e){
return e.getMessage();
}
}
}
......@@ -28,7 +28,7 @@ public class DeviceTools {
@Tool(description = "根据主机号和设备ID查询设备状态信息.")
public DeviceStatus findDeviceState(@ToolParam(description = "主机号") String ccuName,
@ToolParam(description = "设备ID") Integer devId) {
log.info("根据主机号和设备ID查询设备状态信息....ccuName:{},devId:{}",ccuName,devId);
log.info("mcp调用--->根据主机号和设备ID查询设备状态信息....ccuName:{},devId:{}",ccuName,devId);
return deviceStatusUtil.findUserByUserId(CcuUtils.getCcuName(ccuName), devId);
}
......@@ -36,20 +36,20 @@ public class DeviceTools {
public String optDeviceOpen(@ToolParam(description = "主机号")String ccuName,
@ToolParam(description = "设备ID")String devId,
@ToolParam(description = "设备类型")String operateId){
log.info("根据主机号和设备ID控制打开设备....ccuName:{},devId:{},operateId:{}",ccuName,devId,operateId);
log.info("mcp调用--->根据主机号和设备ID控制打开设备....ccuName:{},devId:{},operateId:{}",ccuName,devId,operateId);
return konkeIotServer.optDeviceOpen(CcuUtils.getCcuName(ccuName), devId, operateId);
}
@Tool(description = "根据主机号和设备ID控制关闭设备")
public String optDeviceClosed(@ToolParam(description = "主机号")String ccuName,
@ToolParam(description = "设备ID")String devId,
@ToolParam(description = "设备类型")String operateId){
log.info("根据主机号和设备ID控制关闭设备....ccuName:{},devId:{},operateId:{}",ccuName,devId,operateId);
log.info("mcp调用--->根据主机号和设备ID控制关闭设备....ccuName:{},devId:{},operateId:{}",ccuName,devId,operateId);
return konkeIotServer.optDeviceClosed(CcuUtils.getCcuName(ccuName), devId, operateId);
}
@Tool(description = "根据主机号同步设备")
public boolean synchronousDevice(@ToolParam(description = "主机号")String ccuName){
log.info("根据主机号同步设备....ccuName:{}",ccuName);
log.info("mcp调用--->根据主机号同步设备....ccuName:{}",ccuName);
return sycDeviceService.synchronousDevice(CcuUtils.getCcuName(ccuName));
}
......
......@@ -18,17 +18,17 @@ public class WeatherTools {
@Tool(description = "根据城市名查询当前的天气")
public String getWeatherNow(@ToolParam(description = "城市,如:成都、西安")String city){
log.info("根据城市名查询当前的天气....city:{}",city);
log.info("mcp调用--->根据城市名查询当前的天气....city:{}",city);
return weatherUtils.getWeatherNow(city);
}
@Tool(description = "根据城市名查询未来24小时的天气")
public String getWeatherHourly(@ToolParam(description = "城市,如:成都、西安")String city){
log.info("根据城市名查询未来24小时的天气...city:{}",city);
log.info("mcp调用--->根据城市名查询未来24小时的天气...city:{}",city);
return weatherUtils.getWeatherHourly(city);
}
@Tool(description = "根据城市名查询未来7天的天气")
public String getWeatherDaily(@ToolParam(description = "城市,如:成都、西安")String city){
log.info("根据城市名查询未来7天的天气....city:{}",city);
log.info("mcp调用--->根据城市名查询未来7天的天气....city:{}",city);
return weatherUtils.getWeatherDaily(city);
}
......
......@@ -184,21 +184,78 @@ public class SpacesService {
Date begin_time = DateUtil.parse(beginTime);
Date end_time = DateUtil.parse(endTime);
if(begin_time.getTime() >= end_time.getTime()){
throw new StatefulException(53, "开始时间不能大于结束时间");
throw new StatefulException(530, "开始时间不能大于结束时间");
}
if(!DateUtil.formatDate(begin_time).equals(DateUtil.formatDate(end_time))){
throw new StatefulException(54, "不能跨天预约");
throw new StatefulException(531, "不能跨天预约");
}
if(begin_time.getTime() < System.currentTimeMillis()){
throw new StatefulException(55, "不能预约历史时间");
throw new StatefulException(532, "不能预约历史时间");
}
if(DateUtil.between(new Date(), end_time, DateUnit.DAY) > 7){
throw new StatefulException(56, "不能预约超过7天");
throw new StatefulException(533, "不能预约超过7天");
}
int begin_num = CDCUtils.getTimeSegmentIndex(DateUtil.formatTime(begin_time));
int end_num = CDCUtils.getTimeSegmentIndex(DateUtil.formatTime(end_time));
String use_time = DateUtil.formatDate(begin_time);
//校验预约时间
JSONObject booking_time_param = new JSONObject();
booking_time_param.set("time", use_time);
booking_time_param.set("id", roomId);
if(StrUtil.isNotBlank(subspaceId)){
List<String> roomSubspaceIdsList = new ArrayList<>();
roomSubspaceIdsList.add(subspaceId);
booking_time_param.set("roomSubspaceIds", roomSubspaceIdsList);
}
String post = cdcHttpUtils.post(getSpacesRoomBookingUrl, sn, booking_time_param.toString());
JSONObject jsonObject = new JSONObject(post);
if(jsonObject.getInt("code") == 200){
JSONObject dataJson = jsonObject.getJSONObject("data");
JSONObject firstDayJson = dataJson.getJSONObject("firstDay");
JSONArray info = firstDayJson.getJSONArray("info");
//0=不可预定 1=可预订 2=已被预定
boolean begin_use = info.getInt(begin_num) == 1;
boolean end_use = info.getInt(end_num) == 1;
if(!begin_use || !end_use){
throw new StatefulException(534, "该时间段已经不能被预约了");
}
}else{
throw new StatefulException(535, "该天不能预约");
}
//校验优惠券
String s = cdcHttpUtils.get(getUserCouponsUrl+"?status=0&roomId="+roomId, sn);
JSONObject coupons = JSONUtil.parseObj(s);
if(coupons.getInt("code") == 200){
JSONArray rows = coupons.getJSONArray("rows");
for (int i = 0; i < rows.size(); i++){
JSONObject coup = rows.getJSONObject(i);
String coupons_id = coup.getStr("id");
if(coupons_id.equals(couponId)){
String discountTime = coup.getStr("discount");//抵用时长(只能是0.5的整数倍)
int time = Integer.parseInt(discountTime) * 30;
if(DateUtil.between(begin_time, end_time, DateUnit.MINUTE) > time){
throw new StatefulException(536, "优惠卷的抵扣时间小于了您选择的时间");
}
String coup_start_time_str = coup.getStr("startTime");
Date coup_start_time = DateUtil.parse(coup_start_time_str);
if(begin_time.getTime() < coup_start_time.getTime()){
throw new StatefulException(537, "优惠卷不能使用,因为超过了优惠券的有效期");
}
String coup_end_time_str =coup.getStr("endTime");
Date coup_end_time = DateUtil.parse(coup_end_time_str);
if(end_time.getTime() > coup_end_time.getTime()){
throw new StatefulException(537, "优惠券不能使用,因为超过了优惠券的有效期");
}
}
}
}else{
throw new StatefulException(538, "不能使用该优惠券,请联系工作人员");
}
//====================================
JSONObject param = new JSONObject();
param.set("roomId", roomId);
if(StrUtil.isNotBlank(subspaceId)){
......@@ -214,12 +271,12 @@ public class SpacesService {
param.set("payFlag", "false");
String post = cdcHttpUtils.post(spacesRoomOrderUrl, sn, param.toString());
JSONObject jsonObject = new JSONObject(post);
if(jsonObject.getInt("code") == 200){
String spacesRoomOrder_post = cdcHttpUtils.post(spacesRoomOrderUrl, sn, param.toString());
JSONObject spacesRoomOrder = new JSONObject(spacesRoomOrder_post);
if(spacesRoomOrder.getInt("code") == 200){
return true;
}else{
throw new StatefulException(57, "预约失败");
throw new StatefulException(539, "预约失败");
}
}
......
......@@ -29,6 +29,18 @@ mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.ikonke.konkeaialibabamcp.entity.mysql
logging:
level:
root: info
file:
path: ./log/${server.port}
pattern:
file: '%d{yyyy/MM/dd HH:mm:ss.SSS} %-5level [%X{traceId:-}][%thread] %logger{15} : %msg%n'
console: '%d{yyyy/MM/dd HH:mm:ss.SSS} %clr(%-5level) [%X{traceId:-}][%magenta(%thread)] %cyan(%logger{15}) : %msg%n'
logback:
rollingpolicy:
max-history: 30
konke:
weather:
clientId: da4c19db2be64671
......
- 测试主机
# 设备控制
## 任务
根据用户的输入的主机号{{#1754485785703.ccuName#}}和可操作的设备:{{#1754554523017.body#}}再调用对应的mcp服务来完成用户的控制设备的需求
## 注意
控制设备操作必须调用mcp服务,严禁不调用mcp服务直接回复用户
# 设备状态查询
## 任务
根据用户的输入的主机号{{#1754485785703.ccuName#}}和可操作的设备:{{#17546471575190.body#}}再调用对应的mcp服务来完成用户的查询设备状态的需求
## 注意
查询设备状态操作必须调用mcp服务,严禁不调用mcp服务直接回复用户
# 会所管理
## 任务
1、根据会所信息或调用mcp函数来回答用户关于会所的问题
2、根据会所信息调用mcp函数getUserCoupons来获取某个会所可使用的优惠卷
3、根据会所信息和用户的输入调用mcp函数getAppointmentTimeByRoomId查询可预约时间
4、当用户提出在某个时间段要预约您管理的某个会所或房间时,请按照以下步骤回应用户的控制:
- 调用mcp函数getUserCoupons获取可用优惠卷
- 若有可用优惠券,在这些优惠卷中,如果其deductionTime大于等于用户预约的时间总长度,且用户的预约时间在优惠卷的startTime和endTime内,
就可以使用该张优惠券,若有多张优惠卷符合条件,就选择第一张,然后询问用户:是否使用优惠券(名称)进行预约
- 若用户选择使用优惠卷进行预约,则调用mcp函数bookingOrder使用优惠卷预订房间(会所)
- 若用户没有优惠券或者选择不使用优惠券,则直接回复:暂不支持,请手动购买
## 注意:
- 预约开始时间和预约结束时间不能是过去时间
- 预约结束时间必须大于预约开始时间且要大于1小时
- 预约结束时间和预约开始时间必须是同一天
- 预约时间不能大于当前时间的7天
## 背景
管理的会所信息:{{#1754902598746.body#}}
管理的设备SN:{{#1754485785703.sn#}}
## 示例引导:
用户输入:"帮我查询一下我茶室有没有优惠卷可用"
期望输出:"您有一张茶室的优惠卷,使用时间是2025年8月1日到2025年9月1日,优惠8小时" 或 "您目前还没有对应的优惠券可使用。"
用户输入:"查询一下茶室今天下午2点到4点还可以预约吗?"
期望输出:"茶室2025年8月13日下午2点到4点可以预约" 或 "茶室2025年8月13日下午2点到4点已经不能预约了"
用户输入:"帮我预约下午2点到4点的茶室"
期望输出:"预约成功" 或 "暂不支持在线支付,请自行支付购买"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment