diff --git a/rowers/braintreestuff.py b/rowers/braintreestuff.py index 145a766d..92a10f28 100644 --- a/rowers/braintreestuff.py +++ b/rowers/braintreestuff.py @@ -418,35 +418,72 @@ def create_subscription(rower, data): return False, 0 # pragma: no cover - def cancel_subscription(rower, id): themessages = [] errormessages = [] + + # 1. Fetch subscription first so we can read paid_through_date try: - _ = gateway.subscription.cancel(id) - themessages.append("Subscription canceled") - except: # pragma: no cover + subscription = gateway.subscription.find(id) + paid_through = subscription.paid_through_date # may be None + except Exception: errormessages.append( "We could not find the subscription record in our customer database." - " We have notified the site owner, who will contact you.") + " We have notified the site owner, who will contact you." + ) - name = '{f} {l}'.format(f=rower.user.first_name, - l=rower.user.last_name) + name = f"{rower.user.first_name} {rower.user.last_name}" - _ = myqueue(queuehigh, - handle_send_email_failed_cancel, - name, rower.user.email, rower.user.username, id) + _ = myqueue( + queuehigh, + handle_send_email_failed_cancel, + name, + rower.user.email, + rower.user.username, + id, + ) return False, themessages, errormessages + # 2. Attempt cancellation + try: + _ = gateway.subscription.cancel(id) + themessages.append("Subscription canceled") + except Exception: # pragma: no cover + errormessages.append( + "We could not find the subscription record in our customer database." + " We have notified the site owner, who will contact you." + ) + + name = f"{rower.user.first_name} {rower.user.last_name}" + + _ = myqueue( + queuehigh, + handle_send_email_failed_cancel, + name, + rower.user.email, + rower.user.username, + id, + ) + + return False, themessages, errormessages + + # 3. Update rower object (using paid_through_date) basicplans = PaidPlan.objects.filter(price=0, paymentprocessor='braintree') rower.paidplan = basicplans[0] + + # teamplanexpires stays "now" (as you had it) rower.teamplanexpires = timezone.now() - rower.planexpires = timezone.now() + + # planexpires becomes the user's real, fully paid end date + # fallback = now() if Braintree somehow returns None + rower.planexpires = paid_through or timezone.now() + rower.clubsize = 0 rower.rowerplan = 'basic' rower.subscription_id = None rower.save() + themessages.append("Your plan was reset to basic") return True, themessages, errormessages diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py index b10dd241..b0235bfb 100644 --- a/rowers/management/commands/processemail.py +++ b/rowers/management/commands/processemail.py @@ -93,15 +93,15 @@ class Command(BaseCommand): lines = traceback.format_exception(exc_type, exc_value, exc_traceback) dologging('processemail.log', ''.join('!! ' + line for line in lines)) - rowers = Rower.objects.filter(rp3_auto_import=True) - for r in rowers: # pragma: no cover - try: - rp3_integration = RP3Integration(r.user) - _ = rp3_integration.get_workouts() - except: # pragma: no cover - exc_type, exc_value, exc_traceback = sys.exc_info() - lines = traceback.format_exception(exc_type, exc_value, exc_traceback) - dologging('processemail.log', ''.join('!! ' + line for line in lines)) + #rowers = Rower.objects.filter(rp3_auto_import=True) + #for r in rowers: # pragma: no cover + # try: + # rp3_integration = RP3Integration(r.user) + # _ = rp3_integration.get_workouts() + # except: # pragma: no cover + # exc_type, exc_value, exc_traceback = sys.exc_info() + # lines = traceback.format_exception(exc_type, exc_value, exc_traceback) + # dologging('processemail.log', ''.join('!! ' + line for line in lines)) rowers = Rower.objects.filter(nk_auto_import=True) for r in rowers: # pragma: no cover diff --git a/rowers/templates/frontpage.html b/rowers/templates/frontpage.html index 7b10cdc4..0b12898e 100644 --- a/rowers/templates/frontpage.html +++ b/rowers/templates/frontpage.html @@ -44,14 +44,7 @@ {% if user.is_anonymous %}
  • -
  • - -

    -
    SIGN UP FREE
    -

    -
    -
  • -
  • +
  • diff --git a/rowers/templates/landingpage.html b/rowers/templates/landingpage.html index cb68078a..23d9b9ba 100644 --- a/rowers/templates/landingpage.html +++ b/rowers/templates/landingpage.html @@ -209,13 +209,6 @@ - {% if not user.is_authenticated %} -
    -

    SIGN UP

    -

    I am a rower

    -

    I am a rowing coach

    -
    - {% endif %}
    @@ -353,9 +346,6 @@ using my NK empower oarlock for about a month now, and I‘m really
  • Contact
  • -
  • - Paid Plans -
  • Legal
  • diff --git a/rowers/tests/test_newusers.py b/rowers/tests/atest_newusers.py similarity index 100% rename from rowers/tests/test_newusers.py rename to rowers/tests/atest_newusers.py diff --git a/rowers/tests/test_payments.py b/rowers/tests/atest_payments.py similarity index 100% rename from rowers/tests/test_payments.py rename to rowers/tests/atest_payments.py diff --git a/rowers/tests/mocks.py b/rowers/tests/mocks.py index 63e4440b..398968ac 100644 --- a/rowers/tests/mocks.py +++ b/rowers/tests/mocks.py @@ -557,6 +557,7 @@ class gatewayresult(): # pragma: no cover self.transaction = vtransaction() self.payment_method = vpayment_method() self.subscription = vsubscription() + self.paid_through_date = datetime.datetime.now()+datetime.timedelta(days=365) self.customer = kwargs.pop('customer',customer()) def __unicode__(): @@ -615,6 +616,7 @@ class transaction(): # pragma: no cover 'id': 12 } self.created_at = datetime.datetime.now() + self.paid_through_date = datetime.datetime.now()+datetime.timedelta(days=365) self.currency_iso_code = 'EUR' class vtransaction(): # pragma: no cover @@ -627,6 +629,7 @@ class vtransaction(): # pragma: no cover 'id': 12 } self.created_at = datetime.datetime.now() + self.paid_through_date = datetime.datetime.now()+datetime.timedelta(days=365) self.currency_iso_code = 'EUR' class vsubscription(): # pragma: no cover @@ -636,9 +639,13 @@ class vsubscription(): # pragma: no cover def cancel(*args, **kwargs): return gatewayresult(is_success=True) + def find(*args, **kwargs): + return subscription() + def __init__(self, *args, **kwargs): self.id = '121' self.billing_period_end_date = (datetime.datetime.now()+datetime.timedelta(days=365)).date() + self.paid_through_date = (datetime.datetime.now()+datetime.timedelta(days=365)).date() self.status = 'Active' self.plan_id = 12 self.price = 15 @@ -654,9 +661,13 @@ class subscription(): # pragma: no cover def cancel(*args, **kwargs): return gatewayresult(is_success=True) + def find(*args, **kwargs): + return subscription() + def __init__(self, *args, **kwargs): self.id = '121' self.billing_period_end_date = (datetime.datetime.now()+datetime.timedelta(days=365)).date() + self.paid_through_date = (datetime.datetime.now()+datetime.timedelta(days=365)).date() self.transactions = [vtransaction()] self.status = 'Active' self.plan_id = 12 diff --git a/rowers/tests/test_braintree.py b/rowers/tests/test_braintree.py index 88654e4b..1a6a41bd 100644 --- a/rowers/tests/test_braintree.py +++ b/rowers/tests/test_braintree.py @@ -79,7 +79,8 @@ class BraintreeUnits(TestCase): @patch('rowers.idoklad.requests.post',side_effect=mocked_requests) @patch('rowers.braintreestuff.gateway', side_effect=MockBraintreeGateway) @patch('rowers.braintreestuff.myqueue') - def test_process_webhook(self,mock_token, mock_get,mockpost,mocked_gateway,mocked_myqueue): + @patch('rowers.braintreestuff.cancel_subscription', side_effect=mock_cancel_subscription) + def test_process_webhook(self,mock_token, mock_get,mockpost,mocked_gateway,mocked_myqueue,mock_cancel_subscription): n = notification() res = process_webhook(n) self.assertEqual(res,1) diff --git a/rowers/tests/test_permissions.py b/rowers/tests/test_permissions.py index d802cced..8fd2271b 100644 --- a/rowers/tests/test_permissions.py +++ b/rowers/tests/test_permissions.py @@ -880,8 +880,6 @@ class PermissionsViewTests(TestCase): self.assertTrue(form.is_valid()) - expected_url = reverse('paidplans_view') - response = self.c.post(url,form_data,follow=True) # check that it does not redirect and status code is 200 diff --git a/rowers/tests/test_urls.py b/rowers/tests/test_urls.py index f08b1e9d..a7d5a292 100644 --- a/rowers/tests/test_urls.py +++ b/rowers/tests/test_urls.py @@ -77,7 +77,6 @@ class URLTests(TestCase): '/rowers/404/', '/rowers/500/', '/rowers/502/', - '/rowers/about/', '/rowers/workout/addmanual/', '/rowers/ajax_agegroup/45/hwt/male/1/', '/rowers/analysis/', @@ -119,8 +118,6 @@ class URLTests(TestCase): '/rowers/me/workflowdefault/', '/rowers/partners/', '/rowers/physics/', - '/rowers/register/', - '/rowers/register/thankyou/', '/rowers/sessions/', '/rowers/sessions/coach/', '/rowers/sessions/create/', diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv index 8218f6f2..4db4bdab 100644 --- a/rowers/tests/viewnames.csv +++ b/rowers/tests/viewnames.csv @@ -137,23 +137,7 @@ 178,225,sendmail,feedback form,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 180,232,laboratory_view,lab,TRUE,302,basic,200,302,basic,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE,TRUE, 181,233,errormessage_view,not used,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -182,237,payment_confirm_view,confirm payment,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -183,238,upgrade_confirm_view,confirm upgrade,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -184,240,downgrade_confirm_view,confirm downgrade,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -185,241,billing_view,confirm billing,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -186,242,upgrade_view,confirm upgrade,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -187,243,downgrade_view,confirm downgrade,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -188,244,payment_completed_view,payment completed,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -189,245,downgrade_completed_view,downgrade completed,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -190,246,paidplans_view,paid plans,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, -191,247,plan_stop_view,stop plan,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, 192,248,plan_tobasic_view,reset to basic,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -193,249,checkouts_view,checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -194,250,upgrade_checkouts_view,upgrade checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -195,251,downgrade_checkouts_view,downgrade checkout,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -197,253,start_trial_view,payments,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -198,254,start_plantrial_view,paid plans,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, -199,256,rower_register_view,register rower,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE,TRUE, 201,259,workout_workflow_view,workout workflow vieq,TRUE,302,basic,200,200,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE, 202,260,workout_flexchart3_view,flex chart,TRUE,302,basic,200,403,basic,200,200,coach,200,200,FALSE,FALSE,TRUE,TRUE,TRUE, 203,264,rower_process_testcallback,test callback,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE, diff --git a/rowers/urls.py b/rowers/urls.py index d56dc557..19fc570c 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -832,7 +832,6 @@ urlpatterns = [ name='payment_completed_view'), re_path(r'^downgradecompleted/$', views.downgrade_completed_view, name='downgrade_completed_view'), - re_path(r'^paidplans/$', views.paidplans_view, name='paidplans_view'), re_path(r'^me/cancelsubscriptions/$', views.plan_stop_view, name='plan_stop_view'), re_path(r'^me/cancelsubscription/(?P[\w\ ]+.*)/$', @@ -847,10 +846,6 @@ urlpatterns = [ re_path(r'^starttrial/$', views.start_trial_view, name='start_trial_view'), re_path(r'^legal', TemplateView.as_view( template_name='legal.html'), name='legal'), - re_path(r'^register/$', views.rower_register_view, - name='rower_register_view'), - re_path(r'^coachregister/$', views.coach_register_view, - name='coach_register_view'), path('activate///', views.useractivate, name='useractivate'), re_path(r'^register/thankyou/$', TemplateView.as_view( template_name='registerthankyou.html'), name='registerthankyou'), diff --git a/templates/newbase.html b/templates/newbase.html index 4c606e18..f8818b2b 100644 --- a/templates/newbase.html +++ b/templates/newbase.html @@ -165,11 +165,6 @@ {% else %} -
  • - - - -
  • @@ -225,12 +220,18 @@

  • {% endif %} +
  • +

    + Rowsandall functionality will be transferred to Intervals.icu during 2026. + For more details, read this announcement. +

    +
  • {% if user.rower.planexpires and user.rower|notfree and user.rower.paymenttype == 'single'%} {% if user.rower.planexpires|is_future_date %} {% if user.rower.planexpires|date_dif|ddays < 4 %}
  • - You have {{ user.rower.planexpires|date_dif|ddays }} days left of your one year subscription. Please renew on or before {{ user.rower.planexpires }} or your plan will be reset to Basic. Click here to renew your membership.

    + You have {{ user.rower.planexpires|date_dif|ddays }} days left of your one year subscription. Please renew on or before {{ user.rower.planexpires }} or your plan will be reset to Basic.

  • {% endif %} {% endif %} @@ -239,14 +240,14 @@ {% if user.rower.plantrialexpires and user.rower.plantrialexpires|is_future_date and user.rower.rowerplan != 'plan' %}
  • - {{ user.rower.protrialexpires|date_dif|ddays }} days left of your Self-Coach trial - Would you like to upgrade now? + {{ user.rower.protrialexpires|date_dif|ddays }} days left of your Self-Coach trial

  • {% else %} {% if user.rower.rowerplan == 'basic' %}
  • - {{ user.rower.protrialexpires|date_dif|ddays }} days left of your Pro trial - Would you like to upgrade now? + {{ user.rower.protrialexpires|date_dif|ddays }} days left of your Pro trial

  • {% endif %} @@ -255,7 +256,7 @@ {% if user.rower.coachtrialexpires and user.rower.coachtrialexpires|is_future_date and user.rower.rowerplan != 'coach' %}
  • - {{ user.rower.coachtrialexpires|date_dif|ddays }} days left of your Coach trial - Would you like to upgrade now? + {{ user.rower.coachtrialexpires|date_dif|ddays }} days left of your Coach trial

  • {% endif %} @@ -336,13 +337,7 @@
    - {% if user.is_authenticated and user.rower.rowerplan == 'basic' %} -
    - -
    - {% elif user.is_authenticated and user.rower.rowerplan == 'pro' %} + {% if user.is_authenticated and user.rower.rowerplan == 'pro' %}
    Thank you for supporting Rowsandall.com! @@ -409,14 +404,6 @@ -
  • -

    Support Us

    - -
  • Legal

  • -
  • -

    Paid Plans

    - -
  • Legal