Ejemplo n.º 1
0
def send_ride_receipt_email(customer, ride):
    user = customer.user
    account_email = customer.ride_account.email if customer.ride_account else None
    to_name = user.first_name if user.profile.on_behalf else customer.first_name
    to_email = customer.email if customer.email else account_email if account_email else user.email

    d = {
        'ride': ride,
        'customer': customer,
        'to_name': to_name
    }

    msg_plain = render_to_string('billing/email/ride_receipt_email.txt', d)
    msg_html = render_to_string('billing/email/ride_receipt_email.html', d)

    send_mail(
        'Thanks for riding with Arrive!',
        msg_plain,
        settings.DEFAULT_FROM_EMAIL,
        [to_email],
        html_message=msg_html,
    )

    new_touch = Touch(
        customer=customer,
        date=timezone.now(),
        type=Touch.EMAIL,
        notes='Sent ride receipt email (from balance)'
    )
    new_touch.full_clean()
    new_touch.save()
Ejemplo n.º 2
0
def invoice(request):

    event = json.loads(request.body)
    event_type = event['type']
    stripe_invoice = event['data']['object']
    stripe_cust_id = stripe_invoice['customer']
    customer = None

    try:
        invoice = get_object_or_404(Invoice, stripe_id=stripe_invoice['id'])
        invoice.invoiced = stripe_invoice['attempted']
        invoice.attempt_count = stripe_invoice['attempt_count']
        invoice.total = stripe_invoice['total'] / 100
        invoice.paid = stripe_invoice['paid']
        invoice_type = 'Ride'

        if event_type == 'invoice.sent':
            invoice.invoiced_date = timezone.now()

        if event_type == 'invoice.payment_succeeded':
            invoice.paid_date = timezone.now()
            # apparently the invoice is sent and paid at the same time usually
            if not invoice.invoiced_date:
                invoice.invoiced_date = invoice.paid_date

        invoice.full_clean()
        invoice.save()
        customer = invoice.customer

    except:
        # okay, this isn't an invoice associated with a ride. that means it must be
        # a customer (a subscription payment), so we need to find the customer
        stripe_customer = get_object_or_404(StripeCustomer, stripe_id=stripe_cust_id)

        if stripe_customer.subscription_customer.count():
            customer = stripe_customer.subscription_customer.first()
        if stripe_customer.subscription_group_plan.count():
            customer = stripe_customer.subscription_group_plan.first()
        if stripe_customer.ride_customer.count():
            customer = stripe_customer.ride_customer.first()

        invoice_type = 'Subscription'

    new_touch = Touch(
        customer=customer,
        date=timezone.now(),
        type=Touch.BILLING,
        notes='{}: ${} ({} payment) [Stripe ID {}]'.format(event_type, stripe_invoice['total'] / 100, invoice_type, stripe_invoice['id'])
    )
    new_touch.full_clean()
    new_touch.save()

    return HttpResponse(status=200)
Ejemplo n.º 3
0
def send_welcome_email(user):

    msg_plain = render_to_string('registration/welcome_email.txt', {'user': user})
    msg_html = render_to_string('registration/welcome_email.html', {'user': user})

    send_mail(
        'Welcome to Arrive Rides!',
        msg_plain,
        settings.DEFAULT_FROM_EMAIL,
        [user.email],
        html_message=msg_html,
    )

    new_touch = Touch(
        customer=user.get_customer(),
        date=timezone.now(),
        type=Touch.EMAIL,
        notes='Sent welcome email after registration'
    )
    new_touch.full_clean()
    new_touch.save()
