Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 37 additions & 23 deletions subscription_oca/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Subscription management
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ea96c858a40ee527d0e32ee03859918c082521f205ccc1cb26e96cb3bef27800
!! source digest: sha256:1d7163cf2d7da35b3460a208800f960258c0e321470ab537d8aee3c7dfa6197e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand All @@ -36,6 +36,10 @@ This module allows creating subscriptions that generate recurring
invoices or orders. It also enables the sale of products that generate
subscriptions.

Subscriptions can be paused and resumed, so they can be put on hold
without being closed; the recurring cron skips paused subscriptions and
can resume them automatically on a configured date.

**Table of contents**

.. contents::
Expand Down Expand Up @@ -74,21 +78,31 @@ To create subscriptions with the sale of a product:

Invoice and delivery addresses:

- Each subscription has an *Invoice address* and a *Delivery address*.
They default to the customer's corresponding addresses and can be
overridden per subscription.
- These addresses are propagated to the recurring invoices (the invoice
is addressed to the invoice address and records the delivery one) and
to the sale orders generated by the subscription.
- The fields are shown when the *Customer Addresses* setting (group
*Display Delivery / Invoice addresses*) is enabled.
- Each subscription has an *Invoice address* and a *Delivery address*.
They default to the customer's corresponding addresses and can be
overridden per subscription.
- These addresses are propagated to the recurring invoices (the invoice
is addressed to the invoice address and records the delivery one) and
to the sale orders generated by the subscription.
- The fields are shown when the *Customer Addresses* setting (group
*Display Delivery / Invoice addresses*) is enabled.

To pause and resume a subscription:

1. On an in-progress subscription, press *Pause*. A dialog lets you
optionally set a *Resume on* date.
2. While paused, the cron skips the subscription: it is not invoiced,
started or closed.
3. Press *Resume* to reactivate it manually. If a *Resume on* date was
set, the cron resumes the subscription automatically once that date
is reached. Leaving the date empty pauses it indefinitely.

Known issues / Roadmap
======================

- Refactor all the onchanges that have business logic to computed
write-able fields when possible. Keep onchanges only for UI purposes.
- Add tests.
- Refactor all the onchanges that have business logic to computed
write-able fields when possible. Keep onchanges only for UI purposes.
- Add tests.

Bug Tracker
===========
Expand All @@ -112,22 +126,22 @@ Authors
Contributors
------------

- Carlos Martínez <carlos@domatix.com>
- Carolina Ferrer <carolina@domatix.com>
- `Ooops404 <https://www.ooops404.com>`__:
- Carlos Martínez <carlos@domatix.com>
- Carolina Ferrer <carolina@domatix.com>
- `Ooops404 <https://www.ooops404.com>`__:

- Ilyas <irazor147@gmail.com>
- Ilyas <irazor147@gmail.com>

- `Sygel <https://www.sygel.es>`__:
- `Sygel <https://www.sygel.es>`__:

- Harald Panten
- Valentin Vinagre
- Alberto Martínez
- Harald Panten
- Valentin Vinagre
- Alberto Martínez

- Dennis Sluijk <d.sluijk@onestein.nl>
- `IKU Solutions <https://www.iku.solutions>`__:
- Dennis Sluijk <d.sluijk@onestein.nl>
- `IKU Solutions <https://www.iku.solutions>`__:

- Yan Chirino <yan.chirino@iku.solutions>
- Yan Chirino <yan.chirino@iku.solutions>

Maintainers
-----------
Expand Down
1 change: 1 addition & 0 deletions subscription_oca/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"data/ir_cron.xml",
"data/sale_subscription_data.xml",
"wizard/close_subscription_wizard.xml",
"wizard/pause_subscription_wizard.xml",
"security/subscription_security.xml",
"security/ir.model.access.csv",
],
Expand Down
72 changes: 71 additions & 1 deletion subscription_oca/models/sale_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from markupsafe import Markup

from odoo import Command, api, fields, models
from odoo.exceptions import AccessError
from odoo.exceptions import AccessError, UserError

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -153,15 +153,33 @@ def _read_group_stage_ids(self, stages, domain):
)
crm_team_id = fields.Many2one(comodel_name="crm.team", string="Sale team")
to_renew = fields.Boolean(default=False, string="To renew")
is_paused = fields.Boolean(
string="Paused",
tracking=True,
index="btree_not_null",
copy=False,
help="When ticked, the recurring cron will skip this subscription "
"until it is resumed manually or until `paused_until` is reached.",
)
paused_until = fields.Date(
string="Resume on",
tracking=True,
copy=False,
help="If set, the cron will automatically resume this subscription "
"on or after this date.",
)

@api.model
def cron_subscription_management(self):
self._cron_resume_due_subscriptions()
today = date.today()
subscription_count = self.search_count([])
for subscription in self.search(
[], order="recurring_next_date asc", limit=subscription_count
):
subscription = subscription.with_company(subscription.company_id)
if subscription.is_paused:
continue
if subscription.in_progress:
if (
subscription.recurring_next_date <= today
Expand All @@ -182,6 +200,24 @@ def cron_subscription_management(self):
subscription.action_start_subscription()
subscription.generate_invoice()

@api.model
def _cron_resume_due_subscriptions(self, limit=None):
today = fields.Date.context_today(self)
domain = [
("is_paused", "=", True),
("paused_until", "!=", False),
("paused_until", "<=", today),
]
for subscription in self.search(domain, limit=limit):
try:
subscription.with_company(subscription.company_id).action_resume(
automatic=True
)
except Exception:
logger.exception(
"Error resuming paused subscription %s", subscription.id
)

@api.depends("sale_subscription_line_ids")
def _compute_total(self):
for record in self:
Expand Down Expand Up @@ -315,6 +351,40 @@ def action_start_subscription(self):
)
self.stage_id = in_progress_stage

