• Mahmoud Aglan's avatar
    feat(registration): ask a product's own questions before selling it, and hold names to رباعي · d3113b08
    Mahmoud Aglan authored
    Two things the desk could not previously be made to capture.
    
    A product now carries the details it cannot be sold without — a size, a
    colour, the name printed on the back. The admin declares them per product
    as either free text or a list of predefined answers; the registration
    wizard renders them inline on the cart row and refuses to move to payment
    while a required one is blank.
    
    None of this is a separate product, and none of it is reconstructable
    after the fact from an invoice line that says "قميص تدريب" — which is why
    the answers freeze onto invoice_items.metadata and into the line
    description at sale time. Renaming "لارج" to "L" next season must not
    rewrite what a player ordered last season, exactly as prices freeze.
    
    hotbuyCustomizations is browser-writable by necessity — it is what the
    receptionist is typing — so nothing downstream trusts it. Both the step
    guard and confirm() re-read the questions through Eloquent (Product
    carries BranchScope, so another branch's product resolves to nothing) and
    check every answer against ProductCustomization::accepts(). A select must
    match its own list: the dropdown is a convenience, not the check.
    
    Separately, a person entered into the system must now carry a four-part
    name. Egyptian records are keyed on it — national ID, birth certificate,
    federation card, school file — and a player registered as "محمد أحمد"
    matches none of them; two players sharing a first and father's name are
    common enough that parts three and four are what tell them apart. Applied
    where people are created at the desk and in the portal: the registration
    wizard (player and guardian), retroactive enrolment, the participant form,
    and portal sign-up. Four is a floor, not a target.
    
    FullName splits on Unicode whitespace explicitly. \s under /u still only
    means ASCII whitespace, and an Arabic keyboard produces U+00A0 — glued
    together, a perfectly valid four-part name would have been rejected.
    
    Deliberately left alone:
    - ParticipantImport is exempt. Enforcing the rule on a bulk import would
      block loading an existing roster, which is the one case where the short
      names are already a fact.
    - Records already in the database are untouched. This validates at entry.
    - The POS terminal, settlement wizard, group screen and essential-
      deliveries screen sell these same products and do not yet ask for the
      customizations.
    - Kits carry no customizations, only products.
    
    Migration is additive and guarded; CHECK constraint matches the enum
    character for character. 382 passed / 99 skipped on the restored Postgres
    tenant, 303 passed / 178 skipped on SQLite.
    Co-Authored-By: 's avatarClaude Opus 5 (1M context) <noreply@anthropic.com>
    d3113b08
Name
Last commit
Last update
Screenshots Loading commit data...
app Loading commit data...
bootstrap Loading commit data...
config Loading commit data...
database Loading commit data...
docker Loading commit data...
docs Loading commit data...
docs-site Loading commit data...
flutter_shell Loading commit data...
gap-filling-plans Loading commit data...
lang Loading commit data...
marketing-site Loading commit data...
plans Loading commit data...
public Loading commit data...
reference/oc-sport Loading commit data...
resources Loading commit data...
routes Loading commit data...
scripts Loading commit data...
storage Loading commit data...
tests Loading commit data...
.dockerignore Loading commit data...
.editorconfig Loading commit data...
.env.example Loading commit data...
.gitattributes Loading commit data...
.gitignore Loading commit data...
.npmrc Loading commit data...
Beanding Guide.txt Loading commit data...
CLAUDE.md Loading commit data...
Dockerfile Loading commit data...
README.md Loading commit data...
artisan Loading commit data...
captain-definition Loading commit data...
composer.json Loading commit data...
composer.lock Loading commit data...
deploy.sh Loading commit data...
elcaptain-sportsonly-db.md Loading commit data...
one-click-app.yml Loading commit data...
package-lock.json Loading commit data...
package.json Loading commit data...
phpunit.xml Loading commit data...
system info.txt Loading commit data...
vite.config.js Loading commit data...
نادى الشيخ زايد كشف بيانات اللاعبين (2).html Loading commit data...