Adding pre-commit
This commit is contained in:
parent
a6bac23b9f
commit
3d7261487f
33 changed files with 301 additions and 306 deletions
18
.pre-commit-config.yaml
Normal file
18
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v3.2.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-added-large-files
|
||||||
|
- repo: https://github.com/asottile/reorder-python-imports
|
||||||
|
rev: v3.12.0
|
||||||
|
hooks:
|
||||||
|
- id: reorder-python-imports
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.2.0
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: [ --fix, --exit-non-zero-on-fix ]
|
||||||
|
- id: ruff-format
|
|
@ -7,7 +7,4 @@ from . import models
|
||||||
|
|
||||||
@admin.register(models.User)
|
@admin.register(models.User)
|
||||||
class UserAdmin(BaseUserAdmin):
|
class UserAdmin(BaseUserAdmin):
|
||||||
fieldsets = (
|
fieldsets = (*BaseUserAdmin.fieldsets, (_('Subjects'), {'fields': ('subjects',)}))
|
||||||
*BaseUserAdmin.fieldsets,
|
|
||||||
(_("Subjects"), {"fields": ("subjects",)})
|
|
||||||
)
|
|
||||||
|
|
|
@ -2,5 +2,5 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class AccountConfig(AppConfig):
|
class AccountConfig(AppConfig):
|
||||||
default_auto_field = "django.db.models.BigAutoField"
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = "accounts"
|
name = 'accounts'
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
from crispy_forms import helper, layout
|
from crispy_forms import helper
|
||||||
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
|
from crispy_forms import layout
|
||||||
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
|
from django.contrib.auth.forms import UserCreationForm
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .models import User
|
from .models import User
|
||||||
|
@ -12,19 +14,19 @@ class LoginForm(AuthenticationForm):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.helper = helper.FormHelper()
|
self.helper = helper.FormHelper()
|
||||||
self.helper.form_action = "accounts:login"
|
self.helper.form_action = 'accounts:login'
|
||||||
self.helper.form_method = "post"
|
self.helper.form_method = 'post'
|
||||||
self.helper.add_input(layout.Submit('submit', _('Login')))
|
self.helper.add_input(layout.Submit('submit', _('Login')))
|
||||||
|
|
||||||
|
|
||||||
class RegisterForm(UserCreationForm):
|
class RegisterForm(UserCreationForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = UserCreationForm.Meta.fields + ("first_name", "last_name", "email")
|
fields = UserCreationForm.Meta.fields + ('first_name', 'last_name', 'email')
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.helper = helper.FormHelper()
|
self.helper = helper.FormHelper()
|
||||||
self.helper.form_action = "accounts:register"
|
self.helper.form_action = 'accounts:register'
|
||||||
self.helper.form_method = "post"
|
self.helper.form_method = 'post'
|
||||||
self.helper.add_input(layout.Submit('submit', _('Register')))
|
self.helper.add_input(layout.Submit('submit', _('Register')))
|
||||||
|
|
|
@ -1,131 +1,131 @@
|
||||||
# Generated by Django 5.0 on 2023-12-18 21:42
|
# Generated by Django 5.0 on 2023-12-18 21:42
|
||||||
|
|
||||||
import django.contrib.auth.models
|
import django.contrib.auth.models
|
||||||
import django.contrib.auth.validators
|
import django.contrib.auth.validators
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
from django.db import migrations, models
|
from django.db import migrations
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("auth", "0012_alter_user_first_name_max_length"),
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="User",
|
name='User',
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
"id",
|
'id',
|
||||||
models.BigAutoField(
|
models.BigAutoField(
|
||||||
auto_created=True,
|
auto_created=True,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
serialize=False,
|
serialize=False,
|
||||||
verbose_name="ID",
|
verbose_name='ID',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("password", models.CharField(max_length=128, verbose_name="password")),
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
(
|
(
|
||||||
"last_login",
|
'last_login',
|
||||||
models.DateTimeField(
|
models.DateTimeField(
|
||||||
blank=True, null=True, verbose_name="last login"
|
blank=True, null=True, verbose_name='last login'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"is_superuser",
|
'is_superuser',
|
||||||
models.BooleanField(
|
models.BooleanField(
|
||||||
default=False,
|
default=False,
|
||||||
help_text="Designates that this user has all permissions without explicitly assigning them.",
|
help_text='Designates that this user has all permissions without explicitly assigning them.',
|
||||||
verbose_name="superuser status",
|
verbose_name='superuser status',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"username",
|
'username',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
error_messages={
|
error_messages={
|
||||||
"unique": "A user with that username already exists."
|
'unique': 'A user with that username already exists.'
|
||||||
},
|
},
|
||||||
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
|
help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.',
|
||||||
max_length=150,
|
max_length=150,
|
||||||
unique=True,
|
unique=True,
|
||||||
validators=[
|
validators=[
|
||||||
django.contrib.auth.validators.UnicodeUsernameValidator()
|
django.contrib.auth.validators.UnicodeUsernameValidator()
|
||||||
],
|
],
|
||||||
verbose_name="username",
|
verbose_name='username',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"first_name",
|
'first_name',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=150, verbose_name="first name"
|
blank=True, max_length=150, verbose_name='first name'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"last_name",
|
'last_name',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=150, verbose_name="last name"
|
blank=True, max_length=150, verbose_name='last name'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"email",
|
'email',
|
||||||
models.EmailField(
|
models.EmailField(
|
||||||
blank=True, max_length=254, verbose_name="email address"
|
blank=True, max_length=254, verbose_name='email address'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"is_staff",
|
'is_staff',
|
||||||
models.BooleanField(
|
models.BooleanField(
|
||||||
default=False,
|
default=False,
|
||||||
help_text="Designates whether the user can log into this admin site.",
|
help_text='Designates whether the user can log into this admin site.',
|
||||||
verbose_name="staff status",
|
verbose_name='staff status',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"is_active",
|
'is_active',
|
||||||
models.BooleanField(
|
models.BooleanField(
|
||||||
default=True,
|
default=True,
|
||||||
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
|
help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.',
|
||||||
verbose_name="active",
|
verbose_name='active',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"date_joined",
|
'date_joined',
|
||||||
models.DateTimeField(
|
models.DateTimeField(
|
||||||
default=django.utils.timezone.now, verbose_name="date joined"
|
default=django.utils.timezone.now, verbose_name='date joined'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"groups",
|
'groups',
|
||||||
models.ManyToManyField(
|
models.ManyToManyField(
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
|
help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
|
||||||
related_name="user_set",
|
related_name='user_set',
|
||||||
related_query_name="user",
|
related_query_name='user',
|
||||||
to="auth.group",
|
to='auth.group',
|
||||||
verbose_name="groups",
|
verbose_name='groups',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"user_permissions",
|
'user_permissions',
|
||||||
models.ManyToManyField(
|
models.ManyToManyField(
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="Specific permissions for this user.",
|
help_text='Specific permissions for this user.',
|
||||||
related_name="user_set",
|
related_name='user_set',
|
||||||
related_query_name="user",
|
related_query_name='user',
|
||||||
to="auth.permission",
|
to='auth.permission',
|
||||||
verbose_name="user permissions",
|
verbose_name='user permissions',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
"verbose_name": "user",
|
'verbose_name': 'user',
|
||||||
"verbose_name_plural": "users",
|
'verbose_name_plural': 'users',
|
||||||
"abstract": False,
|
'abstract': False,
|
||||||
},
|
},
|
||||||
managers=[
|
managers=[
|
||||||
("objects", django.contrib.auth.models.UserManager()),
|
('objects', django.contrib.auth.models.UserManager()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
# Generated by Django 5.0 on 2023-12-19 11:53
|
# Generated by Django 5.0 on 2023-12-19 11:53
|
||||||
|
from django.db import migrations
|
||||||
from django.db import migrations, models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("accounts", "0001_initial"),
|
('accounts', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="user",
|
model_name='user',
|
||||||
name="email",
|
name='email',
|
||||||
field=models.EmailField(max_length=254, verbose_name="email address"),
|
field=models.EmailField(max_length=254, verbose_name='email address'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="user",
|
model_name='user',
|
||||||
name="first_name",
|
name='first_name',
|
||||||
field=models.CharField(max_length=150, verbose_name="first name"),
|
field=models.CharField(max_length=150, verbose_name='first name'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="user",
|
model_name='user',
|
||||||
name="last_name",
|
name='last_name',
|
||||||
field=models.CharField(max_length=150, verbose_name="last name"),
|
field=models.CharField(max_length=150, verbose_name='last name'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-29 21:06
|
# Generated by Django 5.0.1 on 2024-01-29 21:06
|
||||||
|
from django.db import migrations
|
||||||
from django.db import migrations, models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("accounts", "0002_alter_user_email_alter_user_first_name_and_more"),
|
('accounts', '0002_alter_user_email_alter_user_first_name_and_more'),
|
||||||
("subjects", "0003_alter_subject_options"),
|
('subjects', '0003_alter_subject_options'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name="user",
|
model_name='user',
|
||||||
name="subjects",
|
name='subjects',
|
||||||
field=models.ManyToManyField(to="subjects.subject"),
|
field=models.ManyToManyField(to='subjects.subject'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-29 21:19
|
# Generated by Django 5.0.1 on 2024-01-29 21:19
|
||||||
|
from django.db import migrations
|
||||||
from django.db import migrations, models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("accounts", "0003_user_subjects"),
|
('accounts', '0003_user_subjects'),
|
||||||
("subjects", "0003_alter_subject_options"),
|
('subjects', '0003_alter_subject_options'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="user",
|
model_name='user',
|
||||||
name="subjects",
|
name='subjects',
|
||||||
field=models.ManyToManyField(blank=True, to="subjects.subject"),
|
field=models.ManyToManyField(blank=True, to='subjects.subject'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -6,11 +6,11 @@ from subjects.models import Subject
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
REQUIRED_FIELDS = ["email", "first_name", "last_name"]
|
REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
|
||||||
|
|
||||||
first_name = models.CharField(_("first name"), max_length=150)
|
first_name = models.CharField(_('first name'), max_length=150)
|
||||||
last_name = models.CharField(_("last name"), max_length=150)
|
last_name = models.CharField(_('last name'), max_length=150)
|
||||||
email = models.EmailField(_("email address"))
|
email = models.EmailField(_('email address'))
|
||||||
|
|
||||||
subjects = models.ManyToManyField(Subject, blank=True)
|
subjects = models.ManyToManyField(Subject, blank=True)
|
||||||
|
|
||||||
|
|
|
@ -7,4 +7,4 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% crispy form form.helper %}
|
{% crispy form form.helper %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
|
|
@ -2,12 +2,12 @@ from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
app_name = "accounts"
|
app_name = 'accounts'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.me, name="me"),
|
path('', views.me, name='me'),
|
||||||
path("me/", views.me, name="me_exp"),
|
path('me/', views.me, name='me_exp'),
|
||||||
path("login/", views.auth_login, name="login"),
|
path('login/', views.auth_login, name='login'),
|
||||||
path("logout/", views.auth_logout, name="logout"),
|
path('logout/', views.auth_logout, name='logout'),
|
||||||
path("register/", views.auth_register, name="register"),
|
path('register/', views.auth_register, name='register'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,28 +1,32 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import login, logout
|
from django.contrib.auth import login
|
||||||
|
from django.contrib.auth import logout
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest
|
||||||
from django.shortcuts import redirect, render, reverse
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.shortcuts import reverse
|
||||||
|
|
||||||
from . import forms
|
from . import forms
|
||||||
|
|
||||||
|
|
||||||
def auth_login(req: HttpRequest) -> HttpResponse:
|
def auth_login(req: HttpRequest) -> HttpResponse:
|
||||||
if req.method == "POST":
|
if req.method == 'POST':
|
||||||
form = forms.LoginForm(data=req.POST)
|
form = forms.LoginForm(data=req.POST)
|
||||||
|
|
||||||
if not form.is_valid():
|
if not form.is_valid():
|
||||||
return render(req, "account/login.html", dict(form=form))
|
return render(req, 'account/login.html', dict(form=form))
|
||||||
|
|
||||||
user = form.get_user()
|
user = form.get_user()
|
||||||
login(req, user)
|
login(req, user)
|
||||||
|
|
||||||
redirect_url = getattr(req.GET, "next", settings.LOGIN_REDIRECT_URL)
|
redirect_url = getattr(req.GET, 'next', settings.LOGIN_REDIRECT_URL)
|
||||||
return redirect(redirect_url)
|
return redirect(redirect_url)
|
||||||
|
|
||||||
elif req.method == "GET":
|
elif req.method == 'GET':
|
||||||
form = forms.LoginForm()
|
form = forms.LoginForm()
|
||||||
return render(req, "account/login.html", dict(form=form))
|
return render(req, 'account/login.html', dict(form=form))
|
||||||
|
|
||||||
return HttpResponse(status=405)
|
return HttpResponse(status=405)
|
||||||
|
|
||||||
|
@ -35,20 +39,20 @@ def auth_logout(req: HttpRequest) -> HttpResponse:
|
||||||
|
|
||||||
def auth_register(req: HttpRequest) -> HttpResponse:
|
def auth_register(req: HttpRequest) -> HttpResponse:
|
||||||
if req.user.is_authenticated:
|
if req.user.is_authenticated:
|
||||||
return redirect(reverse("me"))
|
return redirect(reverse('me'))
|
||||||
if req.method == "POST":
|
if req.method == 'POST':
|
||||||
form = forms.RegisterForm(data=req.POST)
|
form = forms.RegisterForm(data=req.POST)
|
||||||
|
|
||||||
if not form.is_valid():
|
if not form.is_valid():
|
||||||
return render(req, "account/register.html", dict(form=form))
|
return render(req, 'account/register.html', dict(form=form))
|
||||||
|
|
||||||
user = form.save()
|
user = form.save()
|
||||||
login(req, user)
|
login(req, user)
|
||||||
return redirect(settings.LOGIN_BASE_URL)
|
return redirect(settings.LOGIN_BASE_URL)
|
||||||
|
|
||||||
elif req.method == "GET":
|
elif req.method == 'GET':
|
||||||
form = forms.RegisterForm()
|
form = forms.RegisterForm()
|
||||||
return render(req, "account/register.html", dict(form=form))
|
return render(req, 'account/register.html', dict(form=form))
|
||||||
|
|
||||||
return HttpResponse(status=405)
|
return HttpResponse(status=405)
|
||||||
|
|
||||||
|
@ -56,4 +60,4 @@ def auth_register(req: HttpRequest) -> HttpResponse:
|
||||||
@login_required
|
@login_required
|
||||||
def me(req: HttpRequest) -> HttpResponse:
|
def me(req: HttpRequest) -> HttpResponse:
|
||||||
print(req.user.username)
|
print(req.user.username)
|
||||||
return render(req, "account/me.html")
|
return render(req, 'account/me.html')
|
||||||
|
|
|
@ -6,11 +6,10 @@ It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
For more information on this file, see
|
For more information on this file, see
|
||||||
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
|
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.core.asgi import get_asgi_application
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "facturio.settings")
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'facturio.settings')
|
||||||
|
|
||||||
application = get_asgi_application()
|
application = get_asgi_application()
|
||||||
|
|
|
@ -9,8 +9,8 @@ https://docs.djangoproject.com/en/5.0/topics/settings/
|
||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/5.0/ref/settings/
|
https://docs.djangoproject.com/en/5.0/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
@ -20,7 +20,7 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = "django-insecure-+l+g3)q1zz2bz7=mz4ys6lhu5uj+=ucj34flm^clo4vb3(wmdp"
|
SECRET_KEY = 'django-insecure-+l+g3)q1zz2bz7=mz4ys6lhu5uj+=ucj34flm^clo4vb3(wmdp'
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
@ -30,56 +30,56 @@ ALLOWED_HOSTS = ['*']
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
"django.contrib.admin",
|
'django.contrib.admin',
|
||||||
"django.contrib.auth",
|
'django.contrib.auth',
|
||||||
"django.contrib.contenttypes",
|
'django.contrib.contenttypes',
|
||||||
"django.contrib.sessions",
|
'django.contrib.sessions',
|
||||||
"django.contrib.messages",
|
'django.contrib.messages',
|
||||||
"django.contrib.staticfiles",
|
'django.contrib.staticfiles',
|
||||||
"crispy_forms",
|
'crispy_forms',
|
||||||
"crispy_bootstrap5",
|
'crispy_bootstrap5',
|
||||||
"accounts.apps.AccountConfig",
|
'accounts.apps.AccountConfig',
|
||||||
"subjects.apps.SubjectsConfig"
|
'subjects.apps.SubjectsConfig',
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
"django.middleware.security.SecurityMiddleware",
|
'django.middleware.security.SecurityMiddleware',
|
||||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
"django.middleware.locale.LocaleMiddleware",
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
"django.middleware.common.CommonMiddleware",
|
'django.middleware.common.CommonMiddleware',
|
||||||
"django.middleware.csrf.CsrfViewMiddleware",
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
"django.contrib.messages.middleware.MessageMiddleware",
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = "facturio.urls"
|
ROOT_URLCONF = 'facturio.urls'
|
||||||
|
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
"DIRS": [BASE_DIR / "templates"],
|
'DIRS': [BASE_DIR / 'templates'],
|
||||||
"APP_DIRS": True,
|
'APP_DIRS': True,
|
||||||
"OPTIONS": {
|
'OPTIONS': {
|
||||||
"context_processors": [
|
'context_processors': [
|
||||||
"django.template.context_processors.debug",
|
'django.template.context_processors.debug',
|
||||||
"django.template.context_processors.request",
|
'django.template.context_processors.request',
|
||||||
"django.contrib.auth.context_processors.auth",
|
'django.contrib.auth.context_processors.auth',
|
||||||
"django.contrib.messages.context_processors.messages",
|
'django.contrib.messages.context_processors.messages',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
WSGI_APPLICATION = "facturio.wsgi.application"
|
WSGI_APPLICATION = 'facturio.wsgi.application'
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
||||||
|
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
"default": {
|
'default': {
|
||||||
"ENGINE": "django.db.backends.sqlite3",
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
"NAME": BASE_DIR / "db.sqlite3",
|
'NAME': BASE_DIR / 'db.sqlite3',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,33 +88,28 @@ DATABASES = {
|
||||||
|
|
||||||
AUTH_PASSWORD_VALIDATORS = [
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
{
|
{
|
||||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/5.0/topics/i18n/
|
# https://docs.djangoproject.com/en/5.0/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = "cs"
|
LANGUAGE_CODE = 'cs'
|
||||||
LANGUAGES = [
|
LANGUAGES = [('en', _('English')), ('cs', _('Czech'))]
|
||||||
("en", _("English")),
|
|
||||||
("cs", _("Czech"))
|
|
||||||
]
|
|
||||||
|
|
||||||
LOCALE_PATHS = [
|
LOCALE_PATHS = [BASE_DIR / 'locale']
|
||||||
BASE_DIR / "locale"
|
|
||||||
]
|
|
||||||
|
|
||||||
TIME_ZONE = "UTC"
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
|
|
||||||
|
@ -123,22 +118,22 @@ USE_TZ = True
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/5.0/howto/static-files/
|
# https://docs.djangoproject.com/en/5.0/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = "static/"
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
# Default primary key field type
|
# Default primary key field type
|
||||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
|
||||||
|
|
||||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
|
|
||||||
# Auth configuration
|
# Auth configuration
|
||||||
LOGIN_BASE_URL = "/accounts"
|
LOGIN_BASE_URL = '/accounts'
|
||||||
LOGIN_URL = f"{LOGIN_BASE_URL}/login"
|
LOGIN_URL = f'{LOGIN_BASE_URL}/login'
|
||||||
LOGOUT_REDIRECT_URL = f"/"
|
LOGOUT_REDIRECT_URL = '/'
|
||||||
LOGIN_REDIRECT_URL = f"{LOGIN_BASE_URL}/me"
|
LOGIN_REDIRECT_URL = f'{LOGIN_BASE_URL}/me'
|
||||||
|
|
||||||
AUTH_USER_MODEL = "accounts.User"
|
AUTH_USER_MODEL = 'accounts.User'
|
||||||
|
|
||||||
# Crispy config
|
# Crispy config
|
||||||
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
|
CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap5'
|
||||||
|
|
||||||
CRISPY_TEMPLATE_PACK = "bootstrap5"
|
CRISPY_TEMPLATE_PACK = 'bootstrap5'
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
from django.contrib import admin
|
|
||||||
from django.http import HttpRequest, HttpResponse
|
|
||||||
from django.shortcuts import render
|
|
||||||
from django.urls import path, include
|
|
||||||
from django.conf.urls.i18n import i18n_patterns
|
from django.conf.urls.i18n import i18n_patterns
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.http import HttpRequest
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.urls import include
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
|
||||||
def landing_page(req: HttpRequest) -> HttpResponse:
|
def landing_page(req: HttpRequest) -> HttpResponse:
|
||||||
return render(req, "facturio/index.html")
|
return render(req, 'facturio/index.html')
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = i18n_patterns(
|
urlpatterns = i18n_patterns(
|
||||||
path("", landing_page, name="main-page"),
|
path('', landing_page, name='main-page'),
|
||||||
path("accounts/", include("accounts.urls")),
|
path('accounts/', include('accounts.urls')),
|
||||||
path("subjects/", include("subjects.urls")),
|
path('subjects/', include('subjects.urls')),
|
||||||
path("admin/", admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
prefix_default_language=False
|
prefix_default_language=False,
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,11 +6,10 @@ It exposes the WSGI callable as a module-level variable named ``application``.
|
||||||
For more information on this file, see
|
For more information on this file, see
|
||||||
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
|
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "facturio.settings")
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'facturio.settings')
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
|
|
|
@ -6,17 +6,17 @@ import sys
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Run administrative tasks."""
|
"""Run administrative tasks."""
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "facturio.settings")
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'facturio.settings')
|
||||||
try:
|
try:
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
raise ImportError(
|
raise ImportError(
|
||||||
"Couldn't import Django. Are you sure it's installed and "
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
"available on your PYTHONPATH environment variable? Did you "
|
'available on your PYTHONPATH environment variable? Did you '
|
||||||
"forget to activate a virtual environment?"
|
'forget to activate a virtual environment?'
|
||||||
) from exc
|
) from exc
|
||||||
execute_from_command_line(sys.argv)
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -17,3 +17,6 @@ ares-util = "^0.3.0"
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core"]
|
requires = ["poetry-core"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
quote-style = "single"
|
||||||
|
|
|
@ -5,5 +5,4 @@ from . import models
|
||||||
|
|
||||||
@admin.register(models.Subject)
|
@admin.register(models.Subject)
|
||||||
class SubjectAdmin(admin.ModelAdmin):
|
class SubjectAdmin(admin.ModelAdmin):
|
||||||
list_display = ["id", "name", "city", "city_part", "zip_code"]
|
list_display = ['id', 'name', 'city', 'city_part', 'zip_code']
|
||||||
|
|
||||||
|
|
|
@ -2,5 +2,5 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class SubjectsConfig(AppConfig):
|
class SubjectsConfig(AppConfig):
|
||||||
default_auto_field = "django.db.models.BigAutoField"
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
name = "subjects"
|
name = 'subjects'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from ares_util.ares import validate_czech_company_id
|
from ares_util.ares import validate_czech_company_id
|
||||||
from ares_util.exceptions import InvalidCompanyIDError
|
from ares_util.exceptions import InvalidCompanyIDError
|
||||||
from crispy_forms import helper, layout
|
from crispy_forms import helper
|
||||||
|
from crispy_forms import layout
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms import fields
|
from django.forms import fields
|
||||||
|
@ -11,36 +12,32 @@ from . import models
|
||||||
|
|
||||||
class CreateSubjectForm(forms.Form):
|
class CreateSubjectForm(forms.Form):
|
||||||
error_messages = {
|
error_messages = {
|
||||||
"invalid_cin": _("Your provided CIN is not correct."),
|
'invalid_cin': _('Your provided CIN is not correct.'),
|
||||||
"already_existing": _("Subject with provided CIN already exists.")
|
'already_existing': _('Subject with provided CIN already exists.'),
|
||||||
}
|
}
|
||||||
cin = fields.CharField(
|
cin = fields.CharField(
|
||||||
label=_("CIN"),
|
label=_('CIN'),
|
||||||
max_length=8,
|
max_length=8,
|
||||||
help_text=_("Enter the subject CIN, rest will be generated automatically")
|
help_text=_('Enter the subject CIN, rest will be generated automatically'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.helper = helper.FormHelper()
|
self.helper = helper.FormHelper()
|
||||||
self.helper.form_action = "subjects:create"
|
self.helper.form_action = 'subjects:create'
|
||||||
self.helper.form_method = "post"
|
self.helper.form_method = 'post'
|
||||||
self.helper.add_input(layout.Submit('submit', _('Add')))
|
self.helper.add_input(layout.Submit('submit', _('Add')))
|
||||||
|
|
||||||
def clean_cin(self):
|
def clean_cin(self):
|
||||||
cin = self.cleaned_data.get("cin")
|
cin = self.cleaned_data.get('cin')
|
||||||
try:
|
try:
|
||||||
validate_czech_company_id(cin)
|
validate_czech_company_id(cin)
|
||||||
except InvalidCompanyIDError:
|
except InvalidCompanyIDError:
|
||||||
raise ValidationError(
|
raise ValidationError(self.error_messages['invalid_cin'])
|
||||||
self.error_messages["invalid_cin"]
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
models.Subject.objects.get(id=cin)
|
models.Subject.objects.get(id=cin)
|
||||||
except models.Subject.DoesNotExist:
|
except models.Subject.DoesNotExist:
|
||||||
return cin
|
return cin
|
||||||
|
|
||||||
raise ValidationError(
|
raise ValidationError(self.error_messages['already_existing'])
|
||||||
self.error_messages["already_existing"]
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Generated by Django 5.0 on 2023-12-20 22:36
|
# Generated by Django 5.0 on 2023-12-20 22:36
|
||||||
|
from django.db import migrations
|
||||||
from django.db import migrations, models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -10,31 +10,31 @@ class Migration(migrations.Migration):
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name="Subject",
|
name='Subject',
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
"id",
|
'id',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
max_length=8,
|
max_length=8,
|
||||||
primary_key=True,
|
primary_key=True,
|
||||||
serialize=False,
|
serialize=False,
|
||||||
verbose_name="cin",
|
verbose_name='cin',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("name", models.CharField(max_length=128, verbose_name="name")),
|
('name', models.CharField(max_length=128, verbose_name='name')),
|
||||||
(
|
(
|
||||||
"vat_id",
|
'vat_id',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=12, null=True, verbose_name="vat_id"
|
blank=True, max_length=12, null=True, verbose_name='vat_id'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
("street", models.CharField(max_length=64, verbose_name="street")),
|
('street', models.CharField(max_length=64, verbose_name='street')),
|
||||||
("zip_code", models.CharField(max_length=6, verbose_name="zip_code")),
|
('zip_code', models.CharField(max_length=6, verbose_name='zip_code')),
|
||||||
("city", models.CharField(max_length=64, verbose_name="city")),
|
('city', models.CharField(max_length=64, verbose_name='city')),
|
||||||
(
|
(
|
||||||
"city_part",
|
'city_part',
|
||||||
models.CharField(
|
models.CharField(
|
||||||
blank=True, max_length=64, null=True, verbose_name="city_part"
|
blank=True, max_length=64, null=True, verbose_name='city_part'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,53 +1,53 @@
|
||||||
# Generated by Django 5.0 on 2023-12-20 22:47
|
# Generated by Django 5.0 on 2023-12-20 22:47
|
||||||
|
from django.db import migrations
|
||||||
from django.db import migrations, models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("subjects", "0001_initial"),
|
('subjects', '0001_initial'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="subject",
|
model_name='subject',
|
||||||
name="city",
|
name='city',
|
||||||
field=models.CharField(max_length=64, verbose_name="City"),
|
field=models.CharField(max_length=64, verbose_name='City'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="subject",
|
model_name='subject',
|
||||||
name="city_part",
|
name='city_part',
|
||||||
field=models.CharField(
|
field=models.CharField(
|
||||||
blank=True, max_length=64, null=True, verbose_name="City part"
|
blank=True, max_length=64, null=True, verbose_name='City part'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="subject",
|
model_name='subject',
|
||||||
name="id",
|
name='id',
|
||||||
field=models.CharField(
|
field=models.CharField(
|
||||||
max_length=8, primary_key=True, serialize=False, verbose_name="CIN"
|
max_length=8, primary_key=True, serialize=False, verbose_name='CIN'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="subject",
|
model_name='subject',
|
||||||
name="name",
|
name='name',
|
||||||
field=models.CharField(max_length=128, verbose_name="Name"),
|
field=models.CharField(max_length=128, verbose_name='Name'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="subject",
|
model_name='subject',
|
||||||
name="street",
|
name='street',
|
||||||
field=models.CharField(max_length=64, verbose_name="Street"),
|
field=models.CharField(max_length=64, verbose_name='Street'),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="subject",
|
model_name='subject',
|
||||||
name="vat_id",
|
name='vat_id',
|
||||||
field=models.CharField(
|
field=models.CharField(
|
||||||
blank=True, max_length=12, null=True, verbose_name="VAT ID"
|
blank=True, max_length=12, null=True, verbose_name='VAT ID'
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name="subject",
|
model_name='subject',
|
||||||
name="zip_code",
|
name='zip_code',
|
||||||
field=models.CharField(max_length=6, verbose_name="Zip Code"),
|
field=models.CharField(max_length=6, verbose_name='Zip Code'),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
# Generated by Django 5.0.1 on 2024-01-29 21:06
|
# Generated by Django 5.0.1 on 2024-01-29 21:06
|
||||||
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
dependencies = [
|
dependencies = [
|
||||||
("subjects", "0002_alter_subject_city_alter_subject_city_part_and_more"),
|
('subjects', '0002_alter_subject_city_alter_subject_city_part_and_more'),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
migrations.AlterModelOptions(
|
migrations.AlterModelOptions(
|
||||||
name="subject",
|
name='subject',
|
||||||
options={"verbose_name": "Subject", "verbose_name_plural": "Subjects"},
|
options={'verbose_name': 'Subject', 'verbose_name_plural': 'Subjects'},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,55 +1,37 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class Subject(models.Model):
|
class Subject(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Subject")
|
verbose_name = _('Subject')
|
||||||
verbose_name_plural = _("Subjects")
|
verbose_name_plural = _('Subjects')
|
||||||
|
|
||||||
id = models.CharField(
|
id = models.CharField(_('CIN'), max_length=8, primary_key=True)
|
||||||
_("CIN"),
|
|
||||||
max_length=8,
|
|
||||||
primary_key=True
|
|
||||||
)
|
|
||||||
|
|
||||||
name = models.CharField(
|
name = models.CharField(_('Name'), max_length=128)
|
||||||
_("Name"),
|
|
||||||
max_length=128
|
|
||||||
)
|
|
||||||
|
|
||||||
vat_id = models.CharField(
|
vat_id = models.CharField(_('VAT ID'), max_length=12, null=True, blank=True)
|
||||||
_("VAT ID"),
|
|
||||||
max_length=12,
|
|
||||||
null=True,
|
|
||||||
blank=True
|
|
||||||
)
|
|
||||||
|
|
||||||
street = models.CharField(
|
street = models.CharField(
|
||||||
_("Street"),
|
_('Street'),
|
||||||
max_length=64,
|
max_length=64,
|
||||||
)
|
)
|
||||||
|
|
||||||
zip_code = models.CharField(
|
zip_code = models.CharField(
|
||||||
_("Zip Code"),
|
_('Zip Code'),
|
||||||
max_length=6,
|
max_length=6,
|
||||||
)
|
)
|
||||||
|
|
||||||
city = models.CharField(
|
city = models.CharField(
|
||||||
_("City"),
|
_('City'),
|
||||||
max_length=64,
|
max_length=64,
|
||||||
)
|
)
|
||||||
|
|
||||||
city_part = models.CharField(
|
city_part = models.CharField(_('City part'), max_length=64, null=True, blank=True)
|
||||||
_("City part"),
|
|
||||||
max_length=64,
|
|
||||||
null=True,
|
|
||||||
blank=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def get_linked_users(self) -> list[int]:
|
def get_linked_users(self) -> list[int]:
|
||||||
return list(self.user_set.values_list("id", flat=True))
|
return list(self.user_set.values_list('id', flat=True))
|
||||||
|
|
|
@ -7,4 +7,4 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% crispy form form.helper %}
|
{% crispy form form.helper %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
|
|
@ -2,11 +2,11 @@ from django.urls import path
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
app_name = "subjects"
|
app_name = 'subjects'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", views.main_page, name="list"),
|
path('', views.main_page, name='list'),
|
||||||
path("new/", views.create_subject, name="create"),
|
path('new/', views.create_subject, name='create'),
|
||||||
path("link/<int:subject_id>", views.link_subject, name="link"),
|
path('link/<int:subject_id>', views.link_subject, name='link'),
|
||||||
path("unlink/<int:subject_id>", views.unlink_subject, name="unlink")
|
path('unlink/<int:subject_id>', views.unlink_subject, name='unlink'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,51 +1,54 @@
|
||||||
from ares_util.ares import call_ares
|
from ares_util.ares import call_ares
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest
|
||||||
from django.shortcuts import render, redirect
|
from django.http import HttpResponse
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
from django.shortcuts import render
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from . import models, forms
|
from . import forms
|
||||||
|
from . import models
|
||||||
|
|
||||||
|
|
||||||
def build_address(street: str, zip_code: int | str, city: str, city_part: str) -> str:
|
def build_address(street: str, zip_code: int | str, city: str, city_part: str) -> str:
|
||||||
return f"{street}, {zip_code}, {city} - {city_part}"
|
return f'{street}, {zip_code}, {city} - {city_part}'
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def main_page(req: HttpRequest) -> HttpResponse:
|
def main_page(req: HttpRequest) -> HttpResponse:
|
||||||
subjects = models.Subject.objects.all()
|
subjects = models.Subject.objects.all()
|
||||||
return render(req, "subjects/index.html", dict(subjects=subjects))
|
return render(req, 'subjects/index.html', dict(subjects=subjects))
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def create_subject(req: HttpRequest) -> HttpResponse:
|
def create_subject(req: HttpRequest) -> HttpResponse:
|
||||||
if req.method == "POST":
|
if req.method == 'POST':
|
||||||
form = forms.CreateSubjectForm(data=req.POST)
|
form = forms.CreateSubjectForm(data=req.POST)
|
||||||
|
|
||||||
if not form.is_valid():
|
if not form.is_valid():
|
||||||
return render(req, "subjects/create.html", dict(form=form))
|
return render(req, 'subjects/create.html', dict(form=form))
|
||||||
|
|
||||||
ares_data = call_ares(form.cleaned_data.get("cin"))
|
ares_data = call_ares(form.cleaned_data.get('cin'))
|
||||||
|
|
||||||
ares_address_data = ares_data["address"]
|
ares_address_data = ares_data['address']
|
||||||
ares_legal_data = ares_data["legal"]
|
ares_legal_data = ares_data['legal']
|
||||||
|
|
||||||
models.Subject.objects.create(
|
models.Subject.objects.create(
|
||||||
id=ares_legal_data["company_id"],
|
id=ares_legal_data['company_id'],
|
||||||
vat_id=ares_legal_data["company_vat_id"],
|
vat_id=ares_legal_data['company_vat_id'],
|
||||||
name=ares_legal_data["company_name"],
|
name=ares_legal_data['company_name'],
|
||||||
street=ares_address_data["street"],
|
street=ares_address_data['street'],
|
||||||
zip_code=ares_address_data["zip_code"],
|
zip_code=ares_address_data['zip_code'],
|
||||||
city=ares_address_data["city"],
|
city=ares_address_data['city'],
|
||||||
city_part=ares_address_data["city_part"],
|
city_part=ares_address_data['city_part'],
|
||||||
)
|
)
|
||||||
|
|
||||||
return redirect(reverse("subjects:list"))
|
return redirect(reverse('subjects:list'))
|
||||||
|
|
||||||
elif req.method == "GET":
|
elif req.method == 'GET':
|
||||||
form = forms.CreateSubjectForm()
|
form = forms.CreateSubjectForm()
|
||||||
|
|
||||||
return render(req, "subjects/create.html", dict(form=form))
|
return render(req, 'subjects/create.html', dict(form=form))
|
||||||
|
|
||||||
return HttpResponse(status=405)
|
return HttpResponse(status=405)
|
||||||
|
|
||||||
|
@ -54,11 +57,11 @@ def create_subject(req: HttpRequest) -> HttpResponse:
|
||||||
def link_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
|
def link_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
|
||||||
subject = models.Subject.objects.get(pk=subject_id)
|
subject = models.Subject.objects.get(pk=subject_id)
|
||||||
subject.user_set.add(request.user)
|
subject.user_set.add(request.user)
|
||||||
return redirect(reverse("subjects:list"))
|
return redirect(reverse('subjects:list'))
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def unlink_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
|
def unlink_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
|
||||||
subject = models.Subject.objects.get(pk=subject_id)
|
subject = models.Subject.objects.get(pk=subject_id)
|
||||||
subject.user_set.remove(request.user)
|
subject.user_set.remove(request.user)
|
||||||
return redirect(reverse("subjects:list"))
|
return redirect(reverse('subjects:list'))
|
||||||
|
|
|
@ -55,4 +55,4 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{% extends "facturio/base.html" %}
|
{% extends "facturio/base.html" %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "App" %}{% endblock %}
|
{% block title %}{% trans "App" %}{% endblock %}
|
||||||
|
|
|
@ -15,4 +15,4 @@ echo "Compiling messages!"
|
||||||
./manage.py compilemessages >/dev/null
|
./manage.py compilemessages >/dev/null
|
||||||
|
|
||||||
echo "Migrating"
|
echo "Migrating"
|
||||||
./manage.py migrate >/dev/null
|
./manage.py migrate >/dev/null
|
||||||
|
|
Reference in a new issue