Ejemplo n.º 4
0
def send_subscription_receipt_email(user):
    from billing.utils import get_stripe_subscription
    customer = user.get_customer()
    account = customer.subscription_account
    plan = customer.plan
    subscription = get_stripe_subscription(customer)

    next_bill_date = formats.date_format(datetime.fromtimestamp(subscription.current_period_end), "DATE_FORMAT")

    d = {
        'account': account,
        'plan': plan,
        'next_bill_date': next_bill_date
    }

    msg_plain = render_to_string('registration/email/subscription_receipt_email.txt', d)
    msg_html = render_to_string('registration/email/subscription_receipt_email.html', d)

    to_email = account.email if account.email else user.email

    send_mail(
        'Arrive Membership Confirmation',
        msg_plain,
        settings.DEFAULT_FROM_EMAIL,
        [to_email],
        html_message=msg_html,
    )

    new_touch = Touch(
        customer=user.get_customer(),
        date=timezone.now(),
        type=Touch.EMAIL,
        notes='Sent receipt email after payment'
    )
    new_touch.full_clean()
    new_touch.save()
Ejemplo n.º 5
0
def invoice_customer_rides(account, customers, request):

    from accounts.helpers import send_included_rides_email

    success_included = []
    success_billed = []
    success_total = 0
    errors = []
    total = 0
    included_rides = []
    billable_rides = []

    stripe_id = account.stripe_id if account else None
    if stripe_id or [customer.balance for customer in customers]:
        for customer, rides in customers.iteritems():
            for ride in rides:
                try:
                    # the ride cost something
                    if ride.total_cost_estimate == 0:
                        # including, no fees: no billing
                        ride.total_cost = 0
                        ride.complete = True
                        ride.invoiced = True
                        included_rides.append(ride)
                        success_included.append(ride.id)
                        success_total += 1
                    else:
                        ride.total_cost = ride.total_cost_estimate
                        cost_to_bill = ride.total_cost
                        # if customer has an account
                        if hasattr(customer, 'balance'):
                            if customer.balance.amount >= ride.total_cost:
                                # customer balance can cover ride
                                ride.invoiced = True
                                ride.full_clean()
                                ride.save()
                                cost_to_bill = None
                                customer.balance.amount -= ride.total_cost
                                customer.balance.save()
                                send_ride_receipt_email(customer, ride)
                                new_touch = Touch(
                                    customer=customer,
                                    date=timezone.now(),
                                    type=Touch.BILLING,
                                    notes='Balance debit: ${} (Ride payment)'.
                                    format(ride.total_cost))
                                new_touch.full_clean()
                                new_touch.save()
                            else:
                                # ride cost more than balance
                                if stripe_id:
                                    # charge overage to ride account
                                    cost_to_bill = ride.total_cost - customer.balance.amount
                                    customer.balance.amount = 0
                                else:
                                    # ruh roh, they're in the red.
                                    cost_to_bill = None
                                    ride.invoiced = True
                                    ride.full_clean()
                                    ride.save()
                                    customer.balance.amount -= ride.total_cost
                                    customer.balance.save()

                            if customer.balance.amount < settings.BALANCE_ALERT_THRESHOLD_1 and not customer.subscription_account:
                                send_balance_alerts(
                                    customer,
                                    last_action='Ride {}, {}'.format(
                                        ride.id, ride.description))

                        if cost_to_bill:
                            invoiceitem = stripe.InvoiceItem.create(
                                customer=stripe_id,
                                amount=int(cost_to_bill * 100),
                                currency="usd",
                                description=ride.description,
                                idempotency_key='{}{}'.format(
                                    customer.id,
                                    datetime.datetime.now().isoformat()))
                            ride.invoice_item_id = invoiceitem.id
                            billable_rides.append(ride)

                        success_billed.append(ride.id)
                        success_total += 1
                    ride.invoiced_by = request.user
                    ride.save()

                except Exception as ex:
                    errors.append('Ride {}: {}'.format(ride.id, ex.message))
                    continue
            total += 1

        if billable_rides:
            # step out of loop to create one invoice for whole account
            stripe_invoice = stripe.Invoice.create(customer=stripe_id)

            # get back in loop to generate invoices per-customer
            for customer in customers:
                try:
                    new_invoice = Invoice(
                        stripe_id=stripe_invoice.id,
                        customer=customer,
                        created_date=timezone.now(),
                        period_start=datetime_from_timestamp(
                            stripe_invoice.period_start),
                        period_end=datetime_from_timestamp(
                            stripe_invoice.period_end),
                    )

                    new_invoice.full_clean()
                    new_invoice.save()
                except Exception as ex:
                    errors.append('Customer {}: {}'.format(
                        customer.id, ex.message))
                    continue

            for ride in billable_rides:
                try:
                    ride.invoice = new_invoice
                    ride.invoiced = True
                    ride.full_clean()
                    ride.save()
                except Exception as ex:
                    errors.append('Ride {}: {}'.format(ride.id, ex.message))

    else:
        errors.append(
            'Customer {} has no Ride Account specified (no credit card to bill) and/or no funds in their account.'
            .format(customer))
        total = 1

    if included_rides:
        send_included_rides_email(customer, included_rides)

    return {
        'success_included': success_included,
        'success_billed': success_billed,
        'success_total': success_total,
        'errors': errors,
        'total': total
    }
