fix(api): record an elapsed group as expired when its opener cancels

Cancelling the opening unpaid order ran the expiry sweep only implicitly, so a
group whose lifetime had already ended was relabelled cancelled instead of
expired. Both conditions hold in that case; sweep first so the lifetime ending
wins. The behaviour was invisible to shoppers (neither state is joinable) but it
matters to a future refund flow reading expired paid groups.

Add an integration test that reproduces the precedence.
This commit is contained in:
2026-09-18 13:44:02 +00:00
parent cdfb1b06f2
commit d7fddf53ab
2 changed files with 33 additions and 1 deletions
+4 -1
View File
@@ -181,12 +181,15 @@ pub async fn link_opener(tx: &mut PgConnection, group_id: Uuid, order_id: Uuid)
repo::set_leader(tx, group_id, order_id).await
}
/// An unpaid opener cancelling closes a group that has no paid members.
/// An unpaid opener cancelling closes a group that has no paid members. The
/// expiry sweep runs first so an elapsed group records `expired` rather than
/// being relabelled `cancelled`.
pub async fn cancel_opener_group(
tx: &mut PgConnection,
order_id: Uuid,
group_id: Uuid,
) -> ApiResult<()> {
repo::expire_due_groups(&mut *tx).await?;
repo::cancel_empty_opener_group(tx, group_id, order_id).await?;
Ok(())
}