Skip to content

Commit a1e7706

Browse files
authored
use shared lib vin validation, minor refactor (#299)
1 parent 586c4db commit a1e7706

3 files changed

Lines changed: 41 additions & 30 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/DIMO-Network/device-definitions-api
33
go 1.24
44

55
require (
6-
github.com/DIMO-Network/shared v1.0.2
6+
github.com/DIMO-Network/shared v1.0.6
77
github.com/antchfx/xmlquery v1.4.1
88
github.com/arsmn/fiber-swagger/v2 v2.31.1
99
github.com/aws/aws-sdk-go-v2/config v1.27.27

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1M
7676
github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
7777
github.com/DIMO-Network/shared v1.0.2 h1:V5PH+tbhKwm/UBoMJLA0fKxt5lO2TFPNOJCSsrTCDxs=
7878
github.com/DIMO-Network/shared v1.0.2/go.mod h1:lDHUKwwT2LW6Zvd42Nb33dXklRNTmfyOlbUNx2dQfGY=
79+
github.com/DIMO-Network/shared v1.0.6 h1:hUCxB7WFL4+VAFQMjtvZ6O2UrtF1PgA1OQwl0Ilm3h4=
80+
github.com/DIMO-Network/shared v1.0.6/go.mod h1:lDHUKwwT2LW6Zvd42Nb33dXklRNTmfyOlbUNx2dQfGY=
7981
github.com/DIMO-Network/yaml v0.1.0 h1:KQ3oKHUZETchR6Pxbmmol3e4ewrPv/q8cEwqxfwyZbU=
8082
github.com/DIMO-Network/yaml v0.1.0/go.mod h1:KkiehcbkVzH8Pf8f9dja8B2aW81gYYZSqfwzSj9yN68=
8183
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=

internal/core/queries/decode_vin.go

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"strconv"
99
"time"
1010

11+
"github.com/DIMO-Network/shared/pkg/logfields"
12+
1113
"github.com/tidwall/sjson"
1214

1315
"github.com/DIMO-Network/device-definitions-api/internal/infrastructure/metrics"
@@ -74,15 +76,20 @@ func NewDecodeVINQueryHandler(dbs func() *db.ReaderWriter, vinDecodingService se
7476
func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Message) (interface{}, error) {
7577
qry := query.(*DecodeVINQuery)
7678
if len(qry.VIN) < 10 || len(qry.VIN) > 17 {
77-
return nil, &exceptions.ValidationError{Err: fmt.Errorf("invalid vin %s", qry.VIN)}
79+
return nil, &exceptions.ValidationError{Err: fmt.Errorf("invalid VIN %s", qry.VIN)}
7880
}
7981
resp := &p_grpc.DecodeVinResponse{}
80-
vin := vin.VIN(qry.VIN)
81-
resp.Year = int32(vin.Year())
82-
wmi := vin.Wmi()
82+
vinObj := vin.VIN(qry.VIN)
83+
84+
if !vinObj.IsValidJapanChassis() && !vinObj.IsValidVIN() {
85+
return nil, &exceptions.ValidationError{Err: fmt.Errorf("invalid VIN %s", qry.VIN)}
86+
}
87+
88+
resp.Year = int32(vinObj.Year())
89+
wmi := vinObj.Wmi()
8390

8491
localLog := dc.logger.With().
85-
Str("vin", vin.String()).
92+
Str(logfields.VIN, vinObj.String()).
8693
Str("handler", query.Key()).
8794
Str("vinYear", fmt.Sprintf("%d", resp.Year)).
8895
Str("knownModel", qry.KnownModel).
@@ -104,7 +111,7 @@ func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Messa
104111
}
105112
defer txVinNumbers.Rollback() //nolint
106113
vinDecodeNumber, err := models.VinNumbers(
107-
models.VinNumberWhere.Vin.EQ(vin.String())).
114+
models.VinNumberWhere.Vin.EQ(vinObj.String())).
108115
One(ctx, txVinNumbers)
109116
if err != nil && !errors.Is(err, sql.ErrNoRows) {
110117
metrics.InternalError.With(prometheus.Labels{"method": VinErrors}).Inc()
@@ -126,28 +133,28 @@ func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Messa
126133
// future: see if we can self decode model based on data we have before calling external decode WMI and VDS. Only thing is we won't get the style.
127134

128135
if resp.Year == 0 || resp.Year > int32(time.Now().Year()+1) {
129-
localLog.Info().Msgf("encountered vin with non-standard year digit")
136+
localLog.Info().Msgf("encountered vinObj with non-standard year digit")
130137
}
131138
// check if this is a Tesla VIN, if not just follow regular path
132139
vinInfo := &coremodels.VINDecodingInfoData{}
133140
dbWMI, err := models.Wmis(models.WmiWhere.Wmi.EQ(wmi)).One(ctx, dc.dbs().Reader)
134141
if err == nil && dbWMI != nil {
135142
if dbWMI.ManufacturerName == "Tesla" {
136-
vinInfo, err = dc.vinDecodingService.GetVIN(ctx, vin.String(), coremodels.TeslaProvider, qry.Country)
143+
vinInfo, err = dc.vinDecodingService.GetVIN(ctx, vinObj.String(), coremodels.TeslaProvider, qry.Country)
137144
resp.Manufacturer = "Tesla"
138145
}
139146
}
140147
// not a tesla, regular decode path
141148
if vinInfo == nil || vinInfo.Model == "" {
142-
vinInfo, err = dc.vinDecodingService.GetVIN(ctx, vin.String(), coremodels.AllProviders, qry.Country) // this will try drivly first unless of japan
149+
vinInfo, err = dc.vinDecodingService.GetVIN(ctx, vinObj.String(), coremodels.AllProviders, qry.Country) // this will try drivly first unless of japan
143150
}
144151

145152
// if no luck decoding VIN, try buildingVinInfo from known data passed in, typically smartcar or software connections
146153
if err != nil {
147154
if len(qry.KnownModel) > 0 && qry.KnownYear > 0 {
148155
// note if this is successful, err gets set to nil
149156
// todo: the knownModel should correspond with the Make
150-
vinInfo, err = dc.vinInfoFromKnown(vin, qry.KnownModel, qry.KnownYear)
157+
vinInfo, err = dc.vinInfoFromKnown(vinObj, qry.KnownModel, qry.KnownYear)
151158
}
152159
}
153160

@@ -160,7 +167,7 @@ func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Messa
160167
if err == nil {
161168
err = errors.New("failed to decode, vinInfo is nil")
162169
}
163-
localLog.Err(err).Msgf("failed to decode vin from provider, country: %s", qry.Country)
170+
localLog.Err(err).Msgf("failed to decode vinObj from provider, country: %s", qry.Country)
164171
// todo track failed decodes
165172
return nil, err
166173
}
@@ -169,7 +176,7 @@ func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Messa
169176
_, err = dc.vinRepository.GetOrCreateWMI(ctx, wmi, vinInfo.Make)
170177
if err != nil {
171178
// just log, Japan chasis numbers won't really work with this anyways
172-
dc.logger.Error().Err(err).Msgf("failed to get or create wmi for vin %s", vin.String())
179+
dc.logger.Error().Err(err).Msgf("failed to get or create wmi for vinObj %s", vinObj.String())
173180
}
174181
}
175182
resp.Manufacturer = vinInfo.Make
@@ -183,11 +190,11 @@ func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Messa
183190

