Jiaqi Xia

Merge branch 'feature/nongxinweixinnotice' into 'master'

Feature/nongxinweixinnotice



See merge request !7
package com.tianting.infoloop.mapper;
import com.tianting.infoloop.inject.MyBaseMapper;
import com.tianting.infoloop.model.db.OrderSubscriptionMessageDb;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface OrderSubscriptionMessageMapper extends MyBaseMapper<OrderSubscriptionMessageDb> {
/**
* 批量物理删除(绕过逻辑删除)
*/
@Delete("<script>" +
"DELETE FROM order_subscription_message " +
"WHERE enterpriseId = #{enterpriseId} " +
"AND id IN " +
"<foreach collection='ids' item='id' open='(' separator=',' close=')'>" +
"#{id}" +
"</foreach>" +
"</script>")
int physicalDeleteByIds(@Param("ids") List<Long> ids, @Param("enterpriseId") int enterpriseId);
}
package com.tianting.infoloop.model.db;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* order subscription message DB
* @TableName order_subscription_message
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
@TableName(value = "meal_order_subscription_messages")
public class OrderSubscriptionMessageDb extends Model<OrderSubscriptionMessageDb> {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 企业ID
*/
private Integer enterpriseId;
/**
* 订餐用户ID(dinerId)
*/
private Integer dinerId;
/**
* 微信用户OpenID
*/
private String openId;
/**
* 订阅消息模板ID
*/
private String templateId;
/**
* 跳转路径(小程序 path)
*/
private String jumpPath;
/**
* 关联的订餐周期开始时间(精确到秒)
*/
private LocalDateTime orderPeriodStartDate;
/**
* 关联的订餐周期结束时间(精确到秒)
*/
private LocalDateTime orderPeriodEndDate;
/**
* 授权时间(创建时间)
*/
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdAt;
/**
* 更新时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedAt;
/**
* 授权状态,0-待使用(已授权但未发送),1-已使用(已发送,逻辑删除)
*/
@TableLogic
private Boolean isDeleted;
}
package com.tianting.infoloop.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.infoloop.tianting.mealorderservice.CreateOrderSubscriptionMessageRpcRequest;
import com.infoloop.tianting.mealorderservice.GetUserOrderSubscriptionMessageHistoryRpcRequest;
import com.tianting.infoloop.model.db.OrderSubscriptionMessageDb;
import java.util.List;
public interface OrderSubscriptionMessageDbService extends IService<OrderSubscriptionMessageDb> {
OrderSubscriptionMessageDb createOrderSubscriptionMessage(CreateOrderSubscriptionMessageRpcRequest request);
List<OrderSubscriptionMessageDb> getUserOrderSubscriptionMessageHistory(GetUserOrderSubscriptionMessageHistoryRpcRequest request);
/**
* 批量逻辑删除授权记录(表示已使用)
* @param ids 要删除的记录ID列表
* @param enterpriseId 企业ID
* @return 受影响的行数
*/
int batchDeleteByIds(java.util.List<Long> ids, int enterpriseId);
/**
* 批量物理删除授权记录
* @param ids 要删除的记录ID列表
* @param enterpriseId 企业ID
* @return 受影响的行数
*/
int batchPhysicalDeleteByIds(java.util.List<Long> ids, int enterpriseId);
/**
* 查询待发送的订阅消息(未删除的记录)
* @param enterpriseId 企业ID
* @return 待发送的订阅消息列表
*/
List<OrderSubscriptionMessageDb> queryPendingMessages(int enterpriseId);
}
package com.tianting.infoloop.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.infoloop.tianting.mealorderservice.CreateOrderSubscriptionMessageRpcRequest;
import com.infoloop.tianting.mealorderservice.GetUserOrderSubscriptionMessageHistoryRpcRequest;
import com.tianting.infoloop.mapper.OrderSubscriptionMessageMapper;
import com.tianting.infoloop.model.db.OrderSubscriptionMessageDb;
import com.tianting.infoloop.service.OrderSubscriptionMessageDbService;
import com.tianting.infoloop.utils.exception.ErrorCodeConstants;
import com.tianting.infoloop.utils.exception.ServiceExceptionUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class OrderSubscriptionMessageDbServiceImpl extends ServiceImpl<OrderSubscriptionMessageMapper, OrderSubscriptionMessageDb> implements OrderSubscriptionMessageDbService {
@Override
public OrderSubscriptionMessageDb createOrderSubscriptionMessage(CreateOrderSubscriptionMessageRpcRequest request) {
OrderSubscriptionMessageDb orderSubscriptionMessageDb = new OrderSubscriptionMessageDb();
orderSubscriptionMessageDb.setEnterpriseId(request.getEnterpriseId());
if (request.getDinerId() != 0) {
orderSubscriptionMessageDb.setDinerId(request.getDinerId());
}
orderSubscriptionMessageDb.setOpenId(request.getOpenId());
orderSubscriptionMessageDb.setTemplateId(request.getTemplateId());
if (!request.getJumpPath().isEmpty()) {
orderSubscriptionMessageDb.setJumpPath(request.getJumpPath());
}
// 转换时间戳为LocalDateTime(精确到秒),与项目中其他时间字段保持一致
LocalDateTime orderPeriodStartDate = Instant.ofEpochMilli(request.getOrderPeriodStartDate())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
orderSubscriptionMessageDb.setOrderPeriodStartDate(orderPeriodStartDate);
if (request.getOrderPeriodEndDate() > 0) {
LocalDateTime orderPeriodEndDate = Instant.ofEpochMilli(request.getOrderPeriodEndDate())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
orderSubscriptionMessageDb.setOrderPeriodEndDate(orderPeriodEndDate);
}
boolean res = this.save(orderSubscriptionMessageDb);
if (!res) {
log.error("创建订阅消息授权记录失败, request: {}", request);
throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_GEN_FAIL);
}
return orderSubscriptionMessageDb;
}
@Override
public List<OrderSubscriptionMessageDb> getUserOrderSubscriptionMessageHistory(GetUserOrderSubscriptionMessageHistoryRpcRequest request) {
LambdaQueryWrapper<OrderSubscriptionMessageDb> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderSubscriptionMessageDb::getEnterpriseId, request.getEnterpriseId());
queryWrapper.eq(OrderSubscriptionMessageDb::getOpenId, request.getOpenId());
// 如果传入了 orderPeriodStartDate,查询大于等于该值的记录
if (request.getOrderPeriodStartDate() > 0) {
LocalDateTime orderPeriodStartDate = Instant.ofEpochMilli(request.getOrderPeriodStartDate())
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
queryWrapper.ge(OrderSubscriptionMessageDb::getOrderPeriodStartDate, orderPeriodStartDate);
}
queryWrapper.orderByDesc(OrderSubscriptionMessageDb::getCreatedAt);
return this.list(queryWrapper);
}
@Override
public int batchDeleteByIds(java.util.List<Long> ids, int enterpriseId) {
if (ids == null || ids.isEmpty()) {
return 0;
}
LambdaQueryWrapper<OrderSubscriptionMessageDb> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderSubscriptionMessageDb::getEnterpriseId, enterpriseId);
queryWrapper.in(OrderSubscriptionMessageDb::getId, ids);
// 逻辑删除(使用 MyBatis-Plus 的 @TableLogic)
return this.remove(queryWrapper) ? ids.size() : 0;
}
@Override
public int batchPhysicalDeleteByIds(java.util.List<Long> ids, int enterpriseId) {
if (ids == null || ids.isEmpty()) {
return 0;
}
// 物理删除(使用 Mapper 中的 SQL,绕过逻辑删除)
return this.baseMapper.physicalDeleteByIds(ids, enterpriseId);
}
@Override
public List<OrderSubscriptionMessageDb> queryPendingMessages(int enterpriseId) {
LambdaQueryWrapper<OrderSubscriptionMessageDb> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderSubscriptionMessageDb::getEnterpriseId, enterpriseId)
.eq(OrderSubscriptionMessageDb::getIsDeleted, false)
.orderByAsc(OrderSubscriptionMessageDb::getCreatedAt);
return this.list(queryWrapper);
}
}
......@@ -63,6 +63,13 @@ service MealOrderServiceRpc {
rpc batchCreateDinerMealSuspensionRecords(BatchCreateDinerMealSuspensionRecordsRpcRequest) returns (BatchCreateDinerMealSuspensionRecordsRpcResponse);
rpc updateDinerMealSuspensionRecord(UpdateDinerMealSuspensionRecordRpcRequest) returns (UpdateDinerMealSuspensionRecordRpcResponse);
rpc deleteDinerMealSuspensionRecordsByIds(DeleteDinerMealSuspensionRecordsByIdsRpcRequest) returns (DeleteDinerMealSuspensionRecordsRpcResponse);
// 订餐订阅消息相关服务
rpc CreateOrderSubscriptionMessage (CreateOrderSubscriptionMessageRpcRequest) returns (CreateOrderSubscriptionMessageRpcResponse) {}
rpc GetUserOrderSubscriptionMessageHistory (GetUserOrderSubscriptionMessageHistoryRpcRequest) returns (GetUserOrderSubscriptionMessageHistoryRpcResponse) {}
rpc BatchDeleteOrderSubscriptionMessagesByIds (BatchDeleteOrderSubscriptionMessagesByIdsRpcRequest) returns (BatchDeleteOrderSubscriptionMessagesByIdsRpcResponse) {}
rpc BatchPhysicalDeleteOrderSubscriptionMessagesByIds (BatchPhysicalDeleteOrderSubscriptionMessagesByIdsRpcRequest) returns (BatchPhysicalDeleteOrderSubscriptionMessagesByIdsRpcResponse) {}
rpc QueryPendingOrderSubscriptionMessages (QueryPendingOrderSubscriptionMessagesRpcRequest) returns (QueryPendingOrderSubscriptionMessagesRpcResponse) {}
}
enum MealOrderOrderMethodEnum {
......@@ -955,3 +962,76 @@ message BatchCreateDinerMealSuspensionRecordsRpcResponse {
bool isCreated = 1;
repeated int32 ids = 2;
}
// 订餐订阅消息相关消息定义
message CreateOrderSubscriptionMessageRpcRequest {
int32 enterpriseId = 1;
int32 dinerId = 2;
string openId = 3;
string templateId = 4;
int64 orderPeriodStartDate = 5; // Unix 时间戳(毫秒),精确到秒
string jumpPath = 6; // 跳转路径(小程序 path),可选
int64 orderPeriodEndDate = 7; // Unix 时间戳(毫秒),精确到秒,可选
}
message CreateOrderSubscriptionMessageRpcResponse {
int64 id = 1;
}
message GetUserOrderSubscriptionMessageHistoryRpcRequest {
int32 enterpriseId = 1;
string openId = 2;
int64 orderPeriodStartDate = 3; // Unix 时间戳(毫秒),精确到秒,可选,如果传入则查询大于等于该值的记录
}
message OrderSubscriptionMessageRpcResponse {
int64 id = 1;
int64 orderPeriodStartDate = 2; // Unix 时间戳(毫秒),精确到秒
int64 createdAt = 3; // Unix 时间戳(毫秒)
bool isDeleted = 4;
string jumpPath = 5; // 跳转路径(小程序 path),可选
int64 orderPeriodEndDate = 6; // Unix 时间戳(毫秒),精确到秒,可选
}
message GetUserOrderSubscriptionMessageHistoryRpcResponse {
repeated OrderSubscriptionMessageRpcResponse response = 1;
}
message BatchDeleteOrderSubscriptionMessagesByIdsRpcRequest {
int32 enterpriseId = 1;
repeated int64 ids = 2; // 要删除的记录ID列表
}
message BatchDeleteOrderSubscriptionMessagesByIdsRpcResponse {
int32 affectedRows = 1; // 受影响的行数
}
message BatchPhysicalDeleteOrderSubscriptionMessagesByIdsRpcRequest {
int32 enterpriseId = 1;
repeated int64 ids = 2; // 要删除的记录ID列表
}
message BatchPhysicalDeleteOrderSubscriptionMessagesByIdsRpcResponse {
int32 affectedRows = 1; // 受影响的行数
}
// 查询待发送的订阅消息(未删除的记录)
message QueryPendingOrderSubscriptionMessagesRpcRequest {
int32 enterpriseId = 1;
}
message PendingOrderSubscriptionMessageRpcResponse {
int64 id = 1;
int32 enterpriseId = 2;
int32 dinerId = 3;
string openId = 4;
string templateId = 5;
int64 orderPeriodStartDate = 6;
string jumpPath = 7;
int64 orderPeriodEndDate = 8;
int64 createdAt = 9;
}
message QueryPendingOrderSubscriptionMessagesRpcResponse {
repeated PendingOrderSubscriptionMessageRpcResponse responses = 1;
}
......