Beispiel #1
0
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')))
Beispiel #2
0
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
Beispiel #3
0
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'))
Beispiel #4
0
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'))
Beispiel #5
0
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)
Beispiel #6
0
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'))
Beispiel #7
0
 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 ""
Beispiel #9
0
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)
Beispiel #10
0
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)
Beispiel #11
0
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)
Beispiel #12
0
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)
Beispiel #13
0
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)
Beispiel #14
0
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)