Problem
Every record assumes a linked Price Guide Price (PGP) in the prices table. The PGP is the canonical source for artist, label, format, year range, detail, footnote, and price range — pulled from the imported Goldmine guide. With a linked PGP a record is "real": valuation works, metadata is full, search lights up. Without one, the record is half-real and falls out of most flows.
Today, the only way to link a price is via Price Guide Review (/admin/price_review/:id, see #320), which can ONLY pick from existing PGPs. Two cases break:
- Creating a record where no PGP exists yet → the record gets stranded with no price link, no proper metadata, no valuation. Nothing in the UI lets you create the missing PGP.
- A linked PGP is wrong (wrong pressing, wrong year, typo'd detail, bad price range) → there's no way to fix it. You can clear the link, but then you're back to case 1.
We used to support user-created PGPs — schema still has prices.user_id (every PGP, imported or not, has one), and there are real user-created entries already in the DB from a 2017 "priceless records" feature that was removed without a replacement (commit 4fe7b67 added it, 41085fa deleted it).
This is a single-user workflow. No flagging, no review queues, no new schema — the user creating or editing the PGP is the same person who'll use it. Just give them the tools.
Proposed Solution — two flows
Flow 1 — Create a PGP inline while creating a record
The record creation form (/records/new, app/views/records/_form.html.erb) currently has no price field at all. Add a price selector that:
- Searches the existing
prices table as you type (artist + label + detail), same query the Price Review page uses
- If a match exists → pick it, done
- If nothing matches → "+ Create new price guide entry" opens an inline form that prefills from what you've already entered on the record form (artist, label, format, year, media type)
- On submit, the new PGP is created and the record is linked to it in the same save
┌──────────────────────────────────────────────────────────┐
│ New Record │
│ ────────────────────────────────────────────────────── │
│ Artist * [ EL DORADOS ] │
│ Label * [ VEE-JAY ] │
│ Format * [ Singles: 7-inch ▼ ] │
│ Year [ 1955 ] │
│ Condition [ VG+ ▼ ] │
│ │
│ Price Guide Entry │
│ ┌──────────────────────────────────────────────────┐ │
│ │ 🔍 Search… │ │
│ └──────────────────────────────────────────────────┘ │
│ ↳ no matches found for \"EL DORADOS VEE-JAY\" │
│ │
│ [ + Create new price guide entry ] │
│ │
│ [ Cancel ] [ Create Record ] │
└──────────────────────────────────────────────────────────┘
Clicking "+ Create new price guide entry" expands inline (Turbo frame, no nav):
│ Price Guide Entry │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Artist * [ EL DORADOS ] (from form)│ │
│ │ Label * [ VEE-JAY ] (from form)│ │
│ │ Format * [ Singles: 7-inch ▼ ] (from form)│ │
│ │ Media type [ Black vinyl ] │ │
│ │ Detail [ 147 \"At My Front Door\" ] │ │
│ │ Year range [ 1955 ] – [ 1958 ] │ │
│ │ Price low $ [ 6000 ] │ │
│ │ Price high $ [ 8000 ] │ │
│ │ Footnote [____________________________] │ │
│ │ │ │
│ │ [ Cancel ] [ Use this entry ] │ │
│ └──────────────────────────────────────────────────┘ │
"Use this entry" stages the PGP in the form (doesn't save yet — saving happens when the user submits the record). Submitting the record creates the PGP with user_id = current_user.id and links it.
This same inline-create affordance also belongs in the Price Review page (#320) for existing records that came in without a PGP — the empty state of search there should show the same "+ Create new price guide entry" CTA, prefilled from the record.
Flow 2 — Edit a wrong PGP, or clear and recreate
When a record's linked PGP is wrong, the user has two options from the record show page:
A) Edit the PGP directly (preferred when only some fields are wrong — bad price range, typo in detail, missing footnote):
Add an "Edit price guide entry" button to the price card alongside the existing "Review / Change Price" button. It opens an edit form for the linked Price record. Saving updates the PGP — and because PGPs are shared (prices has_many :records), this affects every record linked to it. That's correct behavior in a single-user system, but the UI should warn:
┌──────────────────────────────────────────────────────────┐
│ Edit Price Guide Entry │
│ ────────────────────────────────────────────────────── │
│ ⓘ This entry is linked to 3 records. Editing affects │
│ all of them. │
│ │
│ Artist * [ EL DORADOS ] │
│ Label * [ VEE-JAY ] │
│ Format * [ Singles: 7-inch ▼ ] │
│ Detail [ 147 \"At My Front Door\" ] │
│ Year range [ 1955 ] – [ 1958 ] │
│ Price low $ [ 6000 ] │
│ Price high $ [ 8000 ] │
│ Footnote [____________________________] │
│ │
│ [ Cancel ] [ Save changes ] │
└──────────────────────────────────────────────────────────┘
B) Clear the link and create a fresh one (when the linked PGP is for a totally different pressing — wrong artist, wrong format, wrong record entirely):
This is already half-built. The Price Review page (#320) has a "Clear price link" button. After clearing, the page shows the search panel with "No price linked." The fix: the empty-search-results state on Price Review should expose the same "+ Create new price guide entry" CTA from Flow 1, prefilled from the record. Clear → search yields nothing → create → linked. One screen, no dead ends.
Distinguishing user-created vs imported PGPs
prices.user_id is required on every PGP, so we can't just check IS NOT NULL. Imports are presumably attributed to a known system/admin user. Before building anything, verify in production which user_id the imported entries point at — then user-created PGPs are simply WHERE user_id != <import_user_id>.
No new column, no new table, no schema change. If we ever need a sortier label like 👤 User-submitted next to entries in Price Review search, it can derive from this same query.
Things to design around
- Duplicates — two records each create a near-identical PGP for the same pressing instead of sharing one. Mitigation: the search-then-create pattern in Flow 1 already pushes users to pick the existing entry first; the create CTA only appears after a search returns nothing.
- Editing a shared PGP affects all linked records — surface this with the "linked to N records" notice in the edit form. Single-user system, so the trade-off is fine; just make it visible.
- Bad price ranges — basic form validation:
price_low <= price_high, both positive integers. No fancy outlier detection.
Files involved (for the implementer)
app/controllers/api/prices_controller.rb — add #create and #update
app/controllers/admin/price_review_controller.rb — add create CTA to empty state
app/views/admin/price_review/show.html.erb:142-149 — replace generic empty state with create CTA
app/views/records/_form.html.erb — add price selector with search + inline create
app/views/admin/records/show.html.erb — add "Edit price guide entry" button next to "Review / Change Price"
app/views/records/show.html.erb — same edit button if appropriate for non-admin
config/routes.rb:54 — extend prices: [:index] to include :create, :update
app/javascript/controllers/form_autocomplete_controller.js — already supports create-on-the-fly pattern (lines 137-222), reuse for the price selector
Verification checklist
Flow 1 — create during record creation
Flow 1b — create from Price Review for existing records
Flow 2 — edit a wrong PGP
Out of scope / won't do
- ❌ No flagging system, no review queue, no badges
- ❌ No new schema columns (
source, verified_at, etc.) — derive from existing user_id
- ❌ No multi-user trust hierarchy — single-user system
Problem
Every record assumes a linked Price Guide Price (PGP) in the
pricestable. The PGP is the canonical source for artist, label, format, year range, detail, footnote, and price range — pulled from the imported Goldmine guide. With a linked PGP a record is "real": valuation works, metadata is full, search lights up. Without one, the record is half-real and falls out of most flows.Today, the only way to link a price is via Price Guide Review (
/admin/price_review/:id, see #320), which can ONLY pick from existing PGPs. Two cases break:We used to support user-created PGPs — schema still has
prices.user_id(every PGP, imported or not, has one), and there are real user-created entries already in the DB from a 2017 "priceless records" feature that was removed without a replacement (commit4fe7b67added it,41085fadeleted it).This is a single-user workflow. No flagging, no review queues, no new schema — the user creating or editing the PGP is the same person who'll use it. Just give them the tools.
Proposed Solution — two flows
Flow 1 — Create a PGP inline while creating a record
The record creation form (
/records/new,app/views/records/_form.html.erb) currently has no price field at all. Add a price selector that:pricestable as you type (artist + label + detail), same query the Price Review page usesClicking "+ Create new price guide entry" expands inline (Turbo frame, no nav):
"Use this entry" stages the PGP in the form (doesn't save yet — saving happens when the user submits the record). Submitting the record creates the PGP with
user_id = current_user.idand links it.This same inline-create affordance also belongs in the Price Review page (#320) for existing records that came in without a PGP — the empty state of search there should show the same "+ Create new price guide entry" CTA, prefilled from the record.
Flow 2 — Edit a wrong PGP, or clear and recreate
When a record's linked PGP is wrong, the user has two options from the record show page:
A) Edit the PGP directly (preferred when only some fields are wrong — bad price range, typo in detail, missing footnote):
Add an "Edit price guide entry" button to the price card alongside the existing "Review / Change Price" button. It opens an edit form for the linked
Pricerecord. Saving updates the PGP — and because PGPs are shared (prices has_many :records), this affects every record linked to it. That's correct behavior in a single-user system, but the UI should warn:B) Clear the link and create a fresh one (when the linked PGP is for a totally different pressing — wrong artist, wrong format, wrong record entirely):
This is already half-built. The Price Review page (#320) has a "Clear price link" button. After clearing, the page shows the search panel with "No price linked." The fix: the empty-search-results state on Price Review should expose the same "+ Create new price guide entry" CTA from Flow 1, prefilled from the record. Clear → search yields nothing → create → linked. One screen, no dead ends.
Distinguishing user-created vs imported PGPs
prices.user_idis required on every PGP, so we can't just checkIS NOT NULL. Imports are presumably attributed to a known system/admin user. Before building anything, verify in production which user_id the imported entries point at — then user-created PGPs are simplyWHERE user_id != <import_user_id>.No new column, no new table, no schema change. If we ever need a sortier label like
👤 User-submittednext to entries in Price Review search, it can derive from this same query.Things to design around
price_low <= price_high, both positive integers. No fancy outlier detection.Files involved (for the implementer)
app/controllers/api/prices_controller.rb— add#createand#updateapp/controllers/admin/price_review_controller.rb— add create CTA to empty stateapp/views/admin/price_review/show.html.erb:142-149— replace generic empty state with create CTAapp/views/records/_form.html.erb— add price selector with search + inline createapp/views/admin/records/show.html.erb— add "Edit price guide entry" button next to "Review / Change Price"app/views/records/show.html.erb— same edit button if appropriate for non-adminconfig/routes.rb:54— extendprices: [:index]to include:create, :updateapp/javascript/controllers/form_autocomplete_controller.js— already supports create-on-the-fly pattern (lines 137-222), reuse for the price selectorVerification checklist
Flow 1 — create during record creation
/records/newform has a price selector that searches existing PGPs as you typeuser_id = current_user.idFlow 1b — create from Price Review for existing records
/admin/price_review/:idwith no search results, the same "+ Create new price guide entry" CTA appearsFlow 2 — edit a wrong PGP
price_low <= price_high, both positiveOut of scope / won't do
source,verified_at, etc.) — derive from existinguser_id