Fixed issue 2624, Creating command to charge all members for their membership month, Fixing bug on make charge membership command, Added language activation for make charge command
This commit is contained in:
parent
447ddc7c2e
commit
1a8b5e69a0
8 changed files with 466 additions and 9 deletions
|
@ -7,7 +7,7 @@ from datetime import datetime
|
||||||
from utils.models import BillingAddress
|
from utils.models import BillingAddress
|
||||||
from utils.forms import LoginFormMixin, SignupFormMixin, BillingAddressForm
|
from utils.forms import LoginFormMixin, SignupFormMixin, BillingAddressForm
|
||||||
|
|
||||||
from .models import MembershipType
|
from .models import MembershipType, MembershipOrder
|
||||||
from .models import Booking
|
from .models import Booking
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,23 @@ class MembershipBillingForm(BillingAddressForm):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class MembershipOrderForm(forms.ModelForm):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = MembershipOrder
|
||||||
|
fields = ['membership', 'customer', 'billing_address',
|
||||||
|
'last4', 'cc_brand', 'stripe_charge_id', 'amount']
|
||||||
|
|
||||||
|
# def save(self, commit=True):
|
||||||
|
# instance = super(MembershipOrderForm, self).save(commit=False)
|
||||||
|
|
||||||
|
# # if commit:
|
||||||
|
# # DonatorStatus.create(self.cleaned_data['donator'].user)
|
||||||
|
# # instance.save()
|
||||||
|
|
||||||
|
# return instance
|
||||||
|
|
||||||
|
|
||||||
class BookingBillingForm(BillingAddressForm):
|
class BookingBillingForm(BillingAddressForm):
|
||||||
token = forms.CharField(widget=forms.HiddenInput())
|
token = forms.CharField(widget=forms.HiddenInput())
|
||||||
start_date = forms.DateField(widget=forms.HiddenInput())
|
start_date = forms.DateField(widget=forms.HiddenInput())
|
||||||
|
|
166
digitalglarus/management/commands/make_membership_charge.py
Normal file
166
digitalglarus/management/commands/make_membership_charge.py
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
from django.utils import translation
|
||||||
|
|
||||||
|
from utils.stripe_utils import StripeUtils
|
||||||
|
|
||||||
|
from utils.mailer import BaseEmail
|
||||||
|
from digitalglarus.models import MembershipOrder
|
||||||
|
from digitalglarus.forms import MembershipOrderForm
|
||||||
|
# from membership.U
|
||||||
|
# from nosystemd.models import DonatorStatus, Donation
|
||||||
|
# from nosystemd.forms import DonationForm
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Make the monthly stripe charge to all donators'
|
||||||
|
CURRENCY = 'usd'
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
translation.activate('en-us')
|
||||||
|
memberships_orders = MembershipOrder.objects.filter(membership__active=True)
|
||||||
|
current_month = datetime.now().month
|
||||||
|
current_year = datetime.now().year
|
||||||
|
|
||||||
|
print("--------- STARTING MEMBERSHIP CHARGING SCRIPT ---------")
|
||||||
|
print("Memberhips date: %s-%s" % (current_month, current_year))
|
||||||
|
|
||||||
|
for membership_order in memberships_orders:
|
||||||
|
member = membership_order.customer
|
||||||
|
try:
|
||||||
|
MembershipOrder.objects.get(created_at__month=current_month,
|
||||||
|
created_at__year=current_year,
|
||||||
|
customer=member)
|
||||||
|
except MembershipOrder.DoesNotExist:
|
||||||
|
try:
|
||||||
|
current_membership_price = membership_order.membership.type.price
|
||||||
|
|
||||||
|
last_membership_order = MembershipOrder.objects.filter(customer=member).last()
|
||||||
|
|
||||||
|
# Make stripe charge to a customer
|
||||||
|
stripe_utils = StripeUtils()
|
||||||
|
stripe_utils.CURRENCY = self.CURRENCY
|
||||||
|
charge_response = stripe_utils.make_charge(amount=current_membership_price,
|
||||||
|
customer=member.stripe_id)
|
||||||
|
charge = charge_response.get('response_object')
|
||||||
|
# Check if the payment was approved
|
||||||
|
if not charge:
|
||||||
|
# There is an error trying to creating the stripe charge
|
||||||
|
context = {
|
||||||
|
'paymentError': charge_response.get('error'),
|
||||||
|
}
|
||||||
|
print("--------- STRIPE PAYMENT ERROR ---------")
|
||||||
|
print(context)
|
||||||
|
print("-------------------------")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Create a donation
|
||||||
|
charge = charge_response.get('response_object')
|
||||||
|
membership_order_data = {
|
||||||
|
'cc_brand': charge.source.brand,
|
||||||
|
'stripe_charge_id': charge.id,
|
||||||
|
'last4': charge.source.last4,
|
||||||
|
'membership': last_membership_order.membership.id,
|
||||||
|
'billing_address': last_membership_order.billing_address.id,
|
||||||
|
'customer': member.id,
|
||||||
|
'amount': current_membership_price
|
||||||
|
}
|
||||||
|
membership_order_form = MembershipOrderForm(membership_order_data)
|
||||||
|
import pdb
|
||||||
|
pdb.set_trace()
|
||||||
|
if membership_order_form.is_valid():
|
||||||
|
membership_order = membership_order_form.save()
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'order': membership_order,
|
||||||
|
'base_url': "{0}://{1}".format('https', 'dynamicweb.ungleich.ch')
|
||||||
|
|
||||||
|
}
|
||||||
|
email_data = {
|
||||||
|
'subject': 'Your monthly membership has been charged',
|
||||||
|
'to': member.user.email,
|
||||||
|
'context': context,
|
||||||
|
'template_name': 'membership_monthly_charge',
|
||||||
|
'template_path': 'digitalglarus/emails/'
|
||||||
|
}
|
||||||
|
email = BaseEmail(**email_data)
|
||||||
|
email.send()
|
||||||
|
|
||||||
|
print("--------- PAYMENT DONATION SUCCESSFULL ---------")
|
||||||
|
print("Member: %s" % member.user.email)
|
||||||
|
print("Amount: %s %s" % (current_membership_price, self.CURRENCY))
|
||||||
|
print("-----------------------------------------------")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("--------- ERROR ---------")
|
||||||
|
print(e)
|
||||||
|
print("-------------------------")
|
||||||
|
continue
|
||||||
|
# for donator_status in donators:
|
||||||
|
# donator = donator_status.user.stripecustomer
|
||||||
|
# try:
|
||||||
|
# Donation.objects.get(created_at__month=current_month,
|
||||||
|
# created_at__year=current_year,
|
||||||
|
# donator=donator)
|
||||||
|
# except Donation.DoesNotExist:
|
||||||
|
# try:
|
||||||
|
# # Get donator last donation amount
|
||||||
|
# last_donation = Donation.objects.filter(donator=donator).last()
|
||||||
|
# donation_amount = last_donation.donation
|
||||||
|
|
||||||
|
# # Make stripe charge to a customer
|
||||||
|
# stripe_utils = StripeUtils()
|
||||||
|
# stripe_utils.CURRENCY = self.CURRENCY
|
||||||
|
# charge_response = stripe_utils.make_charge(amount=donation_amount,
|
||||||
|
# customer=donator.stripe_id)
|
||||||
|
# charge = charge_response.get('response_object')
|
||||||
|
|
||||||
|
# # Check if the payment was approved
|
||||||
|
# if not charge:
|
||||||
|
# # There is an error trying to creating the stripe charge
|
||||||
|
# context = {
|
||||||
|
# 'paymentError': charge_response.get('error'),
|
||||||
|
# }
|
||||||
|
# print("--------- STRIPE PAYMENT ERROR ---------")
|
||||||
|
# print(context)
|
||||||
|
# print("-------------------------")
|
||||||
|
# continue
|
||||||
|
# # Create a donation
|
||||||
|
# charge = charge_response.get('response_object')
|
||||||
|
# donation_data = {
|
||||||
|
# 'cc_brand': charge.source.brand,
|
||||||
|
# 'stripe_charge_id': charge.id,
|
||||||
|
# 'last4': charge.source.last4,
|
||||||
|
# 'billing_address': last_donation.billing_address.id,
|
||||||
|
# 'donator': donator.id,
|
||||||
|
# 'donation': donation_amount
|
||||||
|
# }
|
||||||
|
# donation_form = DonationForm(donation_data)
|
||||||
|
# if donation_form.is_valid():
|
||||||
|
# donation = donation_form.save()
|
||||||
|
|
||||||
|
# context = {
|
||||||
|
# 'donation': donation,
|
||||||
|
# 'base_url': "{0}://{1}".format('https', 'dynamicweb.ungleich.ch')
|
||||||
|
|
||||||
|
# }
|
||||||
|
# email_data = {
|
||||||
|
# 'subject': 'Your donation have been charged',
|
||||||
|
# 'to': donation.donator.user.email,
|
||||||
|
# 'context': context,
|
||||||
|
# 'template_name': 'donation_charge',
|
||||||
|
# 'template_path': 'nosystemd/emails/'
|
||||||
|
# }
|
||||||
|
# email = BaseEmail(**email_data)
|
||||||
|
# email.send()
|
||||||
|
|
||||||
|
# print("--------- PAYMENT DONATION SUCCESSFULL ---------")
|
||||||
|
# print("Donator: %s" % donation.donator.user.email)
|
||||||
|
# print("Amount: %s %s" % (donation.donation, self.CURRENCY))
|
||||||
|
# print("-----------------------------------------------")
|
||||||
|
# except Exception as e:
|
||||||
|
# print("--------- ERROR ---------")
|
||||||
|
# print(e)
|
||||||
|
# print("-------------------------")
|
||||||
|
# continue
|
|
@ -63,6 +63,11 @@ class Membership(models.Model):
|
||||||
type = models.ForeignKey(MembershipType)
|
type = models.ForeignKey(MembershipType)
|
||||||
active = models.BooleanField(default=True)
|
active = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, data):
|
||||||
|
instance = cls.objects.create(**data)
|
||||||
|
return instance
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_digitalglarus_active_member(cls, user):
|
def is_digitalglarus_active_member(cls, user):
|
||||||
past_month = (datetime.today() - relativedelta(months=1)).month
|
past_month = (datetime.today() - relativedelta(months=1)).month
|
||||||
|
@ -74,11 +79,6 @@ class Membership(models.Model):
|
||||||
return cls.objects.filter(has_booking_past_month | has_booking_current_month).\
|
return cls.objects.filter(has_booking_past_month | has_booking_current_month).\
|
||||||
filter(active_membership).exists()
|
filter(active_membership).exists()
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def create(cls, data):
|
|
||||||
instance = cls.objects.create(**data)
|
|
||||||
return instance
|
|
||||||
|
|
||||||
def deactivate(self):
|
def deactivate(self):
|
||||||
self.active = False
|
self.active = False
|
||||||
self.save()
|
self.save()
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
{% load static from staticfiles %}
|
||||||
|
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Oxygen Invoice</title>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#f7f7f7" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; color: white; margin: 0;">
|
||||||
|
<style type="text/css">
|
||||||
|
@media only screen and (max-width: 480px) {
|
||||||
|
table[class*="container-for-gmail-android"] {
|
||||||
|
min-width: 290px !important; width: 100% !important;
|
||||||
|
}
|
||||||
|
img[class="force-width-gmail"] {
|
||||||
|
display: none !important; width: 0 !important; height: 0 !important;
|
||||||
|
}
|
||||||
|
table[class="w320"] {
|
||||||
|
width: 320px !important;
|
||||||
|
}
|
||||||
|
td[class*="mobile-header-padding-left"] {
|
||||||
|
width: 160px !important; padding-left: 0 !important;
|
||||||
|
}
|
||||||
|
td[class*="mobile-header-padding-right"] {
|
||||||
|
width: 160px !important; padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
td[class="header-lg"] {
|
||||||
|
font-size: 24px !important; padding-bottom: 5px !important;
|
||||||
|
}
|
||||||
|
td[class="content-padding"] {
|
||||||
|
padding: 5px 0 5px !important;
|
||||||
|
}
|
||||||
|
td[class="button"] {
|
||||||
|
padding: 5px 5px 30px !important;
|
||||||
|
}
|
||||||
|
td[class*="free-text"] {
|
||||||
|
padding: 10px 18px 30px !important;
|
||||||
|
}
|
||||||
|
td[class~="mobile-hide-img"] {
|
||||||
|
display: none !important; height: 0 !important; width: 0 !important; line-height: 0 !important;
|
||||||
|
}
|
||||||
|
td[class~="item"] {
|
||||||
|
width: 140px !important; vertical-align: top !important;
|
||||||
|
}
|
||||||
|
td[class~="quantity"] {
|
||||||
|
width: 50px !important;
|
||||||
|
}
|
||||||
|
td[class~="price"] {
|
||||||
|
width: 90px !important;
|
||||||
|
}
|
||||||
|
td[class="item-table"] {
|
||||||
|
padding: 30px 20px !important;
|
||||||
|
}
|
||||||
|
td[class="mini-container-left"] {
|
||||||
|
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||||
|
}
|
||||||
|
td[class="mini-container-right"] {
|
||||||
|
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%" style="border-collapse: collapse !important; min-width: 600px; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td align="left" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #ffffff url(http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg) repeat-x;" bgcolor="#ffffff">
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" background="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; background: transparent;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; line-height: 21px;" align="center">
|
||||||
|
<!--[if gte mso 9]>
|
||||||
|
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000;height:80px; v-text-anchor:middle;">
|
||||||
|
<v:fill type="tile" src="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" color="#ffffff" />
|
||||||
|
<v:textbox inset="0,0,0,0">
|
||||||
|
<![endif]-->
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellpadding="0" cellspacing="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="pull-left mobile-header-padding-left" style="vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: left; line-height: 21px; width: 290px; padding-left: 10px;" align="left" valign="middle">
|
||||||
|
<a href="{{base_url}}" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; color: #676767; text-decoration: none !important;"><img width="137" src="{{base_url}}{% static "hosting/img/logo_black.png" %}" alt="logo" style="max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; border: none;"></a>
|
||||||
|
</td>
|
||||||
|
<td class="pull-right mobile-header-padding-right" style="color: #4d4d4d; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; text-align: right; line-height: 21px; width: 290px; padding-left: 10px;" align="right">
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
</center>
|
||||||
|
<!--[if gte mso 9]>
|
||||||
|
</v:textbox>
|
||||||
|
</v:rect>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td align="center" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7; padding: 20px 0 5px;" class="content-padding" bgcolor="#f7f7f7">
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="header-lg" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 32px; color: #4d4d4d; text-align: center; line-height: normal; font-weight: 700; padding: 35px 0 0;" align="center">
|
||||||
|
Thank you for your subscription.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center">
|
||||||
|
Your monthly membership for {{order.created_at|date:"F"}} has been charged. <br/> You can view your invoice clicking on the button below.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="button" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||||
|
<div style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<!--[if mso]>
|
||||||
|
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
|
||||||
|
<w:anchorlock/>
|
||||||
|
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
|
||||||
|
</v:roundrect>
|
||||||
|
<![endif]--><a href="{{ base_url }}{% url 'digitalglarus:membership_orders_detail' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td align="center" valign="top" width="100%" style="height: 100px; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7;" bgcolor="#f7f7f7">
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 25px 0;" align="center">
|
||||||
|
<strong style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">ungleich</strong><br style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
{% load static from staticfiles %}
|
||||||
|
<!-- Inliner Build Version 4380b7741bb759d6cb997545f3add21ad48f010b -->
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Oxygen Invoice</title>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#f7f7f7" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; width: 100% !important; height: 100%; color: white; margin: 0;">
|
||||||
|
<style type="text/css">
|
||||||
|
@media only screen and (max-width: 480px) {
|
||||||
|
table[class*="container-for-gmail-android"] {
|
||||||
|
min-width: 290px !important; width: 100% !important;
|
||||||
|
}
|
||||||
|
img[class="force-width-gmail"] {
|
||||||
|
display: none !important; width: 0 !important; height: 0 !important;
|
||||||
|
}
|
||||||
|
table[class="w320"] {
|
||||||
|
width: 320px !important;
|
||||||
|
}
|
||||||
|
td[class*="mobile-header-padding-left"] {
|
||||||
|
width: 160px !important; padding-left: 0 !important;
|
||||||
|
}
|
||||||
|
td[class*="mobile-header-padding-right"] {
|
||||||
|
width: 160px !important; padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
td[class="header-lg"] {
|
||||||
|
font-size: 24px !important; padding-bottom: 5px !important;
|
||||||
|
}
|
||||||
|
td[class="content-padding"] {
|
||||||
|
padding: 5px 0 5px !important;
|
||||||
|
}
|
||||||
|
td[class="button"] {
|
||||||
|
padding: 5px 5px 30px !important;
|
||||||
|
}
|
||||||
|
td[class*="free-text"] {
|
||||||
|
padding: 10px 18px 30px !important;
|
||||||
|
}
|
||||||
|
td[class~="mobile-hide-img"] {
|
||||||
|
display: none !important; height: 0 !important; width: 0 !important; line-height: 0 !important;
|
||||||
|
}
|
||||||
|
td[class~="item"] {
|
||||||
|
width: 140px !important; vertical-align: top !important;
|
||||||
|
}
|
||||||
|
td[class~="quantity"] {
|
||||||
|
width: 50px !important;
|
||||||
|
}
|
||||||
|
td[class~="price"] {
|
||||||
|
width: 90px !important;
|
||||||
|
}
|
||||||
|
td[class="item-table"] {
|
||||||
|
padding: 30px 20px !important;
|
||||||
|
}
|
||||||
|
td[class="mini-container-left"] {
|
||||||
|
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||||
|
}
|
||||||
|
td[class="mini-container-right"] {
|
||||||
|
padding: 0 15px 15px !important; display: block !important; width: 290px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<table align="center" cellpadding="0" cellspacing="0" class="container-for-gmail-android" width="100%" style="border-collapse: collapse !important; min-width: 600px; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td align="left" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #ffffff url(http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg) repeat-x;" bgcolor="#ffffff">
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="100%" bgcolor="#ffffff" background="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; background: transparent;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td width="100%" height="80" valign="top" style="text-align: center; vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; line-height: 21px;" align="center">
|
||||||
|
<!--[if gte mso 9]>
|
||||||
|
<v:rect xmlns:v="urn:schemas-microsoft-com:vml" fill="true" stroke="false" style="mso-width-percent:1000;height:80px; v-text-anchor:middle;">
|
||||||
|
<v:fill type="tile" src="http://s3.amazonaws.com/swu-filepicker/4E687TRe69Ld95IDWyEg_bg_top_02.jpg" color="#ffffff" />
|
||||||
|
<v:textbox inset="0,0,0,0">
|
||||||
|
<![endif]-->
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellpadding="0" cellspacing="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="pull-left mobile-header-padding-left" style="vertical-align: middle; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: left; line-height: 21px; width: 290px; padding-left: 10px;" align="left" valign="middle">
|
||||||
|
<a href="{{base_url}}" style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; color: #676767; text-decoration: none !important;"><img width="137" src="{{base_url}}{% static "hosting/img/logo_black.png" %}" alt="logo" style="max-width: 600px; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; border: none;"></a>
|
||||||
|
</td>
|
||||||
|
<td class="pull-right mobile-header-padding-right" style="color: #4d4d4d; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; text-align: right; line-height: 21px; width: 290px; padding-left: 10px;" align="right">
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
</center>
|
||||||
|
<!--[if gte mso 9]>
|
||||||
|
</v:textbox>
|
||||||
|
</v:rect>
|
||||||
|
<![endif]-->
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td align="center" valign="top" width="100%" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7; padding: 20px 0 5px;" class="content-padding" bgcolor="#f7f7f7">
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="header-lg" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 32px; color: #4d4d4d; text-align: center; line-height: normal; font-weight: 700; padding: 35px 0 0;" align="center">
|
||||||
|
Thank you for your subscription.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="free-text" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; width: 100% !important; padding: 10px 60px 0px;" align="center">
|
||||||
|
Your monthly membership for {{order.created_at|date:"F"}} has been charged. <br/> You can view your invoice clicking on the button below.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td class="button" style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 30px 0;" align="center">
|
||||||
|
<div style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<!--[if mso]>
|
||||||
|
<v:roundrect xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="urn:schemas-microsoft-com:office:word" href="http://" style="height:45px;v-text-anchor:middle;width:155px;" arcsize="15%" strokecolor="#ffffff" fillcolor="#ff6f6f">
|
||||||
|
<w:anchorlock/>
|
||||||
|
<center style="color:#ffffff;font-family:Helvetica, Arial, sans-serif;font-size:14px;font-weight:regular;">My Account</center>
|
||||||
|
</v:roundrect>
|
||||||
|
<![endif]--><a href="{{ base_url }}{% url 'digitalglarus:membership_orders_detail' order.id %}" style="border-radius: 5px; color: #ffffff; display: inline-block; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; font-weight: regular; line-height: 45px; text-align: center; text-decoration: none !important; width: 155px; -webkit-text-size-adjust: none; mso-hide: all; background: #ff6f6f;">View Invoice</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td align="center" valign="top" width="100%" style="height: 100px; border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; background: #f7f7f7;" bgcolor="#f7f7f7">
|
||||||
|
<center style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<table cellspacing="0" cellpadding="0" width="600" class="w320" style="border-collapse: collapse !important; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;"><tr style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
<td style="border-collapse: collapse; font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important; font-size: 14px; color: #777777; text-align: center; line-height: 21px; padding: 25px 0;" align="center">
|
||||||
|
<strong style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">ungleich</strong><br style="font-family: 'Oxygen', 'Helvetica Neue', 'Arial', 'sans-serif' !important;">
|
||||||
|
</td>
|
||||||
|
</tr></table>
|
||||||
|
</center>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<div class="signup-container">
|
<div class="signup-container">
|
||||||
<div class="col-xs-12 col-sm-6 col-lg-8 text-center wow fadeInDown">
|
<div class="col-xs-12 col-sm-6 col-lg-8 text-center wow fadeInDown">
|
||||||
<div class="payment-box">
|
<div class="payment-box">
|
||||||
<h2 class="section-heading payment-head">Your Membership Order Detail</h2>
|
<h2 class="section-heading payment-head">Your membership invoice for {{order.created_at|date:"F"}}</h2>
|
||||||
<hr class="greyline-long">
|
<hr class="greyline-long">
|
||||||
<h2 class="billing-head">Invoice<btn class="btn btn-primary btn-grey btn-edit print hidden-print" data-print="price">Get PDF</btn></h2>
|
<h2 class="billing-head">Invoice<btn class="btn btn-primary btn-grey btn-edit print hidden-print" data-print="price">Get PDF</btn></h2>
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ def get_anonymous_user_instance(User):
|
||||||
validation_slug=make_password(None))
|
validation_slug=make_password(None))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MyUserManager(BaseUserManager):
|
class MyUserManager(BaseUserManager):
|
||||||
def create_user(self, email, name, password=None):
|
def create_user(self, email, name, password=None):
|
||||||
"""
|
"""
|
||||||
|
@ -89,6 +88,10 @@ class CustomUser(AbstractBaseUser, PermissionsMixin):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_all_members(cls):
|
||||||
|
return cls.objects.filter(stripecustomer__membershiporder__isnull=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_url(cls, validation_slug):
|
def validate_url(cls, validation_slug):
|
||||||
user = cls.objects.filter(validation_slug=validation_slug).first()
|
user = cls.objects.filter(validation_slug=validation_slug).first()
|
||||||
|
|
|
@ -9,7 +9,6 @@ from nosystemd.models import DonatorStatus, Donation
|
||||||
from nosystemd.forms import DonationForm
|
from nosystemd.forms import DonationForm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
help = 'Make the monthly stripe charge to all donators'
|
help = 'Make the monthly stripe charge to all donators'
|
||||||
CURRENCY = 'usd'
|
CURRENCY = 'usd'
|
||||||
|
|
Loading…
Reference in a new issue