feat: add station matching from receipt merchant name (refs #132)
Add Google Places Text Search to match receipt merchant names (e.g. "Shell", "COSTCO #123") to real gas stations. Backend exposes POST /api/stations/match endpoint. Frontend calls it after OCR extraction and pre-fills locationData with matched station's placeId, name, and address. Users can clear the match in the review modal. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import { pool } from '../../../core/config/database';
|
||||
import { logger } from '../../../core/logging/logger';
|
||||
import {
|
||||
StationSearchBody,
|
||||
StationMatchBody,
|
||||
SaveStationBody,
|
||||
StationParams,
|
||||
UpdateSavedStationBody
|
||||
@@ -53,6 +54,29 @@ export class StationsController {
|
||||
}
|
||||
}
|
||||
|
||||
async matchStation(request: FastifyRequest<{ Body: StationMatchBody }>, reply: FastifyReply) {
|
||||
try {
|
||||
const { merchantName } = request.body;
|
||||
|
||||
if (!merchantName || !merchantName.trim()) {
|
||||
return reply.code(400).send({
|
||||
error: 'Bad Request',
|
||||
message: 'Merchant name is required',
|
||||
});
|
||||
}
|
||||
|
||||
const result = await this.stationsService.matchStationFromReceipt(merchantName);
|
||||
|
||||
return reply.code(200).send(result);
|
||||
} catch (error: any) {
|
||||
logger.error('Error matching station from receipt', { error, merchantName: request.body?.merchantName });
|
||||
return reply.code(500).send({
|
||||
error: 'Internal server error',
|
||||
message: 'Failed to match station',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async saveStation(request: FastifyRequest<{ Body: SaveStationBody }>, reply: FastifyReply) {
|
||||
try {
|
||||
const userId = (request as any).user.sub;
|
||||
|
||||
Reference in New Issue
Block a user