예제 #1
0
    def post(self, request, campaign_id, *args, **kwargs):
        # Validate request and campaign status
        try:
            campaign = Campaign.objects.get(id=campaign_id)
        except Campaign.DoesNotExist:
            return HttpResponseBadRequest("Campaign with ID {campaign_id} does not exist.".format(campaign_id=campaign_id))
        else:
            if not campaign.open():
                return HttpResponseBadRequest("This campaign is no longer accepting investments.")
        form = PaymentChargeForm(request.POST, campaign=campaign)
        if not form.is_valid():
            return HttpResponseBadRequest(unicode(form.errors))
        d = form.cleaned_data

        # Get card and customer
        card = d['card']
        customer = customers.get_customer_for_user(request.user)
        if not customer:
            customer = customers.create(request.user, card=card, plan=None, charge_immediately=False)

        # Create charge
        num_shares = d['num_shares']
        amount = decimal.Decimal(campaign.total(num_shares))
        try:
            charge = charges.create(amount=amount, customer=customer.stripe_id)
        except CardError as e:
            return HttpResponseBadRequest(e.message)
        Investment.objects.create(charge=charge, campaign=campaign, num_shares=num_shares)
        return HttpResponse(status=205)
예제 #2
0
    def post(self, request, campaign_id, *args, **kwargs):
        # Validate request and campaign status
        try:
            campaign = Campaign.objects.get(id=campaign_id)
        except Campaign.DoesNotExist:
            return Response(
                "Campaign with ID {campaign_id} does not exist.".format(
                    campaign_id=campaign_id),
                status=status.HTTP_400_BAD_REQUEST,
            )
        else:
            if not campaign.open():
                return Response(
                    "This campaign is no longer accepting investments.",
                    status=status.HTTP_400_BAD_REQUEST,
                )
        form = PaymentChargeForm(request.data, campaign=campaign)
        if not form.is_valid():
            return Response(str(form.errors),
                            status=status.HTTP_400_BAD_REQUEST)
        d = form.cleaned_data

        # Get card and customer
        card = d["card"]
        customer = customers.get_customer_for_user(request.user)
        if not customer:
            customer = customers.create(request.user,
                                        card=card,
                                        plan=None,
                                        charge_immediately=False)
            card = Card.objects.get(customer=customer)
        else:
            # Check if we have the card the user is using
            # and if not, create it
            card_fingerprint = stripe.Token.retrieve(
                card)["card"]["fingerprint"]
            cards_with_fingerprint = Card.objects.filter(
                customer=customer, fingerprint=card_fingerprint)
            if cards_with_fingerprint.exists():
                card = cards_with_fingerprint[0]
            else:
                card = sources.create_card(customer=customer, token=card)

        # Create charge
        num_shares = d["num_shares"]
        amount = decimal.Decimal(campaign.total(num_shares))
        try:
            charge = charges.create(amount=amount,
                                    customer=customer.stripe_id,
                                    source=card)
        except stripe.CardError as e:
            return Response(e.message, status=status.HTTP_400_BAD_REQUEST)
        Investment.objects.create(charge=charge,
                                  campaign=campaign,
                                  num_shares=num_shares)
        return Response(status=status.HTTP_205_RESET_CONTENT)
예제 #3
0
def stripe_sub_status(store):

    stripe_customer = get_customer_for_user(store)
    active = has_active_subscription(customer=stripe_customer)

    subscription = Subscription.objects.filter(customer=stripe_customer).order_by('-start').first()
    if not subscription:
        plan = "No plan"
    else:
        plan = subscription.plan.name

    if active:
        return "<span class='label label-success'>Stripe: Active - " + str(plan)+ "</span>"
    else:
        return "<span class='label label-default'>Stripe: Inactive - " + str(plan)+ "</span>"
예제 #4
0
def invoice_list(request, *args, **kwargs):

    with request.user.session:

        template = "main_app/invoice_list.html"

        stripe_customer = get_customer_for_user(request.user)

        table = CustomerInvoiceTable(Invoice.objects.filter(customer=stripe_customer).order_by('date'))

        RequestConfig(request, paginate={'per_page': 50}).configure(table)

        return render(request, template, {
            'table': table,
        })
예제 #5
0
    def process_request(self, request):
        # TODO Add messages limit check.
        is_authenticated = request.user.is_authenticated
        if django.VERSION < (1, 10):
            is_authenticated = is_authenticated()

        if is_authenticated and not request.user.is_staff:
            url_name = resolve(request.path).url_name
            if url_name in settings.PINAX_STRIPE_SUBSCRIPTION_REQUIRED_URLS:
                customer = customers.get_customer_for_user(request.user)
                user_plan = UserPlan.objects.filter(user=request.user)[0]
                if not subscriptions.has_active_subscription(
                        customer) and user_plan.exceeded_limit(
                        ) or user_plan.exceeded_limit():
                    return redirect(
                        settings.PINAX_STRIPE_SUBSCRIPTION_REQUIRED_REDIRECT)
예제 #6
0
    def post(self, request, campaign_id, *args, **kwargs):
        # Validate request and campaign status
        try:
            campaign = Campaign.objects.get(id=campaign_id)
        except Campaign.DoesNotExist:
            return Response(
                "Campaign with ID {campaign_id} does not exist.".format(campaign_id=campaign_id),
                status=status.HTTP_400_BAD_REQUEST
            )
        else:
            if not campaign.open():
                return Response(
                    "This campaign is no longer accepting investments.",
                    status=status.HTTP_400_BAD_REQUEST
                )
        form = PaymentChargeForm(request.data, campaign=campaign)
        if not form.is_valid():
            return Response(str(form.errors), status=status.HTTP_400_BAD_REQUEST)
        d = form.cleaned_data

        # Get card and customer
        card = d['card']
        customer = customers.get_customer_for_user(request.user)
        if not customer:
            customer = customers.create(request.user, card=card, plan=None, charge_immediately=False)
            card = Card.objects.get(customer=customer)
        else:
            # Check if we have the card the user is using
            # and if not, create it
            card_fingerprint = stripe.Token.retrieve(card)['card']['fingerprint']
            cards_with_fingerprint = Card.objects.filter(customer=customer, fingerprint=card_fingerprint)
            if cards_with_fingerprint.exists():
                card = cards_with_fingerprint[0]
            else:
                card = sources.create_card(customer=customer, token=card)

        # Create charge
        num_shares = d['num_shares']
        amount = decimal.Decimal(campaign.total(num_shares))
        try:
            charge = charges.create(amount=amount, customer=customer.stripe_id, source=card)
        except stripe.CardError as e:
            return Response(e.message, status=status.HTTP_400_BAD_REQUEST)
        Investment.objects.create(charge=charge, campaign=campaign, num_shares=num_shares)
        return Response(status=status.HTTP_205_RESET_CONTENT)
예제 #7
0
def ask_for_review(domain):
    try:
        store = models.AuthAppShopUser.objects.get(myshopify_domain=domain)
    except ObjectDoesNotExist:
        logging.warning("Review-Check-Task-No-User: "******"created_at")

        if store.userprofile.setup_required == False and stripe_customer and cards:

            # Send an email
            ctx = {
                "myshopify_domain": store.myshopify_domain,
            }
            subject = render_to_string("main_app/email/review_subject.txt",
                                       ctx)
            subject = subject.strip()
            message = render_to_string("main_app/email/review_body.txt", ctx)

            email = store.userprofile.shop_contact_email

            num_sent = EmailMessage(
                subject,
                message,
                to=[email],
                from_email=settings.PINAX_STRIPE_INVOICE_FROM_EMAIL).send()

            store.userprofile.review_email_sent = True
            store.userprofile.save()

            return

    else:
        return
예제 #8
0
def admin_store_transfers(request, *args, **kwargs):

    template = "main_app/admin_store_transfers.html"
    active_menu = "stores"

    # Get store from kwargs
    store = get_object_or_404(AuthAppShopUser, pk=kwargs.get('pk', None))

    stripe_customer = get_customer_for_user(store)

    table = InvoiceTable(Invoice.objects.filter(customer=stripe_customer).order_by('-period_start'))

    RequestConfig(request, paginate={'per_page': 50}).configure(table)

    return render(request, template, {
        'active_menu': active_menu,
        'table': table,
        'store': store
    })
예제 #9
0
def payment_information(request, *args, **kwargs):

    with request.user.session:

        # Get the current stores stripe customer info.
        stripe_customer = get_customer_for_user(request.user)
        # Get all the current customers/stores payment methods
        cards = Card.objects.filter(customer=stripe_customer).order_by("created_at")

        STRIPE_PUBLIC_KEY = settings.PINAX_STRIPE_PUBLIC_KEY

        if request.method == "POST":

            stripe_customer = process_stripe_user(request.user, request.POST.get('stripeToken', None), existing_cards=cards)
            create_stripe_user_subscription(store=request.user, stripe_customer=stripe_customer)

            messages.success(request, "The payment method was changed.")
            return redirect('main_app:payment_information', store_url=request.user.store_url_str())

        return render(request, "main_app/payment_information.html", {'cards':cards, 'STRIPE_PUBLIC_KEY': STRIPE_PUBLIC_KEY} )
예제 #10
0
def create_stripe_user_subscription(store, stripe_customer=None):

    if not stripe_customer:
        stripe_customer = get_customer_for_user(store)

    if subscriptions.has_active_subscription(stripe_customer):
        return True

    plan, reason = estimate_donation_volume(store)

    subscription = subscriptions.create(stripe_customer, plan)

    StripeCustomerSubReason.objects.update_or_create(store=store,
                                                     defaults={
                                                         "subscription":
                                                         subscription,
                                                         'reason': reason
                                                     })

    return True
예제 #11
0
def process_stripe_user(store, card_token, existing_cards=None):

    # Get the current stores stripe customer info.
    stripe_customer = get_customer_for_user(store)
    # Get all the current customers/stores payment methods
    if not existing_cards:
        existing_cards = Card.objects.filter(
            customer=stripe_customer).order_by("created_at")

    stripe_card_token = card_token

    # If the store has no stripe customer, create one.
    if not stripe_customer:
        stripe_customer = create_without_account_custom(store,
                                                        card=stripe_card_token)
    else:
        # Save the new card to the existing user, and delete old cards.
        for card in existing_cards:
            delete_card(stripe_customer, card.stripe_id)

        create_card(stripe_customer, token=stripe_card_token)

    return stripe_customer
예제 #12
0
def handle_user_pre_delete(sender, **kwargs):
    user = kwargs.get('instance')
    customer = customers.get_customer_for_user(user=user)
    if customer:
        customers.purge(customer=customer)
