package com.talentcard.server.service; import static org.assertj.core.api.Assertions.assertThat; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; 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; /** * 商户首页统计卡片的取数口径。 * *

「交易总额」是商户首页最显眼的数字,口径必须是**已支付且已核销**的订单实付金额: * 未核销的订单钱还扣在通道的延迟户里,核销后才分账给商户,把它算进交易总额等于告诉商户 * 他已经收到了还没到手的钱。 * *

另一个必守的性质是**退款受理后首页立刻回落**。人才端的退款受理成功只把订单置为「退款中」, * 通道的最终结果要等对账任务或下一次读订单才收敛(最长十分钟),中间这段时间订单还是 * {@code order_status = 1}。所以统计口径不能依赖订单状态收敛,必须靠「是否核销」把这类订单挡在外面。 */ @SpringBootTest @ActiveProfiles("test") class MerchantSettlementStatisticsServiceTests { @Autowired private JdbcTemplate jdbc; @Autowired private MerchantSettlementStatisticsService service; private Long merchantId; private Long talentId; @BeforeEach void prepareMerchant() { String suffix = String.valueOf(System.nanoTime()); jdbc.update("insert into merchant(merchant_name, status, can_login_merchant_app, deleted) values (?, 1, 1, 0)", "首页统计测试商户 " + suffix); merchantId = jdbc.queryForObject("select max(id) from merchant", Long.class); jdbc.update("insert into talent_user(openid, name, mobile, status, deleted) values (?, ?, ?, 1, 0)", "dashboard-test-" + suffix, "首页统计测试人才", "13800000000"); talentId = jdbc.queryForObject("select max(id) from talent_user", Long.class); } @Test void countsOnlyVerifiedOrdersInDashboardTransactionAmount() { long verifiedPayAmount = 1000L; // 已支付且已核销:钱已经确认分账给商户,计入。 insertOrder("VER", 1, 1, 0, verifiedPayAmount); // 已支付但未核销:钱还在延迟户,未核销就不算。 insertOrder("UNV", 1, 0, 0, 2000L); // 已支付、未核销、退款受理中:人才端刚点了退款,通道结果还没收敛,首页必须立刻回落。 insertOrder("REF", 1, 0, 1, 4000L); Map cards = service.dashboardCards(merchantId); assertThat(((Number) cards.get("transactionAmountCents")).longValue()).isEqualTo(verifiedPayAmount); } private void insertOrder(String marker, int orderStatus, int verifyStatus, int refundStatus, long payAmount) { LocalDateTime now = LocalDateTime.now(); jdbc.update(""" insert into benefit_order(order_no, order_type, merchant_id, talent_id, product_name_snapshot, order_amount, pay_amount, subsidy_amount, order_status, verify_status, refund_status, created_at, updated_at, deleted) values (?, 'GROUP_BUY', ?, ?, ?, ?, ?, 0, ?, ?, ?, ?, ?, 0) """, "DASHBOARD-" + marker + "-" + System.nanoTime(), merchantId, talentId, "首页统计测试商品", payAmount, payAmount, orderStatus, verifyStatus, refundStatus, Timestamp.valueOf(now), Timestamp.valueOf(now)); } }