earnrate 0.2.9 → 0.2.11

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.
Files changed (49) hide show
  1. package/README.md +14 -6
  2. package/data/CHANGELOG.md +56 -0
  3. package/data/VERSION +1 -1
  4. package/data/cards/amex-blue-cash-preferred.yaml +3 -1
  5. package/data/cards/amex-delta-skymiles-gold.yaml +120 -0
  6. package/data/cards/amex-delta-skymiles-platinum.yaml +118 -0
  7. package/data/cards/amex-delta-skymiles-reserve.yaml +80 -0
  8. package/data/cards/amex-hilton-honors-aspire.yaml +140 -0
  9. package/data/cards/amex-hilton-honors-surpass.yaml +151 -0
  10. package/data/cards/amex-hilton-honors.yaml +117 -0
  11. package/data/cards/amex-marriott-bonvoy-bevy.yaml +116 -0
  12. package/data/cards/amex-marriott-bonvoy-brilliant.yaml +91 -0
  13. package/data/cards/amex-platinum.yaml +14 -0
  14. package/data/cards/bank-of-america-atmos-rewards-ascent.yaml +13 -0
  15. package/data/cards/bank-of-america-atmos-rewards-business.yaml +13 -0
  16. package/data/cards/bank-of-america-atmos-rewards-summit.yaml +16 -0
  17. package/data/cards/capital-one-quicksilver.yaml +80 -0
  18. package/data/cards/chase-aeroplan.yaml +28 -0
  19. package/data/cards/chase-ihg-one-rewards.yaml +1 -1
  20. package/data/cards/chase-marriott-bonvoy-bold.yaml +123 -0
  21. package/data/cards/chase-marriott-bonvoy-boundless.yaml +76 -0
  22. package/data/cards/chase-sapphire-reserve.yaml +29 -0
  23. package/data/cards/chase-united-business.yaml +10 -0
  24. package/data/cards/chase-united-club-business.yaml +19 -0
  25. package/data/cards/chase-united-club.yaml +31 -0
  26. package/data/cards/chase-united-explorer.yaml +19 -0
  27. package/data/cards/chase-united-gateway.yaml +18 -0
  28. package/data/cards/chase-united-quest.yaml +20 -1
  29. package/data/cards/citi-aadvantage-business.yaml +12 -1
  30. package/data/cards/citi-aadvantage-platinum-select.yaml +12 -1
  31. package/data/cards/discover-it-cash-back.yaml +169 -0
  32. package/data/currencies.yaml +26 -0
  33. package/data/issuers.yaml +3 -0
  34. package/data/merchants/overrides.yaml +24 -2
  35. package/data/merchants/seed.yaml +40 -6
  36. package/dist/engine/cheat-sheet.js +3 -0
  37. package/dist/engine/explore.js +8 -4
  38. package/dist/engine/milestones.js +10 -2
  39. package/dist/engine/recommend.js +42 -16
  40. package/dist/engine/rule-text.js +12 -4
  41. package/dist/format/recommendation.js +8 -2
  42. package/dist/format/wallet.js +6 -2
  43. package/dist/mcp/prompts.js +90 -0
  44. package/dist/mcp/schemas.js +3 -0
  45. package/dist/mcp/server.js +19 -1
  46. package/dist/mcp/tools/account.js +5 -4
  47. package/dist/mcp/tools/answers.js +7 -0
  48. package/dist/mcp/tools/wallet.js +1 -0
  49. package/package.json +1 -1
@@ -64,7 +64,20 @@ rules:
64
64
  ],
65
65
  }
66
66
  rate: 2
67
- note: Only Chase's select streaming list (Apple Music, Apple TV, Disney+, ESPN+, Fubo TV, Max, Hulu, Netflix, Pandora, Paramount+, Peacock, Showtime, SiriusXM, Sling, Spotify, YouTube Premium, YouTube TV, Vudu).
67
+ note: Only the services on Chase's select streaming list, like Netflix, Hulu, Disney+ and Spotify.
68
+ milestones:
69
+ - id: spend-20k
70
+ spend: 20000
71
+ period: calendar_year
72
+ rewards:
73
+ - a 10,000-mile award flight discount
74
+ note: "One a calendar year. It posts to MileagePlus within 6-8 weeks and expires 12 months after it's issued. Separate from the 10,000-mile discount every cardmember anniversary."
75
+ - id: spend-40k
76
+ spend: 40000
77
+ period: calendar_year
78
+ rewards:
79
+ - 2 global Economy Plus seat upgrades
80
+ note: 'For the primary cardmember, on tickets bought with the card. Chase says to allow 6-8 weeks for them to post; use them within 12 months.'
68
81
  todo:
69
82
  - United Card Events from Chase also earn 4x; no merchant exists for them, so they aren't modeled.
70
83
  # Issuer text backing each rule; `yarn check-sources` checks it weekly.
@@ -120,3 +133,9 @@ evidence:
120
133
  - rule: foreign_transaction_fee
121
134
  url: https://sites.chase.com/services/creatives/pricingandterms.html/content/dam/pricingandterms/LGC65756.html
122
135
  quote: 'Foreign Transactions None Penalty Fees'
136
+ - rule: spend-20k
137
+ url: https://creditcards.chase.com/travel-credit-cards/united/united-quest
138
+ quote: 'Earn a 10,000-mile award flight discount after spending $20,000 each calendar year'
139
+ - rule: spend-40k
140
+ url: https://creditcards.chase.com/travel-credit-cards/united/united-quest
141
+ quote: 'Earn 2 global Economy Plus® seat upgrades after spending $40,000 each calendar year.'
@@ -37,8 +37,16 @@ rules:
37
37
  match: { categories: [phone, tv_internet] }
38
38
  rate: 2
39
39
  note: Telecom merchants (phone service and equipment such as cell phones) and cable and satellite TV, internet, phone and radio providers.
40
- # Not modeled: free checked bag, companion certificate after $30,000 spend. Loyalty Points toward status aren't card earnings.
40
+ milestones:
41
+ - id: spend-30k
42
+ spend: 30000
43
+ period: cardmember_year
44
+ rewards:
45
+ - an American Airlines Companion Certificate
46
+ note: "Citi's cardmembership year runs from the billing cycle after the anniversary month, so it can be a few weeks off the anniversary date. Issued after the card renews: the companion pays $99 plus taxes and fees on a domestic Main Cabin round trip."
47
+ # Not modeled: free checked bag. Loyalty Points toward status aren't card earnings.
41
48
  todo:
49
+ - Citi counts the $30,000 milestone over a cardmembership year that starts with the billing cycle after the anniversary month; `cardmember_year` uses the anniversary date, so progress can be a few weeks off.
42
50
  - Warehouse-club gas earns 2x if the club codes it as a gas station; earnrate's gas.superstore can't tell, so it's excluded. Moot at Costco, which takes only Visa.
43
51
  evidence:
44
52
  - rule: base_rate
@@ -86,3 +94,6 @@ evidence:
86
94
  - rule: foreign_transaction_fee
87
95
  url: https://www.citi.com/credit-cards/citi-aadvantage-business-credit-card
88
96
  quote: 'Fee for Foreign Purchases — None'
97
+ - rule: spend-30k
98
+ url: https://www.citi.com/credit-cards/citi-aadvantage-business-credit-card
99
+ quote: 'Earn an American Airlines Companion Certificate for qualifying domestic travel after you spend $30,000 in purchases each cardmembership year'
@@ -30,8 +30,16 @@ rules:
30
30
  exclude: { categories: [gas.superstore] }
31
31
  rate: 2
32
32
  note: Warehouse-club gas counts only when the club codes it as a gas station, so superstore and warehouse-club gas is excluded here to stay conservative. Discount, department and convenience stores don't count.
33
- # Not modeled: free first checked bag, preferred boarding, companion certificate. Loyalty Points toward status aren't card earnings.
33
+ milestones:
34
+ - id: spend-20k
35
+ spend: 20000
36
+ period: cardmember_year
37
+ rewards:
38
+ - a $125 American Airlines Flight Discount
39
+ note: "Citi's cardmembership year runs from the billing cycle after the anniversary month, so it can be a few weeks off the anniversary date. The discount expires a year after it's issued."
40
+ # Not modeled: free first checked bag, preferred boarding. Loyalty Points toward status aren't card earnings.
34
41
  todo:
