diff --git a/subscription_oca/__manifest__.py b/subscription_oca/__manifest__.py index a54c7c2090..80c70ef869 100644 --- a/subscription_oca/__manifest__.py +++ b/subscription_oca/__manifest__.py @@ -12,6 +12,7 @@ "depends": ["sale_management", "account"], "data": [ "views/product_template_views.xml", + "views/account_move_views.xml", "views/sale_subscription_views.xml", "views/sale_subscription_stage_views.xml", "views/sale_subscription_tag_views.xml", diff --git a/subscription_oca/data/sale_subscription_data.xml b/subscription_oca/data/sale_subscription_data.xml index 6ee56a620e..eebea52b07 100644 --- a/subscription_oca/data/sale_subscription_data.xml +++ b/subscription_oca/data/sale_subscription_data.xml @@ -13,11 +13,21 @@ - Ready to start + Draft 0 + draft + + Draft, still working on the specifics. + + + + + + Ready to start + 1 pre - 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. + 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. @@ -25,7 +35,7 @@ In progress - 1 + 2 in_progress @@ -36,7 +46,7 @@ Closed - 2 + 3 post diff --git a/subscription_oca/models/account_move.py b/subscription_oca/models/account_move.py index 570a02f29a..7b3679697f 100644 --- a/subscription_oca/models/account_move.py +++ b/subscription_oca/models/account_move.py @@ -10,3 +10,11 @@ class AccountMove(models.Model): subscription_id = fields.Many2one( comodel_name="sale.subscription", string="Subscription" ) + + def action_open_subscription(self): + self.ensure_one() + action = self.env["ir.actions.act_window"]._for_xml_id( + "subscription_oca.sale_subscription_action" + ) + action["domain"] = [("id", "=", self.subscription_id.id)] + return action diff --git a/subscription_oca/models/sale_subscription.py b/subscription_oca/models/sale_subscription.py index 6845706840..301a0782d1 100644 --- a/subscription_oca/models/sale_subscription.py +++ b/subscription_oca/models/sale_subscription.py @@ -142,21 +142,24 @@ def cron_subscription_management(self): for subscription in self.search([]): if subscription.in_progress: if ( - subscription.recurring_next_date == today + subscription.recurring_next_date <= today and subscription.sale_subscription_line_ids ): try: subscription.generate_invoice() except Exception: logger.exception("Error on subscription invoice generate") - if not subscription.recurring_rule_boundary: - if subscription.date == today: - subscription.action_close_subscription() + if ( + not subscription.recurring_rule_boundary + and subscription.date <= today + ): + subscription.close_subscription() - else: - if subscription.date_start == today: - subscription.action_start_subscription() - subscription.generate_invoice() + elif ( + subscription.date_start <= today and subscription.stage_id.type == "pre" + ): + subscription.action_start_subscription() + subscription.generate_invoice() @api.depends("sale_subscription_line_ids") def _compute_total(self): @@ -239,7 +242,6 @@ def action_start_subscription(self): self.stage_id = in_progress_stage def action_close_subscription(self): - self.recurring_next_date = False return { "view_type": "form", "view_mode": "form", @@ -249,6 +251,15 @@ def action_close_subscription(self): "res_id": False, } + def close_subscription(self, close_reason_id=False): + self.ensure_one() + self.recurring_next_date = False + closed_stage = self.env["sale.subscription.stage"].search( + [("type", "=", "post")], limit=1 + ) + self.close_reason_id = close_reason_id + self.stage_id = closed_stage + def _prepare_sale_order(self, line_ids=False): self.ensure_one() return { @@ -271,6 +282,7 @@ def _prepare_account_move(self, line_ids): "invoice_user_id": self.user_id.id, "partner_bank_id": self.company_id.partner_id.bank_ids[:1].id, "invoice_line_ids": line_ids, + "subscription_id": self.id, } if self.journal_id: values["journal_id"] = self.journal_id.id @@ -294,7 +306,6 @@ def create_invoice(self): .with_context(default_move_type="out_invoice", journal_type="sale") .create(invoice_values) ) - self.write({"invoice_ids": [(4, invoice_id.id)]}) return invoice_id def create_sale_order(self): @@ -464,7 +475,7 @@ def create(self, values): values["date_start"] = values["recurring_next_date"] values["stage_id"] = ( self.env["sale.subscription.stage"] - .search([("type", "=", "pre")], order="sequence desc", limit=1) + .search([("type", "=", "draft")], order="sequence desc", limit=1) .id ) return super(SaleSubscription, self).create(values) diff --git a/subscription_oca/models/sale_subscription_stage.py b/subscription_oca/models/sale_subscription_stage.py index 8bc3961788..02a88ac4a9 100644 --- a/subscription_oca/models/sale_subscription_stage.py +++ b/subscription_oca/models/sale_subscription_stage.py @@ -16,7 +16,12 @@ class SaleSubscriptionStage(models.Model): fold = fields.Boolean(string="Kanban folded") description = fields.Text(translate=True) type = fields.Selection( - [("pre", "Ready to start"), ("in_progress", "In progress"), ("post", "Closed")], + [ + ("draft", "Draft"), + ("pre", "Ready to start"), + ("in_progress", "In progress"), + ("post", "Closed"), + ], default="pre", ) diff --git a/subscription_oca/static/description/index.html b/subscription_oca/static/description/index.html index c5a029c4ca..0247e4d805 100644 --- a/subscription_oca/static/description/index.html +++ b/subscription_oca/static/description/index.html @@ -1,3 +1,4 @@ + diff --git a/subscription_oca/tests/test_subscription_oca.py b/subscription_oca/tests/test_subscription_oca.py index 6711f5e2a4..ab486c4a02 100644 --- a/subscription_oca/tests/test_subscription_oca.py +++ b/subscription_oca/tests/test_subscription_oca.py @@ -2,6 +2,7 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import uuid +from unittest.mock import patch from dateutil.relativedelta import relativedelta @@ -182,6 +183,14 @@ def setUpClass(cls): "journal_id": cls.cash_journal.id, } ) + cls.sub9 = cls.create_sub( + { + "template_id": cls.tmpl3.id, + "date_start": fields.Date.today() - relativedelta(days=100), + "in_progress": True, + "recurring_rule_boundary": True, + } + ) cls.sub_line = cls.create_sub_line(cls.sub1) cls.sub_line2 = cls.env["sale.subscription.line"].create( @@ -334,6 +343,18 @@ def test_subscription_oca_sub_lines(self): move_res = self.sub_line._prepare_account_move_line() self.assertIsInstance(move_res, dict) + @patch( + "odoo.addons.subscription_oca.models.sale_subscription." + "SaleSubscription.generate_invoice" + ) + def test_subscription_oca_sub_cron_error(self, generate_invoice_patch): + # Simulate something failing in generating an invoice, + # we expect something being logged + generate_invoice_patch.side_effect = exceptions.UserError("Error") + with self.assertLogs(level="ERROR"): + with self.assertRaises(exceptions.UserError): + self.sub1.cron_subscription_management() + def test_subscription_oca_sub_cron(self): # sale.subscription self.sub1.cron_subscription_management() @@ -518,7 +539,7 @@ def test_subscription_oca_sub_stage(self): def test_x_subscription_oca_pricelist_related(self): res = self.partner.read(["subscription_count", "subscription_ids"]) - self.assertEqual(res[0]["subscription_count"], 8) + self.assertEqual(res[0]["subscription_count"], 9) res = self.partner.action_view_subscription_ids() self.assertIsInstance(res, dict) sale_order = self.sub1.create_sale_order() @@ -540,7 +561,7 @@ def test_x_subscription_oca_pricelist_related(self): wiz = self.env["close.reason.wizard"].create({}) wiz.with_context(active_id=self.sub1.id).button_confirm() self.assertEqual(self.sub1.stage_id.name, "Closed") - self.assertFalse(self.sub1.active) + self.assertTrue(self.sub1.active) self.tmpl1.action_view_subscription_ids() self.tmpl1.action_view_product_ids() self.tmpl1.read(["product_ids_count", "subscription_count"]) @@ -616,6 +637,11 @@ def test_compute_display_name(self): stage.display_name, "Updated Test Stage", "display_name not computed" ) + def test_open_subscription(self): + invoice = self.sub1.create_invoice() + action = invoice.action_open_subscription() + self.assertEqual(action["domain"], [("id", "=", self.sub1.id)]) + def _collect_all_sub_test_results(self, subscription): test_res = [] sale_order = subscription.create_sale_order() diff --git a/subscription_oca/views/account_move_views.xml b/subscription_oca/views/account_move_views.xml new file mode 100644 index 0000000000..0af0012123 --- /dev/null +++ b/subscription_oca/views/account_move_views.xml @@ -0,0 +1,20 @@ + + + + account.move + + + + +