A hall with four seat grades and three audiences sells twelve tariffs, and a season of forty productions means retyping them forty times. Nothing helps with that today: cloning is switched off on purpose (the entity_clone operation is stripped from every yoyaku entity, because bookings and transactions must never be cloned), the venue package deliberately excludes the sales setup, and the slot generator only seeds downwards, from a resource's own tariffs onto its slots.
What sites do instead is visible in real data: two productions in the same hall each carry the same seven tariffs, and because the audience had nowhere to live, its name was typed into every label, giving rows like "Plein tarif - Catégorie 1" and "Tarif jeune - Catégorie 1".
Proposal
A yoyaku_tariff_preset: a named, reusable set of tariff prototypes, each carrying a price and a quota for one (grade, tariff class) cell. Applying a preset to a production creates its tariffs already priced and capped. "Grille A" and "Grille B" then describe how a house prices a big production against a small one, and a gala that should offer fewer reduced seats becomes a quota on one cell instead of a manual edit repeated across every production.
Overrides must always win. A price or quota typed on a tariff, or on a single session's slot tariff, outranks whatever the preset supplied. The chain today is the slot tariff's price, then the tariff's own payment block when it does not inherit, then the resource block; a preset belongs below both overrides and above the resource default.
Open questions to settle here
- Prototypes or live source? Copying rows when a preset is applied needs no new read path, lets a production diverge freely, and cannot move prices for tickets already on sale. Keeping the preset as the source of truth lets a mid-season repricing propagate, but needs a resolution step for price and a second one for quota, and no quota resolution exists at all today.
- Where a preset lives. Grade keys are unique within a venue, so a preset naming grades is already bound to one hall. Venue scope makes that structural and mirrors the venue-default-plus-resource-override chain that placement configurations use; tenant scope reads better in the admin menu but needs a constraint to stop one preset mixing two halls' grades. A row naming no grade would let venue-less resources use a preset too.
- A tariff that merges grades. One tariff may price several grades a production does not distinguish. If those grades sit at different prices in the preset, either the merged tariff keeps its own price, or the preset is keyed by tariff class alone and the grade set stays the tariff's business.
Prerequisite, folded in deliberately
The tariff class has no administrative interface at all: it is absent from the entity UI map, declares no link templates, and can only be created in code. It is also scoped per resource, which would fragment the vocabulary the moment two presets each invented their own "Plein tarif". So it needs to become a tenant-level vocabulary with its own collection route before a preset can reference it. That work sits in this issue rather than a separate one, because a preset is the reason it matters.
Depends on #3614378: Rename the category entities to tariff, because to a buyer a category is a seat grade, which gives these entities the names used above.
Issue fork yoyaku-3614386
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #4
mably commented