184191
tblDef, _, errTbl := dc.deviceDefinitionOnChainService.GetDefinitionByID(ctx, tid)
185192
if errTbl != nil {
186-
dc.logger.Warn().Err(errTbl).Msgf("failed to get definition from tableland for vin: %s, id: %s", vin.String(), tid)
193+
dc.logger.Warn().Err(errTbl).Msgf("failed to get definition from tableland for vinObj: %s, id: %s", vinObj.String(), tid)
187194
} else if tblDef == nil {
188-
dc.logger.Warn().Msgf("failed to get definition from tableland for vin: %s, id: %s", vin.String(), tid)
195+
dc.logger.Warn().Msgf("failed to get definition from tableland for vinObj: %s, id: %s", vinObj.String(), tid)
189196
} else {
190-
dc.logger.Info().Str("vin", vin.String()).Msgf("found definition from tableland %s: %+v", tid, tblDef)
197+
dc.logger.Info().Str(logfields.VIN, vinObj.String()).Msgf("found definition from tableland %s: %+v", tid, tblDef)
191198
}
192199

193200
// add images if we don't have any for this definition_id
@@ -236,7 +243,7 @@ func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Messa
236243
})
237244
if err != nil {
238245
metrics.InternalError.With(prometheus.Labels{"method": VinErrors}).Inc()
239-
return nil, errors.Wrap(err, "error creating new device definition on-chain from decoded vin")
246+
return nil, errors.Wrap(err, "error creating new device definition on-chain from decoded vinObj")
240247
}
241248
resp.NewTrxHash = *trx
242249
}
@@ -248,22 +255,22 @@ func (dc DecodeVINQueryHandler) Handle(ctx context.Context, query mediator.Messa
248255
var styleErr error
249256
resp.DeviceStyleId, styleErr = dc.processDeviceStyle(ctx, vinInfo, tid, resp.Powertrain)
250257
if styleErr != nil {
251-
dc.logger.Error().Err(styleErr).Msgf("error processing device style for vin: %s. continuing", vin.String())
258+
dc.logger.Error().Err(styleErr).Msgf("error processing device style for vinObj: %s. continuing", vinObj.String())
252259
}
253260
}
254261

