Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-04-18 10:48:46 +08:00
commit 04cbe9c200
117 files changed
+4341 -508

No files matched your search

+113 -21
View File
@@ -52,11 +52,13 @@ CREATE TABLE hard_door_manager
power_status int DEFAULT NULL COMMENT '1:通电;2:断电',
net_status int DEFAULT NULL COMMENT '在线状态。1:在线;2:离线',
sale_status int DEFAULT NULL COMMENT '售卖状态。1:在售;2:停售',
sim_sn varchar(32) NOT NULL COMMENT 'sim 卡号。设备有上报会返回,若一次上报都没有,则返回 null',
signal_intensity int DEFAULT NULL COMMENT 'sim 信号强度。大于-95 表示信号强度好;-95 到-105 表示信号强度中等;小于-105 表示信号差;',
signal_ratio int DEFAULT NULL COMMENT '信噪比,体现信道传输质量的参数。大于 15 表示质量好;15 到 0 表示质量中等;小于等于 0 表示质量差;',
signal_time int DEFAULT NULL COMMENT 'sim 信号值更新时间。yyyy-MM-dd HH:mm:ss',
cabinet_list text DEFAULT NULL COMMENT '货柜列表JSON',
signal_time datetime DEFAULT NULL COMMENT 'sim 信号值更新时间。yyyy-MM-dd HH:mm:ss',
restart_time datetime DEFAULT NULL COMMENT '上次重启时间',
system_volume int DEFAULT 0 COMMENT '系统音量',
media_volume int DEFAULT 0 COMMENT '媒体音量',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
@@ -68,6 +70,87 @@ CREATE TABLE hard_door_manager
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='柜子设备管理';
-- ----------------------------
-- Table structure for hard_door_cabinet
-- ----------------------------
DROP TABLE IF EXISTS `hard_door_cabinet`;
CREATE TABLE hard_door_cabinet
(
id bigint NOT NULL COMMENT '编号',
hard_door_id bigint NOT NULL COMMENT '智能柜编号',
cabinet_no int NOT NULL COMMENT '货柜编号(1,2)',
is_lock_online varchar(16) NOT NULL COMMENT '锁在线1:在线;2:离线;',
lock_status int NOT NULL COMMENT '锁状态1:开锁;2:关锁;',
door_status int NOT NULL COMMENT '门状态1:门关;2:门开',
sale_status int NOT NULL COMMENT '货柜售卖状态1:在售;2:停售',
qr_code varchar(256) DEFAULT NULL COMMENT '二维码',
# 其他字段
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
update_time datetime DEFAULT NULL COMMENT '修改时间',
del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
tenant_id bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='智能柜货柜';
-- ----------------------------
-- Table structure for hard_door_flow
-- ----------------------------
DROP TABLE IF EXISTS `hard_door_flow`;
CREATE TABLE hard_door_flow
(
id bigint NOT NULL COMMENT '编号',
user_id bigint NOT NULL COMMENT '用户编号',
biz_type varchar(32) NOT NULL COMMENT '业务类型',
hard_id bigint DEFAULT NULL COMMENT '硬件id',
hard_door_id bigint DEFAULT NULL COMMENT '智能柜id',
cabinet_no int DEFAULT NULL COMMENT '货柜编号',
order_id bigint DEFAULT NULL COMMENT '订单编号',
auth_id bigint DEFAULT NULL COMMENT '授权编号',
# 请求开门
request_open_dto varchar(512) DEFAULT NULL COMMENT '请求开门参数',
request_open_vo varchar(512) DEFAULT NULL COMMENT '请求开门返回',
request_open_time datetime DEFAULT NULL COMMENT '请求开门时间',
# 请求开门回调
is_open varchar(32) DEFAULT NULL COMMENT '是否开门',
open_callback_time datetime DEFAULT NULL COMMENT '开门回调时间',
open_callback_vo varchar(512) DEFAULT NULL COMMENT '开门回调结果',
# 视频回调
video_callback_vo varchar(512) DEFAULT NULL COMMENT '视频回调结果',
video_callback_time datetime DEFAULT NULL COMMENT '视频回调时间',
# sku识别
sku_submit_dto varchar(512) DEFAULT NULL COMMENT 'sku识别提交参数',
sku_submit_vo varchar(512) DEFAULT NULL COMMENT 'sku识别提交结果',
sku_submit_recog_id varchar(32) DEFAULT NULL COMMENT 'sku识别提交id(用于查询)',
sku_submit_time datetime DEFAULT NULL COMMENT 'sku识别提交时间',
# sku识别回调
sku_callback_vo varchar(512) DEFAULT NULL COMMENT 'sku识别回调结果',
sku_callback_time datetime DEFAULT NULL COMMENT 'sku识别回调时间',
# sku主动获取
sku_driving_dto varchar(512) DEFAULT NULL COMMENT 'sku识别主动获取参数',
sku_driving_vo varchar(512) DEFAULT NULL COMMENT 'sku识别主动获取结果',
sku_driving_time datetime DEFAULT NULL COMMENT 'sku识别主动获取时间',
# 流程相关
flow_status varchar(32) DEFAULT NULL COMMENT '流程状态',
error varchar(512) DEFAULT NULL COMMENT '流程错误信息',
error_desc varchar(64) DEFAULT NULL COMMENT '流程错误描述(展示)',
# 购买成功
pay_time datetime DEFAULT NULL COMMENT '购买成功时间',
# 其他字段
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
update_time datetime DEFAULT NULL COMMENT '修改时间',
del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
tenant_id bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='柜子订单流程';
-- ----------------------------
-- Table structure for hard_group
-- ----------------------------
@@ -266,6 +349,7 @@ CREATE TABLE hard_broadcast
user_id bigint NOT NULL COMMENT '预定用户',
hard_id bigint NOT NULL COMMENT '硬件id',
topic varchar(128) NOT NULL COMMENT 'mq主题',
biz_type varchar(64) NOT NULL COMMENT '关联业务类型',
biz_id varchar(64) NOT NULL COMMENT '关联业务编号',
title varchar(64) NOT NULL COMMENT '预定标题',
content varchar(128) NOT NULL COMMENT '广播内容',
@@ -289,20 +373,24 @@ CREATE TABLE hard_broadcast
DROP TABLE IF EXISTS hard_auth;
CREATE TABLE hard_auth
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
auth_type varchar(32) DEFAULT NULL COMMENT '授权类型如微信小程序、支付宝、浙政钉',
user_id bigint NOT NULL COMMENT '预定用户',
hard_id bigint NOT NULL COMMENT '硬件id',
auth_status char(1) DEFAULT '0' COMMENT '是否授权',
auth_time datetime DEFAULT NULL COMMENT '授权时间',
is_done char(1) DEFAULT '0' COMMENT '是否完成',
is_done_time datetime DEFAULT NULL COMMENT '完成时间',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
update_time datetime DEFAULT NULL COMMENT '修改时间',
del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
tenant_id bigint DEFAULT NULL COMMENT '租户ID',
id bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
auth_type varchar(32) DEFAULT NULL COMMENT '授权类型如微信小程序、支付宝、浙政钉',
user_id bigint NOT NULL COMMENT '预定用户',
hard_id bigint NOT NULL COMMENT '硬件id',
cabinet_no int DEFAULT NULL COMMENT '货柜编号',
auth_status char(1) DEFAULT '0' COMMENT '是否授权',
auth_time datetime DEFAULT NULL COMMENT '授权时间',
is_done char(1) DEFAULT '0' COMMENT '是否完成',
is_done_time datetime DEFAULT NULL COMMENT '完成时间',
is_manual_change varchar(32) DEFAULT NULL COMMENT '是否人工处理',
manual_change_time datetime DEFAULT NULL COMMENT '人工处理时间',
manual_change_remark varchar(512) DEFAULT NULL COMMENT '人工处理备注',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
update_time datetime DEFAULT NULL COMMENT '修改时间',
del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
tenant_id bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (id)
) ENGINE = InnoDB COMMENT ='硬件授权';
@@ -313,9 +401,10 @@ DROP TABLE IF EXISTS hard_spu;
CREATE TABLE hard_spu
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
spu_category_id bigint NOT NULL COMMENT '商品分类id',
spu_category_id bigint DEFAULT NULL COMMENT '商品分类id',
name varchar(64) NOT NULL COMMENT '商品名',
pic varchar(256) NOT NULL COMMENT '商品图片',
cover varchar(256) NOT NULL COMMENT '商品封面图片',
pic varchar(1024) NOT NULL COMMENT '商品图片用于识别',
price int NOT NULL COMMENT '单价(分)',
sales_count int DEFAULT 0 NOT NULL COMMENT '销量',
repertory_count int DEFAULT 0 NOT NULL COMMENT '库存',
@@ -325,13 +414,16 @@ CREATE TABLE hard_spu
specs_taste varchar(128) DEFAULT NULL COMMENT '规格-口味',
specs_capacity varchar(128) DEFAULT NULL COMMENT '规格-容量',
specs_weight varchar(128) DEFAULT NULL COMMENT '规格-重量',
sku_type varchar(32) DEFAULT NULL COMMENT 'sku类型,0:标准库;1:私有库 ',
sku_type varchar(32) DEFAULT NULL COMMENT 'sku类型,0:标准库;1:私有库',
ks_sku_id varchar(32) DEFAULT NULL COMMENT '旷世skuid',
ks_res_sku_id varchar(32) DEFAULT NULL COMMENT '旷世返回的业务方sku_id',
ks_barcode varchar(32) DEFAULT NULL COMMENT '69码',
ks_has_sub_sku varchar(128) DEFAULT NULL COMMENT '是否为集合SKU',
ks_sub_sku text DEFAULT NULL COMMENT '集合SKU的子SKU信息',
ks_sub_sku_json text DEFAULT NULL COMMENT '集合SKU的子SKU信息JSON',
ks_status char(1) DEFAULT NULL COMMENT '旷世审核状态',
ks_status_title varchar(64) DEFAULT NULL COMMENT '旷世审核状态标题',
ks_comments varchar(512) DEFAULT NULL COMMENT '旷世审核状态描述',
version int DEFAULT 0 NOT NULL COMMENT '乐观锁',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
@@ -389,10 +481,10 @@ CREATE TABLE hard_spu_repertory
(
id bigint NOT NULL AUTO_INCREMENT COMMENT '编号',
user_id bigint NOT NULL COMMENT '用户id',
hard_id bigint NOT NULL COMMENT '设备id',
spu_id bigint NOT NULL COMMENT '商品id',
before_count int NOT NULL COMMENT '更新前的库存数量',
count int DEFAULT 0 COMMENT '更新库存数量',
biz_id bigint DEFAULT NULL COMMENT '上架业务关联id',
biz_type tinytext NOT NULL COMMENT '上架类型',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
+1
View File
@@ -415,6 +415,7 @@ CREATE TABLE wallet_code_use
status char(1) DEFAULT '0' NOT NULL COMMENT '是否使用',
code varchar(1024) DEFAULT NULL COMMENT '二维码',
code_content varchar(1024) DEFAULT NULL COMMENT '二维码内容',
short_code varchar(32) DEFAULT '' COMMENT '短码',
use_time timestamp NULL COMMENT '使用时间',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
@@ -6,7 +6,8 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum MerchantTypeEnum {
CANTEEN("1", "食堂"),
OTHER_CANTEEN("0", "其他食堂"),
CANTEEN("1", "自营食堂"),
SUPERMARKET("2", "合作商家"),
SELF_SUPERMARKET("3", "自营商家"),
;
@@ -52,5 +52,11 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.bsd</groupId>
<artifactId>pjcloud-thirdparty-api</artifactId>
<version>5.7.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,27 @@
package com.bsd.pjcloud.hard.api.constant;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 硬件授权类型
*/
@AllArgsConstructor
@Getter
public enum HardAuthTypeEnum {
HARD_DDOR_AUTH("10", "智能柜授权"),
;
private final String type;
private final String description;
public static HardAuthTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,24 @@
package com.bsd.pjcloud.hard.api.constant;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 硬件广播类型
*/
@AllArgsConstructor
@Getter
public enum HardBroadcastEnum {
OFFLINE_CANTEEN_RESERVE("1", "线下食堂订餐广播"),
;
private final String type;
private final String description;
public static HardBroadcastEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,31 @@
package com.bsd.pjcloud.hard.api.constant;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
/**
* 开门类型
*/
@AllArgsConstructor
@Getter
public enum HardDoorOpenTypeEnum {
RECORD_VIDEO("1", "录制视频"),
NO_RECORD_VIDEO("4", "不录制视频"),
MAINTENANCE_UNLOCK("5", "检修开锁"),
MAINTENANCE_LOCK("6", "检修关锁");;
private final String type;
private final String description;
public static List<String> getMaintenanceListCodes() {
return List.of(MAINTENANCE_UNLOCK.getType(), MAINTENANCE_LOCK.getType());
}
public static HardDoorOpenTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,26 @@
package com.bsd.pjcloud.hard.api.constant.flow;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 智能柜开门流程
*/
@AllArgsConstructor
@Getter
public enum HardDoorFlowBizEnum {
PAY_OPEN("10", "购买开门"),
REPERTORY_OPEN("20", "上架开门"),
ACCESS_OPEN("30", "检修开门"),
;
private final String type;
private final String description;
public static HardDoorFlowBizEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,39 @@
package com.bsd.pjcloud.hard.api.constant.flow;
import cn.hutool.core.util.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 智能柜流程
*/
@AllArgsConstructor
@Getter
public enum HardDoorFlowEnum {
FLOW_AUTH("10", "用户授权", "20"),
FLOW_APPLY_OPEN("20", "智能柜申请开门", "30"),
FLOW_CALLBACK_OPEN("30", "智能柜开门响应", "40"),
FLOW_CALLBACK_VIDEO("40", "智能柜视频回调", "50"),
FLOW_SUBMIT_RECOGNITION("50", "旷世提交识别", "60"),
FLOW_CALLBACK_RECOGNITION("60", "旷世识别响应", "70"),
FLOW_PAY_ORDER("70", "订单结算", null),
;
private final String type;
private final String description;
private final String nextType;
public static HardDoorFlowEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
public static HardDoorFlowEnum getNextType(HardDoorFlowEnum type) {
if (ObjectUtil.isEmpty(type)) return null;
HardDoorFlowEnum currentFlow = valueOfByType(type.getType());
if (ObjectUtil.isEmpty(currentFlow) || ObjectUtil.isEmpty(currentFlow.getNextType())) return null;
return valueOfByType(currentFlow.getNextType());
}
}
@@ -19,6 +19,7 @@ public enum HardOrderStatusEnum {
OFFLINE_PAY("6", "没有网络本地支付"),
REFUND("10", "退款"),
CANCEL("20", "已核销"),
UNFOLLOW("30", "已取消(智能柜使用)"),
;
private final String type;
private final String description;
@@ -23,6 +23,7 @@ public enum HardPayTypeEnum {
FOREIGN_TICKET_QR_CODE("6", "外来人员二维码支付"),
RESERVE_QR_CODE("7", "线上订餐二维码支付"),
CASH("8", "现金支付"),
HARD_DOOR_FREE_PAY("9", "智能柜免密支付"),
;
private final String type;
private final String description;
@@ -13,7 +13,7 @@ import java.util.Arrays;
@Getter
public enum HardSpuRepertoryTypeEnum {
HANDLER("10", "手动上架"),
AUTO("20", "自动上架"),
PERSION("20", "上架员上架"),
;
private final String type;
private final String description;
@@ -0,0 +1,27 @@
package com.bsd.pjcloud.hard.api.dto;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HardAuthAppDto {
/**
* 用户id
*/
private Long userId;
/**
* 授权id
*/
@NotNull(message = "授权id不能为空")
private Long authId;
/**
* 是否授权
*/
@NotEmpty(message = "是否授权不能为空")
private String authStatus;
}
@@ -0,0 +1,13 @@
package com.bsd.pjcloud.hard.api.dto;
import com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity;
import lombok.Data;
import java.time.LocalDate;
@Data
public class HardDoorFlowDto extends HardDoorFlowEntity {
private LocalDate[] createTimeList;
}
@@ -0,0 +1,48 @@
package com.bsd.pjcloud.hard.api.dto;
import com.bsd.pjcloud.hard.api.constant.flow.HardDoorFlowBizEnum;
import com.bsd.pjcloud.hard.api.constant.HardDoorOpenTypeEnum;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HardDoorFlowOpenDto {
/**
* 柜子id
*/
@NotNull(message = "hardDoorId不能为空")
private Long hardDoorId;
/**
* 智能柜编号
*/
@NotNull(message = "货柜编号不能为空")
private Integer cabinetNo;
/**
* 智能柜子流程id
*/
private Long hardDoorFlowId;
/**
* 流程类型
*/
private HardDoorFlowBizEnum flowType;
/**
* 开门操作类型
*/
private HardDoorOpenTypeEnum openType;
/**
* 开门用户id
*/
private Long userId;
/**
* 授权id
*/
private Long authId;
}
@@ -0,0 +1,26 @@
package com.bsd.pjcloud.hard.api.dto;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HardGetAuthAppDto {
/**
* 用户id
*/
private Long userId;
/**
* 智能柜设备id
*/
@NotNull(message = "智能柜设备id不能为空")
private Long doorHardId;
/**
* 货柜编号
*/
@NotNull(message = "货柜编号不能为空")
private Integer cabinetNo;
}
@@ -22,7 +22,8 @@ public class HardAdminRefundDto {
@Schema(description = "相关描述")
private String applyDescription;
@Schema(description="补充凭证图片")
@Schema(description = "补充凭证图片")
@NotNull(message = "补充凭证图片不能为空")
private String applyPicUrls;
}
@@ -0,0 +1,37 @@
package com.bsd.pjcloud.hard.api.dto.spu;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Data
public class DeductionSpuRepertoryDto {
/**
* 流程id
*/
@NotNull(message = "流程id不能为空")
private Long flowId;
/**
* 上架数量
*/
@NotEmpty(message = "商品列表不能为空")
private List<DeductionSpuRepertoryDto.Item> list;
@Data
public static class Item {
@NotNull(message = "商品id不能为空")
private Long hardSpuId;
@NotNull(message = "增加库存不能为空")
private Integer plusCount;
}
}
@@ -0,0 +1,15 @@
package com.bsd.pjcloud.hard.api.dto.spu;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
@Data
public class DeductionSpuStockDto {
private Long hardSpuId;
private Integer incrCount;
}
@@ -0,0 +1,21 @@
package com.bsd.pjcloud.hard.api.dto.spu;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class HardPutawayDto {
/**
* 绑定id
*/
@NotNull(message = "绑定id不能为空")
private Long id;
/**
* 商品id
*/
@NotNull(message = "商品id")
private Long hardSpuId;
}
@@ -1,18 +1,12 @@
package com.bsd.pjcloud.hard.api.dto.spu;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class HardSpuDto extends HardSpuEntity {
private List<Long> spuIdList;
@@ -5,4 +5,10 @@ import lombok.Data;
@Data
public class HardSpuJoinDto extends HardSpuJoinEntity {
/**
* 是否有商品
*/
private Boolean isSpu = false;
}
@@ -3,8 +3,7 @@ package com.bsd.pjcloud.hard.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
@@ -12,6 +11,9 @@ import java.time.LocalDateTime;
/**
* 硬件授权
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@TenantTable
@TableName("hard_auth")
@@ -40,9 +42,15 @@ public class HardAuthEntity extends Model<HardAuthEntity> {
private Long hardId;
/**
* 是否授权
* 货柜编号
*/
@Schema(description = "是否授权")
@Schema(description = "货柜编号")
private Integer cabinetNo;
/**
* 授权类型
*/
@Schema(description = "授权类型")
private String authType;
/**
@@ -69,6 +77,24 @@ public class HardAuthEntity extends Model<HardAuthEntity> {
@Schema(description = "完成时间")
private LocalDateTime isDoneTime;
/**
* 是否人工处理
*/
@Schema(description = "是否人工处理")
private String isManualChange;
/**
* 人工处理时间
*/
@Schema(description = "人工处理时间")
private LocalDateTime manualChangeTime;
/**
* 人工处理备注
*/
@Schema(description = "人工处理时间")
private String manualChangeRemark;
/**
* 创建人
*/
@@ -3,14 +3,17 @@ package com.bsd.pjcloud.hard.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
* 设备广播
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@TenantTable
@TableName("hard_broadcast")
@@ -19,118 +22,124 @@ import java.time.LocalDateTime;
public class HardBroadcastEntity extends Model<HardBroadcastEntity> {
/**
* 编号
*/
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description="编号")
@Schema(description = "编号")
private Long id;
/**
* 预定用户
*/
@Schema(description="预定用户")
/**
* 预定用户
*/
@Schema(description = "预定用户")
private Long userId;
/**
* 硬件id
*/
@Schema(description="硬件id")
/**
* 硬件id
*/
@Schema(description = "硬件id")
private Long hardId;
/**
* mq主题
*/
@Schema(description="mq主题")
/**
* mq主题
*/
@Schema(description = "mq主题")
private String topic;
/**
* 关联业务编号
*/
@Schema(description="关联业务编号")
/**
* 业务类型
*/
@Schema(description = "业务类型")
private String bizType;
/**
* 关联业务编号
*/
@Schema(description = "关联业务编号")
private String bizId;
/**
* 预定标题
*/
@Schema(description="预定标题")
/**
* 预定标题
*/
@Schema(description = "预定标题")
private String title;
/**
* 广播内容
*/
@Schema(description="广播内容")
/**
* 广播内容
*/
@Schema(description = "广播内容")
private String content;
/**
* 当前广播次数
*/
@Schema(description="当前广播次数")
/**
* 当前广播次数
*/
@Schema(description = "当前广播次数")
private Integer broadcastCount;
/**
* 最大广播次数
*/
@Schema(description="最大广播次数")
/**
* 最大广播次数
*/
@Schema(description = "最大广播次数")
private Integer broadcastMaxCount;
/**
* 是否广播语音
*/
@Schema(description="是否广播语音")
/**
* 是否广播语音
*/
@Schema(description = "是否广播语音")
private String isBroadcast;
/**
* 是否完成
*/
@Schema(description="是否完成")
/**
* 是否完成
*/
@Schema(description = "是否完成")
private String isDone;
/**
* 完成时间
*/
@Schema(description="完成时间")
/**
* 完成时间
*/
@Schema(description = "完成时间")
private LocalDateTime isDoneTime;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建人")
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建时间")
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改人")
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改时间")
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description="删除标记")
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description="租户ID")
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -0,0 +1,244 @@
package com.bsd.pjcloud.hard.api.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
* 智能柜流程
*
* @author hard
* @date 2025-04-14 16:08:33
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@TenantTable
@TableName("hard_door_flow")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "智能柜流程")
public class HardDoorFlowEntity extends Model<HardDoorFlowEntity> {
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "编号")
private Long id;
/**
* 用户编号
*/
@Schema(description = "用户编号")
private Long userId;
/**
* 业务类型
*/
@Schema(description = "业务类型")
private String bizType;
/**
* 硬件id
*/
@Schema(description = "硬件id")
private Long hardId;
/**
* 智能柜id
*/
@Schema(description = "智能柜id")
private Long hardDoorId;
/**
* 货柜编号
*/
@Schema(description = "货柜编号")
private Integer cabinetNo;
/**
* 订单编号
*/
@Schema(description = "订单编号")
private Long orderId;
/**
* 授权编号
*/
@Schema(description = "授权编号")
private Long authId;
/**
* 请求开门参数
*/
@Schema(description = "请求开门参数")
private String requestOpenDto;
/**
* 请求开门返回
*/
@Schema(description = "请求开门返回")
private String requestOpenVo;
/**
* 请求开门时间
*/
@Schema(description = "请求开门时间")
private LocalDateTime requestOpenTime;
/**
* 是否开门
*/
@Schema(description = "是否开门")
private String isOpen;
/**
* 开门回调时间
*/
@Schema(description = "开门回调时间")
private LocalDateTime openCallbackTime;
/**
* 开门回调结果
*/
@Schema(description = "开门回调结果")
private String openCallbackVo;
/**
* 视频回调结果
*/
@Schema(description = "视频回调结果")
private String videoCallbackVo;
/**
* 视频回调时间
*/
@Schema(description = "视频回调时间")
private LocalDateTime videoCallbackTime;
/**
* sku识别提交参数
*/
@Schema(description = "sku识别提交参数")
private String skuSubmitDto;
/**
* sku识别提交结果
*/
@Schema(description = "sku识别提交结果")
private String skuSubmitVo;
/**
* sku识别提交id(用于查询)
*/
@Schema(description = "sku识别提交id(用于查询)")
private String skuSubmitRecogId;
/**
* sku识别提交时间
*/
@Schema(description = "sku识别提交时间")
private LocalDateTime skuSubmitTime;
/**
* sku识别回调结果
*/
@Schema(description = "sku识别回调结果")
private String skuCallbackVo;
/**
* sku识别回调时间
*/
@Schema(description = "sku识别回调时间")
private LocalDateTime skuCallbackTime;
/**
* sku识别主动获取参数
*/
@Schema(description = "sku识别主动获取参数")
private String skuDrivingDto;
/**
* sku识别主动获取结果
*/
@Schema(description = "sku识别主动获取结果")
private String skuDrivingVo;
/**
* sku识别主动获取时间
*/
@Schema(description = "sku识别主动获取时间")
private LocalDateTime skuDrivingTime;
/**
* 支付时间
*/
@Schema(description = "支付时间")
private LocalDateTime payTime;
/**
* 流程状态
*/
@Schema(description = "流程状态")
private String flowStatus;
/**
* 流程错误信息
*/
@Schema(description = "流程错误信息")
private String error;
/**
* 流程错误描述(展示)
*/
@Schema(description = "流程错误描述(展示)")
private String errorDesc;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -0,0 +1,115 @@
package com.bsd.pjcloud.hard.api.entity.manager;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
* 智能柜货柜
*
* @author dzc
* @date 2025-04-15 18:28:46
*/
@Data
@TenantTable
@TableName("hard_door_cabinet")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "智能柜货柜")
public class HardDoorCabinetEntity extends Model<HardDoorCabinetEntity> {
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description="编号")
private Long id;
/**
* 智能柜编号
*/
@Schema(description="智能柜编号")
private Long hardDoorId;
/**
* 货柜编号(1,2)
*/
@Schema(description="货柜编号(1,2)")
private Integer cabinetNo;
/**
* 锁在线1:在线;2:离线;
*/
@Schema(description="锁在线1:在线;2:离线;")
private String isLockOnline;
/**
* 锁状态1:开锁;2:关锁;
*/
@Schema(description="锁状态1:开锁;2:关锁;")
private Integer lockStatus;
/**
* 门状态1:门关;2:门开
*/
@Schema(description="门状态1:门关;2:门开")
private Integer doorStatus;
/**
* 货柜售卖状态1:在售;2:停售
*/
@Schema(description="货柜售卖状态1:在售;2:停售")
private Integer saleStatus;
/**
* 二维码
*/
@Schema(description="二维码")
private String qrCode;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description="删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description="租户ID")
private Long tenantId;
}
@@ -7,6 +7,7 @@ import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
import java.util.List;
/**
* 智能柜设置
@@ -89,6 +90,12 @@ public class HardDoorManagerEntity extends Model<HardDoorManagerEntity> {
@Schema(description = "售卖状态。1:在售;2:停售")
private Integer saleStatus;
/**
* sim 卡号。设备有上报会返回,若一次上报都没有,则返回 null。
*/
@Schema(description = "sim 卡号。设备有上报会返回,若一次上报都没有,则返回 null。")
private String simSn;
/**
* sim 信号强度。大于-95 表示信号强度好;-95 到-105 表示信号强度中等;小于-105 表示信号差;
*/
@@ -105,13 +112,7 @@ public class HardDoorManagerEntity extends Model<HardDoorManagerEntity> {
* sim 信号值更新时间。yyyy-MM-dd HH:mm:ss
*/
@Schema(description = "sim 信号值更新时间。yyyy-MM-dd HH:mm:ss")
private Integer signalTime;
/**
* 货柜列表JSON
*/
@Schema(description = "货柜列表JSON")
private String cabinetList;
private LocalDateTime signalTime;
/**
* 上次重启时间
@@ -119,6 +120,18 @@ public class HardDoorManagerEntity extends Model<HardDoorManagerEntity> {
@Schema(description = "上次重启时间")
private LocalDateTime restartTime;
/**
* 系统音量
*/
@Schema(description = "系统音量")
private Integer systemVolume;
/**
* 媒体音量
*/
@Schema(description = "媒体音量")
private Integer mediaVolume;
/**
* 创建人
*/
@@ -178,11 +178,17 @@ public class HardOrderEntity extends Model<HardOrderEntity> {
private String refundStatus;
/**
* 订单取消时间
* 订单取消时间(退款订单)
*/
@Schema(description = "订单取消时间")
private LocalDateTime applyCancelTime;
/**
* 订单取消时间(智能柜)
*/
@Schema(description = "订单取消时间(智能柜)")
private LocalDateTime unfollowTime;
/**
* 设备上的唯一订单号
*/
@@ -7,8 +7,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
@@ -16,6 +15,9 @@ import java.time.LocalDateTime;
/**
* 硬件商品
*/
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
@TenantTable
@TableName("hard_spu")
@@ -46,9 +48,15 @@ public class HardSpuEntity extends Model<HardSpuEntity> {
private String name;
/**
* 商品图片
* 商品封面图片
*/
@Schema(description = "商品图片")
@Schema(description = "商品封面图片")
private String cover;
/**
* 商品图片用于识别
*/
@Schema(description = "商品图片用于识别")
private String pic;
/**
@@ -109,11 +117,24 @@ public class HardSpuEntity extends Model<HardSpuEntity> {
/**
* sku类型,0:标准库;1:私有库
*
* @see HardKsSkuTypeEnum
*/
@Schema(description = "sku类型,0:标准库;1:私有库")
private String skuType;
/**
* 旷世skuid
*/
@Schema(description = "旷世skuid")
private String ksSkuId;
/**
* 旷世返回的业务方sku_id
*/
@Schema(description = "旷世返回的业务方sku_id")
private String ksResSkuId;
/**
* 69码
*/
@@ -130,7 +151,7 @@ public class HardSpuEntity extends Model<HardSpuEntity> {
* 是否为集合SKU
*/
@Schema(description = "是否为集合SKU")
private String ksSubSku;
private String ksSubSkuJson;
/**
* 旷世审核状态
@@ -144,6 +165,12 @@ public class HardSpuEntity extends Model<HardSpuEntity> {
@Schema(description = "旷世审核状态标题")
private String ksStatusTitle;
/**
* 乐观锁
*/
@Version
private Integer version;
/**
* 旷世审核状态描述
*/
@@ -36,12 +36,6 @@ public class HardSpuRepertoryEntity extends Model<HardSpuRepertoryEntity> {
@Schema(description = "用户id")
private Long userId;
/**
* 设备id
*/
@Schema(description = "设备id")
private Long hardId;
/**
* 商品id
*/
@@ -63,6 +57,12 @@ public class HardSpuRepertoryEntity extends Model<HardSpuRepertoryEntity> {
@Schema(description = "更新库存数量")
private Integer count;
/**
* 上架业务关联id
*/
@Schema(description = "上架业务关联id")
private Long bizId;
/**
* 上架类型
*/
@@ -0,0 +1,45 @@
package com.bsd.pjcloud.hard.api.feign;
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.thirdparty.dto.door.DoorOpenCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorStatusCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorVideoCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(contextId = "remoteHardDoorService", value = ServiceNameConstants.HARDWARE_SERVICE)
public interface RemoteHardDoorService {
/**
* 处理柜子开门回调
*/
@NoToken
@PostMapping("/hard-door-flow/dispose-locak-callback")
void disposeLocakCallback(@RequestBody DoorOpenCallbackDto dto);
/**
* 处理柜子视频回调
*/
@NoToken
@PostMapping("/hard-door-flow/dispose-video-callback")
void disposeVideoCallback(@RequestBody DoorVideoCallbackDto dto);
/**
* 处理柜子视频回调
*/
@NoToken
@PostMapping("/hard-door-flow/dispose-status-callback")
void disposeStatusCallback(@RequestBody DoorStatusCallbackDto dto);
/**
* 处理旷世识别回调
*/
@NoToken
@PostMapping("/hard-door-flow/dispose-recognition-callback")
void disposeRecognitionCallback(@RequestBody KsRecognitionCallbackDto dto);
}
@@ -0,0 +1,36 @@
package com.bsd.pjcloud.hard.api.vo;
import com.bsd.pjcloud.admin.api.vo.base.BaseUserDeptInterface;
import com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity;
import com.bsd.pjcloud.hard.api.vo.base.BaseHardInterface;
import lombok.Data;
import java.util.List;
@Data
public class HardDoorFlowVo extends HardDoorFlowEntity implements BaseHardInterface, BaseUserDeptInterface {
/**
* 设备相关
*/
private String hardName;
private String hardType;
private List<String> hardTypeCodes;
/**
* 用户相关
*/
private String username;
private String userMobile;
private String userAvatar;
private Long userDeptId;
private String userDeptName;
}
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.hard.api.vo;
import lombok.Data;
@Data
public class HardGetAuthAppVo {
/**
* 授权id
*/
private Long authId;
/**
* 授权信息
*/
private String authDesc;
}
@@ -0,0 +1,18 @@
package com.bsd.pjcloud.hard.api.vo.manager;
import lombok.Data;
@Data
public class HardDoorCabinetCodeVo {
/**
* 智能柜id
*/
private String hardDoorId;
/**
* 货柜编号
*/
private String cabinetNo;
}
@@ -1,10 +1,14 @@
package com.bsd.pjcloud.hard.api.vo.manager;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorCabinetEntity;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorManagerEntity;
import com.bsd.pjcloud.hard.api.vo.base.BaseHardInterface;
import lombok.Data;
import java.util.List;
@Data
public class HardDoorManagerVo extends HardDoorManagerEntity {
public class HardDoorManagerVo extends HardDoorManagerEntity implements BaseHardInterface {
/**
* 硬件设备相关
*/
@@ -12,4 +16,8 @@ public class HardDoorManagerVo extends HardDoorManagerEntity {
private String hardType;
private List<String> hardTypeCodes;
private List<HardDoorCabinetEntity> cabinetList;
}
@@ -2,12 +2,11 @@ package com.bsd.pjcloud.hard.api.vo.spu;
import com.bsd.pjcloud.admin.api.vo.base.BaseUserInterface;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuRepertoryEntity;
import com.bsd.pjcloud.hard.api.vo.base.BaseHardInterface;
import com.bsd.pjcloud.wallet.api.vo.base.BaseMchInterface;
import lombok.Data;
@Data
public class HardSpuRepertoryVo extends HardSpuRepertoryEntity implements BaseMchInterface, BaseHardInterface, BaseUserInterface {
public class HardSpuRepertoryVo extends HardSpuRepertoryEntity implements BaseMchInterface, BaseUserInterface {
/**
* 商品相关
@@ -34,13 +33,6 @@ public class HardSpuRepertoryVo extends HardSpuRepertoryEntity implements BaseMc
private String logoPic;
/**
* 设备相关
*/
private String hardName;
private String hardType;
/**
* 用户相关
*/
@@ -1,2 +1,3 @@
com.bsd.pjcloud.hard.api.feign.RemoteHardDoorService
com.bsd.pjcloud.hard.api.feign.RemoteHardOrderService
com.bsd.pjcloud.hard.api.feign.RemoteHardThirdSelfZyService
@@ -2,16 +2,21 @@ package com.bsd.pjcloud.hard.controller;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.hard.api.dto.HardAuthAppDto;
import com.bsd.pjcloud.hard.api.dto.HardAuthDto;
import com.bsd.pjcloud.hard.api.dto.HardGetAuthAppDto;
import com.bsd.pjcloud.hard.api.entity.HardAuthEntity;
import com.bsd.pjcloud.hard.api.vo.HardAuthVo;
import com.bsd.pjcloud.hard.api.vo.HardGetAuthAppVo;
import com.bsd.pjcloud.hard.service.HardAuthService;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -23,7 +28,6 @@ import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
* 硬件授权
@@ -37,6 +41,26 @@ public class HardAuthController {
private final HardAuthService hardAuthService;
/* ************************************* start app start ************************************* */
@Operation(summary = "app获取智能柜授权信息", description = "app获取智能柜授权信息")
@PostMapping("/app/get-auth-hard-door")
public R<HardGetAuthAppVo> appGetAuthHardDoor(@Valid @RequestBody HardGetAuthAppDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setUserId(user.getId());
return R.ok(hardAuthService.appGetAuthHardDoor(dto));
}
@Operation(summary = "app智能柜授权", description = "app智能柜授权")
@PostMapping("/app/auth-hard-door")
public R appAuthHardDoor(@Valid @RequestBody HardAuthAppDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setUserId(user.getId());
return R.ok(hardAuthService.appAuthHardDoor(dto));
}
/* ************************************* end app end ************************************* */
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page-join")
@PreAuthorize("@pms.hasPermission('hard_hardAuth_view')")
@@ -0,0 +1,178 @@
package com.bsd.pjcloud.hard.controller;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.hard.api.constant.flow.HardDoorFlowBizEnum;
import com.bsd.pjcloud.hard.api.constant.HardDoorOpenTypeEnum;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowDto;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowOpenDto;
import com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity;
import com.bsd.pjcloud.hard.api.vo.HardDoorFlowVo;
import com.bsd.pjcloud.hard.service.HardDoorFlowService;
import com.bsd.pjcloud.thirdparty.dto.door.DoorOpenCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorStatusCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorVideoCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 智能柜流程
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/hard-door-flow")
@Tag(description = "hard-door-flow", name = "智能柜流程管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class HardDoorFlowController {
private final HardDoorFlowService hardDoorFlowService;
/* ************************************* start 远程调用 start ************************************* */
/**
* 处理柜子开门回调
*/
@Inner()
@PostMapping("/dispose-locak-callback")
public void disposeLocakCallback(@RequestBody DoorOpenCallbackDto dto) {
hardDoorFlowService.disposeLocakCallback(dto);
}
/**
* 处理柜子视频回调
*/
@Inner()
@PostMapping("/dispose-video-callback")
public void disposeVideoCallback(@RequestBody DoorVideoCallbackDto dto) {
hardDoorFlowService.disposeVideoCallback(dto);
}
/**
* 处理柜子状态回调
*/
@Inner()
@PostMapping("/dispose-status-callback")
public void disposeStatusCallback(@RequestBody DoorStatusCallbackDto dto) {
hardDoorFlowService.disposeStatusCallback(dto);
}
/**
* 处理旷世识别回调
*/
@Inner()
@PostMapping("/dispose-recognition-callback")
public void disposeRecognitionCallback(@RequestBody KsRecognitionCallbackDto dto) {
hardDoorFlowService.disposeRecognitionCallback(dto);
}
/* ************************************* end 远程调用 end ************************************* */
/* ************************************* start app start ************************************* */
@Operation(summary = "上架开门", description = "上架开门")
@PostMapping("/app/open-repertory")
public R<Long> openRepertory(@Validated @RequestBody HardDoorFlowOpenDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setFlowType(HardDoorFlowBizEnum.REPERTORY_OPEN);
dto.setOpenType(HardDoorOpenTypeEnum.NO_RECORD_VIDEO);
dto.setUserId(user.getId());
return R.ok(hardDoorFlowService.openDoorRepertory(dto));
}
/* ************************************* end app end ************************************* */
@Operation(summary = "检修开门", description = "检修开门")
@PostMapping("/open-access")
public R openAccess(@Validated @RequestBody HardDoorFlowOpenDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setFlowType(HardDoorFlowBizEnum.ACCESS_OPEN);
dto.setOpenType(HardDoorOpenTypeEnum.MAINTENANCE_UNLOCK);
dto.setUserId(user.getId());
hardDoorFlowService.openDoorAccess(dto);
return R.ok();
}
@Operation(summary = "检修关门", description = "检修关门")
@PostMapping("/close-access")
public R closeAccess(@Validated @RequestBody HardDoorFlowOpenDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setFlowType(HardDoorFlowBizEnum.ACCESS_OPEN);
dto.setOpenType(HardDoorOpenTypeEnum.MAINTENANCE_LOCK);
dto.setUserId(user.getId());
hardDoorFlowService.closeAccess(dto);
return R.ok();
}
@Operation(summary = "复杂查询", description = "复杂查询")
@GetMapping("/page-join")
@PreAuthorize("@pms.hasPermission('dzc_hardDoorFlow_view')")
public R<Page<HardDoorFlowVo>> pageJoin(@ParameterObject Page page, @ParameterObject HardDoorFlowDto dto) {
DataScope dataScope = null;
return R.ok(hardDoorFlowService.scopePageJoin(page, dto, dataScope));
}
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('dzc_hardDoorFlow_view')")
public R<HardDoorFlowVo> join(@PathVariable("id") Long id) {
return R.ok(hardDoorFlowService.join(id));
}
@Operation(summary = "通过订单id查询流程", description = "通过订单id查询流程")
@GetMapping("/get-by-order-id")
@PreAuthorize("@pms.hasPermission('dzc_hardDoorFlow_view')")
public R<HardDoorFlowVo> getByOrderId(@RequestParam Long orderId) {
return R.ok(hardDoorFlowService.getByOrderId(orderId));
}
@Operation(summary = "新增智能柜流程", description = "新增智能柜流程")
@SysLog("新增智能柜流程")
@PostMapping
@PreAuthorize("@pms.hasPermission('dzc_hardDoorFlow_add')")
public R save(@RequestBody HardDoorFlowEntity hardDoorFlow) {
return R.ok(hardDoorFlowService.save(hardDoorFlow));
}
@Operation(summary = "修改智能柜流程", description = "修改智能柜流程")
@SysLog("修改智能柜流程")
@PutMapping
@PreAuthorize("@pms.hasPermission('dzc_hardDoorFlow_edit')")
public R updateById(@RequestBody HardDoorFlowEntity hardDoorFlow) {
return R.ok(hardDoorFlowService.updateById(hardDoorFlow));
}
@Operation(summary = "通过id删除智能柜流程", description = "通过id删除智能柜流程")
@SysLog("通过id删除智能柜流程")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('dzc_hardDoorFlow_del')")
public R removeById(@RequestBody Long[] ids) {
return R.ok(hardDoorFlowService.removeBatchByIds(CollUtil.toList(ids)));
}
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('dzc_hardDoorFlow_export')")
public List<HardDoorFlowEntity> export(HardDoorFlowEntity hardDoorFlow, Long[] ids) {
return hardDoorFlowService.list(Wrappers.lambdaQuery(hardDoorFlow).in(ArrayUtil.isNotEmpty(ids), HardDoorFlowEntity::getId, ids));
}
}
@@ -13,8 +13,8 @@ import com.bsd.pjcloud.hard.api.dto.manager.HardDoorManagerDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardChangeVolume;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorManagerEntity;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorManagerVo;
import com.bsd.pjcloud.hard.service.HardDoorCabinetService;
import com.bsd.pjcloud.hard.service.HardDoorManagerService;
import com.bsd.pjcloud.thirdparty.dto.door.DoorVolumeDto;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -39,16 +39,39 @@ import java.util.List;
public class HardDoorManagerController {
private final HardDoorManagerService hardDoorManagerService;
private final HardDoorCabinetService hardDoorCabinetService;
/* ************************************* start APP start ************************************* */
@Operation(summary = "app查询智能柜列表", description = "app查询智能柜列表")
@GetMapping("/app/page")
public R<Page<HardDoorManagerVo>> appPage(@ParameterObject Page page, @ParameterObject HardDoorManagerDto dto) {
DataScope dataScope = null;
return R.ok(hardDoorManagerService.scopePageJoin(page, dto, dataScope));
}
@Operation(summary = "app查询智能柜详情", description = "app查询智能柜详情")
@GetMapping("/app/detail")
public R appDetail(@RequestParam Long hardDoorId) {
return R.ok(hardDoorManagerService.getByHardDoorId(hardDoorId));
}
/* ************************************* start APP start ************************************* */
@Operation(summary = "绑定设备", description = "绑定设备")
@PostMapping("/bind")
public R bind(@RequestBody HardDoorManagerEntity dto) {
if (ObjectUtil.isEmpty(dto.getImei())) throw new RuntimeException("设备IMEI卡号不能为空");
if (ObjectUtil.isEmpty(dto.getDeviceCode())) throw new RuntimeException("设备内置设备编号不能为空");
hardDoorManagerService.bind(dto);
return R.ok();
}
@Operation(summary = "刷新智能柜货柜二维码", description = "刷新智能柜货柜二维码")
@GetMapping("/refresh-qr-code")
public R refreshQrCode(@RequestParam Long hardDoorId, @RequestParam Integer cabinetNo) {
return R.ok(hardDoorCabinetService.refreshQrCode(hardDoorId, cabinetNo));
}
@Operation(summary = "音量修改", description = "音量修改")
@PostMapping("/change-volume")
public R changeVolume(@Validated @RequestBody HardChangeVolume dto) {
@@ -83,7 +106,7 @@ public class HardDoorManagerController {
@GetMapping("/get-by-hard-id")
@PreAuthorize("@pms.hasPermission('hard_hardDoorManager_view')")
public R<HardDoorManagerVo> getByHardId(@RequestParam Long hardId) {
return R.ok(hardDoorManagerService.getByHardId(hardId));
return R.ok(hardDoorManagerService.getByHardDoorId(hardId));
}
@Operation(summary = "通过id删除智能柜设置", description = "通过id删除智能柜设置")
@@ -8,10 +8,12 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.hard.api.dto.spu.HardPutawayDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuDto;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuJoinVo;
import com.bsd.pjcloud.hard.service.HardSpuService;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -39,6 +41,36 @@ public class HardSpuController {
private final HardSpuService hardSpuService;
/* ************************************* start APP start ************************************* */
@Operation(summary = "app上架", description = "上架")
@PostMapping("/app/putaway")
public R appPutaway(@Valid @RequestBody HardPutawayDto dto) {
hardSpuService.putaway(dto);
return R.ok();
}
@Operation(summary = "app下架", description = "下架")
@PostMapping("/app/un-putaway")
public R appUnPutaway(@Valid @RequestBody HardPutawayDto dto) {
hardSpuService.unPutaway(dto);
return R.ok();
}
@Operation(summary = "app查询货柜补货商品列表", description = "查询货柜补货商品列表")
@GetMapping("/app/cabinet-putaway-list")
public R appCabinetPutawayList(@RequestParam Long hardDoorId, @RequestParam String cabinetNo) {
return R.ok(hardSpuService.appCabinetPutawayList(hardDoorId, cabinetNo));
}
@Operation(summary = "app查询货柜商品列表", description = "查询货柜商品列表")
@GetMapping("/app/cabinet-list")
public R appCabinetList(@RequestParam Long hardId, @RequestParam String cabinetNo) {
return R.ok(hardSpuService.getByCabinetNo(hardId, cabinetNo));
}
/* ************************************* end APP end ************************************* */
@Operation(summary = "拉取旷世商品", description = "拉取旷世商品")
@GetMapping("/async-all")
public R asyncAll() {
@@ -52,6 +84,21 @@ public class HardSpuController {
return R.ok(hardSpuService.getByCabinetNo(hardId, cabinetNo));
}
@Operation(summary = "上架", description = "上架")
@PostMapping("/putaway")
public R putaway(@RequestBody HardPutawayDto dto) {
hardSpuService.putaway(dto);
return R.ok();
}
@Operation(summary = "下架", description = "下架")
@PostMapping("/un-putaway")
public R unPutaway(@RequestBody HardPutawayDto dto) {
hardSpuService.unPutaway(dto);
return R.ok();
}
@Operation(summary = "下拉查询", description = "下拉查询")
@GetMapping("/select")
public R select(@ParameterObject Page page, @ParameterObject HardSpuDto dto) {
@@ -10,9 +10,11 @@ import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.hard.api.dto.spu.DeductionSpuRepertoryDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuRepertoryDto;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuRepertoryEntity;
import com.bsd.pjcloud.hard.service.HardSpuRepertoryService;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -25,7 +27,6 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
* 硬件商品库存更新记录
@@ -39,10 +40,16 @@ public class HardSpuRepertoryController {
private final HardSpuRepertoryService hardSpuRepertoryService;
/* ************************************* start app start ************************************* */
/* ************************************* start APP start ************************************* */
@Operation(summary = "app上架完成", description = "app上架完成")
@PostMapping("/app/repertory-done")
public R<Boolean> appRepertoryDone(@Valid @RequestBody DeductionSpuRepertoryDto body) {
PjcloudUser user = SecurityUtils.getUser();
return R.ok(hardSpuRepertoryService.appRepertoryDone(body, user.getId()));
}
/* ************************************* end app end ************************************* */
/* ************************************* end APP end ************************************* */
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@@ -0,0 +1,38 @@
package com.bsd.pjcloud.hard.mapper;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowDto;
import com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.HardDoorFlowVo;
import com.github.yulichang.query.MPJLambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface HardDoorFlowMapper extends PjcloudBaseMapper<HardDoorFlowEntity> {
default Page<HardDoorFlowVo> scopePageJoin(Page page, HardDoorFlowDto dto, DataScope dataScope) {
MPJLambdaQueryWrapper<HardDoorFlowEntity> wrapper = new MPJLambdaQueryWrapper<HardDoorFlowEntity>()
.selectAll(HardDoorFlowEntity.class)
.eq(ObjectUtil.isNotEmpty(dto.getUserId()), HardDoorFlowEntity::getUserId, dto.getUserId())
.eq(ObjectUtil.isNotEmpty(dto.getBizType()), HardDoorFlowEntity::getBizType, dto.getBizType())
.eq(ObjectUtil.isNotEmpty(dto.getHardDoorId()), HardDoorFlowEntity::getHardDoorId, dto.getHardDoorId())
.eq(ObjectUtil.isNotEmpty(dto.getCabinetNo()), HardDoorFlowEntity::getCabinetNo, dto.getCabinetNo())
.eq(ObjectUtil.isNotEmpty(dto.getOrderId()), HardDoorFlowEntity::getOrderId, dto.getOrderId())
.eq(ObjectUtil.isNotEmpty(dto.getIsOpen()), HardDoorFlowEntity::getIsOpen, dto.getIsOpen())
.between(
ObjectUtil.isNotEmpty(dto.getCreateTimeList()),
HardDoorFlowEntity::getCreateTime,
ObjectUtil.isNotEmpty(dto.getCreateTimeList()) ? dto.getCreateTimeList()[0] : null,
ObjectUtil.isNotEmpty(dto.getCreateTimeList()) ? dto.getCreateTimeList()[1] : null
)
.orderByDesc(HardDoorFlowEntity::getCreateTime)
.orderByDesc(HardDoorFlowEntity::getId);
return selectJoinPage(page, HardDoorFlowVo.class, wrapper);
}
}
@@ -0,0 +1,11 @@
package com.bsd.pjcloud.hard.mapper.manager;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorCabinetEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface HardDoorCabinetMapper extends PjcloudBaseMapper<HardDoorCabinetEntity> {
}
@@ -3,11 +3,30 @@ package com.bsd.pjcloud.hard.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.dto.HardAuthAppDto;
import com.bsd.pjcloud.hard.api.dto.HardAuthDto;
import com.bsd.pjcloud.hard.api.dto.HardGetAuthAppDto;
import com.bsd.pjcloud.hard.api.entity.HardAuthEntity;
import com.bsd.pjcloud.hard.api.vo.HardAuthVo;
import com.bsd.pjcloud.hard.api.vo.HardGetAuthAppVo;
import jakarta.validation.Valid;
public interface HardAuthService extends IService<HardAuthEntity> {
Page<HardAuthVo> scopePageJoin(Page page, HardAuthDto dto, DataScope dataScope);
/**
* app获取智能柜授权信息
*/
HardGetAuthAppVo appGetAuthHardDoor(@Valid HardGetAuthAppDto dto);
/**
* app智能柜授权
*/
Long appAuthHardDoor(HardAuthAppDto dto);
/**
* 判断当前用户信誉
*/
boolean judgeUserCredit(Long userId);
}
@@ -5,10 +5,20 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.dto.HardBroadcastDto;
import com.bsd.pjcloud.hard.api.entity.HardBroadcastEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.HardBroadcastVo;
public interface HardBroadcastService extends IService<HardBroadcastEntity> {
Page<HardBroadcastVo> scopePageJoin(Page page, HardBroadcastDto dto, DataScope dataScope);
/**
* 添加线下食堂预约订单广播
*/
void addReserveOrderTask(HardOrderEntity orderdetail);
/**
* 完成硬件广播
*/
void doneBroadcast(HardOrderEntity orderdetail);
}
@@ -31,27 +31,17 @@ public interface HardCarService extends IService<HardCarEntity> {
/**
* 新增或者更新购物车
*
* @param dto
*/
void saveOrUpload(HardCarSaveOrUpdateDto dto);
/**
* @param userId 用户id
* @param merchantId 商户id
* @param sysType 硬件设备类型
* @param list g购物车类表
* @return 父购物车id
* 创建购物车
*/
Long createCard(Long userId, Long merchantId, HardTypeEnum sysType, HardOrderTypeEnum orderTYpe, List<HardCreateCarDto> list);
/**
* 生成购买商品的描述
*
* @param sysType 订单类型
* @param list 购物车列表
* @return
*/
String computerCarSubject(HardTypeEnum sysType, HardOrderTypeEnum orderType, List<HardCreateCarDto> list);
}
@@ -0,0 +1,19 @@
package com.bsd.pjcloud.hard.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorCabinetEntity;
import com.bsd.pjcloud.thirdparty.vo.door.DoorStatusVo;
import java.util.List;
public interface HardDoorCabinetService extends IService<HardDoorCabinetEntity> {
void saveOrUpdate(Long hardDoorId, List<DoorStatusVo.Cabinet> list);
List<HardDoorCabinetEntity> getListByHardDoorId(Long hardDoorId);
/**
* 刷新智能柜货柜二维码
*/
String refreshQrCode(Long hardDoorId, Integer cabinetNo);
}
@@ -0,0 +1,69 @@
package com.bsd.pjcloud.hard.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowDto;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowOpenDto;
import com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity;
import com.bsd.pjcloud.hard.api.vo.HardDoorFlowVo;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorManagerVo;
import com.bsd.pjcloud.thirdparty.dto.door.DoorOpenCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorStatusCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorVideoCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
public interface HardDoorFlowService extends IService<HardDoorFlowEntity> {
/**
* 复杂查询
*/
Page<HardDoorFlowVo> scopePageJoin(Page page, HardDoorFlowDto dto, DataScope dataScope);
HardDoorFlowVo join(Long id);
/**
* 通过订单id查询流程
*/
HardDoorFlowVo getByOrderId(Long orderId);
/**
* 检修开门
*/
void openDoorAccess(HardDoorFlowOpenDto dto);
/**
* 检修关门
*/
void closeAccess(HardDoorFlowOpenDto dto);
/**
* 购买开门
*/
void openDoorPay(HardDoorFlowOpenDto dto, HardDoorManagerVo hardDoorDetail);
/**
* 上架开门
*/
Long openDoorRepertory(HardDoorFlowOpenDto dto);
/**
* 处理开门回调
*/
void disposeLocakCallback(DoorOpenCallbackDto dto);
/**
* 处理柜子状态回调
*/
void disposeStatusCallback(DoorStatusCallbackDto dto);
/**
* 处理视频回调
*/
void disposeVideoCallback(DoorVideoCallbackDto dto);
/**
* 处理旷世识别回调
*/
void disposeRecognitionCallback(KsRecognitionCallbackDto dto);
}
@@ -15,15 +15,30 @@ public interface HardDoorManagerService extends IService<HardDoorManagerEntity>
/**
* 根据硬件id查询详情
*/
HardDoorManagerVo getByHardId(Long hardId);
HardDoorManagerVo getByHardDoorId(Long hardId);
/**
* 根据硬件设备编号查询详情
*/
HardDoorManagerVo getByDeviceCode(String deviceCode);
/**
* 绑定设备
*/
void bind(HardDoorManagerEntity dto);
/**
* 刷新设备信息
*/
HardDoorManagerEntity refresh(String deviceCode);
/**
* 音量修改
*/
void changeVolume(HardChangeVolume dto);
/**
* 校验设备和货柜编号
*/
HardDoorManagerVo checkDeviceAndCabinet(Long hardDoorId, Integer cabinetNo);
}
@@ -7,10 +7,12 @@ import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.hard.api.dto.hard.HandCancelCodeDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardCreateOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.app.HardAppCreateOrderDto;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
import jakarta.validation.Valid;
import java.util.List;
@@ -42,6 +44,21 @@ public interface HardOrderService extends IService<HardOrderEntity> {
*/
Long appCreateOrderScancode(@Valid HardAppCreateOrderDto dto);
/**
* 创建智能柜订单
*/
Long createHardDoorOrder(Long userId, Long hardId);
/**
* 结算智能柜订单
*/
Long payHardDoorOrder(HardOrderEntity dto, List<KsRecognitionCallbackDto.ResultSku> ksSpuList);
/**
* 智能柜取消订单
*/
Long cancelHardDoorOrder(Long orderId);
/**
* 快速扣款,离线订单使用
*/
@@ -10,4 +10,6 @@ import java.util.List;
public interface HardSpuJoinService extends IService<HardSpuJoinEntity> {
List<HardSpuJoinVo> scopeList(HardSpuJoinDto dto);
List<HardSpuJoinVo> getSpuList(Long hardDoorId, Integer cabinetNo);
}
@@ -4,9 +4,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.hard.api.dto.spu.DeductionSpuRepertoryDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuRepertoryDto;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuRepertoryEntity;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuRepertoryVo;
import jakarta.validation.Valid;
import java.util.ArrayList;
@@ -28,4 +30,9 @@ public interface HardSpuRepertoryService extends IService<HardSpuRepertoryEntity
* 删除
*/
void delByIds(ArrayList<Long> list);
/**
* app上架完成
*/
Boolean appRepertoryDone(DeductionSpuRepertoryDto body, Long userId);
}
@@ -3,6 +3,8 @@ package com.bsd.pjcloud.hard.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.dto.spu.DeductionSpuStockDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardPutawayDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuDto;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuJoinVo;
@@ -19,6 +21,10 @@ public interface HardSpuService extends IService<HardSpuEntity> {
*/
Page<HardSpuVo> scopPageJoin(Page page, HardSpuDto dto, DataScope dataScope);
List<HardSpuEntity> get(List<String> ksSpuIds);
List<HardSpuEntity> getByIds(List<Long> spuIds);
/**
* 新增
*/
@@ -39,8 +45,33 @@ public interface HardSpuService extends IService<HardSpuEntity> {
*/
List<Map<Integer, List<HardSpuJoinVo>>> getByCabinetNo(Long hardId, String cabinetNo);
/**
* 查询货柜补货商品列表
*/
List<HardSpuJoinVo> appCabinetPutawayList(Long hardDoorId, String cabinetNo);
/**
* 上架
*/
void putaway(HardPutawayDto dto);
/**
* 下架
*/
void unPutaway(HardPutawayDto dto);
/**
* 拉取旷世商品
*/
void asyncAll();
/**
* 检验商品
*/
HardSpuEntity validateSpu(Long hardSpuId);
/**
* 扣减库存
*/
Boolean deductionSpuStock(List<DeductionSpuStockDto> list);
}
@@ -1,28 +1,42 @@
package com.bsd.pjcloud.hard.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.admin.api.utils.DataUtil;
import com.bsd.pjcloud.admin.api.vo.UserVO;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.constant.HardAuthTypeEnum;
import com.bsd.pjcloud.hard.api.constant.flow.HardDoorFlowBizEnum;
import com.bsd.pjcloud.hard.api.constant.HardDoorOpenTypeEnum;
import com.bsd.pjcloud.hard.api.dto.HardAuthAppDto;
import com.bsd.pjcloud.hard.api.dto.HardAuthDto;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowOpenDto;
import com.bsd.pjcloud.hard.api.dto.HardGetAuthAppDto;
import com.bsd.pjcloud.hard.api.dto.manager.HardManagerDto;
import com.bsd.pjcloud.hard.api.entity.HardAuthEntity;
import com.bsd.pjcloud.hard.api.entity.manager.HardManagerEntity;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.HardAuthVo;
import com.bsd.pjcloud.hard.api.vo.HardGetAuthAppVo;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorManagerVo;
import com.bsd.pjcloud.hard.mapper.HardAuthMapper;
import com.bsd.pjcloud.hard.mapper.manager.HardDoorManagerMapper;
import com.bsd.pjcloud.hard.mapper.manager.HardManagerMapper;
import com.bsd.pjcloud.hard.service.HardAuthService;
import com.bsd.pjcloud.hard.service.HardDoorFlowService;
import com.bsd.pjcloud.hard.service.HardDoorManagerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@@ -35,7 +49,11 @@ import java.util.List;
@Service
public class HardAuthServiceImpl extends ServiceImpl<HardAuthMapper, HardAuthEntity> implements HardAuthService {
private final HardDoorManagerService hardDoorManagerService;
private final HardDoorFlowService hardDoorFlowService;
private final HardManagerMapper hardManagerMapper;
private final HardDoorManagerMapper hardDoorManagerMapper;
private final RemoteUserService remoteUserService;
@@ -46,6 +64,72 @@ public class HardAuthServiceImpl extends ServiceImpl<HardAuthMapper, HardAuthEnt
return pageList;
}
/**
* app获取智能柜授权信息
*/
@Override
public HardGetAuthAppVo appGetAuthHardDoor(HardGetAuthAppDto dto) {
// 检验智能柜
HardDoorManagerVo hardDoorDetail = hardDoorManagerService.checkDeviceAndCabinet(dto.getDoorHardId(), dto.getCabinetNo());
if (ObjectUtil.isEmpty(hardDoorDetail)) {
throw new RuntimeException("获取智能柜授权信息错误");
}
HardAuthEntity insetObj = HardAuthEntity.builder()
.userId(dto.getUserId())
.hardId(hardDoorDetail.getHardId())
.cabinetNo(dto.getCabinetNo())
.authType(HardAuthTypeEnum.HARD_DDOR_AUTH.getType())
.authStatus(YesNoEnum.NO.getCode())
.isDone(YesNoEnum.NO.getCode())
.build();
baseMapper.insert(insetObj);
HardGetAuthAppVo auhtVo = new HardGetAuthAppVo();
auhtVo.setAuthDesc(getHardDoorAuthDesc());
auhtVo.setAuthId(insetObj.getId());
return auhtVo;
}
/**
* app智能柜授权
*/
@Override
public Long appAuthHardDoor(HardAuthAppDto dto) {
// 查询授权信息
HardAuthEntity authEntity = baseMapper.selectById(dto.getAuthId());
if (ObjectUtil.isEmpty(authEntity)) throw new RuntimeException("授权信息不存在");
// 查询设备信息
HardDoorManagerVo hardDoorDetail = hardDoorManagerService.getByHardDoorId(authEntity.getHardId());
if (ObjectUtil.isEmpty(hardDoorDetail)) throw new RuntimeException("授权信息不存在");
HardAuthEntity updateObj = HardAuthEntity.builder().id(dto.getAuthId()).authStatus(dto.getAuthStatus()).authTime(LocalDateTime.now()).build();
baseMapper.updateById(updateObj);
if (ObjectUtil.equals(dto.getAuthStatus(), YesNoEnum.YES.getCode())) {
// 开门
HardDoorFlowOpenDto openDoorDto = new HardDoorFlowOpenDto();
openDoorDto.setHardDoorId(hardDoorDetail.getId());
openDoorDto.setCabinetNo(authEntity.getCabinetNo());
openDoorDto.setFlowType(HardDoorFlowBizEnum.PAY_OPEN);
openDoorDto.setOpenType(HardDoorOpenTypeEnum.RECORD_VIDEO);
openDoorDto.setUserId(dto.getUserId());
openDoorDto.setAuthId(dto.getAuthId());
hardDoorFlowService.openDoorPay(openDoorDto, hardDoorDetail);
}
return dto.getAuthId();
}
/**
* 判断当前用户信誉
*/
@Override
public boolean judgeUserCredit(Long userId) {
Long count = baseMapper.selectCount(new LambdaQueryWrapper<HardAuthEntity>()
.eq(HardAuthEntity::getUserId, userId)
.eq(HardAuthEntity::getAuthStatus, YesNoEnum.YES.getCode())
.eq(HardAuthEntity::getIsDone, YesNoEnum.NO.getCode())
.ne(HardAuthEntity::getIsManualChange, YesNoEnum.YES.getCode())
);
return count <= 5;
}
private void disposeList(List<HardAuthVo> list, HardAuthDto dto) {
if (ObjectUtil.isEmpty(list)) return;
// 设备
@@ -67,4 +151,26 @@ public class HardAuthServiceImpl extends ServiceImpl<HardAuthMapper, HardAuthEnt
}
}
}
/**
* 获取智能柜授权描述
*/
private String getHardDoorAuthDesc() {
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("授权告示\n")
.append("欢迎使用我们的智能柜设备!为确保您可以顺利使用免密支付的先拿后付功能,请您仔细阅读以下授权条款:\n")
.append("\n授权使用\n")
.append("我们需要您的授权,以允许您通过智能柜进行商品的获取和自动结算。您同意在使用本设备时遵守以下条款。\n")
.append("\n使用流程\n")
.append("请您首先同意本授权,并启动开门程序。\n")
.append("设备开门后,您可以选择并取走所需商品。\n")
.append("关闭柜门后,系统将自动进行结算,费用将通过您事先绑定的支付方式扣除。\n")
.append("\n免密支付\n")
.append("您的支付信息将被安全存储,结算时无需再次输入密码。请确认您所使用的支付方式已正确绑定至您的账户。\n")
.append("\n隐私保护\n")
.append("您的个人信息和支付信息将受到严格保护,并仅用于本次交易及相关服务。\n")
.append("\n同意条款\n")
.append("使用本智能柜设备即视为您已阅读并同意以上所有条款。请谨慎使用,确保遵守使用规定。");
return strBuilder.toString();
}
}
@@ -1,20 +1,25 @@
package com.bsd.pjcloud.hard.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.admin.api.utils.DataUtil;
import com.bsd.pjcloud.admin.api.vo.UserVO;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.constant.HardBroadcastEnum;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.dto.HardBroadcastDto;
import com.bsd.pjcloud.hard.api.dto.manager.HardManagerDto;
import com.bsd.pjcloud.hard.api.entity.HardBroadcastEntity;
import com.bsd.pjcloud.hard.api.entity.manager.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.HardAuthVo;
import com.bsd.pjcloud.hard.api.vo.HardBroadcastVo;
import com.bsd.pjcloud.hard.mapper.HardBroadcastMapper;
import com.bsd.pjcloud.hard.mapper.manager.HardManagerMapper;
@@ -36,6 +41,8 @@ import java.util.List;
@Service
public class HardBroadcastServiceImpl extends ServiceImpl<HardBroadcastMapper, HardBroadcastEntity> implements HardBroadcastService {
static private final String TAG = "硬件广播";
private final HardManagerMapper hardManagerMapper;
private final RemoteUserService remoteUserService;
@@ -47,6 +54,84 @@ public class HardBroadcastServiceImpl extends ServiceImpl<HardBroadcastMapper, H
return pageList;
}
/**
* 添加线下食堂预约订单广播
*/
@Override
public void addReserveOrderTask(HardOrderEntity orderdetail) {
if (ObjectUtil.isEmpty(orderdetail)) return;
HardTypeEnum hardTypeEnum = HardTypeEnum.valueOfByType(orderdetail.getSysType());
if (ObjectUtil.isEmpty(orderdetail)) {
log.error("|{}|addReserveOrderTask发送mq消息失败,设备类型错误hardType不存在hardType|{}|", TAG, orderdetail.getSysType());
return;
}
if (ObjectUtil.notEqual(hardTypeEnum, HardTypeEnum.CANTEEN)) return;
HardOrderTypeEnum hardOrderType = HardOrderTypeEnum.valueOfByType(orderdetail.getOrderType());
if (ObjectUtil.isEmpty(hardOrderType)) {
log.error("|{}|addReserveOrderTask发送mq消息失败,订餐类型错误hardType不存在hardType|{}|", TAG, orderdetail.getOrderType());
return;
}
if (ObjectUtil.notEqual(hardOrderType, HardOrderTypeEnum.RESERVE)) return;
// 是否重复
HardBroadcastEntity broadcastDetail = baseMapper.selectOne(new LambdaQueryWrapper<HardBroadcastEntity>()
.eq(HardBroadcastEntity::getBizId, orderdetail.getId())
);
if (ObjectUtil.isNotEmpty(broadcastDetail)) {
log.error("|{}|addReserveOrderTask发送mq消息失败,广播已存在|{}|", TAG, orderdetail.getId());
return;
}
// 查询设备
HardBroadcastEntity saveObj = HardBroadcastEntity.builder()
.userId(orderdetail.getUserId())
.hardId(orderdetail.getHardId())
.topic("")
.bizType(HardBroadcastEnum.OFFLINE_CANTEEN_RESERVE.getType())
.bizId(String.valueOf(orderdetail.getId()))
.title(HardBroadcastEnum.OFFLINE_CANTEEN_RESERVE.getDescription())
.content("")
.broadcastCount(0)
.broadcastMaxCount(20)
.isBroadcast(YesNoEnum.YES.getCode())
.isDone(YesNoEnum.NO.getCode())
.build();
baseMapper.insert(saveObj);
}
/**
* 完成硬件广播
*/
@Override
public void doneBroadcast(HardOrderEntity orderdetail) {
if (ObjectUtil.isEmpty(orderdetail)) return;
HardTypeEnum hardTypeEnum = HardTypeEnum.valueOfByType(orderdetail.getSysType());
if (ObjectUtil.isEmpty(orderdetail)) {
log.error("|{}|doneBroadcast发送mq消息失败,设备类型错误hardType不存在hardType|{}|", TAG, orderdetail.getSysType());
return;
}
if (ObjectUtil.notEqual(hardTypeEnum, HardTypeEnum.CANTEEN)) return;
HardOrderTypeEnum hardOrderType = HardOrderTypeEnum.valueOfByType(orderdetail.getOrderType());
if (ObjectUtil.isEmpty(hardOrderType)) {
log.error("|{}|doneBroadcast发送mq消息失败,订餐类型错误hardType不存在hardType|{}|", TAG, orderdetail.getOrderType());
return;
}
if (ObjectUtil.notEqual(hardOrderType, HardOrderTypeEnum.RESERVE)) return;
HardBroadcastEntity broadcastDetail = baseMapper.selectOne(new LambdaQueryWrapper<HardBroadcastEntity>()
.eq(HardBroadcastEntity::getBizId, orderdetail.getId())
);
if (ObjectUtil.isEmpty(broadcastDetail)) {
log.error("|{}|doneBroadcast发送mq消息失败,广播不存在|{}|", TAG, orderdetail.getId());
return;
}
HardBroadcastEntity updateObj = HardBroadcastEntity.builder()
.id(broadcastDetail.getId())
.isBroadcast(YesNoEnum.NO.getCode())
.isDone(YesNoEnum.YES.getCode())
.isDoneTime(orderdetail.getCreateTime())
.build();
baseMapper.updateById(updateObj);
}
private void disposeList(List<HardBroadcastVo> list, HardBroadcastDto dto) {
if (ObjectUtil.isEmpty(list)) return;
// 设备
@@ -0,0 +1,526 @@
package com.bsd.pjcloud.hard.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
import com.bsd.pjcloud.admin.api.utils.DataUtil;
import com.bsd.pjcloud.admin.api.vo.UserVO;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.constant.flow.HardDoorFlowBizEnum;
import com.bsd.pjcloud.hard.api.constant.flow.HardDoorFlowEnum;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowDto;
import com.bsd.pjcloud.hard.api.dto.HardDoorFlowOpenDto;
import com.bsd.pjcloud.hard.api.dto.manager.HardManagerDto;
import com.bsd.pjcloud.hard.api.entity.HardAuthEntity;
import com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorManagerEntity;
import com.bsd.pjcloud.hard.api.entity.manager.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.HardDoorFlowVo;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorManagerVo;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuJoinVo;
import com.bsd.pjcloud.hard.mapper.HardAuthMapper;
import com.bsd.pjcloud.hard.mapper.HardDoorFlowMapper;
import com.bsd.pjcloud.hard.mapper.manager.HardManagerMapper;
import com.bsd.pjcloud.hard.service.*;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdDoorApiService;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdKsService;
import com.bsd.pjcloud.thirdparty.dto.door.*;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionDto;
import com.bsd.pjcloud.thirdparty.vo.door.DoorOpenVo;
import com.bsd.pjcloud.thirdparty.vo.ks.KsRecognitionVo;
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 智能柜流程
*/
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class HardDoorFlowServiceImpl extends ServiceImpl<HardDoorFlowMapper, HardDoorFlowEntity> implements HardDoorFlowService {
private static final String TAG = "智能柜流程";
private final HardDoorManagerService hardDoorManagerService;
private final HardDoorCabinetService hardDoorCabinetService;
private final HardSpuJoinService hardSpuJoinService;
private final HardOrderService hardOrderService;
@Lazy
private final HardAuthService hardAuthService;
private final HardAuthMapper hardAuthMapper;
private final HardManagerMapper hardManagerMapper;
private final RemoterThirdDoorApiService thirdDoorApiService;
private final RemoterThirdKsService thirdKsService;
private final RemoteUserService remoteUserService;
private final RemoteWalletService remoteWalletService;
/**
* 复杂查询
*/
@Override
public Page<HardDoorFlowVo> scopePageJoin(Page page, HardDoorFlowDto dto, DataScope dataScope) {
Page<HardDoorFlowVo> pageList = baseMapper.scopePageJoin(page, dto, dataScope);
disposeList(pageList.getRecords(), dto);
return pageList;
}
@Override
public HardDoorFlowVo join(Long id) {
HardDoorFlowEntity detail = baseMapper.selectById(id);
if (ObjectUtil.isEmpty(detail)) return null;
HardDoorFlowVo result = BeanUtil.toBean(detail, HardDoorFlowVo.class);
disposeList(result);
return result;
}
/**
* 通过订单id查询流程
*/
@Override
public HardDoorFlowVo getByOrderId(Long orderId) {
HardDoorFlowEntity detail = baseMapper.selectOne(new LambdaQueryWrapper<HardDoorFlowEntity>().eq(HardDoorFlowEntity::getOrderId, orderId));
if (ObjectUtil.isEmpty(detail)) return null;
HardDoorFlowVo result = BeanUtil.toBean(detail, HardDoorFlowVo.class);
disposeList(result);
return result;
}
/**
* 根据旷世识别id查询
*/
public HardDoorFlowEntity get(String ksRecogId) {
return baseMapper.selectOne(new LambdaQueryWrapper<HardDoorFlowEntity>()
.eq(HardDoorFlowEntity::getSkuSubmitRecogId, ksRecogId)
);
}
/**
* 开门
*/
@Transactional(rollbackFor = Exception.class)
public Long openDoor(HardDoorFlowOpenDto dto, HardDoorManagerVo hardDoorVo) {
HardDoorFlowEntity saveObj = HardDoorFlowEntity.builder().flowStatus(HardDoorFlowEnum.FLOW_AUTH.getType()).userId(dto.getUserId()).bizType(dto.getFlowType().getType()).isOpen(YesNoEnum.NO.getCode()).build();
baseMapper.insert(saveObj);
HardDoorManagerEntity hardDoorStatus = hardDoorManagerService.refresh(hardDoorVo.getDeviceCode());
// 校验设备和货柜编号
hardDoorStatus = hardDoorManagerService.checkDeviceAndCabinet(dto.getHardDoorId(), dto.getCabinetNo());
HardDoorFlowEntity updateObj = HardDoorFlowEntity.builder().id(saveObj.getId()).flowStatus(saveObj.getFlowStatus()).hardId(hardDoorStatus.getHardId()).hardDoorId(dto.getHardDoorId()).cabinetNo(dto.getCabinetNo()).build();
// 请求开门
DoorOpenDto openDto = BeanUtil.toBean(dto, DoorOpenDto.class);
openDto.setDeviceCode(hardDoorVo.getDeviceCode());
openDto.setCabinetNo(dto.getCabinetNo());
openDto.setOutOpenNo(String.valueOf(saveObj.getId()));
openDto.setEventType(Integer.valueOf(dto.getOpenType().getType()));
DoorOpenVo openVo = thirdDoorApiService.open(openDto).getData();
if (ObjectUtil.isEmpty(openVo) || !openVo.isSuccess()) {
String errorMsg = "智能柜申请开门错误," + openVo.getMessage();
flowStatusControl(updateObj, openDto, openVo, errorMsg);
throw new RuntimeException(errorMsg);
}
if (ObjectUtil.isNotEmpty(dto.getAuthId())) {
updateObj.setAuthId(dto.getAuthId());
}
flowStatusControl(updateObj, openDto, openVo, null);
return updateObj.getId();
}
/**
* 检修开门
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void openDoorAccess(HardDoorFlowOpenDto dto) {
// 查询智能柜
HardDoorManagerVo doorDetail = hardDoorManagerService.checkDeviceAndCabinet(dto.getHardDoorId(), dto.getCabinetNo());
getSelf().openDoor(dto, doorDetail);
}
/**
* 检修关门
*/
@Override
public void closeAccess(HardDoorFlowOpenDto dto) {
// 查询智能柜
HardDoorManagerVo doorDetail = hardDoorManagerService.checkDeviceAndCabinet(dto.getHardDoorId(), dto.getCabinetNo());
// 请求关门
DoorOpenDto openDto = BeanUtil.toBean(dto, DoorOpenDto.class);
openDto.setDeviceCode(doorDetail.getDeviceCode());
openDto.setCabinetNo(dto.getCabinetNo());
openDto.setOutOpenNo(RandomUtil.randomString(32));
openDto.setEventType(Integer.valueOf(dto.getOpenType().getType()));
DoorOpenVo openVo = thirdDoorApiService.open(openDto).getData();
if (ObjectUtil.isEmpty(openVo) || !openVo.isSuccess()) {
throw new RuntimeException("关门失败");
}
}
/**
* 购买开门
*/
@Override
public void openDoorPay(HardDoorFlowOpenDto dto, HardDoorManagerVo hardDoorDetail) {
if (ObjectUtil.isNotEmpty(dto.getHardDoorFlowId()) || ObjectUtil.isEmpty(hardDoorDetail)) {
return;
}
// 查看用户消费钱包余额
String walletErrorMsg = remoteWalletService.innserIsUseDoor(dto.getUserId()).getData();
if (ObjectUtil.isNotEmpty(walletErrorMsg)) {
throw new RuntimeException(walletErrorMsg);
}
// 查看用户信誉
boolean userCredit = hardAuthService.judgeUserCredit(dto.getUserId());
if (!userCredit) {
throw new RuntimeException("用户信誉不足,请联系管理员");
}
// 查询货柜是否配置spu信息
List<HardSpuJoinVo> spuList = hardSpuJoinService.getSpuList(hardDoorDetail.getId(), dto.getCabinetNo());
if (ObjectUtil.isEmpty(spuList) || spuList.isEmpty()) throw new RuntimeException("货柜商品信息为空,请上架");
getSelf().openDoor(dto, hardDoorDetail);
}
/**
* 上架开门
*/
@Override
public Long openDoorRepertory(HardDoorFlowOpenDto dto) {
// 查询智能柜
HardDoorManagerVo doorDetail = hardDoorManagerService.checkDeviceAndCabinet(dto.getHardDoorId(), dto.getCabinetNo());
return getSelf().openDoor(dto, doorDetail);
}
/**
* 处理开门回调
*/
@Override
public void disposeLocakCallback(DoorOpenCallbackDto dto) {
if (ObjectUtil.isEmpty(dto) || ObjectUtil.isEmpty(dto.getType()) || ObjectUtil.equals(dto.getResultCode(), "FAIL")) {
log.info("|{}|disposeLocakCallback 意外的错误,参数错误dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
// 查询流程
HardDoorFlowEntity flowDetail = baseMapper.selectById(dto.getOutOpenNo());
if (ObjectUtil.isEmpty(flowDetail) || ObjectUtil.isNotEmpty(flowDetail.getOpenCallbackTime())) {
log.info("|{}|disposeLocakCallback 意外的错误,流程不存在或者重复dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
boolean isOpenDoor = ObjectUtil.equals(dto.getType(), "OPEN");
HardDoorFlowEntity updateObj = HardDoorFlowEntity.builder().id(flowDetail.getId()).flowStatus(flowDetail.getFlowStatus()).isOpen(isOpenDoor ? YesNoEnum.YES.getCode() : YesNoEnum.NO.getCode()).build();
// 如果是购买的话
if (ObjectUtil.equals(flowDetail.getBizType(), HardDoorFlowBizEnum.PAY_OPEN.getType())) {
// 创建订单
Long orderId = hardOrderService.createHardDoorOrder(flowDetail.getUserId(), flowDetail.getHardId());
updateObj.setOrderId(orderId);
}
getSelf().flowStatusControl(updateObj, null, dto, null);
}
/**
* 处理柜子状态回调
*/
@Override
public void disposeStatusCallback(DoorStatusCallbackDto dto) {
if (ObjectUtil.isEmpty(dto)) {
log.error("|{}|disposeStatusCallback 意外的错误,参数错误dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
HardDoorManagerVo hardDoorDetail = hardDoorManagerService.getByDeviceCode(dto.getDeviceCode());
if (ObjectUtil.isEmpty(hardDoorDetail)) {
log.error("|{}|disposeStatusCallback 意外的错误,设备不存在dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
try {
hardDoorCabinetService.saveOrUpdate(hardDoorDetail.getId(), dto.getCabinetList());
} catch (Exception e) {
log.error("|{}|disposeStatusCallback 更新柜子状态失败dto|{}|", TAG, JSONUtil.toJsonStr(dto), e);
}
}
/**
* 处理视频回调
*/
@Override
public void disposeVideoCallback(DoorVideoCallbackDto dto) {
if (ObjectUtil.isEmpty(dto) || ObjectUtil.isEmpty(dto.getVideoList()) || ObjectUtil.equals(dto.getResultCode(), "FAIL")) {
log.info("|{}|disposeVideoCallback 意外的错误,参数错误或者状态错误dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
// 查询流程
HardDoorFlowEntity flowDetail = baseMapper.selectById(dto.getOutOpenNo());
if (ObjectUtil.isEmpty(flowDetail) || ObjectUtil.isNotEmpty(flowDetail.getSkuSubmitTime())) {
log.info("|{}|disposeVideoCallback 意外的错误,流程不存在或重复dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
// 提交视频
List<String> videoList = dto.getVideoList().stream().map(DoorVideoCallbackDto.Video::getVideoUrl).toList();
// 提交柜子商品信息
List<HardSpuJoinVo> spuList = hardSpuJoinService.getSpuList(flowDetail.getHardDoorId(), flowDetail.getCabinetNo());
Map<String, Object> ksMap = new HashMap<>();
List<Map<String, Object>> ksSpuMap = new ArrayList<>();
for (HardSpuJoinVo v : spuList) {
if (ObjectUtil.isEmpty(v.getSpuDetail())) continue;
Map<String, Object> map = new HashMap<>();
map.put("sku_id", v.getSpuDetail().getKsSkuId());
map.put("floor_num", v.getHardDoorNumber());
ksSpuMap.add(map);
}
ksMap.put("origin_time", System.currentTimeMillis());
ksMap.put("sku_scope", ksSpuMap);
// 更新流程
getSelf().flowStatusControl(flowDetail, null, dto, null);
// 提交识别
KsRecognitionDto ksRecognitionDto = new KsRecognitionDto();
ksRecognitionDto.setRecog_id(String.valueOf(flowDetail.getId()));
ksRecognitionDto.setExtra_params(ksMap);
ksRecognitionDto.setResource_type("1");
ksRecognitionDto.setContainer_id(String.valueOf(flowDetail.getHardDoorId()));
ksRecognitionDto.setResource_urls(videoList);
// third服务生成
ksRecognitionDto.setNotify_url("");
ksRecognitionDto.setSub_mch_id(String.valueOf(flowDetail.getOrderId()));
KsRecognitionVo ksRecognitionVo = thirdKsService.recognition(ksRecognitionDto).getData();
if (ObjectUtil.isEmpty(ksRecognitionVo) || !ksRecognitionVo.isSuccess()) {
String errorMsg = String.format("|%s|disposeVideoCallback 提交识别错误dto|%s|vo|%s|", TAG, JSONUtil.toJsonStr(ksRecognitionDto), JSONUtil.toJsonStr(ksRecognitionVo));
log.error(errorMsg);
getSelf().flowStatusControl(flowDetail, ksRecognitionDto, ksRecognitionVo, errorMsg);
return;
}
// 更新流程
flowDetail.setSkuSubmitRecogId(ksRecognitionVo.getKs_recog_id());
getSelf().flowStatusControl(flowDetail, ksRecognitionDto, ksRecognitionVo, null);
}
/**
* 处理旷世识别回调
*/
@Override
public void disposeRecognitionCallback(KsRecognitionCallbackDto dto) {
if (ObjectUtil.isEmpty(dto)) {
log.error("|{}|disposeRecognitionCallback 参数错误dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
// 更新流程
HardDoorFlowEntity flowDetail = get(dto.getKs_recog_id());
if (ObjectUtil.isEmpty(flowDetail) || ObjectUtil.isNotEmpty(flowDetail.getSkuCallbackTime())) {
log.error("|{}|disposeRecognitionCallback 意外的错误,流程不存在或重复dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
// 查询授权流程
HardAuthEntity authDetail = hardAuthMapper.selectById(flowDetail.getAuthId());
if (ObjectUtil.isEmpty(authDetail)) {
log.error("|{}|disposeRecognitionCallback 意外的错误,授权流程不存在dto|{}|", TAG, JSONUtil.toJsonStr(dto));
return;
}
String ksFlowCode = dto.getState().getCode();
String ksRecognitionCode = dto.getResult().getStatus().getCode();
if (ObjectUtil.notEqual(ksFlowCode, "2") || ObjectUtil.notEqual(ksRecognitionCode, "2")) {
if (ObjectUtil.equals(ksFlowCode, "2") && ObjectUtil.notEqual(ksRecognitionCode, "2")) {
// 未拿商品取消订单
hardOrderService.cancelHardDoorOrder(flowDetail.getOrderId());
getSelf().flowStatusControl(flowDetail, null, dto, "");
return;
}
String ksErrorMsg = String.format("商品识别响应错误:ksFlowCode:%s;ksRecognitionCode:%s;", ksFlowCode, ksRecognitionCode);
log.error(ksErrorMsg);
getSelf().flowStatusControl(flowDetail, null, dto, ksErrorMsg);
return;
}
KsRecognitionCallbackDto.Result result = dto.getResult();
List<KsRecognitionCallbackDto.ResultSku> resultSkuList = result.getResult();
if (ObjectUtil.isEmpty(resultSkuList)) {
String ksErrorMsg = "商品识别响应错误,识别的商品列表为空";
log.error(ksErrorMsg);
getSelf().flowStatusControl(flowDetail, null, dto, ksErrorMsg);
return;
}
getSelf().flowStatusControl(flowDetail, null, dto, null);
// 查询订单
HardOrderEntity orderDetail = hardOrderService.getById(flowDetail.getOrderId());
if (ObjectUtil.isEmpty(orderDetail)) {
String ksErrorMsg = String.format("订单结算错误,订单不存在orderId%s", flowDetail.getOrderId());
log.error(ksErrorMsg);
getSelf().flowStatusControl(flowDetail, null, dto, ksErrorMsg);
return;
}
try {
getSelf().flowStatusControl(flowDetail, null, null, null);
Long orderId = hardOrderService.payHardDoorOrder(orderDetail, resultSkuList);
if (ObjectUtil.isNotEmpty(orderId)) {
flowDetail.setFlowStatus(HardDoorFlowEnum.FLOW_CALLBACK_RECOGNITION.getType());
getSelf().flowStatusControl(flowDetail, null, null, null);
}
// 完成授权流程
HardAuthEntity updateAuthObj = HardAuthEntity.builder().id(authDetail.getId()).isDone(YesNoEnum.YES.getCode()).isDoneTime(LocalDateTime.now()).build();
hardAuthMapper.updateById(updateAuthObj);
} catch (Exception e) {
e.printStackTrace();
String ksErrorMsg = String.format("订单结算错误,订单支付失败error%s;", e.getMessage());
log.error(ksErrorMsg);
getSelf().flowStatusControl(flowDetail, null, dto, ksErrorMsg);
}
}
/**
* 流程状态控制(发起流程需要手动)
*/
@Transactional(rollbackFor = Exception.class)
public void flowStatusControl(HardDoorFlowEntity flow, Object dto, Object vo, String error) {
if (!ObjectUtil.isAllNotEmpty(flow.getId(), flow.getFlowStatus())) {
log.error("|{}|flowStatusControl 意外的错误,流程id或者flowstatus为空", TAG);
return;
}
HardDoorFlowEnum flowStatus = HardDoorFlowEnum.valueOfByType(flow.getFlowStatus());
HardDoorFlowEnum nextType = HardDoorFlowEnum.getNextType(flowStatus);
if (ObjectUtil.isEmpty(nextType)) {
log.error("|{}|flowStatusControl 意外的错误,流程状态控制错误该流程已结束", TAG);
return;
}
HardDoorFlowEntity updateObj = new HardDoorFlowEntity();
updateObj.setId(flow.getId());
updateObj.setError(error);
updateObj.setFlowStatus(nextType.getType());
switch (nextType) {
// 智能柜申请开门
case FLOW_APPLY_OPEN -> {
updateObj.setRequestOpenDto(JSONUtil.toJsonStr(dto));
updateObj.setRequestOpenVo(JSONUtil.toJsonStr(vo));
updateObj.setRequestOpenTime(LocalDateTime.now());
if (ObjectUtil.isNotEmpty(flow.getAuthId())) {
updateObj.setAuthId(flow.getAuthId());
}
if (ObjectUtil.isNotEmpty(flow.getHardId())) {
updateObj.setHardId(flow.getHardId());
}
if (ObjectUtil.isNotEmpty(flow.getHardDoorId())) {
updateObj.setHardDoorId(flow.getHardDoorId());
}
if (ObjectUtil.isNotEmpty(flow.getCabinetNo())) {
updateObj.setCabinetNo(flow.getCabinetNo());
}
if (ObjectUtil.isNotEmpty(error)) {
updateObj.setErrorDesc("智能柜申请开门错误");
}
break;
}
// 智能柜开门响应
case FLOW_CALLBACK_OPEN -> {
updateObj.setOpenCallbackVo(JSONUtil.toJsonStr(vo));
updateObj.setOpenCallbackTime(LocalDateTime.now());
if (ObjectUtil.isNotEmpty(flow.getIsOpen())) {
updateObj.setIsOpen(flow.getIsOpen());
}
if (ObjectUtil.isNotEmpty(flow.getOrderId())) {
updateObj.setOrderId(flow.getOrderId());
}
if (ObjectUtil.isNotEmpty(error)) {
updateObj.setErrorDesc("智能柜开门响应错误");
}
break;
}
// 智能柜视频回调
case FLOW_CALLBACK_VIDEO -> {
updateObj.setVideoCallbackVo(JSONUtil.toJsonStr(vo));
updateObj.setVideoCallbackTime(LocalDateTime.now());
if (ObjectUtil.isNotEmpty(error)) {
updateObj.setErrorDesc("智能柜视频回调错误");
}
break;
}
// 商品提交识别提交
case FLOW_SUBMIT_RECOGNITION -> {
updateObj.setSkuSubmitDto(JSONUtil.toJsonStr(dto));
updateObj.setSkuSubmitVo(JSONUtil.toJsonStr(vo));
updateObj.setSkuSubmitTime(LocalDateTime.now());
if (ObjectUtil.isNotEmpty(flow.getSkuSubmitRecogId())) {
updateObj.setSkuSubmitRecogId(flow.getSkuSubmitRecogId());
}
if (ObjectUtil.isNotEmpty(error)) {
updateObj.setErrorDesc("商品提交识别提交错误");
}
break;
}
// 商品识别响应
case FLOW_CALLBACK_RECOGNITION -> {
updateObj.setSkuCallbackVo(JSONUtil.toJsonStr(vo));
updateObj.setSkuCallbackTime(LocalDateTime.now());
if (ObjectUtil.isNotEmpty(error)) {
updateObj.setErrorDesc("商品识别响应错误");
}
break;
}
case FLOW_PAY_ORDER -> {
updateObj.setPayTime(LocalDateTime.now());
if (ObjectUtil.isNotEmpty(error)) {
updateObj.setErrorDesc("商品识别响应错误");
}
break;
}
}
baseMapper.updateById(updateObj);
}
private void disposeList(List<HardDoorFlowVo> list, HardDoorFlowDto dto) {
if (ObjectUtil.isEmpty(list)) return;
// 设备
List<Long> hardIds = list.stream().map(HardDoorFlowVo::getHardId).filter(ObjectUtil::isNotEmpty).distinct().toList();
if (ObjectUtil.isNotEmpty(hardIds)) {
HardManagerDto hardManagerDto = new HardManagerDto();
hardManagerDto.setIds(hardIds);
List<HardManagerEntity> hardList = hardManagerMapper.list(hardManagerDto);
if (ObjectUtil.isNotEmpty(hardList)) {
HardUtil.convertHardList(list, CollectionUtils.convertMap(hardList, HardManagerEntity::getId));
}
}
// 用户相关
List<Long> userIds = list.stream().map(HardDoorFlowVo::getUserId).distinct().toList();
if (ObjectUtil.isNotEmpty(userIds)) {
R<List<UserVO>> userList = remoteUserService.getUserDeptByIds(new ArrayList<>(userIds));
if (ObjectUtil.isNotEmpty(userList.getData())) {
DataUtil.convertUserDeptList(list, CollectionUtils.convertMap(userList.getData(), UserVO::getUserId));
}
}
}
private void disposeList(HardDoorFlowVo detail) {
// 用户
List<UserVO> usrList = remoteUserService.getUserDeptByIds(List.of(detail.getUserId())).getData();
if (ObjectUtil.isNotEmpty(usrList)) {
DataUtil.convertUserDept(detail, usrList.get(0));
}
// 设备
HardManagerEntity hardManager = hardManagerMapper.selectById(detail.getHardDoorId());
if (ObjectUtil.isNotEmpty(hardManager)) {
HardUtil.convertHard(detail, hardManager);
}
}
private HardDoorFlowServiceImpl getSelf() {
return SpringUtil.getBean(getClass());
}
}
@@ -0,0 +1,112 @@
package com.bsd.pjcloud.hard.service.impl.manager;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.feign.RemoteFileService;
import com.bsd.pjcloud.common.core.util.QRCodeImageGenerator;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorCabinetEntity;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorCabinetCodeVo;
import com.bsd.pjcloud.hard.mapper.manager.HardDoorCabinetMapper;
import com.bsd.pjcloud.hard.service.HardDoorCabinetService;
import com.bsd.pjcloud.thirdparty.vo.door.DoorStatusVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 智能柜货柜
*/
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class HardDoorCabinetServiceImpl extends ServiceImpl<HardDoorCabinetMapper, HardDoorCabinetEntity> implements HardDoorCabinetService {
private final RemoteFileService remoteFileService;
@Override
public void saveOrUpdate(Long hardDoorId, List<DoorStatusVo.Cabinet> list) {
List<HardDoorCabinetEntity> cabinetList = baseMapper.selectList(new LambdaQueryWrapper<HardDoorCabinetEntity>()
.eq(HardDoorCabinetEntity::getHardDoorId, hardDoorId)
);
if (ObjectUtil.isEmpty(cabinetList)) {
List<HardDoorCabinetEntity> addList = new ArrayList<>();
for (DoorStatusVo.Cabinet cabinet : list) {
HardDoorCabinetEntity entity = new HardDoorCabinetEntity();
entity.setHardDoorId(hardDoorId);
entity.setCabinetNo(cabinet.getCabinetNo());
entity.setIsLockOnline(cabinet.getIsLockOnline());
entity.setLockStatus(cabinet.getLockStatus());
entity.setDoorStatus(cabinet.getDoorStatus());
entity.setSaleStatus(cabinet.getSaleStatus());
addList.add(entity);
}
baseMapper.insert(addList);
return;
}
for (DoorStatusVo.Cabinet cabinet : list) {
cabinetList.stream().filter(i -> ObjectUtil.equals(i.getCabinetNo(), cabinet.getCabinetNo()))
.findFirst()
.ifPresent(i -> {
i.setIsLockOnline(cabinet.getIsLockOnline());
i.setLockStatus(cabinet.getLockStatus());
i.setDoorStatus(cabinet.getDoorStatus());
i.setSaleStatus(cabinet.getSaleStatus());
baseMapper.updateById(i);
});
}
}
@Override
public List<HardDoorCabinetEntity> getListByHardDoorId(Long hardDoorId) {
return baseMapper.selectList(new LambdaQueryWrapper<HardDoorCabinetEntity>()
.eq(HardDoorCabinetEntity::getHardDoorId, hardDoorId)
);
}
/**
* 刷新智能柜货柜二维码
*/
@Override
public String refreshQrCode(Long hardDoorId, Integer cabinetNo) {
// 查找货柜
HardDoorCabinetEntity cabinetDetail = baseMapper.selectOne(new LambdaQueryWrapper<HardDoorCabinetEntity>()
.eq(HardDoorCabinetEntity::getHardDoorId, hardDoorId)
.eq(HardDoorCabinetEntity::getCabinetNo, cabinetNo)
);
if (ObjectUtil.isEmpty(cabinetDetail)) throw new RuntimeException("货柜不存在");
HardDoorCabinetCodeVo cabinetCodeVo = new HardDoorCabinetCodeVo();
cabinetCodeVo.setHardDoorId(String.valueOf(hardDoorId));
cabinetCodeVo.setCabinetNo(String.valueOf(cabinetNo));
// 生成二维码
String coeContent = Base64.encode(JSONUtil.toJsonStr(cabinetCodeVo));
try {
byte[] bytes = QRCodeImageGenerator.generateQrCodeImage(coeContent, 300);
MultipartFile multipartFile = new MockMultipartFile("file", hardDoorId + "-" + System.currentTimeMillis() + ".png", "image/png", new ByteArrayInputStream(bytes));
R upload = remoteFileService.innerUpload(multipartFile, null, null, null);
Map data = (Map) upload.getData();
String url = (String) data.get("url");
// 更新
HardDoorCabinetEntity updateObj = new HardDoorCabinetEntity();
updateObj.setId(cabinetDetail.getId());
updateObj.setQrCode(url);
baseMapper.updateById(updateObj);
return url;
} catch (Exception e) {
log.error("refreshQrCode刷新智能柜货柜二维码,hardDoorId:{},cabinetNo:{}", hardDoorId, cabinetNo, e);
throw new RuntimeException("刷新二维码失败");
}
}
}
@@ -1,28 +1,38 @@
package com.bsd.pjcloud.hard.service.impl.manager;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.dto.manager.HardDoorManagerDto;
import com.bsd.pjcloud.hard.api.dto.manager.HardManagerDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardChangeVolume;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorCabinetEntity;
import com.bsd.pjcloud.hard.api.entity.manager.HardDoorManagerEntity;
import com.bsd.pjcloud.hard.api.entity.manager.HardManagerEntity;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorManagerVo;
import com.bsd.pjcloud.hard.mapper.manager.HardDoorManagerMapper;
import com.bsd.pjcloud.hard.mapper.manager.HardManagerMapper;
import com.bsd.pjcloud.hard.service.HardDoorCabinetService;
import com.bsd.pjcloud.hard.service.HardDoorManagerService;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdDoorApiService;
import com.bsd.pjcloud.thirdparty.dto.door.DoorBindDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorRegisterDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorVideoDto;
import com.bsd.pjcloud.thirdparty.dto.door.DoorVolumeDto;
import com.bsd.pjcloud.thirdparty.dto.door.*;
import com.bsd.pjcloud.thirdparty.vo.door.DoorBindVo;
import com.bsd.pjcloud.thirdparty.vo.door.DoorRegisterVo;
import com.bsd.pjcloud.thirdparty.vo.door.DoorStatusVo;
import com.bsd.pjcloud.thirdparty.vo.door.DoorVolumeVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.List;
/**
* 智能柜设置
*/
@@ -32,51 +42,75 @@ import org.springframework.validation.annotation.Validated;
@Service
public class HardDoorManagerServiceImpl extends ServiceImpl<HardDoorManagerMapper, HardDoorManagerEntity> implements HardDoorManagerService {
private final HardDoorCabinetService hardDoorCabinetService;
private final HardManagerMapper hardManagerMapper;
private final RemoterThirdDoorApiService thirdDoorApiService;
@Override
public Page<HardDoorManagerVo> scopePageJoin(Page page, HardDoorManagerDto dto, DataScope dataScope) {
return baseMapper.scopePageJoin(page, dto, dataScope);
Page<HardDoorManagerVo> pageList = baseMapper.scopePageJoin(page, dto, dataScope);
disposeList(pageList.getRecords(), dto);
return pageList;
}
/**
* 根据硬件id查询详情
*/
@Override
public HardDoorManagerVo getByHardId(Long hardId) {
return baseMapper.pageJoin(hardId);
public HardDoorManagerVo getByHardDoorId(Long hardId) {
HardDoorManagerVo hardDoor = baseMapper.pageJoin(hardId);
if (ObjectUtil.isNotEmpty(hardDoor)) {
List<HardDoorCabinetEntity> cabinetList = hardDoorCabinetService.getListByHardDoorId(hardDoor.getId());
if (ObjectUtil.isNotEmpty(cabinetList)) {
hardDoor.setCabinetList(cabinetList);
}
}
return hardDoor;
}
@Override
public HardDoorManagerVo getByDeviceCode(String deviceCode) {
HardDoorManagerEntity hardDoor = baseMapper.selectOne(new LambdaQueryWrapper<HardDoorManagerEntity>()
.eq(HardDoorManagerEntity::getDeviceCode, deviceCode)
);
if (ObjectUtil.isEmpty(hardDoor)) return null;
HardDoorManagerVo hardDoorVo = BeanUtil.toBean(hardDoor, HardDoorManagerVo.class);
if (ObjectUtil.isNotEmpty(hardDoorVo)) {
List<HardDoorCabinetEntity> cabinetList = hardDoorCabinetService.getListByHardDoorId(hardDoor.getId());
if (ObjectUtil.isNotEmpty(cabinetList)) {
hardDoorVo.setCabinetList(cabinetList);
}
}
return hardDoorVo;
}
/**
* 绑定设备
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void bind(HardDoorManagerEntity dto) {
// 查询设备
HardDoorManagerVo hardDoorDetail = getByHardId(dto.getHardId());
HardDoorManagerVo hardDoorDetail = getByHardDoorId(dto.getHardId());
if (ObjectUtil.isEmpty(hardDoorDetail)) {
HardDoorManagerEntity saveOrUpdate = new HardDoorManagerEntity();
saveOrUpdate.setHardId(dto.getHardId());
saveOrUpdate.setImei(dto.getImei());
saveOrUpdate.setDeviceCode(dto.getDeviceCode());
saveOrUpdate.setDoorCount(dto.getDoorCount());
baseMapper.insert(saveOrUpdate);
dto.setId(saveOrUpdate.getId());
} else {
HardDoorManagerEntity saveOrUpdate = new HardDoorManagerEntity();
saveOrUpdate.setId(hardDoorDetail.getId());
saveOrUpdate.setHardId(dto.getHardId());
saveOrUpdate.setImei(dto.getImei());
saveOrUpdate.setDeviceCode(dto.getDeviceCode());
saveOrUpdate.setDoorCount(dto.getDoorCount());
baseMapper.updateById(saveOrUpdate);
}
// 设备绑定
DoorBindDto bindDto = new DoorBindDto();
bindDto.setImei(dto.getImei());
bindDto.setDeviceCode(dto.getDeviceCode());
bindDto.setOutDeviceCode(String.valueOf(dto.getHardId()));
DoorBindVo bindVo = thirdDoorApiService.bind(bindDto).getData();
if (!bindVo.isSuccess()) {
throw new RuntimeException(bindVo.getMessage());
}
// 设备注册
DoorRegisterDto registerDto = new DoorRegisterDto();
registerDto.setImei(dto.getImei());
@@ -85,6 +119,59 @@ public class HardDoorManagerServiceImpl extends ServiceImpl<HardDoorManagerMappe
if (!registerVo.isSuccess()) {
throw new RuntimeException(registerVo.getMessage());
}
// 设备绑定
DoorBindDto bindDto = new DoorBindDto();
bindDto.setImei(dto.getImei());
bindDto.setDeviceCode(registerVo.getDeviceCode());
bindDto.setOutDeviceCode(String.valueOf(dto.getHardId()));
DoorBindVo bindVo = thirdDoorApiService.bind(bindDto).getData();
if (!bindVo.isSuccess()) {
throw new RuntimeException(bindVo.getMessage());
}
// 查询设备详情
HardDoorManagerEntity hardDoorManagerDetail = baseMapper.selectById(dto.getId());
// 注册的设备信息
HardDoorManagerEntity updateObj = new HardDoorManagerEntity();
updateObj.setId(hardDoorManagerDetail.getId());
updateObj.setDeviceCode(registerVo.getDeviceCode());
updateObj.setCabinetNum(registerVo.getCabinetNum());
updateObj.setCabinetCameraNum(registerVo.getCabinetCameraNum());
updateObj.setCabinetWeightUnitNum(registerVo.getCabinetWeightUnitNum());
baseMapper.updateById(updateObj);
refresh(updateObj.getDeviceCode());
}
@Override
@Transactional(rollbackFor = Exception.class)
public HardDoorManagerEntity refresh(String deviceCode) {
// 查询设备
HardDoorManagerEntity hardDoorDetail = baseMapper.selectOne(new LambdaQueryWrapper<HardDoorManagerEntity>()
.eq(HardDoorManagerEntity::getDeviceCode, deviceCode)
.orderByDesc(HardDoorManagerEntity::getCreateTime)
.last("limit 1")
);
if (ObjectUtil.isEmpty(hardDoorDetail)) throw new RuntimeException("刷新失败,设备不存在");
DoorStatusDto statusDto = new DoorStatusDto();
statusDto.setDeviceCode(deviceCode);
DoorStatusVo statusVo = thirdDoorApiService.status(statusDto).getData();
if (!statusVo.isSuccess()) {
throw new RuntimeException(statusVo.getMessage());
}
HardDoorManagerEntity updateObj = new HardDoorManagerEntity();
updateObj.setId(hardDoorDetail.getId());
updateObj.setPowerStatus(statusVo.getPowerStatus());
updateObj.setNetStatus(statusVo.getNetStatus());
updateObj.setNetStatus(statusVo.getSaleStatus());
updateObj.setSaleStatus(statusVo.getSaleStatus());
updateObj.setSimSn(statusVo.getSimSn());
updateObj.setSignalIntensity(statusVo.getSignalIntensity());
updateObj.setSignalRatio(statusVo.getSignalRatio());
updateObj.setSignalTime(statusVo.getSignalTime());
if (ObjectUtil.isNotEmpty(statusVo.getCabinetStatusList())) {
hardDoorCabinetService.saveOrUpdate(hardDoorDetail.getId(), statusVo.getCabinetStatusList());
}
baseMapper.updateById(updateObj);
return updateObj;
}
/**
@@ -93,7 +180,7 @@ public class HardDoorManagerServiceImpl extends ServiceImpl<HardDoorManagerMappe
@Override
public void changeVolume(HardChangeVolume dto) {
// 查询设备
HardDoorManagerVo hardDoorDetail = getByHardId(dto.getHardId());
HardDoorManagerVo hardDoorDetail = getByHardDoorId(dto.getHardId());
if (ObjectUtil.isEmpty(hardDoorDetail)) {
throw new RuntimeException("设备不存在");
}
@@ -105,5 +192,42 @@ public class HardDoorManagerServiceImpl extends ServiceImpl<HardDoorManagerMappe
if (!volumeVo.isSuccess()) {
throw new RuntimeException(volumeVo.getMessage());
}
// 修改音量
HardDoorManagerEntity updateObj = new HardDoorManagerEntity();
updateObj.setId(hardDoorDetail.getId());
updateObj.setSystemVolume(dto.getSystemVolume());
updateObj.setMediaVolume(dto.getMediaVolume());
baseMapper.updateById(updateObj);
}
/**
* 校验设备和货柜编号
*/
public HardDoorManagerVo checkDeviceAndCabinet(Long hardDoorId, Integer cabinetNo) {
// 查询智能柜
HardDoorManagerEntity doorDetail = getById(hardDoorId);
if (ObjectUtil.isEmpty(doorDetail)) throw new RuntimeException("智能柜不存在");
List<HardDoorCabinetEntity> cabinetList = hardDoorCabinetService.getListByHardDoorId(hardDoorId);
if (ObjectUtil.isEmpty(cabinetList)) throw new RuntimeException("货柜不存在");
if (ObjectUtil.isEmpty(cabinetList.stream().filter(i -> ObjectUtil.equals(i.getCabinetNo(), cabinetNo)).findFirst().orElse(null))) {
throw new RuntimeException("货柜不存在");
}
HardDoorManagerVo doorVo = BeanUtil.toBean(doorDetail, HardDoorManagerVo.class);
doorVo.setCabinetList(cabinetList);
return doorVo;
}
private void disposeList(List<HardDoorManagerVo> list, HardDoorManagerDto dto) {
if (ObjectUtil.isEmpty(list)) return;
// 设备
List<Long> hardIds = list.stream().map(HardDoorManagerVo::getHardId).filter(ObjectUtil::isNotEmpty).distinct().toList();
if (ObjectUtil.isNotEmpty(hardIds)) {
HardManagerDto hardManagerDto = new HardManagerDto();
hardManagerDto.setIds(hardIds);
List<HardManagerEntity> hardList = hardManagerMapper.list(hardManagerDto);
if (ObjectUtil.isNotEmpty(hardList)) {
HardUtil.convertHardList(list, CollectionUtils.convertMap(hardList, HardManagerEntity::getId));
}
}
}
}
@@ -20,11 +20,13 @@ import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardParentCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.mapper.order.HardCarMapper;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.mapper.order.HardParentCarMapper;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardSpuService;
import com.bsd.pjcloud.supermarket.api.feign.RemoteSupermarketUnitSkuService;
import com.bsd.pjcloud.supermarket.vo.erp.SmErpUnitWithSpuVo;
import lombok.RequiredArgsConstructor;
@@ -53,6 +55,7 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
private final HardOrderMapper hardCarMapper;
private final HardParentCarMapper hardParentCarMapper;
private final HardSpuService hardSpuService;
private final RemoteOnlineCanteenSpuService onlineCanteenSpuService;
private final RemoteCanteenSpuService canteenSpuService;
@@ -180,6 +183,27 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
}
yield supermarketTotalPrice.get();
}
case DOOR -> {
AtomicInteger doorTotalPrice = new AtomicInteger();
// 查询智能柜
List<HardSpuEntity> supList = hardSpuService.getByIds(productIds);
for (HardCreateCarDto v : list) {
supList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
Integer price = spu.getPrice();
if (ObjectUtil.isNotEmpty(v.getProductCount()) && !ObjectUtil.equals(v.getProductCount(), 0)) {
// 按数量
int itemTotalPrice = v.getProductCount() * price;
doorTotalPrice.addAndGet(itemTotalPrice);
} else if (ObjectUtil.isNotEmpty(v.getProductWeight()) && v.getProductWeight().compareTo(BigDecimal.valueOf(0)) != 0) {
// 按重量
// 向上取整
int itemTotalPrice = v.getProductWeight().multiply(BigDecimal.valueOf(price)).setScale(0, RoundingMode.CEILING).intValue();
doorTotalPrice.addAndGet(itemTotalPrice);
}
});
}
yield doorTotalPrice.get();
}
default -> null;
};
}
@@ -272,6 +296,37 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
baseMapper.insert(carObjectList);
return;
}
// 智能柜
if (ObjectUtil.equals(sysType, HardTypeEnum.DOOR)) {
List<HardCarEntity> carObjectList = new ArrayList<>();
List<HardSpuEntity> supList = hardSpuService.getByIds(productIds);
for (HardCreateCarDto v : productList) {
HardCarEntity item = HardCarEntity.builder().parentCarId(parentCarId).build();
supList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
Integer price = spu.getPrice();
int totalPrice = 0;
// 按重量
if (ObjectUtil.isNotEmpty(v.getProductCount()) && !ObjectUtil.equals(v.getProductCount(), 0)) {
// 按数量
totalPrice = v.getProductCount() * price;
} else if (ObjectUtil.isNotEmpty(v.getProductWeight()) && v.getProductWeight().compareTo(BigDecimal.valueOf(0)) != 0) {
// 按重量
totalPrice = v.getProductWeight().multiply(BigDecimal.valueOf(price)).setScale(0, RoundingMode.CEILING).intValue();
}
item.setProductId(spu.getId());
item.setProductName(spu.getName());
item.setProductPrice(price);
item.setProductPic(spu.getCover());
item.setTotalPrice((long) totalPrice);
// item.setProductNature(v.getProductNature().getType());
item.setProductCount(v.getProductCount());
item.setProductWeight(v.getProductWeight());
carObjectList.add(item);
});
}
baseMapper.insert(carObjectList);
return;
}
}
@Override
@@ -308,6 +363,15 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
});
}
}
// 智能柜
if (ObjectUtil.equals(sysType, HardTypeEnum.DOOR)) {
List<HardSpuEntity> supList = hardSpuService.getByIds(productIds);
for (HardCreateCarDto v : list) {
supList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getProductId())).findFirst().ifPresent(spu -> {
str.append(spu.getName()).append("x").append(v.getProductCount()).append(";");
});
}
}
return str.toString();
}
@@ -2,6 +2,7 @@ package com.bsd.pjcloud.hard.service.impl.order;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -19,6 +20,7 @@ import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.hard.api.constant.HardProductNatureEnum;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
@@ -29,21 +31,22 @@ import com.bsd.pjcloud.hard.api.dto.hard.HardCreateOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.app.HardAppCreateOrderDto;
import com.bsd.pjcloud.hard.api.dto.spu.DeductionSpuStockDto;
import com.bsd.pjcloud.hard.api.entity.manager.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardParentCarEntity;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.manager.HardManagerVo;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.mapper.manager.HardManagerMapper;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardInvoiceService;
import com.bsd.pjcloud.hard.service.HardManagerService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.hard.service.*;
import com.bsd.pjcloud.supermarket.api.feign.RemoteSupermarketSpuService;
import com.bsd.pjcloud.supermarket.dto.SupermarketSpuUpdateStockReqDTO;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletCodeBizEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
@@ -90,6 +93,8 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
private final HardParentCarServiceImpl hardParentCarServiceImpl;
@Lazy
private final HardInvoiceService hardInvoiceService;
private final HardBroadcastService hardBroadcastService;
private final HardSpuService hardSpuService;
private final RemoteMchService remoteMchService;
private final RemoteCodeUseService remoteCodeUseService;
@@ -297,7 +302,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
HardParentCarEntity parentCar = hardCarService.getParentCarById(dto.getCarParentId());
if (ObjectUtil.isEmpty(parentCar)) throw new RuntimeException("购物车不存在");
// 查询商户
MchManageVo hardManager = remoteMchService.getById(dto.getMerchantId()).getData();
MchManageVo hardManager = remoteMchService.getById(parentCar.getMerchantId()).getData();
if (ObjectUtil.isEmpty(hardManager)) throw new RuntimeException("商户不存在");
// 查询父购物车
List<HardCarEntity> carList = hardCarService.getByParentCarId(dto.getCarParentId());
@@ -345,6 +350,8 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
if (isPay) getSelf().fastReduceBalance(orderObj);
// 是否需要创建二维码
getSelf().generateCode(orderObj);
// 发送mq消息
getSelf().createOrderAfterSendMqMsg(orderObj.getId());
// 扣减库存
getSelf().fastenerInventory(orderObj, YesNoEnum.YES);
return orderObj.getId();
@@ -398,6 +405,123 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
return orderObj.getId();
}
/**
* 创建智能柜订单
*/
@Override
public Long createHardDoorOrder(Long userId, Long hardId) {
// 查询用户
UserInfo userDetail = userService.getByUserId(userId).getData();
if (ObjectUtil.isEmpty(userDetail)) throw new RuntimeException("创建智能柜订单失败,用户不存在");
// 查询设备
HardManagerVo hard = hardManagerService.getByHardId(hardId);
if (ObjectUtil.isEmpty(hard)) throw new RuntimeException("创建智能柜订单失败,设备不存在");
// 查询商户
MchManageVo mch = remoteMchService.getById(hard.getMerchantId()).getData();
if (ObjectUtil.isEmpty(hard)) throw new RuntimeException("创建智能柜订单失败,商户不存在");
// 默认超市钱包
WalletManageEntity wallet = remoteWalletService.getWallet(userId, WalletTypeEnum.PAY).getData();
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("创建智能柜订单失败,用户消费钱包不存在");
HardOrderEntity orderObj = HardOrderEntity.builder()
.walletId(wallet.getId())
.hardId(hardId)
.merchantType(mch.getTypes())
.merchantId(mch.getId())
.merchantDeptId(mch.getDeptId())
.userId(userDetail.getSysUser().getUserId())
.userDeptId(userDetail.getSysUser().getDeptId())
.sysType(HardTypeEnum.DOOR.getType())
.orderStatus(HardOrderStatusEnum.CREATE.getType())
.orderType(HardOrderTypeEnum.BELOW.getType())
.payType(HardPayTypeEnum.HARD_DOOR_FREE_PAY.getType())
.totalPrice(0)
.extraPrice(0)
.payPrice(0)
.isOfflineOrder(YesNoEnum.NO.getCode())
.productDesc("智能柜商品*?")
.build();
baseMapper.insert(orderObj);
return orderObj.getId();
}
/**
* 结算智能柜订单
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Long payHardDoorOrder(HardOrderEntity dto, List<KsRecognitionCallbackDto.ResultSku> ksSpuList) {
if (ObjectUtil.isEmpty(dto) || ObjectUtil.isEmpty(ksSpuList)) return null;
// 创建购物车
List<String> ksSpuIds = ksSpuList.stream().map(KsRecognitionCallbackDto.ResultSku::getKs_sku_id).toList();
List<HardSpuEntity> hardSpuList = hardSpuService.get(ksSpuIds);
if (ObjectUtil.isEmpty(hardSpuList)) {
log.error("|{}|智能柜订单结算,商品不存在dto|{}|ksSpuList|{}|", TAG, JSONUtil.toJsonStr(dto), JSONUtil.toJsonStr(ksSpuList));
return null;
}
List<HardCreateCarDto> carListDto = new ArrayList<>();
for (KsRecognitionCallbackDto.ResultSku v : ksSpuList) {
hardSpuList.stream().filter(i -> ObjectUtil.equals(i.getKsSkuId(), v.getKs_sku_id())).findFirst().ifPresent(hardSpu -> {
HardCreateCarDto entity = new HardCreateCarDto();
entity.setProductId(hardSpu.getId());
entity.setProductNature(HardProductNatureEnum.DEFAULT);
entity.setProductCount(Integer.parseInt(v.getSku_num()));
carListDto.add(entity);
});
}
HardTypeEnum sysType = HardTypeEnum.valueOfByType(dto.getSysType());
HardOrderTypeEnum orderType = HardOrderTypeEnum.valueOfByType(dto.getOrderType());
// 获取商品价格
Integer totalPrice = hardCarService.computerCarTotalPrice(sysType, orderType, carListDto);
// 添加购物车
Long parentCarId = hardCarService.createCard(dto.getUserId(), dto.getMerchantId(), sysType, orderType, carListDto);
// 获取商品描述
String subject = hardCarService.computerCarSubject(sysType, orderType, carListDto);
// 更新订单信息
HardOrderEntity updateObj = HardOrderEntity.builder()
.id(dto.getId())
.parentCarId(parentCarId)
.totalPrice(totalPrice)
.payPrice(totalPrice)
.extraPrice(0)
.productDesc(subject)
.build();
baseMapper.updateById(updateObj);
HardOrderEntity orderObj = baseMapper.selectById(updateObj.getId());
// 扣减库存
getSelf().fastenerInventory(orderObj, YesNoEnum.YES);
// 钱包扣款
getSelf().fastReduceBalance(orderObj);
return orderObj.getId();
}
/**
* 智能柜取消订单
*/
@Override
public Long cancelHardDoorOrder(Long orderId) {
// 查询订单
HardOrderEntity order = baseMapper.selectById(orderId);
if (ObjectUtil.isEmpty(order)) {
log.error("|{}|智能柜订单取消失败,订单不存在|{}|", TAG, orderId);
return null;
}
if (ObjectUtil.isNotEmpty(order.getPayPrice()) && order.getPayPrice() > 0) {
log.error("|{}|智能柜订单取消失败,订单价格大于0|{}|", TAG, orderId);
return null;
}
if (ObjectUtil.isNotEmpty(order.getOrderStatus()) && ObjectUtil.equals(order.getOrderStatus(), HardOrderStatusEnum.UNFOLLOW.getType())) {
log.error("|{}|智能柜订单取消失败,订单已核销|{}|", TAG, orderId);
return null;
}
HardOrderEntity updateObj = HardOrderEntity.builder()
.id(order.getId())
.orderStatus(HardOrderStatusEnum.UNFOLLOW.getType())
.unfollowTime(LocalDateTime.now())
.build();
baseMapper.updateById(updateObj);
return updateObj.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void fastReduceBalance(HardOrderEntity order) {
@@ -513,7 +637,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
if (!ObjectUtil.isAllNotEmpty(hardTypeEnum, orderTypeEnum)) return;
String CarErrorMsg = ObjectUtil.equals(isReduce, YesNoEnum.YES) ? "扣减库存" : "恢复库存";
int base = ObjectUtil.equals(isReduce, YesNoEnum.YES) ? -1 : 1;
// 食堂扣件库存
// 食堂扣减库存
if (ObjectUtil.equals(hardTypeEnum, HardTypeEnum.CANTEEN) && ObjectUtil.equals(orderTypeEnum, HardOrderTypeEnum.RESERVE)) {
// 查询购物车
List<HardCarEntity> carList = hardCarService.getByParentCarId(order.getParentCarId());
@@ -534,7 +658,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
log.info("|{}|{},成功,order:|{}|,isReduce:|{}|,params:|{}|", TAG, CarErrorMsg, JSON.toJSON(order), isReduce, JSON.toJSON(dto));
return;
}
// 超市扣家库存
// 超市扣减库存
if (ObjectUtil.equals(hardTypeEnum, HardTypeEnum.SUPERMARKET)) {
// 查询购物车
List<HardCarEntity> carList = hardCarService.getByParentCarId(order.getParentCarId());
@@ -563,6 +687,25 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
log.info("|{}|{},成功,order:|{}|,isReduce:|{}|,params:|{}|", TAG, CarErrorMsg, JSON.toJSON(order), isReduce, JSON.toJSON(dto));
return;
}
// 智能柜扣减库存
if (ObjectUtil.equals(hardTypeEnum, HardTypeEnum.DOOR)) {
// 查询购物车
List<HardCarEntity> carList = hardCarService.getByParentCarId(order.getParentCarId());
if (ObjectUtil.isEmpty(carList)) throw new RuntimeException("扣减库存错误,购物车不存在");
List<DeductionSpuStockDto> list = carList.stream().map(v -> {
DeductionSpuStockDto entity = new DeductionSpuStockDto();
entity.setHardSpuId(v.getProductId());
entity.setIncrCount(v.getProductCount());
return entity;
}).toList();
Boolean isDeduction = hardSpuService.deductionSpuStock(list);
if (!isDeduction) {
log.info("|{}|{},失败,order:|{}|,isReduce:|{}|,params:|{}|", TAG, CarErrorMsg, JSON.toJSON(order), isReduce, JSON.toJSON(list));
throw new RuntimeException("扣减智能柜库存" + CarErrorMsg + "错误");
}
log.info("扣减智能柜库存成功|{}|{},成功,order:|{}|,isReduce:|{}|,params:|{}|", TAG, CarErrorMsg, JSON.toJSON(order), isReduce, JSON.toJSON(list));
return;
}
}
// 发送mq消息
@@ -587,8 +730,20 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
log.info("|{}|发送mq消息成功,超市打印发票order|{}|", TAG, JSON.toJSONString(orderId));
}
}
case CANTEEN -> {
HardOrderTypeEnum hardOrderType = HardOrderTypeEnum.valueOfByType(orderdetail.getOrderType());
if (ObjectUtil.isEmpty(hardTypeEnum)) {
log.error("|{}|发送mq消息失败,订餐类型错误hardType不存在hardType|{}|", TAG, orderdetail.getOrderType());
return;
}
// 发送订餐mq
if (ObjectUtil.equals(hardOrderType, HardOrderTypeEnum.RESERVE)) {
hardBroadcastService.addReserveOrderTask(orderdetail);
}
}
}
} catch (Exception e) {
// 不返回错误
log.info("|{}|发送mq消息成功,意外的错误error|{}|", TAG, e.getMessage());
}
}
@@ -17,6 +17,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List;
/**
@@ -33,20 +34,34 @@ public class HardSpuJoinServiceImpl extends ServiceImpl<HardSpuJoinMapper, HardS
@Override
public List<HardSpuJoinVo> scopeList(HardSpuJoinDto dto) {
List<HardSpuJoinEntity> list = baseMapper.selectList(new LambdaQueryWrapper<HardSpuJoinEntity>()
.eq(HardSpuJoinEntity::getHardDoorNumber, dto.getHardDoorNumber())
.eq(HardSpuJoinEntity::getHardDoorId, dto.getHardDoorId())
.eq(HardSpuJoinEntity::getCabinetNo, dto.getCabinetNo())
.eq(ObjectUtil.isNotEmpty(dto.getHardDoorNumber()), HardSpuJoinEntity::getHardDoorNumber, dto.getHardDoorNumber())
.eq(ObjectUtil.isNotEmpty(dto.getHardDoorId()), HardSpuJoinEntity::getHardDoorId, dto.getHardDoorId())
.eq(ObjectUtil.isNotEmpty(dto.getCabinetNo()), HardSpuJoinEntity::getCabinetNo, dto.getCabinetNo())
.isNotNull(ObjectUtil.isNotEmpty(dto.getIsSpu()) && dto.getIsSpu(), HardSpuJoinEntity::getSpuId)
.orderByAsc(HardSpuJoinEntity::getHardDoorNumber)
.orderByDesc(HardSpuJoinEntity::getSpuId)
);
if (ObjectUtil.isEmpty(list)) return List.of();
if (ObjectUtil.isEmpty(list)) return new ArrayList<>();
List<HardSpuJoinVo> joinList = BeanUtils.toBean(list, HardSpuJoinVo.class);
List<Long> spuIds = joinList.stream().map(HardSpuJoinVo::getSpuId).toList();
// 查询商品
if (ObjectUtil.isNotEmpty(spuIds)) {
List<HardSpuVo> spuList = hardSpuMapper.scopPageList(HardSpuDto.builder().build(), null);
HardSpuDto spuDto = new HardSpuDto();
spuDto.setSpuIdList(spuIds);
List<HardSpuVo> spuList = hardSpuMapper.scopPageList(spuDto, null);
for (HardSpuJoinVo v : joinList) {
spuList.stream().filter(i -> ObjectUtil.equals(i.getId(), v.getSpuId())).findFirst().ifPresent(v::setSpuDetail);
}
}
return List.of();
return joinList;
}
@Override
public List<HardSpuJoinVo> getSpuList(Long hardDoorId, Integer cabinetNo) {
HardSpuJoinDto queryDto = new HardSpuJoinDto();
queryDto.setHardDoorId(hardDoorId);
queryDto.setCabinetNo(String.valueOf(cabinetNo));
queryDto.setIsSpu(true);
return scopeList(queryDto);
}
}
@@ -12,15 +12,15 @@ import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.hard.api.constant.spu.HardSpuRepertoryTypeEnum;
import com.bsd.pjcloud.hard.api.dto.manager.HardManagerDto;
import com.bsd.pjcloud.hard.api.dto.spu.DeductionSpuRepertoryDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuRepertoryDto;
import com.bsd.pjcloud.hard.api.entity.manager.HardManagerEntity;
import com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuRepertoryEntity;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuRepertoryVo;
import com.bsd.pjcloud.hard.mapper.manager.HardManagerMapper;
import com.bsd.pjcloud.hard.mapper.spu.HardSpuRepertoryMapper;
import com.bsd.pjcloud.hard.service.HardDoorFlowService;
import com.bsd.pjcloud.hard.service.HardSpuRepertoryService;
import com.bsd.pjcloud.hard.service.HardSpuService;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
@@ -45,12 +45,11 @@ import java.util.List;
public class HardSpuRepertoryServiceImpl extends ServiceImpl<HardSpuRepertoryMapper, HardSpuRepertoryEntity> implements HardSpuRepertoryService {
private final HardSpuService hardSpuService;
private final HardDoorFlowService hardDoorFlowService;
private final RemoteMchService remoteMchService;
private final RemoteUserService remoteUserService;
private final HardManagerMapper hardManagerMapper;
@Override
public Page<HardSpuRepertoryVo> scopePageJoin(Page page, HardSpuRepertoryDto dto, DataScope dataScope) {
Page<HardSpuRepertoryVo> pageList = baseMapper.scopePageJoin(page, dto, dataScope);
@@ -69,13 +68,18 @@ public class HardSpuRepertoryServiceImpl extends ServiceImpl<HardSpuRepertoryMap
if (ObjectUtil.isEmpty(spuDetail)) {
throw new RuntimeException("商品不存在");
}
if (ObjectUtil.isEmpty(spuDetail.getSpuCategoryId())) {
throw new RuntimeException("商品分类不能为空");
}
if (ObjectUtil.equals(spuDetail.getPrice(), 0)) {
throw new RuntimeException("商品价格不能为0");
}
Integer beforeCount = 0;
if (ObjectUtil.isNotEmpty(spuDetail.getRepertoryCount())) {
beforeCount = spuDetail.getRepertoryCount();
}
entity.setBeforeCount(beforeCount);
entity.setUserId(user.getId());
entity.setHardId(entity.getHardId());
entity.setBizType(HardSpuRepertoryTypeEnum.HANDLER.getType());
baseMapper.insert(entity);
// 更新商品库存
@@ -143,6 +147,59 @@ public class HardSpuRepertoryServiceImpl extends ServiceImpl<HardSpuRepertoryMap
}
}
/**
* app上架完成
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean appRepertoryDone(DeductionSpuRepertoryDto body, Long userId) {
// 查询流程是否存在
HardDoorFlowEntity hardDoorFlow = hardDoorFlowService.getById(body.getFlowId());
if (ObjectUtil.isEmpty(hardDoorFlow)) {
throw new RuntimeException("上架流程不存在");
}
Long count = baseMapper.selectCount(new LambdaQueryWrapper<HardSpuRepertoryEntity>().eq(HardSpuRepertoryEntity::getBizId, body.getFlowId()));
if (count > 0) {
throw new RuntimeException("改上架已结束");
}
List<DeductionSpuRepertoryDto.Item> list = body.getList().stream().filter(v -> v.getPlusCount() > 0).toList();
if (ObjectUtil.isEmpty(list)) {
throw new RuntimeException("上架商品不能为空");
}
// 查询商品列表
List<Long> spuIds = list.stream().map(DeductionSpuRepertoryDto.Item::getHardSpuId).toList();
List<HardSpuEntity> spuList = hardSpuService.listByIds(spuIds);
// 更新上架记录
List<HardSpuRepertoryEntity> spuRepertoryList = new ArrayList<>();
List<HardSpuEntity> spuUpdateList = new ArrayList<>();
for (DeductionSpuRepertoryDto.Item i : list) {
spuList.stream().filter(v -> v.getId().equals(i.getHardSpuId())).findFirst().ifPresent(spu -> {
HardSpuRepertoryEntity entity = new HardSpuRepertoryEntity();
Integer beforeCount = 0;
if (ObjectUtil.isNotEmpty(spu.getRepertoryCount())) {
beforeCount = spu.getRepertoryCount();
}
entity.setSpuId(spu.getId());
entity.setUserId(userId);
entity.setBeforeCount(beforeCount);
entity.setCount(i.getPlusCount() + beforeCount);
entity.setBizId(body.getFlowId());
entity.setBizType(HardSpuRepertoryTypeEnum.PERSION.getType());
spuRepertoryList.add(entity);
HardSpuEntity spuEntity = new HardSpuEntity();
spuEntity.setId(spu.getId());
spuEntity.setRepertoryCount(entity.getCount());
spuUpdateList.add(spuEntity);
});
}
// 添加上架记录
baseMapper.insert(spuRepertoryList);
// 更新商品库存
hardSpuService.updateBatchById(spuUpdateList);
return false;
}
private void disposeList(List<HardSpuRepertoryVo> list, HardSpuRepertoryDto dto) {
if (ObjectUtil.isEmpty(list)) return;
// 商户
@@ -154,16 +211,6 @@ public class HardSpuRepertoryServiceImpl extends ServiceImpl<HardSpuRepertoryMap
WalletDataUtil.convertMchList(list, CollectionUtils.convertMap(mchList, MchManageVo::getId));
}
}
// 设备
List<Long> hardIds = list.stream().map(HardSpuRepertoryVo::getHardId).filter(ObjectUtil::isNotEmpty).distinct().toList();
if (ObjectUtil.isNotEmpty(hardIds)) {
HardManagerDto hardManagerDto = new HardManagerDto();
hardManagerDto.setIds(hardIds);
List<HardManagerEntity> hardList = hardManagerMapper.list(hardManagerDto);
if (ObjectUtil.isNotEmpty(hardList)) {
HardUtil.convertHardList(list, CollectionUtils.convertMap(hardList, HardManagerEntity::getId));
}
}
// 用户
List<Long> userIds = list.stream().map(HardSpuRepertoryVo::getUserId).distinct().toList();
R<List<SysUser>> userList = remoteUserService.getUserById(new ArrayList<>(userIds));
@@ -1,14 +1,22 @@
package com.bsd.pjcloud.hard.service.impl.spu;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.hard.api.constant.spu.HardKsCheckStatusEnum;
import com.bsd.pjcloud.hard.api.constant.spu.HardKsSkuTypeEnum;
import com.bsd.pjcloud.hard.api.dto.spu.DeductionSpuStockDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardPutawayDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuDto;
import com.bsd.pjcloud.hard.api.dto.spu.HardSpuJoinDto;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuEntity;
import com.bsd.pjcloud.hard.api.entity.spu.HardSpuJoinEntity;
import com.bsd.pjcloud.hard.api.vo.manager.HardDoorManagerVo;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuJoinVo;
import com.bsd.pjcloud.hard.api.vo.spu.HardSpuVo;
@@ -20,10 +28,12 @@ import com.bsd.pjcloud.hard.service.HardSpuService;
import com.bsd.pjcloud.thirdparty.api.feign.RemoterThirdKsService;
import com.bsd.pjcloud.thirdparty.dto.ks.KsBarcodeLikeDto;
import com.bsd.pjcloud.thirdparty.vo.ks.KsBarcodeLikeVo;
import com.bsd.pjcloud.thirdparty.vo.ks.KsSpuVo;
import com.bsd.pjcloud.wallet.api.feign.RemoteMchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.*;
@@ -37,6 +47,8 @@ import java.util.*;
@Service
public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity> implements HardSpuService {
private static final String TAG = "硬件商品";
private final HardManagerService hardManagerService;
private final HardDoorManagerService hardDoorManagerService;
private final HardSpuJoinService hardSpuJoinService;
@@ -55,14 +67,24 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
return pageList;
}
@Override
public List<HardSpuEntity> get(List<String> ksSpuIds) {
return baseMapper.selectList(new LambdaQueryWrapper<HardSpuEntity>().in(HardSpuEntity::getKsSkuId, ksSpuIds));
}
@Override
public List<HardSpuEntity> getByIds(List<Long> spuIds) {
return baseMapper.selectList(new LambdaQueryWrapper<HardSpuEntity>().in(HardSpuEntity::getId, spuIds));
}
/**
* 新增
*/
@Override
public Long create(HardSpuEntity entity) {
if (existName(entity)) {
throw new RuntimeException("商品名不能重复");
}
// if (existName(entity)) {
// throw new RuntimeException("商品名不能重复");
// }
entity.setSkuType(HardKsSkuTypeEnum.SELF.getType());
baseMapper.insert(entity);
// 发起审核
@@ -75,9 +97,9 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
*/
@Override
public Long edit(HardSpuEntity entity) {
if (existName(entity)) {
throw new RuntimeException("商品名不能重复");
}
// if (existName(entity)) {
// throw new RuntimeException("商品名不能重复");
// }
baseMapper.updateById(entity);
return entity.getId();
}
@@ -95,10 +117,11 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
* 根据 hardwareId 和 cabinetNo 查询商品
*/
@Override
@Transactional(rollbackFor = Exception.class)
public List<Map<Integer, List<HardSpuJoinVo>>> getByCabinetNo(Long hardId, String cabinetNo) {
List<Map<Integer, List<HardSpuJoinVo>>> result = new LinkedList<>();
// 查询设备
HardDoorManagerVo doorManagerVo = hardDoorManagerService.getByHardId(hardId);
HardDoorManagerVo doorManagerVo = hardDoorManagerService.getByHardDoorId(hardId);
if (ObjectUtil.isEmpty(doorManagerVo)) return result;
int doorCount = 6;
int storeySpuMaxCount = 10;
@@ -108,22 +131,84 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
for (int i = 1; i <= doorCount; i++) {
HardSpuJoinDto spuJoinDto = new HardSpuJoinDto();
spuJoinDto.setHardDoorNumber(i);
spuJoinDto.setHardDoorId(hardId);
spuJoinDto.setHardDoorId(doorManagerVo.getId());
spuJoinDto.setCabinetNo(cabinetNo);
List<HardSpuJoinVo> storeySpu = hardSpuJoinService.scopeList(spuJoinDto);
int storeySpuSize = storeySpu.size();
int emptyStoreySpuSize = storeySpuMaxCount - storeySpuSize;
for (int j = 0; j < emptyStoreySpuSize; j++) {
HardSpuJoinVo hardSpuJoinEntity = new HardSpuJoinVo();
hardSpuJoinEntity.setHardDoorId(hardId);
HardSpuJoinEntity hardSpuJoinEntity = new HardSpuJoinEntity();
hardSpuJoinEntity.setCabinetNo(cabinetNo);
hardSpuJoinEntity.setHardDoorId(doorManagerVo.getId());
hardSpuJoinEntity.setHardDoorNumber(i);
storeySpu.add(hardSpuJoinEntity);
hardSpuJoinService.save(hardSpuJoinEntity);
HardSpuJoinVo hardSpuJoinVo = new HardSpuJoinVo();
hardSpuJoinVo.setId(hardSpuJoinEntity.getId());
hardSpuJoinVo.setCabinetNo(hardSpuJoinEntity.getCabinetNo());
hardSpuJoinVo.setHardDoorId(hardSpuJoinEntity.getHardDoorId());
hardSpuJoinVo.setHardDoorNumber(hardSpuJoinEntity.getHardDoorNumber());
if (ObjectUtil.isNotEmpty(hardSpuJoinVo)) {
storeySpu.add(hardSpuJoinVo);
}
}
Map<Integer, List<HardSpuJoinVo>> addMap = new HashMap<>();
addMap.put(i, storeySpu);
result.add(addMap);
}
return List.of();
return result;
}
/**
* 查询货柜补货商品列表
*/
@Override
public List<HardSpuJoinVo> appCabinetPutawayList(Long hardDoorId, String cabinetNo) {
HardSpuJoinDto spuJoinDto = new HardSpuJoinDto();
spuJoinDto.setHardDoorId(hardDoorId);
spuJoinDto.setCabinetNo(cabinetNo);
spuJoinDto.setIsSpu(true);
return hardSpuJoinService.scopeList(spuJoinDto);
}
/**
* 上架id
*/
@Override
public void putaway(HardPutawayDto dto) {
// 查询有没有货柜
HardSpuJoinEntity spuJoinDetail = hardSpuJoinService.getOne(new LambdaQueryWrapper<HardSpuJoinEntity>()
.eq(HardSpuJoinEntity::getId, dto.getId())
);
if (ObjectUtil.isEmpty(spuJoinDetail)) throw new RuntimeException("货柜不存在");
// 校验商品
HardSpuEntity spuDetail = validateSpu(dto.getHardSpuId());
// 判断这一层是否重复
long doorCount = hardSpuJoinService.count(new LambdaUpdateWrapper<HardSpuJoinEntity>()
.eq(HardSpuJoinEntity::getHardDoorNumber, spuJoinDetail.getHardDoorNumber())
.eq(HardSpuJoinEntity::getSpuId, spuDetail.getId())
);
if (doorCount > 0) throw new RuntimeException("该层已有相同商品");
LambdaUpdateWrapper<HardSpuJoinEntity> updateObj = new LambdaUpdateWrapper<HardSpuJoinEntity>()
.set(HardSpuJoinEntity::getSpuId, spuDetail.getId())
.eq(HardSpuJoinEntity::getId, dto.getId());
hardSpuJoinService.update(updateObj);
}
/**
* 下架
*/
@Override
public void unPutaway(HardPutawayDto dto) {
// 查询有没有商品
HardSpuJoinEntity hardSpuJoinDetail = hardSpuJoinService.getOne(new LambdaQueryWrapper<HardSpuJoinEntity>()
.eq(HardSpuJoinEntity::getSpuId, dto.getHardSpuId())
.eq(HardSpuJoinEntity::getId, dto.getId())
);
if (ObjectUtil.isEmpty(hardSpuJoinDetail)) throw new RuntimeException("该商品不存在");
LambdaUpdateWrapper<HardSpuJoinEntity> updateObj = new LambdaUpdateWrapper<HardSpuJoinEntity>()
.set(HardSpuJoinEntity::getSpuId, null)
.eq(HardSpuJoinEntity::getId, dto.getId());
hardSpuJoinService.update(updateObj);
}
/**
@@ -135,16 +220,149 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
KsBarcodeLikeDto likeDto = new KsBarcodeLikeDto();
likeDto.setPage_num(pageNum);
while (true) {
asyncAllGroup(likeDto);
boolean hasnext = asyncAllGroup(likeDto);
if (hasnext) {
pageNum++;
likeDto.setPage_num(pageNum);
continue;
}
break;
}
}
public void asyncAllGroup(KsBarcodeLikeDto likeDto) {
KsBarcodeLikeVo data = remoterThirdKsService.barcodeSkuLike(likeDto).getData();
if (ObjectUtil.isEmpty(data)) {
/**
* 校验商品
*/
@Override
public HardSpuEntity validateSpu(Long hardSpuId) {
HardSpuEntity spuDetail = baseMapper.selectById(hardSpuId);
if (ObjectUtil.isEmpty(spuDetail)) throw new RuntimeException("商品不存在");
if (ObjectUtil.equals(spuDetail.getPrice(), 0)) {
throw new RuntimeException("商品价格不能为0");
}
if (spuDetail.getRepertoryCount() <= 0) {
throw new RuntimeException("商品库存不能小于0");
}
return spuDetail;
}
/**
* 扣减库存
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean deductionSpuStock(List<DeductionSpuStockDto> list) {
if (ObjectUtil.isEmpty(list)) {
log.error("|{}|扣减商品库存失败list为空", TAG);
return false;
}
List<Long> hardSpuIdes = list.stream().map(DeductionSpuStockDto::getHardSpuId).toList();
List<HardSpuEntity> hardSpuList = getByIds(hardSpuIdes);
if (ObjectUtil.isEmpty(hardSpuList)) {
log.error("|{}|扣减商品库存失败查询到的智能柜商品为空dto|{}|", TAG, JSONUtil.toJsonStr(list));
return false;
}
for (HardSpuEntity i : hardSpuList) {
list.stream().filter(j -> ObjectUtil.equals(i.getId(), j.getHardSpuId())).findFirst().ifPresent(hardSpu -> {
if (ObjectUtil.isNotEmpty(hardSpu.getIncrCount())) {
HardSpuEntity entity = new HardSpuEntity();
entity.setId(hardSpu.getHardSpuId());
entity.setSalesCount(i.getSalesCount() + hardSpu.getIncrCount());
entity.setRepertoryCount(i.getRepertoryCount() - hardSpu.getIncrCount());
// 乐观锁循环扣减库存
baseMapper.updateById(entity);
}
});
}
return true;
}
public boolean asyncAllGroup(KsBarcodeLikeDto likeDto) {
KsBarcodeLikeVo data = remoterThirdKsService.barcodeSkuLike(likeDto).getData();
if (ObjectUtil.isEmpty(data) || !data.isSuccess() || ObjectUtil.isEmpty(data.getResultList())) return false;
List<HardSpuEntity> spuList = new ArrayList<>();
for (KsSpuVo i : data.getResultList()) {
try {
HardSpuEntity entity = HardSpuEntity
.builder()
.spuCategoryId(null)
.name(i.getSku_name())
.cover(i.getCover())
.skuType(i.getSku_type())
.ksSkuId(i.getKs_sku_id())
.ksResSkuId(i.getSku_id())
.ksBarcode(i.getBarcode())
.ksHasSubSku(i.getHas_sub_sku())
.build();
// 图片
if (ObjectUtil.isNotEmpty(i.getImg_urls())) {
entity.setPic(String.join(",", i.getImg_urls()));
}
// 审核状态
entity.setKsStatus(HardKsCheckStatusEnum.CHECK_DONE.getType());
entity.setKsStatusTitle(HardKsCheckStatusEnum.CHECK_DONE.getDescription());
entity.setKsComments("API同步");
// 处理规格
KsSpuVo.KsSpuSpecsVo specs = i.getSpecs();
if (ObjectUtil.isNotEmpty(specs)) {
if (ObjectUtil.isNotEmpty(specs.getTaste())) entity.setSpecsTaste(specs.getTaste());
if (ObjectUtil.isNotEmpty(specs.getCapacity())) entity.setSpecsCapacity(specs.getCapacity());
if (ObjectUtil.isNotEmpty(specs.getWeight())) entity.setSpecsWeight(specs.getWeight());
}
// 处理集合SKU的子SKU信息
if (ObjectUtil.isEmpty(i.getSub_sku())) {
entity.setKsSubSkuJson("");
spuList.add(entity);
} else {
HardSpuEntity entityCopy = BeanUtil.toBean(entity, HardSpuEntity.class);
for (KsSpuVo j : i.getSub_sku()) {
entityCopy.setKsSkuId(j.getKs_sku_id());
entityCopy.setKsResSkuId(j.getSku_id());
entityCopy.setKsBarcode(j.getBarcode());
entityCopy.setName(j.getSku_name());
entityCopy.setSkuType(j.getSku_type());
entityCopy.setCover(i.getCover());
entityCopy.setKsSubSkuJson(JSONUtil.toJsonStr(j.getSub_sku()));
// 图片
if (ObjectUtil.isNotEmpty(j.getImg_urls())) {
entityCopy.setPic(String.join(",", j.getImg_urls()));
}
spuList.add(entityCopy);
}
}
} catch (Exception e) {
log.error("|{}|添加旷世商品错误|{}|", TAG, e.getMessage());
}
}
if (ObjectUtil.isNotEmpty(spuList)) {
List<HardSpuEntity> insertList = new ArrayList<>();
List<HardSpuEntity> updateList = new ArrayList<>();
for (HardSpuEntity i : spuList) {
HardSpuEntity entity = baseMapper.selectOne(new LambdaQueryWrapper<HardSpuEntity>()
.eq(HardSpuEntity::getKsResSkuId, i.getKsResSkuId())
.eq(HardSpuEntity::getKsSkuId, i.getKsSkuId())
);
if (ObjectUtil.isEmpty(entity)) {
i.setPrice(0);
i.setSalesCount(0);
i.setRepertoryCount(0);
i.setSort(0);
i.setIsDefault(YesNoEnum.YES.getCode());
i.setStatus(YesNoEnum.YES.getCode());
insertList.add(i);
} else {
i.setId(entity.getId());
updateList.add(i);
}
}
if (ObjectUtil.isNotEmpty(insertList)) {
baseMapper.insert(insertList);
}
if (ObjectUtil.isNotEmpty(updateList)) {
baseMapper.updateById(updateList);
}
}
return true;
}
/**
@@ -39,10 +39,13 @@
<sql id="whereA">
a.del_flag = '0'
<if test="dto.userId != null">
and a.userId = #{dto.userId}
and a.user_id = #{dto.userId}
</if>
<if test="dto.hardId != null">
and a.hard_id = #{dto.hardId}
</if>
<if test="dto.authStatus != null and dto.authStatus != '' ">
and a.authStatus = #{dto.auth_status}
and a.auth_status = #{dto.authStatus}
</if>
<if test="dto.isDone != null">
and a.is_done = #{dto.isDone}
@@ -65,5 +68,6 @@
<where>
<include refid="whereA"/>
</where>
order by a.create_time desc , a.id desc
</select>
</mapper>
@@ -7,6 +7,7 @@
<result property="userId" column="user_id"/>
<result property="hardId" column="hard_id"/>
<result property="topic" column="topic"/>
<result property="bizType" column="biz_type"/>
<result property="bizId" column="biz_id"/>
<result property="title" column="title"/>
<result property="content" column="content"/>
@@ -28,6 +29,7 @@
a.user_id,
a.hard_id,
a.topic,
a.biz_type,
a.biz_id,
a.title,
a.content,
@@ -52,6 +54,9 @@
<if test="dto.hardId != null">
and a.hard_id = #{dto.hardId}
</if>
<if test="dto.bizType != null">
and a.biz_type = #{dto.bizType}
</if>
<if test="dto.bizId != null">
and a.biz_id = #{dto.bizId}
</if>
@@ -77,5 +82,4 @@
<include refid="whereA"/>
</where>
</select>
</mapper>
@@ -0,0 +1,28 @@
<?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.bsd.pjcloud.hard.mapper.HardDoorFlowMapper">
<resultMap id="hardDoorFlowMap" type="com.bsd.pjcloud.hard.api.entity.HardDoorFlowEntity">
<id property="id" column="id"/>
<result property="orderId" column="order_id"/>
<result property="authId" column="auth_id"/>
<result property="openEventId" column="open_event_id"/>
<result property="openOutOpenNo" column="open_out_open_no"/>
<result property="openCallbackRes" column="open_callback_res"/>
<result property="openCallbackTime" column="open_callback_time"/>
<result property="videoCallbackRes" column="video_callback_res"/>
<result property="videoCallbackTime" column="video_callback_time"/>
<result property="skuKsRecogId" column="sku_ks_recog_id"/>
<result property="skuSubmitTime" column="sku_submit_time"/>
<result property="skuCallbackRes" column="sku_callback_res"/>
<result property="skuCallbackTime" column="sku_callback_time"/>
<result property="skuDrivingRes" column="sku_driving_res"/>
<result property="skuDrivingTime" column="sku_driving_time"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -0,0 +1,22 @@
<?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.bsd.pjcloud.hard.mapper.manager.HardDoorCabinetMapper">
<resultMap id="hardDoorCabinetMap" type="com.bsd.pjcloud.hard.api.entity.manager.HardDoorCabinetEntity">
<id property="id" column="id"/>
<result property="hardDoorId" column="hard_door_id"/>
<result property="cabinetNo" column="cabinet_no"/>
<result property="isLockOnline" column="is_lock_online"/>
<result property="lockStatus" column="lock_status"/>
<result property="doorStatus" column="door_status"/>
<result property="saleStatus" column="sale_status"/>
<result property="qrCode" column="qr_code"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="delFlag" column="del_flag"/>
<result property="tenantId" column="tenant_id"/>
</resultMap>
</mapper>
@@ -14,11 +14,13 @@
<result property="powerStatus" column="power_status"/>
<result property="netStatus" column="net_status"/>
<result property="saleStatus" column="sale_status"/>
<result property="simSn" column="sim_sn"/>
<result property="signalIntensity" column="signal_intensity"/>
<result property="signalRatio" column="signal_ratio"/>
<result property="signalTime" column="signal_time"/>
<result property="cabinetList" column="cabinet_list"/>
<result property="restartTime" column="restart_time"/>
<result property="systemVolume" column="system_volume"/>
<result property="mediaVolume" column="media_volume"/>
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
@@ -39,11 +41,13 @@
a.power_status,
a.net_status,
a.sale_status,
a.sim_sn,
a.signal_intensity,
a.signal_ratio,
a.signal_time,
a.cabinet_list,
a.restart_time,
a.system_volume,
a.media_volume,
a.create_by,
a.create_time,
a.update_by,
@@ -6,6 +6,7 @@
<id property="id" column="id"/>
<result property="spuCategoryId" column="spu_category_id"/>
<result property="name" column="name"/>
<result property="cover" column="cover"/>
<result property="pic" column="pic"/>
<result property="price" column="price"/>
<result property="salesCount" column="sales_count"/>
@@ -17,9 +18,11 @@
<result property="specsCapacity" column="specs_capacity"/>
<result property="specsWeight" column="specs_weight"/>
<result property="skuType" column="sku_type"/>
<result property="ksSkuId" column="ks_sku_id"/>
<result property="ksResSkuId" column="ks_res_sku_id"/>
<result property="ksBarcode" column="ks_barcode"/>
<result property="ksHasSubSku" column="ks_has_sub_sku"/>
<result property="ksSubSku" column="ks_sub_sku"/>
<result property="ksSubSkuJson" column="ks_sub_sku_json"/>
<result property="ksStatus" column="ks_status"/>
<result property="ksStatusTitle" column="ks_status_title"/>
<result property="ksComments" column="ks_comments"/>
@@ -35,6 +38,7 @@
select a.id,
a.spu_category_id,
a.name,
a.cover,
a.pic,
a.price,
a.sales_count,
@@ -46,9 +50,11 @@
a.specs_capacity,
a.specs_weight,
a.sku_type,
a.ks_res_sku_id,
a.ks_sku_id,
a.ks_barcode,
a.ks_has_sub_sku,
a.ks_sub_sku,
a.ks_sub_sku_json,
a.ks_status,
a.ks_status_title,
a.ks_comments,
@@ -106,7 +112,7 @@
</sql>
<select id="scopPageJoin" resultType="com.bsd.pjcloud.hard.api.vo.spu.HardSpuVo">
<include refid="selectJoin" />
<include refid="selectJoin"/>
</select>
<select id="scopPageList" resultType="com.bsd.pjcloud.hard.api.vo.spu.HardSpuVo">
@@ -5,7 +5,6 @@
<resultMap id="hardSpuRepertoryMap" type="com.bsd.pjcloud.hard.api.entity.spu.HardSpuRepertoryEntity">
<id property="id" column="id"/>
<result property="userId" column="user_id"/>
<result property="hardId" column="hard_id"/>
<result property="spuId" column="spu_id"/>
<result property="beforeCount" column="before_count"/>
<result property="count" column="count"/>
@@ -21,7 +20,6 @@
<sql id="selectA">
select a.id,
a.user_id,
a.hard_id,
a.spu_id,
a.before_count,
a.count,
@@ -36,9 +34,6 @@
<sql id="whereA">
a.del_flag = '0'
<if test="dto.hardId != null and dto.hardId != '' ">
and a.hard_id = #{dto.hardId}
</if>
<if test="dto.spuId != null and dto.spuId != '' ">
and a.spu_id = #{dto.spuId}
</if>
@@ -60,8 +55,6 @@
<include refid="selectA"/>
s.name as spuName,
s.spu_category_id,
s.hard_door_number,
s.mch_id as spuMchId,
c.name as spuCategoryName
from hard_spu_repertory a
left join hard_spu s on s.id = a.spu_id
@@ -11,7 +11,7 @@ import java.util.Arrays;
@Getter
public enum ThirdDoorKsApiTypeEnum {
REGISTER("10", "常规SKU提交审核"),
SKU_SUBMIT("10", "常规SKU提交审核"),
SKU_SUBMIT_COLLECTION("20", "集合SKU提交审核(未公开)"),
SKU_RESULT("30", "SKU审核结果主动获取"),
SKU_EDIT("40", "常规SKU修改"),
@@ -21,6 +21,8 @@ public enum ThirdDoorKsApiTypeEnum {
BARCODE_SKU_LIKE("80", "模糊查询标准库和私有库商品信息"),
RECOGNITION("90", "SKU提交识别"),
RECOGNITION_RESULT("100", "SKU识别结果主动获取"),
RECOGNITION_CALLBACK("110", "SKU识别结果回调通知"),
SKU_SUBMIT_CALLBACK("120", "SKU审核结果回调通知"),
;
private final String type;
@@ -0,0 +1,91 @@
package com.bsd.pjcloud.thirdparty.dto.door;
import com.bsd.pjcloud.thirdparty.vo.door.DoorStatusVo;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class DoorStatusCallbackDto {
/**
* 设备编号
*/
private String deviceCode;
/**
* 1:通电;2:断电
*/
private Integer powerStatus;
/**
* 在线状态,1:在线;2:离线
*/
private Integer netStatus;
/**
* 售卖状态。1:在售;2:停售
*/
private Integer saleStatus;
/**
* sim卡号设备有上报会返回,若一次上报都没有,则返回null。
*/
private String simSn;
/**
* sim 信号强度
* 大于-95 表示信号强度好
* -95 到-105 表示信号强度中等
* 小于-105 表示信号差
*/
private Integer signalIntensity;
/**
* 信噪比,体现信道传输质量的参数
* 大于 15 表示质量好
* 15 到 0 表示质量中等
* 小于等于 0 表示质量差
*/
private Integer signalRatio;
/**
* sim 信号值更新时间。yyyy-MM-dd HH:mm:ss
*/
private LocalDateTime signalTime;
/**
* 货柜列表
*/
private List<DoorStatusVo.Cabinet> cabinetList;
@Data
public static class Cabinet {
/**
* 货柜号(1,2)
*/
private Integer cabinetNo;
/**
* 锁在线1:在线;2:离线
*/
private String isLockOnline;
/**
* 锁状态1:锁关;2:锁开
*/
private Integer lockStatus;
/**
* 门状态1:门关;2:门开
*/
private Integer doorStatus;
/**
* 货柜售卖状态1:在售;2:停售
*/
private Integer saleStatus;
}
}
@@ -43,7 +43,7 @@ public class DoorVideoCallbackDto {
private List<DoorVideoCallbackDto.Video> videoList;
@Data
public class Video {
public static class Video {
/**
* 摄像头号:1:主摄;2:辅摄
@@ -0,0 +1,80 @@
package com.bsd.pjcloud.thirdparty.dto.ks;
import lombok.Data;
import java.util.List;
@Data
public class KsRecognitionCallbackDto {
private String ks_recog_id;
private State state;
private Result result;
@Data
public static class State {
/**
* 该字段用于表示识别任务进行到了哪个阶段,返回结果为字典值,不同code代表不同结果
* 1:识别进行中
* 2:识别完成(已生成识别结果,但未经过人工二次复核,如业务方对此识别结果不认同,还可通过售后识别接口发起一次售后识别)
* 3:二次验证中(业务方对识别结果不认同,通过售后识别接口发起售后识别,人工二次验证中)
* 4:自动二次验证中(已生成识别结果,但由于识别结果为失败或告警,为谨慎返回失败或告警的结果,人工二次验证中)
* 5:识别完成(已生成识别结果,且已经过人工二次复核,此时的结果为最终结果,不可再通过售后识别接口发起售后识别)
* 注意:2和5的区别为,当结果为2时,可通过售后识别接口发起售后识别,当结果为5时,不可再通过售后识别接口发起售后识别
*/
private String code;
private String desc;
}
@Data
public static class Result {
private ResultStatus status;
/**
* 标注备注信息
*/
private String comments;
/**
* 只有status:code值为2是该字段才返回
*/
private List<ResultSku> result;
}
@Data
public static class ResultStatus {
/***
* 1:识别中
* 2:成功
* 3:成功:未拿商品
* 4:失败:无法识别
* 6:告警:故意遮挡
* 7:告警:柜中无此SKU
* 8:告警:其他告警
* 9:告警:异物拿放
* 10:告警:疑似设备故障
*/
private String code;
private String desc;
}
@Data
public static class ResultSku {
/**
* 识别到的sku_id(超级收银员平台的sku_id)
*/
private String ks_sku_id;
/**
* 识别到的sku数量
*/
private String sku_num;
}
}
@@ -2,6 +2,8 @@ package com.bsd.pjcloud.thirdparty.dto.ks;
import lombok.Data;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
@Data
@@ -24,7 +26,7 @@ public class KsRecognitionDto {
* floor_num(非必选):
* SKU所在的货架层数
*/
private String extra_params;
private Map<String, Object> extra_params;
/**
* 货柜ID
@@ -42,7 +44,7 @@ public class KsRecognitionDto {
* <p>
* 需将主摄像头,即设备左上角或右上角的摄像头(开门那侧的最优),的url作为第一个链接
*/
private String resource_urls;
private List<String> resource_urls;
/**
* 资源信息列表,与resource_urls二选一。
@@ -0,0 +1,41 @@
package com.bsd.pjcloud.thirdparty.dto.ks;
import lombok.Data;
@Data
public class KsSkuSubmitCallbackDto {
/**
* 该字段为使用方系统sku_id
*/
private String sku_id;
/**
* 该字段为超级收银员平台的sku_id,后续SKU管理域所有请求都需要以该字段作为参数
*/
private String ks_sku_id;
/**
* 该字段返回结果为字典值,不同code代表不同结果
*/
private Result result;
/**
* 审核不通过时该字段才有值
*/
private String comments;
@Data
public static class Result {
/**
* 2:审核通过
* 3:审核不通过
*/
private Integer code;
private String desc;
}
}
@@ -1,7 +0,0 @@
package com.bsd.pjcloud.thirdparty.vo.door;
import lombok.Data;
@Data
public class DoorOpenCallbackVo {
}
@@ -59,10 +59,10 @@ public class DoorStatusVo extends DoorBaseInnerVo {
/**
* 货柜列表
*/
private List<Cabinet> cabinetList;
private List<Cabinet> cabinetStatusList;
@Data
public class Cabinet {
public static class Cabinet {
/**
* 货柜号(1,2)
@@ -72,7 +72,7 @@ public class DoorStatusVo extends DoorBaseInnerVo {
/**
* 锁在线1:在线;2:离线
*/
private Integer isLockOnline;
private String isLockOnline;
/**
* 锁状态1:锁关;2:锁开
@@ -1,7 +0,0 @@
package com.bsd.pjcloud.thirdparty.vo.door;
import lombok.Data;
@Data
public class DoorVideoCallbackVo {
}
@@ -2,60 +2,29 @@ package com.bsd.pjcloud.thirdparty.vo.ks;
import lombok.Data;
import java.util.List;
@Data
public class KsBarcodeByIdsVo {
/**
* 该字段为超级收银员平台的商品ID
* 当前页码,正整数,默认1
*/
private String ks_sku_id;
private Integer page_num;
/**
* 商品69码,集合SKU无返回
* 分页大小,正整数,默认10,最大50
*/
private String barcode;
private Integer page_size;
/**
* 商品名称
* 总数
*/
private String sku_name;
private Integer total;
/**
* 业务方sku_id
* 商品列表
*/
private String sku_id;
/**
* 商品包装图片列表,用于供无人零售柜运营方确认商品包装是否同拟售卖商品一致。因69码并非包装的唯一ID,同一69码会出现包装不一致的情况。所以该确认过程非常重要。
*/
private String img_urls;
/**
* 商品封图300*300
*/
private String cover;
/**
* SKU类型:
* 0:标准库
* 1:私有库
*/
private String sku_type;
/**
* 该字段为SKU所对应的规格,包含口味、容量、重量,taste表示口味,capacity表示容量,单位:ml,weight表示重量,单位:g
*/
private String specs;
/**
* 是否集合SKU
*/
private String has_sub_sku;
/**
* 集合SKU的子SKU信息,
* 子SKU更多详情可以通过4.1.8接口根据ks_sku_id查询。
*/
private String sub_sku;
private List<KsSpuVo> resultList;
}
@@ -2,6 +2,29 @@ package com.bsd.pjcloud.thirdparty.vo.ks;
import lombok.Data;
import java.util.List;
@Data
public class KsBarcodeLikeVo extends KsBaseInnerVo {
/**
* 当前页码,正整数,默认1
*/
private Integer page_num;
/**
* 分页大小,正整数,默认10,最大50
*/
private Integer page_size;
/**
* 总数
*/
private Integer total;
/**
* 商品列表
*/
private List<KsSpuVo> resultList;
}
@@ -2,60 +2,28 @@ package com.bsd.pjcloud.thirdparty.vo.ks;
import lombok.Data;
import java.util.List;
@Data
public class KsBarcodeSkuVo {
/**
* 该字段为超级收银员平台的商品ID
* 当前页码,正整数,默认1
*/
private String ks_sku_id;
private Integer page_num;
/**
* 商品69码,集合SKU无返回
* 分页大小,正整数,默认10,最大50
*/
private String barcode;
private Integer page_size;
/**
* 商品名称
* 总数
*/
private String sku_name;
private Integer total;
/**
* 业务方sku_id
* 商品列表
*/
private String sku_id;
/**
* 商品包装图片列表,用于供无人零售柜运营方确认商品包装是否同拟售卖商品一致。因69码并非包装的唯一ID,同一69码会出现包装不一致的情况。所以该确认过程非常重要。
*/
private String img_urls;
/**
* 商品封图300*300
*/
private String cover;
/**
* SKU类型:
* 0:标准库
* 1:私有库
*/
private String sku_type;
/**
* 该字段为SKU所对应的规格,包含口味、容量、重量,taste表示口味,capacity表示容量,单位:ml,weight表示重量,单位:g
*/
private String specs;
/**
* 是否集合SKU
*/
private String has_sub_sku;
/**
* 集合SKU的子SKU信息,
* 子SKU更多详情可以通过4.1.8接口根据ks_sku_id查询。
*/
private String sub_sku;
private List<KsSpuVo> resultList;
}
@@ -19,7 +19,7 @@ public class KsBaseVo {
private String data;
public boolean isSuccess() {
return ObjectUtil.equal(code, KsBaseVo.successCode);
return ObjectUtil.isEmpty(msg);
}
}
@@ -3,7 +3,7 @@ package com.bsd.pjcloud.thirdparty.vo.ks;
import lombok.Data;
@Data
public class KsRecognitionVo {
public class KsRecognitionVo extends KsBaseInnerVo {
/**
* 识别任务唯一ID,用于结果获取、重新发起售后识别
@@ -3,7 +3,7 @@ package com.bsd.pjcloud.thirdparty.vo.ks;
import lombok.Data;
@Data
public class KsSkuSubmitVo {
public class KsSkuSubmitVo extends KsBaseInnerVo {
private String ks_sku_id;
@@ -0,0 +1,77 @@
package com.bsd.pjcloud.thirdparty.vo.ks;
import lombok.Data;
import java.util.List;
/**
* 旷世商品
*/
@Data
public class KsSpuVo {
/**
* 该字段为超级收银员平台的商品ID
*/
private String ks_sku_id;
/**
* 商品69码,集合SKU无返回
*/
private String barcode;
/**
* 商品名称
*/
private String sku_name;
/**
* 业务方sku_id
*/
private String sku_id;
/**
* 商品包装图片列表,用于供无人零售柜运营方确认商品包装是否同拟售卖商品一致。因69码并非包装的唯一ID,同一69码会出现包装不一致的情况。所以该确认过程非常重要。
*/
private List<String> img_urls;
/**
* 商品封图300*300
*/
private String cover;
/**
* SKU类型:
* 0:标准库
* 1:私有库
*/
private String sku_type;
/**
* 该字段为SKU所对应的规格,包含口味、容量、重量,taste表示口味,capacity表示容量,单位:ml,weight表示重量,单位:g
*/
private KsSpuSpecsVo specs;
/**
* 是否集合SKU
*/
private String has_sub_sku;
/**
* 集合SKU的子SKU信息,
* 子SKU更多详情可以通过4.1.8接口根据ks_sku_id查询。
*/
private List<KsSpuVo> sub_sku;
@Data
public static class KsSpuSpecsVo {
private String taste;
private String capacity;
private String weight;
}
}
@@ -15,5 +15,18 @@ public class DoorConfig {
private String appKey;
private String selfBaseUrl;
/**
* 回调基础url
*/
private String callbackBaseUrl;
/**
* 开锁回调url
*/
private String callbackLockUrl;
/**
* 视频回调url
*/
private String callbackVideoUrl;
}
@@ -16,4 +16,19 @@ public class KsDiscernConfig {
private String accessKey;
private String secretKey;
/**
* 回调基础url
*/
private String callbackBaseUrl;
/**
* sku审核回调
*/
private String callbackSkuUrl;
/**
* 识别回调
*/
private String callbackRecognitionUrl;
}
@@ -1,6 +1,7 @@
package com.bsd.pjcloud.thirdparty.controller.door;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.thirdparty.dto.door.*;
@@ -10,11 +11,11 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequiredArgsConstructor
@@ -84,22 +85,25 @@ public class ThirdDoorApiController {
@Inner(value = false)
@Operation(summary = "门锁开关通知回调")
@PostMapping("/callback/open")
public R<DoorOpenCallbackVo> callbackOpen(@RequestBody DoorOpenCallbackDto dto) {
return R.ok(thirdDoorApiService.callbackOpen(dto));
public void callbackOpen(HttpEntity<String> httpEntity, @RequestHeader Map<String, String> headers) {
String body = httpEntity.getBody();
thirdDoorApiService.callbackOpen(body, headers);
}
@Inner(value = false)
@Operation(summary = "视频地址通知回调")
@PostMapping("/callback/video")
public R<DoorVideoCallbackVo> callbackVideo(@RequestBody DoorVideoCallbackDto dto) {
return R.ok(thirdDoorApiService.callbackVideo(dto));
public void callbackVideo(HttpEntity<String> httpEntity, @RequestHeader Map<String, String> headers) {
String body = httpEntity.getBody();
thirdDoorApiService.callbackVideo(body, headers);
}
@Inner(value = false)
@Operation(summary = "设备状态通知回调")
@PostMapping("/callback/status")
public R<DoorStatusVo> callbackStatus(@RequestBody DoorStatusDto dto) {
return R.ok(thirdDoorApiService.callbackStatus(dto));
public void callbackStatus(HttpEntity<String> httpEntity, @RequestHeader Map<String, String> headers) {
String body = httpEntity.getBody();
thirdDoorApiService.callbackStatus(body, headers);
}
@@ -11,9 +11,12 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequiredArgsConstructor
@RequestMapping("/third-ks")
@@ -97,4 +100,24 @@ public class ThirdKsApiController {
/* ************************************* end 远程调用 end ************************************* */
/* ************************************* start 回调 start ************************************* */
@Inner(value = false)
@Operation(summary = "sku审核回调")
@PostMapping("/callback/sku")
public void callbackSKu(HttpEntity<String> httpEntity, @RequestHeader Map<String, String> headers) {
String body = httpEntity.getBody();
thirdKsApiService.callbackSKu(body, headers);
}
@Inner(value = false)
@Operation(summary = "识别回调")
@PostMapping("/callback/recognition")
public void callbackRecognition(HttpEntity<String> httpEntity, @RequestHeader Map<String, String> headers) {
String body = httpEntity.getBody();
thirdKsApiService.callbackRecognition(body, headers);
}
/* ************************************* end 回调 end ************************************* */
}
@@ -4,6 +4,8 @@ package com.bsd.pjcloud.thirdparty.service;
import com.bsd.pjcloud.thirdparty.dto.door.*;
import com.bsd.pjcloud.thirdparty.vo.door.*;
import java.util.Map;
public interface ThirdDoorApiService {
/**
@@ -44,15 +46,15 @@ public interface ThirdDoorApiService {
/**
* 门锁开关通知回调
*/
DoorOpenCallbackVo callbackOpen(DoorOpenCallbackDto dto);
void callbackOpen(String json, Map<String, String> headers);
/**
* 视频地址通知回调
*/
DoorVideoCallbackVo callbackVideo(DoorVideoCallbackDto dto);
void callbackVideo(String json, Map<String, String> headers);
/**
* 设备状态通知回调
*/
DoorStatusVo callbackStatus(DoorStatusDto dto);
void callbackStatus(String json, Map<String, String> headers);
}
@@ -6,6 +6,8 @@ import com.bsd.pjcloud.thirdparty.dto.ks.*;
import com.bsd.pjcloud.thirdparty.vo.door.DoorRegisterVo;
import com.bsd.pjcloud.thirdparty.vo.ks.*;
import java.util.Map;
public interface ThirdKsApiService {
/**
@@ -57,4 +59,14 @@ public interface ThirdKsApiService {
* SKU识别结果主动获取
*/
KsRecognitionResultVo recognitionResult(KsRecognitionResultDto dto);
/**
* sku审核回调
*/
void callbackSKu(String json, Map<String, String> headers);
/**
* 识别回调
*/
void callbackRecognition(String json, Map<String, String> headers);
}
@@ -3,6 +3,7 @@ package com.bsd.pjcloud.thirdparty.service.impl.door;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.hard.api.feign.RemoteHardDoorService;
import com.bsd.pjcloud.thirdparty.config.DoorConfig;
import com.bsd.pjcloud.thirdparty.dto.door.*;
import com.bsd.pjcloud.thirdparty.entity.door.ThirdDoorLogEntity;
@@ -31,6 +32,8 @@ public class ThirdDoorApiServiceImpl implements ThirdDoorApiService {
private final ThirdDoorLogService doorLogService;
private final RemoteHardDoorService remoteHardDoorService;
/**
* 设备注册
*/
@@ -212,6 +215,8 @@ public class ThirdDoorApiServiceImpl implements ThirdDoorApiService {
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(JSONUtil.toJsonStr(dto));
try {
dto.setLockNotifyUrl(doorConfig.getCallbackBaseUrl() + doorConfig.getCallbackLockUrl());
dto.setVideoNotifyUrl(doorConfig.getCallbackBaseUrl() + doorConfig.getCallbackVideoUrl());
String body = JSONUtil.toJsonStr(dto);
String res = api.getHttpRequest().header(apiCountersign(body)).body(body).execute().body();
if (ObjectUtil.isEmpty(res)) throw new RuntimeException("response响应为空");
@@ -273,25 +278,81 @@ public class ThirdDoorApiServiceImpl implements ThirdDoorApiService {
* 门锁开关通知回调
*/
@Override
public DoorOpenCallbackVo callbackOpen(DoorOpenCallbackDto dto) {
return null;
public void callbackOpen(String json, Map<String, String> headers) {
DoorOpenCallbackDto dto = JSONUtil.toBean(json, DoorOpenCallbackDto.class);
boolean isSign = apiParseSign(json, headers);
if (!isSign) {
log.error("|{}| callbackOpen 签名错误", TAG);
return;
}
long startTime = System.currentTimeMillis();
DoorApi.Api api = DoorApi.OPEN_CALLBACK.setBaseUrl(doorConfig.getBaseUrl());
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(json);
try {
remoteHardDoorService.disposeLocakCallback(dto);
} catch (Exception e) {
String error = String.format("|%s||callbackOpen|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
logEntity.setError(error);
} finally {
logEntity.setTimeConsuming(Long.toString(System.currentTimeMillis() - startTime));
doorLogService.save(logEntity);
}
}
/**
* 视频地址通知回调
*/
@Override
public DoorVideoCallbackVo callbackVideo(DoorVideoCallbackDto dto) {
return null;
public void callbackVideo(String json, Map<String, String> headers) {
DoorVideoCallbackDto dto = JSONUtil.toBean(json, DoorVideoCallbackDto.class);
boolean isSign = apiParseSign(json, headers);
if (!isSign) {
log.error("|{}| callbackVideo 签名错误", TAG);
return;
}
long startTime = System.currentTimeMillis();
DoorApi.Api api = DoorApi.VIDEO_CALLBACK.setBaseUrl(doorConfig.getBaseUrl());
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(json);
try {
remoteHardDoorService.disposeVideoCallback(dto);
} catch (Exception e) {
String error = String.format("|%s||callbackVideo|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
logEntity.setError(error);
} finally {
logEntity.setTimeConsuming(Long.toString(System.currentTimeMillis() - startTime));
doorLogService.save(logEntity);
}
}
/**
* 设备状态通知回调
*/
@Override
public DoorStatusVo callbackStatus(DoorStatusDto dto) {
return null;
public void callbackStatus(String json, Map<String, String> headers) {
DoorStatusCallbackDto dto = JSONUtil.toBean(json, DoorStatusCallbackDto.class);
boolean isSign = apiParseSign(json, headers);
if (!isSign) {
log.error("|{}| callbackStatus 签名错误", TAG);
return;
}
long startTime = System.currentTimeMillis();
DoorApi.Api api = DoorApi.STATUS_CALLBACK.setBaseUrl(doorConfig.getBaseUrl());
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(json);
try {
remoteHardDoorService.disposeStatusCallback(dto);
} catch (Exception e) {
String error = String.format("|%s||callbackStatus|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
logEntity.setError(error);
} finally {
logEntity.setTimeConsuming(Long.toString(System.currentTimeMillis() - startTime));
doorLogService.save(logEntity);
}
}
/**
@@ -317,4 +378,35 @@ public class ThirdDoorApiServiceImpl implements ThirdDoorApiService {
header.put("sign", List.of(map.get("sign")));
return header;
}
/**
* 接口解签
*/
private boolean apiParseSign(String json, Map<String, String> headers) {
if (ObjectUtil.isEmpty(headers)) {
log.error("|{}|apiParseSign 接口解签错误headers为空dto|{}|headers|{}|", TAG, json, JSONUtil.toJsonStr(headers));
return false;
}
String appid = headers.get("Appid");
String noncestr = headers.get("Noncestr");
String timestamp = headers.get("Timestamp");
String sign = headers.get("Sign");
if (ObjectUtil.notEqual(doorConfig.getAppId(), appid)) {
log.error("|{}|apiParseSign 接口解签错误appId错误dto|{}|headers|{}|", TAG, json, JSONUtil.toJsonStr(headers));
return false;
}
// 计算正确的sign
String successSign = "";
successSign += doorConfig.getAppId() + "&";
successSign += doorConfig.getAppKey() + "&";
successSign += noncestr + "&";
successSign += timestamp + "&";
successSign += json;
String successSignMd5 = DigestUtils.md5Hex(successSign);
if (ObjectUtil.notEqual(successSignMd5.toLowerCase(), sign.toLowerCase())) {
log.error("|{}|apiParseSign 接口解签错误sign错误dto|{}|headers|{}|", TAG, json, JSONUtil.toJsonStr(headers));
return false;
}
return true;
}
}
@@ -2,17 +2,20 @@ package com.bsd.pjcloud.thirdparty.service.impl.ks;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.json.JSONUtil;
import com.bsd.pjcloud.hard.api.feign.RemoteHardDoorService;
import com.bsd.pjcloud.thirdparty.config.KsDiscernConfig;
import com.bsd.pjcloud.thirdparty.dto.ks.*;
import com.bsd.pjcloud.thirdparty.entity.door.ThirdDoorLogEntity;
import com.bsd.pjcloud.thirdparty.service.ThirdDoorLogService;
import com.bsd.pjcloud.thirdparty.service.ThirdKsApiService;
import com.bsd.pjcloud.thirdparty.utils.ks.api.KsApi;
import com.bsd.pjcloud.thirdparty.utils.ks.tool.KsRetailSignUtils;
import com.bsd.pjcloud.thirdparty.vo.ks.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@@ -31,6 +34,8 @@ public class ThirdKsApiServiceImpl implements ThirdKsApiService {
private final ThirdDoorLogService doorLogService;
private final RemoteHardDoorService remoteHardDoorService;
/**
* 常规SKU提交审核
*/
@@ -230,7 +235,8 @@ public class ThirdKsApiServiceImpl implements ThirdKsApiService {
logEntity.setTimeConsuming(Long.toString(System.currentTimeMillis() - startTime));
doorLogService.save(logEntity);
}
return JSONUtil.toBean(ksBaseVo.getData(), KsBarcodeLikeVo.class);
KsBarcodeLikeVo result = JSONUtil.toBean(ksBaseVo.getData(), KsBarcodeLikeVo.class);
return result;
}
/**
@@ -238,13 +244,30 @@ public class ThirdKsApiServiceImpl implements ThirdKsApiService {
*/
@Override
public KsRecognitionVo recognition(KsRecognitionDto dto) {
dto.setNotify_url(ksDiscernConfig.getCallbackBaseUrl() + ksDiscernConfig.getCallbackRecognitionUrl());
long startTime = System.currentTimeMillis();
KsBaseVo ksBaseVo = new KsBaseVo();
KsApi.Api api = KsApi.BARCODE_SKU.setBaseUrl(ksDiscernConfig.getBaseUrl()).setParams(BeanUtil.beanToMap(dto));
KsApi.Api api = KsApi.RECOGNITION.setBaseUrl(ksDiscernConfig.getBaseUrl())
.setParams(BeanUtil.beanToMap(dto))
.setAccessKey(ksDiscernConfig.getAccessKey())
.setSecretKey(ksDiscernConfig.getSecretKey())
.setHost(ksDiscernConfig.getHost());
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(JSONUtil.toJsonStr(dto));
try {
String body = JSONUtil.toJsonStr(dto);
api.setBody(body);
String res = api.getHttpRequest().execute().body();
if (ObjectUtil.isEmpty(res)) throw new RuntimeException("response响应为空");
logEntity.setRes(res);
ksBaseVo = JSONUtil.toBean(res, KsBaseVo.class);
if (!ksBaseVo.isSuccess()) {
String errorLog = String.format("请求错误res|%s|url|%s|body|%s|", res, api, body);
log.error(errorLog);
KsRecognitionVo errorVo = new KsRecognitionVo();
errorVo.setMessage(ksBaseVo.getMsg());
return errorVo;
}
} catch (Exception e) {
String error = String.format("|%s||recognition|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
@@ -278,4 +301,83 @@ public class ThirdKsApiServiceImpl implements ThirdKsApiService {
}
return JSONUtil.toBean(ksBaseVo.getData(), KsRecognitionResultVo.class);
}
/**
* sku审核回调
*/
@Override
public void callbackSKu(String json, Map<String, String> headers) {
KsSkuSubmitCallbackDto dto = JSONUtil.toBean(json, KsSkuSubmitCallbackDto.class);
boolean isSign = apiParseSign(json, ksDiscernConfig.getCallbackSkuUrl(), headers);
if (!isSign) {
log.error("|{}| callbackSKu 签名错误", TAG);
return;
}
long startTime = System.currentTimeMillis();
KsApi.Api api = KsApi.SKU_SUBMIT_CALLBACK;
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(json);
try {
} catch (Exception e) {
String error = String.format("|%s||callbackSKu|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
logEntity.setError(error);
} finally {
logEntity.setTimeConsuming(Long.toString(System.currentTimeMillis() - startTime));
doorLogService.save(logEntity);
}
}
/**
* 识别回调
*/
@Override
public void callbackRecognition(String json, Map<String, String> headers) {
KsRecognitionCallbackDto dto = JSONUtil.toBean(json, KsRecognitionCallbackDto.class);
boolean isSign = apiParseSign(json, ksDiscernConfig.getCallbackRecognitionUrl(), headers);
if (!isSign) {
log.error("|{}| callbackRecognition 签名错误", TAG);
return;
}
long startTime = System.currentTimeMillis();
KsApi.Api api = KsApi.RECOGNITION_CALLBACK;
ThirdDoorLogEntity logEntity = api.getInitLogEntity();
logEntity.setReq(json);
try {
remoteHardDoorService.disposeRecognitionCallback(dto);
} catch (Exception e) {
String error = String.format("|%s||callbackRecognition|意外的错误error|%s|stack|%s|", TAG, e.getMessage(), Arrays.toString(e.getStackTrace()));
log.error(error);
logEntity.setError(error);
} finally {
logEntity.setTimeConsuming(Long.toString(System.currentTimeMillis() - startTime));
doorLogService.save(logEntity);
}
}
/**
* 接口解签
*/
private boolean apiParseSign(String json, String uri, Map<String, String> headers) {
String authorization = headers.get("Authorization");
if (ObjectUtil.isEmpty(authorization)) {
throw new RuntimeException("签名参数缺失");
}
String referer = headers.get("Referer");
if (ObjectUtil.isEmpty(referer)) {
throw new RuntimeException("签名参数缺失");
}
String cleanUrl = referer.replaceAll("^(http|https)://", "");
String contentType = headers.get("Content-Type");
if (ObjectUtil.isEmpty(contentType)) {
throw new RuntimeException("签名参数缺失");
}
String timestamp = headers.get("X-Request-Date");
if (ObjectUtil.isEmpty(timestamp)) {
throw new RuntimeException("签名参数缺失");
}
String signAuth = KsRetailSignUtils.getSignAuth(cleanUrl, uri, contentType, HttpPost.METHOD_NAME, Long.valueOf(timestamp), ksDiscernConfig.getAccessKey(), ksDiscernConfig.getSecretKey(), json, "");
return ObjectUtil.equals(signAuth, authorization);
}
}
@@ -29,34 +29,40 @@ import java.util.TreeMap;
public class KsApi {
// 常规SKU提交审核
public static final KsApi.Api SKU_SUBMIT = KsApi.Api.builder().url("/openapi/sc/v1/sku").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_SUBMIT = KsApi.Api.builder().url("/openapi/sc/v1/sku").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// 集合SKU提交审核(未公开)
public static final KsApi.Api SKU_SUBMIT_COLLECTION = KsApi.Api.builder().url("/openapi/sc/v1/sku/collection").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_SUBMIT_COLLECTION = KsApi.Api.builder().url("/openapi/sc/v1/sku/collection").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU审核结果主动获取
public static final KsApi.Api SKU_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// 常规SKU修改
public static final KsApi.Api SKU_EDIT = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPatch.METHOD_NAME).contentType("application/json").build();
// SKU识别结果回调通知
public static final KsApi.Api SKU_EDIT = KsApi.Api.builder().url("/callback").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPatch.METHOD_NAME).contentType("application/json").build();
// SKU审核结果回调通知
public static final KsApi.Api SKU_SUBMIT_CALLBACK = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT_CALLBACK).method(HttpPatch.METHOD_NAME).contentType("application/json").build();
// SKU删除
public static final KsApi.Api SKU_DELETE = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpDelete.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api SKU_DELETE = KsApi.Api.builder().url("/openapi/sc/v1/sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpDelete.METHOD_NAME).contentType("application/json").build();
// 根据69码查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU = KsApi.Api.builder().url("/openapi/sc/v1/sku/all_sku/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpGet.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU = KsApi.Api.builder().url("/openapi/sc/v1/sku/all_sku/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// 根据ks_sku_id查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU_BY_ID = KsApi.Api.builder().url("/openapi/sc/v1/sku/skus/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpGet.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU_BY_ID = KsApi.Api.builder().url("/openapi/sc/v1/sku/skus/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// 模糊查询标准库和私有库商品信息
public static final KsApi.Api BARCODE_SKU_LIKE = KsApi.Api.builder().url("/openapi/sc/v1/sku/sku_list").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpGet.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api BARCODE_SKU_LIKE = KsApi.Api.builder().url("/openapi/sc/v1/sku/sku_list").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpGet.METHOD_NAME).contentType("application/json").build();
// SKU提交识别
public static final KsApi.Api RECOGNITION = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api RECOGNITION = KsApi.Api.builder().url("/openapi/sc/v1/recognition").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU识别结果回调通知
public static final KsApi.Api RECOGNITION_CALLBACK = KsApi.Api.builder().url("/callback").bizType(ThirdDoorKsApiTypeEnum.RECOGNITION_CALLBACK).method(HttpPost.METHOD_NAME).contentType("application/json").build();
// SKU识别结果主动获取
public static final KsApi.Api RECOGNITION_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThirdDoorKsApiTypeEnum.REGISTER).method(HttpPost.METHOD_NAME).contentType("application/json").build();
public static final KsApi.Api RECOGNITION_RESULT = KsApi.Api.builder().url("/openapi/sc/v1/recognition/%s").bizType(ThirdDoorKsApiTypeEnum.SKU_SUBMIT).method(HttpPost.METHOD_NAME).contentType("application/json").build();
@Data
@Builder
@@ -113,6 +119,11 @@ public class KsApi {
return this;
}
public KsApi.Api setBody(String body) {
this.body = body;
return this;
}
/**
* 获取当前时间戳
*/
@@ -148,13 +159,16 @@ public class KsApi {
Map<String, List<String>> header = new HashMap<>();
header.put("Authorization", List.of(auth));
header.put("Content-Type", List.of(getContentType()));
header.put("X-Request-Date", List.of(String.valueOf(getXRequestDate())));
header.put("X-Request-Date", List.of(String.valueOf(currentTime)));
header.put("X-Request-id", List.of(requestId));
header.put("Referer", List.of("https://" + getHost()));
return header;
}
public HttpRequest getHttpRequest() {
// 初始化数据
if (ObjectUtil.isEmpty(getBody())) setBody("");
if (ObjectUtil.isEmpty(getParams())) setParams(new TreeMap<>());
String fullPatch = baseUrl + url;
String query = getQueryString();
if (ObjectUtil.isNotEmpty(query)) {
@@ -75,16 +75,19 @@ door:
base-url: https://www.365e-life.net:8443/bkopenapi
app-id: 2025040991646569
app-key: 2800650617d44e0d8b31ad5287431179
self-base-url:
callback-base-url: http://h1yzkslmyx.ny.takin.cc
callback-lock-url: /third/third-door/callback/open
callback-video-url: /third/third-door/callback/video
# 旷世识别
ks-discern:
base-url: https://retail.xlsdn.com
access-key: ed5A923eF0e941A1968eGTpF
secret-key: Ex3X0kgoc94sBOtivjWm5Vz9AyZTOUpl
host: retail.xlsdn.com
callback-base-url: http://h1yzkslmyx.ny.takin.cc
callback-recognition-url: /third/third-ks/callback/recognition
callback-sku-url: /third/third-ks/callback/sku
@@ -87,6 +87,16 @@ public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> impl
public Boolean removeDeptById(Long id) {
// 级联删除部门
List<Long> idList = this.listDescendant(id).stream().map(SysDept::getDeptId).collect(Collectors.toList());
if (idList.size() > 1) throw new RuntimeException("该部门下有子部门,无法删除");
for (Long v : idList) {
// 查询该部门下的用户
List<SysUser> userList = userMapper.selectList(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId, v));
if (CollUtil.isNotEmpty(userList)) {
SysDept sysDept = baseMapper.selectById(v);
throw new RuntimeException("该部门<" + sysDept.getName() + ">下有" + userList.size() + "名用户,无法删除,请先删除该部门下的用户");
}
}
Optional.ofNullable(idList).filter(CollUtil::isNotEmpty).ifPresent(this::removeByIds);
@@ -78,6 +78,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -174,6 +174,7 @@
FROM
sys_user u
LEFT JOIN sys_dept d ON d.dept_id = u.dept_id
LEFT JOIN sys_user_role urole ON urole.user_id = u.user_id
<where>
u.del_flag = '0'
<if test="query.userId != null">
@@ -193,6 +194,12 @@
<if test="query.deptId != null">
AND u.dept_id = #{query.deptId}
</if>
<if test="query.role != null and query.role.size() != 0">
and urole.role_id IN
<foreach collection="query.role" item="v" open="(" close=")" separator=",">
#{v}
</foreach>
</if>
<if test="query.deptIds != null and query.deptIds.size() != 0">
<choose>
<when test="query.isInclude != null and query.isInclude == true">
@@ -224,6 +231,7 @@
</foreach>
</if>
</where>
group by u.user_id
<if test="_databaseId != 'mssql'">
ORDER BY u.create_time DESC, u.user_id DESC
</if>
Loaded 100 of 117 files, more files were not shown because too many files have changed in this diff. Show more