feat:消息推送查询
fix:消费机库存显示更改
This commit is contained in:
1 parent
bf5db4bbb9
commit
96abe868ef
8 files changed
+136
-14
No files matched your search
+2
-2
@@ -93,7 +93,7 @@ public class DailyMenuAppVO {
|
||||
|
||||
/**
|
||||
* 当前可售库存。
|
||||
* <p>App/移动端:移动端可预订剩余;AD:总库存 − 移动端已预订。字段名保持 stock 兼容旧客户端。
|
||||
* <p>App/移动端:移动端可预订剩余;AD:剩余总库存(总库存 − 线上已订 − 线下已售)。字段名保持 stock 兼容旧客户端。
|
||||
*/
|
||||
private Integer stock;
|
||||
|
||||
@@ -112,7 +112,7 @@ public class DailyMenuAppVO {
|
||||
/** 移动端可预订剩余 */
|
||||
private Integer remainOnlineStock;
|
||||
|
||||
/** App:剩余总库存;AD:与 stock 同为 总库存−移动端已预订 */
|
||||
/** 剩余总库存(AD 与 stock 同值;管理端 remainStock 同口径) */
|
||||
private Integer remainOfflineStock;
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -385,7 +385,7 @@ public class CanteenDailyMenuServiceImpl extends ServiceImpl<CanteenDailyMenuMap
|
||||
public List<DailyMenuAppVO> getCanteenMenuListScope(String day, Integer hourType, Long categoryId, Long merchantId) {
|
||||
List<DailyMenuAppVO> list = baseMapper.getCanteenMenuList(day, hourType, categoryId, merchantId, DataScope.of());
|
||||
fillDailyMenuAppCombo(list);
|
||||
// 安卓消费机:stock = 当日线下剩余
|
||||
// 安卓消费机:stock = 剩余总库存(与管理端 remainStock、线下扣减边界同口径)
|
||||
LocalDate mealDate = null;
|
||||
try {
|
||||
mealDate = day == null ? null : LocalDate.parse(day);
|
||||
|
||||
+7
-7
@@ -30,7 +30,7 @@ import java.util.stream.Collectors;
|
||||
* <pre>
|
||||
* 剩余总库存 = max(0, 总库存 − 移动端已预订 − 消费机已销售)
|
||||
* 移动端可预订剩余 = min(移动端上限 − 已预订, 剩余总库存)
|
||||
* AD stock = max(0, 总库存 − 移动端已预订)
|
||||
* AD stock = 剩余总库存(与管理端 remainStock、线下扣减边界同口径)
|
||||
* </pre>
|
||||
* PC 管理端只展示总库存、移动端上限、移动端已订、消费机已售、剩余总库存。
|
||||
* 扣减仍受「剩余总库存」边界约束,防止超卖。
|
||||
@@ -95,7 +95,8 @@ public class CanteenDailyMenuStockSupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* AD 返回的 stock:总库存 − 移动端已预订(不含消费机已售;已售由 offline_sold 单独体现)。
|
||||
* 总库存 − 移动端已预订(不含消费机已售)。
|
||||
* 仅作库存扣减流程的线下游标基线;AD 列表展示已改用 {@link #sharedRemain}。
|
||||
*/
|
||||
public static int adStockOf(Integer totalStock, Integer onlineSold) {
|
||||
return Math.max(0, totalStockOf(totalStock) - soldOrDefault(onlineSold));
|
||||
@@ -126,7 +127,7 @@ public class CanteenDailyMenuStockSupport {
|
||||
applyAppComboLinkedRemain(rows, true);
|
||||
}
|
||||
|
||||
/** 安卓消费机:stock = 总库存 − 移动端已预订 */
|
||||
/** 安卓消费机:stock = 剩余总库存(管理端 remainStock 同口径) */
|
||||
public void fillAdOfflineRemain(List<DailyMenuAppVO> rows, Long merchantId, LocalDate mealDate) {
|
||||
if (CollUtil.isEmpty(rows)) {
|
||||
return;
|
||||
@@ -206,15 +207,14 @@ public class CanteenDailyMenuStockSupport {
|
||||
int offlineSold = soldOrDefault(row.getOfflineSold());
|
||||
int shared = sharedRemain(total, onlineSold, offlineSold);
|
||||
int onlineRemain = onlineRemain(total, mobile, onlineSold, offlineSold);
|
||||
int adStock = adStockOf(total, onlineSold);
|
||||
row.setOnlineStock(mobile);
|
||||
row.setOfflineStock(total);
|
||||
row.setOnlineSold(onlineSold);
|
||||
row.setOfflineSold(offlineSold);
|
||||
row.setRemainOnlineStock(onlineRemain);
|
||||
// AD:remainOfflineStock / stock = 总库存 − 线上已订;App 侧 remainOffline 仍给剩余总库存供参考
|
||||
row.setRemainOfflineStock(stockAsOnline ? shared : adStock);
|
||||
row.setStock(stockAsOnline ? onlineRemain : adStock);
|
||||
// remainOfflineStock = 剩余总库存;stock:App=移动端可订剩余,AD=剩余总库存(与线下扣减边界一致)
|
||||
row.setRemainOfflineStock(shared);
|
||||
row.setStock(stockAsOnline ? onlineRemain : shared);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
package com.bsd.pjcloud.thirdparty.dto.appmessage;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* PC重新推送失败终态投递记录的请求。
|
||||
*/
|
||||
@Data
|
||||
public class AppPushDeliveryRetryDto implements Serializable {
|
||||
|
||||
/** 当前操作的商户ID,用于复核管理员数据范围。 */
|
||||
@NotNull(message = "商户ID不能为空")
|
||||
private Long mchId;
|
||||
|
||||
/** 待重新推送的投递记录ID列表,仅失败终态记录会被重置。 */
|
||||
@NotEmpty(message = "请选择要重新推送的投递记录")
|
||||
@Size(max = 100, message = "单次最多重新推送100条投递记录")
|
||||
private List<Long> deliveryIds;
|
||||
}
|
||||
+3
@@ -23,6 +23,9 @@ public class AppPushDeliveryVo implements Serializable {
|
||||
/** 目标用户ID。 */
|
||||
private Long recipientUserId;
|
||||
|
||||
/** 接收用户姓名,远程用户服务不可用或用户已删除时为空。 */
|
||||
private String recipientName;
|
||||
|
||||
/** 投递状态。 */
|
||||
private String status;
|
||||
|
||||
|
||||
+20
-2
@@ -6,6 +6,7 @@ import com.bsd.pjcloud.common.core.constant.enums.MerchantTypeEnum;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import com.bsd.pjcloud.common.security.util.SecurityUtils;
|
||||
import com.bsd.pjcloud.thirdparty.dto.appmessage.AppPushDeliveryRetryDto;
|
||||
import com.bsd.pjcloud.thirdparty.dto.appmessage.AppPushPolicySaveDto;
|
||||
import com.bsd.pjcloud.thirdparty.dto.appmessage.AppPushTestDto;
|
||||
import com.bsd.pjcloud.thirdparty.service.appmessage.ThirdAppMessageSettingService;
|
||||
@@ -121,6 +122,7 @@ public class ThirdAppMessagePcController {
|
||||
* @param mchId 商户ID
|
||||
* @param status 可选投递状态
|
||||
* @param eventCode 可选事件编码
|
||||
* @param recipientUserId 可选接收用户ID
|
||||
* @return 商户投递记录分页
|
||||
*/
|
||||
@Operation(summary = "分页查询商户业务Push投递记录")
|
||||
@@ -128,9 +130,10 @@ public class ThirdAppMessagePcController {
|
||||
@GetMapping("/deliveries")
|
||||
public R<Page<AppPushDeliveryVo>> pageDeliveries(@ParameterObject Page<?> page, @RequestParam Long mchId,
|
||||
@RequestParam(required = false) String status,
|
||||
@RequestParam(required = false) String eventCode) {
|
||||
@RequestParam(required = false) String eventCode,
|
||||
@RequestParam(required = false) Long recipientUserId) {
|
||||
requireMerchantAccess(mchId);
|
||||
return R.ok(deliveryService.page(page, mchId, status, eventCode));
|
||||
return R.ok(deliveryService.page(page, mchId, status, eventCode, recipientUserId));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,6 +151,21 @@ public class ThirdAppMessagePcController {
|
||||
return R.ok(deliveryService.listAttempts(deliveryId, mchId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 把失败终态的投递记录重置回待投递,由投递扫描任务在数秒内重新推送。
|
||||
*
|
||||
* @param dto 商户与投递记录ID集合
|
||||
* @return 实际重置的记录数量
|
||||
*/
|
||||
@Operation(summary = "重新推送App投递记录")
|
||||
@SysLog("重新推送App投递记录")
|
||||
@PreAuthorize("@pms.hasPermission('wallet_mchManage_setting')")
|
||||
@PostMapping("/deliveries/retry")
|
||||
public R<Integer> retryDeliveries(@Valid @RequestBody AppPushDeliveryRetryDto dto) {
|
||||
requireMerchantAccess(dto.getMchId());
|
||||
return R.ok(deliveryService.retryDeliveries(dto.getMchId(), dto.getDeliveryIds()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询当前部署Push供应商只读状态。
|
||||
*
|
||||
|
||||
+11
-1
@@ -35,9 +35,10 @@ public interface ThirdPushDeliveryService {
|
||||
* @param mchId 商户ID
|
||||
* @param status 可选投递状态
|
||||
* @param eventCode 可选事件编码
|
||||
* @param recipientUserId 可选接收用户ID
|
||||
* @return 商户投递记录分页
|
||||
*/
|
||||
Page<AppPushDeliveryVo> page(Page<?> page, Long mchId, String status, String eventCode);
|
||||
Page<AppPushDeliveryVo> page(Page<?> page, Long mchId, String status, String eventCode, Long recipientUserId);
|
||||
|
||||
/**
|
||||
* 查询指定商户投递任务的供应商调用详情。
|
||||
@@ -48,6 +49,15 @@ public interface ThirdPushDeliveryService {
|
||||
*/
|
||||
List<AppPushDeliveryAttemptVo> listAttempts(Long deliveryId, Long mchId);
|
||||
|
||||
/**
|
||||
* 把失败终态的投递记录重置回待投递,由既有扫描任务在数秒内重新推送。
|
||||
*
|
||||
* @param mchId 商户ID
|
||||
* @param deliveryIds 待重新推送的投递记录ID
|
||||
* @return 实际重置的记录数量,非失败终态或非本商户记录不计入
|
||||
*/
|
||||
int retryDeliveries(Long mchId, List<Long> deliveryIds);
|
||||
|
||||
/**
|
||||
* 返回供应商只读健康状态,不包含部署密钥。
|
||||
*
|
||||
|
||||
+67
-1
@@ -1,9 +1,14 @@
|
||||
package com.bsd.pjcloud.thirdparty.service.impl.appmessage;
|
||||
|
||||
import cn.hutool.core.collection.IterUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.bsd.pjcloud.admin.api.entity.SysUser;
|
||||
import com.bsd.pjcloud.admin.api.feign.RemoteUserService;
|
||||
import com.bsd.pjcloud.common.core.util.R;
|
||||
import com.bsd.pjcloud.common.data.tenant.TenantBroker;
|
||||
import com.bsd.pjcloud.thirdparty.constant.appmessage.AppMessageConstants;
|
||||
import com.bsd.pjcloud.thirdparty.constant.push.ThirdPushBizTypeEnum;
|
||||
@@ -83,6 +88,9 @@ public class ThirdPushDeliveryServiceImpl implements ThirdPushDeliveryService {
|
||||
/** 事务模板,保证任务领取、供应商尝试留痕与最终投递状态在同一数据库事务中提交。 */
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
|
||||
/** UPMS远程用户服务,用于PC列表补齐接收用户姓名。 */
|
||||
private final RemoteUserService remoteUserService;
|
||||
|
||||
/**
|
||||
* 创建一条唯一Push决策;没有有效设备时把原本待投递任务记录为跳过。
|
||||
*
|
||||
@@ -157,23 +165,56 @@ public class ThirdPushDeliveryServiceImpl implements ThirdPushDeliveryService {
|
||||
* @param mchId 商户ID
|
||||
* @param status 可选投递状态
|
||||
* @param eventCode 可选事件编码
|
||||
* @param recipientUserId 可选接收用户ID
|
||||
* @return PC投递记录分页
|
||||
*/
|
||||
@Override
|
||||
public Page<AppPushDeliveryVo> page(Page<?> page, Long mchId, String status, String eventCode) {
|
||||
public Page<AppPushDeliveryVo> page(Page<?> page, Long mchId, String status, String eventCode, Long recipientUserId) {
|
||||
Page<ThirdPushDeliveryEntity> entityPage = deliveryMapper.selectPage(
|
||||
new Page<>(page.getCurrent(), page.getSize()),
|
||||
Wrappers.<ThirdPushDeliveryEntity>lambdaQuery()
|
||||
.eq(ThirdPushDeliveryEntity::getSourceMchId, mchId)
|
||||
.eq(StrUtil.isNotBlank(status), ThirdPushDeliveryEntity::getStatus, status)
|
||||
.eq(StrUtil.isNotBlank(eventCode), ThirdPushDeliveryEntity::getEventCode, eventCode)
|
||||
.eq(recipientUserId != null, ThirdPushDeliveryEntity::getRecipientUserId, recipientUserId)
|
||||
.orderByDesc(ThirdPushDeliveryEntity::getCreateTime)
|
||||
.orderByDesc(ThirdPushDeliveryEntity::getId));
|
||||
Page<AppPushDeliveryVo> result = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
|
||||
result.setRecords(entityPage.getRecords().stream().map(this::toDeliveryVo).toList());
|
||||
fillRecipientNames(result.getRecords());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量补齐投递记录接收用户姓名,远程服务异常或用户已删除不阻断诊断列表。
|
||||
*
|
||||
* @param records 当前页PC投递记录
|
||||
*/
|
||||
private void fillRecipientNames(List<AppPushDeliveryVo> records) {
|
||||
List<Long> userIdList = records.stream().map(AppPushDeliveryVo::getRecipientUserId)
|
||||
.filter(ObjectUtil::isNotEmpty).distinct().toList();
|
||||
if (ObjectUtil.isEmpty(userIdList)) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
R<List<SysUser>> result = remoteUserService.getInnerUserById(userIdList);
|
||||
List<SysUser> userList = result == null || !result.isOk() ? null : result.getData();
|
||||
if (ObjectUtil.isEmpty(userList)) {
|
||||
return;
|
||||
}
|
||||
Map<Long, SysUser> userMap = IterUtil.toMap(userList, SysUser::getUserId);
|
||||
for (AppPushDeliveryVo record : records) {
|
||||
SysUser targetUser = userMap.get(record.getRecipientUserId());
|
||||
if (targetUser == null) {
|
||||
continue;
|
||||
}
|
||||
record.setRecipientName(targetUser.getName());
|
||||
}
|
||||
} catch (Exception exception) {
|
||||
log.warn("投递记录列表补充接收用户姓名失败,errorType:{}", exception.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定商户投递任务的供应商调用详情,先校验任务确实属于该商户。
|
||||
*
|
||||
@@ -196,6 +237,31 @@ public class ThirdPushDeliveryServiceImpl implements ThirdPushDeliveryService {
|
||||
.stream().map(this::toAttemptVo).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 把失败终态的投递记录条件重置回待投递,交由既有扫描任务重新领取处理。
|
||||
*
|
||||
* @param mchId 商户ID
|
||||
* @param deliveryIds 待重新推送的投递记录ID
|
||||
* @return 实际重置的记录数量
|
||||
*/
|
||||
@Override
|
||||
public int retryDeliveries(Long mchId, List<Long> deliveryIds) {
|
||||
if (ObjectUtil.isEmpty(deliveryIds)) {
|
||||
return 0;
|
||||
}
|
||||
return deliveryMapper.update(null, Wrappers.<ThirdPushDeliveryEntity>lambdaUpdate()
|
||||
.set(ThirdPushDeliveryEntity::getStatus, AppMessageConstants.DELIVERY_PENDING)
|
||||
.set(ThirdPushDeliveryEntity::getAttemptCount, 0)
|
||||
.set(ThirdPushDeliveryEntity::getNextRetryTime, null)
|
||||
.set(ThirdPushDeliveryEntity::getFinalProviderCode, null)
|
||||
.set(ThirdPushDeliveryEntity::getLastError, null)
|
||||
.set(ThirdPushDeliveryEntity::getSuccessTime, null)
|
||||
.set(ThirdPushDeliveryEntity::getUpdateTime, LocalDateTime.now())
|
||||
.in(ThirdPushDeliveryEntity::getId, deliveryIds)
|
||||
.eq(ThirdPushDeliveryEntity::getSourceMchId, mchId)
|
||||
.eq(ThirdPushDeliveryEntity::getStatus, AppMessageConstants.DELIVERY_FAILED));
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回全部供应商只读状态。
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user