255262
// insert vin_numbers
256-
errVinNumber := dc.saveVinDecodeNumber(ctx, vin, vinInfo, resp)
263+
errVinNumber := dc.saveVinDecodeNumber(ctx, vinObj, vinInfo, resp)
257264
if errVinNumber != nil {
258265
return nil, errors.Wrap(errVinNumber, "error saving vin_number")
259266
}
260267

261268
localLog.Info().Str("device_definition_id", resp.DefinitionId).
262269
Str("style_id", resp.DeviceStyleId).
263270
Str("wmi", wmi).
264-
Str("vds", vin.VDS()).
265-
Str("vis", vin.VIS()).
266-
Str("check_digit", vin.CheckDigit()).Msgf("decoded vin ok with: %s", vinInfo.Source)
271+
Str("vds", vinObj.VDS()).
272+
Str("vis", vinObj.VIS()).
273+
Str("check_digit", vinObj.CheckDigit()).Msgf("decoded vinObj ok with: %s", vinInfo.Source)
267274

268275
metrics.Success.With(prometheus.Labels{"method": VinSuccess}).Inc()
269276

@@ -367,20 +374,20 @@ func (dc DecodeVINQueryHandler) processDeviceStyle(ctx context.Context, vinInfo
367374
return style.ID, nil
368375
}
369376

370-
func (dc DecodeVINQueryHandler) saveVinDecodeNumber(ctx context.Context, vin vin.VIN, vinInfo *coremodels.VINDecodingInfoData, resp *p_grpc.DecodeVinResponse) error {
377+
func (dc DecodeVINQueryHandler) saveVinDecodeNumber(ctx context.Context, vinObj vin.VIN, vinInfo *coremodels.VINDecodingInfoData, resp *p_grpc.DecodeVinResponse) error {
371378
vinDecodeNumber := &models.VinNumber{
372-
Vin: vin.String(),
379+
Vin: vinObj.String(),
373380
ManufacturerName: resp.Manufacturer,
374-
Wmi: null.StringFrom(vin.Wmi()),
375-
SerialNumber: vin.SerialNumber(),
381+
Wmi: null.StringFrom(vinObj.Wmi()),
382+
SerialNumber: vinObj.SerialNumber(),
376383
DecodeProvider: null.StringFrom(string(vinInfo.Source)),
377384
Year: int(resp.Year),
378385
DefinitionID: resp.DefinitionId,
379386
}
380-
if !vin.IsJapanChassis() {
381-
vinDecodeNumber.VDS = null.StringFrom(vin.VDS())
382-
vinDecodeNumber.Vis = null.StringFrom(vin.VIS())
383-
vinDecodeNumber.CheckDigit = null.StringFrom(vin.CheckDigit())
387+
if vinObj.IsValidVIN() {
388+
vinDecodeNumber.VDS = null.StringFrom(vinObj.VDS())
389+
vinDecodeNumber.Vis = null.StringFrom(vinObj.VIS())
390+
vinDecodeNumber.CheckDigit = null.StringFrom(vinObj.CheckDigit())
384391
}
385392

386393
// Optional fields based on response and VIN info
@@ -409,6 +416,8 @@ func (dc DecodeVINQueryHandler) saveVinDecodeNumber(ctx context.Context, vin vin
409416
if len(vinInfo.Raw) > 0 {
410417
vinDecodeNumber.Vin17Data = null.JSONFrom(vinInfo.Raw)
411418
}
419+
case coremodels.CarVXVIN:
420+
// we currently do not store the raw payload since seemed to not gain much for now
412421
}
413422

414423
// Insert VIN decode number into the database

0 commit comments

Comments
 (0)