Adding pre-commit

This commit is contained in:
Jakub Kropáček 2024-02-03 21:07:20 +00:00
parent a6bac23b9f
commit 3d7261487f
33 changed files with 301 additions and 306 deletions

18
.pre-commit-config.yaml Normal file
View 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

View file

@ -7,7 +7,4 @@ from . import models
@admin.register(models.User)
class UserAdmin(BaseUserAdmin):
fieldsets = (
*BaseUserAdmin.fieldsets,
(_("Subjects"), {"fields": ("subjects",)})
)
fieldsets = (*BaseUserAdmin.fieldsets, (_('Subjects'), {'fields': ('subjects',)}))

View file

@ -2,5 +2,5 @@ from django.apps import AppConfig
class AccountConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "accounts"
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'

View file

@ -1,5 +1,7 @@
from crispy_forms import helper, layout
from django.contrib.auth.forms import AuthenticationForm, UserCreationForm
from crispy_forms import helper
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 .models import User
@ -12,19 +14,19 @@ class LoginForm(AuthenticationForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = helper.FormHelper()
self.helper.form_action = "accounts:login"
self.helper.form_method = "post"
self.helper.form_action = 'accounts:login'
self.helper.form_method = 'post'
self.helper.add_input(layout.Submit('submit', _('Login')))
class RegisterForm(UserCreationForm):
class Meta:
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):
super().__init__(*args, **kwargs)
self.helper = helper.FormHelper()
self.helper.form_action = "accounts:register"
self.helper.form_method = "post"
self.helper.form_action = 'accounts:register'
self.helper.form_method = 'post'
self.helper.add_input(layout.Submit('submit', _('Register')))

View file

@ -1,131 +1,131 @@
# Generated by Django 5.0 on 2023-12-18 21:42
import django.contrib.auth.models
import django.contrib.auth.validators
import django.utils.timezone
from django.db import migrations, models
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
initial = True
dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name="User",
name='User',
fields=[
(
"id",
'id',
models.BigAutoField(
auto_created=True,
primary_key=True,
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(
blank=True, null=True, verbose_name="last login"
blank=True, null=True, verbose_name='last login'
),
),
(
"is_superuser",
'is_superuser',
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
help_text='Designates that this user has all permissions without explicitly assigning them.',
verbose_name='superuser status',
),
),
(
"username",
'username',
models.CharField(
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,
unique=True,
validators=[
django.contrib.auth.validators.UnicodeUsernameValidator()
],
verbose_name="username",
verbose_name='username',
),
),
(
"first_name",
'first_name',
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(
blank=True, max_length=150, verbose_name="last name"
blank=True, max_length=150, verbose_name='last name'
),
),
(
"email",
'email',
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(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
help_text='Designates whether the user can log into this admin site.',
verbose_name='staff status',
),
),
(
"is_active",
'is_active',
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.',
verbose_name='active',
),
),
(
"date_joined",
'date_joined',
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="date joined"
default=django.utils.timezone.now, verbose_name='date joined'
),
),
(
"groups",
'groups',
models.ManyToManyField(
blank=True,
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_query_name="user",
to="auth.group",
verbose_name="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_query_name='user',
to='auth.group',
verbose_name='groups',
),
),
(
"user_permissions",
'user_permissions',
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.permission",
verbose_name="user permissions",
help_text='Specific permissions for this user.',
related_name='user_set',
related_query_name='user',
to='auth.permission',
verbose_name='user permissions',
),
),
],
options={
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
("objects", django.contrib.auth.models.UserManager()),
('objects', django.contrib.auth.models.UserManager()),
],
),
]

View file

@ -1,27 +1,27 @@
# Generated by Django 5.0 on 2023-12-19 11:53
from django.db import migrations, models
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("accounts", "0001_initial"),
('accounts', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name="user",
name="email",
field=models.EmailField(max_length=254, verbose_name="email address"),
model_name='user',
name='email',
field=models.EmailField(max_length=254, verbose_name='email address'),
),
migrations.AlterField(
model_name="user",
name="first_name",
field=models.CharField(max_length=150, verbose_name="first name"),
model_name='user',
name='first_name',
field=models.CharField(max_length=150, verbose_name='first name'),
),
migrations.AlterField(
model_name="user",
name="last_name",
field=models.CharField(max_length=150, verbose_name="last name"),
model_name='user',
name='last_name',
field=models.CharField(max_length=150, verbose_name='last name'),
),
]

