feat(platform): resolve vehicle detail keyword
This commit is contained in:
@@ -48,6 +48,19 @@ func TestHandlerVehicleDetail(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHandlerVehicleDetailResolvesPlateToVIN(t *testing.T) {
|
||||||
|
handler := NewHandler(NewService(NewMockStore()))
|
||||||
|
rec := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/api/vehicles/detail?vin=粤AG18312", nil)
|
||||||
|
handler.ServeHTTP(rec, req)
|
||||||
|
if rec.Code != http.StatusOK {
|
||||||
|
t.Fatalf("status = %d body=%s", rec.Code, rec.Body.String())
|
||||||
|
}
|
||||||
|
if !strings.Contains(rec.Body.String(), `"vin":"LB9A32A24R0LS1426"`) {
|
||||||
|
t.Fatalf("response should resolve plate to VIN: %s", rec.Body.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestHandlerRealtimeLocations(t *testing.T) {
|
func TestHandlerRealtimeLocations(t *testing.T) {
|
||||||
handler := NewHandler(NewService(NewMockStore()))
|
handler := NewHandler(NewService(NewMockStore()))
|
||||||
rec := httptest.NewRecorder()
|
rec := httptest.NewRecorder()
|
||||||
|
|||||||
@@ -47,22 +47,28 @@ func (s *Service) Vehicles(ctx context.Context, query url.Values) (Page[VehicleR
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) VehicleDetail(ctx context.Context, vin string, protocol string) (VehicleDetail, error) {
|
func (s *Service) VehicleDetail(ctx context.Context, vin string, protocol string) (VehicleDetail, error) {
|
||||||
vin = strings.TrimSpace(vin)
|
keyword := strings.TrimSpace(vin)
|
||||||
protocol = strings.TrimSpace(protocol)
|
protocol = strings.TrimSpace(protocol)
|
||||||
vehicleQuery := url.Values{"keyword": {vin}, "limit": {"10"}}
|
vehicleQuery := url.Values{"keyword": {keyword}, "limit": {"10"}}
|
||||||
realtimeQuery := url.Values{"vin": {vin}, "limit": {"20"}}
|
vehicles, err := s.store.Vehicles(ctx, vehicleQuery)
|
||||||
historyQuery := url.Values{"vin": {vin}, "limit": {"20"}}
|
if err != nil {
|
||||||
rawQuery := RawFrameQuery{VIN: vin, IncludeFields: true, Limit: 10}
|
return VehicleDetail{}, err
|
||||||
mileageQuery := url.Values{"vin": {vin}, "limit": {"20"}}
|
}
|
||||||
|
identity := resolveVehicleIdentity(keyword, vehicles.Items)
|
||||||
|
resolvedVIN := keyword
|
||||||
|
if identity != nil && strings.TrimSpace(identity.VIN) != "" {
|
||||||
|
resolvedVIN = identity.VIN
|
||||||
|
}
|
||||||
|
|
||||||
|
realtimeQuery := url.Values{"vin": {resolvedVIN}, "limit": {"20"}}
|
||||||
|
historyQuery := url.Values{"vin": {resolvedVIN}, "limit": {"20"}}
|
||||||
|
rawQuery := RawFrameQuery{VIN: resolvedVIN, IncludeFields: true, Limit: 10}
|
||||||
|
mileageQuery := url.Values{"vin": {resolvedVIN}, "limit": {"20"}}
|
||||||
if protocol != "" {
|
if protocol != "" {
|
||||||
realtimeQuery.Set("protocol", protocol)
|
realtimeQuery.Set("protocol", protocol)
|
||||||
historyQuery.Set("protocol", protocol)
|
historyQuery.Set("protocol", protocol)
|
||||||
rawQuery.Protocol = protocol
|
rawQuery.Protocol = protocol
|
||||||
}
|
}
|
||||||
vehicles, err := s.store.Vehicles(ctx, vehicleQuery)
|
|
||||||
if err != nil {
|
|
||||||
return VehicleDetail{}, err
|
|
||||||
}
|
|
||||||
realtime, err := s.store.RealtimeLocations(ctx, realtimeQuery)
|
realtime, err := s.store.RealtimeLocations(ctx, realtimeQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return VehicleDetail{}, err
|
return VehicleDetail{}, err
|
||||||
@@ -79,18 +85,8 @@ func (s *Service) VehicleDetail(ctx context.Context, vin string, protocol string
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return VehicleDetail{}, err
|
return VehicleDetail{}, err
|
||||||
}
|
}
|
||||||
var identity *VehicleRow
|
|
||||||
for index := range vehicles.Items {
|
|
||||||
if strings.EqualFold(vehicles.Items[index].VIN, vin) {
|
|
||||||
identity = &vehicles.Items[index]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if identity == nil && len(vehicles.Items) > 0 {
|
|
||||||
identity = &vehicles.Items[0]
|
|
||||||
}
|
|
||||||
return VehicleDetail{
|
return VehicleDetail{
|
||||||
VIN: vin,
|
VIN: resolvedVIN,
|
||||||
Identity: identity,
|
Identity: identity,
|
||||||
Sources: vehicleSources(vehicles.Items, realtime.Items, raw.Items, mileage.Items),
|
Sources: vehicleSources(vehicles.Items, realtime.Items, raw.Items, mileage.Items),
|
||||||
Realtime: realtime.Items,
|
Realtime: realtime.Items,
|
||||||
@@ -100,6 +96,27 @@ func (s *Service) VehicleDetail(ctx context.Context, vin string, protocol string
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func resolveVehicleIdentity(keyword string, vehicles []VehicleRow) *VehicleRow {
|
||||||
|
keyword = strings.TrimSpace(keyword)
|
||||||
|
if keyword == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
for index := range vehicles {
|
||||||
|
if strings.EqualFold(vehicles[index].VIN, keyword) {
|
||||||
|
return &vehicles[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for index := range vehicles {
|
||||||
|
if strings.EqualFold(vehicles[index].Plate, keyword) || strings.EqualFold(vehicles[index].Phone, keyword) {
|
||||||
|
return &vehicles[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(vehicles) > 0 {
|
||||||
|
return &vehicles[0]
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) RealtimeLocations(ctx context.Context, query url.Values) (Page[RealtimeLocationRow], error) {
|
func (s *Service) RealtimeLocations(ctx context.Context, query url.Values) (Page[RealtimeLocationRow], error) {
|
||||||
return s.store.RealtimeLocations(ctx, query)
|
return s.store.RealtimeLocations(ctx, query)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user