Today the only way to stop a constraint policy enforcing is to remove it from its host. That loses the settings it was tuned with, and on a resource type it loses more: the policy list is a sequence, so removing one entry shifts the index of every entry after it, and the booker message is a translatable label keyed by that index. An operator who lifts a cap for one concert and puts it back afterwards retypes the numbers, and the translated message of the entries below has moved.

What is wanted is an operator-facing switch: a policy that is stored, listed and editable, but not asked.

Proposed shape. An enabled boolean on the policy entry itself, beside id and settings. Not inside settings: whether a policy is asked at all is the engine's business, not the plugin's. A key inside settings would have to be declared once per plugin id, since the settings type is resolved as yoyaku.constraint_policy.[%parent.id], and it would then be handed to every plugin as configuration none of them reads. ConstraintPolicyBase::setConfiguration() already rebuilds a plugin's configuration down to settings alone, so an entry-level key cannot reach a plugin by accident.

An absent key means enabled, deliberately. This is pre-1.0, so there is no update hook and existing entries carry no flag; the safe reading of a missing one is that the rule still bites.

The seams this touches.

  • ConstraintPolicyResolver::normalize() rebuilds every entry as an id and its settings, so it silently strips anything else. The new key has to be carried there first or nothing downstream ever sees it.
  • ConstraintPolicyManager::attachmentsFor() is the single gate feeding both evaluate() and ceilingFor(), so skipping a switched-off entry there stops it refusing and stops it capping a quantity stepper. Skip before the missing-plugin check, so an entry that is off and names a plugin that has gone is neither logged nor answered with the stand-in that refuses.
  • ConstraintPolicyResolver::sharesLimit() does not go through the manager. It reads the stored list to expand a cross_resource_limit name into the resources sharing it, so a switched-off cross-resource limit on one resource would keep dragging that resource into the set counted by an enabled limit elsewhere. This is the seam that testing the refusal alone will not find.
  • The add and edit form rebuilds the stored entry from scratch on save, so it has to carry the flag or editing a policy re-enables what an operator switched off. The checkbox belongs outside the settings subform, which the plugin owns.
  • The overview lists a policy's settings but not its state, so it needs a column of its own.
  • yoyaku.constraint_policy_attachment in the engine's schema gains the boolean. The content hosts keep their policies in a JSON field and need nothing.

It applies at every checkpoint, including the hold. The per-transaction waiver an operator sets by confirming anyway is honored everywhere but the hold, because it says one finished order may be confirmed as it stands. A policy that is off is not a rule at all while it is off, so it is skipped at the hold too. Worth writing down, because whoever implements this reads the waiver first and will be tempted to copy its carve-out.

A one-click enable and disable operation on the overview is deliberately not proposed. The checkbox sits with the settings, on the one form that already serves all four hosts, where a toggle route would add a fifth screen to each of them.

Tests.

  • A cap that refuses stops refusing once it is off, and its settings are still stored afterwards.
  • ceilingFor() reports no ceiling when the only capping policy is off, so a stepper is not capped by a rule nothing enforces.
  • resourceIdsSharingLimit() leaves out a resource whose cross-resource limit is off.
  • A type-hosted entry carrying the flag saves against the schema.
  • The checkbox round-trips through the UI, an entry stored without the key reads as enabled, and the overview states the status as text rather than by styling alone.

Docs: the constraint policies guide, in the enforcement and overrides section, beside the per-transaction waiver. The French translation ships in the same change.

Issue fork yoyaku-3614891

Command icon 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

mably created an issue. See original summary.

  • mably committed 2338dce3 on 1.x
    feat: #3614891 Let a policy be switched off without removing it, keeping...
mably’s picture

Status: Active » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.