View file

@ -1,18 +1,18 @@
# Generated by Django 5.0.1 on 2024-01-29 21:06
from django.db import migrations, models
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("accounts", "0002_alter_user_email_alter_user_first_name_and_more"),
("subjects", "0003_alter_subject_options"),
('accounts', '0002_alter_user_email_alter_user_first_name_and_more'),
('subjects', '0003_alter_subject_options'),
]
operations = [
migrations.AddField(
model_name="user",
name="subjects",
field=models.ManyToManyField(to="subjects.subject"),
model_name='user',
name='subjects',
field=models.ManyToManyField(to='subjects.subject'),
),
]

View file

@ -1,18 +1,18 @@
# Generated by Django 5.0.1 on 2024-01-29 21:19
from django.db import migrations, models
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("accounts", "0003_user_subjects"),
("subjects", "0003_alter_subject_options"),
('accounts', '0003_user_subjects'),
('subjects', '0003_alter_subject_options'),
]
operations = [
migrations.AlterField(
model_name="user",
name="subjects",
field=models.ManyToManyField(blank=True, to="subjects.subject"),
model_name='user',
name='subjects',
field=models.ManyToManyField(blank=True, to='subjects.subject'),
),
]

View file

@ -6,11 +6,11 @@ from subjects.models import Subject
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)
last_name = models.CharField(_("last name"), max_length=150)
email = models.EmailField(_("email address"))
first_name = models.CharField(_('first name'), max_length=150)
last_name = models.CharField(_('last name'), max_length=150)
email = models.EmailField(_('email address'))
subjects = models.ManyToManyField(Subject, blank=True)

View file

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here.

View file

@ -2,12 +2,12 @@ from django.urls import path
from . import views
app_name = "accounts"
app_name = 'accounts'
urlpatterns = [
path("", views.me, name="me"),
path("me/", views.me, name="me_exp"),
path("login/", views.auth_login, name="login"),
path("logout/", views.auth_logout, name="logout"),
path("register/", views.auth_register, name="register"),
path('', views.me, name='me'),
path('me/', views.me, name='me_exp'),
path('login/', views.auth_login, name='login'),
path('logout/', views.auth_logout, name='logout'),
path('register/', views.auth_register, name='register'),
]

View file

@ -1,28 +1,32 @@
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.http import HttpRequest, HttpResponse
from django.shortcuts import redirect, render, reverse
from django.http import HttpRequest
from django.http import HttpResponse
from django.shortcuts import redirect
from django.shortcuts import render
from django.shortcuts import reverse
from . import forms
def auth_login(req: HttpRequest) -> HttpResponse:
if req.method == "POST":
if req.method == 'POST':
form = forms.LoginForm(data=req.POST)
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()
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)
elif req.method == "GET":
elif req.method == 'GET':
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)
@ -35,20 +39,20 @@ def auth_logout(req: HttpRequest) -> HttpResponse:
def auth_register(req: HttpRequest) -> HttpResponse:
if req.user.is_authenticated:
return redirect(reverse("me"))
if req.method == "POST":
return redirect(reverse('me'))
if req.method == 'POST':
form = forms.RegisterForm(data=req.POST)
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()
login(req, user)
return redirect(settings.LOGIN_BASE_URL)
elif req.method == "GET":
elif req.method == 'GET':
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)
@ -56,4 +60,4 @@ def auth_register(req: HttpRequest) -> HttpResponse:
@login_required
def me(req: HttpRequest) -> HttpResponse:
print(req.user.username)
return render(req, "account/me.html")
return render(req, 'account/me.html')

View file

@ -6,11 +6,10 @@ It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
"""
import os
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()

View file

@ -9,8 +9,8 @@ https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/ref/settings/
"""
from pathlib import Path
from django.utils.translation import gettext_lazy as _
# 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/
# 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!
DEBUG = True
@ -30,56 +30,56 @@ ALLOWED_HOSTS = ['*']
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"crispy_forms",
"crispy_bootstrap5",
"accounts.apps.AccountConfig",
"subjects.apps.SubjectsConfig"
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'crispy_forms',
'crispy_bootstrap5',
'accounts.apps.AccountConfig',
'subjects.apps.SubjectsConfig',
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = "facturio.urls"
ROOT_URLCONF = 'facturio.urls'
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [BASE_DIR / "templates"],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR / 'templates'],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = "facturio.wsgi.application"
WSGI_APPLICATION = 'facturio.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
@ -88,33 +88,28 @@ DATABASES = {
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
# https://docs.djangoproject.com/en/5.0/topics/i18n/
LANGUAGE_CODE = "cs"
LANGUAGES = [
("en", _("English")),
("cs", _("Czech"))
]
LANGUAGE_CODE = 'cs'
LANGUAGES = [('en', _('English')), ('cs', _('Czech'))]
LOCALE_PATHS = [
BASE_DIR / "locale"
]
LOCALE_PATHS = [BASE_DIR / 'locale']
TIME_ZONE = "UTC"
TIME_ZONE = 'UTC'
USE_I18N = True
@ -123,22 +118,22 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.0/howto/static-files/
STATIC_URL = "static/"
STATIC_URL = 'static/'
# Default primary key field type
# 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
LOGIN_BASE_URL = "/accounts"
LOGIN_URL = f"{LOGIN_BASE_URL}/login"
LOGOUT_REDIRECT_URL = f"/"
LOGIN_REDIRECT_URL = f"{LOGIN_BASE_URL}/me"
LOGIN_BASE_URL = '/accounts'
LOGIN_URL = f'{LOGIN_BASE_URL}/login'
LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL = f'{LOGIN_BASE_URL}/me'
AUTH_USER_MODEL = "accounts.User"
AUTH_USER_MODEL = 'accounts.User'
# Crispy config
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_ALLOWED_TEMPLATE_PACKS = 'bootstrap5'
CRISPY_TEMPLATE_PACK = "bootstrap5"
CRISPY_TEMPLATE_PACK = 'bootstrap5'

View file

@ -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.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:
return render(req, "facturio/index.html")
return render(req, 'facturio/index.html')
urlpatterns = i18n_patterns(
path("", landing_page, name="main-page"),
path("accounts/", include("accounts.urls")),
path("subjects/", include("subjects.urls")),
path("admin/", admin.site.urls),
prefix_default_language=False
path('', landing_page, name='main-page'),
path('accounts/', include('accounts.urls')),
path('subjects/', include('subjects.urls')),
path('admin/', admin.site.urls),
prefix_default_language=False,
)

View file

@ -6,11 +6,10 @@ It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
"""
import os
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()

View file

@ -6,17 +6,17 @@ import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "facturio.settings")
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'facturio.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
'available on your PYTHONPATH environment variable? Did you '
'forget to activate a virtual environment?'
) from exc
execute_from_command_line(sys.argv)
if __name__ == "__main__":
if __name__ == '__main__':
main()

View file

@ -17,3 +17,6 @@ ares-util = "^0.3.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.ruff.format]
quote-style = "single"

View file

@ -5,5 +5,4 @@ from . import models
@admin.register(models.Subject)
class SubjectAdmin(admin.ModelAdmin):
list_display = ["id", "name", "city", "city_part", "zip_code"]
list_display = ['id', 'name', 'city', 'city_part', 'zip_code']

View file

@ -2,5 +2,5 @@ from django.apps import AppConfig
class SubjectsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "subjects"
default_auto_field = 'django.db.models.BigAutoField'
name = 'subjects'

View file

@ -1,6 +1,7 @@
from ares_util.ares import validate_czech_company_id
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.core.exceptions import ValidationError
from django.forms import fields
@ -11,36 +12,32 @@ from . import models
class CreateSubjectForm(forms.Form):
error_messages = {
"invalid_cin": _("Your provided CIN is not correct."),
"already_existing": _("Subject with provided CIN already exists.")
'invalid_cin': _('Your provided CIN is not correct.'),
'already_existing': _('Subject with provided CIN already exists.'),
}
cin = fields.CharField(
label=_("CIN"),
label=_('CIN'),
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):
super().__init__(*args, **kwargs)
self.helper = helper.FormHelper()
self.helper.form_action = "subjects:create"
self.helper.form_method = "post"
self.helper.form_action = 'subjects:create'
self.helper.form_method = 'post'
self.helper.add_input(layout.Submit('submit', _('Add')))
def clean_cin(self):
cin = self.cleaned_data.get("cin")
cin = self.cleaned_data.get('cin')
try:
validate_czech_company_id(cin)
except InvalidCompanyIDError:
raise ValidationError(
self.error_messages["invalid_cin"]
)
raise ValidationError(self.error_messages['invalid_cin'])
try:
models.Subject.objects.get(id=cin)
except models.Subject.DoesNotExist:
return cin
raise ValidationError(
self.error_messages["already_existing"]
)
raise ValidationError(self.error_messages['already_existing'])

View file

@ -1,6 +1,6 @@
# Generated by Django 5.0 on 2023-12-20 22:36
from django.db import migrations, models
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
@ -10,31 +10,31 @@ class Migration(migrations.Migration):
operations = [
migrations.CreateModel(
name="Subject",
name='Subject',
fields=[
(
"id",
'id',
models.CharField(
max_length=8,
primary_key=True,
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(
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")),
("zip_code", models.CharField(max_length=6, verbose_name="zip_code")),
("city", models.CharField(max_length=64, verbose_name="city")),
('street', models.CharField(max_length=64, verbose_name='street')),
('zip_code', models.CharField(max_length=6, verbose_name='zip_code')),
('city', models.CharField(max_length=64, verbose_name='city')),
(
"city_part",
'city_part',
models.CharField(
blank=True, max_length=64, null=True, verbose_name="city_part"
blank=True, max_length=64, null=True, verbose_name='city_part'
),
),
],

View file

@ -1,53 +1,53 @@
# Generated by Django 5.0 on 2023-12-20 22:47
from django.db import migrations, models
from django.db import migrations
from django.db import models
class Migration(migrations.Migration):
dependencies = [
("subjects", "0001_initial"),
('subjects', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name="subject",
name="city",
field=models.CharField(max_length=64, verbose_name="City"),
model_name='subject',
name='city',
field=models.CharField(max_length=64, verbose_name='City'),
),
migrations.AlterField(
model_name="subject",
name="city_part",
model_name='subject',
name='city_part',
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(
model_name="subject",
name="id",
model_name='subject',
name='id',
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(
model_name="subject",
name="name",
field=models.CharField(max_length=128, verbose_name="Name"),
model_name='subject',
name='name',
field=models.CharField(max_length=128, verbose_name='Name'),
),
migrations.AlterField(
model_name="subject",
name="street",
field=models.CharField(max_length=64, verbose_name="Street"),
model_name='subject',
name='street',
field=models.CharField(max_length=64, verbose_name='Street'),
),
migrations.AlterField(
model_name="subject",
name="vat_id",
model_name='subject',
name='vat_id',
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(
model_name="subject",
name="zip_code",
field=models.CharField(max_length=6, verbose_name="Zip Code"),
model_name='subject',
name='zip_code',
field=models.CharField(max_length=6, verbose_name='Zip Code'),
),
]

View file

@ -1,16 +1,15 @@
# Generated by Django 5.0.1 on 2024-01-29 21:06
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("subjects", "0002_alter_subject_city_alter_subject_city_part_and_more"),
('subjects', '0002_alter_subject_city_alter_subject_city_part_and_more'),
]
operations = [
migrations.AlterModelOptions(
name="subject",
options={"verbose_name": "Subject", "verbose_name_plural": "Subjects"},
name='subject',
options={'verbose_name': 'Subject', 'verbose_name_plural': 'Subjects'},
),
]

View file

@ -1,55 +1,37 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
class Subject(models.Model):
class Meta:
verbose_name = _("Subject")
verbose_name_plural = _("Subjects")
verbose_name = _('Subject')
verbose_name_plural = _('Subjects')
id = models.CharField(
_("CIN"),
max_length=8,
primary_key=True
)
id = models.CharField(_('CIN'), max_length=8, primary_key=True)
name = models.CharField(
_("Name"),
max_length=128
)
name = models.CharField(_('Name'), max_length=128)
vat_id = models.CharField(
_("VAT ID"),
max_length=12,
null=True,
blank=True
)
vat_id = models.CharField(_('VAT ID'), max_length=12, null=True, blank=True)
street = models.CharField(
_("Street"),
_('Street'),
max_length=64,
)
zip_code = models.CharField(
_("Zip Code"),
_('Zip Code'),
max_length=6,
)
city = models.CharField(
_("City"),
_('City'),
max_length=64,
)
city_part = models.CharField(
_("City part"),
max_length=64,
null=True,
blank=True
)
city_part = models.CharField(_('City part'), max_length=64, null=True, blank=True)
def __str__(self):
return self.name
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))

View file

@ -1,3 +1 @@
from django.test import TestCase
# Create your tests here.

View file

@ -2,11 +2,11 @@ from django.urls import path
from . import views
app_name = "subjects"
app_name = 'subjects'
urlpatterns = [
path("", views.main_page, name="list"),
path("new/", views.create_subject, name="create"),
path("link/<int:subject_id>", views.link_subject, name="link"),
path("unlink/<int:subject_id>", views.unlink_subject, name="unlink")
path('', views.main_page, name='list'),
path('new/', views.create_subject, name='create'),
path('link/<int:subject_id>', views.link_subject, name='link'),
path('unlink/<int:subject_id>', views.unlink_subject, name='unlink'),
]

View file

@ -1,51 +1,54 @@
from ares_util.ares import call_ares
from django.contrib.auth.decorators import login_required
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render, redirect
from django.http import HttpRequest
from django.http import HttpResponse
from django.shortcuts import redirect
from django.shortcuts import render
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:
return f"{street}, {zip_code}, {city} - {city_part}"
return f'{street}, {zip_code}, {city} - {city_part}'
@login_required
def main_page(req: HttpRequest) -> HttpResponse:
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
def create_subject(req: HttpRequest) -> HttpResponse:
if req.method == "POST":
if req.method == 'POST':
form = forms.CreateSubjectForm(data=req.POST)
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_legal_data = ares_data["legal"]
ares_address_data = ares_data['address']
ares_legal_data = ares_data['legal']
models.Subject.objects.create(
id=ares_legal_data["company_id"],
vat_id=ares_legal_data["company_vat_id"],
name=ares_legal_data["company_name"],
street=ares_address_data["street"],
zip_code=ares_address_data["zip_code"],
city=ares_address_data["city"],
city_part=ares_address_data["city_part"],
id=ares_legal_data['company_id'],
vat_id=ares_legal_data['company_vat_id'],
name=ares_legal_data['company_name'],
street=ares_address_data['street'],
zip_code=ares_address_data['zip_code'],
city=ares_address_data['city'],
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()
return render(req, "subjects/create.html", dict(form=form))
return render(req, 'subjects/create.html', dict(form=form))
return HttpResponse(status=405)
@ -54,11 +57,11 @@ def create_subject(req: HttpRequest) -> HttpResponse:
def link_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
subject = models.Subject.objects.get(pk=subject_id)
subject.user_set.add(request.user)
return redirect(reverse("subjects:list"))
return redirect(reverse('subjects:list'))
@login_required
def unlink_subject(request: HttpRequest, subject_id: int) -> HttpResponse:
subject = models.Subject.objects.get(pk=subject_id)
subject.user_set.remove(request.user)
return redirect(reverse("subjects:list"))
return redirect(reverse('subjects:list'))