feat: 推广 V3.5 实时氢耗并完善导出

This commit is contained in:
lingniu
2026-09-04 15:42:02 +08:00
parent a26179c8fe
commit e402eb5e60
53 changed files with 2855 additions and 320 deletions
@@ -547,6 +547,7 @@ type countingStore struct {
vehiclesCalls int
vehicleRealtimeCalls int
overviewBatchCalls int
lastOverviewBatchQuery VehicleOverviewBatchQuery
lastVehicleQuery url.Values
lastRealtimeQuery url.Values
lastHistoryQuery url.Values
@@ -1010,6 +1011,7 @@ func TestVehicleSourcePolicyUpdateRequiresAdminAndUsesOptimisticVersion(t *testi
func (s *countingStore) VehicleServiceOverviews(ctx context.Context, query VehicleOverviewBatchQuery) (Page[VehicleServiceOverview], error) {
s.overviewBatchCalls++
s.lastOverviewBatchQuery = query
return s.MockStore.VehicleServiceOverviews(ctx, query)
}
@@ -1046,6 +1048,26 @@ func TestVehicleServiceOverviewsUsesBatchDataPath(t *testing.T) {
}
}
func TestCustomerVehicleServiceOverviewsStayInsideGrantedVINScope(t *testing.T) {
store := newCountingStore()
service := NewService(store)
ctx := WithPrincipal(context.Background(), Principal{
Name: "客户甲", Role: "customer", UserType: "customer", VehicleVINs: []string{"LB9A32A24R0LS1426"},
})
page, err := service.VehicleServiceOverviews(ctx, VehicleOverviewBatchQuery{
Keywords: []string{"粤AG18312", "LMRKH9AC2R1004087"}, Limit: 200,
})
if err != nil {
t.Fatalf("customer batch lookup returned error: %v", err)
}
if len(store.lastOverviewBatchQuery.ScopeVINs) != 1 || store.lastOverviewBatchQuery.ScopeVINs[0] != "LB9A32A24R0LS1426" {
t.Fatalf("customer grant scope was not passed to batch store: %+v", store.lastOverviewBatchQuery.ScopeVINs)
}
if page.Total != 2 || len(page.Items) != 2 || page.Items[0].VIN != "LB9A32A24R0LS1426" || page.Items[1].VIN != "" {
t.Fatalf("batch lookup must preserve input order without exposing ungranted vehicles: %+v", page)
}
}
func TestVehicleServiceSummaryCountsProtocolOnlineByProtocolSlot(t *testing.T) {
service := NewService(NewMockStore())
summary, err := service.VehicleServiceSummary(context.Background())