Ejemplo n.º 6
0
def debit_customer_balance(customer):
    # if an inactive customer got in here somehow, skip them
    if not customer.is_active or not customer.plan:
        return False

    try:

        monthly_cost = customer.plan.monthly_cost
        available_balance = customer.balance.amount

        if available_balance >= monthly_cost:
            customer.balance.amount -= monthly_cost
            customer.balance.save()
            if customer.balance.amount < settings.BALANCE_ALERT_THRESHOLD_1 and not customer.subscription_account:
                send_balance_alerts(customer,
                                    last_action='Monthly Subscription')

            funds_touch = Touch(
                customer=customer,
                date=timezone.now(),
                type=Touch.FUNDS,
                notes='Debited subscription from customer balance')
            funds_touch.full_clean()
            funds_touch.save()

        else:
            deficit = monthly_cost - available_balance
            if customer.subscription_account:
                invoiceitem = stripe.InvoiceItem.create(
                    customer=customer.subscription_account.stripe_id,
                    amount=int(deficit * 100),
                    currency="usd",
                    description="Monthly Subscription",
                    idempotency_key='{}{}'.format(
                        customer.id,
                        datetime.datetime.now().isoformat()))

                funds_touch1 = Touch(
                    customer=customer,
                    date=timezone.now(),
                    type=Touch.FUNDS,
                    notes=
                    'Charged subscription card for monthly balance shortfall of {}'
                    .format(deficit))
                funds_touch1.full_clean()
                funds_touch1.save()

                # If they have an Arrive subscription in addition to a Stripe one, we need to
                # deactivate their Arrive subscription so they don't get double-charged.
                # Monthly Billing will now be handled by Stripe.
                if customer.subscription:
                    customer.subscription.is_active = False
                    customer.subscription.save()
                    funds_touch2 = Touch(
                        customer=customer,
                        date=timezone.now(),
                        type=Touch.FUNDS,
                        notes=
                        'Deactivated empty Arrive subscription account in favor of subscription card payments'
                    )
                    funds_touch2.full_clean()
                    funds_touch2.save()

            else:
                # this will be negative:
                customer.balance.amount -= monthly_cost
                customer.balance.save()
                send_balance_alerts(customer,
                                    last_action='Monthly Subscription')
                funds_touch3 = Touch(
                    customer=customer,
                    date=timezone.now(),
                    type=Touch.FUNDS,
                    notes='Customer has a negative balance and no backup card!'
                )
                funds_touch3.full_clean()
                funds_touch3.save()

        return True

    except Exception as ex:
        msg_plain = 'Customer {}, Exception: {}'.format(customer, ex.message)
        send_mail('[Arrive] Problem with subscription balance ', msg_plain,
                  settings.DEFAULT_FROM_EMAIL, ['*****@*****.**'])
        return False