//! Purchase queries: the pending-transaction lifecycle, free claims, refunds //! and cart settlement. //! //! A paid checkout writes a `pending` row before the buyer leaves for Stripe, //! and completion flips it to `completed`; nothing else moves a row between //! those states. A pending row that is never completed is deleted by the //! caller who abandoned it, or by `cleanup_stale_pending` past the age the //! scheduler passes it (25h), which returns any `promo_code_id` so the //! reservation is released with the row. //! //! The dedup these queries lean on is a set of partial unique indexes on //! `transactions`, one pair per subject: //! `(buyer_id, item_id)` and `(buyer_id, project_id)`, each once for //! `status = 'pending'` and once for `status = 'completed'`, and //! `(guest_email, item_id)` for `status = 'completed'`. All are partial on //! the id being NOT NULL, so a project purchase (NULL `item_id`) does not //! collide with an item purchase. `ON CONFLICT DO NOTHING` and the 23505 //! backstops throughout this file name those indexes; changing one means //! revisiting every claim and checkout path here. mod checkout; mod claims; mod guest; mod reads; mod refunds; pub use checkout::*; pub use claims::*; pub use guest::*; pub use reads::*; pub use refunds::*;