Phase 8 (Core): stateful draft, quick-sell, objectives by ID, market listings
CI / Build, lint & test (push) Failing after 1m21s

Draft v2 — stateful FUT-style pick sessions:
  - POST /draft/start?difficulty=<> — creates session, returns 5
    candidates for GK slot (position order: GK RB CB CB LB CDM CM CAM RW ST LW)
  - POST /draft/sessions/:id/pick { card_id } — validates candidate,
    advances to next position; on last pick grants coins+pack reward
    (avg OVR ≥84 → gold pack + 2000 coins, ≥78 → silver + 1000, else 400)
  - GET /draft/sessions/:id — session state with per-pick cards
  - POST /draft/sessions/:id/abandon — cancel without reward
  - Migration 0005_draft_sessions.sql

Quick-sell:
  - DELETE /collection/:owned_card_id — removes card, credits coins based
    on overall (85+ → 1500, 80-84 → 900, 75-79 → 600, 65-74 → 300, <65 → 150)

Objectives:
  - GET /objectives/:id — single objective with progress
  - POST /objectives/:id/claim — claim reward by URL param (complement to
    existing POST /objectives/claim body-param endpoint)

Market:
  - GET /market/my-listings — active listings posted by current club
  - DELETE /market/listings/:id — cancel a listing, returns card to collection

Tests: 9 new integration tests (37 total, all passing)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
funman300
2026-06-25 16:41:55 -07:00
parent 8fa125cfd6
commit bfd6de6896
12 changed files with 828 additions and 9 deletions
+24
View File
@@ -125,6 +125,10 @@ pub async fn build(pool: Pool, cfg: Config) -> Result<Router> {
.route("/cards", get(routes::cards::get_cards))
.route("/cards/:card_id", get(routes::cards::get_card))
.route("/collection", get(routes::cards::get_collection))
.route(
"/collection/:owned_card_id",
delete(routes::cards::delete_owned_card),
)
.route("/packs", get(routes::packs::get_packs))
.route("/packs/buy", post(routes::packs::post_buy_pack))
.route("/packs/open/:pack_id", post(routes::packs::post_open_pack))
@@ -134,10 +138,15 @@ pub async fn build(pool: Pool, cfg: Config) -> Result<Router> {
.route("/squads/:squad_id", get(routes::squad::get_squad_by_id))
.route("/squads/:squad_id", delete(routes::squad::delete_squad))
.route("/objectives", get(routes::objectives::get_objectives))
.route("/objectives/:objective_id", get(routes::objectives::get_objective))
.route(
"/objectives/claim",
post(routes::objectives::post_claim_objective),
)
.route(
"/objectives/:objective_id/claim",
post(routes::objectives::post_claim_objective_by_id),
)
.route("/matches", get(routes::matches::get_matches))
.route("/matches/opponent", get(routes::matches::get_opponent))
.route("/matches/result", post(routes::matches::post_match_result))
@@ -148,6 +157,11 @@ pub async fn build(pool: Pool, cfg: Config) -> Result<Router> {
.route("/market/buy", post(routes::market::post_market_buy))
.route("/market/sell", post(routes::market::post_market_sell))
.route("/market/refresh", post(routes::market::post_market_refresh))
.route("/market/my-listings", get(routes::market::get_my_listings))
.route(
"/market/listings/:listing_id",
delete(routes::market::delete_market_listing),
)
.route("/statistics", get(routes::statistics::get_statistics))
.route(
"/statistics/history",
@@ -156,6 +170,16 @@ pub async fn build(pool: Pool, cfg: Config) -> Result<Router> {
.route("/settings", get(routes::settings::get_settings))
.route("/settings", put(routes::settings::put_settings))
.route("/draft/squad", get(routes::draft::get_draft_squad))
.route("/draft/start", post(routes::draft::post_draft_start))
.route("/draft/sessions/:id", get(routes::draft::get_draft_session))
.route(
"/draft/sessions/:id/pick",
post(routes::draft::post_draft_pick),
)
.route(
"/draft/sessions/:id/abandon",
post(routes::draft::post_draft_abandon),
)
.route("/events", get(routes::events::get_events))
.route("/events/:event_id", get(routes::events::get_event))
.route(