diff --git a/account/templates/account/me.html b/account/templates/account/me.html
deleted file mode 100644
index 5887c40..0000000
--- a/account/templates/account/me.html
+++ /dev/null
@@ -1,16 +0,0 @@
-{% extends "facturio/base.html" %}
-
-{% block title %}About Me{% endblock %}
-
-{% block content %}
-
-
About Me
-
-
-
- - Username: {{ request.user.username }}
- - Email: {{ request.user.email }}
-
-
-
-{% endblock %}
diff --git a/account/__init__.py b/accounts/__init__.py
similarity index 100%
rename from account/__init__.py
rename to accounts/__init__.py
diff --git a/account/admin.py b/accounts/admin.py
similarity index 100%
rename from account/admin.py
rename to accounts/admin.py
diff --git a/account/apps.py b/accounts/apps.py
similarity index 85%
rename from account/apps.py
rename to accounts/apps.py
index 2c684a9..ec4e357 100644
--- a/account/apps.py
+++ b/accounts/apps.py
@@ -3,4 +3,4 @@ from django.apps import AppConfig
class AccountConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
- name = "account"
+ name = "accounts"
diff --git a/account/forms.py b/accounts/forms.py
similarity index 88%
rename from account/forms.py
rename to accounts/forms.py
index e85403f..0e3f646 100644
--- a/account/forms.py
+++ b/accounts/forms.py
@@ -11,7 +11,7 @@ class LoginForm(AuthenticationForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = helper.FormHelper()
- self.helper.form_action = "login"
+ self.helper.form_action = "accounts:login"
self.helper.form_method = "post"
self.helper.add_input(layout.Submit('submit', 'Login'))
@@ -24,6 +24,6 @@ class RegisterForm(UserCreationForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = helper.FormHelper()
- self.helper.form_action = "register"
+ self.helper.form_action = "accounts:register"
self.helper.form_method = "post"
self.helper.add_input(layout.Submit('submit', 'Register'))
diff --git a/account/migrations/0001_initial.py b/accounts/migrations/0001_initial.py
similarity index 100%
rename from account/migrations/0001_initial.py
rename to accounts/migrations/0001_initial.py
diff --git a/account/migrations/0002_alter_user_email_alter_user_first_name_and_more.py b/accounts/migrations/0002_alter_user_email_alter_user_first_name_and_more.py
similarity index 95%
rename from account/migrations/0002_alter_user_email_alter_user_first_name_and_more.py
rename to accounts/migrations/0002_alter_user_email_alter_user_first_name_and_more.py
index b8f4201..be9e06f 100644
--- a/account/migrations/0002_alter_user_email_alter_user_first_name_and_more.py
+++ b/accounts/migrations/0002_alter_user_email_alter_user_first_name_and_more.py
@@ -5,7 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
- ("account", "0001_initial"),
+ ("accounts", "0001_initial"),
]
operations = [
diff --git a/account/migrations/__init__.py b/accounts/migrations/__init__.py
similarity index 100%
rename from account/migrations/__init__.py
rename to accounts/migrations/__init__.py
diff --git a/account/models.py b/accounts/models.py
similarity index 100%
rename from account/models.py
rename to accounts/models.py
diff --git a/account/templates/account/login.html b/accounts/templates/account/login.html
similarity index 100%
rename from account/templates/account/login.html
rename to accounts/templates/account/login.html
diff --git a/accounts/templates/account/me.html b/accounts/templates/account/me.html
new file mode 100644
index 0000000..37caf86
--- /dev/null
+++ b/accounts/templates/account/me.html
@@ -0,0 +1,14 @@
+{% extends "facturio/base.html" %}
+
+{% block title %}About Me{% endblock %}
+
+{% block content %}
+ About Me
+
+
+
+ - Username: {{ request.user.username }}
+ - Email: {{ request.user.email }}
+
+
+{% endblock %}
diff --git a/account/templates/account/register.html b/accounts/templates/account/register.html
similarity index 100%
rename from account/templates/account/register.html
rename to accounts/templates/account/register.html
diff --git a/account/tests.py b/accounts/tests.py
similarity index 100%
rename from account/tests.py
rename to accounts/tests.py
diff --git a/account/urls.py b/accounts/urls.py
similarity index 79%
rename from account/urls.py
rename to accounts/urls.py
index 2184e52..8e7a9ac 100644
--- a/account/urls.py
+++ b/accounts/urls.py
@@ -1,8 +1,9 @@
-from django.http import HttpResponse
-from django.urls import path, re_path
+from django.urls import path
from . import views
+app_name = "accounts"
+
urlpatterns = [
path("", views.me, name="me"),
path("me/", views.me, name="me_exp"),
diff --git a/account/views.py b/accounts/views.py
similarity index 100%
rename from account/views.py
rename to accounts/views.py
diff --git a/facturio/settings.py b/facturio/settings.py
index fbc69af..b92181f 100644
--- a/facturio/settings.py
+++ b/facturio/settings.py
@@ -37,7 +37,7 @@ INSTALLED_APPS = [
"django.contrib.staticfiles",
"crispy_forms",
"crispy_bootstrap5",
- "account.apps.AccountConfig",
+ "accounts.apps.AccountConfig",
"subjects.apps.SubjectsConfig"
]
@@ -121,12 +121,12 @@ STATIC_URL = "static/"
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# Auth configuration
-LOGIN_BASE_URL = "/account"
+LOGIN_BASE_URL = "/accounts"
LOGIN_URL = f"{LOGIN_BASE_URL}/login"
LOGOUT_REDIRECT_URL = f"/"
LOGIN_REDIRECT_URL = f"{LOGIN_BASE_URL}/me"
-AUTH_USER_MODEL = "account.User"
+AUTH_USER_MODEL = "accounts.User"
# Crispy config
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
diff --git a/facturio/urls.py b/facturio/urls.py
index 9a5aecd..a932a8d 100644
--- a/facturio/urls.py
+++ b/facturio/urls.py
@@ -26,7 +26,7 @@ def landing_page(req: HttpRequest) -> HttpResponse:
urlpatterns = [
path("", landing_page, name="main-page"),
- path("account/", include("account.urls")),
+ path("accounts/", include("accounts.urls")),
path("subjects/", include("subjects.urls")),
path("admin/", admin.site.urls),
]
diff --git a/subjects/admin.py b/subjects/admin.py
index dd45906..17549f6 100644
--- a/subjects/admin.py
+++ b/subjects/admin.py
@@ -2,4 +2,8 @@ from django.contrib import admin
from . import models
-admin.site.register(models.Subject)
+
+@admin.register(models.Subject)
+class SubjectAdmin(admin.ModelAdmin):
+ list_display = ["id", "name", "city", "city_part", "zip_code"]
+
diff --git a/subjects/forms.py b/subjects/forms.py
new file mode 100644
index 0000000..13f4b8e
--- /dev/null
+++ b/subjects/forms.py
@@ -0,0 +1,46 @@
+from ares_util.ares import validate_czech_company_id
+from ares_util.exceptions import InvalidCompanyIDError
+from crispy_forms import helper, layout
+from django import forms
+from django.core.exceptions import ValidationError
+from django.forms import fields
+from django.utils.translation import gettext_lazy as _
+
+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.")
+ }
+ cin = fields.CharField(
+ label=_("CIN"),
+ max_length=8,
+ 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.add_input(layout.Submit('submit', 'Add'))
+
+ def clean_cin(self):
+ cin = self.cleaned_data.get("cin")
+ try:
+ validate_czech_company_id(cin)
+ except InvalidCompanyIDError as ex:
+ 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"]
+ )
diff --git a/subjects/migrations/0001_initial.py b/subjects/migrations/0001_initial.py
index e5f9dd5..28c57bb 100644
--- a/subjects/migrations/0001_initial.py
+++ b/subjects/migrations/0001_initial.py
@@ -1,4 +1,4 @@
-# Generated by Django 5.0 on 2023-12-19 13:38
+# Generated by Django 5.0 on 2023-12-20 22:36
from django.db import migrations, models
@@ -21,6 +21,22 @@ class Migration(migrations.Migration):
verbose_name="cin",
),
),
+ ("name", models.CharField(max_length=128, verbose_name="name")),
+ (
+ "vat_id",
+ models.CharField(
+ 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")),
+ (
+ "city_part",
+ models.CharField(
+ blank=True, max_length=64, null=True, verbose_name="city_part"
+ ),
+ ),
],
),
]
diff --git a/subjects/migrations/0002_alter_subject_city_alter_subject_city_part_and_more.py b/subjects/migrations/0002_alter_subject_city_alter_subject_city_part_and_more.py
new file mode 100644
index 0000000..fdb6fb1
--- /dev/null
+++ b/subjects/migrations/0002_alter_subject_city_alter_subject_city_part_and_more.py
@@ -0,0 +1,53 @@
+# Generated by Django 5.0 on 2023-12-20 22:47
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("subjects", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="subject",
+ name="city",
+ field=models.CharField(max_length=64, verbose_name="City"),
+ ),
+ migrations.AlterField(
+ model_name="subject",
+ name="city_part",
+ field=models.CharField(
+ blank=True, max_length=64, null=True, verbose_name="City part"
+ ),
+ ),
+ migrations.AlterField(
+ model_name="subject",
+ name="id",
+ field=models.CharField(
+ 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"),
+ ),
+ migrations.AlterField(
+ model_name="subject",
+ name="street",
+ field=models.CharField(max_length=64, verbose_name="Street"),
+ ),
+ migrations.AlterField(
+ model_name="subject",
+ name="vat_id",
+ field=models.CharField(
+ 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"),
+ ),
+ ]
diff --git a/subjects/models.py b/subjects/models.py
index d3a9805..78ad294 100644
--- a/subjects/models.py
+++ b/subjects/models.py
@@ -5,7 +5,44 @@ from django.utils.translation import gettext_lazy as _
class Subject(models.Model):
id = models.CharField(
- _("cin"),
+ _("CIN"),
max_length=8,
primary_key=True
)
+
+ name = models.CharField(
+ _("Name"),
+ max_length=128
+ )
+
+ vat_id = models.CharField(
+ _("VAT ID"),
+ max_length=12,
+ null=True,
+ blank=True
+ )
+
+ street = models.CharField(
+ _("Street"),
+ max_length=64,
+ )
+
+ zip_code = models.CharField(
+ _("Zip Code"),
+ max_length=6,
+ )
+
+ city = models.CharField(
+ _("City"),
+ max_length=64,
+ )
+
+ city_part = models.CharField(
+ _("City part"),
+ max_length=64,
+ null=True,
+ blank=True
+ )
+
+ def __str__(self):
+ return self.name
diff --git a/subjects/templates/subjects/ares.html b/subjects/templates/subjects/ares.html
deleted file mode 100644
index eae6f1a..0000000
--- a/subjects/templates/subjects/ares.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{% extends "facturio/base.html" %}
-
-{% block title %}AresTest{% endblock %}
-
-{% block content %}
-
-
Ares data
-
- {% if error %}
-
-
Ares search failed!
-
{{ error }}
-
- {% endif %}
- {% if ares_data %}
-
-
Ares data
-
{{ ares_data|pprint }}
-
- {% endif %}
-
-
-{% endblock %}
diff --git a/subjects/templates/subjects/create.html b/subjects/templates/subjects/create.html
new file mode 100644
index 0000000..cd4f345
--- /dev/null
+++ b/subjects/templates/subjects/create.html
@@ -0,0 +1,9 @@
+{% extends "facturio/base.html" %}
+
+{% load crispy_forms_tags %}
+
+{% block title %}Create Subjects{% endblock %}
+
+{% block content %}
+ {% crispy form form.helper %}
+{% endblock %}
\ No newline at end of file
diff --git a/subjects/templates/subjects/index.html b/subjects/templates/subjects/index.html
new file mode 100644
index 0000000..62d8d90
--- /dev/null
+++ b/subjects/templates/subjects/index.html
@@ -0,0 +1,33 @@
+{% extends "facturio/base.html" %}
+
+{% block title %}Subjects{% endblock %}
+
+{% block content %}
+ Add new
+
+
+
+ CIN |
+ Name |
+ VAT ID |
+ Street |
+ Zip Code |
+ City |
+ City part |
+
+
+
+ {% for subject in subjects %}
+
+ {{ subject.id }} |
+ {{ subject.name }} |
+ {{ subject.vat_id }} |
+ {{ subject.street }} |
+ {{ subject.zip_code }} |
+ {{ subject.city }} |
+ {{ subject.city_part }} |
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/subjects/urls.py b/subjects/urls.py
index b2a4c93..799d82a 100644
--- a/subjects/urls.py
+++ b/subjects/urls.py
@@ -2,6 +2,9 @@ from django.urls import path
from . import views
+app_name = "subjects"
+
urlpatterns = [
- path("", views.test, name="ares_test")
+ path("", views.main_page, name="list"),
+ path("new/", views.create_subject, name="create")
]
diff --git a/subjects/views.py b/subjects/views.py
index ee36ee3..0c8cab5 100644
--- a/subjects/views.py
+++ b/subjects/views.py
@@ -1,38 +1,47 @@
-from ares_util.ares import call_ares, validate_czech_company_id
-from ares_util.exceptions import InvalidCompanyIDError
+from ares_util.ares import call_ares
from django.http import HttpRequest, HttpResponse
-from django.shortcuts import render
+from django.shortcuts import render, redirect
+from django.urls import reverse
-ARES_BASE_URL = "https://wwwinfo.mfcr.cz/cgi-bin/ares/darv_rzp.cgi?ico=27074358&xml=0&ver=1.0.4"
+from . import models, forms
def build_address(street: str, zip_code: int | str, city: str, city_part: str) -> str:
return f"{street}, {zip_code}, {city} - {city_part}"
-def test(req: HttpRequest, ico: str) -> HttpResponse:
- try:
- validate_czech_company_id(ico)
- except InvalidCompanyIDError as ex:
- return render(req, "subjects/ares.html", dict(error=ex, ares_data={}))
+def main_page(req: HttpRequest) -> HttpResponse:
+ subjects = models.Subject.objects.all()
+ return render(req, "subjects/index.html", dict(subjects=subjects))
- ares_data = call_ares(ico)
- ares_address_data = ares_data["address"]
- ares_legal_data = ares_data["legal"]
+def create_subject(req: HttpRequest) -> HttpResponse:
+ if req.method == "POST":
+ form = forms.CreateSubjectForm(data=req.POST)
- address_line = build_address(
- ares_address_data["street"],
- ares_address_data["zip_code"],
- ares_address_data["city"],
- ares_address_data["city_part"]
- )
+ if not form.is_valid():
+ return render(req, "subjects/create.html", dict(form=form))
- important_data = dict(
- copmany_name=ares_legal_data["company_name"],
- company_id=ares_legal_data["company_id"],
- company_vat_id=ares_legal_data["company_vat_id"],
- address_line=address_line,
- )
+ ares_data = call_ares(form.cleaned_data.get("cin"))
- return render(req, "subjects/ares.html", dict(error="", ares_data=important_data))
+ 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"],
+ )
+
+ return redirect(reverse("subjects:list"))
+
+ elif req.method == "GET":
+ form = forms.CreateSubjectForm()
+
+ return render(req, "subjects/create.html", dict(form=form))
+
+ return HttpResponse(status=405)
diff --git a/templates/facturio/base.html b/templates/facturio/base.html
index e1d98ec..9296e0b 100644
--- a/templates/facturio/base.html
+++ b/templates/facturio/base.html
@@ -2,20 +2,20 @@
+
Facturio - {% block title %}App{% endblock %}
-