@bytebrand/export-cars 1.26.41 → 1.26.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/services/autouncle-feed-run.js +2 -1
- package/dist/services/autouncle-feed-run.js.map +1 -1
- package/dist/transformers/autouncle.transformer.d.ts +1 -0
- package/dist/transformers/autouncle.transformer.js +2 -1
- package/dist/transformers/autouncle.transformer.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/autouncle/AUDIT.md +103 -101
- package/package.json +1 -1
- package/src/services/autouncle-feed-run.ts +5 -2
- package/src/transformers/autouncle.transformer.ts +3 -0
- package/test/autouncle-feed-run.test.ts +2 -2
package/docs/autouncle/AUDIT.md
CHANGED
|
@@ -1,101 +1,103 @@
|
|
|
1
|
-
# AutoUncle inventory feed — audit (ADV-322 / ADV-323)
|
|
2
|
-
|
|
3
|
-
Status 13.10.2026, base `origin/deploy_develop` 3a025095, `@bytebrand/export-cars` 1.26.31.
|
|
4
|
-
Historical documents (Confluence "autouncle [paused]", "2.7.2 Export Plugins", ACF-3604/3650/3717/3725/6172/6190)
|
|
5
|
-
are evidence only. No current AutoUncle inventory schema is available; the public AutoUncle B2B
|
|
6
|
-
"automotive API" is a dealer/DMS **valuation** API and is not used as a schema here.
|
|
7
|
-
|
|
8
|
-
## 1. Is the export live? — No
|
|
9
|
-
|
|
10
|
-
| Where | Event | State | Last run | Output |
|
|
11
|
-
|---|---|---|---|---|
|
|
12
|
-
| PROD Cronicle (`auto-de-prod-cronicle-01`, export-cars 1.26.18) | `3.0 Export to autouncle - part 1` `ek61rkico08` | **disabled**, no timing, nothing chains into it | one manual run 07.07.2026, aborted by user | `resources/autouncle-export/api_export_cars_autouncle.json` = 8 bytes (`{"ads":[`) |
|
|
13
|
-
| | `3.1 Export to autouncle - part 2` `ek61ro0yv09` | **disabled**; shell `cp` of the JSON to `htdocs/autouncle/export_cars_autouncle.json` | never ran | `htdocs/autouncle/` does not exist |
|
|
14
|
-
| DEV Cronicle (`auto-de-dev-cronicle-01`, 1.26.31) | `3.0 Export to Autouncle part1` `ek60tym7m0b` | enabled, no timing; chained from `2.1 Export facebook - part 2` | 10.09.2026, code 0 | 467 KB JSON of 10.09 (298 ads) |
|
|
15
|
-
| | `3.1 Export to Autouncle part2` `ek60u1gsd0c` | enabled, chains to `ek87441xa04` | 10.09.2026, **code 1** every run (`cp: … htdocs/autouncle/… No such file or directory`) | — the rest of the DEV chain (criteo, meinestadt, ooyyo, …) stops here |
|
|
16
|
-
|
|
17
|
-
PROD 3.0 params: `environment=production`, `String` = allow-list of 19 dealer `metaData.ownerId`s, `Number` =
|
|
18
|
-
`metaData.imagesCount:2`. DEV 3.0: no rules. Both events were last modified 2023 (DEV) / 01.04.2026 (PROD,
|
|
19
|
-
migration). Events, keys and scripts were read with `storage-cli list_get`, secrets redacted.
|
|
20
|
-
|
|
21
|
-
Hosting: `https://scheduler.auto.de/autouncle/export_cars_autouncle.json` (historic) — no answer (timeout);
|
|
22
|
-
`https://cronicle.auto.de/autouncle/…` and `http://cronicle.autode-dev.de/autouncle/…` — 404. Nothing is
|
|
23
|
-
hosted for AutoUncle today, on any environment.
|
|
24
|
-
|
|
25
|
-
## 2. Code path
|
|
26
|
-
|
|
27
|
-
`ExportType.AUTOUNCLE = 'autouncle'` → `AutouncleConfig` + `AutouncleExporter` (`export.schema.ts`).
|
|
28
|
-
|
|
29
|
-
Before (unchanged since the monorepo import 3046a15d, CO2 class ADV-187 b46e7e83):
|
|
30
|
-
`emptyDir(resources/autouncle-export)` → for every car of the base export snapshot: shared `filterCar`
|
|
31
|
-
(imagesCount > 0 + Cronicle rules) → UPA dealer profile (skip if none) → `AutouncleTransformer` →
|
|
32
|
-
`AutouncleJsonBuilder` appends `{"ads":[…]}` directly to the published file.
|
|
33
|
-
|
|
34
|
-
After (this branch): `AutouncleFeedRun` (`services/autouncle-feed-run.ts`) — lock → source snapshot check
|
|
35
|
-
(shared ADV-335 `FeedGuard`) → per car: duplicate id, `filterCar`, car-level exclusions, dealer address (UPA,
|
|
36
|
-
cached per dealer), clean images (ADV-336 `getCleanImages` + `ImageUrlValidator` + `selectOpenAiImageFields`)
|
|
37
|
-
→ pure `mapAutouncleItem` → temp file → count check → atomic rename (`.prev` kept) → report.
|
|
38
|
-
Dry-run is the default and writes `resources/autouncle-dryrun/`, which no Cronicle step reads.
|
|
39
|
-
|
|
40
|
-
## 3. Field mapping (`ads[]`, keys/order/spellings unchanged)
|
|
41
|
-
|
|
42
|
-
| Key | Source | Before | Now | Open |
|
|
43
|
-
|---|---|---|---|---|
|
|
44
|
-
| back_link | CBD `_id` | `https://www.<domain>/search/vehicle/<_id>?source=classifieds&medium=cpc&campaign=autouncle` | stable across runs; since 1.26.41 (ADV-324) `?source=autouncle&medium=listing&campaign=listing&utm_source=autouncle&utm_medium=listing&utm_campaign=listing` | pending AutoUncle approval → Q8 |
|
|
45
|
-
| make / model_name / model_variant | mainData.make / model / subModel | raw | same | `SONSTIGE` placeholder models are exported (data) → Q9 |
|
|
46
|
-
| fuel / body / gear_type | consumption.fuel / mainData.category / driveSuspension.gearbox | fixed maps; an unmapped or null selector made the key **disappear** from JSON | unmapped/null → `Other` / `other` | enum values → Q6 |
|
|
47
|
-
| doors | mainData.doors | string | same | |
|
|
48
|
-
| price | price.currentSalesPrice | `EUR <value>`; missing price → `"EUR "` and the car was still sent | same format; no valid positive price → car not sent (`no_valid_price`). Never a rate, never purchasePrice | currency format → Q6 |
|
|
49
|
-
| year | mainData.firstRegistration (Unix s) | null → `moment(0)` → **1970** (143 of 1044 DEV cars) | missing/0/null/invalid → `""`; outside 1900..next year → `""` | null vs "" → Q6 |
|
|
50
|
-
| status | same | `Neuwagen` only when firstRegistration === 0 | `Neuwagen` when no valid firstRegistration (same rule, null included) | 3 of 143 DEV cars are `condition=used` without registration → Q7 |
|
|
51
|
-
| mileage | mainData.mileage | `<n>km`, 0 → `1km` | same | |
|
|
52
|
-
| leasing / has_4wd | — | always `""` | same | → Q10 |
|
|
53
|
-
| color | exterior.exteriorColor, German label | same | same | |
|
|
54
|
-
| engine_size | engineData.cubicCapacity | `ccm` with no number when missing (189/1044) | `""` when missing | |
|
|
55
|
-
| power | engineData.powerKW | kW, no unit | same | unit → Q6 |
|
|
56
|
-
| seller_type / seller_name | — | `Dealer` / `auto.de` | same | marketplace vs dealer identity → Q3 |
|
|
57
|
-
| seller_id | metaData.ownerId | **dealer** id already (not a vehicle id) | same; contract test with two cars of one dealer | |
|
|
58
|
-
| seller_region / city / street_address / postcode | UPA businessAddress, else mainAddress; region from the postal code table | if the table did not know the place, street/city/zip were **blanked** (664/1044 DEV cars) | dealer's own values kept, region `Deutschland` | |
|
|
59
|
-
| description | offer.offerDescription | raw | same; 192/1002 empty on DEV, some contain literal `\\` line breaks (dealer data) | → Q10 |
|
|
60
|
-
| images | Imbo images | default profile: `/large` (format negotiated, can be WebP), padded with **3 noimage placeholders** below 17 photos (2820 placeholder URLs on DEV) | `[{url}]`, ADV-336 clean profile, explicit `large-cached.jpeg`, every URL checked (200 + image/jpeg|png); no valid 3/4 hero → car not sent | limits → ADV-323 gate |
|
|
61
|
-
| fuel_economy / co2_emission | consumption.consumptionCombined / environmentEmissions.co2 | raw legacy fields; a BEV sent its kWh (CBD mirrors it into consumptionCombined) as fuel economy | since 1.26.41: the Google feed's EnVKV picks as plain numbers (WLTP first, legacy only as fallback; confirmed plug-in weighted); BEV: fuel `""`, CO₂ `0`; estimated values withheld by the publication gate (enforce) | units → Q6 |
|
|
62
|
-
| co2_effiency_class | environmentEmissions.wltpEnergyEfficiencyClass (ADV-187) | raw | same; `""` when the CO₂ value is withheld (the class is derived from CO₂) | → Q6 |
|
|
63
|
-
| euro_emission_class / enviromental_sticker | environmentEmissions.* | raw selector keys | same (no schema to translate to) | → Q6 |
|
|
64
|
-
|
|
65
|
-
Car-level exclusions (new, counted in the report): `duplicate_id`, `filtered`, `no_id`, `no_dealer`,
|
|
66
|
-
`reserved_or_sold` (offer.offerAvailability reserved/sold), `no_valid_price`, `no_valid_image`.
|
|
67
|
-
|
|
68
|
-
## 4. Fixes on this branch
|
|
69
|
-
|
|
70
|
-
1. Builder wrote the first car twice (`{"ads":[A,A,B…`) — fixed, test.
|
|
71
|
-
2. Year 1970 for a null first registration (ACF-3717/3725 class of bug) — fixed, tests.
|
|
72
|
-
3. Price must be a valid positive end-customer price, otherwise the car is not sent.
|
|
73
|
-
4. Reserved / sold cars are not sent (absence = removal; partner semantics unknown → Q5).
|
|
74
|
-
5. Dealer address no longer blanked when the postal code table misses the place.
|
|
75
|
-
6. `engine_size` without a value is `""`, not `ccm`; unmapped selectors never drop a key.
|
|
76
|
-
7. Images: clean profile + validator, no placeholders, no WebP risk, hero first (ADV-323).
|
|
77
|
-
8. Fail-closed: no `emptyDir`; empty / partial / stale snapshot, empty result or a drop > 20 % against the
|
|
78
|
-
last good run → run blocked (exit 1, `3.1` copy does not run), last good file stays. Lock per state dir.
|
|
79
|
-
9. Dry-run default; live only with `autouncleDryRun=false`.
|
|
80
|
-
10. (1.26.41, 10.11) EnVKV: WLTP picks + EnVKV C8 publication gate (same params as the Google job). A live run
|
|
81
|
-
refuses to start without `publicationGate=enforce`. The run report has `envkv.estimated`
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
- `
|
|
101
|
-
|
|
1
|
+
# AutoUncle inventory feed — audit (ADV-322 / ADV-323)
|
|
2
|
+
|
|
3
|
+
Status 13.10.2026, base `origin/deploy_develop` 3a025095, `@bytebrand/export-cars` 1.26.31.
|
|
4
|
+
Historical documents (Confluence "autouncle [paused]", "2.7.2 Export Plugins", ACF-3604/3650/3717/3725/6172/6190)
|
|
5
|
+
are evidence only. No current AutoUncle inventory schema is available; the public AutoUncle B2B
|
|
6
|
+
"automotive API" is a dealer/DMS **valuation** API and is not used as a schema here.
|
|
7
|
+
|
|
8
|
+
## 1. Is the export live? — No
|
|
9
|
+
|
|
10
|
+
| Where | Event | State | Last run | Output |
|
|
11
|
+
|---|---|---|---|---|
|
|
12
|
+
| PROD Cronicle (`auto-de-prod-cronicle-01`, export-cars 1.26.18) | `3.0 Export to autouncle - part 1` `ek61rkico08` | **disabled**, no timing, nothing chains into it | one manual run 07.07.2026, aborted by user | `resources/autouncle-export/api_export_cars_autouncle.json` = 8 bytes (`{"ads":[`) |
|
|
13
|
+
| | `3.1 Export to autouncle - part 2` `ek61ro0yv09` | **disabled**; shell `cp` of the JSON to `htdocs/autouncle/export_cars_autouncle.json` | never ran | `htdocs/autouncle/` does not exist |
|
|
14
|
+
| DEV Cronicle (`auto-de-dev-cronicle-01`, 1.26.31) | `3.0 Export to Autouncle part1` `ek60tym7m0b` | enabled, no timing; chained from `2.1 Export facebook - part 2` | 10.09.2026, code 0 | 467 KB JSON of 10.09 (298 ads) |
|
|
15
|
+
| | `3.1 Export to Autouncle part2` `ek60u1gsd0c` | enabled, chains to `ek87441xa04` | 10.09.2026, **code 1** every run (`cp: … htdocs/autouncle/… No such file or directory`) | — the rest of the DEV chain (criteo, meinestadt, ooyyo, …) stops here |
|
|
16
|
+
|
|
17
|
+
PROD 3.0 params: `environment=production`, `String` = allow-list of 19 dealer `metaData.ownerId`s, `Number` =
|
|
18
|
+
`metaData.imagesCount:2`. DEV 3.0: no rules. Both events were last modified 2023 (DEV) / 01.04.2026 (PROD,
|
|
19
|
+
migration). Events, keys and scripts were read with `storage-cli list_get`, secrets redacted.
|
|
20
|
+
|
|
21
|
+
Hosting: `https://scheduler.auto.de/autouncle/export_cars_autouncle.json` (historic) — no answer (timeout);
|
|
22
|
+
`https://cronicle.auto.de/autouncle/…` and `http://cronicle.autode-dev.de/autouncle/…` — 404. Nothing is
|
|
23
|
+
hosted for AutoUncle today, on any environment.
|
|
24
|
+
|
|
25
|
+
## 2. Code path
|
|
26
|
+
|
|
27
|
+
`ExportType.AUTOUNCLE = 'autouncle'` → `AutouncleConfig` + `AutouncleExporter` (`export.schema.ts`).
|
|
28
|
+
|
|
29
|
+
Before (unchanged since the monorepo import 3046a15d, CO2 class ADV-187 b46e7e83):
|
|
30
|
+
`emptyDir(resources/autouncle-export)` → for every car of the base export snapshot: shared `filterCar`
|
|
31
|
+
(imagesCount > 0 + Cronicle rules) → UPA dealer profile (skip if none) → `AutouncleTransformer` →
|
|
32
|
+
`AutouncleJsonBuilder` appends `{"ads":[…]}` directly to the published file.
|
|
33
|
+
|
|
34
|
+
After (this branch): `AutouncleFeedRun` (`services/autouncle-feed-run.ts`) — lock → source snapshot check
|
|
35
|
+
(shared ADV-335 `FeedGuard`) → per car: duplicate id, `filterCar`, car-level exclusions, dealer address (UPA,
|
|
36
|
+
cached per dealer), clean images (ADV-336 `getCleanImages` + `ImageUrlValidator` + `selectOpenAiImageFields`)
|
|
37
|
+
→ pure `mapAutouncleItem` → temp file → count check → atomic rename (`.prev` kept) → report.
|
|
38
|
+
Dry-run is the default and writes `resources/autouncle-dryrun/`, which no Cronicle step reads.
|
|
39
|
+
|
|
40
|
+
## 3. Field mapping (`ads[]`, keys/order/spellings unchanged)
|
|
41
|
+
|
|
42
|
+
| Key | Source | Before | Now | Open |
|
|
43
|
+
|---|---|---|---|---|
|
|
44
|
+
| back_link | CBD `_id` | `https://www.<domain>/search/vehicle/<_id>?source=classifieds&medium=cpc&campaign=autouncle` | stable across runs; since 1.26.41 (ADV-324) `?source=autouncle&medium=listing&campaign=listing&utm_source=autouncle&utm_medium=listing&utm_campaign=listing` | pending AutoUncle approval → Q8 |
|
|
45
|
+
| make / model_name / model_variant | mainData.make / model / subModel | raw | same | `SONSTIGE` placeholder models are exported (data) → Q9 |
|
|
46
|
+
| fuel / body / gear_type | consumption.fuel / mainData.category / driveSuspension.gearbox | fixed maps; an unmapped or null selector made the key **disappear** from JSON | unmapped/null → `Other` / `other` | enum values → Q6 |
|
|
47
|
+
| doors | mainData.doors | string | same | |
|
|
48
|
+
| price | price.currentSalesPrice | `EUR <value>`; missing price → `"EUR "` and the car was still sent | same format; no valid positive price → car not sent (`no_valid_price`). Never a rate, never purchasePrice | currency format → Q6 |
|
|
49
|
+
| year | mainData.firstRegistration (Unix s) | null → `moment(0)` → **1970** (143 of 1044 DEV cars) | missing/0/null/invalid → `""`; outside 1900..next year → `""` | null vs "" → Q6 |
|
|
50
|
+
| status | same | `Neuwagen` only when firstRegistration === 0 | `Neuwagen` when no valid firstRegistration (same rule, null included) | 3 of 143 DEV cars are `condition=used` without registration → Q7 |
|
|
51
|
+
| mileage | mainData.mileage | `<n>km`, 0 → `1km` | same | |
|
|
52
|
+
| leasing / has_4wd | — | always `""` | same | → Q10 |
|
|
53
|
+
| color | exterior.exteriorColor, German label | same | same | |
|
|
54
|
+
| engine_size | engineData.cubicCapacity | `ccm` with no number when missing (189/1044) | `""` when missing | |
|
|
55
|
+
| power | engineData.powerKW | kW, no unit | same | unit → Q6 |
|
|
56
|
+
| seller_type / seller_name | — | `Dealer` / `auto.de` | same | marketplace vs dealer identity → Q3 |
|
|
57
|
+
| seller_id | metaData.ownerId | **dealer** id already (not a vehicle id) | same; contract test with two cars of one dealer | |
|
|
58
|
+
| seller_region / city / street_address / postcode | UPA businessAddress, else mainAddress; region from the postal code table | if the table did not know the place, street/city/zip were **blanked** (664/1044 DEV cars) | dealer's own values kept, region `Deutschland` | |
|
|
59
|
+
| description | offer.offerDescription | raw | same; 192/1002 empty on DEV, some contain literal `\\` line breaks (dealer data) | → Q10 |
|
|
60
|
+
| images | Imbo images | default profile: `/large` (format negotiated, can be WebP), padded with **3 noimage placeholders** below 17 photos (2820 placeholder URLs on DEV) | `[{url}]`, ADV-336 clean profile, explicit `large-cached.jpeg`, every URL checked (200 + image/jpeg|png); no valid 3/4 hero → car not sent | limits → ADV-323 gate |
|
|
61
|
+
| fuel_economy / co2_emission | consumption.consumptionCombined / environmentEmissions.co2 | raw legacy fields; a BEV sent its kWh (CBD mirrors it into consumptionCombined) as fuel economy | since 1.26.41: the Google feed's EnVKV picks as plain numbers (WLTP first, legacy only as fallback; confirmed plug-in weighted); BEV: fuel `""`, CO₂ `0`; estimated values withheld by the publication gate (enforce) | units → Q6 |
|
|
62
|
+
| co2_effiency_class | environmentEmissions.wltpEnergyEfficiencyClass (ADV-187) | raw | same; `""` when the CO₂ value is withheld (the class is derived from CO₂) | → Q6 |
|
|
63
|
+
| euro_emission_class / enviromental_sticker | environmentEmissions.* | raw selector keys | same (no schema to translate to) | → Q6 |
|
|
64
|
+
|
|
65
|
+
Car-level exclusions (new, counted in the report): `duplicate_id`, `filtered`, `no_id`, `no_dealer`,
|
|
66
|
+
`reserved_or_sold` (offer.offerAvailability reserved/sold), `no_valid_price`, `no_valid_image`.
|
|
67
|
+
|
|
68
|
+
## 4. Fixes on this branch
|
|
69
|
+
|
|
70
|
+
1. Builder wrote the first car twice (`{"ads":[A,A,B…`) — fixed, test.
|
|
71
|
+
2. Year 1970 for a null first registration (ACF-3717/3725 class of bug) — fixed, tests.
|
|
72
|
+
3. Price must be a valid positive end-customer price, otherwise the car is not sent.
|
|
73
|
+
4. Reserved / sold cars are not sent (absence = removal; partner semantics unknown → Q5).
|
|
74
|
+
5. Dealer address no longer blanked when the postal code table misses the place.
|
|
75
|
+
6. `engine_size` without a value is `""`, not `ccm`; unmapped selectors never drop a key.
|
|
76
|
+
7. Images: clean profile + validator, no placeholders, no WebP risk, hero first (ADV-323).
|
|
77
|
+
8. Fail-closed: no `emptyDir`; empty / partial / stale snapshot, empty result or a drop > 20 % against the
|
|
78
|
+
last good run → run blocked (exit 1, `3.1` copy does not run), last good file stays. Lock per state dir.
|
|
79
|
+
9. Dry-run default; live only with `autouncleDryRun=false`.
|
|
80
|
+
10. (1.26.41, 10.11) EnVKV: WLTP picks + EnVKV C8 publication gate (same params as the Google job). A live run
|
|
81
|
+
refuses to start without `publicationGate=enforce`. The run report has `envkv.estimated` for the two sent
|
|
82
|
+
attributes (fuel_consumption, co2_emissions; 1.26.42). DEV dry-run 10.11 (enforce): 1731 ads, estimated fuel 884 /
|
|
83
|
+
CO₂ 848 sent empty, 128 BEV with fuel "" and CO₂ 0, WLTP picks changed 338 fuel / 403 CO₂ values.
|
|
84
|
+
11. (1.26.41, 10.11) `back_link` parameters per ADV-324 (partner in `source`, identical utm pair).
|
|
85
|
+
|
|
86
|
+
## 5. Evidence
|
|
87
|
+
|
|
88
|
+
- `npm test`: 138 ok (116 existing + 14 mapping + 8 run).
|
|
89
|
+
- Other feeds byte-identical: `origin/deploy_develop` and this branch compiled with the same `node_modules`;
|
|
90
|
+
every emitted `.js` outside the AutoUncle files is identical (only `params.interface.d.ts` gains three
|
|
91
|
+
optional fields). Covers Google, FB/Meta, Criteo, meinestadt, OOYYO, OpenAI and the rest.
|
|
92
|
+
- DEV dry-run 13.10.2026 (local, DEV snapshot 12.10 15:00 CEST, DEV `3.0` params): 2234 source cars →
|
|
93
|
+
1002 ads, 370 dealers, excluded `filtered` 1190 / `no_valid_image` 42, images 7259/7259 ok, 0 placeholders,
|
|
94
|
+
0 × 1970, 0 duplicate links. Old exporter on the same snapshot: 1045 ads (first duplicated), 143 × 1970,
|
|
95
|
+
2820 placeholder URLs. 20-car sample in `autouncle-sample/` (worktree, not committed).
|
|
96
|
+
|
|
97
|
+
## 6. Not done / not decided
|
|
98
|
+
|
|
99
|
+
- No partner schema, no test import, no activation, no Cronicle change, no version bump / publish.
|
|
100
|
+
- `minPublishedItems` default is 1 (PROD exports an allow-list of 19 dealers; real size unknown) — set per job
|
|
101
|
+
before activation.
|
|
102
|
+
- `3.1` copy target `htdocs/autouncle/` does not exist on either Cronicle; hosting/transport is a partner question (Q4).
|
|
103
|
+
- Portrait / small images: the validator checks status + MIME only, no pixel size — waits for partner limits.
|
package/package.json
CHANGED
|
@@ -4,7 +4,9 @@ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
|
|
|
4
4
|
import { DataSchemes } from '@bytebrand/car-schema';
|
|
5
5
|
|
|
6
6
|
import { AutouncleJsonBuilder } from '../formats/autouncle-json.builder';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
AUTOUNCLE_ENVKV_ATTRIBUTES, AutouncleAddress, AutouncleExclusion, getAutouncleExclusion, mapAutouncleItem,
|
|
9
|
+
} from '../transformers/autouncle.transformer';
|
|
8
10
|
import { FeedGuard, FeedGuardError, LastGood, inspectSourceSnapshot } from './feed-guard';
|
|
9
11
|
import { PublicationGate } from './publication-gate';
|
|
10
12
|
|
|
@@ -147,7 +149,8 @@ export class AutouncleFeedRun {
|
|
|
147
149
|
continue;
|
|
148
150
|
}
|
|
149
151
|
const images = await this.deps.resolveImages(source);
|
|
150
|
-
const estimated = this.deps.gate ? this.deps.gate.estimatedAttributes(source.car) : []
|
|
152
|
+
const estimated = (this.deps.gate ? this.deps.gate.estimatedAttributes(source.car) : [])
|
|
153
|
+
.filter(attribute => AUTOUNCLE_ENVKV_ATTRIBUTES.includes(attribute));
|
|
151
154
|
const mapped = mapAutouncleItem(source.car, {
|
|
152
155
|
domain: this.options.domain,
|
|
153
156
|
address,
|
|
@@ -19,6 +19,9 @@ import { GoogleEnvkvAttribute, envkvCo2Value, envkvFuelConsumptionValue } from '
|
|
|
19
19
|
export const AUTOUNCLE_LINK_PARAMS =
|
|
20
20
|
'source=autouncle&medium=listing&campaign=listing&utm_source=autouncle&utm_medium=listing&utm_campaign=listing';
|
|
21
21
|
|
|
22
|
+
// The EnVKV attributes the feed sends (fuel_economy, co2_emission); the gate knows more (range, kWh, …).
|
|
23
|
+
export const AUTOUNCLE_ENVKV_ATTRIBUTES: GoogleEnvkvAttribute[] = ['fuel_consumption', 'co2_emissions'];
|
|
24
|
+
|
|
22
25
|
export enum AutouncleExclusion {
|
|
23
26
|
duplicateId = 'duplicate_id',
|
|
24
27
|
filtered = 'filtered',
|
|
@@ -237,8 +237,8 @@ const tests: Array<[string, () => Promise<void>]> = [
|
|
|
237
237
|
['EnVKV gate: enforce sends estimated values empty, audit only counts them; off without a gate', async () => {
|
|
238
238
|
const world = await newWorld();
|
|
239
239
|
await writeSource(world, [source('v1'), source('v2')]);
|
|
240
|
-
// v1: the CO2 value it would send is a CBD estimate
|
|
241
|
-
const estimatedAttributes = (c: any): any[] => (c._id === 'v1' ? ['co2_emissions'] : []);
|
|
240
|
+
// v1: the CO2 value it would send is a CBD estimate; the range is too, but the feed has no range key
|
|
241
|
+
const estimatedAttributes = (c: any): any[] => (c._id === 'v1' ? ['co2_emissions', 'electric_range'] : []);
|
|
242
242
|
|
|
243
243
|
const off = await run(world);
|
|
244
244
|
assert.deepEqual(off.envkv, { gate: 'off', estimated: {} });
|