A charge-mode security deposit cannot be returned without refunding the whole booking

Authorize mode has "Release deposit", which voids a hold and leaves the price alone. Charge mode had no counterpart: the caution is collected inside the checkout amount, so the only way to give it back was to refund the whole booking and collect the price again by hand.

One step, both modes. yoyaku_release_deposit now answers for whichever form the guarantee took, because a workflow branches on how the stay went and not on how a resource happens to be configured. It voids an authorized hold, and it refunds the charge-mode caution total out of the captured checkout payment, labelling the refund PaymentPurpose::GUARANTEE so a returned deposit reads as a deposit in reporting while the payment it came from stays booking. The price stays captured. No example-workflow change at all: both existing nodes, the attended path and the rejection path, start working in charge mode, and [#3614440] stays a rename.

It gains an optional amount, mirroring what yoyaku_capture_deposit already has, for the case where some damage was done and only part of the guarantee goes back. A hold cannot be voided in part, so it is released whole either way, and the description says so.

Two consequences settled with it. refundablePayments() now tests the balance rather than the amount, so a payment whose deposit has already gone back is still refundable for its price and one refunded in full is not. And RefundOrderAction reports what actually went back on that step rather than the payment's original figure, which the two differ on the moment a deposit has been returned: a notification that overstates a refund is worse than one that says nothing.

What this depends on. Partial refunds in kessai, [#3614923] (kessai MR !40 (merged), CI green). This MR calls refund($payment, $amount, $kind) and reads getBalance(), so its own phpstan and phpunit lanes stay red until that lands in drupal/kessai 1.x-dev and is repackaged. Verified locally against the kessai branch: every kernel class green, one class at a time.

Tests: a new DepositReturnTest covering the charged deposit coming back while the price stays captured, the refund being recorded as a guarantee, an authorize-mode hold still being voided with nothing taken out of the price, a partial return, a booking with no deposit coming out of the step untouched, and a later cancellation refunding only the price and reporting only the price. Proved fail-first: with the new path disabled, four of the six fail and the two that pass are exactly the ones that do not depend on it. PaymentActionsTest pins the new amount setting. Also run green: DefaultSettlementSubscriberTest, RefundPolicyResolverTest, RejectionPathShapeTest, PaymentCascadeDescriberTest, PaymentPolicyResolverTest, CheckoutPolicyTest, BookingRouteOutcomeTest.

Prose swept where the behavior moved, per the issue's own correction: PaymentPurpose and DefaultSettlementSubscriber both described a charge-mode deposit as a guarantee payment of its own, which never existed. docs/payment.md and docs/deposits.md now say how a charged caution comes back. French translation updated.

Merge request reports

Loading
Loading