package playback import ( "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tcs-iptv/tcs/internal/model" ) func ev(ma, plat string, t model.PlaybackEventType, rev int64) model.PlaybackEvent { return model.PlaybackEvent{MACode: ma, PlatformID: plat, EventType: t, RevenueCent: rev} } func TestIngestAndSummary(t *testing.T) { s := NewStore() ma := "MA.156.8531.6101/WD/20260000001" n := s.Ingest([]model.PlaybackEvent{ ev(ma, "CT-SX", model.EventPlay, 0), ev(ma, "CT-SX", model.EventComplete, 1500), // 完播且付费 15.00 元 ev(ma, "CM-SX", model.EventPlay, 0), ev(ma, "CM-SX", model.EventPurchase, 990), // 购买 9.90 元 }) assert.Equal(t, 4, n) sum := s.Summary(ma) assert.Equal(t, int64(2), sum.TotalPlays) assert.Equal(t, int64(1), sum.TotalComplete) assert.Equal(t, int64(2490), sum.TotalRevenue) // 1500+990 assert.Equal(t, int64(1500), sum.ByPlatform["CT-SX"].RevenueCent) assert.Equal(t, int64(990), sum.ByPlatform["CM-SX"].RevenueCent) } func TestIngestSkipsEmptyMA(t *testing.T) { s := NewStore() n := s.Ingest([]model.PlaybackEvent{{MACode: ""}, ev("MA-1", "P", model.EventPlay, 0)}) assert.Equal(t, 1, n) } func TestComputeSettlement_SplitExact(t *testing.T) { s := NewStore() ma := "MA-1" s.Ingest([]model.PlaybackEvent{ev(ma, "P", model.EventPurchase, 10000)}) // 100.00 元 st, err := s.ComputeSettlement(ma, "2026-06", model.DefaultShareConfig()) require.NoError(t, err) assert.Equal(t, int64(10000), st.TotalRevenue) assert.Equal(t, int64(6000), st.CPShare) // 60% assert.Equal(t, int64(3400), st.PlatformShare) // 34% assert.Equal(t, int64(600), st.HubFee) // 6% // 三方之和精确等于总额(无丢分) assert.Equal(t, st.TotalRevenue, st.CPShare+st.PlatformShare+st.HubFee) assert.Equal(t, "链上可信播放数据", st.DataSource) } func TestComputeSettlement_RoundingNoLoss(t *testing.T) { s := NewStore() ma := "MA-1" s.Ingest([]model.PlaybackEvent{ev(ma, "P", model.EventPurchase, 9999)}) // 故意取整有余数 st, err := s.ComputeSettlement(ma, "2026-06", model.DefaultShareConfig()) require.NoError(t, err) // 服务费取余数兜底,保证不丢分 assert.Equal(t, st.TotalRevenue, st.CPShare+st.PlatformShare+st.HubFee) } func TestComputeSettlement_BadConfig(t *testing.T) { s := NewStore() _, err := s.ComputeSettlement("MA-1", "2026-06", model.RevenueShareConfig{CPShareBp: 5000}) assert.Error(t, err, "比例合计不等于 10000bp 应报错") }