42
+ - Citi counts the $20,000 milestone over a cardmembership year that starts with the billing cycle after the anniversary month; `cardmember_year` uses the anniversary date, so progress can be a few weeks off.
35
43
  - Warehouse-club gas earns 2x if the club codes it as a gas station; earnrate's gas.superstore can't tell, so it's excluded. Moot at Costco, which takes only Visa.
36
44
  evidence:
37
45
  - rule: base_rate
@@ -73,3 +81,6 @@ evidence:
73
81
  - rule: foreign_transaction_fee
74
82
  url: https://www.citi.com/credit-cards/citi-aadvantage-platinum-elite-credit-card
75
83
  quote: 'there are no foreign transaction fees'
84
+ - rule: spend-20k
85
+ url: https://www.citi.com/credit-cards/citi-aadvantage-platinum-elite-credit-card
86
+ quote: 'Earn a $125 American Airlines Flight Discount certificate (the “Flight Discount”) after you spend $20,000 or more in purchases'
@@ -0,0 +1,169 @@
1
+ id: discover-it-cash-back
2
+ name: Discover it Cash Back Credit Card
3
+ # Discover merged into Capital One, N.A.; the application terms are headed
4
+ # "Discover by Capital One" and served from disclosures.capitalone.com.
5
+ issuer: discover
6
+ network: discover
7
+ currency: cash
8
+ last_verified: 2026-11-03
9
+ verified_by: claude
10
+ source_urls:
11
+ - https://www.discover.com/credit-cards/cash-back/it-card/
12
+ # The card page's "See rates, rewards, fees, and other cost information"
13
+ # (pricing and rewards FAQ); the number is the page's offer id and changes
14
+ # when Capital One changes it.
15
+ - https://disclosures.capitalone.com/disclosure.42300.en-US.html
16
+ - https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
17
+ - https://www.discover.com/credit-cards/cash-back/cashback-bonus.html
18
+ # The calendar page's "See our FAQs".
19
+ - https://www.discover.com/credit-cards/card-smarts/using-cashback-bonus/
20
+ base_rate: 1
21
+ annual_fee: 0
22
+ # No page states it: the application terms' fee table lists no foreign
23
+ # transaction fee row, but nothing says "None".
24
+ foreign_transaction_fee: null
25
+ welcome_offer:
26
+ dollars: 200
27
+ spend: 500
28
+ months: 3
29
+ note: One-time $200 statement credit, available by applying through the card page. Existing or previous cardmembers may not be eligible if they received a new cardmember bonus for this product in the past 48 months. New cardmembers also get Cashback Match (all cash back earned in the first year matched), which isn't counted here.
30
+ caps:
31
+ # Discover's quarterly maximum on the rotating 5% categories.
32
+ - id: five-percent-quarterly
33
+ amount: 1500
34
+ period: quarter
35
+ then_rate: 1
36
+ rotating: true
37
+ rules:
38
+ - id: capital-one-travel
39
+ match:
40
+ {
41
+ merchants:
42
+ [
43
+ capital-one-travel-hotels,
44
+ capital-one-travel-vacation-rentals,
45
+ capital-one-travel-car-rentals,
46
+ capital-one-travel-activities,
47
+ ],
48
+ }
49
+ rate: 5
50
+ note: Hotels, vacation rentals, rental cars and activities booked through Capital One Travel only. Flights booked there, and hotel incidentals or upgrades paid outside Capital One Travel, earn the base 1%.
51
+ - id: capital-one-entertainment
52
+ match: { merchants: [capital-one-entertainment] }
53
+ rate: 5
54
+ note: Tickets bought on the Capital One Entertainment ticketing platform only. Cardholder-exclusive pre-sales, tickets bought directly from Capital One Hall or Capital One Arena, and Capital One Dining are excluded.
55
+ # Rotating 5% categories. Activation is per quarter and isn't retroactive:
56
+ # only purchases from the day you activate earn 5%.
57
+ - id: q4-2026-restaurants
58
+ match: { categories: [dining] }
59
+ rate: 5
60
+ geography: us_only
61
+ cap: five-percent-quarterly
62
+ requires: { activation: true }
63
+ valid_from: 2026-10-01
64
+ valid_to: 2026-12-31
65
+ activate_by: 2026-12-31
66
+ note: Full-service restaurants, cafes, cafeterias, fast-food locations and caterers. Restaurants inside hotels or retail stores, and bakeries, may not qualify. Earns 5% only from the day you activate (any time through December 31, 2026).
67
+ - id: q4-2026-entertainment
68
+ match: { categories: [entertainment, movie_theaters] }
69
+ rate: 5
70
+ geography: us_only
71
+ cap: five-percent-quarterly
72
+ requires: { activation: true }
73
+ valid_from: 2026-10-01
74
+ valid_to: 2026-12-31
75
+ activate_by: 2026-12-31
76
+ note: Tickets at movie theaters, professional and semi-professional sports promoters, theatrical and concert promoters, amusement parks, tourist attractions, aquariums, zoos, dance halls, record stores, video rental locations, pool halls and bowling alleys. Golf courses, country clubs, some collegiate sporting events, charitable events, cable and streaming subscriptions, amusement park tickets bought on third-party sites and packages coded as travel or hotel don't count. Earns 5% only from the day you activate.
77
+ - id: q4-2026-utilities
78
+ match: { categories: [utilities, tv_internet, phone] }
79
+ rate: 5
80
+ geography: us_only
81
+ cap: five-percent-quarterly
82
+ requires: { activation: true }
83
+ valid_from: 2026-10-01
84
+ valid_to: 2026-12-31
85
+ activate_by: 2026-12-31
86
+ note: Residential electricity, natural gas and water, plus internet, cable, satellite TV and mobile and landline phone service paid by phone or online. Paying for those at a physical store, through a landlord, property manager or HOA, home fuel delivery and standalone streaming services may not qualify. Earns 5% only from the day you activate.
87
+ todo:
88
+ - 'Discover has published only 2026 on its 5% calendar (Oct-Dec 2026 is the last quarter shown). Add 2027 quarters when Discover posts them.'
89
+ - Discover's 5% activation isn't retroactive (5% applies "from 10/1/26 (or the date on which you activate 5%, whichever is later)"), and you can activate until the quarter's last day. The schema's activate_by can't say that purchases before activation earn 1%; it's set to the quarter's last day and the rule notes say so.
90
+ - Cashback Match (Discover matches all cash back a new cardmember earns in the first year, no limit) can't be expressed as a fixed welcome offer; it roughly doubles first-year earnings on every rule. Not modeled.
91
+ - The card page's Cashback Match terms say "through your first 365 days"; the Cashback Bonus page says "your first 12 consecutive billing periods or 365 days, whichever is longer". Which one current applicants get is unclear; it doesn't change any rate here.
92
+ - Foreign transaction fee isn't stated on any Discover page or in the application terms (their fee table has no foreign transaction row). Left null; confirm with the Cardmember Agreement or Capital One.
93
+ - Discover says 5% purchases "must be made with merchants in the U.S." The application terms put that sentence in the general earning paragraph, so it may also apply to the 1% base and Capital One Travel; only the rotating rules are marked us_only.
94
+ - Amusement parks, tourist attractions, aquariums, zoos, record stores, video rental, pool halls and bowling alleys earn 5% as Q4 2026 entertainment but have no earnrate category. Golf courses, country clubs and collegiate sporting events are excluded but can't be told apart from the entertainment category.
95
+ - Third-party payment accounts and digital wallet transactions may not earn 5% if they don't carry a qualifying MCC. Not modeled.
96
+ # Issuer text backing each rule; `yarn check-sources` checks it weekly.
97
+ evidence:
98
+ - rule: base_rate
99
+ url: https://www.discover.com/credit-cards/cash-back/it-card/
100
+ quote: 'Plus, earn 1% cash back on all other purchases.'
101
+ - rule: base_rate
102
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
103
+ quote: 'There is no cap to the amount of 1% rewards you can earn on purchases.'
104
+ - rule: capital-one-travel
105
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
106
+ quote: 'earn 5% cash back on purchases (hotels, vacation rentals, rental cars and activities only) made on Capital One Travel'
107
+ - rule: capital-one-travel
108
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
109
+ quote: 'such as hotel incidentals, upgrades or other expenses, will not earn 5% cash back'
110
+ - rule: capital-one-entertainment
111
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
112
+ quote: 'You will earn 5% cash back on Capital One Entertainment purchases.'
113
+ - rule: capital-one-entertainment
114
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
115
+ quote: 'and dining reservations or purchases through Capital One Dining are excluded'
116
+ - rule: q4-2026-restaurants
117
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
118
+ quote: 'Earn 5% Cashback Bonus at Restaurants, Entertainment and Utilities, now to December 31, 2026'
119
+ - rule: q4-2026-restaurants
120
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
121
+ quote: 'from 10/1/26 (or the date on which you activate 5%, whichever is later) through 12/31/26'
122
+ - rule: q4-2026-restaurants
123
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
124
+ quote: 'Restaurant purchases include those made at merchants classified as full-service restaurants, cafes, cafeterias, fast-food locations, and caterers.'
125
+ - rule: q4-2026-restaurants
126
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
127
+ quote: 'Purchases must be made with merchants in the U.S.'
128
+ - rule: q4-2026-restaurants
129
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
130
+ quote: '5% category purchases over the quarterly maximum, and all other purchases, except as noted below, earn 1% cash back.'
131
+ - rule: q4-2026-restaurants
132
+ url: https://www.discover.com/credit-cards/cash-back/cashback-bonus.html
133
+ quote: 'NOW: Earn 5% Cashback Bonus at Restaurants, Entertainment and Utilities'
134
+ - rule: q4-2026-entertainment
135
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
136
+ quote: 'on up to $1,500 in purchases when you activate'
137
+ - rule: q4-2026-entertainment
138
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
139
+ quote: 'Entertainment purchases include ticket purchases at movie theaters, sports promoters (professional and semi-professional live events)'
140
+ - rule: q4-2026-entertainment
141
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
142
+ quote: 'Tickets for or fees at golf courses, country clubs, some collegiate sporting events, charitable events'
143
+ - rule: q4-2026-utilities
144
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
145
+ quote: 'Utilities purchases include purchases for residential electricity, natural gas, and water service.'
146
+ - rule: q4-2026-utilities
147
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
148
+ quote: 'purchases made over the phone or online for internet, cable, satellite TV, and mobile and landline phone service'
149
+ - rule: q4-2026-utilities
150
+ url: https://www.discover.com/credit-cards/cash-back/cashback-calendar.html
151
+ quote: 'Purchases at physical retail stores for internet, cable, satellite, and mobile and landline phone service do not qualify.'
152
+ - rule: q4-2026-utilities
153
+ url: https://www.discover.com/credit-cards/card-smarts/using-cashback-bonus/
154
+ quote: 'you need to activate to earn each quarter'
155
+ - rule: annual_fee
156
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
157
+ quote: 'Annual Fee None.'
158
+ - rule: annual_fee
159
+ url: https://www.discover.com/credit-cards/cash-back/it-card/
160
+ quote: 'No, there is no annual fee for the Discover it Card.'
161
+ - rule: welcome_offer
162
+ url: https://www.discover.com/credit-cards/cash-back/it-card/
163
+ quote: 'Earn a $200 bonus statement credit when you spend $500 in the first 3 months.'
164
+ - rule: welcome_offer
165
+ url: https://disclosures.capitalone.com/disclosure.42300.en-US.html
166
+ quote: 'You will receive a $200 statement credit if you spend at least $500 within 3 months'
167
+ - rule: welcome_offer
168
+ url: https://www.discover.com/credit-cards/cash-back/it-card/
169
+ quote: 'Get an unlimited dollar-for-dollar match of all the cash back you earn at the end of your first year'
@@ -131,6 +131,32 @@
131
131
  sources:
132
132
  - https://thepointsguy.com/loyalty-programs/monthly-valuations/
133
133
 
134
+ - id: delta-skymiles
135
+ name: Delta SkyMiles
136
+ value_cents: 1.0
137
+ range: [1.0, 1.2]
138
+ note: Delta's Pay with Miles lets Delta Amex cardholders take $50 off a Delta fare for every 5,000 miles (1.0¢ a mile). 1.2¢ is TPG's November 2026 valuation.
139
+ sources:
140
+ - https://www.delta.com/paywithmiles
141
+ - https://thepointsguy.com/loyalty-programs/monthly-valuations/
142
+
143
+ - id: hilton-honors
144
+ name: Hilton Honors points
145
+ value_cents: 0.4
146
+ note: Hilton publishes no general cash value for points; its terms say rewards can't be redeemed for cash, and the only fixed rate is for Event Credits on group bills (25,000 points for $50, 0.2¢). 0.4¢ is TPG's November 2026 valuation, below the 0.5¢ default used for IHG, so it's the default here.
147
+ sources:
148
+ - https://www.hilton.com/en/hilton-honors/terms/
149
+ - https://thepointsguy.com/loyalty-programs/monthly-valuations/
150
+
151
+ - id: marriott-bonvoy
152
+ name: Marriott Bonvoy points
153
+ value_cents: 0.5
154
+ range: [0.5, 0.75]
155
+ note: Marriott publishes no general cash value for points. The only fixed rate is Chase's Pay Yourself Back on the Bonvoy Bold card, $100 for every 12,500 points (0.8¢), limited to airline and Marriott purchases on that card. 0.5¢ is the conservative default IHG uses too; 0.75¢ is TPG's November 2026 valuation.
156
+ sources:
157
+ - https://creditcards.chase.com/travel-credit-cards/marriott-bonvoy/bold
158
+ - https://thepointsguy.com/loyalty-programs/monthly-valuations/
159
+
134
160
  - id: kohls-rewards
135
161
  name: Kohl's Rewards
136
162
  value_cents: 1.0
package/data/issuers.yaml CHANGED
@@ -19,6 +19,9 @@
19
19
  # Column N.A. issues the Bilt card; people know it as Bilt.
20
20
  name: Bilt
21
21
  search: [bilt]
22
+ - id: discover
23
+ name: Discover
24
+ search: [discover it]
22
25
  - id: sofi
23
26
  name: SoFi
24
27
  - id: td-bank
@@ -212,6 +212,11 @@
212
212
  aliases: [capital one travel car rental],
213
213
  category: travel,
214
214
  }
215
+ - id: capital-one-travel-activities
216
+ kind: booking
217
+ name: Activity through Capital One Travel
218
+ aliases: [capital one travel activity]
219
+ category: travel
215
220
  - {
216
221
  id: capital-one-travel-flights,
217
222
  kind: booking,
@@ -287,10 +292,16 @@
287
292
  # drugstores" (chase.com/personal/credit-cards/rewards-category-faq).
288
293
  - id: bjs-wholesale-club
289
294
  name: "BJ's Wholesale Club"
290
- aliases: [bjs wholesale, bjs wholesale club, bjs club]
295
+ aliases: [bjs, bjs wholesale, bjs wholesale club, bjs club]
291
296
  domains: [bjs.com]
292
297
  category: warehouse_club
293
- note: Codes as a warehouse club, which Amex, Chase and Capital One leave out of their grocery bonuses.
298
+ note: Codes as a warehouse club, which Amex, Chase and Capital One leave out of their grocery bonuses. For the restaurant chain, ask about BJ's Restaurant & Brewhouse.
299
+ # Listed here, beside BJ's Wholesale Club, so "BJ's" alone means the club
300
+ # and the restaurant still answers to its own names.
301
+ - id: bjs-restaurant
302
+ name: "BJ's Restaurant & Brewhouse"
303
+ aliases: [bjs restaurant, bjs restaurant and brewhouse, bjs brewhouse]
304
+ category: dining
294
305
  - id: bjs-gas
295
306
  name: "BJ's Gas"
296
307
  aliases: [bjs gas, bjs gas station]
@@ -439,6 +450,17 @@
439
450
  domains: [postmates.com]
440
451
  category: dining
441
452
  note: A delivery app that codes as a restaurant for most issuers. Bonuses limited to buying directly from a restaurant don't count it.
453
+ - id: caviar
454
+ name: Caviar
455
+ domains: [trycaviar.com]
456
+ category: dining
457
+ note: A delivery app that codes as a restaurant for most issuers. Bonuses limited to buying directly from a restaurant don't count it.
458
+ - id: delivery-com
459
+ name: Delivery.com
460
+ aliases: [delivery com]
461
+ domains: [delivery.com]
462
+ category: dining
463
+ note: A delivery app that codes as a restaurant for most issuers. Bonuses limited to buying directly from a restaurant don't count it.
442
464
 
443
465
  # A dinner theater: food ordered at your seat may land on the same check.
444
466
  - id: alamo-drafthouse
@@ -266,12 +266,6 @@
266
266
  aliases: [pf changs, p f changs, p.f. changs],
267
267
  category: dining,
268
268
  }
269
- - {
270
- id: bjs-restaurant,
271
- name: "BJ's Restaurant & Brewhouse",
272
- aliases: [bjs restaurant, bjs restaurant and brewhouse, bjs brewhouse],
273
- category: dining,
274
- }
275
269
  - { id: waffle-house, name: Waffle House, category: dining }
276
270
  - {
277
271
  id: tgi-fridays,
@@ -1042,6 +1036,18 @@
1042
1036
  domains: [delta.com],
1043
1037
  category: travel.flights,
1044
1038
  }
1039
+ - {
1040
+ id: delta-vacations,
1041
+ name: Delta Vacations,
1042
+ domains: [deltavacations.com],
1043
+ category: travel,
1044
+ }
1045
+ - {
1046
+ id: delta-stays,
1047
+ name: Delta Stays,
1048
+ aliases: [delta stays, delta hotels],
1049
+ category: travel.hotels,
1050
+ }
1045
1051
  - {
1046
1052
  id: united,
1047
1053
  name: United Airlines,
@@ -1338,6 +1344,34 @@
1338
1344
  domains: [thrifty.com],
1339
1345
  category: travel.car_rental,
1340
1346
  }
1347
+ - {
1348
+ id: ez-rent-a-car,
1349
+ name: E-Z Rent-A-Car,
1350
+ aliases: [ez rent a car],
1351
+ domains: [e-zrentacar.com],
1352
+ category: travel.car_rental,
1353
+ }
1354
+ - {
1355
+ id: fox-rent-a-car,
1356
+ name: Fox Rent A Car,
1357
+ aliases: [fox car rental],
1358
+ domains: [foxrentacar.com],
1359
+ category: travel.car_rental,
1360
+ }
1361
+ - {
1362
+ id: payless-car-rental,
1363
+ name: Payless Car Rental,
1364
+ aliases: [payless car],
1365
+ domains: [paylesscar.com],
1366
+ category: travel.car_rental,
1367
+ }
1368
+ - {
1369
+ id: sixt,
1370
+ name: Sixt,
1371
+ aliases: [sixt rent a car],
1372
+ domains: [sixt.com],
1373
+ category: travel.car_rental,
1374
+ }
1341
1375
  - {
1342
1376
  id: dollar-car-rental,
1343
1377
  name: Dollar Rent A Car,
@@ -20,6 +20,9 @@ export const EVERYDAY_PURCHASES = [
20
20
  { label: 'Drugstores', category: 'drugstore' },
21
21
  { label: 'Everything else', category: 'other' },
22
22
  ];
23
+ // What a quick pick searches for: "Streaming (Netflix)" searches "Netflix",
24
+ // since streaming bonuses follow each issuer's list of services.
25
+ export const quickPickText = (item) => /\((.+)\)$/.exec(item.label)?.[1] ?? item.label;
23
26
  // The best card in the wallet for each everyday kind of purchase on `date`,
24
27
  // with caps, picks and activations as the wallet has them.
25
28
  export function cheatSheet(catalog, wallet, date, items = EVERYDAY_PURCHASES) {
@@ -2,7 +2,7 @@ import { categoryResolution, resolvePlace } from "../merchants/resolve.js";
2
2
  import { evaluateCard, purchaseContext } from "./evaluate.js";
3
3
  import { membershipName, membershipNeeded, paidMemberships, } from "./memberships.js";
4
4
  import { choicePeriod, periodKey } from "./periods.js";
5
- import { recommend } from "./recommend.js";
5
+ import { FOREIGN_ASSUMPTION, isForeign, recommend } from "./recommend.js";
6
6
  import { rotationGap } from "./rotation.js";
7
7
  import { membershipsUsed } from "./setup.js";
8
8
  import { optionName } from "./rule-text.js";
@@ -129,8 +129,10 @@ function membershipUpgrades(catalog, card, held, merchant, purchase, options, cu
129
129
  memberships: [...options.memberships, membership],
130
130
  });
131
131
  const ctx = purchaseContext(catalog, wallet, merchant, merchant.category, purchase);
132
+ const fee = isForeign(purchase) ? (card.foreign_transaction_fee ?? 0) : 0;
132
133
  const pct = evaluateCard(card, held, ctx).best.rate *
133
- cardValuation(catalog, wallet, card).centsPerUnit;
134
+ cardValuation(catalog, wallet, card).centsPerUnit -
135
+ fee;
134
136
  if (pct > current + EPSILON)
135
137
  upgrades.push({ membership, effectiveReturnPct: pct });
136
138
  }
@@ -212,11 +214,11 @@ export function exploreCards(catalog, query, options, resolved) {
212
214
  merchant,
213
215
  ranked,
214
216
  excluded,
215
- assumptions: exploreAssumptions(catalog, merchant, ranked, options),
217
+ assumptions: exploreAssumptions(catalog, merchant, ranked, options, purchase),
216
218
  warnings: exploreWarnings(catalog, merchant),
217
219
  };
218
220
  }
219
- function exploreAssumptions(catalog, merchant, ranked, options) {
221
+ function exploreAssumptions(catalog, merchant, ranked, options, purchase) {
220
222
  const assumptions = [];
221
223
  if (merchant.source === 'category') {
222
224
  assumptions.push(`Ranks purchases that code as ${categoryPhrase(catalog, merchant.category)}.`);
@@ -231,6 +233,8 @@ function exploreAssumptions(catalog, merchant, ranked, options) {
231
233
  const values = pointValuesText(catalog, ranked.slice(0, 10));
232
234
  if (values !== null)
233
235
  assumptions.push(values);
236
+ if (isForeign(purchase))
237
+ assumptions.push(FOREIGN_ASSUMPTION);
234
238
  return assumptions;
235
239
  }
236
240
  function exploreWarnings(catalog, merchant) {
@@ -45,11 +45,19 @@ export function milestonePays(m) {
45
45
  }
46
46
  // "the $15,000 calendar-year spend for 10,000 bonus points"
47
47
  export const milestoneWhat = (m) => `the ${wholeDollars(m.spend)} ${MILESTONE_PERIODS[m.period]} spend for ${milestonePays(m)}`;
48
- export function reachedText(card, hit) {
48
+ export function reachedText(card, hit, centsPerPoint) {
49
49
  const m = card.milestones.find((x) => x.id === hit.id);
50
50
  if (!m)
51
51
  return '';
52
- return `This purchase reaches ${milestoneWhat(m)} (${money(hit.before)} tracked on this card in ${hit.period} before it).`;
52
+ const points = hit.points === null
53
+ ? null
54
+ : `${hit.points.toLocaleString('en-US')} bonus points, worth about ${money(roundCents((hit.points * centsPerPoint) / 100))}`;
55
+ const pays = points === null
56
+ ? listed(hit.rewards)
57
+ : hit.rewards.length === 0
58
+ ? points
59
+ : `${points}, plus ${listed(hit.rewards)}`;
60
+ return `This purchase reaches the ${wholeDollars(m.spend)} ${MILESTONE_PERIODS[m.period]} spend: ${pays} (${money(hit.before)} tracked on this card in ${hit.period} before it).`;
53
61
  }
54
62
  const THIS_PERIOD = {
55
63
  calendar_year: 'this year',