Skip to content

CouponHubBot: show /list visibility status in /added - #386

Merged
Szer merged 1 commit into
mainfrom
added-coupon-visibility-status
Aug 15, 2026
Merged

CouponHubBot: show /list visibility status in /added#386
Szer merged 1 commit into
mainfrom
added-coupon-visibility-status

Conversation

@Szer

@Szer Szer commented Aug 15, 2026

Copy link
Copy Markdown
Owner

Problem

Owners running /added could see a coupon was available but had no way to tell whether it was actually being shown in /list right now, still waiting in a same-denomination queue, or not yet valid. pickCouponsForList (BotHelpers.fs) selects: all coupons expiring today (Dublin) + the 2 soonest-expiring min_check=25 coupons + 1 each of min_check 40/50/100 + fill-to-6 — so an available coupon can easily sit outside the current /list selection with zero visible signal.

Change

Adds CouponListStatus (BotHelpers.fs), computed from the same pool /list reads (db.GetAvailableCoupons()) and the same pickCouponsForList selection, so the verdict shown in /added always matches what /list actually displays. handleAdded (CommandHandler.fs) now fetches that pool/selection before rendering and replaces the old inline taken/reported-only suffix with couponListStatus + formatCouponListStatusSuffix.

Status taxonomy and example /added output lines:

Status Suffix Example line
Shown (в списке) 1. ID:42 — 10€ из 50€, 1 января, четверг (в списке)
Taken (взят) 2. ID:43 — 10€ из 50€, 5 января, понедельник (взят)
Reported (отмечен использованным) 3. ID:44 — 10€ из 50€, 10 января, суббота (отмечен использованным)
NotYetValid vf (начнёт действовать с {date}) 4. ID:45 — 20€ из 100€, 20 февраля, пятница (начнёт действовать с 11 января, воскресенье)
Waiting(ahead, mc) (в очереди: впереди {ahead} {купон/купона/купонов} из {mc}€, точно будет в списке в день истечения) 5. ID:46 — 5€ из 25€, 30 января, пятница (в очереди: впереди 2 купона из 25€, точно будет в списке в день истечения)
WaitingGeneric (incl. Waiting(0,_)) (в очереди, точно будет в списке в день истечения) 6. ID:47 — 5€ из 15€, 30 января, пятница (в очереди, точно будет в списке в день истечения)
WaitingUnknown (defensive, should be unreachable) (в очереди) 7. ID:48 — 10€ из 50€, 15 января, четверг (в очереди)

"в день истечения" is honest, not aspirational: GetVoidableCouponsByOwner and GetAvailableCoupons filter with the same todayUtc() and differ only on valid_from, and pickCouponsForList's expiringToday rule unconditionally includes every valid, available coupon on its own Dublin expiry date — so every waiting coupon is guaranteed to appear in /list by the day it expires.

No DB/migration changes — valid_from was already on Coupon, both queries already existed.

Test plan

  • dotnet build src/CouponHubBot — clean, 0 warnings/errors
  • dotnet test tests/CouponHubBot.Tests — 214/214 passed (208 pre-existing + 6 new), including existing /added//list tests unmodified
  • New AddedStatusTests.fs (6 tests): today→Shown, 3rd fiver→Waiting(ahead=2), future valid_from→NotYetValid, taken/reported regression, waiting-suffix day-of-expiry phrase, out-of-catalog min_check→WaitingGeneric

🤖 Generated with Claude Code

https://claude.ai/code/session_01NZuqUZZ4jkpgh6MFbQ6TVV

Owners couldn't tell from /added whether an "available" coupon was
currently shown in /list, still queued behind same-denomination
coupons, or not yet valid. Adds CouponListStatus (BotHelpers.fs) that
mirrors pickCouponsForList's selection logic exactly, plus a
formatCouponListStatusSuffix renderer; wires both into handleAdded so
its verdict always matches what /list actually shows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NZuqUZZ4jkpgh6MFbQ6TVV
@Szer
Szer marked this pull request as ready for review August 15, 2026 18:51
@Szer
Szer merged commit 181a655 into main Aug 15, 2026
4 checks passed
@Szer
Szer deleted the added-coupon-visibility-status branch August 15, 2026 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant