def toggle_subscription(request): try: if request.method == 'POST' and request.POST.get('id', None): subscription_id = int(request.POST.get('id')) subscription = get_object_or_404(Subscription, id=subscription_id) gatewayManager = InitPaymentGateway(request, subscription=subscription) resultSet = gatewayManager.toggle_recurring_payment() # add to the update actions log addUpdateSubsActionLog( gatewayManager.subscription, SUBS_ACTION_PAUSE if resultSet['recurring-status'] == STATUS_PAUSED else SUBS_ACTION_RESUME, user=request.user) messages.add_message( request, messages.SUCCESS, str( _('Subscription %(id)d status is toggled to %(status)s.') % { 'id': subscription_id, 'status': resultSet['recurring-status'].capitalize() })) return redirect( reverse('donations_subscription_modeladmin_inspect', kwargs={'instance_pk': subscription_id})) except Exception as e: _exception(str(e)) messages.add_message(request, messages.ERROR, str(e)) return redirect(reverse('donations_subscription_modeladmin_index'))
def set_subscription_status(request): try: if request.method == 'POST' and request.POST.get('id', None): id = int(request.POST.get('id')) subscription = get_object_or_404(Subscription, id=id) old_status = subscription.recurring_status if not request.POST.get('status', ''): raise _("Empty value submitted for subscription status update") subscription.recurring_status = request.POST.get('status').lower() subscription.save() new_status = subscription.recurring_status # add to the update actions log addUpdateSubsActionLog(subscription, SUBS_ACTION_MANUAL, action_notes='%s -> %s' % (old_status, new_status), user=request.user) # notify donor of action sendSubscriptionStatusChangeToDonor(subscription) messages.add_message( request, messages.SUCCESS, str( _('Subscription %(id)d status set to %(status)s.') % { 'id': id, 'status': subscription.recurring_status })) return redirect( reverse('donations_subscription_modeladmin_inspect', kwargs={'instance_pk': id})) except Exception as e: _exception(str(e)) messages.add_message(request, messages.ERROR, str(e)) return redirect(reverse('donations_subscription_modeladmin_index'))
def cancel_subscription(request): try: if request.method == 'POST' and request.POST.get('id', None): subscription_id = int(request.POST.get('id')) subscription = get_object_or_404(Subscription, id=subscription_id) gatewayManager = InitPaymentGateway(request, subscription=subscription) resultSet = gatewayManager.cancel_recurring_payment() # add to the update actions log addUpdateSubsActionLog(gatewayManager.subscription, SUBS_ACTION_CANCEL, user=request.user) messages.add_message( request, messages.SUCCESS, str( _('Subscription %(id)d status is cancelled.') % {'id': subscription_id})) return redirect( reverse('donations_subscription_modeladmin_inspect', kwargs={'instance_pk': subscription_id})) except Exception as e: _exception(str(e)) messages.add_message(request, messages.ERROR, str(e)) return redirect(reverse('donations_subscription_modeladmin_index'))
def edit_recurring(request, id): """ This is called when the user clicks the 'Edit recurring donation' button on page donations.views.my_recurring_donations We only update the subscription if it is owned by request.user Action is logged for the corresponding subscription, action logs can be viewed by inspecting the subscription's 'Action Log' tab Sample (Form) request: { 'recurring_amount': 10.00, 'billing_cycle_now': 'on' } * only Stripe's form has the billing_cycle_now option @todo: revise error handling, avoid catching all exceptions at the end """ try: subscription = get_object_or_404(Subscription, id=id) if subscription.user == request.user: # Form object is initialized according to the specific gateway and if request.method=='POST' form = InitEditRecurringPaymentForm(request.POST, request.method, subscription) if request.method == 'POST': if form.is_valid(): # use gatewayManager to process the data in form.cleaned_data as required gatewayManager = InitPaymentGateway( request, subscription=subscription) # check if frequency limitation is enabled and passed if not isUpdateSubsFrequencyLimitationPassed( gatewayManager): raise Exception( _('You have already carried out 5 subscription update action in the last 5 minutes, our current limit is 5 subscription update actions(edit/pause/resume) every 5 minutes.' )) original_value = gatewayManager.subscription.recurring_amount gatewayManager.update_recurring_payment(form.cleaned_data) new_value = gatewayManager.subscription.recurring_amount # add to the update actions log addUpdateSubsActionLog( gatewayManager.subscription, SUBS_ACTION_UPDATE, 'Recurring Amount: %s -> %s' % (str(original_value), str(new_value))) return redirect('donations:edit-recurring', id=id) else: raise PermissionError( _('You are not authorized to edit subscription %(id)d.') % {'id': id}) except PermissionError as e: _exception(str(e)) messages.add_message(request, messages.ERROR, str(e)) return redirect('donations:my-recurring-donations') except (ValueError, RuntimeError, Exception) as e: _exception(str(e)) messages.add_message(request, messages.ERROR, str(e)) return render(request, getEditRecurringPaymentHtml(subscription), { 'form': form, 'subscription': subscription })
def toggle_recurring(request): """ This is called when the user clicks the 'Pause/Resume recurring donation' button on page donations.views.my_recurring_donations We only update the subscription if it is owned by request.user Action is logged for the corresponding subscription, action logs can be viewed by inspecting the subscription's 'Action Log' tab Sample request: { 'subscription_id': 1, 'csrfmiddlewaretoken': 'LZSpOsb364pn9R3gEPXdw2nN3dBEi7RWtMCBeaCse2QawCFIndu93fD3yv9wy0ij' } @todo: revise error handling, avoid catching all exceptions at the end """ try: if request.method == 'POST': json_data = json.loads(request.body) if 'subscription_id' not in json_data: print("No subscription_id in JSON body", flush=True) return HttpResponse(status=400) subscription_id = int(json_data['subscription_id']) subscription = get_object_or_404(Subscription, id=subscription_id) if subscription.user == request.user: gatewayManager = InitPaymentGateway(request, subscription=subscription) # check if frequency limitation is enabled and passed if not isUpdateSubsFrequencyLimitationPassed(gatewayManager): raise Exception( _('You have already carried out 5 subscription update action in the last 5 minutes, our current limit is 5 subscription update actions(edit/pause/resume) every 5 minutes.' )) resultSet = gatewayManager.toggle_recurring_payment() # add to the update actions log addUpdateSubsActionLog( gatewayManager.subscription, SUBS_ACTION_PAUSE if resultSet['recurring-status'] == STATUS_PAUSED else SUBS_ACTION_RESUME) return JsonResponse({ 'status': 'success', 'button-text': resultSet['button-text'], 'recurring-status': str(_(resultSet['recurring-status'].capitalize())), 'success-message': resultSet['success-message'] }) else: raise PermissionError( _('You are not authorized to pause/resume subscription %(id)d.' ) % {'id': subscription_id}) else: return HttpResponse(400) except (ValueError, PermissionError, RuntimeError, Exception) as e: _exception(str(e)) return JsonResponse({'status': 'failure', 'reason': str(e)})
def cancel_recurring(request): """ This is called when the user clicks confirm when cancelling a recurring donation on page donations.views.my_recurring_donations We only cancel the subscription if it is owned by request.user Action is logged for the corresponding subscription, action logs can be viewed by inspecting the subscription's 'Action Log' tab Sample (JSON) request: { 'subscription_id': 1, 'csrfmiddlewaretoken': 'LZSpOsb364pn9R3gEPXdw2nN3dBEi7RWtMCBeaCse2QawCFIndu93fD3yv9wy0ij' } @todo: revise error handling, avoid catching all exceptions at the end """ try: if request.method == 'POST': json_data = json.loads(request.body) if 'subscription_id' not in json_data: print("No subscription_id in JSON body", flush=True) return HttpResponse(status=400) subscription_id = int(json_data['subscription_id']) subscription = get_object_or_404(Subscription, id=subscription_id) if subscription.user == request.user: gatewayManager = InitPaymentGateway(request, subscription=subscription) gatewayManager.cancel_recurring_payment() # add to the update actions log addUpdateSubsActionLog(gatewayManager.subscription, SUBS_ACTION_CANCEL) return JsonResponse({ 'status': 'success', 'button-text': str(_('View all renewals')), 'recurring-status': str(_(STATUS_CANCELLED.capitalize())), 'button-href': reverse('donations:my-renewals', kwargs={'id': subscription_id}) }) else: raise PermissionError( _('You are not authorized to cancel subscription %(id)d.') % {'id': subscription_id}) else: return HttpResponse(400) except (ValueError, PermissionError, RuntimeError, Exception) as e: _exception(str(e)) return JsonResponse({'status': 'failure', 'reason': str(e)})
def cancel_recurring_payment(self): if not self.subscription: raise ValueError( _('Subscription object is None. Cannot cancel recurring payment.' )) # update newstream model self.subscription.recurring_status = STATUS_PROCESSING self.subscription.save() # add to the update actions log addUpdateSubsActionLog(self.subscription, SUBS_ACTION_CANCEL, action_notes='Cancellation Request') # email notifications sendRecurringCancelRequestNotifToAdmins(self.subscription) # raise error so that main code goes to failure path raise Exception( _('Direct cancellation of subscription is not supported for this gateway. Email has been sent to site admin to take further action. Site admin will manually cancel this subscription.' ))