def action_open_pause_wizard(self):
self.ensure_one()
return {
"type": "ir.actions.act_window",
"name": self.env._("Pause subscription"),
"res_model": "sale.subscription.pause.wizard",
"view_mode": "form",
"target": "new",
}

def action_pause(self, paused_until=None):
self.ensure_one()
if self.stage_id.type == "post":
raise UserError(self.env._("Cannot pause a closed subscription."))
if self.is_paused:
raise UserError(self.env._("This subscription is already paused."))
self.write({"is_paused": True, "paused_until": paused_until or False})
if paused_until:
body = self.env._("Subscription paused until %(date)s.", date=paused_until)
else:
body = self.env._("Subscription paused.")
self.message_post(body=body)

def action_resume(self, automatic=False):
self.ensure_one()
if not self.is_paused:
raise UserError(self.env._("This subscription is not paused."))
self.write({"is_paused": False, "paused_until": False})
if automatic:
body = self.env._("Subscription resumed automatically.")
else:
body = self.env._("Subscription resumed.")
self.message_post(body=body)

def action_close_subscription(self):
return {
"view_type": "form",
Expand Down
4 changes: 4 additions & 0 deletions subscription_oca/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
This module allows creating subscriptions that generate recurring
invoices or orders. It also enables the sale of products that generate
subscriptions.

Subscriptions can be paused and resumed, so they can be put on hold
without being closed; the recurring cron skips paused subscriptions and
can resume them automatically on a configured date.
10 changes: 10 additions & 0 deletions subscription_oca/readme/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,13 @@ Invoice and delivery addresses:
to the sale orders generated by the subscription.
- The fields are shown when the *Customer Addresses* setting
(group *Display Delivery / Invoice addresses*) is enabled.

To pause and resume a subscription:

1. On an in-progress subscription, press *Pause*. A dialog lets you
optionally set a *Resume on* date.
2. While paused, the cron skips the subscription: it is not invoiced,
started or closed.
3. Press *Resume* to reactivate it manually. If a *Resume on* date was
set, the cron resumes the subscription automatically once that date
is reached. Leaving the date empty pauses it indefinitely.
1 change: 1 addition & 0 deletions subscription_oca/security/ir.model.access.csv
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ access_custom_sale_subscription_stage,sale.subscription.stage,model_sale_subscri
access_custom_sale_subscription_line,sale.subscription.line,model_sale_subscription_line,sales_team.group_sale_salesman,1,1,1,1
access_custom_sale_subscription_tag,sale.subscription.tag,model_sale_subscription_tag,sales_team.group_sale_salesman,1,1,1,1
access_close_subscription,Close subscription access,model_close_reason_wizard,sales_team.group_sale_salesman,1,1,1,1
access_pause_subscription_wizard,Pause subscription wizard access,model_sale_subscription_pause_wizard,sales_team.group_sale_salesman,1,1,1,1
15 changes: 14 additions & 1 deletion subscription_oca/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -372,12 +372,15 @@ <h1>Subscription management</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:ea96c858a40ee527d0e32ee03859918c082521f205ccc1cb26e96cb3bef27800
!! source digest: sha256:1d7163cf2d7da35b3460a208800f960258c0e321470ab537d8aee3c7dfa6197e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/license-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/contract/tree/19.0/subscription_oca"><img alt="OCA/contract" src="https://img.shields.io/badge/github-OCA%2Fcontract-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/contract-19-0/contract-19-0-subscription_oca"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/contract&amp;target_branch=19.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module allows creating subscriptions that generate recurring
invoices or orders. It also enables the sale of products that generate
subscriptions.</p>
<p>Subscriptions can be paused and resumed, so they can be put on hold
without being closed; the recurring cron skips paused subscriptions and
can resume them automatically on a configured date.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
Expand Down Expand Up @@ -433,6 +436,16 @@ <h2><a class="toc-backref" href="#toc-entry-1">Usage</a></h2>
<li>The fields are shown when the <em>Customer Addresses</em> setting (group
<em>Display Delivery / Invoice addresses</em>) is enabled.</li>
</ul>
<p>To pause and resume a subscription:</p>
<ol class="arabic simple">
<li>On an in-progress subscription, press <em>Pause</em>. A dialog lets you
optionally set a <em>Resume on</em> date.</li>
<li>While paused, the cron skips the subscription: it is not invoiced,
started or closed.</li>
<li>Press <em>Resume</em> to reactivate it manually. If a <em>Resume on</em> date was
set, the cron resumes the subscription automatically once that date
is reached. Leaving the date empty pauses it indefinitely.</li>
</ol>
</div>
<div class="section" id="known-issues-roadmap">
<h2><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h2>
Expand Down
1 change: 1 addition & 0 deletions subscription_oca/tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
from . import test_subscription_security
from . import test_subscription_recurrence_dates
from . import test_subscription_partner_addresses
from . import test_subscription_pause
Loading
Loading