记得上下班打卡 | git大法好,push需谨慎

Commit 0c7fd4c2 authored by 姜秀龙's avatar 姜秀龙

Merge remote-tracking branch 'refs/remotes/origin/master' into jxl_20240313_prod

parents 68f38dc0 f2af79bb
......@@ -34,6 +34,8 @@ public class GoblinFrontGoodDetailVo implements Serializable {
@ApiModelProperty(value = "条码识别到的SKUID列表", notes = "仅当条码识别时有效")
private List<String> hitSkuIdList;
@ApiModelProperty(value = "当前用户是否已购买本场演出门票(与收钱吧下单换购价校验一致);仅收钱吧商品(spuType=33)且传入 performancesId 时返回 true/false,其他情况为 null;未登录为 false")
private Boolean boughtPerformance;
private static final long serialVersionUID = 1L;
......
......@@ -41,6 +41,9 @@ public class GoblinGoodsSkuInfoDetailVo implements Serializable, Cloneable {
@ApiModelProperty(position = 20, value = "单品销售价-原价[20,2]")
private BigDecimal sellPrice;
@ApiModelProperty(value = "收钱吧商品(spuType=33)演出关联换购价(元);其他商品类型恒为 null;SQB 且传入 performancesId 且后台已配置时返回")
private BigDecimal settlementPrice;
@ApiModelProperty(position = 26, value = "限量[0-无限制|X:限购数量]")
private Integer buyLimit;
@ApiModelProperty(position = 27, value = "剩余库存(实时:Redis getSkuStock)")
......
......@@ -19,7 +19,7 @@ public class GoblinSqbPerformanceGoodsInfoVo extends GoblinGoodsInfoVo {
@ApiModelProperty(value = "正常售价")
private BigDecimal price;
@ApiModelProperty(value = "换购价(不设置则按正常价)")
@ApiModelProperty(value = "收钱吧商品(spuType=33)换购价展示(元):关联 SKU 换购价最小值;非 SQB 商品恒为 null;未配置换购价时不返回")
private BigDecimal settlementPrice;
@ApiModelProperty(value = "已上架 SKU 明细(含 restStock、stockLess、canBuy 等,与商品详情接口字段一致)")
......
......@@ -77,7 +77,7 @@ public class GoblinFrontController {
@GetMapping("getGoodsDetail")
@ApiOperation("获得商品详情")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", required = false, dataType = "String", name = "performancesId", value = "演出ID,可选;收钱吧商品(spuType=33)时传入则仅返回该演出已关联的 SKU")
@ApiImplicitParam(paramType = "query", required = false, dataType = "String", name = "performancesId", value = "演出ID,可选;收钱吧商品(spuType=33)时传入则仅返回该演出已关联的 SKU,并返回 boughtPerformance 是否已购本场票")
})
public ResponseDto<GoblinFrontGoodDetailVo> getGoodsDetail(
@RequestParam(name = "spuId", required = true) String spuId,
......
......@@ -394,14 +394,81 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
return buildOnShelfSkuDetailList(goblinGoodsInfoVo, null);
}
/**
* 从演出-商品关联构建 skuId → 后台配置的换购价(原始值,展示前需经 {@link #resolveSqbDisplaySettlementPrice})
*/
private Map<String, BigDecimal> buildSqbSettlementPriceBySkuId(List<GoblinSqbPerformanceGoods> relations, String spuId) {
Map<String, BigDecimal> map = new HashMap<>();
if (CollectionUtils.isEmpty(relations)) {
return map;
}
String spu = StringUtil.isBlank(spuId) ? null : spuId.trim();
for (GoblinSqbPerformanceGoods r : relations) {
if (r == null || StringUtil.isBlank(r.getSkuId())) {
continue;
}
if (spu != null && (StringUtil.isBlank(r.getSpuId()) || !spu.equals(r.getSpuId().trim()))) {
continue;
}
map.put(r.getSkuId().trim(), r.getSettlementPrice());
}
return map;
}
/**
* 前台展示换购价:与收钱吧下单 {@code resolveSqbUnitPriceYuan} 一致(换购价须有效且不超过 SKU 售价),但不校验用户是否已购演出门票。
*/
private BigDecimal resolveSqbDisplaySettlementPrice(GoblinGoodsSkuInfoVo skuVo, BigDecimal configuredSettlement) {
if (skuVo == null || configuredSettlement == null) {
return null;
}
if (configuredSettlement.compareTo(BigDecimal.ZERO) <= 0) {
return null;
}
BigDecimal base = skuVo.getSellPrice() != null ? skuVo.getSellPrice() : skuVo.getPrice();
if (base == null) {
return configuredSettlement;
}
if (configuredSettlement.compareTo(base) > 0) {
return base;
}
return configuredSettlement;
}
private BigDecimal resolveSpuMinSettlementPrice(List<GoblinGoodsSkuInfoDetailVo> skuList) {
if (CollectionUtils.isEmpty(skuList)) {
return null;
}
BigDecimal min = null;
for (GoblinGoodsSkuInfoDetailVo sku : skuList) {
if (sku == null || sku.getSettlementPrice() == null) {
continue;
}
if (min == null || sku.getSettlementPrice().compareTo(min) < 0) {
min = sku.getSettlementPrice();
}
}
return min;
}
/**
* @param allowedSkuIds 非 null 时仅保留集合内的 SKU(用于收钱吧演出关联 SKU、spuType=33 详情)
* @param settlementPriceBySkuId 仅 spuType=33 时传入;其他商品类型忽略
*/
private ArrayList<GoblinGoodsSkuInfoDetailVo> buildOnShelfSkuDetailList(GoblinGoodsInfoVo goblinGoodsInfoVo, Set<String> allowedSkuIds) {
return buildOnShelfSkuDetailList(goblinGoodsInfoVo, allowedSkuIds, null);
}
private ArrayList<GoblinGoodsSkuInfoDetailVo> buildOnShelfSkuDetailList(GoblinGoodsInfoVo goblinGoodsInfoVo, Set<String> allowedSkuIds,
Map<String, BigDecimal> settlementPriceBySkuId) {
ArrayList<GoblinGoodsSkuInfoDetailVo> list = ObjectUtil.goblinGoodsSkuInfoDetailVos();
if (goblinGoodsInfoVo == null) {
return list;
}
boolean sqbSpu = isSqbSpuGoods(goblinGoodsInfoVo);
if (!sqbSpu) {
settlementPriceBySkuId = null;
}
String spuId = goblinGoodsInfoVo.getSpuId();
List<String> skuIdList = goblinGoodsInfoVo.getSkuIdList();
if (CollectionUtils.isEmpty(skuIdList)) {
......@@ -422,6 +489,7 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
int stock = goblinRedisUtils.getSkuStock(pre, goblinGoodsSkuInfoVo.getSkuId());
log.debug("skuId:{},库存数量{}", goblinGoodsSkuInfoVo.getSkuId(), stock);
GoblinGoodsSkuInfoDetailVo goblinGoodsSkuInfoDetailVo = GoblinGoodsSkuInfoDetailVo.getNew();
goblinGoodsSkuInfoDetailVo.setSettlementPrice(null);
BeanUtils.copyProperties(goblinGoodsSkuInfoVo, goblinGoodsSkuInfoDetailVo);
fillSkuPicIfBlank(goblinGoodsSkuInfoDetailVo, goblinGoodsInfoVo);
if (0 != goblinGoodsSkuInfoDetailVo.getBuyLimit()) {
......@@ -438,6 +506,15 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
goblinGoodsSkuInfoDetailVo.setStockLess(false);
}
goblinGoodsSkuInfoDetailVo.setRestStock(stock);
if (sqbSpu && settlementPriceBySkuId != null && !settlementPriceBySkuId.isEmpty()) {
String skuKey = goblinGoodsSkuInfoVo.getSkuId();
BigDecimal configured = skuKey != null ? settlementPriceBySkuId.get(skuKey) : null;
if (configured == null && StringUtil.isNotBlank(sku)) {
configured = settlementPriceBySkuId.get(sku.trim());
}
goblinGoodsSkuInfoDetailVo.setSettlementPrice(
resolveSqbDisplaySettlementPrice(goblinGoodsSkuInfoVo, configured));
}
list.add(goblinGoodsSkuInfoDetailVo);
}
}
......@@ -456,6 +533,7 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
*/
public GoblinFrontGoodDetailVo getGoodsDetail(String spuId, String performancesId) {
GoblinFrontGoodDetailVo goblinFrontGoodDetailVo = GoblinFrontGoodDetailVo.getNew();
goblinFrontGoodDetailVo.setBoughtPerformance(null);
GoblinGoodsInfoVo goblinGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(spuId);
GoblinGoodsInfoDetailVo goblinGoodsInfoDetailVo = GoblinGoodsInfoDetailVo.getNew();
//skuIdList
......@@ -464,16 +542,24 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
goblinFrontGoodDetailVo.setGoblinGoodsInfoVo(goblinGoodsInfoDetailVo);
// int limit= getStockCount(goblinGoodsInfoVo.getStoreId());
Set<String> sqbSkuAllow = null;
Map<String, BigDecimal> settlementPriceBySkuId = null;
if (isSqbSpuGoods(goblinGoodsInfoVo)) {
sqbSkuAllow = loadSqbLinkedSkuIdSet(spuId, performancesId);
if (StringUtil.isNotBlank(performancesId)) {
List<GoblinSqbPerformanceGoods> perfRelations =
loadSqbPerformanceGoodsRelationsFromCacheOrDb(performancesId);
settlementPriceBySkuId = buildSqbSettlementPriceBySkuId(perfRelations, spuId);
}
}
ArrayList<GoblinGoodsSkuInfoDetailVo> list = buildOnShelfSkuDetailList(goblinGoodsInfoVo, sqbSkuAllow);
ArrayList<GoblinGoodsSkuInfoDetailVo> list =
buildOnShelfSkuDetailList(goblinGoodsInfoVo, sqbSkuAllow, settlementPriceBySkuId);
//goblinGoodsInfoVo
GoblinStoreInfoVo goblinStoreInfoVo = this.getStore(goblinGoodsInfoVo.getStoreId());
if (null != goblinStoreInfoVo) {
goblinFrontGoodDetailVo.setStoreName(goblinStoreInfoVo.getStoreName());
}
goblinFrontGoodDetailVo.setGoblinGoodsSkuInfoVolist(list);
fillBoughtPerformanceFlag(goblinFrontGoodDetailVo, goblinGoodsInfoVo, performancesId);
} else {
return null;
}
......@@ -482,6 +568,23 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
return goblinFrontGoodDetailVo;
}
/**
* 详情页:是否已购本场演出门票(仅 SQB + performancesId;与下单换购价逻辑同源)
*/
private void fillBoughtPerformanceFlag(GoblinFrontGoodDetailVo detailVo, GoblinGoodsInfoVo goodsInfoVo,
String performancesId) {
if (detailVo == null || !isSqbSpuGoods(goodsInfoVo) || StringUtil.isBlank(performancesId)) {
return;
}
String userId = CurrentUtil.getCurrentUid();
if (StringUtils.isBlank(userId)) {
detailVo.setBoughtPerformance(false);
return;
}
int buyCount = goblinRedisUtils.getUserPerformanceBuyCount(userId, performancesId.trim());
detailVo.setBoughtPerformance(buyCount > 0);
}
/**
* 根据条码获得商品详情
*/
......@@ -508,6 +611,7 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
Integer buyCount = 0;
GoblinFrontGoodDetailVo goblinFrontGoodDetailVo = GoblinFrontGoodDetailVo.getNew();
goblinFrontGoodDetailVo.setBoughtPerformance(null);
GoblinGoodsInfoVo goblinGoodsInfoVo = goblinRedisUtils.getGoodsInfoVo(spuId);
GoblinGoodsInfoDetailVo goblinGoodsInfoDetailVo = GoblinGoodsInfoDetailVo.getNew();
//skuIdList
......@@ -1300,8 +1404,17 @@ public class GoblinFrontServiceImpl implements GoblinFrontService {
BigDecimal normalPrice = resolveGoodsSellPrice(goodsInfoVo, linkedSkuIds);
frontGoods.setSellPrice(normalPrice);
frontGoods.setPrice(normalPrice);
frontGoods.setSettlementPrice(rel.getSettlementPrice());
frontGoods.setGoblinGoodsSkuInfoVolist(buildOnShelfSkuDetailList(goodsInfoVo, linkedSkuIds));
frontGoods.setSettlementPrice(null);
ArrayList<GoblinGoodsSkuInfoDetailVo> skuDetailList;
if (isSqbSpuGoods(goodsInfoVo)) {
Map<String, BigDecimal> settlementPriceBySkuId =
buildSqbSettlementPriceBySkuId(relations, rel.getSpuId());
skuDetailList = buildOnShelfSkuDetailList(goodsInfoVo, linkedSkuIds, settlementPriceBySkuId);
frontGoods.setSettlementPrice(resolveSpuMinSettlementPrice(skuDetailList));
} else {
skuDetailList = buildOnShelfSkuDetailList(goodsInfoVo, linkedSkuIds);
}
frontGoods.setGoblinGoodsSkuInfoVolist(skuDetailList);
allGoods.add(frontGoods);
}
}
......
......@@ -3092,6 +3092,29 @@ public class GoblinRedisUtils {
return performanceData;
}
/**
* 用户维度本场演出已购票数量(与 order {@code DataUtils#getUserPBuyCount} 一致)
*/
public int getUserPerformanceBuyCount(String userId, String performanceId) {
if (!StringUtils.hasText(userId) || !StringUtils.hasText(performanceId)) {
return 0;
}
try {
String key = KylinRedisConst.USERID_BUY_INFO + userId.trim() + ":"
+ KylinRedisConst.PERFORMANCE_ID + ":" + performanceId.trim();
Object val = redisUtil.get(key);
if (val == null) {
return 0;
}
if (val instanceof Number) {
return ((Number) val).intValue();
}
return Integer.parseInt(String.valueOf(val));
} catch (Exception e) {
return 0;
}
}
public void setSqbPerformanceGoodsListCache(String performancesId, List<GoblinSqbPerformanceGoods> relations) {
String key = GoblinRedisConst.SQB_PERFORMANCE_GOODS.concat(performancesId);
redisUtil.set(key, relations, RedisKeyExpireConst.SQB_PERFORMANCE_GOODS_EXPIRE);
......
......@@ -356,7 +356,7 @@ public class GoblinSqbOrderServiceImpl implements IGoblinSqbOrderService {
storeOrderVo.getUserId(), storeOrderVo.getUserName(), storeOrderVo.getUserMobile(), storeOrderVo.getPriceTotal(), storeOrderVo.getPayCode(),
storeOrderVo.getPriceActual(), storeOrderVo.getPriceRefund(), storeOrderVo.getPriceExpress(), storeOrderVo.getPriceCoupon(), storeOrderVo.getStorePriceCoupon(),
storeOrderVo.getPriceVoucher(), storeOrderVo.getStatus(), storeOrderVo.getUcouponId(), storeOrderVo.getStoreCouponId(), storeOrderVo.getPayType(), storeOrderVo.getDeviceFrom(),
storeOrderVo.getSource(), storeOrderVo.getVersion(), storeOrderVo.getIsMember(), storeOrderVo.getOrderType(), storeOrderVo.getWriteOffCode(), storeOrderVo.getPayCountdownMinute(),
storeOrderVo.getSource(), "", "", storeOrderVo.getVersion(), storeOrderVo.getIsMember(), storeOrderVo.getOrderType(), storeOrderVo.getWriteOffCode(), storeOrderVo.getPayCountdownMinute(),
storeOrderVo.getIpAddress(), storeOrderVo.getMarketId(), storeOrderVo.getMarketType(), storeOrderVo.getCreatedAt(), "", ""
});
......
......@@ -519,7 +519,7 @@ public class MixOrderServiceImpl implements IMixOrderService {
sqlDataGoblin.add(new Object[]{
storeOrder.getMasterOrderCode(), storeOrder.getOrderId(), storeOrder.getStoreId(), storeOrder.getStoreName(), storeOrder.getOrderCode(), storeOrder.getUserId(), storeOrder.getUserName(), storeOrder.getUserMobile(), storeOrder.getPriceTotal(), storeOrder.getPayCode(),
storeOrder.getPriceActual(), storeOrder.getPriceRefund(), storeOrder.getPriceExpress(), storeOrder.getPriceCoupon(), storeOrder.getStorePriceCoupon(), storeOrder.getPriceVoucher(), storeOrder.getStatus(), storeOrder.getUcouponId(), storeOrder.getStoreCouponId(), storeOrder.getPayType(), storeOrder.getDeviceFrom(),
storeOrder.getSource(), storeOrder.getVersion(), storeOrder.getIsMember(), storeOrder.getOrderType(), storeOrder.getWriteOffCode(), storeOrder.getPayCountdownMinute(), storeOrder.getIpAddress(), storeOrder.getMarketId(), storeOrder.getMarketType(), storeOrder.getCreatedAt(), mixId, masterCode
storeOrder.getSource(), "", "", storeOrder.getVersion(), storeOrder.getIsMember(), storeOrder.getOrderType(), storeOrder.getWriteOffCode(), storeOrder.getPayCountdownMinute(), storeOrder.getIpAddress(), storeOrder.getMarketId(), storeOrder.getMarketType(), storeOrder.getCreatedAt(), mixId, masterCode
});
GoblinOrderAttr orderAttr = preParam.getOrderAttr();
sqlDataAttr.add(new Object[]{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment