Issue #3626904: Row operation links are written five times, the way back to a locked order re-implements Orchestra's resolver, and the docs miss the delete rules

Closes #3626904.

MERGE THIS LAST, AND MERGE NOTHING AFTER IT BEFORE TAGGING. Its last commit regenerates docs/metrics.md on 1.x as it stands with !398 (merged) and !400 (merged) merged, and the tag pipeline measures that page against a fresh count.

  • One trait builds every table's Edit and Delete links (first commit). RowOperationsTrait moves from yoyaku_ui to the engine (Drupal\yoyaku\Form), beside SelectableOverviewFormBase, so yoyaku_placement, which cannot depend on the admin UI, uses it too. The four copies go:
    • ResourceTariffOrderForm::getRowOperations() is deleted;
    • ApplyTariffPresetForm::getRowOperations() keeps only its back URL;
    • VenueInventoryOrderFormBase::getOperations() keeps only its back URL;
    • InventoryListTrait::getRowOperations() is deleted, and the trait now composes RowOperationsTrait.
  • The way back to a locked order asks Orchestra (second commit). CheckoutResumeHooks::getParkedPaymentToken() ran its own query for an instance's parked tokens and read each node's interaction by hand. It now asks InteractionResolver::findParkedInteractiveTokens() and getNodeInteraction(), which answer in token-id order and leave out an interaction whose plugin is gone. The resolver arrives as a service closure: the booking page builds this hook class on every view and never asks, so it costs that page nothing. The class loses two dependencies.
  • Docs (third and fourth commits). Deleting records also covers the rules !398 (merged) added: ReferencingRecords and the tariff, resource type and tariff class refusals, what goes with a record, and the booking that is released or canceled rather than deleted.
  • Docs, first part (third commit). docs/booking-channels.md names BookingChannelField::getDefinition(), its real name. docs/api.md gains Deleting slots and resources: what is refused, the two methods that count what is left, and the slot delete cascade in a finally block, as the example modules use it.

Cost: none added. The trait builds the same links; the resolver runs the same query the copy ran, ordered, and only where a way back is looked for.

Tests: these are refactors, so the existing tests over those screens are their test, and all pass locally:

  • the tariff order, apply-preset and slot overview screens (ResourceTariffOrderTest, ResourceTariffColumnOrderTest, TariffPresetAdminTest, SlotOverviewFilterTest);
  • the placement inventories (PinnedPlaceMapFormTest, ScreenReadCountTest);
  • the way back to a locked order (CheckoutResumeControllerTest, whose hand-built hooks now take the resolver's closure).

AI-Generated: Yes (Claude Code was used to write this change and this description. I reviewed them before posting.)

Edited by Frank Mably

Merge request reports

Loading
Loading