feat:拉取旷世商品

This commit is contained in:
dzc committed 2025-04-14 15:35:44 +08:00
1 parent 3fd191429e
commit 753078984c
14 files changed
+279 -112

No files matched your search

+7 -4
View File
@@ -317,9 +317,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 '库存',
@@ -329,10 +330,12 @@ 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 '旷世审核状态描述',
@@ -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;
@@ -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;
/**
* 旷世审核状态
@@ -42,7 +42,8 @@ public class HardSpuJoinServiceImpl extends ServiceImpl<HardSpuJoinMapper, HardS
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();
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);
}
@@ -1,15 +1,20 @@
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.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.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;
@@ -21,6 +26,7 @@ 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;
@@ -38,6 +44,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;
@@ -115,10 +123,12 @@ public class HardSpuServiceImpl extends ServiceImpl<HardSpuMapper, HardSpuEntity
int storeySpuSize = storeySpu.size();
int emptyStoreySpuSize = storeySpuMaxCount - storeySpuSize;
for (int j = 0; j < emptyStoreySpuSize; j++) {
HardSpuJoinVo hardSpuJoinEntity = new HardSpuJoinVo();
HardSpuJoinEntity hardSpuJoinEntity = new HardSpuJoinEntity();
hardSpuJoinEntity.setCabinetNo(cabinetNo);
hardSpuJoinEntity.setHardDoorId(hardId);
hardSpuJoinEntity.setHardDoorNumber(i);
storeySpu.add(hardSpuJoinEntity);
hardSpuJoinService.save(hardSpuJoinEntity);
storeySpu.add(BeanUtil.toBean(hardSpuJoinEntity, HardSpuJoinVo.class));
}
Map<Integer, List<HardSpuJoinVo>> addMap = new HashMap<>();
addMap.put(i, storeySpu);
@@ -144,16 +154,102 @@ 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) {
public boolean asyncAllGroup(KsBarcodeLikeDto likeDto) {
KsBarcodeLikeVo data = remoterThirdKsService.barcodeSkuLike(likeDto).getData();
if (ObjectUtil.isEmpty(data)) {
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 false;
}
/**
@@ -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">
@@ -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.equal(code, KsBaseVo.successCode) || ObjectUtil.isNotEmpty(request_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;
}
}
@@ -230,7 +230,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;
}
/**
@@ -148,18 +148,27 @@ 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)) {
fullPatch = fullPatch + "?" + query;
}
// 计算签名
Long currentTime = getXRequestDate();
String queryString = getQueryString();
String auth = KsRetailSignUtils.getSignAuth(getHost(), getUrl(), contentType, getMethod(), currentTime, getAccessKey(), getSecretKey(), getBody(), queryString);
String requestId = getXRequestDate() + RandomUtil.randomString(19);
setRequestId(requestId);
if (ObjectUtil.equals(method, HttpPost.METHOD_NAME)) {
return HttpRequest.post(fullPatch).header(getHeader()).body(getBody());
} else if (ObjectUtil.equals(method, HttpGet.METHOD_NAME)) {
@@ -83,7 +83,6 @@ ks-discern:
base-url: https://retail.xlsdn.com
access-key: ed5A923eF0e941A1968eGTpF
secret-key: Ex3X0kgoc94sBOtivjWm5Vz9AyZTOUpl
host: retail.xlsdn.com