From 6d6ff5ea2bbe0e01c69505663c6465122c124693 Mon Sep 17 00:00:00 2001
From: Ahmad Khanalizadeh <khah@odoo.com>
Date: Wed, 26 Oct 2022 13:08:41 +0000
Subject: [PATCH] [FIX] membership: calculate membership state

Steps to reproduce:
1. Create a membership product for a period of time in the past,
 and one including the current day
2. Create a member, make him non-free
3. Create an invoice for the member for the past membership, cancel
 the invoice
4. Note that membership state is not updated to `cancelled` (Problem 1)
5. Change the `date_cancel` on membership.membership.line
 to a date in the past
6. Add an invoice for the current membership, note that the state is
 updated to `cancelled`
7. confirm the invoice and register payment, note that the state is
 not update to `paid` (Problem 2)

This line in `_compute_membership_state` causes the bug to appear:
```
if partner.membership_cancel and today > partner.membership_cancel:
    partner.membership_state = 'free' if partner.free_member else 'canceled'
    continue
```

To solve the issue, we remove the lines of code that made the state
to be stuck and use the membership lines only to calculate the correct
state.

opw-2978902

closes odoo/odoo#104178

Signed-off-by: Grazioso Andrea (agr) <agr@odoo.com>
---
 addons/membership/models/partner.py | 57 ++++++++++-------------------
 1 file changed, 19 insertions(+), 38 deletions(-)

diff --git a/addons/membership/models/partner.py b/addons/membership/models/partner.py
index 5528d7ada53e..30de29f7e2d2 100644
--- a/addons/membership/models/partner.py
+++ b/addons/membership/models/partner.py
@@ -43,60 +43,41 @@ class Partner(models.Model):
                  'member_lines.account_invoice_line.move_id.partner_id',
                  'free_member',
                  'member_lines.date_to', 'member_lines.date_from',
-                 'associate_member')
+                 'associate_member', 'associate_member.membership_state')
     def _compute_membership_state(self):
         today = fields.Date.today()
         for partner in self:
-            state = 'none'
-
             partner.membership_start = self.env['membership.membership_line'].search([
-                ('partner', '=', partner.associate_member.id or partner.id), ('date_cancel','=',False)
+                ('partner', '=', partner.associate_member.id or partner.id), ('date_cancel', '=', False)
             ], limit=1, order='date_from').date_from
             partner.membership_stop = self.env['membership.membership_line'].search([
-                ('partner', '=', partner.associate_member.id or partner.id),('date_cancel','=',False)
+                ('partner', '=', partner.associate_member.id or partner.id), ('date_cancel', '=', False)
             ], limit=1, order='date_to desc').date_to
             partner.membership_cancel = self.env['membership.membership_line'].search([
                 ('partner', '=', partner.id)
             ], limit=1, order='date_cancel').date_cancel
 
-            if partner.membership_cancel and today > partner.membership_cancel:
-                partner.membership_state = 'free' if partner.free_member else 'canceled'
-                continue
-            if partner.membership_stop and today > partner.membership_stop:
-                if partner.free_member:
-                    partner.membership_state = 'free'
-                    continue
             if partner.associate_member:
-                partner.associate_member._compute_membership_state()
                 partner.membership_state = partner.associate_member.membership_state
                 continue
 
-            line_states = [mline.state for mline in partner.member_lines if \
-                           (mline.date_to or date.min) >= today and \
-                           (mline.date_from or date.min) <= today and \
-                           mline.account_invoice_line.move_id.partner_id == partner]
-
-            if 'paid' in line_states:
-                state = 'paid'
-            elif 'invoiced' in line_states:
-                state = 'invoiced'
-            elif 'waiting' in line_states:
-                state = 'waiting'
-            elif 'canceled' in line_states:
-                state = 'canceled'
-
-            if state == 'none':
-                for mline in partner.member_lines:
-                    # if there is an old invoice paid, set the state to 'old'
-                    if ((mline.date_from or date.min) < today and (mline.date_to or date.min) < today and \
-                            (mline.date_from or date.min) <= (mline.date_to or date.min) and \
-                            mline.account_invoice_id and mline.account_invoice_id.payment_state in ('in_payment', 'paid')):
-                        state = 'old'
-                        break
+            if partner.free_member and partner.membership_state != 'paid':
+                partner.membership_state = 'free'
+                continue
 
-            if partner.free_member and state != 'paid':
-                state = 'free'
-            partner.membership_state = state
+            for mline in partner.member_lines:
+                if (mline.date_to or date.min) >= today and (mline.date_from or date.min) <= today:
+                    partner.membership_state = mline.state
+                    break
+                elif ((mline.date_from or date.min) < today and (mline.date_to or date.min) <= today and \
+                      (mline.date_from or date.min) < (mline.date_to or date.min)):
+                    if mline.account_invoice_id and mline.account_invoice_id.payment_state in ('in_payment', 'paid'):
+                        partner.membership_state = 'old'
+                    elif mline.account_invoice_id and mline.account_invoice_id.state == 'cancel':
+                        partner.membership_state = 'canceled'
+                    break
+            else:
+                partner.membership_state = 'none'
 
     @api.constrains('associate_member')
     def _check_recursion_associate_member(self):
-- 
GitLab