OrderSubscriptionMessageDbServiceTest.java
16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
package com.tianting.infoloop.service;
import com.infoloop.tianting.ordersubscriptionmessageservice.CreateOrderSubscriptionMessageRpcRequest;
import com.infoloop.tianting.ordersubscriptionmessageservice.GetUserOrderSubscriptionMessageHistoryRpcRequest;
import java.util.Arrays;
import java.util.List;
import com.tianting.infoloop.App;
import com.tianting.infoloop.model.db.OrderSubscriptionMessageDb;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ActiveProfiles;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@ActiveProfiles("dev")
@SpringBootTest(classes = App.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class OrderSubscriptionMessageDbServiceTest {
@Autowired
private JdbcTemplate jdbcTemplate;
@Autowired
private OrderSubscriptionMessageDbService orderSubscriptionMessageDbService;
@BeforeAll
void ensureTable() {
jdbcTemplate.execute(
"CREATE TABLE IF NOT EXISTS order_subscription_message ("
+ "id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',"
+ "enterpriseId INT NOT NULL COMMENT '企业ID',"
+ "dinerId INT DEFAULT NULL COMMENT '订餐用户ID(dinerId)',"
+ "openId VARCHAR(255) NOT NULL COMMENT '微信用户OpenID',"
+ "templateId VARCHAR(255) NOT NULL COMMENT '订阅消息模板ID',"
+ "jumpPath VARCHAR(255) DEFAULT NULL COMMENT '跳转路径(小程序 path)',"
+ "orderPeriodStartDate DATETIME DEFAULT NULL COMMENT '关联的订餐周期开始时间(精确到秒)',"
+ "orderPeriodEndDate DATETIME DEFAULT NULL COMMENT '关联的订餐周期结束时间(精确到秒)',"
+ "createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',"
+ "updatedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',"
+ "isDeleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否删除;0:未删除,1:已删除',"
+ "PRIMARY KEY (id),"
+ "KEY idx_enterprise_id (enterpriseId)"
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订餐订阅消息授权表';");
// 兼容本地已存在的旧表结构(修改字段类型为 DATETIME,精确到秒)
Integer startDateType = jdbcTemplate.queryForObject(
"SELECT COUNT(1) FROM information_schema.COLUMNS "
+ "WHERE table_schema = DATABASE() "
+ "AND table_name = 'order_subscription_message' "
+ "AND column_name = 'orderPeriodStartDate' "
+ "AND data_type IN ('date', 'bigint')",
Integer.class);
if (startDateType != null && startDateType > 0) {
// 如果字段是 bigint,需要先清空数据或转换数据,这里先清空(测试环境)
jdbcTemplate.update("UPDATE order_subscription_message SET orderPeriodStartDate = NULL WHERE orderPeriodStartDate IS NOT NULL");
jdbcTemplate.execute(
"ALTER TABLE order_subscription_message "
+ "MODIFY COLUMN orderPeriodStartDate DATETIME DEFAULT NULL COMMENT '关联的订餐周期开始时间(精确到秒)'");
}
Integer endDateExists = jdbcTemplate.queryForObject(
"SELECT COUNT(1) FROM information_schema.COLUMNS "
+ "WHERE table_schema = DATABASE() "
+ "AND table_name = 'order_subscription_message' "
+ "AND column_name = 'orderPeriodEndDate'",
Integer.class);
if (endDateExists == null || endDateExists == 0) {
jdbcTemplate.execute(
"ALTER TABLE order_subscription_message "
+ "ADD COLUMN orderPeriodEndDate DATETIME DEFAULT NULL COMMENT '关联的订餐周期结束时间(精确到秒)' "
+ "AFTER orderPeriodStartDate");
} else {
Integer endDateType = jdbcTemplate.queryForObject(
"SELECT COUNT(1) FROM information_schema.COLUMNS "
+ "WHERE table_schema = DATABASE() "
+ "AND table_name = 'order_subscription_message' "
+ "AND column_name = 'orderPeriodEndDate' "
+ "AND data_type IN ('date', 'bigint')",
Integer.class);
if (endDateType != null && endDateType > 0) {
// 如果字段是 bigint,需要先清空数据或转换数据,这里先清空(测试环境)
jdbcTemplate.update("UPDATE order_subscription_message SET orderPeriodEndDate = NULL WHERE orderPeriodEndDate IS NOT NULL");
jdbcTemplate.execute(
"ALTER TABLE order_subscription_message "
+ "MODIFY COLUMN orderPeriodEndDate DATETIME DEFAULT NULL COMMENT '关联的订餐周期结束时间(精确到秒)'");
}
}
}
@Test
void shouldCreateAndQueryHistory() {
final String openId = "openId_test_junit_001";
// clean
jdbcTemplate.update("DELETE FROM order_subscription_message WHERE enterpriseId=? AND openId=?", 1, openId);
// create
CreateOrderSubscriptionMessageRpcRequest createReq = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_junit_001")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1738512000000L) // 2025-02-03 00:00:00 (毫秒时间戳,转换为 LocalDateTime)
.setOrderPeriodEndDate(1739030400000L) // 2025-02-09 00:00:00 (毫秒时间戳,转换为 LocalDateTime)
.build();
OrderSubscriptionMessageDb created = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq);
assertThat(created.getId()).isNotNull();
assertThat(created.getEnterpriseId()).isEqualTo(1);
assertThat(created.getDinerId()).isEqualTo(100);
assertThat(created.getJumpPath()).isEqualTo("/pages/order/index");
assertThat(created.getOrderPeriodEndDate()).isNotNull();
// query history
GetUserOrderSubscriptionMessageHistoryRpcRequest historyReq = GetUserOrderSubscriptionMessageHistoryRpcRequest.newBuilder()
.setEnterpriseId(1)
.setOpenId(openId)
.setOrderPeriodStartDate(0)
.build();
List<OrderSubscriptionMessageDb> list = orderSubscriptionMessageDbService.getUserOrderSubscriptionMessageHistory(historyReq);
assertThat(list).isNotEmpty();
assertThat(list.get(0).getOpenId()).isEqualTo(openId);
assertThat(list.get(0).getJumpPath()).isEqualTo("/pages/order/index");
assertThat(list.get(0).getOrderPeriodEndDate()).isNotNull();
}
@Test
void shouldQueryByOrderPeriodStartDateWithGreaterEqual() {
final String openId = "openId_test_junit_date_query";
// clean
jdbcTemplate.update("DELETE FROM order_subscription_message WHERE enterpriseId=? AND openId=?", 1, openId);
// 创建多条不同开始时间的记录
// 记录1: 2025-02-03 00:00:00
CreateOrderSubscriptionMessageRpcRequest createReq1 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_date_1")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1738512000000L) // 2025-02-03 00:00:00
.setOrderPeriodEndDate(1739030400000L) // 2025-02-09 00:00:00
.build();
OrderSubscriptionMessageDb created1 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq1);
// 记录2: 2025-02-10 00:00:00 (晚于记录1)
CreateOrderSubscriptionMessageRpcRequest createReq2 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_date_2")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1739116800000L) // 2025-02-10 00:00:00
.setOrderPeriodEndDate(1739635200000L) // 2025-02-16 00:00:00
.build();
OrderSubscriptionMessageDb created2 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq2);
// 记录3: 2025-01-27 00:00:00 (早于记录1)
CreateOrderSubscriptionMessageRpcRequest createReq3 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_date_3")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1737907200000L) // 2025-01-27 00:00:00
.setOrderPeriodEndDate(1738425600000L) // 2025-02-02 00:00:00
.build();
OrderSubscriptionMessageDb created3 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq3);
// 记录4: 2025-02-03 12:00:00 (等于记录1的日期,但时间更晚)
CreateOrderSubscriptionMessageRpcRequest createReq4 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_date_4")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1738555200000L) // 2025-02-03 12:00:00
.setOrderPeriodEndDate(1739073600000L) // 2025-02-09 12:00:00
.build();
OrderSubscriptionMessageDb created4 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq4);
// 测试1: 查询 orderPeriodStartDate >= 2025-02-03 00:00:00
// 应该返回: 记录1(等于), 记录2(大于), 记录4(大于)
// 不应该返回: 记录3(小于)
GetUserOrderSubscriptionMessageHistoryRpcRequest historyReq = GetUserOrderSubscriptionMessageHistoryRpcRequest.newBuilder()
.setEnterpriseId(1)
.setOpenId(openId)
.setOrderPeriodStartDate(1738512000000L) // 2025-02-03 00:00:00
.build();
List<OrderSubscriptionMessageDb> list = orderSubscriptionMessageDbService.getUserOrderSubscriptionMessageHistory(historyReq);
// 验证返回的记录数量:应该包含记录1、记录2、记录4,共3条
assertThat(list.size()).isEqualTo(3);
// 验证所有返回的记录的开始时间都 >= 2025-02-03 00:00:00
java.time.LocalDateTime threshold = java.time.Instant.ofEpochMilli(1738512000000L)
.atZone(java.time.ZoneId.systemDefault())
.toLocalDateTime();
for (OrderSubscriptionMessageDb db : list) {
assertThat(db.getOrderPeriodStartDate()).isNotNull();
assertThat(db.getOrderPeriodStartDate().isAfter(threshold) || db.getOrderPeriodStartDate().isEqual(threshold))
.as("开始时间应该 >= 2025-02-03 00:00:00,实际: %s", db.getOrderPeriodStartDate())
.isTrue();
}
// 验证包含记录1(等于)
assertThat(list.stream().anyMatch(db -> db.getId().equals(created1.getId()))).isTrue();
// 验证包含记录2(大于)
assertThat(list.stream().anyMatch(db -> db.getId().equals(created2.getId()))).isTrue();
// 验证包含记录4(大于,同一天但时间更晚)
assertThat(list.stream().anyMatch(db -> db.getId().equals(created4.getId()))).isTrue();
// 验证不包含记录3(小于)
assertThat(list.stream().anyMatch(db -> db.getId().equals(created3.getId()))).isFalse();
// 测试2: 查询 orderPeriodStartDate >= 2025-02-10 00:00:00
// 应该只返回: 记录2(等于)
GetUserOrderSubscriptionMessageHistoryRpcRequest historyReq2 = GetUserOrderSubscriptionMessageHistoryRpcRequest.newBuilder()
.setEnterpriseId(1)
.setOpenId(openId)
.setOrderPeriodStartDate(1739116800000L) // 2025-02-10 00:00:00
.build();
List<OrderSubscriptionMessageDb> list2 = orderSubscriptionMessageDbService.getUserOrderSubscriptionMessageHistory(historyReq2);
// 验证只返回记录2
assertThat(list2.size()).isEqualTo(1);
assertThat(list2.get(0).getId()).isEqualTo(created2.getId());
}
@Test
void shouldBatchDeleteByIds() {
final String openId = "openId_test_junit_delete";
// clean
jdbcTemplate.update("DELETE FROM order_subscription_message WHERE enterpriseId=? AND openId=?", 1, openId);
// create multiple records
CreateOrderSubscriptionMessageRpcRequest createReq1 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_junit_delete_1")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1738512000000L)
.setOrderPeriodEndDate(1739030400000L)
.build();
CreateOrderSubscriptionMessageRpcRequest createReq2 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_junit_delete_2")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1738512000000L)
.setOrderPeriodEndDate(1739030400000L)
.build();
OrderSubscriptionMessageDb created1 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq1);
OrderSubscriptionMessageDb created2 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq2);
List<Long> ids = Arrays.asList(created1.getId(), created2.getId());
// verify records exist
List<OrderSubscriptionMessageDb> beforeDelete = orderSubscriptionMessageDbService.getUserOrderSubscriptionMessageHistory(
GetUserOrderSubscriptionMessageHistoryRpcRequest.newBuilder()
.setEnterpriseId(1)
.setOpenId(openId)
.setOrderPeriodStartDate(0)
.build());
assertThat(beforeDelete.size()).isGreaterThanOrEqualTo(2);
// batch delete (逻辑删除)
int affectedRows = orderSubscriptionMessageDbService.batchDeleteByIds(ids, 1);
assertThat(affectedRows).isEqualTo(2);
// verify deleted - 逻辑删除后查询不到
List<OrderSubscriptionMessageDb> afterDelete = orderSubscriptionMessageDbService.getUserOrderSubscriptionMessageHistory(
GetUserOrderSubscriptionMessageHistoryRpcRequest.newBuilder()
.setEnterpriseId(1)
.setOpenId(openId)
.setOrderPeriodStartDate(0)
.build());
assertThat(afterDelete.size()).isLessThan(beforeDelete.size());
// verify deleted - 但数据库里还存在(isDeleted=1)
Integer count = jdbcTemplate.queryForObject(
"SELECT COUNT(1) FROM order_subscription_message WHERE id IN (?,?) AND isDeleted=1",
Integer.class,
created1.getId(), created2.getId());
assertThat(count).isEqualTo(2);
}
@Test
void shouldBatchPhysicalDeleteByIds() {
final String openId = "openId_test_junit_physical_delete";
// clean
jdbcTemplate.update("DELETE FROM order_subscription_message WHERE enterpriseId=? AND openId=?", 1, openId);
// create multiple records
CreateOrderSubscriptionMessageRpcRequest createReq1 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_junit_physical_delete_1")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1738512000000L)
.setOrderPeriodEndDate(1739030400000L)
.build();
CreateOrderSubscriptionMessageRpcRequest createReq2 = CreateOrderSubscriptionMessageRpcRequest.newBuilder()
.setEnterpriseId(1)
.setDinerId(100)
.setOpenId(openId)
.setTemplateId("template_test_junit_physical_delete_2")
.setJumpPath("/pages/order/index")
.setOrderPeriodStartDate(1738512000000L)
.setOrderPeriodEndDate(1739030400000L)
.build();
OrderSubscriptionMessageDb created1 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq1);
OrderSubscriptionMessageDb created2 = orderSubscriptionMessageDbService.createOrderSubscriptionMessage(createReq2);
List<Long> ids = Arrays.asList(created1.getId(), created2.getId());
// batch physical delete
int affectedRows = orderSubscriptionMessageDbService.batchPhysicalDeleteByIds(ids, 1);
assertThat(affectedRows).isEqualTo(2);
// verify deleted - 物理删除后数据库里也不存在
Integer count = jdbcTemplate.queryForObject(
"SELECT COUNT(1) FROM order_subscription_message WHERE id IN (?,?)",
Integer.class,
created1.getId(), created2.getId());
assertThat(count).isEqualTo(0);
}
}