Skip to content

Commit 7692fa2

Browse files
committed
Merge PR #1058 into 16.0
Signed-off-by dreispt
2 parents ea15f99 + e03cded commit 7692fa2

9 files changed

+101
-26
lines changed

subscription_oca/__manifest__.py

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"depends": ["sale_management", "account"],
1313
"data": [
1414
"views/product_template_views.xml",
15+
"views/account_move_views.xml",
1516
"views/sale_subscription_views.xml",
1617
"views/sale_subscription_stage_views.xml",
1718
"views/sale_subscription_tag_views.xml",

subscription_oca/data/sale_subscription_data.xml

+14-4
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,29 @@
1313
<data noupdate="1">
1414
<record id="subscription_stage_draft" model="sale.subscription.stage">
1515
<!-- <field eval="True" name="active"/> -->
16-
<field name="name">Ready to start</field>
16+
<field name="name">Draft</field>
1717
<field name="sequence">0</field>
18+
<field name="type">draft</field>
19+
<field name="description">
20+
Draft, still working on the specifics.
21+
</field>
22+
<field eval="False" name="fold" />
23+
</record>
24+
<record id="subscription_stage_ready" model="sale.subscription.stage">
25+
<!-- <field eval="True" name="active"/> -->
26+
<field name="name">Ready to start</field>
27+
<field name="sequence">1</field>
1828
<field name="type">pre</field>
1929
<field name="description">
20-
Draft equivalent, a subscription is ready to start when is not marked as in progress but it can be at any moment. If there's no 'Closed'-type stage defined, when a subscription comes to an end by automatic means, it will be marked with this stage.
30+
A subscription is ready to start when is not marked as in progress but it can be at any moment. If there's no 'Closed'-type stage defined, when a subscription comes to an end by automatic means, it will be marked with this stage.
2131
</field>
2232
<field eval="False" name="fold" />
2333
</record>
2434

2535
<record id="subscription_stage_in_progress" model="sale.subscription.stage">
2636
<!-- <field eval="True" name="active"/> -->
2737
<field name="name">In progress</field>
28-
<field name="sequence">1</field>
38+
<field name="sequence">2</field>
2939
<field name="type">in_progress</field>
3040
<field eval="False" name="fold" />
3141
<field name="description">
@@ -36,7 +46,7 @@
3646
<record id="subscription_stage_closed" model="sale.subscription.stage">
3747
<!-- <field eval="True" name="active"/> -->
3848
<field name="name">Closed</field>
39-
<field name="sequence">2</field>
49+
<field name="sequence">3</field>
4050
<field name="type">post</field>
4151
<field eval="False" name="fold" />
4252
<field name="description">

subscription_oca/models/account_move.py

+8
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,11 @@ class AccountMove(models.Model):
1010
subscription_id = fields.Many2one(
1111
comodel_name="sale.subscription", string="Subscription"
1212
)
13+
14+
def action_open_subscription(self):
15+
self.ensure_one()
16+
action = self.env["ir.actions.act_window"]._for_xml_id(
17+
"subscription_oca.sale_subscription_action"
18+
)
19+
action["domain"] = [("id", "=", self.subscription_id.id)]
20+
return action

subscription_oca/models/sale_subscription.py

+22-11
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,24 @@ def cron_subscription_management(self):
142142
for subscription in self.search([]):
143143
if subscription.in_progress:
144144
if (
145-
subscription.recurring_next_date == today
145+
subscription.recurring_next_date <= today
146146
and subscription.sale_subscription_line_ids
147147
):
148148
try:
149149
subscription.generate_invoice()
150150
except Exception:
151151
logger.exception("Error on subscription invoice generate")
152-
if not subscription.recurring_rule_boundary:
153-
if subscription.date == today:
154-
subscription.action_close_subscription()
152+
if (
153+
not subscription.recurring_rule_boundary
154+
and subscription.date <= today
155+
):
156+
subscription.close_subscription()
155157

156-
else:
157-
if subscription.date_start == today:
158-
subscription.action_start_subscription()
159-
subscription.generate_invoice()
158+
elif (
159+
subscription.date_start <= today and subscription.stage_id.type == "pre"
160+
):
161+
subscription.action_start_subscription()
162+
subscription.generate_invoice()
160163

161164
@api.depends("sale_subscription_line_ids")
162165
def _compute_total(self):
@@ -239,7 +242,6 @@ def action_start_subscription(self):
239242
self.stage_id = in_progress_stage
240243

241244
def action_close_subscription(self):
242-
self.recurring_next_date = False
243245
return {
244246
"view_type": "form",
245247
"view_mode": "form",
@@ -249,6 +251,15 @@ def action_close_subscription(self):
249251
"res_id": False,
250252
}
251253

254+
def close_subscription(self, close_reason_id=False):
255+
self.ensure_one()
256+
self.recurring_next_date = False
257+
closed_stage = self.env["sale.subscription.stage"].search(
258+
[("type", "=", "post")], limit=1
259+
)
260+
self.close_reason_id = close_reason_id
261+
self.stage_id = closed_stage
262+
252263
def _prepare_sale_order(self, line_ids=False):
253264
self.ensure_one()
254265
return {
@@ -271,6 +282,7 @@ def _prepare_account_move(self, line_ids):
271282
"invoice_user_id": self.user_id.id,
272283
"partner_bank_id": self.company_id.partner_id.bank_ids[:1].id,
273284
"invoice_line_ids": line_ids,
285+
"subscription_id": self.id,
274286
}
275287
if self.journal_id:
276288
values["journal_id"] = self.journal_id.id
@@ -294,7 +306,6 @@ def create_invoice(self):
294306
.with_context(default_move_type="out_invoice", journal_type="sale")
295307
.create(invoice_values)
296308
)
297-
self.write({"invoice_ids": [(4, invoice_id.id)]})
298309
return invoice_id
299310

