Skip to content

Commit

Permalink
Add initial support for new Chevrolet Inventory API (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben-Chapman authored Aug 24, 2024
1 parent 4bbafca commit 3248a09
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 88 deletions.
22 changes: 11 additions & 11 deletions app/src/components/InventoryTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
variant="light"
@click="
openUrlInNewWindow(
vinDetail[row.item.vin]['DI']['DealerVDPURL'],
vinDetail[row.item.vin]['DI']['DealerVDPURL']
)
"
class="mr-2 align-middle"
Expand All @@ -149,7 +149,7 @@
variant="light"
@click="
openUrlInNewWindow(
generateGenesisWindowStickerUrl(row.item.vin, form.model),
generateGenesisWindowStickerUrl(row.item.vin, form.model)
)
"
class="mr-2 align-middle"
Expand Down Expand Up @@ -344,7 +344,7 @@
sortable: true,
sortDirection: "desc",
showFor: ["all"],
hideFor: [],
hideFor: ["Chevrolet"],
},
{
key: "drivetrainDesc",
Expand Down Expand Up @@ -446,15 +446,15 @@
// A lot of additional detail is included in the inventory data, so
// passing the inventory API response into getVinDetail to display in the
// VIN detail section
this.item,
this.item
);
},
async hyundai() {
return await getHyundaiVinDetail(
this.item.vin,
this.manufacturer,
this.model,
this.year,
this.year
);
},
async kia() {
Expand All @@ -470,7 +470,7 @@
return await getVolkswagenVinDetail(
this.zipcode,
this.item.vin,
this.manufacturer,
this.manufacturer
);
},
async ford() {
Expand All @@ -481,7 +481,7 @@
this.item.modelYear,
this.item.dealerPaCode,
this.zipcode,
this.manufacturer,
this.manufacturer
);
},
async audi() {
Expand Down Expand Up @@ -568,7 +568,7 @@
filterFunction(rowRecord, filterSelections) {
// selectedCategories looks like ['trimDesc', ['LIMITED', 'SEL']]
var selectedCategories = Object.entries(filterSelections).filter(
(f) => f[1].length > 0,
(f) => f[1].length > 0
);
var selectedCategoriesCount = selectedCategories.length;
var isMatch = [];
Expand All @@ -583,7 +583,7 @@
return this.filterByPrice(rowRecord, selectedPrice);
} else {
return selectedCategories[0][1].some((val) =>
Object.values(rowRecord).includes(val),
Object.values(rowRecord).includes(val)
);
}
} else if (selectedCategoriesCount > 1) {
Expand All @@ -598,7 +598,7 @@
// Each loop is a category. Do we have an OR match for the selected filter items?
// e.g. Blue OR Black OR White
isMatch.push(
selectedItems.some((s) => Object.values(rowRecord).includes(s)),
selectedItems.some((s) => Object.values(rowRecord).includes(s))
);
}
}
Expand Down Expand Up @@ -639,7 +639,7 @@
(field) =>
(field.showFor.includes("all") ||
field.showFor.includes(this.form.manufacturer)) &&
!field.hideFor.includes(this.form.manufacturer),
!field.hideFor.includes(this.form.manufacturer)
);
return f;
Expand Down
91 changes: 14 additions & 77 deletions app/src/manufacturers/chevrolet.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2023 Joel Gomez, Ben Chapman
* Copyright 2023 Joel Gomez, 2023 - 2024 Ben Chapman
*
* This file is part of The EV Finder.
*
Expand All @@ -17,7 +17,7 @@

import { convertToCurrency, generateErrorMessage, titleCase } from "../helpers/libs";
import { apiRequest } from "../helpers/request";
import { chevroletInventoryMapping, chevroletVinMapping } from "./chevroletMappings";
import { chevroletVinMapping } from "./chevroletMappings";

const manufacturer = "chevrolet";

