Part number variants: optional {variant} token, derived families#45
Open
abbyfluoroethane wants to merge 4 commits into
Open
Part number variants: optional {variant} token, derived families#45abbyfluoroethane wants to merge 4 commits into
abbyfluoroethane wants to merge 4 commits into
Conversation
Adds an optional {variant} placeholder to the part numbering format
(default 3-digit code, width configurable in the wizard). New parts mint
variant 001; POST /api/parts/{id}/variants creates a draft sibling with
the next code, copying attributes and BOM. Families are derived from the
PN itself — one fact, one home — so no schema change; variant codes are
never reused and the tier sequence counter never advances for variants.
Part page gains a VARIANT action and a VAR ledger row, both absent when
the format mints no variants.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
/parts/{pn} is now the canonical detail URL; id URLs 302-redirect to it
(parts whose PN holds a '/' or shadows a literal sibling route stay
id-addressed). VARIANT now opens the shared part form in a third mode —
identity rendered as locked facts (next code, source tier), every other
field prefilled from the source and editable — via the /parts/{ref}/variant
deep link; the variants endpoint accepts an optional override body
(omitted fields copy, explicit nulls clear, identity never overridable).
BOM still copies server-side and is edited on the new draft's page.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Parts numbered before {variant} entered the format (e.g. 001-0001) no
longer fall outside the feature: a base regex (format with the {variant}
segment stripped) places them in their tier+sequence family as variant 1,
so the VARIANT action appears and the first explicit variant mints -002 —
code 001 stays a permanent gap, because the base IS configuration 1.
Without this, enabling {variant} on an existing fleet left every
pre-existing part with no way to mint variants.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The wizard's VARIANT DIGITS select becomes VARIANTS: OFF / 2 / 3 / 4
digits. Choosing a width appends {sep}{variant} to the format template;
OFF strips it — the format string remains the single home of the on/off
fact, and hand-edits to the template sync the select back. No backend
change: enablement was already derived from the format.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
{variant}placeholder to the part numbering format ({tier_code}{sep}{sequence}{sep}{variant}), with a configurablevariant_digitswidth (default 3) in the project wizard. Formats without{variant}behave byte-identically to today.001;POST /api/parts/{id}/variantscreates a draft sibling with the next code, copying attributes and BOM lines (audit-logged). An optional body overrides the copied attributes (omitted fields copy, explicit nulls clear; tier/PN never overridable)./parts/{pn}is the canonical detail URL; id URLs 302-redirect to it (PNs containing/or shadowing literal sibling routes stay id-addressed)./parts/{ref}/variant): next code and tier rendered as locked facts, everything else prefilled from the source and editable; submit lands on the new draft's page where the existing BOM ledger handles modifications. Part page also gains a VAR ledger row listing live siblings.Test plan
uv run pytest --no-cov— 601 passed, 1 skipped (numbering round-trips, counter isolation, never-recycle, endpoint override/null/parent semantics, PN-URL resolution + redirects, variant-form rendering, graceful degrade without{variant})/parts/RV-F-0001-001direct 200;/parts/1→ 302 to PN URL; VARIANT → form showsRV-F-0001-002locked + prefilled name; rename + CREATE VARIANT → draft created with BOM copied; sibling listed in VAR ledger🤖 Generated with Claude Code