fix: stations and community-stations repository mappers return DECIMAL prices as strings #243
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Per the audit performed for #241, the stations features have the same numeric-as-string bug. node-postgres returns
numeric/decimalcolumns as strings, but the TypeScript interfaces declare them asnumber. The mappers pass values through raw.Affected
backend/src/features/stations/data/stations.repository.tsCache row mapper returns these fields without coercion:
priceRegular—DECIMAL(10,2)pricePremium—DECIMAL(10,2)priceDiesel—DECIMAL(10,2)rating—DECIMAL(2,1)backend/src/features/stations/data/community-stations.repository.tsmapRow.price93—DECIMAL(5,3)Investigation Required (before fixing)
Unlike maintenance and ownership-costs, the stations price fields may be consumed in places that already work around the string-as-number behavior (e.g., parsing back to number for sorting, displaying as-is in formatted strings). Before fixing the mapper:
priceRegular,pricePremium,priceDiesel,rating, andprice93— backend and frontend.numberchanges behavior (e.g., a<sort by price>UI that doesNumber(a.priceRegular) - Number(b.priceRegular)will continue to work; a UI that doespriceRegular.includes(".")would break).Suggested Fix (mapper layer)
Match the pattern used in
vehicles.repository.tsand the fix applied in PR #242:Acceptance Criteria
Number()calls in consumers that become unnecessary.Related
Closing as not-a-bug — original audit was wrong
Investigated this before fixing and discovered the mappers already coerce these fields. The audit that originated this issue (the one performed for #241) claimed the stations mappers "return raw rows" but it was inferring from the audit summary table without actually reading the files.
Actual state of the code
backend/src/features/stations/data/stations.repository.ts:157-172—mapCacheRow:backend/src/features/stations/data/community-stations.repository.ts:308-333—mapRow:A grep across the stations feature confirms there is no path that bypasses these mappers — every consumer accesses the camelCase mapped object, the domain types declare
number, and the API validator (api/community-stations.validation.ts:19) usesz.number(). End-to-end the type contract is already honest.Minor code-quality detail (not fixing here)
The truthiness check pattern
row.field ? parseFloat(...) : undefinedwould drop a legitimate0value (e.g., a station rated 0.0 by Google Maps, or — implausibly — free fuel). Same pattern exists invehicles.repository.tsalready onmain. If you want to tighten this to!= nulleverywhere, that's a separate code-quality issue worth filing on its own. It is not what #243 was reporting, so closing this as not-a-bug rather than expanding scope.Lesson for future audits
The audit table that fed #241 marked stations as "needs fix: YES" based on phrases like "(mapCacheRow) not shown but inferred to return raw rows" — i.e. it never opened the file. Future audits should not flag a file as broken without reading it. The fuel-logs audit done for #244 caught its own errors precisely because the agent did read the file.
Closing.