Track purchase prices so FPL selling prices can be computed #18
Labels
No labels
architecture
cleanup
dependencies
performance
priority: high
priority: medium
reliability
security
testing
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
solvreven/FPL#18
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found 2026-08-29 from a user report: "Tried to sell Maguire, says I have
4.7 million, but I've bought Lewis Hall for 5.0, which was the exact amount of
money I had as well."
The 4.7 is not a rounding slip or a stale cache. It is arithmetic the app
cannot do correctly, because it has no representation of money at all.
What the app actually computes (
main.py, /api/squad):totalis the sum of every pick's current price. Reproduced exactlyagainst the live bootstrap:
Why that is not a bank. It is only equal to your money if two things hold:
your squad cost exactly 100.0 to assemble, and no price has moved since. Both
fail the moment a season starts.
What is missing, concretely.
data/squad.jsonis:Ids and nothing else. There is nowhere to record what a player cost when it was
bought, so:
half of any rise, rounded down to 0.1 — never the current price. The app has
never stored a purchase price, so every sale it models is wrong by up to
half the player's appreciation.
exactly this: 5.0 in hand, 5.0 spent on Hall, so 0.0 remains. The app
recomputed 4.7 from today's prices — a number with no causal relationship to
the user's money, which happens to look plausible.
Note also that the file holds 14 picks, not 15, and contains neither
Maguire nor Hall. So it has drifted from the real team as well, and nothing
detects that: a 14-man squad simply produces a larger "bank".
A plausible number with no provenance is the failure this repo names first.
The 4.7 is well-formed, correctly typed, in the right units, and on screen
beside real data — indistinguishable from a measurement.
Suggested fix, in two independent parts.
Part 1 — take the bank from FPL instead of deriving it.
entry/{id}/needsno authentication and carries it, verified today:
The app currently has no idea which FPL entry is the user's — there is no entry
id in config, no
/entry/call anywhere, and no sync route (your_xiandfriends in squad.json can only arrive via a hand-made POST to
/api/squad).Storing an entry id would also make the squad self-syncing rather than
hand-maintained, which is the drift above.
Part 2 — record purchase price per pick. Extend squad.json from a list of ids
to a list of
{id, bought_for}and compute selling price by FPL's rule. Thisis the only way to get sales right, and it is independent of Part 1: the bank
can be authoritative while sale proceeds are still wrong, and vice versa.
my-team/{id}/returnsselling_priceper pick directly and would settle bothat once, but it requires a logged-in session — checked today, returns HTTP
error unauthenticated. Worth noting as the ideal source if a login is ever
added, and worth NOT waiting for.
Until either lands, the bank figure on screen should say what it is — a
budget-minus-current-prices estimate, not your bank. A wrong number labelled as
an estimate is a different object from a wrong number presented as a fact.
Related: #12 (the app reports cache freshness but never its own code version) —
same family, a displayed value whose provenance is not stated.
Authoritative bank/selling prices require user-specific state that is not currently available. Please provide or decide:
bought_forfield now, or wait for authenticatedmy-team/{id}/access?data/squad.jsonbe migrated when purchase prices are unknowable: reject it, preserve picks with “selling price unavailable”, or ask once for explicit values?The migration policy is especially important: inventing purchase prices would recreate the provenance defect described by this issue.
Partly implemented on
fix/gw2-window-and-provenance(9d9bd4d, pushed just now). Answering the questions above against what exists.6261. It lives in.envasFPL_ENTRY_ID, i.e. local and private, not repository config.backend/web/fpl_team.pyreads it; with none configured the sync refuses and says what is missing rather than defaulting.entry/{id}/event/{gw}/picks/carries the 15 picks, captain, vice andentry_history.bank. Confirmed against the live account: bank is now0.0from FPL where the derived figure said4.7, which is what prompted the report. Manual squad editing still works; the sync merges over the keys it owns and leaves notes/overrides alone.my-team/{id}/, which requires a login; verified unavailable unauthenticated. Nobought_forfield has been added, deliberately: inventing one would be a plausible number with no provenance.data/squad.jsonis preserved and enriched, not rejected.fetch_squadrefuses anything that is not exactly 15 picks, because a short squad silently becomes a larger bank, which is the state the hand-written file had drifted into (14 picks containing neither Maguire nor Hall)./api/squadcarriesbank_source: "FPL" | "ESTIMATE"andsynced_gw, so the screen can say which it is instead of hedging permanently. A derived figure is still labelled as an estimate; a synced one is not.Also fixed alongside it:
validate_squadcompared today's prices against the constant 100.0, so a legal synced team came back "budget exceeded: 1003 > 1000". It now takes the squad's own value plus bank.What is left for this issue: purchase/selling prices only. Suggest the title or scope be narrowed to that, since bank itself is no longer derived.
WHAT THE PUBLIC ENDPOINT CANNOT KNOW, stated because the UI has to: it serves the team as of a deadline that has passed. A transfer made for the next round is not published until that round locks. So during a round it returns the team playing; between rounds it returns the team that just played, not the one being planned.
synced_gwis on every response so that distinction is visible rather than inferred.Bank is derived as budget minus current prices, not tracked; selling prices are unknowableto Track purchase prices so FPL selling prices can be computed