feat(stripe): subscriptions and recurring reconciliation#241
feat(stripe): subscriptions and recurring reconciliation#241Tarunkumar0601 wants to merge 6 commits into
Conversation
|
Tick the box to add this pull request to the merge queue (same as
|
Confidence Score: 4/5The webhook reconciliation path is now correct for the happy path, but the SI-generation inside All 20 previously-flagged concerns appear addressed. One residual concern:
Reviews (27): Last reviewed commit: "feat(stripe): subscriptions and recurrin..." | Re-trigger Greptile |
77847da to
4368ab6
Compare
4368ab6 to
e51884f
Compare
85239d2 to
9e67140
Compare
4ab6529 to
cbd3e7a
Compare
a0f69f7 to
9072b7c
Compare
3cc0e28 to
84e49e2
Compare
9353348 to
7a1bcf2
Compare
7a1bcf2 to
5c22513
Compare
0a0c9c4 to
ab7b2da
Compare
ab7b2da to
37847e0
Compare
879f0b1 to
90ab96b
Compare
169f6fa to
57fb077
Compare
9a8f25b to
4c915e4
Compare
4c915e4 to
848df01
Compare
| def _generate_and_find_sales_invoice(erpnext_sub, invoice): | ||
| """Stripe billed before ERPNext's scheduler — generate the period SI, then re-find.""" | ||
| _, end = _invoice_period(invoice) | ||
| try: | ||
| sub_doc = frappe.get_doc("Subscription", erpnext_sub) | ||
| # No commit here: keep SI generation in the webhook's transaction so a later | ||
| # Payment Entry failure rolls back the SI too (handle_event retries the event). | ||
| sub_doc.process(posting_date=end or getdate(now_datetime())) | ||
| except Exception: | ||
| frappe.log_error(frappe.get_traceback(), "Stripe: could not generate subscription invoice") | ||
| return None | ||
| return _find_period_sales_invoice(erpnext_sub, invoice) |
There was a problem hiding this comment.
ERPNext
sub_doc.process() commits internally — orphaned SI on PE failure
The comment says "No commit here: keep SI generation in the webhook's transaction so a later Payment Entry failure rolls back the SI too." ERPNext's Subscription.process() calls frappe.db.commit() internally after generating each invoice, so the SI is committed to the database before _create_payment_entry is called. If _create_payment_entry then raises (e.g., validation error), handle_event rolls back — but the SI commit is already durable. The result is a submitted SI with no Payment Entry, identical to the issue that was fixed by removing the earlier explicit frappe.db.commit(). The retry will find _find_period_sales_invoice returning the committed SI and can proceed to create the PE, so it is eventually consistent — but the claim in the comment that the SI is inside the webhook transaction is incorrect and may mislead future contributors into assuming rollback protection that does not exist.
Adds native recurring billing through Stripe and reconciles each renewal back to ERPNext.
Depends on feat/stripe-webhooks-reconciliation.
Backport Needed: V15 & V16