Ares #2

Merged
JustScreaMy merged 3 commits from ares into master 2024-01-13 12:14:31 +01:00
28 changed files with 274 additions and 88 deletions
Showing only changes of commit d2faa872ac - Show all commits

View file

@ -1,16 +0,0 @@
{% extends "facturio/base.html" %}
{% block title %}About Me{% endblock %}
{% block content %}
<div class="container mt-4">
<h2 class="mb-4">About Me</h2>
<div class="card">
<h5 class="card-header">Welcome, {{ request.user.first_name }} {{ request.user.last_name }}!</h5>
<ul class="list-group list-group-flush">
<li class="list-group-item">Username: {{ request.user.username }}</li>
<li class="list-group-item">Email: {{ request.user.email }}</li>
</ul>
</div>
</div>
{% endblock %}

View file

@ -3,4 +3,4 @@ from django.apps import AppConfig
class AccountConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "account"
name = "accounts"

View file

@ -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'))

View file

@ -5,7 +5,7 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("account", "0001_initial"),
("accounts", "0001_initial"),
]
operations = [

View file

@ -0,0 +1,14 @@
{% extends "facturio/base.html" %}
{% block title %}About Me{% endblock %}
{% block content %}
<h2 class="mb-4">About Me</h2>
<div class="card">
<h5 class="card-header">Welcome, {{ request.user.first_name }} {{ request.user.last_name }}!</h5>
<ul class="list-group list-group-flush">
<li class="list-group-item">Username: {{ request.user.username }}</li>
<li class="list-group-item">Email: {{ request.user.email }}</li>
</ul>
</div>
{% endblock %}

View file

@ -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"),

View file

@ -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"

View file

@ -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),
]

View file

@ -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"]

46
subjects/forms.py Normal file
View file

@ -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"]
)

View file

@ -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"
),
),
],
),
]

View file

@ -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"),
),
]

View file

@ -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

View file

@ -1,23 +0,0 @@
{% extends "facturio/base.html" %}
{% block title %}AresTest{% endblock %}
{% block content %}
<div class="container mt-4">
<h2 class="mb-4">Ares data</h2>
<div class="card {% if error %}bg-danger{% endif %}">
{% if error %}
<div class="card-body">
<h5 class="card-title">Ares search failed!</h5>
<p class="card-text">{{ error }}</p>
</div>
{% endif %}
{% if ares_data %}
<div class="card-body">
<h5 class="card-title">Ares data</h5>
<pre class="card-text">{{ ares_data|pprint }}</pre>
</div>
{% endif %}
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "facturio/base.html" %}
{% load crispy_forms_tags %}
{% block title %}Create Subjects{% endblock %}
{% block content %}
{% crispy form form.helper %}
{% endblock %}

View file

@ -0,0 +1,33 @@
{% extends "facturio/base.html" %}
{% block title %}Subjects{% endblock %}
{% block content %}
<a href="{% url "subjects:create" %}" class="btn btn-primary" role="button">Add new</a>
<table class="table">
<thead>
<tr>
<th>CIN</th>
<th>Name</th>
<th>VAT ID</th>
<th>Street</th>
<th>Zip Code</th>
<th>City</th>
<th>City part</th>
</tr>
</thead>
<tbody>
{% for subject in subjects %}
<tr>
<td>{{ subject.id }}</td>
<td>{{ subject.name }}</td>
<td>{{ subject.vat_id }}</td>
<td>{{ subject.street }}</td>
<td>{{ subject.zip_code }}</td>
<td>{{ subject.city }}</td>
<td>{{ subject.city_part }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View file

@ -2,6 +2,9 @@ from django.urls import path
from . import views
app_name = "subjects"
urlpatterns = [
path("<str:ico>", views.test, name="ares_test")
path("", views.main_page, name="list"),
path("new/", views.create_subject, name="create")
]

View file

@ -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)

View file

@ -2,20 +2,20 @@
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Facturio - {% block title %}App{% endblock %}</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container-fluid">
<a class="navbar-brand" href="{% url "main-page" %}">Facturio</a>
<div class="collapse navbar-collapse" id="navbarLeft">
<div class="collapse navbar-collapse">
<ul class="navbar-nav">
{#<li class="nav-item">#}
{# <a class="nav-link" href="#">Item 1</a>#}
{#</li>#}
<li class="nav-item">
<a class="nav-link" href="{% url "subjects:list" %}">Subjects</a>
</li>
{#<li class="nav-item">#}
{# <a class="nav-link" href="#">Item 2</a>#}
{#</li>#}
@ -26,17 +26,17 @@
<ul class="navbar-nav">
{% if request.user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'me' %}">Profile</a>
<a class="nav-link" href="{% url 'accounts:me' %}">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">Logout</a>
<a class="nav-link" href="{% url 'accounts:logout' %}">Logout</a>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'login' %}">Login</a>
<a class="nav-link" href="{% url 'accounts:login' %}">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'register' %}">Register</a>
<a class="nav-link" href="{% url 'accounts:register' %}">Register</a>
</li>
{% endif %}
</ul>