예제 #13
0
def admin_store_detail(request, *args, **kwargs):

    template = "main_app/admin_store_detail.html"
    active_menu = "stores"

    # Get store from kwargs
    store = get_object_or_404(AuthAppShopUser, pk=kwargs.get('pk', None))

    try:
        with shopify.Session.temp(store.myshopify_domain, store.token):
            shop_details = Shop.current()
    except (UnauthorizedAccess, ClientError):
        shop_details = None

    # Get dashboard details
    round_up_count = RoundUpOrders.objects.exclude(
        shopify_payment_status=RoundUpOrders.SHOPIFY_PAYMENT_STATUS.REFUNDED).filter(store=store).count()

    round_up_total = [
        Money(data['order_roundup_total__sum'], data['order_roundup_total_currency']) for data in
        RoundUpOrders.objects.exclude(
        shopify_payment_status=RoundUpOrders.SHOPIFY_PAYMENT_STATUS.REFUNDED).filter(store=store).values(
            'order_roundup_total_currency').annotate(Sum('order_roundup_total')).order_by()
    ]

    if round_up_total and len(round_up_total) == 1:
        round_up_total = round_up_total[0]
    else:
        round_up_total = Money(0.0, settings.DEFAULT_CURRENCY)

    stripe_customer = get_customer_for_user(store)
    stripe_invoice_count = Invoice.objects.filter(customer=stripe_customer, paid=True).count()

    stripe_invoice_sum = Invoice.objects.filter(customer=stripe_customer, paid=True).aggregate(Sum('total'))
    try:
        stripe_invoice_sum = Money(stripe_invoice_sum['total__sum'], settings.DEFAULT_CURRENCY)
    except (KeyError, InvalidOperation):
        stripe_invoice_sum = Money(0.0, settings.DEFAULT_CURRENCY)

    pending_round_up_count = RoundUpOrders.objects.exclude(
        shopify_payment_status=RoundUpOrders.SHOPIFY_PAYMENT_STATUS.REFUNDED).filter(store=store, state__in=[
        RoundUpOrders.STATE.PENDING, RoundUpOrders.STATE.PROCESSING_STRIPE_TRANSFER, RoundUpOrders.STATE.FAILED]
                                                          ).count()

    pending_round_up_total = [
        Money(data['order_roundup_total__sum'], data['order_roundup_total_currency']) for data in
        RoundUpOrders.objects.exclude(
        shopify_payment_status=RoundUpOrders.SHOPIFY_PAYMENT_STATUS.REFUNDED).filter(store=store, state__in=[
        RoundUpOrders.STATE.PENDING, RoundUpOrders.STATE.PROCESSING_STRIPE_TRANSFER, RoundUpOrders.STATE.FAILED]
                                                          ).values(
            'order_roundup_total_currency').annotate(Sum('order_roundup_total')).order_by()
    ]

    converted_currency_USD = None

    if pending_round_up_total and len(pending_round_up_total) == 1:
        pending_round_up_total = pending_round_up_total[0]

        try:
            if str(pending_round_up_total.currency) != settings.DEFAULT_CURRENCY:
                exchange = Fixer(base=str(pending_round_up_total.currency), symbols=[settings.DEFAULT_CURRENCY])
                response = exchange.convert()
                converted_currency_USD = Money(Decimal(pending_round_up_total.amount *
                                           Decimal(response['rates'][settings.DEFAULT_CURRENCY])),
                                           settings.DEFAULT_CURRENCY)
        except Exception:
            pass
    else:
        pending_round_up_total = Money(0.0, settings.DEFAULT_CURRENCY)

    subscription = Subscription.objects.filter(customer=stripe_customer).order_by('-start').first()

    if request.POST:
        subscription_lock = request.POST.get('sub-lock', None)
        switch_high = request.POST.get('switch-high', None)
        switch_low = request.POST.get('switch-low', None)

        if subscription_lock:
            if store.stripe_sub_reason.plan_locked == True:
                store.stripe_sub_reason.plan_locked = False
                store.stripe_sub_reason.save()
            elif store.stripe_sub_reason.plan_locked == False:
                store.stripe_sub_reason.plan_locked = True
                store.stripe_sub_reason.save()

        if switch_high:
            high_plan = Plan.objects.get(stripe_id=settings.PINAX_STRIPE_HIGH_VOLUME_PLAN)
            update(subscription, plan=high_plan, prorate=False)
            # Clear subscription reason
            models.StripeCustomerSubReason.objects.update_or_create(
                store=store, defaults={"subscription": subscription, 'reason': "On {0} Vesey manually moved this customer from the low usage plan to the high usage plan.".format(str(timezone.now()))}
            )
            store.stripe_sub_reason.reset_compliance()

        if switch_low:
            low_plan = Plan.objects.get(stripe_id=settings.PINAX_STRIPE_DEFAULT_PLAN)
            update(subscription, plan=low_plan, prorate=False)
            models.StripeCustomerSubReason.objects.update_or_create(
                    store=store, defaults={"subscription": subscription, 'reason': "On {0} Vesey manually moved this customer from the high usage plan to the low usage plan.".format(str(timezone.now()))}
                )
            store.stripe_sub_reason.reset_compliance()

        redirect('main_app:admin_store_detail', pk=store.id)


    return render(request, template, {
        'active_menu': active_menu,
        'store': store,
        'shopify_details': shop_details,
        'round_up_count': round_up_count,
        'round_up_total': round_up_total,
        'stripe_invoice_count': stripe_invoice_count,
        'stripe_invoice_sum': stripe_invoice_sum,
        'pending_round_up_count': pending_round_up_count,
        'pending_round_up_total': pending_round_up_total,
        'converted_currency_USD': converted_currency_USD,
        'subscription': subscription
    })
