fix(orders): the restaurant is the merchant, not the courier
ci / lint-test (push) Successful in 43s
ci / lint-test (push) Successful in 43s
Reverses a change made on request. The platform in the headline
fragmented the merchant: the same restaurant read as two, depending on
who carried the bag, and that is not a distinction anyone rating the food
cares about. It also already has a home — the expandable Order details
panel renders expense_metadata.platform next to its heading, which is
where the user asked for it.
The fragmentation was worse than cosmetic. merchantVerdict joined on an
exact merchant_normalized, and the platforms capitalise differently
("TEG Kebabs & Biryani" on Uber Eats, "TEG KEBABS & BIRYANI" on
DoorDash), so one restaurant kept two separate histories and a "never
again" recorded through one app never warned in the other — silently
defeating the point of the memory. Now case-folded; verified on real
data, where the DoorDash order sees 1 prior verdict against 0 before.
81 existing descriptions backfilled in one transaction, dry-run first and
dumped beforehand. The regex is anchored to the end so suburb parens
survive: "Order - Coles (Wyndham Vale) (Uber Eats)" becomes
"Order - Coles (Wyndham Vale)", not "Order - Coles".
This commit is contained in:
@@ -26,13 +26,16 @@ export const PLATFORM_LABEL: Record<ParsedOrder["platform"], string> = {
|
||||
* look for the detail, and there are restaurants on both platforms. The
|
||||
* platform is the one thing the parser always knows and used to discard.
|
||||
*/
|
||||
export function orderDescription(platform: ParsedOrder["platform"], merchant: string): string {
|
||||
const label = PLATFORM_LABEL[platform];
|
||||
// A trip's merchant is literally "Uber Trip", so the suffix would restate it
|
||||
// — "Order - Uber Trip (Uber)". The addresses that actually identify a trip
|
||||
// are in the Order details panel, not squeezed into the description.
|
||||
if (merchant.toLowerCase().includes(label.toLowerCase())) return `Order - ${merchant}`;
|
||||
return `Order - ${merchant} (${label})`;
|
||||
export function orderDescription(_platform: ParsedOrder["platform"], merchant: string): string {
|
||||
// The platform is deliberately NOT in the headline. What identifies the
|
||||
// transaction is the restaurant; which courier delivered it is provenance,
|
||||
// and it already has a home — the expandable Order details panel renders
|
||||
// `expense_metadata.platform` next to its heading (user, 2026-07-28).
|
||||
//
|
||||
// Keeping it here also fragmented the merchant: the same restaurant reads
|
||||
// "Mad Mex (DoorDash)" and "Mad Mex (Uber Eats)" depending on who carried
|
||||
// the bag, which is not a distinction anyone rating the food cares about.
|
||||
return `Order - ${merchant}`;
|
||||
}
|
||||
|
||||
export interface IngestResult {
|
||||
|
||||
@@ -151,7 +151,12 @@ export async function merchantVerdict(
|
||||
JOIN expense_metadata em
|
||||
ON em.transaction_id = r.transaction_id
|
||||
OR em.matched_transaction_id = r.transaction_id
|
||||
WHERE em.merchant_normalized = $1
|
||||
-- Case-folded: the platforms capitalise the same restaurant differently
|
||||
-- ("TEG Kebabs & Biryani" on Uber Eats, "TEG KEBABS & BIRYANI" on
|
||||
-- DoorDash). An exact match split one restaurant's history in two, so a
|
||||
-- "never again" recorded through one app never warned you in the other —
|
||||
-- silently defeating the whole point of the memory.
|
||||
WHERE lower(em.merchant_normalized) = lower($1)
|
||||
AND ($2::int IS NULL OR r.transaction_id <> $2)
|
||||
ORDER BY t.transaction_date DESC, r.participant_id
|
||||
LIMIT 50`,
|
||||
|
||||
Reference in New Issue
Block a user