Jatin3128 edc8daae21 fix(subscription): don't reactivate a cancelled subscription (backport #57774) (#57780)
* fix(subscription): don't reactivate a cancelled subscription

Backport of #57774 to version-15-hotfix.

set_subscription_status() unconditionally set status to Active once
there was no outstanding invoice, with no check for whether the
subscription had been intentionally cancelled. process()'s
cancel_at_period_end check compared posting_date against
getdate(self.end_date), and getdate(None) returns today, so an empty
end_date was silently treated as "cancel now" on every reprocess.

version-15-hotfix does not yet have the Payment Entry -> invoice ->
refresh_subscription_status() hook chain that #57761 reports (that
was added later), and the scheduler already excludes Cancelled
subscriptions, so the exact automatic repro in the issue does not
apply here. The underlying status logic is defective the same way
though, and reachable directly (e.g. any caller invoking the
whitelisted process()/set_subscription_status() on a cancelled
subscription), so fixing it here too rather than leaving the same
class of bug in place.

Related to #57761

* fix(test): avoid tripping the unrelated period-end cancel clause

The test backdated start_date to 2018-01-01, so by the time process()
ran, current_invoice_end was long past. That made the *other* half of
the cancel_at_period_end OR-condition (period end reached) true on
its own, so process() tried to cancel an already-cancelled
subscription and hit cancel_subscription()'s "already cancelled"
guard - unrelated to the empty end_date bug being tested.

Use nowdate() as start_date so current_invoice_end sits safely in the
future, isolating the assertion to the empty end_date guard. Also
drop the fragile intermediate "Unpaid" status assertion, which
wasn't part of what this test verifies.

* fix(subscription): don't let period rollover defeat cancel_at_period_end

process() can advance current_invoice_end to the next period (via
update_subscription_period(), when generating the current period's
invoice) before the cancel_at_period_end check further down runs. For
a subscription with no end_date, that check now compared posting_date
against the already-rolled-forward current_invoice_end, which is
always in the future, so cancel_at_period_end was silently never
honored.

Snapshot current_invoice_end before any rollover and use that in the
check instead, so it still targets the period that just ended.

Fixes the P1 flagged by Greptile review on this PR.

---------

Co-authored-by: test <test@test.com>
2026-08-05 12:26:01 +05:30
2022-03-30 12:36:09 +05:30
2023-11-16 12:18:47 +05:30
2018-07-19 17:47:04 +05:30
2017-07-01 21:35:10 +05:30
2021-03-17 20:06:35 +05:30

ERPNext

ERP made simple

CI UI Open Source Helpers codecov docker pulls

https://erpnext.com

ERPNext as a monolith includes the following areas for managing businesses:

  1. Accounting
  2. Warehouse Management
  3. CRM
  4. Sales
  5. Purchase
  6. HRMS
  7. Project Management
  8. Support
  9. Asset Management
  10. Quality Management
  11. Manufacturing
  12. Website Management
  13. Customize ERPNext
  14. And More

ERPNext is built on the Frappe Framework, a full-stack web app framework built with Python & JavaScript.

Installation

Login for the PWD site: (username: Administrator, password: admin)

Containerized Installation

Use docker to deploy ERPNext in production or for development of Frappe apps. See https://github.com/frappe/frappe_docker for more details.

Manual Install

The Easy Way: our install script for bench will install all dependencies (e.g. MariaDB). See https://github.com/frappe/bench for more details.

New passwords will be created for the ERPNext "Administrator" user, the MariaDB root user, and the frappe user (the script displays the passwords and saves them to ~/frappe_passwords.txt).

Learning and community

  1. Frappe School - Learn Frappe Framework and ERPNext from the various courses by the maintainers or from the community.
  2. Official documentation - Extensive documentation for ERPNext.
  3. Discussion Forum - Engage with community of ERPNext users and service providers.
  4. Telegram Group - Get instant help from huge community of users.

Contributing

  1. Issue Guidelines
  2. Report Security Vulnerabilities
  3. Pull Request Requirements
  4. Translations

License

GNU/General Public License (see license.txt)

The ERPNext code is licensed as GNU General Public License (v3) and the Documentation is licensed as Creative Commons (CC-BY-SA-3.0) and the copyright is owned by Frappe Technologies Pvt Ltd (Frappe) and Contributors.

By contributing to ERPNext, you agree that your contributions will be licensed under its GNU General Public License (v3).

Logo and Trademark Policy

Please read our Logo and Trademark Policy.

Languages
Python 78.5%
JavaScript 14.3%
TypeScript 4.9%
HTML 1.8%
SCSS 0.3%
Other 0.2%