Merge branch 'master' of f.sfconservancy.org:Conservancy/website

This commit is contained in:
Daniel Pono Takamori 2024-12-19 15:23:51 -08:00
commit 53b95a217f
8 changed files with 49 additions and 5 deletions

View file

@ -5,5 +5,7 @@ from .models import Unsubscription
@admin.register(Unsubscription) @admin.register(Unsubscription)
class UnsubscriptionAdmin(admin.ModelAdmin): class UnsubscriptionAdmin(admin.ModelAdmin):
list_display = ['created', 'email', 'mailout'] list_display = ['created', 'email', 'mailout', 'actioned']
list_editable = ['actioned']
list_filter = ['mailout', 'actioned']
search_fields = ['email', 'mailout'] search_fields = ['email', 'mailout']

View file

@ -0,0 +1,18 @@
# Generated by Django 5.1.2 on 2024-12-10 18:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('contacts', '0002_unsubscription_mailout'),
]
operations = [
migrations.AddField(
model_name='unsubscription',
name='actioned',
field=models.DateField(blank=True, null=True),
),
]

View file

@ -5,6 +5,13 @@ class Unsubscription(models.Model):
created = models.DateTimeField(auto_now_add=True, blank=True) created = models.DateTimeField(auto_now_add=True, blank=True)
email = models.EmailField() email = models.EmailField()
mailout = models.SlugField() mailout = models.SlugField()
actioned = models.DateField(null=True, blank=True)
class Meta: class Meta:
ordering = ['created'] ordering = ['created']
def __str__(self):
if self.mailout:
return f'{self.email} ({self.mailout})'
else:
return self.email

View file

@ -27,15 +27,27 @@ def unsubscribe(request):
Interfaces like Gmail will then provide a user interface to unsubscribe Interfaces like Gmail will then provide a user interface to unsubscribe
which will hit this endpoint. which will hit this endpoint.
Our understanding is that Gmail will submit the form with and HTTP POST request, but
with GET-style URL parameters. Hence this feature has been built to work both with
GET and POST-style data as well as GET and POST methods, just in case. Test it like
this:
curl -X POST -d 'email=foo@bar.com&mailout=jan2024-new' https://sfconservancy.org/contacts/unsubscribe/
curl -X POST 'https://sfconservancy.org/contacts/unsubscribe/?email=foo@bar.com&mailout=jan2024-new'
Or visit in a browser:
https://sfconservancy.org/contacts/unsubscribe/?email=foo@bar.com&mailout=jan2024-new
""" """
if request.method == 'POST': if request.method == 'POST':
logger.debug('Unsubscribe GET: %s', request.GET) logger.debug('Unsubscribe GET: %s', request.GET)
logger.debug('Unsubscribe POST: %s', request.POST) logger.debug('Unsubscribe POST: %s', request.POST)
form = UnsubscribeForm(request.GET) form = UnsubscribeForm(request.GET.dict() | request.POST.dict())
if form.is_valid(): if form.is_valid():
form.save() form.save()
logger.info('Unsubscribed %s', form.cleaned_data['email']) logger.info('Unsubscribed %s', form.cleaned_data['email'])
return render(request, 'contacts/unsubscribe_success.html') return render(request, 'contacts/unsubscribe_success.html')
else: else:
form = UnsubscribeForm() form = UnsubscribeForm(request.GET.dict() | request.POST.dict())
return render(request, 'contacts/unsubscribe.html', {'form': form}) return render(request, 'contacts/unsubscribe.html', {'form': form})

View file

@ -18,7 +18,7 @@
a <a href="https://sfconservancy.org/docs/software-freedom-conservancy-v-vizio_2023-12-01_SFC-Motion-Summary-Adjudication.pdf">motion a <a href="https://sfconservancy.org/docs/software-freedom-conservancy-v-vizio_2023-12-01_SFC-Motion-Summary-Adjudication.pdf">motion
for summary adjudication</a>.</p> for summary adjudication</a>.</p>
<p>The case's expected trial date is mid-2025.</p> <p>The case's expected trial date is in September 2025.</p>
<h3>Portions of Interest from the Docket in the Vizio Case</h3> <h3>Portions of Interest from the Docket in the Vizio Case</h3>

View file

@ -10,7 +10,7 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
payments = SustainerPayment.objects.select_related('order').order_by('paid_time') payments = SustainerPayment.objects.select_related('order').order_by('paid_time')
columns = ['order_time', 'payment_time', 'name', 'email', 'amount', 'transaction_id', 'public_ack', 'shirt_size', 'join_list', 'street', 'city', 'state', 'zip_code', 'country'] columns = ['order_time', 'payment_time', 'name', 'email', 'amount', 'transaction_id', 'recurring', 'subscription_id', 'public_ack', 'shirt_size', 'join_list', 'street', 'city', 'state', 'zip_code', 'country']
writer = csv.writer(sys.stdout) writer = csv.writer(sys.stdout)
writer.writerow(columns) writer.writerow(columns)
for payment in payments: for payment in payments:
@ -22,6 +22,8 @@ class Command(BaseCommand):
order.email, order.email,
payment.amount, payment.amount,
payment.stripe_payment_intent_ref, payment.stripe_payment_intent_ref,
order.recurring,
order.stripe_subscription_ref,
order.acknowledge_publicly, order.acknowledge_publicly,
repr(order.tshirt_size if order.tshirt_size else ''), repr(order.tshirt_size if order.tshirt_size else ''),
order.add_to_mailing_list, order.add_to_mailing_list,

View file

@ -14,5 +14,7 @@ Postal address:
{% if order.recurring == 'month' and order.tshirt_size %} {% if order.recurring == 'month' and order.tshirt_size %}
Please note that you may not receive the T-shirt until you've paid at least $60.{% endif %} Please note that you may not receive the T-shirt until you've paid at least $60.{% endif %}
An official donation receipt suitable for tax purposes should arrive via email within 2 weeks.
Kind regards, Kind regards,
Software Freedom Conservancy{% endautoescape %} Software Freedom Conservancy{% endautoescape %}

View file

@ -43,6 +43,7 @@ any of its sponsors.</p>
<li><a rel="nofollow" href="https://code.wildebeest.org/">Mark Wielaard</a></li> <li><a rel="nofollow" href="https://code.wildebeest.org/">Mark Wielaard</a></li>
<li><a rel="nofollow" href="https://www.mozilla.org/foundation/"><img src="{% static 'img/sponsors/mozilla.png' %}" height="101" width="250" alt="Mozilla Foundation" /></a></li> <li><a rel="nofollow" href="https://www.mozilla.org/foundation/"><img src="{% static 'img/sponsors/mozilla.png' %}" height="101" width="250" alt="Mozilla Foundation" /></a></li>
<li><b>David Turner and Danielle Sucher</b></li> <li><b>David Turner and Danielle Sucher</b></li>
<li><b>John Gilmore</b></li>
</ul> </ul>
<!-- This section will be added when we have in-kind contributions --> <!-- This section will be added when we have in-kind contributions -->