300311
def create_sale_order(self):
@@ -464,7 +475,7 @@ def create(self, values):
464475
values["date_start"] = values["recurring_next_date"]
465476
values["stage_id"] = (
466477
self.env["sale.subscription.stage"]
467-
.search([("type", "=", "pre")], order="sequence desc", limit=1)
478+
.search([("type", "=", "draft")], order="sequence desc", limit=1)
468479
.id
469480
)
470481
return super(SaleSubscription, self).create(values)

subscription_oca/models/sale_subscription_stage.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ class SaleSubscriptionStage(models.Model):
1616
fold = fields.Boolean(string="Kanban folded")
1717
description = fields.Text(translate=True)
1818
type = fields.Selection(
19-
[("pre", "Ready to start"), ("in_progress", "In progress"), ("post", "Closed")],
19+
[
20+
("draft", "Draft"),
21+
("pre", "Ready to start"),
22+
("in_progress", "In progress"),
23+
("post", "Closed"),
24+
],
2025
default="pre",
2126
)
2227

subscription_oca/static/description/index.html

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
12
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
23
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
34
<head>

subscription_oca/tests/test_subscription_oca.py

+28-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
33

44
import uuid
5+
from unittest.mock import patch
56

67
from dateutil.relativedelta import relativedelta
78

@@ -182,6 +183,14 @@ def setUpClass(cls):
182183
"journal_id": cls.cash_journal.id,
183184
}
184185
)
186+
cls.sub9 = cls.create_sub(
187+
{
188+
"template_id": cls.tmpl3.id,
189+
"date_start": fields.Date.today() - relativedelta(days=100),
190+
"in_progress": True,
191+
"recurring_rule_boundary": True,
192+
}
193+
)
185194

186195
cls.sub_line = cls.create_sub_line(cls.sub1)
187196
cls.sub_line2 = cls.env["sale.subscription.line"].create(
@@ -334,6 +343,18 @@ def test_subscription_oca_sub_lines(self):
334343
move_res = self.sub_line._prepare_account_move_line()
335344
self.assertIsInstance(move_res, dict)
336345

346+
@patch(
347+
"odoo.addons.subscription_oca.models.sale_subscription."
348+
"SaleSubscription.generate_invoice"
349+
)
350+
def test_subscription_oca_sub_cron_error(self, generate_invoice_patch):
351+
# Simulate something failing in generating an invoice,
352+
# we expect something being logged
353+
generate_invoice_patch.side_effect = exceptions.UserError("Error")
354+
with self.assertLogs(level="ERROR"):
355+
with self.assertRaises(exceptions.UserError):
356+
self.sub1.cron_subscription_management()
357+
337358
def test_subscription_oca_sub_cron(self):
338359
# sale.subscription
339360
self.sub1.cron_subscription_management()
@@ -518,7 +539,7 @@ def test_subscription_oca_sub_stage(self):
518539

519540
def test_x_subscription_oca_pricelist_related(self):
520541
res = self.partner.read(["subscription_count", "subscription_ids"])
521-
self.assertEqual(res[0]["subscription_count"], 8)
542+
self.assertEqual(res[0]["subscription_count"], 9)
522543
res = self.partner.action_view_subscription_ids()
523544
self.assertIsInstance(res, dict)
524545
sale_order = self.sub1.create_sale_order()
@@ -540,7 +561,7 @@ def test_x_subscription_oca_pricelist_related(self):
540561
wiz = self.env["close.reason.wizard"].create({})
541562
wiz.with_context(active_id=self.sub1.id).button_confirm()
542563
self.assertEqual(self.sub1.stage_id.name, "Closed")
543-
self.assertFalse(self.sub1.active)
564+
self.assertTrue(self.sub1.active)
544565
self.tmpl1.action_view_subscription_ids()
545566
self.tmpl1.action_view_product_ids()
546567
self.tmpl1.read(["product_ids_count", "subscription_count"])
@@ -616,6 +637,11 @@ def test_compute_display_name(self):
616637
stage.display_name, "Updated Test Stage", "display_name not computed"
617638
)
618639

640+
def test_open_subscription(self):
641+
invoice = self.sub1.create_invoice()
642+
action = invoice.action_open_subscription()
643+
self.assertEqual(action["domain"], [("id", "=", self.sub1.id)])
644+
619645
def _collect_all_sub_test_results(self, subscription):
620646
test_res = []
621647
sale_order = subscription.create_sale_order()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" ?>
2+
<odoo>
3+
<record id="view_move_form" model="ir.ui.view">
4+
<field name="model">account.move</field>
5+
<field name="inherit_id" ref="account.view_move_form" />
6+
<field name="arch" type="xml">
7+
<xpath expr="//div[@name='button_box']" position="inside">
8+
<field name="subscription_id" invisible="1" />
9+
<button
10+
name="action_open_subscription"
11+
type="object"
12+
class="oe_stat_button"
13+
icon="fa-calendar"
14+
string="Subscription"
15+
attrs="{'invisible': [('subscription_id', '=', False)]}"
16+
/>
17+
</xpath>
18+
</field>
19+
</record>
20+
</odoo>

subscription_oca/wizard/close_subscription_wizard.py

+1-8
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,4 @@ def button_confirm(self):
1515
sale_subscription = self.env["sale.subscription"].browse(
1616
self.env.context["active_id"]
1717
)
18-
sale_subscription.close_reason_id = self.close_reason_id.id
19-
stage = sale_subscription.stage_id
20-
closed_stage = self.env["sale.subscription.stage"].search(
21-
[("type", "=", "post")], limit=1
22-
)
23-
if stage != closed_stage:
24-
sale_subscription.stage_id = closed_stage
25-
sale_subscription.active = False
18+
sale_subscription.close_subscription(self.close_reason_id.id)

0 commit comments

Comments
 (0)