Expand Down Expand Up @@ -46,69 +46,19 @@ export async function getChevroletInventory(zip, year, model, radius, manufactur
* @returns a "normalized" inventory object
*/
function formatChevroletInventoryResults(input) {
// find exterior and interior color mappings from filter values
const extColors = input.data?.filters
.find((item) => item.key == "extColor")
.values.reduce(
(colors, color) => ({ ...colors, [color.value]: color.displayValue }),
{},
);

// for interior colors, also include a hint for the material type
const intColors = input.data?.filters
.find((item) => item.key == "intColor")
.values.reduce(
(colors, color) => ({
...colors,
[color.value]: `${color.displayValue.split(",")[0]}, ${
color.displayValue.split(",")[1].split(" ")[1]
}`,
}),
{},
);

const results = [];

input.data?.listResponse.forEach((vehicle) => {
const _vehicle = {};

// bring some nested values up to the top level and create entries that don't exist
const enhancedResult = {
...vehicle,
dealerName: titleCase(vehicle?.dealer?.name),
dealerDistance: vehicle.dealer?.distance,
trimName: vehicle.trim?.name,
totalPrice: vehicle.pricing?.cash?.summary?.items
.find((item) => item.type == "total_vehicle_price")
.value.toString(),
vehicleAvailabilityDisplayStatus: titleCase(
vehicle.vehicleAvailabilityStatus?.displayStatus,
),
extColor: extColors[colorCodeFromUrl(vehicle.extImages[0])],
intColor: intColors[colorCodeFromUrl(vehicle.intImages[0])],
drivetrainDesc: "FWD", // hard coded for Bolt EV, Bolt EUV; future models may require better strategy for deriving this.
};

Object.keys(enhancedResult).forEach((key) => {
// Remap the Chevrolet-specific key into the EV Finder specific key
if (Object.keys(chevroletInventoryMapping).includes(key)) {
_vehicle[chevroletInventoryMapping[key]] = enhancedResult[key];
} else {
// If there's no EV Finder-specific key, just append the Chevrolet key
_vehicle[key] = enhancedResult[key];
}
input?.data?.hits.forEach((vehicle) => {
results.push({
dealerName: titleCase(vehicle.dealer.name),
deliveryDate: vehicle.stockDetails.estimatedDeliveryDate,
drivetrainDesc: vehicle.driveType,
distance: vehicle.dealer.distance.value,
price: vehicle.pricing.cash.msrp.value,
exteriorColor: vehicle.baseExteriorColor,
interiorColor: vehicle.baseInteriorColor,
vin: vehicle.id,
trimDesc: vehicle.variant.name,
});

// Some inventory is marked as "Temporarily Unavailable", which is exposed through
// a recall key, and not vehicleAvailabilityStatus. Dealing with that here
if (vehicle.recall) {
_vehicle["deliveryDate"] = vehicle.recall?.displayStatus;
}

// Populate inventoryStatus which is exposed as the Availability filter
_vehicle["inventoryStatus"] = _vehicle["deliveryDate"];

results.push(_vehicle);
});
return results;
}
Expand All @@ -135,7 +85,7 @@ export async function getChevroletVinDetail(vin) {
totalVehiclePrice: convertToCurrency(
vinData.data.prices?.summary
.find((item) => item.type == "total_vehicle_price")
.value.toString() ?? "0",
.value.toString() ?? "0"
),
trimName: vinData.data.trim?.name,
extColorOptionCode: vinData.data.extColor?.optionCode,
Expand All @@ -157,16 +107,3 @@ export async function getChevroletVinDetail(vin) {

return vinFormattedData;
}

/**
* Utility function to extract the color code from image urls.
* An image url has the color code as the first substring of a substring
* in a long query param.
*
* @param {String} url the image url to extract the color code from
* @returns the color code as a string, e.g. GAZ
*/
function colorCodeFromUrl(url) {
const color = new URL(url);
return color.search.split("/")[3].split("_")[0];
}

0 comments on commit 3248a09

Please sign in to comment.