def set_up_payment_method_success(request): "a view for receiving success message from stripe" #mark an event event = Event(category='successfully_set_up_payment_method', user=request.user, comment=None) event.save() # GET stripes session-id and retrieve the session, stripe_session_id = request.GET['stripe_session_id'] try: completed_stripe_session = stripe.checkout.Session.retrieve(stripe_session_id, expand=['setup_intent']) except: logger.error("%(date)s %(logtype)s: set_up_payment_method_success: Stripe returned a successful payment attempt for user %(user)s, but we were unable to retrieve the stripe session. We should set default payment method manually, and check that everything is in order!"\ % { 'date': datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'logtype': 'ERROR: ', 'user': request.user }) messages.success(request, _('Looks like you were able to set up a payment method, but we were unable to get data from our payment provider just now. Don\'t worry though, our support staff have been notified and will fix it!'), extra_tags='alert alert-success') return HttpResponseRedirect(reverse('payments_current_plan')) #get the new payment method, and set it to default pm = completed_stripe_session.setup_intent.payment_method invoice_settings = {'default_payment_method': pm} c = stripe.Customer.modify(request.user.organization.stripe_id, invoice_settings=invoice_settings) #declare success and return to overview messages.success(request, _('Payment method set up successfully!'), extra_tags='alert alert-success') return HttpResponseRedirect(request.GET.get('next', reverse('payments_current_plan')))
def make_event(name, days_from_now, n_week, workshop_time: time, description, prereq, period, location): """ Create event and associated weekly-occuring workshops. Args: name: the name of the event days_from_now: the days between today and the first workshop n_week: the number of weeks the event will run for workshop_time: the local time of the start of each workshop description: event description prereq: description of event prerequisites period: the event period location: the location of each workshop Returns: the created Event """ start_date = date.today() + timedelta(days=days_from_now) if n_week == 1: # single event finish_date = start_date + timedelta(days=1) else: finish_date = start_date + timedelta(days=n_week * 7 - 6) start_dt = datetime.combine(start_date, time.min) finish_dt = datetime.combine(finish_date, time.min) # generate weekly workshop times workshop_times = [] wkshop_time = datetime.combine(start_date, workshop_time) while wkshop_time < finish_dt: workshop_times.append(wkshop_time) wkshop_time += timedelta(days=7) assert len(workshop_times) == n_week event = Event(name=name, start_date=local2utc(start_dt), finish_date=local2utc(finish_dt), description=description, prerequisite=prereq, period=period) event.save() # create workshops for each time workshops = [] for i, start_time in enumerate(workshop_times): finish_time = start_time + timedelta(hours=1) workshops.append( Workshop(event=event, name=f'Workshop #{i+1}', date=start_time.date(), start_time=start_time.time(), end_time=finish_time.time(), location=location)) for workshop in workshops: workshop.save() return event
def set_up_payment_method_cancel(request): "a view for receiving error message from stripe" #mark an event event = Event(category='failed_to_set_up_payment_method', user=request.user, comment=None) event.save() #do things messages.error(request, _('The subscription setup process was cancelled. Try again?'), extra_tags='alert alert-warning') logger.warning("%s %s: set_up_payment_method_cancel: Stripe returned a failed payment attempt for user %s."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', request.user)) return HttpResponseRedirect(reverse('payments-set-up-payment-method'))
def restart_cancelled_subscription_view(request, **kwargs): """View function for ...""" subscription_id = kwargs.get('subscription_id', None) try: if subscription_id == request.user.organization.stripe_subscription_id: rs = restart_cancelled_stripe_subscription(subscription_id) if rs is not None: messages.success(request, _('Your subscription was restarted!'), extra_tags='alert alert-success') #update payment status request.user.organization.update_subscription_paid_until() #mark an event event = Event(category='succesfully_restarted_subscription', user=request.user, comment=None) event.save() else: logger.warning("%s %s: restart_cancelled_subscription_view: Tried to restart subscription for user %s, but was unsuccessful."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', request.user)) messages.warning(request, _('We tried to restart your subscription, but it may not have worked. Try again later, or contact support.'), extra_tags='alert alert-warning') #mark an event event = Event(category='failed_to_restart_subscription', user=request.user, comment=None) event.save() else: return HttpResponseForbidden() except Exception as err: logger.exception("%s %s: restart_cancelled_subscription_view: (user: %s) %s: %s."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'EXCEPTION: ', request.user, type(err), err)) return HttpResponseServerError() return HttpResponseRedirect(reverse('payments_current_plan'))
def login_view(request): """View function for logging in.""" #is user already logged in? if request.user.is_authenticated: messages.error(request, _('You are already logged in.'), extra_tags='alert alert-warning') return HttpResponseRedirect( request.GET.get('next', reverse('surveys-dashboard'))) #If we receive POST data if request.method == 'POST': # Create a form instance and populate it with data from the request (binding it): form = LoginForm(request.POST) context = { 'submit_button_text': _('Login'), 'back_button_text': _('Cancel'), 'show_back_button': False, 'form': form, } # Check if the form is valid: if form.is_valid(): # process the data in form.cleaned_data as required username = form.cleaned_data['username'] password = form.cleaned_data['password'] user = authenticate(request, username=username, password=password) if user is not None: auth.login(request, user) request.user.organization.update_subscription_paid_until() messages.success(request, _('You have logged in.'), extra_tags='alert alert-success') #mark an event - user logged in event = Event(category='completed_log_in', user=request.user, comment=None) event.save() return HttpResponseRedirect(request.GET.get('next', '/')) else: #make context form = LoginForm context = { 'submit_button_text': _('Login'), 'back_button_text': _('Cancel'), 'show_back_button': False, 'form': form, } return render(request, 'login_form.html', context)
def create_subscription_view(request, **kwargs): """View function for ...""" #grab the desired sub ID from the url subscription_id = kwargs.get('subscription_id', None) #get the default payment method if any, and assign to variable stripe_customer = retrieve_stripe_customer(request.user.organization.stripe_id) if stripe_customer == None: logger.error("%s %s: create_subscription_view: Tried to retrieve stripe Subscriber object for user %s, with ID %s, but was unsuccessful."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'ERROR: ', request.user, request.user.organization.stripe_id)) return HttpResponseServerError() payment_method_id = stripe_customer.invoice_settings.default_payment_method default_payment_method = None if payment_method_id != None and payment_method_id != '': default_payment_method = retrieve_stripe_payment_method(payment_method_id) if default_payment_method == None: #redirect to set up PM before coming back here... return HttpResponseRedirect(reverse('payments-set-up-payment-method')+'?next='+reverse('payments-create-subscription', args=[subscription_id])) try: #Update and retrieve the number of co-workers to charge quantity=request.user.organization.update_stripe_subscription_quantity() #get the Customer object ID stripe_id = request.user.organization.stripe_id #create subscription with stripe s = create_stripe_subscription(stripe_id, subscription_id, trial_from_plan=True, quantity=quantity) request.user.organization.stripe_subscription_id=s.id request.user.organization.save() #check if succeeded if s is not None: #declare success messages.success(request, _('Your subscription was started!'), extra_tags='alert alert-success') #update payment status request.user.organization.update_subscription_paid_until() #mark an event event = Event(category='succesfully_set_up_subscription', user=request.user, comment=None) event.save() else: #log failure logger.warning("%s %s: create_subscription_view: Tried to start subscription for user %s, but was unsuccessful."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', request.user)) messages.warning(request, _('We tried to start your subscription, but something went wrong. You can try again, and we\'ll make sure you don\'t get charged twice!'), extra_tags='alert alert-warning') #mark an event event = Event(category='failed_to_set_up_subscription', user=request.user, comment=None) event.save() except Exception as err: logger.exception("%s %s: create_subscription_view: (user: %s) %s: %s."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'EXCEPTION: ', request.user, type(err), err)) return HttpResponseServerError() return HttpResponseRedirect(reverse('payments_current_plan'))
def test_events(self): #test that we can create events for event_number, event_category in enumerate( Event.ALLOWED_CATEGORIES): e = Event(category=event_category) e.save() self.assertEqual(event_number + 1, e.id) self.assertIn(e.category, Event.ALLOWED_CATEGORIES) event_list = Event.objects.all() self.assertEqual(len(Event.ALLOWED_CATEGORIES), len(event_list)) #test that we CAN also create non-specified types of categories nse = Event(category="non-specified_category") nse.save() event_list = Event.objects.all() self.assertEqual(len(Event.ALLOWED_CATEGORIES) + 1, len(event_list))
def render(self, context): context[self.context_name] = Event.get_next_events() return ""
def sign_up(request): """View function for signing up.""" #logged in users are redirected if request.user.is_authenticated: messages.error( request, _('You are already signed in, and can\'t make a new account until you sign out.' ), extra_tags='alert alert-warning') return render(request, 'you_did_something.html') #mark an event - someone visited this site event = Event(category='visited_sign_up_view') event.save() #create the form form = SignUpForm context = {'form': form, 'submit_button_text': _('Sign up', )} # If this is a POST request then process the Form data if request.method == 'POST': # Create a form instance and populate it with data from the request (binding): form = SignUpForm(request.POST) context.update({'form': form}) # Check if the form is valid: if form.is_valid(): # process the data in form.cleaned_data as required (here we just write it to the model due_back field) user = User.objects.create_user(form.cleaned_data['username'], form.cleaned_data['username'], form.cleaned_data['password']) user.save() organization = Organization( owner=user, phone=form.cleaned_data['phone'], name=form.cleaned_data['name'], address_line_1=form.cleaned_data['address_line_1'], address_line_2=form.cleaned_data['address_line_2'], zip_code=form.cleaned_data['zip_code'], city=form.cleaned_data['city'], country=form.cleaned_data['country'], accepted_terms_and_conditions=form. cleaned_data['accepted_terms_and_conditions'], ) organization.save() messages.success( request, _("Welcome aboard. Let's start by adding some employees to survey!" ), extra_tags='alert alert-success') send_mail( '[www] New user: %s!' % (user.username), 'User: %s has signed up!' % (user.username), '*****@*****.**', ['*****@*****.**'], fail_silently=True, ) if user is not None: auth.login(request, user) #mark an event - someone signed up successfully event = Event(category='completed_sign_up', user=user) event.save() # redirect to a new URL: return HttpResponseRedirect(reverse('surveys-dashboard')) else: #mark an event - someone failed to sign up comment = "" for field in form.visible_fields(): if field.field.label != _( "Choose a password") and field.field.label != _( "Confirm password"): field_data = "%s: %s \n" % (field.field.label, field.data) comment += (field_data) event = Event(category='failed_sign_up', comment=comment) event.save() return render(request, 'sign_up_form.html', context)
def answer_survey_view(request, **kwargs): #Validate link and get the correct survey_instance or 404 try: #get the si-id and token from the url, and check that it's format is correct url_token = kwargs.get('token', None) url_token_args = url_token.split("-") assert len(url_token_args) == 2, \ "Faulty link (wrong link format)" #get the associated SurveyInstance si_id = int(force_text(urlsafe_base64_decode(url_token_args[0]))) survey_instance = SurveyInstance.objects.get(id=si_id) #ensure the url_token matches the SurveyInstance assert survey_instance.get_hash_string() == url_token_args[1], \ "Faulty link (invalid hash)" #ensure the Survey that the SurveyInstance belongs to is still open assert survey_instance.survey.is_closed == False, \ "This survey has already closed, closed %s."%(survey_instance.survey.date_close) except (AssertionError, SurveyInstance.DoesNotExist, DjangoUnicodeDecodeError) as err: #mark an event comment = "url-token: %s.\n Error: %s " % (url_token, err) event = Event(category='failed_to_open_survey_instance_link', comment=comment) event.save() #log and redirect logger.exception( "%s %s: answer_survey_view: (user: %s) %s: %s." % (datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'EXCEPTION: ', request.user, type(err), err)) raise Http404( _("The survey you asked for does not exist. If you pasted a link, make sure you got the entire link." )) #get the page argument, to see if we should be inn the paginated pages, and if so, which one page = kwargs.get('page', None) if page is not None: page = int(page) # make the context context = { 'survey_instance': survey_instance, 'page': page, 'submit_button_text': _('Continue'), } #set how many questions will be shown per page page_size = 5 #if this view was requested without a page argument, we can skip forward a bit if page is None: #First check if method was post, and maybe update the consent variable if request.method == 'POST': form = ConsentToAnswerForm(request.POST) context.update({'form': form}) #deal with data if it's valid if form.is_valid(): survey_instance.consent_was_given = form.cleaned_data[ 'consent_to_answer'] survey_instance.started = True survey_instance.save() #mark an event event = Event(category='accepted_terms_and_conditions', comment="%s" % (survey_instance)) event.save() #If its not post and we havent givent consent, we need to provide that form if request.method != 'POST' and survey_instance.consent_was_given != True: form = ConsentToAnswerForm() context.update({'form': form}) #mark an event event = Event(category='opened_survey_instance_link', comment="%s" % (survey_instance)) event.save() #if consent was given, and if survey was started but not completed, go directly to where the respondent left off: elif request.method != 'POST' and survey_instance.consent_was_given == True and survey_instance.check_completed( ) == False: items = survey_instance.surveyinstanceitem_set.all().order_by('pk') answered_item_counter = 0 for item in items: answered_item_counter += 1 if item.answered == False: current_page = math.ceil( (answered_item_counter / page_size)) messages.info( request, _("Welcome back! We saved your place, so you can continue where you left off." ), extra_tags='alert alert-info') return HttpResponseRedirect( reverse('surveys-answer-survey-pages', args=(url_token, current_page))) #finally, R has given consent, but not started or completed the survey, send him to first page elif request.method == 'POST' and survey_instance.consent_was_given == True and survey_instance.check_completed( ) == False: return HttpResponseRedirect( reverse('surveys-answer-survey-pages', args=(url_token, 1))) #finally/otherwise show a plain welcoming view, or a thank you return render(request, 'answer_survey.html', context) #if page is not none, make sure consent was given else: if survey_instance.consent_was_given != True: messages.info( request, _("Thank you for taking the time to answer this survey! Please indicate that you consent to answer the survey to continue." ), extra_tags='alert alert-info') return HttpResponseRedirect( reverse('surveys-answer-survey', args=[url_token])) #Show questions now that we know we are in the paginated part #make a list 'item_list' containing exactly the items the user should be asked all_survey_instance_items_list = survey_instance.surveyinstanceitem_set.all( ).order_by('pk') item_list = [] last_item_id = page * page_size for count, item in enumerate(all_survey_instance_items_list): if count < last_item_id and count >= (last_item_id - page_size): item_list.append(item) #add the progress so the progress bar may be shown progress = last_item_id / len(all_survey_instance_items_list) * 100 if progress > 100: progress = 100 context.update({'progress': progress}) #make the form, including previous answers if any data = {} #get previous answers for the questions in qlist and add them to the dict for i in item_list: if i.answered == True: a = i.answer data.update({'item_%s' % (i.pk): a}) form = AnswerSurveyForm(items=item_list, initial=data) context.update({'form': form}) #did the user POST something? if request.method == 'POST': #overwrite the existing form with the values POSTED posted_form = AnswerSurveyForm(request.POST, items=item_list) context.update({'form': posted_form}) #deal with data if it's valid if posted_form.is_valid(): for answer in posted_form.cleaned_data: # identify the question that has been answered item_id = int(answer.replace('item_', '')) item = SurveyInstanceItem.objects.get(id=item_id) #make sure it's in the item_list try: assert item in item_list, \ "An answer was submitted for an unexpected item with the id %s, but expected one of %s."%\ (item.id, [item.id for item in item_list]) except AssertionError as err: logger.exception( "%s %s: answer_survey_view: (user: %s) %s: %s."\ %(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'EXCEPTION: ', request.user, type(err), err)) return HttpResponseForbidden() # find the value that has been provided as the answer if isinstance(item, RatioSurveyInstanceItem): value = posted_form.cleaned_data[answer] #elif other types of scales else: logger.warning( "%s %s: %s: tried answer a SurveyInstanceItem, but its subclass (%s) was not recognized:\n---\"%s\""\ %(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', __name__, type(item), item) ) value = None # use the answer method of the question to create answer objects for this si if value is not None: item.answer_item(value=value) #if there are more questions, send them to the next page if len(all_survey_instance_items_list) > int(page) * page_size: return HttpResponseRedirect( reverse('surveys-answer-survey-pages', args=(url_token, page + 1))) #else, we are done answering, and redirect to thank you message #mark an event event = Event(category='completed_survey_instance', comment="%s" % (survey_instance)) event.save() return HttpResponseRedirect( reverse('surveys-answer-survey', args=(url_token, ))) return render(request, 'answer_survey.html', context)
def add_or_remove_employee_view(request): """View function for adding employees.""" #Prepare a normal GET view that will be shown no matter what: organization = request.user.organization employee_list = organization.respondent_set.all() form = AddRespondentForm() context = { 'form': form, 'submit_button_text': _('Add employee'), 'show_back_button': True, 'employee_list': employee_list, } # If this is a POST request, then process the Form bfore showing the view if request.method == 'POST': # Create a form instance and populate it with data from the request (binding): form = AddRespondentForm(request.POST) context.update({'form': form}) # Check if the form is valid: if form.is_valid(): r = Respondent(organization=organization, email=form.cleaned_data['email'], first_name=form.cleaned_data['first_name'], last_name=form.cleaned_data['last_name']) r.save() #also update stripe subscription quantity q = request.user.organization.update_stripe_subscription_quantity() if request.user.organization.stripe_subscription_id is not None: stripe_logic.modify_stripe_subscription( request.user.organization.stripe_subscription_id, quantity=q) #declare success and make a new form for the next employee messages.success( request, _('You have added a coworker (%(email)s)! You can continue to add more below.' % {'email': form.cleaned_data['email']}), extra_tags='alert alert-success') form = AddRespondentForm() context.update({ 'form': form, 'show_back_button': False, }) #mark an event - user added an employee comment = "Employee: %s." % (r) event = Event(category='successfully_add_employee', user=request.user, comment=comment) event.save() else: #mark an event - someone failed to add an employee comment = "" for field in form.visible_fields(): field_data = "%s: %s \n" % (field.field.label, field.data) comment += (field_data) event = Event(category='failed_to_add_employee', user=request.user, comment=comment) event.save() #finally, return the prepared view return render(request, 'add_or_remove_employees.html', context)
def setup_instrument_view(request, **kwargs): #get the Instrument to be configured instrument_slug_name = kwargs.get('instrument', None) instrument = get_object_or_404(Instrument, slug_name=instrument_slug_name) #get the SurveySetting to be configured try: survey_setting = SurveySetting.objects.get( organization=request.user.organization, instrument=instrument) except SurveySetting.DoesNotExist as err: survey_setting = survey_logic.configure_survey_setting( organization=request.user.organization, instrument=instrument) survey_setting.save() #prepare a form in case it's a get request data = { 'is_active': survey_setting.is_active, 'survey_interval': survey_setting.survey_interval, 'surveys_remain_open_days': survey_setting.surveys_remain_open_days, 'survey_language_preference': request.user.organization.survey_language_preference, } form = EditSurveySettingsForm(initial=data) #if post, validate form and save, redirect to dashboard if request.method == 'POST': form = EditSurveySettingsForm(request.POST) if form.is_valid(): #update settings survey_setting.is_active = form.cleaned_data['is_active'] survey_setting.survey_interval = form.cleaned_data[ 'survey_interval'] survey_setting.surveys_remain_open_days = form.cleaned_data[ 'surveys_remain_open_days'] survey_setting.save() request.user.organization.survey_language_preference = form.cleaned_data[ 'survey_language_preference'] request.user.organization.save() #report back if survey_setting.is_active == True: success_string = _("Your settings were updated successfully, %(instrument_name)s tracking is ACTIVE!"\ %{'instrument_name': survey_setting.instrument.name}) messages.success(request, success_string, extra_tags='alert alert-success') #mark an event event = Event(category='started_tracking_with_an_instrument', user=request.user, comment=None) event.save() else: success_string = _("Your settings were updated successfully, %(instrument_name)s tracking is INACTIVE!"\ %{'instrument_name': survey_setting.instrument.name}) messages.success(request, success_string, extra_tags='alert alert-warning') #mark an event event = Event(category='stopped_tracking_with_an_instrument', user=request.user, comment=None) event.save() #redirect to dashboard return HttpResponseRedirect(reverse('surveys-dashboard')) #if get, make form, return form, context = { 'form': form, 'instrument': instrument, 'submit_button_text': _("Update settings") } return render(request, 'setup_instrument.html', context)
def current_plan_view(request): """View function for ...""" ## what do we know about this user? #get the customer object id from DB stripe_id = request.user.organization.stripe_id #get the subscription object id from DB stripe_subscription_id = request.user.organization.stripe_subscription_id #get the customer object from Stripe, if any, or make one stripe_customer = None if stripe_id is not None and stripe_id != '': stripe_customer = retrieve_stripe_customer(stripe_id) if stripe_customer == None: #mark an event - someone visited for the first time event = Event(category='visited_pick_a_plan_first_time', user=request.user, comment=None) event.save() #Try make a customer stripe_customer = create_stripe_customer(request.user.organization) #if it wasnt made, error connecting to Stripe if stripe_customer == None: logger.warning("%s %s: current_plan_view: Unable to get a Customer object from Stripe for user %s."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', request.user)) return HttpResponseServerError() #if it WAS made, save it, so we can retrieve it later stripe_id = stripe_customer.id request.user.organization.stripe_id = stripe_id request.user.organization.save() ##SUBSCRIPTION #if there is a sub_id, get the subscription object from Stripe, stripe_subscription = None if stripe_subscription_id is not None and stripe_subscription_id != '': #UPDATE QUANTITY HERE? -> No, this should be handled in the add/delete employee views now stripe_subscription = retrieve_stripe_subscription(stripe_subscription_id) if stripe_subscription_id is not None and stripe_subscription is None: logger.warning("%s %s: current_plan_view: Unable to get a Subscription object from Stripe for user %s, and sub_id %s."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', request.user, stripe_subscription_id)) return HttpResponseServerError() #clean it up for the template: clean_stripe_subscription = None if stripe_subscription is not None: #clean plan_interval if stripe_subscription.plan.interval == "month": plan_interval = _("month") elif stripe_subscription.plan.interval == "year": plan_interval = _("year") else: plan_interval = stripe_subscription.plan.interval #clean plan_name if stripe_subscription.plan.nickname == "Quarterly": plan_name = _("Quarterly") elif stripe_subscription.plan.nickname == "Yearly": plan_name = _("Yearly") else: plan_name = stripe_subscription.plan.nickname #clean status if stripe_subscription.status == "active": stripe_subscription_status = _("active") elif stripe_subscription.status == "trialing": stripe_subscription_status = _("trialing") elif stripe_subscription.status == "canceled": stripe_subscription_status = _("canceled") elif stripe_subscription.status == "unpaid": stripe_subscription_status = _("unpaid") elif stripe_subscription.status == "past_due": stripe_subscription_status = _("past_due") elif stripe_subscription.status == "incomplete": stripe_subscription_status = _("incomplete") elif stripe_subscription.status == "incomplete_expired": stripe_subscription_status = _("incomplete_expired") else: stripe_subscription_status = stripe_subscription.status #make cleaned dict clean_stripe_subscription = { 'id': stripe_subscription.id, 'cancel_at_period_end': stripe_subscription.cancel_at_period_end, 'latest_invoice': stripe_subscription.latest_invoice, 'plan_active': stripe_subscription.plan.active, 'plan_interval_amount': "%.0f" % int(stripe_subscription.plan.amount/stripe_subscription.plan.interval_count/100), 'plan_total': "%.0f" % int(stripe_subscription.plan.amount/stripe_subscription.plan.interval_count*stripe_subscription.quantity/100), 'plan_currency': stripe_subscription.plan.currency, 'plan_id': stripe_subscription.plan.id, 'plan_interval': plan_interval, 'plan_name': plan_name, 'quantity': stripe_subscription.quantity, 'status': stripe_subscription_status, 'english_status': stripe_subscription.status, 'current_period_start': datetime.datetime.fromtimestamp(stripe_subscription.current_period_start).date(), 'current_period_end': datetime.datetime.fromtimestamp(stripe_subscription.current_period_end).date(), 'billing_cycle_anchor': datetime.datetime.fromtimestamp(stripe_subscription.billing_cycle_anchor).date(), } ##PAYMENT METHOD #get the default payment method if any, and assign to variable payment_method_id = stripe_customer.invoice_settings.default_payment_method default_payment_method = None if payment_method_id != None: default_payment_method = retrieve_stripe_payment_method(payment_method_id) #get a list of payment methods pm_list = list_stripe_payment_methods(stripe_id) ##PLANS #get a list of the product and all of its plans: product = retrieve_stripe_product(settings.STRIPE_STANDARD_PLAN) plan_list = list_stripe_plans(product.id) #Clean it up for display clean_plan_list = [] for plan in plan_list: if plan.product == product.id and plan.active == True: #clean plan_interval if plan.interval == "month": plan_interval = _("month") elif plan.interval == "year": plan_interval = _("year") else: plan_interval = plan.interval #clean plan_name if plan.nickname == "Quarterly": plan_name = _("Quarterly") elif plan.nickname == "Yearly": plan_name = _("Yearly") else: plan_name = stripe_subscription.plan.nickname #clean data and dict for each plan cleaned_plan = { 'name': plan_name, 'currency': plan.currency, 'id': plan.id, 'interval': plan_interval, 'interval_count': plan.interval_count, 'trial_period_days': plan.trial_period_days, 'amount': "%.0f" % int(plan.amount/100), 'interval_amount': "%.0f" % int(plan.amount/plan.interval_count/100), 'tiers': [] #make room for tiers, which will be appended later } clean_plan_list.append(cleaned_plan) clean_plan_list2 = sorted(clean_plan_list, key=itemgetter('amount'), reverse=True) ##INVOICES #List of invoices invoice_list = list_stripe_invoices(customer=stripe_id) #Clean them up for display clean_invoice_list = None if invoice_list is not None and len(invoice_list) > 0: clean_invoice_list = [] for invoice in invoice_list: cleaned_invoice = { 'number': invoice.number, 'created': datetime.datetime.fromtimestamp(invoice.created).date(), 'paid': invoice.paid, 'invoice_pdf': invoice.invoice_pdf, 'line_items': [], } #add info from line items: for item in invoice.lines: clean_line={ 'amount': "%.0f" % item.amount, 'currency': item.currency, 'period_start': datetime.datetime.fromtimestamp(item.period.start).date(), 'period_end': datetime.datetime.fromtimestamp(item.period.end).date(), 'plan_name': item.plan.nickname, } cleaned_invoice['line_items'].append(clean_line) clean_invoice_list.append(cleaned_invoice) context = { 'stripe_subscription': clean_stripe_subscription, 'default_payment_method': default_payment_method, 'pm_list': pm_list, 'product': product, 'plan_list': clean_plan_list2, 'invoice_list': clean_invoice_list, #'clean_product_list': clean_product_list, } # Render the HTML template index.html with the data in the context variable return render(request, 'current_plan.html', context=context)
def set_up_payment_view(request): """View function for ...""" #mark an event - someone clicked pick a plan or add payment method - who knows which? event = Event(category='created_stripe_checkout_session', user=request.user, comment=None) event.save() #get the customer object id from DB, if any stripe_id = request.user.organization.stripe_id #get the subscription object id from DB, if any stripe_subscription_id = request.user.organization.stripe_subscription_id #Make sure we have a customer object, either retrive or create: stripe_customer = retrieve_stripe_customer(stripe_id) if stripe_customer == None: #Make a customer stripe_customer = create_stripe_customer(request.user.organization) #If it wasnt made, error connecting to stripe if stripe_customer == None: logger.warning("%s %s: set_up_payment_view: Unable to get a Customer object from Stripe for user %s."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', request.user)) return HttpResponseServerError() #if it was made, save it in DB, so we can use it later stripe_id = stripe_customer.id request.user.organization.stripe_id = stripe_id request.user.organization.save() #catch cases where we have subscription id, but are not able to get the corresponding object from stripe if stripe_subscription_id is not None and stripe_subscription_id is not '': stripe_subscription = retrieve_stripe_subscription(stripe_subscription_id) if stripe_subscription is None: logger.warning("%s %s: set_up_payment_view: Unable to retrieve a Subscription object from Stripe for user %s, with stripe ID %s."%(datetime.datetime.now().strftime('[%d/%m/%Y %H:%M:%S]'), 'WARNING: ', request.user, stripe_id)) return HttpResponseServerError() #Now we know we have a stripe Customer object: That means we can get to work: #Prepare a NEW PAYMENT-METHOD.-checkout-session #make the success URL: success_url = request.build_absolute_uri(reverse('payments-set-up-payment-method-success'))+'?stripe_session_id={CHECKOUT_SESSION_ID}' next_url = request.GET.get('next', None) if next_url is not None: success_url = success_url+'&next='+next_url #This is used if we also should set up a subscription #make session stripe_session = stripe.checkout.Session.create( payment_method_types=['card'], mode='setup', customer=stripe_customer, success_url=success_url, cancel_url=request.build_absolute_uri(reverse('payments-set-up-payment-method-cancel')) ) if settings.DEBUG == True: messages.info(request, 'Use this credit card in testing: Visa: 4242 4242 4242 4242', extra_tags='alert alert-info') messages.info(request, 'Use this credit card in testing: American Express: 3782 822463 10005', extra_tags='alert alert-info') messages.info(request, 'Use this credit card in testing: Mastercard: 5555 5555 5555 4444', extra_tags='alert alert-info') #Ensure we have a stripe_subscriptiuon variable try: stripe_subscription except UnboundLocalError as err: stripe_subscription = None #initiate context variable to send to view context = { 'stripe_session': stripe_session, 'stripe_pk': settings.STRIPE_PUBLISHABLE_KEY, 'stripe_subscription': stripe_subscription, } return render(request, 'set_up_payment_method.html', context=context)