Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions membership_extension/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"application": False,
"installable": True,
"depends": ["membership"],
"maintainers": ["rafaelbn", "yajo"],
"data": [
"security/membership_security.xml",
"security/ir.model.access.csv",
Expand Down
10 changes: 10 additions & 0 deletions membership_extension/migrations/16.0.3.0.0/post-recompute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright 2024 Moduon Team S.L.
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl-3.0)
from openupgradelib import openupgrade


@openupgrade.migrate()
def migrate(env, version):
env["res.partner"].search(
["|", ("membership_cancel", "!=", False), ("membership_state", "=", "free")]
)._compute_membership_date()
8 changes: 1 addition & 7 deletions membership_extension/models/membership_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ class MembershipLine(models.Model):
)
date_from = fields.Date(readonly=False)
date_to = fields.Date(readonly=False)
state = fields.Selection(
compute="_compute_state", inverse="_inverse_state", store=True, readonly=False
)
state = fields.Selection(compute="_compute_state", readonly=False)
partner = fields.Many2one(ondelete="restrict")
member_price = fields.Float(
compute="_compute_member_price", readonly=False, store=True
Expand Down Expand Up @@ -66,10 +64,6 @@ def _compute_state(self):
MembershipLine, self - no_invoice_lines - cancelled_lines
)._compute_state()

# Empty method _inverse_state
def _inverse_state(self):
return True # pragma: no cover

def unlink(self):
allow = self.env.context.get("allow_membership_line_unlink", False)
if self.filtered("account_invoice_id") and not allow:
Expand Down
5 changes: 4 additions & 1 deletion membership_extension/models/res_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def _membership_member_states(self):

List of membership line states that define a partner as member
"""
return ("invoiced", "paid")
return ("invoiced", "free", "paid")

def _membership_state_prior(self):
"""Inherit this method to define membership state precedence
Expand Down Expand Up @@ -167,6 +167,9 @@ def _compute_membership_date(self):
line.date_cancel and last_cancel < line.date_cancel
):
last_cancel = line.date_cancel
if last_cancel and last_from and last_cancel < last_from:
# Membership was restarted after a cancellation
last_cancel = False
partner.membership_start = date_from
partner.membership_last_start = last_from
partner.membership_stop = last_to
Expand Down
89 changes: 73 additions & 16 deletions membership_extension/tests/test_membership.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
# Copyright 2019 Onestein - Andrea Stirpe
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from datetime import datetime, timedelta
from datetime import date, datetime, timedelta

from freezegun import freeze_time
from psycopg2 import IntegrityError

from odoo import fields
Expand All @@ -13,6 +14,7 @@
from odoo.tools import mute_logger


