Refactoring things and doing stuff in a MVP way. #15
|
@ -1,21 +1,20 @@
|
|||
#!/bin/sh
|
||||
|
||||
|
||||
echo "Waiting for postgres..."
|
||||
|
||||
|
||||
POSTGRES_PORT=${POSTGRES_PORT:-5432}
|
||||
POSTGRES_HOST=${POSTGRES_HOST:-localhost}
|
||||
|
||||
while ! nc -z "$POSTGRES_HOST" "$POSTGRES_PORT"; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
|
||||
echo "PostgreSQL started"
|
||||
|
||||
|
||||
# Only migrate and collectstatic if we are NOT in development
|
||||
if [ -z "$DEBUG" ]; then
|
||||
python manage.py migrate
|
||||
python manage.py collectstatic --no-input;
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
||||
exec "$@"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# Generated by Django 3.1.7 on 2021-02-27 20:06
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import djmoney.models.fields
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -16,67 +16,221 @@ class Migration(migrations.Migration):
|
|||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Account',
|
||||
name="Account",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='oprettet')),
|
||||
('owner', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"modified",
|
||||
models.DateTimeField(auto_now=True, verbose_name="modified"),
|
||||
),
|
||||
(
|
||||
"created",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="oprettet"),
|
||||
),
|
||||
(
|
||||
"owner",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Order',
|
||||
name="Order",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='oprettet')),
|
||||
('description', models.CharField(max_length=1024, verbose_name='description')),
|
||||
('price_currency', djmoney.models.fields.CurrencyField(choices=[('DKK', 'DKK')], default='XYZ', editable=False, max_length=3)),
|
||||
('price', djmoney.models.fields.MoneyField(decimal_places=2, max_digits=16, verbose_name='price (excl. VAT)')),
|
||||
('vat_currency', djmoney.models.fields.CurrencyField(choices=[('DKK', 'DKK')], default='XYZ', editable=False, max_length=3)),
|
||||
('vat', djmoney.models.fields.MoneyField(decimal_places=2, max_digits=16, verbose_name='VAT')),
|
||||
('is_paid', models.BooleanField(default=False, verbose_name='is paid')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounting.account')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"modified",
|
||||
models.DateTimeField(auto_now=True, verbose_name="modified"),
|
||||
),
|
||||
(
|
||||
"created",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="oprettet"),
|
||||
),
|
||||
(
|
||||
"description",
|
||||
models.CharField(max_length=1024, verbose_name="description"),
|
||||
),
|
||||
(
|
||||
"price_currency",
|
||||
djmoney.models.fields.CurrencyField(
|
||||
choices=[("DKK", "DKK")],
|
||||
default="XYZ",
|
||||
editable=False,
|
||||
max_length=3,
|
||||
),
|
||||
),
|
||||
(
|
||||
"price",
|
||||
djmoney.models.fields.MoneyField(
|
||||
decimal_places=2,
|
||||
max_digits=16,
|
||||
verbose_name="price (excl. VAT)",
|
||||
),
|
||||
),
|
||||
(
|
||||
"vat_currency",
|
||||
djmoney.models.fields.CurrencyField(
|
||||
choices=[("DKK", "DKK")],
|
||||
default="XYZ",
|
||||
editable=False,
|
||||
max_length=3,
|
||||
),
|
||||
),
|
||||
(
|
||||
"vat",
|
||||
djmoney.models.fields.MoneyField(
|
||||
decimal_places=2, max_digits=16, verbose_name="VAT"
|
||||
),
|
||||
),
|
||||
("is_paid", models.BooleanField(default=False, verbose_name="is paid")),
|
||||
(
|
||||
"account",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="accounting.account",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Order',
|
||||
'verbose_name_plural': 'Orders',
|
||||
"verbose_name": "Order",
|
||||
"verbose_name_plural": "Orders",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Transaction',
|
||||
name="Transaction",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='oprettet')),
|
||||
('amount_currency', djmoney.models.fields.CurrencyField(choices=[('DKK', 'DKK')], default='XYZ', editable=False, max_length=3)),
|
||||
('amount', djmoney.models.fields.MoneyField(decimal_places=2, help_text='This will include VAT', max_digits=16, verbose_name='amount')),
|
||||
('description', models.CharField(max_length=1024, verbose_name='description')),
|
||||
('account', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transactions', to='accounting.account')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"modified",
|
||||
models.DateTimeField(auto_now=True, verbose_name="modified"),
|
||||
),
|
||||
(
|
||||
"created",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="oprettet"),
|
||||
),
|
||||
(
|
||||
"amount_currency",
|
||||
djmoney.models.fields.CurrencyField(
|
||||
choices=[("DKK", "DKK")],
|
||||
default="XYZ",
|
||||
editable=False,
|
||||
max_length=3,
|
||||
),
|
||||
),
|
||||
(
|
||||
"amount",
|
||||
djmoney.models.fields.MoneyField(
|
||||
decimal_places=2,
|
||||
help_text="This will include VAT",
|
||||
max_digits=16,
|
||||
verbose_name="amount",
|
||||
),
|
||||
),
|
||||
(
|
||||
"description",
|
||||
models.CharField(max_length=1024, verbose_name="description"),
|
||||
),
|
||||
(
|
||||
"account",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="transactions",
|
||||
to="accounting.account",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Payment',
|
||||
name="Payment",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='oprettet')),
|
||||
('amount_currency', djmoney.models.fields.CurrencyField(choices=[('DKK', 'DKK')], default='XYZ', editable=False, max_length=3)),
|
||||
('amount', djmoney.models.fields.MoneyField(decimal_places=2, max_digits=16)),
|
||||
('description', models.CharField(max_length=1024, verbose_name='description')),
|
||||
('stripe_charge_id', models.CharField(blank=True, max_length=255, null=True)),
|
||||
('order', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='accounting.order')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"modified",
|
||||
models.DateTimeField(auto_now=True, verbose_name="modified"),
|
||||
),
|
||||
(
|
||||
"created",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="oprettet"),
|
||||
),
|
||||
(
|
||||
"amount_currency",
|
||||
djmoney.models.fields.CurrencyField(
|
||||
choices=[("DKK", "DKK")],
|
||||
default="XYZ",
|
||||
editable=False,
|
||||
max_length=3,
|
||||
),
|
||||
),
|
||||
(
|
||||
"amount",
|
||||
djmoney.models.fields.MoneyField(decimal_places=2, max_digits=16),
|
||||
),
|
||||
(
|
||||
"description",
|
||||
models.CharField(max_length=1024, verbose_name="description"),
|
||||
),
|
||||
(
|
||||
"stripe_charge_id",
|
||||
models.CharField(blank=True, max_length=255, null=True),
|
||||
),
|
||||
(
|
||||
"order",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to="accounting.order",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'payment',
|
||||
'verbose_name_plural': 'payments',
|
||||
"verbose_name": "payment",
|
||||
"verbose_name_plural": "payments",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import Membership, MembershipType
|
||||
from .models import Membership
|
||||
from .models import MembershipType
|
||||
|
||||
|
||||
@admin.register(Membership)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# Generated by Django 3.1.7 on 2021-02-28 21:09
|
||||
|
||||
from django.conf import settings
|
||||
import django.contrib.postgres.fields.ranges
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
@ -16,31 +16,78 @@ class Migration(migrations.Migration):
|
|||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='MembershipType',
|
||||
name="MembershipType",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='oprettet')),
|
||||
('name', models.CharField(max_length=64, verbose_name='navn')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"modified",
|
||||
models.DateTimeField(auto_now=True, verbose_name="modified"),
|
||||
),
|
||||
(
|
||||
"created",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="oprettet"),
|
||||
),
|
||||
("name", models.CharField(max_length=64, verbose_name="navn")),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'membership type',
|
||||
'verbose_name_plural': 'membership types',
|
||||
"verbose_name": "membership type",
|
||||
"verbose_name_plural": "membership types",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Membership',
|
||||
name="Membership",
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
|
||||
('created', models.DateTimeField(auto_now_add=True, verbose_name='oprettet')),
|
||||
('period', django.contrib.postgres.fields.ranges.DateTimeRangeField(help_text='The duration this subscription is for. ')),
|
||||
('membership_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='memberships', to='membership.membershiptype', verbose_name='subscription type')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"modified",
|
||||
models.DateTimeField(auto_now=True, verbose_name="modified"),
|
||||
),
|
||||
(
|
||||
"created",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="oprettet"),
|
||||
),
|
||||
(
|
||||
"period",
|
||||
django.contrib.postgres.fields.ranges.DateTimeRangeField(
|
||||
help_text="The duration this subscription is for. "
|
||||
),
|
||||
),
|
||||
(
|
||||
"membership_type",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
related_name="memberships",
|
||||
to="membership.membershiptype",
|
||||
verbose_name="subscription type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.PROTECT,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'membership',
|
||||
'verbose_name_plural': 'memberships',
|
||||
"verbose_name": "membership",
|
||||
"verbose_name_plural": "memberships",
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -15,14 +15,12 @@ class CreatedModifiedAbstract(models.Model):
|
|||
abstract = True
|
||||
|
||||
|
||||
|
||||
class Membership(CreatedModifiedAbstract):
|
||||
"""
|
||||
Tracks that a user has membership of a given type for a given period.
|
||||
"""
|
||||
|
||||
class QuerySet(models.QuerySet):
|
||||
|
||||
def for_user(self, user):
|
||||
return self.filter(user=user)
|
||||
|
||||
|
@ -76,6 +74,3 @@ class MembershipType(CreatedModifiedAbstract):
|
|||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
<p>{% trans "Period" %}: {{ current_membership.period.lower|date:"SHORT_DATE_FORMAT" }} to {{ current_membership.period.upper|date:"SHORT_DATE_FORMAT" }}</p>
|
||||
<p>{% trans "Type" %}: {{ current_membership.membership_type }}</p>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -15,4 +15,4 @@ def membership_overview(request):
|
|||
previous_memberships=previous_memberships,
|
||||
)
|
||||
|
||||
return render(request, "membership_overview.html", context)
|
||||
return render(request, "membership_overview.html", context)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from pathlib import Path
|
||||
|
||||
from environs import Env
|
||||
|
||||
env = Env()
|
||||
|
@ -116,4 +117,4 @@ CURRENCY_CHOICES = [("DKK", "DKK")]
|
|||
ACCOUNT_AUTHENTICATION_METHOD = "email"
|
||||
ACCOUNT_EMAIL_REQUIRED = True
|
||||
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False
|
||||
ACCOUNT_USERNAME_REQUIRED = False
|
||||
ACCOUNT_USERNAME_REQUIRED = False
|
||||
|
|
2
src/project/static/css/bootstrap.min.css
vendored
2
src/project/static/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -127,4 +127,4 @@
|
|||
})();
|
||||
</script>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -51,4 +51,4 @@
|
|||
href="{% url "account_signup" %}">
|
||||
{% trans "Become a member" %}
|
||||
</a>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
{% block content %}
|
||||
<h1>{% trans "Password Reset" %}</h1>
|
||||
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
{% include "account/snippets/already_logged_in.html" %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
<p>{% blocktrans %}We have sent you an e-mail. Please contact us if you do not receive it within a few minutes.{% endblocktrans %}</p>
|
||||
{% endblock %}
|
||||
|
|
|
@ -72,4 +72,4 @@
|
|||
{% trans "Back to login" %}
|
||||
</a>
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -7,4 +7,4 @@
|
|||
<p>
|
||||
This is yet to be implemented.
|
||||
</p>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
"""URLs for the membersystem"""
|
||||
import debug_toolbar
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.urls import include
|
||||
from django.urls import path
|
||||
|
||||
import debug_toolbar
|
||||
|
||||
from .views import index, services_overview
|
||||
from membership.views import membership_overview
|
||||
|
||||
from .views import index
|
||||
from .views import services_overview
|
||||
|
||||
urlpatterns = [
|
||||
path("", login_required(index), name="index"),
|
||||
path("services/", login_required(services_overview), name="services-overview"),
|
||||
path("membership/", membership_overview, name="membership-overview"),
|
||||
path('accounts/', include('allauth.urls')),
|
||||
path("accounts/", include("allauth.urls")),
|
||||
path("admin/", admin.site.urls),
|
||||
path("__debug__/", include(debug_toolbar.urls)),
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue