docs: backend FX/notifications gaps, add CHANGELOG for recent work
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -422,6 +422,7 @@ Worth knowing explicitly, so nobody assumes a gateway swap will "just work" for
|
||||
- **User experience (wishlist/compare/recently-viewed/saved-searches)** — fully denormalized objects in `localStorage`, guest-first. A DI token exists for a future authenticated repository, but nothing is bound to it — comment in code notes it "can be switched to authenticated repository later."
|
||||
- **Diagnostics** — inspects runtime/bootstrap/widget state locally; the one live-ish probe is a `/ping` health check.
|
||||
- **Cart contents** — see §7, real payment/order calls exist, cart *state* never round-trips to a backend.
|
||||
- **Currency conversion / display rates** — `CurrencyRatesService` holds RUB-based conversion rates in-memory, admin-editable via Admin Settings, persisted to `localStorage` only. `CurrencyConvertPipe` applies them client-side wherever a storefront price is rendered. The `Currency` request header (§6) is still sent on every call, but nothing round-trips a rate from the backend — see §12.7.
|
||||
|
||||
---
|
||||
|
||||
@@ -523,7 +524,22 @@ Separately, `createCartPayment()` (payment-gateway charge creation) still sends
|
||||
```
|
||||
`telegramUserId` may be `null` for a non-Telegram web session - decide whether to also accept an email address as an alternative identifier (the frontend has no email capture on this flow today, so that would need a small frontend addition too). Once this ships, the frontend's localStorage fallback becomes purely a resilience path rather than the common case, and could optionally sync any locally-queued subscriptions on next successful call.
|
||||
|
||||
### 12.6 Trending search terms
|
||||
### 12.7 Currency conversion / FX rates
|
||||
|
||||
**Gap:** the backend has no per-currency pricing — it sends prices in one base currency (`RUB`) regardless of the `Currency` header (§6), and there's no exchange-rate endpoint. Client fix already shipped: admin manually enters a RUB-based rate per supported currency (Admin Settings → Currency rates), and every storefront price display converts client-side via that static, admin-typed number. Rates never update themselves and can drift from the real market rate.
|
||||
|
||||
**Ask:** this was raised as a real accounting concern (bank settlement totals not reconciling against order counts) — two options, not mutually exclusive:
|
||||
1. Backend returns prices already converted per the `Currency` header (removes client-side conversion entirely, most correct).
|
||||
2. Backend exposes a live/periodically-updated FX-rate endpoint (e.g. pegged to Rapira or another exchange) that the frontend polls instead of relying on an admin-typed static number — smaller change, keeps pricing display client-side but removes the manual-entry drift.
|
||||
Either way, the *authoritative* amount charged (`createCartPayment`'s `amount`, §12.3) must be computed/validated server-side against whichever rate source is authoritative — a client-side conversion (current or future) must never be trusted for the actual charge amount.
|
||||
|
||||
### 12.8 Admin purchase notifications depend on Orders CRUD being real
|
||||
|
||||
**Gap:** `AdminOrderWatcherService` (new — polls for new orders to toast/badge the admin) polls `AdminOrdersGateway.loadOrders()` (§8), which is bound to the mock `AdminOrdersLocalGateway` — a static, 24-row in-memory seed with no create path (see §8's gateway table, "Orders … MOCK-ONLY, no seam"). No genuinely new order can ever appear today, so the feature is functionally inert until Orders CRUD gets a real backend (§10 step 6).
|
||||
|
||||
**Ask:** nothing new beyond what §10/§11 already ask for — once a real `AdminOrdersApiGateway` is bound, this feature starts working with no additional frontend change. Flagging here only so nobody spends time debugging "why doesn't the notification ever fire" against the mock.
|
||||
|
||||
### 12.9 Trending search terms
|
||||
|
||||
**Gap:** `SearchTrendingService.loadTrending()` is a stub returning `of(null)` - no trending-searches endpoint exists. It already degrades gracefully (UI hides the trending section rather than showing an error), so this is purely a missing-feature gap, not a bug.
|
||||
|
||||
|
||||
27
CHANGELOG.md
Normal file
27
CHANGELOG.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Changelog
|
||||
|
||||
Recent work, newest first. Scoped to what changed and why — see `BACKEND-API-REFERENCE.md` for the backend-dependency detail on anything marked "depends on backend."
|
||||
|
||||
## 2026-08-15 — Admin purchase notifications
|
||||
|
||||
Admin gets notified when a new order lands: a toast (click-to-navigate) plus an unread badge + order list on the topbar bell icon (previously an unused "no notifications" placeholder). Poll-based — the backend has no WebSocket/SSE, so this follows the same polling pattern already used for payment status.
|
||||
|
||||
- `AdminOrderWatcherService` (new) polls `AdminOrdersGateway.loadOrders()` on an admin-editable interval (default 15s, editable in Admin Settings), diffs against persisted "last notified"/"last acknowledged" order pointers, and fires toasts only for genuinely new orders — never spams on first load.
|
||||
- `UserNotificationService` gained an optional click-to-navigate `route` so a toast can jump straight to the order detail page.
|
||||
- Reactively stops/starts polling off `AdminAuthService.isAuthenticated()` — a first attempt at this (tying it to component destruction) turned out not to work because logout never navigates or destroys the admin shell; caught and corrected before merge.
|
||||
- **Depends on backend:** the mock `AdminOrdersLocalGateway` has no create path, so this feature is functionally inert until Orders CRUD gets a real backend gateway. See `BACKEND-API-REFERENCE.md` §12.8.
|
||||
- Design/plan: `docs/superpowers/specs/2026-08-15-admin-purchase-notifications-design.md`, `docs/superpowers/plans/2026-08-15-admin-purchase-notifications.md`.
|
||||
|
||||
## 2026-08-14 — Currency conversion (client-side)
|
||||
|
||||
Switching currency (RUB/USD/EUR/AMD) now actually converts displayed prices, instead of just swapping the currency label next to an unchanged number.
|
||||
|
||||
- `CurrencyRatesService` (new) holds RUB-based conversion rates, admin-editable in Admin Settings → Currency rates, persisted to `localStorage`.
|
||||
- `CurrencyConvertPipe` (new) applies the selected currency's rate wherever a storefront price renders: product cards, product detail page, quick-view dialog, delivery pricing, compare table, cart line items and totals, delivery selector.
|
||||
- Admin backoffice screens intentionally keep showing raw stored-currency values — that's the existing convention for every other admin price display.
|
||||
- Fixed a follow-on bug: the cart's delivery-selector component was using the item's *source* currency as both the display label and the conversion target, so the amount never actually converted (only the label matched) — same number shown in every currency.
|
||||
- **Depends on backend:** rates are a manually-typed admin number today, not a live exchange rate, because the backend doesn't return per-currency pricing. See `BACKEND-API-REFERENCE.md` §12.7 for the two proposed backend directions (server-side conversion, or a live FX-rate endpoint) — raised because bank settlement totals weren't reconciling against order counts, which points at a real pricing-accuracy gap, not just a display one.
|
||||
|
||||
---
|
||||
|
||||
Earlier history: `git log`.
|
||||
Reference in New Issue
Block a user