@freeze_time("2025-01-01")
class TestMembership(common.TransactionCase):
@classmethod
def setUpClass(cls):
Expand Down Expand Up @@ -129,28 +131,28 @@ def test_compute_membership(self):
self.assertEqual(fields.Date.today(), self.child.membership_last_start)
self.assertEqual(self.next_month, self.child.membership_stop)
self.assertFalse(self.child.membership_cancel)
line.write({"date_cancel": self.yesterday})
self.assertEqual("old", self.partner.membership_state)
line.write({"date_cancel": fields.Date.today()})
self.assertEqual("invoiced", self.partner.membership_state)
self.assertEqual(fields.Date.today(), self.partner.membership_start)
self.assertEqual(fields.Date.today(), self.partner.membership_last_start)
self.assertEqual(self.yesterday, self.partner.membership_stop)
self.assertEqual(self.yesterday, self.partner.membership_cancel)
self.assertEqual("old", self.child.membership_state)
self.assertEqual(fields.Date.today(), self.partner.membership_stop)
self.assertEqual(fields.Date.today(), self.partner.membership_cancel)
self.assertEqual("invoiced", self.child.membership_state)
self.assertEqual(fields.Date.today(), self.child.membership_start)
self.assertEqual(fields.Date.today(), self.child.membership_last_start)
self.assertEqual(self.yesterday, self.child.membership_stop)
self.assertEqual(self.yesterday, self.child.membership_cancel)
self.assertEqual(fields.Date.today(), self.child.membership_stop)
self.assertEqual(fields.Date.today(), self.child.membership_cancel)
line.write({"state": "canceled"})
self.assertEqual("none", self.partner.membership_state)
self.assertEqual("canceled", self.partner.membership_state)
self.assertFalse(self.partner.membership_start)
self.assertFalse(self.partner.membership_last_start)
self.assertFalse(self.partner.membership_stop)
self.assertEqual(self.yesterday, self.partner.membership_cancel)
self.assertEqual("none", self.child.membership_state)
self.assertEqual(fields.Date.today(), self.partner.membership_cancel)
self.assertEqual("canceled", self.child.membership_state)
self.assertFalse(self.child.membership_start)
self.assertFalse(self.child.membership_last_start)
self.assertFalse(self.child.membership_stop)
self.assertEqual(self.yesterday, self.child.membership_cancel)
self.assertEqual(fields.Date.today(), self.child.membership_cancel)
other_line = self.env["membership.membership_line"].create(
{
"membership_id": self.silver_product.id,
Expand All @@ -166,23 +168,23 @@ def test_compute_membership(self):
self.assertFalse(self.partner.membership_start)
self.assertFalse(self.partner.membership_last_start)
self.assertFalse(self.partner.membership_stop)
self.assertEqual(self.yesterday, self.partner.membership_cancel)
self.assertEqual(fields.Date.today(), self.partner.membership_cancel)
self.assertEqual("waiting", self.child.membership_state)
self.assertFalse(self.child.membership_start)
self.assertFalse(self.child.membership_last_start)
self.assertFalse(self.child.membership_stop)
self.assertEqual(self.yesterday, self.child.membership_cancel)
self.assertEqual(fields.Date.today(), self.child.membership_cancel)
other_line.write({"state": "paid"})
self.assertEqual("paid", self.partner.membership_state)
self.assertEqual(fields.Date.today(), self.partner.membership_start)
self.assertEqual(fields.Date.today(), self.partner.membership_last_start)
self.assertEqual(self.next_two_months, self.partner.membership_stop)
self.assertEqual(self.yesterday, self.partner.membership_cancel)
self.assertEqual(fields.Date.today(), self.partner.membership_cancel)
self.assertEqual("paid", self.child.membership_state)
self.assertEqual(fields.Date.today(), self.child.membership_start)
self.assertEqual(fields.Date.today(), self.child.membership_last_start)
self.assertEqual(self.next_two_months, self.child.membership_stop)
self.assertEqual(self.yesterday, self.child.membership_cancel)
self.assertEqual(fields.Date.today(), self.child.membership_cancel)
self.partner.free_member = True
self.assertEqual("free", self.child.membership_state)

Expand Down Expand Up @@ -497,3 +499,58 @@ def test_no_dates(self):
"membership_date_to": "1970-01-02",
}
)

def test_restore_after_cancel(self):
"""Membership is cancelled and, later, restarted."""
self.partner.write(
{
"member_lines": [
# Was member in 2022 but cancelled
fields.Command.create(
{
"membership_id": self.gold_product.id,
"member_price": 100.00,
"date": "2022-01-01",
"date_from": "2022-01-01",
"date_to": "2022-12-31",
"date_cancel": "2022-06-01",
"state": "free",
}
),
# Started again being member in 2024
fields.Command.create(
{
"membership_id": self.gold_product.id,
"member_price": 100.00,
"date": "2024-01-01",
"date_from": "2024-01-01",
"date_to": "2024-12-31",
"state": "free",
}
),
# In 2025 is still member
fields.Command.create(
{
"membership_id": self.gold_product.id,
"member_price": 100.00,
"date": "2025-01-01",
"date_from": "2025-01-01",
"date_to": "2025-12-31",
"state": "free",
}
),
]
}
)
self.assertRecordValues(
self.partner,
[
{
"membership_start": date(2022, 1, 1),
"membership_last_start": date(2025, 1, 1),
"membership_stop": date(2025, 12, 31),
"membership_cancel": False,
"membership_state": "free",
}
],
)