예제 #14
0
def app_uninstall_task(data, **kwargs):
    try:
        user = models.AuthAppShopUser.objects.get(
            myshopify_domain=kwargs['domain'])

        user.token = '00000000000000000000000000000000'
        user.save()

        # Cancel any Stripe subscriptions
        try:
            stripe_customer = get_customer_for_user(user)
            if subscriptions.has_active_subscription(stripe_customer):
                user_subscriptions = models.Subscription.objects.filter(
                    customer=stripe_customer).filter(
                        Q(ended_at__isnull=True)
                        | Q(ended_at__gt=timezone.now()))
                for subscription in user_subscriptions:
                    subscriptions.cancel(subscription, at_period_end=False)

                # Clear subscription reason
                models.StripeCustomerSubReason.objects.update_or_create(
                    store=user,
                    defaults={
                        "subscription": None,
                        'reason': None
                    })

                # Clear stripe cards
                user_cards = Card.objects.filter(
                    customer=stripe_customer).order_by("created_at")
                for card in user_cards:
                    delete_card(stripe_customer, card.stripe_id)
        except StripeError as e:
            logging.error(str(e.message))

        # Send an email to the user to welcome them
        try:
            ctx = {
                "myshopify_domain": user.myshopify_domain,
            }
            subject = render_to_string("main_app/email/uninstall_subject.txt",
                                       ctx)
            subject = subject.strip()
            message = render_to_string("main_app/email/uninstall_body.txt",
                                       ctx)

            email = user.userprofile.shop_contact_email

            num_sent = EmailMessage(
                subject,
                message,
                to=[email],
                from_email=settings.PINAX_STRIPE_INVOICE_FROM_EMAIL).send()
        except Exception:
            pass

        # Invalidate any existing user sessions.
        user.clear_user_sessions()
        connection.close()

    except ObjectDoesNotExist:
        if kwargs['domain']:
            logging.warning("App-Uninstall-Webhook-No-User-Found:  " +
                            str(kwargs['domain']))
            return
    except Exception as e:
        logging.error("App-Uninstall-Webhook-Unknown-Exception: " +
                      str(e.message))
        raise e
예제 #15
0
def check_user_onboarding_progress(domain):
    try:
        store = models.AuthAppShopUser.objects.get(myshopify_domain=domain)
    except ObjectDoesNotExist:
        logging.warning("Onboarding-Check-Task-No-User: "******"created_at")

        if not stripe_customer or not cards:
            required_steps_string = '- Please add your payment information to the Round Up App payment settings (Required to make donations).\n'

        # Does the customer have a charity selected?
        try:
            if not store.store_charity.selected_charity:
                required_steps_string = '- Please select a Charity in the Round Up app.\n'
        except ObjectDoesNotExist:
            required_steps_string = '- Please select a Charity in the Round Up app.\n'

        # Has the customer signalled that they have included the setup stuff?
        try:
            if not store.userprofile.install_user_verified:
                required_steps_string = '- Please ensure that you have modified your Cart page theme to include the Round Up app code snippet.\n'
        except ObjectDoesNotExist:
            required_steps_string = '- Please ensure that you have modified your Cart page theme to include the Round Up app code snippet.\n'

        if required_steps_string != '':

            # Send an email
            ctx = {
                "myshopify_domain": store.myshopify_domain,
                "required_steps_string": required_steps_string
            }
            subject = render_to_string(
                "main_app/email/required_steps_subject.txt", ctx)
            subject = subject.strip()
            message = render_to_string(
                "main_app/email/required_steps_body.txt", ctx)

            email = store.userprofile.shop_contact_email

            num_sent = EmailMessage(
                subject,
                message,
                to=[email],
                from_email=settings.PINAX_STRIPE_INVOICE_FROM_EMAIL).send()

            store.userprofile.onboarding_email_sent = True
            store.userprofile.save()

            return

    else:
        return
예제 #16
0
 def customer(self):
     if not hasattr(self, "_customer"):
         self._customer = customers.get_customer_for_user(self.request.user)
         if self._customer is None:
             self._customer = customers.create(self.request.user)
     return self._customer