Skip to content

V1 Baseline — Current State

V1 is the system Stefan uses today. It is not being rebuiltV2 is built directly and inherits the full V1 history via migration. This page documents V1 as a reference for what V2 must preserve, replace, and improve.

Source artifacts

  • Spreadsheet: stringing_orders.xlsx (repo root) — 4 sheets: Client-Stringing-Orders, Self-Stringing-Orders, Stats, Lists.
  • Public site: stringing.wagen.io — single page "Listing all Orders" with per-row PDF receipts at /receipt_<id>.pdf. Backed by a script that reads the XLSX directly; no separate database.

Sheets at a glance

Client-Stringing-Orders

The big one — 329 real orders, IDs 1..329, dates 2019-05-02 → 2026-04-25. Two-row header (group label + field), 35 columns:

Group Fields
ID ID (sequential)
Dates Ordered, Strung, Returned, Paid
Player Last Name, First Name
Racquet Model, Head Size, String Pattern
Main-String Manufacturer, Model, Gauge, Tension, Price, BYO (Yes/No)
Cross-String Manufacturer, Model, Gauge, Tension, Price, BYO
Price Labor, Strings (formula skips price for BYO sides), Total
DT empty in samples — Dynamic Tension reading
Comments free text
Status derived: Ordered, Strung, Payment open, Done
Stats derived: Year, Month, Strung (any-of-status)

47 distinct players, 65 distinct racket-model strings (free text — same model written multiple ways), ~43 distinct string mfr/model combos.

Self-Stringing-Orders

Stefan's own jobs — 416 rows, dates 2020-03 → 2026-04. 20 columns. Single date (Strung). Uses a per-racket ID (e.g. PA98_2023_45, B98_V8_NS_43) that VLOOKUPs into Lists for model + pattern. Adds Color per side, Method (e.g. "Standard"), Dynamic Tension After Stringing. No prices, no payment, no player.

Lists

Two lookup tables:

  • BYO: Yes / No.
  • My Racquets: 30 of Stefan's own rackets — ID, Racket, String Pattern, Head Size, Year, Current (in rotation), # Stringjobs (COUNTIF).

Stats

Derived dashboard: counts and revenue, all-time and per-year (2019–2027), Self vs Client split, plus a 12-month cross-tab.

V1 domain model (synthesis)

Entities

  • Player / Client — identified only by (Last Name, First Name). No email, phone, address, or stable ID. Stefan himself is on a separate sheet.
  • Client Racket — free-text model + head size + string pattern, attached directly to an order. No persistence across orders.
  • Own Racket — first-class entity in Lists, with stable ID, year, in-rotation flag, history count. Linked from Self-Stringing-Orders by ID.
  • Stringing Order / Job — central record. For clients, 4-stage lifecycle: Ordered → Strung → Returned → Paid. For self-jobs, single Strung date.
  • String Spec (per side: Main, Cross) — manufacturer, model, gauge, (color for self), tension, price, BYO flag.
  • Receipt — PDF artefact per client order at receipt_<id>.pdf.

Primary flows

  1. Client stringing job (happy path): Stefan logs order with player + racket + main/cross specs and tensions, sets Ordered date. Strings the racket, sets Strung date and any Comments / DT. Returns to player, sets Returned date. Receives payment, sets Paid date. Status columns derive lifecycle position. Pricing auto-computes (BYO sides excluded). Receipt PDF served by the website.
  2. Self stringing job: Stefan picks one of his own rackets (by ID), records main/cross strings + tensions + colors + method + post-stringing DT.
  3. Reporting: Stats sheet rolls up counts and revenue per year and per month, Self vs Client.
  4. Public visibility: stringing.wagen.io exposes the full client-orders list and printable receipts to anyone with the URL.

Implicit business rules

  • Each order has exactly one player, one racket, one main string spec, one cross string spec.
  • "BYO = Yes" on a side excludes that side's price from the Strings subtotal.
  • A job is "Done" only when both Returned and Paid are set.
  • Stefan's own rackets have richer modelling than client rackets (because he tracks per-racket performance over time).
  • Dates are required in causal order (Ordered ≤ Strung ≤ Returned ≤ Paid), not enforced by the spreadsheet.

Data findings

Computed from the XLSX on 2026-04-27:

  • Main vs Cross identity (same mfr + model + gauge): Client 89.1%, Self 87.7%. Hybrid setups are the ~11% minority. → "Same as main" shortcut for cross is the right default.
  • BYO (client orders): Main 48.3%, Cross 49.2%, both sides 48.3%, cross-only 0.9%, main-only 0%. → BYO is essentially all-or-nothing in practice.
  • Tension delta (main − cross): mean +0.46 kg, median 0.00, range −1.0 to +2.0. 95% of orders are at delta 0 or +1 kg. → UI should default cross-tension = main-tension with a one-tap ±1 kg nudge.

Gaps and smells visible in V1

  • Client identity has no stable key — duplicate or misspelled names will silently create new "players".
  • Client rackets are free-text — no normalization; "Wilson Blade 98" vs "Wilson Blade 98 V7" vs "Wilson Blade 98 V8 (306g)" all coexist.
  • String catalogue is free-text on both sides — same string typed inconsistently.
  • No contact info → no way to notify a client that their racket is ready.
  • The public site exposes client names with no auth — fine in a friend-circle context but not intentional.
  • Receipts are static PDFs — invoicing/payment status invisible to the client.
  • Spreadsheet and website are two stores fed by a script — risk of drift.

Migration commitment

V2 migrates the full XLSX history: all 329 client orders + all 416 self orders + Stefan's Lists.My Racquets rackets. See data model for the target shape and the V2 scope Must list (M15).