@@ -92,7 +92,7 @@ WITH state AS ( |
| 92 | ELSE org_billing_states.grace_until | 92 | ELSE org_billing_states.grace_until |
| 93 | END, | 93 | END, |
| 94 | updated_at = now() | 94 | updated_at = now() |
| 95 | - RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 95 | + RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 96 | ), org_update AS ( | 96 | ), org_update AS ( |
| 97 | UPDATE orgs | 97 | UPDATE orgs |
| 98 | SET plan = $2::org_plan, | 98 | SET plan = $2::org_plan, |
@@ -100,7 +100,7 @@ WITH state AS ( |
| 100 | WHERE id = $1::bigint | 100 | WHERE id = $1::bigint |
| 101 | RETURNING id | 101 | RETURNING id |
| 102 | ) | 102 | ) |
| 103 | -SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 103 | +SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 104 | ` | 104 | ` |
| 105 | | 105 | |
| 106 | type ApplySubscriptionSnapshotParams struct { | 106 | type ApplySubscriptionSnapshotParams struct { |
@@ -139,6 +139,7 @@ type ApplySubscriptionSnapshotRow struct { |
| 139 | LastWebhookEventID string | 139 | LastWebhookEventID string |
| 140 | CreatedAt pgtype.Timestamptz | 140 | CreatedAt pgtype.Timestamptz |
| 141 | UpdatedAt pgtype.Timestamptz | 141 | UpdatedAt pgtype.Timestamptz |
| | 142 | + LastEventAt pgtype.Timestamptz |
| 142 | } | 143 | } |
| 143 | | 144 | |
| 144 | func (q *Queries) ApplySubscriptionSnapshot(ctx context.Context, db DBTX, arg ApplySubscriptionSnapshotParams) (ApplySubscriptionSnapshotRow, error) { | 145 | func (q *Queries) ApplySubscriptionSnapshot(ctx context.Context, db DBTX, arg ApplySubscriptionSnapshotParams) (ApplySubscriptionSnapshotRow, error) { |
@@ -178,6 +179,7 @@ func (q *Queries) ApplySubscriptionSnapshot(ctx context.Context, db DBTX, arg Ap |
| 178 | &i.LastWebhookEventID, | 179 | &i.LastWebhookEventID, |
| 179 | &i.CreatedAt, | 180 | &i.CreatedAt, |
| 180 | &i.UpdatedAt, | 181 | &i.UpdatedAt, |
| | 182 | + &i.LastEventAt, |
| 181 | ) | 183 | ) |
| 182 | return i, err | 184 | return i, err |
| 183 | } | 185 | } |
@@ -260,7 +262,7 @@ WITH state AS ( |
| 260 | ELSE user_billing_states.grace_until | 262 | ELSE user_billing_states.grace_until |
| 261 | END, | 263 | END, |
| 262 | updated_at = now() | 264 | updated_at = now() |
| 263 | - RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 265 | + RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 264 | ), user_update AS ( | 266 | ), user_update AS ( |
| 265 | UPDATE users | 267 | UPDATE users |
| 266 | SET plan = $2::user_plan, | 268 | SET plan = $2::user_plan, |
@@ -268,7 +270,7 @@ WITH state AS ( |
| 268 | WHERE id = $1::bigint | 270 | WHERE id = $1::bigint |
| 269 | RETURNING id | 271 | RETURNING id |
| 270 | ) | 272 | ) |
| 271 | -SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 273 | +SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 272 | ` | 274 | ` |
| 273 | | 275 | |
| 274 | type ApplyUserSubscriptionSnapshotParams struct { | 276 | type ApplyUserSubscriptionSnapshotParams struct { |
@@ -305,6 +307,7 @@ type ApplyUserSubscriptionSnapshotRow struct { |
| 305 | LastWebhookEventID string | 307 | LastWebhookEventID string |
| 306 | CreatedAt pgtype.Timestamptz | 308 | CreatedAt pgtype.Timestamptz |
| 307 | UpdatedAt pgtype.Timestamptz | 309 | UpdatedAt pgtype.Timestamptz |
| | 310 | + LastEventAt pgtype.Timestamptz |
| 308 | } | 311 | } |
| 309 | | 312 | |
| 310 | // Mirrors ApplySubscriptionSnapshot for orgs minus the seat columns | 313 | // Mirrors ApplySubscriptionSnapshot for orgs minus the seat columns |
@@ -345,6 +348,7 @@ func (q *Queries) ApplyUserSubscriptionSnapshot(ctx context.Context, db DBTX, ar |
| 345 | &i.LastWebhookEventID, | 348 | &i.LastWebhookEventID, |
| 346 | &i.CreatedAt, | 349 | &i.CreatedAt, |
| 347 | &i.UpdatedAt, | 350 | &i.UpdatedAt, |
| | 351 | + &i.LastEventAt, |
| 348 | ) | 352 | ) |
| 349 | return i, err | 353 | return i, err |
| 350 | } | 354 | } |
@@ -365,7 +369,7 @@ WITH state AS ( |
| 365 | grace_until = NULL, | 369 | grace_until = NULL, |
| 366 | updated_at = now() | 370 | updated_at = now() |
| 367 | WHERE org_id = $1 | 371 | WHERE org_id = $1 |
| 368 | - RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 372 | + RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 369 | ), org_update AS ( | 373 | ), org_update AS ( |
| 370 | UPDATE orgs | 374 | UPDATE orgs |
| 371 | SET plan = state.plan, | 375 | SET plan = state.plan, |
@@ -374,7 +378,7 @@ WITH state AS ( |
| 374 | WHERE orgs.id = state.org_id | 378 | WHERE orgs.id = state.org_id |
| 375 | RETURNING orgs.id | 379 | RETURNING orgs.id |
| 376 | ) | 380 | ) |
| 377 | -SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 381 | +SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 378 | ` | 382 | ` |
| 379 | | 383 | |
| 380 | type ClearBillingLockRow struct { | 384 | type ClearBillingLockRow struct { |
@@ -399,6 +403,7 @@ type ClearBillingLockRow struct { |
| 399 | LastWebhookEventID string | 403 | LastWebhookEventID string |
| 400 | CreatedAt pgtype.Timestamptz | 404 | CreatedAt pgtype.Timestamptz |
| 401 | UpdatedAt pgtype.Timestamptz | 405 | UpdatedAt pgtype.Timestamptz |
| | 406 | + LastEventAt pgtype.Timestamptz |
| 402 | } | 407 | } |
| 403 | | 408 | |
| 404 | func (q *Queries) ClearBillingLock(ctx context.Context, db DBTX, orgID int64) (ClearBillingLockRow, error) { | 409 | func (q *Queries) ClearBillingLock(ctx context.Context, db DBTX, orgID int64) (ClearBillingLockRow, error) { |
@@ -426,6 +431,7 @@ func (q *Queries) ClearBillingLock(ctx context.Context, db DBTX, orgID int64) (C |
| 426 | &i.LastWebhookEventID, | 431 | &i.LastWebhookEventID, |
| 427 | &i.CreatedAt, | 432 | &i.CreatedAt, |
| 428 | &i.UpdatedAt, | 433 | &i.UpdatedAt, |
| | 434 | + &i.LastEventAt, |
| 429 | ) | 435 | ) |
| 430 | return i, err | 436 | return i, err |
| 431 | } | 437 | } |
@@ -446,7 +452,7 @@ WITH state AS ( |
| 446 | grace_until = NULL, | 452 | grace_until = NULL, |
| 447 | updated_at = now() | 453 | updated_at = now() |
| 448 | WHERE user_id = $1 | 454 | WHERE user_id = $1 |
| 449 | - RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 455 | + RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 450 | ), user_update AS ( | 456 | ), user_update AS ( |
| 451 | UPDATE users | 457 | UPDATE users |
| 452 | SET plan = state.plan, | 458 | SET plan = state.plan, |
@@ -455,7 +461,7 @@ WITH state AS ( |
| 455 | WHERE users.id = state.user_id | 461 | WHERE users.id = state.user_id |
| 456 | RETURNING users.id | 462 | RETURNING users.id |
| 457 | ) | 463 | ) |
| 458 | -SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 464 | +SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 459 | ` | 465 | ` |
| 460 | | 466 | |
| 461 | type ClearUserBillingLockRow struct { | 467 | type ClearUserBillingLockRow struct { |
@@ -478,6 +484,7 @@ type ClearUserBillingLockRow struct { |
| 478 | LastWebhookEventID string | 484 | LastWebhookEventID string |
| 479 | CreatedAt pgtype.Timestamptz | 485 | CreatedAt pgtype.Timestamptz |
| 480 | UpdatedAt pgtype.Timestamptz | 486 | UpdatedAt pgtype.Timestamptz |
| | 487 | + LastEventAt pgtype.Timestamptz |
| 481 | } | 488 | } |
| 482 | | 489 | |
| 483 | func (q *Queries) ClearUserBillingLock(ctx context.Context, db DBTX, userID int64) (ClearUserBillingLockRow, error) { | 490 | func (q *Queries) ClearUserBillingLock(ctx context.Context, db DBTX, userID int64) (ClearUserBillingLockRow, error) { |
@@ -503,6 +510,7 @@ func (q *Queries) ClearUserBillingLock(ctx context.Context, db DBTX, userID int6 |
| 503 | &i.LastWebhookEventID, | 510 | &i.LastWebhookEventID, |
| 504 | &i.CreatedAt, | 511 | &i.CreatedAt, |
| 505 | &i.UpdatedAt, | 512 | &i.UpdatedAt, |
| | 513 | + &i.LastEventAt, |
| 506 | ) | 514 | ) |
| 507 | return i, err | 515 | return i, err |
| 508 | } | 516 | } |
@@ -667,7 +675,7 @@ func (q *Queries) CreateWebhookEventReceipt(ctx context.Context, db DBTX, arg Cr |
| 667 | const getOrgBillingState = `-- name: GetOrgBillingState :one | 675 | const getOrgBillingState = `-- name: GetOrgBillingState :one |
| 668 | | 676 | |
| 669 | | 677 | |
| 670 | -SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM org_billing_states WHERE org_id = $1 | 678 | +SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM org_billing_states WHERE org_id = $1 |
| 671 | ` | 679 | ` |
| 672 | | 680 | |
| 673 | // SPDX-License-Identifier: AGPL-3.0-or-later | 681 | // SPDX-License-Identifier: AGPL-3.0-or-later |
@@ -697,12 +705,13 @@ func (q *Queries) GetOrgBillingState(ctx context.Context, db DBTX, orgID int64) |
| 697 | &i.LastWebhookEventID, | 705 | &i.LastWebhookEventID, |
| 698 | &i.CreatedAt, | 706 | &i.CreatedAt, |
| 699 | &i.UpdatedAt, | 707 | &i.UpdatedAt, |
| | 708 | + &i.LastEventAt, |
| 700 | ) | 709 | ) |
| 701 | return i, err | 710 | return i, err |
| 702 | } | 711 | } |
| 703 | | 712 | |
| 704 | const getOrgBillingStateByStripeCustomer = `-- name: GetOrgBillingStateByStripeCustomer :one | 713 | const getOrgBillingStateByStripeCustomer = `-- name: GetOrgBillingStateByStripeCustomer :one |
| 705 | -SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM org_billing_states | 714 | +SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM org_billing_states |
| 706 | WHERE provider = 'stripe' | 715 | WHERE provider = 'stripe' |
| 707 | AND stripe_customer_id = $1 | 716 | AND stripe_customer_id = $1 |
| 708 | ` | 717 | ` |
@@ -732,12 +741,13 @@ func (q *Queries) GetOrgBillingStateByStripeCustomer(ctx context.Context, db DBT |
| 732 | &i.LastWebhookEventID, | 741 | &i.LastWebhookEventID, |
| 733 | &i.CreatedAt, | 742 | &i.CreatedAt, |
| 734 | &i.UpdatedAt, | 743 | &i.UpdatedAt, |
| | 744 | + &i.LastEventAt, |
| 735 | ) | 745 | ) |
| 736 | return i, err | 746 | return i, err |
| 737 | } | 747 | } |
| 738 | | 748 | |
| 739 | const getOrgBillingStateByStripeSubscription = `-- name: GetOrgBillingStateByStripeSubscription :one | 749 | const getOrgBillingStateByStripeSubscription = `-- name: GetOrgBillingStateByStripeSubscription :one |
| 740 | -SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM org_billing_states | 750 | +SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM org_billing_states |
| 741 | WHERE provider = 'stripe' | 751 | WHERE provider = 'stripe' |
| 742 | AND stripe_subscription_id = $1 | 752 | AND stripe_subscription_id = $1 |
| 743 | ` | 753 | ` |
@@ -767,13 +777,14 @@ func (q *Queries) GetOrgBillingStateByStripeSubscription(ctx context.Context, db |
| 767 | &i.LastWebhookEventID, | 777 | &i.LastWebhookEventID, |
| 768 | &i.CreatedAt, | 778 | &i.CreatedAt, |
| 769 | &i.UpdatedAt, | 779 | &i.UpdatedAt, |
| | 780 | + &i.LastEventAt, |
| 770 | ) | 781 | ) |
| 771 | return i, err | 782 | return i, err |
| 772 | } | 783 | } |
| 773 | | 784 | |
| 774 | const getUserBillingState = `-- name: GetUserBillingState :one | 785 | const getUserBillingState = `-- name: GetUserBillingState :one |
| 775 | | 786 | |
| 776 | -SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM user_billing_states WHERE user_id = $1 | 787 | +SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM user_billing_states WHERE user_id = $1 |
| 777 | ` | 788 | ` |
| 778 | | 789 | |
| 779 | // ─── user_billing_states (PRO03) ────────────────────────────────── | 790 | // ─── user_billing_states (PRO03) ────────────────────────────────── |
@@ -800,12 +811,13 @@ func (q *Queries) GetUserBillingState(ctx context.Context, db DBTX, userID int64 |
| 800 | &i.LastWebhookEventID, | 811 | &i.LastWebhookEventID, |
| 801 | &i.CreatedAt, | 812 | &i.CreatedAt, |
| 802 | &i.UpdatedAt, | 813 | &i.UpdatedAt, |
| | 814 | + &i.LastEventAt, |
| 803 | ) | 815 | ) |
| 804 | return i, err | 816 | return i, err |
| 805 | } | 817 | } |
| 806 | | 818 | |
| 807 | const getUserBillingStateByStripeCustomer = `-- name: GetUserBillingStateByStripeCustomer :one | 819 | const getUserBillingStateByStripeCustomer = `-- name: GetUserBillingStateByStripeCustomer :one |
| 808 | -SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM user_billing_states | 820 | +SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM user_billing_states |
| 809 | WHERE provider = 'stripe' | 821 | WHERE provider = 'stripe' |
| 810 | AND stripe_customer_id = $1 | 822 | AND stripe_customer_id = $1 |
| 811 | ` | 823 | ` |
@@ -833,12 +845,13 @@ func (q *Queries) GetUserBillingStateByStripeCustomer(ctx context.Context, db DB |
| 833 | &i.LastWebhookEventID, | 845 | &i.LastWebhookEventID, |
| 834 | &i.CreatedAt, | 846 | &i.CreatedAt, |
| 835 | &i.UpdatedAt, | 847 | &i.UpdatedAt, |
| | 848 | + &i.LastEventAt, |
| 836 | ) | 849 | ) |
| 837 | return i, err | 850 | return i, err |
| 838 | } | 851 | } |
| 839 | | 852 | |
| 840 | const getUserBillingStateByStripeSubscription = `-- name: GetUserBillingStateByStripeSubscription :one | 853 | const getUserBillingStateByStripeSubscription = `-- name: GetUserBillingStateByStripeSubscription :one |
| 841 | -SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM user_billing_states | 854 | +SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM user_billing_states |
| 842 | WHERE provider = 'stripe' | 855 | WHERE provider = 'stripe' |
| 843 | AND stripe_subscription_id = $1 | 856 | AND stripe_subscription_id = $1 |
| 844 | ` | 857 | ` |
@@ -866,6 +879,7 @@ func (q *Queries) GetUserBillingStateByStripeSubscription(ctx context.Context, d |
| 866 | &i.LastWebhookEventID, | 879 | &i.LastWebhookEventID, |
| 867 | &i.CreatedAt, | 880 | &i.CreatedAt, |
| 868 | &i.UpdatedAt, | 881 | &i.UpdatedAt, |
| | 882 | + &i.LastEventAt, |
| 869 | ) | 883 | ) |
| 870 | return i, err | 884 | return i, err |
| 871 | } | 885 | } |
@@ -896,6 +910,49 @@ func (q *Queries) GetWebhookEventReceipt(ctx context.Context, db DBTX, providerE |
| 896 | return i, err | 910 | return i, err |
| 897 | } | 911 | } |
| 898 | | 912 | |
| | 913 | +const isOrgBillingEventStale = `-- name: IsOrgBillingEventStale :one |
| | 914 | +SELECT COALESCE(last_event_at > $1::timestamptz, false)::boolean AS stale |
| | 915 | + FROM org_billing_states |
| | 916 | + WHERE org_id = $2::bigint |
| | 917 | +` |
| | 918 | + |
| | 919 | +type IsOrgBillingEventStaleParams struct { |
| | 920 | + EventAt pgtype.Timestamptz |
| | 921 | + OrgID int64 |
| | 922 | +} |
| | 923 | + |
| | 924 | +// PRO08 D4: returns true when an incoming Stripe event's timestamp |
| | 925 | +// is older than the last event we've already applied for this org. |
| | 926 | +// Stripe doesn't guarantee delivery order across retries; without |
| | 927 | +// this guard a stale `subscription.updated[active]` could re-activate |
| | 928 | +// a canceled subscription. Returns false when no prior event has |
| | 929 | +// been recorded (last_event_at IS NULL) — the first event is never |
| | 930 | +// stale. |
| | 931 | +func (q *Queries) IsOrgBillingEventStale(ctx context.Context, db DBTX, arg IsOrgBillingEventStaleParams) (bool, error) { |
| | 932 | + row := db.QueryRow(ctx, isOrgBillingEventStale, arg.EventAt, arg.OrgID) |
| | 933 | + var stale bool |
| | 934 | + err := row.Scan(&stale) |
| | 935 | + return stale, err |
| | 936 | +} |
| | 937 | + |
| | 938 | +const isUserBillingEventStale = `-- name: IsUserBillingEventStale :one |
| | 939 | +SELECT COALESCE(last_event_at > $1::timestamptz, false)::boolean AS stale |
| | 940 | + FROM user_billing_states |
| | 941 | + WHERE user_id = $2::bigint |
| | 942 | +` |
| | 943 | + |
| | 944 | +type IsUserBillingEventStaleParams struct { |
| | 945 | + EventAt pgtype.Timestamptz |
| | 946 | + UserID int64 |
| | 947 | +} |
| | 948 | + |
| | 949 | +func (q *Queries) IsUserBillingEventStale(ctx context.Context, db DBTX, arg IsUserBillingEventStaleParams) (bool, error) { |
| | 950 | + row := db.QueryRow(ctx, isUserBillingEventStale, arg.EventAt, arg.UserID) |
| | 951 | + var stale bool |
| | 952 | + err := row.Scan(&stale) |
| | 953 | + return stale, err |
| | 954 | +} |
| | 955 | + |
| 899 | const listFailedWebhookEvents = `-- name: ListFailedWebhookEvents :many | 956 | const listFailedWebhookEvents = `-- name: ListFailedWebhookEvents :many |
| 900 | SELECT id, provider, provider_event_id, event_type, api_version, | 957 | SELECT id, provider, provider_event_id, event_type, api_version, |
| 901 | received_at, processed_at, processing_attempts, process_error, | 958 | received_at, processed_at, processing_attempts, process_error, |
@@ -1137,7 +1194,7 @@ WITH state AS ( |
| 1137 | last_webhook_event_id = $1::text, | 1194 | last_webhook_event_id = $1::text, |
| 1138 | updated_at = now() | 1195 | updated_at = now() |
| 1139 | WHERE org_id = $2::bigint | 1196 | WHERE org_id = $2::bigint |
| 1140 | - RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1197 | + RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1141 | ), org_update AS ( | 1198 | ), org_update AS ( |
| 1142 | UPDATE orgs | 1199 | UPDATE orgs |
| 1143 | SET plan = 'free', | 1200 | SET plan = 'free', |
@@ -1145,7 +1202,7 @@ WITH state AS ( |
| 1145 | WHERE id = $2::bigint | 1202 | WHERE id = $2::bigint |
| 1146 | RETURNING id | 1203 | RETURNING id |
| 1147 | ) | 1204 | ) |
| 1148 | -SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 1205 | +SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 1149 | ` | 1206 | ` |
| 1150 | | 1207 | |
| 1151 | type MarkCanceledParams struct { | 1208 | type MarkCanceledParams struct { |
@@ -1175,6 +1232,7 @@ type MarkCanceledRow struct { |
| 1175 | LastWebhookEventID string | 1232 | LastWebhookEventID string |
| 1176 | CreatedAt pgtype.Timestamptz | 1233 | CreatedAt pgtype.Timestamptz |
| 1177 | UpdatedAt pgtype.Timestamptz | 1234 | UpdatedAt pgtype.Timestamptz |
| | 1235 | + LastEventAt pgtype.Timestamptz |
| 1178 | } | 1236 | } |
| 1179 | | 1237 | |
| 1180 | func (q *Queries) MarkCanceled(ctx context.Context, db DBTX, arg MarkCanceledParams) (MarkCanceledRow, error) { | 1238 | func (q *Queries) MarkCanceled(ctx context.Context, db DBTX, arg MarkCanceledParams) (MarkCanceledRow, error) { |
@@ -1202,6 +1260,7 @@ func (q *Queries) MarkCanceled(ctx context.Context, db DBTX, arg MarkCanceledPar |
| 1202 | &i.LastWebhookEventID, | 1260 | &i.LastWebhookEventID, |
| 1203 | &i.CreatedAt, | 1261 | &i.CreatedAt, |
| 1204 | &i.UpdatedAt, | 1262 | &i.UpdatedAt, |
| | 1263 | + &i.LastEventAt, |
| 1205 | ) | 1264 | ) |
| 1206 | return i, err | 1265 | return i, err |
| 1207 | } | 1266 | } |
@@ -1216,7 +1275,7 @@ UPDATE org_billing_states |
| 1216 | last_webhook_event_id = $2::text, | 1275 | last_webhook_event_id = $2::text, |
| 1217 | updated_at = now() | 1276 | updated_at = now() |
| 1218 | WHERE org_id = $3::bigint | 1277 | WHERE org_id = $3::bigint |
| 1219 | -RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1278 | +RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1220 | ` | 1279 | ` |
| 1221 | | 1280 | |
| 1222 | type MarkPastDueParams struct { | 1281 | type MarkPastDueParams struct { |
@@ -1250,6 +1309,7 @@ func (q *Queries) MarkPastDue(ctx context.Context, db DBTX, arg MarkPastDueParam |
| 1250 | &i.LastWebhookEventID, | 1309 | &i.LastWebhookEventID, |
| 1251 | &i.CreatedAt, | 1310 | &i.CreatedAt, |
| 1252 | &i.UpdatedAt, | 1311 | &i.UpdatedAt, |
| | 1312 | + &i.LastEventAt, |
| 1253 | ) | 1313 | ) |
| 1254 | return i, err | 1314 | return i, err |
| 1255 | } | 1315 | } |
@@ -1275,7 +1335,7 @@ WITH state AS ( |
| 1275 | last_webhook_event_id = $1::text, | 1335 | last_webhook_event_id = $1::text, |
| 1276 | updated_at = now() | 1336 | updated_at = now() |
| 1277 | WHERE org_id = $2::bigint | 1337 | WHERE org_id = $2::bigint |
| 1278 | - RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1338 | + RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1279 | ), org_update AS ( | 1339 | ), org_update AS ( |
| 1280 | UPDATE orgs | 1340 | UPDATE orgs |
| 1281 | SET plan = state.plan, | 1341 | SET plan = state.plan, |
@@ -1284,7 +1344,7 @@ WITH state AS ( |
| 1284 | WHERE orgs.id = state.org_id | 1344 | WHERE orgs.id = state.org_id |
| 1285 | RETURNING orgs.id | 1345 | RETURNING orgs.id |
| 1286 | ) | 1346 | ) |
| 1287 | -SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 1347 | +SELECT org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 1288 | ` | 1348 | ` |
| 1289 | | 1349 | |
| 1290 | type MarkPaymentSucceededParams struct { | 1350 | type MarkPaymentSucceededParams struct { |
@@ -1314,6 +1374,7 @@ type MarkPaymentSucceededRow struct { |
| 1314 | LastWebhookEventID string | 1374 | LastWebhookEventID string |
| 1315 | CreatedAt pgtype.Timestamptz | 1375 | CreatedAt pgtype.Timestamptz |
| 1316 | UpdatedAt pgtype.Timestamptz | 1376 | UpdatedAt pgtype.Timestamptz |
| | 1377 | + LastEventAt pgtype.Timestamptz |
| 1317 | } | 1378 | } |
| 1318 | | 1379 | |
| 1319 | func (q *Queries) MarkPaymentSucceeded(ctx context.Context, db DBTX, arg MarkPaymentSucceededParams) (MarkPaymentSucceededRow, error) { | 1380 | func (q *Queries) MarkPaymentSucceeded(ctx context.Context, db DBTX, arg MarkPaymentSucceededParams) (MarkPaymentSucceededRow, error) { |
@@ -1341,6 +1402,7 @@ func (q *Queries) MarkPaymentSucceeded(ctx context.Context, db DBTX, arg MarkPay |
| 1341 | &i.LastWebhookEventID, | 1402 | &i.LastWebhookEventID, |
| 1342 | &i.CreatedAt, | 1403 | &i.CreatedAt, |
| 1343 | &i.UpdatedAt, | 1404 | &i.UpdatedAt, |
| | 1405 | + &i.LastEventAt, |
| 1344 | ) | 1406 | ) |
| 1345 | return i, err | 1407 | return i, err |
| 1346 | } | 1408 | } |
@@ -1358,7 +1420,7 @@ WITH state AS ( |
| 1358 | last_webhook_event_id = $1::text, | 1420 | last_webhook_event_id = $1::text, |
| 1359 | updated_at = now() | 1421 | updated_at = now() |
| 1360 | WHERE user_id = $2::bigint | 1422 | WHERE user_id = $2::bigint |
| 1361 | - RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1423 | + RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1362 | ), user_update AS ( | 1424 | ), user_update AS ( |
| 1363 | UPDATE users | 1425 | UPDATE users |
| 1364 | SET plan = 'free', | 1426 | SET plan = 'free', |
@@ -1366,7 +1428,7 @@ WITH state AS ( |
| 1366 | WHERE id = $2::bigint | 1428 | WHERE id = $2::bigint |
| 1367 | RETURNING id | 1429 | RETURNING id |
| 1368 | ) | 1430 | ) |
| 1369 | -SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 1431 | +SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 1370 | ` | 1432 | ` |
| 1371 | | 1433 | |
| 1372 | type MarkUserCanceledParams struct { | 1434 | type MarkUserCanceledParams struct { |
@@ -1394,6 +1456,7 @@ type MarkUserCanceledRow struct { |
| 1394 | LastWebhookEventID string | 1456 | LastWebhookEventID string |
| 1395 | CreatedAt pgtype.Timestamptz | 1457 | CreatedAt pgtype.Timestamptz |
| 1396 | UpdatedAt pgtype.Timestamptz | 1458 | UpdatedAt pgtype.Timestamptz |
| | 1459 | + LastEventAt pgtype.Timestamptz |
| 1397 | } | 1460 | } |
| 1398 | | 1461 | |
| 1399 | func (q *Queries) MarkUserCanceled(ctx context.Context, db DBTX, arg MarkUserCanceledParams) (MarkUserCanceledRow, error) { | 1462 | func (q *Queries) MarkUserCanceled(ctx context.Context, db DBTX, arg MarkUserCanceledParams) (MarkUserCanceledRow, error) { |
@@ -1419,6 +1482,7 @@ func (q *Queries) MarkUserCanceled(ctx context.Context, db DBTX, arg MarkUserCan |
| 1419 | &i.LastWebhookEventID, | 1482 | &i.LastWebhookEventID, |
| 1420 | &i.CreatedAt, | 1483 | &i.CreatedAt, |
| 1421 | &i.UpdatedAt, | 1484 | &i.UpdatedAt, |
| | 1485 | + &i.LastEventAt, |
| 1422 | ) | 1486 | ) |
| 1423 | return i, err | 1487 | return i, err |
| 1424 | } | 1488 | } |
@@ -1433,7 +1497,7 @@ UPDATE user_billing_states |
| 1433 | last_webhook_event_id = $2::text, | 1497 | last_webhook_event_id = $2::text, |
| 1434 | updated_at = now() | 1498 | updated_at = now() |
| 1435 | WHERE user_id = $3::bigint | 1499 | WHERE user_id = $3::bigint |
| 1436 | -RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1500 | +RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1437 | ` | 1501 | ` |
| 1438 | | 1502 | |
| 1439 | type MarkUserPastDueParams struct { | 1503 | type MarkUserPastDueParams struct { |
@@ -1465,6 +1529,7 @@ func (q *Queries) MarkUserPastDue(ctx context.Context, db DBTX, arg MarkUserPast |
| 1465 | &i.LastWebhookEventID, | 1529 | &i.LastWebhookEventID, |
| 1466 | &i.CreatedAt, | 1530 | &i.CreatedAt, |
| 1467 | &i.UpdatedAt, | 1531 | &i.UpdatedAt, |
| | 1532 | + &i.LastEventAt, |
| 1468 | ) | 1533 | ) |
| 1469 | return i, err | 1534 | return i, err |
| 1470 | } | 1535 | } |
@@ -1490,7 +1555,7 @@ WITH state AS ( |
| 1490 | last_webhook_event_id = $1::text, | 1555 | last_webhook_event_id = $1::text, |
| 1491 | updated_at = now() | 1556 | updated_at = now() |
| 1492 | WHERE user_id = $2::bigint | 1557 | WHERE user_id = $2::bigint |
| 1493 | - RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1558 | + RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1494 | ), user_update AS ( | 1559 | ), user_update AS ( |
| 1495 | UPDATE users | 1560 | UPDATE users |
| 1496 | SET plan = state.plan, | 1561 | SET plan = state.plan, |
@@ -1499,7 +1564,7 @@ WITH state AS ( |
| 1499 | WHERE users.id = state.user_id | 1564 | WHERE users.id = state.user_id |
| 1500 | RETURNING users.id | 1565 | RETURNING users.id |
| 1501 | ) | 1566 | ) |
| 1502 | -SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at FROM state | 1567 | +SELECT user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at FROM state |
| 1503 | ` | 1568 | ` |
| 1504 | | 1569 | |
| 1505 | type MarkUserPaymentSucceededParams struct { | 1570 | type MarkUserPaymentSucceededParams struct { |
@@ -1527,6 +1592,7 @@ type MarkUserPaymentSucceededRow struct { |
| 1527 | LastWebhookEventID string | 1592 | LastWebhookEventID string |
| 1528 | CreatedAt pgtype.Timestamptz | 1593 | CreatedAt pgtype.Timestamptz |
| 1529 | UpdatedAt pgtype.Timestamptz | 1594 | UpdatedAt pgtype.Timestamptz |
| | 1595 | + LastEventAt pgtype.Timestamptz |
| 1530 | } | 1596 | } |
| 1531 | | 1597 | |
| 1532 | func (q *Queries) MarkUserPaymentSucceeded(ctx context.Context, db DBTX, arg MarkUserPaymentSucceededParams) (MarkUserPaymentSucceededRow, error) { | 1598 | func (q *Queries) MarkUserPaymentSucceeded(ctx context.Context, db DBTX, arg MarkUserPaymentSucceededParams) (MarkUserPaymentSucceededRow, error) { |
@@ -1552,6 +1618,7 @@ func (q *Queries) MarkUserPaymentSucceeded(ctx context.Context, db DBTX, arg Mar |
| 1552 | &i.LastWebhookEventID, | 1618 | &i.LastWebhookEventID, |
| 1553 | &i.CreatedAt, | 1619 | &i.CreatedAt, |
| 1554 | &i.UpdatedAt, | 1620 | &i.UpdatedAt, |
| | 1621 | + &i.LastEventAt, |
| 1555 | ) | 1622 | ) |
| 1556 | return i, err | 1623 | return i, err |
| 1557 | } | 1624 | } |
@@ -1627,7 +1694,7 @@ ON CONFLICT (org_id) DO UPDATE |
| 1627 | SET stripe_customer_id = EXCLUDED.stripe_customer_id, | 1694 | SET stripe_customer_id = EXCLUDED.stripe_customer_id, |
| 1628 | provider = 'stripe', | 1695 | provider = 'stripe', |
| 1629 | updated_at = now() | 1696 | updated_at = now() |
| 1630 | -RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1697 | +RETURNING org_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, billable_seats, seat_snapshot_at, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1631 | ` | 1698 | ` |
| 1632 | | 1699 | |
| 1633 | type SetStripeCustomerParams struct { | 1700 | type SetStripeCustomerParams struct { |
@@ -1660,6 +1727,7 @@ func (q *Queries) SetStripeCustomer(ctx context.Context, db DBTX, arg SetStripeC |
| 1660 | &i.LastWebhookEventID, | 1727 | &i.LastWebhookEventID, |
| 1661 | &i.CreatedAt, | 1728 | &i.CreatedAt, |
| 1662 | &i.UpdatedAt, | 1729 | &i.UpdatedAt, |
| | 1730 | + &i.LastEventAt, |
| 1663 | ) | 1731 | ) |
| 1664 | return i, err | 1732 | return i, err |
| 1665 | } | 1733 | } |
@@ -1671,7 +1739,7 @@ ON CONFLICT (user_id) DO UPDATE |
| 1671 | SET stripe_customer_id = EXCLUDED.stripe_customer_id, | 1739 | SET stripe_customer_id = EXCLUDED.stripe_customer_id, |
| 1672 | provider = 'stripe', | 1740 | provider = 'stripe', |
| 1673 | updated_at = now() | 1741 | updated_at = now() |
| 1674 | -RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at | 1742 | +RETURNING user_id, provider, stripe_customer_id, stripe_subscription_id, stripe_subscription_item_id, plan, subscription_status, current_period_start, current_period_end, cancel_at_period_end, trial_end, past_due_at, canceled_at, locked_at, lock_reason, grace_until, last_webhook_event_id, created_at, updated_at, last_event_at |
| 1675 | ` | 1743 | ` |
| 1676 | | 1744 | |
| 1677 | type SetUserStripeCustomerParams struct { | 1745 | type SetUserStripeCustomerParams struct { |
@@ -1702,6 +1770,7 @@ func (q *Queries) SetUserStripeCustomer(ctx context.Context, db DBTX, arg SetUse |
| 1702 | &i.LastWebhookEventID, | 1770 | &i.LastWebhookEventID, |
| 1703 | &i.CreatedAt, | 1771 | &i.CreatedAt, |
| 1704 | &i.UpdatedAt, | 1772 | &i.UpdatedAt, |
| | 1773 | + &i.LastEventAt, |
| 1705 | ) | 1774 | ) |
| 1706 | return i, err | 1775 | return i, err |
| 1707 | } | 1776 | } |
@@ -1730,6 +1799,42 @@ func (q *Queries) SetWebhookEventSubject(ctx context.Context, db DBTX, arg SetWe |
| 1730 | return err | 1799 | return err |
| 1731 | } | 1800 | } |
| 1732 | | 1801 | |
| | 1802 | +const touchOrgBillingLastEventAt = `-- name: TouchOrgBillingLastEventAt :exec |
| | 1803 | +UPDATE org_billing_states |
| | 1804 | + SET last_event_at = GREATEST(COALESCE(last_event_at, $1::timestamptz), $1::timestamptz) |
| | 1805 | + WHERE org_id = $2::bigint |
| | 1806 | +` |
| | 1807 | + |
| | 1808 | +type TouchOrgBillingLastEventAtParams struct { |
| | 1809 | + EventAt pgtype.Timestamptz |
| | 1810 | + OrgID int64 |
| | 1811 | +} |
| | 1812 | + |
| | 1813 | +// PRO08 D4: bump last_event_at on successful apply. Conditional so |
| | 1814 | +// a fresh apply driven by an out-of-order-but-recent retry doesn't |
| | 1815 | +// regress the timestamp (GREATEST). NULL last_event_at acquires the |
| | 1816 | +// incoming value. |
| | 1817 | +func (q *Queries) TouchOrgBillingLastEventAt(ctx context.Context, db DBTX, arg TouchOrgBillingLastEventAtParams) error { |
| | 1818 | + _, err := db.Exec(ctx, touchOrgBillingLastEventAt, arg.EventAt, arg.OrgID) |
| | 1819 | + return err |
| | 1820 | +} |
| | 1821 | + |
| | 1822 | +const touchUserBillingLastEventAt = `-- name: TouchUserBillingLastEventAt :exec |
| | 1823 | +UPDATE user_billing_states |
| | 1824 | + SET last_event_at = GREATEST(COALESCE(last_event_at, $1::timestamptz), $1::timestamptz) |
| | 1825 | + WHERE user_id = $2::bigint |
| | 1826 | +` |
| | 1827 | + |
| | 1828 | +type TouchUserBillingLastEventAtParams struct { |
| | 1829 | + EventAt pgtype.Timestamptz |
| | 1830 | + UserID int64 |
| | 1831 | +} |
| | 1832 | + |
| | 1833 | +func (q *Queries) TouchUserBillingLastEventAt(ctx context.Context, db DBTX, arg TouchUserBillingLastEventAtParams) error { |
| | 1834 | + _, err := db.Exec(ctx, touchUserBillingLastEventAt, arg.EventAt, arg.UserID) |
| | 1835 | + return err |
| | 1836 | +} |
| | 1837 | + |
| 1733 | const tryAcquireWebhookEventLock = `-- name: TryAcquireWebhookEventLock :one | 1838 | const tryAcquireWebhookEventLock = `-- name: TryAcquireWebhookEventLock :one |
| 1734 | SELECT pg_try_advisory_xact_lock(hashtext($1)::bigint) AS acquired | 1839 | SELECT pg_try_advisory_xact_lock(hashtext($1)::bigint) AS acquired |
| 1735 | ` | 1840 | ` |